⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cl_netstring.c

📁 在LINUX下实现HA的源代码
💻 C
字号:
/* * netstring implementation * * Copyright (c) 2003 Guochun Shi <gshi@ncsa.uiuc.edu> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include <portability.h>#include <heartbeat.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <time.h>#include <unistd.h>#include <ha_msg.h>#include <unistd.h>#include <clplumbing/ipc.h>#include <clplumbing/netstring.h>#include <clplumbing/base64.h>/* * Avoid sprintf.  Use snprintf instead, even if you count your bytes. * It can detect calculation errors (if used properly) * and will not make the security audit tools crazy. */extern const char *	FT_strings[];static int (*authmethod)(int whichauth,	const void * data,	size_t datalen,	char * authstr,	size_t authlen) = NULL;voidcl_set_authentication_computation_method(int (*method)(int whichauth,	const void * data,	size_t datalen,	char * authstr,	size_t authlen)){	authmethod = method;}static intcompose_netstring(char * s, const char * smax, size_t len,		  const char * data, int* comlen){	char *	sp = s;	/* 3 == ":" + "," + at least one digit number */	if (s + len + 3 > smax) {		cl_log(LOG_ERR		,	"netstring pointer out of boundary(compose_netstring)");		return(HA_FAIL);	}	sp += sprintf(sp, "%ld:", (long)len);	memcpy(sp, data, len);	sp += len;	*sp++ = ',';	*comlen = sp - s;	return(HA_OK);}/* Converts a message into a netstring */static intmsg2netstring_buf(const struct ha_msg *m, char *s,		  size_t buflen, size_t * slen){	int	i;	char *	sp;	char *	smax;	char *	datap;	int	datalen = 0;	char	authtoken[MAXLINE];	char	authstring[MAXLINE];	int	authnum;	sp = s;	smax = s + buflen;	strcpy(sp, MSG_START_NETSTRING);	sp += strlen(MSG_START_NETSTRING);	datap = sp;	for (i=0; i < m->nfields; i++) {		int comlen;		size_t llen;		if (compose_netstring(sp, smax, m->nlens[i]		,	m->names[i],&comlen) != HA_OK){			cl_log(LOG_ERR			,	"compose_netstring fails for"			" name(msg2netstring_buf)");			return(HA_FAIL);		}		sp += comlen;		datalen +=comlen;		if (compose_netstring(sp, smax, 1		,	FT_strings[m->types[i]],&comlen) != HA_OK) {			cl_log(LOG_ERR			, "compose_netstring fails for"			" type(msg2netstring_buf)");			return(HA_FAIL);		}		sp += comlen;		datalen +=comlen;		llen = (size_t)m->nlens[i];		if (m->types[i] == FT_STRUCT) {			size_t	tmplen;			char	*sp_save = sp;			llen =  get_netstringlen((struct ha_msg *)m->values[i]			,	0);			sp += sprintf(sp, "%ld:", (long)llen);			if (msg2netstring_buf((struct ha_msg * )m->values[i]			,	sp, llen, &tmplen) != HA_OK){				cl_log(LOG_ERR				,	"msg2netstring_buf()"				": msg2netstring_buf() failed");				return(HA_FAIL);			}			sp +=llen;			*sp++ = ',';			comlen = sp - sp_save;			datalen += comlen;		} else if (compose_netstring(sp, smax, m->vlens[i]		,	m->values[i],&comlen) != HA_OK){			cl_log(LOG_ERR			,	"compose_netstring fails for"			" value(msg2netstring_buf)");			return(HA_FAIL);		} else{			sp += comlen;			datalen +=comlen;		}	}	/* Add authentication */	if ((authnum=authmethod(-1, datap, datalen, authtoken	,		sizeof(authtoken))) < 0) {		cl_log(LOG_WARNING		,	"Cannot compute message authentication!");		return(HA_FAIL);	}	sprintf(authstring, "%d %s", authnum, authtoken);	sp += sprintf(sp, "%ld:%s,", (long)strlen(authstring), authstring);	strcpy(sp, MSG_END_NETSTRING);	sp += sizeof(MSG_END_NETSTRING) -1;	if (sp > smax){		cl_log(LOG_ERR		,	"msg2netstring: exceed memory boundary sp =%p smax=%p"		,	sp, smax);		return(HA_FAIL);	}	*slen = sp - s + 1;	return(HA_OK);}char *msg2netstring(const struct ha_msg *m, size_t * slen){	int	len;	void	*s;	len= get_netstringlen(m, 0) + 1;	s = ha_calloc(1, len);	if (!s){		cl_log(LOG_ERR, "msg2netstring: no memory for netstring");		return(NULL);	}	if (msg2netstring_buf(m, s, len, slen) != HA_OK){		cl_log(LOG_ERR, "msg2netstring: msg2netstring_buf() failed");		ha_free(s);		return(NULL);	}	return(s);}/* * Peel one string off in a netstring */static intpeel_netstring(const char * s, const char * smax, int* len,	       const char ** data, int* parselen ){	const char *	sp = s;	if (sp >= smax){		return(HA_FAIL);	}	sscanf(sp,"%d", len);	if (len <= 0){		return(HA_FAIL);	}	while (*sp != ':' && sp < smax) {		sp ++;	}	if (sp >= smax ){		return(HA_FAIL);	}	sp ++;	*data = sp;	sp += (*len);	if (*sp != ','){		return(HA_FAIL);	}	sp++;	*parselen = sp - s;	return(HA_OK);}/* Converts a netstring into a message*/struct ha_msg *netstring2msg(const char *s, size_t length, int need_auth){	struct ha_msg*	ret = NULL;	const char *	sp = s;	const char *	smax = s + length;	int		startlen;	int		endlen;	const char *	datap;	int		datalen = 0;	if ((ret = ha_msg_new(0)) == NULL){		return(NULL);	}	startlen = sizeof(MSG_START_NETSTRING)-1;	if (strncmp(sp, MSG_START_NETSTRING, startlen) != 0) {		/* This can happen if the sender gets killed */		/* at just the wrong time... */		if (!cl_msg_quiet_fmterr) {			cl_log(LOG_WARNING, "netstring2msg: no MSG_START");			ha_msg_del(ret);		}		return(NULL);	}else{		sp += startlen;	}	endlen = sizeof(MSG_END_NETSTRING) - 1;	datap = sp;	while (sp < smax && strncmp(sp, MSG_END_NETSTRING, endlen) !=0  ){		int nlen;		int vlen;		const char * name;		const char * value;		int parselen;		int tmp;		int tlen;		const char * type;		tmp = datalen;		if (peel_netstring(sp , smax, &nlen, &name,&parselen) != HA_OK){			cl_log(LOG_ERR			,	"peel_netstring fails for name(netstring2msg)");			ha_msg_del(ret);			return(NULL);		}		sp +=  parselen;		datalen += parselen;		if (strncmp(sp, MSG_END_NETSTRING, endlen) == 0) {			if (!is_auth_netstring(datap, tmp, name,nlen) ){				if (!cl_msg_quiet_fmterr) {					cl_log(LOG_ERR					,	"netstring authentication"					" failed, s=%s, autotoken=%s, sp=%s"					,	s, name, sp);					cl_log_message(ret);				}				ha_msg_del(ret);				return(NULL);			}			return(ret);		}		if (peel_netstring(sp , smax, &tlen, &type, &parselen) !=HA_OK){			cl_log(LOG_ERR			,	"peel_netstring() error in netstring2msg"			" for type");			ha_msg_del(ret);			return(NULL);		}		sp +=  parselen;		datalen += parselen;		if (peel_netstring(sp, smax, &vlen, &value, &parselen) !=HA_OK){			cl_log(LOG_ERR			,  "peel_netstring() error in netstring2msg for value");			ha_msg_del(ret);			return(NULL);		}		sp +=  parselen;		datalen += parselen;		if (atoi(type) == FT_STRUCT){			struct ha_msg	*tmpmsg;			tmpmsg = netstring2msg(value, vlen, 1);			value = (char *)tmpmsg;			vlen = sizeof(struct ha_msg);		}		if (ha_msg_nadd_type(ret, name, nlen, value, vlen, atoi(type))		!= HA_OK) {			cl_log(LOG_ERR, "ha_msg_nadd fails(netstring2msg)");			ha_msg_del(ret);			return(NULL);		}	}	if (!need_auth){		return(ret);	}else {		if (!cl_msg_quiet_fmterr) {			cl_log(LOG_ERR, "no authentication found in netstring");		}		ha_msg_del(ret);		return(NULL);	}}intis_auth_netstring(const char * datap, size_t datalen,		  const char * authstring, size_t authlen){	char	authstr[MAXLINE];	/* A copy of authstring */	int	authwhich;	char	authtoken[MAXLINE];	/*	 * If we don't have any authentication method - everything is authentic...	 */	if (!authmethod) {		return TRUE;	}	strncpy(authstr, authstring, MAXLINE);	authstr[authlen] = 0;	if (sscanf(authstr, "%d %s", &authwhich, authtoken) != 2) {		if (!cl_msg_quiet_fmterr) {			cl_log(LOG_WARNING			,	"Bad/invalid netstring auth string");		}		return(0);	}	if (authmethod(authwhich, datap, datalen, authstr, authlen)	!=	authwhich) {		if (!cl_msg_quiet_fmterr) {			cl_log(LOG_WARNING			,	"Invalid authentication [%d] in message!"			,	authwhich);		}		return(FALSE);	}	if (strcmp(authtoken, authstr) == 0) {		return(TRUE);	}	if (!cl_msg_quiet_fmterr) {		cl_log(LOG_ERR		,	"authtoken does not match, authtoken=%s, authstr=%s"		,	authtoken, authstr);	}	return(FALSE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -