diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 87 |
1 files changed, 43 insertions, 44 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.485 2017/03/15 03:52:30 deraadt Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.492 2017/09/12 06:32:07 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -88,7 +88,6 @@ | |||
88 | #include "xmalloc.h" | 88 | #include "xmalloc.h" |
89 | #include "ssh.h" | 89 | #include "ssh.h" |
90 | #include "ssh2.h" | 90 | #include "ssh2.h" |
91 | #include "rsa.h" | ||
92 | #include "sshpty.h" | 91 | #include "sshpty.h" |
93 | #include "packet.h" | 92 | #include "packet.h" |
94 | #include "log.h" | 93 | #include "log.h" |
@@ -195,10 +194,10 @@ int have_agent = 0; | |||
195 | * not very useful. Currently, memory locking is not implemented. | 194 | * not very useful. Currently, memory locking is not implemented. |
196 | */ | 195 | */ |
197 | struct { | 196 | struct { |
198 | Key **host_keys; /* all private host keys */ | 197 | struct sshkey **host_keys; /* all private host keys */ |
199 | Key **host_pubkeys; /* all public host keys */ | 198 | struct sshkey **host_pubkeys; /* all public host keys */ |
200 | Key **host_certificates; /* all public host certificates */ | 199 | struct sshkey **host_certificates; /* all public host certificates */ |
201 | int have_ssh2_key; | 200 | int have_ssh2_key; |
202 | } sensitive_data; | 201 | } sensitive_data; |
203 | 202 | ||
204 | /* This is set to true when a signal is received. */ | 203 | /* This is set to true when a signal is received. */ |
@@ -223,6 +222,7 @@ int startup_pipe; /* in child */ | |||
223 | int use_privsep = -1; | 222 | int use_privsep = -1; |
224 | struct monitor *pmonitor = NULL; | 223 | struct monitor *pmonitor = NULL; |
225 | int privsep_is_preauth = 1; | 224 | int privsep_is_preauth = 1; |
225 | static int privsep_chroot = 1; | ||
226 | 226 | ||
227 | /* global authentication context */ | 227 | /* global authentication context */ |
228 | Authctxt *the_authctxt = NULL; | 228 | Authctxt *the_authctxt = NULL; |
@@ -449,10 +449,8 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) | |||
449 | chop(server_version_string); | 449 | chop(server_version_string); |
450 | debug("Local version string %.200s", server_version_string); | 450 | debug("Local version string %.200s", server_version_string); |
451 | 451 | ||
452 | if (remote_major == 2 || | 452 | if (remote_major != 2 || |
453 | (remote_major == 1 && remote_minor == 99)) { | 453 | (remote_major == 1 && remote_minor != 99)) { |
454 | enable_compat20(); | ||
455 | } else { | ||
456 | s = "Protocol major versions differ.\n"; | 454 | s = "Protocol major versions differ.\n"; |
457 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | 455 | (void) atomicio(vwrite, sock_out, s, strlen(s)); |
458 | close(sock_in); | 456 | close(sock_in); |
@@ -487,7 +485,7 @@ destroy_sensitive_data(void) | |||
487 | void | 485 | void |
488 | demote_sensitive_data(void) | 486 | demote_sensitive_data(void) |
489 | { | 487 | { |
490 | Key *tmp; | 488 | struct sshkey *tmp; |
491 | int i; | 489 | int i; |
492 | 490 | ||
493 | for (i = 0; i < options.num_host_key_files; i++) { | 491 | for (i = 0; i < options.num_host_key_files; i++) { |
@@ -541,7 +539,7 @@ privsep_preauth_child(void) | |||
541 | demote_sensitive_data(); | 539 | demote_sensitive_data(); |
542 | 540 | ||
543 | /* Demote the child */ | 541 | /* Demote the child */ |
544 | if (getuid() == 0 || geteuid() == 0) { | 542 | if (privsep_chroot) { |
545 | /* Change our root directory */ | 543 | /* Change our root directory */ |
546 | if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) | 544 | if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) |
547 | fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, | 545 | fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, |
@@ -650,6 +648,7 @@ privsep_postauth(Authctxt *authctxt) | |||
650 | else if (pmonitor->m_pid != 0) { | 648 | else if (pmonitor->m_pid != 0) { |
651 | verbose("User child is on pid %ld", (long)pmonitor->m_pid); | 649 | verbose("User child is on pid %ld", (long)pmonitor->m_pid); |
652 | buffer_clear(&loginmsg); | 650 | buffer_clear(&loginmsg); |
651 | monitor_clear_keystate(pmonitor); | ||
653 | monitor_child_postauth(pmonitor); | 652 | monitor_child_postauth(pmonitor); |
654 | 653 | ||
655 | /* NEVERREACHED */ | 654 | /* NEVERREACHED */ |
@@ -687,7 +686,7 @@ list_hostkey_types(void) | |||
687 | const char *p; | 686 | const char *p; |
688 | char *ret; | 687 | char *ret; |
689 | int i; | 688 | int i; |
690 | Key *key; | 689 | struct sshkey *key; |
691 | 690 | ||
692 | buffer_init(&b); | 691 | buffer_init(&b); |
693 | for (i = 0; i < options.num_host_key_files; i++) { | 692 | for (i = 0; i < options.num_host_key_files; i++) { |
@@ -743,11 +742,11 @@ list_hostkey_types(void) | |||
743 | return ret; | 742 | return ret; |
744 | } | 743 | } |
745 | 744 | ||
746 | static Key * | 745 | static struct sshkey * |
747 | get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) | 746 | get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) |
748 | { | 747 | { |
749 | int i; | 748 | int i; |
750 | Key *key; | 749 | struct sshkey *key; |
751 | 750 | ||
752 | for (i = 0; i < options.num_host_key_files; i++) { | 751 | for (i = 0; i < options.num_host_key_files; i++) { |
753 | switch (type) { | 752 | switch (type) { |
@@ -771,19 +770,19 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) | |||
771 | return NULL; | 770 | return NULL; |
772 | } | 771 | } |
773 | 772 | ||
774 | Key * | 773 | struct sshkey * |
775 | get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) | 774 | get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) |
776 | { | 775 | { |
777 | return get_hostkey_by_type(type, nid, 0, ssh); | 776 | return get_hostkey_by_type(type, nid, 0, ssh); |
778 | } | 777 | } |
779 | 778 | ||
780 | Key * | 779 | struct sshkey * |
781 | get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) | 780 | get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) |
782 | { | 781 | { |
783 | return get_hostkey_by_type(type, nid, 1, ssh); | 782 | return get_hostkey_by_type(type, nid, 1, ssh); |
784 | } | 783 | } |
785 | 784 | ||
786 | Key * | 785 | struct sshkey * |
787 | get_hostkey_by_index(int ind) | 786 | get_hostkey_by_index(int ind) |
788 | { | 787 | { |
789 | if (ind < 0 || ind >= options.num_host_key_files) | 788 | if (ind < 0 || ind >= options.num_host_key_files) |
@@ -791,7 +790,7 @@ get_hostkey_by_index(int ind) | |||
791 | return (sensitive_data.host_keys[ind]); | 790 | return (sensitive_data.host_keys[ind]); |
792 | } | 791 | } |
793 | 792 | ||
794 | Key * | 793 | struct sshkey * |
795 | get_hostkey_public_by_index(int ind, struct ssh *ssh) | 794 | get_hostkey_public_by_index(int ind, struct ssh *ssh) |
796 | { | 795 | { |
797 | if (ind < 0 || ind >= options.num_host_key_files) | 796 | if (ind < 0 || ind >= options.num_host_key_files) |
@@ -800,7 +799,7 @@ get_hostkey_public_by_index(int ind, struct ssh *ssh) | |||
800 | } | 799 | } |
801 | 800 | ||
802 | int | 801 | int |
803 | get_hostkey_index(Key *key, int compare, struct ssh *ssh) | 802 | get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) |
804 | { | 803 | { |
805 | int i; | 804 | int i; |
806 | 805 | ||
@@ -1367,8 +1366,8 @@ main(int ac, char **av) | |||
1367 | u_int n; | 1366 | u_int n; |
1368 | u_int64_t ibytes, obytes; | 1367 | u_int64_t ibytes, obytes; |
1369 | mode_t new_umask; | 1368 | mode_t new_umask; |
1370 | Key *key; | 1369 | struct sshkey *key; |
1371 | Key *pubkey; | 1370 | struct sshkey *pubkey; |
1372 | int keytype; | 1371 | int keytype; |
1373 | Authctxt *authctxt; | 1372 | Authctxt *authctxt; |
1374 | struct connection_info *connection_info = get_connection_info(0, 0); | 1373 | struct connection_info *connection_info = get_connection_info(0, 0); |
@@ -1622,9 +1621,6 @@ main(int ac, char **av) | |||
1622 | "enabled authentication methods"); | 1621 | "enabled authentication methods"); |
1623 | } | 1622 | } |
1624 | 1623 | ||
1625 | /* set default channel AF */ | ||
1626 | channel_set_af(options.address_family); | ||
1627 | |||
1628 | /* Check that there are no remaining arguments. */ | 1624 | /* Check that there are no remaining arguments. */ |
1629 | if (optind < ac) { | 1625 | if (optind < ac) { |
1630 | fprintf(stderr, "Extra argument %s.\n", av[optind]); | 1626 | fprintf(stderr, "Extra argument %s.\n", av[optind]); |
@@ -1640,8 +1636,9 @@ main(int ac, char **av) | |||
1640 | ); | 1636 | ); |
1641 | 1637 | ||
1642 | /* Store privilege separation user for later use if required. */ | 1638 | /* Store privilege separation user for later use if required. */ |
1639 | privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0); | ||
1643 | if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { | 1640 | if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { |
1644 | if (use_privsep || options.kerberos_authentication) | 1641 | if (privsep_chroot || options.kerberos_authentication) |
1645 | fatal("Privilege separation user %s does not exist", | 1642 | fatal("Privilege separation user %s does not exist", |
1646 | SSH_PRIVSEP_USER); | 1643 | SSH_PRIVSEP_USER); |
1647 | } else { | 1644 | } else { |
@@ -1655,9 +1652,9 @@ main(int ac, char **av) | |||
1655 | 1652 | ||
1656 | /* load host keys */ | 1653 | /* load host keys */ |
1657 | sensitive_data.host_keys = xcalloc(options.num_host_key_files, | 1654 | sensitive_data.host_keys = xcalloc(options.num_host_key_files, |
1658 | sizeof(Key *)); | 1655 | sizeof(struct sshkey *)); |
1659 | sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, | 1656 | sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, |
1660 | sizeof(Key *)); | 1657 | sizeof(struct sshkey *)); |
1661 | 1658 | ||
1662 | if (options.host_key_agent) { | 1659 | if (options.host_key_agent) { |
1663 | if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) | 1660 | if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) |
@@ -1676,14 +1673,6 @@ main(int ac, char **av) | |||
1676 | key = key_load_private(options.host_key_files[i], "", NULL); | 1673 | key = key_load_private(options.host_key_files[i], "", NULL); |
1677 | pubkey = key_load_public(options.host_key_files[i], NULL); | 1674 | pubkey = key_load_public(options.host_key_files[i], NULL); |
1678 | 1675 | ||
1679 | if ((pubkey != NULL && pubkey->type == KEY_RSA1) || | ||
1680 | (key != NULL && key->type == KEY_RSA1)) { | ||
1681 | verbose("Ignoring RSA1 key %s", | ||
1682 | options.host_key_files[i]); | ||
1683 | key_free(key); | ||
1684 | key_free(pubkey); | ||
1685 | continue; | ||
1686 | } | ||
1687 | if (pubkey == NULL && key != NULL) | 1676 | if (pubkey == NULL && key != NULL) |
1688 | pubkey = key_demote(key); | 1677 | pubkey = key_demote(key); |
1689 | sensitive_data.host_keys[i] = key; | 1678 | sensitive_data.host_keys[i] = key; |
@@ -1729,7 +1718,7 @@ main(int ac, char **av) | |||
1729 | * indices to the public keys that they relate to. | 1718 | * indices to the public keys that they relate to. |
1730 | */ | 1719 | */ |
1731 | sensitive_data.host_certificates = xcalloc(options.num_host_key_files, | 1720 | sensitive_data.host_certificates = xcalloc(options.num_host_key_files, |
1732 | sizeof(Key *)); | 1721 | sizeof(struct sshkey *)); |
1733 | for (i = 0; i < options.num_host_key_files; i++) | 1722 | for (i = 0; i < options.num_host_key_files; i++) |
1734 | sensitive_data.host_certificates[i] = NULL; | 1723 | sensitive_data.host_certificates[i] = NULL; |
1735 | 1724 | ||
@@ -1767,7 +1756,7 @@ main(int ac, char **av) | |||
1767 | key_type(key)); | 1756 | key_type(key)); |
1768 | } | 1757 | } |
1769 | 1758 | ||
1770 | if (use_privsep) { | 1759 | if (privsep_chroot) { |
1771 | struct stat st; | 1760 | struct stat st; |
1772 | 1761 | ||
1773 | if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || | 1762 | if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || |
@@ -1963,8 +1952,14 @@ main(int ac, char **av) | |||
1963 | packet_set_connection(sock_in, sock_out); | 1952 | packet_set_connection(sock_in, sock_out); |
1964 | packet_set_server(); | 1953 | packet_set_server(); |
1965 | ssh = active_state; /* XXX */ | 1954 | ssh = active_state; /* XXX */ |
1955 | |||
1966 | check_ip_options(ssh); | 1956 | check_ip_options(ssh); |
1967 | 1957 | ||
1958 | /* Prepare the channels layer */ | ||
1959 | channel_init_channels(ssh); | ||
1960 | channel_set_af(ssh, options.address_family); | ||
1961 | process_permitopen(ssh, &options); | ||
1962 | |||
1968 | /* Set SO_KEEPALIVE if requested. */ | 1963 | /* Set SO_KEEPALIVE if requested. */ |
1969 | if (options.tcp_keep_alive && packet_connection_is_on_socket() && | 1964 | if (options.tcp_keep_alive && packet_connection_is_on_socket() && |
1970 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) | 1965 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) |
@@ -2040,6 +2035,7 @@ main(int ac, char **av) | |||
2040 | */ | 2035 | */ |
2041 | if (use_privsep) { | 2036 | if (use_privsep) { |
2042 | mm_send_keystate(pmonitor); | 2037 | mm_send_keystate(pmonitor); |
2038 | packet_clear_keys(); | ||
2043 | exit(0); | 2039 | exit(0); |
2044 | } | 2040 | } |
2045 | 2041 | ||
@@ -2087,10 +2083,10 @@ main(int ac, char **av) | |||
2087 | options.client_alive_count_max); | 2083 | options.client_alive_count_max); |
2088 | 2084 | ||
2089 | /* Try to send all our hostkeys to the client */ | 2085 | /* Try to send all our hostkeys to the client */ |
2090 | notify_hostkeys(active_state); | 2086 | notify_hostkeys(ssh); |
2091 | 2087 | ||
2092 | /* Start session. */ | 2088 | /* Start session. */ |
2093 | do_authenticated(authctxt); | 2089 | do_authenticated(ssh, authctxt); |
2094 | 2090 | ||
2095 | /* The connection has been terminated. */ | 2091 | /* The connection has been terminated. */ |
2096 | packet_get_bytes(&ibytes, &obytes); | 2092 | packet_get_bytes(&ibytes, &obytes); |
@@ -2117,8 +2113,9 @@ main(int ac, char **av) | |||
2117 | } | 2113 | } |
2118 | 2114 | ||
2119 | int | 2115 | int |
2120 | sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen, | 2116 | sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey, |
2121 | const u_char *data, size_t dlen, const char *alg, u_int flag) | 2117 | u_char **signature, size_t *slen, const u_char *data, size_t dlen, |
2118 | const char *alg, u_int flag) | ||
2122 | { | 2119 | { |
2123 | int r; | 2120 | int r; |
2124 | u_int xxx_slen, xxx_dlen = dlen; | 2121 | u_int xxx_slen, xxx_dlen = dlen; |
@@ -2198,7 +2195,7 @@ do_ssh2_kex(void) | |||
2198 | kex->host_key_index=&get_hostkey_index; | 2195 | kex->host_key_index=&get_hostkey_index; |
2199 | kex->sign = sshd_hostkey_sign; | 2196 | kex->sign = sshd_hostkey_sign; |
2200 | 2197 | ||
2201 | dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); | 2198 | ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); |
2202 | 2199 | ||
2203 | session_id2 = kex->session_id; | 2200 | session_id2 = kex->session_id; |
2204 | session_id2_len = kex->session_id_len; | 2201 | session_id2_len = kex->session_id_len; |
@@ -2217,8 +2214,10 @@ do_ssh2_kex(void) | |||
2217 | void | 2214 | void |
2218 | cleanup_exit(int i) | 2215 | cleanup_exit(int i) |
2219 | { | 2216 | { |
2217 | struct ssh *ssh = active_state; /* XXX */ | ||
2218 | |||
2220 | if (the_authctxt) { | 2219 | if (the_authctxt) { |
2221 | do_cleanup(the_authctxt); | 2220 | do_cleanup(ssh, the_authctxt); |
2222 | if (use_privsep && privsep_is_preauth && | 2221 | if (use_privsep && privsep_is_preauth && |
2223 | pmonitor != NULL && pmonitor->m_pid > 1) { | 2222 | pmonitor != NULL && pmonitor->m_pid > 1) { |
2224 | debug("Killing privsep child %d", pmonitor->m_pid); | 2223 | debug("Killing privsep child %d", pmonitor->m_pid); |