Shadow Password Suite, version 2 (part 1 of 5)
John F Haugh II
jfh at rpp386.cactus.org
Thu Dec 13 05:45:59 AEST 1990
I've started getting a steady stream of requests for this code and thought
it might be nice to post it rather than sending out half a dozen copies
every week.
This is the "old" version of the shadow login code. There is a new version,
but it isn't completed yet. If you have been collecting parts of the "new"
version, beware - this isn't completely compatible with it.
There are bugs in the code (as always ...) and I will send out fixes if
you send in bug reports. The code worked just fine here until I started
working on the new release. The only problem with fixing this version is
going to be making the branch deltas in SCCS. Not exactly a big deal,
but don't expect enthusiasm over minor bugs (like, /etc/nologin and how
it is handled ...) Anyone who has maintained multiple versions of software
using SCCS will attest to the Joy and Satisfaction of doing so.
There are manpages in various places for most of the features. I will
gladly accept any new ones you write and even give out credit as appropriate.
This code has the old copyright that everyone objected to all over it.
If you read the README file you might begin to understand the whole mess
a little better. The new code has the new copyright. You will be
relieved to see it I suppose.
--
#! /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
# newgrp.c
# Makefile
# config.h
# pwunconv.c
# obscure.c
# age.c
# sub.c
# login.c
# shell.c
# lastlog.h
# This archive created: Wed Dec 12 12:36:30 1990
# By: John F Haugh II (River Parishes Programming, Austin TX)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(12258 characters)'
if test -f 'README'
then
echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XThis is the explanatory document for John F. Haugh II's login replacement.
XThis document is for version 2, last modified on 11/26/90.
X
XThis software is copyright 1988, 1989, 1990, John F. Haugh II. All rights
Xreserved. Use, duplication and disclosure is permitted according to the
Xguidelines listed below.
X
XThis software is being provided as a freely redistributable login clone.
XYou may distribute this software provided you do not charge for other than
Xtransmission costs. You are free to copy this software provided you
Xdo not restrict the rights of the recipients to further copy this software.
X
XTHIS SOFTWARE IS BEING DISTRIBUTED AS-IS. THE AUTHORS DISCLAIM ALL
XLIABILITY FOR ANY CONSEQUENCES OF USE. THE USER IS SOLELY RESPONSIBLE
XFOR THE MAINTENANCE OF THIS SOFTWARE PACKAGE. THE AUTHORS ARE UNDER NO
XOBLIGATION TO PROVIDE MODIFICATIONS OR IMPROVEMENTS. THE USER IS
XENCOURAGE TO TAKE ANY AND ALL STEPS NEEDED TO PROTECT AGAINST ACCIDENTAL
XLOSE OF INFORMATION OR MACHINE RESOURCES.
X
XSpecial thanks are due to Chip Rosenthal for his fine testing efforts;
Xto Steve Simmons for his work in porting this code to BSD; and to Bill
XKennedy for his contributions of LaserJet printer time and energies.
X
XBegin by reading and editing the config.h file. All options are selected
Xby using #define's. A brief description for each available option appears
Xbelow. You may want to print this file out as it is LONG and you will
Xneed to refer to it while editting config.h. You will also have to edit
Xthe Makefile. The possible differences are documented there. Pay close
Xattention to the install: rule. DO NOT MAIL ME DIFFERENCES FOR VARIOUS
XINSTALLATION PROBLEMS. If you must share your experiences, do so on the
Xnet. Login now runs on about 30 different varieties of UNIX that I have
Xbeen made aware of.
X
XNote that there are MANY options. As distributed most options are turned
Xon, which produces a really nice package. This is the system as used on
Xthe authors' machines.
X
XDialup Password Files -
X This option permits individual ports to have an additional
X password prompted for on a by-shell basis. /etc/dialups
X contains a list of dialup ports, d_passwd contains the
X password for each shell requiring a dialup password.
X
X Select this option by defining the DIALUP macro.
X
XPort Access Times File -
X This option permits individual ports to have restrictions
X based on user name and time of day and week.
X
X Select this option by defining the PORTTIME macro.
X
XShadow [ unreadable ] Password Files -
X This option utilizes an alternate, non-readable file to
X contain the actual encrypted passwords. This is presumed
X to increase system security by increasing the difficulty
X with which system crackers obtain encrypted passwords.
X
X Select this option by defining the SHADOWPWD macro.
X
XDBM Password Files -
X This option utilizes the DBM database access routines to
X increase the performance of user name and ID lookups in the
X password file.
X
X Select this option by defining both the DBM and GETPWENT
X macros. The FGETPWENT macro must also be defined or the
X fgetpwent() library routine must be present.
X
XDouble Length Passwords -
X This option extends the maximum length of a user password
X to 16 characters from eight.
X
X Select this option by defining the DOUBLESIZE macro.
X Credit for this option is due Jonathan Bayer.
X
XObscure Password Testing -
X This option includes code to test user passwords for
X complexity. The programmer is encouraged to edit the
X file obscure.c to add additional methods for detecting
X simplistic passwords.
X
X Select this option by defining the OBSCURE macro.
X
X Additionally, the PASSLENGTH macro must be defined to
X control the minimum length for a legal password.
X
XMandatory Password Prompting -
X This option requires all passwords, including null ones,
X to be prompted for. Traditionally an account with a
X password field of '::' does not require prompting for.
X This option modifies this behavior to require even
X null passwords be prompted for.
X
X Select this option by defining the NOBLANK macro.
X
XPassword Aging Defaults -
X You may select the default number of days during which a
X password is valid. The pwconv command adds aging
X information to accounts which do not include it already.
X
X The MINDAYS macro must be defined to be the minimum
X number of days which must pass before a password may be
X changed. The MAXDAYS macro must be defined to be the
X maximum number of days which a password will remain
X valid during.
X
X The WARNDAYS macro controls how many days warning a user
X is given that their password is about to expire. The
X default is 10.
X
XHZ Environmental Variable -
X This option pre-defines the HZ environmental variable.
X Certain systems require this variable be defined for
X system time reporting functions to work properly.
X
X Select this option by defining the HZ macro to have
X the desired environmental variable value.
X
XTZ Environmental Variable -
X This option pre-defines the TZ environmental variable.
X This provides a default timezone variable for use by
X various utilities.
X
X Select this option by defining the TZ macro to have
X the desired environmental variable value, or the name
X of the file containing the desired value.
X
XPassword Aging -
X This option includes code to perform password aging.
X Password aging is presumed to increase system security
X by forcing users to change passwords on a regular
X basis. The resolution on password age is in weeks for
X non-shadow password systems and in days otherwise.
X
X Select this option by defining the AGING macro.
X
XMailbox Checking -
X This option includes code to check the status of the
X user's mailbox. One of three messages are produced
X depending on the status of the user's mailbox.
X
X Select this option by defining the MAILCHECK macro.
X
XConsole Restricted Root Logins -
X This option restricts the port which root may legally
X login on. This option presumably increases system
X security by preventing outside attacks against the root
X account.
X
X Select this option by defining the CONSOLE macro to
X have the desired port name. If this file is a regular
X file, it is considered to contain a list of legal port
X names, one per line. Note that the port names DO NOT
X begin with "/dev/" and that a file name would have to
X be fully qualified. See config.h for a pair of
X examples.
X
XRestricted User Logins -
X This option permits you to specify a file which disables
X user logins. This options permits you to keep normal
X users off of the system while performing maintenance
X functions.
X
X Select this option by defining NOLOGINS to be the name
X of the file to use.
X
XRestricted Use Accounts -
X This option permits certain accounts to be used for
X identification purposes only. This options associates
X login ID's with UID's, such as for disk space accounting
X or anonymous FTP accounts. Passwords for these accounts
X may only be changed by root.
X
X Select this option by defining NOUSE to be the string
X to include in the password file in place of the user's
X shell.
X
XMessage of the Day Printing -
X This option causes the message of the day to be
X printed at login time.
X
X Select this option by defining the MOTD macro.
X
X If you wish this feature to be overriden on a per-user
X basis, define the macro HUSHLOGIN and users may then
X turn off the /etc/motd message by creating a file
X '.hushlogin' in their home directories.
X
XLast Login Time Logging -
X This option causes a record to be made of successful
X logins in /usr/adm/lastlog. The format of the
X structure is defined in lastlog.h.
X
X Select this option by defining the LASTLOG macro.
X
X You will need to determine if you system already has
X a lastlog.h file and use that file if present.
X
XFailed Login Logging -
X This option causes a record to be kept of the most
X recent login failure by date and port. A cummulative
X count of failures is maintained and compared against
X an allowable limit.
X
X Select this option by defining the FAILLOG macro.
X
X An additional option is provided which will create
X utmp-like entries for each failed login. Because of
X security concerns, only valid account names will be
X logged.
X
X Select this option by defining the FTMP macro to be
X the name of a utmp-like file. You may control the
X recording of unknown login names by defining the
X UNKNOWNS macro. This prevents possible passwords from
X being entered into the FTMP file.
X
X See the file faillog.h and config.h for more details.
X
XTerminal Permissions -
X This option allows the terminal modes to be set at
X login time. This is particularly useful to disable
X messages on user's terminals.
X
X Select this option by defining the TTYPERM macro as
X having the desired mode.
X
XTerminal Type Setup -
X This option allows the terminal type to be set at
X login time. The environmental variable TERM will be
X set from the specified terminal to port mapping
X file.
X
X Select this option by defining the TTYTYPE macro as
X having the value of the name of the type to port
X mapping file. Credit for this option is due Chip
X Rosenthal.
X
XFile Size Setting -
X This option includes code to set the user's ulimit
X at login time. Additional code to set the umask and
X nice value is also included.
X
X Select this option by defining the QUOTAS macro.
X
XSwitch-User Logging -
X This option causes su(1) to log attempts to switch
X users. Su(1) will log all attempt, giving the old
X and new user ID's, tty port, and time. It also
X indicates if the attempt was successful.
X
X Select this option by defining the SULOG macro to
X have the value of the name of the file you want
X attempts logged to.
X
XConfigurable Editing Keys -
X This options allows the erase and kill characters to
X be selected. A default value is provided. By default
X ERASE will be ^H and KILL will be ^U.
X
X Select this option by defining the ERASECHAR macro
X to be the desired erase character and the KILLCHAR
X macro to be the desired KILL character.
X
XDefault ulimit and umask Values -
X This option allows you to select the default values
X for ulimit and umask, allowing you to avoid
X regenerating your system kernel. These values may be
X overriden with appropriate entries in the GECOS field.
X
X Select the default ulimit by defining the ULIMIT
X macro, and the default umask by defining the UMASK
X macro.
X
X Warning: These values will not apply to processes
X executed by /etc/cron or any of their children.
X
XBSD Notes: Steve Simmons scs at iti.org
X
XThe full port of the shadow package to BSD is not complete; but some
Xof the issues have been worked out. These notes describe the current
Xstate of things:
X
XIn order to make use of password aging under BSD, minor changes to
X/usr/include/pwd.h and getpwent() are needed. These changes are to
Xkeep the password age from messing up the encrypted password when not
Xusing shadow passwords, and involve placing a new field in the password
Xdata structure. To use this, you should apply the following two patches:
X pwd.h.patch
X getpwent.c.patch
Xto the BSD /usr/include/pwd.h and /usr/src/lib/libc/gen/getpwent.c,
Xrespectively. After applying the patches, rebuild your standard C
Xlibrary with the new getpwent. Programs which use the old getpwent
Xwill fail on password checking if they do a strcmp rather than a strncmp.
X[ I do not seem to have these two patches. I have provided an entire
Xgetpwent collection of code which may be useful instead. -jfh ]
X
XThese changes are based on BSD4.3, not Tahoe
X
XToDo BSD:
X
XI'm working on this in my copious spare time (hah!); any help would
Xbe appreciated. If you decide to help, do these independantly rather
Xthan rework BSD code! Keep it redistributable!
X
XNo dbm functions have been put in place. Dbm functionality is needed
Xfor both /etc/password and /etc/shadow management. [ It is now possible
Xto create /etc/passwd.dir and /etc/passwd.pag using the new mkpasswd
Xcommand. getpwuid and getpwnam both use these files. Also, the
Xcommands chfn, chsh, and chage all update the DBM files. -jfh ]
X
XThe BSD GECOS field gets used for lots more stuff than the USG. At a
Xminimum this functionality should be duplicated under BSD; better is to put
Xit into USG as well; still better would be to make the chfn command for
Xboth systems; best would be site-configurable data to be put into GECOS/chfn.
X[ this is now possible using chfn and the -o option. - jfh ]
SHAR_EOF
if test 12258 -ne "`wc -c < 'README'`"
then
echo shar: "error transmitting 'README'" '(should have been 12258 characters)'
fi
fi
echo shar: "extracting 'newgrp.c'" '(8415 characters)'
if test -f 'newgrp.c'
then
echo shar: "will not over-write existing file 'newgrp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newgrp.c'
X/*
X * Copyright 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 <sys/types.h>
X#include <string.h>
X#include <stdio.h>
X#include <grp.h>
X#include <pwd.h>
X#include <termio.h>
X#ifdef SYS3
X#include <sys/ioctl.h>
X#endif
X#include "config.h"
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)newgrp.c 1.2 14:01:27 7/22/90";
X#endif
X
X#ifdef NGROUPS
Xint ngroups;
Xgid_t groups[NGROUPS];
X#endif
X
Xstruct passwd *pwd;
Xstruct passwd *getpwuid();
Xstruct passwd *getpwnam();
X
X#ifdef SHADOWPWD
X#include "shadow.h"
Xstruct spwd *spwd;
Xstruct spwd *getspnam();
X#endif
Xstruct group *grp;
Xstruct group *getgrgid();
Xstruct group *getgrnam();
X
Xchar *getlogin();
Xchar *crypt();
X
Xchar *name;
Xchar *group;
Xint gid;
X
Xchar *myname;
Xchar shell[BUFSIZ];
Xchar base[BUFSIZ];
Xchar passwd[BUFSIZ];
Xchar *cpasswd;
Xchar *salt;
X
X/*
X * usage - print command usage message
X */
X
Xusage ()
X{
X fprintf (stderr, "usage: newgrp [ - ] [ group ]\n");
X exit (1);
X}
X
X/*
X * newgrp - change the invokers current real and effective group id
X */
X
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X int initflag = 0;
X int needspasswd = 0;
X int i;
X char *cp;
X#ifdef DOUBLESIZE
X int longpass;
X#endif
X
X /*
X * let me parse the command line first. the only legal flag
X * is a "-", which indicates the shell is to perform the same
X * initialization it does at login time. the remaining
X * optional argument is the name of a new group. if it isn't
X * present i just use the login group id of this user.
X */
X
X if (argc > 1 && strcmp (argv[1], "-") == 0) {
X initflag = 1;
X argc--; argv++;
X }
X if (argc > 2)
X usage ();
X
X#ifdef NGROUPS
X
X /*
X * get the current users groupset. the new group will be
X * added to the concurrent groupset if there is room, otherwise
X * you get a nasty message but at least your real and effective
X * group id's are set.
X */
X
X ngroups = getgroups (groups);
X#endif
X
X /*
X * save my name for error messages and save my real gid incase
X * of errors. if there is an error i have to exec a new login
X * shell for the user since her old shell won't have fork'd to
X * create the process.
X */
X
X myname = argv[0];
X gid = getgid ();
X
X /*
X * now i get to determine my current name. i do this to validate
X * my access to the requested group. the validation works like
X * this -
X * 1) get the name associated with my current user id
X * 2) get my login name, as told by getlogin().
X * 3) if they match, my name is the login name
X * 4) if they don't match, my name is the name in the
X * password file.
X *
X * this isn't perfect, but it works more often then not.
X */
X
X pwd = getpwuid (getuid ());
X
X if (! (name = getlogin ()) || strcmp (name, pwd->pw_name) != 0)
X name = pwd->pw_name;
X
X if (! (pwd = getpwnam (name))) {
X fprintf (stderr, "unknown user: %s\n", name);
X exit (1);
X }
X
X /*
X * now we determine the name of the new group which she wishes
X * to become a member of. the password file entry for her
X * current user id has been gotten. if there is no optional
X * group argument she will have her real and effective group id
X * set to the value from her password file entry. otherwise
X * we validate her access to the specified group.
X */
X
X if (argv[1] != (char *) 0) {
X
X /*
X * start by getting the entry for the requested group.
X */
X
X if (! (grp = getgrnam (group = argv[1]))) {
X fprintf (stderr, "unknown group: %s\n", group);
X goto failure;
X }
X
X /*
X * see if she is a member of this group.
X */
X
X for (i = 0;grp->gr_mem[i];i++)
X if (strcmp (name, grp->gr_mem[i]) == 0)
X break;
X
X /*
X * if she isn't a member, she needs to provide the
X * group password. if there is no group password, she
X * will be denied access anyway.
X */
X
X if (grp->gr_mem[i] == (char *) 0)
X needspasswd = 1;
X#ifdef SHADOWPWD
X
X /*
X * if she does not have either a shadowed password,
X * or a regular password, and the group has a password,
X * she needs to give the group password.
X */
X
X if (spwd = getspnam (name)) {
X if (spwd->sp_pwdp[0] == '\0' && grp->gr_passwd[0])
X needspasswd = 1;
X } else {
X if (pwd->pw_passwd[0] == '\0' && grp->gr_passwd[0])
X needspasswd = 1;
X }
X#else
X
X /*
X * if she does not have a regular password she will have
X * to give the group password, if one exists.
X */
X
X if (pwd->pw_passwd[0] == '\0' && grp->gr_passwd[0])
X needspasswd = 1;
X#endif
X } else {
X
X /*
X * get the group file entry for her login group id.
X * the entry must exist, simply to be annoying.
X */
X
X if (! (grp = getgrgid (pwd->pw_gid))) {
X fprintf (stderr, "unknown gid: %d\n", pwd->pw_gid);
X goto failure;
X }
X }
X
X /*
X * now i see about letting her into the group she requested.
X * if she is the root user, i'll let her in without having to
X * prompt for the password. otherwise i ask for a password
X * if she flunked one of the tests above. note that she
X * won't have to provide the password to her login group even
X * if she isn't listed as a member.
X */
X
X if (getuid () != 0 && needspasswd) {
X if (grp->gr_passwd[0]) {
X
X /*
X * get the password from her, and set the salt for
X * the decryption from the group file.
X */
X
X password ("Password:", passwd);
X salt = grp->gr_passwd;
X } else {
X
X /*
X * there is no password, print out "Sorry" and give up
X */
X
X fputs ("Sorry\n", stderr);
X goto failure;
X }
X
X /*
X * encrypt the key she gave us using the salt from
X * the password in the group file. the result of
X * this encryption must match the previously
X * encrypted value in the file.
X *
X * each chunk of encrypted string is 11 characters
X * long, plus 2 characters for the salt. each
X * group of 11 characters represents 8 characters
X * of cleartext.
X */
X
X cpasswd = crypt (passwd, salt);
X
X if (strncmp (cpasswd, grp->gr_passwd, 13) != 0) {
X fputs ("Sorry\n", stderr);
X goto failure;
X }
X#ifdef DOUBLESIZE
X if (strlen (grp->gr_passwd) > 13) {
X cpasswd = crypt (passwd + 8, salt);
X
X if (strcmp (cpasswd + 2, grp->gr_passwd + 13) != 0) {
X fputs ("Sorry\n", stderr);
X goto failure;
X }
X }
X#endif
X }
X
X /*
X * all successful validations pass through this point. the
X * group id will be set, and the group added to the concurrent
X * groupset.
X */
X
X gid = grp->gr_gid;
X#ifdef NGROUPS
X
X /*
X * i am going to try to add her new group id to her concurrent
X * group set. if the group id is already present i'll just
X * skip this part. if the group doesn't fit, i'll complain
X * loudly and skip this part ...
X */
X
X for (i = 0;i < ngroups;i++) {
X if (gid == groups[i])
X break;
X }
X if (i == ngroups) {
X if (ngroups == NGROUPS) {
X fprintf (stderr, "too many groups\n");
X } else {
X groups[ngroups++] = gid;
X if (setgroups (ngroups, groups))
X perror (myname);
X }
X }
X#endif
X
X /*
X * this is where all failures land. the group id will not
X * have been set, so the setgid() below will set me to the
X * original group id i had when i was invoked.
X */
X
Xfailure:
X
X /*
X * i set her group id either to the value she requested, or
X * to the original value. i have to go back to the original
X * be she no longer has a shell running.
X */
X
X if (setgid (gid))
X perror ("setgid");
X
X if (setuid (getuid ()))
X perror ("setuid");
X
X /*
X * i have to get the pathname of her login shell. as a favor
X * i'll try her environment for a $SHELL value first, and
X * then try the password file entry.
X */
X
X if ((cp = getenv ("SHELL")) && ! initflag)
X strncpy (shell, cp, sizeof shell);
X else if (pwd->pw_shell && pwd->pw_shell[0])
X strncpy (shell, pwd->pw_shell, sizeof shell);
X else
X strcpy (shell, "/bin/sh");
X
X /*
X * now i try to find the basename of the login shell. this
X * will become argv[0] of the spawned command.
X */
X
X if (cp = strrchr (shell, '/'))
X cp++;
X else
X cp = shell;
X
X /*
X * to have the shell perform login processing i will set the
X * first character in the first argument to a "-".
X */
X
X if (initflag)
X strcat (strcpy (base, "-"), cp);
X else
X strcpy (base, cp);
X
X#ifdef SHADOWPWD
X endspent ();
X#endif
X endpwent ();
X endgrent ();
X
X /*
X * switch back to her home directory if i am doing login
X * initialization.
X */
X
X if (initflag)
X chdir (pwd->pw_dir);
X
X /*
X * exec the login shell and report and error if the exec
X * fails. not much i can do after that ...
X */
X
X execl (shell, base, (char *) 0);
X perror (shell);
X exit (1);
X}
SHAR_EOF
if test 8415 -ne "`wc -c < 'newgrp.c'`"
then
echo shar: "error transmitting 'newgrp.c'" '(should have been 8415 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(8384 characters)'
if test -f 'Makefile'
then
echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
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# @(#)Makefile 2.16 08:41:16 - Shadow password system
X#
X# @(#)Makefile 2.16 08:41:16 11/8/90
X#
XSHELL = /bin/sh
X
X#
X# Set this flag to decide what level of code "get" returns.
X# The base USENET release was release 1. It is no longer supported.
X# The unreleased version with the utilities added is release 2.
XRELEASE = 2
XGFLAGS = -t -r$(RELEASE)
X
X# Define the directory login is copied to. BE VERY CAREFUL!!!
X# LOGINDIR = /bin
XLOGINDIR = /etc
X
X# Pick your favorite C compiler and tags command
XCC = cc
XTAGS = ctags
X
X# OS. Currently only BSD and USG are defined. If you don't use BSD,
X# USG (System V) is assumed.
X# OS = -DBSD
X
X# Do you have to do ranlib? Sorry to hear that ...
XRANLIB = ranlib
X# RANLIB = echo
X
X# Flags for SCO Xenix/386
XCFLAGS = -O -M3 -g $(PWDEF) $(AL64DEF) $(OS)
XLIBS = -lcrypt -ldbm
XLDFLAGS = -M3 -g
XLTFLAGS =
X# This should be Slibsec.a for small model, or Llibsec.a for
X# large model or whatever. MUST AGREE WITH CFLAGS!!!
XLIBSEC = Slibsec.a
X
X# Flags for normal machines
X# CFLAGS = -O -g $(PWDEF) $(AL64DEF) $(OS)
X# LIBS =
X# LDFLAGS = -g
X# LIBSEC = libsec.a
X
XLOBJS = lmain.o login.o env.o password.o entry.o valid.o setup.o shell.o age.o \
X pwent.o utmp.o sub.o mail.o motd.o log.o shadow.o dialup.o dialchk.o \
X ttytype.o failure.o port.o pwpack.o
X
XLSRCS = lmain.c login.c env.c password.c entry.c valid.c setup.c shell.c age.c \
X pwent.c utmp.c sub.c mail.c motd.c log.c shadow.c dialup.c dialchk.c \
X ttytype.c failure.c port.c pwpack.c
X
XSOBJS = smain.o env.o password.o entry.o suvalid.o susetup.o sushell.o \
X pwent.o susub.o mail.o motd.o sulog.o shadow.o suage.o pwpack.o
X
XSSRCS = smain.c env.c password.c entry.c valid.c setup.c shell.c \
X pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c
X
XPOBJS = pmain.o password.o entry.o valid.o pwage.o pwent.o obscure.o shadow.o \
X pwpack.o
X
XPSRCS = pmain.c password.c entry.c valid.c age.c pwent.c obscure.c shadow.c \
X pwpack.c
X
XGPSRCS = gpmain.c password.c grent.c
X
XGPOBJS = gpmain.o password.o grent.o
X
XPWOBJS = pwconv.o pwent.o shadow.o pwage.o pwpack.o
X
XPWSRCS = pwconv.c pwent.c shadow.c age.c pwpack.c
X
XPWUNOBJS = pwunconv.o pwent.o shadow.o pwage.o pwpack.o
X
XPWUNSRCS = pwunconv.c pwent.c shadow.c age.c pwpack.c
X
XSULOGOBJS = sulogin.o entry.o env.o password.o pwage.o pwent.o setup.o \
X shadow.o shell.o valid.o pwpack.o
X
XSULOGSRCS = sulogin.c entry.c env.c password.c age.c pwent.c setup.c \
X shadow.c shell.c valid.c pwpack.c
X
XDBOBJS = mkpasswd.o pwent.o pwpack.o
X
XDBSRCS = mkpasswd.c pwent.c pwpack.c
X
XNGSRCS = newgrp.c shadow.c password.c
X
XNGOBJS = newgrp.o shadow.o password.o
X
XCHFNSRCS = chfn.c pwent.c pwpack.c
X
XCHFNOBJS = chfn.o pwent.o pwpack.o
X
XCHSHSRCS = chsh.c pwent.c pwpack.c
X
XCHSHOBJS = chsh.o pwent.o pwpack.o
X
XCHAGEOBJS = chage.o pwent.o pwpack.o pwage.o shadow.o
X
XCHAGESRCS = chage.c pwent.c pwpack.c age.c shadow.c
X
XALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \
X motd.c obscure.c password.c pmain.c pwconv.c pwent.c pwunconv.c \
X setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \
X utmp.c valid.c port.c newgrp.c gpmain.c grent.c mkpasswd.c pwpack.c \
X chfn.c chsh.c chage.c
X
XFILES1 = README newgrp.c Makefile config.h pwunconv.c obscure.c age.c \
X sub.c login.c shell.c lastlog.h
X
XFILES2 = pmain.c port.c lmain.c mkpasswd.c sulogin.c pwpack.c dialup.c \
X sulog.c password.c env.c mail.c dialchk.c
X
XFILES3 = chfn.c chsh.c smain.c faillog.c pwconv.c failure.c utmp.c shadow.c \
X log.c shadow.h faillog.h
X
XFILES4 = gpmain.c chage.c pwent.c valid.c setup.c entry.c ttytype.c port.h \
X grent.c motd.c dialup.h
X
XMAN_1 = chage.1 chfn.1 chsh.1 login.1 passwd.1 su.1
XMAN_3 = shadow.3
XMAN_4 = faillog.4 passwd.4 porttime.4 shadow.4
XMAN_8 = faillog.8 pwconv.8 pwunconv.8 sulogin.8
X
XDOCS = $(MAN_1) $(MAN_3) $(MAN_4) $(MAN_8)
X
XBINS = su login pwconv pwunconv passwd sulogin faillog newgrp gpasswd \
X mkpasswd chfn chsh chage
X
Xall: $(BINS) $(DOCS)
X
Xlibsec: shadow.o
X ar rv $(LIBSEC) shadow.o
X $(RANLIB) $(LIBSEC)
X
Xinstall: all
X strip $(BINS)
X cp login $(LOGINDIR)/login
X cp mkpasswd pwconv pwunconv sulogin /etc
X cp su passwd gpasswd faillog newgrp chfn chsh /bin
X cp shadow.h /usr/include
X chown root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
X /bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd
X chgrp root $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \
X /bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd
X chown bin /bin/faillog /usr/include/shadow.h
X chgrp bin /bin/faillog /usr/include/shadow.h
X chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin /etc/mkpasswd
X chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd /bin/gpasswd \
X /bin/newgrp /bin/chfn
X chmod 711 /bin/faillog
X chmod 444 /usr/include/shadow.h
X
Xlint: su.L login.L pwconv.L pwunconv.L passwd.L sulogin.L faillog.L \
X newgrp.L gpasswd.L mkpasswd.L chfn.L chsh.L chage.L
X
Xtags: $(ALLSRCS)
X $(TAGS) $(ALLSRCS)
X
XREADME: s.README
X get -t -r$(RELEASE) s.README
X
X$(DOCS):
X get -t -r$(RELEASE) s.$@
X
Xlogin: $(LOBJS)
X $(CC) -o login $(LDFLAGS) $(LOBJS) $(LIBS)
X
Xlogin.L: $(LSRCS)
X lint $(LSRCS) > login.L
X
Xsu: $(SOBJS)
X $(CC) -o su $(LDFLAGS) $(SOBJS) $(LIBS)
X
Xsu.L: $(SSRCS)
X lint -DSU $(SSRCS) > su.L
X
Xpasswd: $(POBJS)
X $(CC) -o passwd $(LDFLAGS) $(POBJS) $(LIBS)
X
Xpasswd.L: $(PSRCS)
X lint -DPASSWD $(PSRCS) > passwd.L
X
Xgpasswd: $(GPOBJS)
X $(CC) -o gpasswd $(LDFLAGS) $(GPOBJS) $(LIBS)
X
Xgpasswd.L: $(GPSRCS)
X lint $(GPSRCS) > gpasswd.L
X
Xpwconv: $(PWOBJS)
X $(CC) -o pwconv $(LDFLAGS) $(PWOBJS) $(LIBS)
X
Xpwconv.L: $(PWSRCS)
X lint -DPASSWD $(PWSRCS) > pwconv.L
X
Xpwunconv: $(PWUNOBJS)
X $(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) $(LIBS)
X
Xpwunconv.L: $(PWUNSRCS)
X lint -DPASSWD $(PWUNSRCS) > pwunconv.L
X
Xsulogin: $(SULOGOBJS)
X $(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) $(LIBS)
X
Xsulogin.L: $(SULOGSRCS)
X lint $(SULOGSRCS) > sulogin.L
X
Xfaillog: faillog.o
X $(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS)
X
Xfaillog.L: faillog.c faillog.h config.h
X lint faillog.c > faillog.L
X
Xmkpasswd: $(DBOBJS)
X $(CC) -o mkpasswd $(LDFLAGS) $(DBOBJS) $(LIBS)
X
Xmkpasswd.L: $(DBSRCS)
X lint $(DBSRCS) > mkpasswd.L
X
Xnewgrp: $(NGOBJS)
X $(CC) -o newgrp $(LDFLAGS) $(NGOBJS) $(LIBS)
X
Xnewgrp.L: $(NGSRCS)
X lint $(NGSRCS) > newgrp.L
X
Xchfn: $(CHFNOBJS)
X $(CC) -o chfn $(LDFLAGS) $(CHFNOBJS) $(LIBS)
X
Xchfn.L: $(CHFNSRCS)
X lint $(CHFNSRCS) > chfn.L
X
Xchsh: $(CHSHOBJS)
X $(CC) -o chsh $(LDFLAGS) $(CHSHOBJS) $(LIBS)
X
Xchsh.L: $(CHSHSRCS)
X lint $(CHSHSRCS) > chsh.L
X
Xchage: $(CHAGEOBJS)
X $(CC) -o chage $(LDFLAGS) $(CHAGEOBJS) $(LIBS)
X
Xchage.L: $(CHAGESRCS)
X lint -DPASSWD $(CHAGESRCS) > chage.L
X
Xsushell.c: shell.c
X cp shell.c sushell.c
X
Xsushell.o: config.h sushell.c
X $(CC) -c $(CFLAGS) -DSU sushell.c
X
Xsusub.c: sub.c
X cp sub.c susub.c
X
Xsusub.o: config.h susub.c
X $(CC) -c $(CFLAGS) -DSU susub.c
X
Xsulog.o: config.h
X
Xsusetup.c: setup.c
X cp setup.c susetup.c
X
Xsusetup.o: config.h setup.c
X $(CC) -c $(CFLAGS) -DSU susetup.c
X
Xsuvalid.c: valid.c
X cp valid.c suvalid.c
X
Xsuvalid.o: config.h valid.c
X $(CC) -c $(CFLAGS) -DSU suvalid.c
X
Xpmain.o: config.h lastlog.h shadow.h
X
Xpwage.o: age.c config.h
X cp age.c pwage.c
X $(CC) -c $(CFLAGS) -DPASSWD pwage.c
X rm pwage.c
X
Xsuage.o: age.c config.h
X cp age.c suage.c
X $(CC) -c $(CFLAGS) -DSU suage.c
X rm suage.c
X
Xlmain.o: config.h lastlog.h faillog.h
X
Xsmain.o: config.h lastlog.h
X
Xsetup.o: config.h
X
Xutmp.o: config.h
X
Xmail.o: config.h
X
Xmotd.o: config.h
X
Xage.o: config.h
X
Xlog.o: config.h lastlog.h
X
Xshell.o: config.h
X
Xentry.o: config.h shadow.h
X
Xshadow.o: shadow.h
X
Xdialup.o: dialup.h
X
Xdialchk.o: dialup.h config.h
X
Xvalid.o: config.h
X
Xfailure.o: faillog.h config.h
X
Xfaillog.o: faillog.h config.h
X
Xpwent.o: config.h
X
Xport.o: port.h
X
Xnewgrp.o: config.h shadow.h
X
Xmkpasswd.o: config.h
X
Xgpmain.o: config.h
X
Xchfn.o: config.h
X
Xchsh.o: config.h
X
Xchage.o: config.h shadow.h
X
Xclean:
X -rm -f *.o a.out core npasswd nshadow *.pag *.dir
X
Xclobber: clean
X -rm -f $(BINS) *.L sushell.c susetup.c susub.c suvalid.c
X
Xshar: login.sh.1 login.sh.2 login.sh.3 login.sh.4 login.sh.5
X
Xlogin.sh.1: $(FILES1)
X shar -a $(FILES1) > login.sh.1
X
Xlogin.sh.2: $(FILES2)
X shar -a $(FILES2) > login.sh.2
X
Xlogin.sh.3: $(FILES3)
X shar -a $(FILES3) > login.sh.3
X
Xlogin.sh.4: $(FILES4)
X shar -a $(FILES4) > login.sh.4
X
Xlogin.sh.5: $(DOCS)
X shar -a $(DOCS) > login.sh.5
SHAR_EOF
if test 8384 -ne "`wc -c < 'Makefile'`"
then
echo shar: "error transmitting 'Makefile'" '(should have been 8384 characters)'
fi
fi
echo shar: "extracting 'config.h'" '(6050 characters)'
if test -f 'config.h'
then
echo shar: "will not over-write existing file 'config.h'"
else
sed 's/^X//' << \SHAR_EOF > 'config.h'
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/*
X * Configuration file for login.
X *
X * @(#)config.h 2.6 08:26:28 8/20/90
X */
X
X/*
X * Define DIALUP to use dialup password files. Define PORTTIME
X * to use the port time restriction file, see port.h for more
X * information.
X */
X
X#define DIALUP
X#define PORTTIME
X
X/*
X * Define SHADOWPWD to use shadow [ unreadable ] password file
X */
X
X#define SHADOWPWD
X
X/*
X * Define DOUBLESIZE to use 16 character passwords
X */
X
X#define DOUBLESIZE
X
X/*
X * Define OBSCURE to include hard password testing code.
X */
X
X#define OBSCURE
X
X/*
X * Define PASSLENGTH to be shortest legal password
X */
X
X#define PASSLENGTH 5
X
X/*
X * Define NOBLANK if you want all passwords prompted for, including
X * empty ones.
X
X#undef NOBLANK
X
X/*
X * Define MAXDAYS to be the default maximum number of days a password
X * is valid for when converting to shadow passwords. Define MINDAYS
X * to be the minimum number of days before a password may be changed.
X * See pwconv.c for more details.
X */
X
X#define MAXDAYS 10000
X#define MINDAYS 0
X
X/*
X * Define NDEBUG for production versions
X */
X
X#define NDEBUG
X
X/*
X * Define HZ if login must set HZ value
X */
X
X#define HZ "HZ=50"
X
X/*
X * Define TZ if login must set timezone
X *
X * The first example sets the variable directly. The
X * second example names a file which is read to determine
X * the proper value. The file consists of a single line
X * of the form 'TZ=zone-name'
X */
X
X/* #define TZ "TZ=CST6CDT" */
X#define TZ "/etc/tzname"
X
X/*
X * Define the default PATH and SUPATH here. PATH is for non-privileged
X * users, SUPATH is for root. The first pair are for real trusting
X * systems, the second pair are for the paranoid ...
X */
X
X/* #define PATH "PATH=:/bin:/usr/bin" */
X/* #define SUPATH "PATH=:/bin:/usr/bin:/etc" */
X#define PATH "PATH=/bin:/usr/bin"
X#define SUPATH "PATH=/bin:/usr/bin:/etc"
X
X/*
X * Define the mailbox directory
X */
X
X#define MAILDIR "/usr/spool/mail/"
X
X/*
X * Define AGING if you want the password aging checks made.
X * Define WARNAGE to be the number of days notice a user receives
X * of a soon to expire password.
X */
X
X#define AGING
X#define WARNAGE 10
X
X/*
X * Define MAILCHECK if you want the mailbox checked for new mail
X *
X * One of two messages are printed - `You have new mail.' or
X * `You have mail.'.
X */
X
X#define MAILCHECK
X
X/*
X * Define CONSOLE if you want ROOT restricted to a particular terminal.
X *
X * Use the name of the tty line if you only want a single line, or use
X * the name of the file containing the permissible ports if you wish to
X * allow root logins on more than one port.
X */
X
X/* #define CONSOLE "console" /* root on /dev/console only */
X#define CONSOLE "/etc/consoles" /* check /etc/consoles for a list */
X
X/*
X * Define NOLOGINS if you want to be able to deny non-root users logins.
X * Logins will not be permitted if this file exists.
X */
X
X#define NOLOGINS "/etc/nologin"
X
X/*
X * Define NOUSE if you want to be able to declare accounts which can't
X * be logged into. Define NOLOGIN if you want it to be an su-only account.
X */
X
X#define NOUSE "NOUSE"
X#define NOLOGIN "NOLOGIN"
X
X/*
X * Define MOTD if you want the message of the day (/etc/motd) printed
X * at login time.
X */
X
X#define MOTD
X
X/*
X * Define HUSHLOGIN if you want the code added to avoid printing the
X * motd if a file $HOME/.hushlogin exists. This obviously only matters
X * if any of MOTD, MAILCHECK or LASTLOG are #define'd.
X */
X
X#define HUSHLOGIN
X
X/*
X * Define LASTLOG if you want a record made of logins in /usr/adm/lastlog.
X */
X
X#define LASTLOG
X
X/*
X * Define FAILLOG if you want a record make of failed logins in
X * /usr/adm/faillog. See faillog.h for more details. See fail(1L)
X * for even still more details ... Also, define FTMP to record utmp
X * style records for failed logins. FTMP is the name of a utmp-like
X * file. You can use who(1) instead of faillog(L), which is an
X * advantage. Define UNKNOWNS if you do want unknown user names
X * recorded. This can be a security hole since passwords are often
X * entered mistakenly as user names.
X */
X
X#define FAILLOG
X#define FTMP "/etc/ftmp"
X#define UNKNOWNS
X
X/*
X * Define TTYPERM to be the initial terminal permissions. Defining
X * as 0600 will not allow messages, 0622 will.
X */
X
X#define TTYPERM 0600
X
X/*
X * Define TTYTYPE to the be name of the port to terminal type
X * mapping file. This is used to set the environmental variable
X * "TERM" to the correct terminal type.
X */
X
X#define TTYTYPE "/etc/ttytype"
X
X/*
X * Define QUOTAS if you want the code added in setup.c to support
X * file ulimit and nice [ and umask as well ] setting from the password
X * file.
X */
X
X#define QUOTAS
X
X/*
X * Pick your version of DBM. Only DBM is presently supported, NDBM will
X * follow. You must also define the GETPWENT macro below.
X */
X
X#define DBM
X
X/*
X * Define file name for sulog. If SULOG is not defined, there will be
X * no logging. This is NOT a good idea ... We also define other file
X * names.
X */
X
X#define SULOG "/usr/adm/sulog"
X#define SUCON "/dev/console"
X#define PWDFILE "/etc/passwd"
X#define OPWDFILE "/etc/-passwd"
X#define NPWDFILE "/etc/npasswd"
X#define OSHADOW "/etc/-shadow"
X#define NSHADOW "/etc/nshadow"
X#define GRPFILE "/etc/group"
X#define OGRPFILE "/etc/-group"
X#define NGRPFILE "/etc/ngroup"
X
X/*
X * Define PWDLOCK to be a locking semaphore for updating the password
X * file. GRPLOCK is the same for the group file.
X */
X
X#define PWDLOCK "/etc/.pwdlock"
X#define GRPLOCK "/etc/.grplock"
X
X/*
X * Wierd stuff follows ...
X *
X * The following macros exist solely to override stuff ...
X * You will probably want to change their values to suit your
X * fancy.
X */
X
X#define ERASECHAR '\b'
X#define KILLCHAR '\025'
X#define UMASK 022
X
X#define ULIMIT (1L<<20) /* Define if your UNIX supports ulimit() */
X#define FGETPWENT /* Define if library does not include FGETPWENT */
X#define GETPWENT /* Define if you want my GETPWENT(3) routines */
X#define NEED_AL64 /* Define if library does not include a64l() */
SHAR_EOF
if test 6050 -ne "`wc -c < 'config.h'`"
then
echo shar: "error transmitting 'config.h'" '(should have been 6050 characters)'
fi
fi
echo shar: "extracting 'pwunconv.c'" '(3123 characters)'
if test -f 'pwunconv.c'
then
echo shar: "will not over-write existing file 'pwunconv.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pwunconv.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/*
X * pwunconv - restore old password file from shadow password file.
X *
X * Pwunconv copies the password file information from the shadow
X * password file, merging entries from an optional existing shadow
X * file.
X *
X * The new password file is left in npasswd. There is no new
X * shadow file. Password aging information is translated where
X * possible.
X */
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <fcntl.h>
X#include <pwd.h>
X#include "config.h"
X#include "shadow.h"
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)pwunconv.c 2.2 19:24:08 7/29/90";
X#endif
X
Xchar buf[BUFSIZ];
Xchar *l64a ();
X
Xint main ()
X{
X struct passwd *pw;
X struct passwd *sgetpwent ();
X FILE *pwd;
X FILE *npwd;
X struct spwd *spwd;
X int fd;
X
X if (! (pwd = fopen (PWDFILE, "r"))) {
X perror (PWDFILE);
X return (1);
X }
X unlink ("npasswd");
X if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
X ! (npwd = fdopen (fd, "w"))) {
X perror ("npasswd");
X return (1);
X }
X while (fgets (buf, BUFSIZ, pwd) == buf) {
X buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
X
X if (buf[0] == '#') { /* comment line */
X (void) fprintf (npwd, "%s\n", buf);
X continue;
X }
X if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
X (void) fprintf (npwd, "%s\n", buf);
X continue;
X }
X setspent (); /* rewind shadow file */
X
X if (! (spwd = getspnam (pw->pw_name))) {
X (void) fprintf (npwd, "%s\n", buf);
X continue;
X }
X pw->pw_passwd = spwd->sp_pwdp;
X
X /*
X * Password aging works differently in the two different systems.
X * With shadow password files you apparently must have some aging
X * information. The maxweeks or minweeks may not map exactly.
X * In pwconv we set max == 10000, which is about 30 years. Here
X * we have to undo that kludge. So, if maxdays == 10000, no aging
X * information is put into the new file. Otherwise, the days are
X * converted to weeks and so on.
X */
X
X if (spwd->sp_max > (63*7) && spwd->sp_max < 10000)
X spwd->sp_max = (63*7); /* 10000 is infinity this week */
X
X if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
X spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
X spwd->sp_max /= 7; /* turn it into weeks */
X spwd->sp_min /= 7;
X spwd->sp_lstchg /= 7;
X pw->pw_age = l64a ((long) spwd->sp_lstchg * (64L*64L) +
X spwd->sp_min * (64L) +
X spwd->sp_max);
X } else
X pw->pw_age = (char *) 0;
X
X if (pw->pw_age)
X (void) fprintf (npwd, "%s:%s,%s:%d:%d:%s:%s:%s\n",
X pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
X pw->pw_age, pw->pw_uid, pw->pw_gid,
X pw->pw_gecos, pw->pw_dir,
X pw->pw_shell ? pw->pw_shell:"");
X else
X (void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:%s\n",
X pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
X pw->pw_uid, pw->pw_gid,
X pw->pw_gecos, pw->pw_dir,
X pw->pw_shell ? pw->pw_shell:"");
X }
X endspent ();
X
X if (ferror (npwd)) {
X perror ("pwunconv");
X (void) unlink ("npasswd");
X }
X (void) fclose (npwd);
X (void) fclose (pwd);
X return (0);
X}
SHAR_EOF
if test 3123 -ne "`wc -c < 'pwunconv.c'`"
then
echo shar: "error transmitting 'pwunconv.c'" '(should have been 3123 characters)'
fi
fi
echo shar: "extracting 'obscure.c'" '(2817 characters)'
if test -f 'obscure.c'
then
echo shar: "will not over-write existing file 'obscure.c'"
else
sed 's/^X//' << \SHAR_EOF > 'obscure.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 <ctype.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[] = "@(#)obscure.c 2.3 08:58:09 11/5/90";
X#endif
X
X/*
X * Obscure - see if password is obscure enough.
X *
X * The programmer is encouraged to add as much complexity to this
X * routine as desired. Included are some of my favorite ways to
X * check passwords.
X */
X
Xextern char pass[]; /* the new password */
Xextern char orig[]; /* the original password */
X#ifdef OBSCURE
Xchar mono[32]; /* a monocase version of pass */
X#endif
Xint obscure ()
X{
X#ifdef OBSCURE
X int i;
X#endif
X if (orig[0] == '\0')
X return (1);
X
X if (strlen (pass) < PASSLENGTH) { /* too short */
X printf ("Too short. ");
X return (0);
X }
X#ifdef OBSCURE
X for (i = 0;pass[i];i++)
X mono[i] = tolower (pass[i]);
X
X if (strcmp (pass, orig) == 0) /* the same */
X return (0);
X
X if (palindrome ()) /* a palindrome */
X return (0);
X
X if (caseshift ()) /* upper/lower case changes only */
X return (0);
X
X if (similiar ()) /* jumbled version of original */
X return (0);
X
X if (simple ()) /* keyspace size */
X return (0);
X#endif
X return (1);
X}
X
X#ifdef OBSCURE
X
X/*
X * can't be a palindrome - like `R A D A R' or `M A D A M'
X */
X
Xint palindrome ()
X{
X int i, j;
X
X i = strlen (pass);
X
X for (j = 0;j < i;j++)
X if (pass[i - j - 1] != pass[j])
X return (0);
X
X printf ("No palindromes. ");
X return (1);
X}
X
X/*
X * may not be a shifted version of original
X */
X
Xint caseshift ()
X{
X int i;
X
X for (i = 0;pass[i] && orig[i];i++) {
X if (tolower (pass[i]) == tolower (orig[i]))
X continue;
X else
X return (0);
X }
X printf ("May not be case-shifted. ");
X return (1);
X}
X
X/*
X * more than half of the characters are different ones.
X */
X
Xint similiar ()
X{
X int i, j;
X char *strchr ();
X
X for (i = j = 0;pass[i] && orig[i];i++)
X if (strchr (mono, tolower (orig[i])))
X j++;
X
X if (i >= j * 2)
X return (0);
X
X printf ("Too similiar. ");
X return (1);
X}
X
X/*
X * a nice mix of characters.
X */
X
Xint simple ()
X{
X int digits = 0;
X int uppers = 0;
X int lowers = 0;
X int others = 0;
X int size;
X int i;
X double complexity;
X
X for (i = 0;pass[i];i++) {
X if (isdigit (pass[i]))
X digits++;
X else if (isupper (pass[i]))
X uppers++;
X else if (islower (pass[i]))
X lowers++;
X else
X others++;
X }
X
X /*
X * The scam is this - a password of only one character type
X * must be 8 letters long. Two types, 7, and so on.
X */
X
X size = 9;
X if (digits) size--;
X if (uppers) size--;
X if (lowers) size--;
X if (others) size--;
X
X if (size <= i)
X return 0;
X
X printf ("Too Simple. ");
X return 1;
X}
X#endif
SHAR_EOF
if test 2817 -ne "`wc -c < 'obscure.c'`"
then
echo shar: "error transmitting 'obscure.c'" '(should have been 2817 characters)'
fi
fi
echo shar: "extracting 'age.c'" '(2588 characters)'
if test -f 'age.c'
then
echo shar: "will not over-write existing file 'age.c'"
else
sed 's/^X//' << \SHAR_EOF > 'age.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 "config.h"
X
X#ifndef lint
Xstatic char _sccsid[] = "@(#)age.c 2.6 10:20:04 11/9/90";
X#endif
X
X#ifndef PASSWD
Xextern char *newenvp[];
X#endif
X
X#ifndef WARNAGE
X#define WARNAGE 10
X#endif
X
Xtime_t time ();
X
Xint c64i (c)
Xchar c;
X{
X if (c == '.')
X return (0);
X
X if (c == '/')
X return (1);
X
X if (c >= '0' && c <= '9')
X return (c - '0' + 2);
X
X if (c >= 'A' && c <= 'Z')
X return (c - 'A' + 12);
X
X if (c >= 'a' && c <= 'z')
X return (c - 'a' + 38);
X else
X return (-1);
X}
X
Xint i64c (i)
Xint i;
X{
X if (i < 0)
X return ('.');
X else if (i > 63)
X return ('z');
X
X if (i == 0)
X return ('.');
X
X if (i == 1)
X return ('/');
X
X if (i >= 2 && i <= 11)
X return ('0' - 2 + i);
X
X if (i >= 12 && i <= 37)
X return ('A' - 12 + i);
X
X if (i >= 38 && i <= 63)
X return ('a' - 38 + i);
X
X return ('\0');
X}
X
X#ifdef AGING
X#ifdef NEED_AL64
X#ifdef PASSWD
Xchar *l64a (l)
Xlong l;
X{
X static char buf[8];
X int i = 0;
X
X if (i < 0L)
X return ((char *) 0);
X
X do {
X buf[i++] = i64c ((int) (l % 64));
X buf[i] = '\0';
X } while (l /= 64L, l > 0 && i < 6);
X
X return (buf);
X}
X#endif
X
Xlong a64l (s)
Xchar *s;
X{
X int i;
X long value;
X long shift = 0;
X
X for (i = 0, value = 0L;i < 6 && *s;s++) {
X value += (c64i (*s) << shift);
X shift += 6;
X }
X return (value);
X}
X#endif
X#ifndef PASSWD
Xvoid expire (name, last, min, max)
Xchar *name;
Xlong last;
Xint min;
Xint max;
X{
X long clock;
X long week;
X long expires;
X extern int errno;
X
X (void) time (&clock);
X clock /= (24L * 60L * 60L);
X
X if (min < 0)
X min = 0;
X
X if (max < 0)
X max = 10000; /* 10000 is infinity */
X
X if (last <= 0L)
X expires = 0L;
X else
X expires = last + max;
X
X if (max < 10000 && (clock >= expires || min == max)) {
X#ifndef SU
X printf ("Your password has expired.");
X
X if (max < min) {
X puts (" Contact the system administrator.\n");
X exit (1);
X }
X puts (" Choose a new one.\n");
X
X execl ("/bin/passwd", "-passwd", name, (char *) 0);
X puts ("Can't execute /bin/passwd");
X exit (errno);
X#else
X printf ("Your password has expired.\n");
X#ifdef SULOG
X sulog (0);
X#endif
X exit (1);
X#endif
X }
X}
X
Xvoid agecheck (last, min, max, warn)
Xlong last;
Xint min;
Xint max;
Xint warn;
X{
X long clock = time ((long *) 0) / (24L * 3600);
X long remain;
X
X if (last == 0)
X return;
X
X if ((remain = (last + max) - clock) <= warn)
X printf ("Your password will expire in %d %s.\n",
X remain, remain == 1 ? "day":"days");
X}
X#endif
X#endif
SHAR_EOF
if test 2588 -ne "`wc -c < 'age.c'`"
then
echo shar: "error transmitting 'age.c'" '(should have been 2588 characters)'
fi
fi
echo shar: "extracting 'sub.c'" '(1671 characters)'
if test -f 'sub.c'
then
echo shar: "will not over-write existing file 'sub.c'"
else
sed 's/^X//' << \SHAR_EOF > 'sub.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 <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
X#ifndef lint
Xstatic char _sccsid[] = "@(#)sub.c 2.2 19:24:19 7/29/90";
X#endif
X
Xextern struct passwd pwent;
X#ifndef SU
Xextern struct utmp utent;
X#endif
X
Xvoid setutmp ();
X
X/*
X * I have heard of two different types of behavior with subsystem roots.
X * One has you execute login no matter what. The other has you execute
X * the command [ if one exists ] after the '*' in the shell name. The
X * macro SUBLOGIN says to execute /bin/login [ followed by /etc/login ]
X * regardless. Otherwise, pwent.pw_shell is fixed up and that command
X * is executed [ by returning to the caller ]. I prefer the latter since
X * it doesn't require having a "login" on the new root filesystem.
X */
X
Xvoid subsystem ()
X{
X char *strdup ();
X
X if (pwent.pw_dir[0] != '/')
X exit (1);
X
X if (chdir (pwent.pw_dir) || chroot (pwent.pw_dir)) {
X printf ("Can't change to \"%s\"\n", pwent.pw_dir);
X exit (1);
X }
X#ifndef SU
X (void) strcpy (utent.ut_line, "<!sublogin>");
X
X setutmp ();
X#endif
X#ifdef SUBLOGIN
X execl ("/bin/login", "login", name, (char *) 0);
X execl ("/etc/login", "login", name, (char *) 0);
X puts ("No /bin/login or /etc/login on root");
X exit (1);
X#else
X if (! pwent.pw_shell || strlen (pwent.pw_shell) == 1)
X pwent.pw_shell = "/bin/sh"; /* default shell */
X else
X pwent.pw_shell++; /* skip over '*' */
X#endif
X}
SHAR_EOF
if test 1671 -ne "`wc -c < 'sub.c'`"
then
echo shar: "error transmitting 'sub.c'" '(should have been 1671 characters)'
fi
fi
echo shar: "extracting 'login.c'" '(1164 characters)'
if test -f 'login.c'
then
echo shar: "will not over-write existing file 'login.c'"
else
sed 's/^X//' << \SHAR_EOF > 'login.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 <ctype.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
X#ifndef lint
Xstatic char sccsid[] = "@(#)login.c 2.3 19:23:55 7/29/90";
X#endif
X
Xvoid setenv ();
X
Xvoid login (name)
Xchar *name;
X{
X char buf[BUFSIZ];
X char *envp[32];
X int envc;
X char *cp;
X int i;
X
X#ifndef BSD
X (void) memset (buf, '\0', sizeof buf);
X#else
X bzero (buf, sizeof buf);
X#endif
X fputs ("login: ", stdout);
X
X if (fgets (buf, BUFSIZ, stdin) != buf)
X exit (1);
X
X buf[strlen (buf) - 1] = '\0'; /* remove \n [ must be there ] */
X
X for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
X ;
X
X for (i = 0;i < BUFSIZ - 1 && isgraph (*cp);name[i++] = *cp++)
X ;
X
X if (*cp)
X cp++;
X
X name[i] = '\0';
X
X if (*cp != '\0') { /* process new variables */
X for (envc = 0;envc < 32;envc++) {
X envp[envc] = strtok (envc == 0 ? cp:(char *) 0, " \t,");
X
X if (envp[envc] == (char *) 0)
X break;
X }
X setenv (envc, envp);
X }
X}
SHAR_EOF
if test 1164 -ne "`wc -c < 'login.c'`"
then
echo shar: "error transmitting 'login.c'" '(should have been 1164 characters)'
fi
fi
echo shar: "extracting 'shell.c'" '(854 characters)'
if test -f 'shell.c'
then
echo shar: "will not over-write existing file 'shell.c'"
else
sed 's/^X//' << \SHAR_EOF > 'shell.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#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[] = "@(#)shell.c 2.2 19:24:15 7/29/90";
X#endif
X
Xextern char *newenvp[];
X
Xvoid shell (file)
Xchar *file;
X{
X char arg0[BUFSIZ];
X char *path;
X extern int errno;
X
X if (file == (char *) 0)
X exit (1);
X
X if (path = strrchr (file, '/'))
X path++;
X else
X path = file;
X
X (void) strcpy (arg0 + 1, path);
X arg0[0] = '-';
X#ifndef NDEBUG
X printf ("Executing shell %s\n", file);
X#endif
X execle (file, arg0, (char *) 0, newenvp);
X printf ("Can't execute %s\n", file);
X exit (errno);
X}
SHAR_EOF
if test 854 -ne "`wc -c < 'shell.c'`"
then
echo shar: "error transmitting 'shell.c'" '(should have been 854 characters)'
fi
fi
echo shar: "extracting 'lastlog.h'" '(511 characters)'
if test -f 'lastlog.h'
then
echo shar: "will not over-write existing file 'lastlog.h'"
else
sed 's/^X//' << \SHAR_EOF > 'lastlog.h'
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/*
X * lastlog.h - structure of lastlog file
X *
X * @(#)lastlog.h 2.3 19:23:49 7/29/90
X *
X * This file defines a lastlog file structure which should be sufficient
X * to hold the information required by login. It should only be used if
X * there is no real lastlog.h file.
X */
X
Xstruct lastlog {
X time_t ll_time;
X char ll_line[8];
X};
SHAR_EOF
if test 511 -ne "`wc -c < 'lastlog.h'`"
then
echo shar: "error transmitting 'lastlog.h'" '(should have been 511 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