Added the ssl_session_ticket_handshake event and fixed a few SSL bugs.

This commit is contained in:
Seth Hall 2011-11-23 16:10:58 -05:00
parent c8839da069
commit 03646a8d55
3 changed files with 61 additions and 44 deletions

View file

@ -280,6 +280,7 @@ event ssh_server_version%(c: connection, version: string%);
event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%); event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%);
event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%); event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%);
event ssl_extension%(c: connection, code: count, val: string%); event ssl_extension%(c: connection, code: count, val: string%);
event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count, ticket: string%);
event ssl_established%(c: connection%); event ssl_established%(c: connection%);
event ssl_alert%(c: connection, level: count, desc: count%); event ssl_alert%(c: connection, level: count, desc: count%);

View file

@ -138,7 +138,7 @@ refine connection SSL_Conn += {
if ( ssl_client_hello ) if ( ssl_client_hello )
{ {
vector<int>* cipher_suites = new vector<int>(); vector<int>* cipher_suites = new vector<int>();
if ( cipher_suites16 ) if ( cipher_suites16 )
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites)); std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites));
else else
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int()); std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int());
@ -199,6 +199,18 @@ refine connection SSL_Conn += {
return true; return true;
%} %}
function proc_session_ticket_handshake(rec: SessionTicketHandshake, is_orig: bool): bool
%{
if ( ssl_session_ticket_handshake )
{
BifEvent::generate_ssl_session_ticket_handshake(bro_analyzer(),
bro_analyzer()->Conn(),
${rec.ticket_lifetime_hint},
new StringVal(${rec.data}.length(), (const char*) ${rec.data}.data()));
}
return true;
%}
function proc_ssl_extension(type: int, data: bytestring) : bool function proc_ssl_extension(type: int, data: bytestring) : bool
%{ %{
@ -263,13 +275,14 @@ refine connection SSL_Conn += {
der_cert); der_cert);
// Are there any X509 extensions? // Are there any X509 extensions?
//printf("Number of x509 extensions: %d\n", X509_get_ext_count(pTemp));
if ( x509_extension && X509_get_ext_count(pTemp) > 0 ) if ( x509_extension && X509_get_ext_count(pTemp) > 0 )
{ {
int num_ext = X509_get_ext_count(pTemp); int num_ext = X509_get_ext_count(pTemp);
for ( int k = 0; k < num_ext; ++k ) for ( int k = 0; k < num_ext; ++k )
{ {
unsigned char *pBuffer = 0; unsigned char *pBuffer = 0;
int length = 0; uint length = 0;
X509_EXTENSION* ex = X509_get_ext(pTemp, k); X509_EXTENSION* ex = X509_get_ext(pTemp, k);
if (ex) if (ex)
@ -277,7 +290,7 @@ refine connection SSL_Conn += {
ASN1_STRING *pString = X509_EXTENSION_get_data(ex); ASN1_STRING *pString = X509_EXTENSION_get_data(ex);
length = ASN1_STRING_to_UTF8(&pBuffer, pString); length = ASN1_STRING_to_UTF8(&pBuffer, pString);
//i2t_ASN1_OBJECT(&pBuffer, length, obj) //i2t_ASN1_OBJECT(&pBuffer, length, obj)
printf("extension length: %u\n", length);
// -1 indicates an error. // -1 indicates an error.
if ( length < 0 ) if ( length < 0 )
continue; continue;
@ -436,6 +449,10 @@ refine typeattr Handshake += &let {
proc : bool = $context.connection.proc_handshake(this, rec.is_orig); 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);
}
refine typeattr UnknownRecord += &let { refine typeattr UnknownRecord += &let {
proc : bool = $context.connection.proc_unknown_record(rec); proc : bool = $context.connection.proc_unknown_record(rec);
}; };

View file

@ -57,22 +57,15 @@ type SSLRecord(is_orig: bool) = record {
type RecordText(rec: SSLRecord, is_orig: bool) = case $context.connection.state() of { type RecordText(rec: SSLRecord, is_orig: bool) = case $context.connection.state() of {
STATE_ABBREV_SERVER_ENCRYPTED, STATE_CLIENT_ENCRYPTED, STATE_ABBREV_SERVER_ENCRYPTED, STATE_CLIENT_ENCRYPTED,
STATE_COMM_ENCRYPTED, STATE_CONN_ESTABLISHED STATE_COMM_ENCRYPTED, STATE_CONN_ESTABLISHED
-> ciphertext : CiphertextRecord(rec, is_orig); -> ciphertext : CiphertextRecord(rec);
default default
-> plaintext : PlaintextRecord(rec, is_orig); -> plaintext : PlaintextRecord(rec);
}; };
type PossibleEncryptedHandshake(rec: SSLRecord, is_orig: bool) = case $context.connection.state() of { type PlaintextRecord(rec: SSLRecord) = case rec.content_type of {
# Deal with encrypted handshakes before the server cipher spec change.
STATE_CLIENT_FINISHED, STATE_CLIENT_ENCRYPTED
-> ct : CiphertextRecord(rec, is_orig);
default -> hs : Handshake(rec);
};
type PlaintextRecord(rec: SSLRecord, is_orig: bool) = case rec.content_type of {
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec); CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
ALERT -> alert : Alert(rec); ALERT -> alert : Alert(rec);
HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec, is_orig); HANDSHAKE -> handshake : Handshake(rec);
APPLICATION_DATA -> app_data : ApplicationData(rec); APPLICATION_DATA -> app_data : ApplicationData(rec);
V2_ERROR -> v2_error : V2Error(rec); V2_ERROR -> v2_error : V2Error(rec);
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec); V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
@ -265,18 +258,19 @@ enum AnalyzerState {
###################################################################### ######################################################################
enum HandshakeType { enum HandshakeType {
HELLO_REQUEST = 0, HELLO_REQUEST = 0,
CLIENT_HELLO = 1, CLIENT_HELLO = 1,
SERVER_HELLO = 2, SERVER_HELLO = 2,
CERTIFICATE = 11, SESSION_TICKET = 4, # RFC 5077
SERVER_KEY_EXCHANGE = 12, CERTIFICATE = 11,
CERTIFICATE_REQUEST = 13, SERVER_KEY_EXCHANGE = 12,
SERVER_HELLO_DONE = 14, CERTIFICATE_REQUEST = 13,
CERTIFICATE_VERIFY = 15, SERVER_HELLO_DONE = 14,
CLIENT_KEY_EXCHANGE = 16, CERTIFICATE_VERIFY = 15,
FINISHED = 20, CLIENT_KEY_EXCHANGE = 16,
CERTIFICATE_URL = 21, # RFC 3546 FINISHED = 20,
CERTIFICATE_STATUS = 22, # RFC 3546 CERTIFICATE_URL = 21, # RFC 3546
CERTIFICATE_STATUS = 22, # RFC 3546
}; };
%code{ %code{
@ -286,6 +280,7 @@ enum HandshakeType {
case HELLO_REQUEST: return string("HELLO_REQUEST"); case HELLO_REQUEST: return string("HELLO_REQUEST");
case CLIENT_HELLO: return string("CLIENT_HELLO"); case CLIENT_HELLO: return string("CLIENT_HELLO");
case SERVER_HELLO: return string("SERVER_HELLO"); case SERVER_HELLO: return string("SERVER_HELLO");
case SESSION_TICKET: return string("SESSION_TICKET");
case CERTIFICATE: return string("CERTIFICATE"); case CERTIFICATE: return string("CERTIFICATE");
case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE"); case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE");
case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST"); case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST");
@ -457,8 +452,7 @@ type V2ServerHello(rec: SSLRecord) = record {
cert_data : bytestring &length = cert_len; cert_data : bytestring &length = cert_len;
ciphers : uint24[ciph_len/3]; ciphers : uint24[ciph_len/3];
conn_id_data : bytestring &length = conn_id_len; conn_id_data : bytestring &length = conn_id_len;
} #&length = 8 + cert_len + ciph_len + conn_id_len, } &let {
&let {
state_changed : bool = state_changed : bool =
(session_id_hit > 0 ? (session_id_hit > 0 ?
$context.connection.transition(STATE_CLIENT_HELLO_RCVD, $context.connection.transition(STATE_CLIENT_HELLO_RCVD,
@ -608,7 +602,7 @@ type CertificateVerify(rec: SSLRecord) = record {
###################################################################### ######################################################################
# The finished messages are always sent after encryption is in effect, # The finished messages are always sent after encryption is in effect,
# so we will not be able to read those message. # so we will not be able to read those messages.
type Finished(rec: SSLRecord) = record { type Finished(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient; cont : bytestring &restofdata &transient;
} &let { } &let {
@ -620,13 +614,17 @@ type Finished(rec: SSLRecord) = record {
$context.connection.lost_track(); $context.connection.lost_track();
}; };
type SessionTicketHandshake(rec: SSLRecord) = record {
ticket_lifetime_hint: uint32;
data: bytestring &restofdata;
};
###################################################################### ######################################################################
# V3 Handshake Protocol (7.) # V3 Handshake Protocol (7.)
###################################################################### ######################################################################
type UnknownHandshake(hs: Handshake, is_orig: bool) = record { type UnknownHandshake(hs: Handshake, is_orig: bool) = record {
cont : bytestring &restofdata &transient; data : bytestring &restofdata &transient;
} &let { } &let {
state_changed : bool = $context.connection.lost_track(); state_changed : bool = $context.connection.lost_track();
}; };
@ -636,19 +634,20 @@ type Handshake(rec: SSLRecord) = record {
length : uint24; length : uint24;
body : case msg_type of { body : case msg_type of {
HELLO_REQUEST -> hello_request : HelloRequest(rec); HELLO_REQUEST -> hello_request : HelloRequest(rec);
CLIENT_HELLO -> client_hello : ClientHello(rec); CLIENT_HELLO -> client_hello : ClientHello(rec);
SERVER_HELLO -> server_hello : ServerHello(rec); SERVER_HELLO -> server_hello : ServerHello(rec);
CERTIFICATE -> certificate : Certificate(rec); SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec);
SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec); CERTIFICATE -> certificate : Certificate(rec);
CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec); SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec); CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec); SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec);
CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec); CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec);
FINISHED -> finished : Finished(rec); CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec);
CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient; FINISHED -> finished : Finished(rec);
CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient; CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient;
default -> unknown_handshake : UnknownHandshake(this, rec.is_orig); CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient;
default -> unknown_handshake : UnknownHandshake(this, rec.is_orig);
} &length = to_int()(length); } &length = to_int()(length);
}; };
@ -663,7 +662,7 @@ type UnknownRecord(rec: SSLRecord) = record {
state_changed : bool = $context.connection.lost_track(); state_changed : bool = $context.connection.lost_track();
}; };
type CiphertextRecord(rec: SSLRecord, is_orig: bool) = record { type CiphertextRecord(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient; cont : bytestring &restofdata &transient;
} &let { } &let {
state_changed : bool = state_changed : bool =