From cc838c6b2e1d20bb8ae07bec91840eca13285dc6 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 10 Apr 2014 15:11:43 -0700 Subject: [PATCH] rip out state handline from ssl analyzer. still seems to work, but basically untested. --- src/analyzer/protocol/ssl/ssl-analyzer.pac | 79 ++----- src/analyzer/protocol/ssl/ssl-protocol.pac | 249 ++++----------------- 2 files changed, 55 insertions(+), 273 deletions(-) diff --git a/src/analyzer/protocol/ssl/ssl-analyzer.pac b/src/analyzer/protocol/ssl/ssl-analyzer.pac index 49104fa549..39388c448e 100644 --- a/src/analyzer/protocol/ssl/ssl-analyzer.pac +++ b/src/analyzer/protocol/ssl/ssl-analyzer.pac @@ -107,25 +107,6 @@ refine connection SSL_Conn += { %cleanup{ %} - function proc_change_cipher_spec(rec: SSLRecord) : bool - %{ - if ( state_ == STATE_TRACK_LOST ) - bro_analyzer()->ProtocolViolation(fmt("unexpected ChangeCipherSpec from %s at state %s", - orig_label(${rec.is_orig}).c_str(), - state_label(old_state_).c_str())); - return true; - %} - - function proc_application_data(rec: SSLRecord) : bool - %{ - if ( state_ != STATE_CONN_ESTABLISHED && - (state_ != STATE_CLIENT_FINISHED && ! ${rec.is_orig}) ) - bro_analyzer()->ProtocolViolation(fmt("unexpected ApplicationData from %s at state %s", - orig_label(${rec.is_orig}).c_str(), - state_label(old_state_).c_str())); - return true; - %} - function proc_alert(rec: SSLRecord, level : int, desc : int) : bool %{ BifEvent::generate_ssl_alert(bro_analyzer(), bro_analyzer()->Conn(), @@ -267,11 +248,6 @@ refine connection SSL_Conn += { function proc_v2_client_master_key(rec: SSLRecord, cipher_kind: int) : bool %{ - if ( state_ == STATE_TRACK_LOST ) - bro_analyzer()->ProtocolViolation(fmt("unexpected v2 client master key message from %s in state %s", - orig_label(${rec.is_orig}).c_str(), - state_label(old_state_).c_str())); - BifEvent::generate_ssl_established(bro_analyzer(), bro_analyzer()->Conn()); @@ -285,17 +261,6 @@ refine connection SSL_Conn += { return true; %} - function proc_handshake(hs: Handshake, is_orig: bool) : bool - %{ - if ( state_ == STATE_TRACK_LOST ) - bro_analyzer()->ProtocolViolation(fmt("unexpected Handshake message %s from %s in state %s", - handshake_type_label(${hs.msg_type}).c_str(), - orig_label(is_orig).c_str(), - state_label(old_state_).c_str())); - - return true; - %} - function proc_unknown_record(rec: SSLRecord) : bool %{ bro_analyzer()->ProtocolViolation(fmt("unknown SSL record type (%d) from %s", @@ -306,13 +271,8 @@ refine connection SSL_Conn += { function proc_ciphertext_record(rec : SSLRecord) : bool %{ - if ( state_ == STATE_TRACK_LOST ) - bro_analyzer()->ProtocolViolation(fmt("unexpected ciphertext record from %s in state %s", - orig_label(${rec.is_orig}).c_str(), - state_label(old_state_).c_str())); - - else if ( state_ == STATE_CONN_ESTABLISHED && - old_state_ == STATE_COMM_ENCRYPTED ) + if ( client_state_ == STATE_ENCRYPTED && + server_state_ == STATE_ENCRYPTED ) { BifEvent::generate_ssl_established(bro_analyzer(), bro_analyzer()->Conn()); @@ -322,10 +282,10 @@ refine connection SSL_Conn += { %} }; -refine typeattr ChangeCipherSpec += &let { - proc : bool = $context.connection.proc_change_cipher_spec(rec) - &requires(state_changed); -}; +#refine typeattr ChangeCipherSpec += &let { +# proc : bool = $context.connection.proc_change_cipher_spec(rec) +# &requires(state_changed); +#}; refine typeattr Alert += &let { proc : bool = $context.connection.proc_alert(rec, level, description); @@ -335,42 +295,37 @@ refine typeattr V2Error += &let { proc : bool = $context.connection.proc_alert(rec, -1, error_code); }; -refine typeattr ApplicationData += &let { - proc : bool = $context.connection.proc_application_data(rec); -}; +#refine typeattr ApplicationData += &let { +# proc : bool = $context.connection.proc_application_data(rec); +#}; refine typeattr ClientHello += &let { proc : bool = $context.connection.proc_client_hello(rec, client_version, gmt_unix_time, random_bytes, - session_id, csuits, 0) - &requires(state_changed); + session_id, csuits, 0); }; refine typeattr V2ClientHello += &let { proc : bool = $context.connection.proc_client_hello(rec, client_version, 0, - challenge, session_id, 0, ciphers) - &requires(state_changed); + challenge, session_id, 0, ciphers); }; refine typeattr ServerHello += &let { proc : bool = $context.connection.proc_server_hello(rec, server_version, gmt_unix_time, random_bytes, session_id, cipher_suite, 0, - compression_method) - &requires(state_changed); + compression_method); }; refine typeattr V2ServerHello += &let { proc : bool = $context.connection.proc_server_hello(rec, server_version, 0, - conn_id_data, 0, 0, ciphers, 0) - &requires(state_changed); + conn_id_data, 0, 0, ciphers, 0); cert : bool = $context.connection.proc_v2_certificate(rec, cert_data) &requires(proc); }; refine typeattr Certificate += &let { - proc : bool = $context.connection.proc_v3_certificate(rec, certificates) - &requires(state_changed); + proc : bool = $context.connection.proc_v3_certificate(rec, certificates); }; refine typeattr V2ClientMasterKey += &let { @@ -382,9 +337,9 @@ refine typeattr UnknownHandshake += &let { proc : bool = $context.connection.proc_unknown_handshake(hs, is_orig); }; -refine typeattr Handshake += &let { - proc : bool = $context.connection.proc_handshake(this, rec.is_orig); -}; +#refine typeattr Handshake += &let { +# proc : bool = $context.connection.proc_handshake(this, rec.is_orig); +#}; refine typeattr SessionTicketHandshake += &let { proc : bool = $context.connection.proc_session_ticket_handshake(this, rec.is_orig); diff --git a/src/analyzer/protocol/ssl/ssl-protocol.pac b/src/analyzer/protocol/ssl/ssl-protocol.pac index 9368122eaa..7ee71df352 100644 --- a/src/analyzer/protocol/ssl/ssl-protocol.pac +++ b/src/analyzer/protocol/ssl/ssl-protocol.pac @@ -34,7 +34,7 @@ type SSLRecord(is_orig: bool) = record { head4 : uint8; rec : RecordText(this)[] &length=length, &requires(content_type); } &length = length+5, &byteorder=bigendian, - &let { + &let { version : int = $context.connection.determine_ssl_version(head0, head1, head2); @@ -51,9 +51,8 @@ type SSLRecord(is_orig: bool) = record { }; }; -type RecordText(rec: SSLRecord) = case $context.connection.state() of { - STATE_ABBREV_SERVER_ENCRYPTED, STATE_CLIENT_ENCRYPTED, - STATE_COMM_ENCRYPTED, STATE_CONN_ESTABLISHED +type RecordText(rec: SSLRecord) = case $context.connection.state(rec.is_orig) of { + STATE_ENCRYPTED -> ciphertext : CiphertextRecord(rec); default -> plaintext : PlaintextRecord(rec); @@ -82,64 +81,18 @@ type SSLExtension(rec: SSLRecord) = record { ###################################################################### enum AnalyzerState { - STATE_INITIAL, - STATE_CLIENT_HELLO_RCVD, - STATE_IN_SERVER_HELLO, - STATE_SERVER_HELLO_DONE, - STATE_CLIENT_CERT, - STATE_CLIENT_KEY_WITH_CERT, - STATE_CLIENT_KEY_NO_CERT, - STATE_CLIENT_CERT_VERIFIED, - STATE_CLIENT_ENCRYPTED, - STATE_CLIENT_FINISHED, - STATE_ABBREV_SERVER_ENCRYPTED, - STATE_ABBREV_SERVER_FINISHED, - STATE_COMM_ENCRYPTED, - STATE_CONN_ESTABLISHED, - STATE_V2_CL_MASTER_KEY_EXPECTED, - - STATE_TRACK_LOST, - STATE_ANY + STATE_CLEAR, + STATE_ENCRYPTED }; %code{ string state_label(int state_nr) { switch ( state_nr ) { - case STATE_INITIAL: - return string("INITIAL"); - case STATE_CLIENT_HELLO_RCVD: - return string("CLIENT_HELLO_RCVD"); - case STATE_IN_SERVER_HELLO: - return string("IN_SERVER_HELLO"); - case STATE_SERVER_HELLO_DONE: - return string("SERVER_HELLO_DONE"); - case STATE_CLIENT_CERT: - return string("CLIENT_CERT"); - case STATE_CLIENT_KEY_WITH_CERT: - return string("CLIENT_KEY_WITH_CERT"); - case STATE_CLIENT_KEY_NO_CERT: - return string("CLIENT_KEY_NO_CERT"); - case STATE_CLIENT_CERT_VERIFIED: - return string("CLIENT_CERT_VERIFIED"); - case STATE_CLIENT_ENCRYPTED: - return string("CLIENT_ENCRYPTED"); - case STATE_CLIENT_FINISHED: - return string("CLIENT_FINISHED"); - case STATE_ABBREV_SERVER_ENCRYPTED: - return string("ABBREV_SERVER_ENCRYPTED"); - case STATE_ABBREV_SERVER_FINISHED: - return string("ABBREV_SERVER_FINISHED"); - case STATE_COMM_ENCRYPTED: - return string("COMM_ENCRYPTED"); - case STATE_CONN_ESTABLISHED: - return string("CONN_ESTABLISHED"); - case STATE_V2_CL_MASTER_KEY_EXPECTED: - return string("STATE_V2_CL_MASTER_KEY_EXPECTED"); - case STATE_TRACK_LOST: - return string("TRACK_LOST"); - case STATE_ANY: - return string("ANY"); + case STATE_CLEAR: + return string("CLEAR"); + case STATE_ENCRYPTED: + return string("ENCRYPTED"); default: return string(fmt("UNKNOWN (%d)", state_nr)); @@ -176,21 +129,7 @@ type ChangeCipherSpec(rec: SSLRecord) = record { type : uint8; } &length = 1, &let { state_changed : bool = - $context.connection.transition(STATE_CLIENT_FINISHED, - STATE_COMM_ENCRYPTED, rec.is_orig, false) || - $context.connection.transition(STATE_IN_SERVER_HELLO, - STATE_ABBREV_SERVER_ENCRYPTED, rec.is_orig, false) || - $context.connection.transition(STATE_CLIENT_KEY_NO_CERT, - STATE_CLIENT_ENCRYPTED, rec.is_orig, true) || - $context.connection.transition(STATE_CLIENT_CERT_VERIFIED, - STATE_CLIENT_ENCRYPTED, rec.is_orig, true) || - $context.connection.transition(STATE_CLIENT_CERT, - STATE_CLIENT_ENCRYPTED, rec.is_orig, true) || - $context.connection.transition(STATE_CLIENT_KEY_WITH_CERT, - STATE_CLIENT_ENCRYPTED, rec.is_orig, true) || - $context.connection.transition(STATE_ABBREV_SERVER_FINISHED, - STATE_COMM_ENCRYPTED, rec.is_orig, true) || - $context.connection.lost_track(); + $context.connection.startEncryption(rec.is_orig); }; @@ -209,7 +148,7 @@ type Alert(rec: SSLRecord) = record { ###################################################################### type V2Error(rec: SSLRecord) = record { - data: bytestring &restofdata &transient; + data : bytestring &restofdata &transient; } &let { error_code : uint16 = ((rec.head3 << 8) | rec.head4); }; @@ -234,9 +173,7 @@ type ApplicationData(rec: SSLRecord) = record { ###################################################################### # Hello Request is empty -type HelloRequest(rec: SSLRecord) = empty &let { - hr: bool = $context.connection.set_hello_requested(true); -}; +type HelloRequest(rec: SSLRecord) = empty; ###################################################################### @@ -257,13 +194,6 @@ type ClientHello(rec: SSLRecord) = record { # of the following fields. ext_len: uint16[] &until($element == 0 || $element != 0); extensions : SSLExtension(rec)[] &until($input.length() == 0); -} &let { - state_changed : bool = - $context.connection.transition(STATE_INITIAL, - STATE_CLIENT_HELLO_RCVD, rec.is_orig, true) || - ($context.connection.hello_requested() && - $context.connection.transition(STATE_ANY, STATE_CLIENT_HELLO_RCVD, rec.is_orig, true)) || - $context.connection.lost_track(); }; @@ -279,13 +209,6 @@ type V2ClientHello(rec: SSLRecord) = record { session_id : uint8[session_len]; challenge : bytestring &length = chal_len; } &length = 6 + csuit_len + session_len + chal_len, &let { - state_changed : bool = - $context.connection.transition(STATE_INITIAL, - STATE_CLIENT_HELLO_RCVD, rec.is_orig, true) || - ($context.connection.hello_requested() && - $context.connection.transition(STATE_ANY, STATE_CLIENT_HELLO_RCVD, rec.is_orig, true)) || - $context.connection.lost_track(); - client_version : int = rec.version; }; @@ -306,11 +229,6 @@ type ServerHello(rec: SSLRecord) = record { # of the following fields. ext_len: uint16[] &until($element == 0 || $element != 0); extensions : SSLExtension(rec)[] &until($input.length() == 0); -} &let { - state_changed : bool = - $context.connection.transition(STATE_CLIENT_HELLO_RCVD, - STATE_IN_SERVER_HELLO, rec.is_orig, false) || - $context.connection.lost_track(); }; @@ -329,14 +247,6 @@ type V2ServerHello(rec: SSLRecord) = record { ciphers : uint24[ciph_len/3]; conn_id_data : bytestring &length = conn_id_len; } &let { - state_changed : bool = - (session_id_hit > 0 ? - $context.connection.transition(STATE_CLIENT_HELLO_RCVD, - STATE_CONN_ESTABLISHED, rec.is_orig, false) : - $context.connection.transition(STATE_CLIENT_HELLO_RCVD, - STATE_V2_CL_MASTER_KEY_EXPECTED, rec.is_orig, false)) || - $context.connection.lost_track(); - session_id_hit : uint8 = rec.head3; cert_type : uint8 = rec.head4; }; @@ -357,12 +267,10 @@ type Certificate(rec: SSLRecord) = record { length : uint24; certificates : CertificateList &length = to_int()(length); } &let { - state_changed : bool = - $context.connection.transition(STATE_IN_SERVER_HELLO, - STATE_IN_SERVER_HELLO, rec.is_orig, false) || - $context.connection.transition(STATE_SERVER_HELLO_DONE, - STATE_CLIENT_CERT, rec.is_orig, true) || - $context.connection.lost_track(); + state_changed_client : bool = + $context.connection.startEncryption(true); + state_changed_server : bool = + $context.connection.startEncryption(false); }; @@ -373,11 +281,6 @@ type Certificate(rec: SSLRecord) = record { # For now ignore details; just eat up complete message type ServerKeyExchange(rec: SSLRecord) = record { key : bytestring &restofdata &transient; -} &let { - state_changed : bool = - $context.connection.transition(STATE_IN_SERVER_HELLO, - STATE_IN_SERVER_HELLO, rec.is_orig, false) || - $context.connection.lost_track(); }; @@ -388,11 +291,6 @@ type ServerKeyExchange(rec: SSLRecord) = record { # For now, ignore Certificate Request Details; just eat up message. type CertificateRequest(rec: SSLRecord) = record { cont : bytestring &restofdata &transient; -} &let { - state_changed : bool = - $context.connection.transition(STATE_IN_SERVER_HELLO, - STATE_IN_SERVER_HELLO, rec.is_orig, false) || - $context.connection.lost_track(); }; @@ -401,12 +299,7 @@ type CertificateRequest(rec: SSLRecord) = record { ###################################################################### # Server Hello Done is empty -type ServerHelloDone(rec: SSLRecord) = empty &let { - state_changed : bool = - $context.connection.transition(STATE_IN_SERVER_HELLO, - STATE_SERVER_HELLO_DONE, rec.is_orig, false) || - $context.connection.lost_track(); -}; +type ServerHelloDone(rec: SSLRecord) = empty; ###################################################################### @@ -425,15 +318,6 @@ type ServerHelloDone(rec: SSLRecord) = empty &let { # encrypted anyway); just eat up message. type ClientKeyExchange(rec: SSLRecord) = record { key : bytestring &restofdata &transient; -} &let { - state_changed : bool = - $context.connection.transition(STATE_SERVER_HELLO_DONE, - STATE_CLIENT_KEY_NO_CERT, rec.is_orig, true) || - $context.connection.transition(STATE_CLIENT_CERT, - STATE_CLIENT_KEY_WITH_CERT, rec.is_orig, true) || - $context.connection.transition(STATE_CLIENT_CERT, - STATE_CLIENT_KEY_WITH_CERT, rec.is_orig, true) || - $context.connection.lost_track(); }; ###################################################################### @@ -449,11 +333,6 @@ type V2ClientMasterKey(rec: SSLRecord) = record { en_key_data : bytestring &length = en_key_len &transient; key_arg_data : bytestring &length = key_arg_len &transient; } &length = 7 + cl_key_len + en_key_len + key_arg_len, &let { - state_changed : bool = - $context.connection.transition(STATE_V2_CL_MASTER_KEY_EXPECTED, - STATE_CONN_ESTABLISHED, rec.is_orig, true) || - $context.connection.lost_track(); - cipher_kind : int = (((rec.head3 << 16) | (rec.head4 << 8)) | cipher_kind_8); }; @@ -465,11 +344,6 @@ type V2ClientMasterKey(rec: SSLRecord) = record { # For now, ignore Certificate Verify; just eat up the message. type CertificateVerify(rec: SSLRecord) = record { cont : bytestring &restofdata &transient; -} &let { - state_changed : bool = - $context.connection.transition(STATE_CLIENT_KEY_WITH_CERT, - STATE_CLIENT_CERT_VERIFIED, rec.is_orig, true) || - $context.connection.lost_track(); }; @@ -481,13 +355,6 @@ type CertificateVerify(rec: SSLRecord) = record { # so we will not be able to read those messages. type Finished(rec: SSLRecord) = record { cont : bytestring &restofdata &transient; -} &let { - state_changed : bool = - $context.connection.transition(STATE_SERVER_HELLO_DONE, - STATE_COMM_ENCRYPTED, rec.is_orig, true) || - $context.connection.transition(STATE_CLIENT_FINISHED, - STATE_COMM_ENCRYPTED, rec.is_orig, false) || - $context.connection.lost_track(); }; type SessionTicketHandshake(rec: SSLRecord) = record { @@ -499,10 +366,8 @@ type SessionTicketHandshake(rec: SSLRecord) = record { # V3 Handshake Protocol (7.) ###################################################################### -type UnknownHandshake(hs: Handshake, is_orig: bool) = record { +type UnknownHandshake(hs: Handshake, is_orig: bool) = record { data : bytestring &restofdata &transient; -} &let { - state_changed : bool = $context.connection.lost_track(); }; type Handshake(rec: SSLRecord) = record { @@ -532,33 +397,12 @@ type Handshake(rec: SSLRecord) = record { # Fragmentation (6.2.1.) ###################################################################### -type UnknownRecord(rec: SSLRecord) = record { +type UnknownRecord(rec: SSLRecord) = record { cont : bytestring &restofdata &transient; -} &let { - state_changed : bool = $context.connection.lost_track(); }; type CiphertextRecord(rec: SSLRecord) = record { cont : bytestring &restofdata &transient; -} &let { - state_changed : bool = - $context.connection.transition(STATE_CLIENT_FINISHED, - STATE_CLIENT_FINISHED, rec.is_orig, false) || - $context.connection.transition(STATE_CLIENT_FINISHED, - STATE_CLIENT_FINISHED, rec.is_orig, true) || - $context.connection.transition(STATE_ABBREV_SERVER_ENCRYPTED, - STATE_ABBREV_SERVER_FINISHED, rec.is_orig, false) || - $context.connection.transition(STATE_CLIENT_ENCRYPTED, - STATE_CLIENT_FINISHED, rec.is_orig, true) || - $context.connection.transition(STATE_COMM_ENCRYPTED, - STATE_CONN_ESTABLISHED, rec.is_orig, false) || - $context.connection.transition(STATE_COMM_ENCRYPTED, - STATE_CONN_ESTABLISHED, rec.is_orig, true) || - $context.connection.transition(STATE_CONN_ESTABLISHED, - STATE_CONN_ESTABLISHED, rec.is_orig, false) || - $context.connection.transition(STATE_CONN_ESTABLISHED, - STATE_CONN_ESTABLISHED, rec.is_orig, true) || - $context.connection.lost_track(); }; @@ -578,22 +422,22 @@ type SSLPDU(is_orig: bool) = record { refine connection SSL_Conn += { %member{ - int state_; + int client_state_; + int server_state_; int old_state_; bool hello_requested_; %} %init{ - state_ = STATE_INITIAL; - old_state_ = STATE_INITIAL; - hello_requested_ = false; + server_state_ = STATE_CLEAR; + client_state_ = STATE_CLEAR; %} function determine_ssl_version(head0 : uint8, head1 : uint8, head2 : uint8) : int %{ if ( head0 >= 20 && head0 <= 23 && - head1 == 0x03 && head2 <= 0x03 ) + head1 == 0x03 && head2 <= 0x03 ) // This is most probably SSL version 3. return (head1 << 8) | head2; @@ -606,39 +450,22 @@ refine connection SSL_Conn += { return UNKNOWN_VERSION; %} - function state() : int %{ return state_; %} - function old_state() : int %{ return old_state_; %} + function client_state() : int %{ return client_state_; %} + function server_state() : int %{ return client_state_; %} + function state(is_orig: bool) : int + %{ + if ( is_orig ) + return client_state_; + else + return server_state_; + %} - function transition(olds : AnalyzerState, news : AnalyzerState, - current_record_is_orig : bool, is_orig : bool) : bool + function startEncryption(is_orig: bool) : bool %{ - if ( (olds != STATE_ANY && olds != state_) || - current_record_is_orig != is_orig ) - return false; - - old_state_ = state_; - state_ = news; - - //printf("transitioning from %s to %s\n", state_label(old_state()).c_str(), state_label(state()).c_str()); + if ( is_orig ) + client_state_ = STATE_ENCRYPTED; + else + server_state_ = STATE_ENCRYPTED; return true; %} - - function lost_track() : bool - %{ - state_ = STATE_TRACK_LOST; - return false; - %} - - function hello_requested() : bool - %{ - bool ret = hello_requested_; - hello_requested_ = false; - return ret; - %} - - function set_hello_requested(val : bool) : bool - %{ - hello_requested_ = val; - return val; - %} };