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

📄 radiusd.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		       packet->src_port, packet->id,		       curreq->number);		return NULL;	}	/*	 *	The old request is finished.  We now check the	 *	authentication vectors.  If the client has sent us a	 *	request with identical code && ID, but different	 *	vector, then they MUST have gotten our response, so we	 *	can delete the original request, and process the new	 *	one.	 *	 *	If the vectors are the same, then it's a duplicate	 *	request, and we can send a duplicate reply.	 */	if (memcmp(curreq->packet->vector, packet->vector,		   sizeof(packet->vector)) == 0) {		RAD_SNMP_INC(rad_snmp.auth.total_dup_requests);		/*		 *	If the packet has been delayed, then silently		 *	send a response, and clear the delayed flag.		 *		 *	Note that this means if the NAS kicks us while		 *	we're delaying a reject, then the reject may		 *	be sent sooner than otherwise.		 *		 *	This COULD be construed as a bug.  Maybe what		 *	we want to do is to ignore the duplicate		 *	packet, and send the reject later.		 */		if (curreq->options & RAD_REQUEST_OPTION_DELAYED_REJECT) {			curreq->options &= ~RAD_REQUEST_OPTION_DELAYED_REJECT;			rad_send(curreq->reply, curreq->packet, curreq->secret);			return NULL;		}		/*		 *	Maybe we've saved a reply packet.  If so,		 *	re-send it.  Otherwise, just complain.		 */		if (curreq->reply->code != 0) {			DEBUG2("Sending duplicate reply "			       "to client %s:%d - ID: %d",			       client_name(packet->src_ipaddr),			       packet->src_port, packet->id);			rad_send(curreq->reply, curreq->packet, curreq->secret);			return NULL;		}		/*		 *	Else we never sent a reply to the NAS,		 *	as we decided somehow we didn't like the request.		 *		 *	This shouldn't happen, in general...		 */		DEBUG2("Discarding duplicate request from client %s:%d - ID: %d",		       client_name(packet->src_ipaddr),		       packet->src_port, packet->id);		return NULL;	} /* else the vectors were different, so we discard the old request. */	/*	 *	'packet' has the same source IP, source port, code,	 *	and Id as 'curreq', but a different authentication	 *	vector.  We can therefore delete 'curreq', as we were	 *	only keeping it around to send out duplicate replies,	 *	if the first reply got lost in the network.	 */	rl_delete(curreq);	/*	 *	The request is OK.  We can process it...	 *	 *	Don't bother checking the maximum nubmer of requests	 *	here.  we've just deleted one, so we KNOW we're under	 *	the limit if we add one more.	 */	return fun;}/* *  Do a proxy check of the REQUEST list when using the new proxy code. */static REQUEST *proxy_ok(RADIUS_PACKET *packet){	REALM *cl;	REQUEST *oldreq;	char buffer[32];	/*	 *	Find the original request in the request list	 */	oldreq = rl_find_proxy(packet);	/*	 *	If we haven't found the original request which was	 *	sent, to get this reply.  Complain, and discard this	 *	request, as there's no way for us to send it to a NAS.	 */	if (!oldreq) {		radlog(L_PROXY, "No outstanding request was found for proxy reply from home server %s:%d - ID %d",		       ip_ntoa(buffer, packet->src_ipaddr),		       packet->src_port, packet->id);		return NULL;	}	/*	 *	The proxy reply has arrived too late, as the original	 *	(old) request has timed out, been rejected, and marked	 *	as finished.  The client has already received a	 *	response, so there is nothing that can be done. Delete	 *	the tardy reply from the home server, and return NULL.	 */	if ((oldreq->reply->code != 0) ||	    (oldreq->finished)) {		radlog(L_ERR, "Reply from home server %s:%d  - ID: %d arrived too late for request %d. Try increasing 'retry_delay' or 'max_request_time'",		       ip_ntoa(buffer, packet->src_ipaddr),		       packet->src_port, packet->id,		       oldreq->number);		return NULL;	}	/*	 *	If there is already a reply, maybe this one is a	 *	duplicate?	 */	if (oldreq->proxy_reply) {		if (memcmp(oldreq->proxy_reply->vector,			   packet->vector,			   sizeof(oldreq->proxy_reply->vector)) == 0) {			radlog(L_ERR, "Discarding duplicate reply from home server %s:%d  - ID: %d for request %d",			       ip_ntoa(buffer, packet->src_ipaddr),			       packet->src_port, packet->id,			       oldreq->number);		} else {			/*			 *	? The home server gave us a new *			 *	proxy reply, which doesn't match * the			 *	old one.  Delete it			 !  */			DEBUG2("Ignoring conflicting proxy reply");		}		/*		 *	We've already received a reply, so		 *	we discard this one, as we don't want		 *	to do duplicate work.		 */		return NULL;	} /* else there wasn't a proxy reply yet, so we can process it */	/*	 *	 Refresh the old request, and update it with the proxy	 *	 reply.	 *	 *	? Can we delete the proxy request here?  * Is there	 *	any more need for it?	 *	 *	FIXME: we probably shouldn't be updating the time	 *	stamp here.	 */	oldreq->timestamp = time_now;	oldreq->proxy_reply = packet;	/*	 *	Now that we've verified the packet IS actually	 *	from that realm, and not forged, we can go mark the	 *	realms for this home server as active.	 *	 *	If we had done this check in the 'find realm by IP address'	 *	function, then an attacker could force us to use a home	 *	server which was inactive, by forging reply packets	 *	which didn't match any request.  We would think that	 *	the reply meant the home server was active, would	 *	re-activate the realms, and THEN bounce the packet	 *	as garbage.	 */	for (cl = mainconfig.realms; cl != NULL; cl = cl->next) {		if (oldreq->proxy_reply->src_ipaddr == cl->ipaddr) {			if (oldreq->proxy_reply->src_port == cl->auth_port) {				cl->active = TRUE;				cl->last_reply = oldreq->timestamp;			} else if (oldreq->proxy_reply->src_port == cl->acct_port) {				cl->acct_active = TRUE;				cl->last_reply = oldreq->timestamp;			}		}	}	return oldreq;}/* *	Do more checks, this time on the REQUEST data structure. * *	The main purpose of this code is to handle proxied requests. */static REQUEST *request_ok(RADIUS_PACKET *packet, uint8_t *secret,			   rad_listen_t *listener){	REQUEST		*request = NULL;	/*	 *	If the request has come in on the proxy FD, then	 *	it's a proxy reply, so pass it through the code which	 *	tries to find the original request, which we should	 *	process, rather than processing the reply as a "new"	 *	request.	 */	if (listener->type == RAD_LISTEN_PROXY) {		/*		 *	Find the old request, based on the current		 *	packet.		 */		request = proxy_ok(packet);		if (!request) {			return NULL;		}		rad_assert(request->magic == REQUEST_MAGIC);		/*		 *	We must have passed through the code below		 *	for the original request, which adds the		 *	reply packet to it.		 */		rad_assert(request->reply != NULL);	} else {		/* remember the new request */		/*		 *	A unique per-request counter.		 */		static int request_num_counter = 0;		request = request_alloc(); /* never fails */		request->packet = packet;		request->number = request_num_counter++;		strNcpy(request->secret, (char *)secret,			sizeof(request->secret));		/*		 *	Remember the request.		 */		rl_add(request);		/*		 *	ADD IN "server identifier" from "listen"		 *	directive!		 */		/*		 *	The request passes many of our sanity checks.		 *	From here on in, if anything goes wrong, we		 *	send a reject message, instead of dropping the		 *	packet.		 *		 *	Build the reply template from the request		 *	template.		 */		rad_assert(request->reply == NULL);		if ((request->reply = rad_alloc(0)) == NULL) {			radlog(L_ERR, "No memory");			exit(1);		}		request->reply->sockfd = request->packet->sockfd;		request->reply->dst_ipaddr = request->packet->src_ipaddr;		request->reply->src_ipaddr = request->packet->dst_ipaddr;		request->reply->dst_port = request->packet->src_port;		request->reply->src_port = request->packet->dst_port;		request->reply->id = request->packet->id;		request->reply->code = 0; /* UNKNOWN code */		memcpy(request->reply->vector, request->packet->vector,		       sizeof(request->reply->vector));		request->reply->vps = NULL;		request->reply->data = NULL;		request->reply->data_len = 0;	}	return request;}/* *	The main guy. */int main(int argc, char *argv[]){	REQUEST *request;	RADIUS_PACKET *packet;	u_char *secret;	unsigned char buffer[4096];	fd_set readfds;	int argval;	int pid;	int max_fd;	int status;	struct timeval *tv = NULL;#ifdef HAVE_SIGACTION	struct sigaction act;#endif	rad_listen_t *listener;	syslog_facility = LOG_DAEMON;#ifdef OSFC2	set_auth_parameters(argc,argv);#endif	if ((progname = strrchr(argv[0], '/')) == NULL)		progname = argv[0];	else		progname++;	debug_flag = 0;	spawn_flag = TRUE;	radius_dir = strdup(RADIUS_DIR);	/*	 *	Ensure that the configuration is initialized.	 */	memset(&mainconfig, 0, sizeof(mainconfig));#ifdef HAVE_SIGACTION	memset(&act, 0, sizeof(act));	act.sa_flags = 0 ;	sigemptyset( &act.sa_mask ) ;#endif	/*  Process the options.  */	while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:p:sSvxXyz")) != EOF) {		switch(argval) {			case 'A':				log_auth_detail = TRUE;				break;			case 'a':				if (radacct_dir) xfree(radacct_dir);				radacct_dir = strdup(optarg);				break;			case 'c':				/* ignore for backwards compatibility with Cistron */				break;			case 'd':				if (radius_dir) xfree(radius_dir);				radius_dir = strdup(optarg);				break;			case 'f':				dont_fork = TRUE;				break;			case 'h':				usage(0);				break;			case 'i':				if ((mainconfig.myip = ip_getaddr(optarg)) == INADDR_NONE) {					fprintf(stderr, "radiusd: %s: host unknown\n",						optarg);					exit(1);				}				break;			case 'l':				radlog_dir = strdup(optarg);				break;				/*				 *  We should also have this as a configuration				 *  file directive.				 */			case 'g':				syslog_facility = str2fac(optarg);				break;			case 'S':				log_stripped_names++;				break;			case 'p':				fprintf(stderr, "Ignoring deprecated command-line option -p");				break;			case 's':	/* Single process mode */				spawn_flag = FALSE;				dont_fork = TRUE;				break;			case 'v':				version();				break;				/*				 *  BIG debugging mode for users who are				 *  TOO LAZY to type '-sfxxyz -l stdout' themselves.				 */			case 'X':				spawn_flag = FALSE;				dont_fork = TRUE;				debug_flag += 2;				mainconfig.log_auth = TRUE;				mainconfig.log_auth_badpass = TRUE;				mainconfig.log_auth_goodpass = TRUE;				radlog_dir = strdup("stdout");				break;			case 'x':				debug_flag++;				break;			case 'y':				mainconfig.log_auth = TRUE;				mainconfig.log_auth_badpass = TRUE;				break;			case 'z':				mainconfig.log_auth_badpass = TRUE;				mainconfig.log_auth_goodpass = TRUE;				break;			default:				usage(1);				break;		}	}	/*	 *	Get our PID.	 */	radius_pid = getpid();	/*  Read the configuration files, BEFORE doing anything else.  */	if (read_mainconfig(0) < 0) {		exit(1);	}	/*	 *	If we're NOT debugging, trap fatal signals, so we can	 *	easily clean up after ourselves.	 *	 *	If we ARE debugging, don't trap them, so we can	 *	dump core.	 */	if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {#ifdef SIGSEGV#ifdef HAVE_SIGACTION		act.sa_handler = sig_fatal;		sigaction(SIGSEGV, &act, NULL);#else		signal(SIGSEGV, sig_fatal);#endif#endif	}	/*  Reload the modules.  */	DEBUG2("radiusd:  entering modules setup");	if (setup_modules() < 0) {		radlog(L_ERR|L_CONS, "Errors setting up modules");		exit(1);	}#ifdef HAVE_SYSLOG_H	/*	 *  If they asked for syslog, then give it to them.	 *  Also, initialize the logging facility with the	 *  configuration that they asked for.	 */	if (strcmp(radlog_dir, "syslog") == 0) {		openlog(progname, LOG_PID, syslog_facility);		radlog_dest = RADLOG_SYSLOG;	}	/* Do you want a warning if -g is used without a -l to activate it? */#endif	if (strcmp(radlog_dir, "stdout") == 0) {		radlog_dest = RADLOG_STDOUT;	} else if (strcmp(radlog_dir, "stderr") == 0) {		radlog_dest = RADLOG_STDERR;	}	/*  Initialize the request list.  */	rl_init();	/*	 *  Register built-in compare functions.	 */	pair_builtincompare_init();#ifdef WITH_SNMP	if (mainconfig.do_snmp) radius_snmp_init();#endif	/*	 *  Disconnect from session

⌨️ 快捷键说明

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