diff options
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 94 |
1 files changed, 58 insertions, 36 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.283 2019/03/01 03:29:32 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 |
@@ -58,6 +58,7 @@ | |||
58 | #include <string.h> | 58 | #include <string.h> |
59 | #include <unistd.h> | 59 | #include <unistd.h> |
60 | #include <limits.h> | 60 | #include <limits.h> |
61 | #include <poll.h> | ||
61 | #include <signal.h> | 62 | #include <signal.h> |
62 | #include <time.h> | 63 | #include <time.h> |
63 | 64 | ||
@@ -228,6 +229,7 @@ ssh_alloc_session_state(void) | |||
228 | 229 | ||
229 | if ((ssh = calloc(1, sizeof(*ssh))) == NULL || | 230 | if ((ssh = calloc(1, sizeof(*ssh))) == NULL || |
230 | (state = calloc(1, sizeof(*state))) == NULL || | 231 | (state = calloc(1, sizeof(*state))) == NULL || |
232 | (ssh->kex = kex_new()) == NULL || | ||
231 | (state->input = sshbuf_new()) == NULL || | 233 | (state->input = sshbuf_new()) == NULL || |
232 | (state->output = sshbuf_new()) == NULL || | 234 | (state->output = sshbuf_new()) == NULL || |
233 | (state->outgoing_packet = sshbuf_new()) == NULL || | 235 | (state->outgoing_packet = sshbuf_new()) == NULL || |
@@ -250,6 +252,10 @@ ssh_alloc_session_state(void) | |||
250 | ssh->state = state; | 252 | ssh->state = state; |
251 | return ssh; | 253 | return ssh; |
252 | fail: | 254 | fail: |
255 | if (ssh) { | ||
256 | kex_free(ssh->kex); | ||
257 | free(ssh); | ||
258 | } | ||
253 | if (state) { | 259 | if (state) { |
254 | sshbuf_free(state->input); | 260 | sshbuf_free(state->input); |
255 | sshbuf_free(state->output); | 261 | sshbuf_free(state->output); |
@@ -257,7 +263,6 @@ ssh_alloc_session_state(void) | |||
257 | sshbuf_free(state->outgoing_packet); | 263 | sshbuf_free(state->outgoing_packet); |
258 | free(state); | 264 | free(state); |
259 | } | 265 | } |
260 | free(ssh); | ||
261 | return NULL; | 266 | return NULL; |
262 | } | 267 | } |
263 | 268 | ||
@@ -272,8 +277,7 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) | |||
272 | int | 277 | int |
273 | ssh_packet_is_rekeying(struct ssh *ssh) | 278 | ssh_packet_is_rekeying(struct ssh *ssh) |
274 | { | 279 | { |
275 | return ssh->state->rekeying || | 280 | return ssh->state->rekeying || ssh->kex->done == 0; |
276 | (ssh->kex != NULL && ssh->kex->done == 0); | ||
277 | } | 281 | } |
278 | 282 | ||
279 | /* | 283 | /* |
@@ -837,6 +841,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
837 | u_int64_t *max_blocks; | 841 | u_int64_t *max_blocks; |
838 | const char *wmsg; | 842 | const char *wmsg; |
839 | int r, crypt_type; | 843 | int r, crypt_type; |
844 | const char *dir = mode == MODE_OUT ? "out" : "in"; | ||
840 | 845 | ||
841 | debug2("set_newkeys: mode %d", mode); | 846 | debug2("set_newkeys: mode %d", mode); |
842 | 847 | ||
@@ -852,14 +857,12 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
852 | max_blocks = &state->max_blocks_in; | 857 | max_blocks = &state->max_blocks_in; |
853 | } | 858 | } |
854 | if (state->newkeys[mode] != NULL) { | 859 | if (state->newkeys[mode] != NULL) { |
855 | debug("set_newkeys: rekeying, input %llu bytes %llu blocks, " | 860 | debug("%s: rekeying %s, input %llu bytes %llu blocks, " |
856 | "output %llu bytes %llu blocks", | 861 | "output %llu bytes %llu blocks", __func__, dir, |
857 | (unsigned long long)state->p_read.bytes, | 862 | (unsigned long long)state->p_read.bytes, |
858 | (unsigned long long)state->p_read.blocks, | 863 | (unsigned long long)state->p_read.blocks, |
859 | (unsigned long long)state->p_send.bytes, | 864 | (unsigned long long)state->p_send.bytes, |
860 | (unsigned long long)state->p_send.blocks); | 865 | (unsigned long long)state->p_send.blocks); |
861 | cipher_free(*ccp); | ||
862 | *ccp = NULL; | ||
863 | kex_free_newkeys(state->newkeys[mode]); | 866 | kex_free_newkeys(state->newkeys[mode]); |
864 | state->newkeys[mode] = NULL; | 867 | state->newkeys[mode] = NULL; |
865 | } | 868 | } |
@@ -877,7 +880,9 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
877 | return r; | 880 | return r; |
878 | } | 881 | } |
879 | mac->enabled = 1; | 882 | mac->enabled = 1; |
880 | DBG(debug("cipher_init_context: %d", mode)); | 883 | DBG(debug("%s: cipher_init_context: %s", __func__, dir)); |
884 | cipher_free(*ccp); | ||
885 | *ccp = NULL; | ||
881 | if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len, | 886 | if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len, |
882 | enc->iv, enc->iv_len, crypt_type)) != 0) | 887 | enc->iv, enc->iv_len, crypt_type)) != 0) |
883 | return r; | 888 | return r; |
@@ -916,7 +921,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
916 | if (state->rekey_limit) | 921 | if (state->rekey_limit) |
917 | *max_blocks = MINIMUM(*max_blocks, | 922 | *max_blocks = MINIMUM(*max_blocks, |
918 | state->rekey_limit / enc->block_size); | 923 | state->rekey_limit / enc->block_size); |
919 | debug("rekey after %llu blocks", (unsigned long long)*max_blocks); | 924 | debug("rekey %s after %llu blocks", dir, |
925 | (unsigned long long)*max_blocks); | ||
920 | return 0; | 926 | return 0; |
921 | } | 927 | } |
922 | 928 | ||
@@ -932,7 +938,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) | |||
932 | return 0; | 938 | return 0; |
933 | 939 | ||
934 | /* Haven't keyed yet or KEX in progress. */ | 940 | /* Haven't keyed yet or KEX in progress. */ |
935 | if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh)) | 941 | if (ssh_packet_is_rekeying(ssh)) |
936 | return 0; | 942 | return 0; |
937 | 943 | ||
938 | /* Peer can't rekey */ | 944 | /* Peer can't rekey */ |
@@ -1805,10 +1811,10 @@ sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l) | |||
1805 | /* | 1811 | /* |
1806 | * Pretty-print connection-terminating errors and exit. | 1812 | * Pretty-print connection-terminating errors and exit. |
1807 | */ | 1813 | */ |
1808 | void | 1814 | static void |
1809 | sshpkt_fatal(struct ssh *ssh, const char *tag, int r) | 1815 | sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap) |
1810 | { | 1816 | { |
1811 | char remote_id[512]; | 1817 | char *tag = NULL, remote_id[512]; |
1812 | 1818 | ||
1813 | sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); | 1819 | sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); |
1814 | 1820 | ||
@@ -1842,6 +1848,11 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r) | |||
1842 | } | 1848 | } |
1843 | /* FALLTHROUGH */ | 1849 | /* FALLTHROUGH */ |
1844 | default: | 1850 | default: |
1851 | if (vasprintf(&tag, fmt, ap) == -1) { | ||
1852 | ssh_packet_clear_keys(ssh); | ||
1853 | logdie("%s: could not allocate failure message", | ||
1854 | __func__); | ||
1855 | } | ||
1845 | ssh_packet_clear_keys(ssh); | 1856 | ssh_packet_clear_keys(ssh); |
1846 | logdie("%s%sConnection %s %s: %s", | 1857 | logdie("%s%sConnection %s %s: %s", |
1847 | tag != NULL ? tag : "", tag != NULL ? ": " : "", | 1858 | tag != NULL ? tag : "", tag != NULL ? ": " : "", |
@@ -1850,6 +1861,18 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r) | |||
1850 | } | 1861 | } |
1851 | } | 1862 | } |
1852 | 1863 | ||
1864 | void | ||
1865 | sshpkt_fatal(struct ssh *ssh, int r, const char *fmt, ...) | ||
1866 | { | ||
1867 | va_list ap; | ||
1868 | |||
1869 | va_start(ap, fmt); | ||
1870 | sshpkt_vfatal(ssh, r, fmt, ap); | ||
1871 | /* NOTREACHED */ | ||
1872 | va_end(ap); | ||
1873 | logdie("%s: should have exited", __func__); | ||
1874 | } | ||
1875 | |||
1853 | /* | 1876 | /* |
1854 | * Logs the error plus constructs and sends a disconnect packet, closes the | 1877 | * Logs the error plus constructs and sends a disconnect packet, closes the |
1855 | * connection, and exits. This function never returns. The error message | 1878 | * connection, and exits. This function never returns. The error message |
@@ -1885,10 +1908,10 @@ ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...) | |||
1885 | * for it to get sent. | 1908 | * for it to get sent. |
1886 | */ | 1909 | */ |
1887 | if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0) | 1910 | if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0) |
1888 | sshpkt_fatal(ssh, __func__, r); | 1911 | sshpkt_fatal(ssh, r, "%s", __func__); |
1889 | 1912 | ||
1890 | if ((r = ssh_packet_write_wait(ssh)) != 0) | 1913 | if ((r = ssh_packet_write_wait(ssh)) != 0) |
1891 | sshpkt_fatal(ssh, __func__, r); | 1914 | sshpkt_fatal(ssh, r, "%s", __func__); |
1892 | 1915 | ||
1893 | /* Close the connection. */ | 1916 | /* Close the connection. */ |
1894 | ssh_packet_close(ssh); | 1917 | ssh_packet_close(ssh); |
@@ -2123,6 +2146,7 @@ void | |||
2123 | ssh_packet_set_server(struct ssh *ssh) | 2146 | ssh_packet_set_server(struct ssh *ssh) |
2124 | { | 2147 | { |
2125 | ssh->state->server_side = 1; | 2148 | ssh->state->server_side = 1; |
2149 | ssh->kex->server = 1; /* XXX unify? */ | ||
2126 | } | 2150 | } |
2127 | 2151 | ||
2128 | void | 2152 | void |
@@ -2175,9 +2199,9 @@ kex_to_blob(struct sshbuf *m, struct kex *kex) | |||
2175 | (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || | 2199 | (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || |
2176 | (r = sshbuf_put_stringb(m, kex->my)) != 0 || | 2200 | (r = sshbuf_put_stringb(m, kex->my)) != 0 || |
2177 | (r = sshbuf_put_stringb(m, kex->peer)) != 0 || | 2201 | (r = sshbuf_put_stringb(m, kex->peer)) != 0 || |
2178 | (r = sshbuf_put_u32(m, kex->flags)) != 0 || | 2202 | (r = sshbuf_put_stringb(m, kex->client_version)) != 0 || |
2179 | (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || | 2203 | (r = sshbuf_put_stringb(m, kex->server_version)) != 0 || |
2180 | (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) | 2204 | (r = sshbuf_put_u32(m, kex->flags)) != 0) |
2181 | return r; | 2205 | return r; |
2182 | return 0; | 2206 | return 0; |
2183 | } | 2207 | } |
@@ -2327,12 +2351,8 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) | |||
2327 | struct kex *kex; | 2351 | struct kex *kex; |
2328 | int r; | 2352 | int r; |
2329 | 2353 | ||
2330 | if ((kex = calloc(1, sizeof(struct kex))) == NULL || | 2354 | if ((kex = kex_new()) == NULL) |
2331 | (kex->my = sshbuf_new()) == NULL || | 2355 | return SSH_ERR_ALLOC_FAIL; |
2332 | (kex->peer = sshbuf_new()) == NULL) { | ||
2333 | r = SSH_ERR_ALLOC_FAIL; | ||
2334 | goto out; | ||
2335 | } | ||
2336 | if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || | 2356 | if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || |
2337 | (r = sshbuf_get_u32(m, &kex->we_need)) != 0 || | 2357 | (r = sshbuf_get_u32(m, &kex->we_need)) != 0 || |
2338 | (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || | 2358 | (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || |
@@ -2341,23 +2361,20 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) | |||
2341 | (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || | 2361 | (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || |
2342 | (r = sshbuf_get_stringb(m, kex->my)) != 0 || | 2362 | (r = sshbuf_get_stringb(m, kex->my)) != 0 || |
2343 | (r = sshbuf_get_stringb(m, kex->peer)) != 0 || | 2363 | (r = sshbuf_get_stringb(m, kex->peer)) != 0 || |
2344 | (r = sshbuf_get_u32(m, &kex->flags)) != 0 || | 2364 | (r = sshbuf_get_stringb(m, kex->client_version)) != 0 || |
2345 | (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || | 2365 | (r = sshbuf_get_stringb(m, kex->server_version)) != 0 || |
2346 | (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) | 2366 | (r = sshbuf_get_u32(m, &kex->flags)) != 0) |
2347 | goto out; | 2367 | goto out; |
2348 | kex->server = 1; | 2368 | kex->server = 1; |
2349 | kex->done = 1; | 2369 | kex->done = 1; |
2350 | r = 0; | 2370 | r = 0; |
2351 | out: | 2371 | out: |
2352 | if (r != 0 || kexp == NULL) { | 2372 | if (r != 0 || kexp == NULL) { |
2353 | if (kex != NULL) { | 2373 | kex_free(kex); |
2354 | sshbuf_free(kex->my); | ||
2355 | sshbuf_free(kex->peer); | ||
2356 | free(kex); | ||
2357 | } | ||
2358 | if (kexp != NULL) | 2374 | if (kexp != NULL) |
2359 | *kexp = NULL; | 2375 | *kexp = NULL; |
2360 | } else { | 2376 | } else { |
2377 | kex_free(*kexp); | ||
2361 | *kexp = kex; | 2378 | *kexp = kex; |
2362 | } | 2379 | } |
2363 | return r; | 2380 | return r; |
@@ -2468,6 +2485,12 @@ sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v) | |||
2468 | return sshbuf_put_stringb(ssh->state->outgoing_packet, v); | 2485 | return sshbuf_put_stringb(ssh->state->outgoing_packet, v); |
2469 | } | 2486 | } |
2470 | 2487 | ||
2488 | int | ||
2489 | sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp) | ||
2490 | { | ||
2491 | return sshbuf_froms(ssh->state->incoming_packet, valp); | ||
2492 | } | ||
2493 | |||
2471 | #ifdef WITH_OPENSSL | 2494 | #ifdef WITH_OPENSSL |
2472 | #ifdef OPENSSL_HAS_ECC | 2495 | #ifdef OPENSSL_HAS_ECC |
2473 | int | 2496 | int |
@@ -2544,11 +2567,10 @@ sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g) | |||
2544 | } | 2567 | } |
2545 | #endif /* OPENSSL_HAS_ECC */ | 2568 | #endif /* OPENSSL_HAS_ECC */ |
2546 | 2569 | ||
2547 | |||
2548 | int | 2570 | int |
2549 | sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v) | 2571 | sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp) |
2550 | { | 2572 | { |
2551 | return sshbuf_get_bignum2(ssh->state->incoming_packet, v); | 2573 | return sshbuf_get_bignum2(ssh->state->incoming_packet, valp); |
2552 | } | 2574 | } |
2553 | #endif /* WITH_OPENSSL */ | 2575 | #endif /* WITH_OPENSSL */ |
2554 | 2576 | ||