xtacacsd.c

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

C
1,593
字号
/* #define DEBUG1   #define DEBUG *//* * TACACS daemon suitable for using on Un*x systems. * * Janruary 1989, Greg Satz * * Copyright (c) 1989 by cisco Systems, Inc. * All rights reserved. * * VMS note: Stand-alone mode is the opposite from Unix systems. *//* HUJI - list of machines */#define	LOCAL_INTERNET_NAME	"MINNIE.ACS.WMICH.EDU"char           *TrustedHosts[] = {"HUMUS.CS.HUJI.AC.IL", "SHAWARMA.CS.HUJI.AC.IL",	"SHUM.CC.HUJI.AC.IL", "KINERET.HUJI.AC.IL",	"BATATA.FH.HUJI.AC.IL", "PLUTO.HUJI.AC.IL","MARS.HUJI.AC.IL", "MERCURY.HUJI.AC.IL", "COMA.HUJI.AC.IL", ""};#define	REMOTE_TACACS_TIMEOUT	5	/* Wait up to 5 seconds for reply					 * from remote server */#ifndef VMS#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/file.h>#include <netinet/in.h>#include <stdio.h>#include <errno.h>#include <pwd.h>#include <netdb.h>#include <sys/syslog.h>#include <utmp.h>#include <sys/time.h>#include <sys/types.h>#else				/* VMS */#include "includes.h"		/* Will include all needed files */#define index strchr#define	errno	socket_errno	/* Multinet calls it Socket_Errno */#define	read	socket_read#define	write	socket_write#define	close	socket_close#define	perror	socket_perror#endif				/* VMS */#ifdef SYSV#include <fcntl.h>#define index strchr#endif/* * TACACS protocol defintions */#define uchar unsigned char#define ulong unsigned long#include "tacacs.h"#define oresponse namelen#define oreason pwlen#define	TIMEOUT		(5*60)#define	TACACS_PORT	49#define VECTOR_LEN	16	/* random vector length */#define SECRET		"tempVAXtacacs"#define SEC_IN_DAY      (24*60*60)	/* seconds in a day */#define WARNING_PERIOD  14	/* days of expiration warning */#ifdef VMS#define	PASSWD_LENGTH	32	/* length of password for crypt */#else				/* VMS */#define	PASSWD_LENGTH	14	/* length of password for crypt */#endif				/* VMS */#define SOME_ARBITRARILY_LARGE_NUMBER 100/* our own structure -- neat, eh? */typedef struct newxtacacstype_{	xtacacstype     tp;	char            data[BUFSIZ];}               newxtacacstype;int             debug;		/* debugging flag */int             logging;	/* syslog logging flag */int             stand;		/* running standalone or not */char           *file;		/* validation filename */char           *wtmpfile;	/* wtmp format filename */FILE           *wtmpf;unsigned long   querytime;	/* time query came in */struct sockaddr_in from;int             fromlen;char            SenderHost[256];/* Who sent us the request - for logging */newxtacacstype  buf;char           *monthname[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};long            days_ere_month[] = {0, 31, 59, 90, 120, 151,181, 212, 243, 273, 304, 334};/* * main * We can be called from inetd or via the rc scripts directly * Parse arguments are act appropiately. */main (argc, argv)int             argc;char          **argv;{	int             cc,	                c,	                on = 1,	                s;	struct servent *sp;	tacacstype     *tp;	extern char    *optarg;	struct hostent *hp;	debug = 0;		/* no debugging */#ifdef VMS	logging = 1;		/* Full logging */	stand = 1;		/* Stand alone - we are run with RUN/DETACH */#else				/* VMS */	logging = 0;		/* No logging */	stand = 0;		/* under inetd */#endif	file = NULL;		/* /etc/passwd */	wtmpfile = NULL;	wtmpf = NULL;#ifdef LOG_LOCAL6	openlog ("tacacsd", LOG_PID, LOG_LOCAL6);#else	openlog ("tacacsd", LOG_PID);#endif#ifdef VMS	for (cc = 1; cc < argc; cc++)		switch (argv[cc][1])		{#else				/* VMS */	while ((c = getopt (argc, argv, "df:lsw:")) != EOF)		switch (c)		{#endif				/* VMS */		    case 'd':	/* debug */			debug = 1;			break;		    case 'f':	/* file name */#ifdef VMS			file = argv[++cc];#else				/* VMS */			file = optarg;#endif				/* VMS */			break;		    case 'l':	/* logging */			logging = 1;			break;		    case 's':	/* stand-alone */#ifdef VMS			stand = 0;#else				/* VMS */			stand = 1;#endif				/* VMS */			break;		    case 'w':#ifdef VMS			wtmpfile = argv[++cc];#else				/* VMS */			wtmpfile = optarg;#endif				/* VMS */			break;		    default:			fprintf (stderr, "%s: illegal switch\n", argv[0]);			exit (1);		}	if (debug)		syslog (LOG_DEBUG, "server starting\n");	read_tacacs_users_file ();	/* HUJI - read the users database */	if (stand)	{		/*		 * Background ourselves and let go of controlling tty		 */		if (!debug)		{#ifndef VMS			/* On VMS it will run from the beginning in				 * detach mode */			if (fork ())				exit (0);			for (c = 0; c < getdtablesize (); c++)				(void) close (c);			(void) open ("/", O_RDONLY);			(void) dup2 (0, 1);			(void) dup2 (0, 2);#ifndef SYSV			c = open ("/dev/tty", O_RDWR);			if (c >= 0)			{				ioctl (c, TIOCNOTTY, (char *) 0);				(void) close (c);			}#endif#ifdef LOG_LOCAL6			openlog ("tacacsd", LOG_PID, LOG_LOCAL6);#else			openlog ("tacacsd", LOG_PID);#endif#endif				/* !VMS */		}	}	if (stand)	{		/*		 * Pick up a socket		 */		if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)		{			syslog (LOG_ERR, "socket: %m\n");			exit (1);		}		/*		 * Get port we need to pay attention to		 */		bzero ((caddr_t) & from, sizeof (from));#ifdef sun		from.sin_family = AF_INET;		from.sin_addr.s_addr = INADDR_ANY;#endif		sp = getservbyname ("tacacs", "udp");		if (sp == NULL)			from.sin_port = ntohs (TACACS_PORT);		else			from.sin_port = ntohs (sp->s_port);		if (bind (s, &from, sizeof (from)) < 0)		{			syslog (LOG_ERR, "bind: %m\n");			exit (1);		}	}	else	{		s = 0;#ifndef VMS		if (ioctl (s, FIONBIO, &on) < 0)		{			syslog (LOG_ERR, "ioctl(FIONBIO): %m\n");			exit (1);		}#endif	}	/*	 * For 4.3BSD machines, this routine sets the file the pw routines	 * use to the given argument. We emulate it for others.	 */#ifdef VMS	if (getenv ("TACACS_UAF"))	{		printf ("Using localy defined UAF file\n");		init_tacacs_uaf ();	}	else		printf ("Using the standard VMS SYSUAF file\n");#else				/* VMS */	if (file != NULL)		setpwfile (file);#endif				/* VMS */	if (wtmpfile != NULL)	{		wtmpf = fopen (wtmpfile, "a+");		if (!wtmpf)			fprintf (stderr, "\nCan't open wtmp file \"%s\"", wtmpfile);	}	if (!stand)		alarm (TIMEOUT);again:	fromlen = sizeof (from);	c = recvfrom (s, &buf, sizeof (buf), 0, (caddr_t) & from, &fromlen);	if (c <= 0)	{		if (errno == EINTR && stand)			goto again;		syslog (LOG_ERR, "recvfrom: %m\n");		exit (1);	}/* Copy HP since next call to GetHostxxx will ruin it */#ifdef DEBUG	hp = gethostbyaddr (&from.sin_addr, sizeof (struct in_addr), AF_INET);	fprintf (stderr, "main: received validation request from %s\n",		 hp ? hp->h_name : (char *) inet_ntoa (from.sin_addr));#endif	if (logging)	{		hp = gethostbyaddr (&from.sin_addr, sizeof (struct in_addr), AF_INET);		if (hp != NULL)			strcpy (SenderHost, hp->h_name);		else			strcpy (SenderHost, (char *) inet_ntoa (from.sin_addr));		syslog (LOG_INFO, "validation request from %s\n", SenderHost);	}	if (buf.tp.version == TA_VERSION)		old_process (s, &from, &buf.tp);	else if (buf.tp.version == XTA_VERSION)		new_process (s, &from, &buf);	else if (logging)		syslog (LOG_INFO, "illegal version specified: %d\n", buf.tp.version);	if (stand)		goto again;	exit (0);}#ifndef VMS/* * pw_verify * verify the provided name/password. */pw_verify (name, passwd, ppw)#ifdef SYSVchar            name[SOME_ARBITRARILY_LARGE_NUMBER];char            passwd[SOME_ARBITRARILY_LARGE_NUMBER];#elsechar           *name,               *passwd;#endifstruct passwd **ppw;{	struct passwd  *pw;	setpwent ();	if (file != NULL)		setpwfile (file);	pw = getpwnam (name);#ifdef DEBUG	if (pw)		fprintf (stderr, "password: user %8.8s, password %13.13s\r\n",			 pw->pw_name, pw->pw_passwd);#endif	/*	 * Verify the entry.	 */	if (pw != NULL && *passwd != '\0' && *pw->pw_passwd != '\0')	{#ifdef SYSV		strcpy (passwd, (char *) crypt (passwd, pw->pw_passwd));#else		passwd = (char *) crypt (passwd, pw->pw_passwd);#endif		*ppw = pw;		if (strcmp (passwd, pw->pw_passwd) == 0)			return (1);	}	*ppw = NULL;	return (0);}#endif				/* VMS *//* * process * Perform necessary stuff to do a query operation. Return ANSWER. */old_process (s, client, tp)int             s;struct sockaddr_in *client;tacacstype     *tp;{#ifdef SYSV	char            name[SOME_ARBITRARILY_LARGE_NUMBER];	char            passwd[SOME_ARBITRARILY_LARGE_NUMBER];#else	char           *name,	               *passwd;#endif#ifdef VMS	int             pw;#else				/* VMS */	struct passwd  *pw;#endif	int             expired;	querytime = time (NULL);#ifdef DEBUG	fprintf (stderr, "process: starting\r\n");	fprintf (stderr, "process: namelen %d, pwdlen %d\r\n",		 tp->namelen, tp->pwlen);#endif#ifndef SYSV	name = (char *) malloc (tp->namelen + 1);	if (name == NULL)		perror ("Malloc");	passwd = (char *) malloc (tp->pwlen + 1);	if (passwd == NULL)		perror ("Malloc");	if (name == NULL || passwd == NULL)		return;#endif				/* not SYSV */	strncpy (name, (char *) (tp + 1), tp->namelen);	name[tp->namelen] = '\0';	strncpy (passwd, (char *) (tp + 1) + tp->namelen, tp->pwlen);	if (tp->pwlen > PASSWD_LENGTH)		tp->pwlen = PASSWD_LENGTH;	passwd[tp->pwlen] = '\0';#ifdef DEBUG	fprintf (stderr, "packet: %s %s\r\n", (char *) (tp + 1),		 (char *) (tp + 1) + tp->namelen);	fprintf (stderr, "local:  %s %s\r\n", name, passwd);#endif	/*	 * Assume failure	 */	tp->oresponse = TA_A_REJECTED;	tp->oreason = TA_A_DENIED;/* HUJI - check whether the user is in our local database */	{		char            phone[256],		                flags;		if (get_user_entry (name, passwd, &flags, phone))		{		/* got it ok */			if (flags & F_DIALBACK)			{	/* Need a dialback */				syslog (LOG_INFO, "Dialback requested by '%s' to phone %s\n",					name, phone);				tp->oreason = TA_A_EXPIRING;	/* Reject with expired								 * message */			}			else			{	/* OK - let him in */				syslog (LOG_INFO, "User '%s' passed-in according to NUI file\n",					name);				tp->oresponse = TA_A_ACCEPTED;				tp->oreason = TA_A_NONE;			}			goto o_ok;	/* jump over the regular					 * authorization */		}	}/* Remove @Host or %host form username if there is */	{		char           *p;		if ((p = strchr (name, '@')) != NULL)			*p = '\0';		else if ((p = strchr (name, '%')) != NULL)			*p = '\0';	}/* HUJI - end of modifications */#ifdef VMS	if ((verify_user (name, passwd, &pw) & 0x1) == 1)	{			/* Verify returned ok */		if (pw == USER_OK)		{			tp->oresponse = TA_A_ACCEPTED;			tp->oreason = TA_A_NONE;		}		else if (pw == USER_EXPIRING)		{			tp->oresponse = TA_A_ACCEPTED;			tp->oreason = TA_A_EXPIRING;		}		else if (pw == USER_EXPIRED)		{			tp->oreason = TA_A_EXPIRING;

⌨️ 快捷键说明

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