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

📄 radiud.mp.c

📁 国际标准协议的
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 *	RADIUS
 *	Remote Authentication Dial In User Service
 *
 */

static char sccsid[] =
"@(#)radiusd.c	2.0 Copyright 2000 Xiang Tiansheng";

#include	<sys/types.h>
#include	<sys/socket.h>
#include	<sys/time.h>
#include	<sys/file.h>
#include	<netinet/in.h>

#include	<stdio.h>
#include	<netdb.h>
#include	<fcntl.h>
#include	<pwd.h>
#include	<time.h>
#include	<ctype.h>
#include	<unistd.h>
#include	<signal.h>
#include	<errno.h>
#include	<sys/wait.h>
#include 	<sys/stat.h>

#if !defined(NOSHADOW)
#include	<shadow.h>
#endif /* !NOSHADOW */

#include	"radius.h"
#include	"account.h"

char		recv_buffer[4096];
char		send_buffer[4096];
char		*progname;
int		sockfd;
int		acctfd;
int		debug_flag;
int		spawn_flag;
int		acct_pid;
char		*radius_dir;
char		*radacct_dir;
UINT4		expiration_seconds;
UINT4		warning_seconds;
extern int	errno;
static AUTH_REQ		*first_request;
REALM_STRUCT	*first_realm;
CLIENT_STRUCT	*first_client;
USER_ONLINE	*first_online_user;

void		sig_fatal();
void		sig_hup();
void		sig_cleanup();
void		rad_passchange();

main(argc, argv)
int	argc;
char	**argv;
{
	int			salen;
	int			result;
	struct	sockaddr	salocal;
	struct	sockaddr	saremote;
	struct	sockaddr_in	*sin;
	struct	servent		*svp;
        u_short                 lport;
	AUTH_REQ		*authreq;
	AUTH_REQ		*radrecv();
	char			argval;
	int			t;
	int			pid;
	int			cons;
	fd_set			readfds;
	int			status;
	int			reply_code;
	int			auth__client();
	void			send_reply_to_client();

	progname = *argv++;
	argc--;

	debug_flag = 0;
	spawn_flag = 1;
	radacct_dir = RADACCT_DIR;
	radius_dir = RADIUS_DIR;

	signal(SIGHUP, sig_hup);
	signal(SIGINT, sig_fatal);
	signal(SIGQUIT, sig_fatal);
	signal(SIGILL, sig_fatal);
	signal(SIGTRAP, sig_fatal);
	signal(SIGIOT, sig_fatal);
	signal(SIGFPE, sig_fatal);
	signal(SIGTERM, sig_fatal);
	signal(SIGCHLD, sig_cleanup);

	while(argc) {

		if(**argv != '-') {
			usage();
		}

		argval = *(*argv + 1);
		argc--;
		argv++;

		switch(argval) {

		case 'a':
			if(argc == 0) {
				usage();
			}
			radacct_dir = *argv;
			argc--;
			argv++;
			break;
		
		case 'd':
			if(argc == 0) {
				usage();
			}
			radius_dir = *argv;
			argc--;
			argv++;
			break;
		
		case 's':	/* Single process mode */
			spawn_flag = 0;
			break;

		case 'v':
			version();
			break;

		case 'x':
			debug_flag = 1;
			break;
		
		default:
			usage();
			break;
		}
	}

	/* Initialize the dictionary */
	if(dict_init() != 0) {
		exit(-1);
	}
	
	/* Initialize the realms */
	if(client_realm_init() != 0) {
		exit(-1);
	}
	
	/* Mallocate a cache to init the online user record */
	if(user_online_init() != 0) {
		exit(-1);
	}

	/* Initialize Configuration Values */
	if(config_init() != 0) {
		exit(-1);
	}

	svp = getservbyname ("radius", "udp");
	if (svp == (struct servent *) 0) {
		fprintf (stderr, "%s: No such service: radius/udp\n",
			progname);
		exit(-1);
	}
	lport = (u_short) svp->s_port;

	sockfd = socket (AF_INET, SOCK_DGRAM, 0);
	if (sockfd < 0) {
		(void) perror ("auth socket");
		exit(-1);
	}

	sin = (struct sockaddr_in *) & salocal;
        memset ((char *) sin, '\0', sizeof (salocal));
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	sin->sin_port = lport;

	result = bind (sockfd, & salocal, sizeof (*sin));
	if (result < 0) {
		(void) perror ("auth bind");
		exit(-1);
	}

	/*
	 * Open Accounting Socket.
	 */
	/* svp = getservbyname ("radacct", "udp");
	if (svp == (struct servent *) 0) {
		fprintf (stderr, "%s: No such service: %s/%s\n",
			progname, "radacct", "udp");
		exit(-1);
	} */
	lport = htons(ntohs(lport) +1);
	acctfd = socket (AF_INET, SOCK_DGRAM, 0);
	if (acctfd < 0) {
		(void) perror ("acct socket");
		exit(-1);
	}

	sin = (struct sockaddr_in *) & salocal;
        memset ((char *) sin, '\0', sizeof (salocal));
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	sin->sin_port = lport;

	result = bind (acctfd, & salocal, sizeof (*sin));
	if (result < 0) {
		(void) perror ("acct bind");
		exit(-1);
	}

	/*
	 *	Disconnect from session
	 */
	if(debug_flag == 0) {
		pid = fork();
		if(pid < 0) {
			fprintf(stderr, "%s: Couldn't fork\n",
						progname);
			exit(-1);
		}
		if(pid > 0) {
			exit(0);
		}
	}

	/*
	 *	Disconnect from tty
	 */
	for (t = 32; t >= 3; t--) {
		if(t != sockfd && t != acctfd) {
			close(t);
		}
	}

#if !defined(M_UNIX)
	/*
	 * Open system console as stderr
	 */
	cons = open("/dev/console", O_WRONLY | O_NOCTTY);
	if(cons != 2) {
		dup2(cons, 2);
		close(cons);
	}
#endif
	/*
	 * If we are able to spawn processes, we will start a child
	 * to listen for Accounting requests.  If not, we will 
	 * listen for them ourself.
	 */

/*
	if(spawn_flag) {
		acct_pid = fork();
		if(acct_pid < 0) {
			fprintf(stderr, "%s: Couldn't fork\n",
						progname);
			exit(-1);
		}
		if(acct_pid > 0) {
			close(acctfd);
			acctfd = -1;
		}
		else {
			close(sockfd);
			sockfd = -1;
		}
	}
*/		



	/*
	 *	Receive user requests
	 */
	sin = (struct sockaddr_in *) & saremote;

	for(;;) {

		FD_ZERO(&readfds);
		if(sockfd >= 0) {
			FD_SET(sockfd, &readfds);
		}
		if(acctfd >= 0) {
			FD_SET(acctfd, &readfds);
		}

		status = select(32, &readfds, NULL, NULL, NULL);
		if(status == -1) {
			if (errno == EINTR)
				continue;
			sig_fatal(101);
		}
		if(sockfd >= 0 && FD_ISSET(sockfd, &readfds)) {
			salen = sizeof (saremote);
			result = recvfrom (sockfd, (char *) recv_buffer,
				(int) sizeof(recv_buffer),
				(int) 0, & saremote, & salen);

			if(result > 0) {

#ifdef CHECK_KNOWNCLIENT
				if(!knownclient(ntohl(sin->sin_addr.s_addr))) {
					/* packet, meet floor */

					char lbuf[128];
					sprintf(lbuf, "Unknown Client - %s",
						inet_ntoa(sin->sin_addr));
					log_err(lbuf);
					continue;
				}						
#endif

				authreq = radrecv(
					ntohl(sin->sin_addr.s_addr),
					ntohs(sin->sin_port),
					recv_buffer, result, sockfd);
				if(auth_client(authreq) == 0){
					radrespond(authreq, sockfd);
				
				}else{	reply_code = PW_AUTHENTICATION_REJECT;	
					send_reply_to_client(authreq,(char *)NULL,sockfd,reply_code);
				}
			}
			else if(result < 0 && errno == EINTR) {
				result = 0;
			}
		}
		if(acctfd >=0 && FD_ISSET(acctfd, &readfds)) {
			salen = sizeof (saremote);
			result = recvfrom (acctfd, (char *) recv_buffer,
				(int) sizeof(recv_buffer),
				(int) 0, & saremote, & salen);

			if(result > 0) {
				authreq = radrecv(
					ntohl(sin->sin_addr.s_addr),
					ntohs(sin->sin_port),
					recv_buffer, result, acctfd);
				if(auth_client(authreq) == 0) {
					radrespond(authreq, acctfd);
		
				}else{	reply_code = PW_ACCOUNTING_RESPONSE;	
					send_reply_to_client(authreq,(char *)NULL,acctfd,reply_code);
				}
			}
			else if(result < 0 && errno == EINTR) {
				result = 0;
			}
		}
	}
}

/*************************************************************************
 *
 *	Function: radrecv
 *
 *	Purpose: Receive UDP client requests, build an authorization request
 *		 structure, and attach attribute-value pairs contained in
 *		 the request to the new structure.
 *
 *************************************************************************/

AUTH_REQ	*
radrecv(host, udp_port, buffer, length, activefd)
UINT4	host;
u_short	udp_port;
u_char	*buffer;
int	length;
int	activefd;
{
	u_char		*ptr;
	AUTH_HDR	*auth;
	int		totallen;
	int		attribute;
	int		attrlen;
	DICT_ATTR	*attr;
	DICT_ATTR	*dict_attrget();
	char		string[64];
	UINT4		lvalue;
	char		*ip_hostname();
	VALUE_PAIR	*first_pair;
	VALUE_PAIR	*prev;
	VALUE_PAIR	*pair;
	AUTH_REQ	*authreq;

	/*
	 * Pre-allocate the new request data structure
	 */

	if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) ==
						(AUTH_REQ *)NULL) {
		fprintf(stderr, "%s: no memory\n", progname);
		exit(-1);
	}

	auth = (AUTH_HDR *)buffer;
	totallen = ntohs(auth->length);

	DEBUG("radrecv: Request from host %lx code=%d, id=%d, length=%d\n",
				(u_long)host, auth->code, auth->id, totallen);

	/*
	 * Fill header fields
	 */
	authreq->ipaddr = host;
	authreq->udp_port = udp_port;
	authreq->id = auth->id;
	authreq->code = auth->code;
	authreq->proxy_state = 0;
	memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN);
	

	/*
	 * Extract attribute-value pairs
	 */
	ptr = auth->data;
	length -= AUTH_HDR_LEN;
	first_pair = (VALUE_PAIR *)NULL;
	prev = (VALUE_PAIR *)NULL;

	while(length > 0) {

		attribute = *ptr++;
		attrlen = *ptr++;
		if(attrlen < 2) {
			length = 0;
			continue;
		}
		attrlen -= 2;
		if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) {
			DEBUG("Received unknown attribute %d\n", attribute);
		}
		else if ( attrlen >= AUTH_STRING_LEN ) {
			DEBUG("attribute %d too long, %d >= %d\n", attribute,
				attrlen, AUTH_STRING_LEN);
		}
		else {
			if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
						(VALUE_PAIR *)NULL) {
				fprintf(stderr, "%s: no memory\n",
						progname);
				exit(-1);
			}
			strcpy(pair->name, attr->name);
			pair->attribute = attr->value;
			pair->type = attr->type;
			pair->next = (VALUE_PAIR *)NULL;

			switch(attr->type) {

			case PW_TYPE_STRING:
				memcpy(pair->strvalue, ptr, attrlen);
				pair->strvalue[attrlen] = '\0';
				debug_pair(stdout, pair);
				if(first_pair == (VALUE_PAIR *)NULL) {
					first_pair = pair;
				}
				else {
					prev->next = pair;
				}
				prev = pair;
				break;
			
			case PW_TYPE_INTEGER:
			case PW_TYPE_IPADDR:
				memcpy(&lvalue, ptr, sizeof(UINT4));
				pair->lvalue = ntohl(lvalue);
				debug_pair(stdout, pair);
				if(first_pair == (VALUE_PAIR *)NULL) {
					first_pair = pair;
				}
				else {
					prev->next = pair;
				}
				prev = pair;
				break;
			
			default:
				DEBUG("    %s (Unknown Type %d)\n", attr->name,attr->type);
				free(pair);
				break;
			}

		}
		ptr += attrlen;
		length -= attrlen + 2;
	}
	authreq->request = first_pair;
	return(authreq);
}


/**************** function multi_thre(authreq,activefd) ***************/

multi_thre(authreq,activefd)
AUTH_REQ	*authreq;
int		activefd;
{
	int	reply_code;

	switch(authreq->code) {

	case PW_AUTHENTICATION_REQUEST:
		rad_authenticate(authreq, activefd);
		break;

	case PW_ACCOUNTING_REQUEST:
		rad_accounting(authreq, activefd);
		break;

#ifdef PASSCHANGE
	
	case PW_PASSWORD_REQUEST:
		rad_passchange(authreq, activefd);
		break;

#endif
	
	default:
		break;
	}
	return(0);
}


⌨️ 快捷键说明

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