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

📄 radiusd.c

📁 RADIUS协议的认证计费服务
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	/*	 * Loop where we spend the rest of our life.	 */	result = 0;	memcpy ((char *) &savetime, (char *) &timeout, sizeof (struct timeval));	do	{		if (ddt != (FILE *) NULL && debug_flag <= 0)		{			fprintf (ddt, "Debug turned OFF\n");			if ((ddt == stderr) ||				(fileno(ddt) == STDERR_FILENO) ||				(fileno(ddt) == fileno(stderr)))			{				reset_stderr ("/dev/console", 1);			}			else			{				(void) fclose (ddt);			}			ddt = (FILE *) NULL;		}		/* Enable signal processing now */		sigprocmask (SIG_UNBLOCK, &signals, NULL);#ifdef USR_CCA		/* Send out the resource query requests */		if (qry_init == FALSE && dns_done == TRUE)		{			qry_init = TRUE;			rq_req_init ();			if (!alarm_set || global_auth_q.q)			{				alarm (1);				alarm_set++;			}		}#endif	/* USR_CCA */		memcpy ((char *) &readfds, (char *) &select_mask,							sizeof (readfds));		memcpy ((char *) &timeout, (char *) &savetime,			sizeof (struct timeval));		selcnt = select (maxfd + 1, &readfds, NULL, NULL, selecttime);		if (selcnt == 0)		{			logit (LOG_DAEMON, LOG_INFO,			     "%s: terminated by inactivity timeout (%ld secs.)",				progname, timeout.tv_sec);			sig_term (0);		}		if (selcnt < 0)		{			if (errno == EINTR)			{				continue;			}			logit (LOG_DAEMON, LOG_ALERT, "FATAL select: %s",				get_errmsg ());			dumpcore = 1;			abort ();		}		/*		 * Suspend signal processing while we do our stuff.		 * This is to prevent possible recursive calls to		 * nonreentrant functions.		 */		sigprocmask (SIG_BLOCK, &signals, NULL);/*#ifdef USR_CCA		* Send out the resource query requests *		if (qry_init == FALSE && dns_done == TRUE)		{			qry_init = TRUE;			rq_req_init ();			if (!alarm_set || global_auth_q.q)			{				alarm (1);				alarm_set++;			}		}*//* #endif	* USR_CCA */		for (i = 0; (aatv = sockfd_tv[i]) != NULL; i++)		{			time_t dummy_time;			select_cur = time (&dummy_time);			if (select_cur == (time_t) -1)			{				logit (LOG_DAEMON, LOG_ERR,					"%s: time() error, #%d", func, errno);			}			if (FD_ISSET(aatv->sockfd, &readfds))			{				len = sizeof (struct sockaddr_in);				memset ((char *) &fromsin, '\0', len);				result = recvfrom (aatv->sockfd,						   (char *) recv_buffer,						   (int) sizeof (recv_buffer) -							MAX_SECRET_LENGTH,						   (int) 0,						   (struct sockaddr *) &fromsin,						   & len);				if (result < 0)				{					if (errno == ECONNREFUSED)					{						result = 0;					}					else					{						break;					}				}				if (result > 0) /* Handle received request */				{					/* For some event.value to be filled */					/* in on return from AATV recv call */					event.state = ST_ANY;					event.a.aatv = aatv;					event.isproxy = 0;					event.xstring[0] = '\0';					authreq = aatv->recv (aatv->sockfd,						& fromsin,						ntohl(fromsin.sin_addr.s_addr),						result, & event);					if (authreq != (AUTH_REQ *) NULL)					{						authreq->fsm_aatv = aatv;						state_machine (event, authreq);					/* Set alarm if a request is pending */						if (!alarm_set &&							(global_acct_q.q ||							 global_auth_q.q))						{							alarm (1);							alarm_set++;						}					}				}			}			if ((time (0) - select_cur) > select_max)			{				tofmaxdelay = time (0);				select_max = tofmaxdelay - select_cur;			}		}	} while (result >= 0);	logit (LOG_DAEMON, LOG_ALERT, "%s: FATAL recvfrom: returned %d '%s'",		func, result, get_errmsg ());	dumpcore = 1;	abort ();} /* end of main () *//************************************************************************* * *	Function: aatv_process_end * *	Purpose: Start up next deferred request on a forking type AATV. * *************************************************************************/static voidaatv_process_end (aatv)AATV         *aatv;{	u_char          save_state;	int             evalue;	PROC_ENT       *pe;	AUTH_REQ       *authreq;	char            estring[sizeof (pe->estring)];	static char    *func = "aatv_process_end";	dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func));	/* Only applies for forking type AATVs. */	if (aatv == (AATV *) NULL ||		(aatv->aatvfunc_type != AA_FORK &&		 aatv->aatvfunc_type != AA_FREPLY))	{		return;	}	/*	 *	See if AATV was at process maximum and	 *	if we are able to de-queue anything.	 */	aatv->proc_cnt--;	if (((pe = aatv->proc_q) == (PROC_ENT *) NULL) ||		(aatv->proc_cnt >= aatv->proc_max))	{		return;	}	authreq = pe->authreq;	dprintf(2, (LOG_DAEMON, LOG_DEBUG,		"%s: proc_ent [%d '%s' '%s' %d '%s']",		func, pe->state,		(pe->fsm_aatv == (AATV *) NULL)			? (u_char *) "?" : pe->fsm_aatv->id,		(pe->sub_aatv == (AATV *) NULL)			? (u_char *) "?" : pe->sub_aatv->id,		pe->evalue,		(pe->estring[0] == '\0') ? "?" : pe->estring));	/* Unlink proc_ent from the authreq. */	save_state = authreq->state;	authreq->state = pe->state;	authreq->fsm_aatv = pe->fsm_aatv;	authreq->direct_aatv = pe->direct_aatv;	evalue = pe->evalue;	strncpy (estring, pe->estring, sizeof (estring));	dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: invoking AATV '%s'",		func, (pe->sub_aatv == (AATV *) NULL)					? (u_char *) "?" : pe->sub_aatv->id));	/* Unlink and free this proc_ent structure. */	authreq->proc_q = pe->next;	free_proc_ent (pe);	/* Now, process the de-queued request. */	call_action (aatv, authreq, evalue, estring);	authreq->state = save_state;	return;} /* end of aatv_process_end () *//************************************************************************* * *	Function: acc_chal_action * *	Purpose: Return EV_ACC_CHAL event for FSM purposes. * *************************************************************************/static intacc_chal_action (authreq, value, afpar)AUTH_REQ       *authreq;int             value;char           *afpar;{	static char    *func = "acc_chal_action";	dprintf(4, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func));	return EV_ACC_CHAL;} /* end of acc_chal_action () *//************************************************************************* * *	Function: authreq_dup_check * *	Purpose: Determine if a authreq1 is a duplicate of authreq2. * *	Returns: 0, if not a duplicate, *		 1, if is a duplicate.	  * *************************************************************************/static intauthreq_dup_check (auth1, auth2, p_pw_vp1, p_pw1, p_why)AUTH_REQ       *auth1;		/* Authreq to check. */AUTH_REQ       *auth2;		/* Authreq to compare against. */VALUE_PAIR    **p_pw_vp1;	/* Password found in auth1 (if any) */char          **p_pw1;		/* Decrypted password found in auth1 (if any) */char          **p_why;		/* Message indicating why decision was made. */{	int             vp_type;	/* attribute type (string, etc.) */	DICT_ATTR      *da;		/* What dictionary entry it is. */	VALUE_PAIR     *pw_vp1 = NULL_VP;	/* Save password. */	VALUE_PAIR     *pw_vp2 = NULL_VP;	/* Save password. */	VALUE_PAIR     *vp1;	VALUE_PAIR     *vp2;	char           *pw1 = *p_pw1;		/* Saved password (if any) */	char            pw2[AUTH_PASS_LEN + 1];	static char     pw1_buff[AUTH_PASS_LEN + 1];	static char    *func = "authreq_dup_check";	dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func));	/*	 *	If the packet types are different,	 *	or the source IP address is different,	 *	or the source UDP port is different,	 *	or the lengths are different, then	 *	it can not be a duplicate.	 */	if (auth1->code != auth2->code ||		/* Packet type */		auth1->ipaddr != auth2->ipaddr ||	/* Source IP address */		auth1->udp_port != auth2->udp_port ||	/* Source UDP port # */		auth1->rcv_len != auth2->rcv_len)	/* Packet length */	{		/* Definitely is NOT a duplicate. */		*p_why = "source, packet type or length different";		return (0);	}	/*	 *	If the packet type, source IP address,	 *	the source UDP port, the sequence number,	 *	and the reply vector are the same, then	 *	it is a duplicate.	 */	if (auth1->rep_id == auth2->rep_id) 	{		if (memcmp (auth1->repvec, auth2->repvec, AUTH_VECTOR_LEN) == 0)		{			/* Definitely IS a duplicate. */			*p_why = "reply id and authenticating vector match";			return (1);		}	}	/*	 *	Packet type, source IP address, source UDP port,	 *	and received length are all the same.  Plus	 *	either the sequence number or the authenticating	 *	vector are different (or both).	 *	 *	If the client is not a NAS (assume it's a PROXY),	 *	presume that it will change the reply id and the	 *	authenticating vector only for completely new	 *	requests, nor for retransmissions.  For instance,	 *	the Merit AAA Server does NOT change the reply id	 *	and the authenticating vector when it retransmits.	 *	 *	However, allow some non-NAS clients to require the	 *	more extensive checking by configuring "check_all"	 *	in the "clients" file, if that proves necessary.	 */	if ((auth1->client->client_type & CE_NAS) == CE_NAS) /* came from NAS */	{		/*		 * For some NAS vendors, the reply id and authenticating		 * vector are changed based on PPP exchanges, so if the		 * PPP client retransmits, everything is the same EXCEPT		 * the reply ID and vector.		 *		 * These requests need to be processed further by		 * comparing each and every attribute.   The attribute		 * order is assumed to be preserved for these kinds of		 * re-transmissions.		 *		 * The default should be to do more extensive checking,		 * but some NAS vendors may not behave in this way.		 * Therefore, let the check be overridden by a configuration		 * in the "clients" file.		 */		if ((auth1->client->client_type & CE_NO_CHECK) == CE_NO_CHECK)		{			/*			 * The clients file indicates that PPP retransmissions			 * won't cause the reply id and authenticating vector			 * to be changed.			 *			 * Leave now, indicating that this is NOT a duplicate.			 */			*p_why = "new request (NAS, config)";			return (0);		}		/* Fall through to more extensive checking. */	}	else /* was not from a NAS */	{		if ((auth1->client->client_type & CE_CHECK_ALL) == 0)		{			*p_why = "new request (non-NAS, default)";			return (0);		}	}	/*	 *	EXTENSIVE, attribute by attribute checking.	 *	 *	Still may be a duplicate, check all attributes to be sure.	 *	 *	"vp1" is the current attribute/value pair from the	 *	incoming request.	 *	 *	"vp2" is the attribute/value pair from the request	 *	which we are checking to see if it is a duplicate.	 */	for (vp1 = auth1->request, vp2 = auth2->request; 		(vp1 != NULL_VP) && (vp2 != NULL_VP);		vp1 = vp1->next, vp2 = vp2->next)	{		/*		 *	The lvalue of the attribute structure is the		 *	data payload for the integer types and the		 *	length of the string types.  Since it is always		 *	compared, check it here for effeciency.		 *		 *	Check it first, because new, incoming requests		 *	which are retransmissions of already enqueued		 *	requests will probably have the same attributes		 *	in the same order, differing only in their value(s).		 */		if (vp1->lvalue != vp2->lvalue) /* Definitely not duplicate. */		{			*p_why = "not a dup (value/length)";			return (0);		}		/* Easy check for attribute and vendor_id match */		if (vp1->ap != vp2->ap) /* Definitely is not a duplicate. */		{			*p_why = "not a dup (attr)";			return (0);		}		/* Compare tags, too. */		if (vp1->tag != vp2->tag)		{			*p_why = "not a dup (tags)";			return (0);		}		da = vp1->ap;		/* Get dictionary entry */		vp_type = da->type;	/* Attribute type (string, etc.) */		/*		 * 	If this attribute is not a string type,		 *	then all the comparisons are done.		 *	Attributes vp1 and vp2 are equal.		 */		if ((vp_type != PW_TYPE_STRING) &&			(vp_type != PW_TYPE_TAG_STR)#if defined(BINARY_FILTERS)		    && (vp_type != PW_TYPE_FILTER_BINARY)#endif /* BINARY_FILTERS */#if !defined(NO_EXTENDED_TYPES)		    && (vp_type != PW_TYPE_OCTETS)		    && (vp_type != PW_TYPE_VENDOR)#endif /* !defined(NO_EXTENDED_TYPES) */			)		{			continue;	/* Attributes vp1 and vp2 are equal. */		}		/*		 *	If this attribute is a User-Password,		 *	then special case code handles it below.		 */		if ((vp1->attribute != PW_USER_PASSWORD) ||			(da->vendor_id != VC_RADIUS))		{			/* Default string matching check. */			if (memcmp (vp1->strvalue, vp2->strvalue,					vp1->lvalue) == 0)			{				/*				 *	The request might be a duplicate				 *	(if all the rest match, too.)				 */

⌨️ 快捷键说明

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