sendserver.c

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

C
939
字号
/* * 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 * *//* * * Public entry points in this file: * * dir_init * send_server * send_server_done * */static char     rcsid[] = "$Id: sendserver.c,v 1.1.1.1 2001/08/10 20:49:29 bonze Exp $";#include	<sys/types.h>#include	<sys/socket.h>#include	<netinet/in.h>#include	<arpa/inet.h>#include	<sys/param.h>#include	<sys/time.h>#if !(defined(FD_SET) || defined(linux))#include	<sys/select.h>#endif	/* FD_SET */#include	<errno.h>#include	<memory.h>#include	<netdb.h>#include	<stdio.h>#include	<stdlib.h>#include	<syslog.h>#include	<unistd.h>#include	"radius.h"#if !defined(__FreeBSD__) && !defined(_BSDI_VERSION) && !defined(__NetBSD__)/* commented by bonzeextern char    *sys_errlist[];*/extern __const char *__const _sys_errlist[];#endif	/* __FreeBSD__ */#ifndef DEFAULT_SERVER#define DEFAULT_SERVER	"127.0.0.1"#endif#ifndef DEFAULT_DIR#define DEFAULT_DIR	"../config"#endif#ifndef DEFAULT_DIR2#define DEFAULT_DIR2	"../config"#endif#ifndef DEFAULT_VERSION#define DEFAULT_VERSION	1#endifextern UINT2    send_buffer_size;extern char     recv_buffer[RAD_RECV_BUFFER_SIZE];extern char     send_buffer[RAD_SEND_BUFFER_SIZE];extern char     ourhostname[MAXHOSTNAMELEN];extern char    *progname;extern int      debug_flag;extern char    *radius_dir;int             radsock = -1;	/* fd for radius socket, if non-blocking mode */static int      sockfd = -1;static int      check_radius_reply PROTO((u_char *, u_int, char *, u_char *,						UINT4, SEND_DATA *, char *));static int      find_server PROTO((char *, int, UINT4 *, char *, char *));/************************************************************************* * *	Function: dir_init * *	Purpose: Initializes global variable for RADIUS clients. * **************************************************************************/voiddir_init (){	if (radius_dir == NULL || radius_dir[0] == '\0')	{		radius_dir = DEFAULT_DIR;		if (access (radius_dir, X_OK) != 0)		{			radius_dir = DEFAULT_DIR2;		}	}	return;} /* end of dir_init () *//************************************************************************* * *	Function: pack_list * *	Purpose: Packs an attribute value pair list into a buffer. * *	Returns: Number of octets packed. * *************************************************************************/static voidpack_list (vp, auth)VALUE_PAIR     *vp;AUTH_HDR       *auth;{	while (vp != NULL_VP)	{		avpair_out (vp, auth, send_buffer_size, (VENDOR_LIST *) NULL);		vp = vp->next;	}	return;} /* end of pack_list () *//************************************************************************* * *	Function: send_server * *	Purpose: Sends request to specified RADIUS server and waits *		 for response.  Request is retransmitted every *		 "response_timeout" seconds a maximum of "retry_max" *		 times.  Result is 0 if response was received, -1 if *		 a problem occurred, or +1 on no-response condition. *		 Returns request retransmit count in "retries" if *		 server does respond. * *	Returns: -1 ERROR_RC   -- on local error, *		  0 OK_RC      -- on valid response from server, *		  1 TIMEOUT_RC -- after retries * resp_timeout seconds, *		 -2 BADRESP_RC -- if response from server had errors. * **************************************************************************/int send_server (data, retries, msg)SEND_DATA      *data;		/* Data structure built by clients */int            *retries;	/* Maximum num of times to retransmit request */				/* Receives number of retries required, also */char           *msg;		/* Receives error or advisory message */{	u_short         seq_nbr;    /* Sequence number to use in request  */	u_int           length;	int             fptype;     /* Framed proto, ustype == PW_FRAMED */	int             i;	int             len;	int             result;	int             retry_max;	int             salen;	int             timeout;    /* Number of secs. to wait for response */	int             total_length;	int             ustype;     /* User service type for this user */	int		version;	UINT4           auth_ipaddr;	UINT4           lvalue;	AUTH_HDR       *auth;	VALUE_PAIR     *check;	VALUE_PAIR     *reply;	char           *passwd;		/* User password (unencrypted) */	char           *server_name;	/* Name of server to query */	char	       *vector;	struct sockaddr_in *sin;	struct servent *svp;	struct timeval  authtime;	fd_set          readfds;	struct sockaddr salocal;	struct sockaddr saremote;	char            ara_vector[ARA_PASS_LEN + 1];	char            file[MAXPATHLEN];	char            secret[MAX_SECRET_LENGTH + 1];	char            chap_auth;	u_char          md5buf[1 + AUTH_VECTOR_LEN];	u_char          buffer[AUTH_PASS_LEN + AUTH_VECTOR_LEN + 1];#if 0 /* Don't really do KCHAP */	u_char          user_secret[CHAP_VALUE_LENGTH + 1];#endif /* Do CHAP instead */	static char    *func = "send_server";	/* Set up some defaults */	dir_init ();	server_name = data->server;	if (server_name == (char *) NULL || server_name[0] == '\0')	{		server_name = DEFAULT_SERVER;	}	ustype = data->ustype;	if (ustype == 255) /* CHAP indicator */	{		chap_auth = 1;		ustype = PW_FRAMED;	}	else	{		chap_auth = 0;	}	if (find_server (server_name, ustype, &auth_ipaddr, secret, msg) != 0)	{		return (ERROR_RC);	}	timeout = data->timeout;	if (timeout == 0)	{		timeout++;	}	if (data->svc_port == 0)	{		if ((svp = getservbyname ("radius", "udp")) == NULL)		{			data->svc_port = PW_AUTH_UDP_PORT;		}		else		{			data->svc_port = ntohs(svp->s_port);		}	}	if (sockfd < 0)	{		if (radsock < 0)		{			if (sockfd < 0)			{				sockfd = socket (AF_INET, SOCK_DGRAM, 0);			}			if (sockfd < 0)			{				sprintf (msg, "socket: %s\n",					sys_errlist[errno]);				return (ERROR_RC);			}			len = sizeof (salocal);			sin = (struct sockaddr_in *) & salocal;			memset ((char *) sin, '\0', len);			sin->sin_family = AF_INET;			sin->sin_addr.s_addr = INADDR_ANY;			sin->sin_port = htons(0);			if (bind (sockfd, (struct sockaddr *) sin, len) < 0 ||				getsockname (sockfd, (struct sockaddr *) sin,								&len) < 0)			{				/* XXX close (sockfd); */				sprintf (msg, "bind: %s\n", sys_errlist[errno]);				return (ERROR_RC);			}			retry_max = *retries; /* Max. times to try for reply */			*retries = 0;	/* Init retry cnt for blocking call */		}		else		{			sockfd = radsock;			retry_max = 0;	/* No retries if non-blocking */		}	}	/* Build an authentication request */	auth = (AUTH_HDR *) send_buffer;	seq_nbr = data->seq_nbr;	if ((version = data->version) == 0)	{		version = DEFAULT_VERSION;	}	vector = build_header (version, (char *) NULL, data->code, seq_nbr,				 auth, (CLIENT_ENTRY *) NULL);	/* User Name */	if (data->user_name != (char *) NULL)	{		len = strlen (data->user_name);		if (len > AUTH_ID_LEN)		{			len = AUTH_ID_LEN;		}		attribute_out (auth, send_buffer_size, PW_USER_NAME, 0,				data->user_name, len, 0,				(VENDOR_LIST *) NULL);	}	passwd = data->password;	if ((data->code != PW_ACCOUNTING_REQUEST) && (passwd != (char *) NULL))	{		if (chap_auth)		{			/* User Password */			*md5buf = seq_nbr;  /* Pass CHAP identifier to RADIUS */			*buffer = seq_nbr;/* Put CHAP id in work area for md5 */#if 0 /* Don't really do KCHAP */			afs_pwd_to_secret (passwd, user_secret);/* Get secret */			passwd = user_secret;#endif /* Do CHAP instead */			len = strlen (passwd);			strcpy ((char *) buffer + 1, (char *) passwd);			memcpy ((char *) buffer + 1 + len,				(char *) vector, AUTH_VECTOR_LEN);			md5_calc (md5buf + 1, buffer,			  	1 + len + AUTH_VECTOR_LEN);			attribute_out (auth, send_buffer_size,					PW_CHAP_PASSWORD, 0, md5buf, 					AUTH_VECTOR_LEN + 1, 0,					(VENDOR_LIST *) NULL);		}#ifdef ASCEND		else if (data->arades == 1)		{			length = strlen (passwd);			if (length > ARA_PASS_LEN)			{				length = ARA_PASS_LEN;			}			for (i = 0; i < length; ++i)			{				passwd[i] = (u_char) (passwd[i] <<1);			}			if (des_init ())			{				/* XXX close (sockfd); */				sprintf (msg, "des_init: Can't initialize");				return (ERROR_RC);			}			dessetkey ((char *)passwd);			memcpy (ara_vector, vector, ARA_PASS_LEN);			endes (ara_vector);			attribute_out (auth, send_buffer_size,					PW_ASCEND_ARADES, VC_ASCEND,					ara_vector, ARA_PASS_LEN, 0,					(VENDOR_LIST *) NULL);			desdone ();		}#endif	/* ASCEND */		else		{			attribute_pw_out (auth, send_buffer_size,						passwd, secret);		}	}	/* State */	if (data->challenge > 0)	/* Add zero length state */	{		attribute_out (auth, send_buffer_size, PW_STATE, 0, "", 0, 0,				(VENDOR_LIST *) NULL);	}	/* Service Type */	if (ustype != -1)	{		lvalue = ustype;		attribute_out (auth, send_buffer_size, PW_SERVICE_TYPE, 0,				&lvalue, 0, 0, (VENDOR_LIST *) NULL);	}	/* Framed Protocol Type */	fptype = data->fptype;	if (fptype > 0)			/* if -t [slip | ppp] */	{		lvalue = fptype;		attribute_out (auth, send_buffer_size, PW_FRAMED_PROTOCOL, 0,				&lvalue, 0, 0, (VENDOR_LIST *) NULL);	}	/* Client IP Address */	if (data->client_id != (UINT4) -1)	{		attribute_out (auth, send_buffer_size, PW_NAS_IP_ADDRESS, 0,				&data->client_id, 0, 0,				(VENDOR_LIST *) NULL);	}	/* Client Port Number */	if (data->port_num != -1)	{		lvalue = data->port_num;		attribute_out (auth, send_buffer_size, PW_NAS_PORT, 0, &lvalue,				0, 0, (VENDOR_LIST *) NULL);	}	if (data->user_file != (char *) NULL) /* add a/v pairs from user_file */	{		sprintf (file, "%s.", data->user_file);		check = NULL_VP;		if ((user_find (file, data->group, 0, &check,				(VALUE_PAIR **) NULL, &reply, 1)) == 0)		{			pack_list (check, auth);			pack_list (reply, auth);		}	}	if (data->send_pairs != NULL_VP) /* add more a/v pairs */	{		pack_list (data->send_pairs, auth);	}	total_length = (u_short) build_request_mic (auth, secret);	sin = (struct sockaddr_in *) & saremote;	memset ((char *) sin, '\0', sizeof (saremote));

⌨️ 快捷键说明

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