mirror of
https://github.com/zeek/zeek.git
synced 2025-10-10 02:28:21 +00:00
Merge remote-tracking branch 'origin/master' into topic/vladg/sip
This commit is contained in:
commit
25d7b71c50
1460 changed files with 70473 additions and 191398 deletions
1
scripts/base/protocols/conn/README
Normal file
1
scripts/base/protocols/conn/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for connection (TCP, UDP, or ICMP) analysis.
|
|
@ -16,12 +16,12 @@
|
|||
module Conn;
|
||||
|
||||
export {
|
||||
## The prefix given to files containing extracted connections as they are
|
||||
## opened on disk.
|
||||
## The prefix given to files containing extracted connections as they
|
||||
## are opened on disk.
|
||||
const extraction_prefix = "contents" &redef;
|
||||
|
||||
## If this variable is set to ``T``, then all contents of all connections
|
||||
## will be extracted.
|
||||
## If this variable is set to ``T``, then all contents of all
|
||||
## connections will be extracted.
|
||||
const default_extract = F &redef;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
##! This script manages the tracking/logging of general information regarding
|
||||
##! TCP, UDP, and ICMP traffic. For UDP and ICMP, "connections" are to
|
||||
##! be interpreted using flow semantics (sequence of packets from a source
|
||||
##! host/post to a destination host/port). Further, ICMP "ports" are to
|
||||
##! host/port to a destination host/port). Further, ICMP "ports" are to
|
||||
##! be interpreted as the source port meaning the ICMP message type and
|
||||
##! the destination port being the ICMP message code.
|
||||
|
||||
|
@ -23,7 +23,7 @@ export {
|
|||
id: conn_id &log;
|
||||
## The transport layer protocol of the connection.
|
||||
proto: transport_proto &log;
|
||||
## An identification of an application protocol being sent over the
|
||||
## An identification of an application protocol being sent over
|
||||
## the connection.
|
||||
service: string &log &optional;
|
||||
## How long the connection lasted. For 3-way or 4-way connection
|
||||
|
@ -31,9 +31,10 @@ export {
|
|||
duration: interval &log &optional;
|
||||
## The number of payload bytes the originator sent. For TCP
|
||||
## this is taken from sequence numbers and might be inaccurate
|
||||
## (e.g., due to large connections)
|
||||
## (e.g., due to large connections).
|
||||
orig_bytes: count &log &optional;
|
||||
## The number of payload bytes the responder sent. See ``orig_bytes``.
|
||||
## The number of payload bytes the responder sent. See
|
||||
## *orig_bytes*.
|
||||
resp_bytes: count &log &optional;
|
||||
|
||||
## ========== ===============================================
|
||||
|
@ -55,20 +56,20 @@ export {
|
|||
## ========== ===============================================
|
||||
conn_state: string &log &optional;
|
||||
|
||||
## If the connection is originated locally, this value will be T. If
|
||||
## it was originated remotely it will be F. In the case that the
|
||||
## :bro:id:`Site::local_nets` variable is undefined, this field will
|
||||
## be left empty at all times.
|
||||
## If the connection is originated locally, this value will be T.
|
||||
## If it was originated remotely it will be F. In the case that
|
||||
## the :bro:id:`Site::local_nets` variable is undefined, this
|
||||
## field will be left empty at all times.
|
||||
local_orig: bool &log &optional;
|
||||
|
||||
## Indicates the number of bytes missed in content gaps, which is
|
||||
## representative of packet loss. A value other than zero will
|
||||
## normally cause protocol analysis to fail but some analysis may
|
||||
## have been completed prior to the packet loss.
|
||||
## Indicates the number of bytes missed in content gaps, which
|
||||
## is representative of packet loss. A value other than zero
|
||||
## will normally cause protocol analysis to fail but some
|
||||
## analysis may have been completed prior to the packet loss.
|
||||
missed_bytes: count &log &default=0;
|
||||
|
||||
## Records the state history of connections as a string of letters.
|
||||
## The meaning of those letters is:
|
||||
## Records the state history of connections as a string of
|
||||
## letters. The meaning of those letters is:
|
||||
##
|
||||
## ====== ====================================================
|
||||
## Letter Meaning
|
||||
|
@ -83,24 +84,25 @@ export {
|
|||
## i inconsistent packet (e.g. SYN+RST bits both set)
|
||||
## ====== ====================================================
|
||||
##
|
||||
## If the event comes from the originator, the letter is in upper-case; if it comes
|
||||
## from the responder, it's in lower-case. Multiple packets of the same type will
|
||||
## only be noted once (e.g. we only record one "d" in each direction, regardless of
|
||||
## how many data packets were seen.)
|
||||
## If the event comes from the originator, the letter is in
|
||||
## upper-case; if it comes from the responder, it's in
|
||||
## lower-case. Multiple packets of the same type will only be
|
||||
## noted once (e.g. we only record one "d" in each direction,
|
||||
## regardless of how many data packets were seen.)
|
||||
history: string &log &optional;
|
||||
## Number of packets that the originator sent.
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T.
|
||||
orig_pkts: count &log &optional;
|
||||
## Number of IP level bytes that the originator sent (as seen on the wire,
|
||||
## taken from IP total_length header field).
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T
|
||||
## Number of IP level bytes that the originator sent (as seen on
|
||||
## the wire, taken from the IP total_length header field).
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T.
|
||||
orig_ip_bytes: count &log &optional;
|
||||
## Number of packets that the responder sent.
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T.
|
||||
resp_pkts: count &log &optional;
|
||||
## Number og IP level bytes that the responder sent (as seen on the wire,
|
||||
## taken from IP total_length header field).
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T
|
||||
## Number of IP level bytes that the responder sent (as seen on
|
||||
## the wire, taken from the IP total_length header field).
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T.
|
||||
resp_ip_bytes: count &log &optional;
|
||||
## If this connection was over a tunnel, indicate the
|
||||
## *uid* values for any encapsulating parent connections
|
||||
|
|
|
@ -11,10 +11,11 @@ export {
|
|||
## c: The connection to watch.
|
||||
##
|
||||
## callback: A callback function that takes as arguments the monitored
|
||||
## *connection*, and counter *cnt* that increments each time the
|
||||
## callback is called. It returns an interval indicating how long
|
||||
## in the future to schedule an event which will call the
|
||||
## callback. A negative return interval causes polling to stop.
|
||||
## *connection*, and counter *cnt* that increments each time
|
||||
## the callback is called. It returns an interval indicating
|
||||
## how long in the future to schedule an event which will call
|
||||
## the callback. A negative return interval causes polling
|
||||
## to stop.
|
||||
##
|
||||
## cnt: The initial value of a counter which gets passed to *callback*.
|
||||
##
|
||||
|
|
1
scripts/base/protocols/dhcp/README
Normal file
1
scripts/base/protocols/dhcp/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Dynamic Host Configuration Protocol (DHCP) analysis.
|
4
scripts/base/protocols/dhcp/__load__.bro
Normal file
4
scripts/base/protocols/dhcp/__load__.bro
Normal file
|
@ -0,0 +1,4 @@
|
|||
@load ./consts
|
||||
@load ./main
|
||||
|
||||
@load-sigs ./dpd.sig
|
20
scripts/base/protocols/dhcp/consts.bro
Normal file
20
scripts/base/protocols/dhcp/consts.bro
Normal file
|
@ -0,0 +1,20 @@
|
|||
##! Types, errors, and fields for analyzing DHCP data. A helper file
|
||||
##! for DHCP analysis scripts.
|
||||
|
||||
module DHCP;
|
||||
|
||||
export {
|
||||
|
||||
## Types of DHCP messages. See :rfc:`1533`.
|
||||
const message_types = {
|
||||
[1] = "DHCP_DISCOVER",
|
||||
[2] = "DHCP_OFFER",
|
||||
[3] = "DHCP_REQUEST",
|
||||
[4] = "DHCP_DECLINE",
|
||||
[5] = "DHCP_ACK",
|
||||
[6] = "DHCP_NAK",
|
||||
[7] = "DHCP_RELEASE",
|
||||
[8] = "DHCP_INFORM",
|
||||
} &default = function(n: count): string { return fmt("unknown-message-type-%d", n); };
|
||||
|
||||
}
|
5
scripts/base/protocols/dhcp/dpd.sig
Normal file
5
scripts/base/protocols/dhcp/dpd.sig
Normal file
|
@ -0,0 +1,5 @@
|
|||
signature dhcp_cookie {
|
||||
ip-proto == udp
|
||||
payload /^.*\x63\x82\x53\x63/
|
||||
enable "dhcp"
|
||||
}
|
76
scripts/base/protocols/dhcp/main.bro
Normal file
76
scripts/base/protocols/dhcp/main.bro
Normal file
|
@ -0,0 +1,76 @@
|
|||
##! Analyzes DHCP traffic in order to log DHCP leases given to clients.
|
||||
##! This script ignores large swaths of the protocol, since it is rather
|
||||
##! noisy on most networks, and focuses on the end-result: assigned leases.
|
||||
##!
|
||||
##! If you'd like to track known DHCP devices and to log the hostname
|
||||
##! supplied by the client, see
|
||||
##! :doc:`/scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro`.
|
||||
|
||||
@load ./utils.bro
|
||||
|
||||
module DHCP;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
## The record type which contains the column fields of the DHCP log.
|
||||
type Info: record {
|
||||
## The earliest time at which a DHCP message over the
|
||||
## associated connection is observed.
|
||||
ts: time &log;
|
||||
## A unique identifier of the connection over which DHCP is
|
||||
## occurring.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## Client's hardware address.
|
||||
mac: string &log &optional;
|
||||
## Client's actual assigned IP address.
|
||||
assigned_ip: addr &log &optional;
|
||||
## IP address lease interval.
|
||||
lease_time: interval &log &optional;
|
||||
## A random number chosen by the client for this transaction.
|
||||
trans_id: count &log;
|
||||
};
|
||||
|
||||
## Event that can be handled to access the DHCP
|
||||
## record as it is sent on to the logging framework.
|
||||
global log_dhcp: event(rec: Info);
|
||||
}
|
||||
|
||||
# Add the dhcp info to the connection record.
|
||||
redef record connection += {
|
||||
dhcp: Info &optional;
|
||||
};
|
||||
|
||||
# 67/udp is the server's port, 68/udp the client.
|
||||
const ports = { 67/udp, 68/udp };
|
||||
redef likely_server_ports += { 67/udp };
|
||||
|
||||
event bro_init()
|
||||
{
|
||||
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)
|
||||
{
|
||||
local info: Info;
|
||||
info$ts = network_time();
|
||||
info$id = c$id;
|
||||
info$uid = c$uid;
|
||||
info$lease_time = lease;
|
||||
info$trans_id = msg$xid;
|
||||
|
||||
if ( msg$h_addr != "" )
|
||||
info$mac = msg$h_addr;
|
||||
|
||||
if ( reverse_ip(msg$yiaddr) != 0.0.0.0 )
|
||||
info$assigned_ip = reverse_ip(msg$yiaddr);
|
||||
else
|
||||
info$assigned_ip = c$id$orig_h;
|
||||
|
||||
c$dhcp = info;
|
||||
|
||||
Log::write(DHCP::LOG, c$dhcp);
|
||||
}
|
19
scripts/base/protocols/dhcp/utils.bro
Normal file
19
scripts/base/protocols/dhcp/utils.bro
Normal file
|
@ -0,0 +1,19 @@
|
|||
##! Utilities specific for DHCP processing.
|
||||
|
||||
module DHCP;
|
||||
|
||||
export {
|
||||
## Reverse the octets of an IPv4 address.
|
||||
##
|
||||
## ip: An IPv4 address.
|
||||
##
|
||||
## Returns: A reversed IPv4 address.
|
||||
global reverse_ip: function(ip: addr): addr;
|
||||
}
|
||||
|
||||
function reverse_ip(ip: addr): addr
|
||||
{
|
||||
local octets = split(cat(ip), /\./);
|
||||
return to_addr(cat(octets[4], ".", octets[3], ".", octets[2], ".", octets[1]));
|
||||
}
|
||||
|
1
scripts/base/protocols/dnp3/README
Normal file
1
scripts/base/protocols/dnp3/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Distributed Network Protocol (DNP3) analysis.
|
3
scripts/base/protocols/dnp3/__load__.bro
Normal file
3
scripts/base/protocols/dnp3/__load__.bro
Normal file
|
@ -0,0 +1,3 @@
|
|||
@load ./main
|
||||
|
||||
@load-sigs ./dpd.sig
|
49
scripts/base/protocols/dnp3/consts.bro
Normal file
49
scripts/base/protocols/dnp3/consts.bro
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
module DNP3;
|
||||
|
||||
export {
|
||||
## Standard defined Modbus function codes.
|
||||
const function_codes = {
|
||||
# Requests.
|
||||
[0x00] = "CONFIRM",
|
||||
[0x01] = "READ",
|
||||
[0x02] = "WRITE",
|
||||
[0x03] = "SELECT",
|
||||
[0x04] = "OPERATE",
|
||||
[0x05] = "DIRECT_OPERATE",
|
||||
[0x06] = "DIRECT_OPERATE_NR",
|
||||
[0x07] = "IMMED_FREEZE",
|
||||
[0x08] = "IMMED_FREEZE_NR",
|
||||
[0x09] = "FREEZE_CLEAR",
|
||||
[0x0a] = "FREEZE_CLEAR_NR",
|
||||
[0x0b] = "FREEZE_AT_TIME",
|
||||
[0x0c] = "FREEZE_AT_TIME_NR",
|
||||
[0x0d] = "COLD_RESTART",
|
||||
[0x0e] = "WARM_RESTART",
|
||||
[0x0f] = "INITIALIZE_DATA",
|
||||
[0x10] = "INITIALIZE_APPL",
|
||||
[0x11] = "START_APPL",
|
||||
[0x12] = "STOP_APPL",
|
||||
[0x13] = "SAVE_CONFIG",
|
||||
[0x14] = "ENABLE_UNSOLICITED",
|
||||
[0x15] = "DISABLE_UNSOLICITED",
|
||||
[0x16] = "ASSIGN_CLASS",
|
||||
[0x17] = "DELAY_MEASURE",
|
||||
[0x18] = "RECORD_CURRENT_TIME",
|
||||
[0x19] = "OPEN_FILE",
|
||||
[0x1a] = "CLOSE_FILE",
|
||||
[0x1b] = "DELETE_FILE",
|
||||
[0x1c] = "GET_FILE_INFO",
|
||||
[0x1d] = "AUTHENTICATE_FILE",
|
||||
[0x1e] = "ABORT_FILE",
|
||||
[0x1f] = "ACTIVATE_CONFIG",
|
||||
[0x20] = "AUTHENTICATE_REQ",
|
||||
[0x21] = "AUTHENTICATE_ERR",
|
||||
|
||||
# Responses.
|
||||
[0x81] = "RESPONSE",
|
||||
[0x82] = "UNSOLICITED_RESPONSE",
|
||||
[0x83] = "AUTHENTICATE_RESP",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); } &redef;
|
||||
}
|
||||
|
9
scripts/base/protocols/dnp3/dpd.sig
Normal file
9
scripts/base/protocols/dnp3/dpd.sig
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
# DNP3 packets always starts with 0x05 0x64 .
|
||||
|
||||
signature dpd_dnp3_server {
|
||||
ip-proto == tcp
|
||||
payload /\x05\x64/
|
||||
tcp-state responder
|
||||
enable "dnp3"
|
||||
}
|
73
scripts/base/protocols/dnp3/main.bro
Normal file
73
scripts/base/protocols/dnp3/main.bro
Normal file
|
@ -0,0 +1,73 @@
|
|||
##! A very basic DNP3 analysis script that just logs requests and replies.
|
||||
|
||||
module DNP3;
|
||||
|
||||
@load ./consts
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Time of the request.
|
||||
ts: time &log;
|
||||
## Unique identifier for the connection.
|
||||
uid: string &log;
|
||||
## Identifier for the connection.
|
||||
id: conn_id &log;
|
||||
## The name of the function message in the request.
|
||||
fc_request: string &log &optional;
|
||||
## The name of the function message in the reply.
|
||||
fc_reply: string &log &optional;
|
||||
## The response's "internal indication number".
|
||||
iin: count &log &optional;
|
||||
};
|
||||
|
||||
## Event that can be handled to access the DNP3 record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_dnp3: event(rec: Info);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
dnp3: Info &optional;
|
||||
};
|
||||
|
||||
const ports = { 20000/tcp };
|
||||
redef likely_server_ports += { ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(DNP3::LOG, [$columns=Info, $ev=log_dnp3]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_DNP3, ports);
|
||||
}
|
||||
|
||||
event dnp3_application_request_header(c: connection, is_orig: bool, fc: count)
|
||||
{
|
||||
if ( ! c?$dnp3 )
|
||||
c$dnp3 = [$ts=network_time(), $uid=c$uid, $id=c$id];
|
||||
|
||||
c$dnp3$ts = network_time();
|
||||
c$dnp3$fc_request = function_codes[fc];
|
||||
}
|
||||
|
||||
event dnp3_application_response_header(c: connection, is_orig: bool, fc: count, iin: count)
|
||||
{
|
||||
if ( ! c?$dnp3 )
|
||||
c$dnp3 = [$ts=network_time(), $uid=c$uid, $id=c$id];
|
||||
|
||||
c$dnp3$ts = network_time();
|
||||
c$dnp3$fc_reply = function_codes[fc];
|
||||
c$dnp3$iin = iin;
|
||||
|
||||
Log::write(LOG, c$dnp3);
|
||||
|
||||
delete c$dnp3;
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( ! c?$dnp3 )
|
||||
return;
|
||||
|
||||
Log::write(LOG, c$dnp3);
|
||||
delete c$dnp3;
|
||||
}
|
1
scripts/base/protocols/dns/README
Normal file
1
scripts/base/protocols/dns/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Domain Name System (DNS) protocol analysis.
|
|
@ -8,7 +8,8 @@ export {
|
|||
const EDNS = 41; ##< An OPT RR TYPE value described by EDNS.
|
||||
const ANY = 255; ##< A QTYPE value describing a request for all records.
|
||||
|
||||
## Mapping of DNS query type codes to human readable string representation.
|
||||
## Mapping of DNS query type codes to human readable string
|
||||
## representation.
|
||||
const query_types = {
|
||||
[1] = "A", [2] = "NS", [3] = "MD", [4] = "MF",
|
||||
[5] = "CNAME", [6] = "SOA", [7] = "MB", [8] = "MG",
|
||||
|
@ -64,8 +65,8 @@ export {
|
|||
[32768] = "DNS_SEC_OK", # accepts DNS Sec RRs
|
||||
} &default="?";
|
||||
|
||||
## Possible values of the CLASS field in resource records or QCLASS field
|
||||
## in query messages.
|
||||
## Possible values of the CLASS field in resource records or QCLASS
|
||||
## field in query messages.
|
||||
const classes = {
|
||||
[1] = "C_INTERNET",
|
||||
[2] = "C_CSNET",
|
||||
|
|
|
@ -22,8 +22,8 @@ export {
|
|||
id: conn_id &log;
|
||||
## The transport layer protocol of the connection.
|
||||
proto: transport_proto &log;
|
||||
## A 16 bit identifier assigned by the program that generated the
|
||||
## DNS query. Also used in responses to match up replies to
|
||||
## A 16-bit identifier assigned by the program that generated
|
||||
## the DNS query. Also used in responses to match up replies to
|
||||
## outstanding queries.
|
||||
trans_id: count &log &optional;
|
||||
## The domain name that is the subject of the DNS query.
|
||||
|
@ -40,17 +40,17 @@ export {
|
|||
rcode: count &log &optional;
|
||||
## A descriptive name for the response code value.
|
||||
rcode_name: string &log &optional;
|
||||
## The Authoritative Answer bit for response messages specifies that
|
||||
## the responding name server is an authority for the domain name
|
||||
## in the question section.
|
||||
## The Authoritative Answer bit for response messages specifies
|
||||
## that the responding name server is an authority for the
|
||||
## domain name in the question section.
|
||||
AA: bool &log &default=F;
|
||||
## The Truncation bit specifies that the message was truncated.
|
||||
TC: bool &log &default=F;
|
||||
## The Recursion Desired bit in a request message indicates that
|
||||
## the client wants recursive service for this query.
|
||||
RD: bool &log &default=F;
|
||||
## The Recursion Available bit in a response message indicates that
|
||||
## the name server supports recursive queries.
|
||||
## The Recursion Available bit in a response message indicates
|
||||
## that the name server supports recursive queries.
|
||||
RA: bool &log &default=F;
|
||||
## A reserved field that is currently supposed to be zero in all
|
||||
## queries and responses.
|
||||
|
@ -58,29 +58,32 @@ export {
|
|||
## The set of resource descriptions in the query answer.
|
||||
answers: vector of string &log &optional;
|
||||
## The caching intervals of the associated RRs described by the
|
||||
## ``answers`` field.
|
||||
## *answers* field.
|
||||
TTLs: vector of interval &log &optional;
|
||||
## The DNS query was rejected by the server.
|
||||
rejected: bool &log &default=F;
|
||||
|
||||
## This value indicates if this request/response pair is ready to be
|
||||
## logged.
|
||||
ready: bool &default=F;
|
||||
## The total number of resource records in a reply message's answer
|
||||
## section.
|
||||
## The total number of resource records in a reply message's
|
||||
## answer section.
|
||||
total_answers: count &optional;
|
||||
## The total number of resource records in a reply message's answer,
|
||||
## authority, and additional sections.
|
||||
## The total number of resource records in a reply message's
|
||||
## answer, authority, and additional sections.
|
||||
total_replies: count &optional;
|
||||
|
||||
## Whether the full DNS query has been seen.
|
||||
saw_query: bool &default=F;
|
||||
## Whether the full DNS reply has been seen.
|
||||
saw_reply: bool &default=F;
|
||||
};
|
||||
|
||||
## An event that can be handled to access the :bro:type:`DNS::Info`
|
||||
## record as it is sent to the logging framework.
|
||||
global log_dns: event(rec: Info);
|
||||
|
||||
## This is called by the specific dns_*_reply events with a "reply" which
|
||||
## may not represent the full data available from the resource record, but
|
||||
## it's generally considered a summarization of the response(s).
|
||||
## This is called by the specific dns_*_reply events with a "reply"
|
||||
## which may not represent the full data available from the resource
|
||||
## record, but it's generally considered a summarization of the
|
||||
## responses.
|
||||
##
|
||||
## c: The connection record for which to fill in DNS reply data.
|
||||
##
|
||||
|
@ -89,30 +92,50 @@ export {
|
|||
## ans: The general information of a RR response.
|
||||
##
|
||||
## reply: The specific response information according to RR type/class.
|
||||
global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
|
||||
global do_reply: hook(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
|
||||
|
||||
## A hook that is called whenever a session is being set.
|
||||
## This can be used if additional initialization logic needs to happen
|
||||
## when creating a new session value.
|
||||
##
|
||||
## c: The connection involved in the new session
|
||||
## c: The connection involved in the new session.
|
||||
##
|
||||
## msg: The DNS message header information.
|
||||
##
|
||||
## is_query: Indicator for if this is being called for a query or a response.
|
||||
global set_session: hook(c: connection, msg: dns_msg, is_query: bool);
|
||||
|
||||
## Yields a queue of :bro:see:`DNS::Info` objects for a given
|
||||
## DNS message query/transaction ID.
|
||||
type PendingMessages: table[count] of Queue::Queue;
|
||||
|
||||
## The amount of time that DNS queries or replies for a given
|
||||
## query/transaction ID are allowed to be queued while waiting for
|
||||
## a matching reply or query.
|
||||
const pending_msg_expiry_interval = 2min &redef;
|
||||
|
||||
## Give up trying to match pending DNS queries or replies for a given
|
||||
## query/transaction ID once this number of unmatched queries or replies
|
||||
## is reached (this shouldn't happen unless either the DNS server/resolver
|
||||
## is broken, Bro is not seeing all the DNS traffic, or an AXFR query
|
||||
## response is ongoing).
|
||||
const max_pending_msgs = 50 &redef;
|
||||
|
||||
## Give up trying to match pending DNS queries or replies across all
|
||||
## query/transaction IDs once there is at least one unmatched query or
|
||||
## reply across this number of different query IDs.
|
||||
const max_pending_query_ids = 50 &redef;
|
||||
|
||||
## A record type which tracks the status of DNS queries for a given
|
||||
## :bro:type:`connection`.
|
||||
type State: record {
|
||||
## Indexed by query id, returns Info record corresponding to
|
||||
## query/response which haven't completed yet.
|
||||
pending: table[count] of Queue::Queue;
|
||||
## queries that haven't been matched with a response yet.
|
||||
pending_queries: PendingMessages;
|
||||
|
||||
## This is the list of DNS responses that have completed based on the
|
||||
## number of responses declared and the number received. The contents
|
||||
## of the set are transaction IDs.
|
||||
finished_answers: set[count];
|
||||
## Indexed by query id, returns Info record corresponding to
|
||||
## replies that haven't been matched with a query yet.
|
||||
pending_replies: PendingMessages;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -142,6 +165,66 @@ function new_session(c: connection, trans_id: count): Info
|
|||
return info;
|
||||
}
|
||||
|
||||
function log_unmatched_msgs_queue(q: Queue::Queue)
|
||||
{
|
||||
local infos: vector of Info;
|
||||
Queue::get_vector(q, infos);
|
||||
|
||||
for ( i in infos )
|
||||
{
|
||||
event flow_weird("dns_unmatched_msg",
|
||||
infos[i]$id$orig_h, infos[i]$id$resp_h);
|
||||
Log::write(DNS::LOG, infos[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function log_unmatched_msgs(msgs: PendingMessages)
|
||||
{
|
||||
for ( trans_id in msgs )
|
||||
log_unmatched_msgs_queue(msgs[trans_id]);
|
||||
|
||||
msgs = PendingMessages();
|
||||
}
|
||||
|
||||
function enqueue_new_msg(msgs: PendingMessages, id: count, msg: Info)
|
||||
{
|
||||
if ( id !in msgs )
|
||||
{
|
||||
if ( |msgs| > max_pending_query_ids )
|
||||
{
|
||||
event flow_weird("dns_unmatched_query_id_quantity",
|
||||
msg$id$orig_h, msg$id$resp_h);
|
||||
# Throw away all unmatched on assumption they'll never be matched.
|
||||
log_unmatched_msgs(msgs);
|
||||
}
|
||||
|
||||
msgs[id] = Queue::init();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( Queue::len(msgs[id]) > max_pending_msgs )
|
||||
{
|
||||
event flow_weird("dns_unmatched_msg_quantity",
|
||||
msg$id$orig_h, msg$id$resp_h);
|
||||
log_unmatched_msgs_queue(msgs[id]);
|
||||
# Throw away all unmatched on assumption they'll never be matched.
|
||||
msgs[id] = Queue::init();
|
||||
}
|
||||
}
|
||||
|
||||
Queue::put(msgs[id], msg);
|
||||
}
|
||||
|
||||
function pop_msg(msgs: PendingMessages, id: count): Info
|
||||
{
|
||||
local rval: Info = Queue::get(msgs[id]);
|
||||
|
||||
if ( Queue::len(msgs[id]) == 0 )
|
||||
delete msgs[id];
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
hook set_session(c: connection, msg: dns_msg, is_query: bool) &priority=5
|
||||
{
|
||||
if ( ! c?$dns_state )
|
||||
|
@ -150,29 +233,39 @@ hook set_session(c: connection, msg: dns_msg, is_query: bool) &priority=5
|
|||
c$dns_state = state;
|
||||
}
|
||||
|
||||
if ( msg$id !in c$dns_state$pending )
|
||||
c$dns_state$pending[msg$id] = Queue::init();
|
||||
|
||||
local info: Info;
|
||||
# If this is either a query or this is the reply but
|
||||
# no Info records are in the queue (we missed the query?)
|
||||
# we need to create an Info record and put it in the queue.
|
||||
if ( is_query ||
|
||||
Queue::len(c$dns_state$pending[msg$id]) == 0 )
|
||||
{
|
||||
info = new_session(c, msg$id);
|
||||
Queue::put(c$dns_state$pending[msg$id], info);
|
||||
}
|
||||
|
||||
if ( is_query )
|
||||
# If this is a query, assign the newly created info variable
|
||||
# so that the world looks correct to anything else handling
|
||||
# this query.
|
||||
c$dns = info;
|
||||
{
|
||||
if ( msg$id in c$dns_state$pending_replies &&
|
||||
Queue::len(c$dns_state$pending_replies[msg$id]) > 0 )
|
||||
{
|
||||
# Match this DNS query w/ what's at head of pending reply queue.
|
||||
c$dns = pop_msg(c$dns_state$pending_replies, msg$id);
|
||||
}
|
||||
else
|
||||
{
|
||||
# Create a new DNS session and put it in the query queue so
|
||||
# we can wait for a matching reply.
|
||||
c$dns = new_session(c, msg$id);
|
||||
enqueue_new_msg(c$dns_state$pending_queries, msg$id, c$dns);
|
||||
}
|
||||
}
|
||||
else
|
||||
# Peek at the next item in the queue for this trans_id and
|
||||
# assign it to c$dns since this is a response.
|
||||
c$dns = Queue::peek(c$dns_state$pending[msg$id]);
|
||||
{
|
||||
if ( msg$id in c$dns_state$pending_queries &&
|
||||
Queue::len(c$dns_state$pending_queries[msg$id]) > 0 )
|
||||
{
|
||||
# Match this DNS reply w/ what's at head of pending query queue.
|
||||
c$dns = pop_msg(c$dns_state$pending_queries, msg$id);
|
||||
}
|
||||
else
|
||||
{
|
||||
# Create a new DNS session and put it in the reply queue so
|
||||
# we can wait for a matching query.
|
||||
c$dns = new_session(c, msg$id);
|
||||
event conn_weird("dns_unmatched_reply", c, "");
|
||||
enqueue_new_msg(c$dns_state$pending_replies, msg$id, c$dns);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! is_query )
|
||||
{
|
||||
|
@ -182,36 +275,36 @@ hook set_session(c: connection, msg: dns_msg, is_query: bool) &priority=5
|
|||
if ( ! c$dns?$total_answers )
|
||||
c$dns$total_answers = msg$num_answers;
|
||||
|
||||
if ( c$dns?$total_replies &&
|
||||
c$dns$total_replies != msg$num_answers + msg$num_addl + msg$num_auth )
|
||||
{
|
||||
event conn_weird("dns_changed_number_of_responses", c,
|
||||
fmt("The declared number of responses changed from %d to %d",
|
||||
c$dns$total_replies,
|
||||
msg$num_answers + msg$num_addl + msg$num_auth));
|
||||
}
|
||||
else
|
||||
{
|
||||
# Store the total number of responses expected from the first reply.
|
||||
if ( ! c$dns?$total_replies )
|
||||
c$dns$total_replies = msg$num_answers + msg$num_addl + msg$num_auth;
|
||||
}
|
||||
|
||||
if ( msg$rcode != 0 && msg$num_queries == 0 )
|
||||
c$dns$rejected = T;
|
||||
}
|
||||
}
|
||||
|
||||
event dns_message(c: connection, is_orig: bool, msg: dns_msg, len: count) &priority=5
|
||||
{
|
||||
hook set_session(c, msg, is_orig);
|
||||
if ( msg$opcode != 0 )
|
||||
# Currently only standard queries are tracked.
|
||||
return;
|
||||
|
||||
hook set_session(c, msg, ! msg$QR);
|
||||
}
|
||||
|
||||
event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=5
|
||||
hook DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=5
|
||||
{
|
||||
if ( msg$opcode != 0 )
|
||||
# Currently only standard queries are tracked.
|
||||
return;
|
||||
|
||||
if ( ! msg$QR )
|
||||
# This is weird: the inquirer must also be providing answers in
|
||||
# the request, which is not what we want to track.
|
||||
return;
|
||||
|
||||
if ( ans$answer_type == DNS_ANS )
|
||||
{
|
||||
if ( ! c?$dns )
|
||||
{
|
||||
event conn_weird("dns_unmatched_reply", c, "");
|
||||
hook set_session(c, msg, F);
|
||||
}
|
||||
c$dns$AA = msg$AA;
|
||||
c$dns$RA = msg$RA;
|
||||
|
||||
|
@ -225,29 +318,35 @@ event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string)
|
|||
c$dns$TTLs = vector();
|
||||
c$dns$TTLs[|c$dns$TTLs|] = ans$TTL;
|
||||
}
|
||||
|
||||
if ( c$dns?$answers && c$dns?$total_answers &&
|
||||
|c$dns$answers| == c$dns$total_answers )
|
||||
{
|
||||
# Indicate this request/reply pair is ready to be logged.
|
||||
c$dns$ready = T;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=-5
|
||||
event dns_end(c: connection, msg: dns_msg) &priority=5
|
||||
{
|
||||
if ( c$dns$ready )
|
||||
if ( ! c?$dns )
|
||||
return;
|
||||
|
||||
if ( msg$QR )
|
||||
c$dns$saw_reply = T;
|
||||
else
|
||||
c$dns$saw_query = T;
|
||||
}
|
||||
|
||||
event dns_end(c: connection, msg: dns_msg) &priority=-5
|
||||
{
|
||||
if ( c?$dns && c$dns$saw_reply && c$dns$saw_query )
|
||||
{
|
||||
Log::write(DNS::LOG, c$dns);
|
||||
# This record is logged and no longer pending.
|
||||
Queue::get(c$dns_state$pending[c$dns$trans_id]);
|
||||
delete c$dns;
|
||||
}
|
||||
}
|
||||
|
||||
event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) &priority=5
|
||||
{
|
||||
if ( msg$opcode != 0 )
|
||||
# Currently only standard queries are tracked.
|
||||
return;
|
||||
|
||||
c$dns$RD = msg$RD;
|
||||
c$dns$TC = msg$TC;
|
||||
c$dns$qclass = qclass;
|
||||
|
@ -260,64 +359,78 @@ event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qcla
|
|||
# Note: I'm ignoring the name type for now. Not sure if this should be
|
||||
# worked into the query/response in some fashion.
|
||||
if ( c$id$resp_p == 137/udp )
|
||||
{
|
||||
query = decode_netbios_name(query);
|
||||
if ( c$dns$qtype_name == "SRV" )
|
||||
{
|
||||
# The SRV RFC used the ID used for NetBios Status RRs.
|
||||
# So if this is NetBios Name Service we name it correctly.
|
||||
c$dns$qtype_name = "NBSTAT";
|
||||
}
|
||||
}
|
||||
c$dns$query = query;
|
||||
}
|
||||
|
||||
|
||||
event dns_unknown_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5
|
||||
{
|
||||
hook DNS::do_reply(c, msg, ans, fmt("<unknown type=%s>", ans$qtype));
|
||||
}
|
||||
|
||||
event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
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::do_reply(c, msg, ans, str);
|
||||
hook DNS::do_reply(c, msg, ans, str);
|
||||
}
|
||||
|
||||
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
hook DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
}
|
||||
|
||||
event dns_A6_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
hook DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
}
|
||||
|
||||
event dns_NS_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, name);
|
||||
hook DNS::do_reply(c, msg, ans, name);
|
||||
}
|
||||
|
||||
event dns_CNAME_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, name);
|
||||
hook DNS::do_reply(c, msg, ans, name);
|
||||
}
|
||||
|
||||
event dns_MX_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string,
|
||||
preference: count) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, name);
|
||||
hook DNS::do_reply(c, msg, ans, name);
|
||||
}
|
||||
|
||||
event dns_PTR_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, name);
|
||||
hook DNS::do_reply(c, msg, ans, name);
|
||||
}
|
||||
|
||||
event dns_SOA_reply(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, soa$mname);
|
||||
hook DNS::do_reply(c, msg, ans, soa$mname);
|
||||
}
|
||||
|
||||
event dns_WKS_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, "");
|
||||
hook DNS::do_reply(c, msg, ans, "");
|
||||
}
|
||||
|
||||
event dns_SRV_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5
|
||||
event dns_SRV_reply(c: connection, msg: dns_msg, ans: dns_answer, target: string, priority: count, weight: count, p: count) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, "");
|
||||
hook DNS::do_reply(c, msg, ans, target);
|
||||
}
|
||||
|
||||
# TODO: figure out how to handle these
|
||||
|
@ -338,7 +451,8 @@ event dns_SRV_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5
|
|||
|
||||
event dns_rejected(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) &priority=5
|
||||
{
|
||||
c$dns$rejected = T;
|
||||
if ( c?$dns )
|
||||
c$dns$rejected = T;
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
|
@ -346,16 +460,8 @@ event connection_state_remove(c: connection) &priority=-5
|
|||
if ( ! c?$dns_state )
|
||||
return;
|
||||
|
||||
# If Bro is expiring state, we should go ahead and log all unlogged
|
||||
# request/response pairs now.
|
||||
for ( trans_id in c$dns_state$pending )
|
||||
{
|
||||
local infos: vector of Info;
|
||||
Queue::get_vector(c$dns_state$pending[trans_id], infos);
|
||||
for ( i in infos )
|
||||
{
|
||||
Log::write(DNS::LOG, infos[i]);
|
||||
}
|
||||
}
|
||||
# If Bro is expiring state, we should go ahead and log all unmatched
|
||||
# queries and replies now.
|
||||
log_unmatched_msgs(c$dns_state$pending_queries);
|
||||
log_unmatched_msgs(c$dns_state$pending_replies);
|
||||
}
|
||||
|
||||
|
|
1
scripts/base/protocols/ftp/README
Normal file
1
scripts/base/protocols/ftp/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for File Transfer Protocol (FTP) analysis.
|
|
@ -1,4 +1,5 @@
|
|||
@load ./utils-commands
|
||||
@load ./info
|
||||
@load ./main
|
||||
@load ./utils
|
||||
@load ./files
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
@load ./info
|
||||
@load ./main
|
||||
@load ./utils
|
||||
@load base/utils/conn-ids
|
||||
|
|
|
@ -4,21 +4,22 @@
|
|||
##! that successfully negotiate the GSSAPI method of an AUTH request
|
||||
##! and for which the exchange involved an encoded TLS/SSL handshake,
|
||||
##! indicating the GSI mechanism for GSSAPI was used. This analysis
|
||||
##! is all supported internally, this script simple adds the "gridftp"
|
||||
##! is all supported internally, this script simply adds the "gridftp"
|
||||
##! label to the *service* field of the control channel's
|
||||
##! :bro:type:`connection` record.
|
||||
##!
|
||||
##! GridFTP data channels are identified by a heuristic that relies on
|
||||
##! the fact that default settings for GridFTP clients typically
|
||||
##! mutally authenticate the data channel with TLS/SSL and negotiate a
|
||||
##! mutually authenticate the data channel with TLS/SSL and negotiate a
|
||||
##! NULL bulk cipher (no encryption). Connections with those
|
||||
##! attributes are then polled for two minutes with decreasing frequency
|
||||
##! to check if the transfer sizes are large enough to indicate a
|
||||
##! GridFTP data channel that would be undesireable to analyze further
|
||||
##! GridFTP data channel that would be undesirable to analyze further
|
||||
##! (e.g. stop TCP reassembly). A side effect is that true connection
|
||||
##! sizes are not logged, but at the benefit of saving CPU cycles that
|
||||
##! otherwise go to analyzing the large (and likely benign) connections.
|
||||
##! would otherwise go to analyzing the large (and likely benign) connections.
|
||||
|
||||
@load ./info
|
||||
@load ./main
|
||||
@load base/protocols/conn
|
||||
@load base/protocols/ssl
|
||||
|
@ -58,8 +59,8 @@ export {
|
|||
## been exceeded. This is called in a :bro:see:`ssl_established` event
|
||||
## handler and by default looks for both a client and server certificate
|
||||
## and for a NULL bulk cipher. One way in which this function could be
|
||||
## redefined is to make it also consider client/server certificate issuer
|
||||
## subjects.
|
||||
## redefined is to make it also consider client/server certificate
|
||||
## issuer subjects.
|
||||
##
|
||||
## c: The connection which may possibly be a GridFTP data channel.
|
||||
##
|
||||
|
|
74
scripts/base/protocols/ftp/info.bro
Normal file
74
scripts/base/protocols/ftp/info.bro
Normal file
|
@ -0,0 +1,74 @@
|
|||
##! Defines data structures for tracking and logging FTP sessions.
|
||||
|
||||
module FTP;
|
||||
|
||||
@load ./utils-commands
|
||||
|
||||
export {
|
||||
|
||||
## This setting changes if passwords used in FTP sessions are
|
||||
## captured or not.
|
||||
const default_capture_password = F &redef;
|
||||
|
||||
## The expected endpoints of an FTP data channel.
|
||||
type ExpectedDataChannel: record {
|
||||
## Whether PASV mode is toggled for control channel.
|
||||
passive: bool &log;
|
||||
## The host that will be initiating the data connection.
|
||||
orig_h: addr &log;
|
||||
## The host that will be accepting the data connection.
|
||||
resp_h: addr &log;
|
||||
## The port at which the acceptor is listening for the data
|
||||
## connection.
|
||||
resp_p: port &log;
|
||||
};
|
||||
|
||||
type Info: record {
|
||||
## Time when the command was sent.
|
||||
ts: time &log;
|
||||
## Unique ID for the connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## User name for the current FTP session.
|
||||
user: string &log &default="<unknown>";
|
||||
## Password for the current FTP session if captured.
|
||||
password: string &log &optional;
|
||||
## Command given by the client.
|
||||
command: string &log &optional;
|
||||
## Argument for the command if one is given.
|
||||
arg: string &log &optional;
|
||||
|
||||
## Libmagic "sniffed" file type if the command indicates a file
|
||||
## transfer.
|
||||
mime_type: string &log &optional;
|
||||
## Size of the file if the command indicates a file transfer.
|
||||
file_size: count &log &optional;
|
||||
|
||||
## Reply code from the server in response to the command.
|
||||
reply_code: count &log &optional;
|
||||
## Reply message from the server in response to the command.
|
||||
reply_msg: string &log &optional;
|
||||
|
||||
## Expected FTP data channel.
|
||||
data_channel: ExpectedDataChannel &log &optional;
|
||||
|
||||
## Current working directory that this session is in. By making
|
||||
## the default value '.', we can indicate that unless something
|
||||
## more concrete is discovered that the existing but unknown
|
||||
## directory is ok to use.
|
||||
cwd: string &default=".";
|
||||
|
||||
## Command that is currently waiting for a response.
|
||||
cmdarg: CmdArg &optional;
|
||||
## Queue for commands that have been sent but not yet responded
|
||||
## to are tracked here.
|
||||
pending_commands: PendingCmds;
|
||||
|
||||
## Indicates if the session is in active or passive mode.
|
||||
passive: bool &default=F;
|
||||
|
||||
## Determines if the password will be captured for this request.
|
||||
capture_password: bool &default=default_capture_password;
|
||||
};
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
##! will take on the full path that the client is at along with the requested
|
||||
##! file name.
|
||||
|
||||
@load ./info
|
||||
@load ./utils
|
||||
@load ./utils-commands
|
||||
@load base/utils/paths
|
||||
@load base/utils/numbers
|
||||
|
@ -20,74 +22,11 @@ export {
|
|||
"EPSV"
|
||||
} &redef;
|
||||
|
||||
## This setting changes if passwords used in FTP sessions are captured or not.
|
||||
const default_capture_password = F &redef;
|
||||
|
||||
## User IDs that can be considered "anonymous".
|
||||
const guest_ids = { "anonymous", "ftp", "ftpuser", "guest" } &redef;
|
||||
|
||||
## The expected endpoints of an FTP data channel.
|
||||
type ExpectedDataChannel: record {
|
||||
## Whether PASV mode is toggled for control channel.
|
||||
passive: bool &log;
|
||||
## The host that will be initiating the data connection.
|
||||
orig_h: addr &log;
|
||||
## The host that will be accepting the data connection.
|
||||
resp_h: addr &log;
|
||||
## The port at which the acceptor is listening for the data connection.
|
||||
resp_p: port &log;
|
||||
};
|
||||
|
||||
type Info: record {
|
||||
## Time when the command was sent.
|
||||
ts: time &log;
|
||||
## Unique ID for the connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## User name for the current FTP session.
|
||||
user: string &log &default="<unknown>";
|
||||
## Password for the current FTP session if captured.
|
||||
password: string &log &optional;
|
||||
## Command given by the client.
|
||||
command: string &log &optional;
|
||||
## Argument for the command if one is given.
|
||||
arg: string &log &optional;
|
||||
|
||||
## Libmagic "sniffed" file type if the command indicates a file transfer.
|
||||
mime_type: string &log &optional;
|
||||
## Size of the file if the command indicates a file transfer.
|
||||
file_size: count &log &optional;
|
||||
|
||||
## Reply code from the server in response to the command.
|
||||
reply_code: count &log &optional;
|
||||
## Reply message from the server in response to the command.
|
||||
reply_msg: string &log &optional;
|
||||
|
||||
## Expected FTP data channel.
|
||||
data_channel: ExpectedDataChannel &log &optional;
|
||||
|
||||
## Current working directory that this session is in. By making
|
||||
## the default value '.', we can indicate that unless something
|
||||
## more concrete is discovered that the existing but unknown
|
||||
## directory is ok to use.
|
||||
cwd: string &default=".";
|
||||
|
||||
## Command that is currently waiting for a response.
|
||||
cmdarg: CmdArg &optional;
|
||||
## Queue for commands that have been sent but not yet responded to
|
||||
## are tracked here.
|
||||
pending_commands: PendingCmds;
|
||||
|
||||
## Indicates if the session is in active or passive mode.
|
||||
passive: bool &default=F;
|
||||
|
||||
## Determines if the password will be captured for this request.
|
||||
capture_password: bool &default=default_capture_password;
|
||||
};
|
||||
|
||||
## This record is to hold a parsed FTP reply code. For example, for the
|
||||
## 201 status code, the digits would be parsed as: x->2, y->0, z=>1.
|
||||
## 201 status code, the digits would be parsed as: x->2, y->0, z->1.
|
||||
type ReplyCode: record {
|
||||
x: count;
|
||||
y: count;
|
||||
|
@ -102,8 +41,6 @@ export {
|
|||
global log_ftp: event(rec: Info);
|
||||
}
|
||||
|
||||
@load ./utils
|
||||
|
||||
# Add the state tracking information variable to the connection record
|
||||
redef record connection += {
|
||||
ftp: Info &optional;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
##! Utilities specific for FTP processing.
|
||||
|
||||
@load ./main
|
||||
@load ./info
|
||||
@load base/utils/addrs
|
||||
@load base/utils/paths
|
||||
|
||||
module FTP;
|
||||
|
||||
|
@ -10,14 +11,14 @@ export {
|
|||
##
|
||||
## rec: An :bro:type:`FTP::Info` record.
|
||||
##
|
||||
## Returns: A URL, not prefixed by "ftp://".
|
||||
## Returns: A URL, not prefixed by ``"ftp://"``.
|
||||
global build_url: function(rec: Info): string;
|
||||
|
||||
## Creates a URL from an :bro:type:`FTP::Info` record.
|
||||
##
|
||||
## rec: An :bro:type:`FTP::Info` record.
|
||||
##
|
||||
## Returns: A URL prefixed with "ftp://".
|
||||
## Returns: A URL prefixed with ``"ftp://"``.
|
||||
global build_url_ftp: function(rec: Info): string;
|
||||
|
||||
## Create an extremely shortened representation of a log line.
|
||||
|
|
1
scripts/base/protocols/http/README
Normal file
1
scripts/base/protocols/http/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Hypertext Transfer Protocol (HTTP) analysis.
|
|
@ -3,4 +3,4 @@
|
|||
@load ./utils
|
||||
@load ./files
|
||||
|
||||
@load-sigs ./dpd.sig
|
||||
@load-sigs ./dpd.sig
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# List of HTTP headers pulled from:
|
||||
# http://annevankesteren.nl/2007/10/http-methods
|
||||
signature dpd_http_client {
|
||||
ip-proto == tcp
|
||||
payload /^[[:space:]]*(GET|HEAD|POST)[[:space:]]*/
|
||||
payload /^[[:space:]]*(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT|PROPFIND|PROPPATCH|MKCOL|COPY|MOVE|LOCK|UNLOCK|VERSION-CONTROL|REPORT|CHECKOUT|CHECKIN|UNCHECKOUT|MKWORKSPACE|UPDATE|LABEL|MERGE|BASELINE-CONTROL|MKACTIVITY|ORDERPATCH|ACL|PATCH|SEARCH|BCOPY|BDELETE|BMOVE|BPROPFIND|BPROPPATCH|NOTIFY|POLL|SUBSCRIBE|UNSUBSCRIBE|X-MS-ENUMATTS|RPC_OUT_DATA|RPC_IN_DATA)[[:space:]]*/
|
||||
tcp-state originator
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,11 @@ export {
|
|||
|
||||
## The current entity.
|
||||
current_entity: Entity &optional;
|
||||
## Current number of MIME entities in the HTTP request message body.
|
||||
## Current number of MIME entities in the HTTP request message
|
||||
## body.
|
||||
orig_mime_depth: count &default=0;
|
||||
## Current number of MIME entities in the HTTP response message body.
|
||||
## Current number of MIME entities in the HTTP response message
|
||||
## body.
|
||||
resp_mime_depth: count &default=0;
|
||||
};
|
||||
}
|
||||
|
@ -70,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;
|
||||
|
@ -85,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;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
@load base/utils/numbers
|
||||
@load base/utils/files
|
||||
@load base/frameworks/tunnels
|
||||
|
||||
module HTTP;
|
||||
|
||||
|
@ -16,7 +17,8 @@ export {
|
|||
EMPTY
|
||||
};
|
||||
|
||||
## This setting changes if passwords used in Basic-Auth are captured or not.
|
||||
## This setting changes if passwords used in Basic-Auth are captured or
|
||||
## not.
|
||||
const default_capture_password = F &redef;
|
||||
|
||||
type Info: record {
|
||||
|
@ -36,8 +38,8 @@ export {
|
|||
## URI used in the request.
|
||||
uri: string &log &optional;
|
||||
## Value of the "referer" header. The comment is deliberately
|
||||
## misspelled like the standard declares, but the name used here is
|
||||
## "referrer" spelled correctly.
|
||||
## misspelled like the standard declares, but the name used here
|
||||
## is "referrer" spelled correctly.
|
||||
referrer: string &log &optional;
|
||||
## Value of the User-Agent header from the client.
|
||||
user_agent: string &log &optional;
|
||||
|
@ -55,7 +57,8 @@ export {
|
|||
info_code: count &log &optional;
|
||||
## Last seen 1xx informational reply message returned by the server.
|
||||
info_msg: string &log &optional;
|
||||
## Filename given in the Content-Disposition header sent by the server.
|
||||
## Filename given in the Content-Disposition header sent by the
|
||||
## server.
|
||||
filename: string &log &optional;
|
||||
## A set of indicators of various attributes discovered and
|
||||
## related to a particular request/response pair.
|
||||
|
@ -215,6 +218,17 @@ event http_reply(c: connection, version: string, code: count, reason: string) &p
|
|||
c$http$info_code = code;
|
||||
c$http$info_msg = reason;
|
||||
}
|
||||
|
||||
if ( c$http?$method && c$http$method == "CONNECT" && code == 200 )
|
||||
{
|
||||
# Copy this conn_id and set the orig_p to zero because in the case of CONNECT
|
||||
# proxies there will be potentially many source ports since a new proxy connection
|
||||
# is established for each proxied connection. We treat this as a singular
|
||||
# "tunnel".
|
||||
local tid = copy(c$id);
|
||||
tid$orig_p = 0/tcp;
|
||||
Tunnel::register([$cid=tid, $tunnel_type=Tunnel::HTTP]);
|
||||
}
|
||||
}
|
||||
|
||||
event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=5
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
module HTTP;
|
||||
|
||||
export {
|
||||
## Given a string containing a series of key-value pairs separated by "=",
|
||||
## this function can be used to parse out all of the key names.
|
||||
## Given a string containing a series of key-value pairs separated
|
||||
## by "=", this function can be used to parse out all of the key names.
|
||||
##
|
||||
## data: The raw data, such as a URL or cookie value.
|
||||
##
|
||||
|
@ -17,20 +17,20 @@ export {
|
|||
## Returns: A vector of strings containing the keys.
|
||||
global extract_keys: function(data: string, kv_splitter: pattern): string_vec;
|
||||
|
||||
## Creates a URL from an :bro:type:`HTTP::Info` record. This should handle
|
||||
## edge cases such as proxied requests appropriately.
|
||||
## Creates a URL from an :bro:type:`HTTP::Info` record. This should
|
||||
## handle edge cases such as proxied requests appropriately.
|
||||
##
|
||||
## rec: An :bro:type:`HTTP::Info` record.
|
||||
##
|
||||
## Returns: A URL, not prefixed by "http://".
|
||||
## Returns: A URL, not prefixed by ``"http://"``.
|
||||
global build_url: function(rec: Info): string;
|
||||
|
||||
## Creates a URL from an :bro:type:`HTTP::Info` record. This should handle
|
||||
## edge cases such as proxied requests appropriately.
|
||||
## Creates a URL from an :bro:type:`HTTP::Info` record. This should
|
||||
## handle edge cases such as proxied requests appropriately.
|
||||
##
|
||||
## rec: An :bro:type:`HTTP::Info` record.
|
||||
##
|
||||
## Returns: A URL prefixed with "http://".
|
||||
## Returns: A URL prefixed with ``"http://"``.
|
||||
global build_url_http: function(rec: Info): string;
|
||||
|
||||
## Create an extremely shortened representation of a log line.
|
||||
|
|
1
scripts/base/protocols/irc/README
Normal file
1
scripts/base/protocols/irc/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Internet Relay Chat (IRC) protocol analysis.
|
|
@ -15,9 +15,9 @@ export {
|
|||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## Nick name given for the connection.
|
||||
## Nickname given for the connection.
|
||||
nick: string &log &optional;
|
||||
## User name given for the connection.
|
||||
## Username given for the connection.
|
||||
user: string &log &optional;
|
||||
|
||||
## Command given by the client.
|
||||
|
|
1
scripts/base/protocols/modbus/README
Normal file
1
scripts/base/protocols/modbus/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Modbus protocol analysis.
|
|
@ -10,7 +10,7 @@ export {
|
|||
type Info: record {
|
||||
## Time of the request.
|
||||
ts: time &log;
|
||||
## Unique identifier for the connnection.
|
||||
## Unique identifier for the connection.
|
||||
uid: string &log;
|
||||
## Identifier for the connection.
|
||||
id: conn_id &log;
|
||||
|
@ -20,8 +20,8 @@ export {
|
|||
exception: string &log &optional;
|
||||
};
|
||||
|
||||
## Event that can be handled to access the Modbus record as it is sent on
|
||||
## to the logging framework.
|
||||
## Event that can be handled to access the Modbus record as it is sent
|
||||
## on to the logging framework.
|
||||
global log_modbus: event(rec: Info);
|
||||
}
|
||||
|
||||
|
|
1
scripts/base/protocols/pop3/README
Normal file
1
scripts/base/protocols/pop3/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for POP3 (Post Office Protocol) protocol analysis.
|
3
scripts/base/protocols/sip/__load__.bro
Normal file
3
scripts/base/protocols/sip/__load__.bro
Normal file
|
@ -0,0 +1,3 @@
|
|||
@load ./main
|
||||
|
||||
@load-sigs ./dpd.sig
|
5
scripts/base/protocols/sip/dpd.sig
Normal file
5
scripts/base/protocols/sip/dpd.sig
Normal file
|
@ -0,0 +1,5 @@
|
|||
signature dpd_sip {
|
||||
ip-proto == udp
|
||||
payload /^( SIP\/[0-9]\.[0-9]\x0d\x0a|SIP\/[0-9]\.[0-9] [0-9][0-9][0-9] )/
|
||||
enable "sip"
|
||||
}
|
217
scripts/base/protocols/sip/main.bro
Normal file
217
scripts/base/protocols/sip/main.bro
Normal file
|
@ -0,0 +1,217 @@
|
|||
##! Implements base functionality for SIP analysis. The logging model is
|
||||
##! to log request/response pairs and all relevant metadata together in
|
||||
##! a single record.
|
||||
|
||||
@load base/utils/numbers
|
||||
@load base/utils/files
|
||||
|
||||
module SIP;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp for when the request 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;
|
||||
## Represents the pipelined depth into the connection of this
|
||||
## request/response transaction.
|
||||
trans_depth: count &log;
|
||||
## Verb used in the SIP request (INVITE, REGISTER etc.).
|
||||
method: string &log &optional;
|
||||
## URI used in the request.
|
||||
uri: string &log &optional;
|
||||
## Contents of the Date: header from the client
|
||||
date: string &log &optional;
|
||||
## Contents of the From: header (call sender)
|
||||
## Note: The tag= value that's usually appended to the sender
|
||||
## is stripped off and not logged.
|
||||
from: string &log &optional;
|
||||
## Contents of the To: header (call recipient)
|
||||
to: string &log &optional;
|
||||
## Contents of the Reply-To: header
|
||||
reply_to: string &log &optional;
|
||||
## Contents of the Call-ID: header from the client
|
||||
call_id: string &log &optional;
|
||||
## Contents of the CSeq: header from the client
|
||||
seq: string &log &optional;
|
||||
## Contents of the Subject: header from the client
|
||||
subject: string &log &optional;
|
||||
## The message transmission path, as extracted from the headers.
|
||||
path: vector of string &log &optional;
|
||||
## Contents of the User-Agent: header from the client
|
||||
user_agent: string &log &optional;
|
||||
## Status code returned by the server.
|
||||
status_code: count &log &optional;
|
||||
## Status message returned by the server.
|
||||
status_msg: string &log &optional;
|
||||
## Contents of the Warning: header
|
||||
warning: string &log &optional;
|
||||
## Contents of the Content-Length: header from the client
|
||||
request_body_len: string &log &optional;
|
||||
## Contents of the Content-Length: header from the server
|
||||
response_body_len: string &log &optional;
|
||||
## Contents of the Content-Type: header from the server
|
||||
content_type: string &log &optional;
|
||||
};
|
||||
|
||||
type State: record {
|
||||
## Pending requests.
|
||||
pending: table[count] of Info;
|
||||
## Current request in the pending queue.
|
||||
current_request: count &default=0;
|
||||
## Current response in the pending queue.
|
||||
current_response: count &default=0;
|
||||
};
|
||||
|
||||
## A list of SIP methods. Other methods will generate a weird. Note
|
||||
## that the SIP analyzer will only accept methods consisting solely
|
||||
## of letters ``[A-Za-z]``.
|
||||
const sip_methods: set[string] = {
|
||||
"REGISTER", "INVITE", "ACK", "CANCEL", "BYE", "OPTIONS"
|
||||
} &redef;
|
||||
|
||||
## Event that can be handled to access the SIP record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_sip: event(rec: Info);
|
||||
}
|
||||
|
||||
# Add the sip state tracking fields to the connection record.
|
||||
redef record connection += {
|
||||
sip: Info &optional;
|
||||
sip_state: State &optional;
|
||||
};
|
||||
|
||||
const ports = { 5060/udp };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(SIP::LOG, [$columns=Info, $ev=log_sip]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SIP, ports);
|
||||
}
|
||||
|
||||
function new_sip_session(c: connection): Info
|
||||
{
|
||||
local tmp: Info;
|
||||
tmp$ts=network_time();
|
||||
tmp$uid=c$uid;
|
||||
tmp$id=c$id;
|
||||
# $current_request is set prior to the Info record creation so we
|
||||
# can use the value directly here.
|
||||
tmp$trans_depth = c$sip_state$current_request;
|
||||
|
||||
tmp$path = vector();
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function set_state(c: connection, is_request: bool)
|
||||
{
|
||||
if ( ! c?$sip_state )
|
||||
{
|
||||
local s: State;
|
||||
c$sip_state = s;
|
||||
}
|
||||
|
||||
# These deal with new requests and responses.
|
||||
if ( is_request && c$sip_state$current_request !in c$sip_state$pending )
|
||||
c$sip_state$pending[c$sip_state$current_request] = new_sip_session(c);
|
||||
if ( ! is_request && c$sip_state$current_response !in c$sip_state$pending )
|
||||
c$sip_state$pending[c$sip_state$current_response] = new_sip_session(c);
|
||||
|
||||
if ( is_request )
|
||||
c$sip = c$sip_state$pending[c$sip_state$current_request];
|
||||
else
|
||||
c$sip = c$sip_state$pending[c$sip_state$current_response];
|
||||
}
|
||||
|
||||
event sip_request(c: connection, method: string, original_URI: string, version: string) &priority=5
|
||||
{
|
||||
set_state(c, T);
|
||||
|
||||
c$sip$method = method;
|
||||
c$sip$uri = original_URI;
|
||||
|
||||
if ( method !in sip_methods )
|
||||
event conn_weird("unknown_SIP_method", c, method);
|
||||
}
|
||||
|
||||
event sip_reply(c: connection, version: string, code: count, reason: string) &priority=5
|
||||
{
|
||||
if ( c$sip_state$current_response !in c$sip_state$pending )
|
||||
++c$sip_state$current_response;
|
||||
set_state(c, F);
|
||||
|
||||
c$sip$status_code = code;
|
||||
c$sip$status_msg = reason;
|
||||
}
|
||||
|
||||
event sip_header(c: connection, is_request: bool, name: string, value: string) &priority=5
|
||||
{
|
||||
if ( ! c?$sip_state )
|
||||
{
|
||||
local s: State;
|
||||
c$sip_state = s;
|
||||
}
|
||||
|
||||
if ( is_request ) # from client
|
||||
{
|
||||
if ( c$sip_state$current_request !in c$sip_state$pending )
|
||||
++c$sip_state$current_request;
|
||||
set_state(c, is_request);
|
||||
if ( name == "CALL-ID" ) c$sip$call_id = value;
|
||||
else if ( name == "CONTENT-LENGTH" || name == "L" ) c$sip$request_body_len = value;
|
||||
else if ( name == "CSEQ" ) c$sip$seq = value;
|
||||
else if ( name == "DATE" ) c$sip$date = value;
|
||||
else if ( name == "FROM" || name == "F" ) c$sip$from = split1(value, /;[ ]?tag=/)[1];
|
||||
else if ( name == "REPLY-TO" ) c$sip$reply_to = value;
|
||||
else if ( name == "SUBJECT" || name == "S" ) c$sip$subject = value;
|
||||
else if ( name == "TO" || name == "T" ) c$sip$to = value;
|
||||
else if ( name == "USER-AGENT" ) c$sip$user_agent = value;
|
||||
else if ( name == "VIA" || name == "V" ) c$sip$path[|c$sip$path|] = split1(value, /;[ ]?branch/)[1];
|
||||
c$sip_state$pending[c$sip_state$current_request] = c$sip;
|
||||
}
|
||||
else # from server
|
||||
{
|
||||
if ( c$sip_state$current_response !in c$sip_state$pending )
|
||||
++c$sip_state$current_response;
|
||||
set_state(c, is_request);
|
||||
if ( name == "CONTENT-LENGTH" || name == "L" ) c$sip$response_body_len = value;
|
||||
else if ( name == "CONTENT-TYPE" || name == "C" ) c$sip$content_type = value;
|
||||
else if ( name == "WARNING" ) c$sip$warning = value;
|
||||
c$sip_state$pending[c$sip_state$current_response] = c$sip;
|
||||
}
|
||||
}
|
||||
|
||||
event sip_message_done(c: connection, is_request: bool) &priority = 5
|
||||
{
|
||||
set_state(c, is_request);
|
||||
}
|
||||
|
||||
event sip_message_done(c: connection, is_request: bool) &priority = -5
|
||||
{
|
||||
# The reply body is done so we're ready to log.
|
||||
if ( ! is_request )
|
||||
{
|
||||
Log::write(SIP::LOG, c$sip);
|
||||
delete c$sip_state$pending[c$sip_state$current_response];
|
||||
}
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
# Flush all pending but incomplete request/response pairs.
|
||||
if ( c?$sip_state )
|
||||
{
|
||||
for ( r in c$sip_state$pending )
|
||||
{
|
||||
# We don't use pending elements at index 0.
|
||||
if ( r == 0 ) next;
|
||||
Log::write(SIP::LOG, c$sip_state$pending[r]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
scripts/base/protocols/smtp/README
Normal file
1
scripts/base/protocols/smtp/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Simple Mail Transfer Protocol (SMTP) analysis.
|
|
@ -27,8 +27,10 @@ export {
|
|||
|
||||
event mime_begin_entity(c: connection) &priority=10
|
||||
{
|
||||
c$smtp$entity = Entity();
|
||||
++c$smtp_state$mime_depth;
|
||||
if ( c?$smtp )
|
||||
c$smtp$entity = Entity();
|
||||
if ( c?$smtp_state )
|
||||
++c$smtp_state$mime_depth;
|
||||
}
|
||||
|
||||
event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5
|
||||
|
|
|
@ -14,8 +14,8 @@ export {
|
|||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## A count to represent the depth of this message transaction in a single
|
||||
## connection where multiple messages were transferred.
|
||||
## A count to represent the depth of this message transaction in
|
||||
## a single connection where multiple messages were transferred.
|
||||
trans_depth: count &log;
|
||||
## Contents of the Helo header.
|
||||
helo: string &log &optional;
|
||||
|
@ -37,7 +37,7 @@ export {
|
|||
in_reply_to: string &log &optional;
|
||||
## Contents of the Subject header.
|
||||
subject: string &log &optional;
|
||||
## Contents of the X-Origininating-IP header.
|
||||
## Contents of the X-Originating-IP header.
|
||||
x_originating_ip: addr &log &optional;
|
||||
## Contents of the first Received header.
|
||||
first_received: string &log &optional;
|
||||
|
@ -50,7 +50,8 @@ export {
|
|||
## Value of the User-Agent header from the client.
|
||||
user_agent: string &log &optional;
|
||||
|
||||
## Indicates if the "Received: from" headers should still be processed.
|
||||
## 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;
|
||||
|
@ -58,9 +59,9 @@ export {
|
|||
|
||||
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.
|
||||
## 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;
|
||||
|
@ -290,7 +291,7 @@ function describe(rec: Info): string
|
|||
{
|
||||
if ( |rec$subject| > 20 )
|
||||
{
|
||||
abbrev_subject = rec$subject[0:20] + "...";
|
||||
abbrev_subject = rec$subject[0:21] + "...";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
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
|
15
scripts/base/protocols/snmp/main.bro
Normal file
15
scripts/base/protocols/snmp/main.bro
Normal file
|
@ -0,0 +1,15 @@
|
|||
##! Enables analysis of SNMP datagrams.
|
||||
|
||||
module SNMP;
|
||||
|
||||
export {
|
||||
}
|
||||
|
||||
const ports = { 161/udp, 162/udp };
|
||||
|
||||
redef likely_server_ports += { ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SNMP, ports);
|
||||
}
|
1
scripts/base/protocols/socks/README
Normal file
1
scripts/base/protocols/socks/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Socket Secure (SOCKS) protocol analysis.
|
|
@ -9,17 +9,19 @@ export {
|
|||
type Info: record {
|
||||
## Time when the proxy connection was first detected.
|
||||
ts: time &log;
|
||||
## Unique ID for the tunnel - may correspond to connection uid or be non-existent.
|
||||
## Unique ID for the tunnel - may correspond to connection uid
|
||||
## or be non-existent.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## Protocol version of SOCKS.
|
||||
version: count &log;
|
||||
## Username for the proxy if extracted from the network..
|
||||
## Username for the proxy if extracted from the network.
|
||||
user: string &log &optional;
|
||||
## Server status for the attempt at using the proxy.
|
||||
status: string &log &optional;
|
||||
## Client requested SOCKS address. Could be an address, a name or both.
|
||||
## Client requested SOCKS address. Could be an address, a name
|
||||
## or both.
|
||||
request: SOCKS::Address &log &optional;
|
||||
## Client requested port.
|
||||
request_p: port &log &optional;
|
||||
|
|
1
scripts/base/protocols/ssh/README
Normal file
1
scripts/base/protocols/ssh/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Secure Shell (SSH) protocol analysis.
|
|
@ -25,8 +25,8 @@ export {
|
|||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## Indicates if the login was heuristically guessed to be "success",
|
||||
## "failure", or "undetermined".
|
||||
## Indicates if the login was heuristically guessed to be
|
||||
## "success", "failure", or "undetermined".
|
||||
status: string &log &default="undetermined";
|
||||
## Direction of the connection. If the client was a local host
|
||||
## logging into an external host, this would be OUTBOUND. INBOUND
|
||||
|
@ -37,12 +37,6 @@ export {
|
|||
client: string &log &optional;
|
||||
## Software string from the server.
|
||||
server: string &log &optional;
|
||||
## Amount of data returned from the server. This is currently
|
||||
## the only measure of the success heuristic and it is logged to
|
||||
## assist analysts looking at the logs to make their own determination
|
||||
## about the success on a case-by-case basis.
|
||||
resp_size: count &log &default=0;
|
||||
|
||||
## Indicate if the SSH session is done being watched.
|
||||
done: bool &default=F;
|
||||
};
|
||||
|
@ -107,10 +101,10 @@ function check_ssh_connection(c: connection, done: bool)
|
|||
# this matches the conditions for a failed login. Failed
|
||||
# logins are only detected at connection state removal.
|
||||
|
||||
if ( # Require originators to have sent at least 50 bytes.
|
||||
c$orig$size > 50 &&
|
||||
if ( # Require originators and responders to have sent at least 50 bytes.
|
||||
c$orig$size > 50 && c$resp$size > 50 &&
|
||||
# Responders must be below 4000 bytes.
|
||||
c$resp$size < 4000 &&
|
||||
c$resp$size < authentication_data_size &&
|
||||
# Responder must have sent fewer than 40 packets.
|
||||
c$resp$num_pkts < 40 &&
|
||||
# If there was a content gap we can't reliably do this heuristic.
|
||||
|
@ -122,7 +116,7 @@ function check_ssh_connection(c: connection, done: bool)
|
|||
event SSH::heuristic_failed_login(c);
|
||||
}
|
||||
|
||||
if ( c$resp$size > authentication_data_size )
|
||||
if ( c$resp$size >= authentication_data_size )
|
||||
{
|
||||
c$ssh$status = "success";
|
||||
event SSH::heuristic_successful_login(c);
|
||||
|
@ -132,7 +126,7 @@ function check_ssh_connection(c: connection, done: bool)
|
|||
{
|
||||
# If this connection is still being tracked, then it's possible
|
||||
# to watch for it to be a successful connection.
|
||||
if ( c$resp$size > authentication_data_size )
|
||||
if ( c$resp$size >= authentication_data_size )
|
||||
{
|
||||
c$ssh$status = "success";
|
||||
event SSH::heuristic_successful_login(c);
|
||||
|
@ -150,8 +144,6 @@ function check_ssh_connection(c: connection, done: bool)
|
|||
# after detection is done.
|
||||
c$ssh$done=T;
|
||||
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
|
||||
if ( skip_processing_after_detection )
|
||||
{
|
||||
# Stop watching this connection, we don't care about it anymore.
|
||||
|
@ -161,10 +153,24 @@ function check_ssh_connection(c: connection, done: bool)
|
|||
}
|
||||
|
||||
|
||||
event heuristic_successful_login(c: connection) &priority=-5
|
||||
{
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
}
|
||||
|
||||
event heuristic_failed_login(c: connection) &priority=-5
|
||||
{
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( c?$ssh )
|
||||
{
|
||||
check_ssh_connection(c, T);
|
||||
if ( c$ssh$status == "undetermined" )
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
}
|
||||
}
|
||||
|
||||
event ssh_watcher(c: connection)
|
||||
|
|
1
scripts/base/protocols/ssl/README
Normal file
1
scripts/base/protocols/ssl/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Secure Sockets Layer (SSL) protocol analysis.
|
|
@ -1,5 +1,6 @@
|
|||
@load ./consts
|
||||
@load ./main
|
||||
@load ./mozilla-ca-list
|
||||
@load ./files
|
||||
|
||||
@load-sigs ./dpd.sig
|
||||
@load-sigs ./dpd.sig
|
||||
|
|
|
@ -23,7 +23,7 @@ export {
|
|||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between numeric codes and human readable strings for alert
|
||||
## descriptions..
|
||||
## descriptions.
|
||||
const alert_descriptions: table[count] of string = {
|
||||
[0] = "close_notify",
|
||||
[10] = "unexpected_message",
|
||||
|
@ -47,6 +47,7 @@ export {
|
|||
[70] = "protocol_version",
|
||||
[71] = "insufficient_security",
|
||||
[80] = "internal_error",
|
||||
[86] = "inappropriate_fallback",
|
||||
[90] = "user_canceled",
|
||||
[100] = "no_renegotiation",
|
||||
[110] = "unsupported_extension",
|
||||
|
@ -55,6 +56,7 @@ export {
|
|||
[113] = "bad_certificate_status_response",
|
||||
[114] = "bad_certificate_hash_value",
|
||||
[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
|
||||
|
@ -78,11 +80,17 @@ export {
|
|||
[13] = "signature_algorithms",
|
||||
[14] = "use_srtp",
|
||||
[15] = "heartbeat",
|
||||
[16] = "application_layer_protocol_negotiation",
|
||||
[17] = "status_request_v2",
|
||||
[18] = "signed_certificate_timestamp",
|
||||
[35] = "SessionTicket TLS",
|
||||
[40] = "extended_random",
|
||||
[13172] = "next_protocol_negotiation",
|
||||
[13175] = "origin_bound_certificates",
|
||||
[13180] = "encrypted_client_certificates",
|
||||
[30031] = "channel_id",
|
||||
[30032] = "channel_id_new",
|
||||
[35655] = "padding",
|
||||
[65281] = "renegotiation_info"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
|
@ -178,6 +186,21 @@ export {
|
|||
const TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B;
|
||||
const TLS_DH_ANON_WITH_AES_128_CBC_SHA256 = 0x006C;
|
||||
const TLS_DH_ANON_WITH_AES_256_CBC_SHA256 = 0x006D;
|
||||
# draft-ietf-tls-openpgp-keys-06
|
||||
const TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD = 0x0072;
|
||||
const TLS_DHE_DSS_WITH_AES_128_CBC_RMD = 0x0073;
|
||||
const TLS_DHE_DSS_WITH_AES_256_CBC_RMD = 0x0074;
|
||||
const TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD = 0x0077;
|
||||
const TLS_DHE_RSA_WITH_AES_128_CBC_RMD = 0x0078;
|
||||
const TLS_DHE_RSA_WITH_AES_256_CBC_RMD = 0x0079;
|
||||
const TLS_RSA_WITH_3DES_EDE_CBC_RMD = 0x007C;
|
||||
const TLS_RSA_WITH_AES_128_CBC_RMD = 0x007D;
|
||||
const TLS_RSA_WITH_AES_256_CBC_RMD = 0x007E;
|
||||
# draft-chudov-cryptopro-cptls-04
|
||||
const TLS_GOSTR341094_WITH_28147_CNT_IMIT = 0x0080;
|
||||
const TLS_GOSTR341001_WITH_28147_CNT_IMIT = 0x0081;
|
||||
const TLS_GOSTR341094_WITH_NULL_GOSTR3411 = 0x0082;
|
||||
const TLS_GOSTR341001_WITH_NULL_GOSTR3411 = 0x0083;
|
||||
const TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084;
|
||||
const TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085;
|
||||
const TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086;
|
||||
|
@ -244,6 +267,9 @@ export {
|
|||
const TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3;
|
||||
const TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4;
|
||||
const TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5;
|
||||
# draft-bmoeller-tls-downgrade-scsv-01
|
||||
const TLS_FALLBACK_SCSV = 0x5600;
|
||||
# RFC 4492
|
||||
const TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001;
|
||||
const TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002;
|
||||
const TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003;
|
||||
|
@ -303,6 +329,126 @@ export {
|
|||
const TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039;
|
||||
const TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A;
|
||||
const TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B;
|
||||
# RFC 6209
|
||||
const TLS_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC03C;
|
||||
const TLS_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC03D;
|
||||
const TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 = 0xC03E;
|
||||
const TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 = 0xC03F;
|
||||
const TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC040;
|
||||
const TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC041;
|
||||
const TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 = 0xC042;
|
||||
const TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 = 0xC043;
|
||||
const TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC044;
|
||||
const TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC045;
|
||||
const TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256 = 0xC046;
|
||||
const TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384 = 0xC047;
|
||||
const TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 = 0xC048;
|
||||
const TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 = 0xC049;
|
||||
const TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 = 0xC04A;
|
||||
const TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 = 0xC04B;
|
||||
const TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC04C;
|
||||
const TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC04D;
|
||||
const TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC04E;
|
||||
const TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC04F;
|
||||
const TLS_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC050;
|
||||
const TLS_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC051;
|
||||
const TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC052;
|
||||
const TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC053;
|
||||
const TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC054;
|
||||
const TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC055;
|
||||
const TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC056;
|
||||
const TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC057;
|
||||
const TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC058;
|
||||
const TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC059;
|
||||
const TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256 = 0xC05A;
|
||||
const TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384 = 0xC05B;
|
||||
const TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05C;
|
||||
const TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05D;
|
||||
const TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05E;
|
||||
const TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05F;
|
||||
const TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC060;
|
||||
const TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC061;
|
||||
const TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC062;
|
||||
const TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC063;
|
||||
const TLS_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC064;
|
||||
const TLS_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC065;
|
||||
const TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC066;
|
||||
const TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC067;
|
||||
const TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC068;
|
||||
const TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC069;
|
||||
const TLS_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06A;
|
||||
const TLS_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06B;
|
||||
const TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06C;
|
||||
const TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06D;
|
||||
const TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06E;
|
||||
const TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06F;
|
||||
const TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC070;
|
||||
const TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC071;
|
||||
# RFC 6367
|
||||
const TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC072;
|
||||
const TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC073;
|
||||
const TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC074;
|
||||
const TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC075;
|
||||
const TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC076;
|
||||
const TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC077;
|
||||
const TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC078;
|
||||
const TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC079;
|
||||
const TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07A;
|
||||
const TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07B;
|
||||
const TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07C;
|
||||
const TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07D;
|
||||
const TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07E;
|
||||
const TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07F;
|
||||
const TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080;
|
||||
const TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081;
|
||||
const TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC082;
|
||||
const TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC083;
|
||||
const TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256 = 0xC084;
|
||||
const TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384 = 0xC085;
|
||||
const TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086;
|
||||
const TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087;
|
||||
const TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC088;
|
||||
const TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC089;
|
||||
const TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08A;
|
||||
const TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08B;
|
||||
const TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08C;
|
||||
const TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08D;
|
||||
const TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08E;
|
||||
const TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08F;
|
||||
const TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090;
|
||||
const TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091;
|
||||
const TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC092;
|
||||
const TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC093;
|
||||
const TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC094;
|
||||
const TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC095;
|
||||
const TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC096;
|
||||
const TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC097;
|
||||
const TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC098;
|
||||
const TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC099;
|
||||
const TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC09A;
|
||||
const TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC09B;
|
||||
# RFC 6655
|
||||
const TLS_RSA_WITH_AES_128_CCM = 0xC09C;
|
||||
const TLS_RSA_WITH_AES_256_CCM = 0xC09D;
|
||||
const TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E;
|
||||
const TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F;
|
||||
const TLS_RSA_WITH_AES_128_CCM_8 = 0xC0A0;
|
||||
const TLS_RSA_WITH_AES_256_CCM_8 = 0xC0A1;
|
||||
const TLS_DHE_RSA_WITH_AES_128_CCM_8 = 0xC0A2;
|
||||
const TLS_DHE_RSA_WITH_AES_256_CCM_8 = 0xC0A3;
|
||||
const TLS_PSK_WITH_AES_128_CCM = 0xC0A4;
|
||||
const TLS_PSK_WITH_AES_256_CCM = 0xC0A5;
|
||||
const TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6;
|
||||
const TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7;
|
||||
const TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8;
|
||||
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;
|
||||
# draft-agl-tls-chacha20poly1305-02
|
||||
const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13;
|
||||
const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14;
|
||||
const TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC15;
|
||||
|
||||
const SSL_RSA_FIPS_WITH_DES_CBC_SHA = 0xFEFE;
|
||||
const SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA = 0xFEFF;
|
||||
const SSL_RSA_FIPS_WITH_DES_CBC_SHA_2 = 0xFFE1;
|
||||
|
@ -314,8 +460,8 @@ export {
|
|||
const TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
|
||||
|
||||
## 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.
|
||||
## detecting unknown ciphers and for converting the cipher spec
|
||||
## constants into a human readable format.
|
||||
const cipher_desc: table[count] of string = {
|
||||
[SSLv20_CK_RC4_128_EXPORT40_WITH_MD5] =
|
||||
"SSLv20_CK_RC4_128_EXPORT40_WITH_MD5",
|
||||
|
@ -410,6 +556,19 @@ export {
|
|||
[TLS_DHE_RSA_WITH_AES_256_CBC_SHA256] = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
|
||||
[TLS_DH_ANON_WITH_AES_128_CBC_SHA256] = "TLS_DH_ANON_WITH_AES_128_CBC_SHA256",
|
||||
[TLS_DH_ANON_WITH_AES_256_CBC_SHA256] = "TLS_DH_ANON_WITH_AES_256_CBC_SHA256",
|
||||
[TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD] = "TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD",
|
||||
[TLS_DHE_DSS_WITH_AES_128_CBC_RMD] = "TLS_DHE_DSS_WITH_AES_128_CBC_RMD",
|
||||
[TLS_DHE_DSS_WITH_AES_256_CBC_RMD] = "TLS_DHE_DSS_WITH_AES_256_CBC_RMD",
|
||||
[TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD] = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD",
|
||||
[TLS_DHE_RSA_WITH_AES_128_CBC_RMD] = "TLS_DHE_RSA_WITH_AES_128_CBC_RMD",
|
||||
[TLS_DHE_RSA_WITH_AES_256_CBC_RMD] = "TLS_DHE_RSA_WITH_AES_256_CBC_RMD",
|
||||
[TLS_RSA_WITH_3DES_EDE_CBC_RMD] = "TLS_RSA_WITH_3DES_EDE_CBC_RMD",
|
||||
[TLS_RSA_WITH_AES_128_CBC_RMD] = "TLS_RSA_WITH_AES_128_CBC_RMD",
|
||||
[TLS_RSA_WITH_AES_256_CBC_RMD] = "TLS_RSA_WITH_AES_256_CBC_RMD",
|
||||
[TLS_GOSTR341094_WITH_28147_CNT_IMIT] = "TLS_GOSTR341094_WITH_28147_CNT_IMIT",
|
||||
[TLS_GOSTR341001_WITH_28147_CNT_IMIT] = "TLS_GOSTR341001_WITH_28147_CNT_IMIT",
|
||||
[TLS_GOSTR341094_WITH_NULL_GOSTR3411] = "TLS_GOSTR341094_WITH_NULL_GOSTR3411",
|
||||
[TLS_GOSTR341001_WITH_NULL_GOSTR3411] = "TLS_GOSTR341001_WITH_NULL_GOSTR3411",
|
||||
[TLS_RSA_WITH_CAMELLIA_256_CBC_SHA] = "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
||||
[TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA] = "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",
|
||||
[TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA] = "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
||||
|
@ -476,6 +635,7 @@ export {
|
|||
[TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256] = "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",
|
||||
[TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256] = "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
|
||||
[TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256] = "TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256",
|
||||
[TLS_FALLBACK_SCSV] = "TLS_FALLBACK_SCSV",
|
||||
[TLS_ECDH_ECDSA_WITH_NULL_SHA] = "TLS_ECDH_ECDSA_WITH_NULL_SHA",
|
||||
[TLS_ECDH_ECDSA_WITH_RC4_128_SHA] = "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
|
||||
[TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA] = "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||
|
@ -535,10 +695,130 @@ export {
|
|||
[TLS_ECDHE_PSK_WITH_NULL_SHA] = "TLS_ECDHE_PSK_WITH_NULL_SHA",
|
||||
[TLS_ECDHE_PSK_WITH_NULL_SHA256] = "TLS_ECDHE_PSK_WITH_NULL_SHA256",
|
||||
[TLS_ECDHE_PSK_WITH_NULL_SHA384] = "TLS_ECDHE_PSK_WITH_NULL_SHA384",
|
||||
[TLS_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_RSA_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_RSA_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256] = "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384] = "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256] = "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384] = "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256] = "TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384] = "TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_RSA_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_RSA_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256] = "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384] = "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256] = "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384] = "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256] = "TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384] = "TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256] = "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384] = "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256] = "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384] = "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_PSK_WITH_ARIA_128_CBC_SHA256] = "TLS_PSK_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_PSK_WITH_ARIA_256_CBC_SHA384] = "TLS_PSK_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256] = "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384] = "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256] = "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384] = "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_PSK_WITH_ARIA_128_GCM_SHA256] = "TLS_PSK_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_PSK_WITH_ARIA_256_GCM_SHA384] = "TLS_PSK_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256] = "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384] = "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256] = "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256",
|
||||
[TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384] = "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384",
|
||||
[TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256",
|
||||
[TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384",
|
||||
[TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
[TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
[TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
[TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
[TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
[TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
[TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
[TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
[TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256",
|
||||
[TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384",
|
||||
[TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
[TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
[TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
[TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
[TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
[TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
[TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
[TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
[TLS_RSA_WITH_AES_128_CCM] = "TLS_RSA_WITH_AES_128_CCM",
|
||||
[TLS_RSA_WITH_AES_256_CCM] = "TLS_RSA_WITH_AES_256_CCM",
|
||||
[TLS_DHE_RSA_WITH_AES_128_CCM] = "TLS_DHE_RSA_WITH_AES_128_CCM",
|
||||
[TLS_DHE_RSA_WITH_AES_256_CCM] = "TLS_DHE_RSA_WITH_AES_256_CCM",
|
||||
[TLS_RSA_WITH_AES_128_CCM_8] = "TLS_RSA_WITH_AES_128_CCM_8",
|
||||
[TLS_RSA_WITH_AES_256_CCM_8] = "TLS_RSA_WITH_AES_256_CCM_8",
|
||||
[TLS_DHE_RSA_WITH_AES_128_CCM_8] = "TLS_DHE_RSA_WITH_AES_128_CCM_8",
|
||||
[TLS_DHE_RSA_WITH_AES_256_CCM_8] = "TLS_DHE_RSA_WITH_AES_256_CCM_8",
|
||||
[TLS_PSK_WITH_AES_128_CCM] = "TLS_PSK_WITH_AES_128_CCM",
|
||||
[TLS_PSK_WITH_AES_256_CCM] = "TLS_PSK_WITH_AES_256_CCM",
|
||||
[TLS_DHE_PSK_WITH_AES_128_CCM] = "TLS_DHE_PSK_WITH_AES_128_CCM",
|
||||
[TLS_DHE_PSK_WITH_AES_256_CCM] = "TLS_DHE_PSK_WITH_AES_256_CCM",
|
||||
[TLS_PSK_WITH_AES_128_CCM_8] = "TLS_PSK_WITH_AES_128_CCM_8",
|
||||
[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_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",
|
||||
[SSL_RSA_FIPS_WITH_DES_CBC_SHA] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA",
|
||||
[SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",
|
||||
[SSL_RSA_FIPS_WITH_DES_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA_2",
|
||||
[SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2",
|
||||
[SSL_RSA_WITH_RC2_CBC_MD5] = "SSL_RSA_WITH_RC2_CBC_MD5",
|
||||
[SSL_RSA_WITH_IDEA_CBC_MD5] = "SSL_RSA_WITH_IDEA_CBC_MD5",
|
||||
[SSL_RSA_WITH_DES_CBC_MD5] = "SSL_RSA_WITH_DES_CBC_MD5",
|
||||
[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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
149
scripts/base/protocols/ssl/files.bro
Normal file
149
scripts/base/protocols/ssl/files.bro
Normal file
|
@ -0,0 +1,149 @@
|
|||
@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
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
local depth: count;
|
||||
|
||||
if ( is_orig )
|
||||
{
|
||||
depth = c$ssl$client_depth;
|
||||
++c$ssl$client_depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = c$ssl$server_depth;
|
||||
++c$ssl$server_depth;
|
||||
}
|
||||
|
||||
return cat(Analyzer::ANALYZER_SSL, c$start_time, is_orig, id_string(c$id), depth);
|
||||
}
|
||||
|
||||
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$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_subject = c$ssl$client_cert_chain[0]$x509$certificate$subject;
|
||||
c$ssl$client_issuer = c$ssl$client_cert_chain[0]$x509$certificate$issuer;
|
||||
}
|
||||
}
|
|
@ -24,42 +24,25 @@ export {
|
|||
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;
|
||||
## 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;
|
||||
|
||||
## The analyzer ID used for the analyzer instance attached
|
||||
## to each connection. It is not used for logging since it's a
|
||||
## meaningless arbitrary number.
|
||||
analyzer_id: count &optional;
|
||||
|
||||
## Flag to indicate if this ssl session has been established
|
||||
## succesfully, or if it was aborted during the handshake.
|
||||
established: bool &log &default=F;
|
||||
|
||||
## Flag to indicate if this record already has been logged, to
|
||||
## prevent duplicates.
|
||||
logged: bool &default=F;
|
||||
};
|
||||
|
||||
## The default root CA bundle. By loading the
|
||||
## mozilla-ca-list.bro script it will be set to Mozilla's root CA list.
|
||||
## The default root CA bundle. By default, the mozilla-ca-list.bro
|
||||
## script sets this to Mozilla's root CA list.
|
||||
const root_certs: table[string] of string = {} &redef;
|
||||
|
||||
## If true, detach the SSL analyzer from the connection to prevent
|
||||
|
@ -67,11 +50,8 @@ export {
|
|||
## (especially with large file transfers).
|
||||
const disable_analyzer_after_detection = T &redef;
|
||||
|
||||
## The maximum amount of time a script can delay records from being logged.
|
||||
const max_log_delay = 15secs &redef;
|
||||
|
||||
## Delays an SSL record for a specific token: the record will not be logged
|
||||
## as longs the token exists or until :bro:id:`SSL::max_log_delay` elapses.
|
||||
## Delays an SSL record for a specific token: the record will not be
|
||||
## logged as long as the token exists or until 15 seconds elapses.
|
||||
global delay_log: function(info: Info, token: string);
|
||||
|
||||
## Undelays an SSL record for a previously inserted token, allowing the
|
||||
|
@ -90,7 +70,7 @@ redef record connection += {
|
|||
redef record Info += {
|
||||
# Adding a string "token" to this set will cause the SSL script
|
||||
# to delay logging the record until either the token has been removed or
|
||||
# the record has been delayed for :bro:id:`SSL::max_log_delay`.
|
||||
# the record has been delayed.
|
||||
delay_tokens: set[string] &optional;
|
||||
};
|
||||
|
||||
|
@ -109,8 +89,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)
|
||||
|
@ -128,9 +107,13 @@ function undelay_log(info: Info, token: string)
|
|||
|
||||
function log_record(info: Info)
|
||||
{
|
||||
if ( info$logged )
|
||||
return;
|
||||
|
||||
if ( ! info?$delay_tokens || |info$delay_tokens| == 0 )
|
||||
{
|
||||
Log::write(SSL::LOG, info);
|
||||
info$logged = T;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -138,22 +121,28 @@ function log_record(info: Info)
|
|||
{
|
||||
log_record(info);
|
||||
}
|
||||
timeout SSL::max_log_delay
|
||||
timeout 15secs
|
||||
{
|
||||
Reporter::info(fmt("SSL delay tokens not released in time (%s tokens remaining)",
|
||||
|info$delay_tokens|));
|
||||
# We are just going to log the record anyway.
|
||||
delete info$delay_tokens;
|
||||
log_record(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function finish(c: connection)
|
||||
# remove_analyzer flag is used to prevent disabling analyzer for finished
|
||||
# connections.
|
||||
function finish(c: connection, remove_analyzer: bool)
|
||||
{
|
||||
log_record(c$ssl);
|
||||
if ( disable_analyzer_after_detection && c?$ssl && c$ssl?$analyzer_id )
|
||||
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, session_id: string, ciphers: count_set) &priority=5
|
||||
event ssl_client_hello(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: index_vec) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
|
@ -162,7 +151,7 @@ event ssl_client_hello(c: connection, version: count, possible_ts: time, session
|
|||
c$ssl$session_id = bytestring_to_hexstr(session_id);
|
||||
}
|
||||
|
||||
event ssl_server_hello(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count) &priority=5
|
||||
event ssl_server_hello(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
|
@ -170,49 +159,6 @@ event ssl_server_hello(c: connection, version: count, possible_ts: time, session
|
|||
c$ssl$cipher = cipher_desc[cipher];
|
||||
}
|
||||
|
||||
event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &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;
|
||||
|
||||
# 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;
|
||||
|
||||
# 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event ssl_extension(c: connection, is_orig: bool, code: count, val: string) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
@ -228,26 +174,36 @@ 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;
|
||||
}
|
||||
|
||||
event ssl_established(c: connection) &priority=-5
|
||||
{
|
||||
finish(c);
|
||||
finish(c, T);
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( c?$ssl )
|
||||
# called in case a SSL connection that has not been established terminates
|
||||
finish(c, F);
|
||||
}
|
||||
|
||||
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=5
|
||||
{
|
||||
# Check by checking for existence of c$ssl record.
|
||||
if ( c?$ssl && atype == Analyzer::ANALYZER_SSL )
|
||||
if ( atype == Analyzer::ANALYZER_SSL )
|
||||
{
|
||||
set_session(c);
|
||||
c$ssl$analyzer_id = aid;
|
||||
}
|
||||
}
|
||||
|
||||
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count,
|
||||
reason: string) &priority=5
|
||||
{
|
||||
if ( c?$ssl )
|
||||
finish(c);
|
||||
finish(c, T);
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
1
scripts/base/protocols/syslog/README
Normal file
1
scripts/base/protocols/syslog/README
Normal file
|
@ -0,0 +1 @@
|
|||
Support for Syslog protocol analysis.
|
Loading…
Add table
Add a link
Reference in a new issue