diff options
Diffstat (limited to 'crypto/openssh/sshd.c')
-rw-r--r-- | crypto/openssh/sshd.c | 95 |
1 files changed, 54 insertions, 41 deletions
diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c index fa79b63..937ad1e 100644 --- a/crypto/openssh/sshd.c +++ b/crypto/openssh/sshd.c @@ -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 $ */ /* $FreeBSD$ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -251,6 +251,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; @@ -430,9 +431,12 @@ 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_version_get(options.hpn_disabled), newline); - server_version_string = xstrdup(buf); + + xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s%s", + major, minor, SSH_VERSION, + options.hpn_disabled ? "" : SSH_VERSION_HPN, + *options.version_addendum == '\0' ? "" : " ", + options.version_addendum, newline); /* Send our protocol version identification. */ if (roaming_atomicio(vwrite, sock_out, server_version_string, @@ -644,7 +648,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) { @@ -652,9 +656,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 */ @@ -662,10 +666,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", @@ -893,8 +900,14 @@ drop_connection(int startups) static void usage(void) { - fprintf(stderr, "%s, %s\n", - ssh_version_get(0), SSLeay_version(SSLEAY_VERSION)); + if (options.version_addendum && *options.version_addendum != '\0') + fprintf(stderr, "%s%s %s, %s\n", + SSH_RELEASE, options.hpn_disabled ? "" : SSH_VERSION_HPN, + options.version_addendum, SSLeay_version(SSLEAY_VERSION)); + else + fprintf(stderr, "%s%s, %s\n", + SSH_RELEASE, options.hpn_disabled ? "" : SSH_VERSION_HPN, + SSLeay_version(SSLEAY_VERSION)); fprintf(stderr, "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n" " [-f config_file] [-g login_grace_time] [-h host_key_file]\n" @@ -1189,7 +1202,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) { @@ -1335,14 +1351,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); @@ -1464,20 +1480,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); @@ -1489,7 +1494,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; @@ -1526,7 +1531,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! @@ -1545,13 +1550,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)"); @@ -1563,7 +1565,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(); @@ -1583,7 +1585,11 @@ main(int ac, char **av) exit(1); } - debug("sshd version %.100s", ssh_version_get(options.hpn_disabled)); + debug("sshd version %.100s%.100s%s%.100s", + SSH_RELEASE, + options.hpn_disabled ? "" : SSH_VERSION_HPN, + *options.version_addendum == '\0' ? "" : " ", + options.version_addendum); /* Store privilege separation user for later use if required. */ if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { @@ -1725,9 +1731,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); } @@ -2415,8 +2420,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()) |