summaryrefslogtreecommitdiff
path: root/security/ssh2
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>1998-01-20 23:50:15 +0000
committerWarner Losh <imp@FreeBSD.org>1998-01-20 23:50:15 +0000
commit935e28b3a26936764d8f5593245307bbc53a1865 (patch)
tree5c404faf5584fe4c68ac81e69ffcdddd36bc3b0b /security/ssh2
parentFix diff lines (path) (diff)
Upgrade to ssh 1.2.22. Please send problems with the upgrade to me.
1.2.22 fixes a security hole with ssh-agent, so users are encouraged to upgrade. OK'd by: Torsten Blum (torstenb@freebsd.org)
Notes
Notes: svn path=/head/; revision=9384
Diffstat (limited to 'security/ssh2')
-rw-r--r--security/ssh2/Makefile6
-rw-r--r--security/ssh2/distinfo2
-rw-r--r--security/ssh2/files/patch-af777
3 files changed, 359 insertions, 426 deletions
diff --git a/security/ssh2/Makefile b/security/ssh2/Makefile
index 16cd427c1be2..d76c5191fbf6 100644
--- a/security/ssh2/Makefile
+++ b/security/ssh2/Makefile
@@ -1,15 +1,15 @@
# New ports collection makefile for: ssh
-# Version required: 1.2.21
+# Version required: 1.2.22
# Date created: 30 Jul 1995
# Whom: torstenb@FreeBSD.ORG
#
-# $Id: Makefile,v 1.48 1997/11/21 15:31:33 markm Exp $
+# $Id: Makefile,v 1.49 1997/12/24 18:46:11 imp Exp $
#
# Maximal ssh package requires YES values for
# USE_PERL, USE_TCPWRAP
#
-DISTNAME= ssh-1.2.21
+DISTNAME= ssh-1.2.22
CATEGORIES= security net
MASTER_SITES= ftp://ftp.funet.fi/pub/unix/security/login/ssh/
diff --git a/security/ssh2/distinfo b/security/ssh2/distinfo
index a539987481fc..93f7656953f2 100644
--- a/security/ssh2/distinfo
+++ b/security/ssh2/distinfo
@@ -1,2 +1,2 @@
-MD5 (ssh-1.2.21.tar.gz) = 881f612cd3598b5370545ab2ad808795
+MD5 (ssh-1.2.22.tar.gz) = 011f2b6d1935c59be0dae299db4ed7fa
MD5 (rsaref2.tar.gz) = 0b474c97bf1f1c0d27e5a95f1239c08d
diff --git a/security/ssh2/files/patch-af b/security/ssh2/files/patch-af
index 736cd569902f..5a41ba201d43 100644
--- a/security/ssh2/files/patch-af
+++ b/security/ssh2/files/patch-af
@@ -1,423 +1,356 @@
-*** 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)
+--- 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*".
-***************
-*** 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);
- }
++
++ /*
++ * 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);
+ }