X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/67f04db19136c1d19bb4bad51894489212ac271f..0daa6547440ce987e35650166f45fb0b22635c40:/sshd.c diff --git a/sshd.c b/sshd.c index 55c57e19..bc458488 100644 --- a/sshd.c +++ b/sshd.c @@ -42,7 +42,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.257 2002/07/23 16:03:10 stevesk Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.268 2003/06/04 10:23:48 djm Exp $"); #include #include @@ -112,11 +112,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; * Flag indicating whether IPv4 or IPv6. This can be set on the command line. * Default value is AF_UNSPEC means both IPv4 and IPv6. */ -#ifdef IPV4_DEFAULT -int IPv4or6 = AF_INET; -#else int IPv4or6 = AF_UNSPEC; -#endif /* * Debug mode flag. This can be set on the command line. If debug @@ -202,8 +198,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 +254,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); } @@ -304,7 +300,7 @@ grace_alarm_handler(int sig) /* XXX no idea how fix this signal handler */ /* Log error and exit. */ - fatal("Timeout before authentication for %s.", get_remote_ipaddr()); + fatal("Timeout before authentication for %s", get_remote_ipaddr()); } /* @@ -376,7 +372,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(); } @@ -384,7 +380,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(); } @@ -415,7 +411,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(); } @@ -424,8 +420,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(); } @@ -470,7 +472,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(); @@ -562,8 +564,6 @@ privsep_preauth_child(void) do_setusercontext(pw); #else gidset[0] = pw->pw_gid; - if (setgid(pw->pw_gid) < 0) - fatal("setgid failed for %u", pw->pw_gid ); if (setgroups(1, gidset) < 0) fatal("setgroups: %.100s", strerror(errno)); permanently_set_uid(pw); @@ -806,7 +806,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; @@ -822,9 +821,18 @@ 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 + 1)); + for (i = 0; i < ac; i++) + saved_argv[i] = xstrdup(av[i]); + saved_argv[i] = NULL; + +#ifndef HAVE_SETPROCTITLE + /* Prepare for later setproctitle emulation */ + compat_init_setproctitle(ac, av); + av = saved_argv; +#endif /* Initialize configuration options to their default values. */ initialize_server_options(&options); @@ -939,9 +947,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); -#if defined(_CRAY) && !defined(_CRAYSV2) +#ifdef _UNICOS /* Cray can define user privs drop all prives now! * Not needed on PRIV_SU systems! */ @@ -997,15 +1005,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); } @@ -1053,8 +1061,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. */ @@ -1140,7 +1148,8 @@ main(int ac, char **av) continue; } /* Create socket for listening. */ - listen_sock = socket(ai->ai_family, SOCK_STREAM, 0); + listen_sock = socket(ai->ai_family, ai->ai_socktype, + ai->ai_protocol); if (listen_sock < 0) { /* kernel may not support ipv6 */ verbose("socket: %.100s", strerror(errno)); @@ -1152,17 +1161,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); @@ -1178,7 +1182,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)); @@ -1254,7 +1258,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); @@ -1369,7 +1373,7 @@ main(int ac, char **av) if ((options.protocol & SSH_PROTO_1) && key_used == 0) { /* Schedule server key regeneration alarm. */ - signal(SIGALRM, key_regeneration_alarm); + mysignal(SIGALRM, key_regeneration_alarm); alarm(options.key_regeneration_time); key_used = 1; } @@ -1392,8 +1396,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(SSHD_ACQUIRES_CTTY) + /* + * If setsid is called, on some platforms sshd will later acquire a + * controlling terminal which will result in "could not set + * controlling tty" errors. + */ if (!debug_flag && !inetd_flag && setsid() < 0) error("setsid: %.100s", strerror(errno)); #endif @@ -1411,16 +1419,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, @@ -1464,7 +1462,7 @@ main(int ac, char **av) * mode; it is just annoying to have the server exit just when you * are about to discover the bug. */ - signal(SIGALRM, grace_alarm_handler); + mysignal(SIGALRM, grace_alarm_handler); if (!debug_flag) alarm(options.login_grace_time); @@ -1541,7 +1539,8 @@ main(int ac, char **av) verbose("Closing connection to %.100s", remote_ip); #ifdef USE_PAM - finish_pam(); + if (options.use_pam) + finish_pam(); #endif /* USE_PAM */ packet_close(); @@ -1748,7 +1747,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); @@ -1816,6 +1815,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;