Merge remote-tracking branch 'origin/master' into topic/johanna/ocsp-new

This commit is contained in:
Johanna Amann 2017-03-16 12:28:08 -07:00
commit 7aa219758c
99 changed files with 2110 additions and 795 deletions

View file

@ -78,34 +78,23 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
if ( f$source != "KRB_TCP" && f$source != "KRB" )
return;
local info: Info;
if ( ! c?$krb )
{
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
}
else
info = c$krb;
set_session(c);
if ( is_orig )
{
info$client_cert = f$info;
info$client_cert_fuid = f$id;
c$krb$client_cert = f$info;
c$krb$client_cert_fuid = f$id;
}
else
{
info$server_cert = f$info;
info$server_cert_fuid = f$id;
c$krb$server_cert = f$info;
c$krb$server_cert_fuid = f$id;
}
c$krb = info;
}
function fill_in_subjects(c: connection)
{
if ( !c?$krb )
if ( ! c?$krb )
return;
if ( c$krb?$client_cert && c$krb$client_cert?$x509 && c$krb$client_cert$x509?$certificate )

View file

@ -10,41 +10,41 @@ export {
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
ts: time &log;
## Unique ID for the connection.
uid: string &log;
uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
id: conn_id &log;
## Request type - Authentication Service ("AS") or
## Ticket Granting Service ("TGS")
request_type: string &log &optional;
request_type: string &log &optional;
## Client
client: string &log &optional;
client: string &log &optional;
## Service
service: string &log;
service: string &log &optional;
## Request result
success: bool &log &optional;
success: bool &log &optional;
## Error code
error_code: count &optional;
error_code: count &optional;
## Error message
error_msg: string &log &optional;
error_msg: string &log &optional;
## Ticket valid from
from: time &log &optional;
from: time &log &optional;
## Ticket valid till
till: time &log &optional;
till: time &log &optional;
## Ticket encryption type
cipher: string &log &optional;
cipher: string &log &optional;
## Forwardable ticket requested
forwardable: bool &log &optional;
forwardable: bool &log &optional;
## Renewable ticket requested
renewable: bool &log &optional;
renewable: bool &log &optional;
## We've already logged this
logged: bool &default=F;
logged: bool &default=F;
};
## The server response error texts which are *not* logged.
@ -80,172 +80,140 @@ event bro_init() &priority=5
Log::create_stream(KRB::LOG, [$columns=Info, $ev=log_krb, $path="kerberos"]);
}
event krb_error(c: connection, msg: Error_Msg) &priority=5
function set_session(c: connection): bool
{
local info: Info;
if ( msg?$error_text && msg$error_text in ignored_errors )
if ( ! c?$krb )
{
if ( c?$krb ) delete c$krb;
return;
c$krb = Info($ts = network_time(),
$uid = c$uid,
$id = c$id);
}
if ( c?$krb && c$krb$logged )
return;
if ( c?$krb )
info = c$krb;
if ( ! info?$ts )
{
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
}
if ( ! info?$client && ( msg?$client_name || msg?$client_realm ) )
info$client = fmt("%s%s", msg?$client_name ? msg$client_name + "/" : "",
msg?$client_realm ? msg$client_realm : "");
info$service = msg$service_name;
info$success = F;
info$error_code = msg$error_code;
if ( msg?$error_text ) info$error_msg = msg$error_text;
else if ( msg$error_code in error_msg ) info$error_msg = error_msg[msg$error_code];
c$krb = info;
return c$krb$logged;
}
event krb_error(c: connection, msg: Error_Msg) &priority=-5
function do_log(c: connection)
{
if ( c?$krb )
if ( c?$krb && ! c$krb$logged )
{
Log::write(KRB::LOG, c$krb);
c$krb$logged = T;
}
}
event krb_as_request(c: connection, msg: KDC_Request) &priority=5
event krb_error(c: connection, msg: Error_Msg) &priority=5
{
if ( c?$krb && c$krb$logged )
if ( set_session(c) )
return;
local info: Info;
if ( !c?$krb )
if ( msg?$error_text && msg$error_text in ignored_errors )
{
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
if ( c?$krb )
delete c$krb;
return;
}
else
info = c$krb;
info$request_type = "AS";
info$client = fmt("%s/%s", msg?$client_name ? msg$client_name : "", msg$service_realm);
info$service = msg$service_name;
if ( ! c$krb?$client && ( msg?$client_name || msg?$client_realm ) )
c$krb$client = fmt("%s%s", msg?$client_name ? msg$client_name + "/" : "",
msg?$client_realm ? msg$client_realm : "");
if ( msg?$from )
info$from = msg$from;
c$krb$service = msg$service_name;
c$krb$success = F;
c$krb$error_code = msg$error_code;
info$till = msg$till;
info$forwardable = msg$kdc_options$forwardable;
info$renewable = msg$kdc_options$renewable;
c$krb = info;
if ( msg?$error_text )
c$krb$error_msg = msg$error_text;
else if ( msg$error_code in error_msg )
c$krb$error_msg = error_msg[msg$error_code];
}
event krb_tgs_request(c: connection, msg: KDC_Request) &priority=5
event krb_error(c: connection, msg: Error_Msg) &priority=-5
{
if ( c?$krb && c$krb$logged )
do_log(c);
}
event krb_as_request(c: connection, msg: KDC_Request) &priority=5
{
if ( set_session(c) )
return;
local info: Info;
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
info$request_type = "TGS";
info$service = msg$service_name;
if ( msg?$from ) info$from = msg$from;
info$till = msg$till;
c$krb$request_type = "AS";
c$krb$client = fmt("%s/%s", msg?$client_name ? msg$client_name : "", msg$service_realm);
c$krb$service = msg$service_name;
info$forwardable = msg$kdc_options$forwardable;
info$renewable = msg$kdc_options$renewable;
if ( msg?$from )
c$krb$from = msg$from;
c$krb$till = msg$till;
c$krb = info;
c$krb$forwardable = msg$kdc_options$forwardable;
c$krb$renewable = msg$kdc_options$renewable;
}
event krb_as_response(c: connection, msg: KDC_Response) &priority=5
{
local info: Info;
if ( c?$krb && c$krb$logged )
if ( set_session(c) )
return;
if ( c?$krb )
info = c$krb;
if ( ! info?$ts )
if ( ! c$krb?$client && ( msg?$client_name || msg?$client_realm ) )
{
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
c$krb$client = fmt("%s/%s", msg?$client_name ? msg$client_name : "",
msg?$client_realm ? msg$client_realm : "");
}
if ( ! info?$client && ( msg?$client_name || msg?$client_realm ) )
info$client = fmt("%s/%s", msg?$client_name ? msg$client_name : "", msg?$client_realm ? msg$client_realm : "");
info$service = msg$ticket$service_name;
info$cipher = cipher_name[msg$ticket$cipher];
info$success = T;
c$krb = info;
c$krb$service = msg$ticket$service_name;
c$krb$cipher = cipher_name[msg$ticket$cipher];
c$krb$success = T;
}
event krb_as_response(c: connection, msg: KDC_Response) &priority=-5
{
Log::write(KRB::LOG, c$krb);
c$krb$logged = T;
do_log(c);
}
event krb_ap_request(c: connection, ticket: KRB::Ticket, opts: KRB::AP_Options) &priority=5
{
if ( set_session(c) )
return;
}
event krb_tgs_request(c: connection, msg: KDC_Request) &priority=5
{
if ( set_session(c) )
return;
c$krb$request_type = "TGS";
c$krb$service = msg$service_name;
if ( msg?$from )
c$krb$from = msg$from;
c$krb$till = msg$till;
c$krb$forwardable = msg$kdc_options$forwardable;
c$krb$renewable = msg$kdc_options$renewable;
}
event krb_tgs_response(c: connection, msg: KDC_Response) &priority=5
{
local info: Info;
if ( c?$krb && c$krb$logged )
if ( set_session(c) )
return;
if ( c?$krb )
info = c$krb;
if ( ! info?$ts )
if ( ! c$krb?$client && ( msg?$client_name || msg?$client_realm ) )
{
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
c$krb$client = fmt("%s/%s", msg?$client_name ? msg$client_name : "",
msg?$client_realm ? msg$client_realm : "");
}
if ( ! info?$client && ( msg?$client_name || msg?$client_realm ) )
info$client = fmt("%s/%s", msg?$client_name ? msg$client_name : "", msg?$client_realm ? msg$client_realm : "");
info$service = msg$ticket$service_name;
info$cipher = cipher_name[msg$ticket$cipher];
info$success = T;
c$krb = info;
c$krb$service = msg$ticket$service_name;
c$krb$cipher = cipher_name[msg$ticket$cipher];
c$krb$success = T;
}
event krb_tgs_response(c: connection, msg: KDC_Response) &priority=-5
{
Log::write(KRB::LOG, c$krb);
c$krb$logged = T;
do_log(c);
}
event connection_state_remove(c: connection) &priority=-5
{
if ( c?$krb && ! c$krb$logged )
Log::write(KRB::LOG, c$krb);
do_log(c);
}

View file

@ -10,52 +10,51 @@ export {
type Info: record {
## Timestamp for when the event happened.
ts : time &log;
ts : time &log;
## Unique ID for the connection.
uid : string &log;
uid : string &log;
## The connection's 4-tuple of endpoint addresses/ports.
id : conn_id &log;
id : conn_id &log;
## The username, if present.
username : string &log &optional;
username : string &log &optional;
## MAC address, if present.
mac : string &log &optional;
## Remote IP address, if present.
remote_ip : addr &log &optional;
mac : string &log &optional;
## The address given to the network access server, if
## present. This is only a hint from the RADIUS server
## and the network access server is not required to honor
## the address.
framed_addr : addr &log &optional;
## Remote IP address, if present. This is collected
## from the Tunnel-Client-Endpoint attribute.
remote_ip : addr &log &optional;
## Connect info, if present.
connect_info : string &log &optional;
connect_info : string &log &optional;
## Reply message from the server challenge. This is
## frequently shown to the user authenticating.
reply_msg : string &log &optional;
## Successful or failed authentication.
result : string &log &optional;
## Whether this has already been logged and can be ignored.
logged : bool &optional;
result : string &log &optional;
## The duration between the first request and
## either the "Access-Accept" message or an error.
## If the field is empty, it means that either
## the request or response was not seen.
ttl : interval &log &optional;
## Whether this has already been logged and can be ignored.
logged : bool &default=F;
};
## The amount of time we wait for an authentication response before
## expiring it.
const expiration_interval = 10secs &redef;
## Logs an authentication attempt if we didn't see a response in time.
##
## t: A table of Info records.
##
## idx: The index of the connection$radius table corresponding to the
## radius authentication about to expire.
##
## Returns: 0secs, which when this function is used as an
## :bro:attr:`&expire_func`, indicates to remove the element at
## *idx* immediately.
global expire: function(t: table[count] of Info, idx: count): interval;
## Event that can be handled to access the RADIUS record as it is sent on
## to the loggin framework.
## to the logging framework.
global log_radius: event(rec: Info);
}
redef record connection += {
radius: table[count] of Info &optional &write_expire=expiration_interval &expire_func=expire;
radius: Info &optional;
};
const ports = { 1812/udp };
redef likely_server_ports += { ports };
event bro_init() &priority=5
{
@ -63,64 +62,86 @@ event bro_init() &priority=5
Analyzer::register_for_ports(Analyzer::ANALYZER_RADIUS, ports);
}
event radius_message(c: connection, result: RADIUS::Message)
event radius_message(c: connection, result: RADIUS::Message) &priority=5
{
local info: Info;
if ( c?$radius && result$trans_id in c$radius )
info = c$radius[result$trans_id];
else
if ( ! c?$radius )
{
c$radius = table();
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
c$radius = Info($ts = network_time(),
$uid = c$uid,
$id = c$id);
}
switch ( RADIUS::msg_types[result$code] ) {
switch ( RADIUS::msg_types[result$code] )
{
case "Access-Request":
if ( result?$attributes ) {
if ( result?$attributes )
{
# User-Name
if ( ! info?$username && 1 in result$attributes )
info$username = result$attributes[1][0];
if ( ! c$radius?$username && 1 in result$attributes )
c$radius$username = result$attributes[1][0];
# Calling-Station-Id (we expect this to be a MAC)
if ( ! info?$mac && 31 in result$attributes )
info$mac = normalize_mac(result$attributes[31][0]);
if ( ! c$radius?$mac && 31 in result$attributes )
c$radius$mac = normalize_mac(result$attributes[31][0]);
# Tunnel-Client-EndPoint (useful for VPNs)
if ( ! info?$remote_ip && 66 in result$attributes )
info$remote_ip = to_addr(result$attributes[66][0]);
if ( ! c$radius?$remote_ip && 66 in result$attributes )
c$radius$remote_ip = to_addr(result$attributes[66][0]);
# Connect-Info
if ( ! info?$connect_info && 77 in result$attributes )
info$connect_info = result$attributes[77][0];
}
if ( ! c$radius?$connect_info && 77 in result$attributes )
c$radius$connect_info = result$attributes[77][0];
}
break;
case "Access-Challenge":
if ( result?$attributes )
{
# Framed-IP-Address
if ( ! c$radius?$framed_addr && 8 in result$attributes )
c$radius$framed_addr = raw_bytes_to_v4_addr(result$attributes[8][0]);
if ( ! c$radius?$reply_msg && 18 in result$attributes )
c$radius$reply_msg = result$attributes[18][0];
}
break;
case "Access-Accept":
info$result = "success";
c$radius$result = "success";
break;
case "Access-Reject":
info$result = "failed";
c$radius$result = "failed";
break;
}
if ( info?$result && ! info?$logged )
{
info$logged = T;
Log::write(RADIUS::LOG, info);
# TODO: Support RADIUS accounting. (add port 1813/udp above too)
#case "Accounting-Request":
# break;
#
#case "Accounting-Response":
# break;
}
c$radius[result$trans_id] = info;
}
event radius_message(c: connection, result: RADIUS::Message) &priority=-5
{
if ( c$radius?$result )
{
local ttl = network_time() - c$radius$ts;
if ( ttl != 0secs )
c$radius$ttl = ttl;
function expire(t: table[count] of Info, idx: count): interval
{
t[idx]$result = "unknown";
Log::write(RADIUS::LOG, t[idx]);
return 0secs;
}
Log::write(RADIUS::LOG, c$radius);
delete c$radius;
}
}
event connection_state_remove(c: connection) &priority=-5
{
if ( c?$radius && ! c$radius$logged )
{
c$radius$result = "unknown";
Log::write(RADIUS::LOG, c$radius);
}
}