mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 16:18:19 +00:00
Merge remote-tracking branch 'origin/topic/vladg/radius'
* origin/topic/vladg/radius: Fix a couple memleaks. Basic RADIUS functionality implemented. Basic RADIUS support - checkpoint
This commit is contained in:
commit
78ab8de60d
15 changed files with 639 additions and 6 deletions
|
@ -2773,6 +2773,24 @@ export {
|
||||||
name: string &optional;
|
name: string &optional;
|
||||||
} &log;
|
} &log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module RADIUS;
|
||||||
|
|
||||||
|
export {
|
||||||
|
type RADIUS::AttributeList: vector of string;
|
||||||
|
type RADIUS::Attributes: table[count] of RADIUS::AttributeList;
|
||||||
|
|
||||||
|
type RADIUS::Message: record {
|
||||||
|
## The type of message (Access-Request, Access-Accept, etc.).
|
||||||
|
code : count;
|
||||||
|
## The transaction ID.
|
||||||
|
trans_id : count;
|
||||||
|
## The "authenticator" string.
|
||||||
|
authenticator : string;
|
||||||
|
## Any attributes.
|
||||||
|
attributes : RADIUS::Attributes &optional;
|
||||||
|
};
|
||||||
|
}
|
||||||
module GLOBAL;
|
module GLOBAL;
|
||||||
|
|
||||||
@load base/bif/event.bif
|
@load base/bif/event.bif
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
@load base/protocols/irc
|
@load base/protocols/irc
|
||||||
@load base/protocols/modbus
|
@load base/protocols/modbus
|
||||||
@load base/protocols/pop3
|
@load base/protocols/pop3
|
||||||
|
@load base/protocols/radius
|
||||||
@load base/protocols/smtp
|
@load base/protocols/smtp
|
||||||
@load base/protocols/socks
|
@load base/protocols/socks
|
||||||
@load base/protocols/ssh
|
@load base/protocols/ssh
|
||||||
|
|
1
scripts/base/protocols/radius/__load__.bro
Normal file
1
scripts/base/protocols/radius/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@load ./main
|
231
scripts/base/protocols/radius/consts.bro
Normal file
231
scripts/base/protocols/radius/consts.bro
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
|
||||||
|
module RADIUS;
|
||||||
|
|
||||||
|
const msg_types: table[count] of string = {
|
||||||
|
[1] = "Access-Request",
|
||||||
|
[2] = "Access-Accept",
|
||||||
|
[3] = "Access-Reject",
|
||||||
|
[4] = "Accounting-Request",
|
||||||
|
[5] = "Accounting-Response",
|
||||||
|
[11] = "Access-Challenge",
|
||||||
|
[12] = "Status-Server",
|
||||||
|
[13] = "Status-Client",
|
||||||
|
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const attr_types: table[count] of string = {
|
||||||
|
[1] = "User-Name",
|
||||||
|
[2] = "User-Password",
|
||||||
|
[3] = "CHAP-Password",
|
||||||
|
[4] = "NAS-IP-Address",
|
||||||
|
[5] = "NAS-Port",
|
||||||
|
[6] = "Service-Type",
|
||||||
|
[7] = "Framed-Protocol",
|
||||||
|
[8] = "Framed-IP-Address",
|
||||||
|
[9] = "Framed-IP-Netmask",
|
||||||
|
[10] = "Framed-Routing",
|
||||||
|
[11] = "Filter-Id",
|
||||||
|
[12] = "Framed-MTU",
|
||||||
|
[13] = "Framed-Compression",
|
||||||
|
[14] = "Login-IP-Host",
|
||||||
|
[15] = "Login-Service",
|
||||||
|
[16] = "Login-TCP-Port",
|
||||||
|
[18] = "Reply-Message",
|
||||||
|
[19] = "Callback-Number",
|
||||||
|
[20] = "Callback-Id",
|
||||||
|
[22] = "Framed-Route",
|
||||||
|
[23] = "Framed-IPX-Network",
|
||||||
|
[24] = "State",
|
||||||
|
[25] = "Class",
|
||||||
|
[26] = "Vendor-Specific",
|
||||||
|
[27] = "Session-Timeout",
|
||||||
|
[28] = "Idle-Timeout",
|
||||||
|
[29] = "Termination-Action",
|
||||||
|
[30] = "Called-Station-Id",
|
||||||
|
[31] = "Calling-Station-Id",
|
||||||
|
[32] = "NAS-Identifier",
|
||||||
|
[33] = "Proxy-State",
|
||||||
|
[34] = "Login-LAT-Service",
|
||||||
|
[35] = "Login-LAT-Node",
|
||||||
|
[36] = "Login-LAT-Group",
|
||||||
|
[37] = "Framed-AppleTalk-Link",
|
||||||
|
[38] = "Framed-AppleTalk-Network",
|
||||||
|
[39] = "Framed-AppleTalk-Zone",
|
||||||
|
[40] = "Acct-Status-Type",
|
||||||
|
[41] = "Acct-Delay-Time",
|
||||||
|
[42] = "Acct-Input-Octets",
|
||||||
|
[43] = "Acct-Output-Octets",
|
||||||
|
[44] = "Acct-Session-Id",
|
||||||
|
[45] = "Acct-Authentic",
|
||||||
|
[46] = "Acct-Session-Time",
|
||||||
|
[47] = "Acct-Input-Packets",
|
||||||
|
[48] = "Acct-Output-Packets",
|
||||||
|
[49] = "Acct-Terminate-Cause",
|
||||||
|
[50] = "Acct-Multi-Session-Id",
|
||||||
|
[51] = "Acct-Link-Count",
|
||||||
|
[52] = "Acct-Input-Gigawords",
|
||||||
|
[53] = "Acct-Output-Gigawords",
|
||||||
|
[55] = "Event-Timestamp",
|
||||||
|
[56] = "Egress-VLANID",
|
||||||
|
[57] = "Ingress-Filters",
|
||||||
|
[58] = "Egress-VLAN-Name",
|
||||||
|
[59] = "User-Priority-Table",
|
||||||
|
[60] = "CHAP-Challenge",
|
||||||
|
[61] = "NAS-Port-Type",
|
||||||
|
[62] = "Port-Limit",
|
||||||
|
[63] = "Login-LAT-Port",
|
||||||
|
[64] = "Tunnel-Type",
|
||||||
|
[65] = "Tunnel-Medium-Type",
|
||||||
|
[66] = "Tunnel-Client-EndPoint",
|
||||||
|
[67] = "Tunnel-Server-EndPoint",
|
||||||
|
[68] = "Acct-Tunnel-Connection",
|
||||||
|
[69] = "Tunnel-Password",
|
||||||
|
[70] = "ARAP-Password",
|
||||||
|
[71] = "ARAP-Features",
|
||||||
|
[72] = "ARAP-Zone-Access",
|
||||||
|
[73] = "ARAP-Security",
|
||||||
|
[74] = "ARAP-Security-Data",
|
||||||
|
[75] = "Password-Retry",
|
||||||
|
[76] = "Prompt",
|
||||||
|
[77] = "Connect-Info",
|
||||||
|
[78] = "Configuration-Token",
|
||||||
|
[79] = "EAP-Message",
|
||||||
|
[80] = "Message Authenticator",
|
||||||
|
[81] = "Tunnel-Private-Group-ID",
|
||||||
|
[82] = "Tunnel-Assignment-ID",
|
||||||
|
[83] = "Tunnel-Preference",
|
||||||
|
[84] = "ARAP-Challenge-Response",
|
||||||
|
[85] = "Acct-Interim-Interval",
|
||||||
|
[86] = "Acct-Tunnel-Packets-Lost",
|
||||||
|
[87] = "NAS-Port-Id",
|
||||||
|
[88] = "Framed-Pool",
|
||||||
|
[89] = "CUI",
|
||||||
|
[90] = "Tunnel-Client-Auth-ID",
|
||||||
|
[91] = "Tunnel-Server-Auth-ID",
|
||||||
|
[92] = "NAS-Filter-Rule",
|
||||||
|
[94] = "Originating-Line-Info",
|
||||||
|
[95] = "NAS-IPv6-Address",
|
||||||
|
[96] = "Framed-Interface-Id",
|
||||||
|
[97] = "Framed-IPv6-Prefix",
|
||||||
|
[98] = "Login-IPv6-Host",
|
||||||
|
[99] = "Framed-IPv6-Route",
|
||||||
|
[100] = "Framed-IPv6-Pool",
|
||||||
|
[101] = "Error-Cause",
|
||||||
|
[102] = "EAP-Key-Name",
|
||||||
|
[103] = "Digest-Response",
|
||||||
|
[104] = "Digest-Realm",
|
||||||
|
[105] = "Digest-Nonce",
|
||||||
|
[106] = "Digest-Response-Auth",
|
||||||
|
[107] = "Digest-Nextnonce",
|
||||||
|
[108] = "Digest-Method",
|
||||||
|
[109] = "Digest-URI",
|
||||||
|
[110] = "Digest-Qop",
|
||||||
|
[111] = "Digest-Algorithm",
|
||||||
|
[112] = "Digest-Entity-Body-Hash",
|
||||||
|
[113] = "Digest-CNonce",
|
||||||
|
[114] = "Digest-Nonce-Count",
|
||||||
|
[115] = "Digest-Username",
|
||||||
|
[116] = "Digest-Opaque",
|
||||||
|
[117] = "Digest-Auth-Param",
|
||||||
|
[118] = "Digest-AKA-Auts",
|
||||||
|
[119] = "Digest-Domain",
|
||||||
|
[120] = "Digest-Stale",
|
||||||
|
[121] = "Digest-HA1",
|
||||||
|
[122] = "SIP-AOR",
|
||||||
|
[123] = "Delegated-IPv6-Prefix",
|
||||||
|
[124] = "MIP6-Feature-Vector",
|
||||||
|
[125] = "MIP6-Home-Link-Prefix",
|
||||||
|
[126] = "Operator-Name",
|
||||||
|
[127] = "Location-Information",
|
||||||
|
[128] = "Location-Data",
|
||||||
|
[129] = "Basic-Location-Policy-Rules",
|
||||||
|
[130] = "Extended-Location-Policy-Rules",
|
||||||
|
[131] = "Location-Capable",
|
||||||
|
[132] = "Requested-Location-Info",
|
||||||
|
[133] = "Framed-Management-Protocol",
|
||||||
|
[134] = "Management-Transport-Protection",
|
||||||
|
[135] = "Management-Policy-Id",
|
||||||
|
[136] = "Management-Privilege-Level",
|
||||||
|
[137] = "PKM-SS-Cert",
|
||||||
|
[138] = "PKM-CA-Cert",
|
||||||
|
[139] = "PKM-Config-Settings",
|
||||||
|
[140] = "PKM-Cryptosuite-List",
|
||||||
|
[141] = "PKM-SAID",
|
||||||
|
[142] = "PKM-SA-Descriptor",
|
||||||
|
[143] = "PKM-Auth-Key",
|
||||||
|
[144] = "DS-Lite-Tunnel-Name",
|
||||||
|
[145] = "Mobile-Node-Identifier",
|
||||||
|
[146] = "Service-Selection",
|
||||||
|
[147] = "PMIP6-Home-LMA-IPv6-Address",
|
||||||
|
[148] = "PMIP6-Visited-LMA-IPv6-Address",
|
||||||
|
[149] = "PMIP6-Home-LMA-IPv4-Address",
|
||||||
|
[150] = "PMIP6-Visited-LMA-IPv4-Address",
|
||||||
|
[151] = "PMIP6-Home-HN-Prefix",
|
||||||
|
[152] = "PMIP6-Visited-HN-Prefix",
|
||||||
|
[153] = "PMIP6-Home-Interface-ID",
|
||||||
|
[154] = "PMIP6-Visited-Interface-ID",
|
||||||
|
[155] = "PMIP6-Home-IPv4-HoA",
|
||||||
|
[156] = "PMIP6-Visited-IPv4-HoA",
|
||||||
|
[157] = "PMIP6-Home-DHCP4-Server-Address",
|
||||||
|
[158] = "PMIP6-Visited-DHCP4-Server-Address",
|
||||||
|
[159] = "PMIP6-Home-DHCP6-Server-Address",
|
||||||
|
[160] = "PMIP6-Visited-DHCP6-Server-Address",
|
||||||
|
[161] = "PMIP6-Home-IPv4-Gateway",
|
||||||
|
[162] = "PMIP6-Visited-IPv4-Gateway",
|
||||||
|
[163] = "EAP-Lower-Layer",
|
||||||
|
[164] = "GSS-Acceptor-Service-Name",
|
||||||
|
[165] = "GSS-Acceptor-Host-Name",
|
||||||
|
[166] = "GSS-Acceptor-Service-Specifics",
|
||||||
|
[167] = "GSS-Acceptor-Realm-Name",
|
||||||
|
[168] = "Framed-IPv6-Address",
|
||||||
|
[169] = "DNS-Server-IPv6-Address",
|
||||||
|
[170] = "Route-IPv6-Information",
|
||||||
|
[171] = "Delegated-IPv6-Prefix-Pool",
|
||||||
|
[172] = "Stateful-IPv6-Address-Pool",
|
||||||
|
[173] = "IPv6-6rd-Configuration"
|
||||||
|
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const nas_port_types: table[count] of string = {
|
||||||
|
[0] = "Async",
|
||||||
|
[1] = "Sync",
|
||||||
|
[2] = "ISDN Sync",
|
||||||
|
[3] = "ISDN Async V.120",
|
||||||
|
[4] = "ISDN Async V.110",
|
||||||
|
[5] = "Virtual",
|
||||||
|
[6] = "PIAFS",
|
||||||
|
[7] = "HDLC Clear Channel",
|
||||||
|
[8] = "X.25",
|
||||||
|
[9] = "X.75",
|
||||||
|
[10] = "G.3 Fax",
|
||||||
|
[11] = "SDSL - Symmetric DSL",
|
||||||
|
[12] = "ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation",
|
||||||
|
[13] = "ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone",
|
||||||
|
[14] = "IDSL - ISDN Digital Subscriber Line",
|
||||||
|
[15] = "Ethernet",
|
||||||
|
[16] = "xDSL - Digital Subscriber Line of unknown type",
|
||||||
|
[17] = "Cable",
|
||||||
|
[18] = "Wireless - Other",
|
||||||
|
[19] = "Wireless - IEEE 802.11"
|
||||||
|
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const service_types: table[count] of string = {
|
||||||
|
[1] = "Login",
|
||||||
|
[2] = "Framed",
|
||||||
|
[3] = "Callback Login",
|
||||||
|
[4] = "Callback Framed",
|
||||||
|
[5] = "Outbound",
|
||||||
|
[6] = "Administrative",
|
||||||
|
[7] = "NAS Prompt",
|
||||||
|
[8] = "Authenticate Only",
|
||||||
|
[9] = "Callback NAS Prompt",
|
||||||
|
[10] = "Call Check",
|
||||||
|
[11] = "Callback Administrative",
|
||||||
|
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const framed_protocol_types: table[count] of string = {
|
||||||
|
[1] = "PPP",
|
||||||
|
[2] = "SLIP",
|
||||||
|
[3] = "AppleTalk Remote Access Protocol (ARAP)",
|
||||||
|
[4] = "Gandalf proprietary SingleLink/MultiLink protocol",
|
||||||
|
[5] = "Xylogics proprietary IPX/SLIP",
|
||||||
|
[6] = "X.75 Synchronous"
|
||||||
|
} &default=function(i: count): string { return fmt("unknown-%d", i); };
|
127
scripts/base/protocols/radius/main.bro
Normal file
127
scripts/base/protocols/radius/main.bro
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
##! Implements base functionality for RADIUS analysis. Generates the radius.log file.
|
||||||
|
|
||||||
|
module RADIUS;
|
||||||
|
|
||||||
|
@load ./consts.bro
|
||||||
|
|
||||||
|
export {
|
||||||
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
type Info: record {
|
||||||
|
## Timestamp for when the event happened.
|
||||||
|
ts : time &log;
|
||||||
|
## Unique ID for the connection.
|
||||||
|
uid : string &log;
|
||||||
|
## The connection's 4-tuple of endpoint addresses/ports.
|
||||||
|
id : conn_id &log;
|
||||||
|
## The username, if present.
|
||||||
|
username : string &log &optional;
|
||||||
|
## MAC address, if present.
|
||||||
|
mac : string &log &optional;
|
||||||
|
## Remote IP address, if present.
|
||||||
|
remote_ip : addr &log &optional;
|
||||||
|
## Connect info, if present.
|
||||||
|
connect_info : string &log &optional;
|
||||||
|
## Successful or failed authentication.
|
||||||
|
result : string &log &optional;
|
||||||
|
## Whether this has already been logged and can be ignored.
|
||||||
|
logged : bool &optional;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
## The amount of time we wait for an authentication response before
|
||||||
|
## expiring it.
|
||||||
|
const expiration_interval = 10secs &redef;
|
||||||
|
|
||||||
|
## Logs an authentication attempt if we didn't see a response in time.
|
||||||
|
##
|
||||||
|
## t: A table of Info records.
|
||||||
|
##
|
||||||
|
## idx: The index of the connection$radius table corresponding to the
|
||||||
|
## radius authentication about to expire.
|
||||||
|
##
|
||||||
|
## Returns: 0secs, which when this function is used as an
|
||||||
|
## :bro:attr:`&expire_func`, indicates to remove the element at
|
||||||
|
## *idx* immediately.
|
||||||
|
global expire: function(t: table[count] of Info, idx: count): interval;
|
||||||
|
|
||||||
|
## Event that can be handled to access the RADIUS record as it is sent on
|
||||||
|
## to the loggin framework.
|
||||||
|
global log_radius: event(rec: Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
redef record connection += {
|
||||||
|
radius: table[count] of Info &optional &write_expire=expiration_interval &expire_func=expire;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ports = { 1812/udp };
|
||||||
|
|
||||||
|
event bro_init() &priority=5
|
||||||
|
{
|
||||||
|
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius]);
|
||||||
|
Analyzer::register_for_ports(Analyzer::ANALYZER_RADIUS, ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
event radius_message(c: connection, result: RADIUS::Message)
|
||||||
|
{
|
||||||
|
local info: Info;
|
||||||
|
|
||||||
|
if ( c?$radius && result$trans_id in c$radius )
|
||||||
|
info = c$radius[result$trans_id];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c$radius = table();
|
||||||
|
info$ts = network_time();
|
||||||
|
info$uid = c$uid;
|
||||||
|
info$id = c$id;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( result$code ) {
|
||||||
|
case 1:
|
||||||
|
# Acess-Request
|
||||||
|
if ( result?$attributes ) {
|
||||||
|
# User-Name
|
||||||
|
if ( ! info?$username && 1 in result$attributes )
|
||||||
|
info$username = result$attributes[1][0];
|
||||||
|
|
||||||
|
# Calling-Station-Id (we expect this to be a MAC)
|
||||||
|
if ( ! info?$mac && 31 in result$attributes )
|
||||||
|
info$mac = normalize_mac(result$attributes[31][0]);
|
||||||
|
|
||||||
|
# Tunnel-Client-EndPoint (useful for VPNs)
|
||||||
|
if ( ! info?$remote_ip && 66 in result$attributes )
|
||||||
|
info$remote_ip = to_addr(result$attributes[66][0]);
|
||||||
|
|
||||||
|
# Connect-Info
|
||||||
|
if ( ! info?$connect_info && 77 in result$attributes )
|
||||||
|
info$connect_info = result$attributes[77][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
# Access-Accept
|
||||||
|
info$result = "success";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
# Access-Reject
|
||||||
|
info$result = "failed";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( info?$result && ! info?$logged )
|
||||||
|
{
|
||||||
|
info$logged = T;
|
||||||
|
Log::write(RADIUS::LOG, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
c$radius[result$trans_id] = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function expire(t: table[count] of Info, idx: count): interval
|
||||||
|
{
|
||||||
|
t[idx]$result = "unknown";
|
||||||
|
return 0secs;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
##! Functions for parsing and manipulating IP addresses.
|
##! Functions for parsing and manipulating IP and MAC addresses.
|
||||||
|
|
||||||
# Regular expressions for matching IP addresses in strings.
|
# Regular expressions for matching IP addresses in strings.
|
||||||
const ipv4_addr_regex = /[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}/;
|
const ipv4_addr_regex = /[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}/;
|
||||||
|
@ -119,3 +119,30 @@ function addr_to_uri(a: addr): string
|
||||||
else
|
else
|
||||||
return fmt("[%s]", a);
|
return fmt("[%s]", a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## Given a string, extracts the hex digits and returns a MAC address in the
|
||||||
|
## format: 00:a0:32:d7:81:8f. If the string doesn't contain 12 or 16 hex digits,
|
||||||
|
## an empty string is returned.
|
||||||
|
##
|
||||||
|
## a: the string to normalize
|
||||||
|
##
|
||||||
|
## Returns: a normalized MAC address, or an empty string in the case of an error.
|
||||||
|
function normalize_mac(a: string): string
|
||||||
|
{
|
||||||
|
local result = to_lower(gsub(a, /[^A-Fa-f0-9]/, ""));
|
||||||
|
local octets: string_vec;
|
||||||
|
|
||||||
|
if ( |result| == 12 )
|
||||||
|
{
|
||||||
|
octets = str_split(result, vector(2, 4, 6, 8, 10));
|
||||||
|
return fmt("%s:%s:%s:%s:%s:%s", octets[1], octets[2], octets[3], octets[4], octets[5], octets[6]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( |result| == 16 )
|
||||||
|
{
|
||||||
|
octets = str_split(result, vector(2, 4, 6, 8, 10, 12, 14));
|
||||||
|
return fmt("%s:%s:%s:%s:%s:%s:%s:%s", octets[1], octets[2], octets[3], octets[4], octets[5], octets[6], octets[7], octets[8]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
|
@ -19,14 +19,15 @@ add_subdirectory(ident)
|
||||||
add_subdirectory(interconn)
|
add_subdirectory(interconn)
|
||||||
add_subdirectory(irc)
|
add_subdirectory(irc)
|
||||||
add_subdirectory(login)
|
add_subdirectory(login)
|
||||||
add_subdirectory(modbus)
|
|
||||||
add_subdirectory(mime)
|
add_subdirectory(mime)
|
||||||
|
add_subdirectory(modbus)
|
||||||
add_subdirectory(ncp)
|
add_subdirectory(ncp)
|
||||||
add_subdirectory(netflow)
|
|
||||||
add_subdirectory(netbios)
|
add_subdirectory(netbios)
|
||||||
|
add_subdirectory(netflow)
|
||||||
add_subdirectory(ntp)
|
add_subdirectory(ntp)
|
||||||
add_subdirectory(pia)
|
add_subdirectory(pia)
|
||||||
add_subdirectory(pop3)
|
add_subdirectory(pop3)
|
||||||
|
add_subdirectory(radius)
|
||||||
add_subdirectory(rpc)
|
add_subdirectory(rpc)
|
||||||
add_subdirectory(smb)
|
add_subdirectory(smb)
|
||||||
add_subdirectory(smtp)
|
add_subdirectory(smtp)
|
||||||
|
|
10
src/analyzer/protocol/radius/CMakeLists.txt
Normal file
10
src/analyzer/protocol/radius/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
include(BroPlugin)
|
||||||
|
|
||||||
|
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
bro_plugin_begin(Bro RADIUS)
|
||||||
|
bro_plugin_cc(RADIUS.cc Plugin.cc)
|
||||||
|
bro_plugin_bif(events.bif)
|
||||||
|
bro_plugin_pac(radius.pac radius-analyzer.pac radius-protocol.pac)
|
||||||
|
bro_plugin_end()
|
10
src/analyzer/protocol/radius/Plugin.cc
Normal file
10
src/analyzer/protocol/radius/Plugin.cc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#include "plugin/Plugin.h"
|
||||||
|
|
||||||
|
#include "RADIUS.h"
|
||||||
|
|
||||||
|
BRO_PLUGIN_BEGIN(Bro, RADIUS)
|
||||||
|
BRO_PLUGIN_DESCRIPTION("RADIUS analyzer");
|
||||||
|
BRO_PLUGIN_ANALYZER("RADIUS", RADIUS::RADIUS_Analyzer);
|
||||||
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_END
|
40
src/analyzer/protocol/radius/RADIUS.cc
Normal file
40
src/analyzer/protocol/radius/RADIUS.cc
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Generated by binpac_quickstart
|
||||||
|
|
||||||
|
#include "RADIUS.h"
|
||||||
|
|
||||||
|
#include "Reporter.h"
|
||||||
|
|
||||||
|
#include "events.bif.h"
|
||||||
|
|
||||||
|
using namespace analyzer::RADIUS;
|
||||||
|
|
||||||
|
RADIUS_Analyzer::RADIUS_Analyzer(Connection* c)
|
||||||
|
: analyzer::Analyzer("RADIUS", c)
|
||||||
|
{
|
||||||
|
interp = new binpac::RADIUS::RADIUS_Conn(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
RADIUS_Analyzer::~RADIUS_Analyzer()
|
||||||
|
{
|
||||||
|
delete interp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RADIUS_Analyzer::Done()
|
||||||
|
{
|
||||||
|
Analyzer::Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RADIUS_Analyzer::DeliverPacket(int len, const u_char* data,
|
||||||
|
bool orig, int seq, const IP_Hdr* ip, int caplen)
|
||||||
|
{
|
||||||
|
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
interp->NewData(orig, data, data + len);
|
||||||
|
}
|
||||||
|
catch ( const binpac::Exception& e )
|
||||||
|
{
|
||||||
|
ProtocolViolation(fmt("Binpac exception: %s", e.c_msg()));
|
||||||
|
}
|
||||||
|
}
|
34
src/analyzer/protocol/radius/RADIUS.h
Normal file
34
src/analyzer/protocol/radius/RADIUS.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Generated by binpac_quickstart
|
||||||
|
|
||||||
|
#ifndef ANALYZER_PROTOCOL_RADIUS_RADIUS_H
|
||||||
|
#define ANALYZER_PROTOCOL_RADIUS_RADIUS_H
|
||||||
|
|
||||||
|
#include "events.bif.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "analyzer/protocol/udp/UDP.h"
|
||||||
|
|
||||||
|
#include "radius_pac.h"
|
||||||
|
|
||||||
|
namespace analyzer { namespace RADIUS {
|
||||||
|
|
||||||
|
class RADIUS_Analyzer : public analyzer::Analyzer {
|
||||||
|
public:
|
||||||
|
RADIUS_Analyzer(Connection* conn);
|
||||||
|
virtual ~RADIUS_Analyzer();
|
||||||
|
|
||||||
|
// Overriden from Analyzer.
|
||||||
|
virtual void Done();
|
||||||
|
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||||
|
int seq, const IP_Hdr* ip, int caplen);
|
||||||
|
|
||||||
|
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||||
|
{ return new RADIUS_Analyzer(conn); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
binpac::RADIUS::RADIUS_Conn* interp;
|
||||||
|
};
|
||||||
|
|
||||||
|
} } // namespace analyzer::*
|
||||||
|
|
||||||
|
#endif
|
26
src/analyzer/protocol/radius/events.bif
Normal file
26
src/analyzer/protocol/radius/events.bif
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
## Generated for RADIUS messages.
|
||||||
|
##
|
||||||
|
## See `Wikipedia <http://en.wikipedia.org/wiki/RADIUS>`__ for more
|
||||||
|
## information about RADIUS.
|
||||||
|
##
|
||||||
|
## c: The connection
|
||||||
|
## msg_type: The value of the code field (1 == Access-Request, 2 == Access-Accept, etc.)
|
||||||
|
## trans_id: The RADIUS transaction identifier
|
||||||
|
## authenticator: The value of the authenticator field
|
||||||
|
##
|
||||||
|
event radius_message%(c: connection, result: RADIUS::Message%);
|
||||||
|
|
||||||
|
## Generated for each RADIUS attribute.
|
||||||
|
##
|
||||||
|
## See `Wikipedia <http://en.wikipedia.org/wiki/RADIUS>`__ for more
|
||||||
|
## information about RADIUS.
|
||||||
|
##
|
||||||
|
## c: The connection
|
||||||
|
## attr_type: The value of the code field (1 == User-Name, 2 == User-Password, etc.)
|
||||||
|
## authenticator: The value of the authenticator field
|
||||||
|
##
|
||||||
|
event radius_attribute%(c: connection, attr_type: count, value: string%);
|
||||||
|
|
||||||
|
type RADIUS::AttributeList: vector;
|
||||||
|
type RADIUS::Attributes: table;
|
||||||
|
type RADIUS::Message: record;
|
63
src/analyzer/protocol/radius/radius-analyzer.pac
Normal file
63
src/analyzer/protocol/radius/radius-analyzer.pac
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
refine flow RADIUS_Flow += {
|
||||||
|
function proc_radius_message(msg: RADIUS_PDU): bool
|
||||||
|
%{
|
||||||
|
connection()->bro_analyzer()->ProtocolConfirmation();
|
||||||
|
|
||||||
|
if ( ! radius_message )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RecordVal* result = new RecordVal(BifType::Record::RADIUS::Message);
|
||||||
|
result->Assign(0, new Val(${msg.code}, TYPE_COUNT));
|
||||||
|
result->Assign(1, new Val(${msg.trans_id}, TYPE_COUNT));
|
||||||
|
result->Assign(2, bytestring_to_val(${msg.authenticator}));
|
||||||
|
|
||||||
|
if ( ${msg.attributes}->size() )
|
||||||
|
{
|
||||||
|
TableVal* attributes = new TableVal(BifType::Table::RADIUS::Attributes);
|
||||||
|
|
||||||
|
for ( uint i = 0; i < ${msg.attributes}->size(); ++i ) {
|
||||||
|
Val* index = new Val(${msg.attributes[i].code}, TYPE_COUNT);
|
||||||
|
|
||||||
|
// Do we already have a vector of attributes for this type?
|
||||||
|
VectorVal* current = attributes->Lookup(index)->AsVectorVal();
|
||||||
|
Val* val = bytestring_to_val(${msg.attributes[i].value});
|
||||||
|
|
||||||
|
if ( current )
|
||||||
|
current->Assign(current->Size(), val);
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VectorVal* attribute_list = new VectorVal(BifType::Vector::RADIUS::AttributeList);
|
||||||
|
attribute_list->Assign(0, val);
|
||||||
|
attributes->Assign(index, attribute_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
Unref(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
result->Assign(3, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
BifEvent::generate_radius_message(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), result);
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_radius_attribute(attr: RADIUS_Attribute): bool
|
||||||
|
%{
|
||||||
|
if ( ! radius_attribute )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BifEvent::generate_radius_attribute(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(),
|
||||||
|
${attr.code}, bytestring_to_val(${attr.value}));
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
};
|
||||||
|
|
||||||
|
refine typeattr RADIUS_PDU += &let {
|
||||||
|
proc: bool = $context.flow.proc_radius_message(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
refine typeattr RADIUS_Attribute += &let {
|
||||||
|
proc: bool = $context.flow.proc_radius_attribute(this);
|
||||||
|
};
|
14
src/analyzer/protocol/radius/radius-protocol.pac
Normal file
14
src/analyzer/protocol/radius/radius-protocol.pac
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
type RADIUS_PDU(is_orig: bool) = record {
|
||||||
|
code: uint8;
|
||||||
|
trans_id: uint8;
|
||||||
|
length: uint16;
|
||||||
|
authenticator: bytestring &length=16;
|
||||||
|
attributes: RADIUS_Attribute(trans_id)[] &until($input.length() == 0);
|
||||||
|
} &byteorder=bigendian;
|
||||||
|
|
||||||
|
type RADIUS_Attribute(trans_id: uint8) = record {
|
||||||
|
code: uint8;
|
||||||
|
length: uint8;
|
||||||
|
value: bytestring &length=length-2;
|
||||||
|
};
|
30
src/analyzer/protocol/radius/radius.pac
Normal file
30
src/analyzer/protocol/radius/radius.pac
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Analyzer for RADIUS
|
||||||
|
# - radius-protocol.pac: describes the RADIUS protocol messages
|
||||||
|
# - radius-analyzer.pac: describes the RADIUS analyzer code
|
||||||
|
|
||||||
|
%include binpac.pac
|
||||||
|
%include bro.pac
|
||||||
|
|
||||||
|
%extern{
|
||||||
|
#include "events.bif.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
analyzer RADIUS withcontext {
|
||||||
|
connection: RADIUS_Conn;
|
||||||
|
flow: RADIUS_Flow;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Our connection consists of two flows, one in each direction.
|
||||||
|
connection RADIUS_Conn(bro_analyzer: BroAnalyzer) {
|
||||||
|
upflow = RADIUS_Flow(true);
|
||||||
|
downflow = RADIUS_Flow(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
%include radius-protocol.pac
|
||||||
|
|
||||||
|
# Now we define the flow:
|
||||||
|
flow RADIUS_Flow(is_orig: bool) {
|
||||||
|
datagram = RADIUS_PDU(is_orig) withcontext(connection, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
%include radius-analyzer.pac
|
Loading…
Add table
Add a link
Reference in a new issue