*/
#include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.274 2003/07/22 13:35:22 markus Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.285 2004/02/05 05:37:17 dtucker Exp $");
#include <openssl/dh.h>
#include <openssl/bn.h>
#else
char *__progname;
#endif
+extern char **environ;
/* Server configuration options. */
ServerOptions options;
/* variables used for privilege separation */
int use_privsep;
-struct monitor *pmonitor;
+struct monitor *pmonitor = NULL;
/* message to be displayed after login */
Buffer loginmsg;
+/* 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);
{
/* 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());
}
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. */
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;
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);
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;
logit("Protocol major versions differ for %s: %.200s vs. %.200s",
get_remote_ipaddr(),
server_version_string, client_version_string);
- fatal_cleanup();
+ cleanup_exit(255);
}
}
#endif
}
-static Authctxt *
-privsep_preauth(void)
+static int
+privsep_preauth(Authctxt *authctxt)
{
- Authctxt *authctxt = NULL;
int status;
pid_t pid;
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 */
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 */
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;
-
#ifdef DISABLE_FD_PASSING
if (1) {
#else
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);
list_hostkey_types(void)
{
Buffer b;
- char *p;
+ const char *p;
+ char *ret;
int i;
buffer_init(&b);
}
}
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 *
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);
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;
#ifdef HAVE_SECUREWARE
(void)set_auth_parameters(ac, av);
#endif
- __progname = get_progname(av[0]);
+ __progname = ssh_get_progname(av[0]);
init_rng();
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
}
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:
/*
* Clear out any supplemental groups we may have inherited. This
* prevents inadvertent creation of files with bad modes (in the
- * portable version at least, it's certainly possible for PAM
- * to create a file, and we can't control the code in every
+ * portable version at least, it's certainly possible for PAM
+ * to create a file, and we can't control the code in every
* module which might be used).
*/
if (setgroups(0, NULL) < 0)
unmounted if desired. */
chdir("/");
+#ifndef HAVE_CYGWIN
+ /* Clear environment */
+ environ[0] = NULL;
+#endif
+
/* ignore SIGPIPE */
signal(SIGPIPE, SIG_IGN);
verbose("socket: %.100s", strerror(errno));
continue;
}
- if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) {
- error("listen_sock O_NONBLOCK: %s", strerror(errno));
- close(listen_sock);
- continue;
- }
/*
* Set socket options.
* Allow local port reuse in TIME_WAIT.
/* 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));
}
error("accept: %.100s", strerror(errno));
continue;
}
- if (fcntl(newsock, F_SETFL, 0) < 0) {
- error("newsock del O_NONBLOCK: %s", strerror(errno));
- close(newsock);
- continue;
- }
if (drop_connection(startups) == 1) {
debug("drop connection #%d", startups);
close(newsock);
if ((options.protocol & SSH_PROTO_1) &&
key_used == 0) {
/* Schedule server key regeneration alarm. */
- mysignal(SIGALRM, key_regeneration_alarm);
+ signal(SIGALRM, key_regeneration_alarm);
alarm(options.key_regeneration_time);
key_used = 1;
}
signal(SIGCHLD, SIG_DFL);
signal(SIGINT, 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));
* mode; it is just annoying to have the server exit just when you
* are about to discover the bug.
*/
- mysignal(SIGALRM, grace_alarm_handler);
+ signal(SIGALRM, grace_alarm_handler);
if (!debug_flag)
alarm(options.login_grace_time);
sshd_exchange_identification(sock_in, sock_out);
- /*
- * Check that the connection comes from a privileged port.
- * Rhosts-Authentication only makes sense from privileged
- * programs. Of course, if the intruder has root access on his local
- * machine, he can connect from any port. So do not use these
- * authentication methods from machines that you do not trust.
- */
- if (options.rhosts_authentication &&
- (remote_port >= IPPORT_RESERVED ||
- remote_port < IPPORT_RESERVED / 2)) {
- debug("Rhosts Authentication disabled, "
- "originating port %d not trusted.", remote_port);
- options.rhosts_authentication = 0;
- }
-#ifdef KRB5
- if (!packet_connection_is_ipv4() &&
- options.kerberos_authentication) {
- debug("Kerberos Authentication disabled, only available for IPv4.");
- options.kerberos_authentication = 0;
- }
-#endif
packet_set_nonblocking();
- /* prepare buffers to collect authentication messages */
+ /* prepare buffers to collect authentication messages */
buffer_init(&loginmsg);
+ /* 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
destroy_sensitive_data();
}
- /* Perform session preparation. */
+ /* Start session. */
do_authenticated(authctxt);
/* The connection has been terminated. */
/* Declare supported authentication types. */
auth_mask = 0;
- if (options.rhosts_authentication)
- auth_mask |= 1 << SSH_AUTH_RHOSTS;
if (options.rhosts_rsa_authentication)
auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
if (options.rsa_authentication)
auth_mask |= 1 << SSH_AUTH_RSA;
-#ifdef KRB5
- if (options.kerberos_authentication)
- auth_mask |= 1 << SSH_AUTH_KERBEROS;
- if (options.kerberos_tgt_passing)
- auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;
-#endif
if (options.challenge_response_authentication == 1)
auth_mask |= 1 << SSH_AUTH_TIS;
if (options.password_authentication)
#endif
debug("KEX done");
}
+
+/* server specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+ if (the_authctxt)
+ do_cleanup(the_authctxt);
+ _exit(i);
+}