#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  xtacacsd xtacacsd/Makefile xtacacsd/changetac.c
#   xtacacsd/include xtacacsd/inet_ntoa.c xtacacsd/strerror.c
#   xtacacsd/syslog.3 xtacacsd/syslog.c xtacacsd/tacacs.doc
#   xtacacsd/tacacs.h xtacacsd/tacacsd.8 xtacacsd/tacpasswd.c
#   xtacacsd/xtacacsd.c xtacacsd/include/paths.h xtacacsd/include/sys
#   xtacacsd/include/sys/syslog.h
# Wrapped by schaefer@dirt on Mon Aug 26 23:10:11 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'xtacacsd' ; then
    echo shar: Creating directory \"'xtacacsd'\"
    mkdir 'xtacacsd'
fi
if test -f 'xtacacsd/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/Makefile'\"
else
echo shar: Extracting \"'xtacacsd/Makefile'\" \(763 characters\)
sed "s/^X//" >'xtacacsd/Makefile' <<'END_OF_FILE'
X# add -DSYSV as appropriate, -DPW_QUOTA if your passwd struct has one
XCFLAGS=-g -DDEBUG -DBSD43
X
X# may need to -lBSD, -lbsd, or some such
XLIBS=-lresolv -lm
X
X# include these if necessary
X#XOBJS=syslog.o strerror.o
X
Xall:	xtacacsd tacpasswd changetac
X
Xxtacacsd: xtacacsd.c inet_ntoa.o $(SYSLOG)
X	${CC} -Iinclude ${CFLAGS} -o $@ xtacacsd.c inet_ntoa.o \
X		$(SYSLOG) ${LIBS}
X
Xinet_ntoa.o: inet_ntoa.c
X	${CC} -Iinclude ${CFLAGS} -c -o $@ inet_ntoa.c
X
Xsyslog.o: syslog.c
X	${CC} -Iinclude ${CFLAGS} -c -o $@ syslog.c
X
Xstrerror.o: strerror.c
X	${CC} ${CFLAGS} -c -o $@ strerror.c
X
Xtacpasswd: tacpasswd.c
X	${CC} ${CFLAGS} -o $@ tacpasswd.c ${LIBS}
X
Xchangetac: changetac.c
X	${CC} ${CFLAGS} -o $@ changetac.c ${LIBS}
X
Xclean:
X	rm -f xtacacsd tacpasswd changetac a.out core *.o
END_OF_FILE
if test 763 -ne `wc -c <'xtacacsd/Makefile'`; then
    echo shar: \"'xtacacsd/Makefile'\" unpacked with wrong size!
fi
# end of 'xtacacsd/Makefile'
fi
if test -f 'xtacacsd/changetac.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/changetac.c'\"
else
echo shar: Extracting \"'xtacacsd/changetac.c'\" \(17519 characters\)
sed "s/^X//" >'xtacacsd/changetac.c' <<'END_OF_FILE'
X/*
X * changetac
X *
X * This program maintains the /etc/tacpasswd file.  It allows users to
X * change their own TACACS entries.
X *
X * The password generator routines are from Brandon Allbery, as
X * distribured in  comp.sources.misc, volume 5, pwgen.
X *
X * Written by: David Hampton, 20 February 1990.
X * From the tacpaswd program written by: David Hampton, 30 June 89.
X */
X
X#ifdef SYSV
X#define random rand
X#define srandom srand
X#endif
X
X/*
XPath: xanth!mcnc!gatech!cwjcc!hal!ncoast!allbery
XFrom: allbery@ncoast.UUCP (Brandon S. Allbery)
XNewsgroups: comp.sources.misc
XSubject: v05i059: pwgen -- random-but-pronounceable password generator
XMessage-ID: <13184@ncoast.UUCP>
XDate: 26 Nov 88 04:44:18 GMT
XSender: allbery@ncoast.UUCP
XReply-To: allbery@ncoast.UUCP (Brandon S. Allbery)
XOrganization: Cleveland Public Access UN*X, Cleveland, Oh
XLines: 328
XApproved: allbery@ncoast.UUCP
X
XPosting-number: Volume 5, Issue 59
XSubmitted-by: "Brandon S. Allbery" <allbery@ncoast.UUCP>
XArchive-name: pwgen
X
X[Dr. Jekyll and Mr. Hyde, anyone?  ;-)  ++bsa]
X
XI've described this program, in its OSI Superboard-II incarnation, in
Xcomp.unix.wizards and news.sysadmin.  Now, here's the code for a UN*X
Xversion.  It seems to work OK on ncoast, except for some oddness in the
X"random" selections -- which are probably the result of our not having a
Xgood RNG.  (Could someone mail me one or more of the alternative
Xgenerators?  Or maybe even the source to BSD random(), assuming that it
Xfalls outside the subset of BSD code that can be traced to AT&T?  To put it
Xmildly, our random number generator isn't.)
X
XThis is not as complete as the original program, which actually had a list
Xof characters (the current one uses phonemes) which were most likely to
Xfollow other phonemes.  On the other hand, this version does use phonemes
Xrather than characters, so its creations are more pronounceable as a rule
Xthan those of the original.  The resulting passwords aren't quite as
X"natural" as the original, however.  (That may be for the best; the original
Xwas intended as a simple experiment to see if a rule for "proper English
Xwords" could be defined in terms of rules which related letters.  This was
Xbefore I got to college and learned that such things were rather unlikely,
Xbut the original program still did a pretty good job of spewing out some
Xcommon English words.  That can't be said for *this* program.)
X
XTo compile:	cc -O -o pwgen pwgen.c -lm
X(The sqrt() function is used in an attempt to produce a random number which
Xis "weighted" toward one end of the range, so as to prefer one end of a list
Xof "spellings" for a phoneme over the other end.  It seems to work, but with
Xthis rotted RNG, I can't be absolutely certain.  A trial distribution seems
Xto be correct, however.)
X
XWhat's the intent?  I find that I can remember a "word" better if I can
Xpronounce it.  This may or may not be true for other people, but *anything*
Xthat encourages the use of random passwords is an improvement on what I
Xtypically see at client sites every day.  So this program spits out
Xpasswords which are virtually guaranteed not to be found in the dictionary,
Xbut are (usually) pronounceable to speakers of English.  (The tables can be
Xmodified for other languages, but they're rather hairy.  Perhaps I'll write
Xa version which loads "compiled" language descriptions, and let the compiler
Xdeal with the hairy stuff.  Hey, they were even hairier in the BASIC
Xversion!)
X
XOh, well, shar and enjoy.
X
X++Brandon, sitting on the other side of the fence for the moment
X*/
X
X/*
X * Generate (hopefully) pronounceable random passwords.  These can often be
X * remembered more easily than completely random passwords, and are immune to
X * dictionary searches, etc.
X *
X * The original version of this program was written in BASIC on an OSI
X * Superboard II SBC.  That version is long gone (the SB2's cassette drive
X * was never trustworthy, it eventually scrambled the tape), but the basic
X * (pardon the pun) idea lives on here, with a few modification like basing
X * the selection on "graphs" (actually, they are a restricted set of phonemes)
X * and having randomly-selected spellings for those graphs.
X */
X
X#include <stdio.h>
X#include <math.h>
X
X#define RANDOM(c)	((int) (((random(c) & 0x7fff) / 32767.0) * (c)))
X
Xchar *spelling[] = {
X/*a*/	"a",				(char *) 0,	/* 2*/
X/*A*/	"a",	"ae",	"ai",		(char *) 0,	/* 6*/
X/*b*/	"b",				(char *) 0,	/* 8*/
X/*ch*/	"ch",				(char *) 0,	/*10*/
X/*d*/	"d",				(char *) 0,	/*12*/
X/*e*/	"e",				(char *) 0,	/*14*/
X/*E*/	"e",	"ee",	"ie",		(char *) 0,	/*18*/
X/*f*/	"f",	"ph",	"gh",		(char *) 0,	/*22*/
X/*g*/	"g",				(char *) 0,	/*24*/
X/*h*/	"h",				(char *) 0,	/*26*/
X/*i*/	"i",	"e",			(char *) 0,	/*29*/
X/*I*/	"i",	"ai",			(char *) 0,	/*32*/
X/*i'*/	"i",	"ei",			(char *) 0,	/*35*/
X/*j*/	"j",	"g",			(char *) 0,	/*38*/
X/*k*/	"k",	"c",			(char *) 0,	/*41*/
X/*l*/	"l",				(char *) 0,	/*43*/
X/*m*/	"m",				(char *) 0,	/*45*/
X/*n*/	"n",				(char *) 0,	/*47*/
X/*ng*/	"ng",				(char *) 0,	/*49*/
X/*o*/	"o",	"a",	"ah",		(char *) 0,	/*53*/
X/*O*/	"o",	"oh",			(char *) 0,	/*56*/
X/*oo*/	"oo",	"u",			(char *) 0,	/*59*/
X/*OO*/	"oo",	"w",			(char *) 0,	/*62*/
X/*p*/	"p",				(char *) 0,	/*64*/
X/*qu*/	"qu",				(char *) 0,	/*66*/
X/*r*/	"r",				(char *) 0,	/*68*/
X/*s*/	"s",	"c",			(char *) 0,	/*71*/
X/*sh*/	"sh",	"s",			(char *) 0,	/*74*/
X/*t*/	"t",				(char *) 0,	/*76*/
X/*th*/	"th",				(char *) 0,	/*78*/
X/*TH*/	"th",				(char *) 0,	/*80*/
X/*u*/	"u",				(char *) 0,	/*82*/
X/*U*/	"u",	"oo",			(char *) 0,	/*85*/
X/*v*/	"v",				(char *) 0,	/*87*/
X/*x*/	"x",				(char *) 0,	/*89*/
X/*y*/	"y",				(char *) 0,	/*91*/
X/*z*/	"z",	"s",			(char *) 0,	/*94*/
X};
X
Xstruct graph {
X	char *graph;
X	char type;
X#define CONSONANT	0
X#define VOWEL_LONG	1
X#define VOWEL_SHORT	2
X#define VOWEL_OTHER	3
X#define VOWEL_MASK	3
X#define iscons(c)	(((c)->type & VOWEL_MASK) == 0)
X#define isvowel(c)	(((c)->type & VOWEL_MASK) != 0)
X/*	char frequency;			*/	/* unused for now */
X	char **spellings;
X/*	struct graph **following;	*/	/* maybe later */
X} graph[] = {
X	"a",	VOWEL_SHORT,	&spelling[0],
X	"A",	VOWEL_LONG,	&spelling[2],
X	"b",	CONSONANT,	&spelling[6],
X	"ch",	CONSONANT,	&spelling[8],
X	"d",	CONSONANT,	&spelling[10],
X	"e",	VOWEL_SHORT,	&spelling[12],
X	"E",	VOWEL_LONG,	&spelling[14],
X	"f",	CONSONANT,	&spelling[18],
X	"g",	CONSONANT,	&spelling[22],
X	"h",	CONSONANT,	&spelling[24],
X	"i",	VOWEL_SHORT,	&spelling[26],
X	"I",	VOWEL_LONG,	&spelling[29],
X	"i'",	VOWEL_OTHER,	&spelling[32],
X	"j",	CONSONANT,	&spelling[35],
X	"k",	CONSONANT,	&spelling[38],
X	"l",	CONSONANT,	&spelling[41],
X	"m",	CONSONANT,	&spelling[43],
X	"n",	CONSONANT,	&spelling[45],
X	"ng",	CONSONANT,	&spelling[47],
X	"o",	VOWEL_SHORT,	&spelling[49],
X	"O",	VOWEL_LONG,	&spelling[53],
X	"oo",	VOWEL_SHORT,	&spelling[56],
X	"OO",	VOWEL_LONG,	&spelling[59],
X	"p",	CONSONANT,	&spelling[62],
X	"qu",	CONSONANT,	&spelling[64],
X	"r",	CONSONANT,	&spelling[66],
X	"s",	CONSONANT,	&spelling[68],
X	"sh",	CONSONANT,	&spelling[71],
X	"t",	CONSONANT,	&spelling[74],
X	"th",	CONSONANT,	&spelling[76],
X	"TH",	CONSONANT,	&spelling[78],
X	"u",	VOWEL_SHORT,	&spelling[80],
X	"U",	VOWEL_LONG,	&spelling[82],
X	"v",	CONSONANT,	&spelling[85],
X	"x",	CONSONANT,	&spelling[87],
X	"y",	CONSONANT,	&spelling[89],
X	"z",	CONSONANT,	&spelling[91],
X	0,	0,		&spelling[94],
X};
X
Xstruct graph *vowel[] = {
X	&graph[0],	&graph[1],	&graph[5],	&graph[6],
X	&graph[10],	&graph[11],	&graph[12],	&graph[19],
X	&graph[20],	&graph[21],	&graph[22],	&graph[30],
X	&graph[31],
X	(struct graph *) 0,
X};
X
Xstruct graph *consonant[] = {
X	&graph[2],	&graph[3],	&graph[4],	&graph[7],
X	&graph[8],	&graph[9],	&graph[13],	&graph[14],
X	&graph[15],	&graph[16],	&graph[17],	&graph[18],
X	&graph[23],	&graph[24],	&graph[25],	&graph[26],
X	&graph[27],	&graph[28],	&graph[29],	&graph[32],
X	&graph[33],	&graph[34],	&graph[35],
X	(struct graph *) 0,
X};
X
X/*
X * Randomly select a graph from the specifield array.  Eventually, this should
X * account for graph frequencies as well.
X */
X
Xstruct graph *selgraph(graphs)
X	struct graph **graphs;
X{
X	register int cnt;
X
X	for (cnt = 0; graphs[cnt] != (struct graph *) 0; cnt++)
X		;
X	return graphs[RANDOM(cnt)];
X}
X
X/*
X * Randomly select a spelling for the specified graph.  This is not linear:
X * earlier spellings are preferred over later ones, but the latter do
X * sometimes sneak in.
X */
X
Xchar *selspell(graph)
X	struct graph *graph;
X{
X	register int cnt, sel;
X
X	for (cnt = 0; graph->spellings[cnt] != (char *) 0; cnt++)
X		;
X	if (cnt == 0) {
X		fprintf(stderr, "PANIC: selspell(%s) got count(spellings) == 0\n", graph->graph);
X		exit(2);
X	}
X	if (cnt == 1)
X		return *graph->spellings;
X/*
X * This may not be the best way to do it... maybe Weemba'd care to lend a
X * hand here?  After all, my specialty is programming, NOT math.
X */
X	if ((sel = cnt - (int) sqrt((double) RANDOM(cnt * cnt) + 1) - 1) < 0 || sel >= cnt) {
X#ifdef BUGCATCH
X		fprintf(stderr, "PANIC: selspell(%s) got nlrand(%d) == %d\n", graph->graph, cnt, sel);
X		exit(2);
X#else
X		sel = 0;
X#endif
X	}
X	return graph->spellings[sel];
X}
X
X/*
X * Choose the next source for a graph.  The rules are:  a consonant MUST be
X * followed by a vowel; a vowel may be followed by a vowel of a different
X * type or by a consonant, but never more than two consecutive vowel graphs.
X */
X
Xchoosenext(cur, prev)
X{
X	if (cur == CONSONANT)
X		return VOWEL_MASK;
X	else if (prev == -1 || (prev & VOWEL_MASK) != 0)
X		return CONSONANT;
X	else if (RANDOM(10) == 5)
X		return VOWEL_MASK;
X	else
X		return CONSONANT;
X}
X
X/*
X * We are passed an array of (struct graph *); choose an entry randomly and
X * assemble a string fitting the size constraint.  We use the original (OSI)
X * paradigm:  alternate consonants and vowels, with the option of two vowels
X * in a row occasionally.  The only difference is that they must be different
X * *types* of vowels, a distinction that the OSI version didn't consider.
X */
X
Xpwgen(initial, pw, maxlen)
X	struct graph **initial;
X	char *pw;
X{
X	int pwlen, state, prev, tmp;
X	struct graph *graph;
X	char *spelling;
X
X	pwlen = 0;
X	state = initial[0]->type;
X	prev = -1;
X	while (pwlen < maxlen - 1) {
X		do {
X			graph = selgraph(initial);
X		} while (state != CONSONANT && graph->type == prev);
X		if ((spelling = selspell(graph)) == (char *) 0) {
X			fprintf(stderr, "PANIC: got NULL in selspell(%s)\n", graph->graph);
X			exit(2);
X		}
X		strcpy(pw, spelling);
X		while (*pw != '\0')
X			pwlen++, pw++;
X		tmp = prev;
X		prev = graph->type;
X		if ((state = choosenext(prev, tmp)) == CONSONANT)
X			initial = consonant;
X		else
X			initial = vowel;
X	}
X}
X
X/*
X * ==============================  End of pwgen  ==============================
X */
X
X#include <pwd.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#define TACPWFILE "./pwfile"
X#define TMPPWFILE "/tmp/tacpasswd.XXXXXX"
X#define PW_NAMLEN 8				/* max length user name */
X#define PW_PWDLEN 8				/* max length password  */
X#define GEN_PWDLEN 8				/* length of gen passwd */
X#define SPACE_PASSWD 20				/* room allocated for enc passwd */
X#define SPACE_DATE 20				/* room allocated for exp date */
X#define SHORTTIME 30
X#define LONGTIME 180
X
X#define FSEEK_F_BEGIN 0
X#define FSEEK_F_CURR  1
X#define FSEEK_F_END   2
X
X/*
X * Global storage
X */
Xchar *whoami;
XFILE *pwfile, *tmppwfile;
X
X/*
X * Forward declarations
X */
Xchar *mktemp(), *getpass(), *crypt();
Xstruct passwd *fgetpwent();
X
X/*
X * my_exit
X *
X * Close and remove the temporary file if necessary, and then exit.
X */
Xmy_exit(code)
Xint code;
X{
X    if (tmppwfile)
X	fclose(tmppwfile);
X    exit(code);
X}
X
X/*
X * valid
X *
X * Validae this name/password pair against the current record.
X */
Xvalid(entry, name, word)
X    struct passwd *entry;
X    char *name, *word;
X{
X    char salt[2];
X
X    if (strcmp(name, entry->pw_name) != 0)
X	return(0);
X
X    strncpy(salt, entry->pw_passwd, 2);
X    if (strcmp(entry->pw_passwd, crypt(word, salt)) != 0)
X	return(0);
X
X    return(1);
X}
X/*
X * update_expiration
X *
X * Update the expiration date on this entry.  Passwords expire 180 days
X * after they are initially set or changed.
X */
Xupdate_expiration(entry)
X    struct passwd *entry;
X{
X    long now, day, year, delta;
X    char month[10], timestring[26];
X
X    if (entry->pw_shell) {
X	if (sscanf(entry->pw_shell, "%s %d %d, %d", month, &day, &year, &delta) != 4)
X	    return(0);
X	free(entry->pw_shell);
X    } else
X	return(0);
X
X    if (delta != 180)
X	return(0);
X
X    time(&now);
X    now += delta * 24 * 60 * 60;
X    strcpy(timestring, ctime(&now));
X
X    entry->pw_shell = (char *)malloc(SPACE_DATE);
X    sprintf(entry->pw_shell, "%6.6s %4.4s, %d", timestring+4, timestring+20,
X	    delta);
X
X    return(1);
X}
X
X/*
X * make_passwd
X *
X * This routine sets up and calls the password generation routines.  It
X * encrypts the result, and stores it in the password field of the
X * structure.
X */
Xmake_passwd(entry)
X    struct passwd *entry;
X{
X    char genpasswd[20], salt[2];
X
X    pwgen((RANDOM(10) < 4? vowel: consonant), genpasswd, GEN_PWDLEN);
X
X    salt[0] = '\0';
X    salt[1] = '\0';
X    while (!isalpha(salt[0]))
X      salt[0] = random() & 0x7f ;
X    while (!isalpha(salt[1]))
X      salt[1] = random() & 0x7f ;
X    if (entry->pw_passwd)
X	free(entry->pw_passwd);
X    entry->pw_passwd = (char *)malloc(SPACE_PASSWD);
X    strcpy(entry->pw_passwd, crypt(genpasswd, salt));
X    printf("New password for %s is \"%s\"\n", entry->pw_name, genpasswd);
X}
X
X/*
X * copy_pwfile1
X *
X * Copy all entries in the password file before the one we are interested in.
X */
Xstruct passwd *
Xcopy_pwfile1(name)
X    char *name;
X{
X    struct passwd *current;
X
X    fseek(pwfile, 0, FSEEK_F_BEGIN);
X    while (!feof(pwfile)) {
X	current = fgetpwent(pwfile);
X	if (current && strncmp(current->pw_name, name, PW_NAMLEN) != 0) {
X	    if (putpwent(current, tmppwfile) != 0) {
X		fprintf(stderr, "%s: Cannot put current entry for %0.*s\n",
X			whoami, PW_NAMLEN, current->pw_name);
X		perror(whoami);
X		my_exit(1);
X	    }
X	} else {
X	    return(current);
X	}
X    }
X    return(NULL);
X}
X
X/*
X * copy_pwfile2
X *
X * Add the new/modified entry.  Copy all entries in the password file after
X * the one we are interested in.
X */
Xcopy_pwfile2(new)
X    struct passwd *new;
X{
X    struct passwd *current;
X 
X    if (putpwent(new, tmppwfile) != 0) {
X	fprintf(stderr, "%s: Cannot put new entry for %0.*s\n",
X		whoami, PW_NAMLEN, new->pw_name);
X	perror(whoami);
X	my_exit(1);
X    }
X
X    while (!feof(pwfile)) {
X	current = fgetpwent(pwfile);
X	if (current && putpwent(current, tmppwfile) != 0) {
X	    fprintf(stderr, "%s: Cannot put current entry for %0.*s\n",
X		    whoami, PW_NAMLEN, current->pw_name);
X	    perror(whoami);
X	    my_exit(1);
X	}
X    }
X}
X
X/*
X * copy_back
X *
X * Copy the new file back into the original file.  Can't use rename,
X * because the files aren't guaranteed to be on the same file system.
X */
Xcopy_back()
X{
X    char buffer[4096];
X    int count;
X
X    fseek(pwfile, 0, FSEEK_F_BEGIN);
X    fseek(tmppwfile, 0, FSEEK_F_BEGIN);
X
X    while ((count = fread(buffer, sizeof(char), 4096, tmppwfile)) > 0)
X      fwrite(buffer, sizeof(char), count, pwfile);
X
X    fclose(pwfile);
X    fclose(tmppwfile);
X}
X
X/*
X * getuser
X *
X * Get a username and password.  Fail upon end of file.
X */
Xgetuser(name, data)
X    char *name, *data;
X{
X    char buffer[100];
X    int i;
X
X    name[0] = '\0';
X    while (strlen(name) == 0) {
X	printf("TACACS Username: ");
X	if (!fgets(buffer, 100, stdin) || feof(stdin)) {
X	    perror(whoami);
X	    return(0);
X	}
X	strncpy(name, buffer, PW_NAMLEN);
X	for (i = 0; i < PW_NAMLEN; i++)
X	    if (name[i] == '\n')
X		name[i] = '\0';
X	name[PW_NAMLEN] = '\0';
X    }
X
X    strncpy(data, getpass("Old Password: "), PW_PWDLEN);
X    if (feof(stdin))
X	return(0);
X
X    return(1);
X}
X
X/*
X * waitforuser
X *
X * Wait for the user to say he is done.
X */
Xwaitforuser()
X{
X    printf("Hit the 'return' key to exit.");
X    getchar();
X}
X
X/*
X * init
X *
X * Initialize the program.
X */
Xinit(argc, argv)
X    int argc;
X    char **argv;
X{
X    char *c, *tmppwfilename, template[100];
X
X    whoami = argv[0];
X
X    /*
X     * Open TAC password file, and scratch file
X     */
X    if (pwfile)
X	fclose(pwfile);
X    if ((pwfile = fopen(TACPWFILE, "a+")) == NULL) {
X	fprintf(stderr, "%s: cannot open TACACS password file\n", whoami);
X	perror(whoami);
X	my_exit(1);
X    }
X    strcpy(template, TMPPWFILE);
X    tmppwfilename = mktemp(template);
X    if (tmppwfile)
X	fclose(tmppwfile);
X    if ((tmppwfile = fopen(tmppwfilename, "w+")) == NULL) {
X	fprintf(stderr, "%s: cannot open temporary file %s\n", whoami, tmppwfilename);
X	perror(whoami);
X	my_exit(1);
X    }
X    if (unlink(tmppwfilename) != 0) {
X	fprintf(stderr, "%s: cannot unlink temporary file %s\n", whoami, tmppwfilename);
X	perror(whoami);
X	my_exit(1);
X    }
X
X    srandom(time(0) + (getpgrp() << 8) + getpid());
X}
X
Xmain(argc, argv)
X    int argc;
X    char **argv;
X{
X    struct passwd *entry;
X    char username[10], password[10];
X    int i, done;
X
X    for (i = 0; i < 3; i++) {
X	init(argc, argv);
X
X	if (!getuser(username, password))
X	    return(1);
X
X	entry = copy_pwfile1(username);
X	if (!entry) {
X	    printf("I cannot find a user named '%s' in the TACACS database.\n", username);
X	    printf("Please contact cisco Enginering for assistance.\n");
X	    my_exit(1);
X	}
X
X	if (!valid(entry, username, password)) {
X	    printf("You typed an incorrect username/password combinaion.\n");
X	    printf("Please try again\n\n");
X	    continue;
X	}
X
X	if (!update_expiration(entry)) {
X	    printf("You are not allowed to change your password and revalidate\n");
X	    printf("your account.  Please contact cisco Engineering for assistance.\n");
X	    my_exit(1);
X	}
X
X	make_passwd(entry);
X	copy_pwfile2(entry);
X	copy_back();
X	waitforuser();
X	my_exit(0);
X    }
X    my_exit(0);
X}
END_OF_FILE
if test 17519 -ne `wc -c <'xtacacsd/changetac.c'`; then
    echo shar: \"'xtacacsd/changetac.c'\" unpacked with wrong size!
fi
# end of 'xtacacsd/changetac.c'
fi
if test ! -d 'xtacacsd/include' ; then
    echo shar: Creating directory \"'xtacacsd/include'\"
    mkdir 'xtacacsd/include'
fi
if test -f 'xtacacsd/inet_ntoa.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/inet_ntoa.c'\"
else
echo shar: Extracting \"'xtacacsd/inet_ntoa.c'\" \(1497 characters\)
sed "s/^X//" >'xtacacsd/inet_ntoa.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1983 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that: (1) source distributions retain this entire copyright
X * notice and comment, and (2) distributions including binaries display
X * the following acknowledgement:  ``This product includes software
X * developed by the University of California, Berkeley and its contributors''
X * in the documentation or other materials provided with the distribution
X * and in all advertising materials mentioning features or use of this
X * software. Neither the name of the University nor the names of its
X * contributors may be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)inet_ntoa.c	5.5 (Berkeley) 6/1/90";
X#endif /* LIBC_SCCS and not lint */
X
X/*
X * Convert network-format internet address
X * to base 256 d.d.d.d representation.
X */
X#include <sys/types.h>
X#include <netinet/in.h>
X
Xchar *
Xinet_ntoa(in)
X	struct in_addr in;
X{
X	static char b[18];
X	register char *p;
X
X	p = (char *)&in;
X#define	UC(b)	(((int)b)&0xff)
X	sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
X	return (b);
X}
END_OF_FILE
if test 1497 -ne `wc -c <'xtacacsd/inet_ntoa.c'`; then
    echo shar: \"'xtacacsd/inet_ntoa.c'\" unpacked with wrong size!
fi
# end of 'xtacacsd/inet_ntoa.c'
fi
if test -f 'xtacacsd/strerror.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/strerror.c'\"
else
echo shar: Extracting \"'xtacacsd/strerror.c'\" \(1446 characters\)
sed "s/^X//" >'xtacacsd/strerror.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted provided
X * that: (1) source distributions retain this entire copyright notice and
X * comment, and (2) distributions including binaries display the following
X * acknowledgement:  ``This product includes software developed by the
X * University of California, Berkeley and its contributors'' in the
X * documentation or other materials provided with the distribution and in
X * all advertising materials mentioning features or use of this software.
X * Neither the name of the University nor the names of its contributors may
X * be used to endorse or promote products derived from this software without
X * specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strerror.c	5.4 (Berkeley) 6/24/90";
X#endif /* LIBC_SCCS and not lint */
X
X#include <string.h>
X
Xchar *
Xstrerror(errnum)
X	int errnum;
X{
X	extern int sys_nerr;
X	extern char *sys_errlist[];
X	static char ebuf[40];		/* 64-bit number + slop */
X
X	if ((unsigned int)errnum < sys_nerr)
X		return(sys_errlist[errnum]);
X	(void)sprintf(ebuf, "Unknown error: %d", errnum);
X	return(ebuf);
X}
END_OF_FILE
if test 1446 -ne `wc -c <'xtacacsd/strerror.c'`; then
    echo shar: \"'xtacacsd/strerror.c'\" unpacked with wrong size!
fi
# end of 'xtacacsd/strerror.c'
fi
if test -f 'xtacacsd/syslog.3' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/syslog.3'\"
else
echo shar: Extracting \"'xtacacsd/syslog.3'\" \(5474 characters\)
sed "s/^X//" >'xtacacsd/syslog.3' <<'END_OF_FILE'
X.\" Copyright (c) 1985 The Regents of the University of California.
X.\" All rights reserved.
X.\"
X.\" Redistribution and use in source and binary forms are permitted provided
X.\" that: (1) source distributions retain this entire copyright notice and
X.\" comment, and (2) distributions including binaries display the following
X.\" acknowledgement:  ``This product includes software developed by the
X.\" University of California, Berkeley and its contributors'' in the
X.\" documentation or other materials provided with the distribution and in
X.\" all advertising materials mentioning features or use of this software.
X.\" Neither the name of the University nor the names of its contributors may
X.\" be used to endorse or promote products derived from this software without
X.\" specific prior written permission.
X.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
X.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
X.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X.\"
X.\"	@(#)syslog.3	6.13 (Berkeley) 6/23/90
X.\"
X.TH SYSLOG 3 "June 23, 1990"
X.UC 5
X.SH NAME
Xsyslog, openlog, closelog, setlogmask, vsyslog \- control system log
X.SH SYNOPSIS
X.B "#include <syslog.h>
X.PP
X.B "openlog(ident, logopt, facility)
X.br
X.B "char *ident;
X.PP
X.B "syslog(priority, message, parameters ... )
X.br
X.B "int priority;
X.br
X.B "char *message;
X.PP
X.B "#include <varargs.h>
X.br
X.B "vsyslog(priority, message, args)
X.br
X.B "int priority;
X.br
X.B "char *message;
X.br
X.B "va_list args;
X.PP
X.B "closelog()
X.PP
X.B "setlogmask(maskpri)
X.SH DESCRIPTION
X.I Syslog
Xarranges to write
X.I message
Xonto the system log maintained by
X.IR syslogd (8).
XThe message is tagged with
X.IR priority .
XThe message looks like a
X.IR printf (3)
Xstring except that
X.B %m
Xis replaced by the current error message (as referenced by
X.IR errno ).
XA trailing newline is added if needed.
XAn alternate form, in which the arguments have already been captured
Xusing the variable-length argument facilities of
X.IR varargs (3),
Xis available under the name
X.IR vsyslog .
X.PP
XThis message will be read by
X.IR syslogd (8)
Xand written to the system console, log files, or forwarded to
X.I syslogd
Xon another host as appropriate.
X.PP
XPriorities are encoded as a
X.I facility
Xand a
X.IR level .
XThe facility describes the part of the system
Xgenerating the message.
XThe level is selected from an ordered list:
X.TP
XLOG_ALERT
XA condition that should be corrected immediately,
Xsuch as a corrupted system database.
X.TP
XLOG_CRIT
XCritical conditions,
Xe.g., hard device errors.
X.TP
XLOG_DEBUG
XMessages that contain information
Xnormally of use only when debugging a program.
X.TP
XLOG_EMERG
XA panic condition.
XThis is normally broadcast to all users.
X.TP
XLOG_ERR
XErrors.
X.TP
XLOG_INFO
XInformational messages.
X.TP
XLOG_NOTICE
XConditions that are not error conditions,
Xbut should possibly be handled specially.
X.TP
XLOG_WARNING
XWarning messages.
X.PP
XIf
X.I syslog
Xcannot pass the message to
X.IR syslogd ,
Xit will attempt to write the message to the console (``/dev/console'')
Xif the LOG_CONS option is set (see below).
X.PP
XIf special processing is needed,
X.I openlog
Xcan be called to initialize the log file.
XThe parameter
X.I ident
Xis a string that is prepended to every message.
X.I Logopt
Xis a bit field indicating logging options.
XCurrent values for
X.I logopt
Xare:
X.TP
XLOG_CONS
XIf unable to send the message to
X.IR syslogd ,
Xwrite it to the console.
X.TP
XLOG_NDELAY 
XOpen the connection to
X.I syslogd
Ximmediately.
XNormally the open is delayed
Xuntil the first message is logged.
XUseful for programs that need to manage the
Xorder in which file descriptors are allocated.
X.TP
XLOG_PERROR
XWrite the message to stderr as well to the system log.
X.TP
XLOG_PID
XLog the process id with each message:
Xuseful for identifying instantiations of daemons.
X.PP
XThe
X.I facility
Xparameter encodes a default facility to be assigned to all messages
Xthat do not have an explicit facility encoded:
X.TP
XLOG_AUTH
XThe authorization system:
X.IR login (1),
X.IR su (1),
X.IR getty (8),
Xetc.
X.TP
XLOG_CRON
XThe clock daemon.
X.TP
XLOG_DAEMON
XSystem daemons, such as
X.IR ftpd (8),
X.IR routed (8),
Xetc, that are not provided for explicitly by other facilities.
X.TP
XLOG_KERN
XMessages generated by the kernel.
XThese cannot be generated by any user processes.
X.TP
XLOG_LPR
XThe line printer spooling system:
X.IR lpr (1),
X.IR lpc (8),
X.IR lpd (8),
Xetc.
X.TP
XLOG_MAIL
XThe mail system.
X.TP
XLOG_NEWS
XThe network news system.
X.TP
XLOG_SYSLOG
XMessages generated internally by
X.IR syslogd (8).
X.TP
XLOG_USER
XMessages generated by random user processes.
XThis is the default facility identifier if none is specified.
X.TP
XLOG_UUCP
XThe uucp system.
X.TP
XLOG_LOCAL0
XReserved for local use.
XSimilarly for LOG_LOCAL1 through LOG_LOCAL7.
X.PP
X.I Closelog
Xcan be used to close the log file.
X.PP
X.I Setlogmask
Xsets the log priority mask to
X.I maskpri
Xand returns the previous mask.
XCalls to
X.I syslog
Xwith a priority not set in
X.I maskpri
Xare rejected.
XThe mask for an individual priority
X.I pri
Xis calculated by the macro LOG_MASK(\fIpri\fP);
Xthe mask for all priorities up to and including
X.I toppri
Xis given by the macro LOG_UPTO(\fItoppri\fP).
XThe default allows all priorities to be logged.
X.SH EXAMPLES
X.nf
Xsyslog(LOG_ALERT, "who: internal error 23");
X
Xopenlog("ftpd", LOG_PID, LOG_DAEMON);
Xsetlogmask(LOG_UPTO(LOG_ERR));
Xsyslog(LOG_INFO, "Connection from host %d", CallingHost);
X
Xsyslog(LOG_INFO|LOG_LOCAL2, "foobar error: %m");
X.fi
X.SH "SEE ALSO"
Xlogger(1),
Xsyslogd(8)
END_OF_FILE
if test 5474 -ne `wc -c <'xtacacsd/syslog.3'`; then
    echo shar: \"'xtacacsd/syslog.3'\" unpacked with wrong size!
fi
# end of 'xtacacsd/syslog.3'
fi
if test -f 'xtacacsd/syslog.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/syslog.c'\"
else
echo shar: Extracting \"'xtacacsd/syslog.c'\" \(5269 characters\)
sed "s/^X//" >'xtacacsd/syslog.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1983, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted provided
X * that: (1) source distributions retain this entire copyright notice and
X * comment, and (2) distributions including binaries display the following
X * acknowledgement:  ``This product includes software developed by the
X * University of California, Berkeley and its contributors'' in the
X * documentation or other materials provided with the distribution and in
X * all advertising materials mentioning features or use of this software.
X * Neither the name of the University nor the names of its contributors may
X * be used to endorse or promote products derived from this software without
X * specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)syslog.c	5.28 (Berkeley) 6/27/90";
X#endif /* LIBC_SCCS and not lint */
X
X/*
X * SYSLOG -- print message on log file
X *
X * This routine looks a lot like printf, except that it outputs to the
X * log file instead of the standard output.  Also:
X *	adds a timestamp,
X *	prints the module name in front of the message,
X *	has some other formatting types (or will sometime),
X *	adds a newline on the end of the message.
X *
X * The output of this routine is intended to be read by syslogd(8).
X *
X * Author: Eric Allman
X * Modified to use UNIX domain IPC by Ralph Campbell
X */
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/file.h>
X#include <sys/signal.h>
X#include <sys/syslog.h>
X#include <sys/uio.h>
X#include <sys/wait.h>
X#include <netdb.h>
X#include <string.h>
X#include <varargs.h>
X#include <paths.h>
X#include <stdio.h>
X
X#define	_PATH_LOGNAME	"/dev/log"
X
Xstatic int	LogFile = -1;		/* fd for log */
Xstatic int	connected;		/* have done connect */
Xstatic int	LogStat = 0;		/* status bits, set by openlog() */
Xstatic char	*LogTag = "syslog";	/* string to tag the entry with */
Xstatic int	LogFacility = LOG_USER;	/* default facility code */
X
Xsyslog(pri, fmt, args)
X	int pri, args;
X	char *fmt;
X{
X	vsyslog(pri, fmt, &args);
X}
X
Xvsyslog(pri, fmt, ap)
X	int pri;
X	register char *fmt;
X	va_list ap;
X{
X	extern int errno;
X	register int cnt;
X	register char *p;
X	time_t now, time();
X	int fd, saved_errno;
X	char tbuf[2048], fmt_cpy[1024], *stdp, *ctime();
X
X	saved_errno = errno;
X
X	/* see if we should just throw out this message */
X	if (!LOG_MASK(LOG_PRI(pri)) || (pri &~ (LOG_PRIMASK|LOG_FACMASK)))
X		return;
X	if (LogFile < 0 || !connected)
X		openlog(LogTag, LogStat | LOG_NDELAY, 0);
X
X	/* set default facility if none specified */
X	if ((pri & LOG_FACMASK) == 0)
X		pri |= LogFacility;
X
X	/* build the message */
X	(void)time(&now);
X	(void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4);
X	for (p = tbuf; *p; ++p);
X	if (LogStat & LOG_PERROR)
X		stdp = p;
X	if (LogTag) {
X		(void)strcpy(p, LogTag);
X		for (; *p; ++p);
X	}
X	if (LogStat & LOG_PID) {
X		(void)sprintf(p, "[%d]", getpid());
X		for (; *p; ++p);
X	}
X	if (LogTag) {
X		*p++ = ':';
X		*p++ = ' ';
X	}
X
X	/* substitute error message for %m */
X	{
X		register char ch, *t1, *t2;
X		char *strerror();
X
X		for (t1 = fmt_cpy; ch = *fmt; ++fmt)
X			if (ch == '%' && fmt[1] == 'm') {
X				++fmt;
X				for (t2 = strerror(saved_errno);
X				    *t1 = *t2++; ++t1);
X			}
X			else
X				*t1++ = ch;
X		*t1 = '\0';
X	}
X
X	(void)vsprintf(p, fmt_cpy, ap);
X
X	cnt = strlen(tbuf);
X
X	/* output to stderr if requested */
X	if (LogStat & LOG_PERROR) {
X		struct iovec iov[2];
X		register struct iovec *v = iov;
X
X		v->iov_base = stdp;
X		v->iov_len = cnt - (stdp - tbuf);
X		++v;
X		v->iov_base = "\n";
X		v->iov_len = 1;
X		(void)writev(2, iov, 2);
X	}
X
X	/* output the message to the local logger */
X	if (send(LogFile, tbuf, cnt, 0) >= 0 || !(LogStat&LOG_CONS))
X		return;
X
X	/*
X	 * output the message to the console; don't worry about
X	 * blocking, if console blocks everything will.
X	 */
X	if ((fd = open(_PATH_CONSOLE, O_WRONLY, 0)) < 0)
X		return;
X	(void)strcat(tbuf, "\r\n");
X	cnt += 2;
X	p = index(tbuf, '>') + 1;
X	(void)write(fd, p, cnt - (p - tbuf));
X	(void)close(fd);
X}
X
Xstatic struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
X/*
X * OPENLOG -- open system log
X */
Xopenlog(ident, logstat, logfac)
X	char *ident;
X	int logstat, logfac;
X{
X	if (ident != NULL)
X		LogTag = ident;
X	LogStat = logstat;
X	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
X		LogFacility = logfac;
X	if (LogFile == -1) {
X		SyslogAddr.sa_family = AF_UNIX;
X		strncpy(SyslogAddr.sa_data, _PATH_LOGNAME,
X		    sizeof(SyslogAddr.sa_data));
X		if (LogStat & LOG_NDELAY) {
X			LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
X			fcntl(LogFile, F_SETFD, 1);
X		}
X	}
X	if (LogFile != -1 && !connected &&
X	    connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1)
X		connected = 1;
X}
X
X/*
X * CLOSELOG -- close the system log
X */
Xcloselog()
X{
X	(void) close(LogFile);
X	LogFile = -1;
X	connected = 0;
X}
X
Xstatic int	LogMask = 0xff;		/* mask of priorities to be logged */
X/*
X * SETLOGMASK -- set the log mask level
X */
Xsetlogmask(pmask)
X	int pmask;
X{
X	int omask;
X
X	omask = LogMask;
X	if (pmask != 0)
X		LogMask = pmask;
X	return (omask);
X}
END_OF_FILE
if test 5269 -ne `wc -c <'xtacacsd/syslog.c'`; then
    echo shar: \"'xtacacsd/syslog.c'\" unpacked with wrong size!
fi
# end of 'xtacacsd/syslog.c'
fi
if test -f 'xtacacsd/tacacs.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/tacacs.doc'\"
else
echo shar: Extracting \"'xtacacsd/tacacs.doc'\" \(3663 characters\)
sed "s/^X//" >'xtacacsd/tacacs.doc' <<'END_OF_FILE'
Xextended TACACS capability for accounting and auditing.
X
XNew commands (per system)
X
X    tacacs extended
X    tacacs notify connect|slip|enable|logout
X	Notify causes a message to be transmitted to the tacacs server,
X	with retransmition being performed by a background process for
X	up to 5 minutes.  However, the user get the equivilent of an
X	immediate "accepted" response.
X    tacacs authenticate connect|slip|enable
X	Authenticate requires a repsonse from the server to indicate
X	whether the user can prefer the indicated action.
X
XNew packet format:
X
X    uchar version;		/* version of protocol 0x80 */
X    uchar type;			/* Type of query/response */
X	XTA_LOGIN	1
X	XTA_ANSWER	2
X	XTA_CHANGE	3
X	XTA_FOLLOW	4
X	XTA_CONNECT	5
X	XTA_ENABLE	6
X	XTA_LOGOUT	7
X	XTA_RELOAD	8
X	XTA_SLIPON	9
X	XTA_SLIPOFF    10
X	XTA_SLIPADDR   11
X    ushort trans;		/* unique ID to associate query w reply */
X    uchar namelen;		/* length of name */
X    uchar pwlen;		/* length of password */
X    uchar response;		/* response code */
X	XTA_A_ACCEPTED	1
X	XTA_A_REJECTED	2
X    uchar reason;		/* reason for response or query */
X	XTA_A_NONE	0
X	XTA_A_EXPIRING	1
X	XTA_A_PASSWORD	2
X	XTA_A_DENIED	3
X	/*
X	 * The following are reasons for "logout" and "slipoff" 
X	 */
X	XTA_R_QUIT	4	/* user quit normally */
X	XTA_R_IDLE	5	/* idle timeout */
X	XTA_R_DROP	6	/* carrier dropped */
X	XTA_R_BAD	7	/* too many bad passwords */
X
X    ushort accesslist;		/* access list for user returned at login */
X    ulong flags;		/* misc flags */
X    ulong uuid;			/* user id code assigned. */
X    ushort lport;		/* local line number */
X    ulong dhost;		/* destination host */
X    ushort dport;		/* destination port */
X				/* user name */
X				/* password */
X
X
Xnew xtacacsd.c documentation:
X
X	xtacacsd [-s] [-d] [-l] [-f/etc/tacpasswd] [-w/var/log/tacacs.wtmp]
X
X	-s	standalone mode - the server runs continuously.
X		Recomended for extended use.
X
X	-d	Debugging.
X
X	-l	Log events to syslog local6 file.  All events are logged:
X		system reload from server
X		xlogin from server ttyNN for user(gcos) accepted|rejected
X		xconnect from server ttyNN for user(uuid) to host:port
X		xlogout from server ttyNN for user(uuid) reason
X		xslipon from server SLIPNN for user(uuid) address slipaddress
X		xslipoff from server SLIPNN for user(uuid) address slipaddress
X		slipaddress from server ttyNN for host(gcos) accepted|rejected
X
X	-w<wtmpfile> log on/off events in a wtmp format file.
X		In theory, this makes it possible to keep track of per-user
X		connect times, and print them using the "ac" unix utility.
X		Events logged:
X		-  System reload.  "~" in name field, servername in host field
X		-  Login / Logout  username, "TTYnn", slipaddress
X		-  SlipOn / SlipOff username, "SLIPnn", slipaddress
X		If a user logs in and issues a SLIP command, the following
X		sequence should appear in the wtmp file:
X		login TTYnn username servername
X		    time passes
X		slipon SLIPnn username slipname
X		logout TTYnn username servername
X		    time passes
X		slipoff SLIPnn username slipname
X
X		A potential problem exists: data for all servers is stored
X		in the same wtmp file, the differences being noted by the
X		ut_host field in the wtmp entries.  The "ac" program may
X		not look at this field for determining matching entries.
X		Thus having the same user log in on more than one terminal
X		server at the same time may result in invalid final reports.
X
X	-f<passwd-file>	file to find password information.  If not given,
X		/etc/passwd is used, and the following features are not used:
X		-  The user id is used as the uuid.
X		-  The group ID field is used as the access list.
X		-  An expiration data for the account is stored in the shell
X		   field of the entry.
END_OF_FILE
if test 3663 -ne `wc -c <'xtacacsd/tacacs.doc'`; then
    echo shar: \"'xtacacsd/tacacs.doc'\" unpacked with wrong size!
fi
# end of 'xtacacsd/tacacs.doc'
fi
if test -f 'xtacacsd/tacacs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/tacacs.h'\"
else
echo shar: Extracting \"'xtacacsd/tacacs.h'\" \(3151 characters\)
sed "s/^X//" >'xtacacsd/tacacs.h' <<'END_OF_FILE'
X/*
X * tacacs.h - TAC access protocol support
X *
X */
X
X#define	TA_VERSION		0
X#define XTA_VERSION		0x80
X
X/*
X * global flags in tacacs_extended
X */
X#define TACACS_EXTEND		0x01	/* extended tacacs is enabled */
X#define TACACS_ASKCONNECT	0x02	/* ask about connection */
X#define TACACS_NOTECONNECT	0x04	/* notifiy about connections */
X#define TACACS_ASKSLIP		0x08	/* ask about SLIP command */
X#define TACACS_NOTESLIP		0x10	/* notify about SLIP command */
X#define TACACS_ASKENA		0x20	/* ask about "enable" */
X#define TACACS_NOTEENA		0x40	/* notify about enable */
X#define TACACS_NOTELOGOUT	0x80	/* notify about logout/disconnect */
X
X/*
X * Operations
X */
X
X#define	TA_QUERY		1
X#define	TA_ANSWER		2
X#define	TA_CHANGE		3
X#define	TA_FOLLOW		4
X
X/*
X * ANSWER responses
X */
X
X#define	TA_A_ACCEPTED	1
X#define	TA_A_REJECTED	2
X
X/*
X * Reasons included in ANSWER
X */
X
X#define TA_A_NONE	0
X#define	TA_A_EXPIRING	1
X#define	TA_A_PASSWORD	2
X#define	TA_A_DENIED	3
X
X/*
X * TACACS packet structure and sizes
X */
X
Xtypedef struct tacacstype_ {
X    uchar version;
X    uchar type;
X    ushort trans;
X    uchar namelen;
X    uchar pwlen;
X} tacacstype;
X
X#define	TACACS_SIZE	6
X
X/*
X * eXtended TACACS
X * Try to keep longwords longword aligned.
X */
Xtypedef struct xtacacstype_ {
X    uchar version;		/* version of protocol */
X    uchar type;			/* Type of query/response */
X    ushort trans;		/* transaction ID */
X    /*---------------*/
X    uchar namelen;		/* length of name */
X    uchar pwlen;		/* length of password */
X    uchar response;		/* response code */
X    uchar reason;		/* reason for response */
X    /*---------------*/
X    ulong uuid;			/* user id code assigned. */
X    /*---------------*/
X    ulong dhost;		/* destination host */
X    /*---------------*/
X    ushort dport;		/* destination port */
X    ushort lport;		/* local line number */
X    /*---------------*/
X    ulong flags;		/* misc flags */
X    /*---------------*/
X    ushort accesslist;		/* access list for user */
X				/* user name */
X				/* password */
X} xtacacstype;
X
X#define XTACACSSIZE 26
X/*
X * "types"
X */
X
X#define	XTA_LOGIN	1
X#define	XTA_ANSWER	2
X#define	XTA_CHANGE	3
X#define	XTA_FOLLOW	4
X#define XTA_CONNECT	5
X#define XTA_ENABLE	6
X#define XTA_LOGOUT	7
X#define XTA_RELOAD	8
X#define XTA_SLIPON	9
X#define XTA_SLIPOFF    10
X#define XTA_SLIPADDR   11
X
X/*
X * ANSWER responses
X */
X
X#define	XTA_A_ACCEPTED	1
X#define	XTA_A_REJECTED	2
X
X/*
X * reasons for rejection of request
X */
X
X#define XTA_A_NONE	0
X#define	XTA_A_EXPIRING	1
X#define	XTA_A_PASSWORD	2
X#define	XTA_A_DENIED	3
X/*
X * The following are reasons for "logout" and "slipoff" xtacacs messages
X */
X#define XTA_R_QUIT	4	/* user quit normally */
X#define XTA_R_IDLE	5	/* idle timeout */
X#define XTA_R_DROP	6	/* carrier dropped */
X#define XTA_R_BAD	7	/* too many bad passwords */
X
X/*
X * flags used
X */
X#define XTA_F_NOENABLE	   1	/* user may not enable */
X#define XTA_F_NOENAPASS	   2	/* user may enable without password */
X#define XTA_F_NOSLIP	   4	/* user may not run SLIP */
X#define XTA_F_SLIPPASS	   8	/* user needs ok to run SLIP */
X#define XTA_F_CONNPASS	0x10	/* user needs ok to make connections */
X#define XTA_F_ACCESS	0x20	/* use the provided access list number */
END_OF_FILE
if test 3151 -ne `wc -c <'xtacacsd/tacacs.h'`; then
    echo shar: \"'xtacacsd/tacacs.h'\" unpacked with wrong size!
fi
# end of 'xtacacsd/tacacs.h'
fi
if test -f 'xtacacsd/tacacsd.8' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/tacacsd.8'\"
else
echo shar: Extracting \"'xtacacsd/tacacsd.8'\" \(5586 characters\)
sed "s/^X//" >'xtacacsd/tacacsd.8' <<'END_OF_FILE'
X.\"	$Header: /usr/local/src/tacacsd/RCS/tacacsd.8,v 1.2 91/01/22 13:53:00 aggarwal Exp $
X.TH  IN.TACACSD 8 "19 October 1990"
X.SH NAME
Xin.tacacsd \- TAC Access Control server
X.SH SYNOPSIS
X.B in.tacacsd
X.RB [ " \-dls " ]
X[
X.B \-f
X.IR filename \&. \|. \|.
X] 
X.SH DESCRIPTION
X.LP
X.B in.tacacsd
Xis a server which authenticates users logging onto a terminal server
X(or any host which cares to query the server). It uses the standard
Xpassword file (
X.I /etc/passwd
X) by default or the list of specified filenames on the command line \-
Xhowever, it expects these files to be in the same format as the 
X.I passwd
Xfile so that the 
X.I getpwent()
XUnix routines can access the entries.
X.LP
XThe program expects a 
X.B username
Xand 
X.B password
Xto be supplied in the query packet recieved from the terminal server,
Xand it searches all the 
X.B "access"
Xfiles for a match for the query. Only after it cannot find a match in
Xall the supplied access files, will it return a 'authentication failure'
Xreply to the query.
X.LP
XThis program can be used to authenticate users when they try to access
Xa terminal server (
X.B cisco 
Xterminal servers support this option). The server can log information
Xabout all queries coming to the server using 
X.B syslog. It is meant to be invoked by 
X.B inetd
Xbut can be run from a terminal in 
X.B standalone mode
Xif desired. Note that if running from a terminal, the
X.B standalone
Xoption 
X.I has
Xto be specified since otherwise it expects data is to be read on the
XTACACS port (port 49).
X.LP
XThe program can be compiled with the 
X.B DEBUG
Xoption so that it logs extensive debugging information (however, this
Xoption also displays the user's password so it can be a security problem
Xif the log file is publicly accessible). This information is displayed
X.I only
Xif the program is compiled with the 
X.B \-DDEBUG
Xoption.
X.LP
XThe server always returns an authentication failure for any queries
Xthat have a uid of 0 (
X.I root uid
X) or for any users that do not have a password in the password files.
XIt also verifies that the account is current and not expired if the
Xlast password field (
X.I pw_shell )
Xsupports this feature.
X.LP
XSince there is no provision for sending a reply back which
Xsays
X.I "no such user"
Xand if there are two sets of TACACS servers with differant access files,
Xthen if one responds with a DENIED packet, the client host might never
Xquery the second server.Thus, a 
X.B quiet 
Xmode is avaliable in which the server will never send a negative
Xreply back to a query.
X.LP
XIf the UPPER_GID and LOWER_GID are defined while compiling, then the
Xusers group-id in the passwd file is used a a measure of allowed logins.
XThe last 7 bits of the GID are used and the 
X.I /etc/utmp
Xfile is searched for the present number of logins.
X\fI (Note that this assumes that all users connecting to the server log
Xinto the system).\fR
XIf the number of current logins exceeds the number of allowable logins
X(from the GID), then a negative response is sent.
X.LP
XSince in the "SLIP" mode, the query is all uppercase, this requires
Xthat two users be created for SLIP users on unix systems (case sensitive).
XTo prevent this, if the program is compiled with TOLOWER defined, then
Xall usernames are converted to lowercase.
X.SH OPTIONS
X.TP
X.B \-d
Xenable debugging. In the debug mode, the program does not fork and
Xwrites information to the controlling terminal. Useful ONLY if the
Xprogram was compiled with the DEBUG option and in standalone mode
X(since in all other cases the program does not have any controlling
Xterminals).
X.TP
X.B \-s
XTo run the server in standalone mode. The program will sit in an
Xendless loop waiting for data to arrive on the TACACS port. If the
Xdebug
X.TP
X.B \-d
Xoption is not specified, the program forks and detaches itself from
Xthe controlling terminal.
X.TP
X.B \-l
Xlogging. The server logs information via
X.B syslog
Xat the INFO level about all queries that it serves. If compiled
Xwith the 
X.B \-DLOG_LOCAL6
Xoption, the server logs all information at the
X.B local6
Xfacility, otherwise it logs all information via the DAEMON facility.
X.TP
X.B \-q
Xquiet mode. The server will not send negative responses to a query.
XThis is so that a client can then ask the next tacacs server in its
Xlist in case of a timeout.
X.TP
X.BI \-f " files"
Xspecifies an alternate list of access files to be used for authenticating
Xthe queries. \fI This must be the last option on the command line 
X(if present)\fR.
XBy default the file
X.I /etc/passwd
Xis used if no file is specified on the command line. Upto 5 alternate
Xfiles can be specified on the command line and the server will search
Xin all the files until it finds a match or else return an error. The
Xalternate password files must be in the 
X.I /etc/passwd
Xformat. They can be set to only root readable for security reasons
Xsince the server is run as
X.I root.
X.SH FILES
X.TP 20
X.B /etc/in.tacacsd
Xthe main server
X.TP 20
X.B /etc/passwd
Xdefault password file used for authentication
X.SH SEE ALSO
X.BR inetd (8)
X.BR inetd.conf (5),
X.BR services (5),
X.BR syslog (8)
X.BR syslog.conf (5)
X.LP
X.IR "TACACS User Identification Telnet Option"
XBrian A. Anderson,
X.IR "RFC 927"
X.SH AUTHOR
X.LP
XThis program is a modified version of the version originally written
Xby Greg Satz (satz@cisco.com) for cisco routers. The main changes
Xwere the searching of multiple password files and security features
Xlike denying access for any user query with a uid of 0 (else one can
Xtry guessing the root password and bypass security options on the
Xprimary host). 
X.LP
XRewritten by Vikas Aggarwal (vikas@jvnc.net).
X.SH DIAGNOSTICS
X.LP
XExit status is normally 0.
END_OF_FILE
if test 5586 -ne `wc -c <'xtacacsd/tacacsd.8'`; then
    echo shar: \"'xtacacsd/tacacsd.8'\" unpacked with wrong size!
fi
# end of 'xtacacsd/tacacsd.8'
fi
if test -f 'xtacacsd/tacpasswd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/tacpasswd.c'\"
else
echo shar: Extracting \"'xtacacsd/tacpasswd.c'\" \(19175 characters\)
sed "s/^X//" >'xtacacsd/tacpasswd.c' <<'END_OF_FILE'
X/*
X * tacpasswd
X *
X * This program maintains the /etc/tacpasswd file.  It can be used to
X * generate or change passwords for the TACACS system.
X *
X * The password generator routines are from Brandon Allbery, as
X * distribured in  comp.sources.misc, volume 5, pwgen.
X *
X * Written by: David Hampton, 30 June 89
X */
X
X#ifdef SYSV
X#define random rand
X#define srandom srand
X#endif
X
X/*
XPath: xanth!mcnc!gatech!cwjcc!hal!ncoast!allbery
XFrom: allbery@ncoast.UUCP (Brandon S. Allbery)
XNewsgroups: comp.sources.misc
XSubject: v05i059: pwgen -- random-but-pronounceable password generator
XMessage-ID: <13184@ncoast.UUCP>
XDate: 26 Nov 88 04:44:18 GMT
XSender: allbery@ncoast.UUCP
XReply-To: allbery@ncoast.UUCP (Brandon S. Allbery)
XOrganization: Cleveland Public Access UN*X, Cleveland, Oh
XLines: 328
XApproved: allbery@ncoast.UUCP
X
XPosting-number: Volume 5, Issue 59
XSubmitted-by: "Brandon S. Allbery" <allbery@ncoast.UUCP>
XArchive-name: pwgen
X
X[Dr. Jekyll and Mr. Hyde, anyone?  ;-)  ++bsa]
X
XI've described this program, in its OSI Superboard-II incarnation, in
Xcomp.unix.wizards and news.sysadmin.  Now, here's the code for a UN*X
Xversion.  It seems to work OK on ncoast, except for some oddness in the
X"random" selections -- which are probably the result of our not having a
Xgood RNG.  (Could someone mail me one or more of the alternative
Xgenerators?  Or maybe even the source to BSD random(), assuming that it
Xfalls outside the subset of BSD code that can be traced to AT&T?  To put it
Xmildly, our random number generator isn't.)
X
XThis is not as complete as the original program, which actually had a list
Xof characters (the current one uses phonemes) which were most likely to
Xfollow other phonemes.  On the other hand, this version does use phonemes
Xrather than characters, so its creations are more pronounceable as a rule
Xthan those of the original.  The resulting passwords aren't quite as
X"natural" as the original, however.  (That may be for the best; the original
Xwas intended as a simple experiment to see if a rule for "proper English
Xwords" could be defined in terms of rules which related letters.  This was
Xbefore I got to college and learned that such things were rather unlikely,
Xbut the original program still did a pretty good job of spewing out some
Xcommon English words.  That can't be said for *this* program.)
X
XTo compile:	cc -O -o pwgen pwgen.c -lm
X(The sqrt() function is used in an attempt to produce a random number which
Xis "weighted" toward one end of the range, so as to prefer one end of a list
Xof "spellings" for a phoneme over the other end.  It seems to work, but with
Xthis rotted RNG, I can't be absolutely certain.  A trial distribution seems
Xto be correct, however.)
X
XWhat's the intent?  I find that I can remember a "word" better if I can
Xpronounce it.  This may or may not be true for other people, but *anything*
Xthat encourages the use of random passwords is an improvement on what I
Xtypically see at client sites every day.  So this program spits out
Xpasswords which are virtually guaranteed not to be found in the dictionary,
Xbut are (usually) pronounceable to speakers of English.  (The tables can be
Xmodified for other languages, but they're rather hairy.  Perhaps I'll write
Xa version which loads "compiled" language descriptions, and let the compiler
Xdeal with the hairy stuff.  Hey, they were even hairier in the BASIC
Xversion!)
X
XOh, well, shar and enjoy.
X
X++Brandon, sitting on the other side of the fence for the moment
X*/
X
X/*
X * Generate (hopefully) pronounceable random passwords.  These can often be
X * remembered more easily than completely random passwords, and are immune to
X * dictionary searches, etc.
X *
X * The original version of this program was written in BASIC on an OSI
X * Superboard II SBC.  That version is long gone (the SB2's cassette drive
X * was never trustworthy, it eventually scrambled the tape), but the basic
X * (pardon the pun) idea lives on here, with a few modification like basing
X * the selection on "graphs" (actually, they are a restricted set of phonemes)
X * and having randomly-selected spellings for those graphs.
X */
X
X#include <stdio.h>
X#include <math.h>
X
X#define RANDOM(c)	((int) (((random(c) & 0x7fff) / 32767.0) * (c)))
X
Xchar *spelling[] = {
X/*a*/	"a",				(char *) 0,	/* 2*/
X/*A*/	"a",	"ae",	"ai",		(char *) 0,	/* 6*/
X/*b*/	"b",				(char *) 0,	/* 8*/
X/*ch*/	"ch",				(char *) 0,	/*10*/
X/*d*/	"d",				(char *) 0,	/*12*/
X/*e*/	"e",				(char *) 0,	/*14*/
X/*E*/	"e",	"ee",	"ie",		(char *) 0,	/*18*/
X/*f*/	"f",	"ph",	"gh",		(char *) 0,	/*22*/
X/*g*/	"g",				(char *) 0,	/*24*/
X/*h*/	"h",				(char *) 0,	/*26*/
X/*i*/	"i",	"e",			(char *) 0,	/*29*/
X/*I*/	"i",	"ai",			(char *) 0,	/*32*/
X/*i'*/	"i",	"ei",			(char *) 0,	/*35*/
X/*j*/	"j",	"g",			(char *) 0,	/*38*/
X/*k*/	"k",	"c",			(char *) 0,	/*41*/
X/*l*/	"l",				(char *) 0,	/*43*/
X/*m*/	"m",				(char *) 0,	/*45*/
X/*n*/	"n",				(char *) 0,	/*47*/
X/*ng*/	"ng",				(char *) 0,	/*49*/
X/*o*/	"o",	"a",	"ah",		(char *) 0,	/*53*/
X/*O*/	"o",	"oh",			(char *) 0,	/*56*/
X/*oo*/	"oo",	"u",			(char *) 0,	/*59*/
X/*OO*/	"oo",	"w",			(char *) 0,	/*62*/
X/*p*/	"p",				(char *) 0,	/*64*/
X/*qu*/	"qu",				(char *) 0,	/*66*/
X/*r*/	"r",				(char *) 0,	/*68*/
X/*s*/	"s",	"c",			(char *) 0,	/*71*/
X/*sh*/	"sh",	"s",			(char *) 0,	/*74*/
X/*t*/	"t",				(char *) 0,	/*76*/
X/*th*/	"th",				(char *) 0,	/*78*/
X/*TH*/	"th",				(char *) 0,	/*80*/
X/*u*/	"u",				(char *) 0,	/*82*/
X/*U*/	"u",	"oo",			(char *) 0,	/*85*/
X/*v*/	"v",				(char *) 0,	/*87*/
X/*x*/	"x",				(char *) 0,	/*89*/
X/*y*/	"y",				(char *) 0,	/*91*/
X/*z*/	"z",	"s",			(char *) 0,	/*94*/
X};
X
Xstruct graph {
X	char *graph;
X	char type;
X#define CONSONANT	0
X#define VOWEL_LONG	1
X#define VOWEL_SHORT	2
X#define VOWEL_OTHER	3
X#define VOWEL_MASK	3
X#define iscons(c)	(((c)->type & VOWEL_MASK) == 0)
X#define isvowel(c)	(((c)->type & VOWEL_MASK) != 0)
X/*	char frequency;			*/	/* unused for now */
X	char **spellings;
X/*	struct graph **following;	*/	/* maybe later */
X} graph[] = {
X	"a",	VOWEL_SHORT,	&spelling[0],
X	"A",	VOWEL_LONG,	&spelling[2],
X	"b",	CONSONANT,	&spelling[6],
X	"ch",	CONSONANT,	&spelling[8],
X	"d",	CONSONANT,	&spelling[10],
X	"e",	VOWEL_SHORT,	&spelling[12],
X	"E",	VOWEL_LONG,	&spelling[14],
X	"f",	CONSONANT,	&spelling[18],
X	"g",	CONSONANT,	&spelling[22],
X	"h",	CONSONANT,	&spelling[24],
X	"i",	VOWEL_SHORT,	&spelling[26],
X	"I",	VOWEL_LONG,	&spelling[29],
X	"i'",	VOWEL_OTHER,	&spelling[32],
X	"j",	CONSONANT,	&spelling[35],
X	"k",	CONSONANT,	&spelling[38],
X	"l",	CONSONANT,	&spelling[41],
X	"m",	CONSONANT,	&spelling[43],
X	"n",	CONSONANT,	&spelling[45],
X	"ng",	CONSONANT,	&spelling[47],
X	"o",	VOWEL_SHORT,	&spelling[49],
X	"O",	VOWEL_LONG,	&spelling[53],
X	"oo",	VOWEL_SHORT,	&spelling[56],
X	"OO",	VOWEL_LONG,	&spelling[59],
X	"p",	CONSONANT,	&spelling[62],
X	"qu",	CONSONANT,	&spelling[64],
X	"r",	CONSONANT,	&spelling[66],
X	"s",	CONSONANT,	&spelling[68],
X	"sh",	CONSONANT,	&spelling[71],
X	"t",	CONSONANT,	&spelling[74],
X	"th",	CONSONANT,	&spelling[76],
X	"TH",	CONSONANT,	&spelling[78],
X	"u",	VOWEL_SHORT,	&spelling[80],
X	"U",	VOWEL_LONG,	&spelling[82],
X	"v",	CONSONANT,	&spelling[85],
X	"x",	CONSONANT,	&spelling[87],
X	"y",	CONSONANT,	&spelling[89],
X	"z",	CONSONANT,	&spelling[91],
X	0,	0,		&spelling[94],
X};
X
Xstruct graph *vowel[] = {
X	&graph[0],	&graph[1],	&graph[5],	&graph[6],
X	&graph[10],	&graph[11],	&graph[12],	&graph[19],
X	&graph[20],	&graph[21],	&graph[22],	&graph[30],
X	&graph[31],
X	(struct graph *) 0,
X};
X
Xstruct graph *consonant[] = {
X	&graph[2],	&graph[3],	&graph[4],	&graph[7],
X	&graph[8],	&graph[9],	&graph[13],	&graph[14],
X	&graph[15],	&graph[16],	&graph[17],	&graph[18],
X	&graph[23],	&graph[24],	&graph[25],	&graph[26],
X	&graph[27],	&graph[28],	&graph[29],	&graph[32],
X	&graph[33],	&graph[34],	&graph[35],
X	(struct graph *) 0,
X};
X
X/*
X * Randomly select a graph from the specifield array.  Eventually, this should
X * account for graph frequencies as well.
X */
X
Xstruct graph *selgraph(graphs)
X	struct graph **graphs;
X{
X	register int cnt;
X
X	for (cnt = 0; graphs[cnt] != (struct graph *) 0; cnt++)
X		;
X	return graphs[RANDOM(cnt)];
X}
X
X/*
X * Randomly select a spelling for the specified graph.  This is not linear:
X * earlier spellings are preferred over later ones, but the latter do
X * sometimes sneak in.
X */
X
Xchar *selspell(graph)
X	struct graph *graph;
X{
X	register int cnt, sel;
X
X	for (cnt = 0; graph->spellings[cnt] != (char *) 0; cnt++)
X		;
X	if (cnt == 0) {
X		fprintf(stderr, "PANIC: selspell(%s) got count(spellings) == 0\n", graph->graph);
X		exit(2);
X	}
X	if (cnt == 1)
X		return *graph->spellings;
X/*
X * This may not be the best way to do it... maybe Weemba'd care to lend a
X * hand here?  After all, my specialty is programming, NOT math.
X */
X	if ((sel = cnt - (int) sqrt((double) RANDOM(cnt * cnt) + 1) - 1) < 0 || sel >= cnt) {
X#ifdef BUGCATCH
X		fprintf(stderr, "PANIC: selspell(%s) got nlrand(%d) == %d\n", graph->graph, cnt, sel);
X		exit(2);
X#else
X		sel = 0;
X#endif
X	}
X	return graph->spellings[sel];
X}
X
X/*
X * Choose the next source for a graph.  The rules are:  a consonant MUST be
X * followed by a vowel; a vowel may be followed by a vowel of a different
X * type or by a consonant, but never more than two consecutive vowel graphs.
X */
X
Xchoosenext(cur, prev)
X{
X	if (cur == CONSONANT)
X		return VOWEL_MASK;
X	else if (prev == -1 || (prev & VOWEL_MASK) != 0)
X		return CONSONANT;
X	else if (RANDOM(10) == 5)
X		return VOWEL_MASK;
X	else
X		return CONSONANT;
X}
X
X/*
X * We are passed an array of (struct graph *); choose an entry randomly and
X * assemble a string fitting the size constraint.  We use the original (OSI)
X * paradigm:  alternate consonants and vowels, with the option of two vowels
X * in a row occasionally.  The only difference is that they must be different
X * *types* of vowels, a distinction that the OSI version didn't consider.
X */
X
Xpwgen(initial, pw, maxlen)
X	struct graph **initial;
X	char *pw;
X{
X	int pwlen, state, prev, tmp;
X	struct graph *graph;
X	char *spelling;
X
X	pwlen = 0;
X	state = initial[0]->type;
X	prev = -1;
X	while (pwlen < maxlen - 1) {
X		do {
X			graph = selgraph(initial);
X		} while (state != CONSONANT && graph->type == prev);
X		if ((spelling = selspell(graph)) == (char *) 0) {
X			fprintf(stderr, "PANIC: got NULL in selspell(%s)\n", graph->graph);
X			exit(2);
X		}
X		strcpy(pw, spelling);
X		while (*pw != '\0')
X			pwlen++, pw++;
X		tmp = prev;
X		prev = graph->type;
X		if ((state = choosenext(prev, tmp)) == CONSONANT)
X			initial = consonant;
X		else
X			initial = vowel;
X	}
X}
X
X/*
X * ==============================  End of pwgen  ==============================
X */
X
X#include <pwd.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#define TACPWFILE "./pwfile"
X#define TMPPWFILE "/tmp/tacpasswd.XXXXXX"
X#define PW_NAMLEN 8				/* max length user name */
X#define PW_PWDLEN 8				/* max length password  */
X#define GEN_PWDLEN 8				/* length of gen passwd */
X#define SPACE_PASSWD 20				/* room allocated for enc passwd */
X#define SPACE_DATE 20				/* room allocated for exp date */
X#define SHORTTIME 30
X#define LONGTIME 180
X
X#define FSEEK_F_BEGIN 0
X#define FSEEK_F_CURR  1
X#define FSEEK_F_END   2
X
X/*
X * Externals
X */
Xextern char *optarg;
Xextern int optind, opterr;
X
X/*
X * Global storage
X */
Xchar *whoami;
Xchar *emptystring = "";
Xchar *usage = "Type '%s -h' for help\n";
XFILE *pwfile, *tmppwfile;
Xint  generatepwd;
Xint  expires_in;
X
X/*
X * Forward declarations
X */
Xchar *mktemp(), *getpass(), *crypt();
Xstruct passwd *fgetpwent();
X
X/*
X * my_exit
X *
X * Close and remove the temporary file if necessary, and then exit.
X */
Xmy_exit(code)
Xint code;
X{
X    if (tmppwfile)
X	fclose(tmppwfile);
X    exit(code);
X}
X
X/*
X * create_entry
X *
X * Fill in a password structure with all information about a new TAC user.
X */
Xstruct passwd *create_entry(name, fullname, lastuid)
X    char *name, *fullname;
X    int lastuid;
X{
X    struct passwd *newentry;
X
X    fprintf(stderr, "%s: Creating entry for %0.*s\n", whoami, PW_NAMLEN, name);
X
X    newentry = (struct passwd *)malloc(sizeof(struct passwd));
X    newentry->pw_name  = (char *)malloc(strlen(name)+1);
X    strncpy(newentry->pw_name, name, PW_NAMLEN);
X
X    newentry->pw_passwd  = NULL;
X    newentry->pw_uid     = ++lastuid;
X    newentry->pw_gid     = lastuid;
X#ifdef PW_QUOTA
X    newentry->pw_quota   = 0;
X#endif
X    newentry->pw_comment = emptystring;
X
X    if (fullname) {
X	newentry->pw_gecos = (char *)malloc(strlen(fullname)+1);
X	strcpy(newentry->pw_gecos, fullname);
X    } else
X	newentry->pw_gecos =  emptystring;
X
X    newentry->pw_dir     = emptystring;
X    newentry->pw_shell   = NULL;
X    return(newentry);
X}
X
X/*
X * update_expiration
X *
X * Update the expiration date on this entry.  Passwords expire 180 days
X * after they are initially set or changed.
X */
Xupdate_expiration(entry)
X    struct passwd *entry;
X{
X    long now;
X    char timestring[26];
X
X    time(&now);
X    now += expires_in * 24 * 60 * 60;
X    strcpy(timestring, ctime(&now));
X
X    if (entry->pw_shell)
X	free(entry->pw_shell);
X    entry->pw_shell = (char *)malloc(SPACE_DATE);
X    sprintf(entry->pw_shell, "%6.6s %4.4s, %d", timestring+4, timestring+20,
X	    expires_in);
X}
X
X/*
X * make_passwd
X *
X * This routine sets up and calls the password generation routines.  It
X * encrypts the result, and stores it in the password field of the
X * structure.
X */
Xmake_passwd(entry)
X    struct passwd *entry;
X{
X    char genpasswd[20], salt[2];
X
X    pwgen((RANDOM(10) < 4? vowel: consonant), genpasswd, GEN_PWDLEN);
X
X    salt[0] = '\0';
X    salt[1] = '\0';
X    while (!isalpha(salt[0]))
X      salt[0] = random() & 0x7f ;
X    while (!isalpha(salt[1]))
X      salt[1] = random() & 0x7f ;
X    if (entry->pw_passwd)
X	free(entry->pw_passwd);
X    entry->pw_passwd = (char *)malloc(SPACE_PASSWD);
X    strcpy(entry->pw_passwd, crypt(genpasswd, salt));
X    printf("New password for %s is \"%s\"\n", entry->pw_name, genpasswd);
X}
X
X/*
X * read_passwd
X *
X * This routine reads a new password from the terminal.
X */
Xread_passwd(entry)
X    struct passwd *entry;
X{
X    char *p, password[PW_PWDLEN], salt[2];
X
X    strncpy(password, getpass("Password: "), PW_PWDLEN);
X    p = getpass("Again: ");
X    if (strncmp(password, p, PW_PWDLEN) != 0) {
X	fprintf(stderr, "Sorry\n");
X	my_exit(1);
X    }
X
X    do {
X	salt[0] = random() & 0x7f ;
X    } while (!isalpha(salt[0]));
X    do {
X	salt[1] = random() & 0x7f ;
X    } while (!isalpha(salt[1]));
X      
X    if (entry->pw_passwd)
X	free(entry->pw_passwd);
X    entry->pw_passwd = (char *)malloc(SPACE_PASSWD);
X    strcpy(entry->pw_passwd, crypt(password, salt));
X}
X
X/*
X * copy_pwfile1
X *
X * Copy all entries in the password file before the one we are interested in.
X */
Xstruct passwd *
Xcopy_pwfile1(name, lastuid)
X    char *name;
X    int *lastuid;
X{
X    struct passwd *current;
X
X    fseek(pwfile, 0, FSEEK_F_BEGIN);
X    while (!feof(pwfile)) {
X	current = fgetpwent(pwfile);
X	if (current && strncmp(current->pw_name, name, PW_NAMLEN) != 0) {
X	    *lastuid = current->pw_uid;
X	    if (putpwent(current, tmppwfile) != 0) {
X		fprintf(stderr, "%s: Cannot put current entry for %0.*s\n",
X			whoami, PW_NAMLEN, current->pw_name);
X		perror(whoami);
X		my_exit(1);
X	    }
X	} else {
X	    return(current);
X	}
X    }
X    return(NULL);
X}
X
X/*
X * copy_pwfile2
X *
X * Add the new/modified entry.  Copy all entries in the password file after
X * the one we are interested in.
X */
Xcopy_pwfile2(new)
X    struct passwd *new;
X{
X    struct passwd *current;
X 
X    if (putpwent(new, tmppwfile) != 0) {
X	fprintf(stderr, "%s: Cannot put new entry for %0.*s\n",
X		whoami, PW_NAMLEN, new->pw_name);
X	perror(whoami);
X	my_exit(1);
X    }
X
X    while (!feof(pwfile)) {
X	current = fgetpwent(pwfile);
X	if (current && putpwent(current, tmppwfile) != 0) {
X	    fprintf(stderr, "%s: Cannot put current entry for %0.*s\n",
X		    whoami, PW_NAMLEN, current->pw_name);
X	    perror(whoami);
X	    my_exit(1);
X	}
X    }
X}
X
X/*
X * copy_back
X *
X * Copy the new file back into the original file.  Can't use rename,
X * because the files aren't guaranteed to be on the same file system.
X */
Xcopy_back()
X{
X    char buffer[4096];
X    int count;
X
X    fseek(pwfile, 0, FSEEK_F_BEGIN);
X    fseek(tmppwfile, 0, FSEEK_F_BEGIN);
X
X    while ((count = fread(buffer, sizeof(char), 4096, tmppwfile)) > 0)
X      fwrite(buffer, sizeof(char), count, pwfile);
X
X    fclose(pwfile);
X    fclose(tmppwfile);
X}
X
X/*
X * init
X *
X * Initialize the program.
X */
Xinit(argc, argv, username, fullname)
X    int argc;
X    char **argv, **username, **fullname;
X{
X    char *c, *tmppwfilename, template[100];
X    int opt;
X
X    whoami = argv[0];
X    generatepwd = 1;
X    expires_in = 180;
X
X    while ((opt = getopt(argc, argv, "aghlst")) != EOF)
X	switch (opt) {
X	case 'a':
X	    generatepwd = 0;
X	    break;
X	case 'g':
X	    generatepwd = 1;
X	    break;
X	case 'h':
X	    printf("\n%s: Add an entry to the TACACS password file.  The general\n", whoami);
X	    printf("usage format for this command is:\n\n");
X	    printf("    %s: [options] username fullname\n\n", whoami);
X	    printf("The options available are:\n");
X	    printf("    -a  Ask for a password.                  \n");
X	    printf("    -g  Generate a password.        (default)\n");
X	    printf("    -h  This message.                        \n");
X	    printf("    -l  Long expiration - 180 days. (default)\n");
X	    printf("    -s  Short expiration - 30 days.          \n");
X	    printf("    -t  Temporary - 7 days.                  \n");
X	    exit(1);
X	case 'l':
X	    expires_in = 180;
X	    break;
X	case 's':
X	    expires_in = 30;
X	    break;
X	case 't':
X	    expires_in = 7;
X	    break;
X	default:
X	    fprintf(stderr, usage, whoami);
X	    exit(1);
X	}
X    if ((argc - optind < 1) || (argc - optind > 2)) {
X	fprintf(stderr, usage, whoami);
X	exit(1);
X    }
X
X    *username = argv[optind++];
X    if (strlen(username) > 8)
X	username[8] = '\0';
X    *fullname = argv[optind] ? argv[optind] : NULL;
X
X    for (c = *username; *c; c++)
X      if (!isalnum(*c)) {
X	  fprintf(stderr, "%s: bad character (%c) in username\n", whoami, *c);
X	  exit(1);
X      }
X    if (*fullname)
X      for (c = *fullname; *c; c++)
X	if ((!isprint(*c)) || (*c == ':')) {
X	    fprintf(stderr, "%s: bad character (%c) in fullname\n", whoami, *c);
X	    exit(1);
X	}
X    
X    /*
X     * Open TAC password file, and scratch file
X     */
X    if ((pwfile = fopen(TACPWFILE, "a+")) == NULL) {
X	fprintf(stderr, "%s: cannot open TACACS password file\n", whoami);
X	perror(whoami);
X	my_exit(1);
X    }
X    strcpy(template, TMPPWFILE);
X    tmppwfilename = mktemp(template);
X    if ((tmppwfile = fopen(tmppwfilename, "w+")) == NULL) {
X	fprintf(stderr, "%s: cannot open temporary file %s\n", whoami, tmppwfilename);
X	perror(whoami);
X	my_exit(1);
X    }
X    if (unlink(tmppwfilename) != 0) {
X	fprintf(stderr, "%s: cannot unlink temporary file %s\n", whoami, tmppwfilename);
X	perror(whoami);
X	my_exit(1);
X    }
X
X    srandom(time(0) + (getpgrp() << 8) + getpid());
X}
X
Xmain(argc, argv)
X    int argc;
X    char **argv;
X{
X    struct passwd *entry;
X    int lastuid = 0;
X    char *username, *fullname;
X
X    init(argc, argv, &username, &fullname);
X    entry = copy_pwfile1(username, &lastuid);
X    if (entry == NULL)
X      entry = create_entry(username, fullname, lastuid);
X    update_expiration(entry);
X    if (generatepwd)
X      make_passwd(entry);
X    else
X      read_passwd(entry);
X    copy_pwfile2(entry);
X    copy_back();
X    my_exit(0);
X}
END_OF_FILE
if test 19175 -ne `wc -c <'xtacacsd/tacpasswd.c'`; then
    echo shar: \"'xtacacsd/tacpasswd.c'\" unpacked with wrong size!
fi
# end of 'xtacacsd/tacpasswd.c'
fi
if test -f 'xtacacsd/xtacacsd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/xtacacsd.c'\"
else
echo shar: Extracting \"'xtacacsd/xtacacsd.c'\" \(22676 characters\)
sed "s/^X//" >'xtacacsd/xtacacsd.c' <<'END_OF_FILE'
X#define DEBUG1
X/*
X * TACACS daemon suitable for using on Un*x systems.
X *
X * Janruary 1989, Greg Satz
X *
X * Copyright (c) 1989 by cisco Systems, Inc.
X * All rights reserved.
X */
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/ioctl.h>
X#include <sys/file.h>
X
X#include <netinet/in.h>
X
X#include <stdio.h>
X#include <errno.h>
X#include <pwd.h>
X#include <netdb.h>
X#include <sys/syslog.h>
X#include <utmp.h>
X#ifdef SYSV
X#include <fcntl.h>
X#define index strchr
X#endif
X/*
X * TACACS protocol defintions
X */
X#define uchar unsigned char
X#define ulong unsigned long
X#include "tacacs.h"
X#define oresponse namelen
X#define oreason pwlen
X
X#define	TIMEOUT		(5*60)
X
X#define	TACACS_PORT	49
X
X#define SEC_IN_DAY      (24*60*60)	/* seconds in a day */
X#define WARNING_PERIOD  14		/* days of expiration warning */
X#define	PASSWD_LENGTH	14		/* length of password for crypt */
X#define SOME_ARBITRARILY_LARGE_NUMBER 100
X
Xint debug;				/* debugging flag */
Xint logging;				/* syslog logging flag */
Xint stand;				/* running standalone or not */
Xchar *file;				/* validation filename */
Xchar *wtmpfile;				/* wtmp format filename */
XFILE *wtmpf;
Xunsigned long querytime;		/* time query came in */
X
Xstruct sockaddr_in from;
Xint fromlen;
Xstruct hostent *hp;
Xchar buf[BUFSIZ];
X
Xchar *monthname[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
X		     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Xlong days_ere_month[] = {0, 31, 59, 90, 120, 151,
X			 181, 212, 243, 273, 304, 334};
X
X/*
X * main
X * We can be called from inetd or via the rc scripts directly
X * Parse arguments are act appropiately.
X */
X
Xmain (argc, argv)
X    int argc;
X    char **argv;
X{
X    int c, on = 1, s;
X    struct servent *sp;
X    tacacstype *tp;
X    extern char *optarg;
X
X    debug = 0;				/* no debugging */
X    logging = 0;			/* no logging */
X    stand = 0;				/* under inetd */
X    file = NULL;			/* /etc/passwd */
X    wtmpfile = NULL;
X    wtmpf = NULL;
X#ifdef LOG_LOCAL6
X    openlog("tacacsd", LOG_PID, LOG_LOCAL6);
X#else
X    openlog("tacacsd", LOG_PID);
X#endif
X    while ((c = getopt(argc, argv, "df:lsw:")) != EOF)
X	switch (c) {
X	case 'd':			/* debug */
X	    debug = 1;
X	    break;
X	case 'f':			/* file name */
X	    file = optarg;
X	    break;
X	case 'l':			/* logging */
X	    logging = 1;
X	    break;
X	case 's':			/* stand-alone */
X	    stand = 1;
X	    break;
X	case 'w':
X	    wtmpfile = optarg;
X	    break;
X	default:
X	    fprintf(stderr, "%s: illegal switch\n", argv[0]);
X	    exit(1);
X	}
X
X    if (debug)
X	syslog(LOG_DEBUG, "server starting");
X
X
X    if (stand) {
X	/*
X	 * Background ourselves and let go of controlling tty
X	 */
X	if (!debug) {
X	    if (fork())
X		exit(0);
X	    for (c = 0; c < getdtablesize(); c++)
X		(void) close(c);
X	    (void) open("/", O_RDONLY);
X	    (void) dup2(0, 1);
X	    (void) dup2(0, 2);
X#ifndef SYSV
X	    c = open("/dev/tty", O_RDWR);
X	    if (c >= 0) {
X		ioctl(c, TIOCNOTTY, (char *)0);
X		(void) close(c);
X	    }
X#endif
X#ifdef LOG_LOCAL6
X	    openlog("tacacsd", LOG_PID, LOG_LOCAL6);
X#else
X	    openlog("tacacsd", LOG_PID);
X#endif
X	}
X    }
X
X    if (stand) {
X	/*
X	 * Pick up a socket
X	 */
X	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
X	    syslog(LOG_ERR, "socket: %m\n");
X	    exit(1);
X	}
X
X	/*
X	 * Get port we need to pay attention to
X	 */
X	bzero((caddr_t)&from, sizeof(from));
X#ifdef sun
X	from.sin_family = AF_INET;
X	from.sin_addr.s_addr = INADDR_ANY;
X#endif
X	sp = getservbyname("tacacs", "udp");
X	if (sp == NULL)
X	    from.sin_port = ntohs(TACACS_PORT);
X	else
X	    from.sin_port = ntohs(sp->s_port);
X
X	if (bind(s, &from, sizeof(from)) < 0) {
X	    syslog(LOG_ERR, "bind: %m\n");
X	    exit(1);
X	}
X    } else {
X	s = 0;
X	if (ioctl(s, FIONBIO, &on) < 0) {
X	    syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
X	    exit(1);
X	}
X    }
X
X    /*
X     * For 4.3BSD machines, this routine sets the file the pw routines use
X     * to the given argument. We emulate it for others.
X     */
X    if (file != NULL)
X	setpwfile(file);
X
X    if (wtmpfile != NULL) {
X	wtmpf = fopen(wtmpfile, "a+");
X	if (!wtmpf)
X	    fprintf(stderr, "\nCan't open wtmp file \"%s\"",wtmpfile);
X    }
X    if (!stand)
X	alarm(TIMEOUT);
X
Xagain:
X    fromlen = sizeof(from);
X    c = recvfrom(s, buf, sizeof(buf), 0, (caddr_t)&from, &fromlen);
X    if (c <= 0) {
X	if (errno == EINTR && stand)
X	    goto again;
X	syslog(LOG_ERR, "recvfrom: %m\n");
X	exit(1);
X    }
X#ifdef DEBUG
X    hp = gethostbyaddr(&from.sin_addr, sizeof (struct in_addr), AF_INET);
X    fprintf(stderr, "main: received validation request from %s\n",
X	    hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
X#endif
X
X    if (logging) {
X	hp = gethostbyaddr(&from.sin_addr, sizeof (struct in_addr), AF_INET);
X	syslog(LOG_INFO, "validation request from %s",
X	    hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
X#ifdef DEBUG
X	fprintf(stderr, "main: logged validation request\r\n");
X#endif
X    }
X
X
X    tp = (tacacstype *)buf;
X
X    if (tp->version == TA_VERSION)
X	old_process(s, &from, tp);
X    else if (tp->version == XTA_VERSION)
X	new_process(s, &from, tp);
X    else if (logging)
X	syslog(LOG_INFO, "illegal version specified: %d\n", tp->version);
X
X    if (stand)
X	goto again;
X
X    exit(0);
X}
X
X/*
X * pw_verify
X * verify the provided name/password.
X */
Xpw_verify (name, passwd, ppw)
X#ifdef SYSV
X    char name[SOME_ARBITRARILY_LARGE_NUMBER];
X    char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
X#else    
X    char *name, *passwd;
X#endif
X    struct passwd **ppw;
X{
X    struct passwd *pw;
X    
X#ifdef DEBUG
X    fprintf(stderr, "pw_verify: calling setpwent\r\n");
X#endif
X
X    setpwent();
X    if (file != NULL)
X	setpwfile(file);
X#ifdef DEBUG
X    fprintf(stderr, "pw_verify: returned from setpwent\r\n");
X#endif      
X    pw = getpwnam(name);
X#ifdef DEBUG
X    fprintf(stderr, "pw_verify: returned %x from getpwnam\r\n", pw);
X#endif      
X
X#ifdef DEBUG
X    if (pw)
X	fprintf(stderr, "password: user %8.8s, password %13.13s\r\n",
X		pw->pw_name, pw->pw_passwd);
X#endif
X
X
X    /*
X     * Verify the entry.
X     */
X    if (pw != NULL && *passwd != '\0' && *pw->pw_passwd != '\0') {
X#ifdef SYSV
X	strcpy(passwd, (char *)crypt(passwd, pw->pw_passwd));
X#else
X	passwd = (char *)crypt(passwd, pw->pw_passwd);
X#endif	
X#ifdef DEBUG
X	fprintf(stderr, "encrypted: real %s, query %s\r\n", pw->pw_passwd, passwd);
X#endif
X	*ppw = pw;
X	if (strcmp(passwd, pw->pw_passwd) == 0)
X	    return(1);
X    }
X    *ppw = NULL;
X    return(0);
X}
X
X/*
X * process
X * Perform necessary stuff to do a query operation. Return ANSWER.
X */
X
Xold_process (s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    tacacstype *tp;
X{
X#ifdef SYSV
X    char name[SOME_ARBITRARILY_LARGE_NUMBER];
X    char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
X#else    
X    char *name, *passwd;
X#endif
X    struct passwd *pw;
X    int expired;
X
X    querytime = time(NULL);
X#ifdef DEBUG
X    fprintf(stderr, "process: starting\r\n");
X    fprintf(stderr, "process: namelen %d, pwdlen %d\r\n",
X	    tp->namelen, tp->pwlen);
X#endif
X#ifndef SYSV    
X    name = (char *)malloc(tp->namelen+1); 
X#ifdef DEBUG
X    fprintf(stderr, "process: malloc returned (name)\r\n");
X    if (name == NULL)
X      fprintf(stderr, "process: malloc failed on name (%d bytes)\r\n",
X	    tp->namelen+1);
X#endif      
X    passwd = (char *)malloc(tp->pwlen+1);
X#ifdef DEBUG
X    if (passwd == NULL)
X      fprintf(stderr, "process: malloc failed on passwd (%d bytes)\r\n",
X	    tp->pwlen+1);
X#endif      
X    if (name == NULL || passwd == NULL)
X	return;
X#endif /* not SYSV */
X    
X    strncpy(name, (char *)(tp + 1), tp->namelen);
X    name[tp->namelen] = '\0';
X    strncpy(passwd, (char *)(tp + 1) + tp->namelen, tp->pwlen);
X    if (tp->pwlen > PASSWD_LENGTH)
X	tp->pwlen = PASSWD_LENGTH;
X    passwd[tp->pwlen] = '\0';
X
X#ifdef DEBUG
X    fprintf(stderr, "packet: %s %s\r\n", (char *)(tp + 1),
X	    (char *)(tp + 1) + tp->namelen);
X    fprintf(stderr, "local:  %s %s\r\n", name, passwd);
X#endif
X    /*
X     * Assume failure
X     */
X    tp->oresponse = TA_A_REJECTED;
X    tp->oreason = TA_A_DENIED;
X    if (pw_verify(name, passwd, &pw)) {
X	tp->oresponse = TA_A_ACCEPTED;
X	tp->oreason = TA_A_NONE;
X	
X	/*
X	 * Now check the expiration time.
X	 */
X	
X	expired = check_expiration(pw->pw_shell);
X	if (expired == 2) {
X	    tp->oresponse = TA_A_DENIED;
X	    tp->oreason = TA_A_EXPIRING;
X	} else if (expired == 1)
X	    tp->oreason = TA_A_EXPIRING;
X    }
X
X
X#ifdef DEBUG
X    fprintf(stderr, "process: logging query result\r\n");
X#endif
X    if (logging) {
X	if (pw != NULL)
X	    syslog(LOG_INFO, "login query for %s (%s) %s\n", name, pw->pw_gecos,
X		tp->oresponse == TA_A_ACCEPTED ? "accepted" : "rejected");
X	else
X	    syslog(LOG_INFO, "login query for %s %s\n", name,
X		tp->oresponse == TA_A_ACCEPTED ? "accepted" : "rejected");
X    }
X
X    tp->type = TA_ANSWER;
X#ifdef DEBUG
X    fprintf(stderr, "process: sending query result to client\r\n");
X#endif
X    if (sendto(s, buf, sizeof(tacacstype), 0, client,
X	sizeof(struct sockaddr_in)) != sizeof(tacacstype))
X	syslog(LOG_ERR, "write: %m\n");
X
X#ifndef SYSV
X    free(name);
X    free(passwd);
X#endif    
X#ifdef DEBUG
X    fprintf(stderr, "process: done\r\n");
X#endif
X}
X
X/*
X * new_process
X * Perform necessary stuff to do a query operation. Return ANSWER.
X */
X
Xnew_process (s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X#ifdef DEBUG
X    fprintf(stderr, "new_process: start\r\n");
X#endif
X    querytime = time(NULL);
X    switch (tp->type) {
X      case XTA_SLIPADDR:
X      case XTA_LOGIN:
X	xlogin(s, client, tp);
X	break;
X      case XTA_CONNECT:
X	xconnect(s, client, tp);
X	break;
X      case XTA_ENABLE:
X	xenable(s, client, tp);
X	break;
X      case XTA_LOGOUT:
X	xlogout(s, client, tp);
X	break;
X      case XTA_RELOAD:
X	xreload(s, client, tp);
X	break;
X      case XTA_SLIPON:
X	xslipon(s, client, tp);
X	break;
X      case XTA_SLIPOFF:
X	xslipoff(s, client, tp);
X	break;
X      default:
X	if (logging)
X	    syslog(LOG_INFO, "illegal type specified: %d", tp->type);
X    }
X}
X
Xcheck_expiration(date)
X    char *date;
X{
X    long day, month, year, leaps, now, expiration, warning;
X    char monthstr[10];
X
X    /*
X     * If no date or a shell, let it pass.  (Backward compatability.)
X     */
X    if (!date || (strlen(date) == 0) || (*date == '/'))
X	return(0);
X    
X    /*
X     * Parse date string.  Fail it upon error.
X     */
X    if (sscanf(date, "%s %d %d", monthstr, &day, &year) != 3)
X	return(2);
X
X    /*
X     * Compute the expiration date in days.
X     */
X    for (month = 0; month < 12; month++)
X	if (strncmp(monthstr, monthname[month], 3) == 0)
X	    break;
X    if (month > 11)
X	return(2);
X    leaps = (year-1969)/4 + (((year % 4) == 0) && (month > 2));
X    expiration = (((year-1970)*365) + days_ere_month[month] + (day-1) + leaps);
X    warning = expiration - WARNING_PERIOD;
X
X    /*
X     * Get the current time (to the day)
X     */
X    now = querytime/SEC_IN_DAY;
X    
X    if (now > expiration)
X	return(2);
X    if (now > warning)
X	return(1);
X    return(0);
X}
X
X#ifndef BSD43
X/*
X * setpwfile
X * Hack to get around the default for the pw routines using /etc/passwd
X */
X
X#include <sys/stat.h>
X
Xsetpwfile (file)
X    char *file;
X{
X    FILE *f;
X    struct stat pwbuf, fbuf;
X    int i;
X    char *c;
X
X    if (stat("/etc/passwd", &pwbuf) < 0) {
X	syslog(LOG_ERR, "stat: %m\n");
X	exit(1);
X    }
X
X    setpwent();				/* open /etc/passwd */
X
X    /*
X     * This loop assumes that the stdio file buffers are contiguous
X     * which isn't true for 4.3, but then we won't be here.
X     */
X
X    for (f = stderr + 1; f < stdin + getdtablesize(); f++)
X        if (f->_flag & (_IOREAD|_IOWRT|_IORW) &&
X	    fstat(fileno(f), &fbuf) >= 0 &&
X	    pwbuf.st_dev == fbuf.st_dev &&
X	    pwbuf.st_ino == fbuf.st_ino) {
X	    freopen(file, "r", f);
X	    fprintf(stderr, "hit at %d\n", fileno(f));
X	    return;
X	}
X
X    syslog(LOG_ERR, "couldn't find /etc/passwd to replace");
X    exit(1);
X}
X#endif
X
X#ifdef SYSV
Xgetdtablesize()
X{
X  return(_NFILE);
X}
X#endif
X
Xwtmp_entry (line, name, host)
X    char *line, *name, *host;
X{
X    struct utmp entry;
X
X    if (wtmpf == NULL)
X	return;
X
X    bzero(&entry, sizeof entry);
X
X    if (strlen(line) < sizeof entry.ut_line)
X	strcpy(entry.ut_line, line);
X    else bcopy(line, entry.ut_line, sizeof entry.ut_line);
X
X    if (strlen(name) < sizeof entry.ut_name)
X	strcpy(entry.ut_name, name);
X    else bcopy(name, entry.ut_name, sizeof entry.ut_name);
X
X    if (strlen(host) < sizeof entry.ut_host)
X	strcpy(entry.ut_host, host);
X    else bcopy(host, entry.ut_host, sizeof entry.ut_host);
X
X    entry.ut_time = querytime;
X
X    if (fwrite(&entry, sizeof entry, 1, wtmpf) != 1) {
X	if (logging)
X	    syslog(LOG_ERR, "couldn't write syslog file");
X    } else
X	fflush(wtmpf);
X	    
X
X#ifdef DEBUG1
X    fprintf(stderr, "\nwtmp: %s, %s %s %d", line, name, host, querytime);
X#endif
X
X}
X
Xxlogin (s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X#ifdef SYSV
X    char name[SOME_ARBITRARILY_LARGE_NUMBER];
X    char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
X#else    
X    char *name, *passwd;
X#endif
X    struct passwd *pw;
X    int expired;
X    char linename[20];
X
X#ifdef DEBUG
X    fprintf(stderr, "xlogin: starting\r\n");
X    fprintf(stderr, "xlogin: namelen %d, pwdlen %d\r\n",
X	    tp->namelen, tp->pwlen);
X#endif
X#ifndef SYSV    
X    name = (char *)malloc(tp->namelen+1); 
X#ifdef DEBUG
X    fprintf(stderr, "xlogin: malloc returned (name)\r\n");
X    if (name == NULL)
X      fprintf(stderr, "xlogin: malloc failed on name (%d bytes)\r\n",
X	    tp->namelen+1);
X#endif      
X    passwd = (char *)malloc(tp->pwlen+1);
X#ifdef DEBUG
X    if (passwd == NULL)
X      fprintf(stderr, "xlogin: malloc failed on passwd (%d bytes)\r\n",
X	    tp->pwlen+1);
X#endif      
X    if (name == NULL || passwd == NULL)
X	return;
X#endif /* not SYSV */
X    strncpy(name, ((char *)tp)+XTACACSSIZE, tp->namelen);
X    name[tp->namelen] = '\0';
X    strncpy(passwd, ((char *)tp)+XTACACSSIZE + tp->namelen, tp->pwlen);
X    if (tp->pwlen > PASSWD_LENGTH)
X	tp->pwlen = PASSWD_LENGTH;
X    passwd[tp->pwlen] = '\0';
X
X#ifdef DEBUG
X    fprintf(stderr, "packet: %s %s\r\n", (char *)(tp + 1),
X	    (char *)(tp + 1) + tp->namelen);
X    fprintf(stderr, "local:  %s %s\r\n", name, passwd);
X#endif
X#ifdef DEBUG1
X    fprintf(stderr, "\nxlogin: user %s on tty%o, host %s", name, tp->lport,
X	    hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));	    
X#endif
X    /*
X     * Assume failure
X     */
X    tp->response = TA_A_REJECTED;
X    tp->reason = TA_A_DENIED;
X    if (pw_verify(name, passwd, &pw)) {
X	tp->response = XTA_A_ACCEPTED;
X	tp->reason = XTA_A_NONE;
X	tp->uuid = pw->pw_uid;
X	tp->accesslist = pw->pw_gid;
X	tp->flags = xta_getflags(pw->pw_gecos);
X
X	/*
X	 * Now check the expiration time.
X	 */
X
X	expired = check_expiration(pw->pw_shell);
X	if (expired == 2) {
X	    tp->response = TA_A_DENIED;
X	    tp->reason = TA_A_EXPIRING;
X	} else if (expired == 1)
X	    tp->reason = TA_A_EXPIRING;
X    }
X
X#ifdef DEBUG
X    fprintf(stderr, "xlogin: logging query result\r\n");
X#endif
X    sprintf(linename, "TTY%o", tp->lport);
X    if (tp->response == TA_A_ACCEPTED && tp->type == XTA_LOGIN)
X	wtmp_entry(linename, name, 
X	       hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
X
X#ifdef DEBUG
X    fprintf(stderr, "xlogin: sending query result to client\r\n");
X#endif
X    if (logging && tp->type == XTA_LOGIN) {
X	if (pw != NULL)
X	    syslog(LOG_INFO, "xlogin query from %s %s for %s (%s) %s\n", 
X		   hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), 
X		   linename, name, pw->pw_gecos,
X		tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
X	else
X	    syslog(LOG_INFO, "xlogin query from %s %s for %s %s\n",
X		   hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
X		   linename, name,
X		   tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
X    }
X    if (logging && tp->type == XTA_SLIPADDR) {
X	if (pw != NULL)
X	    syslog(LOG_INFO, "slipaddress from %s %s for %s (%s) %s\n", 
X		   hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), 
X		   linename, name, pw->pw_gecos,
X		tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
X	else
X	    syslog(LOG_INFO, "slipaddress from %s %s for %s %s\n",
X		   hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
X		   linename, name,
X		   tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
X    }
X    tp->type = TA_ANSWER;
X    if (sendto(s, buf, XTACACSSIZE, 0, client,
X	sizeof(struct sockaddr_in)) != XTACACSSIZE)
X	syslog(LOG_ERR, "write: %m\n");
X
X#ifndef SYSV
X    free(name);
X    free(passwd);
X#endif    
X#ifdef DEBUG
X    fprintf(stderr, "xlogin: done\r\n");
X#endif
X}
X
Xxconnect(s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X    struct hostent *hp1;
X    char *name = ((char *)tp)+XTACACSSIZE;
X
X    name[tp->namelen] = 0;
X    hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
X
X#ifdef DEBUG1
X    fprintf(stderr, "\nxconnect: user %.*s(%d) to %s:%d", tp->namelen,
X	    ((char *)tp)+XTACACSSIZE, tp->uuid,
X	    hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost), tp->dport);
X#endif
X    
X    
X    if (logging)
X	syslog(LOG_INFO, "xconnect from %s tty%o for %s (%d) to %s:%d\n",
X	       hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
X	       tp->lport, name, tp->uuid,
X	       hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost), tp->dport);
X    replyok (s, client, tp);
X}
X
Xxenable (s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X#ifdef SYSV
X    char name[SOME_ARBITRARILY_LARGE_NUMBER];
X    char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
X#else    
X    char *name, *passwd;
X#endif
X    struct passwd *pw;
X    int expired;
X    char linename[20];
X
X#ifndef SYSV    
X    name = (char *)malloc(tp->namelen+1); 
X    passwd = (char *)malloc(tp->pwlen+1);
X    if (name == NULL || passwd == NULL)
X	return;
X#endif /* not SYSV */
X    
X    sprintf(linename, "TTY%o", tp->lport);
X    strncpy(name, (char *)(tp + 1), tp->namelen);
X    name[tp->namelen] = '\0';
X    strncpy(passwd, (char *)(tp + 1) + tp->namelen, tp->pwlen);
X    if (tp->pwlen > PASSWD_LENGTH)
X	tp->pwlen = PASSWD_LENGTH;
X    passwd[tp->pwlen] = '\0';
X
X#ifdef DEBUG1
X    fprintf(stderr, "\nxenable: user %s on tty%o, host %s", name, tp->lport,
X	    hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));	    
X#endif
X    /*
X     * Assume failure
X     */
X    tp->response = TA_A_REJECTED;
X    tp->reason = TA_A_DENIED;
X    if (pw_verify("$enable$", passwd, &pw)) {
X	tp->response = XTA_A_ACCEPTED;
X	tp->reason = XTA_A_NONE;
X	tp->uuid = pw->pw_uid;
X	tp->accesslist = pw->pw_gid;
X	tp->flags = xta_getflags(pw->pw_gecos);
X
X	/*
X	 * Now check the expiration time.
X	 */
X
X	expired = check_expiration(pw->pw_shell);
X	if (expired == 2) {
X	    tp->response = TA_A_DENIED;
X	    tp->reason = TA_A_EXPIRING;
X	} else if (expired == 1)
X	    tp->reason = TA_A_EXPIRING;
X    }
X
X    sprintf(linename, "TTY%o", tp->lport);
X
X    tp->type = TA_ANSWER;
X    if (logging)
X	    syslog(LOG_INFO, "xenable from %s %s for %s %s\n", 
X		   hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), 
X		   linename, name,
X		tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
X    if (sendto(s, buf, XTACACSSIZE, 0, client,
X	sizeof(struct sockaddr_in)) != XTACACSSIZE)
X	syslog(LOG_ERR, "write: %m\n");
X
X#ifndef SYSV
X    free(name);
X    free(passwd);
X#endif    
X}
X
Xxlogout (s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X    char *name = ((char *)tp)+XTACACSSIZE;
X    char linename[20];
X    char *reason;
X
X    switch(tp->reason) {
X      case XTA_R_IDLE:
X	reason = "Idle-timeout";
X	break;
X      case XTA_R_DROP:
X	reason = "Carrier-Drop";
X	break;
X      case XTA_R_BAD:
X	reason = "Bad-Passwords";
X	break;
X      case XTA_R_QUIT:
X	reason = "";
X	break;
X      default:
X	reason = "Unknown-reason";
X	break;
X    }
X
X    name[tp->namelen] = 0;
X
X#ifdef DEBUG1
X    fprintf(stderr, "\nxlogout:  user %s(%d) line %o %s", name, tp->uuid,
X	    tp->lport, reason);
X#endif
X    sprintf(linename, "TTY%o", tp->lport);
X    if (logging)
X	syslog(LOG_INFO, "xlogout from %s %s, user %s(%d) %s\n",
X	       hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), linename,
X	       name, tp->uuid, reason);
X    wtmp_entry(linename, "", 
X	       hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
X    replyok (s, client, tp);
X}
X
Xxreload(s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X#ifdef DEBUG1
X    fprintf(stderr, "\nxreload: host %s",
X	    hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
X#endif
X    if (logging)
X	syslog(LOG_INFO, "system reload from %s\n",
X	       hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
X    wtmp_entry("~", "", hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
X    replyok (s, client, tp);
X}
X
Xxslipon(s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X    struct hostent *hp1;
X    char linename[20];
X    char *name = (char *) (tp + 1);
X
X    name[tp->namelen] = 0;
X
X    hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
X
X#ifdef DEBUG1
X    fprintf(stderr, "\nxslipon:  user %.*s(%d) line %o slip address %s",
X	    tp->namelen, ((char *)tp)+XTACACSSIZE, tp->uuid, tp->lport, 
X	    hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
X
X#endif
X    sprintf(linename, "SLIP%o", tp->lport);
X    wtmp_entry(linename, name, hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
X    if (logging)
X	syslog(LOG_INFO, "xslipon from %s %s for  user %s(%d) address %s\n",
X	       hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), linename,
X	       name, tp->uuid,
X	       hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
X
X
X    replyok (s, client, tp);
X}
X
X
Xxslipoff(s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X    struct hostent *hp1;
X    char linename[20];
X    char *name;
X
X    hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
X
X
X#ifdef DEBUG1
X    fprintf(stderr, "\nxslipoff:  user %.*s(%d) line %o slip address %s",
X	    tp->namelen, ((char *)tp)+XTACACSSIZE, tp->uuid, tp->lport,
X	    hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
X
X#endif
X    sprintf(linename, "SLIP%o", tp->lport);
X    wtmp_entry(linename, "",  hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
X    name = (char *) (((char *)tp)+XTACACSSIZE);
X    name[tp->namelen] = 0;    if (logging)
X    if (logging)
X	syslog(LOG_INFO, "xslip off from %s %s for %s(%d) address %s\n",
X	       hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), linename,
X	       name, tp->uuid,
X	       hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost));
X
X    replyok (s, client, tp);
X}
X
Xxta_getflags (string)
X    char * string;
X{
X    return(0);
X}
X
X/*
X * Send an "ok" reply to client (for things like reload, logout)
X */
Xreplyok (s, client, tp)
X    int s;
X    struct sockaddr_in *client;
X    xtacacstype *tp;
X{
X    tp->response = XTA_A_ACCEPTED;
X    tp->reason = XTA_A_NONE;
X    tp->type = TA_ANSWER;
X    if (sendto(s, buf, XTACACSSIZE, 0, client,
X	sizeof(struct sockaddr_in)) != XTACACSSIZE)
X	syslog(LOG_ERR, "write: %m\n");
X}
END_OF_FILE
if test 22676 -ne `wc -c <'xtacacsd/xtacacsd.c'`; then
    echo shar: \"'xtacacsd/xtacacsd.c'\" unpacked with wrong size!
fi
# end of 'xtacacsd/xtacacsd.c'
fi
if test -f 'xtacacsd/include/paths.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/include/paths.h'\"
else
echo shar: Extracting \"'xtacacsd/include/paths.h'\" \(1591 characters\)
sed "s/^X//" >'xtacacsd/include/paths.h' <<'END_OF_FILE'
X/*
X * Copyright (c) 1989 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted provided
X * that: (1) source distributions retain this entire copyright notice and
X * comment, and (2) distributions including binaries display the following
X * acknowledgement:  ``This product includes software developed by the
X * University of California, Berkeley and its contributors'' in the
X * documentation or other materials provided with the distribution and in
X * all advertising materials mentioning features or use of this software.
X * Neither the name of the University nor the names of its contributors may
X * be used to endorse or promote products derived from this software without
X * specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	@(#)paths.h	5.7 (Berkeley) 6/24/90
X */
X
X#define	_PATH_BSHELL	"/bin/sh"
X#define	_PATH_CONSOLE	"/dev/console"
X#define	_PATH_CSHELL	"/bin/csh"
X#define	_PATH_DEV	"/dev/"
X#define	_PATH_DEVNULL	"/dev/null"
X#define	_PATH_DRUM	"/dev/drum"
X#define	_PATH_KMEM	"/dev/kmem"
X#define	_PATH_MAILDIR	"/var/mail"
X#define	_PATH_MAN	"/usr/man"
X#define	_PATH_MEM	"/dev/mem"
X#define	_PATH_NOLOGIN	"/etc/nologin"
X#define	_PATH_SENDMAIL	"/usr/sbin/sendmail"
X#define	_PATH_TMP	"/tmp/"
X#define	_PATH_TTY	"/dev/tty"
X#define	_PATH_UNIX	"/vmunix"
X#define	_PATH_VARTMP	"/var/tmp"
X#define	_PATH_VI	"/usr/bin/vi"
END_OF_FILE
if test 1591 -ne `wc -c <'xtacacsd/include/paths.h'`; then
    echo shar: \"'xtacacsd/include/paths.h'\" unpacked with wrong size!
fi
# end of 'xtacacsd/include/paths.h'
fi
if test ! -d 'xtacacsd/include/sys' ; then
    echo shar: Creating directory \"'xtacacsd/include/sys'\"
    mkdir 'xtacacsd/include/sys'
fi
if test -f 'xtacacsd/include/sys/syslog.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtacacsd/include/sys/syslog.h'\"
else
echo shar: Extracting \"'xtacacsd/include/sys/syslog.h'\" \(5262 characters\)
sed "s/^X//" >'xtacacsd/include/sys/syslog.h' <<'END_OF_FILE'
X/*
X * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution is only permitted until one year after the first shipment
X * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
X * binary forms are permitted provided that: (1) source distributions retain
X * this entire copyright notice and comment, and (2) distributions including
X * binaries display the following acknowledgement:  This product includes
X * software developed by the University of California, Berkeley and its
X * contributors'' in the documentation or other materials provided with the
X * distribution and in all advertising materials mentioning features or use
X * of this software.  Neither the name of the University nor the names of
X * its contributors may be used to endorse or promote products derived from
X * this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	@(#)syslog.h	7.16 (Berkeley) 6/28/90
X */
X
X/*
X * priorities/facilities are encoded into a single 32-bit quantity, where the
X * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
X * (0-big number).  Both the priorities and the facilities map roughly
X * one-to-one to strings in the syslogd(8) source code.  This mapping is
X * included in this file.
X *
X * priorities (these are ordered)
X */
X#define	LOG_EMERG	0	/* system is unusable */
X#define	LOG_ALERT	1	/* action must be taken immediately */
X#define	LOG_CRIT	2	/* critical conditions */
X#define	LOG_ERR		3	/* error conditions */
X#define	LOG_WARNING	4	/* warning conditions */
X#define	LOG_NOTICE	5	/* normal but significant condition */
X#define	LOG_INFO	6	/* informational */
X#define	LOG_DEBUG	7	/* debug-level messages */
X
X#define	LOG_PRIMASK	0x07	/* mask to extract priority part (internal) */
X				/* extract priority */
X#define	LOG_PRI(p)	((p) & LOG_PRIMASK)
X#define	LOG_MAKEPRI(fac, pri)	(((fac) << 3) | (pri))
X
X#ifdef SYSLOG_NAMES
X#define	INTERNAL_NOPRI	0x10	/* the "no priority" priority */
X				/* mark "facility" */
X#define	INTERNAL_MARK	LOG_MAKEPRI(LOG_NFACILITIES, 0)
Xtypedef struct _code {
X	char	*c_name;
X	int	c_val;
X} CODE;
X
XCODE prioritynames[] = {
X	"alert",	LOG_ALERT,
X	"crit",		LOG_CRIT,
X	"debug",	LOG_DEBUG,
X	"emerg",	LOG_EMERG,
X	"err",		LOG_ERR,
X	"error",	LOG_ERR,		/* DEPRECATED */
X	"info",		LOG_INFO,
X	"none",		INTERNAL_NOPRI,		/* INTERNAL */
X	"notice",	LOG_NOTICE,
X	"panic", 	LOG_EMERG,		/* DEPRECATED */
X	"warn",		LOG_WARNING,		/* DEPRECATED */
X	"warning",	LOG_WARNING,
X	NULL,		-1,
X};
X#endif
X
X/* facility codes */
X#define	LOG_KERN	(0<<3)	/* kernel messages */
X#define	LOG_USER	(1<<3)	/* random user-level messages */
X#define	LOG_MAIL	(2<<3)	/* mail system */
X#define	LOG_DAEMON	(3<<3)	/* system daemons */
X#define	LOG_AUTH	(4<<3)	/* security/authorization messages */
X#define	LOG_SYSLOG	(5<<3)	/* messages generated internally by syslogd */
X#define	LOG_LPR		(6<<3)	/* line printer subsystem */
X#define	LOG_NEWS	(7<<3)	/* network news subsystem */
X#define	LOG_UUCP	(8<<3)	/* UUCP subsystem */
X#define	LOG_CRON	(9<<3)	/* clock daemon */
X	/* other codes through 15 reserved for system use */
X#define	LOG_LOCAL0	(16<<3)	/* reserved for local use */
X#define	LOG_LOCAL1	(17<<3)	/* reserved for local use */
X#define	LOG_LOCAL2	(18<<3)	/* reserved for local use */
X#define	LOG_LOCAL3	(19<<3)	/* reserved for local use */
X#define	LOG_LOCAL4	(20<<3)	/* reserved for local use */
X#define	LOG_LOCAL5	(21<<3)	/* reserved for local use */
X#define	LOG_LOCAL6	(22<<3)	/* reserved for local use */
X#define	LOG_LOCAL7	(23<<3)	/* reserved for local use */
X
X#define	LOG_NFACILITIES	24	/* current number of facilities */
X#define	LOG_FACMASK	0x03f8	/* mask to extract facility part */
X				/* facility of pri */
X#define	LOG_FAC(p)	(((p) & LOG_FACMASK) >> 3)
X
X#ifdef SYSLOG_NAMES
XCODE facilitynames[] = {
X	"auth",		LOG_AUTH,
X	"cron", 	LOG_CRON,
X	"daemon",	LOG_DAEMON,
X	"kern",		LOG_KERN,
X	"lpr",		LOG_LPR,
X	"mail",		LOG_MAIL,
X	"mark", 	INTERNAL_MARK,		/* INTERNAL */
X	"news",		LOG_NEWS,
X	"security",	LOG_AUTH,		/* DEPRECATED */
X	"syslog",	LOG_SYSLOG,
X	"user",		LOG_USER,
X	"uucp",		LOG_UUCP,
X	"local0",	LOG_LOCAL0,
X	"local1",	LOG_LOCAL1,
X	"local2",	LOG_LOCAL2,
X	"local3",	LOG_LOCAL3,
X	"local4",	LOG_LOCAL4,
X	"local5",	LOG_LOCAL5,
X	"local6",	LOG_LOCAL6,
X	"local7",	LOG_LOCAL7,
X	NULL,		-1,
X};
X#endif
X
X#ifdef KERNEL
X#define	LOG_PRINTF	-1	/* pseudo-priority to indicate use of printf */
X#endif
X
X/*
X * arguments to setlogmask.
X */
X#define	LOG_MASK(pri)	(1 << (pri))		/* mask for one priority */
X#define	LOG_UPTO(pri)	((1 << ((pri)+1)) - 1)	/* all priorities through pri */
X
X/*
X * Option flags for openlog.
X *
X * LOG_ODELAY no longer does anything.
X * LOG_NDELAY is the inverse of what it used to be.
X */
X#define	LOG_PID		0x01	/* log the pid with each message */
X#define	LOG_CONS	0x02	/* log on the console if errors in sending */
X#define	LOG_ODELAY	0x04	/* delay open until first syslog() (default) */
X#define	LOG_NDELAY	0x08	/* don't delay open */
X#define	LOG_NOWAIT	0x10	/* don't wait for console forks: DEPRECATED */
X#define	LOG_PERROR	0x20	/* log to stderr as well */
END_OF_FILE
if test 5262 -ne `wc -c <'xtacacsd/include/sys/syslog.h'`; then
    echo shar: \"'xtacacsd/include/sys/syslog.h'\" unpacked with wrong size!
fi
# end of 'xtacacsd/include/sys/syslog.h'
fi
echo shar: End of shell archive.
exit 0
