Shadow login release 2 (part 1 of 3)
John F. Haugh II
jfh at rpp386.Dallas.TX.US
Tue Jun 20 16:48:40 AEST 1989
X-Archive-Name: shadow2/part1
Part 1 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:
# README
# log.c
# mail.c
# shadow.h
# sulog.c
# Makefile
# entry.c
# obscure.c
# setup.c
# sub.c
# config.h
# pmain.c
# sulogin.c
# dialup.h
# ttytype.c
# This archive created: Tue Jun 20 01:28:03 1989
# By: John F. Haugh II (River Parishes Programming, Plano TX)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'README'
then
echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'
This is the explanatory document for John F. Haugh II's login replacement.
This software is copyright 1989, John F. Haugh II. All rights reserved.
Use, duplication and disclosure is permitted according to the guidelines
listed below. At some point in the future this licence will be
modified to conform to the GNU General Public License.
This software is being provided as a freely redistributable login clone.
You may distribute this software provided you do not charge for other than
transmission costs. You are free to transfer this software provided you
do not restrict the rights of the recipients to further transfer this
software.
This software is being distributed AS-IS. The author disclaims all
liability for any consequences of use. The user is solely responsible
for the maintenance of this software package. The author is under no
obligation to provide modifications or improvements.
Begin by reading and editing the config.h file. All options are selected
by using #define's. A brief description for each available option appears
below. You may want to print this file out as it is LONG and you will
need to refer to it while editting config.h. You will also have to edit
the Makefile. The possible differences are documented there. Pay close
attention to the install: rule. DO NOT MAIL ME DIFFERENCES FOR VARIOUS
INSTALLATION PROBLEMS. If you must share your experiences, do so on the
net. Login now runs on about 15 different varieties of UNIX that I have
been made aware of.
Note that there are MANY options. As distributed most options are turned
on, which produces a really nice package. This is the system as used on
the authors machine. [ The one exception is NOBLANK, that is turned off
because of anonymous UUCP logins. ]
Dialup Password Files -
This option permits individual ports to have an additional
password prompted for on a by-shell basis. /etc/dialups
contains a list of dialup ports, d_passwd contains the
password for each shell requiring a dialup password.
Select this option by defining the DIALUP macro.
Shadow [ unreadable ] Password Files -
This option utilizes an alternate, non-readable file to
contain the actual encrypted passwords. This is presumed
to increase system security by increasing the difficulty
with which system crackers obtain encrypted passwords.
Select this option by defining the SHADOWPWD macro.
Double Length Passwords -
This option extends the maximum length of a user password
to 16 characters from eight.
Select this option by defining the DOUBLESIZE macro.
Credit for this option is due Jonathan Bayer.
Obscure Password Testing -
This option includes code to test user passwords for
complexity. The programmer is encouraged to edit the
file obscure.c to add additional methods for detecting
simplistic passwords.
Select this option by defining the OBSCURE macro.
Additionally, the PASSLENGTH macro must be defined to
control the minimum length for a legal password.
Mandatory Password Prompting -
This option requires all passwords, including null ones,
to be prompted for. Traditionally an account with a
password field of '::' does not require prompting for.
This option modifies this behavior to require even
null passwords be prompted for.
Select this option by defining the NOBLANK macro.
Password Aging Defaults -
You may select the default number of days during which a
password is valid. The pwconv command adds aging
information to accounts which do not include it already.
The MINDAYS macro must be defined to be the minimum
number of days which must pass before a password may be
changed. The MAXDAYS macro must be defined to be the
maximum number of days which a password will remain
valid during.
HZ Environmental Variable -
This option pre-defines the HZ environmental variable.
Certain systems require this variable be defined for
system time reporting functions to work properly.
Select this option by defining the HZ macro to have
the desired environmental variable value.
TZ Environmental Variable -
This option pre-defines the TZ environmental variable.
This provides a default timezone variable for use by
various utilities.
Select this option by defining the TZ macro to have
the desired environmental variable value, or the name
of the file containing the desired value.
Password Aging -
This option includes code to perform password aging.
Password aging is presumed to increase system security
by forcing users to change passwords on a regular
basis. The resolution on password age is in weeks for
non-shadow password systems and in days otherwise.
Select this option by defining the AGING macro.
Mailbox Checking -
This option includes code to check the status of the
user's mailbox. One of three messages are produced
depending on the status of the user's mailbox.
Select this option by defining the MAILCHECK macro.
Console Restricted Root Logins -
This option restricts the port which root may legally
login on. This option presumably increases system
security by preventing outside attacks against the root
account.
Select this option by defining the CONSOLE macro to
have the desired port name. If this file is a regular
file, it is considered to contain a list of legal port
names, one per line. Note that the port names DO NOT
begin with "/dev/" and that a file name would have to
be fully qualified. See config.h for a pair of
examples.
Restricted User Logins -
This option permits you to specify a file which disables
user logins. This options permits you to keep normal
users off of the system while performing maintenance
functions.
Select this option by defining NOLOGINS to be the name
of the file to use.
Restricted Use Accounts -
This option permits certain accounts to be used for
identification purposes only. This options associates
login ID's with UID's, such as for disk space accounting
or anonymous FTP accounts. Passwords for these accounts
may only be changed by root.
Select this option by defining NOUSE to be the string
to include in the password file in place of the user's
shell.
Message of the Day Printing -
This option causes the message of the day to be
printed at login time.
Select this option by defining the MOTD macro.
If you wish this feature to be overriden on a per-user
basis, define the macro HUSHLOGIN and users may then
turn off the /etc/motd message by creating a file
'.hushlogin' in their home directories.
Last Login Time Logging -
This option causes a record to be made of successful
logins in /usr/adm/lastlog. The format of the
structure is defined in lastlog.h.
Select this option by defining the LASTLOG macro.
You will need to determine if you system already has
a lastlog.h file and use that file if present.
Failed Login Logging -
This option causes a record to be kept of the most
recent login failure by date and port. A cummulative
count of failures is maintained and compared against
an allowable limit.
Select this option by defining the FAILLOG macro.
See the file faillog.h for more details.
Terminal Permissions -
This option allows the terminal modes to be set at
login time. This is particularly useful to disable
messages on user's terminals.
Select this option by defining the TTYPERM macro as
having the desired mode.
Terminal Type Setup -
This option allows the terminal type to be set at
login time. The environmental variable TERM will be
set from the specified terminal to port mapping
file.
Select this option by defining the TTYTYPE macro as
having the value of the name of the type to port
mapping file. Credit for this option is due Chip
Rosenthal.
File Size Setting -
This option includes code to set the user's ulimit
at login time. Additional code to set the umask and
nice value is also included.
Select this option by defining the QUOTAS macro.
Switch-User Logging -
This option causes su(1) to log attempts to switch
users. Su(1) will log all attempt, giving the old
and new user ID's, tty port, and time. It also
indicates if the attempt was successful.
Select this option by defining the SULOG macro to
have the value of the name of the file you want
attempts logged to.
Configurable Editing Keys -
This options allows the erase and kill characters to
be selected. A default value is provided. By default
ERASE will be ^H and KILL will be ^U.
Select this option by defining the ERASECHAR macro
to be the desired erase character and the KILLCHAR
macro to be the desired KILL character.
Default ulimit and umask Values -
This option allows you to select the default values
for ulimit and umask, allowing you to avoid
regenerating your system kernel. These values may be
overriden with appropriate entries in the GECOS field.
Select the default ulimit by defining the ULIMIT
macro, and the default umask by defining the UMASK
macro.
Warning: These values will not apply to processes
executed by /etc/cron or any of their children.
BSD Notes: Steve Simmons scs at iti.org
The full port of the shadow package to BSD is not complete; but some
of the issues have been worked out. These notes describe the current
state of things:
In order to make use of password aging under BSD, minor changes to
/usr/include/pwd.h and getpwent() are needed. These changes are to
keep the password age from messing up the encrypted password when not
using shadow passwords, and involve placing a new field in the password
data structure. To use this, you should apply the following two patches:
pwd.h.patch
getpwent.c.patch
to the BSD /usr/include/pwd.h and /usr/src/lib/libc/gen/getpwent.c,
respectively. After applying the patches, rebuild your standard C
library with the new getpwent. Programs which use the old getpwent
will fail on password checking if they do a strcmp rather than a strncmp.
These changes are based on BSD4.3, not Tahoe
ToDo BSD:
I'm working on this in my copious spare time (hah!); any help would
be appreciated. If you decide to help, do these independantly rather
than rework BSD code! Keep it redistributable!
No dbm functions have been put in place. Dbm functionality is needed
for both /etc/password and /etc/shadow management.
The BSD GECOS field gets used for lots more stuff than the USG. At a
minimum this functionality should be duplicated under BSD; better is to put
it into USG as well; still better would be to make the chfn command for
both systems; best would be site-configurable data to be put into GECOS/chfn.
SHAR_EOF
fi
if test -f 'log.c'
then
echo shar: "will not over-write existing file 'log.c'"
else
cat << \SHAR_EOF > 'log.c'
#include <sys/types.h>
#include <utmp.h>
#include <pwd.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 "config.h"
#ifndef lint
static char _sccsid[] = "@(#)log.c 2.1 01:23:21 6/20/89";
#endif
#ifdef LASTLOG
#include "lastlog.h"
extern struct utmp utent;
extern struct passwd pwent;
extern struct lastlog lastlog;
extern char **environ;
long lseek ();
time_t time ();
void log ()
{
int fd;
off_t offset;
struct lastlog newlog;
if ((fd = open ("/usr/adm/lastlog", O_RDWR)) == -1)
return;
offset = pwent.pw_uid * sizeof lastlog;
if (lseek (fd, offset, 0) != offset) {
(void) close (fd);
return;
}
if (read (fd, (char *) &lastlog, sizeof lastlog) != sizeof lastlog)
#ifndef BSD
memset ((char *) &lastlog, sizeof lastlog, 0);
#else
bzero ((char *) &lastlog, sizeof lastlog);
#endif
newlog = lastlog;
(void) time (&newlog.ll_time);
(void) strncpy (newlog.ll_line, utent.ut_line, sizeof newlog.ll_line);
(void) lseek (fd, offset, 0);
(void) write (fd, (char *) &newlog, sizeof newlog);
(void) close (fd);
}
#endif
SHAR_EOF
fi
if test -f 'mail.c'
then
echo shar: "will not over-write existing file 'mail.c'"
else
cat << \SHAR_EOF > 'mail.c'
#include <sys/types.h>
#include <sys/stat.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[] = "@(#)mail.c 2.1 01:23:26 6/20/89";
#endif
extern char mail[];
#ifdef HUSHLOGIN
extern int hushed;
#endif
#ifdef MAILCHECK
void mailcheck ()
{
struct stat statbuf;
char *mailbox;
#ifdef HUSHLOGIN
if (hushed)
return;
#endif
if (mailbox = strchr (mail, '='))
mailbox++;
else
return;
if (stat (mailbox, &statbuf) == -1 || statbuf.st_size == 0)
puts ("No mail.");
else if (statbuf.st_atime > statbuf.st_mtime)
puts ("You have mail.");
else
puts ("You have new mail.");
}
#endif
SHAR_EOF
fi
if test -f 'shadow.h'
then
echo shar: "will not over-write existing file 'shadow.h'"
else
cat << \SHAR_EOF > 'shadow.h'
/*
* This information is not derived from AT&T licensed sources. Posted
* to the USENET 11/88.
*
* @(#)shadow.h 2.1 01:23:51 6/20/89
*/
/*
* Shadow password security file structure.
*/
struct spwd {
char *sp_namp; /* login name */
char *sp_pwdp; /* encrypted password */
long sp_lstchg; /* date of last change */
long sp_max; /* maximum number of days between changes */
long sp_min; /* minimum number of days between changes */
};
/*
* Shadow password security file functions.
*/
struct spwd *getspent ();
struct spwd *getspnam ();
void setspent ();
void endspent ();
struct spwd *fgetspent ();
int putspent ();
#define SHADOW "/etc/shadow"
SHAR_EOF
fi
if test -f 'sulog.c'
then
echo shar: "will not over-write existing file 'sulog.c'"
else
cat << \SHAR_EOF > 'sulog.c'
#include <sys/types.h>
#include <stdio.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"
extern char name[];
extern char oldname[];
time_t time ();
void sulog (success)
int success;
{
#ifdef SULOG
char *tty;
char *cp;
char *ttyname ();
time_t clock;
struct tm *tm;
struct tm *localtime ();
FILE *fp;
if ((fp = fopen (SULOG, "a+")) == (FILE *) 0)
return; /* can't open or create logfile */
(void) time (&clock);
tm = localtime (&clock);
if (isatty (0) && (cp = ttyname (0))) {
if (tty = strrchr (cp, '/'))
tty++;
else
tty = cp;
} else
tty = "???";
(void) fprintf (fp, "SU %.02d/%0.2d %.02d:%.02d %c %.6s %s-%s\n",
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
success ? '+':'-', tty, oldname, name);
fflush (fp);
fclose (fp);
#endif
}
SHAR_EOF
fi
if test -f 'Makefile'
then
echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
# %W% %U% - System V shadow password system
#
# %W% %U% %G%
#
SHELL = /bin/sh
# Define the directory login is copied to. BE VERY CAREFUL!!!
# LOGINDIR = /bin
LOGINDIR = /etc
# Pick your favorite C compiler and tags command
CC = cc
TAGS = ctags
# OS. Currently only BSD and USG are defined. If you don't use BSD,
# USG (System V) is assumed.
# OS = -DBSD
# Do you have to do ranlib? Sorry to hear that ...
RANLIB = ranlib
# RANLIB = echo
# Flags for SCO Xenix/386
CFLAGS = -O -M3 -g $(PWDEF) $(AL64DEF) $(OS)
LIBS = -lcrypt
LDFLAGS = -M3 -g
LTFLAGS =
# This should be Slibsec.a for small model, or Llibsec.a for
# large model or whatever. MUST AGREE WITH CFLAGS!!!
LIBSEC = Slibsec.a
# Flags for normal machines
# CFLAGS = -O -g $(PWDEF) $(AL64DEF) $(OS)
# LIBS =
# LDFLAGS = -g
# LIBSEC = libsec.a
LOBJS = lmain.o login.o env.o password.o entry.o valid.o setup.o shell.o age.o \
pwent.o utmp.o sub.o mail.o motd.o log.o shadow.o dialup.o dialchk.o \
ttytype.o failure.o
LSRCS = lmain.c login.c env.c password.c entry.c valid.c setup.c shell.c age.c \
pwent.c utmp.c sub.c mail.c motd.c log.c shadow.c dialup.c dialchk.c \
ttytype.c failure.c
SOBJS = smain.o env.o password.o entry.o valid.o susetup.o sushell.o \
pwent.o susub.o mail.o motd.o sulog.o shadow.o age.o
SSRCS = smain.c env.c password.c entry.c valid.c setup.c shell.c \
pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c
POBJS = pmain.o password.o entry.o valid.o pwage.o pwent.o obscure.o shadow.o
PSRCS = pmain.c password.c entry.c valid.c age.c pwent.c obscure.c shadow.c
PWOBJS = pwconv.o pwent.o shadow.o pwage.o
PWSRCS = pwconv.c pwent.c shadow.c age.c
PWUNOBJS = pwunconv.o pwent.o shadow.o pwage.o
PWUNSRCS = pwunconv.c pwent.c shadow.c age.c
SULOGOBJS = sulogin.o entry.o env.o password.o pwage.o pwent.o setup.o \
shadow.o shell.o valid.o
SULOGSRCS = sulogin.c entry.c env.c password.c age.c pwent.c setup.c \
shadow.c shell.c valid.c
ALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \
motd.c obscure.c password.c pmain.c pwconv.c pwent.c pwunconv.c \
setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \
utmp.c valid.c
FILES1 = README log.c mail.c shadow.h sulog.c Makefile entry.c obscure.c \
setup.c sub.c config.h pmain.c sulogin.c dialup.h ttytype.c
FILES2 = 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
DOCS = login.1 passwd.1 passwd.4 shadow.3 shadow.4 su.1 sulogin.8 pwconv.8 \
pwunconv.8 faillog.8 faillog.4
all: su login pwconv pwunconv passwd sulogin faillog
libsec: shadow.o
ar rv $(LIBSEC) shadow.o
$(RANLIB) $(LIBSEC)
install: all
cp login $(LOGINDIR)/login
cp pwconv pwunconv sulogin /etc
cp su passwd faillog /bin
chown root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
/bin/su /bin/passwd
chgrp root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
/bin/su /bin/passwd
chown bin /bin/faillog
chgrp bin /bin/faillog
chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin
chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd
chmod 711 /bin/faillog
lint: su.L login.L pwconv.L pwunconv.L passwd.L sulogin.L faillog.L
tags: $(ALLSRCS)
$(TAGS) $(ALLSRCS)
login: $(LOBJS)
$(CC) -o login $(LDFLAGS) $(LOBJS) $(LIBS)
login.L: $(LSRCS)
lint $(LSRCS) > login.L
su: $(SOBJS)
$(CC) -o su $(LDFLAGS) $(SOBJS) $(LIBS)
su.L: $(SSRCS)
lint -DSU $(SSRCS) > su.L
passwd: $(POBJS)
$(CC) -o passwd $(LDFLAGS) $(POBJS) $(LIBS)
passwd.L: $(PSRCS)
lint -DPASSWD $(PSRCS) > passwd.L
pwconv: $(PWOBJS)
$(CC) -o pwconv $(LDFLAGS) $(PWOBJS) $(LIBS)
pwconv.L: $(PWSRCS)
lint -DPASSWD $(PWSRCS) > pwconv.L
pwunconv: $(PWUNOBJS)
$(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) $(LIBS)
pwunconv.L: $(PWUNSRCS)
lint -DPASSWD $(PWUNSRCS) > pwunconv.L
sulogin: $(SULOGOBJS)
$(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) $(LIBS)
sulogin.L: $(SULOGSRCS)
lint $(SULOGSRCS) > sulogin.L
faillog: faillog.o
$(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS)
faillog.L: faillog.c faillog.h config.h
lint faillog.c > faillog.L
sushell.o: config.h shell.c
$(CC) -c $(CFLAGS) -DSU shell.c
mv shell.o sushell.o
susub.o: config.h sub.c
$(CC) -c $(CFLAGS) -DSU sub.c
mv sub.o susub.o
sulog.o: config.h
susetup.o: config.h setup.c
$(CC) -c $(CFLAGS) -DSU setup.c
mv setup.o susetup.o
pmain.o: config.h lastlog.h shadow.h
pwage.o: age.c config.h
cp age.c pwage.c
$(CC) -c $(CFLAGS) -DPASSWD pwage.c
rm pwage.c
lmain.o: config.h lastlog.h
smain.o: config.h lastlog.h
setup.o: config.h
utmp.o: config.h
mail.o: config.h
motd.o: config.h
age.o: config.h
log.o: config.h lastlog.h
shell.o: config.h
entry.o: config.h shadow.h
shadow.o: shadow.h
dialup.o: dialup.h
dialchk.o: dialup.h config.h
valid.o: config.h
failure.o: faillog.h config.h
faillog.o: faillog.h config.h
pwent.o: config.h
clean:
-rm -f *.o a.out core npasswd nshadow
clobber: clean
-rm -f su login passwd pwconv pwunconv sulogin faillog *.L
shar: login.sh.1 login.sh.2 login.sh.3
login.sh.1: $(FILES1)
shar $(FILES1) > login.sh.1
login.sh.2: $(FILES2)
shar $(FILES2) > login.sh.2
login.sh.3: $(DOCS)
shar $(DOCS) > login.sh.3
SHAR_EOF
fi
if test -f 'entry.c'
then
echo shar: "will not over-write existing file 'entry.c'"
else
cat << \SHAR_EOF > 'entry.c'
#include <stdio.h>
#include <pwd.h>
#ifndef BSD
#include <string.h>
#else
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include "config.h"
#ifdef SHADOWPWD
#include "shadow.h"
#endif
#ifndef lint
static char _sccsid[] = "@(#)entry.c 2.1 01:23:09 6/20/89";
#endif
struct passwd *fgetpwent ();
char *malloc ();
char *strdup (s)
char *s;
{
char *cp;
if (s == (char *) 0)
return ((char *) 0);
if (! (cp = malloc ((unsigned) strlen (s) + 1)))
return ((char *) 0);
return (strcpy (cp, s));
}
void entry (name, pwent)
char *name;
struct passwd *pwent;
{
FILE *pwd;
struct passwd *passwd;
#ifdef SHADOWPWD
struct spwd *spwd;
char *l64a ();
#endif
char *cp;
if ((pwd = fopen (PWDFILE, "r")) == (FILE *) 0) {
pwent->pw_passwd = (char *) 0;
return;
}
while (passwd = fgetpwent (pwd)) {
if (strcmp (name, passwd->pw_name) == 0)
break;
}
fclose (pwd);
if (passwd == (struct passwd *) 0) {
pwent->pw_name = (char *) 0;
pwent->pw_passwd = (char *) 0;
} else {
pwent->pw_name = strdup (passwd->pw_name);
pwent->pw_uid = passwd->pw_uid;
pwent->pw_gid = passwd->pw_gid;
pwent->pw_comment = (char *) 0;
pwent->pw_gecos = strdup (passwd->pw_gecos);
pwent->pw_dir = strdup (passwd->pw_dir);
pwent->pw_shell = strdup (passwd->pw_shell);
#ifdef SHADOWPWD
setspent ();
if (spwd = getspnam (name)) {
pwent->pw_passwd = strdup (spwd->sp_pwdp);
if (spwd->sp_lstchg != 0) {
pwent->pw_age = (char *) 0;
} else {
pwent->pw_age = malloc (5);
pwent->pw_age[0] = i64c (spwd->sp_max / 7);
pwent->pw_age[1] = i64c (spwd->sp_min / 7);
cp = l64a (spwd->sp_lstchg / 7);
pwent->pw_age[2] = cp[0];
pwent->pw_age[3] = cp[1];
pwent->pw_age[4] = '\0';
}
endspent ();
return;
}
endspent ();
passwd->pw_age = pwent->pw_age = (char *) 0;
#endif
if (passwd->pw_passwd)
pwent->pw_passwd = strdup (passwd->pw_passwd);
else
pwent->pw_passwd = (char *) 0;
if (passwd->pw_age) {
pwent->pw_age = malloc (5); /* longest legal time */
(void) strncpy (pwent->pw_age, passwd->pw_age, 5);
} else
pwent->pw_age = (char *) 0;
}
}
SHAR_EOF
fi
if test -f 'obscure.c'
then
echo shar: "will not over-write existing file 'obscure.c'"
else
cat << \SHAR_EOF > 'obscure.c'
#include <ctype.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[] = "@(#)obscure.c 2.1 01:23:29 6/20/89";
#endif
/*
* Obscure - see if password is obscure enough.
*
* The programmer is encouraged to add as much complexity to this
* routine as desired. Included are some of my favorite ways to
* check passwords.
*/
extern char pass[]; /* the new password */
extern char orig[]; /* the original password */
#ifdef OBSCURE
char mono[32]; /* a monocase version of pass */
#endif
int obscure ()
{
#ifdef OBSCURE
int i;
#endif
if (orig[0] == '\0')
return (1);
if (strlen (pass) < PASSLENGTH) { /* too short */
printf ("Too short. ");
return (0);
}
#ifdef OBSCURE
for (i = 0;pass[i];i++)
mono[i] = tolower (pass[i]);
if (strcmp (pass, orig) == 0) /* the same */
return (0);
if (palindrome ()) /* a palindrome */
return (0);
if (caseshift ()) /* upper/lower case changes only */
return (0);
if (similiar ()) /* jumbled version of original */
return (0);
#endif
return (1);
}
#ifdef OBSCURE
/*
* can't be a palindrome - like `R A D A R' or `M A D A M'
*/
int palindrome ()
{
int i, j;
i = strlen (pass);
for (j = 0;j < i;j++)
if (pass[i - j - 1] != pass[j])
return (0);
printf ("No palindromes. ");
return (1);
}
/*
* may not be a shifted version of original
*/
int caseshift ()
{
int i;
for (i = 0;pass[i] && orig[i];i++) {
if (tolower (pass[i]) == tolower (orig[i]))
continue;
else
return (0);
}
printf ("May not be case-shifted. ");
return (1);
}
/*
* more than half of the characters are different ones.
*/
int similiar ()
{
int i, j;
char *strchr ();
for (i = j = 0;pass[i] && orig[i];i++)
if (strchr (mono, tolower (orig[i])))
j++;
if (i - j > 2)
return (0);
printf ("Too similiar. ");
return (1);
}
#endif
SHAR_EOF
fi
if test -f 'setup.c'
then
echo shar: "will not over-write existing file 'setup.c'"
else
cat << \SHAR_EOF > 'setup.c'
#include <sys/types.h>
#include <pwd.h>
#include <utmp.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[] = "@(#)setup.c 2.1 01:23:45 6/20/89";
#endif
extern char home[];
extern char prog[];
extern char name[];
extern char mail[];
#ifndef PATH
#define PATH ":/bin:/usr/bin"
#endif
#ifndef SUPATH
#define SUPATH ":/bin:/usr/bin:/etc"
#endif
#ifndef MAILDIR
#define MAILDIR "/usr/spool/mail"
#endif
#ifndef TTYPERM
#define TTYPERM 0622
#endif
#ifndef SU
extern struct utmp utent;
#endif
#ifdef QUOTAS
long strtol ();
#ifdef ULIMIT
long ulimit ();
#endif
#endif
void addenv ();
void setup (info)
struct passwd *info;
{
extern int errno;
char logname[30];
#ifndef SU
char tty[30];
#endif
char *cp;
int i;
long l;
#ifndef SU
(void) strcat (strcpy (tty, "/dev/"), utent.ut_line);
if (chown (tty, info->pw_uid, info->pw_gid) ||
chmod (tty, TTYPERM))
perror (tty);
#endif
if (chdir (info->pw_dir) == -1) {
(void) printf ("Unable to change directory to \"%s\"\n", info->pw_dir);
exit (errno);
}
#ifdef QUOTAS
for (cp = info->pw_gecos;cp != (char *) 0;cp = strchr (cp, ',')) {
if (*cp == ',')
cp++;
if (strncmp (cp, "pri=", 4) == 0) {
i = atoi (cp + 4);
if (i >= -20 && i <= 20)
(void) nice (i);
continue;
}
#ifdef ULIMIT
if (strncmp (cp, "ulimit=", 7) == 0) {
l = strtol (cp + 7, (char **) 0, 10);
(void) ulimit (2, l);
continue;
}
#endif
if (strncmp (cp, "umask=", 6) == 0) {
i = strtol (cp + 6, (char **) 0, 8) & 0777;
(void) umask (i);
continue;
}
}
#endif
if (setgid (info->pw_gid) == -1) {
puts ("Bad group id");
exit (errno);
}
#ifndef BSD
if (setuid (info->pw_uid))
#else
if (setreuid (info->pw_uid, info->pw_uid))
#endif
{
puts ("Bad user id");
exit (errno);
}
(void) strcat (strcpy (home, "HOME="), info->pw_dir);
addenv (home);
if (info->pw_shell == (char *) 0)
info->pw_shell = "/bin/sh";
(void) strcat (strcpy (prog, "SHELL="), info->pw_shell);
addenv (prog);
if (info->pw_uid == 0)
addenv (SUPATH);
else
addenv (PATH);
(void) strcat (strcpy (logname, "LOGNAME="), name);
addenv (logname);
(void) strcat (strcat (strcpy (mail, "MAIL="), MAILDIR), name);
addenv (mail);
}
SHAR_EOF
fi
if test -f 'sub.c'
then
echo shar: "will not over-write existing file 'sub.c'"
else
cat << \SHAR_EOF > 'sub.c'
#include <sys/types.h>
#include <pwd.h>
#include <utmp.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[] = "@(#)sub.c 2.1 01:23:58 6/20/89";
#endif
extern struct passwd pwent;
#ifndef SU
extern struct utmp utent;
#endif
void setutmp ();
/*
* I have heard of two different types of behavior with subsystem roots.
* One has you execute login no matter what. The other has you execute
* the command [ if one exists ] after the '*' in the shell name. The
* macro SUBLOGIN says to execute /bin/login [ followed by /etc/login ]
* regardless. Otherwise, pwent.pw_shell is fixed up and that command
* is executed [ by returning to the caller ]. I prefer the latter since
* it doesn't require having a "login" on the new root filesystem.
*/
void subsystem ()
{
char *strdup ();
if (pwent.pw_dir[0] != '/')
exit (1);
if (chdir (pwent.pw_dir) || chroot (pwent.pw_dir)) {
printf ("Can't change to \"%s\"\n", pwent.pw_dir);
exit (1);
}
#ifndef SU
(void) strcpy (utent.ut_line, "<!sublogin>");
setutmp ();
#endif
#ifdef SUBLOGIN
execl ("/bin/login", "login", name, (char *) 0);
execl ("/etc/login", "login", name, (char *) 0);
puts ("No /bin/login or /etc/login on root");
exit (1);
#else
if (! pwent.pw_shell || strlen (pwent.pw_shell) == 1)
pwent.pw_shell = "/bin/sh"; /* default shell */
else
pwent.pw_shell++; /* skip over '*' */
#endif
}
SHAR_EOF
fi
if test -f 'config.h'
then
echo shar: "will not over-write existing file 'config.h'"
else
cat << \SHAR_EOF > 'config.h'
/*
* Configuration file for login.
*
* @(#)config.h 2.1 01:23:03 6/20/89
*/
/*
* Define DIALUP to use dialup password files
*/
#define DIALUP
/*
* Define SHADOWPWD to use shadow [ unreadable ] password file
*/
#define SHADOWPWD
/*
* Define DOUBLESIZE to use 16 character passwords
*/
#define DOUBLESIZE
/*
* Define OBSCURE to include hard password testing code.
*/
#define OBSCURE
/*
* Define PASSLENGTH to be shortest legal password
*/
#define PASSLENGTH 5
/*
* Define NOBLANK if you want all passwords prompted for, including
* empty ones.
#undef NOBLANK
/*
* Define MAXDAYS to be the default maximum number of days a password
* is valid for when converting to shadow passwords. Define MINDAYS
* to be the minimum number of days before a password may be changed.
* See pwconv.c for more details.
*/
#define MAXDAYS 10000
#define MINDAYS 0
/*
* Define NDEBUG for production versions
*/
#define NDEBUG
/*
* Define HZ if login must set HZ value
*/
#define HZ "HZ=50"
/*
* Define TZ if login must set timezone
*
* The first example sets the variable directly. The
* second example names a file which is read to determine
* the proper value. The file consists of a single line
* of the form 'TZ=zone-name'
*/
/* #define TZ "TZ=CST6CDT" */
#define TZ "/etc/tzname"
/*
* Define the default PATH and SUPATH here. PATH is for non-privileged
* users, SUPATH is for root. The first pair are for real trusting
* systems, the second pair are for the paranoid ...
*/
/* #define PATH "PATH=:/bin:/usr/bin" */
/* #define SUPATH "PATH=:/bin:/usr/bin:/etc" */
#define PATH "PATH=/bin:/usr/bin"
#define SUPATH "PATH=/bin:/usr/bin:/etc"
/*
* Define the mailbox directory
*/
#define MAILDIR "/usr/spool/mail/"
/*
* Define AGING if you want the password aging checks made.
*/
#define AGING
/*
* Define MAILCHECK if you want the mailbox checked for new mail
*
* One of two messages are printed - `You have new mail.' or
* `You have mail.'.
*/
#define MAILCHECK
/*
* Define CONSOLE if you want ROOT restricted to a particular terminal.
*
* Use the name of the tty line if you only want a single line, or use
* the name of the file containing the permissible ports if you wish to
* allow root logins on more than one port.
*/
/* #define CONSOLE "console" /* root on /dev/console only */
#define CONSOLE "/etc/consoles" /* check /etc/consoles for a list */
/*
* Define NOLOGINS if you want to be able to deny non-root users logins.
* Logins will not be permitted if this file exists.
*/
#define NOLOGINS "/etc/nologin"
/*
* Define NOUSE if you want to be able to declare accounts which can't
* be logged into.
*/
#define NOUSE "NOUSE"
/*
* Define MOTD if you want the message of the day (/etc/motd) printed
* at login time.
*/
#define MOTD
/*
* Define HUSHLOGIN if you want the code added to avoid printing the
* motd if a file $HOME/.hushlogin exists. This obviously only matters
* if any of MOTD, MAILCHECK or LASTLOG are #define'd.
*/
#define HUSHLOGIN
/*
* Define LASTLOG if you want a record made of logins in /usr/adm/lastlog.
*/
#define LASTLOG
/*
* Define FAILLOG if you want a record make of failed logins in
* /usr/adm/faillog. See faillog.h for more details. See fail(1L)
* for even still more details ...
*/
#define FAILLOG
/*
* Define TTYPERM to be the initial terminal permissions. Defining
* as 0600 will not allow messages, 0622 will.
*/
#define TTYPERM 0600
/*
* Define TTYTYPE to the be name of the port to terminal type
* mapping file. This is used to set the environmental variable
* "TERM" to the correct terminal type.
*/
#define TTYTYPE "/etc/ttytype"
/*
* Define QUOTAS if you want the code added in setup.c to support
* file ulimit and nice [ and umask as well ] setting from the password
* file.
*/
#define QUOTAS
/*
* Define file name for sulog. If SULOG is not defined, there will be
* no logging. This is NOT a good idea ... We also define other file
* names.
*/
#define SULOG "/usr/adm/sulog"
#define PWDFILE "/etc/passwd"
#define OPWDFILE "/etc/-passwd"
#define NPWDFILE "/etc/npasswd"
#define OSHADOW "/etc/-shadow"
#define NSHADOW "/etc/nshadow"
/*
* Define PWDLOCK to be a locking semaphore for updating the password
* file.
*/
#define PWDLOCK "/etc/.pwdlock"
/*
* Wierd stuff follows ...
*
* The following macros exist solely to override stuff ...
* You will probably want to change their values to suit your
* fancy.
*/
#define ERASECHAR '\b'
#define KILLCHAR '\025'
#define UMASK 022
#define ULIMIT (1L<<20) /* Define if your UNIX supports ulimit() */
#define FGETPWENT /* Define if library does not include FGETPWENT */
#define NEED_AL64 /* Define if library does not include a64l() */
SHAR_EOF
fi
if test -f 'pmain.c'
then
echo shar: "will not over-write existing file 'pmain.c'"
else
cat << \SHAR_EOF > 'pmain.c'
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#ifndef BSD
#include <termio.h>
#include <string.h>
#include <memory.h>
#else
#include <sgtty.h>
#include <strings.h>
#define strchr index
#define strrchr rindex
#endif
#include "config.h"
#include "lastlog.h"
#include "shadow.h"
#ifndef PASSLENGTH
#define PASSLENGTH 5
#endif
#ifndef lint
static char _sccsid[] = "@(#)pmain.c 2.1 01:23:35 6/20/89";
#endif
char name[BUFSIZ];
char orig[BUFSIZ];
char pass[BUFSIZ];
char pass2[BUFSIZ];
struct passwd pwent;
#ifndef RETRIES
#define RETRIES 3
#endif
char *l64a ();
char *crypt ();
extern int errno;
long a64l ();
void entry ();
time_t time ();
int
main (argc, argv)
int argc;
char **argv;
{
void die ();
char *cp;
char *getlogin ();
int amroot;
int lockfd = -1;
#ifdef OBSCURE
int force = 0;
#endif
int retries;
#ifdef AGING
long week;
long lastweek;
#endif
long salttime;
struct passwd *pw;
struct passwd *getpwuid ();
struct passwd *sgetpwent ();
FILE *npwd;
#ifdef SHADOWPWD
struct spwd *spwd;
struct spwd tspwd;
#else
FILE *pwd;
char buf[BUFSIZ];
#endif
char tmp[BUFSIZ];
argc--; argv++; /* shift ... */
if (! isatty (0) || ! isatty (1))
exit (1);
die (0); /* save tty modes */
signal (SIGHUP, die); /* exit if SIGHUP */
signal (SIGINT, die); /* exit if SIGINT */
signal (SIGQUIT, die); /* exit if SIGQUIT */
signal (SIGTERM, die); /* exit if SIGTERM */
if (! (pw = getpwuid (getuid ())))
goto failure; /* can't get my name ... */
#ifdef OBSCURE
if (argc > 0 && strcmp (argv[0], "-f") == 0) {
force = 1;
argc--; argv++; /* shift ... */
}
#endif
if (argc > 0)
(void) strcpy (name, argv[0]);
else if (cp = getlogin ()) /* need user name */
(void) strcpy (name, cp);
else /* can't find user name! */
goto failure;
printf ("Changing password for %s\n", name);
amroot = getuid () == 0; /* currently am super user */
#ifdef OBSCURE
if (! amroot)
force = 0;
#endif
if (! amroot && strcmp (name, pw->pw_name) != 0)
goto failure;
entry (name, &pwent); /* get password file entry */
if (! pwent.pw_name) /* no entry for user??? */
goto failure;
if (! amroot) {
if (! password ("Old Password:", orig))
exit (1);
if (! valid (orig, &pwent)) {
puts ("Sorry.");
exit (1);
}
}
#ifdef AGING
if (! amroot && pwent.pw_age) { /* check out the age */
#ifdef SHADOWPWD
(void) time (&week);
week /= (24L * 60L * 60L); /* days since epoch */
if (spwd = getspnam (name)) { /* use entries in shadow */
if (spwd->sp_min > spwd->sp_max) {
puts ("You may not change this password");
exit (1);
}
if (spwd->sp_lstchg + spwd->sp_min > week) {
printf ("Sorry, less than %d days since the last change\n", spwd->sp_min);
exit (1);
}
} else {
#endif /* SHADOWPWD */
(void) time (&week);
week /= (7L * 24L * 60L * 60L); /* weeks since epoch */
lastweek = a64l (&pwent.pw_age[2]);
if (c64i (pwent.pw_age[0]) < c64i (pwent.pw_age[1])) {
puts ("You may not change this password");
exit (1);
}
if (c64i (pwent.pw_age[1]) + lastweek > week) {
printf ("Sorry, less than %d weeks since the last change\n", c64i (pwent.pw_age[1]));
exit (1);
}
#ifdef SHADOWPWD
}
#endif
}
#endif
printf ("Enter new password (minimum of %d characters)\n", PASSLENGTH);
#ifdef OBSCURE
puts ("Please use a combination of upper and lowercase letters and numbers");
#endif
retries = RETRIES;
retry:
if (! password ("New Password:", pass))
exit (1);
#ifndef OBSCURE
if (! obscure ()) {
puts ("Password not changed.");
exit (1);
}
#else
if (! force && ! obscure ()) {
if (retries-- > 0) {
puts ("Please try again.");
goto retry;
} else
goto toomany;
}
#endif
if (! password ("Re-enter new password:", pass2))
exit (1);
if (strcmp (pass, pass2) != 0) {
puts ("They don't match; try again");
if (retries-- > 0)
goto retry;
else
goto toomany;
}
#ifdef AGING
if (pwent.pw_age) {
cp = l64a (week);
pwent.pw_age[2] = cp[0];
pwent.pw_age[3] = cp[1];
pwent.pw_age[4] = '\0';
}
#endif
(void) time (&salttime);
salttime = ((salttime & 07777) ^ ((salttime >> 14) & 07777)) & 07777;
pwent.pw_passwd = tmp;
strcpy (pwent.pw_passwd, crypt (pass, l64a (salttime)));
#ifdef DOUBLESIZE
if (strlen (pass) > 8) {
strcpy (pwent.pw_passwd + 13,
crypt (pass + 8, l64a (salttime)) + 2);
}
#endif
/*
* Now we get to race the bad guy. I don't think he can get us.
*
* Ignore most reasonable signals.
* Maybe we should ignore more? He can't hurt us until the end.
*
* Get a lock file.
*
* Copy first part of password file to new file.
* Illegal lines are copied verbatim.
* File permissions are r--r--r--, owner root, group root.
*
* Output the new entry.
* Only fields in struct passwd are output.
*
* Copy the rest of the file verbatim.
*
* Rename (link, unlink) password file to backup.
* Kill me now and nothing changes or no one gets in.
*
* Rename (link, unlink) temporary file to password file.
* Kill me now and no one gets in or lock is left.
*
* Remove locking file.
*
* That's all folks ...
*/
signal (SIGHUP, SIG_IGN);
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
signal (SIGTERM, SIG_IGN);
umask (0); /* get new files modes correct */
#ifndef NDEBUG
if ((lockfd = open (".pwdlock", O_RDONLY|O_CREAT|O_EXCL), 0444) == -1)
#else
if ((lockfd = open (PWDLOCK, O_RDONLY|O_CREAT|O_EXCL), 0444) == -1)
#endif /* NDEBUG */
{
puts ("Can't get lock");
exit (1);
}
umask (077); /* close security holes to come ... */
#ifdef SHADOWPWD
if (access (NSHADOW, 0) == 0 && unlink (NSHADOW) == -1)
goto failure;
if ((npwd = fopen (NSHADOW, "w")) == (FILE *) 0)
goto failure;
if (chmod (NSHADOW, 0400) || chown (NSHADOW, 0, 0))
goto failure;
setspent ();
while (spwd = getspent ()) {
if (strcmp (spwd->sp_namp, name) == 0)
break;
if (putspent (spwd, npwd))
goto failure;
}
if (spwd == (struct spwd *) 0) { /* didn't find a match */
spwd = &tspwd; /* use a local structure instead */
spwd->sp_namp = pwent.pw_name;
spwd->sp_max = 10000; /* about as big as possible */
spwd->sp_min = 0; /* about as small as possible */
}
spwd->sp_pwdp = pwent.pw_passwd; /* fixup the password */
(void) time (&lastweek); /* get the current time ... */
lastweek /= (24L*60L*60L); /* ... turn it into days. */
spwd->sp_lstchg = lastweek; /* save it as date of last change */
(void) putspent (spwd, npwd); /* add the new entry */
while (spwd = getspent ()) /* finish the other ones off */
(void) putspent (spwd, npwd);
endspent ();
if (ferror (npwd)) {
perror (NSHADOW);
if (unlink (NPWDFILE) || unlink (PWDLOCK))
fputs ("Help!\n", stderr);
exit (1);
}
fflush (npwd);
fclose (npwd);
if (access (OSHADOW, 0) == 0) {
if (unlink (OSHADOW)) {
puts ("Can't remove backup file");
goto unlock;
}
}
if (link (SHADOW, OSHADOW) || unlink (SHADOW)) {
puts ("Can't save backup file");
goto unlock;
}
#ifndef BSD
if (link (NSHADOW, SHADOW) || unlink (NSHADOW))
#else
if (rename (NSHADOW, SHADOW))
#endif
{
(void) unlink (OSHADOW);
puts ("Can't rename new file");
goto unlock;
}
if (unlink (OSHADOW)) {
puts ("Can't remove backup file");
goto unlock;
}
#else /* ! SHADOWPWD */
if (access (NPWDFILE, 0) == 0 && unlink (NPWDFILE) == -1)
goto failure;
#ifndef NDEBUG
if ((npwd = fopen ("npasswd", "w")) == (FILE *) 0)
#else
umask (077); /* no permissions for non-roots */
if ((npwd = fopen (NPWDFILE, "w")) == (FILE *) 0)
#endif /* NDEBUG */
goto failure;
#ifndef NDEBUG
chmod (NPWDFILE, 0444); /* lets have some security here ... */
chown (NPWDFILE, 0, 0); /* ... and keep the bad guy away */
#endif /* NDEBUG */
if ((pwd = fopen (PWDFILE, "r")) == (FILE *) 0)
goto failure;
while (fgets (buf, BUFSIZ, pwd) != (char *) 0) {
if (buf[0] == '#' || ! (pw = sgetpwent (buf))) {
fputs (buf, npwd);
} else if (strcmp (pw->pw_name, pwent.pw_name) != 0)
fputs (buf, npwd);
else
break;
}
(void) fprintf (npwd, "%s:", pw->pw_name);
if (pwent.pw_age)
(void) fprintf (npwd, "%s,%s:", pwent.pw_passwd, pwent.pw_age);
else
(void) fprintf (npwd, "%s:", pwent.pw_passwd);
(void) fprintf (npwd, "%d:%d:%s:%s:%s\n",
pwent.pw_uid, pwent.pw_gid, pwent.pw_gecos, pwent.pw_dir,
pwent.pw_shell ? pwent.pw_shell:"");
while (fgets (buf, BUFSIZ, pwd) != (char *) 0)
fputs (buf, npwd);
if (ferror (npwd)) {
perror (NPWDFILE);
if (unlink (NPWDFILE) || unlink (PWDLOCK))
fputs ("Help!\n", stderr);
exit (1);
}
fflush (npwd);
fclose (npwd);
#ifdef NDEBUG
chmod (NPWDFILE, 0644);
if (unlink (OPWDFILE) == -1) {
if (errno != ENOENT) {
puts ("Can't unlink backup file");
goto unlock;
}
}
if (link (PWDFILE, OPWDFILE) || unlink (PWDFILE)) {
puts ("Can't save backup file");
goto unlock;
}
#ifndef BSD
if (link (NPWDFILE, PWDFILE) || unlink (NPWDFILE))
#else
if (rename (NPWDFILE, PWDFILE))
#endif
{
puts ("Can't rename new file");
goto unlock;
}
#endif /* NDEBUG */
#endif /* SHADOW */
#ifndef NDEBUG
(void) unlink (".pwdlock");
#else
(void) unlink (PWDLOCK);
#endif
exit (0);
/*NOTREACHED*/
failure:
puts ("Permission denied.");
unlock:
if (lockfd >= 0)
(void) unlink (PWDLOCK);
(void) unlink (NPWDFILE);
exit (1);
/*NOTREACHED*/
toomany:
puts ("Too many tries; try again later.");
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 'sulogin.c'
then
echo shar: "will not over-write existing file 'sulogin.c'"
else
cat << \SHAR_EOF > 'sulogin.c'
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include <utmp.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[] = "@(#)sulogin.c 2.1 01:24:02 6/20/89";
#endif
char name[BUFSIZ];
char pass[BUFSIZ];
char home[BUFSIZ];
char prog[BUFSIZ];
char mail[BUFSIZ];
struct passwd pwent;
struct utmp utent;
#ifdef TZ
FILE *tzfile;
char tzbuf[16] = TZ;
#endif
#ifndef MAXENV
#define MAXENV 64
#endif
char *newenvp[MAXENV];
int newenvc = 0;
int maxenv = MAXENV;
extern char **environ;
#ifndef ALARM
#define ALARM 60
#endif
#ifndef RETRIES
#define RETRIES 3
#endif
int main (argc, argv, envp)
int argc;
char **argv;
char **envp;
{
char *getenv ();
char *ttyname ();
char *cp;
if (access (PWDFILE, 0) == -1) { /* must be a password file! */
printf ("No password file\n");
exit (1);
}
#ifndef DEBUG
if (getppid () != 1) /* parent must be INIT */
exit (1);
#endif
if (! isatty (0)) /* must be a terminal */
exit (1);
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
(void) strcpy (name, "root"); /* KLUDGE!!! */
while (1) { /* repeatedly get login/password pairs */
entry (name, &pwent); /* get entry from password file */
if (pwent.pw_name == (char *) 0) {
printf ("No password entry for 'root'\n");
exit (1);
}
/*
* Here we prompt for the root password, or if no password is
* given we just exit.
*/
/* get a password for root */
if (! password ("Type control-d for normal startup,\n(or give root password for system maintenance):", pass))
exit (0);
if (valid (pass, &pwent)) /* check encrypted passwords ... */
break; /* ... encrypted passwords matched */
puts ("Login incorrect");
}
environ = newenvp; /* make new environment active */
puts ("Entering System Maintenance Mode");
/*
* Normally there would be a utmp entry for login to mung on
* to get the tty name, date, etc. from. We don't need all that
* stuff because we won't update the utmp or wtmp files. BUT!,
* we do need the tty name so we can set the permissions and
* ownership.
*/
if (cp = ttyname (0)) { /* found entry in /dev/ */
if (strrchr (cp, '/') != (char *) 0)
strcpy (utent.ut_line, strrchr (cp, '/') + 1);
else
strcpy (utent.ut_line, cp);
}
if (getenv ("IFS")) /* don't export user IFS ... */
addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
setup (&pwent); /* set UID, GID, HOME, etc ... */
shell (pwent.pw_shell); /* exec the shell finally. */
/*NOTREACHED*/
}
SHAR_EOF
fi
if test -f 'dialup.h'
then
echo shar: "will not over-write existing file 'dialup.h'"
else
cat << \SHAR_EOF > 'dialup.h'
/*
* Structure of d_passwd file
*
* The d_passwd file contains the names of login shells which require
* dialup passwords. Each line contains the fully qualified path name
* for the shell, followed by an optional password. Each field is
* separated by a ':'.
*
* Structure of the dialups file
*
* The dialups file contains the names of ports which may be dialup
* lines. Each line consists of the last component of the path
* name. Any leading directory names are removed.
*
* @(#)dialup.h 2.1 01:23:08 6/20/89
*/
struct dialup {
char *du_shell;
char *du_passwd;
};
void setduent ();
void endduent ();
struct dialup *getduent ();
struct dialup *getdushell ();
#define DIALPWD "/etc/d_passwd"
#define DIALUPS "/etc/dialups"
SHAR_EOF
fi
if test -f 'ttytype.c'
then
echo shar: "will not over-write existing file 'ttytype.c'"
else
cat << \SHAR_EOF > 'ttytype.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"
#ifdef TTYTYPE
#ifndef lint
static char _sccsid[] = "@(#)ttytype.c 2.1 01:24:04 6/20/89";
#endif
/*
* ttytype - set ttytype from port to terminal type mapping database
*/
void ttytype (line)
char *line;
{
FILE *fp;
char buf[BUFSIZ];
char termvar[BUFSIZ];
char *cp;
char *type;
char *port;
char *getenv ();
if (getenv ("TERM"))
return;
if (! (fp = fopen (TTYTYPE, "r")))
return;
while (fgets (buf, BUFSIZ, fp)) {
if (buf[0] == '#')
continue;
if (cp = strchr (buf, '\n'))
*cp = '\0';
if ((type = strtok (buf, " \t"))
&& (port = strtok ((char *) 0, " \t"))) {
if (strcmp (line, port) == 0)
break;
}
}
if (! feof (fp) && ! ferror (fp)) {
strcat (strcpy (termvar, "TERM="), type);
addenv (termvar);
}
fclose (fp);
}
#endif
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