diff options
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 800 |
1 files changed, 206 insertions, 594 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.247 2017/03/11 13:07:35 markus Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.264 2017/09/12 06:32:07 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 |
@@ -68,9 +68,7 @@ | |||
68 | 68 | ||
69 | #include "xmalloc.h" | 69 | #include "xmalloc.h" |
70 | #include "crc32.h" | 70 | #include "crc32.h" |
71 | #include "deattack.h" | ||
72 | #include "compat.h" | 71 | #include "compat.h" |
73 | #include "ssh1.h" | ||
74 | #include "ssh2.h" | 72 | #include "ssh2.h" |
75 | #include "cipher.h" | 73 | #include "cipher.h" |
76 | #include "sshkey.h" | 74 | #include "sshkey.h" |
@@ -186,10 +184,6 @@ struct session_state { | |||
186 | u_int32_t rekey_interval; /* how often in seconds */ | 184 | u_int32_t rekey_interval; /* how often in seconds */ |
187 | time_t rekey_time; /* time of last rekeying */ | 185 | time_t rekey_time; /* time of last rekeying */ |
188 | 186 | ||
189 | /* Session key for protocol v1 */ | ||
190 | u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; | ||
191 | u_int ssh1_keylen; | ||
192 | |||
193 | /* roundup current message to extra_pad bytes */ | 187 | /* roundup current message to extra_pad bytes */ |
194 | u_char extra_pad; | 188 | u_char extra_pad; |
195 | 189 | ||
@@ -216,9 +210,6 @@ struct session_state { | |||
216 | /* One-off warning about weak ciphers */ | 210 | /* One-off warning about weak ciphers */ |
217 | int cipher_warning_done; | 211 | int cipher_warning_done; |
218 | 212 | ||
219 | /* SSH1 CRC compensation attack detector */ | ||
220 | struct deattack_ctx deattack; | ||
221 | |||
222 | /* Hook for fuzzing inbound packets */ | 213 | /* Hook for fuzzing inbound packets */ |
223 | ssh_packet_hook_fn *hook_in; | 214 | ssh_packet_hook_fn *hook_in; |
224 | void *hook_in_ctx; | 215 | void *hook_in_ctx; |
@@ -278,13 +269,12 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) | |||
278 | int | 269 | int |
279 | ssh_packet_is_rekeying(struct ssh *ssh) | 270 | ssh_packet_is_rekeying(struct ssh *ssh) |
280 | { | 271 | { |
281 | return compat20 && | 272 | return ssh->state->rekeying || |
282 | (ssh->state->rekeying || (ssh->kex != NULL && ssh->kex->done == 0)); | 273 | (ssh->kex != NULL && ssh->kex->done == 0); |
283 | } | 274 | } |
284 | 275 | ||
285 | /* | 276 | /* |
286 | * Sets the descriptors used for communication. Disables encryption until | 277 | * Sets the descriptors used for communication. |
287 | * packet_set_encryption_key is called. | ||
288 | */ | 278 | */ |
289 | struct ssh * | 279 | struct ssh * |
290 | ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) | 280 | ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) |
@@ -315,7 +305,6 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) | |||
315 | return NULL; | 305 | return NULL; |
316 | } | 306 | } |
317 | state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL; | 307 | state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL; |
318 | deattack_init(&state->deattack); | ||
319 | /* | 308 | /* |
320 | * Cache the IP address of the remote connection for use in error | 309 | * Cache the IP address of the remote connection for use in error |
321 | * messages that might be generated after the connection has closed. | 310 | * messages that might be generated after the connection has closed. |
@@ -570,8 +559,8 @@ ssh_local_port(struct ssh *ssh) | |||
570 | 559 | ||
571 | /* Closes the connection and clears and frees internal data structures. */ | 560 | /* Closes the connection and clears and frees internal data structures. */ |
572 | 561 | ||
573 | void | 562 | static void |
574 | ssh_packet_close(struct ssh *ssh) | 563 | ssh_packet_close_internal(struct ssh *ssh, int do_close) |
575 | { | 564 | { |
576 | struct session_state *state = ssh->state; | 565 | struct session_state *state = ssh->state; |
577 | u_int mode; | 566 | u_int mode; |
@@ -579,20 +568,25 @@ ssh_packet_close(struct ssh *ssh) | |||
579 | if (!state->initialized) | 568 | if (!state->initialized) |
580 | return; | 569 | return; |
581 | state->initialized = 0; | 570 | state->initialized = 0; |
582 | if (state->connection_in == state->connection_out) { | 571 | if (do_close) { |
583 | shutdown(state->connection_out, SHUT_RDWR); | 572 | if (state->connection_in == state->connection_out) { |
584 | close(state->connection_out); | 573 | close(state->connection_out); |
585 | } else { | 574 | } else { |
586 | close(state->connection_in); | 575 | close(state->connection_in); |
587 | close(state->connection_out); | 576 | close(state->connection_out); |
577 | } | ||
588 | } | 578 | } |
589 | sshbuf_free(state->input); | 579 | sshbuf_free(state->input); |
590 | sshbuf_free(state->output); | 580 | sshbuf_free(state->output); |
591 | sshbuf_free(state->outgoing_packet); | 581 | sshbuf_free(state->outgoing_packet); |
592 | sshbuf_free(state->incoming_packet); | 582 | sshbuf_free(state->incoming_packet); |
593 | for (mode = 0; mode < MODE_MAX; mode++) | 583 | for (mode = 0; mode < MODE_MAX; mode++) { |
594 | kex_free_newkeys(state->newkeys[mode]); | 584 | kex_free_newkeys(state->newkeys[mode]); /* current keys */ |
595 | if (state->compression_buffer) { | 585 | state->newkeys[mode] = NULL; |
586 | ssh_clear_newkeys(ssh, mode); /* next keys */ | ||
587 | } | ||
588 | /* comression state is in shared mem, so we can only release it once */ | ||
589 | if (do_close && state->compression_buffer) { | ||
596 | sshbuf_free(state->compression_buffer); | 590 | sshbuf_free(state->compression_buffer); |
597 | if (state->compression_out_started) { | 591 | if (state->compression_out_started) { |
598 | z_streamp stream = &state->compression_out_stream; | 592 | z_streamp stream = &state->compression_out_stream; |
@@ -620,10 +614,24 @@ ssh_packet_close(struct ssh *ssh) | |||
620 | cipher_free(state->send_context); | 614 | cipher_free(state->send_context); |
621 | cipher_free(state->receive_context); | 615 | cipher_free(state->receive_context); |
622 | state->send_context = state->receive_context = NULL; | 616 | state->send_context = state->receive_context = NULL; |
623 | free(ssh->remote_ipaddr); | 617 | if (do_close) { |
624 | ssh->remote_ipaddr = NULL; | 618 | free(ssh->remote_ipaddr); |
625 | free(ssh->state); | 619 | ssh->remote_ipaddr = NULL; |
626 | ssh->state = NULL; | 620 | free(ssh->state); |
621 | ssh->state = NULL; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | void | ||
626 | ssh_packet_close(struct ssh *ssh) | ||
627 | { | ||
628 | ssh_packet_close_internal(ssh, 1); | ||
629 | } | ||
630 | |||
631 | void | ||
632 | ssh_packet_clear_keys(struct ssh *ssh) | ||
633 | { | ||
634 | ssh_packet_close_internal(ssh, 0); | ||
627 | } | 635 | } |
628 | 636 | ||
629 | /* Sets remote side protocol flags. */ | 637 | /* Sets remote side protocol flags. */ |
@@ -698,7 +706,7 @@ ssh_packet_start_compression(struct ssh *ssh, int level) | |||
698 | { | 706 | { |
699 | int r; | 707 | int r; |
700 | 708 | ||
701 | if (ssh->state->packet_compression && !compat20) | 709 | if (ssh->state->packet_compression) |
702 | return SSH_ERR_INTERNAL_ERROR; | 710 | return SSH_ERR_INTERNAL_ERROR; |
703 | ssh->state->packet_compression = 1; | 711 | ssh->state->packet_compression = 1; |
704 | if ((r = ssh_packet_init_compression(ssh)) != 0 || | 712 | if ((r = ssh_packet_init_compression(ssh)) != 0 || |
@@ -802,136 +810,13 @@ uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) | |||
802 | /* NOTREACHED */ | 810 | /* NOTREACHED */ |
803 | } | 811 | } |
804 | 812 | ||
805 | /* | ||
806 | * Causes any further packets to be encrypted using the given key. The same | ||
807 | * key is used for both sending and reception. However, both directions are | ||
808 | * encrypted independently of each other. | ||
809 | */ | ||
810 | |||
811 | void | 813 | void |
812 | ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, int number) | 814 | ssh_clear_newkeys(struct ssh *ssh, int mode) |
813 | { | 815 | { |
814 | #ifndef WITH_SSH1 | 816 | if (ssh->kex && ssh->kex->newkeys[mode]) { |
815 | fatal("no SSH protocol 1 support"); | 817 | kex_free_newkeys(ssh->kex->newkeys[mode]); |
816 | #else /* WITH_SSH1 */ | 818 | ssh->kex->newkeys[mode] = NULL; |
817 | struct session_state *state = ssh->state; | ||
818 | const struct sshcipher *cipher = cipher_by_number(number); | ||
819 | int r; | ||
820 | const char *wmsg; | ||
821 | |||
822 | if (cipher == NULL) | ||
823 | fatal("%s: unknown cipher number %d", __func__, number); | ||
824 | if (keylen < 20) | ||
825 | fatal("%s: keylen too small: %d", __func__, keylen); | ||
826 | if (keylen > SSH_SESSION_KEY_LENGTH) | ||
827 | fatal("%s: keylen too big: %d", __func__, keylen); | ||
828 | memcpy(state->ssh1_key, key, keylen); | ||
829 | state->ssh1_keylen = keylen; | ||
830 | if ((r = cipher_init(&state->send_context, cipher, key, keylen, | ||
831 | NULL, 0, CIPHER_ENCRYPT)) != 0 || | ||
832 | (r = cipher_init(&state->receive_context, cipher, key, keylen, | ||
833 | NULL, 0, CIPHER_DECRYPT) != 0)) | ||
834 | fatal("%s: cipher_init failed: %s", __func__, ssh_err(r)); | ||
835 | if (!state->cipher_warning_done && | ||
836 | ((wmsg = cipher_warning_message(state->send_context)) != NULL || | ||
837 | (wmsg = cipher_warning_message(state->send_context)) != NULL)) { | ||
838 | error("Warning: %s", wmsg); | ||
839 | state->cipher_warning_done = 1; | ||
840 | } | 819 | } |
841 | #endif /* WITH_SSH1 */ | ||
842 | } | ||
843 | |||
844 | /* | ||
845 | * Finalizes and sends the packet. If the encryption key has been set, | ||
846 | * encrypts the packet before sending. | ||
847 | */ | ||
848 | |||
849 | int | ||
850 | ssh_packet_send1(struct ssh *ssh) | ||
851 | { | ||
852 | struct session_state *state = ssh->state; | ||
853 | u_char buf[8], *cp; | ||
854 | int r, padding, len; | ||
855 | u_int checksum; | ||
856 | |||
857 | /* | ||
858 | * If using packet compression, compress the payload of the outgoing | ||
859 | * packet. | ||
860 | */ | ||
861 | if (state->packet_compression) { | ||
862 | sshbuf_reset(state->compression_buffer); | ||
863 | /* Skip padding. */ | ||
864 | if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0) | ||
865 | goto out; | ||
866 | /* padding */ | ||
867 | if ((r = sshbuf_put(state->compression_buffer, | ||
868 | "\0\0\0\0\0\0\0\0", 8)) != 0) | ||
869 | goto out; | ||
870 | if ((r = compress_buffer(ssh, state->outgoing_packet, | ||
871 | state->compression_buffer)) != 0) | ||
872 | goto out; | ||
873 | sshbuf_reset(state->outgoing_packet); | ||
874 | if ((r = sshbuf_putb(state->outgoing_packet, | ||
875 | state->compression_buffer)) != 0) | ||
876 | goto out; | ||
877 | } | ||
878 | /* Compute packet length without padding (add checksum, remove padding). */ | ||
879 | len = sshbuf_len(state->outgoing_packet) + 4 - 8; | ||
880 | |||
881 | /* Insert padding. Initialized to zero in packet_start1() */ | ||
882 | padding = 8 - len % 8; | ||
883 | if (!cipher_ctx_is_plaintext(state->send_context)) { | ||
884 | cp = sshbuf_mutable_ptr(state->outgoing_packet); | ||
885 | if (cp == NULL) { | ||
886 | r = SSH_ERR_INTERNAL_ERROR; | ||
887 | goto out; | ||
888 | } | ||
889 | arc4random_buf(cp + 8 - padding, padding); | ||
890 | } | ||
891 | if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0) | ||
892 | goto out; | ||
893 | |||
894 | /* Add check bytes. */ | ||
895 | checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet), | ||
896 | sshbuf_len(state->outgoing_packet)); | ||
897 | POKE_U32(buf, checksum); | ||
898 | if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0) | ||
899 | goto out; | ||
900 | |||
901 | #ifdef PACKET_DEBUG | ||
902 | fprintf(stderr, "packet_send plain: "); | ||
903 | sshbuf_dump(state->outgoing_packet, stderr); | ||
904 | #endif | ||
905 | |||
906 | /* Append to output. */ | ||
907 | POKE_U32(buf, len); | ||
908 | if ((r = sshbuf_put(state->output, buf, 4)) != 0) | ||
909 | goto out; | ||
910 | if ((r = sshbuf_reserve(state->output, | ||
911 | sshbuf_len(state->outgoing_packet), &cp)) != 0) | ||
912 | goto out; | ||
913 | if ((r = cipher_crypt(state->send_context, 0, cp, | ||
914 | sshbuf_ptr(state->outgoing_packet), | ||
915 | sshbuf_len(state->outgoing_packet), 0, 0)) != 0) | ||
916 | goto out; | ||
917 | |||
918 | #ifdef PACKET_DEBUG | ||
919 | fprintf(stderr, "encrypted: "); | ||
920 | sshbuf_dump(state->output, stderr); | ||
921 | #endif | ||
922 | state->p_send.packets++; | ||
923 | state->p_send.bytes += len + | ||
924 | sshbuf_len(state->outgoing_packet); | ||
925 | sshbuf_reset(state->outgoing_packet); | ||
926 | |||
927 | /* | ||
928 | * Note that the packet is now only buffered in output. It won't be | ||
929 | * actually sent until ssh_packet_write_wait or ssh_packet_write_poll | ||
930 | * is called. | ||
931 | */ | ||
932 | r = 0; | ||
933 | out: | ||
934 | return r; | ||
935 | } | 820 | } |
936 | 821 | ||
937 | int | 822 | int |
@@ -944,45 +829,33 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
944 | struct sshcipher_ctx **ccp; | 829 | struct sshcipher_ctx **ccp; |
945 | struct packet_state *ps; | 830 | struct packet_state *ps; |
946 | u_int64_t *max_blocks; | 831 | u_int64_t *max_blocks; |
947 | const char *wmsg, *dir; | 832 | const char *wmsg; |
948 | int r, crypt_type; | 833 | int r, crypt_type; |
949 | 834 | ||
950 | debug2("set_newkeys: mode %d", mode); | 835 | debug2("set_newkeys: mode %d", mode); |
951 | 836 | ||
952 | if (mode == MODE_OUT) { | 837 | if (mode == MODE_OUT) { |
953 | dir = "output"; | ||
954 | ccp = &state->send_context; | 838 | ccp = &state->send_context; |
955 | crypt_type = CIPHER_ENCRYPT; | 839 | crypt_type = CIPHER_ENCRYPT; |
956 | ps = &state->p_send; | 840 | ps = &state->p_send; |
957 | max_blocks = &state->max_blocks_out; | 841 | max_blocks = &state->max_blocks_out; |
958 | } else { | 842 | } else { |
959 | dir = "input"; | ||
960 | ccp = &state->receive_context; | 843 | ccp = &state->receive_context; |
961 | crypt_type = CIPHER_DECRYPT; | 844 | crypt_type = CIPHER_DECRYPT; |
962 | ps = &state->p_read; | 845 | ps = &state->p_read; |
963 | max_blocks = &state->max_blocks_in; | 846 | max_blocks = &state->max_blocks_in; |
964 | } | 847 | } |
965 | if (state->newkeys[mode] != NULL) { | 848 | if (state->newkeys[mode] != NULL) { |
966 | debug("%s: rekeying after %llu %s blocks" | 849 | debug("set_newkeys: rekeying, input %llu bytes %llu blocks, " |
967 | " (%llu bytes total)", __func__, | 850 | "output %llu bytes %llu blocks", |
968 | (unsigned long long)ps->blocks, dir, | 851 | (unsigned long long)state->p_read.bytes, |
969 | (unsigned long long)ps->bytes); | 852 | (unsigned long long)state->p_read.blocks, |
853 | (unsigned long long)state->p_send.bytes, | ||
854 | (unsigned long long)state->p_send.blocks); | ||
970 | cipher_free(*ccp); | 855 | cipher_free(*ccp); |
971 | *ccp = NULL; | 856 | *ccp = NULL; |
972 | enc = &state->newkeys[mode]->enc; | 857 | kex_free_newkeys(state->newkeys[mode]); |
973 | mac = &state->newkeys[mode]->mac; | 858 | state->newkeys[mode] = NULL; |
974 | comp = &state->newkeys[mode]->comp; | ||
975 | mac_clear(mac); | ||
976 | explicit_bzero(enc->iv, enc->iv_len); | ||
977 | explicit_bzero(enc->key, enc->key_len); | ||
978 | explicit_bzero(mac->key, mac->key_len); | ||
979 | free(enc->name); | ||
980 | free(enc->iv); | ||
981 | free(enc->key); | ||
982 | free(mac->name); | ||
983 | free(mac->key); | ||
984 | free(comp->name); | ||
985 | free(state->newkeys[mode]); | ||
986 | } | 859 | } |
987 | /* note that both bytes and the seqnr are not reset */ | 860 | /* note that both bytes and the seqnr are not reset */ |
988 | ps->packets = ps->blocks = 0; | 861 | ps->packets = ps->blocks = 0; |
@@ -1027,7 +900,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
1027 | } | 900 | } |
1028 | /* | 901 | /* |
1029 | * The 2^(blocksize*2) limit is too expensive for 3DES, | 902 | * The 2^(blocksize*2) limit is too expensive for 3DES, |
1030 | * blowfish, etc, so enforce a 1GB limit for small blocksizes. | 903 | * so enforce a 1GB limit for small blocksizes. |
904 | * See RFC4344 section 3.2. | ||
1031 | */ | 905 | */ |
1032 | if (enc->block_size >= 16) | 906 | if (enc->block_size >= 16) |
1033 | *max_blocks = (u_int64_t)1 << (enc->block_size*2); | 907 | *max_blocks = (u_int64_t)1 << (enc->block_size*2); |
@@ -1071,7 +945,10 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) | |||
1071 | (int64_t)state->rekey_time + state->rekey_interval <= monotime()) | 945 | (int64_t)state->rekey_time + state->rekey_interval <= monotime()) |
1072 | return 1; | 946 | return 1; |
1073 | 947 | ||
1074 | /* Always rekey when MAX_PACKETS sent in either direction */ | 948 | /* |
949 | * Always rekey when MAX_PACKETS sent in either direction | ||
950 | * As per RFC4344 section 3.1 we do this after 2^31 packets. | ||
951 | */ | ||
1075 | if (state->p_send.packets > MAX_PACKETS || | 952 | if (state->p_send.packets > MAX_PACKETS || |
1076 | state->p_read.packets > MAX_PACKETS) | 953 | state->p_read.packets > MAX_PACKETS) |
1077 | return 1; | 954 | return 1; |
@@ -1424,13 +1301,6 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1424 | r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); | 1301 | r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); |
1425 | if (r != 0) | 1302 | if (r != 0) |
1426 | break; | 1303 | break; |
1427 | if (!compat20 && ( | ||
1428 | *typep == SSH_SMSG_SUCCESS | ||
1429 | || *typep == SSH_SMSG_FAILURE | ||
1430 | || *typep == SSH_CMSG_EOF | ||
1431 | || *typep == SSH_CMSG_EXIT_CONFIRMATION)) | ||
1432 | if ((r = sshpkt_get_end(ssh)) != 0) | ||
1433 | break; | ||
1434 | /* If we got a packet, return it. */ | 1304 | /* If we got a packet, return it. */ |
1435 | if (*typep != SSH_MSG_NONE) | 1305 | if (*typep != SSH_MSG_NONE) |
1436 | break; | 1306 | break; |
@@ -1524,153 +1394,6 @@ ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) | |||
1524 | return 0; | 1394 | return 0; |
1525 | } | 1395 | } |
1526 | 1396 | ||
1527 | /* Checks if a full packet is available in the data received so far via | ||
1528 | * packet_process_incoming. If so, reads the packet; otherwise returns | ||
1529 | * SSH_MSG_NONE. This does not wait for data from the connection. | ||
1530 | * | ||
1531 | * SSH_MSG_DISCONNECT is handled specially here. Also, | ||
1532 | * SSH_MSG_IGNORE messages are skipped by this function and are never returned | ||
1533 | * to higher levels. | ||
1534 | */ | ||
1535 | |||
1536 | int | ||
1537 | ssh_packet_read_poll1(struct ssh *ssh, u_char *typep) | ||
1538 | { | ||
1539 | struct session_state *state = ssh->state; | ||
1540 | u_int len, padded_len; | ||
1541 | const char *emsg; | ||
1542 | const u_char *cp; | ||
1543 | u_char *p; | ||
1544 | u_int checksum, stored_checksum; | ||
1545 | int r; | ||
1546 | |||
1547 | *typep = SSH_MSG_NONE; | ||
1548 | |||
1549 | /* Check if input size is less than minimum packet size. */ | ||
1550 | if (sshbuf_len(state->input) < 4 + 8) | ||
1551 | return 0; | ||
1552 | /* Get length of incoming packet. */ | ||
1553 | len = PEEK_U32(sshbuf_ptr(state->input)); | ||
1554 | if (len < 1 + 2 + 2 || len > 256 * 1024) { | ||
1555 | if ((r = sshpkt_disconnect(ssh, "Bad packet length %u", | ||
1556 | len)) != 0) | ||
1557 | return r; | ||
1558 | return SSH_ERR_CONN_CORRUPT; | ||
1559 | } | ||
1560 | padded_len = (len + 8) & ~7; | ||
1561 | |||
1562 | /* Check if the packet has been entirely received. */ | ||
1563 | if (sshbuf_len(state->input) < 4 + padded_len) | ||
1564 | return 0; | ||
1565 | |||
1566 | /* The entire packet is in buffer. */ | ||
1567 | |||
1568 | /* Consume packet length. */ | ||
1569 | if ((r = sshbuf_consume(state->input, 4)) != 0) | ||
1570 | goto out; | ||
1571 | |||
1572 | /* | ||
1573 | * Cryptographic attack detector for ssh | ||
1574 | * (C)1998 CORE-SDI, Buenos Aires Argentina | ||
1575 | * Ariel Futoransky(futo@core-sdi.com) | ||
1576 | */ | ||
1577 | if (!cipher_ctx_is_plaintext(state->receive_context)) { | ||
1578 | emsg = NULL; | ||
1579 | switch (detect_attack(&state->deattack, | ||
1580 | sshbuf_ptr(state->input), padded_len)) { | ||
1581 | case DEATTACK_OK: | ||
1582 | break; | ||
1583 | case DEATTACK_DETECTED: | ||
1584 | emsg = "crc32 compensation attack detected"; | ||
1585 | break; | ||
1586 | case DEATTACK_DOS_DETECTED: | ||
1587 | emsg = "deattack denial of service detected"; | ||
1588 | break; | ||
1589 | default: | ||
1590 | emsg = "deattack error"; | ||
1591 | break; | ||
1592 | } | ||
1593 | if (emsg != NULL) { | ||
1594 | error("%s", emsg); | ||
1595 | if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 || | ||
1596 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
1597 | return r; | ||
1598 | return SSH_ERR_CONN_CORRUPT; | ||
1599 | } | ||
1600 | } | ||
1601 | |||
1602 | /* Decrypt data to incoming_packet. */ | ||
1603 | sshbuf_reset(state->incoming_packet); | ||
1604 | if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0) | ||
1605 | goto out; | ||
1606 | if ((r = cipher_crypt(state->receive_context, 0, p, | ||
1607 | sshbuf_ptr(state->input), padded_len, 0, 0)) != 0) | ||
1608 | goto out; | ||
1609 | |||
1610 | if ((r = sshbuf_consume(state->input, padded_len)) != 0) | ||
1611 | goto out; | ||
1612 | |||
1613 | #ifdef PACKET_DEBUG | ||
1614 | fprintf(stderr, "read_poll plain: "); | ||
1615 | sshbuf_dump(state->incoming_packet, stderr); | ||
1616 | #endif | ||
1617 | |||
1618 | /* Compute packet checksum. */ | ||
1619 | checksum = ssh_crc32(sshbuf_ptr(state->incoming_packet), | ||
1620 | sshbuf_len(state->incoming_packet) - 4); | ||
1621 | |||
1622 | /* Skip padding. */ | ||
1623 | if ((r = sshbuf_consume(state->incoming_packet, 8 - len % 8)) != 0) | ||
1624 | goto out; | ||
1625 | |||
1626 | /* Test check bytes. */ | ||
1627 | if (len != sshbuf_len(state->incoming_packet)) { | ||
1628 | error("%s: len %d != sshbuf_len %zd", __func__, | ||
1629 | len, sshbuf_len(state->incoming_packet)); | ||
1630 | if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 || | ||
1631 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
1632 | return r; | ||
1633 | return SSH_ERR_CONN_CORRUPT; | ||
1634 | } | ||
1635 | |||
1636 | cp = sshbuf_ptr(state->incoming_packet) + len - 4; | ||
1637 | stored_checksum = PEEK_U32(cp); | ||
1638 | if (checksum != stored_checksum) { | ||
1639 | error("Corrupted check bytes on input"); | ||
1640 | if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 || | ||
1641 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
1642 | return r; | ||
1643 | return SSH_ERR_CONN_CORRUPT; | ||
1644 | } | ||
1645 | if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0) | ||
1646 | goto out; | ||
1647 | |||
1648 | if (state->packet_compression) { | ||
1649 | sshbuf_reset(state->compression_buffer); | ||
1650 | if ((r = uncompress_buffer(ssh, state->incoming_packet, | ||
1651 | state->compression_buffer)) != 0) | ||
1652 | goto out; | ||
1653 | sshbuf_reset(state->incoming_packet); | ||
1654 | if ((r = sshbuf_putb(state->incoming_packet, | ||
1655 | state->compression_buffer)) != 0) | ||
1656 | goto out; | ||
1657 | } | ||
1658 | state->p_read.packets++; | ||
1659 | state->p_read.bytes += padded_len + 4; | ||
1660 | if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) | ||
1661 | goto out; | ||
1662 | if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) { | ||
1663 | error("Invalid ssh1 packet type: %d", *typep); | ||
1664 | if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 || | ||
1665 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
1666 | return r; | ||
1667 | return SSH_ERR_PROTOCOL_ERROR; | ||
1668 | } | ||
1669 | r = 0; | ||
1670 | out: | ||
1671 | return r; | ||
1672 | } | ||
1673 | |||
1674 | static int | 1397 | static int |
1675 | ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | 1398 | ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
1676 | { | 1399 | { |
@@ -1951,75 +1674,48 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1951 | 1674 | ||
1952 | for (;;) { | 1675 | for (;;) { |
1953 | msg = NULL; | 1676 | msg = NULL; |
1954 | if (compat20) { | 1677 | r = ssh_packet_read_poll2(ssh, typep, seqnr_p); |
1955 | r = ssh_packet_read_poll2(ssh, typep, seqnr_p); | 1678 | if (r != 0) |
1956 | if (r != 0) | 1679 | return r; |
1957 | return r; | 1680 | if (*typep) { |
1958 | if (*typep) { | 1681 | state->keep_alive_timeouts = 0; |
1959 | state->keep_alive_timeouts = 0; | 1682 | DBG(debug("received packet type %d", *typep)); |
1960 | DBG(debug("received packet type %d", *typep)); | 1683 | } |
1961 | } | 1684 | switch (*typep) { |
1962 | switch (*typep) { | 1685 | case SSH2_MSG_IGNORE: |
1963 | case SSH2_MSG_IGNORE: | 1686 | debug3("Received SSH2_MSG_IGNORE"); |
1964 | debug3("Received SSH2_MSG_IGNORE"); | 1687 | break; |
1965 | break; | 1688 | case SSH2_MSG_DEBUG: |
1966 | case SSH2_MSG_DEBUG: | 1689 | if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || |
1967 | if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || | 1690 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || |
1968 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || | 1691 | (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { |
1969 | (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { | ||
1970 | free(msg); | ||
1971 | return r; | ||
1972 | } | ||
1973 | debug("Remote: %.900s", msg); | ||
1974 | free(msg); | ||
1975 | break; | ||
1976 | case SSH2_MSG_DISCONNECT: | ||
1977 | if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || | ||
1978 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) | ||
1979 | return r; | ||
1980 | /* Ignore normal client exit notifications */ | ||
1981 | do_log2(ssh->state->server_side && | ||
1982 | reason == SSH2_DISCONNECT_BY_APPLICATION ? | ||
1983 | SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, | ||
1984 | "Received disconnect from %s port %d:" | ||
1985 | "%u: %.400s", ssh_remote_ipaddr(ssh), | ||
1986 | ssh_remote_port(ssh), reason, msg); | ||
1987 | free(msg); | ||
1988 | return SSH_ERR_DISCONNECTED; | ||
1989 | case SSH2_MSG_UNIMPLEMENTED: | ||
1990 | if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) | ||
1991 | return r; | ||
1992 | debug("Received SSH2_MSG_UNIMPLEMENTED for %u", | ||
1993 | seqnr); | ||
1994 | break; | ||
1995 | default: | ||
1996 | return 0; | ||
1997 | } | ||
1998 | } else { | ||
1999 | r = ssh_packet_read_poll1(ssh, typep); | ||
2000 | switch (*typep) { | ||
2001 | case SSH_MSG_NONE: | ||
2002 | return SSH_MSG_NONE; | ||
2003 | case SSH_MSG_IGNORE: | ||
2004 | break; | ||
2005 | case SSH_MSG_DEBUG: | ||
2006 | if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) | ||
2007 | return r; | ||
2008 | debug("Remote: %.900s", msg); | ||
2009 | free(msg); | ||
2010 | break; | ||
2011 | case SSH_MSG_DISCONNECT: | ||
2012 | if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) | ||
2013 | return r; | ||
2014 | error("Received disconnect from %s port %d: " | ||
2015 | "%.400s", ssh_remote_ipaddr(ssh), | ||
2016 | ssh_remote_port(ssh), msg); | ||
2017 | free(msg); | 1692 | free(msg); |
2018 | return SSH_ERR_DISCONNECTED; | 1693 | return r; |
2019 | default: | ||
2020 | DBG(debug("received packet type %d", *typep)); | ||
2021 | return 0; | ||
2022 | } | 1694 | } |
1695 | debug("Remote: %.900s", msg); | ||
1696 | free(msg); | ||
1697 | break; | ||
1698 | case SSH2_MSG_DISCONNECT: | ||
1699 | if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || | ||
1700 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) | ||
1701 | return r; | ||
1702 | /* Ignore normal client exit notifications */ | ||
1703 | do_log2(ssh->state->server_side && | ||
1704 | reason == SSH2_DISCONNECT_BY_APPLICATION ? | ||
1705 | SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, | ||
1706 | "Received disconnect from %s port %d:" | ||
1707 | "%u: %.400s", ssh_remote_ipaddr(ssh), | ||
1708 | ssh_remote_port(ssh), reason, msg); | ||
1709 | free(msg); | ||
1710 | return SSH_ERR_DISCONNECTED; | ||
1711 | case SSH2_MSG_UNIMPLEMENTED: | ||
1712 | if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) | ||
1713 | return r; | ||
1714 | debug("Received SSH2_MSG_UNIMPLEMENTED for %u", | ||
1715 | seqnr); | ||
1716 | break; | ||
1717 | default: | ||
1718 | return 0; | ||
2023 | } | 1719 | } |
2024 | } | 1720 | } |
2025 | } | 1721 | } |
@@ -2071,27 +1767,19 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...) | |||
2071 | va_list args; | 1767 | va_list args; |
2072 | int r; | 1768 | int r; |
2073 | 1769 | ||
2074 | if (compat20 && (ssh->compat & SSH_BUG_DEBUG)) | 1770 | if ((ssh->compat & SSH_BUG_DEBUG)) |
2075 | return; | 1771 | return; |
2076 | 1772 | ||
2077 | va_start(args, fmt); | 1773 | va_start(args, fmt); |
2078 | vsnprintf(buf, sizeof(buf), fmt, args); | 1774 | vsnprintf(buf, sizeof(buf), fmt, args); |
2079 | va_end(args); | 1775 | va_end(args); |
2080 | 1776 | ||
2081 | if (compat20) { | 1777 | if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || |
2082 | if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || | 1778 | (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ |
2083 | (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ | 1779 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || |
2084 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | 1780 | (r = sshpkt_put_cstring(ssh, "")) != 0 || |
2085 | (r = sshpkt_put_cstring(ssh, "")) != 0 || | 1781 | (r = sshpkt_send(ssh)) != 0 || |
2086 | (r = sshpkt_send(ssh)) != 0) | 1782 | (r = ssh_packet_write_wait(ssh)) != 0) |
2087 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2088 | } else { | ||
2089 | if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 || | ||
2090 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | ||
2091 | (r = sshpkt_send(ssh)) != 0) | ||
2092 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2093 | } | ||
2094 | if ((r = ssh_packet_write_wait(ssh)) != 0) | ||
2095 | fatal("%s: %s", __func__, ssh_err(r)); | 1783 | fatal("%s: %s", __func__, ssh_err(r)); |
2096 | } | 1784 | } |
2097 | 1785 | ||
@@ -2116,15 +1804,20 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r) | |||
2116 | 1804 | ||
2117 | switch (r) { | 1805 | switch (r) { |
2118 | case SSH_ERR_CONN_CLOSED: | 1806 | case SSH_ERR_CONN_CLOSED: |
1807 | ssh_packet_clear_keys(ssh); | ||
2119 | logdie("Connection closed by %s", remote_id); | 1808 | logdie("Connection closed by %s", remote_id); |
2120 | case SSH_ERR_CONN_TIMEOUT: | 1809 | case SSH_ERR_CONN_TIMEOUT: |
1810 | ssh_packet_clear_keys(ssh); | ||
2121 | logdie("Connection %s %s timed out", | 1811 | logdie("Connection %s %s timed out", |
2122 | ssh->state->server_side ? "from" : "to", remote_id); | 1812 | ssh->state->server_side ? "from" : "to", remote_id); |
2123 | case SSH_ERR_DISCONNECTED: | 1813 | case SSH_ERR_DISCONNECTED: |
1814 | ssh_packet_clear_keys(ssh); | ||
2124 | logdie("Disconnected from %s", remote_id); | 1815 | logdie("Disconnected from %s", remote_id); |
2125 | case SSH_ERR_SYSTEM_ERROR: | 1816 | case SSH_ERR_SYSTEM_ERROR: |
2126 | if (errno == ECONNRESET) | 1817 | if (errno == ECONNRESET) { |
1818 | ssh_packet_clear_keys(ssh); | ||
2127 | logdie("Connection reset by %s", remote_id); | 1819 | logdie("Connection reset by %s", remote_id); |
1820 | } | ||
2128 | /* FALLTHROUGH */ | 1821 | /* FALLTHROUGH */ |
2129 | case SSH_ERR_NO_CIPHER_ALG_MATCH: | 1822 | case SSH_ERR_NO_CIPHER_ALG_MATCH: |
2130 | case SSH_ERR_NO_MAC_ALG_MATCH: | 1823 | case SSH_ERR_NO_MAC_ALG_MATCH: |
@@ -2132,12 +1825,14 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r) | |||
2132 | case SSH_ERR_NO_KEX_ALG_MATCH: | 1825 | case SSH_ERR_NO_KEX_ALG_MATCH: |
2133 | case SSH_ERR_NO_HOSTKEY_ALG_MATCH: | 1826 | case SSH_ERR_NO_HOSTKEY_ALG_MATCH: |
2134 | if (ssh && ssh->kex && ssh->kex->failed_choice) { | 1827 | if (ssh && ssh->kex && ssh->kex->failed_choice) { |
1828 | ssh_packet_clear_keys(ssh); | ||
2135 | logdie("Unable to negotiate with %s: %s. " | 1829 | logdie("Unable to negotiate with %s: %s. " |
2136 | "Their offer: %s", remote_id, ssh_err(r), | 1830 | "Their offer: %s", remote_id, ssh_err(r), |
2137 | ssh->kex->failed_choice); | 1831 | ssh->kex->failed_choice); |
2138 | } | 1832 | } |
2139 | /* FALLTHROUGH */ | 1833 | /* FALLTHROUGH */ |
2140 | default: | 1834 | default: |
1835 | ssh_packet_clear_keys(ssh); | ||
2141 | logdie("%s%sConnection %s %s: %s", | 1836 | logdie("%s%sConnection %s %s: %s", |
2142 | tag != NULL ? tag : "", tag != NULL ? ": " : "", | 1837 | tag != NULL ? tag : "", tag != NULL ? ": " : "", |
2143 | ssh->state->server_side ? "from" : "to", | 1838 | ssh->state->server_side ? "from" : "to", |
@@ -2302,7 +1997,7 @@ void | |||
2302 | ssh_packet_set_tos(struct ssh *ssh, int tos) | 1997 | ssh_packet_set_tos(struct ssh *ssh, int tos) |
2303 | { | 1998 | { |
2304 | #ifndef IP_TOS_IS_BROKEN | 1999 | #ifndef IP_TOS_IS_BROKEN |
2305 | if (!ssh_packet_connection_is_on_socket(ssh)) | 2000 | if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX) |
2306 | return; | 2001 | return; |
2307 | switch (ssh_packet_connection_af(ssh)) { | 2002 | switch (ssh_packet_connection_af(ssh)) { |
2308 | # ifdef IP_TOS | 2003 | # ifdef IP_TOS |
@@ -2395,36 +2090,6 @@ ssh_packet_get_maxsize(struct ssh *ssh) | |||
2395 | return ssh->state->max_packet_size; | 2090 | return ssh->state->max_packet_size; |
2396 | } | 2091 | } |
2397 | 2092 | ||
2398 | /* | ||
2399 | * 9.2. Ignored Data Message | ||
2400 | * | ||
2401 | * byte SSH_MSG_IGNORE | ||
2402 | * string data | ||
2403 | * | ||
2404 | * All implementations MUST understand (and ignore) this message at any | ||
2405 | * time (after receiving the protocol version). No implementation is | ||
2406 | * required to send them. This message can be used as an additional | ||
2407 | * protection measure against advanced traffic analysis techniques. | ||
2408 | */ | ||
2409 | void | ||
2410 | ssh_packet_send_ignore(struct ssh *ssh, int nbytes) | ||
2411 | { | ||
2412 | u_int32_t rnd = 0; | ||
2413 | int r, i; | ||
2414 | |||
2415 | if ((r = sshpkt_start(ssh, compat20 ? | ||
2416 | SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 || | ||
2417 | (r = sshpkt_put_u32(ssh, nbytes)) != 0) | ||
2418 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2419 | for (i = 0; i < nbytes; i++) { | ||
2420 | if (i % 4 == 0) | ||
2421 | rnd = arc4random(); | ||
2422 | if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) | ||
2423 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2424 | rnd >>= 8; | ||
2425 | } | ||
2426 | } | ||
2427 | |||
2428 | void | 2093 | void |
2429 | ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds) | 2094 | ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds) |
2430 | { | 2095 | { |
@@ -2528,9 +2193,7 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode) | |||
2528 | return r; | 2193 | return r; |
2529 | if ((b = sshbuf_new()) == NULL) | 2194 | if ((b = sshbuf_new()) == NULL) |
2530 | return SSH_ERR_ALLOC_FAIL; | 2195 | return SSH_ERR_ALLOC_FAIL; |
2531 | /* The cipher struct is constant and shared, you export pointer */ | ||
2532 | if ((r = sshbuf_put_cstring(b, enc->name)) != 0 || | 2196 | if ((r = sshbuf_put_cstring(b, enc->name)) != 0 || |
2533 | (r = sshbuf_put(b, &enc->cipher, sizeof(enc->cipher))) != 0 || | ||
2534 | (r = sshbuf_put_u32(b, enc->enabled)) != 0 || | 2197 | (r = sshbuf_put_u32(b, enc->enabled)) != 0 || |
2535 | (r = sshbuf_put_u32(b, enc->block_size)) != 0 || | 2198 | (r = sshbuf_put_u32(b, enc->block_size)) != 0 || |
2536 | (r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 || | 2199 | (r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 || |
@@ -2556,54 +2219,22 @@ int | |||
2556 | ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) | 2219 | ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) |
2557 | { | 2220 | { |
2558 | struct session_state *state = ssh->state; | 2221 | struct session_state *state = ssh->state; |
2559 | u_char *p; | 2222 | int r; |
2560 | size_t slen, rlen; | ||
2561 | int r, ssh1cipher; | ||
2562 | |||
2563 | if (!compat20) { | ||
2564 | ssh1cipher = cipher_ctx_get_number(state->receive_context); | ||
2565 | slen = cipher_get_keyiv_len(state->send_context); | ||
2566 | rlen = cipher_get_keyiv_len(state->receive_context); | ||
2567 | if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 || | ||
2568 | (r = sshbuf_put_u32(m, ssh1cipher)) != 0 || | ||
2569 | (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 || | ||
2570 | (r = sshbuf_put_u32(m, slen)) != 0 || | ||
2571 | (r = sshbuf_reserve(m, slen, &p)) != 0 || | ||
2572 | (r = cipher_get_keyiv(state->send_context, p, slen)) != 0 || | ||
2573 | (r = sshbuf_put_u32(m, rlen)) != 0 || | ||
2574 | (r = sshbuf_reserve(m, rlen, &p)) != 0 || | ||
2575 | (r = cipher_get_keyiv(state->receive_context, p, rlen)) != 0) | ||
2576 | return r; | ||
2577 | } else { | ||
2578 | if ((r = kex_to_blob(m, ssh->kex)) != 0 || | ||
2579 | (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || | ||
2580 | (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || | ||
2581 | (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 || | ||
2582 | (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || | ||
2583 | (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || | ||
2584 | (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || | ||
2585 | (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || | ||
2586 | (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || | ||
2587 | (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || | ||
2588 | (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || | ||
2589 | (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || | ||
2590 | (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0) | ||
2591 | return r; | ||
2592 | } | ||
2593 | 2223 | ||
2594 | slen = cipher_get_keycontext(state->send_context, NULL); | 2224 | if ((r = kex_to_blob(m, ssh->kex)) != 0 || |
2595 | rlen = cipher_get_keycontext(state->receive_context, NULL); | 2225 | (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || |
2596 | if ((r = sshbuf_put_u32(m, slen)) != 0 || | 2226 | (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || |
2597 | (r = sshbuf_reserve(m, slen, &p)) != 0) | 2227 | (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 || |
2598 | return r; | 2228 | (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || |
2599 | if (cipher_get_keycontext(state->send_context, p) != (int)slen) | 2229 | (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || |
2600 | return SSH_ERR_INTERNAL_ERROR; | 2230 | (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || |
2601 | if ((r = sshbuf_put_u32(m, rlen)) != 0 || | 2231 | (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || |
2602 | (r = sshbuf_reserve(m, rlen, &p)) != 0) | 2232 | (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || |
2603 | return r; | 2233 | (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || |
2604 | if (cipher_get_keycontext(state->receive_context, p) != (int)rlen) | 2234 | (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || |
2605 | return SSH_ERR_INTERNAL_ERROR; | 2235 | (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || |
2606 | if ((r = sshbuf_put_stringb(m, state->input)) != 0 || | 2236 | (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0 || |
2237 | (r = sshbuf_put_stringb(m, state->input)) != 0 || | ||
2607 | (r = sshbuf_put_stringb(m, state->output)) != 0) | 2238 | (r = sshbuf_put_stringb(m, state->output)) != 0) |
2608 | return r; | 2239 | return r; |
2609 | 2240 | ||
@@ -2636,12 +2267,15 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) | |||
2636 | comp = &newkey->comp; | 2267 | comp = &newkey->comp; |
2637 | 2268 | ||
2638 | if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 || | 2269 | if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 || |
2639 | (r = sshbuf_get(b, &enc->cipher, sizeof(enc->cipher))) != 0 || | ||
2640 | (r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 || | 2270 | (r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 || |
2641 | (r = sshbuf_get_u32(b, &enc->block_size)) != 0 || | 2271 | (r = sshbuf_get_u32(b, &enc->block_size)) != 0 || |
2642 | (r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 || | 2272 | (r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 || |
2643 | (r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0) | 2273 | (r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0) |
2644 | goto out; | 2274 | goto out; |
2275 | if ((enc->cipher = cipher_by_name(enc->name)) == NULL) { | ||
2276 | r = SSH_ERR_INVALID_FORMAT; | ||
2277 | goto out; | ||
2278 | } | ||
2645 | if (cipher_authlen(enc->cipher) == 0) { | 2279 | if (cipher_authlen(enc->cipher) == 0) { |
2646 | if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0) | 2280 | if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0) |
2647 | goto out; | 2281 | goto out; |
@@ -2659,11 +2293,6 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) | |||
2659 | if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || | 2293 | if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || |
2660 | (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) | 2294 | (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) |
2661 | goto out; | 2295 | goto out; |
2662 | if (enc->name == NULL || | ||
2663 | cipher_by_name(enc->name) != enc->cipher) { | ||
2664 | r = SSH_ERR_INVALID_FORMAT; | ||
2665 | goto out; | ||
2666 | } | ||
2667 | if (sshbuf_len(b) != 0) { | 2296 | if (sshbuf_len(b) != 0) { |
2668 | r = SSH_ERR_INVALID_FORMAT; | 2297 | r = SSH_ERR_INVALID_FORMAT; |
2669 | goto out; | 2298 | goto out; |
@@ -2728,61 +2357,33 @@ int | |||
2728 | ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) | 2357 | ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) |
2729 | { | 2358 | { |
2730 | struct session_state *state = ssh->state; | 2359 | struct session_state *state = ssh->state; |
2731 | const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output; | 2360 | const u_char *input, *output; |
2732 | size_t ssh1keylen, rlen, slen, ilen, olen; | 2361 | size_t ilen, olen; |
2733 | int r; | 2362 | int r; |
2734 | u_int ssh1cipher = 0; | 2363 | |
2735 | 2364 | if ((r = kex_from_blob(m, &ssh->kex)) != 0 || | |
2736 | if (!compat20) { | 2365 | (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || |
2737 | if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 || | 2366 | (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || |
2738 | (r = sshbuf_get_u32(m, &ssh1cipher)) != 0 || | 2367 | (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 || |
2739 | (r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 || | 2368 | (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || |
2740 | (r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 || | 2369 | (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || |
2741 | (r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0) | 2370 | (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || |
2742 | return r; | 2371 | (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || |
2743 | if (ssh1cipher > INT_MAX) | 2372 | (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || |
2744 | return SSH_ERR_KEY_UNKNOWN_CIPHER; | 2373 | (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || |
2745 | ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen, | 2374 | (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || |
2746 | (int)ssh1cipher); | 2375 | (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || |
2747 | if (cipher_get_keyiv_len(state->send_context) != (int)slen || | 2376 | (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) |
2748 | cipher_get_keyiv_len(state->receive_context) != (int)rlen) | 2377 | return r; |
2749 | return SSH_ERR_INVALID_FORMAT; | 2378 | /* |
2750 | if ((r = cipher_set_keyiv(state->send_context, ivout)) != 0 || | 2379 | * We set the time here so that in post-auth privsep slave we |
2751 | (r = cipher_set_keyiv(state->receive_context, ivin)) != 0) | 2380 | * count from the completion of the authentication. |
2752 | return r; | 2381 | */ |
2753 | } else { | 2382 | state->rekey_time = monotime(); |
2754 | if ((r = kex_from_blob(m, &ssh->kex)) != 0 || | 2383 | /* XXX ssh_set_newkeys overrides p_read.packets? XXX */ |
2755 | (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || | 2384 | if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || |
2756 | (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || | 2385 | (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) |
2757 | (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 || | ||
2758 | (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || | ||
2759 | (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || | ||
2760 | (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || | ||
2761 | (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || | ||
2762 | (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || | ||
2763 | (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || | ||
2764 | (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || | ||
2765 | (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || | ||
2766 | (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) | ||
2767 | return r; | ||
2768 | /* | ||
2769 | * We set the time here so that in post-auth privsep slave we | ||
2770 | * count from the completion of the authentication. | ||
2771 | */ | ||
2772 | state->rekey_time = monotime(); | ||
2773 | /* XXX ssh_set_newkeys overrides p_read.packets? XXX */ | ||
2774 | if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || | ||
2775 | (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) | ||
2776 | return r; | ||
2777 | } | ||
2778 | if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || | ||
2779 | (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) | ||
2780 | return r; | 2386 | return r; |
2781 | if (cipher_get_keycontext(state->send_context, NULL) != (int)slen || | ||
2782 | cipher_get_keycontext(state->receive_context, NULL) != (int)rlen) | ||
2783 | return SSH_ERR_INVALID_FORMAT; | ||
2784 | cipher_set_keycontext(state->send_context, keyout); | ||
2785 | cipher_set_keycontext(state->receive_context, keyin); | ||
2786 | 2387 | ||
2787 | if ((r = ssh_packet_set_postauth(ssh)) != 0) | 2388 | if ((r = ssh_packet_set_postauth(ssh)) != 0) |
2788 | return r; | 2389 | return r; |
@@ -2862,13 +2463,6 @@ sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g) | |||
2862 | } | 2463 | } |
2863 | #endif /* OPENSSL_HAS_ECC */ | 2464 | #endif /* OPENSSL_HAS_ECC */ |
2864 | 2465 | ||
2865 | #ifdef WITH_SSH1 | ||
2866 | int | ||
2867 | sshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v) | ||
2868 | { | ||
2869 | return sshbuf_put_bignum1(ssh->state->outgoing_packet, v); | ||
2870 | } | ||
2871 | #endif /* WITH_SSH1 */ | ||
2872 | 2466 | ||
2873 | int | 2467 | int |
2874 | sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v) | 2468 | sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v) |
@@ -2916,6 +2510,12 @@ sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) | |||
2916 | } | 2510 | } |
2917 | 2511 | ||
2918 | int | 2512 | int |
2513 | sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) | ||
2514 | { | ||
2515 | return sshbuf_peek_string_direct(ssh->state->incoming_packet, valp, lenp); | ||
2516 | } | ||
2517 | |||
2518 | int | ||
2919 | sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) | 2519 | sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) |
2920 | { | 2520 | { |
2921 | return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp); | 2521 | return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp); |
@@ -2930,13 +2530,6 @@ sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g) | |||
2930 | } | 2530 | } |
2931 | #endif /* OPENSSL_HAS_ECC */ | 2531 | #endif /* OPENSSL_HAS_ECC */ |
2932 | 2532 | ||
2933 | #ifdef WITH_SSH1 | ||
2934 | int | ||
2935 | sshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v) | ||
2936 | { | ||
2937 | return sshbuf_get_bignum1(ssh->state->incoming_packet, v); | ||
2938 | } | ||
2939 | #endif /* WITH_SSH1 */ | ||
2940 | 2533 | ||
2941 | int | 2534 | int |
2942 | sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v) | 2535 | sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v) |
@@ -2966,15 +2559,13 @@ sshpkt_ptr(struct ssh *ssh, size_t *lenp) | |||
2966 | int | 2559 | int |
2967 | sshpkt_start(struct ssh *ssh, u_char type) | 2560 | sshpkt_start(struct ssh *ssh, u_char type) |
2968 | { | 2561 | { |
2969 | u_char buf[9]; | 2562 | u_char buf[6]; /* u32 packet length, u8 pad len, u8 type */ |
2970 | int len; | ||
2971 | 2563 | ||
2972 | DBG(debug("packet_start[%d]", type)); | 2564 | DBG(debug("packet_start[%d]", type)); |
2973 | len = compat20 ? 6 : 9; | 2565 | memset(buf, 0, sizeof(buf)); |
2974 | memset(buf, 0, len - 1); | 2566 | buf[sizeof(buf) - 1] = type; |
2975 | buf[len - 1] = type; | ||
2976 | sshbuf_reset(ssh->state->outgoing_packet); | 2567 | sshbuf_reset(ssh->state->outgoing_packet); |
2977 | return sshbuf_put(ssh->state->outgoing_packet, buf, len); | 2568 | return sshbuf_put(ssh->state->outgoing_packet, buf, sizeof(buf)); |
2978 | } | 2569 | } |
2979 | 2570 | ||
2980 | static int | 2571 | static int |
@@ -3007,6 +2598,37 @@ ssh_packet_send_mux(struct ssh *ssh) | |||
3007 | return 0; | 2598 | return 0; |
3008 | } | 2599 | } |
3009 | 2600 | ||
2601 | /* | ||
2602 | * 9.2. Ignored Data Message | ||
2603 | * | ||
2604 | * byte SSH_MSG_IGNORE | ||
2605 | * string data | ||
2606 | * | ||
2607 | * All implementations MUST understand (and ignore) this message at any | ||
2608 | * time (after receiving the protocol version). No implementation is | ||
2609 | * required to send them. This message can be used as an additional | ||
2610 | * protection measure against advanced traffic analysis techniques. | ||
2611 | */ | ||
2612 | int | ||
2613 | sshpkt_msg_ignore(struct ssh *ssh, u_int nbytes) | ||
2614 | { | ||
2615 | u_int32_t rnd = 0; | ||
2616 | int r; | ||
2617 | u_int i; | ||
2618 | |||
2619 | if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || | ||
2620 | (r = sshpkt_put_u32(ssh, nbytes)) != 0) | ||
2621 | return r; | ||
2622 | for (i = 0; i < nbytes; i++) { | ||
2623 | if (i % 4 == 0) | ||
2624 | rnd = arc4random(); | ||
2625 | if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) | ||
2626 | return r; | ||
2627 | rnd >>= 8; | ||
2628 | } | ||
2629 | return 0; | ||
2630 | } | ||
2631 | |||
3010 | /* send it */ | 2632 | /* send it */ |
3011 | 2633 | ||
3012 | int | 2634 | int |
@@ -3014,10 +2636,7 @@ sshpkt_send(struct ssh *ssh) | |||
3014 | { | 2636 | { |
3015 | if (ssh->state && ssh->state->mux) | 2637 | if (ssh->state && ssh->state->mux) |
3016 | return ssh_packet_send_mux(ssh); | 2638 | return ssh_packet_send_mux(ssh); |
3017 | if (compat20) | 2639 | return ssh_packet_send2(ssh); |
3018 | return ssh_packet_send2(ssh); | ||
3019 | else | ||
3020 | return ssh_packet_send1(ssh); | ||
3021 | } | 2640 | } |
3022 | 2641 | ||
3023 | int | 2642 | int |
@@ -3031,19 +2650,12 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) | |||
3031 | vsnprintf(buf, sizeof(buf), fmt, args); | 2650 | vsnprintf(buf, sizeof(buf), fmt, args); |
3032 | va_end(args); | 2651 | va_end(args); |
3033 | 2652 | ||
3034 | if (compat20) { | 2653 | if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || |
3035 | if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || | 2654 | (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || |
3036 | (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || | 2655 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || |
3037 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | 2656 | (r = sshpkt_put_cstring(ssh, "")) != 0 || |
3038 | (r = sshpkt_put_cstring(ssh, "")) != 0 || | 2657 | (r = sshpkt_send(ssh)) != 0) |
3039 | (r = sshpkt_send(ssh)) != 0) | 2658 | return r; |
3040 | return r; | ||
3041 | } else { | ||
3042 | if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 || | ||
3043 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | ||
3044 | (r = sshpkt_send(ssh)) != 0) | ||
3045 | return r; | ||
3046 | } | ||
3047 | return 0; | 2659 | return 0; |
3048 | } | 2660 | } |
3049 | 2661 | ||