-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
main.zeek
155 lines (130 loc) · 4.29 KB
/
main.zeek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
##! Implements base functionality for RADIUS analysis. Generates the radius.log file.
@load ./consts
@load base/utils/addrs
@load base/protocols/conn/removal-hooks
module RADIUS;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
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;
## The address given to the network access server, if
## present. This is only a hint from the RADIUS server
## and the network access server is not required to honor
## the address.
framed_addr : addr &log &optional;
## Address (IPv4, IPv6, or FQDN) of the initiator end of the tunnel,
## if present. This is collected from the Tunnel-Client-Endpoint
## attribute.
tunnel_client: string &log &optional;
## Connect info, if present.
connect_info : string &log &optional;
## Reply message from the server challenge. This is
## frequently shown to the user authenticating.
reply_msg : string &log &optional;
## Successful or failed authentication.
result : string &log &optional;
## The duration between the first request and
## either the "Access-Accept" message or an error.
## If the field is empty, it means that either
## the request or response was not seen.
ttl : interval &log &optional;
## Whether this has already been logged and can be ignored.
logged : bool &default=F;
};
## Event that can be handled to access the RADIUS record as it is sent on
## to the logging framework.
global log_radius: event(rec: Info);
## RADIUS finalization hook. Remaining RADIUS info may get logged when it's called.
global finalize_radius: Conn::RemovalHook;
}
redef record connection += {
radius: Info &optional;
};
const ports = { 1812/udp };
redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius, $path="radius", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_RADIUS, ports);
}
event radius_message(c: connection, result: RADIUS::Message) &priority=5
{
if ( ! c?$radius )
{
c$radius = Info($ts = network_time(),
$uid = c$uid,
$id = c$id);
Conn::register_removal_hook(c, finalize_radius);
}
switch ( RADIUS::msg_types[result$code] )
{
case "Access-Request":
if ( result?$attributes )
{
# User-Name
if ( ! c$radius?$username && 1 in result$attributes )
c$radius$username = result$attributes[1][0];
# Calling-Station-Id (we expect this to be a MAC)
if ( ! c$radius?$mac && 31 in result$attributes )
c$radius$mac = normalize_mac(result$attributes[31][0]);
# Tunnel-Client-EndPoint (useful for VPNs)
if ( ! c$radius?$tunnel_client && 66 in result$attributes )
c$radius$tunnel_client = result$attributes[66][0];
# Connect-Info
if ( ! c$radius?$connect_info && 77 in result$attributes )
c$radius$connect_info = result$attributes[77][0];
}
break;
case "Access-Challenge":
if ( result?$attributes )
{
# Framed-IP-Address
if ( ! c$radius?$framed_addr && 8 in result$attributes )
c$radius$framed_addr = raw_bytes_to_v4_addr(result$attributes[8][0]);
if ( ! c$radius?$reply_msg && 18 in result$attributes )
c$radius$reply_msg = result$attributes[18][0];
}
break;
case "Access-Accept":
c$radius$result = "success";
break;
case "Access-Reject":
c$radius$result = "failed";
break;
# TODO: Support RADIUS accounting. (add port 1813/udp above too)
#case "Accounting-Request":
# break;
#
#case "Accounting-Response":
# break;
}
}
event radius_message(c: connection, result: RADIUS::Message) &priority=-5
{
if ( c$radius?$result )
{
local ttl = network_time() - c$radius$ts;
if ( ttl != 0secs )
c$radius$ttl = ttl;
Log::write(RADIUS::LOG, c$radius);
delete c$radius;
}
}
hook finalize_radius(c: connection)
{
if ( c?$radius && ! c$radius$logged )
{
c$radius$result = "unknown";
Log::write(RADIUS::LOG, c$radius);
}
}