=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/sshd.c,v retrieving revision 1.263.2.1 retrieving revision 1.263.2.2 diff -u -r1.263.2.1 -r1.263.2.2 --- src/usr.bin/ssh/sshd.c 2003/09/16 20:50:44 1.263.2.1 +++ src/usr.bin/ssh/sshd.c 2004/03/04 18:18:17 1.263.2.2 @@ -42,7 +42,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.263.2.1 2003/09/16 20:50:44 brad Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.263.2.2 2004/03/04 18:18:17 brad Exp $"); #include #include @@ -190,8 +190,11 @@ /* variables used for privilege separation */ int use_privsep; -struct monitor *pmonitor; +struct monitor *pmonitor = NULL; +/* global authentication context */ +Authctxt *the_authctxt = NULL; + /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); void demote_sensitive_data(void); @@ -290,6 +293,9 @@ { /* XXX no idea how fix this signal handler */ + if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0) + kill(pmonitor->m_pid, SIGALRM); + /* Log error and exit. */ fatal("Timeout before authentication for %s", get_remote_ipaddr()); } @@ -363,7 +369,7 @@ strlen(server_version_string)) != strlen(server_version_string)) { logit("Could not write ident string to %s", get_remote_ipaddr()); - fatal_cleanup(); + cleanup_exit(255); } /* Read other sides version identification. */ @@ -372,7 +378,7 @@ if (atomicio(read, sock_in, &buf[i], 1) != 1) { logit("Did not receive identification string from %s", get_remote_ipaddr()); - fatal_cleanup(); + cleanup_exit(255); } if (buf[i] == '\r') { buf[i] = 0; @@ -402,7 +408,7 @@ close(sock_out); logit("Bad protocol version identification '%.100s' from %s", client_version_string, get_remote_ipaddr()); - fatal_cleanup(); + cleanup_exit(255); } debug("Client protocol version %d.%d; client software version %.100s", remote_major, remote_minor, remote_version); @@ -412,13 +418,13 @@ if (datafellows & SSH_BUG_PROBE) { logit("probed from %s with %s. Don't panic.", get_remote_ipaddr(), client_version_string); - fatal_cleanup(); + cleanup_exit(255); } if (datafellows & SSH_BUG_SCANNER) { logit("scanned from %s with %s. Don't panic.", get_remote_ipaddr(), client_version_string); - fatal_cleanup(); + cleanup_exit(255); } mismatch = 0; @@ -464,7 +470,7 @@ logit("Protocol major versions differ for %s: %.200s vs. %.200s", get_remote_ipaddr(), server_version_string, client_version_string); - fatal_cleanup(); + cleanup_exit(255); } } @@ -559,10 +565,9 @@ #endif } -static Authctxt * -privsep_preauth(void) +static int +privsep_preauth(Authctxt *authctxt) { - Authctxt *authctxt = NULL; int status; pid_t pid; @@ -575,12 +580,11 @@ if (pid == -1) { fatal("fork of unprivileged child failed"); } else if (pid != 0) { - fatal_remove_cleanup((void (*) (void *)) packet_close, NULL); - debug2("Network child is on pid %ld", (long)pid); close(pmonitor->m_recvfd); - authctxt = monitor_child_preauth(pmonitor); + pmonitor->m_pid = pid; + monitor_child_preauth(authctxt, pmonitor); close(pmonitor->m_sendfd); /* Sync memory */ @@ -590,11 +594,7 @@ while (waitpid(pid, &status, 0) < 0) if (errno != EINTR) break; - - /* Reinstall, since the child has finished */ - fatal_add_cleanup((void (*) (void *)) packet_close, NULL); - - return (authctxt); + return (1); } else { /* child */ @@ -605,17 +605,12 @@ privsep_preauth_child(); setproctitle("%s", "[net]"); } - return (NULL); + return (0); } static void privsep_postauth(Authctxt *authctxt) { - extern Authctxt *x_authctxt; - - /* XXX - Remote port forwarding */ - x_authctxt = authctxt; - if (authctxt->pw->pw_uid == 0 || options.use_login) { /* File descriptor passing is broken or root login */ monitor_apply_keystate(pmonitor); @@ -637,8 +632,6 @@ if (pmonitor->m_pid == -1) fatal("fork of unprivileged child failed"); else if (pmonitor->m_pid != 0) { - fatal_remove_cleanup((void (*) (void *)) packet_close, NULL); - debug2("User child is on pid %ld", (long)pmonitor->m_pid); close(pmonitor->m_recvfd); monitor_child_postauth(pmonitor); @@ -663,7 +656,8 @@ list_hostkey_types(void) { Buffer b; - char *p; + const char *p; + char *ret; int i; buffer_init(&b); @@ -682,10 +676,10 @@ } } buffer_append(&b, "\0", 1); - p = xstrdup(buffer_ptr(&b)); + ret = xstrdup(buffer_ptr(&b)); buffer_free(&b); - debug("list_hostkey_types: %s", p); - return p; + debug("list_hostkey_types: %s", ret); + return ret; } Key * @@ -753,7 +747,8 @@ static void usage(void) { - fprintf(stderr, "sshd version %s\n", SSH_VERSION); + fprintf(stderr, "sshd version %s, %s\n", + SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); fprintf(stderr, "Usage: %s [options]\n", __progname); fprintf(stderr, "Options:\n"); fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE); @@ -793,11 +788,12 @@ FILE *f; struct addrinfo *ai; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; + char *line; int listen_sock, maxfd; int startup_p[2]; int startups = 0; - Authctxt *authctxt; Key *key; + Authctxt *authctxt; int ret, key_used = 0; /* Save argv. */ @@ -885,9 +881,11 @@ } break; case 'o': - if (process_server_config_line(&options, optarg, + line = xstrdup(optarg); + if (process_server_config_line(&options, line, "command-line", 0) != 0) exit(1); + xfree(line); break; case '?': default: @@ -1116,7 +1114,7 @@ /* Start listening on the port. */ logit("Server listening on %s port %s.", ntop, strport); - if (listen(listen_sock, 5) < 0) + if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0) fatal("listen: %.100s", strerror(errno)); } @@ -1347,8 +1345,8 @@ signal(SIGQUIT, SIG_DFL); signal(SIGCHLD, SIG_DFL); - /* Set keepalives if requested. */ - if (options.keepalives && + /* 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)); @@ -1398,18 +1396,25 @@ packet_set_nonblocking(); + /* allocate authentication context */ + authctxt = xmalloc(sizeof(*authctxt)); + memset(authctxt, 0, sizeof(*authctxt)); + + /* XXX global for cleanup, access from other modules */ + the_authctxt = authctxt; + if (use_privsep) - if ((authctxt = privsep_preauth()) != NULL) + if (privsep_preauth(authctxt) == 1) goto authenticated; /* perform the key exchange */ /* authenticate user and start session */ if (compat20) { do_ssh2_kex(); - authctxt = do_authentication2(); + do_authentication2(authctxt); } else { do_ssh1_kex(); - authctxt = do_authentication(); + do_authentication(authctxt); } /* * If we use privilege separation, the unprivileged child transfers @@ -1432,7 +1437,7 @@ destroy_sensitive_data(); } - /* Perform session preparation. */ + /* Start session. */ do_authenticated(authctxt); /* The connection has been terminated. */ @@ -1718,4 +1723,13 @@ packet_write_wait(); #endif debug("KEX done"); +} + +/* server specific fatal cleanup */ +void +cleanup_exit(int i) +{ + if (the_authctxt) + do_cleanup(the_authctxt); + _exit(i); }