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

📄 radiusd.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * radiusd.c	Main loop of the radius server. * * Version:	$Id: radiusd.c,v 1.321.2.2 2005/04/11 23:45:21 aland Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program 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 General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2000,2001,2002,2003,2004  The FreeRADIUS server project * Copyright 1999,2000  Miquel van Smoorenburg <miquels@cistron.nl> * Copyright 2000  Alan DeKok <aland@ox.org> * Copyright 2000  Alan Curry <pacman-radius@cqc.com> * Copyright 2000  Jeff Carneal <jeff@apex.net> * Copyright 2000  Chad Miller <cmiller@surfsouth.com> *//* don't look here for the version, run radiusd -v or look in version.c */static const char rcsid[] ="$Id: radiusd.c,v 1.321.2.2 2005/04/11 23:45:21 aland Exp $";#include "autoconf.h"#include "libradius.h"#include <sys/file.h>#ifdef HAVE_NETINET_IN_H#	include <netinet/in.h>#endif#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <ctype.h>#ifdef HAVE_UNISTD_H#	include <unistd.h>#endif#include <signal.h>#ifdef HAVE_GETOPT_H#	include <getopt.h>#endif#ifdef HAVE_SYS_SELECT_H#	include <sys/select.h>#endif#ifdef HAVE_SYSLOG_H#	include <syslog.h>#endif#ifdef HAVE_SYS_WAIT_H#	include <sys/wait.h>#endif#ifndef WEXITSTATUS#	define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)#endif#ifndef WIFEXITED#	define WIFEXITED(stat_val) (((stat_val) & 255) == 0)#endif#include "radiusd.h"#include "rad_assert.h"#include "conffile.h"#include "modules.h"#include "request_list.h"#include "radius_snmp.h"/* *  Global variables. */const char *progname = NULL;const char *radius_dir = NULL;const char *radacct_dir = NULL;const char *radlog_dir = NULL;radlog_dest_t radlog_dest = RADLOG_FILES;const char *radlib_dir = NULL;int syslog_facility;int log_stripped_names;int debug_flag = 0;int log_auth_detail = FALSE;int need_reload = FALSE;int sig_hup_block = FALSE;const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;static time_t time_now;static pid_t radius_pid;/* *  Configuration items. */static int dont_fork = FALSE;static time_t start_time = 0;static int spawn_flag = TRUE;static int do_exit = 0;/* *	Static functions. */static void usage(int);static void sig_fatal (int);static void sig_hup (int);static int rad_status_server(REQUEST *request);/* *  Parse a string into a syslog facility level. */static int str2fac(const char *s){#ifdef LOG_KERN	if(!strcmp(s, "kern"))		return LOG_KERN;	else#endif#ifdef LOG_USER	if(!strcmp(s, "user"))		return LOG_USER;	else#endif#ifdef LOG_MAIL	if(!strcmp(s, "mail"))		return LOG_MAIL;	else#endif#ifdef LOG_DAEMON	if(!strcmp(s, "daemon"))		return LOG_DAEMON;	else#endif#ifdef LOG_AUTH	if(!strcmp(s, "auth"))		return LOG_AUTH;	else#endif#ifdef LOG_SYSLOG	if(!strcmp(s, "auth"))		return LOG_AUTH;	else#endif#ifdef LOG_LPR	if(!strcmp(s, "lpr"))		return LOG_LPR;	else#endif#ifdef LOG_NEWS	if(!strcmp(s, "news"))		return LOG_NEWS;	else#endif#ifdef LOG_UUCP	if(!strcmp(s, "uucp"))		return LOG_UUCP;	else#endif#ifdef LOG_CRON	if(!strcmp(s, "cron"))		return LOG_CRON;	else#endif#ifdef LOG_AUTHPRIV	if(!strcmp(s, "authpriv"))		return LOG_AUTHPRIV;	else#endif#ifdef LOG_FTP	if(!strcmp(s, "ftp"))		return LOG_FTP;	else#endif#ifdef LOG_LOCAL0	if(!strcmp(s, "local0"))		return LOG_LOCAL0;	else#endif#ifdef LOG_LOCAL1	if(!strcmp(s, "local1"))		return LOG_LOCAL1;	else#endif#ifdef LOG_LOCAL2	if(!strcmp(s, "local2"))		return LOG_LOCAL2;	else#endif#ifdef LOG_LOCAL3	if(!strcmp(s, "local3"))		return LOG_LOCAL3;	else#endif#ifdef LOG_LOCAL4	if(!strcmp(s, "local4"))		return LOG_LOCAL4;	else#endif#ifdef LOG_LOCAL5	if(!strcmp(s, "local5"))		return LOG_LOCAL5;	else#endif#ifdef LOG_LOCAL6	if(!strcmp(s, "local6"))		return LOG_LOCAL6;	else#endif#ifdef LOG_LOCAL7	if(!strcmp(s, "local7"))		return LOG_LOCAL7;	else#endif	{		fprintf(stderr, "%s: Error: Unknown syslog facility: %s\n",			progname, s);		exit(1);	}	/* this should never be reached */	return LOG_DAEMON;}/* *	Check if an incoming request is "ok" * *	It takes packets, not requests.  It sees if the packet looks *	OK.  If so, it does a number of sanity checks on it.  */static RAD_REQUEST_FUNP packet_ok(RADIUS_PACKET *packet,				  rad_listen_t *listener){	REQUEST		*curreq;	RAD_REQUEST_FUNP fun = NULL;	/*	 *	Some sanity checks, based on the packet code.	 */	switch(packet->code) {		case PW_AUTHENTICATION_REQUEST:			/*			 *	Check for requests sent to the wrong			 *	port, and ignore them, if so.			 */			if (listener->type != RAD_LISTEN_AUTH) {				RAD_SNMP_INC(rad_snmp.auth.total_packets_dropped);				radlog(L_ERR, "Authentication-Request sent to a non-authentication port from "					"client %s:%d - ID %d : IGNORED",					client_name(packet->src_ipaddr),				       packet->src_port, packet->id);				return NULL;			}			fun = rad_authenticate;			break;		case PW_ACCOUNTING_REQUEST:			/*			 *	Check for requests sent to the wrong			 *	port, and ignore them, if so.			 */			if (listener->type != RAD_LISTEN_ACCT) {				RAD_SNMP_INC(rad_snmp.acct.total_packets_dropped);				radlog(L_ERR, "Accounting-Request packet sent to a non-accounting port from "				       "client %s:%d - ID %d : IGNORED",				       client_name(packet->src_ipaddr),				       packet->src_port, packet->id);				return NULL;			}			fun = rad_accounting;			break;		case PW_AUTHENTICATION_ACK:		case PW_ACCESS_CHALLENGE:		case PW_AUTHENTICATION_REJECT:			/*			 *	Replies NOT sent to the proxy port get			 *	an error message logged, and the			 *	packet is dropped.			 */			if (listener->type != RAD_LISTEN_PROXY) {				RAD_SNMP_INC(rad_snmp.auth.total_packets_dropped);				radlog(L_ERR, "Authentication reply packet code %d sent to a non-proxy reply port from "				       "client %s:%d - ID %d : IGNORED",				       packet->code,				       client_name(packet->src_ipaddr),				       packet->src_port, packet->id);				return NULL;			}			fun = rad_authenticate;			break;		case PW_ACCOUNTING_RESPONSE:			/*			 *	Replies NOT sent to the proxy port get			 *	an error message logged, and the			 *	packet is dropped.			 */			if (listener->type != RAD_LISTEN_PROXY) {				RAD_SNMP_INC(rad_snmp.acct.total_packets_dropped);				radlog(L_ERR, "Accounting reply packet code %d sent to a non-proxy reply port from "				       "client %s:%d - ID %d : IGNORED",				       packet->code,				       client_name(packet->src_ipaddr),				       packet->src_port, packet->id);				return 0;			}			fun = rad_accounting;			break;		case PW_STATUS_SERVER:			if (!mainconfig.status_server) {				DEBUG("WARNING: Ignoring Status-Server request due to security configuration");				return NULL;			}			fun = rad_status_server;			break;		case PW_PASSWORD_REQUEST:			RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);			/*			 *  We don't support this anymore.			 */			radlog(L_ERR, "Deprecated password change request from client %s:%d - ID %d : IGNORED",					client_name(packet->src_ipaddr),			       packet->src_port, packet->id);			return NULL;			break;		default:			RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);			radlog(L_ERR, "Unknown packet code %d from client %s:%d "			       "- ID %d : IGNORED", packet->code,			       client_name(packet->src_ipaddr),			       packet->src_port, packet->id);			return NULL;			break;	} /* switch over packet types */	/*	 *	Don't handle proxy replies here.  They need to	 *	return the *old* request, so we can re-process it.	 */	if (listener->type == RAD_LISTEN_PROXY) {		return fun;	}	/*	 *	If there is no existing request of id, code, etc.,	 *	then we can return, and let it be processed.	 */	if ((curreq = rl_find(packet)) == NULL) {		/*		 *	Count the total number of requests, to see if		 *	there are too many.  If so, return with an		 *	error.		 */		if (mainconfig.max_requests) {			int request_count = rl_num_requests();			/*			 *	This is a new request.  Let's see if			 *	it makes us go over our configured			 *	bounds.			 */			if (request_count > mainconfig.max_requests) {				radlog(L_ERR, "Dropping request (%d is too many): "				       "from client %s:%d - ID: %d", request_count,				       client_name(packet->src_ipaddr),				       packet->src_port, packet->id);				radlog(L_INFO, "WARNING: Please check the radiusd.conf file.\n"				       "\tThe value for 'max_requests' is probably set too low.\n");				return NULL;			} /* else there were a small number of requests */		} /* else there was no configured limit for requests */		/*		 *	FIXME: Add checks for system load.  If the		 *	system is busy, start dropping requests...		 *		 *	We can probably keep some statistics		 *	ourselves...  if there are more requests		 *	coming in than we can handle, start dropping		 *	some.		 */		return fun;	}	/*	 *	"fake" requests MUST NEVER be in the request list.	 *	 *	They're used internally in the server.  Any reply	 *	is a reply to the local server, and any proxied packet	 *	gets sent outside of the tunnel.	 */	rad_assert((curreq->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0);	/*	 *	The current request isn't finished, which	 *	means that the NAS sent us a new packet, while	 *	we are still processing the old request.	 */	if (!curreq->finished) {		/*		 *	If the authentication vectors are identical,		 *	then the NAS is re-transmitting it, trying to		 *	kick us into responding to the request.		 */		if (memcmp(curreq->packet->vector, packet->vector,			   sizeof(packet->vector)) == 0) {			RAD_SNMP_INC(rad_snmp.auth.total_dup_requests);			/*			 *	It's not finished because the request			 *	was proxied, but there was no reply			 *	from the home server.			 */			if (curreq->proxy && !curreq->proxy_reply) {				/*				 *	We're taking care of sending				 *	duplicate proxied packets, so				 *	we ignore any duplicate				 *	requests from the NAS.				 *				 *	FIXME: Make it ALWAYS synchronous!				 */				if (!mainconfig.proxy_synchronous) {					RAD_SNMP_TYPE_INC(listener, total_packets_dropped);					DEBUG2("Ignoring duplicate packet from client "					       "%s:%d - ID: %d, due to outstanding proxied request %d.",					       client_name(packet->src_ipaddr),					       packet->src_port, packet->id,					       curreq->number);					return NULL;					/*					 *	We ARE proxying the request,					 *	and we have NOT received a					 *	proxy reply yet, and we ARE					 *	doing synchronous proxying.					 *					 *	In that case, go kick					 *	the home RADIUS server					 *	again.					 */				} else {					char buffer[64];					DEBUG2("Sending duplicate proxied request to home server %s:%d - ID: %d",					       ip_ntoa(buffer, curreq->proxy->dst_ipaddr),					       curreq->proxy->dst_port,					       curreq->proxy->id);				}				curreq->proxy_next_try = time_now + mainconfig.proxy_retry_delay;				rad_send(curreq->proxy, curreq->packet,					 curreq->proxysecret);				return NULL;			} /* else the packet was not proxied */			/*			 *	Someone's still working on it, so we			 *	ignore the duplicate request.			 */			radlog(L_ERR, "Discarding duplicate request from "			       "client %s:%d - ID: %d due to unfinished request %d",			       client_name(packet->src_ipaddr),			       packet->src_port, packet->id,			       curreq->number);			return NULL;		} /* else the authentication vectors were different */		/*		 *	The authentication vectors are different, so		 *	the NAS has given up on us, as we've taken too		 *	long to process the request.  This is a		 *	SERIOUS problem!		 */		RAD_SNMP_TYPE_INC(listener, total_packets_dropped);		radlog(L_ERR, "Dropping conflicting packet from "		       "client %s:%d - ID: %d due to unfinished request %d",		       client_name(packet->src_ipaddr),

⌨️ 快捷键说明

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