diff options
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 395 |
1 files changed, 143 insertions, 252 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 | 107 | ||
104 | #ifdef GSSAPI | 108 | #ifdef GSSAPI |
105 | static Gssctxt *gsscontext = NULL; | 109 | static Gssctxt *gsscontext = NULL; |
@@ -108,38 +112,13 @@ static Gssctxt *gsscontext = NULL; | |||
108 | /* Imports */ | 112 | /* Imports */ |
109 | extern ServerOptions options; | 113 | extern ServerOptions options; |
110 | extern u_int utmp_len; | 114 | extern u_int utmp_len; |
111 | extern Newkeys *current_keys[]; | ||
112 | extern z_stream incoming_stream; | ||
113 | extern z_stream outgoing_stream; | ||
114 | extern u_char session_id[]; | 115 | extern u_char session_id[]; |
115 | extern Buffer auth_debug; | 116 | extern Buffer auth_debug; |
116 | extern int auth_debug_init; | 117 | extern int auth_debug_init; |
117 | extern Buffer loginmsg; | 118 | extern Buffer loginmsg; |
118 | 119 | ||
119 | /* State exported from the child */ | 120 | /* State exported from the child */ |
120 | 121 | static struct sshbuf *child_state; | |
121 | struct { | ||
122 | z_stream incoming; | ||
123 | z_stream outgoing; | ||
124 | u_char *keyin; | ||
125 | u_int keyinlen; | ||
126 | u_char *keyout; | ||
127 | u_int keyoutlen; | ||
128 | u_char *ivin; | ||
129 | u_int ivinlen; | ||
130 | u_char *ivout; | ||
131 | u_int ivoutlen; | ||
132 | u_char *ssh1key; | ||
133 | u_int ssh1keylen; | ||
134 | int ssh1cipher; | ||
135 | int ssh1protoflags; | ||
136 | u_char *input; | ||
137 | u_int ilen; | ||
138 | u_char *output; | ||
139 | u_int olen; | ||
140 | u_int64_t sent_bytes; | ||
141 | u_int64_t recv_bytes; | ||
142 | } child_state; | ||
143 | 122 | ||
144 | /* Functions on the monitor that answer unprivileged requests */ | 123 | /* Functions on the monitor that answer unprivileged requests */ |
145 | 124 | ||
@@ -504,6 +483,27 @@ monitor_sync(struct monitor *pmonitor) | |||
504 | } | 483 | } |
505 | } | 484 | } |
506 | 485 | ||
486 | /* Allocation functions for zlib */ | ||
487 | static void * | ||
488 | mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) | ||
489 | { | ||
490 | size_t len = (size_t) size * ncount; | ||
491 | void *address; | ||
492 | |||
493 | if (len == 0 || ncount > SIZE_MAX / size) | ||
494 | fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); | ||
495 | |||
496 | address = mm_malloc(mm, len); | ||
497 | |||
498 | return (address); | ||
499 | } | ||
500 | |||
501 | static void | ||
502 | mm_zfree(struct mm_master *mm, void *address) | ||
503 | { | ||
504 | mm_free(mm, address); | ||
505 | } | ||
506 | |||
507 | static int | 507 | static int |
508 | monitor_read_log(struct monitor *pmonitor) | 508 | monitor_read_log(struct monitor *pmonitor) |
509 | { | 509 | { |
@@ -684,28 +684,60 @@ mm_answer_moduli(int sock, Buffer *m) | |||
684 | } | 684 | } |
685 | #endif | 685 | #endif |
686 | 686 | ||
687 | extern AuthenticationConnection *auth_conn; | ||
688 | |||
689 | int | 687 | int |
690 | mm_answer_sign(int sock, Buffer *m) | 688 | mm_answer_sign(int sock, Buffer *m) |
691 | { | 689 | { |
692 | Key *key; | 690 | struct ssh *ssh = active_state; /* XXX */ |
691 | extern int auth_sock; /* XXX move to state struct? */ | ||
692 | struct sshkey *key; | ||
693 | struct sshbuf *sigbuf; | ||
693 | u_char *p; | 694 | u_char *p; |
694 | u_char *signature; | 695 | u_char *signature; |
695 | u_int siglen, datlen; | 696 | size_t datlen, siglen; |
696 | int keyid; | 697 | int r, keyid, is_proof = 0; |
698 | const char proof_req[] = "hostkeys-prove-00@openssh.com"; | ||
697 | 699 | ||
698 | debug3("%s", __func__); | 700 | debug3("%s", __func__); |
699 | 701 | ||
700 | keyid = buffer_get_int(m); | 702 | if ((r = sshbuf_get_u32(m, &keyid)) != 0 || |
701 | p = buffer_get_string(m, &datlen); | 703 | (r = sshbuf_get_string(m, &p, &datlen)) != 0) |
704 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
702 | 705 | ||
703 | /* | 706 | /* |
704 | * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), | 707 | * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), |
705 | * SHA384 (48 bytes) and SHA512 (64 bytes). | 708 | * SHA384 (48 bytes) and SHA512 (64 bytes). |
709 | * | ||
710 | * Otherwise, verify the signature request is for a hostkey | ||
711 | * proof. | ||
712 | * | ||
713 | * XXX perform similar check for KEX signature requests too? | ||
714 | * it's not trivial, since what is signed is the hash, rather | ||
715 | * than the full kex structure... | ||
706 | */ | 716 | */ |
707 | if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) | 717 | if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { |
708 | fatal("%s: data length incorrect: %u", __func__, datlen); | 718 | /* |
719 | * Construct expected hostkey proof and compare it to what | ||
720 | * the client sent us. | ||
721 | */ | ||
722 | if (session_id2_len == 0) /* hostkeys is never first */ | ||
723 | fatal("%s: bad data length: %zu", __func__, datlen); | ||
724 | if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) | ||
725 | fatal("%s: no hostkey for index %d", __func__, keyid); | ||
726 | if ((sigbuf = sshbuf_new()) == NULL) | ||
727 | fatal("%s: sshbuf_new", __func__); | ||
728 | if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || | ||
729 | (r = sshbuf_put_string(sigbuf, session_id2, | ||
730 | session_id2_len) != 0) || | ||
731 | (r = sshkey_puts(key, sigbuf)) != 0) | ||
732 | fatal("%s: couldn't prepare private key " | ||
733 | "proof buffer: %s", __func__, ssh_err(r)); | ||
734 | if (datlen != sshbuf_len(sigbuf) || | ||
735 | memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) | ||
736 | fatal("%s: bad data length: %zu, hostkey proof len %zu", | ||
737 | __func__, datlen, sshbuf_len(sigbuf)); | ||
738 | sshbuf_free(sigbuf); | ||
739 | is_proof = 1; | ||
740 | } | ||
709 | 741 | ||
710 | /* save session id, it will be passed on the first call */ | 742 | /* save session id, it will be passed on the first call */ |
711 | if (session_id2_len == 0) { | 743 | if (session_id2_len == 0) { |
@@ -715,20 +747,26 @@ mm_answer_sign(int sock, Buffer *m) | |||
715 | } | 747 | } |
716 | 748 | ||
717 | if ((key = get_hostkey_by_index(keyid)) != NULL) { | 749 | if ((key = get_hostkey_by_index(keyid)) != NULL) { |
718 | if (key_sign(key, &signature, &siglen, p, datlen) < 0) | 750 | if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, |
719 | fatal("%s: key_sign failed", __func__); | 751 | datafellows)) != 0) |
720 | } else if ((key = get_hostkey_public_by_index(keyid)) != NULL && | 752 | fatal("%s: sshkey_sign failed: %s", |
721 | auth_conn != NULL) { | 753 | __func__, ssh_err(r)); |
722 | if (ssh_agent_sign(auth_conn, key, &signature, &siglen, p, | 754 | } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && |
723 | datlen) < 0) | 755 | auth_sock > 0) { |
724 | fatal("%s: ssh_agent_sign failed", __func__); | 756 | if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, |
757 | p, datlen, datafellows)) != 0) { | ||
758 | fatal("%s: ssh_agent_sign failed: %s", | ||
759 | __func__, ssh_err(r)); | ||
760 | } | ||
725 | } else | 761 | } else |
726 | fatal("%s: no hostkey from index %d", __func__, keyid); | 762 | fatal("%s: no hostkey from index %d", __func__, keyid); |
727 | 763 | ||
728 | debug3("%s: signature %p(%u)", __func__, signature, siglen); | 764 | debug3("%s: %s signature %p(%zu)", __func__, |
765 | is_proof ? "KEX" : "hostkey proof", signature, siglen); | ||
729 | 766 | ||
730 | buffer_clear(m); | 767 | sshbuf_reset(m); |
731 | buffer_put_string(m, signature, siglen); | 768 | if ((r = sshbuf_put_string(m, signature, siglen)) != 0) |
769 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
732 | 770 | ||
733 | free(p); | 771 | free(p); |
734 | free(signature); | 772 | free(signature); |
@@ -1167,9 +1205,18 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1167 | debug3("%s: key_from_blob: %p", __func__, key); | 1205 | debug3("%s: key_from_blob: %p", __func__, key); |
1168 | 1206 | ||
1169 | if (key != NULL && authctxt->valid) { | 1207 | if (key != NULL && authctxt->valid) { |
1208 | /* These should not make it past the privsep child */ | ||
1209 | if (key_type_plain(key->type) == KEY_RSA && | ||
1210 | (datafellows & SSH_BUG_RSASIGMD5) != 0) | ||
1211 | fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); | ||
1212 | |||
1170 | switch (type) { | 1213 | switch (type) { |
1171 | case MM_USERKEY: | 1214 | case MM_USERKEY: |
1172 | allowed = options.pubkey_authentication && | 1215 | allowed = options.pubkey_authentication && |
1216 | !auth2_userkey_already_used(authctxt, key) && | ||
1217 | match_pattern_list(sshkey_ssh_name(key), | ||
1218 | options.pubkey_key_types, | ||
1219 | strlen(options.pubkey_key_types), 0) == 1 && | ||
1173 | user_key_allowed(authctxt->pw, key); | 1220 | user_key_allowed(authctxt->pw, key); |
1174 | pubkey_auth_info(authctxt, key, NULL); | 1221 | pubkey_auth_info(authctxt, key, NULL); |
1175 | auth_method = "publickey"; | 1222 | auth_method = "publickey"; |
@@ -1178,6 +1225,9 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1178 | break; | 1225 | break; |
1179 | case MM_HOSTKEY: | 1226 | case MM_HOSTKEY: |
1180 | allowed = options.hostbased_authentication && | 1227 | allowed = options.hostbased_authentication && |
1228 | match_pattern_list(sshkey_ssh_name(key), | ||
1229 | options.hostbased_key_types, | ||
1230 | strlen(options.hostbased_key_types), 0) == 1 && | ||
1181 | hostbased_key_allowed(authctxt->pw, | 1231 | hostbased_key_allowed(authctxt->pw, |
1182 | cuser, chost, key); | 1232 | cuser, chost, key); |
1183 | pubkey_auth_info(authctxt, key, | 1233 | pubkey_auth_info(authctxt, key, |
@@ -1397,7 +1447,12 @@ mm_answer_keyverify(int sock, Buffer *m) | |||
1397 | debug3("%s: key %p signature %s", | 1447 | debug3("%s: key %p signature %s", |
1398 | __func__, key, (verified == 1) ? "verified" : "unverified"); | 1448 | __func__, key, (verified == 1) ? "verified" : "unverified"); |
1399 | 1449 | ||
1400 | key_free(key); | 1450 | /* If auth was successful then record key to ensure it isn't reused */ |
1451 | if (verified == 1) | ||
1452 | auth2_record_userkey(authctxt, key); | ||
1453 | else | ||
1454 | key_free(key); | ||
1455 | |||
1401 | free(blob); | 1456 | free(blob); |
1402 | free(signature); | 1457 | free(signature); |
1403 | free(data); | 1458 | free(data); |
@@ -1783,105 +1838,40 @@ mm_answer_audit_command(int socket, Buffer *m) | |||
1783 | void | 1838 | void |
1784 | monitor_apply_keystate(struct monitor *pmonitor) | 1839 | monitor_apply_keystate(struct monitor *pmonitor) |
1785 | { | 1840 | { |
1786 | if (compat20) { | 1841 | struct ssh *ssh = active_state; /* XXX */ |
1787 | set_newkeys(MODE_IN); | 1842 | struct kex *kex; |
1788 | set_newkeys(MODE_OUT); | 1843 | int r; |
1789 | } else { | 1844 | |
1790 | packet_set_protocol_flags(child_state.ssh1protoflags); | 1845 | debug3("%s: packet_set_state", __func__); |
1791 | packet_set_encryption_key(child_state.ssh1key, | 1846 | if ((r = ssh_packet_set_state(ssh, child_state)) != 0) |
1792 | child_state.ssh1keylen, child_state.ssh1cipher); | 1847 | fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); |
1793 | free(child_state.ssh1key); | 1848 | sshbuf_free(child_state); |
1794 | } | 1849 | child_state = NULL; |
1795 | 1850 | ||
1796 | /* for rc4 and other stateful ciphers */ | 1851 | if ((kex = ssh->kex) != 0) { |
1797 | packet_set_keycontext(MODE_OUT, child_state.keyout); | 1852 | /* XXX set callbacks */ |
1798 | free(child_state.keyout); | 1853 | #ifdef WITH_OPENSSL |
1799 | packet_set_keycontext(MODE_IN, child_state.keyin); | 1854 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
1800 | free(child_state.keyin); | 1855 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
1801 | 1856 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | |
1802 | if (!compat20) { | 1857 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
1803 | packet_set_iv(MODE_OUT, child_state.ivout); | 1858 | # ifdef OPENSSL_HAS_ECC |
1804 | free(child_state.ivout); | 1859 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
1805 | packet_set_iv(MODE_IN, child_state.ivin); | 1860 | # endif |
1806 | free(child_state.ivin); | 1861 | #endif /* WITH_OPENSSL */ |
1862 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | ||
1863 | kex->load_host_public_key=&get_hostkey_public_by_type; | ||
1864 | kex->load_host_private_key=&get_hostkey_private_by_type; | ||
1865 | kex->host_key_index=&get_hostkey_index; | ||
1866 | kex->sign = sshd_hostkey_sign; | ||
1807 | } | 1867 | } |
1808 | 1868 | ||
1809 | memcpy(&incoming_stream, &child_state.incoming, | ||
1810 | sizeof(incoming_stream)); | ||
1811 | memcpy(&outgoing_stream, &child_state.outgoing, | ||
1812 | sizeof(outgoing_stream)); | ||
1813 | |||
1814 | /* Update with new address */ | 1869 | /* Update with new address */ |
1815 | if (options.compression) | 1870 | if (options.compression) { |
1816 | mm_init_compression(pmonitor->m_zlib); | 1871 | ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib, |
1817 | 1872 | (ssh_packet_comp_alloc_func *)mm_zalloc, | |
1818 | packet_set_postauth(); | 1873 | (ssh_packet_comp_free_func *)mm_zfree); |
1819 | 1874 | } | |
1820 | if (options.rekey_limit || options.rekey_interval) | ||
1821 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, | ||
1822 | (time_t)options.rekey_interval); | ||
1823 | |||
1824 | /* Network I/O buffers */ | ||
1825 | /* XXX inefficient for large buffers, need: buffer_init_from_string */ | ||
1826 | buffer_clear(packet_get_input()); | ||
1827 | buffer_append(packet_get_input(), child_state.input, child_state.ilen); | ||
1828 | explicit_bzero(child_state.input, child_state.ilen); | ||
1829 | free(child_state.input); | ||
1830 | |||
1831 | buffer_clear(packet_get_output()); | ||
1832 | buffer_append(packet_get_output(), child_state.output, | ||
1833 | child_state.olen); | ||
1834 | explicit_bzero(child_state.output, child_state.olen); | ||
1835 | free(child_state.output); | ||
1836 | |||
1837 | /* Roaming */ | ||
1838 | if (compat20) | ||
1839 | roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes); | ||
1840 | } | ||
1841 | |||
1842 | static Kex * | ||
1843 | mm_get_kex(Buffer *m) | ||
1844 | { | ||
1845 | Kex *kex; | ||
1846 | void *blob; | ||
1847 | u_int bloblen; | ||
1848 | |||
1849 | kex = xcalloc(1, sizeof(*kex)); | ||
1850 | kex->session_id = buffer_get_string(m, &kex->session_id_len); | ||
1851 | if (session_id2 == NULL || | ||
1852 | kex->session_id_len != session_id2_len || | ||
1853 | timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0) | ||
1854 | fatal("mm_get_get: internal error: bad session id"); | ||
1855 | kex->we_need = buffer_get_int(m); | ||
1856 | #ifdef WITH_OPENSSL | ||
1857 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | ||
1858 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | ||
1859 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | ||
1860 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | ||
1861 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | ||
1862 | #endif | ||
1863 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | ||
1864 | kex->server = 1; | ||
1865 | kex->hostkey_type = buffer_get_int(m); | ||
1866 | kex->kex_type = buffer_get_int(m); | ||
1867 | blob = buffer_get_string(m, &bloblen); | ||
1868 | buffer_init(&kex->my); | ||
1869 | buffer_append(&kex->my, blob, bloblen); | ||
1870 | free(blob); | ||
1871 | blob = buffer_get_string(m, &bloblen); | ||
1872 | buffer_init(&kex->peer); | ||
1873 | buffer_append(&kex->peer, blob, bloblen); | ||
1874 | free(blob); | ||
1875 | kex->done = 1; | ||
1876 | kex->flags = buffer_get_int(m); | ||
1877 | kex->client_version_string = buffer_get_string(m, NULL); | ||
1878 | kex->server_version_string = buffer_get_string(m, NULL); | ||
1879 | kex->load_host_public_key=&get_hostkey_public_by_type; | ||
1880 | kex->load_host_private_key=&get_hostkey_private_by_type; | ||
1881 | kex->host_key_index=&get_hostkey_index; | ||
1882 | kex->sign = sshd_hostkey_sign; | ||
1883 | |||
1884 | return (kex); | ||
1885 | } | 1875 | } |
1886 | 1876 | ||
1887 | /* This function requries careful sanity checking */ | 1877 | /* This function requries careful sanity checking */ |
@@ -1889,118 +1879,16 @@ mm_get_kex(Buffer *m) | |||
1889 | void | 1879 | void |
1890 | mm_get_keystate(struct monitor *pmonitor) | 1880 | mm_get_keystate(struct monitor *pmonitor) |
1891 | { | 1881 | { |
1892 | Buffer m; | ||
1893 | u_char *blob, *p; | ||
1894 | u_int bloblen, plen; | ||
1895 | u_int32_t seqnr, packets; | ||
1896 | u_int64_t blocks, bytes; | ||
1897 | |||
1898 | debug3("%s: Waiting for new keys", __func__); | 1882 | debug3("%s: Waiting for new keys", __func__); |
1899 | 1883 | ||
1900 | buffer_init(&m); | 1884 | if ((child_state = sshbuf_new()) == NULL) |
1901 | mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); | 1885 | fatal("%s: sshbuf_new failed", __func__); |
1902 | if (!compat20) { | 1886 | mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, |
1903 | child_state.ssh1protoflags = buffer_get_int(&m); | 1887 | child_state); |
1904 | child_state.ssh1cipher = buffer_get_int(&m); | 1888 | debug3("%s: GOT new keys", __func__); |
1905 | child_state.ssh1key = buffer_get_string(&m, | ||
1906 | &child_state.ssh1keylen); | ||
1907 | child_state.ivout = buffer_get_string(&m, | ||
1908 | &child_state.ivoutlen); | ||
1909 | child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); | ||
1910 | goto skip; | ||
1911 | } else { | ||
1912 | /* Get the Kex for rekeying */ | ||
1913 | *pmonitor->m_pkex = mm_get_kex(&m); | ||
1914 | } | ||
1915 | |||
1916 | blob = buffer_get_string(&m, &bloblen); | ||
1917 | current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); | ||
1918 | free(blob); | ||
1919 | |||
1920 | debug3("%s: Waiting for second key", __func__); | ||
1921 | blob = buffer_get_string(&m, &bloblen); | ||
1922 | current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); | ||
1923 | free(blob); | ||
1924 | |||
1925 | /* Now get sequence numbers for the packets */ | ||
1926 | seqnr = buffer_get_int(&m); | ||
1927 | blocks = buffer_get_int64(&m); | ||
1928 | packets = buffer_get_int(&m); | ||
1929 | bytes = buffer_get_int64(&m); | ||
1930 | packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes); | ||
1931 | seqnr = buffer_get_int(&m); | ||
1932 | blocks = buffer_get_int64(&m); | ||
1933 | packets = buffer_get_int(&m); | ||
1934 | bytes = buffer_get_int64(&m); | ||
1935 | packet_set_state(MODE_IN, seqnr, blocks, packets, bytes); | ||
1936 | |||
1937 | skip: | ||
1938 | /* Get the key context */ | ||
1939 | child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); | ||
1940 | child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); | ||
1941 | |||
1942 | debug3("%s: Getting compression state", __func__); | ||
1943 | /* Get compression state */ | ||
1944 | p = buffer_get_string(&m, &plen); | ||
1945 | if (plen != sizeof(child_state.outgoing)) | ||
1946 | fatal("%s: bad request size", __func__); | ||
1947 | memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); | ||
1948 | free(p); | ||
1949 | |||
1950 | p = buffer_get_string(&m, &plen); | ||
1951 | if (plen != sizeof(child_state.incoming)) | ||
1952 | fatal("%s: bad request size", __func__); | ||
1953 | memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); | ||
1954 | free(p); | ||
1955 | |||
1956 | /* Network I/O buffers */ | ||
1957 | debug3("%s: Getting Network I/O buffers", __func__); | ||
1958 | child_state.input = buffer_get_string(&m, &child_state.ilen); | ||
1959 | child_state.output = buffer_get_string(&m, &child_state.olen); | ||
1960 | |||
1961 | /* Roaming */ | ||
1962 | if (compat20) { | ||
1963 | child_state.sent_bytes = buffer_get_int64(&m); | ||
1964 | child_state.recv_bytes = buffer_get_int64(&m); | ||
1965 | } | ||
1966 | |||
1967 | buffer_free(&m); | ||
1968 | } | 1889 | } |
1969 | 1890 | ||
1970 | 1891 | ||
1971 | /* Allocation functions for zlib */ | ||
1972 | void * | ||
1973 | mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) | ||
1974 | { | ||
1975 | size_t len = (size_t) size * ncount; | ||
1976 | void *address; | ||
1977 | |||
1978 | if (len == 0 || ncount > SIZE_T_MAX / size) | ||
1979 | fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); | ||
1980 | |||
1981 | address = mm_malloc(mm, len); | ||
1982 | |||
1983 | return (address); | ||
1984 | } | ||
1985 | |||
1986 | void | ||
1987 | mm_zfree(struct mm_master *mm, void *address) | ||
1988 | { | ||
1989 | mm_free(mm, address); | ||
1990 | } | ||
1991 | |||
1992 | void | ||
1993 | mm_init_compression(struct mm_master *mm) | ||
1994 | { | ||
1995 | outgoing_stream.zalloc = (alloc_func)mm_zalloc; | ||
1996 | outgoing_stream.zfree = (free_func)mm_zfree; | ||
1997 | outgoing_stream.opaque = mm; | ||
1998 | |||
1999 | incoming_stream.zalloc = (alloc_func)mm_zalloc; | ||
2000 | incoming_stream.zfree = (free_func)mm_zfree; | ||
2001 | incoming_stream.opaque = mm; | ||
2002 | } | ||
2003 | |||
2004 | /* XXX */ | 1892 | /* XXX */ |
2005 | 1893 | ||
2006 | #define FD_CLOSEONEXEC(x) do { \ | 1894 | #define FD_CLOSEONEXEC(x) do { \ |
@@ -2036,6 +1924,7 @@ monitor_openfds(struct monitor *mon, int do_logfds) | |||
2036 | struct monitor * | 1924 | struct monitor * |
2037 | monitor_init(void) | 1925 | monitor_init(void) |
2038 | { | 1926 | { |
1927 | struct ssh *ssh = active_state; /* XXX */ | ||
2039 | struct monitor *mon; | 1928 | struct monitor *mon; |
2040 | 1929 | ||
2041 | mon = xcalloc(1, sizeof(*mon)); | 1930 | mon = xcalloc(1, sizeof(*mon)); |
@@ -2048,7 +1937,9 @@ monitor_init(void) | |||
2048 | mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); | 1937 | mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); |
2049 | 1938 | ||
2050 | /* Compression needs to share state across borders */ | 1939 | /* Compression needs to share state across borders */ |
2051 | mm_init_compression(mon->m_zlib); | 1940 | ssh_packet_set_compress_hooks(ssh, mon->m_zlib, |
1941 | (ssh_packet_comp_alloc_func *)mm_zalloc, | ||
1942 | (ssh_packet_comp_free_func *)mm_zfree); | ||
2052 | } | 1943 | } |
2053 | 1944 | ||
2054 | return mon; | 1945 | return mon; |