Subject: bin/936: allow login to force password change
To: None <gnats-admin@NetBSD.ORG>
From: Simon J. Gerraty <sjg@zen.void.oz.au>
List: netbsd-bugs
Date: 04/02/1995 13:20:08
>Number:         936
>Category:       bin
>Synopsis:       patch to allow login to force password change on initial login.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Apr  2 13:20:07 1995
>Originator:     Simon J. Gerraty
>Organization:
Zen Programming...
>Release:        Mar27 -current
>Environment:
	
System: NetBSD zen.void.oz.au 1.0A NetBSD 1.0A (ZEN) #0: Wed Mar 29 22:56:59 EST 1995 root@zen.void.oz.au:/d2/current/src/sys/arch/i386/compile/ZEN i386


>Description:
	
The patch below adds support to login(1) for a "magic" change date
that means expire on next login.  This is useful for newly added
accounts or for simply forcing users to change their passwords after
some security event...

Note: if the user authenticated via S/Key they are only warned about
the need for password change as it makes no sense to make a user enter
a password from an insecure terminal.
>How-To-Repeat:
	
>Fix:
	
*** login/login.c.old	Sun Apr  2 13:05:35 1995
--- login/login.c	Sun Apr  2 15:52:47 1995
***************
*** 83,88 ****
--- 83,89 ----
  int	 rootterm __P((char *));
  void	 sigint __P((int));
  void	 sleepexit __P((int));
+ void	do_chpass __P((void));
  char	*stypeof __P((char *));
  void	 timedout __P((int));
  int	 pwcheck __P((char *, char *, char *, char *));
***************
*** 112,117 ****
--- 113,128 ----
  struct	passwd *pwd;
  int	failures;
  char	term[64], *envinit[1], *hostname, *username, *tty;
+ #ifdef SKEY
+ int	used_skey = 0;
+ #endif
+ 
+ #ifndef IMEDIATE_CHANGE
+ # define IMEDIATE_CHANGE 1
+ #endif
+ #ifndef WARN_DAYS
+ # define WARN_DAYS 7				/* give 1 week warning */
+ #endif
  
  int
  main(argc, argv)
***************
*** 128,133 ****
--- 139,145 ----
  	char *domain, *p, *salt, *ttyn;
  	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
  	char localhost[MAXHOSTNAMELEN];
+ 	int need_chpass = 0;
  	
  	(void)signal(SIGALRM, timedout);
  	(void)alarm(timeout);
***************
*** 349,359 ****
  	if (pwd->pw_change || pwd->pw_expire)
  		(void)gettimeofday(&tp, (struct timezone *)NULL);
  	if (pwd->pw_change)
! 		if (tp.tv_sec >= pwd->pw_change) {
  			(void)printf("Sorry -- your password has expired.\n");
  			sleepexit(1);
  		} else if (pwd->pw_change - tp.tv_sec <
! 		    2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
  			(void)printf("Warning: your password expires on %s",
  			    ctime(&pwd->pw_change));
  	if (pwd->pw_expire)
--- 361,373 ----
  	if (pwd->pw_change || pwd->pw_expire)
  		(void)gettimeofday(&tp, (struct timezone *)NULL);
  	if (pwd->pw_change)
! 		if (pwd->pw_change == IMEDIATE_CHANGE) {
! 			need_chpass = 1;
! 		} else if (tp.tv_sec >= pwd->pw_change) {
  			(void)printf("Sorry -- your password has expired.\n");
  			sleepexit(1);
  		} else if (pwd->pw_change - tp.tv_sec <
! 		    WARN_DAYS * DAYSPERWEEK * SECSPERDAY && !quietlog)
  			(void)printf("Warning: your password expires on %s",
  			    ctime(&pwd->pw_change));
  	if (pwd->pw_expire)
***************
*** 361,367 ****
  			(void)printf("Sorry -- your account has expired.\n");
  			sleepexit(1);
  		} else if (pwd->pw_expire - tp.tv_sec <
! 		    2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
  			(void)printf("Warning: your account expires on %s",
  			    ctime(&pwd->pw_expire));
  
--- 375,381 ----
  			(void)printf("Sorry -- your account has expired.\n");
  			sleepexit(1);
  		} else if (pwd->pw_expire - tp.tv_sec <
! 		    WARN_DAYS * DAYSPERWEEK * SECSPERDAY && !quietlog)
  			(void)printf("Warning: your account expires on %s",
  			    ctime(&pwd->pw_expire));
  
***************
*** 457,462 ****
--- 471,480 ----
  	else
  		(void) setuid(pwd->pw_uid);
  
+ 	/* wait until we are un-privileged */
+ 	if (need_chpass)
+ 		do_chpass();
+ 	
  	execlp(pwd->pw_shell, tbuf, 0);
  	err(1, "%s", pwd->pw_shell);
  }
***************
*** 471,477 ****
  			fprintf(stderr, "You have no s/key. ");
  			return 1;
  		} else {
! 			return skey_authenticate(user);
  		}
  	}
  #endif
--- 489,499 ----
  			fprintf(stderr, "You have no s/key. ");
  			return 1;
  		} else {
! 			int ret = skey_authenticate(user);
! 
! 			if (ret == 0)
! 				used_skey = 1;
! 			return ret;
  		}
  	}
  #endif
***************
*** 675,678 ****
--- 697,718 ----
  {
  	(void)sleep(5);
  	exit(eval);
+ }
+ 
+ void
+ do_chpass()
+ {
+ #ifdef SKEY
+ 	/*
+ 	 * if user logged on using skey, don't make them
+ 	 * type a password in...
+ 	 */
+ 	if (used_skey) {
+ 		(void)printf("Warning: your password has expired, change it as soon as possible.\n");
+ 		return;
+ 	}
+ #endif
+ 	(void)printf("Your password has expired, chose a new one.\n");
+ 	if (system("passwd") != 0)
+ 		sleepexit(1);
  }
>Audit-Trail:
>Unformatted: