do not reset dce stub buffer, if we are dealing with fragmented pdus(holds good only for first frag request pdus)

remotes/origin/master-1.0.x
Anoop Saldanha 15 years ago committed by Victor Julien
parent 73241fc86c
commit c7fdc5ebda

@ -183,6 +183,9 @@ typedef struct DCERPC_ {
uint8_t pad; uint8_t pad;
uint16_t padleft; uint16_t padleft;
uint16_t transaction_id; uint16_t transaction_id;
/* indicates if the dcerpc pdu state is in the middle of processing
* a fragmented pdu */
uint8_t pdu_fragged;
} DCERPC; } DCERPC;
typedef struct DCERPCUDP_ { typedef struct DCERPCUDP_ {

@ -904,8 +904,11 @@ static uint32_t StubDataParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_le
/* if the frag is the the first frag irrespective of it being a part of /* if the frag is the the first frag irrespective of it being a part of
* a multi frag PDU or not, it indicates the previous PDU's stub would * a multi frag PDU or not, it indicates the previous PDU's stub would
* have been buffered and processed and we can use the buffer to hold * have been buffered and processed and we can use the buffer to hold
* frags from a fresh request/response */ * frags from a fresh request/response. Also if the state is in the
if (dcerpc->dcerpchdr.pfc_flags & PFC_FIRST_FRAG) { * process of processing a fragmented pdu, we should append to the
* existing stub and not reset the stub buffer */
if (dcerpc->dcerpchdr.pfc_flags & PFC_FIRST_FRAG &&
!dcerpc->pdu_fragged) {
*stub_data_buffer_len = 0; *stub_data_buffer_len = 0;
} }
@ -1095,6 +1098,7 @@ int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
hdrretval = DCERPCParseHeader(dcerpc, input + parsed, input_len); hdrretval = DCERPCParseHeader(dcerpc, input + parsed, input_len);
if (hdrretval == -1) { if (hdrretval == -1) {
dcerpc->bytesprocessed = 0; dcerpc->bytesprocessed = 0;
dcerpc->pdu_fragged = 0;
SCReturnInt(0); SCReturnInt(0);
} else { } else {
parsed += hdrretval; parsed += hdrretval;
@ -1163,6 +1167,9 @@ int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) { if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) {
dcerpc->bytesprocessed = 0; dcerpc->bytesprocessed = 0;
dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0; dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0;
dcerpc->pdu_fragged = 0;
} else {
dcerpc->pdu_fragged = 1;
} }
break; break;
@ -1271,6 +1278,7 @@ int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) { if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) {
dcerpc->bytesprocessed = 0; dcerpc->bytesprocessed = 0;
dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0; dcerpc->dcerpcbindbindack.ctxbytesprocessed = 0;
dcerpc->pdu_fragged = 0;
/* response and request done */ /* response and request done */
if (dcerpc->dcerpchdr.type == BIND_ACK) { if (dcerpc->dcerpchdr.type == BIND_ACK) {
@ -1279,6 +1287,8 @@ int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCLogDebug("transaction_id updated to %"PRIu16, SCLogDebug("transaction_id updated to %"PRIu16,
dcerpc->transaction_id); dcerpc->transaction_id);
} }
} else {
dcerpc->pdu_fragged = 1;
} }
break; break;
@ -1326,6 +1336,9 @@ int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) { if (dcerpc->bytesprocessed == dcerpc->dcerpchdr.frag_length) {
dcerpc->bytesprocessed = 0; dcerpc->bytesprocessed = 0;
dcerpc->pdu_fragged = 0;
} else {
dcerpc->pdu_fragged = 1;
} }
/* response and request done */ /* response and request done */
@ -1340,6 +1353,7 @@ int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
default: default:
SCLogDebug("DCERPC Type 0x%02x not implemented yet", dcerpc->dcerpchdr.type); SCLogDebug("DCERPC Type 0x%02x not implemented yet", dcerpc->dcerpchdr.type);
dcerpc->bytesprocessed = 0; dcerpc->bytesprocessed = 0;
dcerpc->pdu_fragged = 0;
break; break;
} }
} }
@ -3768,6 +3782,76 @@ end:
return result; return result;
} }
/**
* \test DCERPC fragmented bind PDU(one PDU which is frag'ed).
*/
int DCERPCParserTest06(void) {
int result = 1;
Flow f;
int r = 0;
uint8_t request1[] = {
0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
0x2C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C
};
uint32_t request1_len = sizeof(request1);
uint8_t request2[] = {
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14
};
uint32_t request2_len = sizeof(request2);
TcpSession ssn;
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
StreamTcpInitConfig(TRUE);
FlowL7DataPtrInit(&f);
r = AppLayerParse(&f, ALPROTO_DCERPC, STREAM_TOSERVER|STREAM_START,
request1, request1_len);
if (r != 0) {
printf("dcerpc header check returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
DCERPCState *dcerpc_state = f.aldata[AlpGetStateIdx(ALPROTO_DCERPC)];
if (dcerpc_state == NULL) {
printf("no dcerpc state: ");
result = 0;
goto end;
}
result &= (dcerpc_state->dcerpc.bytesprocessed == 36);
result &= (dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer != NULL &&
dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer_len == 12);
r = AppLayerParse(&f, ALPROTO_DCERPC, STREAM_TOSERVER,
request2, request2_len);
if (r != 0) {
printf("dcerpc header check returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
result &= (dcerpc_state->dcerpc.bytesprocessed == 0);
result &= (dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer != NULL &&
dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer_len == 20);
end:
FlowL7DataPtrFree(&f);
StreamTcpFreeConfig(TRUE);
FLOW_DESTROY(&f);
return result;
}
void DCERPCParserRegisterTests(void) { void DCERPCParserRegisterTests(void) {
printf("DCERPCParserRegisterTests\n"); printf("DCERPCParserRegisterTests\n");
UtRegisterTest("DCERPCParserTest01", DCERPCParserTest01, 1); UtRegisterTest("DCERPCParserTest01", DCERPCParserTest01, 1);
@ -3775,6 +3859,7 @@ void DCERPCParserRegisterTests(void) {
UtRegisterTest("DCERPCParserTest03", DCERPCParserTest03, 1); UtRegisterTest("DCERPCParserTest03", DCERPCParserTest03, 1);
UtRegisterTest("DCERPCParserTest04", DCERPCParserTest04, 1); UtRegisterTest("DCERPCParserTest04", DCERPCParserTest04, 1);
UtRegisterTest("DCERPCParserTest05", DCERPCParserTest05, 1); UtRegisterTest("DCERPCParserTest05", DCERPCParserTest05, 1);
UtRegisterTest("DCERPCParserTest06", DCERPCParserTest06, 1);
} }
#endif #endif

Loading…
Cancel
Save