Shadow Password Suite (part 2 of 5)
John F Haugh II
jfh at rpp386.cactus.org
Thu Dec 13 05:46:58 AEST 1990
#! /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:
# pmain.c
# port.c
# lmain.c
# mkpasswd.c
# sulogin.c
# pwpack.c
# dialup.c
# sulog.c
# password.c
# env.c
# mail.c
# dialchk.c
# This archive created: Wed Dec 12 12:36:45 1990
# By: John F Haugh II (River Parishes Programming, Austin TX)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'pmain.c'" '(11779 characters)'
if test -f 'pmain.c'
then
echo shar: "will not over-write existing file 'pmain.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pmain.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <pwd.h>
X#include <fcntl.h>
X#include <signal.h>
X#include <errno.h>
X#ifndef BSD
X#include <termio.h>
X#include <string.h>
X#include <memory.h>
X#else
X#include <sgtty.h>
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "config.h"
X#include "lastlog.h"
X#include "shadow.h"
X
X#ifdef SHADOW
X# ifndef AGING
X# define AGING
X# endif
X#endif
X
X#ifdef DBM
X#include <dbm.h>
X#endif
X
X#ifndef PASSLENGTH
X#define PASSLENGTH 5
X#endif
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)pmain.c 2.8 07:55:00 11/8/90";
X#endif
X
Xchar name[BUFSIZ];
Xchar orig[BUFSIZ];
Xchar pass[BUFSIZ];
Xchar pass2[BUFSIZ];
X
Xstruct passwd pwent;
X
X#ifndef RETRIES
X#define RETRIES 3
X#endif
X
Xchar *l64a ();
Xchar *crypt ();
Xextern int errno;
Xlong a64l ();
Xvoid entry ();
Xtime_t time ();
X
Xvoid
Xusage ()
X{
X#ifdef OBSCURE
X fprintf (stderr, "usage: passwd { [ -f ] user | -g [ -r ] group }\n");
X#else
X fprintf (stderr, "usage: passwd { user | -g [ -r ] group }\n");
X#endif
X exit (1);
X}
X
X#ifdef DBM
X/*
X * update_dbm
X *
X * Updates the DBM password files, if they exist.
X */
X
Xupdate_dbm (pw)
Xstruct passwd *pw;
X{
X datum key;
X datum content;
X char data[BUFSIZ];
X int len;
X
X strcpy (data, PWDFILE);
X strcat (data, ".pag");
X if (access (data, 0))
X return;
X
X len = pw_pack (pw, data);
X content.dsize = len;
X content.dptr = data;
X
X key.dsize = strlen (pw->pw_name);
X key.dptr = pw->pw_name;
X store (key, content);
X
X key.dsize = sizeof pw->pw_uid;
X key.dptr = (char *) &pw->pw_uid;
X store (key, content);
X}
X#endif
X
Xint
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X void die ();
X char *cp;
X char *getlogin ();
X int amroot;
X int lockfd = -1;
X#ifdef OBSCURE
X int force = 0;
X#endif
X int retries;
X#ifdef AGING
X long week;
X long lastweek;
X char newage[5];
X#endif
X long salttime;
X struct passwd *pw;
X struct passwd *getpwuid ();
X struct passwd *getpwnam ();
X struct passwd *sgetpwent ();
X FILE *npwd;
X#ifdef SHADOWPWD
X struct spwd *spwd;
X struct spwd tspwd;
X#else
X FILE *pwd;
X char buf[BUFSIZ];
X#endif
X char tmp[BUFSIZ];
X
X argc--; argv++; /* shift ... */
X
X if (! isatty (0) || ! isatty (1))
X exit (1);
X
X die (0); /* save tty modes */
X
X signal (SIGHUP, die); /* exit if SIGHUP */
X signal (SIGINT, die); /* exit if SIGINT */
X signal (SIGQUIT, die); /* exit if SIGQUIT */
X signal (SIGTERM, die); /* exit if SIGTERM */
X
X if (argc > 0 && strcmp (argv[0], "-g") == 0) {
X argv[0] = "gpasswd";
X execv ("/bin/gpasswd", &argv[0]);
X perror ("/bin/gpasswd");
X fprintf (stderr, "Unable to change group passwords\n");
X exit (-1);
X }
X#ifdef OBSCURE
X if (argc > 0 && strcmp (argv[0], "-f") == 0) {
X force = 1;
X argc--; argv++; /* shift ... */
X }
X#endif
X if (argc > 0 && argv[0][0] == '-')
X usage ();
X
X if (argc > 0)
X (void) strcpy (name, argv[0]);
X else if (cp = getlogin ()) /* need user name */
X (void) strcpy (name, cp);
X else { /* can't find user name! */
X fprintf (stderr, "unknown user: %s\n", argv[0]);
X exit (1);
X }
X printf ("Changing password for %s\n", name);
X
X if (! (pw = getpwnam (name)))
X goto failure; /* can't get my name ... */
X
X amroot = getuid () == 0; /* currently am super user */
X#ifdef OBSCURE
X if (! amroot)
X force = 0;
X#endif
X if (! amroot && (getuid () != pw->pw_uid ||
X strcmp (name, getlogin ())))
X goto failure;
X
X entry (name, &pwent); /* get password file entry */
X
X if (! pwent.pw_name) /* no entry for user??? */
X goto failure;
X
X if (! amroot) {
X if (! password ("Old Password:", orig))
X exit (1);
X
X if (! valid (orig, &pwent)) {
X puts ("Sorry.");
X exit (1);
X }
X }
X#ifdef AGING
X if (! amroot && pwent.pw_age) { /* check out the age */
X#ifdef SHADOWPWD
X (void) time (&week);
X week /= (24L * 60L * 60L); /* days since epoch */
X if (spwd = getspnam (name)) { /* use entries in shadow */
X if (spwd->sp_min > spwd->sp_max) {
X puts ("You may not change this password");
X exit (1);
X }
X if (spwd->sp_lstchg + spwd->sp_min > week) {
X printf ("Sorry, less than %d days since the last change\n", spwd->sp_min);
X exit (1);
X }
X } else {
X#endif /* SHADOWPWD */
X (void) time (&week);
X week /= (7L * 24L * 60L * 60L); /* weeks since epoch */
X lastweek = a64l (&pwent.pw_age[2]);
X
X if (c64i (pwent.pw_age[0]) < c64i (pwent.pw_age[1])) {
X puts ("You may not change this password");
X exit (1);
X }
X if (c64i (pwent.pw_age[1]) + lastweek > week) {
X printf ("Sorry, less than %d weeks since the last change\n", c64i (pwent.pw_age[1]));
X exit (1);
X }
X#ifdef SHADOWPWD
X }
X#endif
X }
X#endif
X printf ("Enter new password (minimum of %d characters)\n", PASSLENGTH);
X#ifdef OBSCURE
X puts ("Please use a combination of upper and lowercase letters and numbers");
X#endif
X retries = RETRIES;
Xretry:
X if (! password ("New Password:", pass))
X exit (1);
X
X#ifndef OBSCURE
X if (! obscure ()) {
X puts ("Password not changed.");
X exit (1);
X }
X#else
X if (! force && ! obscure ()) {
X if (retries-- > 0) {
X puts ("Please try again.");
X goto retry;
X } else
X goto toomany;
X }
X#endif
X if (! password ("Re-enter new password:", pass2))
X exit (1);
X
X if (strcmp (pass, pass2) != 0) {
X puts ("They don't match; try again");
X
X if (retries-- > 0)
X goto retry;
X else
X goto toomany;
X }
X#ifdef AGING
X if (pwent.pw_age && strlen (pwent.pw_age) >= 2) {
X strcpy (newage, pwent.pw_age);
X pwent.pw_age = newage;
X
X cp = l64a (week);
X
X if (pwent.pw_age[0] == '.' && pwent.pw_age[1] == '.')
X pwent.pw_age[0] = 'z';
X
X pwent.pw_age[2] = cp[0];
X pwent.pw_age[3] = cp[1];
X pwent.pw_age[4] = '\0';
X }
X#endif
X (void) time (&salttime);
X salttime = ((salttime & 07777) ^ ((salttime >> 14) & 07777)) & 07777;
X pwent.pw_passwd = tmp;
X strcpy (pwent.pw_passwd, crypt (pass, l64a (salttime)));
X#ifdef DOUBLESIZE
X if (strlen (pass) > 8) {
X strcpy (pwent.pw_passwd + 13,
X crypt (pass + 8, l64a (salttime)) + 2);
X }
X#endif
X /*
X * Now we get to race the bad guy. I don't think he can get us.
X *
X * Ignore most reasonable signals.
X * Maybe we should ignore more? He can't hurt us until the end.
X *
X * Get a lock file.
X *
X * Copy first part of password file to new file.
X * Illegal lines are copied verbatim.
X * File permissions are r--r--r--, owner root, group root.
X *
X * Output the new entry.
X * Only fields in struct passwd are output.
X *
X * Copy the rest of the file verbatim.
X *
X * Rename (link, unlink) password file to backup.
X * Kill me now and nothing changes or no one gets in.
X *
X * Rename (link, unlink) temporary file to password file.
X * Kill me now and no one gets in or lock is left.
X *
X * Remove locking file.
X *
X * That's all folks ...
X */
X
X signal (SIGHUP, SIG_IGN);
X signal (SIGINT, SIG_IGN);
X signal (SIGQUIT, SIG_IGN);
X signal (SIGTERM, SIG_IGN);
X
X ulimit (30000); /* prevent any funny business */
X umask (0); /* get new files modes correct */
X#ifndef NDEBUG
X if ((lockfd = open (".pwdlock", O_RDONLY|O_CREAT|O_EXCL), 0444) == -1)
X#else
X if ((lockfd = open (PWDLOCK, O_RDONLY|O_CREAT|O_EXCL), 0444) == -1)
X#endif /* NDEBUG */
X {
X puts ("Can't get lock");
X exit (1);
X }
X umask (077); /* close security holes to come ... */
X#ifdef SHADOWPWD
X if (access (NSHADOW, 0) == 0 && unlink (NSHADOW) == -1)
X goto failure;
X
X if ((npwd = fopen (NSHADOW, "w")) == (FILE *) 0)
X goto failure;
X
X if (chmod (NSHADOW, 0400) || chown (NSHADOW, 0, 0))
X goto failure;
X
X setspent ();
X
X while (spwd = getspent ()) {
X if (strcmp (spwd->sp_namp, name) == 0)
X break;
X
X if (putspent (spwd, npwd))
X goto failure;
X }
X if (spwd == (struct spwd *) 0) { /* didn't find a match */
X spwd = &tspwd; /* use a local structure instead */
X spwd->sp_namp = pwent.pw_name;
X spwd->sp_max = 10000; /* about as big as possible */
X spwd->sp_min = 0; /* about as small as possible */
X }
X spwd->sp_pwdp = pwent.pw_passwd; /* fixup the password */
X
X (void) time (&lastweek); /* get the current time ... */
X lastweek /= (24L*60L*60L); /* ... turn it into days. */
X spwd->sp_lstchg = lastweek; /* save it as date of last change */
X
X if (spwd->sp_min == 0 && spwd->sp_max == 0)
X spwd->sp_max = 10000; /* don't force another passwd */
X
X (void) putspent (spwd, npwd); /* add the new entry */
X
X while (spwd = getspent ()) /* finish the other ones off */
X (void) putspent (spwd, npwd);
X
X endspent ();
X
X if (ferror (npwd)) {
X perror (NSHADOW);
X if (unlink (NPWDFILE) || unlink (PWDLOCK))
X fputs ("Help!\n", stderr);
X
X exit (1);
X }
X fflush (npwd);
X fclose (npwd);
X
X if (access (OSHADOW, 0) == 0) {
X if (unlink (OSHADOW)) {
X puts ("Can't remove backup file");
X goto unlock;
X }
X }
X if (link (SHADOW, OSHADOW) || unlink (SHADOW)) {
X puts ("Can't save backup file");
X goto unlock;
X }
X#ifndef BSD
X if (link (NSHADOW, SHADOW) || unlink (NSHADOW))
X#else
X if (rename (NSHADOW, SHADOW))
X#endif
X {
X (void) unlink (OSHADOW);
X puts ("Can't rename new file");
X goto unlock;
X }
X if (unlink (OSHADOW)) {
X puts ("Can't remove backup file");
X goto unlock;
X }
X#else /* ! SHADOWPWD */
X#ifdef DBM
X update_dbm (&pwent);
X#endif
X if (access (NPWDFILE, 0) == 0 && unlink (NPWDFILE) == -1)
X goto failure;
X
X#ifndef NDEBUG
X if ((npwd = fopen ("npasswd", "w")) == (FILE *) 0)
X#else
X umask (077); /* no permissions for non-roots */
X
X if ((npwd = fopen (NPWDFILE, "w")) == (FILE *) 0)
X#endif /* NDEBUG */
X goto failure;
X
X#ifndef NDEBUG
X chmod (NPWDFILE, 0444); /* lets have some security here ... */
X chown (NPWDFILE, 0, 0); /* ... and keep the bad guy away */
X#endif /* NDEBUG */
X if ((pwd = fopen (PWDFILE, "r")) == (FILE *) 0)
X goto failure;
X
X while (fgets (buf, BUFSIZ, pwd) != (char *) 0) {
X if (buf[0] == '#' || ! (pw = sgetpwent (buf))) {
X fputs (buf, npwd);
X } else if (strcmp (pw->pw_name, pwent.pw_name) != 0)
X fputs (buf, npwd);
X else
X break;
X }
X (void) fprintf (npwd, "%s:", pw->pw_name);
X if (pwent.pw_age && pwent.pw_age[0])
X (void) fprintf (npwd, "%s,%s:", pwent.pw_passwd, pwent.pw_age);
X else
X (void) fprintf (npwd, "%s:", pwent.pw_passwd);
X
X (void) fprintf (npwd, "%d:%d:%s:%s:%s\n",
X pwent.pw_uid, pwent.pw_gid, pwent.pw_gecos, pwent.pw_dir,
X pwent.pw_shell ? pwent.pw_shell:"");
X
X while (fgets (buf, BUFSIZ, pwd) != (char *) 0)
X fputs (buf, npwd);
X
X if (ferror (npwd)) {
X perror (NPWDFILE);
X if (unlink (NPWDFILE) || unlink (PWDLOCK))
X fputs ("Help!\n", stderr);
X
X exit (1);
X }
X fflush (npwd);
X fclose (npwd);
X#ifdef NDEBUG
X chmod (NPWDFILE, 0644);
X if (unlink (OPWDFILE) == -1) {
X if (errno != ENOENT) {
X puts ("Can't unlink backup file");
X goto unlock;
X }
X }
X if (link (PWDFILE, OPWDFILE) || unlink (PWDFILE)) {
X puts ("Can't save backup file");
X goto unlock;
X }
X#ifndef BSD
X if (link (NPWDFILE, PWDFILE) || unlink (NPWDFILE))
X#else
X if (rename (NPWDFILE, PWDFILE))
X#endif
X {
X puts ("Can't rename new file");
X goto unlock;
X }
X#endif /* NDEBUG */
X#endif /* SHADOW */
X#ifndef NDEBUG
X (void) unlink (".pwdlock");
X#else
X (void) unlink (PWDLOCK);
X#endif
X exit (0);
X /*NOTREACHED*/
X
Xfailure:
X puts ("Permission denied.");
Xunlock:
X if (lockfd >= 0)
X (void) unlink (PWDLOCK);
X
X (void) unlink (NPWDFILE);
X exit (1);
X /*NOTREACHED*/
X
Xtoomany:
X puts ("Too many tries; try again later.");
X exit (1);
X /*NOTREACHED*/
X}
X
X/*
X * die - set or reset termio modes.
X *
X * die() is called before processing begins. signal() is then
X * called with die() as the signal handler. If signal later
X * calls die() with a signal number, the terminal modes are
X * then reset.
X */
X
Xvoid die (killed)
Xint killed;
X{
X#ifdef BSD
X static struct sgtty sgtty;
X
X if (killed)
X stty (0, &sgtty);
X else
X gtty (0, &sgtty);
X#else
X static struct termio sgtty;
X
X if (killed)
X ioctl (0, TCSETA, &sgtty);
X else
X ioctl (0, TCGETA, &sgtty);
X#endif
X if (killed) {
X putchar ('\n');
X fflush (stdout);
X exit (killed);
X }
X}
SHAR_EOF
if test 11779 -ne "`wc -c < 'pmain.c'`"
then
echo shar: "error transmitting 'pmain.c'" '(should have been 11779 characters)'
fi
fi
echo shar: "extracting 'port.c'" '(8322 characters)'
if test -f 'port.c'
then
echo shar: "will not over-write existing file 'port.c'"
else
sed 's/^X//' << \SHAR_EOF > 'port.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <stdio.h>
X#include <time.h>
X#include <sys/types.h>
X#include <ctype.h>
X#include <errno.h>
X#ifndef BSD
X#include <string.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "port.h"
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)port.c 2.2 08:26:33 8/20/90";
X#endif
X
Xextern int errno;
X
Xstatic FILE *ports;
X
X/*
X * setttyent - open /etc/porttime file or rewind
X *
X * the /etc/porttime file is rewound if already open, or
X * opened for reading.
X */
X
Xvoid
Xsetttyent ()
X{
X if (ports)
X rewind (ports);
X else
X ports = fopen (PORTS, "r");
X}
X
X/*
X * endttyent - close the /etc/porttime file
X *
X * the /etc/porttime file is closed and the ports variable set
X * to NULL to indicate that the /etc/porttime file is no longer
X * open.
X */
X
Xvoid
Xendttyent ()
X{
X if (ports)
X fclose (ports);
X
X ports = (FILE *) 0;
X}
X
X/*
X * getttyent - read a single entry from /etc/porttime
X *
X * the next line in /etc/porttime is converted to a (struct port)
X * and a pointer to a static (struct port) is returned to the
X * invoker. NULL is returned on either EOF or error. errno is
X * set to EINVAL on error to distinguish the two conditions.
X */
X
Xstruct port *
Xgetttyent ()
X{
X static struct port port; /* static struct to point to */
X static char buf[BUFSIZ]; /* some space for stuff */
X static char *users[PORT_IDS]; /* some pointers to user ids */
X static struct pt_time times[PORT_TIMES]; /* some time range things */
X char *cp; /* pointer into line */
X int time; /* scratch time of day */
X int i, j;
X int saveerr = errno; /* errno value on entry */
X
X /*
X * If the ports file is not open, open the file. Do not rewind
X * since we want to search from the beginning each time.
X */
X
X if (! ports)
X setttyent ();
X
X if (! ports) {
X errno = saveerr;
X return 0;
X }
X
X /*
X * Common point for beginning a new line -
X *
X * - read a line, and NUL terminate
X * - skip lines which begin with '#'
X * - parse off the tty name
X * - parse off a list of user names
X * - parse off a list of days and times
X */
X
Xagain:
X
X /*
X * Get the next line and remove the last character, which
X * is a '\n'. Lines which begin with '#' are all ignored.
X */
X
X if (fgets (buf, BUFSIZ, ports) == 0) {
X errno = saveerr;
X return 0;
X }
X if (buf[0] == '#')
X goto again;
X
X /*
X * Get the name of the TTY device. It is the first colon
X * separated field, and is the name of the TTY with no
X * leading "/dev". The entry '*' is used to specify all
X * TTY devices.
X */
X
X buf[strlen (buf) - 1] = 0;
X
X port.pt_name = buf;
X if (! (cp = strchr (buf, ':')))
X goto again;
X
X *cp++ = 0;
X
X /*
X * Get the list of user names. It is the second colon
X * separated field, and is a comma separated list of user
X * names. The entry '*' is used to specify all usernames.
X * The last entry in the list is a (char *) 0 pointer.
X */
X
X if (*cp != ':') {
X port.pt_users = users;
X port.pt_users[0] = cp;
X
X for (j = 1;*cp != ':';cp++) {
X if (*cp == ',' && j < (PORT_IDS-1)) {
X *cp++ = 0;
X port.pt_users[j++] = cp;
X }
X }
X port.pt_users[j] = 0;
X } else
X port.pt_users = 0;
X
X if (*cp != ':')
X goto again;
X
X *cp++ = 0;
X
X /*
X * Get the list of valid times. The times field is the third
X * colon separated field and is a list of days of the week and
X * times during which this port may be used by this user. The
X * valid days are 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', and 'Sa'.
X *
X * In addition, the value 'Al' represents all 7 days, and 'Wk'
X * represents the 5 weekdays.
X *
X * Times are given as HHMM-HHMM. The ending time may be before
X * the starting time. Days are presumed to wrap at 0000.
X */
X
X if (*cp == '\0') {
X port.pt_times = 0;
X return &port;
X }
X
X port.pt_times = times;
X
X /*
X * Get the next comma separated entry
X */
X
X for (j = 0;*cp && j < (PORT_TIMES-1);j++) {
X
X /*
X * Start off with no days of the week
X */
X
X port.pt_times[j].t_days = 0;
X
X /*
X * Check each two letter sequence to see if it is
X * one of the abbreviations for the days of the
X * week or the other two values.
X */
X
X for (i = 0;cp[i] && cp[i + 1] && isalpha (cp[i]);i += 2) {
X switch ((cp[i] << 8) | (cp[i + 1])) {
X case ('S' << 8) | 'u':
X port.pt_times[j].t_days |= 01;
X break;
X case ('M' << 8) | 'o':
X port.pt_times[j].t_days |= 02;
X break;
X case ('T' << 8) | 'u':
X port.pt_times[j].t_days |= 04;
X break;
X case ('W' << 8) | 'e':
X port.pt_times[j].t_days |= 010;
X break;
X case ('T' << 8) | 'h':
X port.pt_times[j].t_days |= 020;
X break;
X case ('F' << 8) | 'r':
X port.pt_times[j].t_days |= 040;
X break;
X case ('S' << 8) | 'a':
X port.pt_times[j].t_days |= 0100;
X break;
X case ('W' << 8) | 'k':
X port.pt_times[j].t_days |= 076;
X break;
X case ('A' << 8) | 'l':
X port.pt_times[j].t_days |= 0177;
X break;
X default:
X errno = EINVAL;
X return 0;
X }
X }
X
X /*
X * The default is 'Al' if no days were seen.
X */
X
X if (i == 0)
X port.pt_times[j].t_days = 0177;
X
X /*
X * The start and end times are separated from each
X * other by a '-'. The times are four digit numbers
X * representing the times of day.
X */
X
X for (time = 0;cp[i] && isdigit (cp[i]);i++)
X time = time * 10 + cp[i] - '0';
X
X if (cp[i] != '-' || time > 2400 || time % 100 > 59)
X goto again;
X port.pt_times[j].t_start = time;
X cp = cp + i + 1;
X
X for (time = i = 0;cp[i] && isdigit (cp[i]);i++)
X time = time * 10 + cp[i] - '0';
X
X if ((cp[i] != ',' && cp[i]) || time > 2400 || time % 100 > 59)
X goto again;
X
X port.pt_times[j].t_end = time;
X cp = cp + i + 1;
X }
X
X /*
X * The end of the list is indicated by a pair of -1's for the
X * start and end times.
X */
X
X port.pt_times[j].t_start = port.pt_times[j].t_end = -1;
X
X return &port;
X}
X
X/*
X * getttyuser - get ports information for user and tty
X *
X * getttyuser() searches the ports file for an entry with a TTY
X * and user field both of which match the supplied TTY and
X * user name. The file is searched from the beginning, so the
X * entries are treated as an ordered list.
X */
X
Xstruct port *
Xgetttyuser (tty, user)
Xchar *tty;
Xchar *user;
X{
X int i;
X struct port *port;
X
X setttyent ();
X
X while (port = getttyent ()) {
X if (strcmp (port->pt_name, tty) != 0 &&
X strcmp (port->pt_name, "*") != 0)
X continue;
X
X if (strcmp (*port->pt_users, "*") == 0)
X break;
X
X for (i = 0;port->pt_users && port->pt_users[i];i++) {
X if (strcmp (user, port->pt_users[i]) == 0)
X break;
X }
X if (port->pt_users && port->pt_users[i])
X break;
X }
X endttyent ();
X return port;
X}
X
X/*
X * isttytime - tell if a given user may login at a particular time
X *
X * isttytime searches the ports file for an entry which matches
X * the user name and TTY given.
X */
X
Xint
Xisttytime (id, port, clock)
Xchar *id;
Xchar *port;
Xlong clock;
X{
X int i;
X int time;
X struct port *pp;
X struct tm *tm,
X *localtime();
X
X /*
X * Try to find a matching entry for this user. Default to
X * letting the user in - there are pleny of ways to have an
X * entry to match all users.
X */
X
X if (! (pp = getttyuser (id, port)))
X return 1;
X
X /*
X * The entry is there, but has not time entries - don't
X * ever let them login.
X */
X
X if (pp->pt_times == 0)
X return 0;
X
X /*
X * The current time is converted to HHMM format for
X * comparision against the time values in the TTY entry.
X */
X
X tm = localtime (&clock);
X time = tm->tm_hour * 100 + tm->tm_min;
X
X /*
X * Each time entry is compared against the current
X * time. For entries with the start after the end time,
X * the comparision is made so that the time is between
X * midnight and either the start or end time.
X */
X
X for (i = 0;pp->pt_times[i].t_start != -1;i++) {
X if (! (pp->pt_times[i].t_days & PORT_DAY(tm->tm_wday)))
X continue;
X
X if (pp->pt_times[i].t_start <= pp->pt_times[i].t_end) {
X if (time >= pp->pt_times[i].t_start &&
X time <= pp->pt_times[i].t_end)
X return 1;
X } else {
X if (time >= pp->pt_times[i].t_start ||
X time <= pp->pt_times[i].t_end)
X return 1;
X }
X }
X
X /*
X * No matching time entry was found, user shouldn't
X * be let in right now.
X */
X
X return 0;
X}
SHAR_EOF
if test 8322 -ne "`wc -c < 'port.c'`"
then
echo shar: "error transmitting 'port.c'" '(should have been 8322 characters)'
fi
fi
echo shar: "extracting 'lmain.c'" '(8196 characters)'
if test -f 'lmain.c'
then
echo shar: "will not over-write existing file 'lmain.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lmain.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <pwd.h>
X#include <utmp.h>
X#include <time.h>
X#include <signal.h>
X#ifndef BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#ifndef BSD
X#include <termio.h>
X#else
X#include <sgtty.h>
X#endif
X#include "config.h"
X#include "lastlog.h"
X#include "faillog.h"
X#ifdef SHADOWPWD
X#include "shadow.h"
X#endif
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)lmain.c 2.7 10:20:08 11/9/90";
X#endif
X
X#ifndef ERASECHAR
X#define ERASECHAR '\b' /* backspace */
X#endif
X
X#ifndef KILLCHAR
X#define KILLCHAR '\025' /* control U */
X#endif
X
Xchar name[BUFSIZ];
Xchar pass[BUFSIZ];
Xchar home[BUFSIZ];
Xchar prog[BUFSIZ];
Xchar mail[BUFSIZ];
X#ifdef HUSHLOGIN
Xchar hush[BUFSIZ];
Xint hushed;
X#endif
X
Xstruct passwd pwent;
Xstruct utmp utent;
Xstruct lastlog lastlog;
X#ifndef BSD
Xstruct termio termio;
X#endif
X
X#ifndef MAXENV
X#define MAXENV 64
X#endif
X
Xchar *newenvp[MAXENV];
Xint newenvc = 0;
Xint maxenv = MAXENV;
Xextern char **environ;
X
Xchar *getenv ();
Xvoid checkutmp ();
Xvoid addenv ();
Xvoid setenv ();
Xunsigned alarm ();
Xvoid login ();
Xvoid entry ();
Xvoid setutmp ();
Xvoid subsystem ();
Xvoid log ();
Xvoid setup ();
Xvoid expire ();
Xvoid motd ();
Xvoid mailcheck ();
Xvoid shell ();
Xlong a64l ();
Xint c64i ();
X
X#ifdef TZ
XFILE *tzfile;
Xchar tzbuf[32] = TZ;
X#endif
X
X#ifndef ALARM
X#define ALARM 60
X#endif
X
X#ifndef RETRIES
X#define RETRIES 3
X#endif
X
X#ifdef FAILLOG
Xstruct faillog faillog;
X#endif
X#ifdef FTMP
Xstruct utmp failent;
X#endif
X#ifndef WARNAGE
X#define WARNAGE 0
X#endif
X
Xint main (argc, argv, envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
X int retries = RETRIES;
X int failed;
X#ifdef CONSOLE
X int conflag;
X char console[BUFSIZ];
X FILE *fp;
X struct stat statbuf;
X#endif
X#ifdef SHADOWPWD
X struct spwd *spwd;
X struct spwd *getspnam();
X#endif
X
X checkutmp (); /* must be lowest level shell */
X
X if (! isatty (0)) /* must be a terminal */
X exit (1);
X
X#ifndef BSD
X (void) ioctl (0, TCGETA, &termio); /* get terminal characteristics */
X
X /*
X * Add your favorite terminal modes here ...
X */
X
X termio.c_lflag |= ISIG;
X
X termio.c_cc[VERASE] = ERASECHAR;
X termio.c_cc[VKILL] = KILLCHAR;
X (void) ioctl (0, TCSETAF, &termio); /* set erase and kill characters */
X#endif
X#ifdef UMASK
X umask (UMASK); /* override the default umask */
X#endif
X#ifdef ULIMIT
X ulimit (2, (long) ULIMIT); /* override the default ulimit */
X#endif
X while (*envp) /* add inherited environment, */
X addenv (*envp++); /* some variables change later */
X
X#ifdef TZ
X if (tzbuf[0] == '/') {
X if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) {
X if (fgets (tzbuf, sizeof tzbuf, tzfile)) {
X tzbuf[strlen (tzbuf) - 1] = '\0';
X addenv (tzbuf);
X }
X fclose (tzfile);
X }
X } else {
X addenv (tzbuf);
X }
X#endif
X#ifdef HZ
X addenv (HZ); /* set the default $HZ, if one */
X#endif
X if (argc >= 2) { /* now set command line variables */
X setenv (argc - 2, &argv[2]);
X (void) strncpy (name, argv[1], sizeof name);
X }
X (void) alarm (ALARM); /* only allow ALARM sec. for login */
X
X while (1) { /* repeatedly get login/password pairs */
X if (! name[0]) { /* need to get a login id */
X login (name);
X continue;
X }
X entry (name, &pwent); /* get entry from password file */
X failed = 0; /* hasn't failed validation yet */
X
X /*
X * Here we have a sticky situation. Some accounts may have no
X * password entry in the password file. So, we don't ask for a
X * password. Others, have a blank password entered - you be the
X * judge. The conditional compilation NOBLANK requires even
X * blank passwords to be prompted for. This may well break
X * quite a few systems. Use with discretion.
X */
X
X#ifdef NOBLANK
X /* get a password from user */
X if (! password ("Password:", pass))
X continue;
X#else
X if ((! pwent.pw_name ||
X (pwent.pw_passwd && strlen (pwent.pw_passwd) > 0))
X && ! password ("Password:", pass))
X continue;
X#endif
X if (! valid (pass, &pwent)) /* check encrypted passwords ... */
X failed = 1;
X
X#ifdef DIALUP
X alarm (30);
X if (! dialcheck (utent.ut_line,
X pwent.pw_shell ? pwent.pw_shell:"/bin/sh"))
X failed = 1;
X#endif
X#ifdef PORTTIME
X if (pwent.pw_name &&
X ! isttytime (utent.ut_line, pwent.pw_name,
X time ((long *) 0)))
X failed = 1;
X#endif
X#ifdef CONSOLE
X if (pwent.pw_uid == 0 && stat (CONSOLE, &statbuf) == 0) {
X if ((statbuf.st_mode & S_IFMT) == S_IFREG) {
X fp = fopen (CONSOLE, "r");
X while (fp && fgets (console, BUFSIZ, fp)
X == console) {
X console[strlen (console) - 1] = '\0';
X if (! strcmp (console, utent.ut_line))
X break;
X }
X if (! fp || feof (fp))
X failed = 1;
X
X fclose (fp);
X } else {
X if (strcmp (CONSOLE, utent.ut_line))
X failed = 1;
X }
X }
X#endif
X#ifdef FAILLOG
X if (! failcheck (pwent.pw_uid, &faillog, failed))
X failed = 1;
X#endif
X if (! failed)
X break;
X
X puts ("Login incorrect");
X#ifdef FAILLOG
X if (pwent.pw_name) /* don't log non-existent users */
X failure (pwent.pw_uid, utent.ut_line, &faillog);
X#endif
X#ifdef FTMP
X failent = utent;
X
X if (pwent.pw_name)
X strncpy (failent.ut_name,
X pwent.pw_name, sizeof failent.ut_name);
X else
X#ifdef UNKNOWNS
X strcpy (failent.ut_name, name);
X#else
X strcpy (failent.ut_name, "UNKNOWN");
X#endif
X failent.ut_time = time ((time_t *) 0);
X failent.ut_type = USER_PROCESS;
X
X failtmp (&failent);
X#endif /* FTMP */
X if (--retries <= 0) /* only allow so many failures */
X exit (1);
X
X#ifndef BSD
X (void) memset (name, '\0', sizeof name);
X (void) memset (pass, '\0', sizeof pass);
X#else
X bzero (name, sizeof name);
X bzero (pass, sizeof pass);
X#endif
X }
X (void) alarm (0); /* turn off alarm clock */
X#ifdef NOLOGINS
X /*
X * Check to see if system is turned off for non-root users.
X * This would be useful to prevent users from logging in
X * during system maintenance.
X */
X
X if (pwent.pw_uid != 0 && access (NOLOGINS, 0) == 0) {
X printf ("\r\nSystem closed for routine maintenance\n");
X exit (0);
X }
X#endif
X environ = newenvp; /* make new environment active */
X
X if (getenv ("IFS")) /* don't export user IFS ... */
X addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
X
X setutmp (); /* make entry in utmp & wtmp files */
X if (pwent.pw_shell && pwent.pw_shell[0] == '*') /* subsystem root */
X subsystem (); /* figure out what to execute */
X
X#ifdef LASTLOG
X log (); /* give last login and log this one */
X#endif
X#ifdef SHADOWPWD
X /*
X * Need to get expiration information before changing UID
X */
X
X spwd = getspnam (pwent.pw_name);
X#endif
X setup (&pwent); /* set UID, GID, HOME, etc ... */
X#ifdef AGING
X#ifdef SHADOWPWD
X if (spwd)
X expire (spwd->sp_namp, spwd->sp_lstchg,
X spwd->sp_min, spwd->sp_max);
X else
X#endif
X if (pwent.pw_age && pwent.pw_age[0]) { /* check for age of password */
X expire (pwent.pw_name, (strlen (pwent.pw_age) == 4 ?
X a64l (pwent.pw_age + 2):0L) * 7,
X c64i (pwent.pw_age[1]) * 7,
X c64i (pwent.pw_age[0]) * 7);
X }
X#endif
X#ifdef HUSHLOGIN
X sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
X hushed = access (hush, 0) != -1;
X#endif
X#ifdef MOTD
X motd (); /* print the message of the day */
X#endif
X#ifdef FAILLOG
X if (faillog.fail_cnt != 0)
X failprint (pwent.pw_uid, &faillog);
X#endif
X#ifdef LASTLOG
X if (lastlog.ll_time != 0 && ! hushed)
X printf ("Last login: %.19s on %s\n",
X ctime (&lastlog.ll_time), lastlog.ll_line);
X#endif
X#ifdef AGING
X#ifdef SHADOWPWD
X if (spwd)
X agecheck (spwd->sp_lstchg,
X spwd->sp_min, spwd->sp_max, 1);
X else
X#endif
X agecheck (strlen (pwent.pw_age) == 4 ?
X a64l (pwent.pw_age + 2):0L,
X c64i (pwent.pw_age[1]), c64i (pwent.pw_age[0]), 7);
X#endif
X#ifdef MAILCHECK
X mailcheck (); /* report on the status of mail */
X#endif
X#ifdef TTYTYPE
X ttytype (utent.ut_line);
X#endif
X signal (SIGINT, SIG_DFL); /* default interrupt signal */
X signal (SIGQUIT, SIG_DFL); /* default quit signal */
X signal (SIGTERM, SIG_DFL); /* default terminate signal */
X signal (SIGALRM, SIG_DFL); /* default alarm signal */
X
X shell (pwent.pw_shell); /* exec the shell finally. */
X /*NOTREACHED*/
X}
SHAR_EOF
if test 8196 -ne "`wc -c < 'lmain.c'`"
then
echo shar: "error transmitting 'lmain.c'" '(should have been 8196 characters)'
fi
fi
echo shar: "extracting 'mkpasswd.c'" '(6587 characters)'
if test -f 'mkpasswd.c'
then
echo shar: "will not over-write existing file 'mkpasswd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mkpasswd.c'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X *
X * Duplication is permitted for non-commercial [ profit making ]
X * purposes provided this and other copyright notices remain
X * intact.
X */
X
X#include "config.h"
X#include <stdio.h>
X#include <fcntl.h>
X#include <pwd.h>
X#ifdef BSD
X#include <strings.h>
X#else
X#include <string.h>
X#endif
X
X#if !defined(DBM)
X#error "What you are trying to do? You have to have a DBM of some kind ..."
X#endif
X
X#ifdef DBM
X#include <dbm.h>
X#endif
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)mkpasswd.c 2.3 08:56:25 11/5/90";
Xstatic char copyright[] = "Copyright 1990, John F. Haugh II";
X#endif
X
Xchar *CANT_OPEN = "%s: cannot open file %s\n";
Xchar *CANT_OVERWRITE = "%s: cannot overwrite file %s\n";
Xchar *CANT_CREATE = "%s: cannot create %s\n";
Xchar *DBM_OPEN_ERR = "%s: cannot open DBM files for %s\n";
Xchar *PARSE_ERR = "%s: error parsing line\n\"%s\"\n";
Xchar *LINE_TOO_LONG = "%s: the beginning with \"%.16s ...\" is too long\n";
Xchar *ADD_NAME = "adding key for name \"%s\"\n";
Xchar *ADD_NAME_ERR = "%s: error adding entry for \"%s\"\n";
Xchar *ADD_UID = "adding key for uid %d, name \"%s\"\n";
Xchar *ADD_UID_ERR = "%s: error adding entry for uid %d, name \"%s\"\n";
Xchar *INFO = "added %d entries, longest was %d\n";
Xchar *USAGE = "Usage: %s [ -v ] [ -f ] file\n";
X
Xchar *Progname;
Xint vflg = 0;
Xint fflg = 0;
X
Xvoid usage();
X
Xextern char *malloc();
Xextern struct passwd *sgetpwent();
X
X/*
X * mkpasswd - create DBM files for /etc/passwd-like input file
X *
X * mkpasswd takes an an argument the name of a file in /etc/passwd format
X * and creates a DBM file keyed by user ID and name. The output files have
X * the same name as the input file, with .dir and .pag appended.
X */
X
Xint
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X extern int optind;
X extern char *optarg;
X FILE *pwfp; /* File pointer for password file */
X char *pwfile; /* Name of password file */
X char *pwdir; /* Name of .dir file */
X char *pwpag; /* Name of .pag file */
X char *cp; /* Temporary character pointer */
X int flag; /* Flag for command line option */
X int fd; /* File descriptor of open DBM file */
X int cnt = 0; /* Number of entries in database */
X int longest = 0; /* Longest entry in database */
X int errors = 0; /* Count of errors processing file */
X char buf[BUFSIZ]; /* Input line from password file */
X char dbmbuf[BUFSIZ]; /* Place to build DBM record */
X struct passwd *passwd; /* Pointer to password file entry */
X datum key; /* Info for DBM key data */
X datum content; /* Info for DBM record data */
X
X /*
X * Figure out what my name is. I will use this later ...
X */
X
X if (Progname = strrchr (argv[0], '/'))
X Progname++;
X else
X Progname = argv[0];
X
X /*
X * Figure out what the flags might be ...
X */
X
X while ((flag = getopt (argc, argv, "fv")) != EOF) {
X switch (flag) {
X case 'v':
X vflg++;
X break;
X case 'f':
X fflg++;
X break;
X default:
X usage ();
X }
X }
X
X /*
X * The last and only remaining argument must be the file name
X */
X
X if (argc - 1 != optind)
X usage ();
X
X pwfile = argv[optind];
X
X if (! (pwfp = fopen (pwfile, "r"))) {
X fprintf (stderr, CANT_OPEN, Progname, pwfile);
X exit (1);
X }
X
X /*
X * Make the filenames for the two DBM files.
X */
X
X pwdir = malloc (strlen (pwfile) + 5); /* space for .dir file */
X strcat (strcpy (pwdir, pwfile), ".dir");
X
X pwpag = malloc (strlen (pwfile) + 5); /* space for .pag file */
X strcat (strcpy (pwpag, pwfile), ".pag");
X
X /*
X * Remove existing files if requested.
X */
X
X if (fflg) {
X (void) unlink (pwdir);
X (void) unlink (pwpag);
X }
X
X /*
X * Create the two DBM files - it is an error for these files
X * to have existed already.
X */
X
X if (access (pwdir, 0) == 0) {
X fprintf (stderr, CANT_OVERWRITE, Progname, pwdir);
X exit (1);
X }
X if (access (pwpag, 0) == 0) {
X fprintf (stderr, CANT_OVERWRITE, Progname, pwpag);
X exit (1);
X }
X
X umask (0);
X if ((fd = open (pwdir, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) {
X fprintf (stderr, CANT_CREATE, Progname, pwdir);
X exit (1);
X } else
X close (fd);
X
X if ((fd = open (pwpag, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) {
X fprintf (stderr, CANT_CREATE, Progname, pwpag);
X unlink (pwdir);
X exit (1);
X } else
X close (fd);
X
X /*
X * Now the DBM database gets initialized
X */
X
X#ifdef DBM
X if (dbminit (pwfile) == -1) {
X fprintf (stderr, DBM_OPEN_ERR, Progname, pwfile);
X exit (1);
X }
X#endif
X
X /*
X * Read every line in the password file and convert it into a
X * data structure to be put in the DBM database files.
X */
X
X while (fgets (buf, BUFSIZ, pwfp) != NULL) {
X
X /*
X * Get the next line and strip off the trailing newline
X * character. Very long lines are fatal errors.
X */
X
X buf[BUFSIZ-1] = '\0';
X if (! (cp = strchr (buf, '\n'))) {
X fprintf (stderr, LINE_TOO_LONG, Progname, buf);
X exit (1);
X }
X *cp = '\0';
X
X /*
X * Parse the password file line into a (struct passwd).
X * Erroneous lines cause error messages, but that's
X * all. YP lines are ignored completely.
X */
X
X if (buf[0] == '-' || buf[0] == '+')
X continue;
X
X if (! (passwd = sgetpwent (buf))) {
X fprintf (stderr, PARSE_ERR, Progname, buf);
X errors++;
X continue;
X }
X
X /*
X * Pack the (struct passwd) into a buffer and build
X * the content structure for the DBM.
X */
X
X content.dsize = pw_pack (passwd, dbmbuf);
X content.dptr = dbmbuf;
X
X /*
X * Store the record using the name as the key
X */
X
X key.dsize = strlen (passwd->pw_name);
X key.dptr = passwd->pw_name;
X if (vflg)
X printf (ADD_NAME, passwd->pw_name);
X#ifdef DBM
X if (store (key, content)) {
X fprintf (stderr, ADD_NAME_ERR, Progname,
X passwd->pw_name);
X errors++;
X }
X#endif
X
X /*
X * Store the record using the UID as the key
X */
X
X key.dsize = sizeof passwd->pw_uid;
X key.dptr = (char *) &passwd->pw_uid;
X if (vflg)
X printf (ADD_UID, passwd->pw_uid, passwd->pw_name);
X#ifdef DBM
X if (store (key, content)) {
X fprintf (stderr, ADD_UID_ERR, Progname,
X passwd->pw_uid, passwd->pw_name);
X errors++;
X }
X#endif
X /*
X * Update the longest record and record count
X */
X
X if (content.dsize > longest)
X longest = content.dsize;
X cnt++;
X }
X
X /*
X * Tell the user how things went ...
X */
X
X if (vflg)
X printf (INFO, cnt, longest);
X
X exit (errors);
X /*NOTREACHED*/
X}
X
X/*
X * usage - print error message and exit
X */
X
Xvoid
Xusage ()
X{
X fprintf (stderr, USAGE, Progname);
X exit (1);
X /*NOTREACHED*/
X}
SHAR_EOF
if test 6587 -ne "`wc -c < 'mkpasswd.c'`"
then
echo shar: "error transmitting 'mkpasswd.c'" '(should have been 6587 characters)'
fi
fi
echo shar: "extracting 'sulogin.c'" '(3193 characters)'
if test -f 'sulogin.c'
then
echo shar: "will not over-write existing file 'sulogin.c'"
else
sed 's/^X//' << \SHAR_EOF > 'sulogin.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <pwd.h>
X#include <utmp.h>
X#ifndef BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "config.h"
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)sulogin.c 2.3.1.1 08:28:36 12/5/90";
X#endif
X
Xchar name[BUFSIZ];
Xchar pass[BUFSIZ];
Xchar home[BUFSIZ];
Xchar prog[BUFSIZ];
Xchar mail[BUFSIZ];
X
Xstruct passwd pwent;
Xstruct utmp utent;
X
X#ifdef TZ
XFILE *tzfile;
Xchar tzbuf[16] = TZ;
X#endif
X
X#ifndef MAXENV
X#define MAXENV 64
X#endif
X
Xchar *newenvp[MAXENV];
Xint newenvc = 0;
Xint maxenv = MAXENV;
Xextern char **environ;
X
X#ifndef ALARM
X#define ALARM 60
X#endif
X
X#ifndef RETRIES
X#define RETRIES 3
X#endif
X
Xint main (argc, argv, envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
X char *getenv ();
X char *ttyname ();
X char *cp;
X
X if (access (PWDFILE, 0) == -1) { /* must be a password file! */
X printf ("No password file\n");
X exit (1);
X }
X#ifdef NDEBUG
X if (getppid () != 1) /* parent must be INIT */
X exit (1);
X#endif
X if (! isatty (0)) /* must be a terminal */
X exit (1);
X
X while (*envp) /* add inherited environment, */
X addenv (*envp++); /* some variables change later */
X
X#ifdef TZ
X if (tzbuf[0] == '/') {
X if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) {
X if (fgets (tzbuf, sizeof tzbuf, tzfile)) {
X tzbuf[strlen (tzbuf) - 1] = '\0';
X addenv (tzbuf);
X }
X fclose (tzfile);
X }
X } else {
X addenv (tzbuf);
X }
X#endif
X#ifdef HZ
X addenv (HZ); /* set the default $HZ, if one */
X#endif
X (void) strcpy (name, "root"); /* KLUDGE!!! */
X
X alarm (ALARM);
X while (1) { /* repeatedly get login/password pairs */
X entry (name, &pwent); /* get entry from password file */
X if (pwent.pw_name == (char *) 0) {
X printf ("No password entry for 'root'\n");
X exit (1);
X }
X
X /*
X * Here we prompt for the root password, or if no password is
X * given we just exit.
X */
X
X /* get a password for root */
X if (! password ("Type control-d for normal startup,\n\
X(or give root password for system maintenance):", pass))
X exit (0);
X
X if (valid (pass, &pwent)) /* check encrypted passwords ... */
X break; /* ... encrypted passwords matched */
X
X puts ("Login incorrect");
X }
X alarm (0);
X environ = newenvp; /* make new environment active */
X
X puts ("Entering System Maintenance Mode");
X
X /*
X * Normally there would be a utmp entry for login to mung on
X * to get the tty name, date, etc. from. We don't need all that
X * stuff because we won't update the utmp or wtmp files. BUT!,
X * we do need the tty name so we can set the permissions and
X * ownership.
X */
X
X if (cp = ttyname (0)) { /* found entry in /dev/ */
X if (strrchr (cp, '/') != (char *) 0)
X strcpy (utent.ut_line, strrchr (cp, '/') + 1);
X else
X strcpy (utent.ut_line, cp);
X }
X if (getenv ("IFS")) /* don't export user IFS ... */
X addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
X
X setup (&pwent); /* set UID, GID, HOME, etc ... */
X
X shell (pwent.pw_shell); /* exec the shell finally. */
X /*NOTREACHED*/
X}
SHAR_EOF
if test 3193 -ne "`wc -c < 'sulogin.c'`"
then
echo shar: "error transmitting 'sulogin.c'" '(should have been 3193 characters)'
fi
fi
echo shar: "extracting 'pwpack.c'" '(2139 characters)'
if test -f 'pwpack.c'
then
echo shar: "will not over-write existing file 'pwpack.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pwpack.c'
X/*
X * Copyright 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X *
X * Duplication is permitted for non-commercial [ profit making ]
X * purposes provided this and other copyright notices remain
X * intact.
X */
X
X#include <stdio.h>
X#include <pwd.h>
X#ifdef BSD
X#include <strings.h>
X#else
X#include <string.h>
X#endif
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)pwpack.c 2.3 23:06:29 8/5/90";
X#endif
X
Xint pw_pack (passwd, buf)
Xstruct passwd *passwd;
Xchar *buf;
X{
X char *cp;
X
X cp = buf;
X strcpy (cp, passwd->pw_name);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_passwd);
X if (passwd->pw_age && passwd->pw_age[0]) {
X cp += strlen (cp);
X *cp++ = ',';
X strcpy (cp, passwd->pw_age);
X }
X cp += strlen (cp) + 1;
X
X memcpy (cp, (void *) &passwd->pw_uid, sizeof passwd->pw_uid);
X cp += sizeof passwd->pw_uid;
X
X memcpy (cp, (void *) &passwd->pw_gid, sizeof passwd->pw_gid);
X cp += sizeof passwd->pw_gid;
X
X strcpy (cp, passwd->pw_gecos);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_dir);
X cp += strlen (cp) + 1;
X
X strcpy (cp, passwd->pw_shell);
X cp += strlen (cp) + 1;
X
X return cp - buf;
X}
X
Xint pw_unpack (buf, len, passwd)
Xchar *buf;
Xint len;
Xstruct passwd *passwd;
X{
X char *org = buf;
X char *cp;
X
X passwd->pw_name = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_passwd = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X if (cp = strchr (passwd->pw_passwd, ',')) {
X *cp++ = '\0';
X passwd->pw_age = cp;
X } else
X passwd->pw_age = "";
X
X memcpy ((void *) &passwd->pw_uid, (void *) buf, sizeof passwd->pw_uid);
X buf += sizeof passwd->pw_uid;
X if (buf - org > len)
X return -1;
X
X memcpy ((void *) &passwd->pw_gid, (void *) buf, sizeof passwd->pw_gid);
X buf += sizeof passwd->pw_gid;
X if (buf - org > len)
X return -1;
X
X passwd->pw_gecos = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_dir = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X passwd->pw_shell = buf;
X buf += strlen (buf) + 1;
X if (buf - org > len)
X return -1;
X
X return 0;
X}
SHAR_EOF
if test 2139 -ne "`wc -c < 'pwpack.c'`"
then
echo shar: "error transmitting 'pwpack.c'" '(should have been 2139 characters)'
fi
fi
echo shar: "extracting 'dialup.c'" '(2171 characters)'
if test -f 'dialup.c'
then
echo shar: "will not over-write existing file 'dialup.c'"
else
sed 's/^X//' << \SHAR_EOF > 'dialup.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <stdio.h>
X#ifndef BSD
X#include <string.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "dialup.h"
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)dialup.c 2.2 19:23:38 7/29/90";
X#endif
X
Xstatic FILE *dialpwd;
X
Xvoid setduent ()
X{
X if (dialpwd)
X rewind (dialpwd);
X else
X dialpwd = fopen (DIALPWD, "r");
X}
X
Xvoid endduent ()
X{
X if (dialpwd)
X fclose (dialpwd);
X
X dialpwd = (FILE *) 0;
X}
X
Xstruct dialup *getduent ()
X{
X static struct dialup dialup; /* static structure to point to */
X static char shell[64]; /* some space for a login shell */
X static char passwd[16]; /* some space for dialup password */
X char buf[BUFSIZ];
X char *cp;
X
X if (! dialpwd)
X setduent ();
X
X if (! dialpwd || feof (dialpwd))
X return ((struct dialup *) 0);
X
X while (fgets (buf, BUFSIZ, dialpwd) == buf && buf[0] == '#')
X ;
X
X if (feof (dialpwd))
X return ((struct dialup *) 0);
X
X cp = strchr (buf, ':');
X if (cp - buf > sizeof shell) /* something is fishy ... */
X return ((struct dialup *) 0);
X
X (void) strncpy (shell, buf, cp - buf);
X shell[cp - buf] = '\0';
X
X if (strlen (cp + 1) > sizeof passwd) /* something is REALLY fishy */
X return ((struct dialup *) 0);
X
X (void) strcpy (passwd, cp + 1);
X passwd[strlen (passwd) - 1] = '\0';
X if (cp = strchr (passwd, ':'))
X *cp = '\0';
X
X dialup.du_shell = shell;
X dialup.du_passwd = passwd;
X
X return (&dialup);
X}
X
Xstruct dialup *getdushell (shell)
Xchar *shell;
X{
X struct dialup *dialup;
X
X while (dialup = getduent ()) {
X if (strcmp (shell, dialup->du_shell) == 0)
X return (dialup);
X
X if (strcmp (dialup->du_shell, "*") == 0)
X return (dialup);
X }
X return ((struct dialup *) 0);
X}
X
Xint isadialup (tty)
Xchar *tty;
X{
X FILE *fp;
X char buf[BUFSIZ];
X int dialup = 0;
X
X if (! (fp = fopen (DIALUPS, "r")))
X return (0);
X
X while (fgets (buf, BUFSIZ, fp) == buf) {
X if (buf[0] == '#')
X continue;
X
X buf[strlen (buf) - 1] = '\0';
X
X if (strcmp (buf, tty) == 0) {
X dialup = 1;
X break;
X }
X }
X fclose (fp);
X
X return (dialup);
X}
SHAR_EOF
if test 2171 -ne "`wc -c < 'dialup.c'`"
then
echo shar: "error transmitting 'dialup.c'" '(should have been 2171 characters)'
fi
fi
echo shar: "extracting 'sulog.c'" '(1172 characters)'
if test -f 'sulog.c'
then
echo shar: "will not over-write existing file 'sulog.c'"
else
sed 's/^X//' << \SHAR_EOF > 'sulog.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <time.h>
X#ifndef BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "config.h"
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)sulog.c 2.2.1.1 09:09:55 11/26/90";
X#endif
X
Xextern char name[];
Xextern char oldname[];
X
Xtime_t time ();
X
Xvoid sulog (success)
Xint success;
X{
X#ifdef SULOG
X char *tty;
X char *cp;
X char *ttyname ();
X time_t clock;
X struct tm *tm;
X struct tm *localtime ();
X FILE *fp;
X
X if ((fp = fopen (SULOG, "a+")) == (FILE *) 0)
X return; /* can't open or create logfile */
X
X (void) time (&clock);
X tm = localtime (&clock);
X
X if (isatty (0) && (cp = ttyname (0))) {
X if (tty = strrchr (cp, '/'))
X tty++;
X else
X tty = cp;
X } else
X tty = "???";
X
X (void) fprintf (fp, "SU %.02d/%0.2d %.02d:%.02d %c %.6s %s-%s\n",
X tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
X success ? '+':'-', tty, oldname, name);
X
X fflush (fp);
X fclose (fp);
X#endif
X}
SHAR_EOF
if test 1172 -ne "`wc -c < 'sulog.c'`"
then
echo shar: "error transmitting 'sulog.c'" '(should have been 1172 characters)'
fi
fi
echo shar: "extracting 'password.c'" '(1939 characters)'
if test -f 'password.c'
then
echo shar: "will not over-write existing file 'password.c'"
else
sed 's/^X//' << \SHAR_EOF > 'password.c'
X/*
X * Copyright 1988,1989,1990, John F. Haugh II
X * All rights reserved.
X *
X * Non-commercial distribution permitted. You must provide this source
X * code in any distribution. This notice must remain intact.
X */
X
X#include <stdio.h>
X#ifndef BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#ifndef BSD
X#include <termio.h>
X#else
X#include <sgtty.h>
X#endif
X
X#include <fcntl.h>
X
X/*
X * password - prompt for password and return entry
X *
X * Need to fake up getpass(). Returns TRUE if a password
X * was successfully input, and FALSE otherwise, including
X * EOF on input or ioctl() failure. pass is not modified
X * on failure. The input length limit may be set by
X * changing the value of PASSLIMIT.
X */
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)password.c 2.2 09:38:59 6/22/90";
X#endif
X
X#define PASSLIMIT 20
X
Xint password (prompt, pass)
Xchar *prompt;
Xchar *pass;
X{
X char buf[BUFSIZ];
X char *cp;
X int eof;
X int ttyopened = 0;
X#ifndef BSD
X struct termio termio;
X struct termio save;
X#else
X struct sgttyb termio ;
X struct sgttyb save ;
X#endif
X FILE *fp;
X
X if ((fp = fopen ("/dev/tty", "r")) == (FILE *) 0)
X fp = stdin;
X else
X ttyopened = 1;
X
X#ifndef BSD
X if (ioctl (fileno (fp), TCGETA, &termio))
X return (0);
X#else
X if ( gtty( fileno(fp), &termio ) )
X return (0);
X#endif
X
X save = termio;
X#ifndef BSD
X termio.c_lflag &= ~(ECHO|ECHOE|ECHOK);
X ioctl (fileno (fp), TCSETAF, &termio);
X#else
X termio.sg_flags &= ~ECHO ;
X stty( fileno( fp ), termio ) ;
X#endif
X
X fputs (prompt, stdout);
X eof = fgets (buf, BUFSIZ, fp) == (char *) 0 || feof (fp) || ferror (fp);
X putchar ('\n');
X
X#ifndef BSD
X ioctl (fileno (fp), TCSETAF, &save);
X#else
X stty( fileno( fp ), save ) ;
X#endif
X
X if (! eof) {
X buf[PASSLIMIT] = '\0';
X if ((cp = strchr (buf, '\n')) || (cp = strchr (buf, '\r')))
X *cp = '\0';
X
X (void) strcpy (pass, buf);
X }
X if (ttyopened)
X fclose (fp);
X
X return (! eof);
X}
SHAR_EOF
if test 1939 -ne "`wc -c < 'password.c'`"
then
echo shar: "error transmitting 'password.c'" '(should have been 1939 characters)'
fi
fi
echo shar: "extracting 'env.c'" '(1788 characters)'
if test -f 'env.c'
then
echo shar: "will not over-write existing file 'env.c'"
else
sed 's/^X//' << \SHAR_EOF > 'env.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <stdio.h>
X#ifndef BSD
X#include <string.h>
X#else
X#define strchr index
X#define strrchr rindex
X#include <strings.h>
X#endif
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)env.c 2.2 19:23:43 7/29/90";
X#endif
X
Xextern char **environ;
Xextern char *newenvp[];
Xextern int newenvc;
Xextern int maxenv;
X
Xchar *strdup ();
Xvoid free ();
X
Xstatic char *forbid[] = {
X "HOME",
X "IFS",
X "PATH",
X "SHELL",
X (char *) 0
X};
X
Xvoid addenv (entry)
Xchar *entry;
X{
X char *cp;
X int i;
X int len;
X
X if (cp = strchr (entry, '='))
X len = cp - entry;
X else
X return;
X
X for (i = 0;i < newenvc;i++)
X if (strncmp (entry, newenvp[i], len) == 0 &&
X (newenvp[i][len] == '=' || newenvp[i][len] == '\0'))
X break;
X
X if (i == maxenv) {
X puts ("Environment overflow");
X return;
X }
X if (i == newenvc) {
X newenvp[newenvc++] = strdup (entry);
X } else {
X free (newenvp[i]);
X newenvp[i] = strdup (entry);
X }
X}
X
Xvoid setenv (argc, argv)
Xint argc;
Xchar **argv;
X{
X int i;
X int n;
X int noname = 1;
X char variable[BUFSIZ];
X char *cp;
X
X for (i = 0;i < argc;i++) {
X if ((n = strlen (argv[i])) >= BUFSIZ)
X continue; /* ignore long entries */
X
X if (! (cp = strchr (argv[i], '='))) {
X (void) strcpy (variable, argv[i]);
X } else {
X (void) strncpy (variable, argv[i], cp - argv[i]);
X variable[cp - argv[i]] = '\0';
X }
X for (n = 0;forbid[n] != (char *) 0;n++)
X if (strcmp (variable, forbid[n]) == 0)
X break;
X
X if (forbid[n] != (char *) 0) {
X printf ("You may not change $%s\n", forbid[n]);
X continue;
X }
X if (cp) {
X addenv (argv[i]);
X } else {
X sprintf (variable, "L%d=%s", noname++, argv[i]);
X addenv (variable);
X }
X }
X}
SHAR_EOF
if test 1788 -ne "`wc -c < 'env.c'`"
then
echo shar: "error transmitting 'env.c'" '(should have been 1788 characters)'
fi
fi
echo shar: "extracting 'mail.c'" '(912 characters)'
if test -f 'mail.c'
then
echo shar: "will not over-write existing file 'mail.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mail.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifndef BSD
X#include <string.h>
X#include <memory.h>
X#else
X#include <strings.h>
X#define strchr index
X#define strrchr rindex
X#endif
X#include "config.h"
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)mail.c 2.2 19:23:56 7/29/90";
X#endif
X
Xextern char mail[];
X
X#ifdef HUSHLOGIN
Xextern int hushed;
X#endif
X
X#ifdef MAILCHECK
Xvoid mailcheck ()
X{
X struct stat statbuf;
X char *mailbox;
X
X#ifdef HUSHLOGIN
X if (hushed)
X return;
X#endif
X if (mailbox = strchr (mail, '='))
X mailbox++;
X else
X return;
X
X if (stat (mailbox, &statbuf) == -1 || statbuf.st_size == 0)
X puts ("No mail.");
X else if (statbuf.st_atime > statbuf.st_mtime)
X puts ("You have mail.");
X else
X puts ("You have new mail.");
X}
X#endif
SHAR_EOF
if test 912 -ne "`wc -c < 'mail.c'`"
then
echo shar: "error transmitting 'mail.c'" '(should have been 912 characters)'
fi
fi
echo shar: "extracting 'dialchk.c'" '(1008 characters)'
if test -f 'dialchk.c'
then
echo shar: "will not over-write existing file 'dialchk.c'"
else
sed 's/^X//' << \SHAR_EOF > 'dialchk.c'
X/*
X * Copyright 1989, 1990, John F. Haugh II
X * All rights reserved.
X *
X * Use, duplication, and disclosure prohibited without
X * the express written permission of the author.
X */
X
X#include <stdio.h>
X#include "config.h"
X#include "dialup.h"
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)dialchk.c 2.2 19:23:36 7/29/90";
X#endif
X
X/*
X * Check for dialup password
X *
X * dialcheck tests to see if tty is listed as being a dialup
X * line. If so, a dialup password may be required if the shell
X * is listed as one which requires a second password.
X */
X
X#ifdef DIALUP
Xint dialcheck (tty, shell)
Xchar *tty;
Xchar *shell;
X{
X char *crypt ();
X char *getpass ();
X struct dialup *dialup;
X char *pass;
X char *cp;
X
X if (! isadialup (tty))
X return (1);
X
X if (! (dialup = getdushell (shell)))
X return (1);
X
X endduent ();
X
X if (dialup->du_passwd[0] == '\0')
X return (1);
X
X if (! (pass = getpass ("Dialup Password:")))
X return (0);
X
X cp = crypt (pass, dialup->du_passwd);
X return (strcmp (cp, dialup->du_passwd) == 0);
X}
X#endif
SHAR_EOF
if test 1008 -ne "`wc -c < 'dialchk.c'`"
then
echo shar: "error transmitting 'dialchk.c'" '(should have been 1008 characters)'
fi
fi
exit 0
# End of shell archive
--
John F. Haugh II UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832 Domain: jfh at rpp386.cactus.org
More information about the Alt.sources
mailing list