Shadow login release 2 (part 2 of 3)
John F. Haugh II
jfh at rpp386.Dallas.TX.US
Tue Jun 20 16:50:33 AEST 1989
X-Archive-Name: shadow2/part2
Part 2 of second USENET release
--
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# lastlog.h
# login.c
# motd.c
# password.c
# shell.c
# utmp.c
# age.c
# env.c
# pwent.c
# shadow.c
# valid.c
# lmain.c
# smain.c
# pwconv.c
# dialup.c
# dialchk.c
# pwunconv.c
# failure.c
# faillog.h
# faillog.c
# This archive created: Tue Jun 20 01:24:59 1989
# By: John F. Haugh II (River Parishes Programming, Plano TX)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'lastlog.h'
then
echo shar: "will not over-write existing file 'lastlog.h'"
else
cat << \SHAR_EOF > 'lastlog.h'
/*
* lastlog.h - structure of lastlog file
*
* This file defines a lastlog file structure which should be sufficient
* to hold the information required by login. It should only be used if
* there is no real lastlog.h file.
*/
struct lastlog {
time_t ll_time;
char ll_line[8];
};
SHAR_EOF
fi
if test -f 'login.c'
then
echo shar: "will not over-write existing file 'login.c'"
else
cat << \SHAR_EOF > 'login.c'
#include <stdio.h>
#include <ctype.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
void setenv ();
void login (name)
char *name;
{
char buf[BUFSIZ];
char *envp[32];
int envc;
char *cp;
int i;
#ifndef BSD
(void) memset (buf, '\0', sizeof buf);
#else
bzero (buf, sizeof buf);
#endif
fputs ("login: ", stdout);
if (fgets (buf, BUFSIZ, stdin) != buf)
exit (1);
buf[strlen (buf) - 1] = '\0'; /* remove \n [ must be there ] */
for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
;
for (i = 0;i < BUFSIZ - 1 && isgraph (*cp);name[i++] = *cp++)
;
if (*cp)
cp++;
name[i] = '\0';
if (*cp != '\0') { /* process new variables */
for (envc = 0;envc < 32;envc++) {
envp[envc] = strtok (envc == 0 ? cp:(char *) 0, " \t,");
if (envp[envc] == (char *) 0)
break;
}
setenv (envc, envp);
}
}
SHAR_EOF
fi
if test -f 'motd.c'
then
echo shar: "will not over-write existing file 'motd.c'"
else
cat << \SHAR_EOF > 'motd.c'
#include <stdio.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)motd.c 2.1 01:23:27 6/20/89";
#endif
extern char home[];
#ifdef HUSHLOGIN
extern int hushed;
#endif
#ifdef MOTD
void motd ()
{
FILE *fp;
register int c;
#ifdef HUSHLOGIN
if (hushed)
return;
#endif
if ((fp = fopen ("/etc/motd", "r")) == (FILE *) 0)
return;
while ((c = getc (fp)) != EOF)
putchar (c);
fclose (fp);
fflush (stdout);
}
#endif
SHAR_EOF
fi
if test -f 'password.c'
then
echo shar: "will not over-write existing file 'password.c'"
else
cat << \SHAR_EOF > 'password.c'
#include <stdio.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#ifndef BSD
#include <termio.h>
#else
#include <sgtty.h>
#endif
#include <fcntl.h>
/*
* password - prompt for password and return entry
*
* Need to fake up getpass(). Returns TRUE if a password
* was successfully input, and FALSE otherwise, including
* EOF on input or ioctl() failure. pass is not modified
* on failure. The input length limit may be set by
* changing the value of PASSLIMIT.
*/
#ifndef lint
static char _sccsid[] = "@(#)password.c 2.1 01:23:33 6/20/89";
#endif
#define PASSLIMIT 20
int password (prompt, pass)
char *prompt;
char *pass;
{
char buf[BUFSIZ];
char *cp;
int eof;
int ttyopened = 0;
#ifndef BSD
struct termio termio;
struct termio save;
#else
struct sgttyb termio ;
struct sgttyb save ;
#endif
FILE *fp;
if ((fp = fopen ("/dev/tty", "r")) == (FILE *) 0)
fp = stdin;
else
ttyopened = 1;
#ifndef BSD
if (ioctl (fileno (fp), TCGETA, &termio))
return (0);
#else
if ( gtty( fileno(fp), &termio ) )
return (0);
#endif
save = termio;
#ifndef BSD
termio.c_lflag &= ~(ECHO|ECHOE|ECHOK);
ioctl (fileno (fp), TCSETAF, &termio);
#else
termio.sg_flags &= ~ECHO ;
stty( fileno( fp ), termio ) ;
#endif
fputs (prompt, stdout);
eof = fgets (buf, BUFSIZ, fp) == (char *) 0 || feof (fp) || ferror (fp);
putchar ('\n');
#ifndef BSD
ioctl (fileno (fp), TCSETAF, &save);
#else
stty( fileno( fp ), save ) ;
#endif
if (! eof) {
buf[PASSLIMIT] = '\0';
if ((cp = strchr (buf, '\n')) || (cp = strchr (buf, '\r')))
*cp = '\0';
(void) strcpy (pass, buf);
}
if (ttyopened)
fclose (fp);
return (! eof);
}
SHAR_EOF
fi
if test -f 'shell.c'
then
echo shar: "will not over-write existing file 'shell.c'"
else
cat << \SHAR_EOF > 'shell.c'
#include <stdio.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)shell.c 2.1 01:23:53 6/20/89";
#endif
extern char *newenvp[];
void shell (file)
char *file;
{
char arg0[BUFSIZ];
char *path;
extern int errno;
if (file == (char *) 0)
exit (1);
if (path = strrchr (file, '/'))
path++;
else
path = file;
(void) strcpy (arg0 + 1, path);
arg0[0] = '-';
#ifndef NDEBUG
printf ("Executing shell %s\n", file);
#endif
execle (file, arg0, (char *) 0, newenvp);
printf ("Can't execute %s\n", file);
exit (errno);
}
SHAR_EOF
fi
if test -f 'utmp.c'
then
echo shar: "will not over-write existing file 'utmp.c'"
else
cat << \SHAR_EOF > 'utmp.c'
#include <sys/types.h>
#include <utmp.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include <stdio.h>
#include "config.h"
extern struct utmp utent;
extern char name[];
struct utmp *getutent ();
void setutent ();
void endutent ();
void pututline ();
time_t time ();
void checkutmp ()
{
struct utmp *ut;
#ifndef NDEBUG
int pid = getppid ();
#else
int pid = getpid ();
#endif
setutent ();
while (ut = getutent ())
if (ut->ut_pid == pid)
break;
if (ut)
utent = *ut;
endutent ();
if (ut && utent.ut_pid == pid)
return;
puts ("No utmp entry. You must exec \"login\" from the lowest level \"sh\"");
exit (1);
}
void setutmp ()
{
FILE *wtmp;
char tty[sizeof utent.ut_line + 1];
char *line;
setutent ();
(void) strncpy (utent.ut_user, name, sizeof utent.ut_user);
utent.ut_type = USER_PROCESS;
if (line = strrchr (utent.ut_line, '/')) {
(void) strcpy (tty, line + 1);
#ifndef BSD
(void) memset (utent.ut_line, '\0', sizeof utent.ut_line);
#else
bzero (utent.ut_line, sizeof utent.ut_line);
#endif
(void) strcpy (utent.ut_line, tty);
}
(void) time (&utent.ut_time);
pututline (&utent);
endutent ();
if ((wtmp = fopen (WTMP_FILE, "a+"))) {
fwrite (&utent, sizeof utent, 1, wtmp);
fclose (wtmp);
}
}
SHAR_EOF
fi
if test -f 'age.c'
then
echo shar: "will not over-write existing file 'age.c'"
else
cat << \SHAR_EOF > 'age.c'
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)age.c 2.11 01:23:02 6/20/89";
#endif
#ifndef PASSWD
extern char *newenvp[];
#endif
time_t time ();
int c64i (c)
char c;
{
if (c == '.')
return (0);
if (c == '/')
return (1);
if (c >= '0' && c <= '9')
return (c - '0' + 2);
if (c >= 'A' && c <= 'Z')
return (c - 'A' + 12);
if (c >= 'a' && c <= 'z')
return (c - 'a' + 38);
else
return (-1);
}
#ifdef AGING
#ifdef PASSWD
#ifdef NEED_AL64
char *l64a (l)
long l;
{
static char buf[8];
int i = 0;
if (i < 0L)
return ((char *) 0);
do {
buf[i++] = i64c ((int) (l % 64));
buf[i] = '\0';
} while (l /= 64L, l > 0 && i < 6);
return (buf);
}
#endif
#endif
int i64c (i)
int i;
{
if (i < 0)
return ('.');
else if (i > 63)
return ('z');
if (i == 0)
return ('.');
if (i == 1)
return ('/');
if (i >= 2 && i <= 11)
return ('0' - 2 + i);
if (i >= 12 && i <= 37)
return ('A' - 12 + i);
if (i >= 38 && i <= 63)
return ('a' - 38 + i);
return ('\0');
}
#ifdef NEED_AL64
long a64l (s)
char *s;
{
int i;
long value;
long shift = 0;
for (i = 0, value = 0L;i < 6 && *s;s++) {
value += (c64i (*s) << shift);
shift += 6;
}
return (value);
}
#endif
#ifndef PASSWD
void expire (age)
char *age;
{
long clock;
long week;
extern char name[];
extern int errno;
(void) time (&clock);
clock /= (7L * 24L * 60L * 60L);
if (strlen (age) < 4)
week = 0L;
else
week = a64l (age + 2);
if (clock >= week + c64i (age[0])) {
printf ("Your password has expired.");
if (c64i (age[0]) < c64i (age[1])) {
puts (" Contact the system administrator.\n");
exit (1);
}
puts (" Choose a new one.\n");
execl ("/bin/passwd", "-passwd", name, (char *) 0);
puts ("Can't execute /bin/passwd");
exit (errno);
}
}
#endif
#endif
SHAR_EOF
fi
if test -f 'env.c'
then
echo shar: "will not over-write existing file 'env.c'"
else
cat << \SHAR_EOF > 'env.c'
#include <stdio.h>
#ifndef BSD
#include <string.h>
#else
#define strchr index
#define strrchr rindex
#include <strings.h>
#endif
#ifndef lint
static char _sccsid[] = "@(#)env.c 2.1 01:23:11 6/20/89";
#endif
extern char **environ;
extern char *newenvp[];
extern int newenvc;
extern int maxenv;
char *strdup ();
void free ();
static char *forbid[] = {
"HOME",
"IFS",
"PATH",
"SHELL",
(char *) 0
};
void addenv (entry)
char *entry;
{
char *cp;
int i;
int len;
if (cp = strchr (entry, '='))
len = cp - entry;
else
return;
for (i = 0;i < newenvc;i++)
if (strncmp (entry, newenvp[i], len) == 0 &&
(newenvp[i][len] == '=' || newenvp[i][len] == '\0'))
break;
if (i == maxenv) {
puts ("Environment overflow");
return;
}
if (i == newenvc) {
newenvp[newenvc++] = strdup (entry);
} else {
free (newenvp[i]);
newenvp[i] = strdup (entry);
}
}
void setenv (argc, argv)
int argc;
char **argv;
{
int i;
int n;
int noname = 1;
char variable[BUFSIZ];
char *cp;
for (i = 0;i < argc;i++) {
if ((n = strlen (argv[i])) >= BUFSIZ)
continue; /* ignore long entries */
if (! (cp = strchr (argv[i], '='))) {
(void) strcpy (variable, argv[i]);
} else {
(void) strncpy (variable, argv[i], cp - argv[i]);
variable[cp - argv[i]] = '\0';
}
for (n = 0;forbid[n] != (char *) 0;n++)
if (strcmp (variable, forbid[n]) == 0)
break;
if (forbid[n] != (char *) 0) {
printf ("You may not change $%s\n", forbid[n]);
continue;
}
if (cp) {
addenv (argv[i]);
} else {
sprintf (variable, "L%d=%s", noname++, argv[i]);
addenv (variable);
}
}
}
SHAR_EOF
fi
if test -f 'pwent.c'
then
echo shar: "will not over-write existing file 'pwent.c'"
else
cat << \SHAR_EOF > 'pwent.c'
#include <stdio.h>
#include <pwd.h>
#include <string.h>
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)pwent.c 2.1 01:23:41 6/20/89";
#endif
#define SBUFSIZ 64
#define NFIELDS 7
static char pwdbuf[BUFSIZ];
static char *pwdfields[NFIELDS];
struct passwd *sgetpwent (buf)
char *buf;
{
int i;
char *cp;
static struct passwd pwent;
strncpy (pwdbuf, buf, BUFSIZ);
pwdbuf[BUFSIZ-1] = '\0';
cp = pwdbuf;
for (i = 0;i < NFIELDS && cp;i++) {
pwdfields[i] = cp;
if (cp = strchr (cp, ':'))
*cp++ = 0;
}
if (i < (NFIELDS-1) || *pwdfields[2] == '\0' || *pwdfields[3] == '\0')
return ((struct passwd *) 0);
for (;i < NFIELDS;i++)
pwdfields[i] = 0;
pwent.pw_name = pwdfields[0];
pwent.pw_passwd = pwdfields[1];
pwent.pw_uid = atoi (pwdfields[2]);
pwent.pw_gid = atoi (pwdfields[3]);
if (cp = strchr (pwent.pw_passwd, ',')) {
pwent.pw_age = cp + 1;
*cp = '\0';
}
pwent.pw_gecos = pwdfields[4];
pwent.pw_dir = pwdfields[5];
pwent.pw_shell = pwdfields[6];
return (&pwent);
}
#ifdef FGETPWENT
struct passwd *fgetpwent (fp)
FILE *fp;
{
char buf[BUFSIZ];
while (fgets (buf, BUFSIZ, fp) != (char *) 0) {
if (buf[0] == '#')
continue;
buf[strlen (buf) - 1] = '\0';
return (sgetpwent (buf));
}
return ((struct passwd *) 0);
}
#endif
SHAR_EOF
fi
if test -f 'shadow.c'
then
echo shar: "will not over-write existing file 'shadow.c'"
else
cat << \SHAR_EOF > 'shadow.c'
#include "shadow.h"
#include <stdio.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#ifndef lint
static char _sccsid[] = "@(#)shadow.c 2.1 01:23:49 6/20/89";
#endif
static FILE *shadow;
void setspent ()
{
if (shadow)
rewind (shadow);
else
shadow = fopen (SHADOW, "r");
}
void endspent ()
{
if (shadow)
(void) fclose (shadow);
shadow = (FILE *) 0;
}
struct spwd *fgetspent (fp)
FILE *fp;
{
static struct spwd spwd;
static char name[32];
static char pass[32];
char buf[BUFSIZ];
char *cp;
int atoi ();
long atol ();
if (! fp)
return (0);
if (fgets (buf, BUFSIZ, fp) == (char *) 0)
return (0);
buf[strlen (buf) - 1] = '\0';
if ((cp = strtok (buf, ":")) && *cp)
(void) strcpy (name, cp);
else
return (0);
if ((cp = strtok ((char *) 0, ":")) && *cp)
(void) strcpy (pass, cp);
else
return (0);
if ((cp = strtok ((char *) 0, ":")) && *cp)
spwd.sp_lstchg = atol (cp);
else
return (0);
if ((cp = strtok ((char *) 0, ":")) && *cp)
spwd.sp_min = atoi (cp);
else
return (0);
if ((cp = strtok ((char *) 0, ":")) && *cp)
spwd.sp_max = atoi (cp);
else
return (0);
spwd.sp_namp = name;
spwd.sp_pwdp = pass;
return (&spwd);
}
struct spwd *getspent ()
{
if (! shadow)
setspent ();
return (fgetspent (shadow));
}
struct spwd *getspnam (name)
char *name;
{
struct spwd *spwd;
setspent ();
while ((spwd = getspent ()) != (struct spwd *) 0) {
if (strcmp (name, spwd->sp_namp) == 0)
return (spwd);
}
return (0);
}
int putspent (spwd, fp)
struct spwd *spwd;
FILE *fp;
{
if (! fp)
return (0);
return (fprintf (fp, "%s:%s:%ld:%ld:%ld\n",
spwd->sp_namp, spwd->sp_pwdp,
spwd->sp_lstchg, spwd->sp_min, spwd->sp_max) != EOF);
}
SHAR_EOF
fi
if test -f 'valid.c'
then
echo shar: "will not over-write existing file 'valid.c'"
else
cat << \SHAR_EOF > 'valid.c'
#include <stdio.h>
#include <pwd.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)valid.c 2.1 01:24:08 6/20/89";
#endif
/*
* valid - compare encrypted passwords
*
* Valid() compares the DES encrypted password from the password file
* against the password which the user has entered after it has been
* encrypted using the same salt as the original.
*/
int valid (password, entry)
char *password;
struct passwd *entry;
{
char *encrypt;
char *salt;
char *crypt ();
#ifdef DOUBLESIZE
int firsthalf;
int longpass;
#endif
/*
* Start with blank or empty password entries. Always encrypt
* a password if no such user exists. Only if the ID exists and
* the password is really empty do you return quickly. This
* routine is meant to waste CPU time.
*/
if (entry->pw_name &&
(entry->pw_passwd == (char *) 0 ||
strlen (entry->pw_passwd) == 0)) {
if (strlen (password) == 0)
return (1); /* user entered nothing */
else
return (0); /* user entered something! */
}
#ifdef DOUBLESIZE
longpass = entry->pw_passwd && strlen (entry->pw_passwd) > 13;
#endif
/*
*
/*
* If there is no entry then we need a salt to use.
*/
if (entry->pw_passwd == (char *) 0 || entry->pw_passwd[0] == '\0')
salt = "xx";
else
salt = entry->pw_passwd;
/*
* Now, perform the encryption using the salt from before on
* the users input. Since we always encrypt the string, it
* should be very difficult to determine if the user exists by
* looking at execution time.
*/
encrypt = crypt (password, salt);
#ifdef DOUBLESIZE
firsthalf = entry->pw_passwd
&& strncmp (encrypt + 2, entry->pw_passwd + 2, 11) == 0;
if (strlen (password) > 8)
encrypt = crypt (password + 8, salt);
else {
(void) crypt (password, salt); /* waste time ... */
encrypt = "";
}
#endif
/*
* One last time we must deal with there being no password file
* entry for the user. We use the pw_passwd == NULL idiom to
* cause non-existent users to not be validated. Even still,
* we are safe because if the string were == "", any encrypted
* string is not going to match - the output of crypt() begins
* with the salt, which is "xx", not "".
*/
#ifdef NOUSE
if (entry->pw_shell && strcmp ("NO_USE", entry->pw_shell) == 0)
return (0);
#endif
#ifndef DOUBLESIZE
if (entry->pw_passwd && strcmp (encrypt, entry->pw_passwd) == 0)
return (1);
else
return (0);
#else
if (! longpass)
return (firsthalf);
if (entry->pw_passwd && firsthalf
&& strncmp (encrypt + 2, entry->pw_passwd + 13) == 0)
return (1);
else
return (0);
#endif
}
SHAR_EOF
fi
if test -f 'lmain.c'
then
echo shar: "will not over-write existing file 'lmain.c'"
else
cat << \SHAR_EOF > 'lmain.c'
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pwd.h>
#include <utmp.h>
#include <time.h>
#include <signal.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#ifndef BSD
#include <termio.h>
#else
#include <sgtty.h>
#endif
#include "config.h"
#include "lastlog.h"
#include "faillog.h"
#ifndef lint
static char _sccsid[] = "@(#)lmain.c 2.1 01:23:18 6/20/89";
#endif
#ifndef ERASECHAR
#define ERASECHAR '\b' /* backspace */
#endif
#ifndef KILLCHAR
#define KILLCHAR '\025' /* control U */
#endif
char name[BUFSIZ];
char pass[BUFSIZ];
char home[BUFSIZ];
char prog[BUFSIZ];
char mail[BUFSIZ];
#ifdef HUSHLOGIN
char hush[BUFSIZ];
int hushed;
#endif
struct passwd pwent;
struct utmp utent;
struct lastlog lastlog;
#ifndef BSD
struct termio termio;
#endif
#ifndef MAXENV
#define MAXENV 64
#endif
char *newenvp[MAXENV];
int newenvc = 0;
int maxenv = MAXENV;
extern char **environ;
char *getenv ();
void checkutmp ();
void addenv ();
void setenv ();
unsigned alarm ();
void login ();
void entry ();
void setutmp ();
void subsystem ();
void log ();
void setup ();
void expire ();
void motd ();
void mailcheck ();
void shell ();
#ifdef TZ
FILE *tzfile;
char tzbuf[32] = TZ;
#endif
#ifndef ALARM
#define ALARM 60
#endif
#ifndef RETRIES
#define RETRIES 3
#endif
#ifdef FAILLOG
struct faillog faillog;
#endif
int main (argc, argv, envp)
int argc;
char **argv;
char **envp;
{
int retries = RETRIES;
int failed;
#ifdef CONSOLE
int conflag;
char console[BUFSIZ];
FILE *fp;
struct stat statbuf;
#endif
checkutmp (); /* must be lowest level shell */
if (! isatty (0)) /* must be a terminal */
exit (1);
#ifndef BSD
(void) ioctl (0, TCGETA, &termio); /* get terminal characteristics */
/*
* Add your favorite terminal modes here ...
*/
termio.c_lflag |= ISIG;
termio.c_cc[VERASE] = ERASECHAR;
termio.c_cc[VKILL] = KILLCHAR;
(void) ioctl (0, TCSETAF, &termio); /* set erase and kill characters */
#endif
#ifdef UMASK
umask (UMASK); /* override the default umask */
#endif
#ifdef ULIMIT
ulimit (2, (long) ULIMIT); /* override the default ulimit */
#endif
while (*envp) /* add inherited environment, */
addenv (*envp++); /* some variables change later */
#ifdef TZ
if (tzbuf[0] == '/') {
if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) {
if (fgets (tzbuf, sizeof tzbuf, tzfile)) {
tzbuf[strlen (tzbuf) - 1] = '\0';
addenv (tzbuf);
}
fclose (tzfile);
}
} else {
addenv (tzbuf);
}
#endif
#ifdef HZ
addenv (HZ); /* set the default $HZ, if one */
#endif
if (argc >= 2) { /* now set command line variables */
setenv (argc - 2, &argv[2]);
(void) strncpy (name, argv[1], sizeof name);
}
(void) alarm (ALARM); /* only allow ALARM sec. for login */
while (1) { /* repeatedly get login/password pairs */
if (! name[0]) { /* need to get a login id */
login (name);
continue;
}
entry (name, &pwent); /* get entry from password file */
failed = 0; /* hasn't failed validation yet */
/*
* Here we have a sticky situation. Some accounts may have no
* password entry in the password file. So, we don't ask for a
* password. Others, have a blank password entered - you be the
* judge. The conditional compilation NOBLANK requires even
* blank passwords to be prompted for. This may well break
* quite a few systems. Use with discretion.
*/
#ifdef NOBLANK
/* get a password from user */
if (! password ("Password:", pass))
continue;
#else
if ((! pwent.pw_name || pwent.pw_passwd)
&& ! password ("Password:", pass))
continue;
#endif
if (! valid (pass, &pwent)) /* check encrypted passwords ... */
failed = 1;
#ifdef DIALUP
alarm (30);
if (! dialcheck (utent.ut_line,
pwent.pw_shell ? pwent.pw_shell:"/bin/sh"))
failed = 1;
#endif
#ifdef CONSOLE
if (pwent.pw_uid == 0 && stat (CONSOLE, &statbuf) == 0) {
if ((statbuf.st_mode & S_IFMT) == S_IFREG) {
fp = fopen (CONSOLE, "r");
while (fp && fgets (console, BUFSIZ, fp)
== console) {
console[strlen (console) - 1] = '\0';
if (! strcmp (console, utent.ut_line))
break;
}
if (! fp || feof (fp))
failed = 1;
fclose (fp);
} else {
if (strcmp (CONSOLE, utent.ut_line))
failed = 1;
}
}
#endif
#ifdef FAILLOG
if (! failcheck (pwent.pw_uid, &faillog, failed))
failed = 1;
#endif
if (! failed)
break;
puts ("Login incorrect");
#ifdef FAILLOG
if (pwent.pw_name) /* don't log non-existent users */
failure (pwent.pw_uid, utent.ut_line, &faillog);
#endif
if (--retries <= 0) /* only allow so many failures */
exit (1);
#ifndef BSD
(void) memset (name, '\0', sizeof name);
(void) memset (pass, '\0', sizeof pass);
#else
bzero (name, sizeof name);
bzero (pass, sizeof pass);
#endif
}
(void) alarm (0); /* turn off alarm clock */
#ifdef NOLOGINS
/*
* Check to see if system is turned off for non-root users.
* This would be useful to prevent users from logging in
* during system maintenance.
*/
if (pwent.pw_uid != 0 && access (NOLOGINS, 0) == 0) {
printf ("\r\nSystem closed for routine maintenance\n");
exit (0);
}
#endif
environ = newenvp; /* make new environment active */
if (getenv ("IFS")) /* don't export user IFS ... */
addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
setutmp (); /* make entry in utmp & wtmp files */
if (pwent.pw_shell && pwent.pw_shell[0] == '*') /* subsystem root */
subsystem (); /* figure out what to execute */
#ifdef LASTLOG
log (); /* give last login and log this one */
#endif
setup (&pwent); /* set UID, GID, HOME, etc ... */
#ifdef AGING
if (pwent.pw_age) /* check for age of password ... */
expire (pwent.pw_age); /* ... ask for new one if expired */
#endif
#ifdef HUSHLOGIN
sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
hushed = access (hush, 0) != -1;
#endif
#ifdef MOTD
motd (); /* print the message of the day */
#endif
#ifdef FAILLOG
if (faillog.fail_cnt != 0)
failprint (pwent.pw_uid, &faillog);
#endif
#ifdef LASTLOG
if (lastlog.ll_time != 0 && ! hushed)
printf ("Last login: %.19s on %s\n",
ctime (&lastlog.ll_time), lastlog.ll_line);
#endif
#ifdef MAILCHECK
mailcheck (); /* report on the status of mail */
#endif
#ifdef TTYTYPE
ttytype (utent.ut_line);
#endif
signal (SIGINT, SIG_DFL); /* default interrupt signal */
signal (SIGQUIT, SIG_DFL); /* default quit signal */
signal (SIGTERM, SIG_DFL); /* default terminate signal */
signal (SIGALRM, SIG_DFL); /* default alarm signal */
shell (pwent.pw_shell); /* exec the shell finally. */
/*NOTREACHED*/
}
SHAR_EOF
fi
if test -f 'smain.c'
then
echo shar: "will not over-write existing file 'smain.c'"
else
cat << \SHAR_EOF > 'smain.c'
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#include <termio.h>
#else
#include <strings.h>
#include <sgtty.h>
#define strchr index
#define strrchr rindex
#endif
#include <signal.h>
#include "config.h"
#include "lastlog.h"
#ifndef lint
static char _sccsid[] = "@(#)smain.c 2.1 01:23:55 6/20/89";
#endif
#ifndef MAXENV
#define MAXENV 64
#endif
#ifndef PATH
#define PATH ":/bin:/usr/bin"
#endif
#ifndef SUPATH
#define SUPATH ":/bin:/usr/bin:/etc"
#endif
#ifdef HUSHLOGIN
char hush[BUFSIZ];
int hushed;
#endif
char name[BUFSIZ];
char pass[BUFSIZ];
char home[BUFSIZ];
char prog[BUFSIZ];
char mail[BUFSIZ];
char oldname[BUFSIZ];
char *newenvp[MAXENV];
int newenvc = 0;
int maxenv = MAXENV;
struct passwd pwent;
#ifdef TZ
FILE *tzfile;
char tzbuf[16] = TZ;
#endif
void addenv ();
void entry ();
void sulog ();
void subsystem ();
void setup ();
void motd ();
void mailcheck ();
void shell ();
extern char **environ;
int main (argc, argv, envp)
int argc;
char **argv;
char **envp;
{
void die ();
char *getenv ();
char *cp;
int doshell;
int fakelogin = 0;
int amroot;
struct passwd *pw;
struct passwd *getpwuid ();
while (*envp) /* add inherited environment, */
addenv (*envp++); /* some variables change later */
#ifdef TZ
if (tzbuf[0] == '/') {
if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) {
if (fgets (tzbuf, sizeof tzbuf, tzfile)) {
tzbuf[strlen (tzbuf) - 1] = '\0';
addenv (tzbuf);
}
fclose (tzfile);
}
} else {
addenv (tzbuf);
}
#endif
#ifdef HZ
addenv (HZ); /* set the default $HZ, if one */
#endif
argc--; argv++; /* shift out command name */
if (argc > 0 && argv[0][0] == '-' && argv[0][1] == '\0') {
fakelogin = 1;
argc--; argv++; /* shift ... */
}
if (argc > 0 && argv[0][0] != '-') {
(void) strcpy (name, argv[0]); /* use this login id */
argc--; argv++; /* shift ... */
}
doshell = argc == 0; /* any arguments remaining? */
if (pw = getpwuid (getuid ())) /* need old user name */
(void) strcpy (oldname, pw->pw_name);
else /* user ID MUST exist */
goto failure;
amroot = getuid () == 0; /* currently am super user */
if (! name[0]) /* use default user ID */
(void) strcpy (name, "root");
entry (name, &pwent); /* get password file entry */
if (pwent.pw_shell == (char *) 0)
pwent.pw_shell = "/bin/sh";
if (pwent.pw_name == (char *) 0) { /* unknown user */
(void) fprintf (stderr, "Unknown id: %s\n", name);
exit (1);
}
/*
* Here we have a sticky situation. Some accounts may have no
* password entry in the password file. So, we don't ask for a
* password. Others, have a blank password entered - you be the
* judge. The conditional compilation NOBLANK requires even
* blank passwords to be prompted for. This may well break
* quite a few systems. Use with discretion.
*/
die (0);
signal (SIGHUP, die);
signal (SIGINT, die);
signal (SIGQUIT, die);
signal (SIGTERM, die);
#ifdef NOBLANK
if (! amroot && ! password ("Password:", pass))
goto failure;
#else
if (! amroot && (pwent.pw_name == (char *) 0 || pwent.pw_passwd)
&& ! password ("Password:", pass))
goto failure;
#endif
/* check encrypted passwords ... */
if (! amroot && ! valid (pass, &pwent)) {
failure: sulog (0); /* log failed attempt */
puts ("Sorry.");
exit (1);
}
signal (SIGHUP, SIG_DFL);
signal (SIGINT, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
signal (SIGTERM, SIG_DFL);
#ifdef SULOG
sulog (1); /* save SU information */
#endif
if (pwent.pw_uid == 0)
addenv (SUPATH);
else
addenv (PATH);
environ = newenvp; /* make new environment active */
if (getenv ("IFS")) /* don't export user IFS ... */
addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
if (doshell && pwent.pw_shell[0] == '*') /* subsystem root required */
subsystem (); /* figure out what to execute */
if (fakelogin)
setup (&pwent); /* set UID, GID, HOME, etc ... */
else {
if (setgid (pwent.pw_gid) || setuid (pwent.pw_uid)) {
perror ("Can't set ID");
exit (1);
}
}
if (! doshell) { /* execute arguments as command */
if (cp = getenv ("SHELL"))
pwent.pw_shell = cp;
argv[-1] = pwent.pw_shell;
(void) execv (pwent.pw_shell, &argv[-1]);
(void) fprintf (stderr, "No shell\n");
exit (1);
}
if (fakelogin) {
#ifdef HUSHLOGIN
sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
hushed = access (hush, 0) != -1;
#endif
#ifdef MOTD
motd (); /* print the message of the day */
#endif
#ifdef MAILCHECK
mailcheck (); /* report on the status of mail */
#endif
shell (pwent.pw_shell); /* exec the shell finally. */
} else {
if (cp = strrchr (pwent.pw_shell, '/'))
cp++;
else
cp = pwent.pw_shell;
execl (pwent.pw_shell, cp, (char *) 0);
perror (pwent.pw_shell);
exit (1);
}
/*NOTREACHED*/
}
/*
* die - set or reset termio modes.
*
* die() is called before processing begins. signal() is then
* called with die() as the signal handler. If signal later
* calls die() with a signal number, the terminal modes are
* then reset.
*/
void die (killed)
int killed;
{
#ifdef BSD
static struct sgtty sgtty;
if (killed)
stty (0, &sgtty);
else
gtty (0, &sgtty);
#else
struct termio sgtty;
if (killed)
ioctl (0, TCSETA, &sgtty);
else
ioctl (0, TCGETA, &sgtty);
#endif
if (killed)
exit (killed);
}
SHAR_EOF
fi
if test -f 'pwconv.c'
then
echo shar: "will not over-write existing file 'pwconv.c'"
else
cat << \SHAR_EOF > 'pwconv.c'
/*
* pwconv - convert and update shadow password files
*
* Pwconv copies the old password file information to a new shadow
* password file, merging entries from an optional existing shadow
* file.
*
* The new password file is left in npasswd, the new shadow file is
* left in nshadow. Existing shadow entries are copied as is.
* New entries are created with passwords which expire in MAXDAYS days,
* with a last changed date of today, unless password aging
* information was already present. Likewise, the minimum number of
* days before which the password may be changed is controlled by
* MINDAYS. Entries with blank passwordsare not copied to the shadow
* file at all.
*/
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#include "config.h"
#include "shadow.h"
#ifndef lint
static char _sccsid[] = "@(#)pwconv.c 2.1 01:23:40 6/20/89";
#endif
char buf[BUFSIZ];
long time ();
long a64l ();
int main ()
{
long today;
struct passwd *pw;
struct passwd *sgetpwent ();
FILE *pwd;
FILE *npwd;
FILE *shadow;
struct spwd *spwd;
struct spwd tspwd;
int fd;
if (! (pwd = fopen (PWDFILE, "r"))) {
perror (PWDFILE);
return (1);
}
unlink ("npasswd");
if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
! (npwd = fdopen (fd, "w"))) {
perror ("npasswd");
return (1);
}
unlink ("nshadow");
if ((fd = open ("nshadow", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
! (shadow = fdopen (fd, "w"))) {
perror ("nshadow");
return (1);
}
(void) time (&today);
today /= (24L * 60L * 60L);
while (fgets (buf, BUFSIZ, pwd) == buf) {
buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
if (buf[0] == '#') { /* comment line */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
if (pw->pw_passwd == (char *) 0) { /* no password, skip */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
setspent (); /* rewind old shadow file */
if (spwd = getspnam (pw->pw_name)) {
if (! putspent (spwd, shadow)) { /* copy old entry */
perror ("nshadow");
return (1);
}
} else { /* need a new entry. */
tspwd.sp_namp = pw->pw_name;
tspwd.sp_pwdp = pw->pw_passwd;
pw->pw_passwd = "x";
if (pw->pw_age) { /* copy old password age stuff */
tspwd.sp_min = c64i (pw->pw_age[1]);
tspwd.sp_max = c64i (pw->pw_age[0]);
if (strlen (pw->pw_age) == 4)
tspwd.sp_lstchg = a64l (&pw->pw_age[2]);
else
tspwd.sp_lstchg = 0L;
/*
* Convert weeks to days
*/
tspwd.sp_min *= 7;
tspwd.sp_max *= 7;
tspwd.sp_lstchg *= 7;
} else { /* fake up new password age stuff */
tspwd.sp_max = MAXDAYS;
tspwd.sp_min = MINDAYS;
tspwd.sp_lstchg = today;
}
if (! putspent (&tspwd, shadow)) { /* output entry */
perror ("nshadow");
return (1);
}
}
(void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:",
pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
pw->pw_uid, pw->pw_gid,
pw->pw_gecos, pw->pw_dir);
if (fprintf (npwd, "%s\n",
pw->pw_shell ? pw->pw_shell:"") == EOF) {
perror ("npasswd");
return (1);
}
}
endspent ();
if (ferror (npwd) || ferror (shadow)) {
perror ("pwconv");
(void) unlink ("npasswd");
(void) unlink ("nshadow");
}
(void) fclose (pwd);
(void) fclose (npwd);
(void) fclose (shadow);
return (0);
}
SHAR_EOF
fi
if test -f 'dialup.c'
then
echo shar: "will not over-write existing file 'dialup.c'"
else
cat << \SHAR_EOF > 'dialup.c'
#include <stdio.h>
#ifndef BSD
#include <string.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include "dialup.h"
#ifndef lint
static char _sccsid[] = "@(#)dialup.c 2.1 01:23:06 6/20/89";
#endif
static FILE *dialpwd;
void setduent ()
{
if (dialpwd)
rewind (dialpwd);
else
dialpwd = fopen (DIALPWD, "r");
}
void endduent ()
{
if (dialpwd)
fclose (dialpwd);
dialpwd = (FILE *) 0;
}
struct dialup *getduent ()
{
static struct dialup dialup; /* static structure to point to */
static char shell[64]; /* some space for a login shell */
static char passwd[16]; /* some space for dialup password */
char buf[BUFSIZ];
char *cp;
if (! dialpwd)
setduent ();
if (! dialpwd || feof (dialpwd))
return ((struct dialup *) 0);
while (fgets (buf, BUFSIZ, dialpwd) == buf && buf[0] == '#')
;
if (feof (dialpwd))
return ((struct dialup *) 0);
cp = strchr (buf, ':');
if (cp - buf > sizeof shell) /* something is fishy ... */
return ((struct dialup *) 0);
(void) strncpy (shell, buf, cp - buf);
shell[cp - buf] = '\0';
if (strlen (cp + 1) > sizeof passwd) /* something is REALLY fishy */
return ((struct dialup *) 0);
(void) strcpy (passwd, cp + 1);
passwd[strlen (passwd) - 1] = '\0';
if (cp = strchr (passwd, ':'))
*cp = '\0';
dialup.du_shell = shell;
dialup.du_passwd = passwd;
return (&dialup);
}
struct dialup *getdushell (shell)
char *shell;
{
struct dialup *dialup;
while (dialup = getduent ()) {
if (strcmp (shell, dialup->du_shell) == 0)
return (dialup);
if (strcmp (dialup->du_shell, "*") == 0)
return (dialup);
}
return ((struct dialup *) 0);
}
int isadialup (tty)
char *tty;
{
FILE *fp;
char buf[BUFSIZ];
int dialup = 0;
if (! (fp = fopen (DIALUPS, "r")))
return (0);
while (fgets (buf, BUFSIZ, fp) == buf) {
if (buf[0] == '#')
continue;
buf[strlen (buf) - 1] = '\0';
if (strcmp (buf, tty) == 0) {
dialup = 1;
break;
}
}
fclose (fp);
return (dialup);
}
SHAR_EOF
fi
if test -f 'dialchk.c'
then
echo shar: "will not over-write existing file 'dialchk.c'"
else
cat << \SHAR_EOF > 'dialchk.c'
#include <stdio.h>
#include "config.h"
#include "dialup.h"
#ifndef lint
static char _sccsid[] = "@(#)dialchk.c 2.1 01:23:05 6/20/89";
#endif
/*
* Check for dialup password
*
* dialcheck tests to see if tty is listed as being a dialup
* line. If so, a dialup password may be required if the shell
* is listed as one which requires a second password.
*/
#ifdef DIALUP
int dialcheck (tty, shell)
char *tty;
char *shell;
{
char *crypt ();
char *getpass ();
struct dialup *dialup;
char *pass;
char *cp;
if (! isadialup (tty))
return (1);
if (! (dialup = getdushell (shell)))
return (1);
endduent ();
if (dialup->du_passwd[0] == '\0')
return (1);
if (! (pass = getpass ("Dialup Password:")))
return (0);
cp = crypt (pass, dialup->du_passwd);
return (strcmp (cp, dialup->du_passwd) == 0);
}
#endif
SHAR_EOF
fi
if test -f 'pwunconv.c'
then
echo shar: "will not over-write existing file 'pwunconv.c'"
else
cat << \SHAR_EOF > 'pwunconv.c'
/*
* pwunconv - restore old password file from shadow password file.
*
* Pwunconv copies the password file information from the shadow
* password file, merging entries from an optional existing shadow
* file.
*
* The new password file is left in npasswd. There is no new
* shadow file. Password aging information is translated where
* possible.
*/
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#include "config.h"
#include "shadow.h"
#ifndef lint
static char _sccsid[] = "@(#)pwunconv.c 2.1 01:23:44 6/20/89";
#endif
char buf[BUFSIZ];
char *l64a ();
int main ()
{
struct passwd *pw;
struct passwd *sgetpwent ();
FILE *pwd;
FILE *npwd;
struct spwd *spwd;
int fd;
if (! (pwd = fopen (PWDFILE, "r"))) {
perror (PWDFILE);
return (1);
}
unlink ("npasswd");
if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
! (npwd = fdopen (fd, "w"))) {
perror ("npasswd");
return (1);
}
while (fgets (buf, BUFSIZ, pwd) == buf) {
buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
if (buf[0] == '#') { /* comment line */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
setspent (); /* rewind shadow file */
if (! (spwd = getspnam (pw->pw_name))) {
(void) fprintf (npwd, "%s\n", buf);
continue;
}
pw->pw_passwd = spwd->sp_pwdp;
/*
* Password aging works differently in the two different systems.
* With shadow password files you apparently must have some aging
* information. The maxweeks or minweeks may not map exactly.
* In pwconv we set max == 10000, which is about 30 years. Here
* we have to undo that kludge. So, if maxdays == 10000, no aging
* information is put into the new file. Otherwise, the days are
* converted to weeks and so on.
*/
if (spwd->sp_max > (63*7) && spwd->sp_max < 10000)
spwd->sp_max = (63*7); /* 10000 is infinity this week */
if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
spwd->sp_max /= 7; /* turn it into weeks */
spwd->sp_min /= 7;
spwd->sp_lstchg /= 7;
pw->pw_age = l64a ((long) spwd->sp_lstchg * (64L*64L) +
spwd->sp_min * (64L) +
spwd->sp_max);
} else
pw->pw_age = (char *) 0;
if (pw->pw_age)
(void) fprintf (npwd, "%s:%s,%s:%d:%d:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
pw->pw_age, pw->pw_uid, pw->pw_gid,
pw->pw_gecos, pw->pw_dir,
pw->pw_shell ? pw->pw_shell:"");
else
(void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
pw->pw_uid, pw->pw_gid,
pw->pw_gecos, pw->pw_dir,
pw->pw_shell ? pw->pw_shell:"");
}
endspent ();
if (ferror (npwd)) {
perror ("pwunconv");
(void) unlink ("npasswd");
}
(void) fclose (npwd);
(void) fclose (pwd);
return (0);
}
SHAR_EOF
fi
if test -f 'failure.c'
then
echo shar: "will not over-write existing file 'failure.c'"
else
cat << \SHAR_EOF > 'failure.c'
#include <sys/types.h>
#include <fcntl.h>
#include <time.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include "faillog.h"
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)failure.c 2.1 01:23:16 6/20/89";
#endif
#ifdef FAILLOG
#define DAY (24L*3600L)
#define YEAR (365L*DAY)
#define NOW (time ((time_t *) 0))
extern struct tm *localtime ();
extern char *asctime ();
extern void failprint ();
/*
* failure - make failure entry
*/
void
failure (uid, tty, faillog)
int uid;
char *tty;
struct faillog *faillog;
{
int fd;
if ((fd = open (FAILFILE, O_RDWR)) < 0)
return;
lseek (fd, (off_t) (sizeof *faillog) * uid, 0);
if (read (fd, (char *) faillog, sizeof *faillog)
!= sizeof *faillog)
#ifndef BSD
memset ((void *) faillog, '\0', sizeof *faillog);
#else
bzero ((char *) faillog, sizeof *faillog);
#endif
if (faillog->fail_max == 0 || faillog->fail_cnt < faillog->fail_max)
faillog->fail_cnt++;
strncpy (faillog->fail_line, tty, sizeof faillog->fail_line);
faillog->fail_time = time ((time_t *) 0);
lseek (fd, (off_t) (sizeof *faillog) * uid, 0);
write (fd, (char *) faillog, sizeof *faillog);
close (fd);
}
/*
* failcheck - check for failures > allowable
*
* failcheck() is called AFTER the password has been validated.
*/
int
failcheck (uid, faillog, failed)
int uid;
struct faillog *faillog;
{
int fd;
int okay = 1;
struct faillog fail;
if ((fd = open (FAILFILE, O_RDWR)) < 0)
return (1);
lseek (fd, (off_t) (sizeof *faillog) * uid, 0);
if (read (fd, (char *) faillog, sizeof *faillog) == sizeof *faillog) {
if (faillog->fail_max != 0
&& faillog->fail_cnt >= faillog->fail_max)
okay = 0;
}
if (!failed && okay) {
fail = *faillog;
fail.fail_cnt = 0;
lseek (fd, (off_t) sizeof fail * uid, 0);
write (fd, (char *) &fail, sizeof fail);
}
close (fd);
return (okay);
}
/*
* failprint - print line of failure information
*/
void
failprint (uid, fail)
struct faillog *fail;
{
int fd;
struct tm *tp;
char *lasttime;
if (fail->fail_cnt == 0)
return;
tp = localtime (&fail->fail_time);
lasttime = asctime (tp);
lasttime[24] = '\0';
if (NOW - fail->fail_time < YEAR)
lasttime[19] = '\0';
if (NOW - fail->fail_time < DAY)
lasttime = lasttime + 11;
if (*lasttime == ' ')
lasttime++;
printf ("%d %s since last login. Last was %s on %s.\n",
fail->fail_cnt, fail->fail_cnt > 1 ? "failures":"failure",
lasttime, fail->fail_line);
}
#endif
SHAR_EOF
fi
if test -f 'faillog.h'
then
echo shar: "will not over-write existing file 'faillog.h'"
else
cat << \SHAR_EOF > 'faillog.h'
/*
* faillog.h - login failure logging file format
*
* @(#)faillog.h 2.1 01:23:15 6/20/89
*
* The login failure file is maintained by login(1) and fail(1L)
* Each record in the file represents a separate UID and the file
* is indexed in that fashion.
*/
#define FAILFILE "/usr/adm/faillog"
struct faillog {
short fail_cnt; /* failures since last success */
short fail_max; /* failures before turning account off */
char fail_line[12]; /* last failure occured here */
time_t fail_time; /* last failure occured then */
};
SHAR_EOF
fi
if test -f 'faillog.c'
then
echo shar: "will not over-write existing file 'faillog.c'"
else
cat << \SHAR_EOF > 'faillog.c'
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pwd.h>
#include <time.h>
#ifndef BSD
#include <string.h>
#include <memory.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include "config.h"
#include "faillog.h"
#ifndef lint
static char _sccsid[] = "@(#)faillog.c 2.1 01:23:12 6/20/89";
#endif
FILE *fail; /* failure file stream */
off_t user; /* one single user, specified on command line */
int days; /* number of days to consider for print command */
time_t seconds; /* that number of days in seconds */
int max; /* maximum failure count for fail_max */
int mflg; /* set fail_max for a given user */
int rflg; /* reset fail_cnt for user or all user's */
int uflg; /* set if user is a valid user id */
int tflg; /* print is restricted to most recent days */
struct faillog faillog; /* scratch structure to play with ... */
struct stat statbuf; /* fstat buffer for file size */
extern int optind;
extern char *optarg;
extern char *asctime ();
extern struct passwd *getpwuid ();
extern struct passwd *getpwnam ();
extern struct passwd *getpwent ();
extern struct tm *localtime ();
#define DAY (24L*3600L)
#define NOW (time ((time_t *) 0))
main (argc, argv)
int argc;
char **argv;
{
char *mode;
int uid = 0;
int c;
struct passwd *pwent;
if (getuid () == 0) /* only root can update anything */
mode = "r+";
else /* all others can only look */
mode = "r";
if ((fail = fopen (FAILFILE, mode)) == (FILE *) 0) {
perror (FAILFILE);
exit (1);
}
while ((c = getopt (argc, argv, "m:pru:t:")) != EOF) {
switch (c) {
case 'm':
max = atoi (optarg);
setmax ();
break;
case 'p':
print ();
break;
case 'r':
reset ();
break;
case 'u':
pwent = getpwnam (optarg);
if (! pwent) {
fprintf (stderr, "Unknown User: %s\n", optarg);
exit (1);
}
uflg++;
user = pwent->pw_uid;
break;
case 't':
days = atoi (optarg);
seconds = days * DAY;
tflg++;
break;
}
}
fclose (fail);
exit (0);
}
print ()
{
int uid;
off_t offset;
if (uflg) {
offset = user * sizeof faillog;
fstat (fileno (fail), &statbuf);
if (offset >= statbuf.st_size)
return;
fseek (fail, (off_t) user * sizeof faillog, 0);
if (fread ((char *) &faillog, sizeof faillog, 1, fail) == 1)
print_one (&faillog, user);
else
perror (FAILFILE);
} else {
for (uid = 0;
fread ((char *) &faillog, sizeof faillog, 1, fail) == 1;
uid++) {
if (faillog.fail_cnt == 0)
continue;
if (tflg && NOW - faillog.fail_time > seconds)
continue;
print_one (&faillog, uid);
}
}
}
print_one (faillog, uid)
struct faillog *faillog;
{
static int once;
char *cp;
struct tm *tm;
struct passwd *pwent;
if (! once) {
printf ("Username Failures Maximum Latest\n");
once++;
}
pwent = getpwuid (uid);
tm = localtime (&faillog->fail_time);
cp = asctime (tm);
cp[24] = '\0';
if (pwent) {
printf ("%-16s %4d %4d",
pwent->pw_name, faillog->fail_cnt, faillog->fail_max);
if (faillog->fail_time)
printf (" %s on %s\n", cp, faillog->fail_line);
else
putchar ('\n');
}
}
reset ()
{
int uid = 0;
if (uflg)
reset_one (user);
else
for (uid = 0;reset_one (uid);uid++)
;
}
reset_one (uid)
int uid;
{
off_t offset;
offset = uid * sizeof faillog;
fstat (fileno (fail), &statbuf);
if (offset >= statbuf.st_size)
return (0);
if (fseek (fail, offset, 0) != 0) {
perror (FAILFILE);
return (0);
}
if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
if (! feof (fail))
perror (FAILFILE);
return (0);
}
if (faillog.fail_cnt == 0)
return (1); /* don't fill in no holes ... */
faillog.fail_cnt = 0;
if (fseek (fail, offset, 0) == 0
&& fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1) {
fflush (fail);
return (1);
} else {
perror (FAILFILE);
}
return (0);
}
setmax ()
{
int uid = 0;
struct passwd *pwent;
if (uflg) {
setmax_one (user);
} else {
setpwent ();
while (pwent = getpwent ())
setmax_one (pwent->pw_uid);
}
}
setmax_one (uid)
int uid;
{
off_t offset;
offset = uid * sizeof faillog;
if (fseek (fail, offset, 0) != 0) {
perror (FAILFILE);
return;
}
if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
if (! feof (fail))
perror (FAILFILE);
} else {
#ifndef BSD
memset ((char *) &faillog, '\0', sizeof faillog);
#else
bzero ((char *) &faillog, sizeof faillog);
#endif
}
faillog.fail_max = max;
if (fseek (fail, offset, 0) == 0
&& fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1)
fflush (fail);
else
perror (FAILFILE);
}
SHAR_EOF
fi
exit 0
# End of shell archive
--
John F. Haugh II +-Button of the Week Club:-------------
VoiceNet: (512) 832-8832 Data: -8835 | "AIX is a three letter word,
InterNet: jfh at rpp386.Cactus.Org | and it's BLUE."
UucpNet : <backbone>!bigtex!rpp386!jfh +--------------------------------------
More information about the Alt.sources
mailing list