mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00

This commit includes renaming a number of methods prefixed with bro_ to be prefixed with zeek_.
841 lines
23 KiB
C++
841 lines
23 KiB
C++
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
#include "zeek-config.h"
|
|
#include "NFS.h"
|
|
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "ZeekString.h"
|
|
#include "NetVar.h"
|
|
#include "XDR.h"
|
|
#include "Event.h"
|
|
|
|
#include "events.bif.h"
|
|
|
|
namespace zeek::analyzer::rpc {
|
|
namespace detail {
|
|
|
|
bool NFS_Interp::RPC_BuildCall(RPC_CallInfo* c, const u_char*& buf, int& n)
|
|
{
|
|
if ( c->Program() != 100003 )
|
|
Weird("bad_RPC_program", zeek::util::fmt("%d", c->Program()));
|
|
|
|
uint32_t proc = c->Proc();
|
|
// The call arguments, depends on the call type obviously ...
|
|
zeek::ValPtr callarg;
|
|
|
|
switch ( proc ) {
|
|
case BifEnum::NFS3::PROC_NULL:
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_GETATTR:
|
|
callarg = nfs3_fh(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_SETATTR:
|
|
callarg = nfs3_sattrargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_LOOKUP:
|
|
callarg = nfs3_diropargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_READ:
|
|
callarg = nfs3_readargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_READLINK:
|
|
callarg = nfs3_fh(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_SYMLINK:
|
|
callarg = nfs3_symlinkargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_LINK:
|
|
callarg = nfs3_linkargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_WRITE:
|
|
callarg = nfs3_writeargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_CREATE:
|
|
callarg = nfs3_diropargs(buf, n);
|
|
// TODO: implement create attributes. For now we just skip
|
|
// over them.
|
|
n = 0;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_MKDIR:
|
|
callarg = nfs3_diropargs(buf, n);
|
|
// TODO: implement mkdir attributes. For now we just skip
|
|
// over them.
|
|
n = 0;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_REMOVE:
|
|
callarg = nfs3_diropargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_RMDIR:
|
|
callarg = nfs3_diropargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_RENAME:
|
|
callarg = nfs3_renameopargs(buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_READDIR:
|
|
callarg = nfs3_readdirargs(false, buf, n);
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_READDIRPLUS:
|
|
callarg = nfs3_readdirargs(true, buf, n);
|
|
break;
|
|
|
|
default:
|
|
if ( proc < BifEnum::NFS3::PROC_END_OF_PROCS )
|
|
{
|
|
// We know the procedure but haven't implemented it.
|
|
// Otherwise DeliverRPC would complain about
|
|
// excess_RPC.
|
|
n = 0;
|
|
}
|
|
else
|
|
Weird("unknown_NFS_request", zeek::util::fmt("%u", proc));
|
|
|
|
// Return 1 so that replies to unprocessed calls will still
|
|
// be processed, and the return status extracted.
|
|
return true;
|
|
}
|
|
|
|
if ( ! buf )
|
|
// There was a parse error while trying to extract the call arguments.
|
|
return false;
|
|
|
|
c->AddVal(std::move(callarg));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NFS_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)
|
|
{
|
|
zeek::EventHandlerPtr event = nullptr;
|
|
zeek::ValPtr reply;
|
|
BifEnum::NFS3::status_t nfs_status = BifEnum::NFS3::NFS3ERR_OK;
|
|
bool rpc_success = ( rpc_status == BifEnum::RPC_SUCCESS );
|
|
|
|
// Reply always starts with the NFS status.
|
|
if ( rpc_success )
|
|
{
|
|
if ( n >= 4 )
|
|
nfs_status = (BifEnum::NFS3::status_t)extract_XDR_uint32(buf, n);
|
|
else
|
|
nfs_status = BifEnum::NFS3::NFS3ERR_UNKNOWN;
|
|
}
|
|
|
|
if ( nfs_reply_status )
|
|
{
|
|
auto vl = event_common_vl(c, rpc_status, nfs_status,
|
|
start_time, last_time, reply_len, 0);
|
|
analyzer->EnqueueConnEvent(nfs_reply_status, std::move(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 = nullptr;
|
|
n = 0;
|
|
}
|
|
|
|
switch ( c->Proc() ) {
|
|
case BifEnum::NFS3::PROC_NULL:
|
|
event = nfs_proc_null;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_GETATTR:
|
|
reply = nfs3_fattr(buf, n);
|
|
event = nfs_proc_getattr;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_SETATTR:
|
|
reply = nfs3_sattr_reply(buf, n, nfs_status);
|
|
event = nfs_proc_sattr;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_LOOKUP:
|
|
reply = nfs3_lookup_reply(buf, n, nfs_status);
|
|
event = nfs_proc_lookup;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_READ:
|
|
bro_uint_t offset;
|
|
offset = c->RequestVal()->AsRecordVal()->GetField(1)->AsCount();
|
|
reply = nfs3_read_reply(buf, n, nfs_status, offset);
|
|
event = nfs_proc_read;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_READLINK:
|
|
reply = nfs3_readlink_reply(buf, n, nfs_status);
|
|
event = nfs_proc_readlink;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_SYMLINK:
|
|
reply = nfs3_newobj_reply(buf, n, nfs_status);
|
|
event = nfs_proc_symlink;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_LINK:
|
|
reply = nfs3_link_reply(buf, n, nfs_status);
|
|
event = nfs_proc_link;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_WRITE:
|
|
reply = nfs3_write_reply(buf, n, nfs_status);
|
|
event = nfs_proc_write;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_CREATE:
|
|
reply = nfs3_newobj_reply(buf, n, nfs_status);
|
|
event = nfs_proc_create;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_MKDIR:
|
|
reply = nfs3_newobj_reply(buf, n, nfs_status);
|
|
event = nfs_proc_mkdir;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_REMOVE:
|
|
reply = nfs3_delobj_reply(buf, n);
|
|
event = nfs_proc_remove;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_RMDIR:
|
|
reply = nfs3_delobj_reply(buf, n);
|
|
event = nfs_proc_rmdir;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_RENAME:
|
|
reply = nfs3_renameobj_reply(buf, n);
|
|
event = nfs_proc_rename;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_READDIR:
|
|
reply = nfs3_readdir_reply(false, buf, n, nfs_status);
|
|
event = nfs_proc_readdir;
|
|
break;
|
|
|
|
case BifEnum::NFS3::PROC_READDIRPLUS:
|
|
reply = nfs3_readdir_reply(true, buf, n, nfs_status);
|
|
event = nfs_proc_readdir;
|
|
break;
|
|
|
|
default:
|
|
if ( c->Proc() < BifEnum::NFS3::PROC_END_OF_PROCS )
|
|
{
|
|
// We know the procedure but haven't implemented it.
|
|
// Otherwise DeliverRPC would complain about
|
|
// excess_RPC.
|
|
n = 0;
|
|
reply = zeek::BifType::Enum::NFS3::proc_t->GetEnumVal(c->Proc());
|
|
event = nfs_proc_not_implemented;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
if ( rpc_success && ! buf )
|
|
// There was a parse error.
|
|
return false;
|
|
|
|
// 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 )
|
|
{
|
|
auto request = c->TakeRequestVal();
|
|
|
|
auto vl = event_common_vl(c, rpc_status, nfs_status,
|
|
start_time, last_time, reply_len, (bool)request + (bool)reply);
|
|
|
|
if ( request )
|
|
vl.emplace_back(std::move(request));
|
|
|
|
if ( reply )
|
|
vl.emplace_back(std::move(reply));
|
|
|
|
analyzer->EnqueueConnEvent(event, std::move(vl));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
zeek::StringValPtr NFS_Interp::nfs3_file_data(const u_char*& buf, int& n, uint64_t offset, int size)
|
|
{
|
|
int data_n;
|
|
|
|
// extract the data, move buf and n
|
|
const u_char *data = extract_XDR_opaque(buf, n, data_n, 1 << 30, true);
|
|
|
|
// check whether we have to deliver data to the event
|
|
if ( ! zeek::BifConst::NFS3::return_data )
|
|
return nullptr;
|
|
|
|
if ( zeek::BifConst::NFS3::return_data_first_only && offset != 0 )
|
|
return nullptr;
|
|
|
|
// Ok, so we want to return some data
|
|
data_n = std::min(data_n, size);
|
|
data_n = std::min(data_n, int(zeek::BifConst::NFS3::return_data_max));
|
|
|
|
if ( data && data_n > 0 )
|
|
return zeek::make_intrusive<zeek::StringVal>(new zeek::String(data, data_n, false));
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
zeek::Args NFS_Interp::event_common_vl(RPC_CallInfo *c, BifEnum::rpc_status rpc_status,
|
|
BifEnum::NFS3::status_t nfs_status,
|
|
double rep_start_time,
|
|
double rep_last_time, int reply_len, int extra_elements)
|
|
{
|
|
// Returns a new val_list that already has a conn_val, and nfs3_info.
|
|
// These are the first parameters for each nfs_* event ...
|
|
zeek::Args vl;
|
|
vl.reserve(2 + extra_elements);
|
|
vl.emplace_back(analyzer->ConnVal());
|
|
auto auxgids = zeek::make_intrusive<zeek::VectorVal>(zeek::id::index_vec);
|
|
|
|
for ( size_t i = 0; i < c->AuxGIDs().size(); ++i )
|
|
auxgids->Assign(i, zeek::val_mgr->Count(c->AuxGIDs()[i]));
|
|
|
|
auto info = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::info_t);
|
|
info->Assign(0, zeek::BifType::Enum::rpc_status->GetEnumVal(rpc_status));
|
|
info->Assign(1, zeek::BifType::Enum::NFS3::status_t->GetEnumVal(nfs_status));
|
|
info->Assign(2, zeek::make_intrusive<zeek::TimeVal>(c->StartTime()));
|
|
info->Assign(3, zeek::make_intrusive<zeek::IntervalVal>(c->LastTime()-c->StartTime()));
|
|
info->Assign(4, zeek::val_mgr->Count(c->RPCLen()));
|
|
info->Assign(5, zeek::make_intrusive<zeek::TimeVal>(rep_start_time));
|
|
info->Assign(6, zeek::make_intrusive<zeek::IntervalVal>(rep_last_time-rep_start_time));
|
|
info->Assign(7, zeek::val_mgr->Count(reply_len));
|
|
info->Assign(8, zeek::val_mgr->Count(c->Uid()));
|
|
info->Assign(9, zeek::val_mgr->Count(c->Gid()));
|
|
info->Assign(10, zeek::val_mgr->Count(c->Stamp()));
|
|
info->Assign(11, zeek::make_intrusive<zeek::StringVal>(c->MachineName()));
|
|
info->Assign(12, std::move(auxgids));
|
|
|
|
vl.emplace_back(std::move(info));
|
|
return vl;
|
|
}
|
|
|
|
zeek::StringValPtr NFS_Interp::nfs3_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 nullptr;
|
|
|
|
return zeek::make_intrusive<zeek::StringVal>(new zeek::String(fh, fh_n, false));
|
|
}
|
|
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_sattr(const u_char*& buf, int& n)
|
|
{
|
|
auto attrs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::sattr_t);
|
|
|
|
attrs->Assign(0, nullptr); // mode
|
|
int mode_set_it = extract_XDR_uint32(buf, n);
|
|
if ( mode_set_it )
|
|
attrs->Assign(0, ExtractUint32(buf, n)); // mode
|
|
|
|
attrs->Assign(1, nullptr); // uid
|
|
int uid_set_it = extract_XDR_uint32(buf, n);
|
|
if ( uid_set_it )
|
|
attrs->Assign(1, ExtractUint32(buf, n)); // uid
|
|
|
|
attrs->Assign(2, nullptr); // gid
|
|
int gid_set_it = extract_XDR_uint32(buf, n);
|
|
if ( gid_set_it )
|
|
attrs->Assign(2, ExtractUint32(buf, n)); // gid
|
|
|
|
attrs->Assign(3, nullptr); // size
|
|
int size_set_it = extract_XDR_uint32(buf, n);
|
|
if ( size_set_it )
|
|
attrs->Assign(3, ExtractTime(buf, n)); // size
|
|
|
|
attrs->Assign(4, nfs3_time_how(buf, n)); // time_how
|
|
|
|
attrs->Assign(5, nfs3_time_how(buf, n)); // time_how
|
|
|
|
return attrs;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_sattr_reply(const u_char*& buf, int& n, BifEnum::NFS3::status_t status)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::sattr_reply_t);
|
|
|
|
if ( status == BifEnum::NFS3::NFS3ERR_OK )
|
|
{
|
|
rep->Assign(0, nfs3_pre_op_attr(buf, n));
|
|
rep->Assign(1, nfs3_post_op_attr(buf, n));
|
|
}
|
|
else
|
|
{
|
|
rep->Assign(1, nullptr);
|
|
rep->Assign(2, nullptr);
|
|
}
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_fattr(const u_char*& buf, int& n)
|
|
{
|
|
auto attrs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::fattr_t);
|
|
|
|
attrs->Assign(0, nfs3_ftype(buf, n)); // file type
|
|
attrs->Assign(1, ExtractUint32(buf, n)); // mode
|
|
attrs->Assign(2, ExtractUint32(buf, n)); // nlink
|
|
attrs->Assign(3, ExtractUint32(buf, n)); // uid
|
|
attrs->Assign(4, ExtractUint32(buf, n)); // gid
|
|
attrs->Assign(5, ExtractUint64(buf, n)); // size
|
|
attrs->Assign(6, ExtractUint64(buf, n)); // used
|
|
attrs->Assign(7, ExtractUint32(buf, n)); // rdev1
|
|
attrs->Assign(8, ExtractUint32(buf, n)); // rdev2
|
|
attrs->Assign(9, ExtractUint64(buf, n)); // fsid
|
|
attrs->Assign(10, ExtractUint64(buf, n)); // fileid
|
|
attrs->Assign(11, ExtractTime(buf, n)); // atime
|
|
attrs->Assign(12, ExtractTime(buf, n)); // mtime
|
|
attrs->Assign(13, ExtractTime(buf, n)); // ctime
|
|
|
|
return attrs;
|
|
}
|
|
|
|
zeek::EnumValPtr NFS_Interp::nfs3_time_how(const u_char*& buf, int& n)
|
|
{
|
|
BifEnum::NFS3::time_how_t t = (BifEnum::NFS3::time_how_t)extract_XDR_uint32(buf, n);
|
|
auto rval = zeek::BifType::Enum::NFS3::time_how_t->GetEnumVal(t);
|
|
return rval;
|
|
}
|
|
|
|
zeek::EnumValPtr NFS_Interp::nfs3_ftype(const u_char*& buf, int& n)
|
|
{
|
|
BifEnum::NFS3::file_type_t t = (BifEnum::NFS3::file_type_t)extract_XDR_uint32(buf, n);
|
|
auto rval = zeek::BifType::Enum::NFS3::file_type_t->GetEnumVal(t);
|
|
return rval;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_wcc_attr(const u_char*& buf, int& n)
|
|
{
|
|
auto attrs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::wcc_attr_t);
|
|
|
|
attrs->Assign(0, ExtractUint64(buf, n)); // size
|
|
attrs->Assign(1, ExtractTime(buf, n)); // mtime
|
|
attrs->Assign(2, ExtractTime(buf, n)); // ctime
|
|
|
|
return attrs;
|
|
}
|
|
|
|
zeek::StringValPtr NFS_Interp::nfs3_filename(const u_char*& buf, int& n)
|
|
{
|
|
int name_len;
|
|
const u_char* name = extract_XDR_opaque(buf, n, name_len);
|
|
|
|
if ( ! name )
|
|
return nullptr;
|
|
|
|
return zeek::make_intrusive<zeek::StringVal>(new zeek::String(name, name_len, false));
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_diropargs(const u_char*& buf, int& n)
|
|
{
|
|
auto diropargs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::diropargs_t);
|
|
|
|
diropargs->Assign(0, nfs3_fh(buf, n));
|
|
diropargs->Assign(1, nfs3_filename(buf, n));
|
|
|
|
return diropargs;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_symlinkdata(const u_char*& buf, int& n)
|
|
{
|
|
auto symlinkdata = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::symlinkdata_t);
|
|
|
|
symlinkdata->Assign(0, nfs3_sattr(buf, n));
|
|
symlinkdata->Assign(1, nfs3_nfspath(buf, n));
|
|
|
|
return symlinkdata;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_renameopargs(const u_char*& buf, int& n)
|
|
{
|
|
auto renameopargs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::renameopargs_t);
|
|
|
|
renameopargs->Assign(0, nfs3_fh(buf, n));
|
|
renameopargs->Assign(1, nfs3_filename(buf, n));
|
|
renameopargs->Assign(2, nfs3_fh(buf, n));
|
|
renameopargs->Assign(3, nfs3_filename(buf, n));
|
|
|
|
return renameopargs;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_post_op_attr(const u_char*& buf, int& n)
|
|
{
|
|
int have_attrs = extract_XDR_uint32(buf, n);
|
|
|
|
if ( have_attrs )
|
|
return nfs3_fattr(buf, n);
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
zeek::StringValPtr NFS_Interp::nfs3_post_op_fh(const u_char*& buf, int& n)
|
|
{
|
|
int have_fh = extract_XDR_uint32(buf, n);
|
|
|
|
if ( have_fh )
|
|
return nfs3_fh(buf, n);
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_pre_op_attr(const u_char*& buf, int& n)
|
|
{
|
|
int have_attrs = extract_XDR_uint32(buf, n);
|
|
|
|
if ( have_attrs )
|
|
return nfs3_wcc_attr(buf, n);
|
|
return nullptr;
|
|
}
|
|
|
|
zeek::EnumValPtr NFS_Interp::nfs3_stable_how(const u_char*& buf, int& n)
|
|
{
|
|
BifEnum::NFS3::stable_how_t stable = (BifEnum::NFS3::stable_how_t)extract_XDR_uint32(buf, n);
|
|
auto rval = zeek::BifType::Enum::NFS3::stable_how_t->GetEnumVal(stable);
|
|
return rval;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_lookup_reply(const u_char*& buf, int& n, BifEnum::NFS3::status_t status)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::lookup_reply_t);
|
|
|
|
if ( status == BifEnum::NFS3::NFS3ERR_OK )
|
|
{
|
|
rep->Assign(0, nfs3_fh(buf,n));
|
|
rep->Assign(1, nfs3_post_op_attr(buf, n));
|
|
rep->Assign(2, nfs3_post_op_attr(buf, n));
|
|
}
|
|
else
|
|
{
|
|
rep->Assign(0, nullptr);
|
|
rep->Assign(1, nullptr);
|
|
rep->Assign(2, nfs3_post_op_attr(buf, n));
|
|
}
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_readargs(const u_char*& buf, int& n)
|
|
{
|
|
auto readargs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::readargs_t);
|
|
|
|
readargs->Assign(0, nfs3_fh(buf, n));
|
|
readargs->Assign(1, ExtractUint64(buf, n)); // offset
|
|
readargs->Assign(2, ExtractUint32(buf,n)); // size
|
|
|
|
return readargs;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_read_reply(const u_char*& buf, int& n, BifEnum::NFS3::status_t status,
|
|
bro_uint_t offset)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::read_reply_t);
|
|
|
|
if (status == BifEnum::NFS3::NFS3ERR_OK)
|
|
{
|
|
uint32_t bytes_read;
|
|
|
|
rep->Assign(0, nfs3_post_op_attr(buf, n));
|
|
bytes_read = extract_XDR_uint32(buf, n);
|
|
rep->Assign(1, zeek::val_mgr->Count(bytes_read));
|
|
rep->Assign(2, ExtractBool(buf, n));
|
|
rep->Assign(3, nfs3_file_data(buf, n, offset, bytes_read));
|
|
}
|
|
else
|
|
{
|
|
rep->Assign(0, nfs3_post_op_attr(buf, n));
|
|
}
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_readlink_reply(const u_char*& buf, int& n, BifEnum::NFS3::status_t status)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::readlink_reply_t);
|
|
|
|
if (status == BifEnum::NFS3::NFS3ERR_OK)
|
|
{
|
|
rep->Assign(0, nfs3_post_op_attr(buf, n));
|
|
rep->Assign(1, nfs3_nfspath(buf,n));
|
|
}
|
|
else
|
|
{
|
|
rep->Assign(0, nfs3_post_op_attr(buf, n));
|
|
}
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_link_reply(const u_char*& buf, int& n, BifEnum::NFS3::status_t status)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::link_reply_t);
|
|
|
|
if ( status == BifEnum::NFS3::NFS3ERR_OK )
|
|
{
|
|
rep->Assign(0, nfs3_post_op_attr(buf, n));
|
|
|
|
// wcc_data
|
|
rep->Assign(1, nfs3_pre_op_attr(buf, n));
|
|
rep->Assign(2, nfs3_post_op_attr(buf, n));
|
|
}
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_symlinkargs(const u_char*& buf, int& n)
|
|
{
|
|
auto symlinkargs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::symlinkargs_t);
|
|
|
|
symlinkargs->Assign(0, nfs3_diropargs(buf, n));
|
|
symlinkargs->Assign(1, nfs3_symlinkdata(buf, n));
|
|
|
|
return symlinkargs;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_sattrargs(const u_char*& buf, int& n)
|
|
{
|
|
auto sattrargs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::sattrargs_t);
|
|
|
|
sattrargs->Assign(0, nfs3_fh(buf, n));
|
|
sattrargs->Assign(1, nfs3_sattr(buf, n));
|
|
|
|
return sattrargs;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_linkargs(const u_char*& buf, int& n)
|
|
{
|
|
auto linkargs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::linkargs_t);
|
|
|
|
linkargs->Assign(0, nfs3_fh(buf, n));
|
|
linkargs->Assign(1, nfs3_diropargs(buf, n));
|
|
|
|
return linkargs;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_writeargs(const u_char*& buf, int& n)
|
|
{
|
|
uint32_t bytes;
|
|
uint64_t offset;
|
|
auto writeargs = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::writeargs_t);
|
|
|
|
writeargs->Assign(0, nfs3_fh(buf, n));
|
|
offset = extract_XDR_uint64(buf, n);
|
|
writeargs->Assign(1, zeek::val_mgr->Count(offset)); // offset
|
|
bytes = extract_XDR_uint32(buf, n);
|
|
writeargs->Assign(2, zeek::val_mgr->Count(bytes)); // size
|
|
|
|
writeargs->Assign(3, nfs3_stable_how(buf, n));
|
|
writeargs->Assign(4, nfs3_file_data(buf, n, offset, bytes));
|
|
|
|
return writeargs;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_write_reply(const u_char*& buf, int& n, BifEnum::NFS3::status_t status)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::write_reply_t);
|
|
|
|
if ( status == BifEnum::NFS3::NFS3ERR_OK )
|
|
{
|
|
rep->Assign(0, nfs3_pre_op_attr(buf, n));
|
|
rep->Assign(1, nfs3_post_op_attr(buf, n));
|
|
rep->Assign(2, ExtractUint32(buf, n));
|
|
rep->Assign(3, nfs3_stable_how(buf, n));
|
|
|
|
// Writeverf. While the RFC says that this should be a fixed
|
|
// length opaque, it specifies the lenght as 8 bytes, so we
|
|
// can also just as easily extract a uint64.
|
|
rep->Assign(4, ExtractUint64(buf, n));
|
|
}
|
|
else
|
|
{
|
|
rep->Assign(0, nfs3_post_op_attr(buf, n));
|
|
rep->Assign(1, nfs3_pre_op_attr(buf, n));
|
|
}
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_newobj_reply(const u_char*& buf, int& n, BifEnum::NFS3::status_t status)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::newobj_reply_t);
|
|
|
|
if (status == BifEnum::NFS3::NFS3ERR_OK)
|
|
{
|
|
int i = 0;
|
|
rep->Assign(0, nfs3_post_op_fh(buf,n));
|
|
rep->Assign(1, nfs3_post_op_attr(buf, n));
|
|
// wcc_data
|
|
rep->Assign(2, nfs3_pre_op_attr(buf, n));
|
|
rep->Assign(3, nfs3_post_op_attr(buf, n));
|
|
}
|
|
else
|
|
{
|
|
rep->Assign(0, nullptr);
|
|
rep->Assign(1, nullptr);
|
|
rep->Assign(2, nfs3_pre_op_attr(buf, n));
|
|
rep->Assign(3, nfs3_post_op_attr(buf, n));
|
|
}
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_delobj_reply(const u_char*& buf, int& n)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::delobj_reply_t);
|
|
|
|
// wcc_data
|
|
rep->Assign(0, nfs3_pre_op_attr(buf, n));
|
|
rep->Assign(1, nfs3_post_op_attr(buf, n));
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_renameobj_reply(const u_char*& buf, int& n)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::renameobj_reply_t);
|
|
|
|
// wcc_data
|
|
rep->Assign(0, nfs3_pre_op_attr(buf, n));
|
|
rep->Assign(1, nfs3_post_op_attr(buf, n));
|
|
rep->Assign(2, nfs3_pre_op_attr(buf, n));
|
|
rep->Assign(3, nfs3_post_op_attr(buf, n));
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_readdirargs(bool isplus, const u_char*& buf, int&n)
|
|
{
|
|
auto args = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::readdirargs_t);
|
|
|
|
args->Assign(0, zeek::val_mgr->Bool(isplus));
|
|
args->Assign(1, nfs3_fh(buf, n));
|
|
args->Assign(2, ExtractUint64(buf,n)); // cookie
|
|
args->Assign(3, ExtractUint64(buf,n)); // cookieverf
|
|
args->Assign(4, ExtractUint32(buf,n)); // dircount
|
|
|
|
if ( isplus )
|
|
args->Assign(5, ExtractUint32(buf,n));
|
|
|
|
return args;
|
|
}
|
|
|
|
zeek::RecordValPtr NFS_Interp::nfs3_readdir_reply(bool isplus, const u_char*& buf,
|
|
int&n, BifEnum::NFS3::status_t status)
|
|
{
|
|
auto rep = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::readdir_reply_t);
|
|
|
|
rep->Assign(0, zeek::val_mgr->Bool(isplus));
|
|
|
|
if ( status == BifEnum::NFS3::NFS3ERR_OK )
|
|
{
|
|
unsigned pos;
|
|
auto entries = zeek::make_intrusive<zeek::VectorVal>(zeek::BifType::Vector::NFS3::direntry_vec_t);
|
|
|
|
rep->Assign(1, nfs3_post_op_attr(buf,n)); // dir_attr
|
|
rep->Assign(2, ExtractUint64(buf,n)); // cookieverf
|
|
|
|
pos = 1;
|
|
|
|
while ( extract_XDR_uint32(buf,n) )
|
|
{
|
|
auto entry = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::NFS3::direntry_t);
|
|
entry->Assign(0, ExtractUint64(buf,n)); // fileid
|
|
entry->Assign(1, nfs3_filename(buf,n)); // fname
|
|
entry->Assign(2, ExtractUint64(buf,n)); // cookie
|
|
|
|
if ( isplus )
|
|
{
|
|
entry->Assign(3, nfs3_post_op_attr(buf,n));
|
|
entry->Assign(4, nfs3_post_op_fh(buf,n));
|
|
}
|
|
|
|
entries->Assign(pos, std::move(entry));
|
|
pos++;
|
|
}
|
|
|
|
rep->Assign(3, entries);
|
|
rep->Assign(4, ExtractBool(buf,n)); // eof
|
|
}
|
|
else
|
|
{
|
|
rep->Assign(1, nfs3_post_op_attr(buf,n));
|
|
}
|
|
|
|
return rep;
|
|
}
|
|
|
|
zeek::ValPtr NFS_Interp::ExtractUint32(const u_char*& buf, int& n)
|
|
{
|
|
return zeek::val_mgr->Count(extract_XDR_uint32(buf, n));
|
|
}
|
|
|
|
zeek::ValPtr NFS_Interp::ExtractUint64(const u_char*& buf, int& n)
|
|
{
|
|
return zeek::val_mgr->Count(extract_XDR_uint64(buf, n));
|
|
}
|
|
|
|
zeek::ValPtr NFS_Interp::ExtractTime(const u_char*& buf, int& n)
|
|
{
|
|
return zeek::make_intrusive<zeek::TimeVal>(extract_XDR_time(buf, n));
|
|
}
|
|
|
|
zeek::ValPtr NFS_Interp::ExtractInterval(const u_char*& buf, int& n)
|
|
{
|
|
return zeek::make_intrusive<zeek::IntervalVal>(double(extract_XDR_uint32(buf, n)), 1.0);
|
|
}
|
|
|
|
zeek::ValPtr NFS_Interp::ExtractBool(const u_char*& buf, int& n)
|
|
{
|
|
return zeek::val_mgr->Bool(extract_XDR_uint32(buf, n));
|
|
}
|
|
|
|
} // namespace detail
|
|
|
|
NFS_Analyzer::NFS_Analyzer(zeek::Connection* conn)
|
|
: RPC_Analyzer("NFS", conn, new detail::NFS_Interp(this))
|
|
{
|
|
orig_rpc = resp_rpc = nullptr;
|
|
}
|
|
|
|
void NFS_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);
|
|
}
|
|
}
|
|
|
|
} // namespace zeek::analyzer::rpc
|