diff options
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 330 |
1 files changed, 170 insertions, 160 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.234 2016/07/18 11:35:33 markus Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.243 2016/10/11 21:47:45 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 |
@@ -38,8 +38,7 @@ | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | #include "includes.h" | 40 | #include "includes.h" |
41 | 41 | ||
42 | #include <sys/param.h> /* MIN roundup */ | ||
43 | #include <sys/types.h> | 42 | #include <sys/types.h> |
44 | #include "openbsd-compat/sys-queue.h" | 43 | #include "openbsd-compat/sys-queue.h" |
45 | #include <sys/socket.h> | 44 | #include <sys/socket.h> |
@@ -122,10 +121,10 @@ struct session_state { | |||
122 | u_int remote_protocol_flags; | 121 | u_int remote_protocol_flags; |
123 | 122 | ||
124 | /* Encryption context for receiving data. Only used for decryption. */ | 123 | /* Encryption context for receiving data. Only used for decryption. */ |
125 | struct sshcipher_ctx receive_context; | 124 | struct sshcipher_ctx *receive_context; |
126 | 125 | ||
127 | /* Encryption context for sending data. Only used for encryption. */ | 126 | /* Encryption context for sending data. Only used for encryption. */ |
128 | struct sshcipher_ctx send_context; | 127 | struct sshcipher_ctx *send_context; |
129 | 128 | ||
130 | /* Buffer for raw input data from the socket. */ | 129 | /* Buffer for raw input data from the socket. */ |
131 | struct sshbuf *input; | 130 | struct sshbuf *input; |
@@ -205,6 +204,9 @@ struct session_state { | |||
205 | /* Used in packet_send2 */ | 204 | /* Used in packet_send2 */ |
206 | int rekeying; | 205 | int rekeying; |
207 | 206 | ||
207 | /* Used in ssh_packet_send_mux() */ | ||
208 | int mux; | ||
209 | |||
208 | /* Used in packet_set_interactive */ | 210 | /* Used in packet_set_interactive */ |
209 | int set_interactive_called; | 211 | int set_interactive_called; |
210 | 212 | ||
@@ -217,6 +219,10 @@ struct session_state { | |||
217 | /* SSH1 CRC compensation attack detector */ | 219 | /* SSH1 CRC compensation attack detector */ |
218 | struct deattack_ctx deattack; | 220 | struct deattack_ctx deattack; |
219 | 221 | ||
222 | /* Hook for fuzzing inbound packets */ | ||
223 | ssh_packet_hook_fn *hook_in; | ||
224 | void *hook_in_ctx; | ||
225 | |||
220 | TAILQ_HEAD(, packet) outgoing; | 226 | TAILQ_HEAD(, packet) outgoing; |
221 | }; | 227 | }; |
222 | 228 | ||
@@ -261,6 +267,13 @@ ssh_alloc_session_state(void) | |||
261 | return NULL; | 267 | return NULL; |
262 | } | 268 | } |
263 | 269 | ||
270 | void | ||
271 | ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) | ||
272 | { | ||
273 | ssh->state->hook_in = hook; | ||
274 | ssh->state->hook_in_ctx = ctx; | ||
275 | } | ||
276 | |||
264 | /* Returns nonzero if rekeying is in progress */ | 277 | /* Returns nonzero if rekeying is in progress */ |
265 | int | 278 | int |
266 | ssh_packet_is_rekeying(struct ssh *ssh) | 279 | ssh_packet_is_rekeying(struct ssh *ssh) |
@@ -326,6 +339,19 @@ ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count) | |||
326 | state->packet_timeout_ms = timeout * count * 1000; | 339 | state->packet_timeout_ms = timeout * count * 1000; |
327 | } | 340 | } |
328 | 341 | ||
342 | void | ||
343 | ssh_packet_set_mux(struct ssh *ssh) | ||
344 | { | ||
345 | ssh->state->mux = 1; | ||
346 | ssh->state->rekeying = 0; | ||
347 | } | ||
348 | |||
349 | int | ||
350 | ssh_packet_get_mux(struct ssh *ssh) | ||
351 | { | ||
352 | return ssh->state->mux; | ||
353 | } | ||
354 | |||
329 | int | 355 | int |
330 | ssh_packet_stop_discard(struct ssh *ssh) | 356 | ssh_packet_stop_discard(struct ssh *ssh) |
331 | { | 357 | { |
@@ -529,7 +555,6 @@ void | |||
529 | ssh_packet_close(struct ssh *ssh) | 555 | ssh_packet_close(struct ssh *ssh) |
530 | { | 556 | { |
531 | struct session_state *state = ssh->state; | 557 | struct session_state *state = ssh->state; |
532 | int r; | ||
533 | u_int mode; | 558 | u_int mode; |
534 | 559 | ||
535 | if (!state->initialized) | 560 | if (!state->initialized) |
@@ -573,10 +598,9 @@ ssh_packet_close(struct ssh *ssh) | |||
573 | inflateEnd(stream); | 598 | inflateEnd(stream); |
574 | } | 599 | } |
575 | } | 600 | } |
576 | if ((r = cipher_cleanup(&state->send_context)) != 0) | 601 | cipher_free(state->send_context); |
577 | error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); | 602 | cipher_free(state->receive_context); |
578 | if ((r = cipher_cleanup(&state->receive_context)) != 0) | 603 | state->send_context = state->receive_context = NULL; |
579 | error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); | ||
580 | free(ssh->remote_ipaddr); | 604 | free(ssh->remote_ipaddr); |
581 | ssh->remote_ipaddr = NULL; | 605 | ssh->remote_ipaddr = NULL; |
582 | free(ssh->state); | 606 | free(ssh->state); |
@@ -759,86 +783,6 @@ uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) | |||
759 | /* NOTREACHED */ | 783 | /* NOTREACHED */ |
760 | } | 784 | } |
761 | 785 | ||
762 | /* Serialise compression state into a blob for privsep */ | ||
763 | static int | ||
764 | ssh_packet_get_compress_state(struct sshbuf *m, struct ssh *ssh) | ||
765 | { | ||
766 | struct session_state *state = ssh->state; | ||
767 | struct sshbuf *b; | ||
768 | int r; | ||
769 | |||
770 | if ((b = sshbuf_new()) == NULL) | ||
771 | return SSH_ERR_ALLOC_FAIL; | ||
772 | if (state->compression_in_started) { | ||
773 | if ((r = sshbuf_put_string(b, &state->compression_in_stream, | ||
774 | sizeof(state->compression_in_stream))) != 0) | ||
775 | goto out; | ||
776 | } else if ((r = sshbuf_put_string(b, NULL, 0)) != 0) | ||
777 | goto out; | ||
778 | if (state->compression_out_started) { | ||
779 | if ((r = sshbuf_put_string(b, &state->compression_out_stream, | ||
780 | sizeof(state->compression_out_stream))) != 0) | ||
781 | goto out; | ||
782 | } else if ((r = sshbuf_put_string(b, NULL, 0)) != 0) | ||
783 | goto out; | ||
784 | r = sshbuf_put_stringb(m, b); | ||
785 | out: | ||
786 | sshbuf_free(b); | ||
787 | return r; | ||
788 | } | ||
789 | |||
790 | /* Deserialise compression state from a blob for privsep */ | ||
791 | static int | ||
792 | ssh_packet_set_compress_state(struct ssh *ssh, struct sshbuf *m) | ||
793 | { | ||
794 | struct session_state *state = ssh->state; | ||
795 | struct sshbuf *b = NULL; | ||
796 | int r; | ||
797 | const u_char *inblob, *outblob; | ||
798 | size_t inl, outl; | ||
799 | |||
800 | if ((r = sshbuf_froms(m, &b)) != 0) | ||
801 | goto out; | ||
802 | if ((r = sshbuf_get_string_direct(b, &inblob, &inl)) != 0 || | ||
803 | (r = sshbuf_get_string_direct(b, &outblob, &outl)) != 0) | ||
804 | goto out; | ||
805 | if (inl == 0) | ||
806 | state->compression_in_started = 0; | ||
807 | else if (inl != sizeof(state->compression_in_stream)) { | ||
808 | r = SSH_ERR_INTERNAL_ERROR; | ||
809 | goto out; | ||
810 | } else { | ||
811 | state->compression_in_started = 1; | ||
812 | memcpy(&state->compression_in_stream, inblob, inl); | ||
813 | } | ||
814 | if (outl == 0) | ||
815 | state->compression_out_started = 0; | ||
816 | else if (outl != sizeof(state->compression_out_stream)) { | ||
817 | r = SSH_ERR_INTERNAL_ERROR; | ||
818 | goto out; | ||
819 | } else { | ||
820 | state->compression_out_started = 1; | ||
821 | memcpy(&state->compression_out_stream, outblob, outl); | ||
822 | } | ||
823 | r = 0; | ||
824 | out: | ||
825 | sshbuf_free(b); | ||
826 | return r; | ||
827 | } | ||
828 | |||
829 | void | ||
830 | ssh_packet_set_compress_hooks(struct ssh *ssh, void *ctx, | ||
831 | void *(*allocfunc)(void *, u_int, u_int), | ||
832 | void (*freefunc)(void *, void *)) | ||
833 | { | ||
834 | ssh->state->compression_out_stream.zalloc = (alloc_func)allocfunc; | ||
835 | ssh->state->compression_out_stream.zfree = (free_func)freefunc; | ||
836 | ssh->state->compression_out_stream.opaque = ctx; | ||
837 | ssh->state->compression_in_stream.zalloc = (alloc_func)allocfunc; | ||
838 | ssh->state->compression_in_stream.zfree = (free_func)freefunc; | ||
839 | ssh->state->compression_in_stream.opaque = ctx; | ||
840 | } | ||
841 | |||
842 | /* | 786 | /* |
843 | * Causes any further packets to be encrypted using the given key. The same | 787 | * Causes any further packets to be encrypted using the given key. The same |
844 | * key is used for both sending and reception. However, both directions are | 788 | * key is used for both sending and reception. However, both directions are |
@@ -870,8 +814,8 @@ ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, | |||
870 | NULL, 0, CIPHER_DECRYPT) != 0)) | 814 | NULL, 0, CIPHER_DECRYPT) != 0)) |
871 | fatal("%s: cipher_init failed: %s", __func__, ssh_err(r)); | 815 | fatal("%s: cipher_init failed: %s", __func__, ssh_err(r)); |
872 | if (!state->cipher_warning_done && | 816 | if (!state->cipher_warning_done && |
873 | ((wmsg = cipher_warning_message(&state->send_context)) != NULL || | 817 | ((wmsg = cipher_warning_message(state->send_context)) != NULL || |
874 | (wmsg = cipher_warning_message(&state->send_context)) != NULL)) { | 818 | (wmsg = cipher_warning_message(state->send_context)) != NULL)) { |
875 | error("Warning: %s", wmsg); | 819 | error("Warning: %s", wmsg); |
876 | state->cipher_warning_done = 1; | 820 | state->cipher_warning_done = 1; |
877 | } | 821 | } |
@@ -917,7 +861,7 @@ ssh_packet_send1(struct ssh *ssh) | |||
917 | 861 | ||
918 | /* Insert padding. Initialized to zero in packet_start1() */ | 862 | /* Insert padding. Initialized to zero in packet_start1() */ |
919 | padding = 8 - len % 8; | 863 | padding = 8 - len % 8; |
920 | if (!state->send_context.plaintext) { | 864 | if (!cipher_ctx_is_plaintext(state->send_context)) { |
921 | cp = sshbuf_mutable_ptr(state->outgoing_packet); | 865 | cp = sshbuf_mutable_ptr(state->outgoing_packet); |
922 | if (cp == NULL) { | 866 | if (cp == NULL) { |
923 | r = SSH_ERR_INTERNAL_ERROR; | 867 | r = SSH_ERR_INTERNAL_ERROR; |
@@ -947,7 +891,7 @@ ssh_packet_send1(struct ssh *ssh) | |||
947 | if ((r = sshbuf_reserve(state->output, | 891 | if ((r = sshbuf_reserve(state->output, |
948 | sshbuf_len(state->outgoing_packet), &cp)) != 0) | 892 | sshbuf_len(state->outgoing_packet), &cp)) != 0) |
949 | goto out; | 893 | goto out; |
950 | if ((r = cipher_crypt(&state->send_context, 0, cp, | 894 | if ((r = cipher_crypt(state->send_context, 0, cp, |
951 | sshbuf_ptr(state->outgoing_packet), | 895 | sshbuf_ptr(state->outgoing_packet), |
952 | sshbuf_len(state->outgoing_packet), 0, 0)) != 0) | 896 | sshbuf_len(state->outgoing_packet), 0, 0)) != 0) |
953 | goto out; | 897 | goto out; |
@@ -978,33 +922,34 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
978 | struct sshenc *enc; | 922 | struct sshenc *enc; |
979 | struct sshmac *mac; | 923 | struct sshmac *mac; |
980 | struct sshcomp *comp; | 924 | struct sshcomp *comp; |
981 | struct sshcipher_ctx *cc; | 925 | struct sshcipher_ctx **ccp; |
926 | struct packet_state *ps; | ||
982 | u_int64_t *max_blocks; | 927 | u_int64_t *max_blocks; |
983 | const char *wmsg; | 928 | const char *wmsg, *dir; |
984 | int r, crypt_type; | 929 | int r, crypt_type; |
985 | 930 | ||
986 | debug2("set_newkeys: mode %d", mode); | 931 | debug2("set_newkeys: mode %d", mode); |
987 | 932 | ||
988 | if (mode == MODE_OUT) { | 933 | if (mode == MODE_OUT) { |
989 | cc = &state->send_context; | 934 | dir = "output"; |
935 | ccp = &state->send_context; | ||
990 | crypt_type = CIPHER_ENCRYPT; | 936 | crypt_type = CIPHER_ENCRYPT; |
991 | state->p_send.packets = state->p_send.blocks = 0; | 937 | ps = &state->p_send; |
992 | max_blocks = &state->max_blocks_out; | 938 | max_blocks = &state->max_blocks_out; |
993 | } else { | 939 | } else { |
994 | cc = &state->receive_context; | 940 | dir = "input"; |
941 | ccp = &state->receive_context; | ||
995 | crypt_type = CIPHER_DECRYPT; | 942 | crypt_type = CIPHER_DECRYPT; |
996 | state->p_read.packets = state->p_read.blocks = 0; | 943 | ps = &state->p_read; |
997 | max_blocks = &state->max_blocks_in; | 944 | max_blocks = &state->max_blocks_in; |
998 | } | 945 | } |
999 | if (state->newkeys[mode] != NULL) { | 946 | if (state->newkeys[mode] != NULL) { |
1000 | debug("set_newkeys: rekeying, input %llu bytes %llu blocks, " | 947 | debug("%s: rekeying after %llu %s blocks" |
1001 | "output %llu bytes %llu blocks", | 948 | " (%llu bytes total)", __func__, |
1002 | (unsigned long long)state->p_read.bytes, | 949 | (unsigned long long)ps->blocks, dir, |
1003 | (unsigned long long)state->p_read.blocks, | 950 | (unsigned long long)ps->bytes); |
1004 | (unsigned long long)state->p_send.bytes, | 951 | cipher_free(*ccp); |
1005 | (unsigned long long)state->p_send.blocks); | 952 | *ccp = NULL; |
1006 | if ((r = cipher_cleanup(cc)) != 0) | ||
1007 | return r; | ||
1008 | enc = &state->newkeys[mode]->enc; | 953 | enc = &state->newkeys[mode]->enc; |
1009 | mac = &state->newkeys[mode]->mac; | 954 | mac = &state->newkeys[mode]->mac; |
1010 | comp = &state->newkeys[mode]->comp; | 955 | comp = &state->newkeys[mode]->comp; |
@@ -1020,6 +965,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
1020 | free(comp->name); | 965 | free(comp->name); |
1021 | free(state->newkeys[mode]); | 966 | free(state->newkeys[mode]); |
1022 | } | 967 | } |
968 | /* note that both bytes and the seqnr are not reset */ | ||
969 | ps->packets = ps->blocks = 0; | ||
1023 | /* move newkeys from kex to state */ | 970 | /* move newkeys from kex to state */ |
1024 | if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL) | 971 | if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL) |
1025 | return SSH_ERR_INTERNAL_ERROR; | 972 | return SSH_ERR_INTERNAL_ERROR; |
@@ -1033,11 +980,11 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
1033 | } | 980 | } |
1034 | mac->enabled = 1; | 981 | mac->enabled = 1; |
1035 | DBG(debug("cipher_init_context: %d", mode)); | 982 | DBG(debug("cipher_init_context: %d", mode)); |
1036 | if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len, | 983 | if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len, |
1037 | enc->iv, enc->iv_len, crypt_type)) != 0) | 984 | enc->iv, enc->iv_len, crypt_type)) != 0) |
1038 | return r; | 985 | return r; |
1039 | if (!state->cipher_warning_done && | 986 | if (!state->cipher_warning_done && |
1040 | (wmsg = cipher_warning_message(cc)) != NULL) { | 987 | (wmsg = cipher_warning_message(*ccp)) != NULL) { |
1041 | error("Warning: %s", wmsg); | 988 | error("Warning: %s", wmsg); |
1042 | state->cipher_warning_done = 1; | 989 | state->cipher_warning_done = 1; |
1043 | } | 990 | } |
@@ -1068,7 +1015,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
1068 | else | 1015 | else |
1069 | *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; | 1016 | *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; |
1070 | if (state->rekey_limit) | 1017 | if (state->rekey_limit) |
1071 | *max_blocks = MIN(*max_blocks, | 1018 | *max_blocks = MINIMUM(*max_blocks, |
1072 | state->rekey_limit / enc->block_size); | 1019 | state->rekey_limit / enc->block_size); |
1073 | debug("rekey after %llu blocks", (unsigned long long)*max_blocks); | 1020 | debug("rekey after %llu blocks", (unsigned long long)*max_blocks); |
1074 | return 0; | 1021 | return 0; |
@@ -1111,7 +1058,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) | |||
1111 | return 1; | 1058 | return 1; |
1112 | 1059 | ||
1113 | /* Rekey after (cipher-specific) maxiumum blocks */ | 1060 | /* Rekey after (cipher-specific) maxiumum blocks */ |
1114 | out_blocks = roundup(outbound_packet_len, | 1061 | out_blocks = ROUNDUP(outbound_packet_len, |
1115 | state->newkeys[MODE_OUT]->enc.block_size); | 1062 | state->newkeys[MODE_OUT]->enc.block_size); |
1116 | return (state->max_blocks_out && | 1063 | return (state->max_blocks_out && |
1117 | (state->p_send.blocks + out_blocks > state->max_blocks_out)) || | 1064 | (state->p_send.blocks + out_blocks > state->max_blocks_out)) || |
@@ -1158,7 +1105,7 @@ ssh_packet_enable_delayed_compress(struct ssh *ssh) | |||
1158 | } | 1105 | } |
1159 | 1106 | ||
1160 | /* Used to mute debug logging for noisy packet types */ | 1107 | /* Used to mute debug logging for noisy packet types */ |
1161 | static int | 1108 | int |
1162 | ssh_packet_log_type(u_char type) | 1109 | ssh_packet_log_type(u_char type) |
1163 | { | 1110 | { |
1164 | switch (type) { | 1111 | switch (type) { |
@@ -1239,7 +1186,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh) | |||
1239 | if (state->extra_pad) { | 1186 | if (state->extra_pad) { |
1240 | tmp = state->extra_pad; | 1187 | tmp = state->extra_pad; |
1241 | state->extra_pad = | 1188 | state->extra_pad = |
1242 | roundup(state->extra_pad, block_size); | 1189 | ROUNDUP(state->extra_pad, block_size); |
1243 | /* check if roundup overflowed */ | 1190 | /* check if roundup overflowed */ |
1244 | if (state->extra_pad < tmp) | 1191 | if (state->extra_pad < tmp) |
1245 | return SSH_ERR_INVALID_ARGUMENT; | 1192 | return SSH_ERR_INVALID_ARGUMENT; |
@@ -1259,7 +1206,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh) | |||
1259 | } | 1206 | } |
1260 | if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0) | 1207 | if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0) |
1261 | goto out; | 1208 | goto out; |
1262 | if (enc && !state->send_context.plaintext) { | 1209 | if (enc && !cipher_ctx_is_plaintext(state->send_context)) { |
1263 | /* random padding */ | 1210 | /* random padding */ |
1264 | arc4random_buf(cp, padlen); | 1211 | arc4random_buf(cp, padlen); |
1265 | } else { | 1212 | } else { |
@@ -1291,7 +1238,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh) | |||
1291 | if ((r = sshbuf_reserve(state->output, | 1238 | if ((r = sshbuf_reserve(state->output, |
1292 | sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0) | 1239 | sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0) |
1293 | goto out; | 1240 | goto out; |
1294 | if ((r = cipher_crypt(&state->send_context, state->p_send.seqnr, cp, | 1241 | if ((r = cipher_crypt(state->send_context, state->p_send.seqnr, cp, |
1295 | sshbuf_ptr(state->outgoing_packet), | 1242 | sshbuf_ptr(state->outgoing_packet), |
1296 | len - aadlen, aadlen, authlen)) != 0) | 1243 | len - aadlen, aadlen, authlen)) != 0) |
1297 | goto out; | 1244 | goto out; |
@@ -1606,7 +1553,7 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep) | |||
1606 | * (C)1998 CORE-SDI, Buenos Aires Argentina | 1553 | * (C)1998 CORE-SDI, Buenos Aires Argentina |
1607 | * Ariel Futoransky(futo@core-sdi.com) | 1554 | * Ariel Futoransky(futo@core-sdi.com) |
1608 | */ | 1555 | */ |
1609 | if (!state->receive_context.plaintext) { | 1556 | if (!cipher_ctx_is_plaintext(state->receive_context)) { |
1610 | emsg = NULL; | 1557 | emsg = NULL; |
1611 | switch (detect_attack(&state->deattack, | 1558 | switch (detect_attack(&state->deattack, |
1612 | sshbuf_ptr(state->input), padded_len)) { | 1559 | sshbuf_ptr(state->input), padded_len)) { |
@@ -1635,7 +1582,7 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep) | |||
1635 | sshbuf_reset(state->incoming_packet); | 1582 | sshbuf_reset(state->incoming_packet); |
1636 | if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0) | 1583 | if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0) |
1637 | goto out; | 1584 | goto out; |
1638 | if ((r = cipher_crypt(&state->receive_context, 0, p, | 1585 | if ((r = cipher_crypt(state->receive_context, 0, p, |
1639 | sshbuf_ptr(state->input), padded_len, 0, 0)) != 0) | 1586 | sshbuf_ptr(state->input), padded_len, 0, 0)) != 0) |
1640 | goto out; | 1587 | goto out; |
1641 | 1588 | ||
@@ -1703,6 +1650,44 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep) | |||
1703 | return r; | 1650 | return r; |
1704 | } | 1651 | } |
1705 | 1652 | ||
1653 | static int | ||
1654 | ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | ||
1655 | { | ||
1656 | struct session_state *state = ssh->state; | ||
1657 | const u_char *cp; | ||
1658 | size_t need; | ||
1659 | int r; | ||
1660 | |||
1661 | if (ssh->kex) | ||
1662 | return SSH_ERR_INTERNAL_ERROR; | ||
1663 | *typep = SSH_MSG_NONE; | ||
1664 | cp = sshbuf_ptr(state->input); | ||
1665 | if (state->packlen == 0) { | ||
1666 | if (sshbuf_len(state->input) < 4 + 1) | ||
1667 | return 0; /* packet is incomplete */ | ||
1668 | state->packlen = PEEK_U32(cp); | ||
1669 | if (state->packlen < 4 + 1 || | ||
1670 | state->packlen > PACKET_MAX_SIZE) | ||
1671 | return SSH_ERR_MESSAGE_INCOMPLETE; | ||
1672 | } | ||
1673 | need = state->packlen + 4; | ||
1674 | if (sshbuf_len(state->input) < need) | ||
1675 | return 0; /* packet is incomplete */ | ||
1676 | sshbuf_reset(state->incoming_packet); | ||
1677 | if ((r = sshbuf_put(state->incoming_packet, cp + 4, | ||
1678 | state->packlen)) != 0 || | ||
1679 | (r = sshbuf_consume(state->input, need)) != 0 || | ||
1680 | (r = sshbuf_get_u8(state->incoming_packet, NULL)) != 0 || | ||
1681 | (r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) | ||
1682 | return r; | ||
1683 | if (ssh_packet_log_type(*typep)) | ||
1684 | debug3("%s: type %u", __func__, *typep); | ||
1685 | /* sshbuf_dump(state->incoming_packet, stderr); */ | ||
1686 | /* reset for next packet */ | ||
1687 | state->packlen = 0; | ||
1688 | return r; | ||
1689 | } | ||
1690 | |||
1706 | int | 1691 | int |
1707 | ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | 1692 | ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
1708 | { | 1693 | { |
@@ -1715,6 +1700,9 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1715 | struct sshcomp *comp = NULL; | 1700 | struct sshcomp *comp = NULL; |
1716 | int r; | 1701 | int r; |
1717 | 1702 | ||
1703 | if (state->mux) | ||
1704 | return ssh_packet_read_poll2_mux(ssh, typep, seqnr_p); | ||
1705 | |||
1718 | *typep = SSH_MSG_NONE; | 1706 | *typep = SSH_MSG_NONE; |
1719 | 1707 | ||
1720 | if (state->packet_discard) | 1708 | if (state->packet_discard) |
@@ -1733,7 +1721,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1733 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; | 1721 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; |
1734 | 1722 | ||
1735 | if (aadlen && state->packlen == 0) { | 1723 | if (aadlen && state->packlen == 0) { |
1736 | if (cipher_get_length(&state->receive_context, | 1724 | if (cipher_get_length(state->receive_context, |
1737 | &state->packlen, state->p_read.seqnr, | 1725 | &state->packlen, state->p_read.seqnr, |
1738 | sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0) | 1726 | sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0) |
1739 | return 0; | 1727 | return 0; |
@@ -1759,7 +1747,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1759 | if ((r = sshbuf_reserve(state->incoming_packet, block_size, | 1747 | if ((r = sshbuf_reserve(state->incoming_packet, block_size, |
1760 | &cp)) != 0) | 1748 | &cp)) != 0) |
1761 | goto out; | 1749 | goto out; |
1762 | if ((r = cipher_crypt(&state->receive_context, | 1750 | if ((r = cipher_crypt(state->receive_context, |
1763 | state->p_send.seqnr, cp, sshbuf_ptr(state->input), | 1751 | state->p_send.seqnr, cp, sshbuf_ptr(state->input), |
1764 | block_size, 0, 0)) != 0) | 1752 | block_size, 0, 0)) != 0) |
1765 | goto out; | 1753 | goto out; |
@@ -1827,7 +1815,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1827 | if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, | 1815 | if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, |
1828 | &cp)) != 0) | 1816 | &cp)) != 0) |
1829 | goto out; | 1817 | goto out; |
1830 | if ((r = cipher_crypt(&state->receive_context, state->p_read.seqnr, cp, | 1818 | if ((r = cipher_crypt(state->receive_context, state->p_read.seqnr, cp, |
1831 | sshbuf_ptr(state->input), need, aadlen, authlen)) != 0) | 1819 | sshbuf_ptr(state->input), need, aadlen, authlen)) != 0) |
1832 | goto out; | 1820 | goto out; |
1833 | if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) | 1821 | if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) |
@@ -1907,9 +1895,11 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1907 | return r; | 1895 | return r; |
1908 | return SSH_ERR_PROTOCOL_ERROR; | 1896 | return SSH_ERR_PROTOCOL_ERROR; |
1909 | } | 1897 | } |
1910 | if (*typep == SSH2_MSG_NEWKEYS) | 1898 | if (state->hook_in != NULL && |
1911 | r = ssh_set_newkeys(ssh, MODE_IN); | 1899 | (r = state->hook_in(ssh, state->incoming_packet, typep, |
1912 | else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side) | 1900 | state->hook_in_ctx)) != 0) |
1901 | return r; | ||
1902 | if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side) | ||
1913 | r = ssh_packet_enable_delayed_compress(ssh); | 1903 | r = ssh_packet_enable_delayed_compress(ssh); |
1914 | else | 1904 | else |
1915 | r = 0; | 1905 | r = 0; |
@@ -2452,21 +2442,14 @@ ssh_packet_get_output(struct ssh *ssh) | |||
2452 | static int | 2442 | static int |
2453 | ssh_packet_set_postauth(struct ssh *ssh) | 2443 | ssh_packet_set_postauth(struct ssh *ssh) |
2454 | { | 2444 | { |
2455 | struct sshcomp *comp; | 2445 | int r; |
2456 | int r, mode; | ||
2457 | 2446 | ||
2458 | debug("%s: called", __func__); | 2447 | debug("%s: called", __func__); |
2459 | /* This was set in net child, but is not visible in user child */ | 2448 | /* This was set in net child, but is not visible in user child */ |
2460 | ssh->state->after_authentication = 1; | 2449 | ssh->state->after_authentication = 1; |
2461 | ssh->state->rekeying = 0; | 2450 | ssh->state->rekeying = 0; |
2462 | for (mode = 0; mode < MODE_MAX; mode++) { | 2451 | if ((r = ssh_packet_enable_delayed_compress(ssh)) != 0) |
2463 | if (ssh->state->newkeys[mode] == NULL) | 2452 | return r; |
2464 | continue; | ||
2465 | comp = &ssh->state->newkeys[mode]->comp; | ||
2466 | if (comp && comp->enabled && | ||
2467 | (r = ssh_packet_init_compression(ssh)) != 0) | ||
2468 | return r; | ||
2469 | } | ||
2470 | return 0; | 2453 | return 0; |
2471 | } | 2454 | } |
2472 | 2455 | ||
@@ -2509,8 +2492,8 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode) | |||
2509 | enc = &newkey->enc; | 2492 | enc = &newkey->enc; |
2510 | mac = &newkey->mac; | 2493 | mac = &newkey->mac; |
2511 | comp = &newkey->comp; | 2494 | comp = &newkey->comp; |
2512 | cc = (mode == MODE_OUT) ? &ssh->state->send_context : | 2495 | cc = (mode == MODE_OUT) ? ssh->state->send_context : |
2513 | &ssh->state->receive_context; | 2496 | ssh->state->receive_context; |
2514 | if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0) | 2497 | if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0) |
2515 | return r; | 2498 | return r; |
2516 | if ((b = sshbuf_new()) == NULL) | 2499 | if ((b = sshbuf_new()) == NULL) |
@@ -2530,7 +2513,6 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode) | |||
2530 | goto out; | 2513 | goto out; |
2531 | } | 2514 | } |
2532 | if ((r = sshbuf_put_u32(b, comp->type)) != 0 || | 2515 | if ((r = sshbuf_put_u32(b, comp->type)) != 0 || |
2533 | (r = sshbuf_put_u32(b, comp->enabled)) != 0 || | ||
2534 | (r = sshbuf_put_cstring(b, comp->name)) != 0) | 2516 | (r = sshbuf_put_cstring(b, comp->name)) != 0) |
2535 | goto out; | 2517 | goto out; |
2536 | r = sshbuf_put_stringb(m, b); | 2518 | r = sshbuf_put_stringb(m, b); |
@@ -2549,18 +2531,18 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) | |||
2549 | int r, ssh1cipher; | 2531 | int r, ssh1cipher; |
2550 | 2532 | ||
2551 | if (!compat20) { | 2533 | if (!compat20) { |
2552 | ssh1cipher = cipher_get_number(state->receive_context.cipher); | 2534 | ssh1cipher = cipher_ctx_get_number(state->receive_context); |
2553 | slen = cipher_get_keyiv_len(&state->send_context); | 2535 | slen = cipher_get_keyiv_len(state->send_context); |
2554 | rlen = cipher_get_keyiv_len(&state->receive_context); | 2536 | rlen = cipher_get_keyiv_len(state->receive_context); |
2555 | if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 || | 2537 | if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 || |
2556 | (r = sshbuf_put_u32(m, ssh1cipher)) != 0 || | 2538 | (r = sshbuf_put_u32(m, ssh1cipher)) != 0 || |
2557 | (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 || | 2539 | (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 || |
2558 | (r = sshbuf_put_u32(m, slen)) != 0 || | 2540 | (r = sshbuf_put_u32(m, slen)) != 0 || |
2559 | (r = sshbuf_reserve(m, slen, &p)) != 0 || | 2541 | (r = sshbuf_reserve(m, slen, &p)) != 0 || |
2560 | (r = cipher_get_keyiv(&state->send_context, p, slen)) != 0 || | 2542 | (r = cipher_get_keyiv(state->send_context, p, slen)) != 0 || |
2561 | (r = sshbuf_put_u32(m, rlen)) != 0 || | 2543 | (r = sshbuf_put_u32(m, rlen)) != 0 || |
2562 | (r = sshbuf_reserve(m, rlen, &p)) != 0 || | 2544 | (r = sshbuf_reserve(m, rlen, &p)) != 0 || |
2563 | (r = cipher_get_keyiv(&state->receive_context, p, rlen)) != 0) | 2545 | (r = cipher_get_keyiv(state->receive_context, p, rlen)) != 0) |
2564 | return r; | 2546 | return r; |
2565 | } else { | 2547 | } else { |
2566 | if ((r = kex_to_blob(m, ssh->kex)) != 0 || | 2548 | if ((r = kex_to_blob(m, ssh->kex)) != 0 || |
@@ -2579,21 +2561,19 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) | |||
2579 | return r; | 2561 | return r; |
2580 | } | 2562 | } |
2581 | 2563 | ||
2582 | slen = cipher_get_keycontext(&state->send_context, NULL); | 2564 | slen = cipher_get_keycontext(state->send_context, NULL); |
2583 | rlen = cipher_get_keycontext(&state->receive_context, NULL); | 2565 | rlen = cipher_get_keycontext(state->receive_context, NULL); |
2584 | if ((r = sshbuf_put_u32(m, slen)) != 0 || | 2566 | if ((r = sshbuf_put_u32(m, slen)) != 0 || |
2585 | (r = sshbuf_reserve(m, slen, &p)) != 0) | 2567 | (r = sshbuf_reserve(m, slen, &p)) != 0) |
2586 | return r; | 2568 | return r; |
2587 | if (cipher_get_keycontext(&state->send_context, p) != (int)slen) | 2569 | if (cipher_get_keycontext(state->send_context, p) != (int)slen) |
2588 | return SSH_ERR_INTERNAL_ERROR; | 2570 | return SSH_ERR_INTERNAL_ERROR; |
2589 | if ((r = sshbuf_put_u32(m, rlen)) != 0 || | 2571 | if ((r = sshbuf_put_u32(m, rlen)) != 0 || |
2590 | (r = sshbuf_reserve(m, rlen, &p)) != 0) | 2572 | (r = sshbuf_reserve(m, rlen, &p)) != 0) |
2591 | return r; | 2573 | return r; |
2592 | if (cipher_get_keycontext(&state->receive_context, p) != (int)rlen) | 2574 | if (cipher_get_keycontext(state->receive_context, p) != (int)rlen) |
2593 | return SSH_ERR_INTERNAL_ERROR; | 2575 | return SSH_ERR_INTERNAL_ERROR; |
2594 | 2576 | if ((r = sshbuf_put_stringb(m, state->input)) != 0 || | |
2595 | if ((r = ssh_packet_get_compress_state(m, ssh)) != 0 || | ||
2596 | (r = sshbuf_put_stringb(m, state->input)) != 0 || | ||
2597 | (r = sshbuf_put_stringb(m, state->output)) != 0) | 2577 | (r = sshbuf_put_stringb(m, state->output)) != 0) |
2598 | return r; | 2578 | return r; |
2599 | 2579 | ||
@@ -2647,7 +2627,6 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) | |||
2647 | mac->key_len = maclen; | 2627 | mac->key_len = maclen; |
2648 | } | 2628 | } |
2649 | if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || | 2629 | if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || |
2650 | (r = sshbuf_get_u32(b, (u_int *)&comp->enabled)) != 0 || | ||
2651 | (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) | 2630 | (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) |
2652 | goto out; | 2631 | goto out; |
2653 | if (enc->name == NULL || | 2632 | if (enc->name == NULL || |
@@ -2735,11 +2714,11 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) | |||
2735 | return SSH_ERR_KEY_UNKNOWN_CIPHER; | 2714 | return SSH_ERR_KEY_UNKNOWN_CIPHER; |
2736 | ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen, | 2715 | ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen, |
2737 | (int)ssh1cipher); | 2716 | (int)ssh1cipher); |
2738 | if (cipher_get_keyiv_len(&state->send_context) != (int)slen || | 2717 | if (cipher_get_keyiv_len(state->send_context) != (int)slen || |
2739 | cipher_get_keyiv_len(&state->receive_context) != (int)rlen) | 2718 | cipher_get_keyiv_len(state->receive_context) != (int)rlen) |
2740 | return SSH_ERR_INVALID_FORMAT; | 2719 | return SSH_ERR_INVALID_FORMAT; |
2741 | if ((r = cipher_set_keyiv(&state->send_context, ivout)) != 0 || | 2720 | if ((r = cipher_set_keyiv(state->send_context, ivout)) != 0 || |
2742 | (r = cipher_set_keyiv(&state->receive_context, ivin)) != 0) | 2721 | (r = cipher_set_keyiv(state->receive_context, ivin)) != 0) |
2743 | return r; | 2722 | return r; |
2744 | } else { | 2723 | } else { |
2745 | if ((r = kex_from_blob(m, &ssh->kex)) != 0 || | 2724 | if ((r = kex_from_blob(m, &ssh->kex)) != 0 || |
@@ -2769,14 +2748,13 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) | |||
2769 | if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || | 2748 | if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || |
2770 | (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) | 2749 | (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) |
2771 | return r; | 2750 | return r; |
2772 | if (cipher_get_keycontext(&state->send_context, NULL) != (int)slen || | 2751 | if (cipher_get_keycontext(state->send_context, NULL) != (int)slen || |
2773 | cipher_get_keycontext(&state->receive_context, NULL) != (int)rlen) | 2752 | cipher_get_keycontext(state->receive_context, NULL) != (int)rlen) |
2774 | return SSH_ERR_INVALID_FORMAT; | 2753 | return SSH_ERR_INVALID_FORMAT; |
2775 | cipher_set_keycontext(&state->send_context, keyout); | 2754 | cipher_set_keycontext(state->send_context, keyout); |
2776 | cipher_set_keycontext(&state->receive_context, keyin); | 2755 | cipher_set_keycontext(state->receive_context, keyin); |
2777 | 2756 | ||
2778 | if ((r = ssh_packet_set_compress_state(ssh, m)) != 0 || | 2757 | if ((r = ssh_packet_set_postauth(ssh)) != 0) |
2779 | (r = ssh_packet_set_postauth(ssh)) != 0) | ||
2780 | return r; | 2758 | return r; |
2781 | 2759 | ||
2782 | sshbuf_reset(state->input); | 2760 | sshbuf_reset(state->input); |
@@ -2969,11 +2947,43 @@ sshpkt_start(struct ssh *ssh, u_char type) | |||
2969 | return sshbuf_put(ssh->state->outgoing_packet, buf, len); | 2947 | return sshbuf_put(ssh->state->outgoing_packet, buf, len); |
2970 | } | 2948 | } |
2971 | 2949 | ||
2950 | static int | ||
2951 | ssh_packet_send_mux(struct ssh *ssh) | ||
2952 | { | ||
2953 | struct session_state *state = ssh->state; | ||
2954 | u_char type, *cp; | ||
2955 | size_t len; | ||
2956 | int r; | ||
2957 | |||
2958 | if (ssh->kex) | ||
2959 | return SSH_ERR_INTERNAL_ERROR; | ||
2960 | len = sshbuf_len(state->outgoing_packet); | ||
2961 | if (len < 6) | ||
2962 | return SSH_ERR_INTERNAL_ERROR; | ||
2963 | cp = sshbuf_mutable_ptr(state->outgoing_packet); | ||
2964 | type = cp[5]; | ||
2965 | if (ssh_packet_log_type(type)) | ||
2966 | debug3("%s: type %u", __func__, type); | ||
2967 | /* drop everything, but the connection protocol */ | ||
2968 | if (type >= SSH2_MSG_CONNECTION_MIN && | ||
2969 | type <= SSH2_MSG_CONNECTION_MAX) { | ||
2970 | POKE_U32(cp, len - 4); | ||
2971 | if ((r = sshbuf_putb(state->output, | ||
2972 | state->outgoing_packet)) != 0) | ||
2973 | return r; | ||
2974 | /* sshbuf_dump(state->output, stderr); */ | ||
2975 | } | ||
2976 | sshbuf_reset(state->outgoing_packet); | ||
2977 | return 0; | ||
2978 | } | ||
2979 | |||
2972 | /* send it */ | 2980 | /* send it */ |
2973 | 2981 | ||
2974 | int | 2982 | int |
2975 | sshpkt_send(struct ssh *ssh) | 2983 | sshpkt_send(struct ssh *ssh) |
2976 | { | 2984 | { |
2985 | if (ssh->state && ssh->state->mux) | ||
2986 | return ssh_packet_send_mux(ssh); | ||
2977 | if (compat20) | 2987 | if (compat20) |
2978 | return ssh_packet_send2(ssh); | 2988 | return ssh_packet_send2(ssh); |
2979 | else | 2989 | else |