res_qry.c

来自「RADIUS协议的认证计费服务」· C语言 代码 · 共 1,034 行 · 第 1/2 页

C
1,034
字号
#ifdef USR_CCA/* * * Copyright (c) 1996 U.S. Robotics, Access Corp. * All rights reserved. * * Permission to copy, display, distribute and make derivative works * from this material in whole or in part for any purpose is granted * provided that the above copyright notice and this paragraph are * duplicated in all copies.  THIS SOFTWARE IS PROVIDED "AS IS" AND * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES INCLUDING, WITHOUT * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * * If providing code not subject to a copyright please indicate that the * code has been dedicated to the public. * *//* * Copyright [C] The Regents of the University of Michigan and Merit Network, * Inc. 1992, 1993, 1994, 1995, 1996, 1997, 1998 All Rights Reserved * * Permission to use, copy, and modify this software and its documentation  * for any purpose and without fee is hereby granted, provided:  * * 1) that the above copyright notice and this permission notice appear in all *    copies of the software and derivative works or modified versions thereof,  * * 2) that both the copyright notice and this permission and disclaimer notice  *    appear in all supporting documentation, and  * * 3) that all derivative works made from this material are returned to the *    Regents of the University of Michigan and Merit Network, Inc. with *    permission to copy, to display, to distribute, and to make derivative *    works from the provided material in whole or in part for any purpose. * * Users of this code are requested to notify Merit Network, Inc. of such use * by sending email to aaa-admin@merit.edu * * Please also use aaa-admin@merit.edu to inform Merit Network, Inc of any * derivative works. * * Distribution of this software or derivative works or the associated * documentation is not allowed without an additional license. * * Licenses for other uses are available on an individually negotiated * basis.  Contact aaa-license@merit.edu for more information. * * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE REGENTS OF THE * UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INC. DO NOT WARRANT THAT THE * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE.  The Regents of the * University of Michigan and Merit Network, Inc. shall not be liable for any * special, indirect, incidental or consequential damages with respect to any * claim by Licensee or any third party arising from use of the software. * * Merit AAA Server Support * Merit Network, Inc. * 4251 Plymouth Road, Suite C. * Ann Arbor, Michigan, USA 48105-2785 * * attn:  John Vollbrecht * voice: 734-764-9430 * fax:   734-647-3185 * email: aaa-admin@merit.edu * */static char     rcsid[] = "$Id: res_qry.c,v 1.1.1.1 2001/08/10 20:49:29 bonze Exp $";/**************************************************************************** * *			res_qry.c * *	This file contains the AATV and the functions required for *	Resource Querying. * ***************************************************************************/#include	<sys/param.h>#include	<sys/types.h>#include	<sys/socket.h>#include	<netinet/in.h>#include	<arpa/inet.h>#include	<sys/ioctl.h>#include	<sys/file.h>#include	<sys/time.h>#include	<sys/file.h>#include	<sys/wait.h>#include	<sys/stat.h>#if defined(sys5)#include	<sys/sysmacros.h>#endif	/* sys5 */#include	<net/if.h>#include	<stdio.h>#include	<stdlib.h>#include	<netdb.h>#include	<fcntl.h>#include	<errno.h>#include	<memory.h>#include	<signal.h>#include	<syslog.h>#include	<string.h>#include	"radius.h"extern int           debug_flag;extern AUTH_REQ_Q    global_auth_q;extern UINT4         self_ip[];extern u_short       auth_port;/**************************************************************************** * *	RES_QRY_RESP AATV definition * ***************************************************************************/static int rad_rq_resp_action PROTO ((AUTH_REQ *, int, char *));static int add_resources PROTO ((VALUE_PAIR *, char *, CLIENT_ENTRY *));static ASSIGNED_IP *make_ip_node PROTO ((UINT4, UINT4, USER_ENTRY *, int));static char nas_proc PROTO ((AUTH_REQ *, AUTH_REQ *));static char proxy_proc PROTO ((AUTH_REQ *, AUTH_REQ *));static int add_local_vpn PROTO ((AUTH_REQ *, char *));static AATV     rq_resp_aatv = DEF_AATV_DIRECT("RES_QRY_RESP",						rad_rq_resp_action);AATVPTR         rad_rq_resp_aatv = &rq_resp_aatv;/*************************************************************************** * *	Function: rq_req_init * *	Purpose: Make up AUTH_REQ structures with code PW_RESOUECE_QUERY_REQ *		 for each Proxy client and insert them into the given queue. * ***************************************************************************/voidrq_req_init (){	CLIENT_ENTRY   *client_ent;	CLIENT_ENTRY   *client_list;	char           *func = "rq_req_init";	dprintf (2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));	client_list = get_client_list ();	/* Process clients. */	for (client_ent = client_list;		client_ent != (CLIENT_ENTRY *) NULL;		client_ent = client_ent->next)	{		if ((((client_ent->client_type & CE_PROXY) != CE_PROXY) &&			    ((client_ent->client_type & CE_NAS) != CE_NAS)) ||			client_ent->version == VER1)		{			client_ent->state = GOT_RQ_RESP;			continue;		}		send_rq_req (client_ent);	}	return;} /* end of rq_req_init () *//**************************************************************************** * *	Function: rad_rq_resp_action *	Purpose: Action function of the RES_QRY_RESP AATV.  It handles the *		 incoming Resource Query Responses while in the Initialization *		 FSM. * ****************************************************************************/static intrad_rq_resp_action (authreq, value, afpar)AUTH_REQ       *authreq;int             value;char           *afpar;{	AUTH_REQ       *auth;	AUTH_REQ_Q     *aaq;	AATV           *paatv;	CLIENT_ENTRY   *ce;	char           *func = "rad_rq_resp_action";	dprintf (2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));	authreq->fsmstatus = EV_ACK;	aaq = queue_find (PW_RESOURCE_QUERY_REQ);	for (auth = aaq->q; auth != (AUTH_REQ *) NULL;		auth = auth->next)	{		if (auth->code != PW_RESOURCE_QUERY_REQ)		{			continue;		}		if (auth->ipaddr == authreq->ipaddr &&			auth->rep_id == authreq->rep_id)		{			break; /* Found original Resource Query Request. */		}	}	if (auth == (AUTH_REQ *) NULL)	{		/* Reply does not match any request.  Silently drop it */		return EV_NAK;	}	if (auth->type == USR_PROXY || auth->type == (USR_PROXY | USR_CHILD))	{		authreq->ipaddr = auth->nas_ip;		authreq->rep_id = auth->fwd_id;		paatv = find_aatv ("REPLY");		call_action (paatv, authreq, 0, "");		free_authreq (auth);		return EV_DONE;	}	if (get_vp (authreq->request, PW_NAS_IP_ADDRESS) == (VALUE_PAIR *) NULL)	{		logit (LOG_DAEMON, LOG_ERR,		       "%s: Missing NAS IP Address", func);		return EV_NAK;	}	if (get_vp_vend (authreq->request, PW_USR_RQ_INDEX, VC_USR) == NULL_VP)	{		logit (LOG_DAEMON, LOG_ERR,		       "%s: Missing Resource Query Index", func);		return EV_NAK;	}	if (find_client (authreq->ipaddr, &ce) != 0)	{		return EV_NAK;	}/* XXX Moved this code from find_client () - It didn't seem to get used XXX	if ((ce->client_type & CE_DAS ) != CE_DAS)	{		logit (LOG_DAEMON, LOG_ERR, "%s: Received a Resource Query Request from a RADIUS server that is not a DAS",			func);		return (EV_NAK);	}*/	/*	 *	Call add_resources() only if there are a/v pairs	 *	other than the NAS-IP-Address and the Index.	 */	if ((authreq->cur_count > 2) &&		add_resources (authreq->request,				authreq->client->file_pfx, ce) == EV_NAK)	{		return EV_NAK;	}	if ((ce->client_type & CE_NAS) == CE_NAS)	{		return nas_proc (auth, authreq);	}	else if ((ce->client_type & CE_PROXY) == CE_PROXY)	{		return proxy_proc (auth, authreq);	}	else	{		logit (LOG_DAEMON, LOG_ERR,"%s: Received Resource Query Response from a host that is not a NAS or a Proxy",		       func);		return EV_NAK;	}} /* end of rad_rq_resp_action () *//*************************************************************************** * *	Function: add_resources * *	Purpose: Creates resource records and places them on the appropriate *		 resource queue * **************************************************************************/static intadd_resources (vp_list, file_pfx, ce)VALUE_PAIR     *vp_list;char           *file_pfx;CLIENT_ENTRY   *ce;{	char            default_pool;	UINT4           ipaddr = 0;	UINT4           nas;	u_int		length;	int             nas_port = 0;	int             result = EV_ACK;	char           *name = (char *) NULL;	char           *packet;	VALUE_PAIR     *list;	VALUE_PAIR     *q;	VALUE_PAIR     *vp;	USER_ENTRY     *user = (USER_ENTRY *) NULL;	ADDR_POOL      *apool = (ADDR_POOL *) NULL;	ASSIGNED_IP   **a;	ASSIGNED_IP   **rem;	ASSIGNED_IP    *temp;	FILE_LIST      *file_ent;	struct in_addr  add;	char           *func = "add_resources";	dprintf (2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));	if ((q = get_vp (vp_list, PW_NAS_IP_ADDRESS)) == (VALUE_PAIR *) NULL)	{		return EV_NAK;	}	nas = q->lvalue;	if ((file_ent = find_file_ent (file_pfx)) == (FILE_LIST *) NULL)	{		logit (LOG_DAEMON, LOG_ERR,		       "%s: NULL file entry", func);		return EV_NAK;	}	if (file_ent->user_list == (USER_ENTRY *) NULL)	{		logit (LOG_DAEMON, LOG_ERR,		       "%s: No users defined in %s.users", func, file_pfx);		/*		 *	This is okay because if no users are defined,		 *	then no users can be authenticated.		 */		return EV_ACK;	}	q = vp_list;	for ( ; q != (VALUE_PAIR *) NULL ; q = q->next)	{		if (q->attribute != PW_USR_PACKET ||			q->ap->vendor_id != VC_USR)		{			continue;		}		if ((packet = (char *) malloc (q->lvalue)) == (char *) NULL)		{			logit (LOG_DAEMON, LOG_INFO,				"%s: Malloc Failed\n", func);			return EV_NAK;		}		memcpy (packet, q->strvalue, q->lvalue);		length = q->lvalue;		list = gen_valpairs ((AUTH_HDR *) packet, length,							ce->veps, GVP_DROP);		if ((vp = get_vp (list, PW_USER_NAME)) != (VALUE_PAIR *) NULL)		{			if ((name = strdup (vp->strvalue)) == (char *) NULL)			{				free (packet);				list_free (list);				logit (LOG_DAEMON, LOG_INFO,					"%s: Malloc Failed\n", func);				return EV_NAK;			}		}		else		{			free (packet);			list_free (list);			continue;		}		if ((vp = get_vp (list, PW_FRAMED_IP_ADDRESS))							!= (VALUE_PAIR *) NULL)		{			ipaddr = vp->lvalue;		}		else		{			/*			 *	Ok to not find a Framed IP Address.			 *	We could be managing Sessions-Allowed.			 */		}		if ((vp = get_vp (list, PW_NAS_PORT)) != (VALUE_PAIR *) NULL)		{			nas_port = vp->lvalue;		}		else		{			free (packet);			list_free (list);			continue;		}		free (packet);		list_free (list);		for (user = file_ent->user_list; user != (USER_ENTRY *) NULL;				user = user->next)		{			if (strcmp (user->name, name) == 0)			{				break;			}		}		if (user == (USER_ENTRY *) NULL)		{			logit (LOG_DAEMON, LOG_INFO,			       "%s: User %s does not exist", func, name);			free (name);			continue;		}		free (name); /* Don't need this anymore */		apool = file_ent->pool_list;		default_pool = 0;		if (strcmp (user->pool_name, DEF_POOL_NAME) != 0)		{			apool = apool->next;  /* First entry is Default pool */			for (; apool != (ADDR_POOL *) NULL; apool = apool->next)			{				if ((ipaddr & apool->netmask) == apool->network)				{					break;				}			}		}		else		{			default_pool = 1;		}		if (apool == (ADDR_POOL *) NULL)		{			add.s_addr = ipaddr;			logit (LOG_DAEMON, LOG_INFO,			       "%s: Couldn't find pool for %s",			       func, inet_ntoa (add));			continue;		}		if (!default_pool && apool->count >= apool->range)		{			add.s_addr = apool->ip_address;			logit (LOG_DAEMON, LOG_INFO,		  "%s: Address Pool %s full or this resource already allocated",				func, inet_ntoa (add));			continue;		}		if (user->count >= user->sessions)		{			logit (LOG_DAEMON, LOG_INFO,			    "%s: User %s cannot be assigned any more addresses",			       func, user->name);			continue;		}		user->count++;		/* Find a place in the address pool to insert new node */		a = &apool->user_q;		rem = a;		if (!default_pool && *a != (ASSIGNED_IP *) NULL)		{			for ( ; *a != (ASSIGNED_IP *) NULL ; a = &((*a)->next))			{				if ((*a)->ip_address == ipaddr)				{					add.s_addr = ipaddr;					logit (LOG_DAEMON, LOG_INFO,					      "%s: Address %s already assigned",					       func, inet_ntoa (add));					result = EV_NAK;					break;				}				if ((*a)->ip_address < ipaddr)				{					rem = &(*a)->next;				}			}		}		if (result == EV_NAK)		{			result = EV_ACK;			user->count--;			continue;		}		temp = make_ip_node (ipaddr, nas, user, nas_port);

⌨️ 快捷键说明

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