[comp.sources.bugs] Shadow Login: Patch #5

jfh@rpp386.Dallas.TX.US (John F. Haugh II) (03/09/89)

This is patch number 5.  It fixes some bugs in passwd and su, and
adds a number of new features.  Yes, still MORE new features ...

Double sized passwords -
	This feature allows passwords up to 16 characters long.
	It is completely compatible with old 8 character passwords.

Hushlogin behaves better -
	.hushlogin files now function like BSD.  Both the mail
	status message and the last login information are suppressed.
	Previously only /etc/motd was canned.

Configurable ERASE and KILL characters -
	login sets ERASE and KILL to configurable values.  Handy
	for ancient systems which still use '#' and '@'.

Configurable default ULIMIT and UMASK -
	Allows ULIMIT and UMASK to be set at login time without
	regenerating the kernel.  Default may still be overriden
	by appropriate entries in the GECOS field.

Console list may now be given -
	The CONSOLE option has been modified to allow a list of
	legal terminals to be provided.  The list is present in
	a file with one name per entry.

Bugs fixed -
	a64l() and l64a() are now included by using -DNEED_AL64.
	login now sets ISIG termio mode.
	passwd makes /etc/passwd readable if shadow isn't being used.
	passwd includes newline after updated entry always.
	su now execs shell more like prior su.
	su provides more secure paths by default.
	su gives correct user name if the requested one did not exist.
	sulogin determines correct tty name.
*** Makefile
--- new/Makefile
**************
*** 1,5
  #
! #	@(#)Makefile	1.4 - System V shadow password system
  #
  #	@(#)Makefile	1.4	18:06:16	2/20/89
  #
--- 1,5 -----
  #
! #	@(#)Makefile	1.5 - System V shadow password system
  #
  #	@(#)Makefile	1.5	15:59:30	3/4/89
  #
**************
*** 1,7
  #
  #	@(#)Makefile	1.4 - System V shadow password system
  #
! #	@(#)Makefile	1.4	18:06:16	2/20/89
  #
  SHELL = /bin/sh
  
--- 1,7 -----
  #
  #	@(#)Makefile	1.5 - System V shadow password system
  #
! #	@(#)Makefile	1.5	15:59:30	3/4/89
  #
  SHELL = /bin/sh
  # Uncomment the next line if you need fgetpwent()
**************
*** 4,9
  #	@(#)Makefile	1.4	18:06:16	2/20/89
  #
  SHELL = /bin/sh
  
  # Flags for SCO Xenix/386
  CFLAGS = -O -M3 -g -DFGETPWENT
--- 4,13 -----
  #	@(#)Makefile	1.5	15:59:30	3/4/89
  #
  SHELL = /bin/sh
+ # Uncomment the next line if you need fgetpwent()
+ PWDEF = -DFGETPWENT
+ # Uncomment the next line if you need a64l() and l64a().
+ AL64DEF = -DNEED_AL64
  
  # Flags for SCO Xenix/386
  CFLAGS = -O -M3 -g $(PWDEF) $(AL64DEF)
**************
*** 6,12
  SHELL = /bin/sh
  
  # Flags for SCO Xenix/386
! CFLAGS = -O -M3 -g -DFGETPWENT
  LIBS = -lcrypt
  LDFLAGS = -M3 -g
  LTFLAGS = 
--- 10,16 -----
  AL64DEF = -DNEED_AL64
  
  # Flags for SCO Xenix/386
! CFLAGS = -O -M3 -g $(PWDEF) $(AL64DEF)
  LIBS = -lcrypt
  LDFLAGS = -M3 -g
  LTFLAGS = 
**************
*** 12,18
  LTFLAGS = 
  
  # Flags for normal machines
! # CFLAGS = -O -g
  # LIBS =
  # LDFLAGS = -g
  
--- 16,22 -----
  LTFLAGS = 
  
  # Flags for normal machines
! # CFLAGS = -O -g $(PWDEF) $(AL64DEF)
  # LIBS =
  # LDFLAGS = -g
  
**************
*** 144,149
  dialup.o: dialup.h
  
  dialchk.o: dialup.h config.h
  
  clean:
  	-rm -f *.o a.out core npasswd nshadow
--- 148,155 -----
  dialup.o: dialup.h
  
  dialchk.o: dialup.h config.h
+ 
+ valid.o: config.h
  
  clean:
  	-rm -f *.o a.out core npasswd nshadow
*** README
--- new/README
**************
*** 16,22
  for the maintenance of this software package.  The author is under no
  obligation to provide modifications or improvements.
  
! Begin by reading and editting the config.h file.  All options are selected
  by using #define's.  A brief description for each available option appears
  below.
  
--- 16,22 -----
  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.
  
**************
*** 20,26
  by using #define's.  A brief description for each available option appears
  below.
  
! Note that there are MANY options.
  
  Dialup Password Files -
  	This option permits individual ports to have an additional
--- 20,28 -----
  by using #define's.  A brief description for each available option appears
  below.
  
! Note that there are MANY options.  As distributed all options are turned
! on, which produces a really nice package.  This is the system as used on
! the authors machine.
  
  Dialup Password Files -
  	This option permits individual ports to have an additional
**************
*** 38,43
  
  	Select this option by defining the SHADOWPWD macro.
  
  Obscure Password Testing -
  	This option includes code to test user passwords for
  	complexity.  The programmer is encouraged to edit the
--- 40,52 -----
  
  	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
**************
*** 97,103
  	account.
  
  	Select this option by defining the CONSOLE macro to
! 	have the desired port name.
  
  Message of the Day Printing -
  	This option causes the message of the day to be
--- 106,114 -----
  	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.
  
  Message of the Day Printing -
  	This option causes the message of the day to be
**************
*** 136,142
  
  	Select this option by defining the TTYTYPE macro as
  	having the value of the name of the type to port
! 	mapping file.
  
  File Size Setting -
  	This option includes code to set the user's ulimit
--- 147,154 -----
  
  	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
**************
*** 154,156
  	Select this option by defining the SULOG macro to
  	have the value of the name of the file you want
  	attempts logged to.
--- 166,190 -----
  	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.
*** age.c
--- new/age.c
**************
*** 4,10
  #include "config.h"
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)age.c	1.2	08:41:03	2/22/89";
  #endif
  
  #ifndef	PASSWD
--- 4,10 -----
  #include "config.h"
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)age.c	1.3	15:59:36	3/4/89";
  #endif
  
  #ifndef	PASSWD
**************
*** 36,41
  
  #ifdef	AGING
  #ifdef	PASSWD
  char	*l64a (l)
  long	l;
  {
--- 36,42 -----
  
  #ifdef	AGING
  #ifdef	PASSWD
+ #ifdef	NEED_AL64
  char	*l64a (l)
  long	l;
  {
**************
*** 53,58
  	return (buf);
  }
  #endif
  int	i64c (i)
  int	i;
  {
--- 54,60 -----
  	return (buf);
  }
  #endif
+ #endif
  int	i64c (i)
  int	i;
  {
**************
*** 79,84
  	return ('\0');
  }
  
  long	a64l (s)
  char	*s;
  {
--- 81,87 -----
  	return ('\0');
  }
  
+ #ifdef	NEED_AL64
  long	a64l (s)
  char	*s;
  {
**************
*** 92,97
  	}
  	return (value);
  }
  #ifndef	PASSWD
  void	expire (age)
  char	*age;
--- 95,101 -----
  	}
  	return (value);
  }
+ #endif
  #ifndef	PASSWD
  void	expire (age)
  char	*age;
*** config.h
--- new/config.h
**************
*** 1,7
  /*
   * Configuration file for login.
   *
!  *	@(#)config.h	1.2	18:06:19	2/20/89
   */
  
  /*
--- 1,7 -----
  /*
   * Configuration file for login.
   *
!  *	@(#)config.h	1.3	15:59:38	3/4/89
   */
  
  /*
**************
*** 17,23
  #define	SHADOWPWD
  
  /*
!  * Define OBSCURE to include hard password testing code.
   */
  
  #define	OBSCURE
--- 17,23 -----
  #define	SHADOWPWD
  
  /*
!  * Define DOUBLESIZE to use 16 character passwords
   */
  
  #define DOUBLESIZE
**************
*** 20,25
   * Define OBSCURE to include hard password testing code.
   */
  
  #define	OBSCURE
  
  /*
--- 20,31 -----
   * Define DOUBLESIZE to use 16 character passwords
   */
  
+ #define DOUBLESIZE
+ 
+ /*
+  * Define OBSCURE to include hard password testing code.
+  */
+ 
  #define	OBSCURE
  
  /*
**************
*** 54,60
  
  /*
   * Define the default PATH and SUPATH here.  PATH is for non-privileged
!  * users, SUPATH is for root.
   */
  
  #define	PATH	"PATH=:/bin:/usr/bin"
--- 60,67 -----
  
  /*
   * 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"	*/
**************
*** 57,64
   * users, SUPATH is for root.
   */
  
! #define	PATH	"PATH=:/bin:/usr/bin"
! #define	SUPATH	"PATH=:/bin:/usr/bin:/etc"
  
  /*
   * Define the mailbox directory
--- 64,73 -----
   * 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
**************
*** 82,88
  #define	MAILCHECK
  
  /*
!  * Define CONSOLE if you want ROOT restricted to a single terminal
   */
  
  #define	CONSOLE	"tty01"
--- 91,101 -----
  #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 */
**************
*** 85,91
   * Define CONSOLE if you want ROOT restricted to a single terminal
   */
  
! #define	CONSOLE	"tty01"
  
  /*
   * Define MOTD if you want the message of the day (/etc/motd) printed
--- 98,105 -----
   * 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 MOTD if you want the message of the day (/etc/motd) printed
**************
*** 97,103
  /*
   * Define HUSHLOGIN if you want the code added to avoid printing the
   * motd if a file $HOME/.hushlogin exists.  This obviously only matters
!  * if MOTD is #define'd.
   */
  
  #define	HUSHLOGIN
--- 111,117 -----
  /*
   * 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
**************
*** 150,152
   */
  
  #define	PWDLOCK	"/etc/.pwdlock"
--- 164,179 -----
   */
  
  #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)
*** lmain.c
--- new/lmain.c
**************
*** 1,4
  #include <sys/types.h>
  #include <stdio.h>
  #include <pwd.h>
  #include <utmp.h>
--- 1,5 -----
  #include <sys/types.h>
+ #include <sys/stat.h>
  #include <stdio.h>
  #include <pwd.h>
  #include <utmp.h>
**************
*** 5,10
  #include <time.h>
  #include <string.h>
  #include <signal.h>
  #include "config.h"
  #include "lastlog.h"
  
--- 6,12 -----
  #include <time.h>
  #include <string.h>
  #include <signal.h>
+ #include <termio.h>
  #include "config.h"
  #include "lastlog.h"
  
**************
*** 9,15
  #include "lastlog.h"
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)lmain.c	1.3	18:06:20	2/20/89";
  #endif
  
  char	name[BUFSIZ];
--- 11,17 -----
  #include "lastlog.h"
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)lmain.c	1.4	15:59:41	3/4/89";
  #endif
  
  #ifndef	ERASECHAR
**************
*** 12,17
  static	char	_sccsid[] = "@(#)lmain.c	1.3	18:06:20	2/20/89";
  #endif
  
  char	name[BUFSIZ];
  char	pass[BUFSIZ];
  char	home[BUFSIZ];
--- 14,27 -----
  static	char	_sccsid[] = "@(#)lmain.c	1.4	15:59:41	3/4/89";
  #endif
  
+ #ifndef	ERASECHAR
+ #define	ERASECHAR	'\b'		/* backspace */
+ #endif
+ 
+ #ifndef	KILLCHAR
+ #define	KILLCHAR	'\025'		/* control U */
+ #endif
+ 
  char	name[BUFSIZ];
  char	pass[BUFSIZ];
  char	home[BUFSIZ];
**************
*** 17,22
  char	home[BUFSIZ];
  char	prog[BUFSIZ];
  char	mail[BUFSIZ];
  
  struct	passwd	pwent;
  struct	utmp	utent;
--- 27,36 -----
  char	home[BUFSIZ];
  char	prog[BUFSIZ];
  char	mail[BUFSIZ];
+ #ifdef	HUSHLOGIN
+ char	hush[BUFSIZ];
+ int	hushed;
+ #endif
  
  struct	passwd	pwent;
  struct	utmp	utent;
**************
*** 21,26
  struct	passwd	pwent;
  struct	utmp	utent;
  struct	lastlog	lastlog;
  
  #ifndef	MAXENV
  #define	MAXENV	64
--- 35,41 -----
  struct	passwd	pwent;
  struct	utmp	utent;
  struct	lastlog	lastlog;
+ struct	termio	termio;
  
  #ifndef	MAXENV
  #define	MAXENV	64
**************
*** 62,67
  char	**envp;
  {
  	int	retries = RETRIES;
  
  	checkutmp ();			/* must be lowest level shell */
  
--- 77,88 -----
  char	**envp;
  {
  	int	retries = RETRIES;
+ #ifdef	CONSOLE
+ 	int	conflag;
+ 	char	console[BUFSIZ];
+ 	FILE	*fp;
+ 	struct	stat	statbuf;
+ #endif
  
  	checkutmp ();			/* must be lowest level shell */
  
**************
*** 68,73
  	if (! isatty (0))		/* must be a terminal */
  		exit (1);
  
  	while (*envp)			/* add inherited environment, */
  		addenv (*envp++);	/* some variables change later */
  
--- 89,112 -----
  	if (! isatty (0))		/* must be a terminal */
  		exit (1);
  
+ 	(void) ioctl (0, TCGETA, &termio); /* get terminal characteristics */
+ 
+ 	/*
+ 	 * Add your favorite terminal modes here ...
+ 	 */
+ 
+ 	termio.c_cflag |= ISIG;
+ 
+ 	termio.c_cc[VERASE] = ERASECHAR;
+ 	termio.c_cc[VKILL] = KILLCHAR;
+ 	(void) ioctl (0, TCSETAF, &termio); /* set erase and kill characters */
+ 
+ #ifdef	UMASK
+ 	umask (UMASK);			/* override the default umask */
+ #endif
+ #ifdef	ULIMIT
+ 	ulimit (2, (long) ULIMIT);	/* override the default ulimit */
+ #endif
  	while (*envp)			/* add inherited environment, */
  		addenv (*envp++);	/* some variables change later */
  
**************
*** 132,140
  
  	setutmp ();			/* make entry in utmp & wtmp files */
  #ifdef	CONSOLE
! 	if (pwent.pw_uid == 0 &&	/* root no logging in on console ? */
! 			strncmp (CONSOLE, utent.ut_line, sizeof utent.ut_line))
! 		exit (1);		/* then exit! */
  #endif
  	if (pwent.pw_shell && pwent.pw_shell[0] == '*') /* subsystem root */
  		subsystem ();		/* figure out what to execute */
--- 171,193 -----
  
  	setutmp ();			/* make entry in utmp & wtmp files */
  #ifdef	CONSOLE
! 	if (pwent.pw_uid == 0 && stat (CONSOLE, &statbuf) == 0) {
! 		if ((statbuf.st_mode & S_IFMT) == S_IFREG) {
! 			fp = fopen (CONSOLE, "r");
! 			while (fp && fgets (console, BUFSIZ, fp) == console) {
! 				console[strlen (console) - 1] = '\0';
! 				if (strcmp (console, utent.ut_line) == 0)
! 					break;
! 			}
! 			if (! fp || feof (fp))
! 				exit (1); /* found EOF before tty line */
! 
! 			fclose (fp);
! 		} else {
! 			if (strcmp (CONSOLE, utent.ut_line) != 0)
! 				exit (1);
! 		}
! 	}
  #endif
  	if (pwent.pw_shell && pwent.pw_shell[0] == '*') /* subsystem root */
  		subsystem ();		/* figure out what to execute */
**************
*** 147,152
  	if (pwent.pw_age)		/* check for age of password ... */
  		expire (pwent.pw_age);	/* ... ask for new one if expired */
  #endif
  #ifdef	MOTD
  	motd ();			/* print the message of the day */
  #endif
--- 200,209 -----
  	if (pwent.pw_age)		/* check for age of password ... */
  		expire (pwent.pw_age);	/* ... ask for new one if expired */
  #endif
+ #ifdef	HUSHLOGIN
+ 	sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
+ 	hushed = access (hush, 0) != -1;
+ #endif
  #ifdef	MOTD
  	motd ();			/* print the message of the day */
  #endif
**************
*** 151,157
  	motd ();			/* print the message of the day */
  #endif
  #ifdef	LASTLOG
! 	if (lastlog.ll_time != 0)
  		printf ("Last login: %.19s on %s\n",
  			ctime (&lastlog.ll_time), lastlog.ll_line);
  #endif
--- 208,214 -----
  	motd ();			/* print the message of the day */
  #endif
  #ifdef	LASTLOG
! 	if (lastlog.ll_time != 0 && ! hushed)
  		printf ("Last login: %.19s on %s\n",
  			ctime (&lastlog.ll_time), lastlog.ll_line);
  #endif
*** login.1
--- new/login.1
**************
*** 56,61
  Ulimit, umask and nice values may also be set according to
  entries in the GECOS field.
  .PP
  An initialization script for your command interpreter may also be
  executed.
  Please see the appropriate manual section for more information on
--- 56,65 -----
  Ulimit, umask and nice values may also be set according to
  entries in the GECOS field.
  .PP
+ On some installations, the environmental variable \fB$TERM\fR will be
+ initialize to the terminal type on your tty line, as specified in
+ \fI/etc/ttytype\fR.
+ .PP
  An initialization script for your command interpreter may also be
  executed.
  Please see the appropriate manual section for more information on
**************
*** 74,79
  /etc/shadow \- encrypted passwords and age information
  .br
  /etc/motd \- system message file
  .br
  $HOME/.profile \- initialization script for default shell
  .br
--- 78,85 -----
  /etc/shadow \- encrypted passwords and age information
  .br
  /etc/motd \- system message file
+ .br
+ /etc/ttytype \- list of terminal types
  .br
  $HOME/.profile \- initialization script for default shell
  .br
*** mail.c
--- new/mail.c
**************
*** 3,9
  #include <string.h>
  #include "config.h"
  
! extern	char	mail[];
  
  #ifdef	MAILCHECK
  void	mailcheck ()
--- 3,11 -----
  #include <string.h>
  #include "config.h"
  
! #ifndef	lint
! static	char	_sccsid[] = "@(#)mail.c	1.2	15:59:47	3/4/89";
! #endif
  
  extern	char	mail[];
  
**************
*** 5,10
  
  extern	char	mail[];
  
  #ifdef	MAILCHECK
  void	mailcheck ()
  {
--- 7,18 -----
  static	char	_sccsid[] = "@(#)mail.c	1.2	15:59:47	3/4/89";
  #endif
  
+ extern	char	mail[];
+ 
+ #ifdef	HUSHLOGIN
+ extern	int	hushed;
+ #endif
+ 
  #ifdef	MAILCHECK
  void	mailcheck ()
  {
**************
*** 11,16
  	struct	stat	statbuf;
  	char	*mailbox;
  
  	if (mailbox = strchr (mail, '='))
  		mailbox++;
  	else
--- 19,28 -----
  	struct	stat	statbuf;
  	char	*mailbox;
  
+ #ifdef	HUSHLOGIN
+ 	if (hushed)
+ 		return;
+ #endif
  	if (mailbox = strchr (mail, '='))
  		mailbox++;
  	else
*** motd.c
--- new/motd.c
**************
*** 2,8
  #include <string.h>
  #include "config.h"
  
! extern	char	home[];
  
  void	motd ()
  {
--- 2,10 -----
  #include <string.h>
  #include "config.h"
  
! #ifndef	lint
! static	char	_sccsid[] = "@(#)motd.c	1.2	15:59:49	3/4/89";
! #endif
  
  extern	char	home[];
  #ifdef	HUSHLOGIN
**************
*** 4,9
  
  extern	char	home[];
  
  void	motd ()
  {
  #ifdef	MOTD
--- 6,17 -----
  static	char	_sccsid[] = "@(#)motd.c	1.2	15:59:49	3/4/89";
  #endif
  
+ extern	char	home[];
+ #ifdef	HUSHLOGIN
+ extern	int	hushed;
+ #endif
+ 
+ #ifdef	MOTD
  void	motd ()
  {
  	FILE	*fp;
**************
*** 6,12
  
  void	motd ()
  {
- #ifdef	MOTD
  	FILE	*fp;
  	register int	c;
  #ifdef	HUSHLOGIN
--- 14,19 -----
  #ifdef	MOTD
  void	motd ()
  {
  	FILE	*fp;
  	register int	c;
  
**************
*** 9,16
  #ifdef	MOTD
  	FILE	*fp;
  	register int	c;
- #ifdef	HUSHLOGIN
- 	char	hush[BUFSIZ];
  
  	(void) strcat (strcpy (hush, home + 5), "/.hushlogin");
  
--- 16,21 -----
  {
  	FILE	*fp;
  	register int	c;
  
  #ifdef	HUSHLOGIN
  	if (hushed)
**************
*** 12,20
  #ifdef	HUSHLOGIN
  	char	hush[BUFSIZ];
  
! 	(void) strcat (strcpy (hush, home + 5), "/.hushlogin");
! 
! 	if (access (hush, 0) == 0)
  		return;
  #endif
  	if ((fp = fopen ("/etc/motd", "r")) == (FILE *) 0)
--- 17,24 -----
  	FILE	*fp;
  	register int	c;
  
! #ifdef	HUSHLOGIN
! 	if (hushed)
  		return;
  #endif
  	if ((fp = fopen ("/etc/motd", "r")) == (FILE *) 0)
**************
*** 25,29
  
  	fclose (fp);
  	fflush (stdout);
- #endif
  }
--- 29,33 -----
  
  	fclose (fp);
  	fflush (stdout);
  }
  #endif
**************
*** 27,29
  	fflush (stdout);
  #endif
  }
--- 30,33 -----
  	fclose (fp);
  	fflush (stdout);
  }
+ #endif
*** password.c
--- new/password.c
**************
*** 9,15
   *	Need to fake up getpass().  Returns TRUE if a password
   *	was successfully input, and FALSE otherwise, including
   *	EOF on input or ioctl() failure.  pass is not modified
!  *	on failure.
   */
  
  #ifndef	lint
--- 9,16 -----
   *	Need to fake up getpass().  Returns TRUE if a password
   *	was successfully input, and FALSE otherwise, including
   *	EOF on input or ioctl() failure.  pass is not modified
!  *	on failure.  The input length limit may be set by
!  *	changing the value of PASSLIMIT.
   */
  
  #ifndef	lint
**************
*** 13,19
   */
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)password.c	1.3	08:41:05	2/22/89";
  #endif
  
  int	password (prompt, pass)
--- 14,20 -----
   */
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)password.c	1.4	15:59:50	3/4/89";
  #endif
  
  #define	PASSLIMIT	20
**************
*** 16,21
  static	char	_sccsid[] = "@(#)password.c	1.3	08:41:05	2/22/89";
  #endif
  
  int	password (prompt, pass)
  char	*prompt;
  char	*pass;
--- 17,24 -----
  static	char	_sccsid[] = "@(#)password.c	1.4	15:59:50	3/4/89";
  #endif
  
+ #define	PASSLIMIT	20
+ 
  int	password (prompt, pass)
  char	*prompt;
  char	*pass;
**************
*** 47,53
  	ioctl (fileno (fp), TCSETAF, &save);
  
  	if (! eof) {
! 		buf[8] = '\0';
  		if ((cp = strchr (buf, '\n')) || (cp = strchr (buf, '\r')))
  			*cp = '\0'; 
  
--- 50,56 -----
  	ioctl (fileno (fp), TCSETAF, &save);
  
  	if (! eof) {
! 		buf[PASSLIMIT] = '\0';
  		if ((cp = strchr (buf, '\n')) || (cp = strchr (buf, '\r')))
  			*cp = '\0'; 
  
*** pmain.c
--- new/pmain.c
**************
*** 14,20
  #endif
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)pmain.c	1.3	08:41:07	2/22/89";
  #endif
  
  char	name[BUFSIZ];
--- 14,20 -----
  #endif
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)pmain.c	1.4	15:59:52	3/4/89";
  #endif
  
  char	name[BUFSIZ];
**************
*** 63,68
  	FILE	*pwd;
  	char	buf[BUFSIZ];
  #endif
  
  	argc--; argv++;			/* shift ... */
  
--- 63,69 -----
  	FILE	*pwd;
  	char	buf[BUFSIZ];
  #endif
+ 	char	tmp[BUFSIZ];
  
  	argc--; argv++;			/* shift ... */
  
**************
*** 184,191
  #endif
  	(void) time (&salttime);
  	salttime = ((salttime & 07777) ^ ((salttime >> 14) & 07777)) & 07777;
! 	pwent.pw_passwd = crypt (pass, l64a (salttime));
! 
  	/*
  	 * Now we get to race the bad guy.  I don't think he can get us.
  	 *
--- 185,198 -----
  #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.
  	 *
**************
*** 329,335
  	else
  		(void) fprintf (npwd, "%s:", pwent.pw_passwd);
  
! 	(void) fprintf (npwd, "%d:%d:%s:%s:%s",
  		pwent.pw_uid, pwent.pw_gid, pwent.pw_gecos, pwent.pw_dir,
  		pwent.pw_shell ? pwent.pw_shell:"");
  
--- 336,342 -----
  	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:"");
  
**************
*** 346,351
  	fflush (npwd);
  	fclose (npwd);
  #ifdef	NDEBUG
  	if (unlink (OPWDFILE) == -1) {
  		if (errno != ENOENT) {
  			puts ("Can't unlink backup file");
--- 353,359 -----
  	fflush (npwd);
  	fclose (npwd);
  #ifdef	NDEBUG
+ 	chmod (NPWDFILE, 0644);
  	if (unlink (OPWDFILE) == -1) {
  		if (errno != ENOENT) {
  			puts ("Can't unlink backup file");
*** smain.c
--- new/smain.c
**************
*** 7,13
  #include "lastlog.h"
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)smain.c	1.4	08:41:11	2/22/89";
  #endif
  
  #ifndef	MAXENV
--- 7,13 -----
  #include "lastlog.h"
  
  #ifndef	lint
! static	char	_sccsid[] = "@(#)smain.c	1.5	15:59:55	3/4/89";
  #endif
  
  #ifndef	MAXENV
**************
*** 22,27
  #define	SUPATH	":/bin:/usr/bin:/etc"
  #endif
  
  char	name[BUFSIZ];
  char	pass[BUFSIZ];
  char	home[BUFSIZ];
--- 22,32 -----
  #define	SUPATH	":/bin:/usr/bin:/etc"
  #endif
  
+ #ifdef	HUSHLOGIN
+ char	hush[BUFSIZ];
+ int	hushed;
+ #endif
+ 
  char	name[BUFSIZ];
  char	pass[BUFSIZ];
  char	home[BUFSIZ];
**************
*** 50,55
  char	**envp;
  {
  	char	*getenv ();
  	int	doshell;
  	int	fakelogin = 0;
  	int	amroot;
--- 55,61 -----
  char	**envp;
  {
  	char	*getenv ();
+ 	char	*cp;
  	int	doshell;
  	int	fakelogin = 0;
  	int	amroot;
**************
*** 92,98
  		pwent.pw_shell = "/bin/sh";
  
  	if (pwent.pw_name == (char *) 0) { /* unknown user */
! 		(void) fprintf (stderr, "Unknown id: %s\n", pwent.pw_name);
  		exit (1);
  	}
  
--- 98,104 -----
  		pwent.pw_shell = "/bin/sh";
  
  	if (pwent.pw_name == (char *) 0) { /* unknown user */
! 		(void) fprintf (stderr, "Unknown id: %s\n", name);
  		exit (1);
  	}
  
**************
*** 144,149
  		}
  	}
  	if (! doshell) {		/* execute arguments as command */
  		argv[-1] = pwent.pw_shell;
  		(void) execv (pwent.pw_shell, &argv[-1]);
  		(void) fprintf (stderr, "No shell\n");
--- 150,157 -----
  		}
  	}
  	if (! doshell) {		/* execute arguments as command */
+ 		if (cp = getenv ("SHELL"))
+ 			pwent.pw_shell = cp;
  		argv[-1] = pwent.pw_shell;
  		(void) execv (pwent.pw_shell, &argv[-1]);
  		(void) fprintf (stderr, "No shell\n");
**************
*** 150,155
  		exit (1);
  	}
  	if (fakelogin) {
  #ifdef	MOTD
  		motd ();		/* print the message of the day */
  #endif
--- 158,167 -----
  		exit (1);
  	}
  	if (fakelogin) {
+ #ifdef	HUSHLOGIN
+ 		sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
+ 		hushed = access (hush, 0) != -1;
+ #endif
  #ifdef	MOTD
  		motd ();		/* print the message of the day */
  #endif
**************
*** 158,164
  #endif
  		shell (pwent.pw_shell);	/* exec the shell finally. */
  	} else {
! 		execl (pwent.pw_shell, "su", (char *) 0);
  		perror (pwent.pw_shell);
  		exit (1);
  	}
--- 170,181 -----
  #endif
  		shell (pwent.pw_shell);	/* exec the shell finally. */
  	} else {
! 		if (cp = strrchr (pwent.pw_shell, '/'))
! 			cp++;
! 		else
! 			cp = pwent.pw_shell;
! 
! 		execl (pwent.pw_shell, cp, (char *) 0);
  		perror (pwent.pw_shell);
  		exit (1);
  	}
*** su.1
--- new/su.1
**************
*** 18,23
  In particular, an argument of \fB-c\fR will cause the
  next argument to be treated as a command by most command
  interpreters.
  .PP
  The user will be prompted for a password, if appropriate.
  Invalid passwords will produce an error message.
--- 18,26 -----
  In particular, an argument of \fB-c\fR will cause the
  next argument to be treated as a command by most command
  interpreters.
+ The command will be executed under the shell specified by
+ \fB$SHELL\fR, or if undefined, by the one specified in
+ \fI/etc/passwd\fR.
  .PP
  The user will be prompted for a password, if appropriate.
  Invalid passwords will produce an error message.
*** sulogin.c
--- new/sulogin.c
**************
*** 2,7
  #include <stdio.h>
  #include <pwd.h>
  #include <utmp.h>
  #include "config.h"
  #include "lastlog.h"
  
--- 2,8 -----
  #include <stdio.h>
  #include <pwd.h>
  #include <utmp.h>
+ #include <string.h>
  #include "config.h"
  #include "lastlog.h"
  
**************
*** 5,10
  #include "config.h"
  #include "lastlog.h"
  
  char	name[BUFSIZ];
  char	pass[BUFSIZ];
  char	home[BUFSIZ];
--- 6,15 -----
  #include "config.h"
  #include "lastlog.h"
  
+ #ifndef	lint
+ static	char	_sccsid[] = "@(#)sulogin.c	1.2	15:59:59	3/4/89";
+ #endif
+ 
  char	name[BUFSIZ];
  char	pass[BUFSIZ];
  char	home[BUFSIZ];
**************
*** 96,104
  	 * ownership.
  	 */
  
! 	if (cp = ttyname (0))		/* found entry in /dev/ */
! 		strcpy (utent.ut_line, cp); /* needed for tty perms (setup) */
! 		
  	if (getenv ("IFS"))		/* don't export user IFS ... */
  		addenv ("IFS= \t\n");	/* ... instead, set a safe IFS */
  
--- 101,112 -----
  	 * 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 */
  
*** valid.c
--- new/valid.c
**************
*** 1,3
  #include <pwd.h>
  
  /*
--- 1,4 -----
+ #include <stdio.h>
  #include <pwd.h>
  #include <string.h>
  #include "config.h"
**************
*** 1,4
  #include <pwd.h>
  
  /*
   * valid - compare encrypted passwords
--- 1,7 -----
  #include <stdio.h>
  #include <pwd.h>
+ #include <string.h>
+ #include "config.h"
  
  #ifndef	lint
  static	char	_sccsid[] = "@(#)valid.c	1.2	16:00:01	3/4/89";
**************
*** 1,5
  #include <pwd.h>
  
  /*
   * valid - compare encrypted passwords
   *
--- 3,12 -----
  #include <string.h>
  #include "config.h"
  
+ #ifndef	lint
+ static	char	_sccsid[] = "@(#)valid.c	1.2	16:00:01	3/4/89";
+ #endif
+ 
  /*
   * valid - compare encrypted passwords
   *
**************
*** 15,20
  	char	*encrypt;
  	char	*salt;
  	char	*crypt ();
  
  	/*
  	 * Start with blank or empty password entries.  Always encrypt
--- 22,31 -----
  	char	*encrypt;
  	char	*salt;
  	char	*crypt ();
+ #ifdef	DOUBLESIZE
+ 	int	firsthalf;
+ 	int	longpass;
+ #endif
  
  	/*
  	 * Start with blank or empty password entries.  Always encrypt
**************
*** 32,37
  			return (0);	/* user entered something! */
  	}
  
  	/*
  	 * If there is no entry then we need a salt to use.
  	 */
--- 43,52 -----
  			return (0);	/* user entered something! */
  	}
  
+ #ifdef	DOUBLESIZE
+ 	longpass = entry->pw_passwd && strlen (entry->pw_passwd) > 13;
+ #endif
+ 
  	/*
  	 *
  	/*
**************
*** 33,38
  	}
  
  	/*
  	 * If there is no entry then we need a salt to use.
  	 */
  
--- 48,55 -----
  #endif
  
  	/*
+ 	 *
+ 	/*
  	 * If there is no entry then we need a salt to use.
  	 */
  
**************
*** 49,54
  	 */
  
  	encrypt = crypt (password, salt);
  
  	/*
  	 * One last time we must deal with there being no password file
--- 66,74 -----
  	 */
  
  	encrypt = crypt (password, salt);
+ #ifdef	DOUBLESIZE
+ 	firsthalf = entry->pw_passwd
+ 		&& strncmp (encrypt + 2, entry->pw_passwd + 2, 11) == 0;
  
  	if (strlen (password) > 8)
  		encrypt = crypt (password + 8, salt);
**************
*** 50,55
  
  	encrypt = crypt (password, salt);
  
  	/*
  	 * One last time we must deal with there being no password file
  	 * entry for the user.  We use the pw_passwd == NULL idiom to
--- 70,82 -----
  	firsthalf = entry->pw_passwd
  		&& strncmp (encrypt + 2, entry->pw_passwd + 2, 11) == 0;
  
+ 	if (strlen (password) > 8)
+ 		encrypt = crypt (password + 8, salt);
+ 	else {
+ 		(void) crypt (password, salt);	/* waste time ... */
+ 		encrypt = "";
+ 	}
+ #endif
  	/*
  	 * One last time we must deal with there being no password file
  	 * entry for the user.  We use the pw_passwd == NULL idiom to
**************
*** 59,65
  	 * with the salt, which is "xx", not "".
  	 */
  
 	if (entry->pw_passwd && strcmp (encrypt, entry->pw_passwd) == 0)
  		return (1);
  	else
  		return (0);
--- 86,93 -----
  	 * with the salt, which is "xx", not "".
  	 */
  
+ #ifndef	DOUBLESIZE
 	if (entry->pw_passwd && strcmp (encrypt, entry->pw_passwd) == 0)
  		return (1);
  	else
  		return (0);
**************
*** 63,66
  		return (1);
  	else
  		return (0);
  }
--- 91,104 -----
  		return (1);
  	else
  		return (0);
+ #else
+ 	if (! longpass)
+ 		return (firsthalf);
+ 
+ 	if (entry->pw_passwd && firsthalf
+ 			&& strncmp (encrypt + 2, entry->pw_passwd + 13) == 0)
+ 		return (1);
+ 	else
+ 		return (0);
+ #endif
  }
-- 
John F. Haugh II                        +--Quote of the Week:------------------
VoiceNet: (214) 250-3311   Data: -6272  | "Give me your poor huddled masses,
InterNet: jfh@rpp386.Dallas.TX.US       |  Let's club 'em to death ..."
UucpNet : <backbone>!killer!rpp386!jfh  +--------------------------------------