*** sshd.c.orig	Wed Apr 23 04:40:08 1997
--- sshd.c	Wed Jun 11 14:56:57 1997
***************
*** 400,405 ****
--- 400,409 ----
  #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
***************
*** 1542,1547 ****
--- 1546,1583 ----
      endspent();
    }
  #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*".
***************
*** 1553,1558 ****
--- 1589,1595 ----
  	return 0;
        }
    }
+ #endif  /* !FreeBSD */
  #ifdef CHECK_ETC_SHELLS
    {
      int  invalid = 1;
***************
*** 1698,1703 ****
--- 1735,1743 ----
    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;
    pwcopy.pw_dir = xstrdup(pw->pw_dir);
***************
*** 2654,2659 ****
--- 2694,2702 ----
    struct sockaddr_in from;
    int fromlen;
    struct pty_cleanup_context cleanup_context;
+ #ifdef HAVE_LOGIN_CAP_H
+   login_cap_t *lc;
+ #endif
  
    /* We no longer need the child running on user's privileges. */
    userfile_uninit();
***************
*** 2725,2735 ****
        record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname, 
  		   &from);
  
        /* 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;
!       
        /* 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
--- 2768,2786 ----
        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
***************
*** 2749,2754 ****
--- 2800,2828 ----
  	    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
  	 print it in /etc/profile or similar. */
***************
*** 2758,2764 ****
--- 2832,2842 ----
  	  FILE *f;
  
  	  /* Print /etc/motd if it exists. */
+ #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))
***************
*** 2766,2771 ****
--- 2844,2872 ----
  	      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
  
        /* Do common processing for the child, such as execing the command. */
        do_child(command, pw, term, display, auth_proto, auth_data, ttyname);
***************
*** 3017,3023 ****
    char *user_shell;
    char *remote_ip;
    int remote_port;
!   
    /* Check /etc/nologin. */
    f = fopen("/etc/nologin", "r");
    if (f)
--- 3118,3130 ----
    char *user_shell;
    char *remote_ip;
    int remote_port;
! #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");
    if (f)
***************
*** 3031,3036 ****
--- 3138,3144 ----
        if (pw->pw_uid != UID_ROOT)
  	exit(254);
      }
+ #endif /* HAVE_LOGIN_CAP_H */
  
    if (command != NULL)
      {
***************
*** 3043,3049 ****
        else
  	log_msg("executing remote command as user %.200s", pw->pw_name);
      }
!   
  #ifdef HAVE_SETLOGIN
    /* Set login name in the kernel.  Warning: setsid() must be called before
       this. */
--- 3151,3158 ----
        else
  	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. */
***************
*** 3064,3069 ****
--- 3173,3179 ----
    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 
***************
*** 3134,3139 ****
--- 3244,3309 ----
    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)
  	{ 
***************
*** 3165,3170 ****
--- 3335,3341 ----
        
        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
***************
*** 3175,3185 ****
--- 3346,3361 ----
       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)
***************
*** 3189,3194 ****
--- 3365,3372 ----
        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
***************
*** 3200,3205 ****
--- 3378,3384 ----
        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
***************
*** 3215,3223 ****
--- 3394,3404 ----
      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) 
***************
*** 3437,3443 ****
--- 3618,3628 ----
  	  /* 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);
***************
*** 3458,3464 ****
--- 3643,3653 ----
    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);
  }
