X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/1c352e975299287eccdd0d883eda976e4cd7c8ff..01dafcb504c448f0d4d5834c21b99e025f492550:/sshd.c diff --git a/sshd.c b/sshd.c index c788ac01..589a1160 100644 --- a/sshd.c +++ b/sshd.c @@ -42,12 +42,16 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.232 2002/03/19 03:03:43 stevesk Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.240 2002/04/23 22:16:29 djm Exp $"); #include #include #include #include +#ifdef HAVE_SECUREWARE +#include +#include +#endif #include "ssh.h" #include "ssh1.h" @@ -276,10 +280,12 @@ sigterm_handler(int sig) static void main_sigchld_handler(int sig) { + pid_t pid; int save_errno = errno; int status; - while (waitpid(-1, &status, WNOHANG) > 0) + while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || + (pid < 0 && errno == EINTR)) ; signal(SIGCHLD, main_sigchld_handler); @@ -516,11 +522,12 @@ demote_sensitive_data(void) /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ } -void +static void privsep_preauth_child(void) { u_int32_t rand[256]; int i; + struct passwd *pw; /* Enable challenge-response authentication for privilege separation */ privsep_challenge_enable(); @@ -532,28 +539,72 @@ privsep_preauth_child(void) /* Demote the private keys to public keys. */ demote_sensitive_data(); + if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) + fatal("Privilege separation user %s does not exist", + SSH_PRIVSEP_USER); + memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); + endpwent(); + /* Change our root directory*/ if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, strerror(errno)); if (chdir("/") == -1) - fatal("chdir(/)"); - + fatal("chdir(\"/\"): %s", strerror(errno)); + /* Drop our privileges */ - setegid(options.unprivileged_group); - setgid(options.unprivileged_group); - seteuid(options.unprivileged_user); - setuid(options.unprivileged_user); + debug3("privsep user:group %u:%u", (u_int)pw->pw_uid, + (u_int)pw->pw_gid); + do_setusercontext(pw); } -void -privsep_postauth(Authctxt *authctxt, pid_t pid) +static Authctxt* +privsep_preauth(void) { - extern Authctxt *x_authctxt; + Authctxt *authctxt = NULL; int status; + pid_t pid; + + /* Set up unprivileged child process to deal with network data */ + monitor = monitor_init(); + /* Store a pointer to the kex for later rekeying */ + monitor->m_pkex = &xxx_kex; + + pid = fork(); + if (pid == -1) { + fatal("fork of unprivileged child failed"); + } else if (pid != 0) { + debug2("Network child is on pid %d", pid); - /* Wait for the child's exit status */ - waitpid(pid, &status, 0); + close(monitor->m_recvfd); + authctxt = monitor_child_preauth(monitor); + close(monitor->m_sendfd); + + /* Sync memory */ + monitor_sync(monitor); + + /* Wait for the child's exit status */ + while (waitpid(pid, &status, 0) < 0) + if (errno != EINTR) + break; + return (authctxt); + } else { + /* child */ + + close(monitor->m_sendfd); + + /* Demote the child */ + if (getuid() == 0 || geteuid() == 0) + privsep_preauth_child(); + setproctitle("%s", "[net]"); + } + return (NULL); +} + +static void +privsep_postauth(Authctxt *authctxt) +{ + extern Authctxt *x_authctxt; /* XXX - Remote port forwarding */ x_authctxt = authctxt; @@ -564,7 +615,7 @@ privsep_postauth(Authctxt *authctxt, pid_t pid) use_privsep = 0; return; } - + /* Authentication complete */ alarm(0); if (startup_pipe != -1) { @@ -579,7 +630,7 @@ privsep_postauth(Authctxt *authctxt, pid_t pid) if (monitor->m_pid == -1) fatal("fork of unprivileged child failed"); else if (monitor->m_pid != 0) { - debug2("User child is on pid %d", pid); + debug2("User child is on pid %d", monitor->m_pid); close(monitor->m_recvfd); monitor_child_postauth(monitor); @@ -599,7 +650,6 @@ privsep_postauth(Authctxt *authctxt, pid_t pid) monitor_apply_keystate(monitor); } - static char * list_hostkey_types(void) { @@ -740,6 +790,9 @@ main(int ac, char **av) Key *key; int ret, key_used = 0; +#ifdef HAVE_SECUREWARE + (void)set_auth_parameters(ac, av); +#endif __progname = get_progname(av[0]); init_rng(); @@ -952,9 +1005,15 @@ main(int ac, char **av) if (test_flag) exit(0); -#ifdef HAVE_SCO_PROTECTED_PW - (void) set_auth_parameters(ac, av); -#endif + /* + * Clear out any supplemental groups we may have inherited. This + * prevents inadvertent creation of files with bad modes (in the + * portable version at least, it's certainly possible for PAM + * to create a file, and we can't control the code in every + * module which might be used). + */ + if (setgroups(0, NULL) < 0) + debug("setgroups() failed: %.200s", strerror(errno)); /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag && !inetd_flag) @@ -1374,36 +1433,9 @@ main(int ac, char **av) packet_set_nonblocking(); - if (!use_privsep) - goto skip_privilegeseparation; - - /* Set up unprivileged child process to deal with network data */ - monitor = monitor_init(); - /* Store a pointer to the kex for later rekeying */ - monitor->m_pkex = &xxx_kex; - - pid = fork(); - if (pid == -1) - fatal("fork of unprivileged child failed"); - else if (pid != 0) { - debug2("Network child is on pid %d", pid); - - close(monitor->m_recvfd); - authctxt = monitor_child_preauth(monitor); - close(monitor->m_sendfd); - - /* Sync memory */ - monitor_sync(monitor); - goto authenticated; - } else { - close(monitor->m_sendfd); - - /* Demote the child */ - if (getuid() == 0 || geteuid() == 0) - privsep_preauth_child(); - } - - skip_privilegeseparation: + if (use_privsep) + if ((authctxt = privsep_preauth()) != NULL) + goto authenticated; /* perform the key exchange */ /* authenticate user and start session */ @@ -1414,20 +1446,23 @@ main(int ac, char **av) do_ssh1_kex(); authctxt = do_authentication(); } - if (use_privsep) + /* + * If we use privilege separation, the unprivileged child transfers + * the current keystate and exits + */ + if (use_privsep) { mm_send_keystate(monitor); - - /* If we use privilege separation, the unprivileged child exits */ - if (use_privsep) exit(0); + } authenticated: - /* + /* * In privilege separation, we fork another child and prepare * file descriptor passing. */ if (use_privsep) { - privsep_postauth(authctxt, pid); + privsep_postauth(authctxt); + /* the monitor process [priv] will not return */ if (!compat20) destroy_sensitive_data(); }