diff options
author | Damien Miller <djm@cvs.openbsd.org> | 2016-03-07 19:02:44 +0000 |
---|---|---|
committer | Damien Miller <djm@cvs.openbsd.org> | 2016-03-07 19:02:44 +0000 |
commit | daa4435f61094021f646c9b2f59a4079546bc826 (patch) | |
tree | 62dc0c52030993ae669e55736d163f4d98c242d3 /usr.bin/ssh/sshd.c | |
parent | fa0c97b67d9de4576728f5754bee7057844bc268 (diff) |
refactor canohost.c: move functions that cache results closer to the
places that use them (authn and session code). After this, no state is
cached in canohost.c
feedback and ok markus@
Diffstat (limited to 'usr.bin/ssh/sshd.c')
-rw-r--r-- | usr.bin/ssh/sshd.c | 118 |
1 files changed, 82 insertions, 36 deletions
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c index 6ec2b1790bd..6a51b9d56f5 100644 --- a/usr.bin/ssh/sshd.c +++ b/usr.bin/ssh/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.465 2016/02/15 09:47:49 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.466 2016/03/07 19:02:43 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -348,7 +348,8 @@ grace_alarm_handler(int sig) } /* Log error and exit. */ - sigdie("Timeout before authentication for %s", get_remote_ipaddr()); + sigdie("Timeout before authentication for %s port %d", + ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); } /* @@ -384,7 +385,7 @@ key_regeneration_alarm(int sig) } static void -sshd_exchange_identification(int sock_in, int sock_out) +sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) { u_int i; int mismatch; @@ -416,7 +417,8 @@ sshd_exchange_identification(int sock_in, int sock_out) if (atomicio(vwrite, sock_out, server_version_string, strlen(server_version_string)) != strlen(server_version_string)) { - logit("Could not write ident string to %s", get_remote_ipaddr()); + logit("Could not write ident string to %s port %d", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); cleanup_exit(255); } @@ -424,8 +426,9 @@ 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) { - logit("Did not receive identification string from %s", - get_remote_ipaddr()); + logit("Did not receive identification string " + "from %s port %d", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); cleanup_exit(255); } if (buf[i] == '\r') { @@ -454,7 +457,7 @@ sshd_exchange_identification(int sock_in, int sock_out) (void) atomicio(vwrite, sock_out, s, strlen(s)); logit("Bad protocol version identification '%.100s' " "from %s port %d", client_version_string, - get_remote_ipaddr(), get_remote_port()); + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); close(sock_in); close(sock_out); cleanup_exit(255); @@ -462,23 +465,25 @@ sshd_exchange_identification(int sock_in, int sock_out) debug("Client protocol version %d.%d; client software version %.100s", remote_major, remote_minor, remote_version); - active_state->compat = compat_datafellows(remote_version); + ssh->compat = compat_datafellows(remote_version); - if ((datafellows & SSH_BUG_PROBE) != 0) { - logit("probed from %s with %s. Don't panic.", - get_remote_ipaddr(), client_version_string); + if ((ssh->compat & SSH_BUG_PROBE) != 0) { + logit("probed from %s port %d with %s. Don't panic.", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + client_version_string); cleanup_exit(255); } - if ((datafellows & SSH_BUG_SCANNER) != 0) { - logit("scanned from %s with %s. Don't panic.", - get_remote_ipaddr(), client_version_string); + if ((ssh->compat & SSH_BUG_SCANNER) != 0) { + logit("scanned from %s port %d with %s. Don't panic.", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + client_version_string); cleanup_exit(255); } - if ((datafellows & SSH_BUG_RSASIGMD5) != 0) { + if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) { logit("Client version \"%.100s\" uses unsafe RSA signature " "scheme; disabling use of RSA keys", remote_version); } - if ((datafellows & SSH_BUG_DERIVEKEY) != 0) { + if ((ssh->compat & SSH_BUG_DERIVEKEY) != 0) { fatal("Client version \"%.100s\" uses unsafe key agreement; " "refusing connection", remote_version); } @@ -523,8 +528,9 @@ sshd_exchange_identification(int sock_in, int sock_out) (void) atomicio(vwrite, sock_out, s, strlen(s)); close(sock_in); close(sock_out); - logit("Protocol major versions differ for %s: %.200s vs. %.200s", - get_remote_ipaddr(), + logit("Protocol major versions differ for %s port %d: " + "%.200s vs. %.200s", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), server_version_string, client_version_string); cleanup_exit(255); } @@ -1383,6 +1389,45 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) } } +/* + * If IP options are supported, make sure there are none (log and + * return an error if any are found). Basically we are worried about + * source routing; it can be used to pretend you are somebody + * (ip-address) you are not. That itself may be "almost acceptable" + * under certain circumstances, but rhosts autentication is useless + * if source routing is accepted. Notice also that if we just dropped + * source routing here, the other side could use IP spoofing to do + * rest of the interaction and could still bypass security. So we + * exit here if we detect any IP options. + */ +static void +check_ip_options(struct ssh *ssh) +{ + int sock_in = ssh_packet_get_connection_in(ssh); + struct sockaddr_storage from; + socklen_t option_size, i, fromlen = sizeof(from); + u_char opts[200]; + char text[sizeof(opts) * 3 + 1]; + + memset(&from, 0, sizeof(from)); + if (getpeername(sock_in, (struct sockaddr *)&from, + &fromlen) < 0) + return; + if (from.ss_family != AF_INET) + return; + /* XXX IPv6 options? */ + + if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, + &option_size) >= 0 && option_size != 0) { + text[0] = '\0'; + for (i = 0; i < option_size; i++) + snprintf(text + i*3, sizeof(text) - i*3, + " %2.2x", opts[i]); + fatal("Connection from %.100s port %d with IP opts: %.800s", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text); + } + return; +} /* * Main program for the daemon. @@ -1390,6 +1435,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) int main(int ac, char **av) { + struct ssh *ssh = NULL; extern char *optarg; extern int optind; int r, opt, i, j, on = 1; @@ -1974,33 +2020,30 @@ main(int ac, char **av) */ packet_set_connection(sock_in, sock_out); packet_set_server(); + ssh = active_state; /* XXX */ + check_ip_options(ssh); /* 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"); + if ((remote_port = ssh_remote_port(ssh)) < 0) { + debug("ssh_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. - */ - (void) get_canonical_hostname(0); - /* * The rest of the code depends on the fact that - * get_remote_ipaddr() caches the remote ip, even if + * ssh_remote_ipaddr() caches the remote ip, even if * the socket goes away. */ - remote_ip = get_remote_ipaddr(); + remote_ip = ssh_remote_ipaddr(ssh); /* Log the connection. */ laddr = get_local_ipaddr(sock_in); verbose("Connection from %s port %d on %s port %d", - remote_ip, remote_port, laddr, get_local_port()); + remote_ip, remote_port, laddr, ssh_local_port(ssh)); free(laddr); /* @@ -2015,7 +2058,7 @@ main(int ac, char **av) if (!debug_flag) alarm(options.login_grace_time); - sshd_exchange_identification(sock_in, sock_out); + sshd_exchange_identification(ssh, sock_in, sock_out); /* In inetd mode, generate ephemeral key only for proto 1 connections */ if (!compat20 && inetd_flag && sensitive_data.server_key == NULL) @@ -2121,6 +2164,7 @@ main(int ac, char **av) int ssh1_session_key(BIGNUM *session_key_int) { + struct ssh *ssh = active_state; /* XXX */ int rsafail = 0; if (BN_cmp(sensitive_data.server_key->rsa->n, @@ -2129,9 +2173,9 @@ ssh1_session_key(BIGNUM *session_key_int) if (BN_num_bits(sensitive_data.server_key->rsa->n) < BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s: " + fatal("do_connection: %s port %d: " "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", - get_remote_ipaddr(), + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), BN_num_bits(sensitive_data.server_key->rsa->n), BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), SSH_KEY_BITS_RESERVED); @@ -2147,9 +2191,9 @@ ssh1_session_key(BIGNUM *session_key_int) if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s: " + fatal("do_connection: %s port %d: " "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", - get_remote_ipaddr(), + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), BN_num_bits(sensitive_data.server_key->rsa->n), SSH_KEY_BITS_RESERVED); @@ -2170,6 +2214,7 @@ ssh1_session_key(BIGNUM *session_key_int) static void do_ssh1_kex(void) { + struct ssh *ssh = active_state; /* XXX */ int i, len; int rsafail = 0; BIGNUM *session_key_int, *fake_key_int, *real_key_int; @@ -2287,9 +2332,10 @@ do_ssh1_kex(void) (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); len = BN_num_bytes(session_key_int); if (len < 0 || (u_int)len > sizeof(session_key)) { - error("do_ssh1_kex: bad session key len from %s: " - "session_key_int %d > sizeof(session_key) %lu", - get_remote_ipaddr(), len, (u_long)sizeof(session_key)); + error("%s: bad session key len from %s port %d: " + "session_key_int %d > sizeof(session_key) %lu", __func__, + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + len, (u_long)sizeof(session_key)); rsafail++; } else { explicit_bzero(session_key, sizeof(session_key)); |