From fa14c18f6603781ed6d629caa7da95a150850e71 Mon Sep 17 00:00:00 2001 From: Martin Nilsson <nilsson@opera.com> Date: Thu, 7 Aug 2014 21:21:03 +0200 Subject: [PATCH] Correctly check the fragment size in the different stages of decoding. --- lib/modules/SSL.pmod/Packet.pike | 27 +++++++++++++++++------- lib/modules/SSL.pmod/State.pike | 36 ++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/lib/modules/SSL.pmod/Packet.pike b/lib/modules/SSL.pmod/Packet.pike index 6195e36fcd..34f4eeda5e 100644 --- a/lib/modules/SSL.pmod/Packet.pike +++ b/lib/modules/SSL.pmod/Packet.pike @@ -1,12 +1,7 @@ #pike __REAL_VERSION__ -/* - * SSL Record Layer - */ - //! SSL Record Layer. Handle formatting and parsing of packets. - import .Constants; int content_type; @@ -38,11 +33,27 @@ protected void create(ProtocolVersion version, void|int extra) marginal_size = extra; } -object check_size(int|void extra) +protected object check_size(string data, int extra) { + if (sizeof(data) > (PACKET_MAX_SIZE + extra)) + return Alert(ALERT_fatal, ALERT_unexpected_message, version); marginal_size = extra; - return (sizeof(fragment) > (PACKET_MAX_SIZE + extra)) - ? Alert(ALERT_fatal, ALERT_unexpected_message, version) : this; + fragment = data; +} + +object set_plaintext(string data) +{ + check_size(data, 0); +} + +object set_compressed(string data) +{ + check_size(data, 1024); +} + +object set_encrypted(string data) +{ + check_size(data, 2048); } //! Receive data read from the network. diff --git a/lib/modules/SSL.pmod/State.pike b/lib/modules/SSL.pmod/State.pike index 2a2a868ebe..93f9ed28ec 100644 --- a/lib/modules/SSL.pmod/State.pike +++ b/lib/modules/SSL.pmod/State.pike @@ -71,8 +71,9 @@ Alert|Packet decrypt_packet(Packet packet) string(8bit) digest = data[<hmac_size-1..]; data = data[..<hmac_size]; - // Set data without HMAC - packet->fragment = data; + // Set data without HMAC. This never returns an Alert as the data + // is smaller. + packet->set_encrypted(data); if (mac->hash_packet(packet, seq_num, hmac_size)[..hmac_size-1] != digest) { // Bad digest. @@ -207,9 +208,6 @@ Alert|Packet decrypt_packet(Packet packet) data = data[tls_iv..]; } - // Set decrypted data. - packet->fragment = data; - if (hmac_size) { #ifdef SSL3_DEBUG_CRYPT @@ -241,8 +239,8 @@ Alert|Packet decrypt_packet(Packet packet) } junk = mac->hash_raw(junk); - // Set data without HMAC. - packet->fragment = data; + // Set decrypted data without HMAC. + fail = fail || [object(Alert)]packet->set_compressed(data); if (digest != mac->hash_packet(packet, seq_num)[..hmac_size-1]) { @@ -260,6 +258,11 @@ Alert|Packet decrypt_packet(Packet packet) } seq_num++; } + else + { + // Set decrypted data. + fail = fail || [object(Alert)]packet->set_compressed(data); + } if (compress) { @@ -275,12 +278,10 @@ Alert|Packet decrypt_packet(Packet packet) "Inflated package >16K\n"); // Set uncompressed data - packet->fragment = data; + fail = fail || [object(Alert)]packet->set_plaintext(data); } - if (fail) return fail; - - return [object(Packet)]packet->check_size(); + return fail || packet; } //! Encrypts a packet (including deflating and MAC-generation). @@ -289,6 +290,7 @@ Alert|Packet encrypt_packet(Packet packet) ProtocolVersion version = packet->protocol_version; string data = packet->fragment; string digest; + Alert res; if (compress) { @@ -298,7 +300,8 @@ Alert|Packet encrypt_packet(Packet packet) data = compress(data); // Set compressed data. - packet->fragment = data; + res = [object(Alert)]packet->set_compressed(data); + if(res) return res; } int hmac_size = mac && (session->truncated_hmac ? 10 : @@ -365,17 +368,18 @@ Alert|Packet encrypt_packet(Packet packet) data += digest; // Set encrypted data. - packet->fragment = data; + res = [object(Alert)]packet->set_encrypted(data); + if(res) return res; if (hmac_size) { // Encrypt-then-MAC mode. data += mac->hash_packet(packet, seq_num, hmac_size)[..hmac_size-1]; // Set HMAC protected data. - packet->fragment = data; + res = [object(Alert)]packet->set_encrypted(data); + if(res) return res; } seq_num++; - - return [object(Packet)]packet->check_size(2048); + return packet; } -- GitLab