X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/7fdc56c58e49d0ea8ef458712b8fcb319a24f461..9a6fee8b2b42608a177803d2351d3cfe732910d8:/sshd.c diff --git a/sshd.c b/sshd.c index 765dac99..62b4f45f 100644 --- a/sshd.c +++ b/sshd.c @@ -42,7 +42,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.254 2002/06/30 21:54:16 deraadt Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.263 2003/02/16 17:09:57 markus Exp $"); #include #include @@ -202,8 +202,8 @@ int *startup_pipes = NULL; int startup_pipe; /* in child */ /* variables used for privilege separation */ -extern struct monitor *pmonitor; -extern int use_privsep; +int use_privsep; +struct monitor *pmonitor; /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); @@ -258,11 +258,11 @@ sighup_handler(int sig) static void sighup_restart(void) { - log("Received SIGHUP; restarting."); + logit("Received SIGHUP; restarting."); close_listen_socks(); close_startup_pipes(); execv(saved_argv[0], saved_argv); - log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], + logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], strerror(errno)); exit(1); } @@ -303,11 +303,8 @@ grace_alarm_handler(int sig) { /* XXX no idea how fix this signal handler */ - /* Close the connection. */ - packet_close(); - /* Log error and exit. */ - fatal("Timeout before authentication for %s.", get_remote_ipaddr()); + fatal("Timeout before authentication for %s", get_remote_ipaddr()); } /* @@ -379,7 +376,7 @@ sshd_exchange_identification(int sock_in, int sock_out) if (atomicio(write, sock_out, server_version_string, strlen(server_version_string)) != strlen(server_version_string)) { - log("Could not write ident string to %s", get_remote_ipaddr()); + logit("Could not write ident string to %s", get_remote_ipaddr()); fatal_cleanup(); } @@ -387,7 +384,7 @@ sshd_exchange_identification(int sock_in, int sock_out) memset(buf, 0, sizeof(buf)); for (i = 0; i < sizeof(buf) - 1; i++) { if (atomicio(read, sock_in, &buf[i], 1) != 1) { - log("Did not receive identification string from %s", + logit("Did not receive identification string from %s", get_remote_ipaddr()); fatal_cleanup(); } @@ -418,7 +415,7 @@ sshd_exchange_identification(int sock_in, int sock_out) (void) atomicio(write, sock_out, s, strlen(s)); close(sock_in); close(sock_out); - log("Bad protocol version identification '%.100s' from %s", + logit("Bad protocol version identification '%.100s' from %s", client_version_string, get_remote_ipaddr()); fatal_cleanup(); } @@ -427,8 +424,14 @@ sshd_exchange_identification(int sock_in, int sock_out) compat_datafellows(remote_version); + if (datafellows & SSH_BUG_PROBE) { + logit("probed from %s with %s. Don't panic.", + get_remote_ipaddr(), client_version_string); + fatal_cleanup(); + } + if (datafellows & SSH_BUG_SCANNER) { - log("scanned from %s with %s. Don't panic.", + logit("scanned from %s with %s. Don't panic.", get_remote_ipaddr(), client_version_string); fatal_cleanup(); } @@ -473,7 +476,7 @@ sshd_exchange_identification(int sock_in, int sock_out) (void) atomicio(write, sock_out, s, strlen(s)); close(sock_in); close(sock_out); - log("Protocol major versions differ for %s: %.200s vs. %.200s", + logit("Protocol major versions differ for %s: %.200s vs. %.200s", get_remote_ipaddr(), server_version_string, client_version_string); fatal_cleanup(); @@ -550,7 +553,7 @@ privsep_preauth_child(void) memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); endpwent(); - /* Change our root directory*/ + /* Change our root directory */ if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, strerror(errno)); @@ -573,7 +576,7 @@ privsep_preauth_child(void) #endif } -static Authctxt* +static Authctxt * privsep_preauth(void) { Authctxt *authctxt = NULL; @@ -589,6 +592,8 @@ privsep_preauth(void) 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); @@ -602,6 +607,10 @@ privsep_preauth(void) 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); } else { /* child */ @@ -624,7 +633,7 @@ privsep_postauth(Authctxt *authctxt) /* XXX - Remote port forwarding */ x_authctxt = authctxt; -#ifdef BROKEN_FD_PASSING +#ifdef DISABLE_FD_PASSING if (1) { #else if (authctxt->pw->pw_uid == 0 || options.use_login) { @@ -649,6 +658,8 @@ privsep_postauth(Authctxt *authctxt) 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); @@ -801,7 +812,6 @@ main(int ac, char **av) const char *remote_ip; int remote_port; FILE *f; - struct linger linger; struct addrinfo *ai; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; int listen_sock, maxfd; @@ -817,9 +827,17 @@ main(int ac, char **av) __progname = get_progname(av[0]); init_rng(); - /* Save argv. */ + /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; saved_argv = av; + saved_argv = xmalloc(sizeof(*saved_argv) * ac); + for (i = 0; i < ac; i++) + saved_argv[i] = xstrdup(av[i]); + +#ifndef HAVE_SETPROCTITLE + /* Prepare for later setproctitle emulation */ + compat_init_setproctitle(ac, av); +#endif /* Initialize configuration options to their default values. */ initialize_server_options(&options); @@ -906,8 +924,10 @@ main(int ac, char **av) break; case 'u': utmp_len = atoi(optarg); - if (utmp_len < 0 || utmp_len > MAXHOSTNAMELEN) - usage(); + if (utmp_len > MAXHOSTNAMELEN) { + fprintf(stderr, "Invalid utmp length.\n"); + exit(1); + } break; case 'o': if (process_server_config_line(&options, optarg, @@ -932,9 +952,9 @@ main(int ac, char **av) SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_AUTH : options.log_facility, - !inetd_flag); + log_stderr || !inetd_flag); -#ifdef _CRAY +#ifdef _UNICOS /* Cray can define user privs drop all prives now! * Not needed on PRIV_SU systems! */ @@ -958,7 +978,8 @@ main(int ac, char **av) debug("sshd version %.100s", SSH_VERSION); /* load private host keys */ - sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*)); + sensitive_data.host_keys = xmalloc(options.num_host_key_files * + sizeof(Key *)); for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_keys[i] = NULL; sensitive_data.server_key = NULL; @@ -989,15 +1010,15 @@ main(int ac, char **av) key_type(key)); } if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { - log("Disabling protocol version 1. Could not load host key"); + logit("Disabling protocol version 1. Could not load host key"); options.protocol &= ~SSH_PROTO_1; } if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { - log("Disabling protocol version 2. Could not load host key"); + logit("Disabling protocol version 2. Could not load host key"); options.protocol &= ~SSH_PROTO_2; } if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { - log("sshd: no hostkeys available -- exiting."); + logit("sshd: no hostkeys available -- exiting."); exit(1); } @@ -1045,8 +1066,8 @@ main(int ac, char **av) #else if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0) #endif - fatal("Bad owner or mode for %s", - _PATH_PRIVSEP_CHROOT_DIR); + fatal("%s must be owned by root and not group or " + "world-writable.", _PATH_PRIVSEP_CHROOT_DIR); } /* Configuration looks good, so exit if in test mode. */ @@ -1144,17 +1165,12 @@ main(int ac, char **av) continue; } /* - * Set socket options. We try to make the port - * reusable and have it close as fast as possible - * without waiting in unnecessary wait states on - * close. + * Set socket options. + * Allow local port reuse in TIME_WAIT. */ - setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)); - linger.l_onoff = 1; - linger.l_linger = 5; - setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, - &linger, sizeof(linger)); + if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)) == -1) + error("setsockopt SO_REUSEADDR: %s", strerror(errno)); debug("Bind to port %s on %s.", strport, ntop); @@ -1170,7 +1186,7 @@ main(int ac, char **av) num_listen_socks++; /* Start listening on the port. */ - log("Server listening on %s port %s.", ntop, strport); + logit("Server listening on %s port %s.", ntop, strport); if (listen(listen_sock, 5) < 0) fatal("listen: %.100s", strerror(errno)); @@ -1246,7 +1262,7 @@ main(int ac, char **av) if (ret < 0 && errno != EINTR) error("select: %.100s", strerror(errno)); if (received_sigterm) { - log("Received signal %d; terminating.", + logit("Received signal %d; terminating.", (int) received_sigterm); close_listen_socks(); unlink(options.pid_file); @@ -1384,8 +1400,12 @@ main(int ac, char **av) * setlogin() affects the entire process group. We don't * want the child to be able to affect the parent. */ -#if 0 - /* XXX: this breaks Solaris */ +#if !defined(STREAMS_PUSH_ACQUIRES_CTTY) + /* + * If setsid is called on Solaris, sshd will acquire the controlling + * terminal while pushing STREAMS modules. This will prevent the + * shell from acquiring it later. + */ if (!debug_flag && !inetd_flag && setsid() < 0) error("setsid: %.100s", strerror(errno)); #endif @@ -1403,16 +1423,6 @@ main(int ac, char **av) signal(SIGCHLD, SIG_DFL); signal(SIGINT, SIG_DFL); - /* - * Set socket options for the connection. We want the socket to - * close as fast as possible without waiting for anything. If the - * connection is not a socket, these will do nothing. - */ - /* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */ - linger.l_onoff = 1; - linger.l_linger = 5; - setsockopt(sock_in, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); - /* Set keepalives if requested. */ if (options.keepalives && setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, @@ -1740,7 +1750,7 @@ do_ssh1_kex(void) u_char *buf = xmalloc(bytes); MD5_CTX md; - log("do_connection: generating a fake encryption key"); + logit("do_connection: generating a fake encryption key"); BN_bn2bin(session_key_int, buf); MD5_Init(&md); MD5_Update(&md, buf, bytes); @@ -1808,6 +1818,8 @@ do_ssh2_kex(void) /* start key exchange */ kex = kex_setup(myproposal); + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->server = 1; kex->client_version_string=client_version_string; kex->server_version_string=server_version_string;