mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 09:08:20 +00:00

pass yet. Changes: - Gave IPAddress/IPPrefix methods AsString() so that one doesn't need to cast to get a string represenation. - Val::AsAddr()/AsSubnet() return references rather than pointers. I find that more intuitive. - ODesc/Serializer/SerializationFormat get methods to support IPAddress/IPPrefix directly. - Reformatted the comments in IPAddr.h from /// to /** style. - Given IPPrefix a Contains() method. - A bit of cleanup.
188 lines
4.6 KiB
C++
188 lines
4.6 KiB
C++
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
#ifndef dce_rpc_h
|
|
#define dce_rpc_h
|
|
|
|
// NOTE: This is a somewhat crude analyzer for DCE/RPC (used on Microsoft
|
|
// Windows systems) and shouldn't be considered as stable.
|
|
|
|
#include "NetVar.h"
|
|
#include "TCP.h"
|
|
#include "IPAddr.h"
|
|
|
|
#include "dce_rpc_simple_pac.h"
|
|
|
|
class UUID {
|
|
public:
|
|
UUID();
|
|
UUID(const u_char data[16]);
|
|
UUID(const binpac::bytestring &uuid);
|
|
UUID(const char* s);
|
|
|
|
const char* to_string() const { return s.c_str(); }
|
|
const string& str() const { return s; }
|
|
bool operator==(const UUID& u) const
|
|
{ return s == u.str(); }
|
|
bool operator<(const UUID& u) const
|
|
{ return s < u.str(); }
|
|
|
|
protected:
|
|
u_char data[16];
|
|
string s;
|
|
};
|
|
|
|
const char* uuid_to_string(const u_char* uuid_data);
|
|
|
|
struct dce_rpc_endpoint_addr {
|
|
// All fields are in host byteorder.
|
|
IPAddr addr;
|
|
u_short port;
|
|
TransportProto proto;
|
|
|
|
dce_rpc_endpoint_addr()
|
|
{
|
|
addr = IPAddr();
|
|
port = 0;
|
|
proto = TRANSPORT_UNKNOWN;
|
|
}
|
|
|
|
bool is_valid_addr() const
|
|
{ return addr != IPAddr() && port != 0 && proto != TRANSPORT_UNKNOWN; }
|
|
|
|
bool operator<(dce_rpc_endpoint_addr const &e) const
|
|
{
|
|
if ( addr != e.addr )
|
|
return addr < e.addr;
|
|
if ( proto != e.proto )
|
|
return proto < e.proto;
|
|
if ( port != e.port )
|
|
return port < e.port;
|
|
|
|
return false;
|
|
}
|
|
|
|
string to_string() const
|
|
{
|
|
static char buf[128];
|
|
snprintf(buf, sizeof(buf), "%s/%d/%s",
|
|
addr.AsString().c_str(), port,
|
|
proto == TRANSPORT_TCP ? "tcp" :
|
|
(proto == TRANSPORT_UDP ? "udp" : "?"));
|
|
|
|
return string(buf);
|
|
}
|
|
};
|
|
|
|
/*
|
|
enum DCE_RPC_PTYPE {
|
|
DCE_RPC_REQUEST, DCE_RPC_PING, DCE_RPC_RESPONSE, DCE_RPC_FAULT,
|
|
DCE_RPC_WORKING, DCE_RPC_NOCALL, DCE_RPC_REJECT, DCE_RPC_ACK,
|
|
DCE_RPC_CL_CANCEL, DCE_RPC_FACK, DCE_RPC_CANCEL_ACK, DCE_RPC_BIND,
|
|
DCE_RPC_BIND_ACK, DCE_RPC_BIND_NAK, DCE_RPC_ALTER_CONTEXT,
|
|
DCE_RPC_ALTER_CONTEXT_RESP, DCE_RPC_SHUTDOWN, DCE_RPC_CO_CANCEL,
|
|
DCE_RPC_ORPHANED,
|
|
};
|
|
*/
|
|
|
|
#define DCE_RPC_HEADER_LENGTH 16
|
|
|
|
class DCE_RPC_Header {
|
|
public:
|
|
DCE_RPC_Header(Analyzer* a, const u_char* bytes);
|
|
|
|
BifEnum::dce_rpc_ptype PTYPE() const { return ptype; }
|
|
int FragLen() const { return frag_len; }
|
|
int LittleEndian() const { return bytes[4] >> 4; }
|
|
bool Fragmented() const { return fragmented; }
|
|
|
|
void Weird(const char* msg) { analyzer->Weird(msg); }
|
|
void SetBytes(const u_char* b) { bytes = b; }
|
|
|
|
protected:
|
|
Analyzer* analyzer;
|
|
const u_char* bytes;
|
|
BifEnum::dce_rpc_ptype ptype;
|
|
int frag_len;
|
|
bool fragmented;
|
|
};
|
|
|
|
// Create a general DCE_RPC_Session class so that it can be used in
|
|
// case the RPC conversation is tunneled through other connections,
|
|
// e.g. through an SMB session.
|
|
|
|
class DCE_RPC_Session {
|
|
public:
|
|
DCE_RPC_Session(Analyzer* a);
|
|
virtual ~DCE_RPC_Session() {}
|
|
virtual void DeliverPDU(int is_orig, int len, const u_char* data);
|
|
|
|
static bool LooksLikeRPC(int len, const u_char* msg);
|
|
static bool any_dce_rpc_event()
|
|
{ return dce_rpc_message || dce_rpc_bind || dce_rpc_request; }
|
|
|
|
protected:
|
|
void DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu);
|
|
void DeliverRequest(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu);
|
|
void DeliverResponse(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu);
|
|
|
|
void DeliverEpmapperRequest(
|
|
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu,
|
|
const binpac::DCE_RPC_Simple::DCE_RPC_Request* req);
|
|
void DeliverEpmapperResponse(
|
|
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu,
|
|
const binpac::DCE_RPC_Simple::DCE_RPC_Response* resp);
|
|
void DeliverEpmapperMapResponse(
|
|
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu,
|
|
const binpac::DCE_RPC_Simple::DCE_RPC_Response* resp);
|
|
|
|
Analyzer* analyzer;
|
|
UUID if_uuid;
|
|
BifEnum::dce_rpc_if_id if_id;
|
|
int opnum;
|
|
struct {
|
|
dce_rpc_endpoint_addr addr;
|
|
UUID uuid;
|
|
} mapped;
|
|
};
|
|
|
|
class Contents_DCE_RPC_Analyzer : public TCP_SupportAnalyzer {
|
|
public:
|
|
Contents_DCE_RPC_Analyzer(Connection* conn, bool orig, DCE_RPC_Session* session,
|
|
bool speculative);
|
|
~Contents_DCE_RPC_Analyzer();
|
|
|
|
protected:
|
|
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
|
virtual void DeliverPDU(int len, const u_char* data);
|
|
|
|
void InitState();
|
|
|
|
int speculation;
|
|
u_char* msg_buf;
|
|
int msg_len;
|
|
int buf_n; // number of bytes in msg_buf
|
|
int buf_len; // size off msg_buf
|
|
DCE_RPC_Header* hdr;
|
|
|
|
bool ParseHeader();
|
|
|
|
DCE_RPC_Session* session;
|
|
};
|
|
|
|
class DCE_RPC_Analyzer : public TCP_ApplicationAnalyzer {
|
|
public:
|
|
DCE_RPC_Analyzer(Connection* conn, bool speculative = false);
|
|
~DCE_RPC_Analyzer();
|
|
|
|
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
|
{ return new DCE_RPC_Analyzer(conn); }
|
|
|
|
static bool Available()
|
|
{ return DCE_RPC_Session::any_dce_rpc_event(); }
|
|
|
|
protected:
|
|
DCE_RPC_Session* session;
|
|
bool speculative;
|
|
};
|
|
|
|
#endif /* dce_rpc_h */
|