diff options
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 289 |
1 files changed, 61 insertions, 228 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.138 2015/01/14 20:05:27 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.139 2015/01/19 19:52:16 markus 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> |
@@ -110,38 +110,13 @@ static Gssctxt *gsscontext = NULL; | |||
110 | /* Imports */ | 110 | /* Imports */ |
111 | extern ServerOptions options; | 111 | extern ServerOptions options; |
112 | extern u_int utmp_len; | 112 | extern u_int utmp_len; |
113 | extern Newkeys *current_keys[]; | ||
114 | extern z_stream incoming_stream; | ||
115 | extern z_stream outgoing_stream; | ||
116 | extern u_char session_id[]; | 113 | extern u_char session_id[]; |
117 | extern Buffer auth_debug; | 114 | extern Buffer auth_debug; |
118 | extern int auth_debug_init; | 115 | extern int auth_debug_init; |
119 | extern Buffer loginmsg; | 116 | extern Buffer loginmsg; |
120 | 117 | ||
121 | /* State exported from the child */ | 118 | /* State exported from the child */ |
122 | 119 | static struct sshbuf *child_state; | |
123 | struct { | ||
124 | z_stream incoming; | ||
125 | z_stream outgoing; | ||
126 | u_char *keyin; | ||
127 | u_int keyinlen; | ||
128 | u_char *keyout; | ||
129 | u_int keyoutlen; | ||
130 | u_char *ivin; | ||
131 | u_int ivinlen; | ||
132 | u_char *ivout; | ||
133 | u_int ivoutlen; | ||
134 | u_char *ssh1key; | ||
135 | u_int ssh1keylen; | ||
136 | int ssh1cipher; | ||
137 | int ssh1protoflags; | ||
138 | u_char *input; | ||
139 | u_int ilen; | ||
140 | u_char *output; | ||
141 | u_int olen; | ||
142 | u_int64_t sent_bytes; | ||
143 | u_int64_t recv_bytes; | ||
144 | } child_state; | ||
145 | 120 | ||
146 | /* Functions on the monitor that answer unprivileged requests */ | 121 | /* Functions on the monitor that answer unprivileged requests */ |
147 | 122 | ||
@@ -506,6 +481,27 @@ monitor_sync(struct monitor *pmonitor) | |||
506 | } | 481 | } |
507 | } | 482 | } |
508 | 483 | ||
484 | /* Allocation functions for zlib */ | ||
485 | static void * | ||
486 | mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) | ||
487 | { | ||
488 | size_t len = (size_t) size * ncount; | ||
489 | void *address; | ||
490 | |||
491 | if (len == 0 || ncount > SIZE_T_MAX / size) | ||
492 | fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); | ||
493 | |||
494 | address = mm_malloc(mm, len); | ||
495 | |||
496 | return (address); | ||
497 | } | ||
498 | |||
499 | static void | ||
500 | mm_zfree(struct mm_master *mm, void *address) | ||
501 | { | ||
502 | mm_free(mm, address); | ||
503 | } | ||
504 | |||
509 | static int | 505 | static int |
510 | monitor_read_log(struct monitor *pmonitor) | 506 | monitor_read_log(struct monitor *pmonitor) |
511 | { | 507 | { |
@@ -1807,105 +1803,41 @@ mm_answer_audit_command(int socket, Buffer *m) | |||
1807 | void | 1803 | void |
1808 | monitor_apply_keystate(struct monitor *pmonitor) | 1804 | monitor_apply_keystate(struct monitor *pmonitor) |
1809 | { | 1805 | { |
1810 | if (compat20) { | 1806 | struct ssh *ssh = active_state; /* XXX */ |
1811 | set_newkeys(MODE_IN); | 1807 | struct kex *kex; |
1812 | set_newkeys(MODE_OUT); | 1808 | int r; |
1813 | } else { | 1809 | |
1814 | packet_set_protocol_flags(child_state.ssh1protoflags); | 1810 | debug3("%s: packet_set_state", __func__); |
1815 | packet_set_encryption_key(child_state.ssh1key, | 1811 | if ((r = ssh_packet_set_state(ssh, child_state)) != 0) |
1816 | child_state.ssh1keylen, child_state.ssh1cipher); | 1812 | fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); |
1817 | free(child_state.ssh1key); | 1813 | sshbuf_free(child_state); |
1818 | } | 1814 | child_state = NULL; |
1819 | 1815 | ||
1820 | /* for rc4 and other stateful ciphers */ | 1816 | if ((kex = ssh->kex) != 0) { |
1821 | packet_set_keycontext(MODE_OUT, child_state.keyout); | 1817 | /* XXX set callbacks */ |
1822 | free(child_state.keyout); | 1818 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
1823 | packet_set_keycontext(MODE_IN, child_state.keyin); | 1819 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
1824 | free(child_state.keyin); | 1820 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
1825 | 1821 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | |
1826 | if (!compat20) { | 1822 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
1827 | packet_set_iv(MODE_OUT, child_state.ivout); | 1823 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
1828 | free(child_state.ivout); | 1824 | kex->load_host_public_key=&get_hostkey_public_by_type; |
1829 | packet_set_iv(MODE_IN, child_state.ivin); | 1825 | kex->load_host_private_key=&get_hostkey_private_by_type; |
1830 | free(child_state.ivin); | 1826 | kex->host_key_index=&get_hostkey_index; |
1827 | kex->sign = sshd_hostkey_sign; | ||
1831 | } | 1828 | } |
1832 | 1829 | ||
1833 | memcpy(&incoming_stream, &child_state.incoming, | ||
1834 | sizeof(incoming_stream)); | ||
1835 | memcpy(&outgoing_stream, &child_state.outgoing, | ||
1836 | sizeof(outgoing_stream)); | ||
1837 | |||
1838 | /* Update with new address */ | 1830 | /* Update with new address */ |
1839 | if (options.compression) | 1831 | if (options.compression) { |
1840 | mm_init_compression(pmonitor->m_zlib); | 1832 | ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib, |
1841 | 1833 | (ssh_packet_comp_alloc_func *)mm_zalloc, | |
1842 | packet_set_postauth(); | 1834 | (ssh_packet_comp_free_func *)mm_zfree); |
1835 | } | ||
1843 | 1836 | ||
1844 | if (options.rekey_limit || options.rekey_interval) | 1837 | if (options.rekey_limit || options.rekey_interval) |
1845 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, | 1838 | ssh_packet_set_rekey_limits(ssh, |
1839 | (u_int32_t)options.rekey_limit, | ||
1846 | (time_t)options.rekey_interval); | 1840 | (time_t)options.rekey_interval); |
1847 | |||
1848 | /* Network I/O buffers */ | ||
1849 | /* XXX inefficient for large buffers, need: buffer_init_from_string */ | ||
1850 | buffer_clear(packet_get_input()); | ||
1851 | buffer_append(packet_get_input(), child_state.input, child_state.ilen); | ||
1852 | explicit_bzero(child_state.input, child_state.ilen); | ||
1853 | free(child_state.input); | ||
1854 | |||
1855 | buffer_clear(packet_get_output()); | ||
1856 | buffer_append(packet_get_output(), child_state.output, | ||
1857 | child_state.olen); | ||
1858 | explicit_bzero(child_state.output, child_state.olen); | ||
1859 | free(child_state.output); | ||
1860 | |||
1861 | /* Roaming */ | ||
1862 | if (compat20) | ||
1863 | roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes); | ||
1864 | } | ||
1865 | |||
1866 | static Kex * | ||
1867 | mm_get_kex(Buffer *m) | ||
1868 | { | ||
1869 | Kex *kex; | ||
1870 | void *blob; | ||
1871 | u_int bloblen; | ||
1872 | |||
1873 | kex = xcalloc(1, sizeof(*kex)); | ||
1874 | kex->session_id = buffer_get_string(m, &kex->session_id_len); | ||
1875 | if (session_id2 == NULL || | ||
1876 | kex->session_id_len != session_id2_len || | ||
1877 | timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0) | ||
1878 | fatal("mm_get_get: internal error: bad session id"); | ||
1879 | kex->we_need = buffer_get_int(m); | ||
1880 | #ifdef WITH_OPENSSL | ||
1881 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | ||
1882 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | ||
1883 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | ||
1884 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | ||
1885 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | ||
1886 | #endif | ||
1887 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | ||
1888 | kex->server = 1; | ||
1889 | kex->hostkey_type = buffer_get_int(m); | ||
1890 | kex->kex_type = buffer_get_int(m); | ||
1891 | blob = buffer_get_string(m, &bloblen); | ||
1892 | buffer_init(&kex->my); | ||
1893 | buffer_append(&kex->my, blob, bloblen); | ||
1894 | free(blob); | ||
1895 | blob = buffer_get_string(m, &bloblen); | ||
1896 | buffer_init(&kex->peer); | ||
1897 | buffer_append(&kex->peer, blob, bloblen); | ||
1898 | free(blob); | ||
1899 | kex->done = 1; | ||
1900 | kex->flags = buffer_get_int(m); | ||
1901 | kex->client_version_string = buffer_get_string(m, NULL); | ||
1902 | kex->server_version_string = buffer_get_string(m, NULL); | ||
1903 | kex->load_host_public_key=&get_hostkey_public_by_type; | ||
1904 | kex->load_host_private_key=&get_hostkey_private_by_type; | ||
1905 | kex->host_key_index=&get_hostkey_index; | ||
1906 | kex->sign = sshd_hostkey_sign; | ||
1907 | |||
1908 | return (kex); | ||
1909 | } | 1841 | } |
1910 | 1842 | ||
1911 | /* This function requries careful sanity checking */ | 1843 | /* This function requries careful sanity checking */ |
@@ -1913,117 +1845,15 @@ mm_get_kex(Buffer *m) | |||
1913 | void | 1845 | void |
1914 | mm_get_keystate(struct monitor *pmonitor) | 1846 | mm_get_keystate(struct monitor *pmonitor) |
1915 | { | 1847 | { |
1916 | Buffer m; | ||
1917 | u_char *blob, *p; | ||
1918 | u_int bloblen, plen; | ||
1919 | u_int32_t seqnr, packets; | ||
1920 | u_int64_t blocks, bytes; | ||
1921 | |||
1922 | debug3("%s: Waiting for new keys", __func__); | 1848 | debug3("%s: Waiting for new keys", __func__); |
1923 | 1849 | ||
1924 | buffer_init(&m); | 1850 | if ((child_state = sshbuf_new()) == NULL) |
1925 | mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); | 1851 | fatal("%s: sshbuf_new failed", __func__); |
1926 | if (!compat20) { | 1852 | mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, |
1927 | child_state.ssh1protoflags = buffer_get_int(&m); | 1853 | child_state); |
1928 | child_state.ssh1cipher = buffer_get_int(&m); | 1854 | debug3("%s: GOT new keys", __func__); |
1929 | child_state.ssh1key = buffer_get_string(&m, | ||
1930 | &child_state.ssh1keylen); | ||
1931 | child_state.ivout = buffer_get_string(&m, | ||
1932 | &child_state.ivoutlen); | ||
1933 | child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); | ||
1934 | goto skip; | ||
1935 | } else { | ||
1936 | /* Get the Kex for rekeying */ | ||
1937 | *pmonitor->m_pkex = mm_get_kex(&m); | ||
1938 | } | ||
1939 | |||
1940 | blob = buffer_get_string(&m, &bloblen); | ||
1941 | current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); | ||
1942 | free(blob); | ||
1943 | |||
1944 | debug3("%s: Waiting for second key", __func__); | ||
1945 | blob = buffer_get_string(&m, &bloblen); | ||
1946 | current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); | ||
1947 | free(blob); | ||
1948 | |||
1949 | /* Now get sequence numbers for the packets */ | ||
1950 | seqnr = buffer_get_int(&m); | ||
1951 | blocks = buffer_get_int64(&m); | ||
1952 | packets = buffer_get_int(&m); | ||
1953 | bytes = buffer_get_int64(&m); | ||
1954 | packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes); | ||
1955 | seqnr = buffer_get_int(&m); | ||
1956 | blocks = buffer_get_int64(&m); | ||
1957 | packets = buffer_get_int(&m); | ||
1958 | bytes = buffer_get_int64(&m); | ||
1959 | packet_set_state(MODE_IN, seqnr, blocks, packets, bytes); | ||
1960 | |||
1961 | skip: | ||
1962 | /* Get the key context */ | ||
1963 | child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); | ||
1964 | child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); | ||
1965 | |||
1966 | debug3("%s: Getting compression state", __func__); | ||
1967 | /* Get compression state */ | ||
1968 | p = buffer_get_string(&m, &plen); | ||
1969 | if (plen != sizeof(child_state.outgoing)) | ||
1970 | fatal("%s: bad request size", __func__); | ||
1971 | memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); | ||
1972 | free(p); | ||
1973 | |||
1974 | p = buffer_get_string(&m, &plen); | ||
1975 | if (plen != sizeof(child_state.incoming)) | ||
1976 | fatal("%s: bad request size", __func__); | ||
1977 | memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); | ||
1978 | free(p); | ||
1979 | |||
1980 | /* Network I/O buffers */ | ||
1981 | debug3("%s: Getting Network I/O buffers", __func__); | ||
1982 | child_state.input = buffer_get_string(&m, &child_state.ilen); | ||
1983 | child_state.output = buffer_get_string(&m, &child_state.olen); | ||
1984 | |||
1985 | /* Roaming */ | ||
1986 | if (compat20) { | ||
1987 | child_state.sent_bytes = buffer_get_int64(&m); | ||
1988 | child_state.recv_bytes = buffer_get_int64(&m); | ||
1989 | } | ||
1990 | |||
1991 | buffer_free(&m); | ||
1992 | } | ||
1993 | |||
1994 | |||
1995 | /* Allocation functions for zlib */ | ||
1996 | void * | ||
1997 | mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) | ||
1998 | { | ||
1999 | size_t len = (size_t) size * ncount; | ||
2000 | void *address; | ||
2001 | |||
2002 | if (len == 0 || ncount > SIZE_T_MAX / size) | ||
2003 | fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); | ||
2004 | |||
2005 | address = mm_malloc(mm, len); | ||
2006 | |||
2007 | return (address); | ||
2008 | } | 1855 | } |
2009 | 1856 | ||
2010 | void | ||
2011 | mm_zfree(struct mm_master *mm, void *address) | ||
2012 | { | ||
2013 | mm_free(mm, address); | ||
2014 | } | ||
2015 | |||
2016 | void | ||
2017 | mm_init_compression(struct mm_master *mm) | ||
2018 | { | ||
2019 | outgoing_stream.zalloc = (alloc_func)mm_zalloc; | ||
2020 | outgoing_stream.zfree = (free_func)mm_zfree; | ||
2021 | outgoing_stream.opaque = mm; | ||
2022 | |||
2023 | incoming_stream.zalloc = (alloc_func)mm_zalloc; | ||
2024 | incoming_stream.zfree = (free_func)mm_zfree; | ||
2025 | incoming_stream.opaque = mm; | ||
2026 | } | ||
2027 | 1857 | ||
2028 | /* XXX */ | 1858 | /* XXX */ |
2029 | 1859 | ||
@@ -2060,6 +1890,7 @@ monitor_openfds(struct monitor *mon, int do_logfds) | |||
2060 | struct monitor * | 1890 | struct monitor * |
2061 | monitor_init(void) | 1891 | monitor_init(void) |
2062 | { | 1892 | { |
1893 | struct ssh *ssh = active_state; /* XXX */ | ||
2063 | struct monitor *mon; | 1894 | struct monitor *mon; |
2064 | 1895 | ||
2065 | mon = xcalloc(1, sizeof(*mon)); | 1896 | mon = xcalloc(1, sizeof(*mon)); |
@@ -2072,7 +1903,9 @@ monitor_init(void) | |||
2072 | mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); | 1903 | mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); |
2073 | 1904 | ||
2074 | /* Compression needs to share state across borders */ | 1905 | /* Compression needs to share state across borders */ |
2075 | mm_init_compression(mon->m_zlib); | 1906 | ssh_packet_set_compress_hooks(ssh, mon->m_zlib, |
1907 | (ssh_packet_comp_alloc_func *)mm_zalloc, | ||
1908 | (ssh_packet_comp_free_func *)mm_zfree); | ||
2076 | } | 1909 | } |
2077 | 1910 | ||
2078 | return mon; | 1911 | return mon; |