From 99e411f621de796b690086342435863211f71455 Mon Sep 17 00:00:00 2001 From: Devin Trejo Date: Thu, 11 Jan 2018 11:38:19 -0500 Subject: [PATCH 1/2] Add mount_proc_null, mount_proc_mnt, mount_proc_umnt, mount_proc_umnt_all, mount_proc_not_implemented, mount_reply_status. --- scripts/base/init-bare.bro | 65 +++++ src/analyzer/protocol/rpc/CMakeLists.txt | 2 +- src/analyzer/protocol/rpc/MOUNT.cc | 299 +++++++++++++++++++++++ src/analyzer/protocol/rpc/MOUNT.h | 55 +++++ src/analyzer/protocol/rpc/Plugin.cc | 2 + src/analyzer/protocol/rpc/events.bif | 117 +++++++++ src/types.bif | 37 +++ 7 files changed, 576 insertions(+), 1 deletion(-) create mode 100644 src/analyzer/protocol/rpc/MOUNT.cc create mode 100644 src/analyzer/protocol/rpc/MOUNT.h diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index f2ea2ed29a..c192f25ed9 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -2350,6 +2350,71 @@ export { }; } # end export + +module MOUNT3; +export { + + ## Record summarizing the general results and status of MOUNT3 + ## request/reply pairs. + ## + ## Note that when *rpc_stat* or *mount_stat* indicates not successful, + ## the reply record passed to the corresponding event will be empty and + ## contain uninitialized fields, so don't use it. Also note that time + # and duration values might not be fully accurate. For TCP, we record + # times when the corresponding chunk of data is delivered to the + # analyzer. Depending on the reassembler, this might be well after the + # first packet of the request was received. + # + # .. bro:see:: mount_proc_mnt mount_proc_dump mount_proc_umnt + # mount_proc_umntall mount_proc_export mount_proc_not_implemented + type info_t: record { + ## The RPC status. + rpc_stat: rpc_status; + ## The MOUNT status. + mnt_stat: status_t; + ## The start time of the request. + req_start: time; + ## The duration of the request. + req_dur: interval; + ## The length in bytes of the request. + req_len: count; + ## The start time of the reply. + rep_start: time; + ## The duration of the reply. + rep_dur: interval; + ## The length in bytes of the reply. + rep_len: count; + ## The user id of the reply. + rpc_uid: count; + ## The group id of the reply. + rpc_gid: count; + ## The stamp of the reply. + rpc_stamp: count; + ## The machine name of the reply. + rpc_machine_name: string; + ## The auxiliary ids of the reply. + rpc_auxgids: index_vec; + }; + + ## MOUNT *mnt* arguments. + ## + ## .. bro:see:: mount_proc_mnt + type dirmntargs_t : record { + dirname: string; ##< Name of directory to mount + }; + + ## MOUNT lookup reply. If the mount failed, *dir_attr* may be set. If the + ## mount succeeded, *fh* is always set. + ## + ## .. bro:see:: mount_proc_mnt + type mnt_reply_t: record { + dirfh: string &optional; ##< Dir handle + auth_flavors: vector of auth_flavor_t &optional; ##< Returned authentication flavors + }; + +} # end export + + module Threading; export { diff --git a/src/analyzer/protocol/rpc/CMakeLists.txt b/src/analyzer/protocol/rpc/CMakeLists.txt index 5696a74cd6..c71c6ddd9a 100644 --- a/src/analyzer/protocol/rpc/CMakeLists.txt +++ b/src/analyzer/protocol/rpc/CMakeLists.txt @@ -4,6 +4,6 @@ include(BroPlugin) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) bro_plugin_begin(Bro RPC) -bro_plugin_cc(RPC.cc NFS.cc Portmap.cc XDR.cc Plugin.cc) +bro_plugin_cc(RPC.cc NFS.cc MOUNT.cc Portmap.cc XDR.cc Plugin.cc) bro_plugin_bif(events.bif) bro_plugin_end() diff --git a/src/analyzer/protocol/rpc/MOUNT.cc b/src/analyzer/protocol/rpc/MOUNT.cc new file mode 100644 index 0000000000..4500f35788 --- /dev/null +++ b/src/analyzer/protocol/rpc/MOUNT.cc @@ -0,0 +1,299 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include +#include + +#include "bro-config.h" + +#include "NetVar.h" +#include "XDR.h" +#include "MOUNT.h" +#include "Event.h" + +#include "events.bif.h" + +using namespace analyzer::rpc; + +int MOUNT_Interp::RPC_BuildCall(RPC_CallInfo* c, const u_char*& buf, int& n) + { + if ( c->Program() != 100005 ) + Weird(fmt("bad_RPC_program (%d)", c->Program())); + + uint32 proc = c->Proc(); + // The call arguments, depends on the call type obviously ... + Val *callarg = 0; + + switch ( proc ) { + case BifEnum::MOUNT3::PROC_NULL: + break; + + case BifEnum::MOUNT3::PROC_MNT: + callarg = mount3_dirmntargs(buf, n); + break; + + case BifEnum::MOUNT3::PROC_UMNT: + callarg = mount3_dirmntargs(buf, n); + break; + + case BifEnum::MOUNT3::PROC_UMNT_ALL: + callarg = mount3_dirmntargs(buf, n); + break; + + default: + callarg = 0; + if ( proc < BifEnum::MOUNT3::PROC_END_OF_PROCS ) + { + // We know the procedure but haven't implemented it. + // Otherwise DeliverRPC would complain about + // excess_RPC. + n = 0; + } + else + Weird(fmt("unknown_MOUNT_request(%u)", proc)); + + // Return 1 so that replies to unprocessed calls will still + // be processed, and the return status extracted. + return 1; + } + + if ( ! buf ) + { + // There was a parse error while trying to extract the call + // arguments. However, we don't know where exactly it + // happened and whether Vals where already allocated (e.g., a + // RecordVal was allocated but we failed to fill it). So we + // Unref() the call arguments, and we are fine. + Unref(callarg); + callarg = 0; + return 0; + } + + c->AddVal(callarg); // It's save to AddVal(0). + + return 1; + } + +int MOUNT_Interp::RPC_BuildReply(RPC_CallInfo* c, BifEnum::rpc_status rpc_status, + const u_char*& buf, int& n, double start_time, + double last_time, int reply_len) + { + EventHandlerPtr event = 0; + Val *reply = 0; + BifEnum::MOUNT3::status_t mount_status = BifEnum::MOUNT3::MNT3_OK; + bool rpc_success = ( rpc_status == BifEnum::RPC_SUCCESS ); + + // Reply always starts with the MOUNT status. + if ( rpc_success ) + { + if ( n >= 4 ) + mount_status = (BifEnum::MOUNT3::status_t)extract_XDR_uint32(buf, n); + else + mount_status = BifEnum::MOUNT3::MOUNT3ERR_UNKNOWN; + } + + if ( mount_reply_status ) + { + val_list* vl = event_common_vl(c, rpc_status, mount_status, + start_time, last_time, reply_len); + analyzer->ConnectionEvent(mount_reply_status, vl); + } + + if ( ! rpc_success ) + { + // We set the buffer to NULL, the function that extract the + // reply from the data stream will then return empty records. + // + buf = NULL; + n = 0; + } + + switch ( c->Proc() ) { + case BifEnum::MOUNT3::PROC_NULL: + event = mount_proc_null; + break; + + case BifEnum::MOUNT3::PROC_MNT: + reply = mount3_mnt_reply(buf, n, mount_status); + event = mount_proc_mnt; + break; + + case BifEnum::MOUNT3::PROC_UMNT: + reply = 0; + n = 0; + mount_status = BifEnum::MOUNT3::MNT3_OK; + event = mount_proc_umnt; + break; + + case BifEnum::MOUNT3::PROC_UMNT_ALL: + reply = 0; + n = 0; + mount_status = BifEnum::MOUNT3::MNT3_OK; + event = mount_proc_umnt; + break; + + default: + if ( c->Proc() < BifEnum::MOUNT3::PROC_END_OF_PROCS ) + { + // We know the procedure but haven't implemented it. + // Otherwise DeliverRPC would complain about + // excess_RPC. + n = 0; + reply = new EnumVal(c->Proc(), BifType::Enum::MOUNT3::proc_t); + event = mount_proc_not_implemented; + } + else + return 0; + } + + if ( rpc_success && ! buf ) + { + // There was a parse error. We have to unref the reply. (see + // also comments in RPC_BuildCall. + Unref(reply); + reply = 0; + return 0; + } + + // Note: if reply == 0, it won't be added to the val_list for the + // event. While we can check for that on the policy layer it's kinda + // ugly, because it's contrary to the event prototype. But having + // this optional argument to the event is really helpful. Otherwise I + // have to let reply point to a RecordVal where all fields are + // optional and all are set to 0 ... + if ( event ) + { + val_list* vl = event_common_vl(c, rpc_status, mount_status, + start_time, last_time, reply_len); + + Val *request = c->TakeRequestVal(); + + if ( request ) + vl->append(request); + + if ( reply ) + vl->append(reply); + + analyzer->ConnectionEvent(event, vl); + } + else + Unref(reply); + return 1; + } + +val_list* MOUNT_Interp::event_common_vl(RPC_CallInfo *c, + BifEnum::rpc_status rpc_status, + BifEnum::MOUNT3::status_t mount_status, + double rep_start_time, + double rep_last_time, int reply_len) + { + // Returns a new val_list that already has a conn_val, and mount3_info. + // These are the first parameters for each mount_* event ... + val_list *vl = new val_list; + vl->append(analyzer->BuildConnVal()); + VectorVal* auxgids = new VectorVal(internal_type("index_vec")->AsVectorType()); + for (size_t i = 0; i < c->AuxGIDs().size(); ++i) + { + auxgids->Assign(i, new Val(c->AuxGIDs()[i], TYPE_COUNT)); + } + + RecordVal *info = new RecordVal(BifType::Record::MOUNT3::info_t); + info->Assign(0, new EnumVal(rpc_status, BifType::Enum::rpc_status)); + info->Assign(1, new EnumVal(mount_status, BifType::Enum::MOUNT3::status_t)); + info->Assign(2, new Val(c->StartTime(), TYPE_TIME)); + info->Assign(3, new Val(c->LastTime()-c->StartTime(), TYPE_INTERVAL)); + info->Assign(4, new Val(c->RPCLen(), TYPE_COUNT)); + info->Assign(5, new Val(rep_start_time, TYPE_TIME)); + info->Assign(6, new Val(rep_last_time-rep_start_time, TYPE_INTERVAL)); + info->Assign(7, new Val(reply_len, TYPE_COUNT)); + info->Assign(8, new Val(c->Uid(), TYPE_COUNT)); + info->Assign(9, new Val(c->Gid(), TYPE_COUNT)); + info->Assign(10, new Val(c->Stamp(), TYPE_COUNT)); + info->Assign(11, new StringVal(c->MachineName())); + info->Assign(12, auxgids); + + vl->append(info); + return vl; + } + +EnumVal* MOUNT_Interp::mount3_auth_flavor(const u_char*& buf, int& n) + { + BifEnum::MOUNT3::auth_flavor_t t = (BifEnum::MOUNT3::auth_flavor_t)extract_XDR_uint32(buf, n); + return new EnumVal(t, BifType::Enum::MOUNT3::auth_flavor_t); + } + +StringVal* MOUNT_Interp::mount3_fh(const u_char*& buf, int& n) + { + int fh_n; + const u_char* fh = extract_XDR_opaque(buf, n, fh_n, 64); + + if ( ! fh ) + return 0; + + return new StringVal(new BroString(fh, fh_n, 0)); + } + +StringVal* MOUNT_Interp::mount3_filename(const u_char*& buf, int& n) + { + int name_len; + const u_char* name = extract_XDR_opaque(buf, n, name_len); + + if ( ! name ) + return 0; + + return new StringVal(new BroString(name, name_len, 0)); + } + +RecordVal* MOUNT_Interp::mount3_dirmntargs(const u_char*& buf, int& n) + { + RecordVal *dirmntargs = new RecordVal(BifType::Record::MOUNT3::dirmntargs_t); + + dirmntargs->Assign(0, mount3_filename(buf, n)); + + return dirmntargs; + } + +RecordVal* MOUNT_Interp::mount3_mnt_reply(const u_char*& buf, int& n, + BifEnum::MOUNT3::status_t status) + { + RecordVal *rep = new RecordVal(BifType::Record::MOUNT3::mnt_reply_t); + + if ( status == BifEnum::MOUNT3::MNT3_OK ) + { + rep->Assign(0, mount3_fh(buf,n)); + + int auth_flavors_count = extract_XDR_uint32(buf, n); + VectorType *enum_vector = new VectorType(base_type(TYPE_ENUM)); + VectorVal *auth_flavors = new VectorVal(enum_vector); + Unref(enum_vector); + for (int i = 0; i < auth_flavors_count; i++) + { + auth_flavors->Assign(auth_flavors->Size(), mount3_auth_flavor(buf, n)); // authentication + } + rep->Assign(1, auth_flavors); + } + else + { + rep->Assign(0, 0); + rep->Assign(1, 0); + } + return rep; + } + +MOUNT_Analyzer::MOUNT_Analyzer(Connection* conn) + : RPC_Analyzer("MOUNT", conn, new MOUNT_Interp(this)) + { + orig_rpc = resp_rpc = 0; + } + +void MOUNT_Analyzer::Init() + { + RPC_Analyzer::Init(); + + if ( Conn()->ConnTransport() == TRANSPORT_TCP ) + { + orig_rpc = new Contents_RPC(Conn(), true, interp); + resp_rpc = new Contents_RPC(Conn(), false, interp); + AddSupportAnalyzer(orig_rpc); + AddSupportAnalyzer(resp_rpc); + } + } diff --git a/src/analyzer/protocol/rpc/MOUNT.h b/src/analyzer/protocol/rpc/MOUNT.h new file mode 100644 index 0000000000..ed0c8fc9fc --- /dev/null +++ b/src/analyzer/protocol/rpc/MOUNT.h @@ -0,0 +1,55 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef ANALYZER_PROTOCOL_RPC_MOUNT_H +#define ANALYZER_PROTOCOL_RPC_MOUNT_H + +#include "RPC.h" +#include "XDR.h" +#include "Event.h" + +namespace analyzer { namespace rpc { + +class MOUNT_Interp : public RPC_Interpreter { +public: + MOUNT_Interp(analyzer::Analyzer* arg_analyzer) : RPC_Interpreter(arg_analyzer) { } + +protected: + int RPC_BuildCall(RPC_CallInfo* c, const u_char*& buf, int& n); + int RPC_BuildReply(RPC_CallInfo* c, BifEnum::rpc_status rpc_status, + const u_char*& buf, int& n, double start_time, + double last_time, int reply_len); + + // Returns a new val_list that already has a conn_val, rpc_status and + // mount_status. These are the first parameters for each mount_* event + // ... + val_list* event_common_vl(RPC_CallInfo *c, BifEnum::rpc_status rpc_status, + BifEnum::MOUNT3::status_t mount_status, + double rep_start_time, double rep_last_time, + int reply_len); + + // These methods parse the appropriate MOUNTv3 "type" out of buf. If + // there are any errors (i.e., buffer to short, etc), buf will be set + // to 0. However, the methods might still return an allocated Val * ! + // So, you might want to Unref() the Val if buf is 0. Method names + // are based on the type names of RFC 1813. + EnumVal* mount3_auth_flavor(const u_char*& buf, int& n); + StringVal* mount3_fh(const u_char*& buf, int& n); + RecordVal* mount3_dirmntargs(const u_char*&buf, int &n); + StringVal* mount3_filename(const u_char*& buf, int& n); + + RecordVal* mount3_mnt_reply(const u_char*& buf, int& n, BifEnum::MOUNT3::status_t status); +}; + +class MOUNT_Analyzer : public RPC_Analyzer { +public: + MOUNT_Analyzer(Connection* conn); + virtual void Init(); + + static analyzer::Analyzer* Instantiate(Connection* conn) + { return new MOUNT_Analyzer(conn); } +}; + + +} } // namespace analyzer::* + +#endif diff --git a/src/analyzer/protocol/rpc/Plugin.cc b/src/analyzer/protocol/rpc/Plugin.cc index 15337f2d6e..abc2f679f2 100644 --- a/src/analyzer/protocol/rpc/Plugin.cc +++ b/src/analyzer/protocol/rpc/Plugin.cc @@ -5,6 +5,7 @@ #include "RPC.h" #include "NFS.h" +#include "MOUNT.h" #include "Portmap.h" namespace plugin { @@ -15,6 +16,7 @@ public: plugin::Configuration Configure() { AddComponent(new ::analyzer::Component("NFS", ::analyzer::rpc::NFS_Analyzer::Instantiate)); + AddComponent(new ::analyzer::Component("MOUNT", ::analyzer::rpc::MOUNT_Analyzer::Instantiate)); AddComponent(new ::analyzer::Component("Portmapper", ::analyzer::rpc::Portmapper_Analyzer::Instantiate)); AddComponent(new ::analyzer::Component("Contents_RPC", 0)); AddComponent(new ::analyzer::Component("Contents_NFS", 0)); diff --git a/src/analyzer/protocol/rpc/events.bif b/src/analyzer/protocol/rpc/events.bif index 881faface1..d637537700 100644 --- a/src/analyzer/protocol/rpc/events.bif +++ b/src/analyzer/protocol/rpc/events.bif @@ -765,3 +765,120 @@ event rpc_call%(c: connection, xid: count, prog: count, ver: count, proc: count, ## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload ## signature. event rpc_reply%(c: connection, xid: count, status: rpc_status, reply_len: count%); + +## Generated for MOUNT3 request/reply dialogues of type *null*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## MOUNT is a service running on top of RPC. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## .. bro:see:: mount_proc_mnt mount_proc_dump mount_proc_umnt +## mount_proc_umntall mount_proc_export mount_proc_not_implemented +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event mount_proc_null%(c: connection, info: MOUNT3::info_t%); + +## Generated for MOUNT3 request/reply dialogues of type *mnt*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## MOUNT is a service running on top of RPC. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: The arguments passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: mount_proc_mnt mount_proc_dump mount_proc_umnt +## mount_proc_umntall mount_proc_export mount_proc_not_implemented +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event mount_proc_mnt%(c: connection, info: MOUNT3::info_t, req: MOUNT3::dirmntargs_t, rep: MOUNT3::mnt_reply_t%); + +## Generated for MOUNT3 request/reply dialogues of type *umnt*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## MOUNT is a service running on top of RPC. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: The arguments passed in the request. +## +## +## .. bro:see:: mount_proc_mnt mount_proc_dump mount_proc_umnt +## mount_proc_umntall mount_proc_export mount_proc_not_implemented +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event mount_proc_umnt%(c: connection, info: MOUNT3::info_t, req: MOUNT3::dirmntargs_t%); + +## Generated for MOUNT3 request/reply dialogues of type *umn_allt*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## MOUNT is a service running on top of RPC. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: The arguments passed in the request. +## +## +## .. bro:see:: mount_proc_mnt mount_proc_dump mount_proc_umnt +## mount_proc_umntall mount_proc_export mount_proc_not_implemented +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event mount_proc_umnt_all%(c: connection, info: MOUNT3::info_t, req: MOUNT3::dirmntargs_t%); + +## Generated for MOUNT3 request/reply dialogues of a type that Bro's MOUNTv3 +## analyzer does not implement. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## proc: The procedure called that Bro does not implement. +## +## .. bro:see:: mount_proc_mnt mount_proc_dump mount_proc_umnt +## mount_proc_umntall mount_proc_export mount_proc_not_implemented +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event mount_proc_not_implemented%(c: connection, info: MOUNT3::info_t, proc: MOUNT3::proc_t%); + +## Generated for each MOUNT3 reply message received, reporting just the +## status included. +## +## n: The connection. +## +## info: Reports the status included in the reply. +## +## .. bro:see:: mount_proc_mnt mount_proc_dump mount_proc_umnt +## mount_proc_umntall mount_proc_export mount_proc_not_implemented +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event mount_reply_status%(n: connection, info: MOUNT3::info_t%); diff --git a/src/types.bif b/src/types.bif index 20995ef105..ad7d1068f4 100644 --- a/src/types.bif +++ b/src/types.bif @@ -13,6 +13,43 @@ enum rpc_status %{ RPC_UNKNOWN_ERROR, %} +module MOUNT3; + +enum proc_t %{ # MOUNT3 procedures + PROC_NULL = 0, # done + PROC_MNT = 1, # done + PROC_DUMP = 2, # not implemented + PROC_UMNT = 3, # done + PROC_UMNT_ALL = 4, # done + PROC_EXPORT = 5, # not implemented + PROC_END_OF_PROCS = 6, # not implemented +%} + +enum status_t %{ # MOUNT3 return status + MNT3_OK = 0, + MNT3ERR_PERM = 1, + MNT3ERR_NOENT = 2, + MNT3ERR_IO = 5, + MNT3ERR_ACCES = 13, + MNT3ERR_NOTDIR = 20, + MNT3ERR_INVAL = 22, + MNT3ERR_NAMETOOLONG = 63, + MNT3ERR_NOTSUPP = 10004, + MNT3ERR_SERVERFAULT = 10006, + MOUNT3ERR_UNKNOWN = 0xffffffff, +%} + +enum auth_flavor_t %{ # MOUNT3 auth flavors + AUTH_NULL = 0, + AUTH_UNIX = 1, + AUTH_SHORT = 2, + AUTH_DES = 3, +%} + +type info_t: record; +type mnt_reply_t: record; +type dirmntargs_t: record; + module NFS3; enum proc_t %{ # NFSv3 procedures From f6cf4a41ff66aec11abfa5f8ecbc54910d803dbd Mon Sep 17 00:00:00 2001 From: Devin Trejo Date: Thu, 11 Jan 2018 17:00:15 -0500 Subject: [PATCH 2/2] Add unit tests for new MOUNT events -- mount_proc_mnt, mount_proc_umnt, mount_proc_umnt_all, mount_proc_not_implemented. --- .../.stdout | 2 ++ testing/btest/Traces/mount/mount_base.pcap | Bin 0 -> 18266 bytes .../scripts/base/protocols/mount/basic.test | 31 ++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 testing/btest/Baseline/scripts.base.protocols.mount.basic/.stdout create mode 100644 testing/btest/Traces/mount/mount_base.pcap create mode 100644 testing/btest/scripts/base/protocols/mount/basic.test diff --git a/testing/btest/Baseline/scripts.base.protocols.mount.basic/.stdout b/testing/btest/Baseline/scripts.base.protocols.mount.basic/.stdout new file mode 100644 index 0000000000..b3e377595b --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.mount.basic/.stdout @@ -0,0 +1,2 @@ +mount_proc_mnt: [id=[orig_h=10.111.131.18, orig_p=765/udp, resp_h=10.111.131.132, resp_p=20048/udp], orig=[size=144, state=1, num_pkts=2, num_bytes_ip=200, flow_label=0, l2_addr=00:50:56:b2:4e:d3], resp=[size=84, state=1, num_pkts=1, num_bytes_ip=52, flow_label=0, l2_addr=00:50:56:b2:78:69], start_time=1514568131.621984, duration=0.000553, service={\x0a\x0a}, history=Dd, uid=CHhAvVGS1DHFjwGM9, tunnel=, vlan=, inner_vlan=]\x0a\x09[rpc_stat=RPC_SUCCESS, mnt_stat=MOUNT3::MNT3_OK, req_start=1514568131.62212, req_dur=0.0, req_len=96, rep_start=1514568131.622537, rep_dur=0.0, rep_len=52, rpc_uid=0, rpc_gid=0, rpc_stamp=19078341, rpc_machine_name=pddevbal802, rpc_auxgids=[0, 5, 10, 24]]\x0a\x09[dirname=/pddevbal801]\x0a\x09[dirfh=\x01\x00\x06\x00\xea,\xbbJ\x9e\xf7I\x95\xa56V(\xce\xda`\xa2, auth_flavors=[MOUNT3::AUTH_UNIX]]\x0a +mount_proc_umnt: [id=[orig_h=10.111.131.18, orig_p=1016/udp, resp_h=10.111.131.132, resp_p=20048/udp], orig=[size=92, state=1, num_pkts=1, num_bytes_ip=120, flow_label=0, l2_addr=00:50:56:b2:4e:d3], resp=[size=24, state=1, num_pkts=0, num_bytes_ip=0, flow_label=0, l2_addr=00:50:56:b2:78:69], start_time=1514568131.665918, duration=0.000266, service={\x0a\x0a}, history=Dd, uid=ClEkJM2Vm5giqnMf4h, tunnel=, vlan=, inner_vlan=]\x0a\x09[rpc_stat=RPC_SUCCESS, mnt_stat=MOUNT3::MNT3_OK, req_start=1514568131.665918, req_dur=0.0, req_len=84, rep_start=1514568131.666184, rep_dur=0.0, rep_len=16, rpc_uid=0, rpc_gid=0, rpc_stamp=1514568131, rpc_machine_name=pddevbal802, rpc_auxgids=[0]]\x0a\x09[dirname=/pddevbal801]\x0a diff --git a/testing/btest/Traces/mount/mount_base.pcap b/testing/btest/Traces/mount/mount_base.pcap new file mode 100644 index 0000000000000000000000000000000000000000..0d7187842424a5ae5a7254b71ec528a5e452c222 GIT binary patch literal 18266 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 C?n-+A literal 0 HcmV?d00001 diff --git a/testing/btest/scripts/base/protocols/mount/basic.test b/testing/btest/scripts/base/protocols/mount/basic.test new file mode 100644 index 0000000000..8576874ce3 --- /dev/null +++ b/testing/btest/scripts/base/protocols/mount/basic.test @@ -0,0 +1,31 @@ +# @TEST-EXEC: bro -b -r $TRACES/mount/mount_base.pcap %INPUT +# @TEST-EXEC: btest-diff .stdout + +global mount_ports: set[port] = { 635/tcp, 635/udp, 20048/tcp, 20048/udp } &redef; +redef ignore_checksums = T; + +event bro_init() + { + Analyzer::register_for_ports(Analyzer::ANALYZER_MOUNT, mount_ports); + Analyzer::enable_analyzer(Analyzer::ANALYZER_MOUNT); + } + +event mount_proc_mnt(c: connection, info: MOUNT3::info_t, req: MOUNT3::dirmntargs_t, rep: MOUNT3::mnt_reply_t) + { + print(fmt("mount_proc_mnt: %s\n\t%s\n\t%s\n\t%s\n", c, info, req, rep)); + } + +event mount_proc_umnt(c: connection, info: MOUNT3::info_t, req: MOUNT3::dirmntargs_t) + { + print(fmt("mount_proc_umnt: %s\n\t%s\n\t%s\n", c, info, req)); + } + +event mount_proc_umnt_all(c: connection, info: MOUNT3::info_t, req: MOUNT3::dirmntargs_t) + { + print(fmt("mount_proc_umnt_all: %s\n\t%s\n\t%s\n", c, info, req)); + } + +event mount_proc_not_implemented(c: connection, info: MOUNT3::info_t, proc: MOUNT3::proc_t) + { + print(fmt("mount_proc_not_implemented: %s\n\t%s\n\t%s\n", c, info, proc)); + }