--- sshd.c~	Tue Jan 20 05:24:10 1998
+++ sshd.c	Tue Jan 20 14:50:40 1998
@@ -428,6 +428,10 @@
 #include "firewall.h"	/* TIS authsrv authentication */
 #endif
 
+#ifdef HAVE_LOGIN_CAP_H
+#include <login_cap.h>
+#endif
+
 #ifdef _PATH_BSHELL
 #define DEFAULT_SHELL		_PATH_BSHELL
 #else
@@ -1593,7 +1597,39 @@
       }
     endspent();
   }
-#endif /* HAVE_ETC_SHADOW */
+#endif /* HAVE_ETC_SHADOW */
+#ifdef __FreeBSD__
+  {
+    time_t currtime;
+
+    if (pwd->pw_change || pwd->pw_expire)
+ 	currtime = time(NULL);
+
+    /*
+     * Check for an expired password
+     */
+    if (pwd->pw_change && pwd->pw_change <= currtime)
+      {
+	debug("Account %.100s's password is too old - forced to change.",
+	      user);
+	if (options.forced_passwd_change)
+	  forced_command = "/usr/bin/passwd";
+	else
+	  {
+	    return 0;
+	  }
+      }
+    
+    /*
+     * Check for expired account
+     */
+    if (pwd->pw_expire && pwd->pw_expire <= currtime)
+      {
+	debug("Account %.100s has expired - access denied.", user);
+	return 0;
+      }
+  }
+#else   /* !FreeBSD */
   /*
    * Check if account is locked. Check if encrypted password starts
    * with "*LK*".
@@ -1605,6 +1641,7 @@
 	return 0;
       }
   }
+#endif /* !FreeBSD */
 #ifdef CHECK_ETC_SHELLS
   {
     int  invalid = 1;
@@ -1817,6 +1854,9 @@
   memset(&pwcopy, 0, sizeof(pwcopy));
   pwcopy.pw_name = xstrdup(pw->pw_name);
   pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
+#ifdef HAVE_LOGIN_CAP_H
+  pwcopy.pw_class = xstrdup(pw->pw_class);
+#endif
   pwcopy.pw_uid = pw->pw_uid;
   pwcopy.pw_gid = pw->pw_gid;
 #if defined (__bsdi__) && _BSDI_VERSION >= 199510
@@ -2796,6 +2836,9 @@
 #if defined (__bsdi__) && _BSDI_VERSION >= 199510 
   struct timeval tp;
 #endif /*  __bsdi__ && _BSDI_VERSION >= 199510 */
+#ifdef HAVE_LOGIN_CAP_H
+  login_cap_t *lc;
+#endif
 
   /* We no longer need the child running on user's privileges. */
   userfile_uninit();
@@ -2867,11 +2910,19 @@
       record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname, 
 		   &from);
 
+#ifdef HAVE_LOGIN_CAP_H
+      lc = login_getclass(pw->pw_class);
+#endif
+
       /* Check if .hushlogin exists.  Note that we cannot use userfile
          here because we are in the child. */
       sprintf(line, "%.200s/.hushlogin", pw->pw_dir);
       quiet_login = stat(line, &st) >= 0;
       
+#ifdef HAVE_LOGIN_CAP_H
+      quiet_login = login_getcapbool(lc, "hushlogin", quiet_login);
+#endif
+
       /* If the user has logged in before, display the time of last login. 
          However, don't display anything extra if a command has been 
 	 specified (so that ssh can be used to execute commands on a remote
@@ -2890,6 +2941,28 @@
 	  else
 	    printf("Last login: %s from %s\r\n", time_string, buf);
 	}
+#ifdef __FreeBSD__
+      if (command == NULL && !quiet_login)
+	{
+#ifdef HAVE_LOGIN_CAP_H
+	  char *cw;
+	  FILE *f;
+
+	  cw = login_getcapstr(lc, "copyright", NULL, NULL);
+	  if (cw != NULL && (f = fopen(cw, "r")) != NULL)
+	    {
+	      while (fgets(line, sizeof(line), f))
+		fputs(line, stdout);
+	      fclose(f);
+	    }
+	  else
+#endif
+	    printf("%s\n\t%s  %s\n\n",
+	    "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
+	    "The Regents of the University of California. ",
+	    "All rights reserved.");
+	}
+#endif
 
       /* Print /etc/motd unless a command was specified or printing it was
 	 disabled in server options.  Note that some machines appear to
@@ -2900,13 +2973,40 @@
 	  FILE *f;
 
 	  /* Print /etc/motd if it exists. */
-	  f = fopen("/etc/motd", "r");
+#ifdef HAVE_LOGIN_CAP_H
+	  f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", "/etc/motd"), "r");
+#else
+  	  f = fopen("/etc/motd", "r");
+#endif
 	  if (f)
 	    {
 	      while (fgets(line, sizeof(line), f))
 		fputs(line, stdout);
 	      fclose(f);
 	    }
+#ifdef __FreeBSD__
+      if (command == NULL && !quiet_login)
+	{
+#ifdef broken_HAVE_LOGIN_CAP_H
+	  char *mp = getenv("MAIL");
+
+	  if (mp != NULL)
+	    {
+		strncpy(line, mp, sizeof line);
+		line[sizeof line - 1] = '\0';
+	    }
+	  else
+#endif
+	  sprintf(line, "%s/%.200s", _PATH_MAILDIR, pw->pw_name);
+	  if (stat(line, &st) == 0 && st.st_size != 0)
+	    printf("You have %smail.\n",
+		   (st.st_mtime > st.st_atime) ? "new " : "");
+	}
+#endif
+
+#ifdef HAVE_LOGIN_CAP_H
+      login_close(lc);
+#endif
 #if defined (__bsdi__) && _BSDI_VERSION >= 199510
 	  if (pw->pw_change || pw->pw_expire)
 	    (void)gettimeofday(&tp, (struct timezone *)NULL);
@@ -3182,6 +3282,13 @@
 #if defined (__bsdi__) && _BSDI_VERSION >= 199510
   login_cap_t *lc = 0;
 #endif /* __bsdi__  && _BSDI_VERSION >= 199510  */
+#ifdef HAVE_LOGIN_CAP_H
+  login_cap_t *lc;
+  char *real_shell;
+  
+  lc = login_getclass(pw->pw_class);
+  auth_checknologin(lc);
+#else /* !HAVE_LOGIN_CAP_H */
 
   /* Check /etc/nologin. */
   f = fopen("/etc/nologin", "r");
@@ -3203,6 +3310,7 @@
 	exit(254);
 #endif /* __bsdi__  && _BSDI_VERSION >= 199510 */ 
     }
+#endif /* HAVE_LOGIN_CAP_H */
 
   if (command != NULL)
     {
@@ -3216,6 +3324,7 @@
 	log_msg("executing remote command as user %.200s", pw->pw_name);
     }
   
+#ifndef HAVE_LOGIN_CAP_H
 #ifdef HAVE_SETLOGIN
   /* Set login name in the kernel.  Warning: setsid() must be called before
      this. */
@@ -3236,6 +3345,7 @@
   if (setpcred((char *)pw->pw_name, NULL))
     log_msg("setpcred %.100s: %.100s", strerror(errno));
 #endif /* HAVE_USERSEC_H */
+#endif /* !HAVE_LOGIN_CAP_H */
 
   /* Save some data that will be needed so that we can do certain cleanups
      before we switch to user's uid.  (We must clear all sensitive data 
@@ -3306,6 +3416,66 @@
   if (command != NULL || !options.use_login)
 #endif /* USELOGIN */
     {
+#ifdef HAVE_LOGIN_CAP_H
+      char *p, *s, **tmpenv;
+
+      /* Initialize the new environment.
+       */
+      envsize = 64;
+      env = xmalloc(envsize * sizeof(char *));
+      env[0] = NULL;
+
+      child_set_env(&env, &envsize, "PATH", DEFAULT_PATH);
+
+#ifdef MAIL_SPOOL_DIRECTORY
+      sprintf(buf, "%.200s/%.50s", MAIL_SPOOL_DIRECTORY, user_name);
+      child_set_env(&env, &envsize, "MAIL", buf);
+#else /* MAIL_SPOOL_DIRECTORY */
+#ifdef MAIL_SPOOL_FILE
+      sprintf(buf, "%.200s/%.50s", user_dir, MAIL_SPOOL_FILE);
+      child_set_env(&env, &envsize, "MAIL", buf);
+#endif /* MAIL_SPOOL_FILE */
+#endif /* MAIL_SPOOL_DIRECTORY */
+
+      /* Let it inherit timezone if we have one. */
+      if (getenv("TZ"))
+	child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+
+      /* Save previous environment array
+       */
+      tmpenv = environ;
+      environ = env;
+
+      /* Set the user's login environment
+       */
+      if (setusercontext(lc, pw, user_uid, LOGIN_SETALL) < 0)
+	{
+	  perror("setusercontext");
+	  exit(1);
+	}
+
+      p = getenv("PATH");
+      s = xmalloc((p != NULL ? strlen(p) + 1 : 0) + sizeof(SSH_BINDIR));
+      *s = '\0';
+      if (p != NULL)
+	{
+	  strcat(s, p);
+	  strcat(s, ":");
+	}
+      strcat(s, SSH_BINDIR);
+
+      env = environ;
+      environ = tmpenv; /* Restore parent environment */
+      for (envsize = 0; env[envsize] != NULL; ++envsize)
+	;
+      /* Reallocate this to what is expected */
+      envsize = (envsize < 100) ? 100 : envsize + 16;
+      env = xrealloc(env, envsize * sizeof(char *));
+
+      child_set_env(&env, &envsize, "PATH", s);
+      xfree(s);
+
+#else /* !HAVE_LOGIN_CAP_H */
       /* Set uid, gid, and groups. */
       if (getuid() == UID_ROOT || geteuid() == UID_ROOT)
 	{ 
@@ -3337,6 +3507,7 @@
       
       if (getuid() != user_uid || geteuid() != user_uid)
 	fatal("Failed to set uids to %d.", (int)user_uid);
+#endif /* HAVE_LOGIN_CAP_H */
     }
   
   /* Reset signals to their default settings before starting the user
@@ -3364,11 +3535,16 @@
      and means /bin/sh. */
   shell = (user_shell[0] == '\0') ? DEFAULT_SHELL : user_shell;
 
+#ifdef HAVE_LOGIN_CAP_H
+  real_shell = login_getcapstr(lc, "shell", (char*)shell, (char*)shell);
+  login_close(lc);
+#else /* !HAVE_LOGIN_CAP_H */
   /* Initialize the environment.  In the first part we allocate space for
      all environment variables. */
   envsize = 100;
   env = xmalloc(envsize * sizeof(char *));
   env[0] = NULL;
+#endif /* HAVE_LOGIN_CAP_H */
 
 #ifdef USELOGIN
   if (command != NULL || !options.use_login)
@@ -3378,6 +3554,8 @@
       child_set_env(&env, &envsize, "HOME", user_dir);
       child_set_env(&env, &envsize, "USER", user_name);
       child_set_env(&env, &envsize, "LOGNAME", user_name);
+
+#ifndef HAVE_LOGIN_CAP_H
       child_set_env(&env, &envsize, "PATH", DEFAULT_PATH ":" SSH_BINDIR);
       
 #ifdef MAIL_SPOOL_DIRECTORY
@@ -3389,6 +3567,7 @@
       child_set_env(&env, &envsize, "MAIL", buf);
 #endif /* MAIL_SPOOL_FILE */
 #endif /* MAIL_SPOOL_DIRECTORY */
+#endif  /* !HAVE_LOGIN_CAP_H */
       
 #ifdef HAVE_ETC_DEFAULT_LOGIN
       /* Read /etc/default/login; this exists at least on Solaris 2.x.  Note
@@ -3404,9 +3583,11 @@
     child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
 		  original_command);
   
+#ifndef HAVE_LOGIN_CAP_H
   /* Let it inherit timezone if we have one. */
   if (getenv("TZ"))
     child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+#endif /* !HAVE_LOGIN_CAP_H */
   
   /* Set custom environment options from RSA authentication. */
   while (custom_environment) 
@@ -3647,7 +3828,11 @@
 	  /* Execute the shell. */
 	  argv[0] = buf;
 	  argv[1] = NULL;
+#ifdef HAVE_LOGIN_CAP_H
+	  execve(real_shell, argv, env);
+#else
 	  execve(shell, argv, env);
+#endif /* HAVE_LOGIN_CAP_H */
 	  /* Executing the shell failed. */
 	  perror(shell);
 	  exit(1);
@@ -3668,7 +3853,11 @@
   argv[1] = "-c";
   argv[2] = (char *)command;
   argv[3] = NULL;
+#ifdef HAVE_LOGIN_CAP_H
+  execve(real_shell, argv, env);
+#else
   execve(shell, argv, env);
+#endif /* HAVE_LOGIN_CAP_H */
   perror(shell);
   exit(1);
 }
