Article View: comp.dcom.sys.cisco
Article #81Re: Need help with TACACS server code on HP
From: Vikas Aggarwal
Date: Wed, 05 Aug 1992 11:57
Date: Wed, 05 Aug 1992 11:57
1200 lines
31140 bytes
31140 bytes
> tacacsd[13581]: ioctl(FIONBIO): Invalid argument
Funny thing is that it compiled okay...
Anyway, the same kind of functionality can be achieved using the 'recvfrom'
call. My version of xtacacsd is considerably different than perhaps the one
on ftp.cisco.com, so you will have to adapt the following code extract.
-vikas (609) 258-2403
vikas@jvnc.net ...rutgers!jvncnet!vikas
--------------------------------------------------------------------------
else /* if not standalone, under inetd */
{
s = 0;
/* if (ioctl(s, FIONBIO, &blockon) < 0)
* {
* syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
* exit(1);
* }
*/
}
/*
* For 4.3BSD machines, this routine sets the file the pw routines use
* to the given argument. We emulate it for others.
*/
setpwent() ; /* open/rewind default /etc/passwd */
if (wtmpfile != NULL)
if ((wtmpf = fopen(wtmpfile, "a+")) == NULL)
fprintf(stderr, "\nCan't open wtmp file \"%s\"", wtmpfile);
signal (SIGALRM, onalarm);
lastmsgtime = time(NULL) ;
alarm(TIMEOUT);
for ( ; ; ) /* forever */
{
fromlen = sizeof(from);
if (!stand)
s = 0 ;
c = recvfrom(s, buf, sizeof(buf), 0, (caddr_t)&from, &fromlen);
if (c <= 0)
{
if (errno == EINTR && stand)
continue ;
if (errno == EINTR && c == 0) /* under inetd */
continue ;
syslog(LOG_ERR, "recvfrom: %m\n");
exit(1); /* some error */
}
sigblock(1<<SIGALRM) ; /* block ALARM's */
lastmsgtime = time(NULL) ;
if (logging)
{
if (nonameserver == 0)
hp = gethostbyaddr(&from.sin_addr, sizeof (struct in_addr), AF_INET);
else
hp = NULL ;
syslog(LOG_INFO, "main: validation request from %s [%s]",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
(char *)inet_ntoa(from.sin_addr));
#ifdef DEBUG
fprintf(stderr, "main: logged validation request\r\n");
#endif
} /* end: if logging */
tp = (tacacstype *)buf;
if (tp->version == TA_VERSION)
old_process(s, &from, tp);
else if (tp->version == XTA_VERSION)
new_process(s, &from, tp);
else if (logging)
syslog(LOG_INFO,
"main: illegal version specified: %d\n", tp->version);
sigsetmask(0) ; /* allow all signals */
} /* end: forever */
/* NOT REACHED */
exit(0);
} /* end: main */
/*+ onalarm
* Exit after MAXIDLE secs of inactivity
*/
onalarm()
{
if (!stand)
if (time(NULL) - lastmsgtime >= MAXIDLE)
{
if (debug)
syslog(LOG_DEBUG,
"Inactive for %d secs, tired of hanging around...",
MAXIDLE) ;
exit (0);
}
alarm(TIMEOUT) ; /* reset alarm */
} /* onalarm() */
/*+ pw_verify:
*
* Verify the provided name/password.
* Checks the password supplied by the user in all the supplied passwd
* filenames (only /etc/passwd if none supplied). The supplied filenames are
* in 'pwfile'.
*
* To prevent password anomalies, does not accept if the password field
* is blank in the passwd file (like netmon or nicol). Also, do not accept
* if the uid is '0'.
*
* Return's 1 if password OK, else '0' and NULLS the 'pw' struct
*/
int pw_verify (name, passwd, ppw)
#ifdef SYSV
char name[SOME_ARBITRARILY_LARGE_NUMBER];
char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
#else
char *name, *passwd;
#endif
struct passwd **ppw;
{
int i = 0 ;
struct passwd *pw;
nextpwf: /* for a loop */
#ifdef DEBUG
fprintf(stderr, "pw_verify: calling setpwent\r\n");
#endif
if (*pwfile != NULL)
if (pwfile[i] != NULL)
{
endpwent() ; /* closes present passwd file */
setpwfile(pwfile[i]); /* changes the current password file */
}
setpwent(); /* rewinds current password file */
#ifdef DEBUG
fprintf(stderr, "pw_verify: returned from setpwent\r\n");
#endif
pw = getpwnam(name);
#ifdef DEBUG
fprintf(stderr, "pw_verify: returned %x from getpwnam\r\n", pw);
#endif
#ifdef DEBUG /* Warning- this prints out the users passwd */
if (pw)
fprintf(stderr, "password: user %8.8s, password %13.13s\r\n",
pw->pw_name, pw->pw_passwd);
#endif
if (debug && logging && pw)
syslog(LOG_INFO, "pw_verify: Match for %s found in file %s\n",
pw->pw_name, *pwfile ? pwfile[i] : "/etc/passwd") ;
/* Verify the entry. No access to uid '0' or blank passwords */
if (pw != NULL && *passwd != '\0' && *pw->pw_passwd != '\0' && pw->pw_uid != 0)
{
#ifdef SYSV
strcpy(passwd, (char *)crypt(passwd, pw->pw_passwd));
#else
passwd = (char *)crypt(passwd, pw->pw_passwd);
#endif
#ifdef DEBUG
fprintf(stderr, "encrypted: real %s, query %s\r\n",
pw->pw_passwd, passwd);
#endif
if (logging && debug)
syslog(LOG_DEBUG, "pw_verify: encrypted real %s, query %s\n",
pw->pw_passwd, passwd);
*ppw = pw;
if (strcmp(passwd, pw->pw_passwd) == 0)
return(1); /* Okay */
}
if (pwfile[++i] != NULL) /* more passwd files */
goto nextpwf ; /* ...and match yet not found */
/*
* Here only if no matching password found
*/
if (logging)
syslog(LOG_INFO, "pw_verify: password match failed for user '%s'\n",
name);
*ppw = NULL; /* set pw to NULL */
return(0); /* No match in passwd files */
} /* end: pw_verify */
/*+ old_process:
*
* Perform necessary stuff to do a query. Return ANSWER
*/
void old_process(s, client, tp)
int s;
struct sockaddr_in *client;
tacacstype *tp;
{
#ifdef SYSV
char name[SOME_ARBITRARILY_LARGE_NUMBER];
char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
#else
char *name, *passwd;
#endif
struct passwd *pw;
int expired;
#ifdef TOLOWER
register char *p ;
register i ;
p = (char *)(tp + 1); /* move past header */
for (i = 0; i < tp->namelen; ++i, ++p) /* reduce name to lower case */
*p = tolower(*p) ;
#endif /* TOLOWER */
querytime = time(NULL);
#ifdef DEBUG
fprintf(stderr, "old_process: starting\r\n");
fprintf(stderr, "old_process: namelen %d, pwdlen %d\r\n",
tp->namelen, tp->pwlen);
#endif
#ifndef SYSV
name = (char *)malloc(tp->namelen+1);
#ifdef DEBUG
fprintf(stderr, "old_process: malloc returned (name)\r\n");
if (name == NULL)
fprintf(stderr, "old_process: malloc failed on name (%d bytes)\r\n",
tp->namelen+1);
#endif
passwd = (char *)malloc(tp->pwlen+1);
#ifdef DEBUG
if (passwd == NULL)
fprintf(stderr, "old_process: malloc failed on passwd (%d bytes)\r\n",
tp->pwlen+1);
#endif
if (name == NULL || passwd == NULL)
return;
#endif /* not SYSV */
strncpy(name, (char *)(tp + 1), tp->namelen);
name[tp->namelen] = '\0';
strncpy(passwd, (char *)(tp + 1) + tp->namelen, tp->pwlen);
if (tp->pwlen > PASSWD_LENGTH)
tp->pwlen = PASSWD_LENGTH;
passwd[tp->pwlen] = '\0';
#ifdef DEBUG
fprintf(stderr, "packet: %s %s\r\n", (char *)(tp + 1),
(char *)(tp + 1) + tp->namelen);
fprintf(stderr, "local: %s %s\r\n", name, passwd);
#endif
/* Assume failure */
tp->oresponse = TA_A_REJECTED;
tp->oreason = TA_A_DENIED;
if (pw_verify(name, passwd, &pw)) /* verify the password */
{
tp->oresponse = TA_A_ACCEPTED;
tp->oreason = TA_A_NONE;
/*
* Now check the expiration time.
*/
expired = check_expiration(pw->pw_shell);
if (expired == 2)
{
tp->oresponse = TA_A_DENIED;
tp->oreason = TA_A_EXPIRING;
}
else if (expired == 1)
tp->oreason = TA_A_EXPIRING;
/*
* Now check the GID. The GID can control a lot,,,
*/
if (pw != NULL && check_gid (pw) != 0) /* deny */
{
tp->oresponse = TA_A_DENIED;
tp->oreason = TA_A_DENIED;
}
}
#ifdef DEBUG
fprintf(stderr, "old_process: logging query result\r\n");
#endif
if (logging)
{
if (pw != NULL)
syslog(LOG_INFO, "old_process: login query for %s (%.10s ..) %s\n",
name, pw->pw_gecos,
tp->oresponse == TA_A_ACCEPTED ? "accepted" : "rejected");
else
syslog(LOG_NOTICE, "old_process: login query for %s %s\n", name,
tp->oresponse == TA_A_ACCEPTED ? "accepted" : "rejected");
}
tp->type = TA_ANSWER;
if (quiet && tp->oresponse != TA_A_ACCEPTED) /* don't respond */
{
if (logging)
syslog(LOG_INFO, "old_process: not sending DENIED since quiet\n");
}
else
{
#ifdef DEBUG
fprintf(stderr, "old_process: sending query result to client\r\n");
#endif
if (sendto(s, buf, sizeof(tacacstype), 0, client,
sizeof(struct sockaddr_in)) != sizeof(tacacstype))
syslog(LOG_ERR, "write: %m\n");
}
#ifndef SYSV
free(name);
free(passwd);
#endif
#ifdef DEBUG
fprintf(stderr, "old_process: done\r\n");
#endif
} /* end: old_process */
/*+ new_process:
*
* Perform necessary stuff to do a query operation. Return ANSWER.
*/
void new_process (s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
#ifdef TOLOWER
register char *p ;
register i ;
p = ((char *)tp) + XTACACSSIZE; /* move past header */
for (i = 0; i < tp->namelen; ++i, ++p) /* reduce name to lower case */
*p = tolower(*p) ;
#endif /* TOLOWER */
#ifdef DEBUG
fprintf(stderr, "new_process: start\r\n");
if (logging)
syslog(LOG_DEBUG, "new_process: Querytype %d for '%.*s'", tp->type,
tp->namelen, ((char *)tp) + XTACACSSIZE ) ;
#endif
querytime = time(NULL);
switch (tp->type)
{
case XTA_SLIPADDR:
case XTA_LOGIN:
xlogin(s, client, tp);
break;
case XTA_CONNECT:
xconnect(s, client, tp);
break;
case XTA_ENABLE:
xenable(s, client, tp);
break;
case XTA_LOGOUT:
xlogout(s, client, tp);
break;
case XTA_RELOAD:
xreload(s, client, tp);
break;
case XTA_SLIPON:
xslipon(s, client, tp);
break;
case XTA_SLIPOFF:
xslipoff(s, client, tp);
break;
default:
if (logging)
syslog(LOG_INFO, "new_process: illegal type specified: %d",tp->type);
} /* end switch */
} /* end new_process */
/*+ check_expiration:
*
* Returns 0 if OK, 1 if warning, 2 if expired
*/
int check_expiration(date)
char *date;
{
long day, month, year, leaps, now, expiration, warning;
char monthstr[10];
/* If no date or a shell, let it pass. (Backward compatability.) */
if (!date || (strlen(date) == 0) || (*date == '/'))
return(0);
/* Parse date string. Fail it upon error. */
if (sscanf(date, "%s %d %d", monthstr, &day, &year) != 3)
return(2);
/* Compute the expiration date in days. */
for (month = 0; month < 12; month++)
if (strncmp(monthstr, monthname[month], 3) == 0)
break;
if (month > 11)
return(2);
leaps = (year-1969)/4 + (((year % 4) == 0) && (month > 2));
expiration = (((year-1970)*365) + days_ere_month[month] + (day-1) + leaps);
warning = expiration - WARNING_PERIOD;
/*
* Get the current time (to the day)
*/
now = querytime/SEC_IN_DAY;
if (now > expiration)
return(2);
if (now > warning)
return(1);
return(0);
} /* end: check_expiration() */
/*
* check_gid:
*
* Checks the pw->gid field. See discussion above on what all the GID
* can/is used for.
* Ignores #logins if the last digit is zero.
* Looks in the UTMP file (not the WTMP file)
*
* Returns '0' if OK.
*/
check_gid(pw)
struct passwd *pw ;
{
int lgid, ugid, gid, current_logins = 0;
int status = 0 ; /* Return status, set to OK */
struct utmp entry ;
register FILE *f ; /* for the utmp file */
gid = (int)pw->pw_gid ;
bzero(&entry, sizeof entry);
#ifdef L_DENY_GID
#ifdef U_DENY_GID
lgid = L_DENY_GID ; ugid = U_DENY_GID ;
if (gid >= lgid && gid <= ugid)
status = 1 ; /* deny permission */
if (logging)
{
if (status)
syslog (LOG_INFO, "check_gid: gid %d matches DENY_GID\n", gid) ;
else if (debug)
syslog (LOG_DEBUG,
"check_gid: Checking 'DENY' limits for gid %d (%d <> %d)\n",
gid, lgid, ugid) ;
}
#endif /* U_DENY_GID */
#endif /* L_DENY_GID */
if (status)
return (status) ;
#ifdef L_NUMLOGINS_GID
#ifdef U_NUMLOGINS_GID
lgid = L_NUMLOGINS_GID ; ugid = U_NUMLOGINS_GID ;
if (gid >= lgid && gid <= ugid) /* check for number of logins */
if ((gid = pw->pw_gid % 10)) /* grab the last digit, ignore 0 */
{
/*
* Now find out the number of logins in the utmp file
*/
if ((f = fopen(utmpfile, "r")) == NULL)
{
syslog(LOG_ERR, "check_gid: Cannot open utmp file- %s\n",
utmpfile);
return (1); /* Cannot open file, deny */
}
while (fread((char *)&entry, sizeof(entry), 1, f) == 1)
{
if (strcmp(entry.ut_name, pw->pw_name)) /* no match */
continue;
else
++current_logins ;
}
fclose (f);
#ifdef DEBUG
fprintf(stderr, "check_gid: current logins= %d, allowed= %d\n",
current_logins, gid);
#endif
if ( current_logins > gid )
status = 2 ; /* Exceeded logins */
if (logging && (status || debug))
syslog(LOG_INFO,
"check_gid: current logins= %d, allowed= %d",
current_logins, gid);
}
#endif /* U_NUMLOGINS_GID */
#endif /* L_NUMLOGINS_GID */
return (status) ;
} /* end: check_gid() */
#ifndef BSD43
/*+ setpwfile:
*
* Hack to get around the default for the pw routines using /etc/passwd
*/
#include <sys/stat.h>
void setpwfile (file)
char *file;
{
FILE *f;
struct stat pwbuf, fbuf;
int i;
char *c;
if (stat("/etc/passwd", &pwbuf) < 0) {
syslog(LOG_ERR, "setpwfile (stat): %m\n");
exit(1);
}
setpwent(); /* open /etc/passwd */
/*
* This loop assumes that the stdio file buffers are contiguous
* which isn't true for 4.3, but then we won't be here.
*/
for (f = stderr + 1; f < stdin + getdtablesize(); f++)
if (f->_flag & (_IOREAD|_IOWRT|_IORW) &&
fstat(fileno(f), &fbuf) >= 0 &&
pwbuf.st_dev == fbuf.st_dev &&
pwbuf.st_ino == fbuf.st_ino) {
freopen(file, "r", f);
fprintf(stderr, "hit at %d\n", fileno(f));
return;
}
syslog(LOG_ERR, "setpwfile: couldn't find /etc/passwd to replace");
exit(1);
}
#endif /* BSD43 */
#ifdef SYSV
getdtablesize()
{
return(_NFILE);
}
#endif
/*+ wtmp_entry:
*
* Updates the main 'wtmpfile' and also the terminal server specific ones.
* Since this is also called by 'slipOn' and 'slipOff' with line types
* of SLIP_TTY, put those entries in the 'WTMP.slip' file.
*
* For other names, it updates a wtmp file of the form 'WTMP.hostname'
*
*/
void wtmp_entry (line, name, host)
char *line ; /* Incoming line for user */
char *name; /* User's login name */
char *host ; /* The name/ip of the host */
{
char wfile[BUFSIZ] ; /* alternate file to update */
FILE *wf ;
struct utmp entry;
if (wtmpf == NULL) /* main wtmp file should exist */
return;
bzero(&entry, sizeof entry);
if (strlen(line) < sizeof entry.ut_line)
strcpy(entry.ut_line, line);
else bcopy(line, entry.ut_line, sizeof entry.ut_line);
if (strlen(name) < sizeof entry.ut_name)
strcpy(entry.ut_name, name);
else bcopy(name, entry.ut_name, sizeof entry.ut_name);
if (strlen(host) < sizeof entry.ut_host)
strcpy(entry.ut_host, host);
else bcopy(host, entry.ut_host, sizeof entry.ut_host);
entry.ut_time = querytime;
#ifdef DEBUG1
fprintf(stderr, "\nwtmp: %s, %s %s %d", line, name, host, querytime);
#endif
if (fwrite(&entry, sizeof entry, 1, wtmpf) != 1) {
syslog(LOG_ERR, "wtmp_entry: couldn't write wtmp file- %s",
wtmpfile);
}
else
fflush(wtmpf);
if (wtmpfile != NULL) /* The 'prefix' for alternate file */
strcat(strcpy(wfile, wtmpfile), ".") ;
/*
* Check and update the 'slip' wtmp file if line type is SLIP_TTY
*/
if (strncmp(line, SLIP_TTY, strlen(SLIP_TTY)) == 0)
strcat(wfile, "slip") ; /* create unique '.slip' file */
else /* create a sensible filename */
{
if (*host < '0' || *host > '9') /* Not an IP address,,, */
strncat(wfile, host, strcspn(host, ".")) ; /* only header */
else
strncat(wfile, host, strlen(host)) ;
wfile[sizeof(wfile)] = '\0'; /* terminating NULL */
}
if ((wf = fopen(wfile, "a+")) == NULL)
{
syslog(LOG_ERR, "wtmp_entry: couldn't open wtmp- %s", wfile);
return ;
}
if (fwrite(&entry, sizeof entry, 1, wf) != 1)
syslog(LOG_ERR, "wtmp_entry: couldn't write wtmp file- %s", wfile);
else
{
fflush(wf); /* close the alternate wtmp file */
fclose(wf) ;
}
} /* end: wtmp_entry */
/*+ xlogin:
*
* Called by new_process(). Checks password of user against all the
* password files. Routine very similar to the 'old_process()' function.
* Calls wtmp_entry() to make an entry in the wtmp file.
*/
void xlogin (s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
#ifdef SYSV
char name[SOME_ARBITRARILY_LARGE_NUMBER];
char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
#else
char *name, *passwd;
#endif
struct passwd *pw;
int expired;
char linename[20];
#ifdef DEBUG
fprintf(stderr, "xlogin: starting\r\n");
fprintf(stderr, "xlogin: namelen %d, pwdlen %d\r\n",
tp->namelen, tp->pwlen);
#endif
#ifndef SYSV
name = (char *)malloc(tp->namelen+1);
#ifdef DEBUG
fprintf(stderr, "xlogin: malloc returned (name)\r\n");
if (name == NULL)
fprintf(stderr, "xlogin: malloc failed on name (%d bytes)\r\n",
tp->namelen+1);
#endif
passwd = (char *)malloc(tp->pwlen+1);
#ifdef DEBUG
if (passwd == NULL)
fprintf(stderr, "xlogin: malloc failed on passwd (%d bytes)\r\n",
tp->pwlen+1);
#endif
/* If no name or no passwd for LOGIN queries, just return */
if ((name == NULL || passwd == NULL) && (tp->type == XTA_LOGIN))
return;
#endif /* not SYSV */
strncpy(name, ((char *)tp) + XTACACSSIZE, tp->namelen);
name[tp->namelen] = '\0';
strncpy(passwd, ((char *)tp) + XTACACSSIZE + tp->namelen, tp->pwlen);
if (tp->pwlen > PASSWD_LENGTH)
tp->pwlen = PASSWD_LENGTH;
passwd[tp->pwlen] = '\0';
sprintf(linename, "%s%o", TS_TTY, tp->lport);
/*
* If IP address is default on the terminal servers, then the 'username'
* will be 'default' for SLIP mode. Set to default for XTA_SLIP and
* reject for XTA_LOGIN.
*/
if ((strncmp(name,"default",7) == 0) && (tp->type == XTA_SLIPADDR))
strcpy(passwd, DEFAULTS_IP_PASSWORD);
if ((strncmp(name,"default",7) == 0) && (tp->type == XTA_LOGIN))
strcpy(passwd, "*") ; /* Junk password */
#ifdef DEBUG
fprintf(stderr, "packet: %s %s\r\n", (char *)(tp + 1),
(char *)(tp + 1) + tp->namelen);
fprintf(stderr, "local: %s %s\r\n", name, passwd);
#endif
#ifdef DEBUG1
fprintf(stderr, "\nxlogin: user '%s' on %s, host %s", name, linename,
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
#endif
/* Assume failure */
tp->response = TA_A_REJECTED;
tp->reason = TA_A_DENIED;
if (pw_verify(name, passwd, &pw))
{
tp->response = XTA_A_ACCEPTED;
tp->reason = XTA_A_NONE;
tp->uuid = pw->pw_uid;
tp->accesslist = pw->pw_gid;
tp->flags = xta_getflags(pw->pw_gecos);
/* Now check the expiration time. */
expired = check_expiration(pw->pw_shell);
if (expired == 2)
{
tp->response = TA_A_DENIED;
tp->reason = TA_A_EXPIRING;
}
else
if (expired == 1)
tp->reason = TA_A_EXPIRING;
/* Check the GID. */
if (pw != NULL && check_gid (pw) != 0) /* deny */
{
tp->response = TA_A_DENIED;
tp->reason = TA_A_DENIED;
}
}
#ifdef DEBUG
fprintf(stderr, "xlogin: logging query result\r\n");
#endif
if (tp->response == TA_A_ACCEPTED && tp->type == XTA_LOGIN)
wtmp_entry(linename, name,
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr)) ;
if (logging && tp->type == XTA_LOGIN)
{
if (pw != NULL)
syslog(LOG_INFO, "xlogin: query from %s %s for %s (%.10s..) %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
linename, name, pw->pw_gecos,
tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
else
syslog(LOG_NOTICE, "xlogin: query from %s %s for %s %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
linename, name,
tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
}
if (logging && tp->type == XTA_SLIPADDR) {
if (pw != NULL)
syslog(LOG_INFO,
"xlogin: slipaddress from %s %s for %s (%.10s) %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
linename, name, pw->pw_gecos,
tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
else
syslog(LOG_NOTICE, "xlogin: slipaddress from %s %s for %s %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
linename, name,
tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
}
tp->type = TA_ANSWER;
if (quiet && tp->response != TA_A_ACCEPTED) /* dont respond */
{
if (logging)
syslog(LOG_INFO, "xlogin: not sending DENIED since quiet\n");
}
else
{
#ifdef DEBUG
fprintf(stderr, "xlogin: sending query result to client\r\n");
#endif
if (sendto(s, buf, sizeof(xtacacstype), 0, client,
sizeof(struct sockaddr_in)) != sizeof(xtacacstype))
syslog(LOG_ERR, "write: %m\n");
}
#ifndef SYSV
free(name);
free(passwd);
#endif
#ifdef DEBUG
fprintf(stderr, "xlogin: done\r\n");
#endif
} /* end: xlogin() */
/*+ xconnect:
*
* Called when user connects to a specific host & port.
*/
void xconnect(s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
struct hostent *hp1;
char linename[20];
char *name = ((char *)tp) + XTACACSSIZE;
name[tp->namelen] = 0;
sprintf(linename, "%s%o", TS_TTY, tp->lport);
if ( nonameserver == 0 )
hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
else
hp1 = NULL ;
#ifdef DEBUG1
fprintf(stderr, "\nxconnect: user %.*s(%d) to %s:%d", tp->namelen,
((char *)tp) + XTACACSSIZE, tp->uuid,
hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost), tp->dport);
#endif
if (logging)
syslog(LOG_INFO, "xconnect: from %s [%s] %s for %s (%d) to %s:%d\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
(char *)inet_ntoa(from.sin_addr),
linename, name, tp->uuid,
hp1 ? hp1->h_name : (char *)inet_ntoa(tp->dhost),
tp->dport);
replyok (s, client, tp);
} /* end: xconnect() */
/*+ xenable:
*
*
*/
void xenable (s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
#ifdef SYSV
char name[SOME_ARBITRARILY_LARGE_NUMBER];
char passwd[SOME_ARBITRARILY_LARGE_NUMBER];
#else
char *name, *passwd;
#endif
struct passwd *pw;
int expired;
char linename[20];
#ifndef SYSV
name = (char *)malloc(tp->namelen+1);
passwd = (char *)malloc(tp->pwlen+1);
if (name == NULL || passwd == NULL)
return;
#endif /* not SYSV */
sprintf(linename, "%s%o", TS_TTY, tp->lport);
strncpy(name, (char *)(tp + 1), tp->namelen);
name[tp->namelen] = '\0';
strncpy(passwd, (char *)(tp + 1) + tp->namelen, tp->pwlen);
if (tp->pwlen > PASSWD_LENGTH)
tp->pwlen = PASSWD_LENGTH;
passwd[tp->pwlen] = '\0';
#ifdef DEBUG1
fprintf(stderr, "\nxenable: user %s on %s, host %s", name, linename,
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
#endif
/*
* Assume failure
*/
tp->response = TA_A_REJECTED;
tp->reason = TA_A_DENIED;
if (pw_verify("$enable$", passwd, &pw))
{
tp->response = XTA_A_ACCEPTED;
tp->reason = XTA_A_NONE;
tp->uuid = pw->pw_uid;
tp->accesslist = pw->pw_gid;
tp->flags = xta_getflags(pw->pw_gecos);
/* Now check the expiration time. */
expired = check_expiration(pw->pw_shell);
if (expired == 2)
{
tp->response = TA_A_DENIED;
tp->reason = TA_A_EXPIRING;
}
else if (expired == 1)
tp->reason = TA_A_EXPIRING;
/* Now check the GID. */
if (pw != NULL && check_gid (pw) != 0) /* deny */
{
tp->response = TA_A_DENIED;
tp->reason = TA_A_DENIED;
}
}
tp->type = TA_ANSWER;
if (logging)
syslog(LOG_INFO, "xenable: from %s %s for %s %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
linename, name,
tp->response == TA_A_ACCEPTED ? "accepted" : "rejected");
if (sendto(s, buf, sizeof(xtacacstype), 0, client,
sizeof(struct sockaddr_in)) != sizeof(xtacacstype))
syslog(LOG_ERR, "write: %m\n");
#ifndef SYSV
free(name);
free(passwd);
#endif
} /* end: xenable() */
/* xlogout:
*
* Called when the user logs out.
*/
void xlogout (s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
char *name = ((char *)tp) + XTACACSSIZE;
char linename[20];
char *reason;
switch(tp->reason) {
case XTA_R_IDLE:
reason = "Idle-timeout";
break;
case XTA_R_DROP:
reason = "Carrier-Drop";
break;
case XTA_R_BAD:
reason = "Bad-Passwords";
break;
case XTA_R_QUIT:
reason = "";
break;
default:
reason = "Unknown-reason";
break;
}
name[tp->namelen] = 0;
#ifdef DEBUG1
fprintf(stderr, "\nxlogout: user %s(%d) line %o %s", name, tp->uuid,
tp->lport, reason);
#endif
sprintf(linename, "%s%o", TS_TTY, tp->lport);
if (logging)
syslog(LOG_INFO, "xlogout: from %s %s, user %s(%d) %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr), linename,
name, tp->uuid, reason);
wtmp_entry(linename, "",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr)) ;
replyok (s, client, tp);
} /* end: xlogout() */
/*+ xreload:
*
* Called when a terminal server is rebooted. It calls wtmp_entry
* to make an entry similar to the one made when a system reboots. Needed
* for accounting 'ac'
*/
void xreload(s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
#ifdef DEBUG1
fprintf(stderr, "\nxreload: host %s",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
#endif
if (logging)
syslog(LOG_NOTICE, "xreload: system reload from %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
wtmp_entry("~", "", hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr)) ;
replyok (s, client, tp);
} /* end: xreload */
/*+ xslipon:
*
* Called when a user invokes 'slip'. Makes an entry in wtmp with
* a tty name of SLIP_TTY and host is the selected SLIP address.
*/
void xslipon(s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
struct hostent *hp1;
char linename[20];
char *name = ((char *)tp) + XTACACSSIZE;
name[tp->namelen] = 0;
sprintf(linename, "%s%o", SLIP_TTY, tp->lport); /* name of line */
if (nonameserver == 0)
hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
else
hp1 = NULL ;
#ifdef DEBUG1
fprintf(stderr, "\nxslipon: user %.*s(%d) on %s slip address %s",
tp->namelen, ((char *)tp) + XTACACSSIZE, tp->uuid, linename,
hp1 ? hp1->h_name : (char *)inet_ntoa(&tp->dhost));
#endif
wtmp_entry(linename, name, (char *)inet_ntoa(&tp->dhost));
if (logging)
syslog(LOG_INFO, "xslipon: from %s [%s] (%s) for %s(%d) address %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
(char *)inet_ntoa(from.sin_addr),
linename, name, tp->uuid,
hp1 ? hp1->h_name : (char *)inet_ntoa(&tp->dhost));
replyok (s, client, tp);
} /* end: xslipon */
/*+ xslipoff:
*
* Called when slip turned off by user. Entry logged in wtmp file
* with host of the selected SLIP address.
*/
void xslipoff(s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
struct hostent *hp1;
char linename[20];
char *name;
sprintf(linename, "%s%o", SLIP_TTY, tp->lport);
if (nonameserver == 0 )
hp1 = gethostbyaddr(&tp->dhost, sizeof (struct in_addr), AF_INET);
else
hp1 = NULL ;
#ifdef DEBUG1
fprintf(stderr, "\nxslipoff: user %.*s(%d) on %s slip address %s",
tp->namelen, ((char *)tp) + XTACACSSIZE, tp->uuid, linename,
hp1 ? hp1->h_name : (char *)inet_ntoa(&tp->dhost));
#endif
wtmp_entry(linename, "", (char *)inet_ntoa(&tp->dhost));
name = (char *) (((char *)tp) + XTACACSSIZE);
name[tp->namelen] = 0; if (logging)
if (logging)
syslog(LOG_INFO, "xslipoff: from %s [%s] (%s) for %s(%d) address %s\n",
hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr),
(char *)inet_ntoa(from.sin_addr),
linename, name, tp->uuid,
hp1 ? hp1->h_name : (char *)inet_ntoa(&tp->dhost));
replyok (s, client, tp);
} /* end: xslipoff() */
xta_getflags (string)
char * string;
{
return(0);
}
/*+ replyok:
*
* This function sends an "ok" reply to client (for things like reload,
* logout). Called by xslipoff()
*
*/
void replyok (s, client, tp)
int s;
struct sockaddr_in *client;
xtacacstype *tp;
{
tp->response = XTA_A_ACCEPTED;
tp->reason = XTA_A_NONE;
tp->type = TA_ANSWER;
if (sendto(s, buf, sizeof(xtacacstype), 0, client,
sizeof(struct sockaddr_in)) != sizeof(xtacacstype))
syslog(LOG_ERR, "write: %m\n");
} /* end: replyok() */
Technical Details
Message-ID:
<9208051157.AA24851@nisc.jvnc.net>Path:
arc1-ca.pugleaf.net!sparky!uunet!stanford.edu!agate!boulder!recnewsShow Full Headers
Complete Article Headers
Newsgroups: comp.dcom.sys.cisco Path: arc1-ca.pugleaf.net!sparky!uunet!stanford.edu!agate!boulder!recnews From: aggarwal@nisc.jvnc.net (Vikas Aggarwal) Subject: Re: Need help with TACACS server code on HP In-Reply-To: <920804090019.25600634@CCV.NERSC.GOV>; from "MACKANIC@CCV.NERSC.GOV" at Aug 4, 92 9:00 am Message-ID: <9208051157.AA24851@nisc.jvnc.net> Sender: news@colorado.edu Date: 5 Aug 92 7:57:02 EDT X-Mailer: ELM [version 2.3 PL11] Lines: 1200