Merge branch 'vendor/OPENSSH'
[dragonfly.git] / crypto / openssh / sshd.c
index e15e8b2..d3c94be 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.393 2012/07/10 02:19:15 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -243,6 +243,7 @@ int startup_pipe;           /* in child */
 /* variables used for privilege separation */
 int use_privsep = -1;
 struct monitor *pmonitor = NULL;
+int privsep_is_preauth = 1;
 
 /* global authentication context */
 Authctxt *the_authctxt = NULL;
@@ -422,9 +423,11 @@ sshd_exchange_identification(int sock_in, int sock_out)
                major = PROTOCOL_MAJOR_1;
                minor = PROTOCOL_MINOR_1;
        }
-       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
-           SSH_RELEASE, newline);
-       server_version_string = xstrdup(buf);
+
+       xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s",
+           major, minor, SSH_VERSION,
+           *options.version_addendum == '\0' ? "" : " ",
+           options.version_addendum, newline);
 
        /* Send our protocol version identification. */
        if (roaming_atomicio(vwrite, sock_out, server_version_string,
@@ -639,7 +642,7 @@ privsep_preauth(Authctxt *authctxt)
        /* Store a pointer to the kex for later rekeying */
        pmonitor->m_pkex = &xxx_kex;
 
-       if (use_privsep == PRIVSEP_SANDBOX)
+       if (use_privsep == PRIVSEP_ON)
                box = ssh_sandbox_init();
        pid = fork();
        if (pid == -1) {
@@ -647,9 +650,9 @@ privsep_preauth(Authctxt *authctxt)
        } else if (pid != 0) {
                debug2("Network child is on pid %ld", (long)pid);
 
+               pmonitor->m_pid = pid;
                if (box != NULL)
                        ssh_sandbox_parent_preauth(box, pid);
-               pmonitor->m_pid = pid;
                monitor_child_preauth(authctxt, pmonitor);
 
                /* Sync memory */
@@ -657,10 +660,13 @@ privsep_preauth(Authctxt *authctxt)
 
                /* Wait for the child's exit status */
                while (waitpid(pid, &status, 0) < 0) {
-                       if (errno != EINTR)
-                               fatal("%s: waitpid: %s", __func__,
-                                   strerror(errno));
+                       if (errno == EINTR)
+                               continue;
+                       pmonitor->m_pid = -1;
+                       fatal("%s: waitpid: %s", __func__, strerror(errno));
                }
+               privsep_is_preauth = 0;
+               pmonitor->m_pid = -1;
                if (WIFEXITED(status)) {
                        if (WEXITSTATUS(status) != 0)
                                fatal("%s: preauth child exited with status %d",
@@ -1184,7 +1190,10 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
                        if (*newsock < 0) {
                                if (errno != EINTR && errno != EAGAIN &&
                                    errno != EWOULDBLOCK)
-                                       error("accept: %.100s", strerror(errno));
+                                       error("accept: %.100s",
+                                           strerror(errno));
+                               if (errno == EMFILE || errno == ENFILE)
+                                       usleep(100 * 1000);
                                continue;
                        }
                        if (unset_nonblock(*newsock) == -1) {
@@ -1330,14 +1339,14 @@ main(int ac, char **av)
        int opt, i, j, on = 1;
        int sock_in = -1, sock_out = -1, newsock = -1;
        const char *remote_ip;
-       char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
        int remote_port;
-       char *line, *p, *cp;
+       char *line;
        int config_s[2] = { -1 , -1 };
        u_int64_t ibytes, obytes;
        mode_t new_umask;
        Key *key;
        Authctxt *authctxt;
+       struct connection_info *connection_info = get_connection_info(0, 0);
 
 #ifdef HAVE_SECUREWARE
        (void)set_auth_parameters(ac, av);
@@ -1459,20 +1468,9 @@ main(int ac, char **av)
                        test_flag = 2;
                        break;
                case 'C':
-                       cp = optarg;
-                       while ((p = strsep(&cp, ",")) && *p != '\0') {
-                               if (strncmp(p, "addr=", 5) == 0)
-                                       test_addr = xstrdup(p + 5);
-                               else if (strncmp(p, "host=", 5) == 0)
-                                       test_host = xstrdup(p + 5);
-                               else if (strncmp(p, "user=", 5) == 0)
-                                       test_user = xstrdup(p + 5);
-                               else {
-                                       fprintf(stderr, "Invalid test "
-                                           "mode specification %s\n", p);
-                                       exit(1);
-                               }
-                       }
+                       if (parse_server_match_testspec(connection_info,
+                           optarg) == -1)
+                               exit(1);
                        break;
                case 'u':
                        utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);
@@ -1484,7 +1482,7 @@ main(int ac, char **av)
                case 'o':
                        line = xstrdup(optarg);
                        if (process_server_config_line(&options, line,
-                           "command-line", 0, NULL, NULL, NULL, NULL) != 0)
+                           "command-line", 0, NULL, NULL) != 0)
                                exit(1);
                        xfree(line);
                        break;
@@ -1521,7 +1519,7 @@ main(int ac, char **av)
         * root's environment
         */
        if (getenv("KRB5CCNAME") != NULL)
-               unsetenv("KRB5CCNAME");
+               (void) unsetenv("KRB5CCNAME");
 
 #ifdef _UNICOS
        /* Cray can define user privs drop all privs now!
@@ -1540,13 +1538,10 @@ main(int ac, char **av)
         * the parameters we need.  If we're not doing an extended test,
         * do not silently ignore connection test params.
         */
-       if (test_flag >= 2 &&
-          (test_user != NULL || test_host != NULL || test_addr != NULL)
-           && (test_user == NULL || test_host == NULL || test_addr == NULL))
+       if (test_flag >= 2 && server_match_spec_complete(connection_info) == 0)
                fatal("user, host and addr are all required when testing "
                   "Match configs");
-       if (test_flag < 2 && (test_user != NULL || test_host != NULL ||
-           test_addr != NULL))
+       if (test_flag < 2 && server_match_spec_complete(connection_info) >= 0)
                fatal("Config test connection parameter (-C) provided without "
                   "test mode (-T)");
 
@@ -1558,7 +1553,7 @@ main(int ac, char **av)
                load_server_config(config_file_name, &cfg);
 
        parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
-           &cfg, NULL, NULL, NULL);
+           &cfg, NULL);
 
        seed_rng();
 
@@ -1735,9 +1730,8 @@ main(int ac, char **av)
        }
 
        if (test_flag > 1) {
-               if (test_user != NULL && test_addr != NULL && test_host != NULL)
-                       parse_server_match_config(&options, test_user,
-                           test_host, test_addr);
+               if (server_match_spec_complete(connection_info) == 1)
+                       parse_server_match_config(&options, connection_info);
                dump_config(&options);
        }
 
@@ -2407,8 +2401,16 @@ do_ssh2_kex(void)
 void
 cleanup_exit(int i)
 {
-       if (the_authctxt)
+       if (the_authctxt) {
                do_cleanup(the_authctxt);
+               if (use_privsep && privsep_is_preauth && pmonitor->m_pid > 1) {
+                       debug("Killing privsep child %d", pmonitor->m_pid);
+                       if (kill(pmonitor->m_pid, SIGKILL) != 0 &&
+                           errno != ESRCH)
+                               error("%s: kill(%d): %s", __func__,
+                                   pmonitor->m_pid, strerror(errno));
+               }
+       }
 #ifdef SSH_AUDIT_EVENTS
        /* done after do_cleanup so it can cancel the PAM auth 'thread' */
        if (!use_privsep || mm_is_monitor())