mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
Merge remote-tracking branch 'origin/master' into topic/vladg/ssh
Conflicts: src/analyzer/protocol/CMakeLists.txt src/analyzer/protocol/ssh/Plugin.cc src/analyzer/protocol/ssh/SSH.h
This commit is contained in:
commit
fa98aee0a7
954 changed files with 128195 additions and 90795 deletions
|
@ -47,13 +47,13 @@ redef record connection += {
|
|||
const ports = { 67/udp, 68/udp };
|
||||
redef likely_server_ports += { 67/udp };
|
||||
|
||||
event bro_init()
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_DHCP, ports);
|
||||
}
|
||||
|
||||
event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string)
|
||||
event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=5
|
||||
{
|
||||
local info: Info;
|
||||
info$ts = network_time();
|
||||
|
@ -71,6 +71,9 @@ event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_lis
|
|||
info$assigned_ip = c$id$orig_h;
|
||||
|
||||
c$dhcp = info;
|
||||
}
|
||||
|
||||
event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=-5
|
||||
{
|
||||
Log::write(DHCP::LOG, c$dhcp);
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ function log_unmatched_msgs(msgs: PendingMessages)
|
|||
for ( trans_id in msgs )
|
||||
log_unmatched_msgs_queue(msgs[trans_id]);
|
||||
|
||||
msgs = PendingMessages();
|
||||
clear_table(msgs);
|
||||
}
|
||||
|
||||
function enqueue_new_msg(msgs: PendingMessages, id: count, msg: Info)
|
||||
|
@ -382,9 +382,19 @@ event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priori
|
|||
hook DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
}
|
||||
|
||||
event dns_TXT_reply(c: connection, msg: dns_msg, ans: dns_answer, str: string) &priority=5
|
||||
event dns_TXT_reply(c: connection, msg: dns_msg, ans: dns_answer, strs: string_vec) &priority=5
|
||||
{
|
||||
hook DNS::do_reply(c, msg, ans, str);
|
||||
local txt_strings: string = "";
|
||||
|
||||
for ( i in strs )
|
||||
{
|
||||
if ( i > 0 )
|
||||
txt_strings += " ";
|
||||
|
||||
txt_strings += fmt("TXT %d %s", |strs[i]|, strs[i]);
|
||||
}
|
||||
|
||||
hook DNS::do_reply(c, msg, ans, txt_strings);
|
||||
}
|
||||
|
||||
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5
|
||||
|
|
|
@ -72,7 +72,7 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
|
|||
|
||||
if ( f$is_orig )
|
||||
{
|
||||
if ( ! c$http?$orig_mime_types )
|
||||
if ( ! c$http?$orig_fuids )
|
||||
c$http$orig_fuids = string_vec(f$id);
|
||||
else
|
||||
c$http$orig_fuids[|c$http$orig_fuids|] = f$id;
|
||||
|
@ -87,7 +87,7 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
|
|||
}
|
||||
else
|
||||
{
|
||||
if ( ! c$http?$resp_mime_types )
|
||||
if ( ! c$http?$resp_fuids )
|
||||
c$http$resp_fuids = string_vec(f$id);
|
||||
else
|
||||
c$http$resp_fuids[|c$http$resp_fuids|] = f$id;
|
||||
|
|
|
@ -76,7 +76,7 @@ event irc_dcc_message(c: connection, is_orig: bool,
|
|||
dcc_expected_transfers[address, p] = c$irc;
|
||||
}
|
||||
|
||||
event expected_connection_seen(c: connection, a: Analyzer::Tag) &priority=10
|
||||
event scheduled_analyzer_applied(c: connection, a: Analyzer::Tag) &priority=10
|
||||
{
|
||||
local id = c$id;
|
||||
if ( [id$resp_h, id$resp_p] in dcc_expected_transfers )
|
||||
|
|
1
scripts/base/protocols/mysql/__load__.bro
Normal file
1
scripts/base/protocols/mysql/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
38
scripts/base/protocols/mysql/consts.bro
Normal file
38
scripts/base/protocols/mysql/consts.bro
Normal file
|
@ -0,0 +1,38 @@
|
|||
module MySQL;
|
||||
|
||||
export {
|
||||
const commands: table[count] of string = {
|
||||
[0] = "sleep",
|
||||
[1] = "quit",
|
||||
[2] = "init_db",
|
||||
[3] = "query",
|
||||
[4] = "field_list",
|
||||
[5] = "create_db",
|
||||
[6] = "drop_db",
|
||||
[7] = "refresh",
|
||||
[8] = "shutdown",
|
||||
[9] = "statistics",
|
||||
[10] = "process_info",
|
||||
[11] = "connect",
|
||||
[12] = "process_kill",
|
||||
[13] = "debug",
|
||||
[14] = "ping",
|
||||
[15] = "time",
|
||||
[16] = "delayed_insert",
|
||||
[17] = "change_user",
|
||||
[18] = "binlog_dump",
|
||||
[19] = "table_dump",
|
||||
[20] = "connect_out",
|
||||
[21] = "register_slave",
|
||||
[22] = "stmt_prepare",
|
||||
[23] = "stmt_execute",
|
||||
[24] = "stmt_send_long_data",
|
||||
[25] = "stmt_close",
|
||||
[26] = "stmt_reset",
|
||||
[27] = "set_option",
|
||||
[28] = "stmt_fetch",
|
||||
[29] = "daemon",
|
||||
[30] = "binlog_dump_gtid",
|
||||
[31] = "reset_connection",
|
||||
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||
}
|
116
scripts/base/protocols/mysql/main.bro
Normal file
116
scripts/base/protocols/mysql/main.bro
Normal file
|
@ -0,0 +1,116 @@
|
|||
##! Implements base functionality for MySQL analysis. Generates the mysql.log file.
|
||||
|
||||
module MySQL;
|
||||
|
||||
@load ./consts
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { mysql::LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp for when the event happened.
|
||||
ts: time &log;
|
||||
## Unique ID for the connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## The command that was issued
|
||||
cmd: string &log;
|
||||
## The argument issued to the command
|
||||
arg: string &log;
|
||||
## The result (error, OK, etc.) from the server
|
||||
result: string &log &optional;
|
||||
## Server message, if any
|
||||
response: string &log &optional;
|
||||
};
|
||||
|
||||
## Event that can be handled to access the MySQL record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_mysql: event(rec: Info);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
mysql: Info &optional;
|
||||
};
|
||||
|
||||
const ports = { 1434/tcp, 3306/tcp };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(mysql::LOG, [$columns=Info, $ev=log_mysql]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_MYSQL, ports);
|
||||
}
|
||||
|
||||
event mysql_handshake(c: connection, username: string)
|
||||
{
|
||||
if ( ! c?$mysql )
|
||||
{
|
||||
local info: Info;
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
info$cmd = "login";
|
||||
info$arg = username;
|
||||
c$mysql = info;
|
||||
}
|
||||
}
|
||||
|
||||
event mysql_command_request(c: connection, command: count, arg: string) &priority=5
|
||||
{
|
||||
if ( ! c?$mysql )
|
||||
{
|
||||
local info: Info;
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
info$cmd = commands[command];
|
||||
info$arg = sub(arg, /\0$/, "");
|
||||
c$mysql = info;
|
||||
}
|
||||
}
|
||||
|
||||
event mysql_command_request(c: connection, command: count, arg: string) &priority=-5
|
||||
{
|
||||
if ( c?$mysql && c$mysql?$cmd && c$mysql$cmd == "quit" )
|
||||
{
|
||||
# We get no response for quits, so let's just log it now.
|
||||
Log::write(mysql::LOG, c$mysql);
|
||||
delete c$mysql;
|
||||
}
|
||||
}
|
||||
|
||||
event mysql_error(c: connection, code: count, msg: string) &priority=5
|
||||
{
|
||||
if ( c?$mysql )
|
||||
{
|
||||
c$mysql$result = "error";
|
||||
c$mysql$response = msg;
|
||||
}
|
||||
}
|
||||
|
||||
event mysql_error(c: connection, code: count, msg: string) &priority=-5
|
||||
{
|
||||
if ( c?$mysql )
|
||||
{
|
||||
Log::write(mysql::LOG, c$mysql);
|
||||
delete c$mysql;
|
||||
}
|
||||
}
|
||||
|
||||
event mysql_ok(c: connection, affected_rows: count) &priority=5
|
||||
{
|
||||
if ( c?$mysql )
|
||||
{
|
||||
c$mysql$result = "ok";
|
||||
c$mysql$response = fmt("Affected rows: %d", affected_rows);
|
||||
}
|
||||
}
|
||||
|
||||
event mysql_ok(c: connection, affected_rows: count) &priority=-5
|
||||
{
|
||||
if ( c?$mysql )
|
||||
{
|
||||
Log::write(mysql::LOG, c$mysql);
|
||||
delete c$mysql;
|
||||
}
|
||||
}
|
1
scripts/base/protocols/radius/__load__.bro
Normal file
1
scripts/base/protocols/radius/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
231
scripts/base/protocols/radius/consts.bro
Normal file
231
scripts/base/protocols/radius/consts.bro
Normal file
|
@ -0,0 +1,231 @@
|
|||
|
||||
module RADIUS;
|
||||
|
||||
const msg_types: table[count] of string = {
|
||||
[1] = "Access-Request",
|
||||
[2] = "Access-Accept",
|
||||
[3] = "Access-Reject",
|
||||
[4] = "Accounting-Request",
|
||||
[5] = "Accounting-Response",
|
||||
[11] = "Access-Challenge",
|
||||
[12] = "Status-Server",
|
||||
[13] = "Status-Client",
|
||||
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||
|
||||
const attr_types: table[count] of string = {
|
||||
[1] = "User-Name",
|
||||
[2] = "User-Password",
|
||||
[3] = "CHAP-Password",
|
||||
[4] = "NAS-IP-Address",
|
||||
[5] = "NAS-Port",
|
||||
[6] = "Service-Type",
|
||||
[7] = "Framed-Protocol",
|
||||
[8] = "Framed-IP-Address",
|
||||
[9] = "Framed-IP-Netmask",
|
||||
[10] = "Framed-Routing",
|
||||
[11] = "Filter-Id",
|
||||
[12] = "Framed-MTU",
|
||||
[13] = "Framed-Compression",
|
||||
[14] = "Login-IP-Host",
|
||||
[15] = "Login-Service",
|
||||
[16] = "Login-TCP-Port",
|
||||
[18] = "Reply-Message",
|
||||
[19] = "Callback-Number",
|
||||
[20] = "Callback-Id",
|
||||
[22] = "Framed-Route",
|
||||
[23] = "Framed-IPX-Network",
|
||||
[24] = "State",
|
||||
[25] = "Class",
|
||||
[26] = "Vendor-Specific",
|
||||
[27] = "Session-Timeout",
|
||||
[28] = "Idle-Timeout",
|
||||
[29] = "Termination-Action",
|
||||
[30] = "Called-Station-Id",
|
||||
[31] = "Calling-Station-Id",
|
||||
[32] = "NAS-Identifier",
|
||||
[33] = "Proxy-State",
|
||||
[34] = "Login-LAT-Service",
|
||||
[35] = "Login-LAT-Node",
|
||||
[36] = "Login-LAT-Group",
|
||||
[37] = "Framed-AppleTalk-Link",
|
||||
[38] = "Framed-AppleTalk-Network",
|
||||
[39] = "Framed-AppleTalk-Zone",
|
||||
[40] = "Acct-Status-Type",
|
||||
[41] = "Acct-Delay-Time",
|
||||
[42] = "Acct-Input-Octets",
|
||||
[43] = "Acct-Output-Octets",
|
||||
[44] = "Acct-Session-Id",
|
||||
[45] = "Acct-Authentic",
|
||||
[46] = "Acct-Session-Time",
|
||||
[47] = "Acct-Input-Packets",
|
||||
[48] = "Acct-Output-Packets",
|
||||
[49] = "Acct-Terminate-Cause",
|
||||
[50] = "Acct-Multi-Session-Id",
|
||||
[51] = "Acct-Link-Count",
|
||||
[52] = "Acct-Input-Gigawords",
|
||||
[53] = "Acct-Output-Gigawords",
|
||||
[55] = "Event-Timestamp",
|
||||
[56] = "Egress-VLANID",
|
||||
[57] = "Ingress-Filters",
|
||||
[58] = "Egress-VLAN-Name",
|
||||
[59] = "User-Priority-Table",
|
||||
[60] = "CHAP-Challenge",
|
||||
[61] = "NAS-Port-Type",
|
||||
[62] = "Port-Limit",
|
||||
[63] = "Login-LAT-Port",
|
||||
[64] = "Tunnel-Type",
|
||||
[65] = "Tunnel-Medium-Type",
|
||||
[66] = "Tunnel-Client-EndPoint",
|
||||
[67] = "Tunnel-Server-EndPoint",
|
||||
[68] = "Acct-Tunnel-Connection",
|
||||
[69] = "Tunnel-Password",
|
||||
[70] = "ARAP-Password",
|
||||
[71] = "ARAP-Features",
|
||||
[72] = "ARAP-Zone-Access",
|
||||
[73] = "ARAP-Security",
|
||||
[74] = "ARAP-Security-Data",
|
||||
[75] = "Password-Retry",
|
||||
[76] = "Prompt",
|
||||
[77] = "Connect-Info",
|
||||
[78] = "Configuration-Token",
|
||||
[79] = "EAP-Message",
|
||||
[80] = "Message Authenticator",
|
||||
[81] = "Tunnel-Private-Group-ID",
|
||||
[82] = "Tunnel-Assignment-ID",
|
||||
[83] = "Tunnel-Preference",
|
||||
[84] = "ARAP-Challenge-Response",
|
||||
[85] = "Acct-Interim-Interval",
|
||||
[86] = "Acct-Tunnel-Packets-Lost",
|
||||
[87] = "NAS-Port-Id",
|
||||
[88] = "Framed-Pool",
|
||||
[89] = "CUI",
|
||||
[90] = "Tunnel-Client-Auth-ID",
|
||||
[91] = "Tunnel-Server-Auth-ID",
|
||||
[92] = "NAS-Filter-Rule",
|
||||
[94] = "Originating-Line-Info",
|
||||
[95] = "NAS-IPv6-Address",
|
||||
[96] = "Framed-Interface-Id",
|
||||
[97] = "Framed-IPv6-Prefix",
|
||||
[98] = "Login-IPv6-Host",
|
||||
[99] = "Framed-IPv6-Route",
|
||||
[100] = "Framed-IPv6-Pool",
|
||||
[101] = "Error-Cause",
|
||||
[102] = "EAP-Key-Name",
|
||||
[103] = "Digest-Response",
|
||||
[104] = "Digest-Realm",
|
||||
[105] = "Digest-Nonce",
|
||||
[106] = "Digest-Response-Auth",
|
||||
[107] = "Digest-Nextnonce",
|
||||
[108] = "Digest-Method",
|
||||
[109] = "Digest-URI",
|
||||
[110] = "Digest-Qop",
|
||||
[111] = "Digest-Algorithm",
|
||||
[112] = "Digest-Entity-Body-Hash",
|
||||
[113] = "Digest-CNonce",
|
||||
[114] = "Digest-Nonce-Count",
|
||||
[115] = "Digest-Username",
|
||||
[116] = "Digest-Opaque",
|
||||
[117] = "Digest-Auth-Param",
|
||||
[118] = "Digest-AKA-Auts",
|
||||
[119] = "Digest-Domain",
|
||||
[120] = "Digest-Stale",
|
||||
[121] = "Digest-HA1",
|
||||
[122] = "SIP-AOR",
|
||||
[123] = "Delegated-IPv6-Prefix",
|
||||
[124] = "MIP6-Feature-Vector",
|
||||
[125] = "MIP6-Home-Link-Prefix",
|
||||
[126] = "Operator-Name",
|
||||
[127] = "Location-Information",
|
||||
[128] = "Location-Data",
|
||||
[129] = "Basic-Location-Policy-Rules",
|
||||
[130] = "Extended-Location-Policy-Rules",
|
||||
[131] = "Location-Capable",
|
||||
[132] = "Requested-Location-Info",
|
||||
[133] = "Framed-Management-Protocol",
|
||||
[134] = "Management-Transport-Protection",
|
||||
[135] = "Management-Policy-Id",
|
||||
[136] = "Management-Privilege-Level",
|
||||
[137] = "PKM-SS-Cert",
|
||||
[138] = "PKM-CA-Cert",
|
||||
[139] = "PKM-Config-Settings",
|
||||
[140] = "PKM-Cryptosuite-List",
|
||||
[141] = "PKM-SAID",
|
||||
[142] = "PKM-SA-Descriptor",
|
||||
[143] = "PKM-Auth-Key",
|
||||
[144] = "DS-Lite-Tunnel-Name",
|
||||
[145] = "Mobile-Node-Identifier",
|
||||
[146] = "Service-Selection",
|
||||
[147] = "PMIP6-Home-LMA-IPv6-Address",
|
||||
[148] = "PMIP6-Visited-LMA-IPv6-Address",
|
||||
[149] = "PMIP6-Home-LMA-IPv4-Address",
|
||||
[150] = "PMIP6-Visited-LMA-IPv4-Address",
|
||||
[151] = "PMIP6-Home-HN-Prefix",
|
||||
[152] = "PMIP6-Visited-HN-Prefix",
|
||||
[153] = "PMIP6-Home-Interface-ID",
|
||||
[154] = "PMIP6-Visited-Interface-ID",
|
||||
[155] = "PMIP6-Home-IPv4-HoA",
|
||||
[156] = "PMIP6-Visited-IPv4-HoA",
|
||||
[157] = "PMIP6-Home-DHCP4-Server-Address",
|
||||
[158] = "PMIP6-Visited-DHCP4-Server-Address",
|
||||
[159] = "PMIP6-Home-DHCP6-Server-Address",
|
||||
[160] = "PMIP6-Visited-DHCP6-Server-Address",
|
||||
[161] = "PMIP6-Home-IPv4-Gateway",
|
||||
[162] = "PMIP6-Visited-IPv4-Gateway",
|
||||
[163] = "EAP-Lower-Layer",
|
||||
[164] = "GSS-Acceptor-Service-Name",
|
||||
[165] = "GSS-Acceptor-Host-Name",
|
||||
[166] = "GSS-Acceptor-Service-Specifics",
|
||||
[167] = "GSS-Acceptor-Realm-Name",
|
||||
[168] = "Framed-IPv6-Address",
|
||||
[169] = "DNS-Server-IPv6-Address",
|
||||
[170] = "Route-IPv6-Information",
|
||||
[171] = "Delegated-IPv6-Prefix-Pool",
|
||||
[172] = "Stateful-IPv6-Address-Pool",
|
||||
[173] = "IPv6-6rd-Configuration"
|
||||
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||
|
||||
const nas_port_types: table[count] of string = {
|
||||
[0] = "Async",
|
||||
[1] = "Sync",
|
||||
[2] = "ISDN Sync",
|
||||
[3] = "ISDN Async V.120",
|
||||
[4] = "ISDN Async V.110",
|
||||
[5] = "Virtual",
|
||||
[6] = "PIAFS",
|
||||
[7] = "HDLC Clear Channel",
|
||||
[8] = "X.25",
|
||||
[9] = "X.75",
|
||||
[10] = "G.3 Fax",
|
||||
[11] = "SDSL - Symmetric DSL",
|
||||
[12] = "ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation",
|
||||
[13] = "ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone",
|
||||
[14] = "IDSL - ISDN Digital Subscriber Line",
|
||||
[15] = "Ethernet",
|
||||
[16] = "xDSL - Digital Subscriber Line of unknown type",
|
||||
[17] = "Cable",
|
||||
[18] = "Wireless - Other",
|
||||
[19] = "Wireless - IEEE 802.11"
|
||||
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||
|
||||
const service_types: table[count] of string = {
|
||||
[1] = "Login",
|
||||
[2] = "Framed",
|
||||
[3] = "Callback Login",
|
||||
[4] = "Callback Framed",
|
||||
[5] = "Outbound",
|
||||
[6] = "Administrative",
|
||||
[7] = "NAS Prompt",
|
||||
[8] = "Authenticate Only",
|
||||
[9] = "Callback NAS Prompt",
|
||||
[10] = "Call Check",
|
||||
[11] = "Callback Administrative",
|
||||
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||
|
||||
const framed_protocol_types: table[count] of string = {
|
||||
[1] = "PPP",
|
||||
[2] = "SLIP",
|
||||
[3] = "AppleTalk Remote Access Protocol (ARAP)",
|
||||
[4] = "Gandalf proprietary SingleLink/MultiLink protocol",
|
||||
[5] = "Xylogics proprietary IPX/SLIP",
|
||||
[6] = "X.75 Synchronous"
|
||||
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
126
scripts/base/protocols/radius/main.bro
Normal file
126
scripts/base/protocols/radius/main.bro
Normal file
|
@ -0,0 +1,126 @@
|
|||
##! Implements base functionality for RADIUS analysis. Generates the radius.log file.
|
||||
|
||||
module RADIUS;
|
||||
|
||||
@load ./consts.bro
|
||||
@load base/utils/addrs
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp for when the event happened.
|
||||
ts : time &log;
|
||||
## Unique ID for the connection.
|
||||
uid : string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id : conn_id &log;
|
||||
## The username, if present.
|
||||
username : string &log &optional;
|
||||
## MAC address, if present.
|
||||
mac : string &log &optional;
|
||||
## Remote IP address, if present.
|
||||
remote_ip : addr &log &optional;
|
||||
## Connect info, if present.
|
||||
connect_info : string &log &optional;
|
||||
## Successful or failed authentication.
|
||||
result : string &log &optional;
|
||||
## Whether this has already been logged and can be ignored.
|
||||
logged : bool &optional;
|
||||
|
||||
};
|
||||
|
||||
## 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.
|
||||
global log_radius: event(rec: Info);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
radius: table[count] of Info &optional &write_expire=expiration_interval &expire_func=expire;
|
||||
};
|
||||
|
||||
const ports = { 1812/udp };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_RADIUS, ports);
|
||||
}
|
||||
|
||||
event radius_message(c: connection, result: RADIUS::Message)
|
||||
{
|
||||
local info: Info;
|
||||
|
||||
if ( c?$radius && result$trans_id in c$radius )
|
||||
info = c$radius[result$trans_id];
|
||||
else
|
||||
{
|
||||
c$radius = table();
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
}
|
||||
|
||||
switch ( RADIUS::msg_types[result$code] ) {
|
||||
case "Access-Request":
|
||||
if ( result?$attributes ) {
|
||||
# User-Name
|
||||
if ( ! info?$username && 1 in result$attributes )
|
||||
info$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]);
|
||||
|
||||
# Tunnel-Client-EndPoint (useful for VPNs)
|
||||
if ( ! info?$remote_ip && 66 in result$attributes )
|
||||
info$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];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Access-Accept":
|
||||
info$result = "success";
|
||||
break;
|
||||
|
||||
case "Access-Reject":
|
||||
info$result = "failed";
|
||||
break;
|
||||
}
|
||||
|
||||
if ( info?$result && ! info?$logged )
|
||||
{
|
||||
info$logged = T;
|
||||
Log::write(RADIUS::LOG, info);
|
||||
}
|
||||
|
||||
c$radius[result$trans_id] = info;
|
||||
}
|
||||
|
||||
|
||||
function expire(t: table[count] of Info, idx: count): interval
|
||||
{
|
||||
t[idx]$result = "unknown";
|
||||
Log::write(RADIUS::LOG, t[idx]);
|
||||
return 0secs;
|
||||
}
|
|
@ -41,13 +41,13 @@ function describe_file(f: fa_file): string
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Files::register_protocol(Analyzer::ANALYZER_SMTP,
|
||||
Files::register_protocol(Analyzer::ANALYZER_SMTP,
|
||||
[$get_file_handle = SMTP::get_file_handle,
|
||||
$describe = SMTP::describe_file]);
|
||||
}
|
||||
|
||||
event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5
|
||||
{
|
||||
if ( c?$smtp )
|
||||
if ( c?$smtp && !c$smtp$tls )
|
||||
c$smtp$fuids[|c$smtp$fuids|] = f$id;
|
||||
}
|
||||
|
|
|
@ -49,38 +49,40 @@ export {
|
|||
path: vector of addr &log &optional;
|
||||
## Value of the User-Agent header from the client.
|
||||
user_agent: string &log &optional;
|
||||
|
||||
|
||||
## Indicates that the connection has switched to using TLS.
|
||||
tls: bool &log &default=F;
|
||||
## Indicates if the "Received: from" headers should still be
|
||||
## processed.
|
||||
process_received_from: bool &default=T;
|
||||
## Indicates if client activity has been seen, but not yet logged.
|
||||
has_client_activity: bool &default=F;
|
||||
};
|
||||
|
||||
|
||||
type State: record {
|
||||
helo: string &optional;
|
||||
## Count the number of individual messages transmitted during
|
||||
## this SMTP session. Note, this is not the number of
|
||||
## recipients, but the number of message bodies transferred.
|
||||
messages_transferred: count &default=0;
|
||||
|
||||
|
||||
pending_messages: set[Info] &optional;
|
||||
};
|
||||
|
||||
|
||||
## Direction to capture the full "Received from" path.
|
||||
## REMOTE_HOSTS - only capture the path until an internal host is found.
|
||||
## LOCAL_HOSTS - only capture the path until the external host is discovered.
|
||||
## ALL_HOSTS - always capture the entire path.
|
||||
## NO_HOSTS - never capture the path.
|
||||
const mail_path_capture = ALL_HOSTS &redef;
|
||||
|
||||
|
||||
## Create an extremely shortened representation of a log line.
|
||||
global describe: function(rec: Info): string;
|
||||
|
||||
global log_smtp: event(rec: Info);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
redef record connection += {
|
||||
smtp: Info &optional;
|
||||
smtp_state: State &optional;
|
||||
};
|
||||
|
@ -93,7 +95,7 @@ event bro_init() &priority=5
|
|||
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SMTP, ports);
|
||||
}
|
||||
|
||||
|
||||
function find_address_in_smtp_header(header: string): string
|
||||
{
|
||||
local ips = find_ip_addresses(header);
|
||||
|
@ -114,17 +116,17 @@ function new_smtp_log(c: connection): Info
|
|||
l$ts=network_time();
|
||||
l$uid=c$uid;
|
||||
l$id=c$id;
|
||||
# The messages_transferred count isn't incremented until the message is
|
||||
# The messages_transferred count isn't incremented until the message is
|
||||
# finished so we need to increment the count by 1 here.
|
||||
l$trans_depth = c$smtp_state$messages_transferred+1;
|
||||
|
||||
|
||||
if ( c$smtp_state?$helo )
|
||||
l$helo = c$smtp_state$helo;
|
||||
|
||||
|
||||
# The path will always end with the hosts involved in this connection.
|
||||
# The lower values in the vector are the end of the path.
|
||||
l$path = vector(c$id$resp_h, c$id$orig_h);
|
||||
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
@ -132,7 +134,7 @@ function set_smtp_session(c: connection)
|
|||
{
|
||||
if ( ! c?$smtp_state )
|
||||
c$smtp_state = [];
|
||||
|
||||
|
||||
if ( ! c?$smtp )
|
||||
c$smtp = new_smtp_log(c);
|
||||
}
|
||||
|
@ -140,17 +142,17 @@ function set_smtp_session(c: connection)
|
|||
function smtp_message(c: connection)
|
||||
{
|
||||
if ( c$smtp$has_client_activity )
|
||||
{
|
||||
Log::write(SMTP::LOG, c$smtp);
|
||||
c$smtp = new_smtp_log(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
event smtp_request(c: connection, is_orig: bool, command: string, arg: string) &priority=5
|
||||
{
|
||||
set_smtp_session(c);
|
||||
local upper_command = to_upper(command);
|
||||
|
||||
if ( upper_command != "QUIT" )
|
||||
c$smtp$has_client_activity = T;
|
||||
|
||||
if ( upper_command == "HELO" || upper_command == "EHLO" )
|
||||
{
|
||||
c$smtp_state$helo = arg;
|
||||
|
@ -159,23 +161,28 @@ event smtp_request(c: connection, is_orig: bool, command: string, arg: string) &
|
|||
|
||||
else if ( upper_command == "RCPT" && /^[tT][oO]:/ in arg )
|
||||
{
|
||||
if ( ! c$smtp?$rcptto )
|
||||
if ( ! c$smtp?$rcptto )
|
||||
c$smtp$rcptto = set();
|
||||
add c$smtp$rcptto[split1(arg, /:[[:blank:]]*/)[2]];
|
||||
c$smtp$has_client_activity = T;
|
||||
}
|
||||
|
||||
else if ( upper_command == "MAIL" && /^[fF][rR][oO][mM]:/ in arg )
|
||||
{
|
||||
# Flush last message in case we didn't see the server's acknowledgement.
|
||||
smtp_message(c);
|
||||
|
||||
local partially_done = split1(arg, /:[[:blank:]]*/)[2];
|
||||
c$smtp$mailfrom = split1(partially_done, /[[:blank:]]?/)[1];
|
||||
c$smtp$has_client_activity = T;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
event smtp_reply(c: connection, is_orig: bool, code: count, cmd: string,
|
||||
msg: string, cont_resp: bool) &priority=5
|
||||
{
|
||||
set_smtp_session(c);
|
||||
|
||||
|
||||
# This continually overwrites, but we want the last reply,
|
||||
# so this actually works fine.
|
||||
c$smtp$last_reply = fmt("%d %s", code, msg);
|
||||
|
@ -196,7 +203,6 @@ event smtp_reply(c: connection, is_orig: bool, code: count, cmd: string,
|
|||
event mime_one_header(c: connection, h: mime_header_rec) &priority=5
|
||||
{
|
||||
if ( ! c?$smtp ) return;
|
||||
c$smtp$has_client_activity = T;
|
||||
|
||||
if ( h$name == "MESSAGE-ID" )
|
||||
c$smtp$msg_id = h$value;
|
||||
|
@ -239,19 +245,19 @@ event mime_one_header(c: connection, h: mime_header_rec) &priority=5
|
|||
if ( 1 in addresses )
|
||||
c$smtp$x_originating_ip = to_addr(addresses[1]);
|
||||
}
|
||||
|
||||
|
||||
else if ( h$name == "X-MAILER" ||
|
||||
h$name == "USER-AGENT" ||
|
||||
h$name == "X-USER-AGENT" )
|
||||
c$smtp$user_agent = h$value;
|
||||
}
|
||||
|
||||
# This event handler builds the "Received From" path by reading the
|
||||
|
||||
# This event handler builds the "Received From" path by reading the
|
||||
# headers in the mail
|
||||
event mime_one_header(c: connection, h: mime_header_rec) &priority=3
|
||||
{
|
||||
# If we've decided that we're done watching the received headers for
|
||||
# whatever reason, we're done. Could be due to only watching until
|
||||
# whatever reason, we're done. Could be due to only watching until
|
||||
# local addresses are seen in the received from headers.
|
||||
if ( ! c?$smtp || h$name != "RECEIVED" || ! c$smtp$process_received_from )
|
||||
return;
|
||||
|
@ -261,7 +267,7 @@ event mime_one_header(c: connection, h: mime_header_rec) &priority=3
|
|||
return;
|
||||
local ip = to_addr(text_ip);
|
||||
|
||||
if ( ! addr_matches_host(ip, mail_path_capture) &&
|
||||
if ( ! addr_matches_host(ip, mail_path_capture) &&
|
||||
! Site::is_private_addr(ip) )
|
||||
{
|
||||
c$smtp$process_received_from = F;
|
||||
|
@ -276,6 +282,15 @@ event connection_state_remove(c: connection) &priority=-5
|
|||
smtp_message(c);
|
||||
}
|
||||
|
||||
event smtp_starttls(c: connection) &priority=5
|
||||
{
|
||||
if ( c?$smtp )
|
||||
{
|
||||
c$smtp$tls = T;
|
||||
c$smtp$has_client_activity = T;
|
||||
}
|
||||
}
|
||||
|
||||
function describe(rec: Info): string
|
||||
{
|
||||
if ( rec?$mailfrom && rec?$rcptto )
|
||||
|
|
1
scripts/base/protocols/snmp/README
Normal file
1
scripts/base/protocols/snmp/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Simple Network Management Protocol (SNMP) analysis.
|
1
scripts/base/protocols/snmp/__load__.bro
Normal file
1
scripts/base/protocols/snmp/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
182
scripts/base/protocols/snmp/main.bro
Normal file
182
scripts/base/protocols/snmp/main.bro
Normal file
|
@ -0,0 +1,182 @@
|
|||
##! Enables analysis and logging of SNMP datagrams.
|
||||
|
||||
module SNMP;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
## Information tracked per SNMP session.
|
||||
type Info: record {
|
||||
## Timestamp of first packet belonging to the SNMP session.
|
||||
ts: time &log;
|
||||
## The unique ID for the connection.
|
||||
uid: string &log;
|
||||
## The connection's 5-tuple of addresses/ports (ports inherently
|
||||
## include transport protocol information)
|
||||
id: conn_id &log;
|
||||
## The amount of time between the first packet beloning to
|
||||
## the SNMP session and the latest one seen.
|
||||
duration: interval &log &default=0secs;
|
||||
## The version of SNMP being used.
|
||||
version: string &log;
|
||||
## The community string of the first SNMP packet associated with
|
||||
## the session. This is used as part of SNMP's (v1 and v2c)
|
||||
## administrative/security framework. See :rfc:`1157` or :rfc:`1901`.
|
||||
community: string &log &optional;
|
||||
|
||||
## The number of variable bindings in GetRequest/GetNextRequest PDUs
|
||||
## seen for the session.
|
||||
get_requests: count &log &default=0;
|
||||
## The number of variable bindings in GetBulkRequest PDUs seen for
|
||||
## the session.
|
||||
get_bulk_requests: count &log &default=0;
|
||||
## The number of variable bindings in GetResponse/Response PDUs seen
|
||||
## for the session.
|
||||
get_responses: count &log &default=0;
|
||||
## The number of variable bindings in SetRequest PDUs seen for
|
||||
## the session.
|
||||
set_requests: count &log &default=0;
|
||||
|
||||
## A system description of the SNMP responder endpoint.
|
||||
display_string: string &log &optional;
|
||||
## The time at which the SNMP responder endpoint claims it's been
|
||||
## up since.
|
||||
up_since: time &log &optional;
|
||||
};
|
||||
|
||||
## Maps an SNMP version integer to a human readable string.
|
||||
const version_map: table[count] of string = {
|
||||
[0] = "1",
|
||||
[1] = "2c",
|
||||
[3] = "3",
|
||||
} &redef &default="unknown";
|
||||
|
||||
## Event that can be handled to access the SNMP record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_snmp: event(rec: Info);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
snmp: SNMP::Info &optional;
|
||||
};
|
||||
|
||||
const ports = { 161/udp, 162/udp };
|
||||
redef likely_server_ports += { ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SNMP, ports);
|
||||
Log::create_stream(SNMP::LOG, [$columns=SNMP::Info, $ev=log_snmp]);
|
||||
}
|
||||
|
||||
function init_state(c: connection, h: SNMP::Header): Info
|
||||
{
|
||||
if ( ! c?$snmp )
|
||||
{
|
||||
c$snmp = Info($ts=network_time(),
|
||||
$uid=c$uid, $id=c$id,
|
||||
$version=version_map[h$version]);
|
||||
}
|
||||
|
||||
local s = c$snmp;
|
||||
|
||||
if ( ! s?$community )
|
||||
{
|
||||
if ( h?$v1 )
|
||||
s$community = h$v1$community;
|
||||
else if ( h?$v2 )
|
||||
s$community = h$v2$community;
|
||||
}
|
||||
|
||||
s$duration = network_time() - s$ts;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( c?$snmp )
|
||||
Log::write(LOG, c$snmp);
|
||||
}
|
||||
|
||||
event snmp_get_request(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::PDU) &priority=5
|
||||
{
|
||||
local s = init_state(c, header);
|
||||
s$get_requests += |pdu$bindings|;
|
||||
}
|
||||
|
||||
event snmp_get_bulk_request(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::BulkPDU) &priority=5
|
||||
{
|
||||
local s = init_state(c, header);
|
||||
s$get_bulk_requests += |pdu$bindings|;
|
||||
}
|
||||
|
||||
event snmp_get_next_request(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::PDU) &priority=5
|
||||
{
|
||||
local s = init_state(c, header);
|
||||
s$get_requests += |pdu$bindings|;
|
||||
}
|
||||
|
||||
event snmp_response(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::PDU) &priority=5
|
||||
{
|
||||
local s = init_state(c, header);
|
||||
s$get_responses += |pdu$bindings|;
|
||||
|
||||
for ( i in pdu$bindings )
|
||||
{
|
||||
local binding = pdu$bindings[i];
|
||||
|
||||
if ( binding$oid == "1.3.6.1.2.1.1.1.0" && binding$value?$octets )
|
||||
c$snmp$display_string = binding$value$octets;
|
||||
else if ( binding$oid == "1.3.6.1.2.1.1.3.0" && binding$value?$unsigned )
|
||||
{
|
||||
local up_seconds = binding$value$unsigned / 100.0;
|
||||
s$up_since = network_time() - double_to_interval(up_seconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event snmp_set_request(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::PDU) &priority=5
|
||||
{
|
||||
local s = init_state(c, header);
|
||||
s$set_requests += |pdu$bindings|;
|
||||
}
|
||||
|
||||
event snmp_trap(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::TrapPDU) &priority=5
|
||||
{
|
||||
init_state(c, header);
|
||||
}
|
||||
|
||||
event snmp_inform_request(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::PDU) &priority=5
|
||||
{
|
||||
init_state(c, header);
|
||||
}
|
||||
|
||||
event snmp_trapV2(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::PDU) &priority=5
|
||||
{
|
||||
init_state(c, header);
|
||||
}
|
||||
|
||||
event snmp_report(c: connection, is_orig: bool, header: SNMP::Header, pdu: SNMP::PDU) &priority=5
|
||||
{
|
||||
init_state(c, header);
|
||||
}
|
||||
|
||||
event snmp_unknown_pdu(c: connection, is_orig: bool, header: SNMP::Header, tag: count) &priority=5
|
||||
{
|
||||
init_state(c, header);
|
||||
}
|
||||
|
||||
event snmp_unknown_scoped_pdu(c: connection, is_orig: bool, header: SNMP::Header, tag: count) &priority=5
|
||||
{
|
||||
init_state(c, header);
|
||||
}
|
||||
|
||||
event snmp_encrypted_pdu(c: connection, is_orig: bool, header: SNMP::Header) &priority=5
|
||||
{
|
||||
init_state(c, header);
|
||||
}
|
||||
|
||||
#event snmp_unknown_header_version(c: connection, is_orig: bool, version: count) &priority=5
|
||||
# {
|
||||
# }
|
|
@ -1,5 +1,6 @@
|
|||
@load ./consts
|
||||
@load ./main
|
||||
@load ./mozilla-ca-list
|
||||
@load ./files
|
||||
|
||||
@load-sigs ./dpd.sig
|
||||
|
|
|
@ -14,15 +14,43 @@ export {
|
|||
[TLSv11] = "TLSv11",
|
||||
[TLSv12] = "TLSv12",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between numeric codes and human readable strings for alert
|
||||
|
||||
## TLS content types:
|
||||
const CHANGE_CIPHER_SPEC = 20;
|
||||
const ALERT = 21;
|
||||
const HANDSHAKE = 22;
|
||||
const APPLICATION_DATA = 23;
|
||||
const HEARTBEAT = 24;
|
||||
const V2_ERROR = 300;
|
||||
const V2_CLIENT_HELLO = 301;
|
||||
const V2_CLIENT_MASTER_KEY = 302;
|
||||
const V2_SERVER_HELLO = 304;
|
||||
|
||||
## TLS Handshake types:
|
||||
const HELLO_REQUEST = 0;
|
||||
const CLIENT_HELLO = 1;
|
||||
const SERVER_HELLO = 2;
|
||||
const HELLO_VERIFY_REQUEST = 3; # RFC 6347
|
||||
const SESSION_TICKET = 4; # RFC 5077
|
||||
const CERTIFICATE = 11;
|
||||
const SERVER_KEY_EXCHANGE = 12;
|
||||
const CERTIFICATE_REQUEST = 13;
|
||||
const SERVER_HELLO_DONE = 14;
|
||||
const CERTIFICATE_VERIFY = 15;
|
||||
const CLIENT_KEY_EXCHANGE = 16;
|
||||
const FINISHED = 20;
|
||||
const CERTIFICATE_URL = 21; # RFC 3546
|
||||
const CERTIFICATE_STATUS = 22; # RFC 3546
|
||||
const SUPPLEMENTAL_DATA = 23; # RFC 4680
|
||||
|
||||
## Mapping between numeric codes and human readable strings for alert
|
||||
## levels.
|
||||
const alert_levels: table[count] of string = {
|
||||
[1] = "warning",
|
||||
[2] = "fatal",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between numeric codes and human readable strings for alert
|
||||
|
||||
## Mapping between numeric codes and human readable strings for alert
|
||||
## descriptions.
|
||||
const alert_descriptions: table[count] of string = {
|
||||
[0] = "close_notify",
|
||||
|
@ -58,7 +86,7 @@ export {
|
|||
[115] = "unknown_psk_identity",
|
||||
[120] = "no_application_protocol",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
|
||||
## Mapping between numeric codes and human readable strings for SSL/TLS
|
||||
## extensions.
|
||||
# More information can be found here:
|
||||
|
@ -83,6 +111,11 @@ export {
|
|||
[16] = "application_layer_protocol_negotiation",
|
||||
[17] = "status_request_v2",
|
||||
[18] = "signed_certificate_timestamp",
|
||||
[19] = "client_certificate_type",
|
||||
[20] = "server_certificate_type",
|
||||
[21] = "padding", # temporary till 2015-03-12
|
||||
[22] = "encrypt_then_mac",
|
||||
[23] = "extended_master_secret", # temporary till 2015-09-26
|
||||
[35] = "SessionTicket TLS",
|
||||
[40] = "extended_random",
|
||||
[13172] = "next_protocol_negotiation",
|
||||
|
@ -93,7 +126,56 @@ export {
|
|||
[35655] = "padding",
|
||||
[65281] = "renegotiation_info"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
|
||||
## Mapping between numeric codes and human readable string for SSL/TLS elliptic curves.
|
||||
# See http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
|
||||
const ec_curves: table[count] of string = {
|
||||
[1] = "sect163k1",
|
||||
[2] = "sect163r1",
|
||||
[3] = "sect163r2",
|
||||
[4] = "sect193r1",
|
||||
[5] = "sect193r2",
|
||||
[6] = "sect233k1",
|
||||
[7] = "sect233r1",
|
||||
[8] = "sect239k1",
|
||||
[9] = "sect283k1",
|
||||
[10] = "sect283r1",
|
||||
[11] = "sect409k1",
|
||||
[12] = "sect409r1",
|
||||
[13] = "sect571k1",
|
||||
[14] = "sect571r1",
|
||||
[15] = "secp160k1",
|
||||
[16] = "secp160r1",
|
||||
[17] = "secp160r2",
|
||||
[18] = "secp192k1",
|
||||
[19] = "secp192r1",
|
||||
[20] = "secp224k1",
|
||||
[21] = "secp224r1",
|
||||
[22] = "secp256k1",
|
||||
[23] = "secp256r1",
|
||||
[24] = "secp384r1",
|
||||
[25] = "secp521r1",
|
||||
[26] = "brainpoolP256r1",
|
||||
[27] = "brainpoolP384r1",
|
||||
[28] = "brainpoolP512r1",
|
||||
# draft-ietf-tls-negotiated-ff-dhe-02
|
||||
[256] = "ffdhe2432",
|
||||
[257] = "ffdhe3072",
|
||||
[258] = "ffdhe4096",
|
||||
[259] = "ffdhe6144",
|
||||
[260] = "ffdhe8192",
|
||||
[0xFF01] = "arbitrary_explicit_prime_curves",
|
||||
[0xFF02] = "arbitrary_explicit_char2_curves"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between numeric codes and human readable string for SSL/TLC EC point formats.
|
||||
# See http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-9
|
||||
const ec_point_formats: table[count] of string = {
|
||||
[0] = "uncompressed",
|
||||
[1] = "ansiX962_compressed_prime",
|
||||
[2] = "ansiX962_compressed_char2"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
# SSLv2
|
||||
const SSLv20_CK_RC4_128_WITH_MD5 = 0x010080;
|
||||
const SSLv20_CK_RC4_128_EXPORT40_WITH_MD5 = 0x020080;
|
||||
|
@ -444,6 +526,10 @@ export {
|
|||
const TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9;
|
||||
const TLS_PSK_DHE_WITH_AES_128_CCM_8 = 0xC0AA;
|
||||
const TLS_PSK_DHE_WITH_AES_256_CCM_8 = 0xC0AB;
|
||||
const TLS_ECDHE_ECDSA_WITH_AES_128_CCM = 0xC0AC;
|
||||
const TLS_ECDHE_ECDSA_WITH_AES_256_CCM = 0xC0AD;
|
||||
const TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE;
|
||||
const TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xC0AF;
|
||||
# draft-agl-tls-chacha20poly1305-02
|
||||
const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13;
|
||||
const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14;
|
||||
|
@ -458,8 +544,8 @@ export {
|
|||
const SSL_RSA_WITH_DES_CBC_MD5 = 0xFF82;
|
||||
const SSL_RSA_WITH_3DES_EDE_CBC_MD5 = 0xFF83;
|
||||
const TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
|
||||
|
||||
## This is a table of all known cipher specs. It can be used for
|
||||
|
||||
## This is a table of all known cipher specs. It can be used for
|
||||
## detecting unknown ciphers and for converting the cipher spec
|
||||
## constants into a human readable format.
|
||||
const cipher_desc: table[count] of string = {
|
||||
|
@ -807,6 +893,10 @@ export {
|
|||
[TLS_PSK_WITH_AES_256_CCM_8] = "TLS_PSK_WITH_AES_256_CCM_8",
|
||||
[TLS_PSK_DHE_WITH_AES_128_CCM_8] = "TLS_PSK_DHE_WITH_AES_128_CCM_8",
|
||||
[TLS_PSK_DHE_WITH_AES_256_CCM_8] = "TLS_PSK_DHE_WITH_AES_256_CCM_8",
|
||||
[TLS_ECDHE_ECDSA_WITH_AES_128_CCM] = "TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
|
||||
[TLS_ECDHE_ECDSA_WITH_AES_256_CCM] = "TLS_ECDHE_ECDSA_WITH_AES_256_CCM",
|
||||
[TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8] = "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",
|
||||
[TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8] = "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",
|
||||
[TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256] = "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256] = "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256] = "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
|
@ -820,43 +910,5 @@ export {
|
|||
[SSL_RSA_WITH_3DES_EDE_CBC_MD5] = "SSL_RSA_WITH_3DES_EDE_CBC_MD5",
|
||||
[TLS_EMPTY_RENEGOTIATION_INFO_SCSV] = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between the constants and string values for SSL/TLS errors.
|
||||
const x509_errors: table[count] of string = {
|
||||
[0] = "ok",
|
||||
[1] = "unable to get issuer cert",
|
||||
[2] = "unable to get crl",
|
||||
[3] = "unable to decrypt cert signature",
|
||||
[4] = "unable to decrypt crl signature",
|
||||
[5] = "unable to decode issuer public key",
|
||||
[6] = "cert signature failure",
|
||||
[7] = "crl signature failure",
|
||||
[8] = "cert not yet valid",
|
||||
[9] = "cert has expired",
|
||||
[10] = "crl not yet valid",
|
||||
[11] = "crl has expired",
|
||||
[12] = "error in cert not before field",
|
||||
[13] = "error in cert not after field",
|
||||
[14] = "error in crl last update field",
|
||||
[15] = "error in crl next update field",
|
||||
[16] = "out of mem",
|
||||
[17] = "depth zero self signed cert",
|
||||
[18] = "self signed cert in chain",
|
||||
[19] = "unable to get issuer cert locally",
|
||||
[20] = "unable to verify leaf signature",
|
||||
[21] = "cert chain too long",
|
||||
[22] = "cert revoked",
|
||||
[23] = "invalid ca",
|
||||
[24] = "path length exceeded",
|
||||
[25] = "invalid purpose",
|
||||
[26] = "cert untrusted",
|
||||
[27] = "cert rejected",
|
||||
[28] = "subject issuer mismatch",
|
||||
[29] = "akid skid mismatch",
|
||||
[30] = "akid issuer serial mismatch",
|
||||
[31] = "keyusage no certsign",
|
||||
[32] = "unable to get crl issuer",
|
||||
[33] = "unhandled critical extension",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
signature dpd_ssl_server {
|
||||
ip-proto == tcp
|
||||
# Server hello.
|
||||
payload /^(\x16\x03[\x00\x01\x02]..\x02...\x03[\x00\x01\x02]|...?\x04..\x00\x02).*/
|
||||
payload /^(\x16\x03[\x00\x01\x02\x03]..\x02...\x03[\x00\x01\x02\x03]|...?\x04..\x00\x02).*/
|
||||
requires-reverse-signature dpd_ssl_client
|
||||
enable "ssl"
|
||||
tcp-state responder
|
||||
|
@ -10,6 +10,6 @@ signature dpd_ssl_server {
|
|||
signature dpd_ssl_client {
|
||||
ip-proto == tcp
|
||||
# Client hello.
|
||||
payload /^(\x16\x03[\x00\x01\x02]..\x01...\x03[\x00\x01\x02]|...?\x01[\x00\x01\x02][\x02\x03]).*/
|
||||
payload /^(\x16\x03[\x00\x01\x02\x03]..\x01...\x03[\x00\x01\x02\x03]|...?\x01[\x00\x03][\x00\x01\x02\x03]).*/
|
||||
tcp-state originator
|
||||
}
|
||||
|
|
137
scripts/base/protocols/ssl/files.bro
Normal file
137
scripts/base/protocols/ssl/files.bro
Normal file
|
@ -0,0 +1,137 @@
|
|||
@load ./main
|
||||
@load base/utils/conn-ids
|
||||
@load base/frameworks/files
|
||||
@load base/files/x509
|
||||
|
||||
module SSL;
|
||||
|
||||
export {
|
||||
redef record Info += {
|
||||
## Chain of certificates offered by the server to validate its
|
||||
## complete signing chain.
|
||||
cert_chain: vector of Files::Info &optional;
|
||||
|
||||
## An ordered vector of all certicate file unique IDs for the
|
||||
## certificates offered by the server.
|
||||
cert_chain_fuids: vector of string &optional &log;
|
||||
|
||||
## Chain of certificates offered by the client to validate its
|
||||
## complete signing chain.
|
||||
client_cert_chain: vector of Files::Info &optional;
|
||||
|
||||
## An ordered vector of all certicate file unique IDs for the
|
||||
## certificates offered by the client.
|
||||
client_cert_chain_fuids: vector of string &optional &log;
|
||||
|
||||
## Subject of the X.509 certificate offered by the server.
|
||||
subject: string &log &optional;
|
||||
|
||||
## Subject of the signer of the X.509 certificate offered by the
|
||||
## server.
|
||||
issuer: string &log &optional;
|
||||
|
||||
## Subject of the X.509 certificate offered by the client.
|
||||
client_subject: string &log &optional;
|
||||
|
||||
## Subject of the signer of the X.509 certificate offered by the
|
||||
## client.
|
||||
client_issuer: string &log &optional;
|
||||
|
||||
## Current number of certificates seen from either side. Used
|
||||
## to create file handles.
|
||||
server_depth: count &default=0;
|
||||
client_depth: count &default=0;
|
||||
};
|
||||
|
||||
## Default file handle provider for SSL.
|
||||
global get_file_handle: function(c: connection, is_orig: bool): string;
|
||||
|
||||
## Default file describer for SSL.
|
||||
global describe_file: function(f: fa_file): string;
|
||||
}
|
||||
|
||||
function get_file_handle(c: connection, is_orig: bool): string
|
||||
{
|
||||
# Unused. File handles are generated in the analyzer.
|
||||
return "";
|
||||
}
|
||||
|
||||
function describe_file(f: fa_file): string
|
||||
{
|
||||
if ( f$source != "SSL" || ! f?$info || ! f$info?$x509 || ! f$info$x509?$certificate )
|
||||
return "";
|
||||
|
||||
# It is difficult to reliably describe a certificate - especially since
|
||||
# we do not know when this function is called (hence, if the data structures
|
||||
# are already populated).
|
||||
#
|
||||
# Just return a bit of our connection information and hope that that is good enough.
|
||||
for ( cid in f$conns )
|
||||
{
|
||||
if ( f$conns[cid]?$ssl )
|
||||
{
|
||||
local c = f$conns[cid];
|
||||
return cat(c$id$resp_h, ":", c$id$resp_p);
|
||||
}
|
||||
}
|
||||
|
||||
return cat("Serial: ", f$info$x509$certificate$serial, " Subject: ",
|
||||
f$info$x509$certificate$subject, " Issuer: ",
|
||||
f$info$x509$certificate$issuer);
|
||||
}
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Files::register_protocol(Analyzer::ANALYZER_SSL,
|
||||
[$get_file_handle = SSL::get_file_handle,
|
||||
$describe = SSL::describe_file]);
|
||||
}
|
||||
|
||||
event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5
|
||||
{
|
||||
if ( ! c?$ssl )
|
||||
return;
|
||||
|
||||
if ( ! c$ssl?$cert_chain )
|
||||
{
|
||||
c$ssl$cert_chain = vector();
|
||||
c$ssl$client_cert_chain = vector();
|
||||
c$ssl$cert_chain_fuids = string_vec();
|
||||
c$ssl$client_cert_chain_fuids = string_vec();
|
||||
}
|
||||
|
||||
if ( is_orig )
|
||||
{
|
||||
c$ssl$client_cert_chain[|c$ssl$client_cert_chain|] = f$info;
|
||||
c$ssl$client_cert_chain_fuids[|c$ssl$client_cert_chain_fuids|] = f$id;
|
||||
}
|
||||
else
|
||||
{
|
||||
c$ssl$cert_chain[|c$ssl$cert_chain|] = f$info;
|
||||
c$ssl$cert_chain_fuids[|c$ssl$cert_chain_fuids|] = f$id;
|
||||
}
|
||||
|
||||
Files::add_analyzer(f, Files::ANALYZER_X509);
|
||||
# always calculate hashes. They are not necessary for base scripts
|
||||
# but very useful for identification, and required for policy scripts
|
||||
Files::add_analyzer(f, Files::ANALYZER_MD5);
|
||||
Files::add_analyzer(f, Files::ANALYZER_SHA1);
|
||||
}
|
||||
|
||||
event ssl_established(c: connection) &priority=6
|
||||
{
|
||||
# update subject and issuer information
|
||||
if ( c$ssl?$cert_chain && |c$ssl$cert_chain| > 0 &&
|
||||
c$ssl$cert_chain[0]?$x509 )
|
||||
{
|
||||
c$ssl$subject = c$ssl$cert_chain[0]$x509$certificate$subject;
|
||||
c$ssl$issuer = c$ssl$cert_chain[0]$x509$certificate$issuer;
|
||||
}
|
||||
|
||||
if ( c$ssl?$client_cert_chain && |c$ssl$client_cert_chain| > 0 &&
|
||||
c$ssl$client_cert_chain[0]?$x509 )
|
||||
{
|
||||
c$ssl$client_subject = c$ssl$client_cert_chain[0]$x509$certificate$subject;
|
||||
c$ssl$client_issuer = c$ssl$client_cert_chain[0]$x509$certificate$issuer;
|
||||
}
|
||||
}
|
|
@ -12,47 +12,38 @@ export {
|
|||
## Time when the SSL connection was first detected.
|
||||
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;
|
||||
## SSL/TLS version that the server offered.
|
||||
version: string &log &optional;
|
||||
## SSL/TLS cipher suite that the server chose.
|
||||
cipher: string &log &optional;
|
||||
## Elliptic curve the server chose when using ECDH/ECDHE.
|
||||
curve: string &log &optional;
|
||||
## Value of the Server Name Indicator SSL/TLS extension. It
|
||||
## indicates the server name that the client was requesting.
|
||||
server_name: string &log &optional;
|
||||
## Session ID offered by the client for session resumption.
|
||||
session_id: string &log &optional;
|
||||
## Subject of the X.509 certificate offered by the server.
|
||||
subject: string &log &optional;
|
||||
## Subject of the signer of the X.509 certificate offered by the
|
||||
## server.
|
||||
issuer_subject: string &log &optional;
|
||||
## NotValidBefore field value from the server certificate.
|
||||
not_valid_before: time &log &optional;
|
||||
## NotValidAfter field value from the server certificate.
|
||||
not_valid_after: time &log &optional;
|
||||
## Not used for logging.
|
||||
session_id: string &optional;
|
||||
## Flag to indicate if the session was resumed reusing
|
||||
## the key material exchanged in an earlier connection.
|
||||
resumed: bool &log &default=F;
|
||||
## Flag to indicate if we saw a non-empty session ticket being
|
||||
## sent by the client using an empty session ID. This value
|
||||
## is used to determine if a session is being resumed. It's
|
||||
## not logged.
|
||||
client_ticket_empty_session_seen: bool &default=F;
|
||||
## Flag to indicate if we saw a client key exchange message sent
|
||||
## by the client. This value is used to determine if a session
|
||||
## is being resumed. It's not logged.
|
||||
client_key_exchange_seen: bool &default=F;
|
||||
## Last alert that was seen during the connection.
|
||||
last_alert: string &log &optional;
|
||||
|
||||
## Subject of the X.509 certificate offered by the client.
|
||||
client_subject: string &log &optional;
|
||||
## Subject of the signer of the X.509 certificate offered by the
|
||||
## client.
|
||||
client_issuer_subject: string &log &optional;
|
||||
|
||||
## Full binary server certificate stored in DER format.
|
||||
cert: string &optional;
|
||||
## Chain of certificates offered by the server to validate its
|
||||
## complete signing chain.
|
||||
cert_chain: vector of string &optional;
|
||||
|
||||
## Full binary client certificate stored in DER format.
|
||||
client_cert: string &optional;
|
||||
## Chain of certificates offered by the client to validate its
|
||||
## complete signing chain.
|
||||
client_cert_chain: vector of string &optional;
|
||||
## Next protocol the server chose using the application layer
|
||||
## next protocol extension, if present.
|
||||
next_protocol: string &log &optional;
|
||||
|
||||
## The analyzer ID used for the analyzer instance attached
|
||||
## to each connection. It is not used for logging since it's a
|
||||
|
@ -61,11 +52,11 @@ export {
|
|||
|
||||
## Flag to indicate if this ssl session has been established
|
||||
## succesfully, or if it was aborted during the handshake.
|
||||
established: bool &log &default=F;
|
||||
established: bool &log &default=F;
|
||||
|
||||
## Flag to indicate if this record already has been logged, to
|
||||
## prevent duplicates.
|
||||
logged: bool &default=F;
|
||||
logged: bool &default=F;
|
||||
};
|
||||
|
||||
## The default root CA bundle. By default, the mozilla-ca-list.bro
|
||||
|
@ -116,8 +107,7 @@ event bro_init() &priority=5
|
|||
function set_session(c: connection)
|
||||
{
|
||||
if ( ! c?$ssl )
|
||||
c$ssl = [$ts=network_time(), $uid=c$uid, $id=c$id, $cert_chain=vector(),
|
||||
$client_cert_chain=vector()];
|
||||
c$ssl = [$ts=network_time(), $uid=c$uid, $id=c$id];
|
||||
}
|
||||
|
||||
function delay_log(info: Info, token: string)
|
||||
|
@ -164,8 +154,10 @@ function finish(c: connection, remove_analyzer: bool)
|
|||
{
|
||||
log_record(c$ssl);
|
||||
if ( remove_analyzer && disable_analyzer_after_detection && c?$ssl && c$ssl?$analyzer_id )
|
||||
{
|
||||
disable_analyzer(c$id, c$ssl$analyzer_id);
|
||||
delete c$ssl$analyzer_id;
|
||||
}
|
||||
}
|
||||
|
||||
event ssl_client_hello(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: index_vec) &priority=5
|
||||
|
@ -173,8 +165,11 @@ event ssl_client_hello(c: connection, version: count, possible_ts: time, client_
|
|||
set_session(c);
|
||||
|
||||
# Save the session_id if there is one set.
|
||||
if ( session_id != /^\x00{32}$/ )
|
||||
if ( |session_id| > 0 && session_id != /^\x00{32}$/ )
|
||||
{
|
||||
c$ssl$session_id = bytestring_to_hexstr(session_id);
|
||||
c$ssl$client_ticket_empty_session_seen = F;
|
||||
}
|
||||
}
|
||||
|
||||
event ssl_server_hello(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count) &priority=5
|
||||
|
@ -183,57 +178,67 @@ event ssl_server_hello(c: connection, version: count, possible_ts: time, server_
|
|||
|
||||
c$ssl$version = version_strings[version];
|
||||
c$ssl$cipher = cipher_desc[cipher];
|
||||
|
||||
if ( c$ssl?$session_id && c$ssl$session_id == bytestring_to_hexstr(session_id) )
|
||||
c$ssl$resumed = T;
|
||||
}
|
||||
|
||||
event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=5
|
||||
event ssl_server_curve(c: connection, curve: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
# We aren't doing anything with client certificates yet.
|
||||
if ( is_orig )
|
||||
{
|
||||
if ( chain_idx == 0 )
|
||||
{
|
||||
# Save the primary cert.
|
||||
c$ssl$client_cert = der_cert;
|
||||
c$ssl$curve = ec_curves[curve];
|
||||
}
|
||||
|
||||
# Also save other certificate information about the primary cert.
|
||||
c$ssl$client_subject = cert$subject;
|
||||
c$ssl$client_issuer_subject = cert$issuer;
|
||||
}
|
||||
else
|
||||
{
|
||||
# Otherwise, add it to the cert validation chain.
|
||||
c$ssl$client_cert_chain[|c$ssl$client_cert_chain|] = der_cert;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( chain_idx == 0 )
|
||||
{
|
||||
# Save the primary cert.
|
||||
c$ssl$cert = der_cert;
|
||||
event ssl_extension_server_name(c: connection, is_orig: bool, names: string_vec) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
# Also save other certificate information about the primary cert.
|
||||
c$ssl$subject = cert$subject;
|
||||
c$ssl$issuer_subject = cert$issuer;
|
||||
c$ssl$not_valid_before = cert$not_valid_before;
|
||||
c$ssl$not_valid_after = cert$not_valid_after;
|
||||
}
|
||||
else
|
||||
{
|
||||
# Otherwise, add it to the cert validation chain.
|
||||
c$ssl$cert_chain[|c$ssl$cert_chain|] = der_cert;
|
||||
}
|
||||
if ( is_orig && |names| > 0 )
|
||||
{
|
||||
c$ssl$server_name = names[0];
|
||||
if ( |names| > 1 )
|
||||
event conn_weird("SSL_many_server_names", c, cat(names));
|
||||
}
|
||||
}
|
||||
|
||||
event ssl_extension_application_layer_protocol_negotiation(c: connection, is_orig: bool, protocols: string_vec)
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
if ( is_orig )
|
||||
return;
|
||||
|
||||
if ( |protocols| > 0 )
|
||||
c$ssl$next_protocol = protocols[0];
|
||||
}
|
||||
|
||||
event ssl_handshake_message(c: connection, is_orig: bool, msg_type: count, length: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
if ( is_orig && msg_type == SSL::CLIENT_KEY_EXCHANGE )
|
||||
c$ssl$client_key_exchange_seen = T;
|
||||
}
|
||||
|
||||
# Extension event is fired _before_ the respective client or server hello.
|
||||
# Important for client_ticket_empty_session_seen.
|
||||
event ssl_extension(c: connection, is_orig: bool, code: count, val: string) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
if ( is_orig && extensions[code] == "server_name" )
|
||||
c$ssl$server_name = sub_bytes(val, 6, |val|);
|
||||
if ( is_orig && SSL::extensions[code] == "SessionTicket TLS" && |val| > 0 )
|
||||
# In this case, we might have an empty ID. Set back to F in client_hello event
|
||||
# if it is not empty after all.
|
||||
c$ssl$client_ticket_empty_session_seen = T;
|
||||
}
|
||||
|
||||
event ssl_change_cipher_spec(c: connection, is_orig: bool) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
if ( is_orig && c$ssl$client_ticket_empty_session_seen && ! c$ssl$client_key_exchange_seen )
|
||||
c$ssl$resumed = T;
|
||||
}
|
||||
|
||||
event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priority=5
|
||||
|
@ -243,7 +248,7 @@ event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priori
|
|||
c$ssl$last_alert = alert_descriptions[desc];
|
||||
}
|
||||
|
||||
event ssl_established(c: connection) &priority=5
|
||||
event ssl_established(c: connection) &priority=7
|
||||
{
|
||||
set_session(c);
|
||||
c$ssl$established = T;
|
||||
|
@ -263,7 +268,7 @@ event connection_state_remove(c: connection) &priority=-5
|
|||
|
||||
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=5
|
||||
{
|
||||
if ( atype == Analyzer::ANALYZER_SSL )
|
||||
if ( atype == Analyzer::ANALYZER_SSL )
|
||||
{
|
||||
set_session(c);
|
||||
c$ssl$analyzer_id = aid;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue