summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2002-04-20 04:38:07 +0000
committerache <ache@FreeBSD.org>2002-04-20 04:38:07 +0000
commit9cec8df7cf5511f91cbc40ee111592c4f468a38a (patch)
tree288a0a3e264b3c045fc208d45835d1e593ee031f /crypto
parentda246f9c45ba8e92a06bb47cfe596a9b44b661e5 (diff)
downloadFreeBSD-src-9cec8df7cf5511f91cbc40ee111592c4f468a38a.zip
FreeBSD-src-9cec8df7cf5511f91cbc40ee111592c4f468a38a.tar.gz
Please repeat after me: setusercontext() modifies _current_ environment, but
sshd uses separate child_env. So, to make setusercontext() really does something, environment must be switched before call and passed to child_env back after it. The error here was that modified environment not passed back to child_env, so all variables that setusercontext() adds are lost, including ones from ~/.login_conf
Diffstat (limited to 'crypto')
-rw-r--r--crypto/openssh/session.c82
1 files changed, 58 insertions, 24 deletions
diff --git a/crypto/openssh/session.c b/crypto/openssh/session.c
index 92c99eb..8e6f300 100644
--- a/crypto/openssh/session.c
+++ b/crypto/openssh/session.c
@@ -917,7 +917,7 @@ read_environment_file(char ***env, u_int *envsize,
* Sets any environment variables which have been specified by PAM
*/
static void
-do_pam_environment(char ***env, int *envsize)
+do_pam_environment(char ***env, u_int *envsize)
{
char *equals, var_name[512], var_val[512];
char **pam_env;
@@ -944,33 +944,36 @@ do_pam_environment(char ***env, int *envsize)
#endif /* USE_PAM */
static char **
-do_setup_env(Session *s, const char *shell)
+do_setup_env(char **env, Session *s, const char *shell)
{
char buf[256];
u_int i, envsize;
- char **env;
struct passwd *pw = s->pw;
- /* Initialize the environment. */
- envsize = 100;
- env = xmalloc(envsize * sizeof(char *));
- env[0] = NULL;
+ if (env == NULL) {
+ /* Initialize the environment. */
+ envsize = 100;
+ env = xmalloc(envsize * sizeof(char *));
+ env[0] = NULL;
+ } else {
+ for (envsize = 0; env[envsize] != NULL; ++envsize)
+ ;
+ envsize = (envsize < 100) ? 100 : envsize + 50;
+ env = xrealloc(env, envsize * sizeof(char *));
+ }
if (!options.use_login) {
/* Set basic environment. */
child_set_env(&env, &envsize, "USER", pw->pw_name);
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
-#ifdef HAVE_LOGIN_CAP
- (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);
- child_set_env(&env, &envsize, "PATH", getenv("PATH"));
-#else
+#ifndef LOGIN_CAP
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
-#endif
snprintf(buf, sizeof buf, "%.200s/%.50s",
_PATH_MAILDIR, pw->pw_name);
child_set_env(&env, &envsize, "MAIL", buf);
+#endif /* !LOGIN_CAP */
/* Normal systems set SHELL by default. */
child_set_env(&env, &envsize, "SHELL", shell);
@@ -1135,17 +1138,47 @@ do_nologin(struct passwd *pw)
}
/* Set login name, uid, gid, and groups. */
-static void
+static char **
do_setusercontext(struct passwd *pw)
{
- if (getuid() == 0 || geteuid() == 0) {
+ char **env = NULL;
#ifdef HAVE_LOGIN_CAP
- if (setusercontext(lc, pw, pw->pw_uid,
- (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
- perror("unable to set user context");
- exit(1);
- }
-#else
+ char buf[256];
+ char **tmpenv;
+ u_int envsize;
+ extern char **environ;
+
+ /* Initialize the environment. */
+ envsize = 100;
+ env = xmalloc(envsize * sizeof(char *));
+ env[0] = NULL;
+
+ child_set_env(&env, &envsize, "PATH",
+ (pw->pw_uid == 0) ?
+ _PATH_STDPATH : _PATH_DEFPATH);
+
+ snprintf(buf, sizeof buf, "%.200s/%.50s",
+ _PATH_MAILDIR, pw->pw_name);
+ child_set_env(&env, &envsize, "MAIL", buf);
+
+ if (getenv("TZ"))
+ child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+
+ /* Save parent environment */
+ tmpenv = environ;
+ /* Switch to env */
+ environ = env;
+
+ if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETALL) < 0)
+ fatal("setusercontext failed: %s", strerror(errno));
+
+ /* NOTE: Modified environment now passed to env! */
+ env = environ;
+ /* Restore parent environment */
+ environ = tmpenv;
+
+#else /* !HAVE_LOGIN_CAP */
+ if (getuid() == 0 || geteuid() == 0) {
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
if (setgid(pw->pw_gid) < 0) {
@@ -1161,10 +1194,11 @@ do_setusercontext(struct passwd *pw)
/* Permanently switch to the desired uid. */
permanently_set_uid(pw);
-#endif
}
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
+#endif /* HAVE_LOGIN_CAP */
+ return env;
}
/*
@@ -1176,7 +1210,7 @@ void
do_child(Session *s, const char *command)
{
extern char **environ;
- char **env;
+ char **env = NULL;
char *argv[10];
const char *shell, *shell0, *hostname = NULL;
struct passwd *pw = s->pw;
@@ -1195,7 +1229,7 @@ do_child(Session *s, const char *command)
*/
if (!options.use_login) {
do_nologin(pw);
- do_setusercontext(pw);
+ env = do_setusercontext(pw);
}
/*
@@ -1207,7 +1241,7 @@ do_child(Session *s, const char *command)
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
#endif
- env = do_setup_env(s, shell);
+ env = do_setup_env(env, s, shell);
/* we have to stash the hostname before we close our socket. */
if (options.use_login)
OpenPOWER on IntegriCloud