mirror of
https://github.com/zeek/zeek.git
synced 2025-10-17 05:58:20 +00:00
Remove measurement scripts
This commit is contained in:
parent
da9b5425e4
commit
d92fd52b35
2 changed files with 0 additions and 1066 deletions
|
@ -1,481 +0,0 @@
|
|||
#! Match OCSP request and response to SSL connection for performance analysis
|
||||
|
||||
@load base/protocols/http
|
||||
@load base/frameworks/files
|
||||
@load base/files/x509
|
||||
@load base/protocols/ssl
|
||||
@load base/utils/queue
|
||||
|
||||
module OCSP_MEASUREMENT;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## cert id for the OCSP request
|
||||
cert_id: OCSP::CertId &log &optional;
|
||||
|
||||
## request timestamp
|
||||
req_ts: time &log &optional;
|
||||
|
||||
## request
|
||||
## NOTE: this is only one request if multiple requests
|
||||
## are sent together in one HTTP message, they will be
|
||||
## logged separately
|
||||
req: OCSP::Info_req &log &optional;
|
||||
|
||||
## response timestamp
|
||||
resp_ts: time &log &optional;
|
||||
|
||||
## response
|
||||
## NOTE: similar to request, if multiple responses are
|
||||
## sent together in one HTTP message, they will be
|
||||
## logged separately
|
||||
resp: OCSP::Info_resp &log &optional;
|
||||
|
||||
## HTTP connection uid
|
||||
cuid: string &log;
|
||||
|
||||
## HTTP connection start time
|
||||
conn_start_ts: time &log;
|
||||
|
||||
## for 1st request, this is the time between first TCP
|
||||
## SYN and resp_ts; for the rest of the requests in
|
||||
## the same connection, this is the time btween req_ts
|
||||
## and resp_ts
|
||||
delay: interval &log &optional;
|
||||
|
||||
## the size of HTTP request body
|
||||
req_size: count &log &optional;
|
||||
|
||||
## the size of HTTP request header
|
||||
req_hdr_size: count &log &optional;
|
||||
|
||||
## the size of HTTP response body
|
||||
resp_size: count &log &optional;
|
||||
|
||||
## the size of HTTP response header
|
||||
resp_hdr_size: count &log &optional;
|
||||
|
||||
## the HTTP code in the HTTP response
|
||||
http_code: count &log &optional;
|
||||
|
||||
## OCSP host, this is host in HTTP request
|
||||
host: string &log;
|
||||
|
||||
## OCSP uri, this is uri in HTTP request
|
||||
uri: string &log;
|
||||
|
||||
## number of HTTP request containing ocsp requests in
|
||||
## this connection including this one; this may be
|
||||
## different from number of OCSP requests since one
|
||||
## HTTP request may contain several OCSP requests
|
||||
num_ocsp: count &log &optional;
|
||||
|
||||
## the time when the corresponding certificate is
|
||||
## received
|
||||
cert_recv_ts: time &log &optional;
|
||||
|
||||
## SSL connection uid
|
||||
ssl_cuid: string &log &optional;
|
||||
|
||||
## SSL connection id
|
||||
ssl_cid: conn_id &optional;
|
||||
|
||||
## the time when client receives change cipher message
|
||||
## from server
|
||||
ssl_change_cipher_ts: time &log &optional;
|
||||
|
||||
## the time when SSL connection is established
|
||||
ssl_establish_ts: time &log &optional;
|
||||
|
||||
## the time when event connection_state_remove happens
|
||||
ssl_end_ts: time &log &optional;
|
||||
};
|
||||
|
||||
## a group of constant string for hash algorithm
|
||||
## to save memory, remove any unseen hash algorithm
|
||||
global hash_algorithm = vector("sha1", "sha224", "sha256", "sha384", "sha512");
|
||||
|
||||
## Event from a worker to the manager that it has encountered
|
||||
## an OCSP response
|
||||
global new_ocsp_info: event(c: connection) &redef;
|
||||
|
||||
## Event from the manager to the workers that a new OCSP info
|
||||
## is to be added.
|
||||
global ocsp_info_add: event(c: connection);
|
||||
}
|
||||
|
||||
## - map to OCSP_MEASUREMENT::Info
|
||||
## - indexed by hash algorithm(string), source ip(addr), ocsp
|
||||
## uri(string), issuer name hash(string), serialNumber(string)
|
||||
## - is it possible server sends two same certificate? To be
|
||||
## safe, let's use a queue to store OCSP_MEASUREMENT::Info
|
||||
global ocsp_map: table[string, addr, string, string, string] of Queue::Queue &read_expire=6mins;
|
||||
|
||||
# track number of ocsp requests in this connection
|
||||
redef record connection += {
|
||||
num_ocsp: count &optional &default=0;
|
||||
};
|
||||
|
||||
# add additional information to http info
|
||||
redef record HTTP::Info += {
|
||||
## header length
|
||||
request_header_len: count &optional &default=0;
|
||||
response_header_len: count &optional &default=0;
|
||||
|
||||
## OCSP file id
|
||||
ocsp_request_fuid: string &optional;
|
||||
ocsp_response_fuid: string &optional;
|
||||
|
||||
## OCSP request and response timestamp
|
||||
ocsp_request_ts: time &optional;
|
||||
ocsp_response_ts: time &optional;
|
||||
|
||||
## store OCSP requests and responses
|
||||
ocsp_request: OCSP::Request &optional;
|
||||
ocsp_response: OCSP::Response &optional;
|
||||
};
|
||||
|
||||
# add additional information to ssl info
|
||||
redef record SSL::Info += {
|
||||
## connection start time
|
||||
connection_start_ts: time &optional;
|
||||
|
||||
## client hello time
|
||||
client_hello_ts: time &optional;
|
||||
|
||||
## ssl connection establish time
|
||||
ssl_establish_ts: time &optional;
|
||||
|
||||
## the time when server sends change-cipher-spec
|
||||
change_cipher_ts: time &optional;
|
||||
|
||||
## - the time when a cert is received AND the cert has ocsp
|
||||
## extension
|
||||
## - the 2nd level table indexed by source ip(addr), ocsp
|
||||
## uri(string), issuer name hash(string), serialNumber
|
||||
## (string)
|
||||
## - the 1st level table indexed by different hash algorithm
|
||||
## for issuer name hash
|
||||
## - is it possible a server sends two same certificate? To be
|
||||
## safe, let's use a queue to store the time
|
||||
cert_ts: table[string] of table[addr, string, string, string] of Queue::Queue &optional;
|
||||
};
|
||||
|
||||
# set up cluster event
|
||||
@if ( Cluster::is_enabled() )
|
||||
@load base/frameworks/cluster
|
||||
redef Cluster::manager2worker_events += /OCSP_MEASUREMENT::ocsp_info_add/;
|
||||
redef Cluster::worker2manager_events += /OCSP_MEASUREMENT::new_ocsp_info/;
|
||||
@endif
|
||||
|
||||
# get all the requests in one HTTP request
|
||||
function get_all_requests(http: HTTP::Info): table[OCSP::CertId] of Queue::Queue
|
||||
{
|
||||
local pending_requests: table[OCSP::CertId] of Queue::Queue = table();
|
||||
if ( http?$ocsp_request && http$ocsp_request?$requestList )
|
||||
{
|
||||
local req = http$ocsp_request;
|
||||
for (x in req$requestList)
|
||||
{
|
||||
local one_req = req$requestList[x];
|
||||
local cert_id: OCSP::CertId = [$hashAlgorithm = one_req$hashAlgorithm,
|
||||
$issuerNameHash = one_req$issuerNameHash,
|
||||
$issuerKeyHash = one_req$issuerKeyHash,
|
||||
$serialNumber = one_req$serialNumber];
|
||||
|
||||
local req_rec: OCSP::Info_req = [$ts=http$ocsp_request_ts, $id=http$ocsp_request_fuid, $certId=cert_id];
|
||||
|
||||
if (req?$version)
|
||||
req_rec$version = req$version;
|
||||
|
||||
if (req?$requestorName)
|
||||
req_rec$requestorName = req$requestorName;
|
||||
|
||||
if (cert_id !in pending_requests)
|
||||
pending_requests[cert_id] = Queue::init();
|
||||
|
||||
Queue::put(pending_requests[cert_id], req_rec);
|
||||
}
|
||||
}
|
||||
return pending_requests;
|
||||
}
|
||||
|
||||
# remove the last '/'
|
||||
function clean_uri(s: string): string
|
||||
{
|
||||
local s_len = |s|;
|
||||
s_len -= 1;
|
||||
if (s[-1] == "/")
|
||||
return clean_uri(s[0:s_len]);
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
# fill in OCSP/HTTP information
|
||||
function fill_ocsp_info(c: connection)
|
||||
{
|
||||
local http: HTTP::Info = c$http;
|
||||
|
||||
# get all the requests which will be matched to response later
|
||||
local pending_requests: table[OCSP::CertId] of Queue::Queue = get_all_requests(http);
|
||||
|
||||
# get all the responses and match them to the requests
|
||||
if ( http?$ocsp_response && http$ocsp_response?$responses )
|
||||
{
|
||||
local resp = http$ocsp_response;
|
||||
for (x in resp$responses)
|
||||
{
|
||||
local single_resp: OCSP::SingleResp = resp$responses[x];
|
||||
local cert_id: OCSP::CertId = [$hashAlgorithm = single_resp$hashAlgorithm,
|
||||
$issuerNameHash = single_resp$issuerNameHash,
|
||||
$issuerKeyHash = single_resp$issuerKeyHash,
|
||||
$serialNumber = single_resp$serialNumber];
|
||||
|
||||
local resp_rec: OCSP::Info_resp = [$ts = http$ocsp_response_ts,
|
||||
$id = http$ocsp_response_fuid,
|
||||
$responseStatus = resp$responseStatus,
|
||||
$responseType = resp$responseType,
|
||||
$version = resp$version,
|
||||
$responderID = resp$responderID,
|
||||
$producedAt = resp$producedAt,
|
||||
$certId = cert_id,
|
||||
$certStatus = single_resp$certStatus,
|
||||
$thisUpdate = single_resp$thisUpdate];
|
||||
|
||||
if (single_resp?$nextUpdate)
|
||||
resp_rec$nextUpdate = single_resp$nextUpdate;
|
||||
|
||||
local ocsp_info: OCSP_MEASUREMENT::Info = [$cert_id = cert_id,
|
||||
$cuid = http$uid,
|
||||
$conn_start_ts = c$start_time,
|
||||
$host = http$host,
|
||||
$uri = http$uri,
|
||||
$resp_ts = resp_rec$ts,
|
||||
$resp = resp_rec,
|
||||
$req_size = http$request_body_len,
|
||||
$req_hdr_size = http$request_header_len,
|
||||
$resp_size = http$response_body_len,
|
||||
$resp_hdr_size = http$response_header_len,
|
||||
$http_code = http$status_code];
|
||||
if (cert_id in pending_requests)
|
||||
{
|
||||
# find a match
|
||||
local req_rec: OCSP::Info_req = Queue::get(pending_requests[cert_id]);
|
||||
ocsp_info$req = req_rec;
|
||||
ocsp_info$req_ts = req_rec$ts;
|
||||
ocsp_info$num_ocsp = c$num_ocsp;
|
||||
|
||||
if (c$num_ocsp == 1)
|
||||
ocsp_info$delay = ocsp_info$resp$ts - c$start_time;
|
||||
else
|
||||
ocsp_info$delay = ocsp_info$resp$ts - ocsp_info$req$ts;
|
||||
|
||||
if (Queue::len(pending_requests[cert_id]) == 0)
|
||||
delete pending_requests[cert_id]; #if queue is empty, delete it?
|
||||
}
|
||||
|
||||
# add to ocsp map
|
||||
local full_uri: string = clean_uri(http$host + http$uri);
|
||||
local h = cert_id$hashAlgorithm;
|
||||
local src_ip: addr = c$id$orig_h;
|
||||
|
||||
if ( [h, src_ip, full_uri, cert_id$issuerNameHash, cert_id$serialNumber] !in ocsp_map )
|
||||
ocsp_map[h, src_ip, full_uri, cert_id$issuerNameHash, cert_id$serialNumber] = Queue::init();
|
||||
|
||||
Queue::put(ocsp_map[h, src_ip, full_uri, cert_id$issuerNameHash, cert_id$serialNumber], ocsp_info);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# work event
|
||||
@if ( Cluster::is_enabled() && Cluster::local_node_type() != Cluster::MANAGER )
|
||||
event OCSP_MEASUREMENT::ocsp_info_add(c: connection)
|
||||
{
|
||||
fill_ocsp_info(c);
|
||||
}
|
||||
@endif
|
||||
|
||||
# manager event
|
||||
@if ( Cluster::is_enabled() && Cluster::local_node_type() == Cluster::MANAGER )
|
||||
event OCSP_MEASUREMENT::new_ocsp_info(c: connection)
|
||||
{
|
||||
event OCSP_MEASUREMENT::ocsp_info_add(c);
|
||||
}
|
||||
@endif
|
||||
|
||||
# record the header length
|
||||
event http_message_done(c: connection, is_orig: bool, stat: http_message_stat)
|
||||
{
|
||||
# proceed only this http connection has ocsp request or response
|
||||
if ( ! c$http?$ocsp_request && ! c$http?$ocsp_response )
|
||||
return;
|
||||
|
||||
if ( is_orig )
|
||||
{
|
||||
c$http$request_header_len = stat$header_length;
|
||||
c$num_ocsp += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c$http$response_header_len = stat$header_length;
|
||||
# here, a http request-response is done
|
||||
# if any ocsp info is present, put it in ocsp_map
|
||||
@if ( ! Cluster::is_enabled() )
|
||||
fill_ocsp_info(c);
|
||||
@endif
|
||||
|
||||
@if ( Cluster::is_enabled() )
|
||||
# send this ocsp info to manager and manager will send
|
||||
# it to all the workder
|
||||
event OCSP_MEASUREMENT::new_ocsp_info(c);
|
||||
@endif
|
||||
}
|
||||
}
|
||||
|
||||
# add ocsp request to http record
|
||||
event ocsp_request(f: fa_file, req_ref: opaque of ocsp_req, req: OCSP::Request)
|
||||
{
|
||||
if ( !f?$http )
|
||||
return;
|
||||
f$http$ocsp_request = req;
|
||||
f$http$ocsp_request_ts = network_time();
|
||||
f$http$ocsp_request_fuid = f$id;
|
||||
}
|
||||
|
||||
# add ocsp response to http record
|
||||
event ocsp_response(f: fa_file, resp_ref: opaque of ocsp_resp, resp: OCSP::Response)
|
||||
{
|
||||
if ( !f?$http )
|
||||
return;
|
||||
f$http$ocsp_response = resp;
|
||||
f$http$ocsp_response_ts = network_time();
|
||||
f$http$ocsp_response_fuid = f$id;
|
||||
}
|
||||
|
||||
# add client hello time and connection start time
|
||||
event ssl_client_hello(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: index_vec)
|
||||
{
|
||||
c$ssl$client_hello_ts = network_time();
|
||||
c$ssl$connection_start_ts = c$start_time;
|
||||
}
|
||||
|
||||
# add time stamp for server's change cipher message
|
||||
event ssl_change_cipher_spec(c: connection, is_orig: bool)
|
||||
{
|
||||
if ( is_orig )
|
||||
return;
|
||||
c$ssl$change_cipher_ts = network_time();
|
||||
}
|
||||
|
||||
# add ssl established time
|
||||
event ssl_established(c: connection)
|
||||
{
|
||||
c$ssl$ssl_establish_ts = network_time();
|
||||
}
|
||||
|
||||
# extract the full ocsp uri from certificate extension
|
||||
function get_ocsp_uri(s: string): string
|
||||
{
|
||||
s = strip(s);
|
||||
s = to_lower(s);
|
||||
local parts = split_string(s, /\x0a/);
|
||||
for (x in parts)
|
||||
{
|
||||
local f4c = sub_bytes(parts[x], 0, 4);
|
||||
if (f4c == "ocsp")
|
||||
{
|
||||
local w = split_string(parts[x], /\/\//);
|
||||
return w[1];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
# create ocsp index if ocsp extension is encountered
|
||||
# record the time when certificate is received
|
||||
event x509_extension(f: fa_file, ext: X509::Extension) &priority= -10 {
|
||||
if (!ext?$name || ext$name != "Authority Information Access")
|
||||
return;
|
||||
|
||||
if ( !f?$info || !f$info?$x509 || !f$info$x509?$handle || !f$info$x509?$certificate)
|
||||
return;
|
||||
|
||||
local ocsp_uri: string = clean_uri(get_ocsp_uri(ext$value));
|
||||
if ( |ocsp_uri| == 0 )
|
||||
return;
|
||||
|
||||
local cert: X509::Certificate = f$info$x509$certificate;
|
||||
local serial_number: string = cert$serial;
|
||||
local cert_ref: opaque of x509 = f$info$x509$handle;
|
||||
|
||||
# get connection
|
||||
local c: connection;
|
||||
# there should be only one loop
|
||||
for ( id in f$conns )
|
||||
c = f$conns[id];
|
||||
|
||||
if ( !c$ssl?$cert_ts )
|
||||
c$ssl$cert_ts = table();
|
||||
|
||||
local current_ts: time = network_time();
|
||||
local source_ip: addr = c$id$orig_h;
|
||||
|
||||
local issuer_name: table[string] of string;
|
||||
# loop through each hash algorithm
|
||||
for (i in hash_algorithm)
|
||||
{
|
||||
local h: string = hash_algorithm[i];
|
||||
issuer_name[h] = x509_issuer_name_hash(cert_ref, h);
|
||||
|
||||
# if given hash algorithm is not in record, create a new table
|
||||
if ( h !in c$ssl$cert_ts )
|
||||
c$ssl$cert_ts[h] = table();
|
||||
|
||||
# if given index is not in record, create a new queue
|
||||
if ( [source_ip, ocsp_uri, issuer_name[h], serial_number] !in c$ssl$cert_ts[h] )
|
||||
c$ssl$cert_ts[h][source_ip, ocsp_uri, issuer_name[h], serial_number] = Queue::init();
|
||||
|
||||
# put the timing information in the queue of ssl info
|
||||
Queue::put(c$ssl$cert_ts[h][source_ip, ocsp_uri, issuer_name[h], serial_number], current_ts);
|
||||
}
|
||||
}
|
||||
|
||||
# log information when ssl connection is removed
|
||||
event connection_state_remove(c: connection) &priority= -20
|
||||
{
|
||||
if ( ! c?$ssl || ! c$ssl?$cert_ts )
|
||||
return;
|
||||
|
||||
for (i in hash_algorithm)
|
||||
{
|
||||
local h = hash_algorithm[i];
|
||||
for ( [src_ip, ocsp_uri, issuer_name, serial_number] in c$ssl$cert_ts[h] )
|
||||
{
|
||||
if ( [h, src_ip, ocsp_uri, issuer_name, serial_number] in ocsp_map )
|
||||
{
|
||||
# find a ocsp to ssl match
|
||||
local ocsp_info: OCSP_MEASUREMENT::Info = Queue::get(ocsp_map[h, src_ip, ocsp_uri, issuer_name, serial_number]);
|
||||
if (Queue::len(ocsp_map[h, src_ip, ocsp_uri, issuer_name, serial_number]) == 0)
|
||||
delete ocsp_map[h, src_ip, ocsp_uri, issuer_name, serial_number];
|
||||
local cert_recv_ts: time = Queue::get(c$ssl$cert_ts[h][src_ip, ocsp_uri, issuer_name, serial_number]);
|
||||
if (Queue::len(c$ssl$cert_ts[h][src_ip, ocsp_uri, issuer_name, serial_number]) == 0)
|
||||
delete c$ssl$cert_ts[h][src_ip, ocsp_uri, issuer_name, serial_number];
|
||||
ocsp_info$cert_recv_ts = cert_recv_ts;
|
||||
ocsp_info$ssl_cuid = c$uid;
|
||||
ocsp_info$ssl_cid = c$id;
|
||||
ocsp_info$ssl_change_cipher_ts = c$ssl$change_cipher_ts;
|
||||
ocsp_info$ssl_establish_ts = c$ssl$ssl_establish_ts;
|
||||
ocsp_info$ssl_end_ts = network_time();
|
||||
Log::write(LOG, ocsp_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event bro_init()
|
||||
{
|
||||
Log::create_stream(LOG, [$columns=Info, $path="ocsp-measurement"]);
|
||||
}
|
|
@ -1,585 +0,0 @@
|
|||
#! log OCSP request, response and related HTTP information
|
||||
#! log SSL connection which has cert with OCSP uri
|
||||
|
||||
@load base/protocols/http
|
||||
@load base/frameworks/files
|
||||
@load base/files/x509
|
||||
@load base/protocols/ssl
|
||||
@load base/utils/queue
|
||||
|
||||
module OCSP_SSL_SPLIT;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG_OCSP };
|
||||
redef enum Log::ID += { LOG_SSL };
|
||||
|
||||
type Info_OCSP: record {
|
||||
## cert id for the OCSP request
|
||||
cert_id: OCSP::CertId &log &optional;
|
||||
|
||||
## request timestamp
|
||||
req_ts: time &log &optional;
|
||||
|
||||
## request
|
||||
## NOTE: this is only one request if multiple requests
|
||||
## are sent together in one HTTP message, they will be
|
||||
## logged separately
|
||||
req: OCSP::Info_req &log &optional;
|
||||
|
||||
## response timestamp
|
||||
resp_ts: time &log &optional;
|
||||
|
||||
## response
|
||||
## NOTE: similar to request, if multiple responses are
|
||||
## sent together in one HTTP message, they will be
|
||||
## logged separately
|
||||
resp: OCSP::Info_resp &log &optional;
|
||||
|
||||
## HTTP connection id
|
||||
cid: conn_id &log;
|
||||
|
||||
## HTTP connection uid
|
||||
cuid: string &log;
|
||||
|
||||
## HTTP connection start time
|
||||
conn_start_ts: time &log;
|
||||
|
||||
## the time between req_ts and resp_ts
|
||||
delay: interval &log &optional;
|
||||
|
||||
## the size of HTTP request body
|
||||
req_size: count &log &optional;
|
||||
|
||||
## the size of HTTP request header
|
||||
req_hdr_size: count &log &optional;
|
||||
|
||||
## the size of HTTP response body
|
||||
resp_size: count &log &optional;
|
||||
|
||||
## the size of HTTP response header
|
||||
resp_hdr_size: count &log &optional;
|
||||
|
||||
## the HTTP code in the HTTP response
|
||||
http_code: count &log &optional;
|
||||
|
||||
## HTTP method
|
||||
method: string &log &optional;
|
||||
|
||||
## host in HTTP request + uri in HTTP request
|
||||
## last '/' is removed
|
||||
## for GET request, OCSP request is remove from url
|
||||
ocsp_uri: string &log &optional;
|
||||
|
||||
## number of HTTP requests containing ocsp requests in
|
||||
## this connection including this one; this may be
|
||||
## different from number of OCSP requests since one
|
||||
## HTTP request may contain several OCSP requests;
|
||||
## this is copied from connection
|
||||
num_ocsp: count &log &optional;
|
||||
|
||||
## the original_uri in HTTP request
|
||||
original_uri: string &log &optional;
|
||||
|
||||
## host in HTTP request
|
||||
host: string &log &optional;
|
||||
|
||||
## user_agent
|
||||
user_agent: string &log &optional;
|
||||
|
||||
## number of certificates in response
|
||||
resp_certs_num: count &log &default=0;
|
||||
};
|
||||
|
||||
type Issuer_Name_Type: record {
|
||||
sha1: string &log &optional;
|
||||
sha224: string &log &optional;
|
||||
sha256: string &log &optional;
|
||||
sha384: string &log &optional;
|
||||
sha512: string &log &optional;
|
||||
};
|
||||
|
||||
type Info_SSL: record {
|
||||
## connection id
|
||||
id: conn_id &log;
|
||||
|
||||
## uid
|
||||
uid: string &log;
|
||||
|
||||
## connection start time
|
||||
conn_start_ts: time &log &optional;
|
||||
|
||||
## client hello time
|
||||
client_hello_ts: time &log &optional;
|
||||
|
||||
## server hello time
|
||||
server_hello_ts: time &log &optional;
|
||||
|
||||
## the time for client change cipher message
|
||||
client_change_cipher_ts: time &log &optional;
|
||||
|
||||
## the time for server change cipher message
|
||||
server_change_cipher_ts: time &log &optional;
|
||||
|
||||
## the time when SSL connection is established
|
||||
establish_ts: time &log &optional;
|
||||
|
||||
## the time for the first encrypted client application data
|
||||
client_first_encrypt_ts: time &log &optional;
|
||||
|
||||
## the time for the first encrypted server application data
|
||||
server_first_encrypt_ts: time &log &optional;
|
||||
|
||||
## the time when event connection_state_remove happens
|
||||
end_ts: time &log &optional;
|
||||
|
||||
## the above are common information for SSL connection
|
||||
## the following is specific to an cert
|
||||
|
||||
## ocsp_uri
|
||||
ocsp_uri: string &log &optional;
|
||||
|
||||
## serial_number
|
||||
serial_number: string &log &optional;
|
||||
|
||||
## the time when the corresponding certificate is
|
||||
## received; formatted as: str(time),str(time)
|
||||
cert_recv_ts: string &log &optional;
|
||||
|
||||
## issuer_name
|
||||
issuer_name: Issuer_Name_Type &log &optional;
|
||||
};
|
||||
}
|
||||
|
||||
redef SSL::disable_analyzer_after_detection=F;
|
||||
|
||||
redef record connection += {
|
||||
## track number of ocsp requests in this connection
|
||||
num_ocsp: count &optional &default=0;
|
||||
};
|
||||
|
||||
# add additional information to http info
|
||||
redef record HTTP::Info += {
|
||||
## header length
|
||||
request_header_len: count &optional &default=0;
|
||||
response_header_len: count &optional &default=0;
|
||||
|
||||
## number of OCSP requests so far, copied from connection
|
||||
num_ocsp: count &optional;
|
||||
|
||||
## connection start time, copied from connection
|
||||
conn_start_ts: time &optional;
|
||||
};
|
||||
|
||||
# add additional information to ssl info
|
||||
redef record SSL::Info += {
|
||||
## connection start time
|
||||
conn_start_ts: time &optional;
|
||||
|
||||
## the time when client hello event happens
|
||||
client_hello_ts: time &optional;
|
||||
|
||||
## server hello time
|
||||
server_hello_ts: time &optional;
|
||||
|
||||
## the time when ssl connection is established
|
||||
establish_ts: time &optional;
|
||||
|
||||
## the time for client change cipher message
|
||||
client_change_cipher_ts: time &optional;
|
||||
|
||||
## the time for server change cipher message
|
||||
server_change_cipher_ts: time &optional;
|
||||
|
||||
## indexed by ocsp_uri(string), serialNumber(string), issuer
|
||||
## name hash(string)
|
||||
cert_ts: table[string, string, OCSP_SSL_SPLIT::Issuer_Name_Type] of Queue::Queue &optional;
|
||||
|
||||
## the time for the first encrypted client application data
|
||||
client_first_encrypt_ts: time &optional;
|
||||
|
||||
## the time for the first encrypted server application data
|
||||
server_first_encrypt_ts: time &optional;
|
||||
};
|
||||
|
||||
# remove the last '/'
|
||||
function clean_uri(s: string): string
|
||||
{
|
||||
local s_len = |s|;
|
||||
if ( s_len == 0 )
|
||||
return s;
|
||||
s_len -= 1;
|
||||
if (s[-1] == "/")
|
||||
return clean_uri(s[0:s_len]);
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
event ocsp_response(f: fa_file, resp_ref: opaque of ocsp_resp, resp: OCSP::Response)
|
||||
{
|
||||
if ( ! f?$http )
|
||||
return;
|
||||
|
||||
# get connection id TODO:TOCHECK
|
||||
local cid: conn_id;
|
||||
for ( id in f$conns )
|
||||
cid = id;
|
||||
|
||||
# check if there is a OCSP GET request
|
||||
if ( f$http?$method && f$http$method == "GET" )
|
||||
f$conns[cid]$num_ocsp += 1;
|
||||
}
|
||||
|
||||
event ocsp_request(f: fa_file, req_ref: opaque of ocsp_req, req: OCSP::Request)
|
||||
{
|
||||
if ( ! f?$http )
|
||||
return;
|
||||
|
||||
# get connection id TODO:TOCHECK
|
||||
local cid: conn_id;
|
||||
for ( id in f$conns )
|
||||
cid = id;
|
||||
|
||||
f$conns[cid]$num_ocsp += 1;
|
||||
}
|
||||
|
||||
event http_reply (c: connection, version: string, code: count, reason: string)
|
||||
{
|
||||
if ( ! c?$http )
|
||||
return;
|
||||
if ( ! c$http?$conn_start_ts )
|
||||
c$http$conn_start_ts = c$start_time;
|
||||
}
|
||||
|
||||
event http_request(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string)
|
||||
{
|
||||
if ( ! c?$http )
|
||||
return;
|
||||
if ( ! c$http?$conn_start_ts )
|
||||
c$http$conn_start_ts = c$start_time;
|
||||
}
|
||||
|
||||
# record the header length
|
||||
event http_message_done(c: connection, is_orig: bool, stat: http_message_stat)
|
||||
{
|
||||
if ( ! c?$http )
|
||||
return;
|
||||
if ( is_orig )
|
||||
c$http$request_header_len = stat$header_length;
|
||||
else
|
||||
c$http$response_header_len = stat$header_length;
|
||||
c$http$num_ocsp = c$num_ocsp;
|
||||
}
|
||||
|
||||
# add server hello time
|
||||
event ssl_server_hello(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count)&priority=5
|
||||
{
|
||||
c$ssl$server_hello_ts = network_time();
|
||||
}
|
||||
|
||||
# add client hello time and connection start time
|
||||
event ssl_client_hello(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: index_vec)
|
||||
{
|
||||
c$ssl$client_hello_ts = network_time();
|
||||
c$ssl$conn_start_ts = c$start_time;
|
||||
}
|
||||
|
||||
# add time stamp for server's change cipher message
|
||||
event ssl_change_cipher_spec(c: connection, is_orig: bool)
|
||||
{
|
||||
if ( is_orig )
|
||||
c$ssl$client_change_cipher_ts = network_time();
|
||||
else
|
||||
c$ssl$server_change_cipher_ts = network_time();
|
||||
}
|
||||
|
||||
# add ssl established time
|
||||
event ssl_established(c: connection)
|
||||
{
|
||||
c$ssl$establish_ts = network_time();
|
||||
}
|
||||
|
||||
# add time when first encrypted application data is sent from client
|
||||
event ssl_encrypted_data(c: connection, is_orig: bool, content_type: count, length: count)
|
||||
{
|
||||
if ( ! c?$ssl )
|
||||
return;
|
||||
|
||||
if ( content_type == SSL::APPLICATION_DATA && length > 0 )
|
||||
{
|
||||
if ( is_orig && ! c$ssl?$client_first_encrypt_ts )
|
||||
c$ssl$client_first_encrypt_ts = network_time();
|
||||
else if ( ! is_orig && ! c$ssl?$server_first_encrypt_ts )
|
||||
c$ssl$server_first_encrypt_ts = network_time();
|
||||
}
|
||||
}
|
||||
|
||||
# extract the full ocsp uri from certificate extension
|
||||
function get_ocsp_uri(s: string): string
|
||||
{
|
||||
s = strip(s);
|
||||
s = to_lower(s);
|
||||
local parts = split_string(s, /\x0a/);
|
||||
for (x in parts)
|
||||
{
|
||||
local f4c = sub_bytes(parts[x], 0, 4);
|
||||
if (f4c == "ocsp")
|
||||
{
|
||||
local w = split_string(parts[x], /\/\//);
|
||||
return w[1];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
# create ocsp index if ocsp extension is encountered
|
||||
# record the time when certificate is received
|
||||
event x509_extension(f: fa_file, ext: X509::Extension) &priority= -10 {
|
||||
if ( ! ext?$name || ext$name != "Authority Information Access")
|
||||
return;
|
||||
|
||||
if ( ! f?$info || ! f$info?$x509 || ! f$info$x509?$handle || ! f$info$x509?$certificate)
|
||||
return;
|
||||
|
||||
local ocsp_uri: string = clean_uri(get_ocsp_uri(ext$value));
|
||||
if ( |ocsp_uri| == 0 )
|
||||
return;
|
||||
|
||||
local cert: X509::Certificate = f$info$x509$certificate;
|
||||
local serial_number: string = cert$serial;
|
||||
local cert_ref: opaque of x509 = f$info$x509$handle;
|
||||
|
||||
# get connection TODO:TOCHECK
|
||||
local c: connection;
|
||||
# there should be only one loop?
|
||||
for ( id in f$conns )
|
||||
c = f$conns[id];
|
||||
|
||||
if ( ! c$ssl?$cert_ts )
|
||||
c$ssl$cert_ts = table();
|
||||
|
||||
local current_ts: time = network_time();
|
||||
|
||||
local issuer_name: Issuer_Name_Type;
|
||||
issuer_name$sha1 = x509_issuer_name_hash(cert_ref, "sha1");
|
||||
issuer_name$sha224 = x509_issuer_name_hash(cert_ref, "sha224");
|
||||
issuer_name$sha256 = x509_issuer_name_hash(cert_ref, "sha256");
|
||||
issuer_name$sha384 = x509_issuer_name_hash(cert_ref, "sha384");
|
||||
issuer_name$sha512 = x509_issuer_name_hash(cert_ref, "sha512");
|
||||
|
||||
# if given index is not in record, create a new queue
|
||||
if ( [ocsp_uri, serial_number, issuer_name] !in c$ssl$cert_ts )
|
||||
c$ssl$cert_ts[ocsp_uri, serial_number, issuer_name] = Queue::init();
|
||||
|
||||
# put the timing information in the queue
|
||||
Queue::put(c$ssl$cert_ts[ocsp_uri, serial_number, issuer_name], current_ts);
|
||||
}
|
||||
|
||||
function clean_bug_host(host: string): string
|
||||
{
|
||||
local s: string = host;
|
||||
s = clean_uri(s);
|
||||
if ( s[0:7] == "http://" )
|
||||
s = s[7:];
|
||||
return s;
|
||||
}
|
||||
|
||||
function clean_bug_uri(uri: string, host: string): string
|
||||
{
|
||||
local s: string = uri;
|
||||
s = clean_uri(s);
|
||||
if ( s[0:7] == "http://" )
|
||||
s = s[7:];
|
||||
|
||||
if ( |host| > 0 && s[0:|host|] == host )
|
||||
s = s[|host|:];
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function update_http_info(ocsp: OCSP_SSL_SPLIT::Info_OCSP, http: HTTP::Info)
|
||||
{
|
||||
if ( http?$num_ocsp )
|
||||
ocsp$num_ocsp = http$num_ocsp;
|
||||
|
||||
if ( http?$method )
|
||||
ocsp$method = http$method;
|
||||
|
||||
if ( http?$user_agent )
|
||||
ocsp$user_agent = http$user_agent;
|
||||
|
||||
if ( http?$original_uri )
|
||||
ocsp$original_uri = http$original_uri;
|
||||
|
||||
local host_str: string = "";
|
||||
if ( http?$host )
|
||||
host_str = clean_bug_host(http$host);
|
||||
|
||||
local uri_str: string = "";
|
||||
if ( http?$uri)
|
||||
{
|
||||
if (http?$host)
|
||||
uri_str = clean_bug_uri(http$uri, host_str);
|
||||
else
|
||||
uri_str = clean_bug_uri(http$uri, "");
|
||||
}
|
||||
|
||||
if ( http?$host )
|
||||
{
|
||||
ocsp$host = host_str;
|
||||
ocsp$ocsp_uri = host_str;
|
||||
}
|
||||
|
||||
if ( http?$uri )
|
||||
{
|
||||
if ( ocsp?$ocsp_uri )
|
||||
ocsp$ocsp_uri += uri_str;
|
||||
else
|
||||
ocsp$ocsp_uri = uri_str;
|
||||
}
|
||||
|
||||
if ( http?$method && http$method == "GET" && http?$uri_prefix )
|
||||
{
|
||||
if ( |http$uri_prefix| > 0)
|
||||
ocsp$ocsp_uri = "";
|
||||
if ( http?$host )
|
||||
ocsp$ocsp_uri = host_str;
|
||||
if ( |http$uri_prefix| > 0)
|
||||
ocsp$ocsp_uri += http$uri_prefix;
|
||||
}
|
||||
|
||||
if ( ocsp?$ocsp_uri )
|
||||
ocsp$ocsp_uri = clean_uri(ocsp$ocsp_uri);
|
||||
|
||||
if ( http?$status_code )
|
||||
ocsp$http_code = http$status_code;
|
||||
|
||||
if ( http?$request_body_len )
|
||||
ocsp$req_size = http$request_body_len;
|
||||
|
||||
if ( http?$request_header_len )
|
||||
ocsp$req_hdr_size = http$request_header_len;
|
||||
|
||||
if ( http?$response_body_len )
|
||||
ocsp$resp_size = http$response_body_len;
|
||||
|
||||
if ( http?$response_header_len )
|
||||
ocsp$resp_hdr_size = http$response_header_len;
|
||||
}
|
||||
|
||||
function start_log_ocsp(rec: OCSP::Info)
|
||||
{
|
||||
local http: HTTP::Info = rec$http;
|
||||
local info_ocsp_rec: OCSP_SSL_SPLIT::Info_OCSP = [$cid = http$id,
|
||||
$cuid = http$uid,
|
||||
$conn_start_ts = http$conn_start_ts];
|
||||
|
||||
if ( rec?$certId )
|
||||
info_ocsp_rec$cert_id = rec$certId;
|
||||
|
||||
if ( rec?$req )
|
||||
{
|
||||
info_ocsp_rec$req = rec$req;
|
||||
info_ocsp_rec$req_ts = rec$req$ts;
|
||||
}
|
||||
|
||||
if ( rec?$resp )
|
||||
{
|
||||
info_ocsp_rec$resp = rec$resp;
|
||||
info_ocsp_rec$resp_ts = rec$resp$ts;
|
||||
if ( rec$resp?$certs )
|
||||
info_ocsp_rec$resp_certs_num = |rec$resp$certs|;
|
||||
}
|
||||
|
||||
if ( rec?$req && rec?$resp )
|
||||
info_ocsp_rec$delay = info_ocsp_rec$resp_ts - info_ocsp_rec$req_ts;
|
||||
|
||||
update_http_info(info_ocsp_rec, http);
|
||||
|
||||
if ( Site::is_private_addr(info_ocsp_rec$cid$orig_h) || !Site::is_local_addr(info_ocsp_rec$cid$orig_h) )
|
||||
return;
|
||||
|
||||
Log::write(LOG_OCSP, info_ocsp_rec);
|
||||
}
|
||||
|
||||
# log OCSP information
|
||||
event OCSP::log_ocsp(rec: OCSP::Info)
|
||||
{
|
||||
start_log_ocsp(rec);
|
||||
}
|
||||
|
||||
# update ssl info
|
||||
function update_ssl_info(ssl_rec: OCSP_SSL_SPLIT::Info_SSL, ssl: SSL::Info)
|
||||
{
|
||||
if ( ssl?$conn_start_ts )
|
||||
ssl_rec$conn_start_ts = ssl$conn_start_ts;
|
||||
|
||||
if ( ssl?$client_hello_ts )
|
||||
ssl_rec$client_hello_ts = ssl$client_hello_ts;
|
||||
|
||||
if ( ssl?$client_first_encrypt_ts )
|
||||
ssl_rec$client_first_encrypt_ts = ssl$client_first_encrypt_ts;
|
||||
|
||||
if ( ssl?$server_first_encrypt_ts )
|
||||
ssl_rec$server_first_encrypt_ts = ssl$server_first_encrypt_ts;
|
||||
|
||||
if ( ssl?$server_hello_ts )
|
||||
ssl_rec$server_hello_ts = ssl$server_hello_ts;
|
||||
|
||||
if ( ssl?$establish_ts )
|
||||
ssl_rec$establish_ts = ssl$establish_ts;
|
||||
|
||||
if ( ssl?$client_change_cipher_ts )
|
||||
ssl_rec$client_change_cipher_ts = ssl$client_change_cipher_ts;
|
||||
|
||||
if ( ssl?$server_change_cipher_ts )
|
||||
ssl_rec$server_change_cipher_ts = ssl$server_change_cipher_ts;
|
||||
}
|
||||
|
||||
# convert all the elements in the queue to a formatted string
|
||||
function convert_time_q2str(q: Queue::Queue, sep: string): string
|
||||
{
|
||||
local s = "";
|
||||
local elem: vector of time = vector();
|
||||
Queue::get_vector(q, elem);
|
||||
for ( i in elem )
|
||||
{
|
||||
s += fmt("%f",elem[i]);
|
||||
if ( i != (|elem| - 1))
|
||||
s += sep;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
# log SSL information when ssl connection is removed
|
||||
event connection_state_remove(c: connection) &priority= -20
|
||||
{
|
||||
if ( ! c?$ssl || ! c$ssl?$cert_ts )
|
||||
return;
|
||||
|
||||
for ( [ocsp_uri, serial_number, issuer_name] in c$ssl$cert_ts )
|
||||
{
|
||||
local ssl_info_rec: OCSP_SSL_SPLIT::Info_SSL = [$id = c$id,
|
||||
$uid = c$uid,
|
||||
$end_ts = network_time()];
|
||||
ssl_info_rec$ocsp_uri = ocsp_uri;
|
||||
ssl_info_rec$serial_number = serial_number;
|
||||
ssl_info_rec$issuer_name = issuer_name;
|
||||
local cert_recv_ts_str:string = convert_time_q2str(c$ssl$cert_ts[ocsp_uri, serial_number, issuer_name], ",");
|
||||
if (|cert_recv_ts_str| > 0)
|
||||
ssl_info_rec$cert_recv_ts = cert_recv_ts_str;
|
||||
update_ssl_info(ssl_info_rec, c$ssl);
|
||||
|
||||
if ( Site::is_private_addr(ssl_info_rec$id$orig_h) || !Site::is_local_addr(ssl_info_rec$id$orig_h) )
|
||||
return;
|
||||
|
||||
Log::write(LOG_SSL, ssl_info_rec);
|
||||
#delete c$ssl$cert_ts[ocsp_uri, serial_number, issuer_name];
|
||||
}
|
||||
clear_table(c$ssl$cert_ts);
|
||||
}
|
||||
|
||||
event bro_init()
|
||||
{
|
||||
Log::create_stream(LOG_OCSP, [$columns=Info_OCSP, $path="ocsp-to-match"]);
|
||||
Log::create_stream(LOG_SSL, [$columns=Info_SSL, $path="ssl-to-match"]);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue