diff options
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 407 |
1 files changed, 149 insertions, 258 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.145 2015/02/20 22:17:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -28,7 +28,6 @@ | |||
28 | #include "includes.h" | 28 | #include "includes.h" |
29 | 29 | ||
30 | #include <sys/types.h> | 30 | #include <sys/types.h> |
31 | #include <sys/param.h> | ||
32 | #include <sys/socket.h> | 31 | #include <sys/socket.h> |
33 | #include "openbsd-compat/sys-tree.h" | 32 | #include "openbsd-compat/sys-tree.h" |
34 | #include <sys/wait.h> | 33 | #include <sys/wait.h> |
@@ -40,6 +39,9 @@ | |||
40 | #endif | 39 | #endif |
41 | #include <pwd.h> | 40 | #include <pwd.h> |
42 | #include <signal.h> | 41 | #include <signal.h> |
42 | #ifdef HAVE_STDINT_H | ||
43 | #include <stdint.h> | ||
44 | #endif | ||
43 | #include <stdlib.h> | 45 | #include <stdlib.h> |
44 | #include <string.h> | 46 | #include <string.h> |
45 | #include <stdarg.h> | 47 | #include <stdarg.h> |
@@ -100,6 +102,8 @@ | |||
100 | #include "ssh2.h" | 102 | #include "ssh2.h" |
101 | #include "roaming.h" | 103 | #include "roaming.h" |
102 | #include "authfd.h" | 104 | #include "authfd.h" |
105 | #include "match.h" | ||
106 | #include "ssherr.h" | ||
103 | #ifdef USE_CONSOLEKIT | 107 | #ifdef USE_CONSOLEKIT |
104 | #include "consolekit.h" | 108 | #include "consolekit.h" |
105 | #endif | 109 | #endif |
@@ -111,38 +115,13 @@ static Gssctxt *gsscontext = NULL; | |||
111 | /* Imports */ | 115 | /* Imports */ |
112 | extern ServerOptions options; | 116 | extern ServerOptions options; |
113 | extern u_int utmp_len; | 117 | extern u_int utmp_len; |
114 | extern Newkeys *current_keys[]; | ||
115 | extern z_stream incoming_stream; | ||
116 | extern z_stream outgoing_stream; | ||
117 | extern u_char session_id[]; | 118 | extern u_char session_id[]; |
118 | extern Buffer auth_debug; | 119 | extern Buffer auth_debug; |
119 | extern int auth_debug_init; | 120 | extern int auth_debug_init; |
120 | extern Buffer loginmsg; | 121 | extern Buffer loginmsg; |
121 | 122 | ||
122 | /* State exported from the child */ | 123 | /* State exported from the child */ |
123 | 124 | static struct sshbuf *child_state; | |
124 | struct { | ||
125 | z_stream incoming; | ||
126 | z_stream outgoing; | ||
127 | u_char *keyin; | ||
128 | u_int keyinlen; | ||
129 | u_char *keyout; | ||
130 | u_int keyoutlen; | ||
131 | u_char *ivin; | ||
132 | u_int ivinlen; | ||
133 | u_char *ivout; | ||
134 | u_int ivoutlen; | ||
135 | u_char *ssh1key; | ||
136 | u_int ssh1keylen; | ||
137 | int ssh1cipher; | ||
138 | int ssh1protoflags; | ||
139 | u_char *input; | ||
140 | u_int ilen; | ||
141 | u_char *output; | ||
142 | u_int olen; | ||
143 | u_int64_t sent_bytes; | ||
144 | u_int64_t recv_bytes; | ||
145 | } child_state; | ||
146 | 125 | ||
147 | /* Functions on the monitor that answer unprivileged requests */ | 126 | /* Functions on the monitor that answer unprivileged requests */ |
148 | 127 | ||
@@ -539,6 +518,27 @@ monitor_sync(struct monitor *pmonitor) | |||
539 | } | 518 | } |
540 | } | 519 | } |
541 | 520 | ||
521 | /* Allocation functions for zlib */ | ||
522 | static void * | ||
523 | mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) | ||
524 | { | ||
525 | size_t len = (size_t) size * ncount; | ||
526 | void *address; | ||
527 | |||
528 | if (len == 0 || ncount > SIZE_MAX / size) | ||
529 | fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); | ||
530 | |||
531 | address = mm_malloc(mm, len); | ||
532 | |||
533 | return (address); | ||
534 | } | ||
535 | |||
536 | static void | ||
537 | mm_zfree(struct mm_master *mm, void *address) | ||
538 | { | ||
539 | mm_free(mm, address); | ||
540 | } | ||
541 | |||
542 | static int | 542 | static int |
543 | monitor_read_log(struct monitor *pmonitor) | 543 | monitor_read_log(struct monitor *pmonitor) |
544 | { | 544 | { |
@@ -719,28 +719,60 @@ mm_answer_moduli(int sock, Buffer *m) | |||
719 | } | 719 | } |
720 | #endif | 720 | #endif |
721 | 721 | ||
722 | extern AuthenticationConnection *auth_conn; | ||
723 | |||
724 | int | 722 | int |
725 | mm_answer_sign(int sock, Buffer *m) | 723 | mm_answer_sign(int sock, Buffer *m) |
726 | { | 724 | { |
727 | Key *key; | 725 | struct ssh *ssh = active_state; /* XXX */ |
726 | extern int auth_sock; /* XXX move to state struct? */ | ||
727 | struct sshkey *key; | ||
728 | struct sshbuf *sigbuf; | ||
728 | u_char *p; | 729 | u_char *p; |
729 | u_char *signature; | 730 | u_char *signature; |
730 | u_int siglen, datlen; | 731 | size_t datlen, siglen; |
731 | int keyid; | 732 | int r, keyid, is_proof = 0; |
733 | const char proof_req[] = "hostkeys-prove-00@openssh.com"; | ||
732 | 734 | ||
733 | debug3("%s", __func__); | 735 | debug3("%s", __func__); |
734 | 736 | ||
735 | keyid = buffer_get_int(m); | 737 | if ((r = sshbuf_get_u32(m, &keyid)) != 0 || |
736 | p = buffer_get_string(m, &datlen); | 738 | (r = sshbuf_get_string(m, &p, &datlen)) != 0) |
739 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
737 | 740 | ||
738 | /* | 741 | /* |
739 | * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), | 742 | * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), |
740 | * SHA384 (48 bytes) and SHA512 (64 bytes). | 743 | * SHA384 (48 bytes) and SHA512 (64 bytes). |
744 | * | ||
745 | * Otherwise, verify the signature request is for a hostkey | ||
746 | * proof. | ||
747 | * | ||
748 | * XXX perform similar check for KEX signature requests too? | ||
749 | * it's not trivial, since what is signed is the hash, rather | ||
750 | * than the full kex structure... | ||
741 | */ | 751 | */ |
742 | if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) | 752 | if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { |
743 | fatal("%s: data length incorrect: %u", __func__, datlen); | 753 | /* |
754 | * Construct expected hostkey proof and compare it to what | ||
755 | * the client sent us. | ||
756 | */ | ||
757 | if (session_id2_len == 0) /* hostkeys is never first */ | ||
758 | fatal("%s: bad data length: %zu", __func__, datlen); | ||
759 | if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) | ||
760 | fatal("%s: no hostkey for index %d", __func__, keyid); | ||
761 | if ((sigbuf = sshbuf_new()) == NULL) | ||
762 | fatal("%s: sshbuf_new", __func__); | ||
763 | if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || | ||
764 | (r = sshbuf_put_string(sigbuf, session_id2, | ||
765 | session_id2_len) != 0) || | ||
766 | (r = sshkey_puts(key, sigbuf)) != 0) | ||
767 | fatal("%s: couldn't prepare private key " | ||
768 | "proof buffer: %s", __func__, ssh_err(r)); | ||
769 | if (datlen != sshbuf_len(sigbuf) || | ||
770 | memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) | ||
771 | fatal("%s: bad data length: %zu, hostkey proof len %zu", | ||
772 | __func__, datlen, sshbuf_len(sigbuf)); | ||
773 | sshbuf_free(sigbuf); | ||
774 | is_proof = 1; | ||
775 | } | ||
744 | 776 | ||
745 | /* save session id, it will be passed on the first call */ | 777 | /* save session id, it will be passed on the first call */ |
746 | if (session_id2_len == 0) { | 778 | if (session_id2_len == 0) { |
@@ -750,20 +782,26 @@ mm_answer_sign(int sock, Buffer *m) | |||
750 | } | 782 | } |
751 | 783 | ||
752 | if ((key = get_hostkey_by_index(keyid)) != NULL) { | 784 | if ((key = get_hostkey_by_index(keyid)) != NULL) { |
753 | if (key_sign(key, &signature, &siglen, p, datlen) < 0) | 785 | if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, |
754 | fatal("%s: key_sign failed", __func__); | 786 | datafellows)) != 0) |
755 | } else if ((key = get_hostkey_public_by_index(keyid)) != NULL && | 787 | fatal("%s: sshkey_sign failed: %s", |
756 | auth_conn != NULL) { | 788 | __func__, ssh_err(r)); |
757 | if (ssh_agent_sign(auth_conn, key, &signature, &siglen, p, | 789 | } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && |
758 | datlen) < 0) | 790 | auth_sock > 0) { |
759 | fatal("%s: ssh_agent_sign failed", __func__); | 791 | if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, |
792 | p, datlen, datafellows)) != 0) { | ||
793 | fatal("%s: ssh_agent_sign failed: %s", | ||
794 | __func__, ssh_err(r)); | ||
795 | } | ||
760 | } else | 796 | } else |
761 | fatal("%s: no hostkey from index %d", __func__, keyid); | 797 | fatal("%s: no hostkey from index %d", __func__, keyid); |
762 | 798 | ||
763 | debug3("%s: signature %p(%u)", __func__, signature, siglen); | 799 | debug3("%s: %s signature %p(%zu)", __func__, |
800 | is_proof ? "KEX" : "hostkey proof", signature, siglen); | ||
764 | 801 | ||
765 | buffer_clear(m); | 802 | sshbuf_reset(m); |
766 | buffer_put_string(m, signature, siglen); | 803 | if ((r = sshbuf_put_string(m, signature, siglen)) != 0) |
804 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
767 | 805 | ||
768 | free(p); | 806 | free(p); |
769 | free(signature); | 807 | free(signature); |
@@ -1226,9 +1264,18 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1226 | debug3("%s: key_from_blob: %p", __func__, key); | 1264 | debug3("%s: key_from_blob: %p", __func__, key); |
1227 | 1265 | ||
1228 | if (key != NULL && authctxt->valid) { | 1266 | if (key != NULL && authctxt->valid) { |
1267 | /* These should not make it past the privsep child */ | ||
1268 | if (key_type_plain(key->type) == KEY_RSA && | ||
1269 | (datafellows & SSH_BUG_RSASIGMD5) != 0) | ||
1270 | fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); | ||
1271 | |||
1229 | switch (type) { | 1272 | switch (type) { |
1230 | case MM_USERKEY: | 1273 | case MM_USERKEY: |
1231 | allowed = options.pubkey_authentication && | 1274 | allowed = options.pubkey_authentication && |
1275 | !auth2_userkey_already_used(authctxt, key) && | ||
1276 | match_pattern_list(sshkey_ssh_name(key), | ||
1277 | options.pubkey_key_types, | ||
1278 | strlen(options.pubkey_key_types), 0) == 1 && | ||
1232 | user_key_allowed(authctxt->pw, key); | 1279 | user_key_allowed(authctxt->pw, key); |
1233 | pubkey_auth_info(authctxt, key, NULL); | 1280 | pubkey_auth_info(authctxt, key, NULL); |
1234 | auth_method = "publickey"; | 1281 | auth_method = "publickey"; |
@@ -1237,6 +1284,9 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1237 | break; | 1284 | break; |
1238 | case MM_HOSTKEY: | 1285 | case MM_HOSTKEY: |
1239 | allowed = options.hostbased_authentication && | 1286 | allowed = options.hostbased_authentication && |
1287 | match_pattern_list(sshkey_ssh_name(key), | ||
1288 | options.hostbased_key_types, | ||
1289 | strlen(options.hostbased_key_types), 0) == 1 && | ||
1240 | hostbased_key_allowed(authctxt->pw, | 1290 | hostbased_key_allowed(authctxt->pw, |
1241 | cuser, chost, key); | 1291 | cuser, chost, key); |
1242 | pubkey_auth_info(authctxt, key, | 1292 | pubkey_auth_info(authctxt, key, |
@@ -1456,7 +1506,12 @@ mm_answer_keyverify(int sock, Buffer *m) | |||
1456 | debug3("%s: key %p signature %s", | 1506 | debug3("%s: key %p signature %s", |
1457 | __func__, key, (verified == 1) ? "verified" : "unverified"); | 1507 | __func__, key, (verified == 1) ? "verified" : "unverified"); |
1458 | 1508 | ||
1459 | key_free(key); | 1509 | /* If auth was successful then record key to ensure it isn't reused */ |
1510 | if (verified == 1) | ||
1511 | auth2_record_userkey(authctxt, key); | ||
1512 | else | ||
1513 | key_free(key); | ||
1514 | |||
1460 | free(blob); | 1515 | free(blob); |
1461 | free(signature); | 1516 | free(signature); |
1462 | free(data); | 1517 | free(data); |
@@ -1842,112 +1897,47 @@ mm_answer_audit_command(int socket, Buffer *m) | |||
1842 | void | 1897 | void |
1843 | monitor_apply_keystate(struct monitor *pmonitor) | 1898 | monitor_apply_keystate(struct monitor *pmonitor) |
1844 | { | 1899 | { |
1845 | if (compat20) { | 1900 | struct ssh *ssh = active_state; /* XXX */ |
1846 | set_newkeys(MODE_IN); | 1901 | struct kex *kex; |
1847 | set_newkeys(MODE_OUT); | 1902 | int r; |
1848 | } else { | 1903 | |
1849 | packet_set_protocol_flags(child_state.ssh1protoflags); | 1904 | debug3("%s: packet_set_state", __func__); |
1850 | packet_set_encryption_key(child_state.ssh1key, | 1905 | if ((r = ssh_packet_set_state(ssh, child_state)) != 0) |
1851 | child_state.ssh1keylen, child_state.ssh1cipher); | 1906 | fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); |
1852 | free(child_state.ssh1key); | 1907 | sshbuf_free(child_state); |
1853 | } | 1908 | child_state = NULL; |
1854 | 1909 | ||
1855 | /* for rc4 and other stateful ciphers */ | 1910 | if ((kex = ssh->kex) != 0) { |
1856 | packet_set_keycontext(MODE_OUT, child_state.keyout); | 1911 | /* XXX set callbacks */ |
1857 | free(child_state.keyout); | 1912 | #ifdef WITH_OPENSSL |
1858 | packet_set_keycontext(MODE_IN, child_state.keyin); | 1913 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
1859 | free(child_state.keyin); | 1914 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
1860 | 1915 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | |
1861 | if (!compat20) { | 1916 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
1862 | packet_set_iv(MODE_OUT, child_state.ivout); | 1917 | # ifdef OPENSSL_HAS_ECC |
1863 | free(child_state.ivout); | 1918 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
1864 | packet_set_iv(MODE_IN, child_state.ivin); | 1919 | # endif |
1865 | free(child_state.ivin); | 1920 | #endif /* WITH_OPENSSL */ |
1921 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | ||
1922 | #ifdef GSSAPI | ||
1923 | if (options.gss_keyex) { | ||
1924 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; | ||
1925 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; | ||
1926 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; | ||
1927 | } | ||
1928 | #endif | ||
1929 | kex->load_host_public_key=&get_hostkey_public_by_type; | ||
1930 | kex->load_host_private_key=&get_hostkey_private_by_type; | ||
1931 | kex->host_key_index=&get_hostkey_index; | ||
1932 | kex->sign = sshd_hostkey_sign; | ||
1866 | } | 1933 | } |
1867 | 1934 | ||
1868 | memcpy(&incoming_stream, &child_state.incoming, | ||
1869 | sizeof(incoming_stream)); | ||
1870 | memcpy(&outgoing_stream, &child_state.outgoing, | ||
1871 | sizeof(outgoing_stream)); | ||
1872 | |||
1873 | /* Update with new address */ | 1935 | /* Update with new address */ |
1874 | if (options.compression) | 1936 | if (options.compression) { |
1875 | mm_init_compression(pmonitor->m_zlib); | 1937 | ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib, |
1876 | 1938 | (ssh_packet_comp_alloc_func *)mm_zalloc, | |
1877 | packet_set_postauth(); | 1939 | (ssh_packet_comp_free_func *)mm_zfree); |
1878 | |||
1879 | if (options.rekey_limit || options.rekey_interval) | ||
1880 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, | ||
1881 | (time_t)options.rekey_interval); | ||
1882 | |||
1883 | /* Network I/O buffers */ | ||
1884 | /* XXX inefficient for large buffers, need: buffer_init_from_string */ | ||
1885 | buffer_clear(packet_get_input()); | ||
1886 | buffer_append(packet_get_input(), child_state.input, child_state.ilen); | ||
1887 | explicit_bzero(child_state.input, child_state.ilen); | ||
1888 | free(child_state.input); | ||
1889 | |||
1890 | buffer_clear(packet_get_output()); | ||
1891 | buffer_append(packet_get_output(), child_state.output, | ||
1892 | child_state.olen); | ||
1893 | explicit_bzero(child_state.output, child_state.olen); | ||
1894 | free(child_state.output); | ||
1895 | |||
1896 | /* Roaming */ | ||
1897 | if (compat20) | ||
1898 | roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes); | ||
1899 | } | ||
1900 | |||
1901 | static Kex * | ||
1902 | mm_get_kex(Buffer *m) | ||
1903 | { | ||
1904 | Kex *kex; | ||
1905 | void *blob; | ||
1906 | u_int bloblen; | ||
1907 | |||
1908 | kex = xcalloc(1, sizeof(*kex)); | ||
1909 | kex->session_id = buffer_get_string(m, &kex->session_id_len); | ||
1910 | if (session_id2 == NULL || | ||
1911 | kex->session_id_len != session_id2_len || | ||
1912 | timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0) | ||
1913 | fatal("mm_get_get: internal error: bad session id"); | ||
1914 | kex->we_need = buffer_get_int(m); | ||
1915 | #ifdef WITH_OPENSSL | ||
1916 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | ||
1917 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | ||
1918 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | ||
1919 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | ||
1920 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | ||
1921 | #endif | ||
1922 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | ||
1923 | #ifdef GSSAPI | ||
1924 | if (options.gss_keyex) { | ||
1925 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; | ||
1926 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; | ||
1927 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; | ||
1928 | } | 1940 | } |
1929 | #endif | ||
1930 | kex->server = 1; | ||
1931 | kex->hostkey_type = buffer_get_int(m); | ||
1932 | kex->kex_type = buffer_get_int(m); | ||
1933 | blob = buffer_get_string(m, &bloblen); | ||
1934 | buffer_init(&kex->my); | ||
1935 | buffer_append(&kex->my, blob, bloblen); | ||
1936 | free(blob); | ||
1937 | blob = buffer_get_string(m, &bloblen); | ||
1938 | buffer_init(&kex->peer); | ||
1939 | buffer_append(&kex->peer, blob, bloblen); | ||
1940 | free(blob); | ||
1941 | kex->done = 1; | ||
1942 | kex->flags = buffer_get_int(m); | ||
1943 | kex->client_version_string = buffer_get_string(m, NULL); | ||
1944 | kex->server_version_string = buffer_get_string(m, NULL); | ||
1945 | kex->load_host_public_key=&get_hostkey_public_by_type; | ||
1946 | kex->load_host_private_key=&get_hostkey_private_by_type; | ||
1947 | kex->host_key_index=&get_hostkey_index; | ||
1948 | kex->sign = sshd_hostkey_sign; | ||
1949 | |||
1950 | return (kex); | ||
1951 | } | 1941 | } |
1952 | 1942 | ||
1953 | /* This function requries careful sanity checking */ | 1943 | /* This function requries careful sanity checking */ |
@@ -1955,118 +1945,16 @@ mm_get_kex(Buffer *m) | |||
1955 | void | 1945 | void |
1956 | mm_get_keystate(struct monitor *pmonitor) | 1946 | mm_get_keystate(struct monitor *pmonitor) |
1957 | { | 1947 | { |
1958 | Buffer m; | ||
1959 | u_char *blob, *p; | ||
1960 | u_int bloblen, plen; | ||
1961 | u_int32_t seqnr, packets; | ||
1962 | u_int64_t blocks, bytes; | ||
1963 | |||
1964 | debug3("%s: Waiting for new keys", __func__); | 1948 | debug3("%s: Waiting for new keys", __func__); |
1965 | 1949 | ||
1966 | buffer_init(&m); | 1950 | if ((child_state = sshbuf_new()) == NULL) |
1967 | mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); | 1951 | fatal("%s: sshbuf_new failed", __func__); |
1968 | if (!compat20) { | 1952 | mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, |
1969 | child_state.ssh1protoflags = buffer_get_int(&m); | 1953 | child_state); |
1970 | child_state.ssh1cipher = buffer_get_int(&m); | 1954 | debug3("%s: GOT new keys", __func__); |
1971 | child_state.ssh1key = buffer_get_string(&m, | ||
1972 | &child_state.ssh1keylen); | ||
1973 | child_state.ivout = buffer_get_string(&m, | ||
1974 | &child_state.ivoutlen); | ||
1975 | child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); | ||
1976 | goto skip; | ||
1977 | } else { | ||
1978 | /* Get the Kex for rekeying */ | ||
1979 | *pmonitor->m_pkex = mm_get_kex(&m); | ||
1980 | } | ||
1981 | |||
1982 | blob = buffer_get_string(&m, &bloblen); | ||
1983 | current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); | ||
1984 | free(blob); | ||
1985 | |||
1986 | debug3("%s: Waiting for second key", __func__); | ||
1987 | blob = buffer_get_string(&m, &bloblen); | ||
1988 | current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); | ||
1989 | free(blob); | ||
1990 | |||
1991 | /* Now get sequence numbers for the packets */ | ||
1992 | seqnr = buffer_get_int(&m); | ||
1993 | blocks = buffer_get_int64(&m); | ||
1994 | packets = buffer_get_int(&m); | ||
1995 | bytes = buffer_get_int64(&m); | ||
1996 | packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes); | ||
1997 | seqnr = buffer_get_int(&m); | ||
1998 | blocks = buffer_get_int64(&m); | ||
1999 | packets = buffer_get_int(&m); | ||
2000 | bytes = buffer_get_int64(&m); | ||
2001 | packet_set_state(MODE_IN, seqnr, blocks, packets, bytes); | ||
2002 | |||
2003 | skip: | ||
2004 | /* Get the key context */ | ||
2005 | child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); | ||
2006 | child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); | ||
2007 | |||
2008 | debug3("%s: Getting compression state", __func__); | ||
2009 | /* Get compression state */ | ||
2010 | p = buffer_get_string(&m, &plen); | ||
2011 | if (plen != sizeof(child_state.outgoing)) | ||
2012 | fatal("%s: bad request size", __func__); | ||
2013 | memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); | ||
2014 | free(p); | ||
2015 | |||
2016 | p = buffer_get_string(&m, &plen); | ||
2017 | if (plen != sizeof(child_state.incoming)) | ||
2018 | fatal("%s: bad request size", __func__); | ||
2019 | memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); | ||
2020 | free(p); | ||
2021 | |||
2022 | /* Network I/O buffers */ | ||
2023 | debug3("%s: Getting Network I/O buffers", __func__); | ||
2024 | child_state.input = buffer_get_string(&m, &child_state.ilen); | ||
2025 | child_state.output = buffer_get_string(&m, &child_state.olen); | ||
2026 | |||
2027 | /* Roaming */ | ||
2028 | if (compat20) { | ||
2029 | child_state.sent_bytes = buffer_get_int64(&m); | ||
2030 | child_state.recv_bytes = buffer_get_int64(&m); | ||
2031 | } | ||
2032 | |||
2033 | buffer_free(&m); | ||
2034 | } | 1955 | } |
2035 | 1956 | ||
2036 | 1957 | ||
2037 | /* Allocation functions for zlib */ | ||
2038 | void * | ||
2039 | mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) | ||
2040 | { | ||
2041 | size_t len = (size_t) size * ncount; | ||
2042 | void *address; | ||
2043 | |||
2044 | if (len == 0 || ncount > SIZE_T_MAX / size) | ||
2045 | fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); | ||
2046 | |||
2047 | address = mm_malloc(mm, len); | ||
2048 | |||
2049 | return (address); | ||
2050 | } | ||
2051 | |||
2052 | void | ||
2053 | mm_zfree(struct mm_master *mm, void *address) | ||
2054 | { | ||
2055 | mm_free(mm, address); | ||
2056 | } | ||
2057 | |||
2058 | void | ||
2059 | mm_init_compression(struct mm_master *mm) | ||
2060 | { | ||
2061 | outgoing_stream.zalloc = (alloc_func)mm_zalloc; | ||
2062 | outgoing_stream.zfree = (free_func)mm_zfree; | ||
2063 | outgoing_stream.opaque = mm; | ||
2064 | |||
2065 | incoming_stream.zalloc = (alloc_func)mm_zalloc; | ||
2066 | incoming_stream.zfree = (free_func)mm_zfree; | ||
2067 | incoming_stream.opaque = mm; | ||
2068 | } | ||
2069 | |||
2070 | /* XXX */ | 1958 | /* XXX */ |
2071 | 1959 | ||
2072 | #define FD_CLOSEONEXEC(x) do { \ | 1960 | #define FD_CLOSEONEXEC(x) do { \ |
@@ -2102,6 +1990,7 @@ monitor_openfds(struct monitor *mon, int do_logfds) | |||
2102 | struct monitor * | 1990 | struct monitor * |
2103 | monitor_init(void) | 1991 | monitor_init(void) |
2104 | { | 1992 | { |
1993 | struct ssh *ssh = active_state; /* XXX */ | ||
2105 | struct monitor *mon; | 1994 | struct monitor *mon; |
2106 | 1995 | ||
2107 | mon = xcalloc(1, sizeof(*mon)); | 1996 | mon = xcalloc(1, sizeof(*mon)); |
@@ -2114,7 +2003,9 @@ monitor_init(void) | |||
2114 | mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); | 2003 | mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); |
2115 | 2004 | ||
2116 | /* Compression needs to share state across borders */ | 2005 | /* Compression needs to share state across borders */ |
2117 | mm_init_compression(mon->m_zlib); | 2006 | ssh_packet_set_compress_hooks(ssh, mon->m_zlib, |
2007 | (ssh_packet_comp_alloc_func *)mm_zalloc, | ||
2008 | (ssh_packet_comp_free_func *)mm_zfree); | ||
2118 | } | 2009 | } |
2119 | 2010 | ||
2120 | return mon; | 2011 | return mon; |