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 + -
显示快捷键?