Project

General

Profile

Bug #77 » 0001-refactor-dcerpc-in-prep-for-dcerpc-over-smb.patch

Kirby Kuehl, 01/31/2010 10:50 AM

View differences:

src/app-layer-dcerpc-common.h
/*
* Copyright (c) 2009,2010 Open Information Security Foundation
* app-layer-dcerpc.h
*
* \author Kirby Kuehl <kkuehl@gmail.com>
*/
#ifndef APPLAYERDCERPCCOMMON_H_
#define APPLAYERDCERPCCOMMON_H_
#include "app-layer-protos.h"
#include "app-layer-parser.h"
#include "flow.h"
#include "queue.h"
#include "util-byte.h"
void RegisterDCERPCParsers(void);
void DCERPCParserTests(void);
void DCERPCParserRegisterTests(void);
// http://www.opengroup.org/onlinepubs/9629399/chap12.htm#tagcjh_17_06
#define REQUEST 0
#define PING 1
#define RESPONSE 2
#define FAULT 3
#define WORKING 4
#define NOCALL 5
#define REJECT 6
#define ACK 7
#define CL_CANCEL 8
#define FACK 9
#define CANCEL_ACK 10
#define BIND 11
#define BIND_ACK 12
#define BIND_NAK 13
#define ALTER_CONTEXT 14
#define ALTER_CONTEXT_RESP 15
#define SHUTDOWN 17
#define CO_CANCEL 18
#define ORPHANED 19
#if 0
typedef struct {
uint8_t rpc_vers; /* 4 RPC protocol major version (4 LSB only)*/
uint8_t ptype; /* Packet type (5 LSB only) */
uint8_t flags1; /* Packet flags */
uint8_t flags2; /* Packet flags */
uint8_t drep[3]; /* Data representation format label */
uint8_t serial_hi; /* High byte of serial number */
uuid_t object; /* Object identifier */
uuid_t if_id; /* Interface identifier */
uuid_t act_id; /* Activity identifier */
unsigned long server_boot;/* Server boot time */
unsigned long if_vers; /* Interface version */
unsigned long seqnum; /* Sequence number */
unsigned short opnum; /* Operation number */
unsigned short ihint; /* Interface hint */
unsigned short ahint; /* Activity hint */
unsigned short len; /* Length of packet body */
unsigned short fragnum; /* Fragment number */
unsigned small auth_proto; /* Authentication protocol identifier*/
unsigned small serial_lo; /* Low byte of serial number */
} dc_rpc_cl_pkt_hdr_t;
#endif
#define RESERVED_01 0x01
#define LASTFRAG 0x02
#define FRAG 0x04
#define NOFACK 0x08
#define MAYBE 0x10
#define IDEMPOTENT 0x20
#define BROADCAST 0x40
#define RESERVED_80 0x80
#define CANCEL_PENDING 0x02
#define RESERVED_04 0x04
#define RESERVED_10 0x10
#define RESERVED_20 0x20
#define RESERVED_40 0x40
#define RESERVED_80 0x80
typedef struct dcerpc_hdr_ {
uint8_t rpc_vers; /* 00:01 RPC version should be 5 */
uint8_t rpc_vers_minor; /* 01:01 minor version */
uint8_t type; /* 02:01 packet type */
uint8_t pfc_flags; /* 03:01 flags (see PFC_... ) */
uint8_t packed_drep[4]; /* 04:04 NDR data representation format label */
uint16_t frag_length; /* 08:02 total length of fragment */
uint16_t auth_length; /* 10:02 length of auth_value */
uint32_t call_id; /* 12:04 call identifier */
}DCERPCHdr;
#define DCERPC_HDR_LEN 16
struct uuid_entry {
uint16_t ctxid;
uint16_t result;
uint8_t uuid[16];
uint16_t version;
uint16_t versionminor;
TAILQ_ENTRY(uuid_entry) next;
};
typedef struct dcerpc_bind_bind_ack_ {
uint8_t numctxitems;
uint8_t numctxitemsleft;
uint8_t ctxbytesprocessed;
uint16_t ctxid;
uint8_t uuid[16];
uint16_t version;
uint16_t versionminor;
struct uuid_entry *uuid_entry;
TAILQ_HEAD(, uuid_entry) uuid_list;
uint16_t secondaryaddrlen;
uint16_t secondaryaddrlenleft;
uint16_t result;
}DCERPCBindBindAck;
typedef struct dcerpc_request_ {
uint16_t opnum;
uint8_t *stub_data;
}DCERPCRequest;
typedef struct DCERPC_ {
DCERPCHdr dcerpchdr;
DCERPCBindBindAck dcerpcbindbindack;
DCERPCRequest dcerpcrequest;
uint16_t bytesprocessed;
uint8_t pad;
uint8_t padleft;
}DCERPC;
#define PFC_FIRST_FRAG 0x01/* First fragment */
#define PFC_LAST_FRAG 0x02/* Last fragment */
#define PFC_PENDING_CANCEL 0x04/* Cancel was pending at sender */
#define PFC_RESERVED_1 0x08
#define PFC_CONC_MPX 0x10/* supports concurrent multiplexing
* of a single connection. */
#define PFC_DID_NOT_EXECUTE 0x20/* only meaningful on `fault' packet;
* if true, guaranteed call did not
* execute. */
#define PFC_MAYBE 0x40/* `maybe' call semantics requested */
#define PFC_OBJECT_UUID 0x80/* if true, a non-nil object UUID
* was specified in the handle, and
* is present in the optional object
* field. If false, the object field
* is omitted. */
#define REASON_NOT_SPECIFIED 0
#define TEMPORARY_CONGESTION 1
#define LOCAL_LIMIT_EXCEEDED 2
#define CALLED_PADDR_UNKNOWN 3 /* not used */
#define PROTOCOL_VERSION_NOT_SUPPORTED 4
#define DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */
#define USER_DATA_NOT_READABLE 6 /* not used */
#define NO_PSAP_AVAILABLE 7 /* not used */
/*
typedef uint16_t p_context_id_t;
typedef struct {
uuid_t if_uuid;
uint32_t if_version;
} p_syntax_id_t;
typedef struct {
p_context_id_t p_cont_id;
uint8_t n_transfer_syn; // number of items
uint8_t reserved; // alignment pad, m.b.z.
p_syntax_id_t abstract_syntax; // transfer syntax list
p_syntax_id_t [size_is(n_transfer_syn)] transfer_syntaxes[];
} p_cont_elem_t;
*/
int DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len);
#endif /* APPLAYERDCERPCCOMMON_H_ */
src/app-layer-dcerpc.c
DCERPC_FIELD_MAX,
};
#if 0
#ifdef UNITTESTS
/* \brief hexdump function from libdnet, used for debugging only */
void hexdump(const void *buf, size_t len) {
/* dumps len bytes of *buf to stdout. Looks like:
......
* \brief DCERPCParseSecondaryAddr reads secondaryaddrlen bytes from the BIND_ACK
* DCERPC call.
*/
static uint32_t DCERPCParseSecondaryAddr(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t DCERPCParseSecondaryAddr(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
while (sstate->secondaryaddrlenleft-- && input_len--) {
while (dcerpc->dcerpcbindbindack.secondaryaddrlenleft-- && input_len--) {
SCLogDebug("0x%02x ", *p);
p++;
}
sstate->bytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
static uint32_t PaddingParser(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t PaddingParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
while (sstate->padleft-- && input_len--) {
while (dcerpc->padleft-- && input_len--) {
SCLogDebug("0x%02x ", *p);
p++;
}
sstate->bytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
static uint32_t DCERPCGetCTXItems(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t DCERPCGetCTXItems(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
if (input_len) {
switch (sstate->ctxbytesprocessed) {
switch (dcerpc->dcerpcbindbindack.ctxbytesprocessed) {
case 0:
if (input_len >= 4) {
sstate->numctxitems = *p;
sstate->numctxitemsleft = sstate->numctxitems;
sstate->ctxbytesprocessed += 4;
sstate->bytesprocessed += 4;
dcerpc->dcerpcbindbindack.numctxitems = *p;
dcerpc->dcerpcbindbindack.numctxitemsleft = dcerpc->dcerpcbindbindack.numctxitems;
dcerpc->dcerpcbindbindack.ctxbytesprocessed += 4;
dcerpc->bytesprocessed += 4;
SCReturnUInt(4U);
} else {
sstate->numctxitems = *(p++);
sstate->numctxitemsleft = sstate->numctxitems;
dcerpc->dcerpcbindbindack.numctxitems = *(p++);
dcerpc->dcerpcbindbindack.numctxitemsleft = dcerpc->dcerpcbindbindack.numctxitems;
if (!(--input_len))
break;
}
......
break;
}
}
sstate->ctxbytesprocessed += (p - input);
sstate->bytesprocessed += (p - input);
dcerpc->dcerpcbindbindack.ctxbytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
......
* each UUID is added to a TAILQ.
*/
static uint32_t DCERPCParseBINDCTXItem(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t DCERPCParseBINDCTXItem(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
if (input_len) {
switch (sstate->ctxbytesprocessed) {
switch (dcerpc->dcerpcbindbindack.ctxbytesprocessed) {
case 0:
if (input_len >= 44) {
sstate->ctxid = *(p);
sstate->ctxid |= *(p + 1) << 8;
sstate->uuid[3] = *(p + 4);
sstate->uuid[2] = *(p + 5);
sstate->uuid[1] = *(p + 6);
sstate->uuid[0] = *(p + 7);
sstate->uuid[5] = *(p + 8);
sstate->uuid[4] = *(p + 9);
sstate->uuid[7] = *(p + 10);
sstate->uuid[6] = *(p + 11);
sstate->uuid[8] = *(p + 12);
sstate->uuid[9] = *(p + 13);
sstate->uuid[10] = *(p + 14);
sstate->uuid[11] = *(p + 15);
sstate->uuid[12] = *(p + 16);
sstate->uuid[13] = *(p + 17);
sstate->uuid[14] = *(p + 18);
sstate->uuid[15] = *(p + 19);
sstate->version = *(p + 20);
sstate->version |= *(p + 21) << 8;
sstate->versionminor = *(p + 22);
sstate->versionminor |= *(p + 23) << 8;
if (sstate->ctxid == sstate->numctxitems
- sstate->numctxitemsleft) {
sstate->uuid_entry = (struct uuid_entry *) calloc(1,
dcerpc->dcerpcbindbindack.ctxid = *(p);
dcerpc->dcerpcbindbindack.ctxid |= *(p + 1) << 8;
dcerpc->dcerpcbindbindack.uuid[3] = *(p + 4);
dcerpc->dcerpcbindbindack.uuid[2] = *(p + 5);
dcerpc->dcerpcbindbindack.uuid[1] = *(p + 6);
dcerpc->dcerpcbindbindack.uuid[0] = *(p + 7);
dcerpc->dcerpcbindbindack.uuid[5] = *(p + 8);
dcerpc->dcerpcbindbindack.uuid[4] = *(p + 9);
dcerpc->dcerpcbindbindack.uuid[7] = *(p + 10);
dcerpc->dcerpcbindbindack.uuid[6] = *(p + 11);
dcerpc->dcerpcbindbindack.uuid[8] = *(p + 12);
dcerpc->dcerpcbindbindack.uuid[9] = *(p + 13);
dcerpc->dcerpcbindbindack.uuid[10] = *(p + 14);
dcerpc->dcerpcbindbindack.uuid[11] = *(p + 15);
dcerpc->dcerpcbindbindack.uuid[12] = *(p + 16);
dcerpc->dcerpcbindbindack.uuid[13] = *(p + 17);
dcerpc->dcerpcbindbindack.uuid[14] = *(p + 18);
dcerpc->dcerpcbindbindack.uuid[15] = *(p + 19);
dcerpc->dcerpcbindbindack.version = *(p + 20);
dcerpc->dcerpcbindbindack.version |= *(p + 21) << 8;
dcerpc->dcerpcbindbindack.versionminor = *(p + 22);
dcerpc->dcerpcbindbindack.versionminor |= *(p + 23) << 8;
if (dcerpc->dcerpcbindbindack.ctxid == dcerpc->dcerpcbindbindack.numctxitems
- dcerpc->dcerpcbindbindack.numctxitemsleft) {
dcerpc->dcerpcbindbindack.uuid_entry = (struct uuid_entry *) calloc(1,
sizeof(struct uuid_entry));
if (sstate->uuid_entry == NULL) {
if (dcerpc->dcerpcbindbindack.uuid_entry == NULL) {
SCReturnUInt(0);
} else {
memcpy(sstate->uuid_entry->uuid, sstate->uuid,
sizeof(sstate->uuid));
sstate->uuid_entry->ctxid = sstate->ctxid;
sstate->uuid_entry->version = sstate->version;
sstate->uuid_entry->versionminor = sstate->versionminor;
TAILQ_INSERT_HEAD(&sstate->uuid_list, sstate->uuid_entry,
memcpy(dcerpc->dcerpcbindbindack.uuid_entry->uuid, dcerpc->dcerpcbindbindack.uuid,
sizeof(dcerpc->dcerpcbindbindack.uuid));
dcerpc->dcerpcbindbindack.uuid_entry->ctxid = dcerpc->dcerpcbindbindack.ctxid;
dcerpc->dcerpcbindbindack.uuid_entry->version = dcerpc->dcerpcbindbindack.version;
dcerpc->dcerpcbindbindack.uuid_entry->versionminor = dcerpc->dcerpcbindbindack.versionminor;
TAILQ_INSERT_HEAD(&dcerpc->dcerpcbindbindack.uuid_list, dcerpc->dcerpcbindbindack.uuid_entry,
next);
//printUUID("BIND", sstate->uuid_entry);
sstate->numctxitemsleft--;
sstate->bytesprocessed += (44);
sstate->ctxbytesprocessed += (44);
//printUUID("BIND", dcerpc->dcerpcbindbindack.uuid_entry);
dcerpc->dcerpcbindbindack.numctxitemsleft--;
dcerpc->bytesprocessed += (44);
dcerpc->dcerpcbindbindack.ctxbytesprocessed += (44);
SCReturnUInt(44U);
}
} else {
SCLogDebug("ctxitem %u, expected %u\n", sstate->ctxid,
sstate->numctxitems - sstate->numctxitemsleft);
SCLogDebug("ctxitem %u, expected %u\n", dcerpc->dcerpcbindbindack.ctxid,
dcerpc->dcerpcbindbindack.numctxitems - dcerpc->dcerpcbindbindack.numctxitemsleft);
SCReturnUInt(0);
}
} else {
sstate->ctxid = *(p++);
dcerpc->dcerpcbindbindack.ctxid = *(p++);
if (!(--input_len))
break;
}
case 1:
sstate->ctxid |= *(p++) << 8;
dcerpc->dcerpcbindbindack.ctxid |= *(p++) << 8;
if (!(--input_len))
break;
case 2:
......
if (!(--input_len))
break;
case 4:
sstate->uuid[3] = *(p++);
dcerpc->dcerpcbindbindack.uuid[3] = *(p++);
if (!(--input_len))
break;
case 5:
sstate->uuid[2] = *(p++);
dcerpc->dcerpcbindbindack.uuid[2] = *(p++);
if (!(--input_len))
break;
case 6:
sstate->uuid[1] = *(p++);
dcerpc->dcerpcbindbindack.uuid[1] = *(p++);
if (!(--input_len))
break;
case 7:
sstate->uuid[0] = *(p++);
dcerpc->dcerpcbindbindack.uuid[0] = *(p++);
if (!(--input_len))
break;
case 8:
sstate->uuid[5] = *(p++);
dcerpc->dcerpcbindbindack.uuid[5] = *(p++);
if (!(--input_len))
break;
case 9:
sstate->uuid[4] = *(p++);
dcerpc->dcerpcbindbindack.uuid[4] = *(p++);
if (!(--input_len))
break;
case 10:
sstate->uuid[7] = *(p++);
dcerpc->dcerpcbindbindack.uuid[7] = *(p++);
if (!(--input_len))
break;
case 11:
sstate->uuid[6] = *(p++);
dcerpc->dcerpcbindbindack.uuid[6] = *(p++);
if (!(--input_len))
break;
case 12:
sstate->uuid[8] = *(p++);
dcerpc->dcerpcbindbindack.uuid[8] = *(p++);
if (!(--input_len))
break;
case 13:
sstate->uuid[9] = *(p++);
dcerpc->dcerpcbindbindack.uuid[9] = *(p++);
if (!(--input_len))
break;
case 14:
sstate->uuid[10] = *(p++);
dcerpc->dcerpcbindbindack.uuid[10] = *(p++);
if (!(--input_len))
break;
case 15:
sstate->uuid[11] = *(p++);
dcerpc->dcerpcbindbindack.uuid[11] = *(p++);
if (!(--input_len))
break;
case 16:
sstate->uuid[12] = *(p++);
dcerpc->dcerpcbindbindack.uuid[12] = *(p++);
if (!(--input_len))
break;
case 17:
sstate->uuid[13] = *(p++);
dcerpc->dcerpcbindbindack.uuid[13] = *(p++);
if (!(--input_len))
break;
case 18:
sstate->uuid[14] = *(p++);
dcerpc->dcerpcbindbindack.uuid[14] = *(p++);
if (!(--input_len))
break;
case 19:
sstate->uuid[15] = *(p++);
dcerpc->dcerpcbindbindack.uuid[15] = *(p++);
if (!(--input_len))
break;
case 20:
sstate->version = *(p++);
dcerpc->dcerpcbindbindack.version = *(p++);
if (!(--input_len))
break;
case 21:
sstate->version |= *(p++);
dcerpc->dcerpcbindbindack.version |= *(p++);
if (!(--input_len))
break;
case 22:
sstate->versionminor = *(p++);
dcerpc->dcerpcbindbindack.versionminor = *(p++);
if (!(--input_len))
break;
case 23:
sstate->versionminor |= *(p++);
dcerpc->dcerpcbindbindack.versionminor |= *(p++);
if (!(--input_len))
break;
case 24:
......
case 43:
p++;
--input_len;
if (sstate->ctxid == sstate->numctxitems - sstate->numctxitemsleft) {
sstate->uuid_entry = (struct uuid_entry *) calloc(1,
if (dcerpc->dcerpcbindbindack.ctxid == dcerpc->dcerpcbindbindack.numctxitems - dcerpc->dcerpcbindbindack.numctxitemsleft) {
dcerpc->dcerpcbindbindack.uuid_entry = (struct uuid_entry *) calloc(1,
sizeof(struct uuid_entry));
if (sstate->uuid_entry == NULL) {
if (dcerpc->dcerpcbindbindack.uuid_entry == NULL) {
SCReturnUInt(0);
} else {
memcpy(sstate->uuid_entry->uuid, sstate->uuid,
sizeof(sstate->uuid));
sstate->uuid_entry->ctxid = sstate->ctxid;
sstate->uuid_entry->version = sstate->version;
sstate->uuid_entry->versionminor = sstate->versionminor;
TAILQ_INSERT_HEAD(&sstate->uuid_list, sstate->uuid_entry,
memcpy(dcerpc->dcerpcbindbindack.uuid_entry->uuid, dcerpc->dcerpcbindbindack.uuid,
sizeof(dcerpc->dcerpcbindbindack.uuid));
dcerpc->dcerpcbindbindack.uuid_entry->ctxid = dcerpc->dcerpcbindbindack.ctxid;
dcerpc->dcerpcbindbindack.uuid_entry->version = dcerpc->dcerpcbindbindack.version;
dcerpc->dcerpcbindbindack.uuid_entry->versionminor = dcerpc->dcerpcbindbindack.versionminor;
TAILQ_INSERT_HEAD(&dcerpc->dcerpcbindbindack.uuid_list, dcerpc->dcerpcbindbindack.uuid_entry,
next);
//printUUID("BIND", sstate->uuid_entry);
sstate->numctxitemsleft--;
sstate->bytesprocessed += (44);
sstate->ctxbytesprocessed += (44);
//printUUID("BIND", dcerpc->dcerpcbindbindack.uuid_entry);
dcerpc->dcerpcbindbindack.numctxitemsleft--;
dcerpc->bytesprocessed += (44);
dcerpc->dcerpcbindbindack.ctxbytesprocessed += (44);
SCReturnUInt(44U);
}
} else {
SCLogDebug("ctxitem %u, expected %u\n", sstate->ctxid,
sstate->numctxitems - sstate->numctxitemsleft);
SCLogDebug("ctxitem %u, expected %u\n", dcerpc->dcerpcbindbindack.ctxid,
dcerpc->dcerpcbindbindack.numctxitems - dcerpc->dcerpcbindbindack.numctxitemsleft);
SCReturnUInt(0);
}
break;
}
}
sstate->ctxbytesprocessed += (p - input);
sstate->bytesprocessed += (p - input);
dcerpc->dcerpcbindbindack.ctxbytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
......
* the BIND_ACK call. The result (Accepted or Rejected) is added to the
* correct UUID from the BIND call.
*/
static uint32_t DCERPCParseBINDACKCTXItem(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t DCERPCParseBINDACKCTXItem(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
struct uuid_entry *uuid_entry;
if (input_len) {
switch (sstate->ctxbytesprocessed) {
switch (dcerpc->dcerpcbindbindack.ctxbytesprocessed) {
case 0:
if (input_len >= 24) {
sstate->result = *p;
sstate->result |= *(p + 1) << 8;
TAILQ_FOREACH(uuid_entry, &sstate->uuid_list, next) {
if (uuid_entry->ctxid == sstate->numctxitems
- sstate->numctxitemsleft) {
uuid_entry->result = sstate->result;
dcerpc->dcerpcbindbindack.result = *p;
dcerpc->dcerpcbindbindack.result |= *(p + 1) << 8;
TAILQ_FOREACH(uuid_entry, &dcerpc->dcerpcbindbindack.uuid_list, next) {
if (uuid_entry->ctxid == dcerpc->dcerpcbindbindack.numctxitems
- dcerpc->dcerpcbindbindack.numctxitemsleft) {
uuid_entry->result = dcerpc->dcerpcbindbindack.result;
//printUUID("BIND_ACK", uuid_entry);
break;
}
}
sstate->numctxitemsleft--;
sstate->bytesprocessed += (24);
sstate->ctxbytesprocessed += (24);
dcerpc->dcerpcbindbindack.numctxitemsleft--;
dcerpc->bytesprocessed += (24);
dcerpc->dcerpcbindbindack.ctxbytesprocessed += (24);
SCReturnUInt(24U);
} else {
sstate->result = *(p++);
dcerpc->dcerpcbindbindack.result = *(p++);
if (!(--input_len))
break;
}
case 1:
sstate->result |= *(p++) << 8;
dcerpc->dcerpcbindbindack.result |= *(p++) << 8;
if (!(--input_len))
break;
case 2:
......
if (!(--input_len))
break;
case 23:
TAILQ_FOREACH(uuid_entry, &sstate->uuid_list, next) {
if (uuid_entry->ctxid == sstate->numctxitems
- sstate->numctxitemsleft) {
uuid_entry->result = sstate->result;
TAILQ_FOREACH(uuid_entry, &dcerpc->dcerpcbindbindack.uuid_list, next) {
if (uuid_entry->ctxid == dcerpc->dcerpcbindbindack.numctxitems
- dcerpc->dcerpcbindbindack.numctxitemsleft) {
uuid_entry->result = dcerpc->dcerpcbindbindack.result;
//printUUID("BIND_ACK", uuid_entry);
break;
}
}
sstate->numctxitemsleft--;
dcerpc->dcerpcbindbindack.numctxitemsleft--;
p++;
--input_len;
break;
}
}
sstate->ctxbytesprocessed += (p - input);
sstate->bytesprocessed += (p - input);
dcerpc->dcerpcbindbindack.ctxbytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
static uint32_t DCERPCParseBIND(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t DCERPCParseBIND(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
if (input_len) {
switch (sstate->bytesprocessed) {
switch (dcerpc->bytesprocessed) {
case 16:
sstate->numctxitems = 0;
dcerpc->dcerpcbindbindack.numctxitems = 0;
if (input_len >= 12) {
TAILQ_INIT(&sstate->uuid_list);
sstate->numctxitems = *(p + 8);
sstate->numctxitemsleft = sstate->numctxitems;
sstate->bytesprocessed += 12;
TAILQ_INIT(&dcerpc->dcerpcbindbindack.uuid_list);
dcerpc->dcerpcbindbindack.numctxitems = *(p + 8);
dcerpc->dcerpcbindbindack.numctxitemsleft = dcerpc->dcerpcbindbindack.numctxitems;
dcerpc->bytesprocessed += 12;
SCReturnUInt(12U);
} else {
/* max_xmit_frag */
......
if (!(--input_len))
break;
case 24:
sstate->numctxitems = *(p++);
sstate->numctxitemsleft = sstate->numctxitems;
TAILQ_INIT(&sstate->uuid_list);
dcerpc->dcerpcbindbindack.numctxitems = *(p++);
dcerpc->dcerpcbindbindack.numctxitemsleft = dcerpc->dcerpcbindbindack.numctxitems;
TAILQ_INIT(&dcerpc->dcerpcbindbindack.uuid_list);
if (!(--input_len))
break;
case 25:
......
break;
}
}
sstate->bytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
static uint32_t DCERPCParseBINDACK(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t DCERPCParseBINDACK(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
switch (sstate->bytesprocessed) {
switch (dcerpc->bytesprocessed) {
case 16:
sstate->numctxitems = 0;
dcerpc->dcerpcbindbindack.numctxitems = 0;
if (input_len >= 10) {
if (sstate->dcerpc.packed_drep[0] == 0x10) {
sstate->secondaryaddrlen = *(p + 8);
sstate->secondaryaddrlen |= *(p + 9) << 8;
if (dcerpc->dcerpchdr.packed_drep[0] == 0x10) {
dcerpc->dcerpcbindbindack.secondaryaddrlen = *(p + 8);
dcerpc->dcerpcbindbindack.secondaryaddrlen |= *(p + 9) << 8;
} else {
sstate->secondaryaddrlen = *(p + 8) << 8;
sstate->secondaryaddrlen |= *(p + 9);
dcerpc->dcerpcbindbindack.secondaryaddrlen = *(p + 8) << 8;
dcerpc->dcerpcbindbindack.secondaryaddrlen |= *(p + 9);
}
sstate->secondaryaddrlenleft = sstate->secondaryaddrlen;
sstate->bytesprocessed += 10;
dcerpc->dcerpcbindbindack.secondaryaddrlenleft = dcerpc->dcerpcbindbindack.secondaryaddrlen;
dcerpc->bytesprocessed += 10;
SCReturnUInt(10U);
} else {
/* max_xmit_frag */
......
if (!(--input_len))
break;
case 24:
sstate->secondaryaddrlen = *(p++);
dcerpc->dcerpcbindbindack.secondaryaddrlen = *(p++);
if (!(--input_len))
break;
case 25:
sstate->secondaryaddrlen |= *(p++) << 8;
if (sstate->dcerpc.packed_drep[0] == 0x01) {
SCByteSwap16(sstate->secondaryaddrlen);
dcerpc->dcerpcbindbindack.secondaryaddrlen |= *(p++) << 8;
if (dcerpc->dcerpchdr.packed_drep[0] == 0x01) {
SCByteSwap16(dcerpc->dcerpcbindbindack.secondaryaddrlen);
}
sstate->secondaryaddrlenleft = sstate->secondaryaddrlen;
SCLogDebug("secondaryaddrlen %u 0x%04x\n", sstate->secondaryaddrlen,
sstate->secondaryaddrlen);
dcerpc->dcerpcbindbindack.secondaryaddrlenleft = dcerpc->dcerpcbindbindack.secondaryaddrlen;
SCLogDebug("secondaryaddrlen %u 0x%04x\n", dcerpc->dcerpcbindbindack.secondaryaddrlen,
dcerpc->dcerpcbindbindack.secondaryaddrlen);
--input_len;
break;
}
sstate->bytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
static uint32_t DCERPCParseREQUEST(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t DCERPCParseREQUEST(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
switch (sstate->bytesprocessed) {
switch (dcerpc->bytesprocessed) {
case 16:
sstate->numctxitems = 0;
dcerpc->dcerpcbindbindack.numctxitems = 0;
if (input_len >= 8) {
if (sstate->dcerpc.packed_drep[0] == 0x10) {
sstate->opnum = *(p + 6);
sstate->opnum |= *(p + 7) << 8;
} else {
sstate->opnum = *(p + 6) << 8;
sstate->opnum |= *(p + 7);
if (dcerpc->dcerpchdr.type == REQUEST) {
if (dcerpc->dcerpchdr.packed_drep[0] == 0x10) {
dcerpc->dcerpcrequest.opnum = *(p + 6);
dcerpc->dcerpcrequest.opnum |= *(p + 7) << 8;
} else {
dcerpc->dcerpcrequest.opnum = *(p + 6) << 8;
dcerpc->dcerpcrequest.opnum |= *(p + 7);
}
}
sstate->bytesprocessed += 8;
dcerpc->bytesprocessed += 8;
SCReturnUInt(8U);
} else {
/* alloc hint 1 */
......
if (!(--input_len))
break;
case 22:
sstate->opnum = *(p++);
if (dcerpc->dcerpchdr.type == REQUEST) {
dcerpc->dcerpcrequest.opnum = *(p++);
} else {
p++;
}
if (!(--input_len))
break;
case 23:
sstate->opnum |= *(p++) << 8;
if (sstate->dcerpc.packed_drep[0] == 0x01) {
SCByteSwap16(sstate->opnum);
if (dcerpc->dcerpchdr.type == REQUEST) {
dcerpc->dcerpcrequest.opnum |= *(p++) << 8;
if (dcerpc->dcerpchdr.packed_drep[0] == 0x01) {
SCByteSwap16(dcerpc->dcerpcrequest.opnum);
}
} else {
p++;
}
--input_len;
break;
}
sstate->bytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
static uint32_t StubDataParser(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t StubDataParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
sstate->stub_data = input;
while (sstate->padleft-- && input_len--) {
dcerpc->dcerpcrequest.stub_data = input;
while (dcerpc->padleft-- && input_len--) {
SCLogDebug("0x%02x ", *p);
p++;
}
sstate->bytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
......
* present to parse the entire header. A slow path is used to parse
* fragmented packets.
*/
static uint32_t DCERPCParseHeader(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
static uint32_t DCERPCParseHeader(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint8_t *p = input;
if (input_len) {
switch (sstate->bytesprocessed) {
switch (dcerpc->bytesprocessed) {
case 0:
if (input_len >= DCERPC_HDR_LEN) {
//if (*p != 5) SCReturnUInt();
//if (!(*(p + 1 ) == 0 || (*(p + 1) == 1))) SCReturnInt(0);
sstate->dcerpc.rpc_vers = *p;
sstate->dcerpc.rpc_vers_minor = *(p + 1);
sstate->dcerpc.type = *(p + 2);
sstate->dcerpc.pfc_flags = *(p + 3);
sstate->dcerpc.packed_drep[0] = *(p + 4);
sstate->dcerpc.packed_drep[1] = *(p + 5);
sstate->dcerpc.packed_drep[2] = *(p + 6);
sstate->dcerpc.packed_drep[3] = *(p + 7);
if (sstate->dcerpc.packed_drep[0] == 0x10) {
sstate->dcerpc.frag_length = *(p + 8);
sstate->dcerpc.frag_length |= *(p + 9) << 8;
sstate->dcerpc.auth_length = *(p + 10);
sstate->dcerpc.auth_length |= *(p + 11) << 8;
sstate->dcerpc.call_id = *(p + 12) << 24;
sstate->dcerpc.call_id |= *(p + 13) << 16;
sstate->dcerpc.call_id |= *(p + 14) << 8;
sstate->dcerpc.call_id |= *(p + 15);
dcerpc->dcerpchdr.rpc_vers = *p;
dcerpc->dcerpchdr.rpc_vers_minor = *(p + 1);
dcerpc->dcerpchdr.type = *(p + 2);
dcerpc->dcerpchdr.pfc_flags = *(p + 3);
dcerpc->dcerpchdr.packed_drep[0] = *(p + 4);
dcerpc->dcerpchdr.packed_drep[1] = *(p + 5);
dcerpc->dcerpchdr.packed_drep[2] = *(p + 6);
dcerpc->dcerpchdr.packed_drep[3] = *(p + 7);
if (dcerpc->dcerpchdr.packed_drep[0] == 0x10) {
dcerpc->dcerpchdr.frag_length = *(p + 8);
dcerpc->dcerpchdr.frag_length |= *(p + 9) << 8;
dcerpc->dcerpchdr.auth_length = *(p + 10);
dcerpc->dcerpchdr.auth_length |= *(p + 11) << 8;
dcerpc->dcerpchdr.call_id = *(p + 12) << 24;
dcerpc->dcerpchdr.call_id |= *(p + 13) << 16;
dcerpc->dcerpchdr.call_id |= *(p + 14) << 8;
dcerpc->dcerpchdr.call_id |= *(p + 15);
} else {
sstate->dcerpc.frag_length = *(p + 8) << 8;
sstate->dcerpc.frag_length |= *(p + 9);
sstate->dcerpc.auth_length = *(p + 10) << 8;
sstate->dcerpc.auth_length |= *(p + 11);
sstate->dcerpc.call_id = *(p + 12);
sstate->dcerpc.call_id |= *(p + 13) << 8;
sstate->dcerpc.call_id |= *(p + 14) << 16;
sstate->dcerpc.call_id |= *(p + 15) << 24;
dcerpc->dcerpchdr.frag_length = *(p + 8) << 8;
dcerpc->dcerpchdr.frag_length |= *(p + 9);
dcerpc->dcerpchdr.auth_length = *(p + 10) << 8;
dcerpc->dcerpchdr.auth_length |= *(p + 11);
dcerpc->dcerpchdr.call_id = *(p + 12);
dcerpc->dcerpchdr.call_id |= *(p + 13) << 8;
dcerpc->dcerpchdr.call_id |= *(p + 14) << 16;
dcerpc->dcerpchdr.call_id |= *(p + 15) << 24;
}
sstate->bytesprocessed = DCERPC_HDR_LEN;
dcerpc->bytesprocessed = DCERPC_HDR_LEN;
SCReturnUInt(16U);
break;
} else {
sstate->dcerpc.rpc_vers = *(p++);
// if (sstate->dcerpc.rpc_vers != 5) SCReturnInt(2);
dcerpc->dcerpchdr.rpc_vers = *(p++);
// if dcerpc->dcerpchdr.rpc_vers != 5) SCReturnInt(2);
if (!(--input_len))
break;
}
case 1:
sstate->dcerpc.rpc_vers_minor = *(p++);
// if ((sstate->dcerpc.rpc_vers_minor != 0) ||
// (sstate->dcerpc.rpc_vers_minor != 1)) SCReturnInt(3);
dcerpc->dcerpchdr.rpc_vers_minor = *(p++);
// if ((sdcerpc->dcerpchdr.rpc_vers_minor != 0) ||
// (dcerpc->dcerpchdr.rpc_vers_minor != 1)) SCReturnInt(3);
if (!(--input_len))
break;
case 2:
sstate->dcerpc.type = *(p++);
dcerpc->dcerpchdr.type = *(p++);
if (!(--input_len))
break;
case 3:
sstate->dcerpc.pfc_flags = *(p++);
dcerpc->dcerpchdr.pfc_flags = *(p++);
if (!(--input_len))
break;
case 4:
sstate->dcerpc.packed_drep[0] = *(p++);
dcerpc->dcerpchdr.packed_drep[0] = *(p++);
if (!(--input_len))
break;
case 5:
sstate->dcerpc.packed_drep[1] = *(p++);
dcerpc->dcerpchdr.packed_drep[1] = *(p++);
if (!(--input_len))
break;
case 6:
sstate->dcerpc.packed_drep[2] = *(p++);
dcerpc->dcerpchdr.packed_drep[2] = *(p++);
if (!(--input_len))
break;
case 7:
sstate->dcerpc.packed_drep[3] = *(p++);
dcerpc->dcerpchdr.packed_drep[3] = *(p++);
if (!(--input_len))
break;
case 8:
sstate->dcerpc.frag_length = *(p++) << 8;
dcerpc->dcerpchdr.frag_length = *(p++) << 8;
if (!(--input_len))
break;
case 9:
sstate->dcerpc.frag_length |= *(p++);
dcerpc->dcerpchdr.frag_length |= *(p++);
if (!(--input_len))
break;
case 10:
sstate->dcerpc.auth_length = *(p++) << 8;
dcerpc->dcerpchdr.auth_length = *(p++) << 8;
if (!(--input_len))
break;
case 11:
sstate->dcerpc.auth_length |= *(p++);
dcerpc->dcerpchdr.auth_length |= *(p++);
if (!(--input_len))
break;
case 12:
sstate->dcerpc.call_id = *(p++) << 24;
dcerpc->dcerpchdr.call_id = *(p++) << 24;
if (!(--input_len))
break;
case 13:
sstate->dcerpc.call_id |= *(p++) << 16;
dcerpc->dcerpchdr.call_id |= *(p++) << 16;
if (!(--input_len))
break;
case 14:
sstate->dcerpc.call_id |= *(p++) << 8;
if (!(--input_len))
break;
dcerpc->dcerpchdr.call_id |= *(p++) << 8;
if (!(--input_len))
break;
case 15:
sstate->dcerpc.call_id |= *(p++);
if (sstate->dcerpc.packed_drep[0] == 0x01) {
SCByteSwap16(sstate->dcerpc.frag_length);
SCByteSwap16(sstate->dcerpc.auth_length);
SCByteSwap32(sstate->dcerpc.call_id);
}
--input_len;
break;
dcerpc->dcerpchdr.call_id |= *(p++);
if (dcerpc->dcerpchdr.packed_drep[0] == 0x01) {
SCByteSwap16(dcerpc->dcerpchdr.frag_length);
SCByteSwap16(dcerpc->dcerpchdr.auth_length);
SCByteSwap32(dcerpc->dcerpchdr.call_id);
}
--input_len;
break;
}
}
sstate->bytesprocessed += (p - input);
dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
static int DCERPCParse(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
int DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
uint32_t retval = 0;
uint32_t parsed = 0;
if (pstate == NULL)
SCReturnInt(-1);
while (sstate->bytesprocessed < DCERPC_HDR_LEN && input_len) {
retval = DCERPCParseHeader(f, dcerpc_state, pstate, input, input_len,
output);
while (dcerpc->bytesprocessed < DCERPC_HDR_LEN && input_len) {
retval = DCERPCParseHeader(dcerpc, input, input_len);
parsed += retval;
input_len -= retval;
}
SCLogDebug("Done with DCERPCParseHeader bytesprocessed %u/%u left %u\n",
sstate->bytesprocessed, sstate->dcerpc.frag_length, input_len);
dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length, input_len);
#if 0
printf("Done with DCERPCParseHeader bytesprocessed %u/%u left %u\n",
dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length, input_len);
printf("\nDCERPC Version:\t%u\n", dcerpc->dcerpchdr.rpc_vers);
printf("DCERPC Version Minor:\t%u\n", dcerpc->dcerpchdr.rpc_vers_minor);
printf("DCERPC Type:\t%u\n", dcerpc->dcerpchdr.type);
printf("DCERPC Flags:\t0x%02x\n", dcerpc->dcerpchdr.pfc_flags);
printf("DCERPC Packed Drep:\t%02x %02x %02x %02x\n",
dcerpc->dcerpchdr.packed_drep[0], dcerpc->dcerpchdr.packed_drep[1],
dcerpc->dcerpchdr.packed_drep[2], dcerpc->dcerpchdr.packed_drep[3]);
printf("DCERPC Frag Length:\t0x%04x %u\n",
dcerpc->dcerpchdr.frag_length, dcerpc->dcerpchdr.frag_length);
printf("DCERPC Auth Length:\t0x%04x\n", dcerpc->dcerpchdr.auth_length);
printf("DCERPC Call Id:\t0x%08x\n", dcerpc->dcerpchdr.call_id);
#endif
switch (sstate->dcerpc.type) {
switch (dcerpc->dcerpchdr.type) {
case BIND:
case ALTER_CONTEXT:
while (sstate->bytesprocessed < DCERPC_HDR_LEN + 12
&& sstate->bytesprocessed < sstate->dcerpc.frag_length
while (dcerpc->bytesprocessed < DCERPC_HDR_LEN + 12
&& dcerpc->bytesprocessed < dcerpc->dcerpchdr.frag_length
&& input_len) {
retval = DCERPCParseBIND(f, dcerpc_state, pstate, input + parsed,
input_len, output);
retval = DCERPCParseBIND(dcerpc, input + parsed, input_len);
if (retval) {
parsed += retval;
input_len -= retval;
......
}
}
SCLogDebug(
"Done with DCERPCParseBIND bytesprocessed %u/%u -- Should be 12\n",
sstate->bytesprocessed, sstate->dcerpc.frag_length);
while (sstate->numctxitemsleft && sstate->bytesprocessed
< sstate->dcerpc.frag_length && input_len) {
retval = DCERPCParseBINDCTXItem(f, dcerpc_state, pstate, input
+ parsed, input_len, output);
"Done with DCERPCParseBIND bytesprocessed %u/%u numctxitems %u\n",
dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length,
dcerpc->dcerpcbindbindack.numctxitems);
while (dcerpc->dcerpcbindbindack.numctxitemsleft && dcerpc->bytesprocessed
< dcerpc->dcerpchdr.frag_length && input_len) {
retval = DCERPCParseBINDCTXItem(dcerpc, input + parsed, input_len);
if (retval) {
if (sstate->ctxbytesprocessed == 44) {
sstate->ctxbytesprocessed = 0;
if (dcerpc->dcerpcbindbindack.ctxbytesprocessed == 44) {
dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0;
}
parsed += retval;
input_len -= retval;
SCLogDebug("BIND processed %u/%u\n", sstate->bytesprocessed,
sstate->dcerpc.frag_length);
SCLogDebug("BIND processed %u/%u ctxitems %u/%u\n",
dcerpc->bytesprocessed,
dcerpc->dcerpchdr.frag_length, dcerpc->dcerpcbindbindack.numctxitemsleft,
dcerpc->dcerpcbindbindack.numctxitems);
} else if (input_len) {
SCLogDebug("Error Parsing CTX Item");
parsed -= input_len;
input_len = 0;
sstate->numctxitemsleft = 0;
dcerpc->dcerpcbindbindack.numctxitemsleft = 0;
}
}
if (sstate->bytesprocessed == sstate->dcerpc.frag_length) {
sstate->bytesprocessed = 0;
sstate->ctxbytesprocessed = 0;
if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) {
dcerpc->bytesprocessed = 0;
dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0;
}
break;
case BIND_ACK:
case ALTER_CONTEXT_RESP:
while (sstate->bytesprocessed < DCERPC_HDR_LEN + 9
&& sstate->bytesprocessed < sstate->dcerpc.frag_length
while (dcerpc->bytesprocessed < DCERPC_HDR_LEN + 9
&& dcerpc->bytesprocessed < dcerpc->dcerpchdr.frag_length
&& input_len) {
retval = DCERPCParseBINDACK(f, dcerpc_state, pstate,
input + parsed, input_len, output);
retval = DCERPCParseBINDACK(dcerpc, input + parsed, input_len);
if (retval) {
parsed += retval;
input_len -= retval;
SCLogDebug("DCERPCParseBINDACK processed %u/%u left %u\n",
sstate->bytesprocessed, sstate->dcerpc.frag_length, input_len);
dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length, input_len);
} else if (input_len) {
SCLogDebug("Error parsing BIND_ACK");
parsed -= input_len;
......
}
}
while (sstate->bytesprocessed < DCERPC_HDR_LEN + 10
+ sstate->secondaryaddrlen && input_len
&& sstate->bytesprocessed < sstate->dcerpc.frag_length) {
retval = DCERPCParseSecondaryAddr(f, dcerpc_state, pstate, input
+ parsed, input_len, output);
while (dcerpc->bytesprocessed < DCERPC_HDR_LEN + 10
+ dcerpc->dcerpcbindbindack.secondaryaddrlen && input_len
&& dcerpc->bytesprocessed < dcerpc->dcerpchdr.frag_length) {
retval = DCERPCParseSecondaryAddr(dcerpc, input + parsed, input_len);
if (retval) {
parsed += retval;
input_len -= retval;
SCLogDebug(
"DCERPCParseSecondaryAddr %u/%u left %u secondaryaddr len(%u)\n",
sstate->bytesprocessed, sstate->dcerpc.frag_length, input_len,
sstate->secondaryaddrlen);
dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length, input_len,
dcerpc->dcerpcbindbindack.secondaryaddrlen);
} else if (input_len) {
SCLogDebug("Error parsing Secondary Address");
parsed -= input_len;
......
}
}
if (sstate->bytesprocessed == DCERPC_HDR_LEN + 10
+ sstate->secondaryaddrlen) {
sstate->pad = sstate->bytesprocessed % 4;
sstate->padleft = sstate->pad;
if (dcerpc->bytesprocessed == DCERPC_HDR_LEN + 10
+ dcerpc->dcerpcbindbindack.secondaryaddrlen) {
if (dcerpc->bytesprocessed % 4) {
dcerpc->pad = (4 - dcerpc->bytesprocessed % 4);
dcerpc->padleft = dcerpc->pad;
}
}
while (sstate->bytesprocessed < DCERPC_HDR_LEN + 10
+ sstate->secondaryaddrlen + sstate->pad && input_len
&& sstate->bytesprocessed < sstate->dcerpc.frag_length) {
retval = PaddingParser(f, dcerpc_state, pstate, input + parsed,
input_len, output);
while (dcerpc->bytesprocessed < DCERPC_HDR_LEN + 10
+ dcerpc->dcerpcbindbindack.secondaryaddrlen + dcerpc->pad && input_len
&& dcerpc->bytesprocessed < dcerpc->dcerpchdr.frag_length) {
retval = PaddingParser(dcerpc, input + parsed, input_len);
if (retval) {
parsed += retval;
input_len -= retval;
SCLogDebug("PaddingParser %u/%u left %u pad(%u)\n",
sstate->bytesprocessed, sstate->dcerpc.frag_length, input_len,
sstate->pad);
dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length, input_len,
dcerpc->pad);
} else if (input_len) {
SCLogDebug("Error parsing DCERPC Padding");
parsed -= input_len;
......
}
}
while (sstate->bytesprocessed >= DCERPC_HDR_LEN + 10 + sstate->pad
+ sstate->secondaryaddrlen && sstate->bytesprocessed
< DCERPC_HDR_LEN + 14 + sstate->pad + sstate->secondaryaddrlen
&& sstate->bytesprocessed < sstate->dcerpc.frag_length) {
retval = DCERPCGetCTXItems(f, dcerpc_state, pstate, input + parsed,
input_len, output);
while (dcerpc->bytesprocessed >= DCERPC_HDR_LEN + 10 + dcerpc->pad
+ dcerpc->dcerpcbindbindack.secondaryaddrlen && dcerpc->bytesprocessed
< DCERPC_HDR_LEN + 14 + dcerpc->pad + dcerpc->dcerpcbindbindack.secondaryaddrlen
&& dcerpc->bytesprocessed < dcerpc->dcerpchdr.frag_length) {
retval = DCERPCGetCTXItems(dcerpc, input + parsed, input_len);
if (retval) {
parsed += retval;
input_len -= retval;
SCLogDebug("DCERPCGetCTXItems %u/%u (%u)\n", sstate->bytesprocessed,
sstate->dcerpc.frag_length, sstate->numctxitems);
SCLogDebug("DCERPCGetCTXItems %u/%u (%u)\n", dcerpc->bytesprocessed,
dcerpc->dcerpchdr.frag_length, dcerpc->dcerpcbindbindack.numctxitems);
} else if (input_len) {
SCLogDebug("Error parsing CTX Items");
parsed -= input_len;
......
}
}
if (sstate->bytesprocessed == DCERPC_HDR_LEN + 14 + sstate->pad
+ sstate->secondaryaddrlen) {
sstate->ctxbytesprocessed = 0;
if (dcerpc->bytesprocessed == DCERPC_HDR_LEN + 14 + dcerpc->pad
+ dcerpc->dcerpcbindbindack.secondaryaddrlen) {
dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0;
}
while (sstate->numctxitemsleft && input_len && sstate->bytesprocessed
< sstate->dcerpc.frag_length) {
retval = DCERPCParseBINDACKCTXItem(f, dcerpc_state, pstate, input
+ parsed, input_len, output);
while (dcerpc->dcerpcbindbindack.numctxitemsleft && input_len && dcerpc->bytesprocessed
< dcerpc->dcerpchdr.frag_length) {
retval = DCERPCParseBINDACKCTXItem(dcerpc, input + parsed, input_len);
if (retval) {
if (sstate->ctxbytesprocessed == 24) {
sstate->ctxbytesprocessed = 0;
if (dcerpc->dcerpcbindbindack.ctxbytesprocessed == 24) {
dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0;
}
parsed += retval;
input_len -= retval;
......
SCLogDebug("Error parsing CTX Items");
parsed -= input_len;
input_len = 0;
sstate->numctxitemsleft = 0;
dcerpc->dcerpcbindbindack.numctxitemsleft = 0;
}
}
SCLogDebug("BINDACK processed %u/%u\n", sstate->bytesprocessed,
sstate->dcerpc.frag_length);
if (sstate->bytesprocessed == sstate->dcerpc.frag_length) {
sstate->bytesprocessed = 0;
sstate->ctxbytesprocessed = 0;
SCLogDebug("BINDACK processed %u/%u\n", dcerpc->bytesprocessed,
dcerpc->dcerpchdr.frag_length);
if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) {
dcerpc->bytesprocessed = 0;
dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0;
}
break;
case REQUEST:
while (sstate->bytesprocessed < DCERPC_HDR_LEN + 8
&& sstate->bytesprocessed < sstate->dcerpc.frag_length
case RESPONSE:
hexdump(input + parsed, input_len);
while (dcerpc->bytesprocessed < DCERPC_HDR_LEN + 8
&& dcerpc->bytesprocessed < dcerpc->dcerpchdr.frag_length
&& input_len) {
retval = DCERPCParseREQUEST(f, dcerpc_state, pstate,
input + parsed, input_len, output);
retval = DCERPCParseREQUEST(dcerpc, input + parsed, input_len);
if (retval) {
parsed += retval;
input_len -= retval;
dcerpc->padleft = dcerpc->dcerpchdr.frag_length - dcerpc->bytesprocessed;
} else if (input_len) {
SCLogDebug("Error parsing DCERPC Request");
parsed -= input_len;
input_len = 0;
}
}
while (sstate->bytesprocessed >= DCERPC_HDR_LEN + 8
&& sstate->bytesprocessed < sstate->dcerpc.frag_length
while (dcerpc->bytesprocessed >= DCERPC_HDR_LEN + 8
&& dcerpc->bytesprocessed < dcerpc->dcerpchdr.frag_length
&& input_len) {
retval = StubDataParser(f, dcerpc_state, pstate, input + parsed,
input_len, output);
retval = StubDataParser(dcerpc, input + parsed, input_len);
if (retval) {
parsed += retval;
input_len -= retval;
......
}
}
SCLogDebug("REQUEST processed %u/%u\n", sstate->bytesprocessed,
sstate->dcerpc.frag_length);
if (sstate->bytesprocessed == sstate->dcerpc.frag_length) {
sstate->bytesprocessed = 0;
SCLogDebug("REQUEST processed %u frag length %u opnum %u input_len %u\n", dcerpc->bytesprocessed,
dcerpc->dcerpchdr.frag_length, dcerpc->dcerpcrequest.opnum, input_len);
if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) {
dcerpc->bytesprocessed = 0;
}
break;
default:
SCLogDebug("DCERPC Type 0x%02x not implemented yet\n", sstate->dcerpc.type);
SCLogDebug("DCERPC Type 0x%02x not implemented yet\n", dcerpc->dcerpchdr.type);
dcerpc->bytesprocessed = 0;
break;
}
SCReturnInt(1);
}
static int DCERPCParse(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
SCEnter();
DCERPCState *sstate = (DCERPCState *) dcerpc_state;
DCERPCParser(&sstate->dcerpc, input, input_len);
if (pstate == NULL)
SCReturnInt(-1);
pstate->parse_field = 0;
pstate->flags |= APP_LAYER_PARSER_DONE;
SCReturnInt(1);
}
......
struct uuid_entry *item;
while ((item = TAILQ_FIRST(&sstate->uuid_list))) {
while ((item = TAILQ_FIRST(&sstate->dcerpc.dcerpcbindbindack.uuid_list))) {
//printUUID("Free", item);
TAILQ_REMOVE(&sstate->uuid_list, item, next);
TAILQ_REMOVE(&sstate->dcerpc.dcerpcbindbindack.uuid_list, item, next);
free(item);
}
......
/* UNITTESTS */
#ifdef UNITTESTS
/** \test DCERPC Header Parsing and BIND / BIND_ACK multiple UUID handling
*/
*/
/* set this to 1 to see problem */
#define KNOWNFAILURE 0
int DCERPCParserTest01(void) {
int result = 1;
Flow f;
......
0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#if KNOWNFAILURE
uint8_t dcerpcrequest[] = {
0x05, 0x00, 0x00, 0x00, 0x10,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
......
0x00, 0x24, 0x00, 0x35, 0x00, 0x34, 0x00, 0x70,
0x00, 0x69, 0x00};
uint32_t requestlen = sizeof(dcerpcrequest);
#endif
uint32_t bindlen = sizeof(dcerpcbind);
uint32_t bindacklen = sizeof(dcerpcbindack);
......
goto end;
}
if (dcerpc_state->dcerpc.rpc_vers != 5) {
if (dcerpc_state->dcerpc.dcerpchdr.rpc_vers != 5) {
printf("expected dcerpc version 0x05, got 0x%02x : ",
dcerpc_state->dcerpc.rpc_vers);
dcerpc_state->dcerpc.dcerpchdr.rpc_vers);
result = 0;
goto end;
}
if (dcerpc_state->dcerpc.type != BIND) {
printf("expected dcerpc type 0x%02x , got 0x%02x : ", BIND, dcerpc_state->dcerpc.type);
if (dcerpc_state->dcerpc.dcerpchdr.type != BIND) {
printf("expected dcerpc type 0x%02x , got 0x%02x : ", BIND, dcerpc_state->dcerpc.dcerpchdr.type);
result = 0;
goto end;
}
if (dcerpc_state->dcerpc.frag_length != 1084) {
printf("expected dcerpc frag_length 0x%02x , got 0x%02x : ", 1084, dcerpc_state->dcerpc.frag_length);
if (dcerpc_state->dcerpc.dcerpchdr.frag_length != 1084) {
printf("expected dcerpc frag_length 0x%02x , got 0x%02x : ", 1084, dcerpc_state->dcerpc.dcerpchdr.frag_length);
result = 0;
goto end;
}
......
result = 0;
goto end;
}
if (dcerpc_state->dcerpc.type != BIND_ACK) {
printf("expected dcerpc type 0x%02x , got 0x%02x : ", BIND_ACK, dcerpc_state->dcerpc.type);
if (dcerpc_state->dcerpc.dcerpchdr.type != BIND_ACK) {
printf("expected dcerpc type 0x%02x , got 0x%02x : ", BIND_ACK, dcerpc_state->dcerpc.dcerpchdr.type);
result = 0;
goto end;
}
if (dcerpc_state->dcerpc.frag_length != 620) {
printf("expected dcerpc frag_length 0x%02x , got 0x%02x : ", 620, dcerpc_state->dcerpc.frag_length);
if (dcerpc_state->dcerpc.dcerpchdr.frag_length != 620) {
printf("expected dcerpc frag_length 0x%02x , got 0x%02x : ", 620, dcerpc_state->dcerpc.dcerpchdr.frag_length);
result = 0;
goto end;
}
TAILQ_FOREACH(uuid_entry, &dcerpc_state->uuid_list, next) {
TAILQ_FOREACH(uuid_entry, &dcerpc_state->dcerpc.dcerpcbindbindack.uuid_list, next) {
printUUID("BIND_ACK", uuid_entry);
}
#if KNOWNFAILURE
printf("Sending dcerpcrequest (%u)", requestlen);
hexdump(dcerpcrequest, requestlen);
r = AppLayerParse(&f, ALPROTO_DCERPC, STREAM_TOSERVER|STREAM_EOF, dcerpcrequest, requestlen, FALSE);
//hexdump(dcerpcrequest, requestlen);
r = AppLayerParse(&f, ALPROTO_DCERPC, STREAM_TOSERVER|STREAM_EOF, dcerpcrequest, requestlen);
if (r != 0) {
printf("dcerpc header check returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
if (dcerpc_state->dcerpc.type != REQUEST) {
printf("expected dcerpc type 0x%02x , got 0x%02x : ", REQUEST, dcerpc_state->dcerpc.type);
if (dcerpc_state->dcerpc.dcerpchdr.type != REQUEST) {
printf("expected dcerpc type 0x%02x , got 0x%02x : ", REQUEST, dcerpc_state->dcerpc.dcerpchdr.type);
result = 0;
goto end;
}
#endif
end:
return result;
}
/** \test DCERPC Request decoding and opnum parsing.
*/
*/
int DCERPCParserTest02(void) {
int result = 1;
Flow f;
......
goto end;
}
if (dcerpc_state->dcerpc.rpc_vers != 5) {
if (dcerpc_state->dcerpc.dcerpchdr.rpc_vers != 5) {
printf("expected dcerpc version 0x05, got 0x%02x : ",
dcerpc_state->dcerpc.rpc_vers);
dcerpc_state->dcerpc.dcerpchdr.rpc_vers);
result = 0;
goto end;
}
if (dcerpc_state->dcerpc.type != REQUEST) {
printf("expected dcerpc type 0x%02x , got 0x%02x : ", REQUEST, dcerpc_state->dcerpc.type);
if (dcerpc_state->dcerpc.dcerpchdr.type != REQUEST) {
printf("expected dcerpc type 0x%02x , got 0x%02x : ", REQUEST, dcerpc_state->dcerpc.dcerpchdr.type);
result = 0;
goto end;
}
if (dcerpc_state->dcerpc.frag_length != 1024) {
printf("expected dcerpc frag_length 0x%02x , got 0x%02x : ", 1024, dcerpc_state->dcerpc.frag_length);
if (dcerpc_state->dcerpc.dcerpchdr.frag_length != 1024) {
printf("expected dcerpc frag_length 0x%02x , got 0x%02x : ", 1024, dcerpc_state->dcerpc.dcerpchdr.frag_length);
result = 0;
goto end;
}
... This diff was truncated because it exceeds the maximum size that can be displayed.
(1-1/3)