diff --git a/CHANGES b/CHANGES index 4cff07b10c..adcdc3173a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,15 @@ +2.6-340 | 2019-05-24 18:02:43 -0700 + + * Add support for parsing additional DHCP options (Jay Wren) + + The following optional fields were added to the DHCP::Options record: + + - time_offset (Option 2) + - time_servers (Option 4) + - name_servers (Option 5) + - ntp_servers (Option 42) + 2.6-338 | 2019-05-24 17:06:08 -0700 * Add input file name to additional ASCII reader warning messages (Christian Kreibich, Corelight) diff --git a/VERSION b/VERSION index aec71dabfc..c1f6f07b7e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.6-338 +2.6-340 diff --git a/doc b/doc index 0a19c6a36d..3db2ff8fa6 160000 --- a/doc +++ b/doc @@ -1 +1 @@ -Subproject commit 0a19c6a36dcdb4e1a7ab4c380b30a5b7cdba0cd0 +Subproject commit 3db2ff8fa65f5acb3f7807a0302d5c81db1e2227 diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index c41613aaef..7e07225a17 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -3521,6 +3521,20 @@ export { ## URL to find a proxy.pac for auto proxy config (Option 252) auto_proxy_config: string &optional; + + ## The offset of the client's subnet in seconds from UTC. (Option 2) + time_offset: int &optional; + + ## A list of :rfc:`868` time servers available to the client. + ## (Option 4) + time_servers: DHCP::Addrs &optional; + + ## A list of IEN 116 name servers available to the client. (Option 5) + name_servers: DHCP::Addrs &optional; + + ## A list of IP addresses indicating NTP servers available to the + ## client. (Option 42) + ntp_servers: DHCP::Addrs &optional; }; } diff --git a/src/analyzer/protocol/dhcp/dhcp-options.pac b/src/analyzer/protocol/dhcp/dhcp-options.pac index 75236b311c..f1b45fbc6f 100644 --- a/src/analyzer/protocol/dhcp/dhcp-options.pac +++ b/src/analyzer/protocol/dhcp/dhcp-options.pac @@ -21,6 +21,29 @@ refine typeattr Option += &let { }; +############################## +# TIME OFFSET OPTION +############################## +let TIME_OFFSET_OPTION = 2; + +# Parse the option +refine casetype OptionValue += { + TIME_OFFSET_OPTION -> time_offset : int32; +}; + +refine flow DHCP_Flow += { + function process_time_offset_option(v: OptionValue): bool + %{ + ${context.flow}->options->Assign(25, val_mgr->GetInt(${v.time_offset})); + return true; + %} +}; + +refine typeattr Option += &let { + proc_timeoffset_option = $context.flow.process_time_offset_option(info.value) &if(code==TIME_OFFSET_OPTION); +}; + + ############################## # ROUTER OPTION ############################## @@ -55,6 +78,74 @@ refine typeattr Option += &let { }; +############################## +# TIME SERVER OPTION +############################## +let TIME_SERVER_OPTION = 4; + +# Parse the option +refine casetype OptionValue += { + TIME_SERVER_OPTION -> timeserver_list : uint32[length/4]; +}; + +refine flow DHCP_Flow += { + function process_timeserver_option(v: OptionValue): bool + %{ + VectorVal* timeserver_list = new VectorVal(BifType::Vector::DHCP::Addrs); + int num_servers = ${v.timeserver_list}->size(); + vector* rlist = ${v.timeserver_list}; + + for ( int i = 0; i < num_servers; ++i ) + { + uint32 raddr = (*rlist)[i]; + timeserver_list->Assign(i, new AddrVal(htonl(raddr))); + } + + ${context.flow}->options->Assign(26, timeserver_list); + + return true; + %} +}; + +refine typeattr Option += &let { + proc_timeserver_option = $context.flow.process_timeserver_option(info.value) &if(code==TIME_SERVER_OPTION); +}; + + +############################## +# NAME SERVER OPTION +############################## +let NAME_SERVER_OPTION = 5; + +# Parse the option +refine casetype OptionValue += { + NAME_SERVER_OPTION -> nameserver_list : uint32[length/4]; +}; + +refine flow DHCP_Flow += { + function process_nameserver_option(v: OptionValue): bool + %{ + VectorVal* nameserver_list = new VectorVal(BifType::Vector::DHCP::Addrs); + int num_servers = ${v.nameserver_list}->size(); + vector* rlist = ${v.nameserver_list}; + + for ( int i = 0; i < num_servers; ++i ) + { + uint32 raddr = (*rlist)[i]; + nameserver_list->Assign(i, new AddrVal(htonl(raddr))); + } + + ${context.flow}->options->Assign(27, nameserver_list); + + return true; + %} +}; + +refine typeattr Option += &let { + proc_nameserver_option = $context.flow.process_nameserver_option(info.value) &if(code==NAME_SERVER_OPTION); +}; + + ############################## # DNS SERVER OPTION ############################## @@ -194,6 +285,39 @@ refine typeattr Option += &let { }; +############################## +# NTP SERVER OPTION +############################## +let NTP_SERVER_OPTION = 42; + +# Parse the option +refine casetype OptionValue += { + NTP_SERVER_OPTION -> ntpserver_list : uint32[length/4]; +}; + +refine flow DHCP_Flow += { + function process_ntpserver_option(v: OptionValue): bool + %{ + VectorVal* ntpserver_list = new VectorVal(BifType::Vector::DHCP::Addrs); + int num_servers = ${v.ntpserver_list}->size(); + vector* rlist = ${v.ntpserver_list}; + + for ( int i = 0; i < num_servers; ++i ) + { + uint32 raddr = (*rlist)[i]; + ntpserver_list->Assign(i, new AddrVal(htonl(raddr))); + } + + ${context.flow}->options->Assign(28, ntpserver_list); + + return true; + %} +}; + +refine typeattr Option += &let { + proc_ntpserver_option = $context.flow.process_ntpserver_option(info.value) &if(code==NTP_SERVER_OPTION); +}; + ############################## # VENDOR SPECIFIC OPTION ############################## diff --git a/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-time-nameserver-events/.stdout b/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-time-nameserver-events/.stdout new file mode 100644 index 0000000000..7e274f0c83 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-time-nameserver-events/.stdout @@ -0,0 +1,4 @@ +time_offset, -18000 +timeserver_list, [192.168.15.101] +nameserver_list, [192.168.15.101] +ntpserver_list, [192.168.15.101] diff --git a/testing/btest/Traces/dhcp/dhcp_time_and_nameserver.trace b/testing/btest/Traces/dhcp/dhcp_time_and_nameserver.trace new file mode 100644 index 0000000000..3395e48d6e Binary files /dev/null and b/testing/btest/Traces/dhcp/dhcp_time_and_nameserver.trace differ diff --git a/testing/btest/scripts/base/protocols/dhcp/dhcp-time-nameserver-events.zeek b/testing/btest/scripts/base/protocols/dhcp/dhcp-time-nameserver-events.zeek new file mode 100644 index 0000000000..bba8a0412f --- /dev/null +++ b/testing/btest/scripts/base/protocols/dhcp/dhcp-time-nameserver-events.zeek @@ -0,0 +1,12 @@ +# @TEST-EXEC: zeek -b -r $TRACES/dhcp/dhcp_time_and_nameserver.trace %INPUT +# @TEST-EXEC: btest-diff .stdout + +@load base/protocols/dhcp + +event DHCP::aggregate_msgs(ts: time, id: conn_id, uid: string, is_orig: bool, msg: DHCP::Msg, options: DHCP::Options) &priority=5 + { + print "time_offset", options$time_offset; + print "timeserver_list", options$time_servers; + print "nameserver_list", options$name_servers; + print "ntpserver_list", options$ntp_servers; + }