diff --git a/lib/modules/SSL.pmod/Alert.pike b/lib/modules/SSL.pmod/Alert.pike index 8af070467be3a71e1c8ea202ed6a6ed3e25e7f13..f9747bcc3d3c261a4b3941d8f21136a40e38f2b8 100644 --- a/lib/modules/SSL.pmod/Alert.pike +++ b/lib/modules/SSL.pmod/Alert.pike @@ -44,8 +44,7 @@ void create(int(1..2) level, int(8bit) description, werror(message); #endif - ::create(); + ::create(version); content_type = PACKET_alert; - protocol_version = version; fragment = sprintf("%1c%1c", level, description); } diff --git a/lib/modules/SSL.pmod/Connection.pike b/lib/modules/SSL.pmod/Connection.pike index 2f6dc9695de9f0d9b567fc7eeccdb0e7f0501e90..5ca17788e8c09846621450da5fe3a48cac062a38 100644 --- a/lib/modules/SSL.pmod/Connection.pike +++ b/lib/modules/SSL.pmod/Connection.pike @@ -113,7 +113,7 @@ Packet handshake_packet(int(8bit) type, string data) addRecord(type,1); #endif /* Perhaps one need to split large packages? */ - Packet packet = Packet(); + Packet packet = Packet(version); packet->content_type = PACKET_handshake; packet->fragment = sprintf("%1c%3H", type, [string(8bit)]data); handshake_messages += packet->fragment; @@ -122,7 +122,7 @@ Packet handshake_packet(int(8bit) type, string data) Packet change_cipher_packet() { - Packet packet = Packet(); + Packet packet = Packet(version); packet->content_type = PACKET_change_cipher_spec; packet->fragment = "\001"; return packet; @@ -153,7 +153,7 @@ Packet certificate_packet(array(string(8bit)) certificates) Packet heartbeat_packet(string(8bit) s) { - Packet packet = Packet(); + Packet packet = Packet(version); packet->content_type = PACKET_heartbeat; packet->fragment = s; return packet; @@ -367,11 +367,11 @@ protected Packet recv_packet(string(8bit) data) // SSL3_DEBUG_MSG("SSL.Connection->recv_packet(%O)\n", data); if (left_over || !packet) { - packet = Packet(2048); - res = packet->recv( (left_over || "") + data, version); + packet = Packet(version, 2048); + res = packet->recv( (left_over || "") + data); } else - res = packet->recv(data, version); + res = packet->recv(data); if (stringp(res)) { /* Finished a packet */ @@ -379,7 +379,7 @@ protected Packet recv_packet(string(8bit) data) if (current_read_state) { SSL3_DEBUG_MSG("SSL.Connection->recv_packet(): version=0x%x\n", version); - return current_read_state->decrypt_packet(packet, version); + return current_read_state->decrypt_packet(packet); } else { SSL3_DEBUG_MSG("SSL.Connection->recv_packet(): current_read_state is zero!\n"); return 0; @@ -483,7 +483,7 @@ string|int to_write() state = [int(0..0)|ConnectionState](state | CONNECTION_local_closed); } } - string res = current_write_state->encrypt_packet(packet, version)->send(); + string res = current_write_state->encrypt_packet(packet)->send(); if (packet->content_type == PACKET_change_cipher_spec) current_write_state = pending_write_state; return res; @@ -502,7 +502,7 @@ void send_close() int send_streaming_data (string(8bit) data) { if (!sizeof(data)) return 0; - Packet packet = Packet(); + Packet packet = Packet(version); packet->content_type = PACKET_application_data; int max_packet_size = session->max_packet_size; int size; @@ -518,7 +518,7 @@ int send_streaming_data (string(8bit) data) // If we have more data, take the opportunity to queue some of it too. send_packet(packet); - packet = Packet(); + packet = Packet(version); packet->content_type = PACKET_application_data; size += sizeof((packet->fragment = data[1..max_packet_size-1])); } diff --git a/lib/modules/SSL.pmod/Packet.pike b/lib/modules/SSL.pmod/Packet.pike index 19e4823b8f9d1ca05f9b9c476220332ee1f9c27a..6195e36fcd890f2ffcdb4a78ba680a4840d4b991 100644 --- a/lib/modules/SSL.pmod/Packet.pike +++ b/lib/modules/SSL.pmod/Packet.pike @@ -18,24 +18,31 @@ constant HEADER_SIZE = 5; private string buffer = ""; private int needed_chars = HEADER_SIZE; -// The packet max size is 2^14 (RFC 5246 6.2.1). Compressed packets -// are however allowed to be 1024 bytes over (6.2.2), and Ciphertexts -// 2048 bytes (6.2.3). State the additional headroom in this variable. +// The fragment max size is 2^14 (RFC 5246 6.2.1). Compressed +// fragments are however allowed to be 1024 bytes over (6.2.2), and +// Ciphertexts 2048 bytes (6.2.3). State the additional headroom in +// this variable. protected int marginal_size; /* Circular dependence */ program Alert = master()->resolv("SSL")["Alert"]; -protected void create(void|int extra) +//! @param version +//! The version sent packets will be created for. +//! @param extra +//! Additional fragment size, over the 2^14 bytes for a plaintext +//! TLS fragment. +protected void create(ProtocolVersion version, void|int extra) { + protocol_version = version; marginal_size = extra; } -object check_size(ProtocolVersion version, int|void extra) +object check_size(int|void extra) { marginal_size = extra; return (sizeof(fragment) > (PACKET_MAX_SIZE + extra)) - ? Alert(ALERT_fatal, ALERT_unexpected_message, version) : 0; + ? Alert(ALERT_fatal, ALERT_unexpected_message, version) : this; } //! Receive data read from the network. @@ -43,16 +50,13 @@ object check_size(ProtocolVersion version, int|void extra) //! @param data //! Raw data from the network. //! -//! @param version -//! Version of the SSL/TLS protocol suite to create a packet for. -//! //! @returns //! Returns a string of leftover data if packet is complete, //! otherwise @expr{0@}. //! //! If there's an error, an alert object is returned. //! -string(8bit)|.Packet recv(string(8bit) data, ProtocolVersion version) +string(8bit)|.Packet recv(string(8bit) data) { buffer += data; while (sizeof(buffer) >= needed_chars) @@ -69,16 +73,16 @@ string(8bit)|.Packet recv(string(8bit) data, ProtocolVersion version) #ifdef SSL3_DEBUG werror("SSL.Packet: Receiving SSL2 packet %O\n", buffer[..4]); #endif - return Alert(ALERT_fatal, ALERT_insufficient_security, version); + return Alert(ALERT_fatal, ALERT_insufficient_security, PROTOCOL_SSL_3_0); } if( !PACKET_types[content_type] ) - return Alert(ALERT_fatal, ALERT_unexpected_message, version); + return Alert(ALERT_fatal, ALERT_unexpected_message, protocol_version); sscanf(buffer, "%*c%2c%2c", protocol_version, length); if ( (length <= 0) || (length > (PACKET_MAX_SIZE + marginal_size))) - return Alert(ALERT_fatal, ALERT_unexpected_message, version); + return Alert(ALERT_fatal, ALERT_unexpected_message, protocol_version); if ((protocol_version & ~0xff) != PROTOCOL_SSL_3_0) - return Alert(ALERT_fatal, ALERT_unexpected_message, version, + return Alert(ALERT_fatal, ALERT_unexpected_message, protocol_version, sprintf("SSL.Packet->send: Version %d.%d " "is not supported\n", protocol_version>>8, protocol_version & 0xff)); diff --git a/lib/modules/SSL.pmod/State.pike b/lib/modules/SSL.pmod/State.pike index 5983818020773f855a7932dc9edda8b344052029..47207d158153baf76631c9c4356bbee838dc33d2 100644 --- a/lib/modules/SSL.pmod/State.pike +++ b/lib/modules/SSL.pmod/State.pike @@ -43,7 +43,7 @@ string salt; //! if needed). On success, returns the decrypted packet. On failure, //! returns an alert packet. These cases are distinguished by looking //! at the is_alert attribute of the returned packet. -Alert|Packet decrypt_packet(Packet packet, ProtocolVersion version) +Alert|Packet decrypt_packet(Packet packet) { /* NOTE: TLS 1.1 recommends performing the hash check before * sending the alerts to protect against timing attacks. @@ -55,6 +55,7 @@ Alert|Packet decrypt_packet(Packet packet, ProtocolVersion version) * even if we have already detected a failure. */ Alert fail; + ProtocolVersion version = packet->protocol_version; #ifdef SSL3_DEBUG_CRYPT werror("SSL.State->decrypt_packet (3.%d, type: %d): data = %O\n", @@ -168,8 +169,7 @@ Alert|Packet decrypt_packet(Packet packet, ProtocolVersion version) string digest = msg[<digest_size-1..]; crypt->set_iv(iv); string auth_data = sprintf("%8c%c%2c%2c", - seq_num, packet->content_type, - packet->protocol_version, + seq_num, packet->content_type, version, sizeof(msg) - (session->cipher_spec->explicit_iv_size + digest_size)); @@ -268,15 +268,15 @@ Alert|Packet decrypt_packet(Packet packet, ProtocolVersion version) if (fail) return fail; - return [object(Alert)]packet->check_size(version) || packet; + return [object(Packet)]packet->check_size(); } //! Encrypts a packet (including deflating and MAC-generation). -Alert|Packet encrypt_packet(Packet packet, ProtocolVersion version) +Alert|Packet encrypt_packet(Packet packet) { + ProtocolVersion version = packet->protocol_version; string digest; - packet->protocol_version = version; - + if (compress) { // RFC 5246 6.2.2. states that data growth must be at most 1024 @@ -339,8 +339,7 @@ Alert|Packet encrypt_packet(Packet packet, ProtocolVersion version) crypt->set_iv(iv); string auth_data = sprintf("%8c%c%2c%2c", seq_num, packet->content_type, - packet->protocol_version, - sizeof(packet->fragment)); + version, sizeof(packet->fragment)); crypt->update(auth_data); packet->fragment = explicit_iv + crypt->crypt(packet->fragment); packet->fragment += crypt->digest(); @@ -358,5 +357,5 @@ Alert|Packet encrypt_packet(Packet packet, ProtocolVersion version) seq_num++; - return [object(Alert)]packet->check_size(version, 2048) || packet; + return [object(Packet)]packet->check_size(2048); }