X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/022487ce01e98352740bbf211fc36604a7743c71..aa2eae64b7a74e7293a673f5dc101189b5342668:/sshd.c diff --git a/sshd.c b/sshd.c index 7f268526..8a68a537 100644 --- a/sshd.c +++ b/sshd.c @@ -42,7 +42,13 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.307 2005/01/21 08:32:02 otto Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.321 2006/02/10 01:44:27 stevesk Exp $"); + +#include +#include +#include + +#include #include #include @@ -358,7 +364,8 @@ key_regeneration_alarm(int sig) static void sshd_exchange_identification(int sock_in, int sock_out) { - int i, mismatch; + u_int i; + int mismatch; int remote_major, remote_minor; int major, minor; char *s; @@ -632,16 +639,8 @@ privsep_postauth(Authctxt *authctxt) if (authctxt->pw->pw_uid == 0 || options.use_login) { #endif /* File descriptor passing is broken or root login */ - monitor_apply_keystate(pmonitor); use_privsep = 0; - return; - } - - /* Authentication complete */ - alarm(0); - if (startup_pipe != -1) { - close(startup_pipe); - startup_pipe = -1; + goto skip; } /* New socket pair */ @@ -668,8 +667,15 @@ privsep_postauth(Authctxt *authctxt) /* Drop privileges */ do_setusercontext(authctxt->pw); + skip: /* It is safe now to apply the key state */ monitor_apply_keystate(pmonitor); + + /* + * Tell the packet layer that authentication was successful, since + * this information is not part of the key state. + */ + packet_set_authenticated(); } static char * @@ -793,6 +799,7 @@ send_rexec_state(int fd, Buffer *conf) * bignum iqmp " * bignum p " * bignum q " + * string rngseed (only if OpenSSL is not self-seeded) */ buffer_init(&m); buffer_put_cstring(&m, buffer_ptr(conf)); @@ -809,6 +816,10 @@ send_rexec_state(int fd, Buffer *conf) } else buffer_put_int(&m, 0); +#ifndef OPENSSL_PRNG_ONLY + rexec_send_rng_seed(&m); +#endif + if (ssh_msg_send(fd, 0, &m) == -1) fatal("%s: ssh_msg_send failed", __func__); @@ -851,6 +862,11 @@ recv_rexec_state(int fd, Buffer *conf) rsa_generate_additional_parameters( sensitive_data.server_key->rsa); } + +#ifndef OPENSSL_PRNG_ONLY + rexec_recv_rng_seed(&m); +#endif + buffer_free(&m); debug3("%s: done", __func__); @@ -907,6 +923,9 @@ main(int ac, char **av) if (geteuid() == 0 && setgroups(0, NULL) == -1) debug("setgroups(): %.200s", strerror(errno)); + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ + sanitise_stdfd(); + /* Initialize configuration options to their default values. */ initialize_server_options(&options); @@ -1030,13 +1049,13 @@ main(int ac, char **av) SYSLOG_FACILITY_AUTH : options.log_facility, log_stderr || !inetd_flag); -#ifdef _AIX /* * Unset KRB5CCNAME, otherwise the user's session may inherit it from * root's environment - */ - unsetenv("KRB5CCNAME"); -#endif /* _AIX */ + */ + if (getenv("KRB5CCNAME") != NULL) + unsetenv("KRB5CCNAME"); + #ifdef _UNICOS /* Cray can define user privs drop all privs now! * Not needed on PRIV_SU systems! @@ -1044,8 +1063,6 @@ main(int ac, char **av) drop_cray_privs(); #endif - seed_rng(); - sensitive_data.server_key = NULL; sensitive_data.ssh1_host_key = NULL; sensitive_data.have_ssh1_key = 0; @@ -1064,6 +1081,8 @@ main(int ac, char **av) if (!rexec_flag) buffer_free(&cfg); + seed_rng(); + /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); @@ -1268,10 +1287,12 @@ main(int ac, char **av) if (num_listen_socks >= MAX_LISTEN_SOCKS) fatal("Too many listen sockets. " "Enlarge MAX_LISTEN_SOCKS"); - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, + if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), - NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("getnameinfo failed"); + NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { + error("getnameinfo failed: %.100s", + (ret != EAI_SYSTEM) ? gai_strerror(ret) : + strerror(errno)); continue; } /* Create socket for listening. */ @@ -1613,21 +1634,32 @@ main(int ac, char **av) signal(SIGCHLD, SIG_DFL); signal(SIGINT, SIG_DFL); - /* Set SO_KEEPALIVE if requested. */ - if (options.tcp_keep_alive && - setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, - sizeof(on)) < 0) - error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); - /* * Register our connection. This turns encryption off because we do * not have a key. */ packet_set_connection(sock_in, sock_out); + packet_set_server(); - remote_port = get_remote_port(); - remote_ip = get_remote_ipaddr(); + /* Set SO_KEEPALIVE if requested. */ + if (options.tcp_keep_alive && packet_connection_is_on_socket() && + setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) + error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); + if ((remote_port = get_remote_port()) < 0) { + debug("get_remote_port failed"); + cleanup_exit(255); + } + + /* + * We use get_canonical_hostname with usedns = 0 instead of + * get_remote_ipaddr here so IP options will be checked. + */ + remote_ip = get_canonical_hostname(0); + +#ifdef SSH_AUDIT_EVENTS + audit_connection_from(remote_ip, remote_port); +#endif #ifdef LIBWRAP /* Check whether logins are denied from this host. */ if (packet_connection_is_on_socket()) { @@ -1649,10 +1681,10 @@ main(int ac, char **av) verbose("Connection from %.500s port %d", remote_ip, remote_port); /* - * We don\'t want to listen forever unless the other side + * We don't want to listen forever unless the other side * successfully authenticates itself. So we set up an alarm which is * cleared after successful authentication. A limit of zero - * indicates no limit. Note that we don\'t set the alarm in debugging + * indicates no limit. Note that we don't set the alarm in debugging * mode; it is just annoying to have the server exit just when you * are about to discover the bug. */ @@ -1668,6 +1700,8 @@ main(int ac, char **av) authctxt = xmalloc(sizeof(*authctxt)); memset(authctxt, 0, sizeof(*authctxt)); + authctxt->loginmsg = &loginmsg; + /* XXX global for cleanup, access from other modules */ the_authctxt = authctxt; @@ -1697,6 +1731,21 @@ main(int ac, char **av) } authenticated: + /* + * Cancel the alarm we set to limit the time taken for + * authentication. + */ + alarm(0); + signal(SIGALRM, SIG_DFL); + if (startup_pipe != -1) { + close(startup_pipe); + startup_pipe = -1; + } + +#ifdef SSH_AUDIT_EVENTS + audit_event(SSH_AUTH_SUCCESS); +#endif + /* * In privilege separation, we fork another child and prepare * file descriptor passing. @@ -1719,6 +1768,10 @@ main(int ac, char **av) finish_pam(); #endif /* USE_PAM */ +#ifdef SSH_AUDIT_EVENTS + PRIVSEP(audit_event(SSH_CONNECTION_CLOSE)); +#endif + packet_close(); if (use_privsep) @@ -1883,7 +1936,7 @@ do_ssh1_kex(void) if (!rsafail) { BN_mask_bits(session_key_int, sizeof(session_key) * 8); len = BN_num_bytes(session_key_int); - if (len < 0 || len > sizeof(session_key)) { + if (len < 0 || (u_int)len > sizeof(session_key)) { error("do_connection: bad session key len from %s: " "session_key_int %d > sizeof(session_key) %lu", get_remote_ipaddr(), len, (u_long)sizeof(session_key)); @@ -1970,10 +2023,14 @@ do_ssh2_kex(void) myproposal[PROPOSAL_MAC_ALGS_CTOS] = myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; } - if (!options.compression) { + if (options.compression == COMP_NONE) { myproposal[PROPOSAL_COMP_ALGS_CTOS] = myproposal[PROPOSAL_COMP_ALGS_STOC] = "none"; + } else if (options.compression == COMP_DELAYED) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = + myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com"; } + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); /* start key exchange */ @@ -2010,5 +2067,10 @@ cleanup_exit(int i) { if (the_authctxt) do_cleanup(the_authctxt); +#ifdef SSH_AUDIT_EVENTS + /* done after do_cleanup so it can cancel the PAM auth 'thread' */ + if (!use_privsep || mm_is_monitor()) + audit_event(SSH_CONNECTION_ABANDON); +#endif _exit(i); }