sendserver.c

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

C
939
字号
	sin->sin_family = AF_INET;	sin->sin_addr.s_addr = htonl(auth_ipaddr);	sin->sin_port = htons(data->svc_port);	for (;;)	{		/*		 * Retransmission loop.		 */		if (debug_flag >= 2)		{			dumpit (LOG_DAEMON, LOG_DEBUG,				(u_char *) auth, total_length, 0,				"%s: sending packet to %s:%d", func,				inet_ntoa(sin->sin_addr),				ntohs(sin->sin_port));		}		sendto (sockfd, (char *) auth, (int) total_length, (int) 0,			(struct sockaddr *) sin, sizeof (struct sockaddr_in));		if (radsock >= 0)		{		/* If non-blocking */			/*			 *	Return stuff to be saved for evaluation			 *	of reply when it comes in.			 */			strcpy (msg, secret);			memcpy (msg + strlen (msg) + 1, (char *) vector,				AUTH_VECTOR_LEN);			return 1;	/* Positive return means no error */		}		authtime.tv_usec = 0L;		authtime.tv_sec = (long) timeout;		FD_ZERO (&readfds);		FD_SET (sockfd, &readfds);		if (select (sockfd + 1, &readfds, NULL, NULL, &authtime) < 0)		{			if (errno == EINTR)				continue;			sprintf (msg, "select: %s\n", sys_errlist[errno]);			/* XXX close (sockfd); */			return (ERROR_RC);		}		if (FD_ISSET (sockfd, &readfds))		{			break;		}		/*		 * Timed out waiting for response.  Retry "retry_max" times		 * before giving up.  If retry_max = 0, don't retry at all.		 */		if (++(*retries) >= retry_max)		{			if (debug_flag > 0)			{				fprintf (stderr, "\n");			}			sprintf (msg,				"No reply from RADIUS server \"%s(%u)\"\n",				 ip_hostname (auth_ipaddr), data->svc_port);			/* XXX close (sockfd); */			return (TIMEOUT_RC);		}		else		{			if (debug_flag > 0)			{				fprintf (stderr, ".");			}		}	}	salen = sizeof (saremote);	len = recvfrom (sockfd, recv_buffer,			   (int) sizeof (recv_buffer) - MAX_SECRET_LENGTH,			   (int) 0, &saremote, &salen);	if (len <= 0)	{		sprintf (msg, "recvfrom: %s\n", sys_errlist[errno]);		/* XXX close (sockfd); */		return (ERROR_RC);	}	length = len;	/*	 * More debugging	 */	if (debug_flag >= 2)	{		dumpit (LOG_DAEMON, LOG_DEBUG, 			(u_char *) recv_buffer, length, 0,			"%s: received reply", func);	}	result = check_radius_reply ((u_char *) recv_buffer, length, secret,					(u_char *) vector, seq_nbr, data, msg);	/* XXX close (sockfd); */	return (result);} /* end of send_server () *//************************************************************************* * *	Function: check_radius_reply * *	Purpose: Verify items in returned packet. * *	Returns: OK_RC       -- upon success, *		 BADRESP_RC  -- if anything looks funny. * **************************************************************************/static int check_radius_reply (buffer, len, secret, vector, seq_nbr, data, msg)u_char         *buffer;u_int           len;char           *secret;u_char         *vector;UINT4           seq_nbr;SEND_DATA      *data;char           *msg;{	int             result;	int             secretlen;	int             totallen;	int             version;	u_short         code;	u_short         rcv_id;	AUTH_HDR       *auth;	AUTH_HDR1      *ah1;	VALUE_PAIR     *vp;	VALUE_PAIR     *rep_vp;	u_char          calc_digest[AUTH_VECTOR_LEN];	u_char          reply_digest[AUTH_VECTOR_LEN];	auth = (AUTH_HDR *) buffer;	if (auth->code == PW_EXTENDED_FORMAT)	{		rcv_id = ntohs(auth->id);		code = ntohs(auth->command);		version = auth->flag_ver & AUTH_HDR_VERSION_BITS;		totallen = ntohs(auth->length);		if ((result = check_mic (auth, totallen, secret,						 (CLIENT_ENTRY *) NULL)) != 0)		{			sprintf (msg, "Received invalid %s in reply",				result < 0 ? "MIC" : "TIMESTAMP");			return (BADRESP_RC);		}	}	else	{		ah1 = (AUTH_HDR1 *) auth;		code = ah1->code;		rcv_id = ah1->id;		version = VER1;		totallen = ntohs(ah1->length);		memcpy ((char *) reply_digest,			(char *) ah1->vector, AUTH_VECTOR_LEN);		memcpy ((char *) ah1->vector, (char *) vector, AUTH_VECTOR_LEN);		secretlen = strlen (secret);		memcpy (buffer + totallen, secret, secretlen);		md5_calc (calc_digest, (char *) auth, totallen + secretlen);		if (memcmp ((char *) reply_digest, (char *) calc_digest,						AUTH_VECTOR_LEN) != 0)		{			sprintf (msg,				"Received invalid reply digest from server\n");			return (BADRESP_RC);		}		seq_nbr = (u_char) seq_nbr;	}	if (totallen > len)	{		sprintf (msg, "Received poorly formed packet (length = %d)\n",			len);		return (BADRESP_RC);	}	if (seq_nbr != rcv_id)	{		sprintf (msg, "Received non-matching id in server response\n");		return (BADRESP_RC);	}	if (debug_flag)	{		fprintf (stderr, "Received attribute/value pair(s):\n");	}		vp = gen_valpairs (auth, len, (VENDOR_LIST *) NULL, GVP_SILENT);	msg[0] = '\0';	for (rep_vp = get_vp (vp, PW_REPLY_MESSAGE);		rep_vp != NULL_VP;		rep_vp = get_vp (rep_vp->next, PW_REPLY_MESSAGE))	{		strcat (msg, rep_vp->strvalue);		strcat (msg, "\n");	/* Artificial newline. */	}	/* Acceptable return code */	if ((code == PW_ACCESS_ACCEPT) ||		(code == PW_PASSWORD_ACK) ||		(code == PW_ACCESS_CHALLENGE) ||#ifdef ASCEND		(code == PW_PASSWORD_EXPIRED) ||#endif	/* ASCEND */		(code == PW_ACCOUNTING_RESPONSE))	{		result = OK_RC;	}	else	{		result = BADRESP_RC;	}	data->result = code;	/* Report any attributes returned from the remote RADIUS server */	if (data->receive_pairs == NULL_VP)	{		data->receive_pairs = vp;	}	else	{		list_cat (&data->receive_pairs, vp);	}	return (result);} /* end of check_radius_reply *//************************************************************************* * *	Function: find_match * *	Purpose: See if given IP address matches any address of hostname. * *	Returns:  0 success *		 -1 failure * **************************************************************************/static int find_match (ip_addr, hostname)UINT4          *ip_addr;char           *hostname;{	UINT4           addr;	char           *ptr;	char          **paddr;	struct hostent *hp;	char            hn[255];	strcpy (hn, hostname);	if ((ptr = (char *) strtok (hn, " :\t\n\r")) == (char *) NULL)	{		return (-1);	}	if (good_ipaddr (ptr) == 0)	{		if (*ip_addr == ntohl(inet_addr (ptr)))		{			return (0);		}	}	else	{		if ((hp = gethostbyname (ptr)) == (struct hostent *) NULL)		{			return (-1);		}		if (hp->h_addr_list != (char **) NULL)		{			for (paddr = hp->h_addr_list; *paddr; paddr++)			{				addr = ** (UINT4 **) paddr;				if (ntohl(addr) == *ip_addr)				{					return (0);				}			}		}	}	return (-1);} /* end of find_match *//************************************************************************* * *	Function: find_server * *	Purpose: Look up the given server name in the clients file. * *	Returns:  0 success *		 -1 failure * **************************************************************************/static int find_server (server_name, ustype, ip_addr, secret, msg)char           *server_name;int             ustype;UINT4          *ip_addr;char           *secret;char           *msg;{	static UINT4    myipaddr = 0;	int             len;	int             line_nbr = 0;	int             result;	FILE           *clientfd;	char           *h;	char           *s;	char           *host2;	char            buffer[128];	char            fname[MAXPATHLEN];	char            hostnm[AUTH_ID_LEN + 1];	/* Get the IP address of the authentication server */	if ((*ip_addr = get_ipaddr (server_name)) == (UINT4) 0)	{		sprintf (msg, "No such server: \"%s\"\n", server_name);		return (-1);	}	/* Just use dummy secret for management polls */	if (ustype == PW_ADMINISTRATIVE_USER) /* was old PW_MANAGEMENT_POLL */	{		strcpy (secret, MGMT_POLL_SECRET);		return 0;	}	sprintf (fname, "%s/%s", radius_dir, RADIUS_CLIENTS);	if ((clientfd = fopen (fname, "r")) == (FILE *) NULL)	{		sprintf (msg, "Couldn't open file \"%s\"\n", fname);		return (-1);	}	if (!myipaddr)	{		if ((myipaddr = get_ipaddr (ourhostname)) == 0)		{			sprintf (msg, "Couldn't get our own ip address\n");			fclose (clientfd);			return (-1);		}	}	result = 0;	while (fgets (buffer, sizeof (buffer), clientfd) != (char *) NULL)	{		line_nbr++;		if (*buffer == '#')		{			continue;		}		/* First hostname... */		if ((h = (char *) strtok (buffer, " \t\n\r")) == NULL)		{			continue;		}		memset (hostnm, '\0', AUTH_ID_LEN);		len = strlen (h);		if (len > AUTH_ID_LEN)		{			len = AUTH_ID_LEN;		}		strncpy (hostnm, h, len);		hostnm[AUTH_ID_LEN] = '\0';		/* ... and secret field */		if ((s = (char *) strtok (NULL, " \t\n\r")) == NULL)		{			continue;		}		memset (secret, '\0', MAX_SECRET_LENGTH);		len = strlen (s);		if (len > MAX_SECRET_LENGTH)		{			len = MAX_SECRET_LENGTH;		}		strncpy (secret, s, len);		secret[MAX_SECRET_LENGTH] = '\0';		if (!strchr (hostnm, '/')) /* If single name form */		{			if (find_match (ip_addr, hostnm) == 0)			{				result++;				break;			}		}		else /* <name1>/<name2> "paired" form */		{			strtok (hostnm, "/"); /* replaces "/" with NULL char */			host2 = (char *) strtok (NULL, " ");			if (find_match (&myipaddr, hostnm) == 0)			{	     /* If we're the 1st name, target is 2nd */				if (find_match (ip_addr, host2) == 0)				{					result++;					break;				}			}			else	/* Check to see if we are the second name */			{				if (find_match (&myipaddr, host2) == 0)				{ /* We are the 2nd name, target is 1st name */					if (find_match (ip_addr, hostnm) == 0)					{						result++;						break;					}				}			}		}	}	fclose (clientfd);	if (result == 0)	{		memset (buffer, '\0', sizeof (buffer));		memset (secret, '\0', sizeof (secret));		sprintf (msg, "Couldn't find server in \"%s/%s\": \"%s\"\n",			 radius_dir, RADIUS_CLIENTS, server_name);		return (-1);	}	return 0;} /* end of find_server () *//************************************************************************* * *	Function: send_server_done * *	Purpose: Clean up after done with send_server(). * **************************************************************************/voidsend_server_done (){	if (sockfd >= 0)	{		close (sockfd);	}	return;} /* end of send_server_done () */

⌨️ 快捷键说明

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