summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2017-05-31 08:09:45 +0000
committerDamien Miller <djm@mindrot.org>2017-06-01 14:54:46 +1000
commit1e0cdf8efb745d0d1116e1aa22bdc99ee731695e (patch)
tree49ffdf3ef98eecd4141610e535f35bab5eea4603 /packet.c
parent92e9fe633130376a95dd533df6e5e6a578c1e6b8 (diff)
upstream commit
clear session keys from memory; ok djm@ Upstream-ID: ecd178819868975affd5fd6637458b7c712b6a0f
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c96
1 files changed, 61 insertions, 35 deletions
diff --git a/packet.c b/packet.c
index 46dcc5b5f..862aeb052 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.256 2017/05/08 06:03:39 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.257 2017/05/31 08:09:45 markus 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
@@ -559,8 +559,8 @@ ssh_local_port(struct ssh *ssh)
559 559
560/* Closes the connection and clears and frees internal data structures. */ 560/* Closes the connection and clears and frees internal data structures. */
561 561
562void 562static void
563ssh_packet_close(struct ssh *ssh) 563ssh_packet_close_internal(struct ssh *ssh, int do_close)
564{ 564{
565 struct session_state *state = ssh->state; 565 struct session_state *state = ssh->state;
566 u_int mode; 566 u_int mode;
@@ -568,20 +568,26 @@ ssh_packet_close(struct ssh *ssh)
568 if (!state->initialized) 568 if (!state->initialized)
569 return; 569 return;
570 state->initialized = 0; 570 state->initialized = 0;
571 if (state->connection_in == state->connection_out) { 571 if (do_close) {
572 shutdown(state->connection_out, SHUT_RDWR); 572 if (state->connection_in == state->connection_out) {
573 close(state->connection_out); 573 shutdown(state->connection_out, SHUT_RDWR);
574 } else { 574 close(state->connection_out);
575 close(state->connection_in); 575 } else {
576 close(state->connection_out); 576 close(state->connection_in);
577 close(state->connection_out);
578 }
577 } 579 }
578 sshbuf_free(state->input); 580 sshbuf_free(state->input);
579 sshbuf_free(state->output); 581 sshbuf_free(state->output);
580 sshbuf_free(state->outgoing_packet); 582 sshbuf_free(state->outgoing_packet);
581 sshbuf_free(state->incoming_packet); 583 sshbuf_free(state->incoming_packet);
582 for (mode = 0; mode < MODE_MAX; mode++) 584 for (mode = 0; mode < MODE_MAX; mode++) {
583 kex_free_newkeys(state->newkeys[mode]); 585 kex_free_newkeys(state->newkeys[mode]); /* current keys */
584 if (state->compression_buffer) { 586 state->newkeys[mode] = NULL;
587 ssh_clear_newkeys(ssh, mode); /* next keys */
588 }
589 /* comression state is in shared mem, so we can only release it once */
590 if (do_close && state->compression_buffer) {
585 sshbuf_free(state->compression_buffer); 591 sshbuf_free(state->compression_buffer);
586 if (state->compression_out_started) { 592 if (state->compression_out_started) {
587 z_streamp stream = &state->compression_out_stream; 593 z_streamp stream = &state->compression_out_stream;
@@ -609,10 +615,24 @@ ssh_packet_close(struct ssh *ssh)
609 cipher_free(state->send_context); 615 cipher_free(state->send_context);
610 cipher_free(state->receive_context); 616 cipher_free(state->receive_context);
611 state->send_context = state->receive_context = NULL; 617 state->send_context = state->receive_context = NULL;
612 free(ssh->remote_ipaddr); 618 if (do_close) {
613 ssh->remote_ipaddr = NULL; 619 free(ssh->remote_ipaddr);
614 free(ssh->state); 620 ssh->remote_ipaddr = NULL;
615 ssh->state = NULL; 621 free(ssh->state);
622 ssh->state = NULL;
623 }
624}
625
626void
627ssh_packet_close(struct ssh *ssh)
628{
629 ssh_packet_close_internal(ssh, 1);
630}
631
632void
633ssh_packet_clear_keys(struct ssh *ssh)
634{
635 ssh_packet_close_internal(ssh, 0);
616} 636}
617 637
618/* Sets remote side protocol flags. */ 638/* Sets remote side protocol flags. */
@@ -791,6 +811,15 @@ uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
791 /* NOTREACHED */ 811 /* NOTREACHED */
792} 812}
793 813
814void
815ssh_clear_newkeys(struct ssh *ssh, int mode)
816{
817 if (ssh->kex && ssh->kex->newkeys) {
818 kex_free_newkeys(ssh->kex->newkeys[mode]);
819 ssh->kex->newkeys[mode] = NULL;
820 }
821}
822
794int 823int
795ssh_set_newkeys(struct ssh *ssh, int mode) 824ssh_set_newkeys(struct ssh *ssh, int mode)
796{ 825{
@@ -820,26 +849,16 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
820 max_blocks = &state->max_blocks_in; 849 max_blocks = &state->max_blocks_in;
821 } 850 }
822 if (state->newkeys[mode] != NULL) { 851 if (state->newkeys[mode] != NULL) {
823 debug("%s: rekeying after %llu %s blocks" 852 debug("set_newkeys: rekeying, input %llu bytes %llu blocks, "
824 " (%llu bytes total)", __func__, 853 "output %llu bytes %llu blocks",
825 (unsigned long long)ps->blocks, dir, 854 (unsigned long long)state->p_read.bytes,
826 (unsigned long long)ps->bytes); 855 (unsigned long long)state->p_read.blocks,
856 (unsigned long long)state->p_send.bytes,
857 (unsigned long long)state->p_send.blocks);
827 cipher_free(*ccp); 858 cipher_free(*ccp);
828 *ccp = NULL; 859 *ccp = NULL;
829 enc = &state->newkeys[mode]->enc; 860 kex_free_newkeys(state->newkeys[mode]);
830 mac = &state->newkeys[mode]->mac; 861 state->newkeys[mode] = NULL;
831 comp = &state->newkeys[mode]->comp;
832 mac_clear(mac);
833 explicit_bzero(enc->iv, enc->iv_len);
834 explicit_bzero(enc->key, enc->key_len);
835 explicit_bzero(mac->key, mac->key_len);
836 free(enc->name);
837 free(enc->iv);
838 free(enc->key);
839 free(mac->name);
840 free(mac->key);
841 free(comp->name);
842 free(state->newkeys[mode]);
843 } 862 }
844 /* note that both bytes and the seqnr are not reset */ 863 /* note that both bytes and the seqnr are not reset */
845 ps->packets = ps->blocks = 0; 864 ps->packets = ps->blocks = 0;
@@ -1784,15 +1803,20 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
1784 1803
1785 switch (r) { 1804 switch (r) {
1786 case SSH_ERR_CONN_CLOSED: 1805 case SSH_ERR_CONN_CLOSED:
1806 ssh_packet_clear_keys(ssh);
1787 logdie("Connection closed by %s", remote_id); 1807 logdie("Connection closed by %s", remote_id);
1788 case SSH_ERR_CONN_TIMEOUT: 1808 case SSH_ERR_CONN_TIMEOUT:
1809 ssh_packet_clear_keys(ssh);
1789 logdie("Connection %s %s timed out", 1810 logdie("Connection %s %s timed out",
1790 ssh->state->server_side ? "from" : "to", remote_id); 1811 ssh->state->server_side ? "from" : "to", remote_id);
1791 case SSH_ERR_DISCONNECTED: 1812 case SSH_ERR_DISCONNECTED:
1813 ssh_packet_clear_keys(ssh);
1792 logdie("Disconnected from %s", remote_id); 1814 logdie("Disconnected from %s", remote_id);
1793 case SSH_ERR_SYSTEM_ERROR: 1815 case SSH_ERR_SYSTEM_ERROR:
1794 if (errno == ECONNRESET) 1816 if (errno == ECONNRESET) {
1817 ssh_packet_clear_keys(ssh);
1795 logdie("Connection reset by %s", remote_id); 1818 logdie("Connection reset by %s", remote_id);
1819 }
1796 /* FALLTHROUGH */ 1820 /* FALLTHROUGH */
1797 case SSH_ERR_NO_CIPHER_ALG_MATCH: 1821 case SSH_ERR_NO_CIPHER_ALG_MATCH:
1798 case SSH_ERR_NO_MAC_ALG_MATCH: 1822 case SSH_ERR_NO_MAC_ALG_MATCH:
@@ -1800,12 +1824,14 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
1800 case SSH_ERR_NO_KEX_ALG_MATCH: 1824 case SSH_ERR_NO_KEX_ALG_MATCH:
1801 case SSH_ERR_NO_HOSTKEY_ALG_MATCH: 1825 case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
1802 if (ssh && ssh->kex && ssh->kex->failed_choice) { 1826 if (ssh && ssh->kex && ssh->kex->failed_choice) {
1827 ssh_packet_clear_keys(ssh);
1803 logdie("Unable to negotiate with %s: %s. " 1828 logdie("Unable to negotiate with %s: %s. "
1804 "Their offer: %s", remote_id, ssh_err(r), 1829 "Their offer: %s", remote_id, ssh_err(r),
1805 ssh->kex->failed_choice); 1830 ssh->kex->failed_choice);
1806 } 1831 }
1807 /* FALLTHROUGH */ 1832 /* FALLTHROUGH */
1808 default: 1833 default:
1834 ssh_packet_clear_keys(ssh);
1809 logdie("%s%sConnection %s %s: %s", 1835 logdie("%s%sConnection %s %s: %s",
1810 tag != NULL ? tag : "", tag != NULL ? ": " : "", 1836 tag != NULL ? tag : "", tag != NULL ? ": " : "",
1811 ssh->state->server_side ? "from" : "to", 1837 ssh->state->server_side ? "from" : "to",