diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 303 |
1 files changed, 192 insertions, 111 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.428 2014/07/15 15:54:14 millert Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.444 2015/02/20 22:17:21 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 |
@@ -71,6 +71,7 @@ | |||
71 | #include <stdlib.h> | 71 | #include <stdlib.h> |
72 | #include <string.h> | 72 | #include <string.h> |
73 | #include <unistd.h> | 73 | #include <unistd.h> |
74 | #include <limits.h> | ||
74 | 75 | ||
75 | #ifdef WITH_OPENSSL | 76 | #ifdef WITH_OPENSSL |
76 | #include <openssl/dh.h> | 77 | #include <openssl/dh.h> |
@@ -122,6 +123,7 @@ | |||
122 | #include "roaming.h" | 123 | #include "roaming.h" |
123 | #include "ssh-sandbox.h" | 124 | #include "ssh-sandbox.h" |
124 | #include "version.h" | 125 | #include "version.h" |
126 | #include "ssherr.h" | ||
125 | 127 | ||
126 | #ifdef USE_SECURITY_SESSION_API | 128 | #ifdef USE_SECURITY_SESSION_API |
127 | #include <Security/AuthSession.h> | 129 | #include <Security/AuthSession.h> |
@@ -197,11 +199,8 @@ int num_listen_socks = 0; | |||
197 | char *client_version_string = NULL; | 199 | char *client_version_string = NULL; |
198 | char *server_version_string = NULL; | 200 | char *server_version_string = NULL; |
199 | 201 | ||
200 | /* for rekeying XXX fixme */ | ||
201 | Kex *xxx_kex; | ||
202 | |||
203 | /* Daemon's agent connection */ | 202 | /* Daemon's agent connection */ |
204 | AuthenticationConnection *auth_conn = NULL; | 203 | int auth_sock = -1; |
205 | int have_agent = 0; | 204 | int have_agent = 0; |
206 | 205 | ||
207 | /* | 206 | /* |
@@ -241,7 +240,7 @@ u_char *session_id2 = NULL; | |||
241 | u_int session_id2_len = 0; | 240 | u_int session_id2_len = 0; |
242 | 241 | ||
243 | /* record remote hostname or ip */ | 242 | /* record remote hostname or ip */ |
244 | u_int utmp_len = MAXHOSTNAMELEN; | 243 | u_int utmp_len = HOST_NAME_MAX+1; |
245 | 244 | ||
246 | /* options.max_startup sized array of fd ints */ | 245 | /* options.max_startup sized array of fd ints */ |
247 | int *startup_pipes = NULL; | 246 | int *startup_pipes = NULL; |
@@ -498,7 +497,7 @@ sshd_exchange_identification(int sock_in, int sock_out) | |||
498 | debug("Client protocol version %d.%d; client software version %.100s", | 497 | debug("Client protocol version %d.%d; client software version %.100s", |
499 | remote_major, remote_minor, remote_version); | 498 | remote_major, remote_minor, remote_version); |
500 | 499 | ||
501 | compat_datafellows(remote_version); | 500 | active_state->compat = compat_datafellows(remote_version); |
502 | 501 | ||
503 | if ((datafellows & SSH_BUG_PROBE) != 0) { | 502 | if ((datafellows & SSH_BUG_PROBE) != 0) { |
504 | logit("probed from %s with %s. Don't panic.", | 503 | logit("probed from %s with %s. Don't panic.", |
@@ -634,7 +633,9 @@ privsep_preauth_child(void) | |||
634 | 633 | ||
635 | arc4random_stir(); | 634 | arc4random_stir(); |
636 | arc4random_buf(rnd, sizeof(rnd)); | 635 | arc4random_buf(rnd, sizeof(rnd)); |
636 | #ifdef WITH_OPENSSL | ||
637 | RAND_seed(rnd, sizeof(rnd)); | 637 | RAND_seed(rnd, sizeof(rnd)); |
638 | #endif | ||
638 | explicit_bzero(rnd, sizeof(rnd)); | 639 | explicit_bzero(rnd, sizeof(rnd)); |
639 | 640 | ||
640 | /* Demote the private keys to public keys. */ | 641 | /* Demote the private keys to public keys. */ |
@@ -664,14 +665,14 @@ privsep_preauth_child(void) | |||
664 | static int | 665 | static int |
665 | privsep_preauth(Authctxt *authctxt) | 666 | privsep_preauth(Authctxt *authctxt) |
666 | { | 667 | { |
667 | int status; | 668 | int status, r; |
668 | pid_t pid; | 669 | pid_t pid; |
669 | struct ssh_sandbox *box = NULL; | 670 | struct ssh_sandbox *box = NULL; |
670 | 671 | ||
671 | /* Set up unprivileged child process to deal with network data */ | 672 | /* Set up unprivileged child process to deal with network data */ |
672 | pmonitor = monitor_init(); | 673 | pmonitor = monitor_init(); |
673 | /* Store a pointer to the kex for later rekeying */ | 674 | /* Store a pointer to the kex for later rekeying */ |
674 | pmonitor->m_pkex = &xxx_kex; | 675 | pmonitor->m_pkex = &active_state->kex; |
675 | 676 | ||
676 | if (use_privsep == PRIVSEP_ON) | 677 | if (use_privsep == PRIVSEP_ON) |
677 | box = ssh_sandbox_init(pmonitor); | 678 | box = ssh_sandbox_init(pmonitor); |
@@ -682,8 +683,14 @@ privsep_preauth(Authctxt *authctxt) | |||
682 | debug2("Network child is on pid %ld", (long)pid); | 683 | debug2("Network child is on pid %ld", (long)pid); |
683 | 684 | ||
684 | pmonitor->m_pid = pid; | 685 | pmonitor->m_pid = pid; |
685 | if (have_agent) | 686 | if (have_agent) { |
686 | auth_conn = ssh_get_authentication_connection(); | 687 | r = ssh_get_authentication_socket(&auth_sock); |
688 | if (r != 0) { | ||
689 | error("Could not get agent socket: %s", | ||
690 | ssh_err(r)); | ||
691 | have_agent = 0; | ||
692 | } | ||
693 | } | ||
687 | if (box != NULL) | 694 | if (box != NULL) |
688 | ssh_sandbox_parent_preauth(box, pid); | 695 | ssh_sandbox_parent_preauth(box, pid); |
689 | monitor_child_preauth(authctxt, pmonitor); | 696 | monitor_child_preauth(authctxt, pmonitor); |
@@ -769,7 +776,9 @@ privsep_postauth(Authctxt *authctxt) | |||
769 | 776 | ||
770 | arc4random_stir(); | 777 | arc4random_stir(); |
771 | arc4random_buf(rnd, sizeof(rnd)); | 778 | arc4random_buf(rnd, sizeof(rnd)); |
779 | #ifdef WITH_OPENSSL | ||
772 | RAND_seed(rnd, sizeof(rnd)); | 780 | RAND_seed(rnd, sizeof(rnd)); |
781 | #endif | ||
773 | explicit_bzero(rnd, sizeof(rnd)); | 782 | explicit_bzero(rnd, sizeof(rnd)); |
774 | 783 | ||
775 | /* Drop privileges */ | 784 | /* Drop privileges */ |
@@ -839,7 +848,7 @@ list_hostkey_types(void) | |||
839 | } | 848 | } |
840 | 849 | ||
841 | static Key * | 850 | static Key * |
842 | get_hostkey_by_type(int type, int need_private) | 851 | get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) |
843 | { | 852 | { |
844 | int i; | 853 | int i; |
845 | Key *key; | 854 | Key *key; |
@@ -860,7 +869,8 @@ get_hostkey_by_type(int type, int need_private) | |||
860 | key = sensitive_data.host_pubkeys[i]; | 869 | key = sensitive_data.host_pubkeys[i]; |
861 | break; | 870 | break; |
862 | } | 871 | } |
863 | if (key != NULL && key->type == type) | 872 | if (key != NULL && key->type == type && |
873 | (key->type != KEY_ECDSA || key->ecdsa_nid == nid)) | ||
864 | return need_private ? | 874 | return need_private ? |
865 | sensitive_data.host_keys[i] : key; | 875 | sensitive_data.host_keys[i] : key; |
866 | } | 876 | } |
@@ -868,15 +878,15 @@ get_hostkey_by_type(int type, int need_private) | |||
868 | } | 878 | } |
869 | 879 | ||
870 | Key * | 880 | Key * |
871 | get_hostkey_public_by_type(int type) | 881 | get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) |
872 | { | 882 | { |
873 | return get_hostkey_by_type(type, 0); | 883 | return get_hostkey_by_type(type, nid, 0, ssh); |
874 | } | 884 | } |
875 | 885 | ||
876 | Key * | 886 | Key * |
877 | get_hostkey_private_by_type(int type) | 887 | get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) |
878 | { | 888 | { |
879 | return get_hostkey_by_type(type, 1); | 889 | return get_hostkey_by_type(type, nid, 1, ssh); |
880 | } | 890 | } |
881 | 891 | ||
882 | Key * | 892 | Key * |
@@ -888,7 +898,7 @@ get_hostkey_by_index(int ind) | |||
888 | } | 898 | } |
889 | 899 | ||
890 | Key * | 900 | Key * |
891 | get_hostkey_public_by_index(int ind) | 901 | get_hostkey_public_by_index(int ind, struct ssh *ssh) |
892 | { | 902 | { |
893 | if (ind < 0 || ind >= options.num_host_key_files) | 903 | if (ind < 0 || ind >= options.num_host_key_files) |
894 | return (NULL); | 904 | return (NULL); |
@@ -896,24 +906,71 @@ get_hostkey_public_by_index(int ind) | |||
896 | } | 906 | } |
897 | 907 | ||
898 | int | 908 | int |
899 | get_hostkey_index(Key *key) | 909 | get_hostkey_index(Key *key, int compare, struct ssh *ssh) |
900 | { | 910 | { |
901 | int i; | 911 | int i; |
902 | 912 | ||
903 | for (i = 0; i < options.num_host_key_files; i++) { | 913 | for (i = 0; i < options.num_host_key_files; i++) { |
904 | if (key_is_cert(key)) { | 914 | if (key_is_cert(key)) { |
905 | if (key == sensitive_data.host_certificates[i]) | 915 | if (key == sensitive_data.host_certificates[i] || |
916 | (compare && sensitive_data.host_certificates[i] && | ||
917 | sshkey_equal(key, | ||
918 | sensitive_data.host_certificates[i]))) | ||
906 | return (i); | 919 | return (i); |
907 | } else { | 920 | } else { |
908 | if (key == sensitive_data.host_keys[i]) | 921 | if (key == sensitive_data.host_keys[i] || |
922 | (compare && sensitive_data.host_keys[i] && | ||
923 | sshkey_equal(key, sensitive_data.host_keys[i]))) | ||
909 | return (i); | 924 | return (i); |
910 | if (key == sensitive_data.host_pubkeys[i]) | 925 | if (key == sensitive_data.host_pubkeys[i] || |
926 | (compare && sensitive_data.host_pubkeys[i] && | ||
927 | sshkey_equal(key, sensitive_data.host_pubkeys[i]))) | ||
911 | return (i); | 928 | return (i); |
912 | } | 929 | } |
913 | } | 930 | } |
914 | return (-1); | 931 | return (-1); |
915 | } | 932 | } |
916 | 933 | ||
934 | /* Inform the client of all hostkeys */ | ||
935 | static void | ||
936 | notify_hostkeys(struct ssh *ssh) | ||
937 | { | ||
938 | struct sshbuf *buf; | ||
939 | struct sshkey *key; | ||
940 | int i, nkeys, r; | ||
941 | char *fp; | ||
942 | |||
943 | if ((buf = sshbuf_new()) == NULL) | ||
944 | fatal("%s: sshbuf_new", __func__); | ||
945 | for (i = nkeys = 0; i < options.num_host_key_files; i++) { | ||
946 | key = get_hostkey_public_by_index(i, ssh); | ||
947 | if (key == NULL || key->type == KEY_UNSPEC || | ||
948 | key->type == KEY_RSA1 || sshkey_is_cert(key)) | ||
949 | continue; | ||
950 | fp = sshkey_fingerprint(key, options.fingerprint_hash, | ||
951 | SSH_FP_DEFAULT); | ||
952 | debug3("%s: key %d: %s %s", __func__, i, | ||
953 | sshkey_ssh_name(key), fp); | ||
954 | free(fp); | ||
955 | if (nkeys == 0) { | ||
956 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | ||
957 | packet_put_cstring("hostkeys-00@openssh.com"); | ||
958 | packet_put_char(0); /* want-reply */ | ||
959 | } | ||
960 | sshbuf_reset(buf); | ||
961 | if ((r = sshkey_putb(key, buf)) != 0) | ||
962 | fatal("%s: couldn't put hostkey %d: %s", | ||
963 | __func__, i, ssh_err(r)); | ||
964 | packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf)); | ||
965 | nkeys++; | ||
966 | } | ||
967 | debug3("%s: sent %d hostkeys", __func__, nkeys); | ||
968 | if (nkeys == 0) | ||
969 | fatal("%s: no hostkeys", __func__); | ||
970 | packet_send(); | ||
971 | sshbuf_free(buf); | ||
972 | } | ||
973 | |||
917 | /* | 974 | /* |
918 | * returns 1 if connection should be dropped, 0 otherwise. | 975 | * returns 1 if connection should be dropped, 0 otherwise. |
919 | * dropping starts at connection #max_startups_begin with a probability | 976 | * dropping starts at connection #max_startups_begin with a probability |
@@ -999,7 +1056,7 @@ send_rexec_state(int fd, Buffer *conf) | |||
999 | #endif | 1056 | #endif |
1000 | buffer_put_int(&m, 0); | 1057 | buffer_put_int(&m, 0); |
1001 | 1058 | ||
1002 | #ifndef OPENSSL_PRNG_ONLY | 1059 | #if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) |
1003 | rexec_send_rng_seed(&m); | 1060 | rexec_send_rng_seed(&m); |
1004 | #endif | 1061 | #endif |
1005 | 1062 | ||
@@ -1052,7 +1109,7 @@ recv_rexec_state(int fd, Buffer *conf) | |||
1052 | #endif | 1109 | #endif |
1053 | } | 1110 | } |
1054 | 1111 | ||
1055 | #ifndef OPENSSL_PRNG_ONLY | 1112 | #if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) |
1056 | rexec_recv_rng_seed(&m); | 1113 | rexec_recv_rng_seed(&m); |
1057 | #endif | 1114 | #endif |
1058 | 1115 | ||
@@ -1219,7 +1276,8 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1219 | logit("Received signal %d; terminating.", | 1276 | logit("Received signal %d; terminating.", |
1220 | (int) received_sigterm); | 1277 | (int) received_sigterm); |
1221 | close_listen_socks(); | 1278 | close_listen_socks(); |
1222 | unlink(options.pid_file); | 1279 | if (options.pid_file != NULL) |
1280 | unlink(options.pid_file); | ||
1223 | exit(received_sigterm == SIGTERM ? 0 : 255); | 1281 | exit(received_sigterm == SIGTERM ? 0 : 255); |
1224 | } | 1282 | } |
1225 | if (key_used && key_do_regen) { | 1283 | if (key_used && key_do_regen) { |
@@ -1382,7 +1440,9 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1382 | */ | 1440 | */ |
1383 | arc4random_stir(); | 1441 | arc4random_stir(); |
1384 | arc4random_buf(rnd, sizeof(rnd)); | 1442 | arc4random_buf(rnd, sizeof(rnd)); |
1443 | #ifdef WITH_OPENSSL | ||
1385 | RAND_seed(rnd, sizeof(rnd)); | 1444 | RAND_seed(rnd, sizeof(rnd)); |
1445 | #endif | ||
1386 | explicit_bzero(rnd, sizeof(rnd)); | 1446 | explicit_bzero(rnd, sizeof(rnd)); |
1387 | } | 1447 | } |
1388 | 1448 | ||
@@ -1401,11 +1461,11 @@ main(int ac, char **av) | |||
1401 | { | 1461 | { |
1402 | extern char *optarg; | 1462 | extern char *optarg; |
1403 | extern int optind; | 1463 | extern int optind; |
1404 | int opt, i, j, on = 1; | 1464 | int r, opt, i, j, on = 1; |
1405 | int sock_in = -1, sock_out = -1, newsock = -1; | 1465 | int sock_in = -1, sock_out = -1, newsock = -1; |
1406 | const char *remote_ip; | 1466 | const char *remote_ip; |
1407 | int remote_port; | 1467 | int remote_port; |
1408 | char *line, *logfile = NULL; | 1468 | char *fp, *line, *logfile = NULL; |
1409 | int config_s[2] = { -1 , -1 }; | 1469 | int config_s[2] = { -1 , -1 }; |
1410 | u_int n; | 1470 | u_int n; |
1411 | u_int64_t ibytes, obytes; | 1471 | u_int64_t ibytes, obytes; |
@@ -1544,8 +1604,8 @@ main(int ac, char **av) | |||
1544 | exit(1); | 1604 | exit(1); |
1545 | break; | 1605 | break; |
1546 | case 'u': | 1606 | case 'u': |
1547 | utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL); | 1607 | utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL); |
1548 | if (utmp_len > MAXHOSTNAMELEN) { | 1608 | if (utmp_len > HOST_NAME_MAX+1) { |
1549 | fprintf(stderr, "Invalid utmp length.\n"); | 1609 | fprintf(stderr, "Invalid utmp length.\n"); |
1550 | exit(1); | 1610 | exit(1); |
1551 | } | 1611 | } |
@@ -1705,21 +1765,25 @@ main(int ac, char **av) | |||
1705 | sizeof(Key *)); | 1765 | sizeof(Key *)); |
1706 | sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, | 1766 | sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, |
1707 | sizeof(Key *)); | 1767 | sizeof(Key *)); |
1708 | for (i = 0; i < options.num_host_key_files; i++) { | ||
1709 | sensitive_data.host_keys[i] = NULL; | ||
1710 | sensitive_data.host_pubkeys[i] = NULL; | ||
1711 | } | ||
1712 | 1768 | ||
1713 | if (options.host_key_agent) { | 1769 | if (options.host_key_agent) { |
1714 | if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) | 1770 | if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) |
1715 | setenv(SSH_AUTHSOCKET_ENV_NAME, | 1771 | setenv(SSH_AUTHSOCKET_ENV_NAME, |
1716 | options.host_key_agent, 1); | 1772 | options.host_key_agent, 1); |
1717 | have_agent = ssh_agent_present(); | 1773 | if ((r = ssh_get_authentication_socket(NULL)) == 0) |
1774 | have_agent = 1; | ||
1775 | else | ||
1776 | error("Could not connect to agent \"%s\": %s", | ||
1777 | options.host_key_agent, ssh_err(r)); | ||
1718 | } | 1778 | } |
1719 | 1779 | ||
1720 | for (i = 0; i < options.num_host_key_files; i++) { | 1780 | for (i = 0; i < options.num_host_key_files; i++) { |
1781 | if (options.host_key_files[i] == NULL) | ||
1782 | continue; | ||
1721 | key = key_load_private(options.host_key_files[i], "", NULL); | 1783 | key = key_load_private(options.host_key_files[i], "", NULL); |
1722 | pubkey = key_load_public(options.host_key_files[i], NULL); | 1784 | pubkey = key_load_public(options.host_key_files[i], NULL); |
1785 | if (pubkey == NULL && key != NULL) | ||
1786 | pubkey = key_demote(key); | ||
1723 | sensitive_data.host_keys[i] = key; | 1787 | sensitive_data.host_keys[i] = key; |
1724 | sensitive_data.host_pubkeys[i] = pubkey; | 1788 | sensitive_data.host_pubkeys[i] = pubkey; |
1725 | 1789 | ||
@@ -1747,11 +1811,17 @@ main(int ac, char **av) | |||
1747 | case KEY_DSA: | 1811 | case KEY_DSA: |
1748 | case KEY_ECDSA: | 1812 | case KEY_ECDSA: |
1749 | case KEY_ED25519: | 1813 | case KEY_ED25519: |
1750 | sensitive_data.have_ssh2_key = 1; | 1814 | if (have_agent || key != NULL) |
1815 | sensitive_data.have_ssh2_key = 1; | ||
1751 | break; | 1816 | break; |
1752 | } | 1817 | } |
1753 | debug("private host key: #%d type %d %s", i, keytype, | 1818 | if ((fp = sshkey_fingerprint(pubkey, options.fingerprint_hash, |
1754 | key_type(key ? key : pubkey)); | 1819 | SSH_FP_DEFAULT)) == NULL) |
1820 | fatal("sshkey_fingerprint failed"); | ||
1821 | debug("%s host key #%d: %s %s", | ||
1822 | key ? "private" : "agent", i, keytype == KEY_RSA1 ? | ||
1823 | sshkey_type(pubkey) : sshkey_ssh_name(pubkey), fp); | ||
1824 | free(fp); | ||
1755 | } | 1825 | } |
1756 | if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { | 1826 | if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { |
1757 | logit("Disabling protocol version 1. Could not load host key"); | 1827 | logit("Disabling protocol version 1. Could not load host key"); |
@@ -1779,6 +1849,8 @@ main(int ac, char **av) | |||
1779 | sensitive_data.host_certificates[i] = NULL; | 1849 | sensitive_data.host_certificates[i] = NULL; |
1780 | 1850 | ||
1781 | for (i = 0; i < options.num_host_cert_files; i++) { | 1851 | for (i = 0; i < options.num_host_cert_files; i++) { |
1852 | if (options.host_cert_files[i] == NULL) | ||
1853 | continue; | ||
1782 | key = key_load_public(options.host_cert_files[i], NULL); | 1854 | key = key_load_public(options.host_cert_files[i], NULL); |
1783 | if (key == NULL) { | 1855 | if (key == NULL) { |
1784 | error("Could not load host certificate: %s", | 1856 | error("Could not load host certificate: %s", |
@@ -1946,7 +2018,7 @@ main(int ac, char **av) | |||
1946 | * Write out the pid file after the sigterm handler | 2018 | * Write out the pid file after the sigterm handler |
1947 | * is setup and the listen sockets are bound | 2019 | * is setup and the listen sockets are bound |
1948 | */ | 2020 | */ |
1949 | if (!debug_flag) { | 2021 | if (options.pid_file != NULL && !debug_flag) { |
1950 | FILE *f = fopen(options.pid_file, "w"); | 2022 | FILE *f = fopen(options.pid_file, "w"); |
1951 | 2023 | ||
1952 | if (f == NULL) { | 2024 | if (f == NULL) { |
@@ -2192,8 +2264,12 @@ main(int ac, char **av) | |||
2192 | if (use_privsep) { | 2264 | if (use_privsep) { |
2193 | if (privsep_preauth(authctxt) == 1) | 2265 | if (privsep_preauth(authctxt) == 1) |
2194 | goto authenticated; | 2266 | goto authenticated; |
2195 | } else if (compat20 && have_agent) | 2267 | } else if (compat20 && have_agent) { |
2196 | auth_conn = ssh_get_authentication_connection(); | 2268 | if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { |
2269 | error("Unable to get agent socket: %s", ssh_err(r)); | ||
2270 | have_agent = 0; | ||
2271 | } | ||
2272 | } | ||
2197 | 2273 | ||
2198 | /* perform the key exchange */ | 2274 | /* perform the key exchange */ |
2199 | /* authenticate user and start session */ | 2275 | /* authenticate user and start session */ |
@@ -2262,12 +2338,15 @@ main(int ac, char **av) | |||
2262 | packet_set_timeout(options.client_alive_interval, | 2338 | packet_set_timeout(options.client_alive_interval, |
2263 | options.client_alive_count_max); | 2339 | options.client_alive_count_max); |
2264 | 2340 | ||
2341 | /* Try to send all our hostkeys to the client */ | ||
2342 | if (compat20) | ||
2343 | notify_hostkeys(active_state); | ||
2344 | |||
2265 | /* Start session. */ | 2345 | /* Start session. */ |
2266 | do_authenticated(authctxt); | 2346 | do_authenticated(authctxt); |
2267 | 2347 | ||
2268 | /* The connection has been terminated. */ | 2348 | /* The connection has been terminated. */ |
2269 | packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); | 2349 | packet_get_bytes(&ibytes, &obytes); |
2270 | packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); | ||
2271 | verbose("Transferred: sent %llu, received %llu bytes", | 2350 | verbose("Transferred: sent %llu, received %llu bytes", |
2272 | (unsigned long long)obytes, (unsigned long long)ibytes); | 2351 | (unsigned long long)obytes, (unsigned long long)ibytes); |
2273 | 2352 | ||
@@ -2349,8 +2428,10 @@ do_ssh1_kex(void) | |||
2349 | { | 2428 | { |
2350 | int i, len; | 2429 | int i, len; |
2351 | int rsafail = 0; | 2430 | int rsafail = 0; |
2352 | BIGNUM *session_key_int; | 2431 | BIGNUM *session_key_int, *fake_key_int, *real_key_int; |
2353 | u_char session_key[SSH_SESSION_KEY_LENGTH]; | 2432 | u_char session_key[SSH_SESSION_KEY_LENGTH]; |
2433 | u_char fake_key_bytes[4096 / 8]; | ||
2434 | size_t fake_key_len; | ||
2354 | u_char cookie[8]; | 2435 | u_char cookie[8]; |
2355 | u_int cipher_type, auth_mask, protocol_flags; | 2436 | u_int cipher_type, auth_mask, protocol_flags; |
2356 | 2437 | ||
@@ -2428,74 +2509,61 @@ do_ssh1_kex(void) | |||
2428 | debug("Encryption type: %.200s", cipher_name(cipher_type)); | 2509 | debug("Encryption type: %.200s", cipher_name(cipher_type)); |
2429 | 2510 | ||
2430 | /* Get the encrypted integer. */ | 2511 | /* Get the encrypted integer. */ |
2431 | if ((session_key_int = BN_new()) == NULL) | 2512 | if ((real_key_int = BN_new()) == NULL) |
2432 | fatal("do_ssh1_kex: BN_new failed"); | 2513 | fatal("do_ssh1_kex: BN_new failed"); |
2433 | packet_get_bignum(session_key_int); | 2514 | packet_get_bignum(real_key_int); |
2434 | 2515 | ||
2435 | protocol_flags = packet_get_int(); | 2516 | protocol_flags = packet_get_int(); |
2436 | packet_set_protocol_flags(protocol_flags); | 2517 | packet_set_protocol_flags(protocol_flags); |
2437 | packet_check_eom(); | 2518 | packet_check_eom(); |
2438 | 2519 | ||
2439 | /* Decrypt session_key_int using host/server keys */ | 2520 | /* Setup a fake key in case RSA decryption fails */ |
2440 | rsafail = PRIVSEP(ssh1_session_key(session_key_int)); | 2521 | if ((fake_key_int = BN_new()) == NULL) |
2522 | fatal("do_ssh1_kex: BN_new failed"); | ||
2523 | fake_key_len = BN_num_bytes(real_key_int); | ||
2524 | if (fake_key_len > sizeof(fake_key_bytes)) | ||
2525 | fake_key_len = sizeof(fake_key_bytes); | ||
2526 | arc4random_buf(fake_key_bytes, fake_key_len); | ||
2527 | if (BN_bin2bn(fake_key_bytes, fake_key_len, fake_key_int) == NULL) | ||
2528 | fatal("do_ssh1_kex: BN_bin2bn failed"); | ||
2529 | |||
2530 | /* Decrypt real_key_int using host/server keys */ | ||
2531 | rsafail = PRIVSEP(ssh1_session_key(real_key_int)); | ||
2532 | /* If decryption failed, use the fake key. Else, the real key. */ | ||
2533 | if (rsafail) | ||
2534 | session_key_int = fake_key_int; | ||
2535 | else | ||
2536 | session_key_int = real_key_int; | ||
2441 | 2537 | ||
2442 | /* | 2538 | /* |
2443 | * Extract session key from the decrypted integer. The key is in the | 2539 | * Extract session key from the decrypted integer. The key is in the |
2444 | * least significant 256 bits of the integer; the first byte of the | 2540 | * least significant 256 bits of the integer; the first byte of the |
2445 | * key is in the highest bits. | 2541 | * key is in the highest bits. |
2446 | */ | 2542 | */ |
2447 | if (!rsafail) { | 2543 | (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); |
2448 | (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); | 2544 | len = BN_num_bytes(session_key_int); |
2449 | len = BN_num_bytes(session_key_int); | 2545 | if (len < 0 || (u_int)len > sizeof(session_key)) { |
2450 | if (len < 0 || (u_int)len > sizeof(session_key)) { | 2546 | error("do_ssh1_kex: bad session key len from %s: " |
2451 | error("do_ssh1_kex: bad session key len from %s: " | 2547 | "session_key_int %d > sizeof(session_key) %lu", |
2452 | "session_key_int %d > sizeof(session_key) %lu", | 2548 | get_remote_ipaddr(), len, (u_long)sizeof(session_key)); |
2453 | get_remote_ipaddr(), len, (u_long)sizeof(session_key)); | 2549 | rsafail++; |
2454 | rsafail++; | 2550 | } else { |
2455 | } else { | 2551 | explicit_bzero(session_key, sizeof(session_key)); |
2456 | explicit_bzero(session_key, sizeof(session_key)); | 2552 | BN_bn2bin(session_key_int, |
2457 | BN_bn2bin(session_key_int, | 2553 | session_key + sizeof(session_key) - len); |
2458 | session_key + sizeof(session_key) - len); | 2554 | |
2459 | 2555 | derive_ssh1_session_id( | |
2460 | derive_ssh1_session_id( | 2556 | sensitive_data.ssh1_host_key->rsa->n, |
2461 | sensitive_data.ssh1_host_key->rsa->n, | 2557 | sensitive_data.server_key->rsa->n, |
2462 | sensitive_data.server_key->rsa->n, | 2558 | cookie, session_id); |
2463 | cookie, session_id); | 2559 | /* |
2464 | /* | 2560 | * Xor the first 16 bytes of the session key with the |
2465 | * Xor the first 16 bytes of the session key with the | 2561 | * session id. |
2466 | * session id. | 2562 | */ |
2467 | */ | ||
2468 | for (i = 0; i < 16; i++) | ||
2469 | session_key[i] ^= session_id[i]; | ||
2470 | } | ||
2471 | } | ||
2472 | if (rsafail) { | ||
2473 | int bytes = BN_num_bytes(session_key_int); | ||
2474 | u_char *buf = xmalloc(bytes); | ||
2475 | struct ssh_digest_ctx *md; | ||
2476 | |||
2477 | logit("do_connection: generating a fake encryption key"); | ||
2478 | BN_bn2bin(session_key_int, buf); | ||
2479 | if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || | ||
2480 | ssh_digest_update(md, buf, bytes) < 0 || | ||
2481 | ssh_digest_update(md, sensitive_data.ssh1_cookie, | ||
2482 | SSH_SESSION_KEY_LENGTH) < 0 || | ||
2483 | ssh_digest_final(md, session_key, sizeof(session_key)) < 0) | ||
2484 | fatal("%s: md5 failed", __func__); | ||
2485 | ssh_digest_free(md); | ||
2486 | if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || | ||
2487 | ssh_digest_update(md, session_key, 16) < 0 || | ||
2488 | ssh_digest_update(md, sensitive_data.ssh1_cookie, | ||
2489 | SSH_SESSION_KEY_LENGTH) < 0 || | ||
2490 | ssh_digest_final(md, session_key + 16, | ||
2491 | sizeof(session_key) - 16) < 0) | ||
2492 | fatal("%s: md5 failed", __func__); | ||
2493 | ssh_digest_free(md); | ||
2494 | explicit_bzero(buf, bytes); | ||
2495 | free(buf); | ||
2496 | for (i = 0; i < 16; i++) | 2563 | for (i = 0; i < 16; i++) |
2497 | session_id[i] = session_key[i] ^ session_key[i + 16]; | 2564 | session_key[i] ^= session_id[i]; |
2498 | } | 2565 | } |
2566 | |||
2499 | /* Destroy the private and public keys. No longer. */ | 2567 | /* Destroy the private and public keys. No longer. */ |
2500 | destroy_sensitive_data(); | 2568 | destroy_sensitive_data(); |
2501 | 2569 | ||
@@ -2503,7 +2571,8 @@ do_ssh1_kex(void) | |||
2503 | mm_ssh1_session_id(session_id); | 2571 | mm_ssh1_session_id(session_id); |
2504 | 2572 | ||
2505 | /* Destroy the decrypted integer. It is no longer needed. */ | 2573 | /* Destroy the decrypted integer. It is no longer needed. */ |
2506 | BN_clear_free(session_key_int); | 2574 | BN_clear_free(real_key_int); |
2575 | BN_clear_free(fake_key_int); | ||
2507 | 2576 | ||
2508 | /* Set the session key. From this on all communications will be encrypted. */ | 2577 | /* Set the session key. From this on all communications will be encrypted. */ |
2509 | packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type); | 2578 | packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type); |
@@ -2520,21 +2589,30 @@ do_ssh1_kex(void) | |||
2520 | } | 2589 | } |
2521 | #endif | 2590 | #endif |
2522 | 2591 | ||
2523 | void | 2592 | int |
2524 | sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, | 2593 | sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen, |
2525 | u_char *data, u_int dlen) | 2594 | const u_char *data, size_t dlen, u_int flag) |
2526 | { | 2595 | { |
2596 | int r; | ||
2597 | u_int xxx_slen, xxx_dlen = dlen; | ||
2598 | |||
2527 | if (privkey) { | 2599 | if (privkey) { |
2528 | if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0)) | 2600 | if (PRIVSEP(key_sign(privkey, signature, &xxx_slen, data, xxx_dlen) < 0)) |
2529 | fatal("%s: key_sign failed", __func__); | 2601 | fatal("%s: key_sign failed", __func__); |
2602 | if (slen) | ||
2603 | *slen = xxx_slen; | ||
2530 | } else if (use_privsep) { | 2604 | } else if (use_privsep) { |
2531 | if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0) | 2605 | if (mm_key_sign(pubkey, signature, &xxx_slen, data, xxx_dlen) < 0) |
2532 | fatal("%s: pubkey_sign failed", __func__); | 2606 | fatal("%s: pubkey_sign failed", __func__); |
2607 | if (slen) | ||
2608 | *slen = xxx_slen; | ||
2533 | } else { | 2609 | } else { |
2534 | if (ssh_agent_sign(auth_conn, pubkey, signature, slen, data, | 2610 | if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slen, |
2535 | dlen)) | 2611 | data, dlen, datafellows)) != 0) |
2536 | fatal("%s: ssh_agent_sign failed", __func__); | 2612 | fatal("%s: ssh_agent_sign failed: %s", |
2613 | __func__, ssh_err(r)); | ||
2537 | } | 2614 | } |
2615 | return 0; | ||
2538 | } | 2616 | } |
2539 | 2617 | ||
2540 | /* | 2618 | /* |
@@ -2544,7 +2622,8 @@ static void | |||
2544 | do_ssh2_kex(void) | 2622 | do_ssh2_kex(void) |
2545 | { | 2623 | { |
2546 | char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; | 2624 | char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; |
2547 | Kex *kex; | 2625 | struct kex *kex; |
2626 | int r; | ||
2548 | 2627 | ||
2549 | if (options.ciphers != NULL) { | 2628 | if (options.ciphers != NULL) { |
2550 | myproposal[PROPOSAL_ENC_ALGS_CTOS] = | 2629 | myproposal[PROPOSAL_ENC_ALGS_CTOS] = |
@@ -2622,13 +2701,17 @@ do_ssh2_kex(void) | |||
2622 | #endif | 2701 | #endif |
2623 | 2702 | ||
2624 | /* start key exchange */ | 2703 | /* start key exchange */ |
2625 | kex = kex_setup(myproposal); | 2704 | if ((r = kex_setup(active_state, myproposal)) != 0) |
2705 | fatal("kex_setup: %s", ssh_err(r)); | ||
2706 | kex = active_state->kex; | ||
2626 | #ifdef WITH_OPENSSL | 2707 | #ifdef WITH_OPENSSL |
2627 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 2708 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
2628 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | 2709 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
2629 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 2710 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
2630 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | 2711 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
2712 | # ifdef OPENSSL_HAS_ECC | ||
2631 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | 2713 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
2714 | # endif | ||
2632 | #endif | 2715 | #endif |
2633 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | 2716 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
2634 | #ifdef GSSAPI | 2717 | #ifdef GSSAPI |
@@ -2646,9 +2729,7 @@ do_ssh2_kex(void) | |||
2646 | kex->host_key_index=&get_hostkey_index; | 2729 | kex->host_key_index=&get_hostkey_index; |
2647 | kex->sign = sshd_hostkey_sign; | 2730 | kex->sign = sshd_hostkey_sign; |
2648 | 2731 | ||
2649 | xxx_kex = kex; | 2732 | dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); |
2650 | |||
2651 | dispatch_run(DISPATCH_BLOCK, &kex->done, kex); | ||
2652 | 2733 | ||
2653 | session_id2 = kex->session_id; | 2734 | session_id2 = kex->session_id; |
2654 | session_id2_len = kex->session_id_len; | 2735 | session_id2_len = kex->session_id_len; |