diff options
author | Jan Pechanec <Jan.Pechanec@Sun.COM> | 2009-03-23 06:46:46 -0700 |
---|---|---|
committer | Jan Pechanec <Jan.Pechanec@Sun.COM> | 2009-03-23 06:46:46 -0700 |
commit | 6f8d59d8fcaf391990ca04c7bdcf65ab23320fe0 (patch) | |
tree | 2cbfb2de5aa13e0c26adf856439b624f7e69fc31 /usr/src/cmd/ssh/libssh/common/uidswap.c | |
parent | ad84d946d04cc1356150710206b0b141a93e935d (diff) | |
download | illumos-gate-6f8d59d8fcaf391990ca04c7bdcf65ab23320fe0.tar.gz |
PSARC/2009/155 ChrootDirectory option for SunSSH server
5043377 provide chroot capability in SunSSH
6809398 default PATH in SunSSH should contain "/bin"
6810759 remove md5crypt.c from SunSSH since it's not used
6813038 Subsystem keyword in sshd_config doesn't accept subsystem's options
6772676 ssh default XAuthLocation should be /usr/X11/bin/xauth
Diffstat (limited to 'usr/src/cmd/ssh/libssh/common/uidswap.c')
-rw-r--r-- | usr/src/cmd/ssh/libssh/common/uidswap.c | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/usr/src/cmd/ssh/libssh/common/uidswap.c b/usr/src/cmd/ssh/libssh/common/uidswap.c index 31acab9341..f5892ee2ac 100644 --- a/usr/src/cmd/ssh/libssh/common/uidswap.c +++ b/usr/src/cmd/ssh/libssh/common/uidswap.c @@ -11,17 +11,18 @@ * called by a name other than "ssh" or "Secure Shell". */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "includes.h" RCSID("$OpenBSD: uidswap.c,v 1.23 2002/07/15 17:15:31 stevesk Exp $"); -#pragma ident "%Z%%M% %I% %E% SMI" +#include <priv.h> #include "log.h" #include "uidswap.h" +#include "servconf.h" /* * Note: all these functions must work in all of the following cases: @@ -164,21 +165,82 @@ restore_uid(void) } /* - * Permanently sets all uids to the given uid. This cannot be - * called while temporarily_use_uid is effective. + * Permanently sets all uids to the given uid. This cannot be called while + * temporarily_use_uid is effective. Note that when the ChrootDirectory option + * is in use we keep a few privileges so that we can call chroot(2) later while + * already running under UIDs of a connecting user. */ void -permanently_set_uid(struct passwd *pw) +permanently_set_uid(struct passwd *pw, char *chroot_directory) { + priv_set_t *pset; + if (temporarily_use_uid_effective) - fatal("permanently_set_uid: temporarily_use_uid effective"); - debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid, - (u_int)pw->pw_gid); + fatal("%s: temporarily_use_uid effective", __func__); + + debug("%s: %u/%u", __func__, (u_int)pw->pw_uid, (u_int)pw->pw_gid); + if (initgroups(pw->pw_name, pw->pw_gid) < 0) fatal("initgroups: %s: %.100s", pw->pw_name, strerror(errno)); + if (setgid(pw->pw_gid) < 0) fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); + + /* + * If root is connecting we are done now. Note that we must have called + * setgid() in case that the SSH server was run under a group other than + * root. + */ + if (pw->pw_uid == 0) + return; + + /* + * This means we will keep all privileges after the UID change. + */ + if (setpflags(PRIV_AWARE, 1) != 0) + fatal("setpflags: %s", strerror(errno)); + + /* Now we are running under UID of the user. */ if (setuid(pw->pw_uid) < 0) fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); + + /* + * We will run with the privileges from the Inheritable set as + * we would have after exec(2) if we had stayed in NPA mode + * before setuid(2) call (see privileges(5), user_attr(4), and + * pam_unix_cred(5)). We want to run with P = E = I, with I as + * set by pam_unix_cred(5). We also add PRIV_PROC_CHROOT, + * obviously, and then PRIV_PROC_FORK and PRIV_PROC_EXEC, since + * those two might have been removed from the I set. Note that + * we are expected to finish the login process without them in + * the I set, the important thing is that those not be passed on + * to a shell or a subsystem later if they were not set in + * pam_unix_cred(5). + */ + if ((pset = priv_allocset()) == NULL) + fatal("priv_allocset: %s", strerror(errno)); + if (getppriv(PRIV_INHERITABLE, pset) != 0) + fatal("getppriv: %s", strerror(errno)); + + /* We do not need PRIV_PROC_CHROOT unless chroot()ing. */ + if (chroot_requested(chroot_directory) && + priv_addset(pset, PRIV_PROC_CHROOT) == -1) { + fatal("%s: priv_addset failed", __func__); + } + + if (priv_addset(pset, PRIV_PROC_FORK) == -1 || + priv_addset(pset, PRIV_PROC_EXEC) == -1) { + fatal("%s: priv_addset failed", __func__); + } + + /* Set only P; this will also set E. */ + if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) == -1) + fatal("setppriv: %s", strerror(errno)); + + /* We don't need the PA flag anymore. */ + if (setpflags(PRIV_AWARE, 0) == -1) + fatal("setpflags: %s", strerror(errno)); + + priv_freeset(pset); } |