aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2010-04-17 21:28:30 +0000
committerlloyd <[email protected]>2010-04-17 21:28:30 +0000
commitee353b33dae5fd2a664ac56556e2037284735a47 (patch)
treee36be6f9a35ec5e0ae08216d8a3ce5339c21868f /src
parentaaa9e92697e16278fb91552f075c020f2b4c26cb (diff)
Add support for reading SSLv2 client hellos
Diffstat (limited to 'src')
-rw-r--r--src/ssl/hello.cpp34
-rw-r--r--src/ssl/rec_read.cpp29
-rw-r--r--src/ssl/tls_magic.h1
-rw-r--r--src/ssl/tls_messages.h11
-rw-r--r--src/ssl/tls_server.cpp19
5 files changed, 86 insertions, 8 deletions
diff --git a/src/ssl/hello.cpp b/src/ssl/hello.cpp
index a23d51c24..b93234813 100644
--- a/src/ssl/hello.cpp
+++ b/src/ssl/hello.cpp
@@ -106,6 +106,40 @@ SecureVector<byte> Client_Hello::serialize() const
return buf;
}
+void Client_Hello::deserialize_sslv2(const MemoryRegion<byte>& buf)
+ {
+ if(buf.size() < 12 || buf[0] != 1)
+ throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
+
+ const u32bit cipher_spec_len = make_u16bit(buf[3], buf[4]);
+ const u32bit sess_id_len = make_u16bit(buf[5], buf[6]);
+ const u32bit challenge_len = make_u16bit(buf[7], buf[8]);
+
+ const u32bit expected_size =
+ (9 + sess_id_len + cipher_spec_len + challenge_len);
+
+ if(buf.size() != expected_size)
+ throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
+
+ if(sess_id_len != 0 || cipher_spec_len % 3 != 0 ||
+ (challenge_len < 16 || challenge_len > 32))
+ {
+ throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
+ }
+
+ for(u32bit i = 9; i != 9 + cipher_spec_len; i += 3)
+ {
+ if(buf[i] != 0) // a SSLv2 cipherspec; ignore it
+ continue;
+
+ suites.push_back(make_u16bit(buf[i+1], buf[i+2]));
+ }
+
+ c_version = static_cast<Version_Code>(make_u16bit(buf[1], buf[2]));
+
+ c_random.set(&buf[9+cipher_spec_len+sess_id_len], challenge_len);
+ }
+
/**
* Deserialize a Client Hello message
*/
diff --git a/src/ssl/rec_read.cpp b/src/ssl/rec_read.cpp
index 8f8e5dc1e..f07744c2a 100644
--- a/src/ssl/rec_read.cpp
+++ b/src/ssl/rec_read.cpp
@@ -124,6 +124,35 @@ u32bit Record_Reader::get_record(byte& msg_type,
*/
input_queue.peek(header, sizeof(header));
+ // SSLv2-format client hello?
+ if(header[0] & 0x80 && header[2] == 1 && header[3] == 3)
+ {
+ u32bit record_len = make_u16bit(header[0], header[1]) & 0x7FFF;
+
+ if(have_in_queue < record_len + 2)
+ return (record_len + 2 - have_in_queue);
+
+ msg_type = HANDSHAKE;
+ output.resize(record_len + 4);
+
+ input_queue.read(&output[2], record_len + 2);
+ output[0] = CLIENT_HELLO_SSLV2;
+ output[1] = 0;
+ output[2] = header[0] & 0x7F;
+ output[3] = header[1];
+
+ return 0;
+ }
+
+ if(header[0] != CHANGE_CIPHER_SPEC &&
+ header[0] != ALERT &&
+ header[0] != HANDSHAKE &&
+ header[0] != APPLICATION_DATA)
+ {
+ throw TLS_Exception(UNEXPECTED_MESSAGE,
+ "Record_Reader: Unknown record type");
+ }
+
const u16bit version = make_u16bit(header[1], header[2]);
const u16bit record_len = make_u16bit(header[3], header[4]);
diff --git a/src/ssl/tls_magic.h b/src/ssl/tls_magic.h
index 35a9fc925..25cd0986a 100644
--- a/src/ssl/tls_magic.h
+++ b/src/ssl/tls_magic.h
@@ -40,6 +40,7 @@ enum Record_Type {
enum Handshake_Type {
HELLO_REQUEST = 0,
CLIENT_HELLO = 1,
+ CLIENT_HELLO_SSLV2 = 255, // not a wire value
SERVER_HELLO = 2,
CERTIFICATE = 11,
SERVER_KEX = 12,
diff --git a/src/ssl/tls_messages.h b/src/ssl/tls_messages.h
index 1f72c05f7..42f81b1fe 100644
--- a/src/ssl/tls_messages.h
+++ b/src/ssl/tls_messages.h
@@ -56,10 +56,19 @@ class BOTAN_DLL Client_Hello : public HandshakeMessage
Client_Hello(RandomNumberGenerator& rng,
Record_Writer&, const TLS_Policy*, HandshakeHash&);
- Client_Hello(const MemoryRegion<byte>& buf) { deserialize(buf); }
+ Client_Hello(const MemoryRegion<byte>& buf,
+ Handshake_Type type)
+ {
+ if(type == CLIENT_HELLO)
+ deserialize(buf);
+ else
+ deserialize_sslv2(buf);
+ }
+
private:
SecureVector<byte> serialize() const;
void deserialize(const MemoryRegion<byte>&);
+ void deserialize_sslv2(const MemoryRegion<byte>&);
Version_Code c_version;
SecureVector<byte> sess_id, c_random;
diff --git a/src/ssl/tls_server.cpp b/src/ssl/tls_server.cpp
index 4e9c3583f..1c8d28c95 100644
--- a/src/ssl/tls_server.cpp
+++ b/src/ssl/tls_server.cpp
@@ -43,7 +43,7 @@ void server_check_state(Handshake_Type new_msg, Handshake_State* state)
Unexpected_Message("State transition error from " + err) {}
};
- if(new_msg == CLIENT_HELLO)
+ if(new_msg == CLIENT_HELLO || new_msg == CLIENT_HELLO_SSLV2)
{
if(state->server_hello)
throw State_Transition_Error("ClientHello");
@@ -330,18 +330,23 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
if(type != HANDSHAKE_CCS && type != FINISHED)
{
- state->hash.update(static_cast<byte>(type));
- u32bit record_length = contents.size();
- for(u32bit j = 0; j != 3; j++)
- state->hash.update(get_byte(j+1, record_length));
+
+ if(type != CLIENT_HELLO_SSLV2)
+ {
+ state->hash.update(static_cast<byte>(type));
+ u32bit record_length = contents.size();
+ for(u32bit j = 0; j != 3; j++)
+ state->hash.update(get_byte(j+1, record_length));
+ }
+
state->hash.update(contents);
}
- if(type == CLIENT_HELLO)
+ if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2)
{
server_check_state(type, state);
- state->client_hello = new Client_Hello(contents);
+ state->client_hello = new Client_Hello(contents, type);
client_requested_hostname = state->client_hello->hostname();