From e1a790d0d165ff70acb502fbfc72bd55cd2b8fb1 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Tue, 16 Sep 2003 11:52:19 +1000 Subject: - (dtucker) [acconfig.h configure.ac defines.h session.c] Bug #252: Retrieve PATH (or SUPATH) and UMASK from /etc/default/login on platforms that have it (eg Solaris, Reliant Unix). Patch from Robert.Dahlem at siemens.com. ok djm@ --- ChangeLog | 7 +++++- acconfig.h | 5 +++- configure.ac | 45 ++++++++++++++++++++++++++-------- defines.h | 6 ++++- session.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 123 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3f1a4cfec..6a32bc1a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +20030916 + - (dtucker) [acconfig.h configure.ac defines.h session.c] Bug #252: Retrieve + PATH (or SUPATH) and UMASK from /etc/default/login on platforms that have it + (eg Solaris, Reliant Unix). Patch from Robert.Dahlem at siemens.com. ok djm@ + 20030914 - (dtucker) [Makefile regress/Makefile] Fix portability issues preventing the regression tests from running with Solaris' make. Patch from Brian @@ -1093,4 +1098,4 @@ - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. Report from murple@murple.net, diagnosis from dtucker@zip.com.au -$Id: ChangeLog,v 1.2991 2003/09/14 03:16:55 dtucker Exp $ +$Id: ChangeLog,v 1.2992 2003/09/16 01:52:19 dtucker Exp $ diff --git a/acconfig.h b/acconfig.h index ea8fcb0b4..9bfb9b6c9 100644 --- a/acconfig.h +++ b/acconfig.h @@ -1,4 +1,4 @@ -/* $Id: acconfig.h,v 1.165 2003/09/08 21:35:17 tim Exp $ */ +/* $Id: acconfig.h,v 1.166 2003/09/16 01:52:19 dtucker Exp $ */ /* * Copyright (c) 1999-2003 Damien Miller. All rights reserved. @@ -359,6 +359,9 @@ /* Define in your struct dirent expects you to allocate extra space for d_name */ #undef BROKEN_ONE_BYTE_DIRENT_D_NAME +/* Define if your system has /etc/default/login */ +#undef HAVE_ETC_DEFAULT_LOGIN + /* Define if your getopt(3) defines and uses optreset */ #undef HAVE_GETOPT_OPTRESET diff --git a/configure.ac b/configure.ac index 3d5389cce..ab630115b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.153 2003/09/13 01:15:15 tim Exp $ +# $Id: configure.ac,v 1.154 2003/09/16 01:52:19 dtucker Exp $ AC_INIT AC_CONFIG_SRCDIR([ssh.c]) @@ -250,6 +250,7 @@ mips-sony-bsd|mips-sony-newsos4) AC_DEFINE(LOCKED_PASSWD_STRING, "*LK*") # Pushing STREAMS modules will cause sshd to acquire a controlling tty. AC_DEFINE(SSHD_ACQUIRES_CTTY) + external_path_file=/etc/default/login # hardwire lastlog location (can't detect it on some versions) conf_lastlog_location="/var/adm/lastlog" AC_MSG_CHECKING(for obsolete utmp and wtmp in solaris2.x) @@ -286,6 +287,7 @@ mips-sony-bsd|mips-sony-newsos4) AC_DEFINE(USE_PIPES) AC_DEFINE(IP_TOS_IS_BROKEN) AC_DEFINE(SSHD_ACQUIRES_CTTY) + external_path_file=/etc/default/login # /usr/ucblib/libucb.a no longer needed on ReliantUNIX # Attention: always take care to bind libsocket and libnsl before libc, # otherwise you will find lots of "SIOCGPGRP errno 22" on syslog @@ -2180,30 +2182,48 @@ else ) fi +# check for /etc/default/login and use it if present. +AC_CHECK_FILE("/etc/default/login", [ external_path_file=/etc/default/login ]) + +if test "x$external_path_file" = "x/etc/default/login"; then + AC_DEFINE(HAVE_ETC_DEFAULT_LOGIN) +fi + dnl BSD systems use /etc/login.conf so --with-default-path= has no effect if test $ac_cv_func_login_getcapbool = "yes" -a \ $ac_cv_header_login_cap_h = "yes" ; then - USES_LOGIN_CONF=yes + external_path_file=/etc/login.conf fi + # Whether to mess with the default path SERVER_PATH_MSG="(default)" AC_ARG_WITH(default-path, [ --with-default-path= Specify default \$PATH environment for server], [ - if test "$USES_LOGIN_CONF" = "yes" ; then + if test "x$external_path_file" = "x/etc/login.conf" ; then AC_MSG_WARN([ --with-default-path=PATH has no effect on this system. Edit /etc/login.conf instead.]) elif test "x$withval" != "xno" ; then + if ! test -z "$external_path_file" ; then + AC_MSG_WARN([ +--with-default-path=PATH will only be used if PATH is not defined in +$external_path_file .]) + fi user_path="$withval" SERVER_PATH_MSG="$withval" fi ], - [ if test "$USES_LOGIN_CONF" = "yes" ; then - AC_MSG_WARN([Make sure the path to scp is in /etc/login.conf]) + [ if test "x$external_path_file" = "x/etc/login.conf" ; then + AC_MSG_WARN([Make sure the path to scp is in /etc/login.conf]) else - AC_TRY_RUN( - [ + if ! test -z "$external_path_file" ; then + AC_MSG_WARN([ +If PATH is defined in $external_path_file, ensure the path to scp is included, +otherwise scp will not work.]) + fi + AC_TRY_RUN( + [ /* find out what STDPATH is */ #include #ifdef HAVE_PATHS_H @@ -2257,7 +2277,7 @@ main() fi fi ] ) -if test "$USES_LOGIN_CONF" != "yes" ; then +if test "x$external_path_file" != "x/etc/login.conf" ; then AC_DEFINE_UNQUOTED(USER_PATH, "$user_path") AC_SUBST(user_path) fi @@ -2627,10 +2647,15 @@ echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" echo " Privilege separation chroot path: $H" -if test "$USES_LOGIN_CONF" = "yes" ; then -echo " At runtime, sshd will use the path defined in /etc/login.conf" +if test "x$external_path_file" = "x/etc/login.conf" ; then +echo " At runtime, sshd will use the path defined in $external_path_file" +echo " Make sure the path to scp is present, otherwise scp will not work" else echo " sshd default user PATH: $I" + if ! test -z "$external_path_file"; then +echo " (If PATH is set in $external_path_file it will be used instead. If" +echo " used, ensure the path to scp is present, otherwise scp will not work.)" + fi fi if test ! -z "$superuser_path" ; then echo " sshd superuser user PATH: $J" diff --git a/defines.h b/defines.h index 7bff839cc..e662966fb 100644 --- a/defines.h +++ b/defines.h @@ -25,7 +25,7 @@ #ifndef _DEFINES_H #define _DEFINES_H -/* $Id: defines.h,v 1.102 2003/08/26 01:58:16 dtucker Exp $ */ +/* $Id: defines.h,v 1.103 2003/09/16 01:52:19 dtucker Exp $ */ /* Constants */ @@ -321,6 +321,10 @@ struct winsize { # define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" #endif +#ifndef SUPERUSER_PATH +# define SUPERUSER_PATH _PATH_STDPATH +#endif + #ifndef _PATH_DEVNULL # define _PATH_DEVNULL "/dev/null" #endif diff --git a/session.c b/session.c index 35328ecbb..4497f5c0b 100644 --- a/session.c +++ b/session.c @@ -801,6 +801,16 @@ child_set_env(char ***envp, u_int *envsizep, const char *name, u_int i, namelen; char **env; + /* + * If we're passed an uninitialized list, allocate a single null + * entry before continuing. + */ + if (*envp == NULL && *envsizep == 0) { + *envp = xmalloc(sizeof(char *)); + *envp[0] = NULL; + *envsizep = 1; + } + /* * Find the slot where the value should be stored. If the variable * already exists, we reuse the slot; otherwise we append a new slot @@ -877,6 +887,59 @@ read_environment_file(char ***env, u_int *envsize, fclose(f); } +#ifdef HAVE_ETC_DEFAULT_LOGIN +/* + * Return named variable from specified environment, or NULL if not present. + */ +static char * +child_get_env(char **env, const char *name) +{ + int i; + size_t len; + + len = strlen(name); + for (i=0; env[i] != NULL; i++) + if (strncmp(name, env[i], len) == 0 && env[i][len] == '=') + return(env[i] + len + 1); + return NULL; +} + +/* + * Read /etc/default/login. + * We pick up the PATH (or SUPATH for root) and UMASK. + */ +static void +read_etc_default_login(char ***env, u_int *envsize, uid_t uid) +{ + char **tmpenv = NULL, *var; + u_int i; + size_t tmpenvsize = 0; + mode_t mask; + + /* + * We don't want to copy the whole file to the child's environment, + * so we use a temporary environment and copy the variables we're + * interested in. + */ + read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login"); + + if (uid == 0) + var = child_get_env(tmpenv, "SUPATH"); + else + var = child_get_env(tmpenv, "PATH"); + if (var != NULL) + child_set_env(env, envsize, "PATH", var); + + if ((var = child_get_env(tmpenv, "UMASK")) != NULL) + if (sscanf(var, "%5lo", &mask) == 1) + umask(mask); + + for (i = 0; tmpenv[i] != NULL; i++) + xfree(tmpenv[i]); + xfree(tmpenv); +} +#endif /* HAVE_ETC_DEFAULT_LOGIN */ + void copy_environment(char **source, char ***env, u_int *envsize) { char *var_name, *var_val; @@ -905,7 +968,7 @@ do_setup_env(Session *s, const char *shell) { char buf[256]; u_int i, envsize; - char **env, *laddr; + char **env, *laddr, *path = NULL; struct passwd *pw = s->pw; /* Initialize the environment. */ @@ -949,12 +1012,15 @@ do_setup_env(Session *s, const char *shell) * needed for loading shared libraries. So the path better * remains intact here. */ -# ifdef SUPERUSER_PATH - child_set_env(&env, &envsize, "PATH", - s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH); -# else - child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); -# endif /* SUPERUSER_PATH */ +# ifdef HAVE_ETC_DEFAULT_LOGIN + read_etc_default_login(&env, &envsize, pw->pw_uid); + path = child_get_env(env, "PATH"); +# endif /* HAVE_ETC_DEFAULT_LOGIN */ + if (path == NULL || *path == '\0') { + child_set_env(&env, &envsize, "PATH", + s->pw->pw_uid == 0 ? + SUPERUSER_PATH : _PATH_STDPATH); + } # endif /* HAVE_CYGWIN */ #endif /* HAVE_LOGIN_CAP */ -- cgit v1.2.3