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

📄 proxy.c

📁 This program is a RADIUS RFC-compliant daemon, which is derived from original Livingston Enterprise
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (server->radport == 0) {			server->radport = radius_port;		}		if (server->acctport == 0) {			server->acctport = radacct_port;		}		if ((ipaddr == ouraddress)		    && ((server->radport == radius_port)			|| (server->acctport == radacct_port))) {			ipaddr = 0;	/* handle ourselves, do not forward */		}		server->ipaddr = ipaddr;		memcpy(server->secret, secret, strlen(secret));		memcpy(server->realm, realm, strlen(realm));		if (strcmp(realm, "DEFAULT") == 0) {			server_default = server;		} else if (strcmp(realm, "NOREALM") == 0) {			server_norealm = server;		} 		if (servers == (PEER *)NULL) {	/* first one */			servers = server;			curserv = server;		} else {			curserv->next = server;			curserv = server;		}		nproxy++;	}	fclose(fd);	last_update_time = statbuf.st_mtime;	debug("found %d proxy realms\n", nproxy);	return(0);}/************************************************************************* *************************************************************************	Subroutines related to forwarding a Proxy request from a client	to the appropriate server	handle_proxy(authreq)	push_proxy(authreq)	find_server(number, realm)	find_server_byaddr(ipaddr, port)	send_proxy2server(authreq, server)	getnextid(authreq) ************************************************************************* *************************************************************************//************************************************************************* * *	Function: handle_proxy * *	Purpose: Called by rad_request() to check if access-request should *		 be forwarded to another server. *		 Called by rad_acctreq() to forward acct-request if needed. * *	Returns: *		-1 on error *		 0 if this request was not forwarded *		 1 if this request was forwarded *	Side-Effects: *		Sets REQ_PROXY flag in authreq if request was forwarded * * *************************************************************************/int handle_proxy(AUTH_REQ*authreq){	PEER		*server;	VALUE_PAIR	*namepair;	VALUE_PAIR	*pair;	char		*name;	char		namebuf[256];	char		*number;	char		*ptr;	char		*realm;	int		ret;	realm = (char *)NULL;	number = (char *)NULL;	namebuf[0] = '\0';	name = namebuf;	if (authreq == (AUTH_REQ *)NULL) {		return -1;	}	if (authreq->code != PW_AUTHENTICATION_REQUEST &&	    authreq->code != PW_ACCOUNTING_REQUEST) {		/* should not happen unless client sent bogus message */		debug("handle_proxy called for packet type %d unexpectedly\n",			authreq->code);		authreq->flags |= REQ_ERR|REQ_FREE;		return -1;	}        namepair = get_attribute(authreq->request, PW_USER_NAME);        if (namepair != (VALUE_PAIR *)NULL) {		memcpy(namebuf, namepair->strvalue, namepair->lvalue);		namebuf[namepair->lvalue] = '\0';		if ((realm=strchr((const char *)name, '@')) != (char *)NULL) {			*realm = '\0';			realm++;		} else if ((ptr=strchr((const char *)name, '/')) != (char *)NULL) {			*ptr = '\0';			ptr++;			realm = name;			name = ptr;		} else {			realm = (char *)NULL;		}	}        pair = get_attribute(authreq->request, PW_CALLED);	if (pair != (VALUE_PAIR *)NULL) {		number = pair->strvalue;	}	/*	look up number or realm in the list of servers.  If a proxy	 *	is found, parse the packet, unencrypt the password if	 *	any, re-encrypt the password (if any), attach a	 *	proxy-state with push_proxy(), and forward it to the proxy.	 *	Use the same Request Authenticator (in case of CHAP) but	 *	use a new Id	 */	if ((server = find_server(number, realm)) == (PEER *)NULL) {		if (namepair != (VALUE_PAIR *)NULL) {			strncpy(authreq->name, namepair->strvalue, 64);			authreq->name[63] = '\0';		} else {			authreq->name[0] = '\0';		}		return 0;	/* no proxy */	}	strncpy(authreq->realm, server->realm, 64);	strncpy(authreq->name, name, 64);	authreq->name[63] = '\0';	if (server->ipaddr == 0) {	/* this is the server for this realm */		return 0;	}	authreq->flags |= REQ_PROXY;	if (server->flags & PEER_IPASS) {		if (authreq->code == PW_AUTHENTICATION_REQUEST) {			ret = rad_forw_ipass(authreq, sockfd, authreq->packet);			authreq->flags |= REQ_FREE;			return ret;		} else if (authreq->code == PW_ACCOUNTING_REQUEST) {			ret = rad_forw_ipass(authreq, acctfd, authreq->packet);			authreq->flags |= REQ_FREE;			return 0;		} else {			authreq->flags |= REQ_ERR|REQ_FREE;			return -1;		}	}	if (authreq->code == PW_AUTHENTICATION_REQUEST) {		if (decrypt_password(authreq, authreq->secret) != (char *)NULL) {			encrypt_password(authreq, server->secret);		}	}	/* If remote server cannot handle proxy, delete realm from User-Name */	if ( server->flags & PEER_NOPROXY ) {		if (namepair != (VALUE_PAIR *)NULL) {			strcpy(namepair->strvalue,name);			namepair->lvalue = strlen(name);		}	} else {		push_proxy(authreq);	}	send_proxy2server(authreq, server);	return 1;}/************************************************************************* * *	Function: push_proxy * *	Purpose: Adds a Proxy-State to the end of a packet *		 Note that RADIUS requires that Proxy-State always be *		 added after any existing Proxy-State attributes. * *		 Any changes made here must also be made in pop_proxy() * *************************************************************************/voidpush_proxy(AUTH_REQ*authreq){	DICT_ATTR       *attr;	VALUE_PAIR	*pair;	VALUE_PAIR	*list;	UINT4		tmp;	u_short		tmps;	pair = pairalloc("push_proxy");	/* Proxy-State contains: Timestamp, Client, Port, Id in network order,	   a pad byte, and 16 octets of Request Authenticator */ 	if((attr = dict_attrget(PW_PROXY)) == (DICT_ATTR *)NULL) {		debug("add Proxy (%d) to dictionary\n", PW_PROXY);		strcpy(pair->name, "Proxy");		pair->type = PW_TYPE_STRING;	} else {		strcpy(pair->name, attr->name);		pair->type = attr->type;	}	pair->attribute = PW_PROXY;	pair->lvalue = 28;	/* length of data */	tmp = htonl(authreq->timestamp);	memcpy(pair->strvalue, (char *)&tmp, 4);	tmp = htonl(authreq->ipaddr);	memcpy(pair->strvalue+4, (char *)&tmp, 4);	tmps = htons(authreq->udp_port);	memcpy(pair->strvalue+8, (char *)&tmps, 2);	memcpy(pair->strvalue+10, (char *)&(authreq->id), 1);	memset(pair->strvalue+11, 0, 1);			/* zero pad */	memcpy(pair->strvalue+12, authreq->vector, AUTH_VECTOR_LEN);	if ((list = authreq->request) == (VALUE_PAIR *)NULL) {		authreq->request = pair;	} else {		while(list->next != (VALUE_PAIR *)NULL) {			list = list->next;		}		list->next = pair;	}}/************************************************************************* * *	Function: find_server * *	Purpose: Returns server to forward to based on number or realm *		 Number takes precedence * *************************************************************************/PEER * find_server(char *number,char *realm){	extern PEER	*servers;	extern PEER	*server_default;	extern PEER	*server_norealm;	PEER	*server;	PEER	*maybe;	maybe = (PEER *)NULL;	server=servers;	/* In a future version we may want to match with or without area code */	while(server != (PEER *)NULL) {		if ((number != (char *)NULL)		    && (strcmp(server->realm, number) == 0)) {			return server;		}		if ((realm != (char *)NULL)		    && (strcmp(server->realm, realm) == 0)) {			maybe = server;		}		server = server->next;	} 	if (maybe == (PEER *)NULL) {		if (realm != (char *)NULL) {			maybe = server_default;		} else {			maybe = server_norealm;		}	}	return maybe;}/************************************************************************* * *	Function: find_server_byaddr * *	Purpose: Returns proxy server based on IP address and source port * *************************************************************************/PEER *find_server_byaddr(UINT4 ipaddr,u_short port){	PEER	*server;	extern PEER	*servers;	server=servers;	while ((server != (PEER *)NULL) && !((server->ipaddr == ipaddr) &&		((server->acctport == port) || (server->radport == port))) ) {		server = server->next;	}	return server;}/************************************************************************* * *	Function: send_proxy2server * *	Purpose: Forward a proxy request to a server *		 Calling routine has already encrypted password (if any) *		 and added our Proxy-State * *************************************************************************/void send_proxy2server(AUTH_REQ*authreq,PEER*server){	extern AUTH_REQ		*first_forwarded;	AUTH_HDR		*auth;	char			ip_str[32];	int			fd;	u_char			saveid;	u_short			total_length;	req2str(ip_str, sizeof(ip_str), authreq);	auth = (AUTH_HDR *)send_buffer;	if (authreq->code == PW_AUTHENTICATION_REQUEST) {		authreq->forw_port = server->radport;		fd = proxyfd;	} else if (authreq->code == PW_ACCOUNTING_REQUEST) {		authreq->forw_port = server->acctport;		fd = proxyacctfd;	} else {		log_err("unknown request type %d from %s ignored\n",			authreq->code, ip_str);		authreq->flags |= REQ_ERR|REQ_FREE;		return;	}	authreq->forw_id = getnextid(authreq);	/* getnextid sets REQ_ERR flag if unable to allocate id */	if ((authreq->flags & REQ_ERR) == REQ_ERR) {		return;	}	saveid = authreq->id;	authreq->id = authreq->forw_id;	authreq->forw_addr = server->ipaddr;	memcpy(authreq->forw_vector, authreq->vector, AUTH_VECTOR_LEN);	strcpy(authreq->forw_secret, server->secret);	debug("forwarding request from %s to %s/%d.%d for %s\n",		ip_str, ipaddr2strp(authreq->forw_addr), authreq->forw_port,		authreq->forw_id, authreq->realm);	total_length = build_packet(authreq, authreq->request, (char *)NULL,				    authreq->code, FW_SERVER, send_buffer, sizeof(send_buffer));	authreq->id = saveid;	memcpy(authreq->forw_vector, auth->vector, AUTH_VECTOR_LEN);	/* forward it to the server */        send_packet(fd, authreq->forw_addr, authreq->forw_port,		    send_buffer, total_length);	if (!(authreq->flags & REQ_DUP)) {		authreq->next = first_forwarded;		first_forwarded = authreq;		if (authreq == authreq->next) {			log_err("ERROR: circular queue detected at %d\n", __LINE__);		}	}	return;}/************************************************************************* * *	Function: getnextid * *	Purpose: Returns next ID for use in forwarding to this server *		 Use one ID counter 0..255 for all forwarded packets * *************************************************************************/u_char getnextid(AUTH_REQ *authreq){	extern AUTH_REQ	*first_forwarded;	AUTH_REQ	*qp;	AUTH_REQ	*prevqp;	static char	inuse[256];	u_short	 	newid;	static u_char	curid = 0;	static int	flushcount = 0;	extern int	max_proxy_time;	extern UINT4	now;	memset(inuse, 0, 256);	prevqp = (AUTH_REQ *)NULL;	qp = first_forwarded;	while (qp != (AUTH_REQ *)NULL) {		if (qp->timestamp + max_proxy_time < now) {			if (++flushcount % 100 == 0) {				debug("%d proxy requests expired unanswered\n",flushcount);			}			if (prevqp == (AUTH_REQ *)NULL) {				first_forwarded = qp->next;				reqfree(qp,"getnextid");				qp = first_forwarded;			} else {				prevqp->next = qp->next;				reqfree(qp,"getnextid");				qp = prevqp->next;			}		} else {			if (authreq->ipaddr == qp->ipaddr &&			    authreq->udp_port == qp->udp_port &&			    authreq->id == qp->id) {				authreq->flags |= REQ_DUP|REQ_FREE;				return qp->forw_id;			}			inuse[qp->forw_id]++;			if (qp == qp->next) {				log_err("ERROR: circular queue detected at %d\n", __LINE__);				qp->next = (AUTH_REQ *)NULL;			}			prevqp = qp;			qp = qp->next;		}	}	for (newid = curid; newid <= 255; newid++) {		if (inuse[newid] == 0) {			curid = ((newid+1) & 0xff);			return newid;		}	}	for (newid = 0; newid < curid; newid++) {		if (inuse[newid] == 0) {			curid = ((newid+1) & 0xff);			return newid;		}	}	/* no ids left, so log an error and mark packet for discard */	log_err("getnextid: out of IDs, dropping packet from %s\n",		req2strp(authreq));	authreq->flags |= REQ_ERR|REQ_FREE;	return 0;}/************************************************************************* *************************************************************************	Misc subroutines for proxy ************************************************************************* *************************************************************************//************************************************************************* * *	Function: proxy_report * *	Purpose: Log proxy queue status for debugging purposes * *	Uses External: first_forwarded * *************************************************************************/void proxy_report(void){	AUTH_REQ	*qp;	UINT4		oldest;	UINT4		clock;	int		n;	if (first_forwarded != (AUTH_REQ *)NULL) {		qp = first_forwarded;		n = 0;		clock = (UINT4)time((time_t *)NULL);		oldest = clock;		while (qp != (AUTH_REQ *)NULL) {			n++;			if (qp->timestamp < oldest) {				oldest = qp->timestamp;			}			qp = qp->next;		}		clock = clock - oldest;		log_err("%d in proxy queue, oldest %d seconds ago\n", n, clock);	} else {		log_err("no entries in proxy queue\n");	}}

⌨️ 快捷键说明

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