app layer error handling

remotes/origin/master-1.0.x
Gurvinder Singh 16 years ago committed by Victor Julien
parent 43fb771268
commit c1e485cc44

@ -130,9 +130,6 @@
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME #undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */ /* Define to the version of this package. */
#undef PACKAGE_VERSION #undef PACKAGE_VERSION

@ -12,6 +12,7 @@
#include "util-print.h" #include "util-print.h"
#include "util-pool.h" #include "util-pool.h"
#include "util-debug.h"
#include "stream-tcp-private.h" #include "stream-tcp-private.h"
#include "stream-tcp-reassemble.h" #include "stream-tcp-reassemble.h"
@ -80,6 +81,8 @@ static int DCERPCParseBINDACK(void *dcerpc_state, AppLayerParserState *pstate, u
#endif #endif
static int DCERPCParseHeader(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { static int DCERPCParseHeader(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
SCEnter();
DCERPCState *sstate = (DCERPCState *)dcerpc_state; DCERPCState *sstate = (DCERPCState *)dcerpc_state;
uint8_t *p = input; uint8_t *p = input;
//hexdump(p, input_len); //hexdump(p, input_len);
@ -87,8 +90,8 @@ static int DCERPCParseHeader(void *dcerpc_state, AppLayerParserState *pstate, ui
switch (sstate->bytesprocessed) { switch (sstate->bytesprocessed) {
case 0: case 0:
if (input_len >= DCERPC_HDR_LEN) { if (input_len >= DCERPC_HDR_LEN) {
//if (*p != 5) return 1; //if (*p != 5) SCReturnInt(1);
//if (!(*(p + 1 ) == 0 || (*(p + 1) == 1))) return 2; //if (!(*(p + 1 ) == 0 || (*(p + 1) == 1))) SCReturnInt(2);
sstate->dcerpc.rpc_vers = *p; sstate->dcerpc.rpc_vers = *p;
sstate->dcerpc.rpc_vers_minor = *(p + 1); sstate->dcerpc.rpc_vers_minor = *(p + 1);
sstate->dcerpc.type = *(p + 2); sstate->dcerpc.type = *(p + 2);
@ -106,17 +109,17 @@ static int DCERPCParseHeader(void *dcerpc_state, AppLayerParserState *pstate, ui
sstate->dcerpc.call_id |= *(p + 14) << 8; sstate->dcerpc.call_id |= *(p + 14) << 8;
sstate->dcerpc.call_id |= *(p + 15); sstate->dcerpc.call_id |= *(p + 15);
sstate->bytesprocessed = 16; sstate->bytesprocessed = 16;
return 1; SCReturnInt(1);
break; break;
} else { } else {
sstate->dcerpc.rpc_vers = *(p++); sstate->dcerpc.rpc_vers = *(p++);
// if (sstate->dcerpc.rpc_vers != 5) return 2; // if (sstate->dcerpc.rpc_vers != 5) SCReturnInt(2);
if (!(--input_len)) break; if (!(--input_len)) break;
} }
case 1: case 1:
sstate->dcerpc.rpc_vers_minor = *(p++); sstate->dcerpc.rpc_vers_minor = *(p++);
if ((sstate->dcerpc.rpc_vers_minor != 0) || if ((sstate->dcerpc.rpc_vers_minor != 0) ||
(sstate->dcerpc.rpc_vers_minor != 1)) return 3; (sstate->dcerpc.rpc_vers_minor != 1)) SCReturnInt(3);
if (!(--input_len)) break; if (!(--input_len)) break;
case 2: case 2:
sstate->dcerpc.type = *(p++); sstate->dcerpc.type = *(p++);
@ -162,22 +165,23 @@ static int DCERPCParseHeader(void *dcerpc_state, AppLayerParserState *pstate, ui
--input_len; --input_len;
break; break;
default: // SHOULD NEVER OCCUR default: // SHOULD NEVER OCCUR
printf("Odd\n"); SCLogDebug("Odd");
return 8; SCReturnInt(8);
} }
} }
sstate->bytesprocessed += (p - input); sstate->bytesprocessed += (p - input);
return 0; SCReturnInt(0);
} }
static int DCERPCParse(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { static int DCERPCParse(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
SCEnter();
// DCERPCState *sstate = (DCERPCState *)dcerpc_state; // DCERPCState *sstate = (DCERPCState *)dcerpc_state;
uint16_t max_fields = 3; uint16_t max_fields = 3;
uint16_t u = 0; uint16_t u = 0;
uint32_t offset = 0; uint32_t offset = 0;
if (pstate == NULL) if (pstate == NULL)
return -1; SCReturnInt(-1);
for (u = pstate->parse_field; u < max_fields; u++) { for (u = pstate->parse_field; u < max_fields; u++) {
printf("DCERPCParse: u %" PRIu32 "\n", u); printf("DCERPCParse: u %" PRIu32 "\n", u);
@ -188,7 +192,11 @@ static int DCERPCParse(void *dcerpc_state, AppLayerParserState *pstate, uint8_t
if (r == 0) { if (r == 0) {
pstate->parse_field = 0; pstate->parse_field = 0;
return 0; SCReturnInt(0);
} else if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, "
"r %d", r);
SCReturnInt(-1);
} }
break; break;
} }
@ -200,7 +208,7 @@ static int DCERPCParse(void *dcerpc_state, AppLayerParserState *pstate, uint8_t
pstate->parse_field = 0; pstate->parse_field = 0;
pstate->flags |= APP_LAYER_PARSER_DONE; pstate->flags |= APP_LAYER_PARSER_DONE;
return 1; SCReturnInt(1);
} }

@ -301,8 +301,11 @@ end:
return proto; return proto;
} }
int AppLayerHandleMsg(StreamMsg *smsg, char need_lock) { int AppLayerHandleMsg(StreamMsg *smsg, char need_lock)
{
SCEnter();
uint16_t alproto = ALPROTO_UNKNOWN; uint16_t alproto = ALPROTO_UNKNOWN;
int r = 0;
if (need_lock == TRUE) mutex_lock(&smsg->flow->m); if (need_lock == TRUE) mutex_lock(&smsg->flow->m);
TcpSession *ssn = smsg->flow->protoctx; TcpSession *ssn = smsg->flow->protoctx;
@ -313,13 +316,15 @@ int AppLayerHandleMsg(StreamMsg *smsg, char need_lock) {
if (ssn != NULL) { if (ssn != NULL) {
if (smsg->flags & STREAM_START) { if (smsg->flags & STREAM_START) {
//printf("L7AppDetectThread: stream initializer (len %" PRIu32 " (%" PRIu32 "))\n", smsg->data.data_len, MSG_DATA_SIZE); SCLogDebug("Stream initializer (len %" PRIu32 " (%" PRIu32 "))",
smsg->data.data_len, MSG_DATA_SIZE);
//printf("=> Init Stream Data -- start\n"); //printf("=> Init Stream Data -- start\n");
//PrintRawDataFp(stdout, smsg->init.data, smsg->init.data_len); //PrintRawDataFp(stdout, smsg->init.data, smsg->init.data_len);
//printf("=> Init Stream Data -- end\n"); //printf("=> Init Stream Data -- end\n");
alproto = AppLayerDetectGetProto(&alp_proto_ctx, &alp_proto_tctx, smsg->data.data, smsg->data.data_len, smsg->flags); alproto = AppLayerDetectGetProto(&alp_proto_ctx, &alp_proto_tctx,
smsg->data.data, smsg->data.data_len, smsg->flags);
if (alproto != ALPROTO_UNKNOWN) { if (alproto != ALPROTO_UNKNOWN) {
/* store the proto and setup the L7 data array */ /* store the proto and setup the L7 data array */
if (need_lock == TRUE) mutex_lock(&smsg->flow->m); if (need_lock == TRUE) mutex_lock(&smsg->flow->m);
@ -327,10 +332,12 @@ int AppLayerHandleMsg(StreamMsg *smsg, char need_lock) {
ssn->alproto = alproto; ssn->alproto = alproto;
if (need_lock == TRUE) mutex_unlock(&smsg->flow->m); if (need_lock == TRUE) mutex_unlock(&smsg->flow->m);
AppLayerParse(smsg->flow, alproto, smsg->flags, smsg->data.data, smsg->data.data_len, need_lock); r = AppLayerParse(smsg->flow, alproto, smsg->flags,
smsg->data.data, smsg->data.data_len, need_lock);
} }
} else { } else {
//printf("AppLayerDetectThread: stream data (len %" PRIu32 " (%" PRIu32 ")), alproto %"PRIu16"\n", smsg->data.data_len, MSG_DATA_SIZE, alproto); SCLogDebug("stream data (len %" PRIu32 " (%" PRIu32 ")), alproto "
"%"PRIu16"", smsg->data.data_len, MSG_DATA_SIZE, alproto);
//printf("=> Stream Data -- start\n"); //printf("=> Stream Data -- start\n");
//PrintRawDataFp(stdout, smsg->data.data, smsg->data.data_len); //PrintRawDataFp(stdout, smsg->data.data, smsg->data.data_len);
@ -339,9 +346,10 @@ int AppLayerHandleMsg(StreamMsg *smsg, char need_lock) {
/* if we don't have a data object here we are not getting it /* if we don't have a data object here we are not getting it
* a start msg should have gotten us one */ * a start msg should have gotten us one */
if (alproto != ALPROTO_UNKNOWN) { if (alproto != ALPROTO_UNKNOWN) {
AppLayerParse(smsg->flow, alproto, smsg->flags, smsg->data.data, smsg->data.data_len, need_lock); r = AppLayerParse(smsg->flow, alproto, smsg->flags,
smsg->data.data, smsg->data.data_len, need_lock);
} else { } else {
//printf("AppLayerDetectThread: smsg not start, but no l7 data? Weird\n"); SCLogDebug(" smsg not start, but no l7 data? Weird");
} }
} }
} }
@ -353,7 +361,7 @@ int AppLayerHandleMsg(StreamMsg *smsg, char need_lock) {
/* return the used message to the queue */ /* return the used message to the queue */
StreamMsgReturnToPool(smsg); StreamMsgReturnToPool(smsg);
return 0; SCReturnInt(r);
} }
void *AppLayerDetectProtoThread(void *td) void *AppLayerDetectProtoThread(void *td)

@ -2,6 +2,7 @@
#include "eidps-common.h" #include "eidps-common.h"
#include "debug.h" #include "debug.h"
#include "util-unittest.h"
#include "decode.h" #include "decode.h"
#include "threads.h" #include "threads.h"
@ -22,8 +23,10 @@
static Pool *al_result_pool = NULL; static Pool *al_result_pool = NULL;
/** \brief Alloc a AppLayerParserResultElmt func for the pool */ /** \brief Alloc a AppLayerParserResultElmt func for the pool */
static void *AlpResultElmtPoolAlloc(void *null) { static void *AlpResultElmtPoolAlloc(void *null)
AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)malloc(sizeof(AppLayerParserResultElmt)); {
AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)malloc
(sizeof(AppLayerParserResultElmt));
if (e == NULL) { if (e == NULL) {
return NULL; return NULL;
} }
@ -32,7 +35,8 @@ static void *AlpResultElmtPoolAlloc(void *null) {
return e; return e;
} }
static void AlpResultElmtPoolFree(void *e) { static void AlpResultElmtPoolFree(void *e)
{
AppLayerParserResultElmt *re = (AppLayerParserResultElmt *)e; AppLayerParserResultElmt *re = (AppLayerParserResultElmt *)e;
if (re->flags & ALP_RESULT_ELMT_ALLOC) { if (re->flags & ALP_RESULT_ELMT_ALLOC) {
@ -42,7 +46,8 @@ static void AlpResultElmtPoolFree(void *e) {
free(re); free(re);
} }
static AppLayerParserResultElmt *AlpGetResultElmt(void) { static AppLayerParserResultElmt *AlpGetResultElmt(void)
{
AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)PoolGet(al_result_pool); AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)PoolGet(al_result_pool);
if (e == NULL) { if (e == NULL) {
return NULL; return NULL;
@ -51,7 +56,8 @@ static AppLayerParserResultElmt *AlpGetResultElmt(void) {
return e; return e;
} }
static void AlpReturnResultElmt(AppLayerParserResultElmt *e) { static void AlpReturnResultElmt(AppLayerParserResultElmt *e)
{
if (e->flags & ALP_RESULT_ELMT_ALLOC) { if (e->flags & ALP_RESULT_ELMT_ALLOC) {
if (e->data_ptr != NULL) if (e->data_ptr != NULL)
free(e->data_ptr); free(e->data_ptr);
@ -64,7 +70,8 @@ static void AlpReturnResultElmt(AppLayerParserResultElmt *e) {
PoolReturn(al_result_pool, (void *)e); PoolReturn(al_result_pool, (void *)e);
} }
static void AlpAppendResultElmt(AppLayerParserResult *r, AppLayerParserResultElmt *e) { static void AlpAppendResultElmt(AppLayerParserResult *r, AppLayerParserResultElmt *e)
{
if (r->head == NULL) { if (r->head == NULL) {
r->head = e; r->head = e;
r->tail = e; r->tail = e;
@ -81,7 +88,9 @@ static void AlpAppendResultElmt(AppLayerParserResult *r, AppLayerParserResultElm
* \retval -1 error * \retval -1 error
* \retval 0 ok * \retval 0 ok
*/ */
static int AlpStoreField(AppLayerParserResult *output, uint16_t idx, uint8_t *ptr, uint32_t len, uint8_t alloc) { static int AlpStoreField(AppLayerParserResult *output, uint16_t idx,
uint8_t *ptr, uint32_t len, uint8_t alloc)
{
SCEnter(); SCEnter();
AppLayerParserResultElmt *e = AlpGetResultElmt(); AppLayerParserResultElmt *e = AlpGetResultElmt();
@ -105,7 +114,10 @@ static int AlpStoreField(AppLayerParserResult *output, uint16_t idx, uint8_t *pt
* \retval 0 Field parsing in progress. * \retval 0 Field parsing in progress.
* \retval -1 error * \retval -1 error
*/ */
int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstate, uint16_t field_idx, uint32_t size, uint8_t *input, uint32_t input_len, uint32_t *offset) { int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstate,
uint16_t field_idx, uint32_t size, uint8_t *input,
uint32_t input_len, uint32_t *offset)
{
SCEnter(); SCEnter();
if ((pstate->store_len + input_len) < size) { if ((pstate->store_len + input_len) < size) {
@ -146,7 +158,8 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
memcpy(pstate->store+pstate->store_len, input, diff); memcpy(pstate->store+pstate->store_len, input, diff);
pstate->store_len += diff; pstate->store_len += diff;
int r = AlpStoreField(output, field_idx, pstate->store, pstate->store_len, /* alloc mem */1); int r = AlpStoreField(output, field_idx, pstate->store,
pstate->store_len, /* alloc mem */1);
if (r == -1) { if (r == -1) {
SCReturnInt(-1); SCReturnInt(-1);
} }
@ -169,7 +182,9 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
* \retval 0 Field parsing in progress. * \retval 0 Field parsing in progress.
* \retval -1 error * \retval -1 error
*/ */
int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate, uint16_t field_idx, uint8_t *input, uint32_t input_len) { int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate,
uint16_t field_idx, uint8_t *input, uint32_t input_len)
{
SCEnter(); SCEnter();
if (pstate->store_len == 0) { if (pstate->store_len == 0) {
@ -239,15 +254,19 @@ int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate
* \retval 0 Field parsing in progress. * \retval 0 Field parsing in progress.
* \retval -1 error * \retval -1 error
*/ */
int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *pstate, uint16_t field_idx, const uint8_t *delim, uint8_t delim_len, uint8_t *input, uint32_t input_len, uint32_t *offset) { int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *pstate,
uint16_t field_idx, const uint8_t *delim, uint8_t delim_len,
uint8_t *input, uint32_t input_len, uint32_t *offset)
{
SCEnter(); SCEnter();
SCLogDebug("pstate->store_len %" PRIu32 ", delim_len %" PRIu32 "", pstate->store_len, delim_len); SCLogDebug("pstate->store_len %" PRIu32 ", delim_len %" PRIu32 "",
pstate->store_len, delim_len);
if (pstate->store_len == 0) { if (pstate->store_len == 0) {
uint8_t *ptr = BinSearch(input, input_len, delim, delim_len); uint8_t *ptr = BinSearch(input, input_len, delim, delim_len);
if (ptr != NULL) { if (ptr != NULL) {
uint32_t len = ptr - input; uint32_t len = ptr - input;
//printf("ParseFieldByDelimiter: len %" PRIu32 "\n", len); SCLogDebug(" len %" PRIu32 "", len);
int r = AlpStoreField(output, field_idx, input, len, 0); int r = AlpStoreField(output, field_idx, input, len, 0);
if (r == -1) { if (r == -1) {
@ -257,11 +276,11 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
SCReturnInt(1); SCReturnInt(1);
} else { } else {
if (pstate->flags & APP_LAYER_PARSER_EOF) { if (pstate->flags & APP_LAYER_PARSER_EOF) {
//printf("ParseFieldByDelimiter: delim not found and EOF\n"); SCLogDebug("delim not found and EOF");
SCReturnInt(0); SCReturnInt(0);
} }
//printf("ParseFieldByDelimiter: delim not found, continue\n"); SCLogDebug("delim not found, continue");
/* delimiter field not found, so store the result for the next run */ /* delimiter field not found, so store the result for the next run */
pstate->store = malloc(input_len); pstate->store = malloc(input_len);
@ -276,7 +295,8 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
uint8_t *ptr = BinSearch(input, input_len, delim, delim_len); uint8_t *ptr = BinSearch(input, input_len, delim, delim_len);
if (ptr != NULL) { if (ptr != NULL) {
uint32_t len = ptr - input; uint32_t len = ptr - input;
//printf("ParseFieldByDelimiter: len %" PRIu32 " + %" PRIu32 " = %" PRIu32 "\n", len, pstate->store_len, len + pstate->store_len); SCLogDebug("len %" PRIu32 " + %" PRIu32 " = %" PRIu32 "", len,
pstate->store_len, len + pstate->store_len);
pstate->store = realloc(pstate->store, (len + pstate->store_len)); pstate->store = realloc(pstate->store, (len + pstate->store_len));
if (pstate->store == NULL) { if (pstate->store == NULL) {
@ -286,7 +306,8 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
memcpy(pstate->store+pstate->store_len, input, len); memcpy(pstate->store+pstate->store_len, input, len);
pstate->store_len += len; pstate->store_len += len;
int r = AlpStoreField(output, field_idx, pstate->store, pstate->store_len, 1); int r = AlpStoreField(output, field_idx, pstate->store,
pstate->store_len, 1);
if (r == -1) { if (r == -1) {
SCReturnInt(-1); SCReturnInt(-1);
} }
@ -300,23 +321,27 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
/* if the input len is smaller than the delim len we search the /* if the input len is smaller than the delim len we search the
* pstate->store since we may match there. */ * pstate->store since we may match there. */
if (delim_len > input_len) { if (delim_len > input_len) {
/* delimiter field not found, so store the result for the next run */ /* delimiter field not found, so store the result for the
pstate->store = realloc(pstate->store, (input_len + pstate->store_len)); * next run */
pstate->store = realloc(pstate->store, (input_len +
pstate->store_len));
if (pstate->store == NULL) { if (pstate->store == NULL) {
SCReturnInt(-1); SCReturnInt(-1);
} }
memcpy(pstate->store+pstate->store_len, input, input_len); memcpy(pstate->store+pstate->store_len, input, input_len);
pstate->store_len += input_len; pstate->store_len += input_len;
//printf("ParseFieldByDelimiter: input_len < delim_len, checking pstate->store\n"); SCLogDebug("input_len < delim_len, checking pstate->store");
if (pstate->store_len >= delim_len) { if (pstate->store_len >= delim_len) {
ptr = BinSearch(pstate->store, pstate->store_len, delim, delim_len); ptr = BinSearch(pstate->store, pstate->store_len, delim,
delim_len);
if (ptr != NULL) { if (ptr != NULL) {
//printf("ParseFieldByDelimiter: now we found the delim\n"); SCLogDebug("now we found the delim");
uint32_t len = ptr - pstate->store; uint32_t len = ptr - pstate->store;
int r = AlpStoreField(output, field_idx, pstate->store, len, 1); int r = AlpStoreField(output, field_idx,
pstate->store, len, 1);
if (r == -1) { if (r == -1) {
SCReturnInt(-1); SCReturnInt(-1);
} }
@ -326,7 +351,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
(*offset) += (input_len); (*offset) += (input_len);
//printf("ParseFieldByDelimiter: offset %" PRIu32 "\n", (*offset)); SCLogDebug("offset %" PRIu32 "", (*offset));
SCReturnInt(1); SCReturnInt(1);
} }
goto free_and_return; goto free_and_return;
@ -334,7 +359,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
goto free_and_return; goto free_and_return;
} }
free_and_return: free_and_return:
//printf("ParseFieldByDelimiter: not found and EOF, so free what we have so far.\n"); SCLogDebug("not found and EOF, so free what we have so far.");
free(pstate->store); free(pstate->store);
pstate->store = NULL; pstate->store = NULL;
pstate->store_len = 0; pstate->store_len = 0;
@ -353,11 +378,11 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
/* if the input len is smaller than the delim len we search the /* if the input len is smaller than the delim len we search the
* pstate->store since we may match there. */ * pstate->store since we may match there. */
if (delim_len > input_len && delim_len <= pstate->store_len) { if (delim_len > input_len && delim_len <= pstate->store_len) {
//printf("ParseFieldByDelimiter: input_len < delim_len, checking pstate->store\n"); SCLogDebug("input_len < delim_len, checking pstate->store");
ptr = BinSearch(pstate->store, pstate->store_len, delim, delim_len); ptr = BinSearch(pstate->store, pstate->store_len, delim, delim_len);
if (ptr != NULL) { if (ptr != NULL) {
//printf("ParseFieldByDelimiter: now we found the delim\n"); SCLogDebug("now we found the delim");
uint32_t len = ptr - pstate->store; uint32_t len = ptr - pstate->store;
int r = AlpStoreField(output, field_idx, pstate->store, len, 1); int r = AlpStoreField(output, field_idx, pstate->store, len, 1);
@ -369,7 +394,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
(*offset) += (input_len); (*offset) += (input_len);
//printf("ParseFieldByDelimiter: offset %" PRIu32 "\n", (*offset)); SCLogDebug("ffset %" PRIu32 "", (*offset));
SCReturnInt(1); SCReturnInt(1);
} }
} }
@ -391,11 +416,13 @@ static uint16_t al_max_parsers = 0; /* incremented for every registered parser *
* *
* \retval Parser subsys id * \retval Parser subsys id
*/ */
uint16_t AppLayerParserGetStorageId(void) { uint16_t AppLayerParserGetStorageId(void)
{
return app_layer_sid; return app_layer_sid;
} }
uint16_t AppLayerGetProtoByName(const char *name) { uint16_t AppLayerGetProtoByName(const char *name)
{
uint8_t u = 1; uint8_t u = 1;
SCLogDebug("looking for name %s", name); SCLogDebug("looking for name %s", name);
@ -418,14 +445,20 @@ uint16_t AppLayerGetProtoByName(const char *name) {
/** \brief Description: register a parser. /** \brief Description: register a parser.
* *
* \param name full parser name, e.g. "http.request_line" * \param name full parser name, e.g. "http.request_line"
* \todo do we need recursive, so a "http" and a "request_line" where the engine knows it's actually "http.request_line"... same difference maybe. * \todo do we need recursive, so a "http" and a "request_line" where the engine
* knows it's actually "http.request_line"... same difference maybe.
* \param AppLayerParser pointer to the parser function * \param AppLayerParser pointer to the parser function
* \param max_outputs max number of unique outputs the parser can generate * \param max_outputs max number of unique outputs the parser can generate
* *
* \retval 0 on success * \retval 0 on success
* \retval -1 on error * \retval -1 on error
*/ */
int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id, int (*AppLayerParser)(void *protocol_state, AppLayerParserState *parser_state, uint8_t *input, uint32_t input_len, AppLayerParserResult *output), char *dependency) { int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id,
int (*AppLayerParser)(void *protocol_state,
AppLayerParserState *parser_state, uint8_t *input,
uint32_t input_len, AppLayerParserResult *output),
char *dependency)
{
al_max_parsers++; al_max_parsers++;
@ -439,21 +472,28 @@ int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id, int (
al_parser_table[al_max_parsers].parser_local_id = parser_id; al_parser_table[al_max_parsers].parser_local_id = parser_id;
al_parser_table[al_max_parsers].AppLayerParser = AppLayerParser; al_parser_table[al_max_parsers].AppLayerParser = AppLayerParser;
SCLogDebug("registered %p at proto %" PRIu32 ", al_proto_table idx %" PRIu32 ", storage_id %" PRIu32 ", parser_local_id %" PRIu32 "", SCLogDebug("registered %p at proto %" PRIu32 ", al_proto_table idx "
AppLayerParser, proto, al_max_parsers, al_proto_table[proto].storage_id, parser_id); "%" PRIu32 ", storage_id %" PRIu32 ", parser_local_id %" PRIu32 "",
AppLayerParser, proto, al_max_parsers,
al_proto_table[proto].storage_id, parser_id);
return 0; return 0;
} }
/** \brief Description: register a protocol parser. /** \brief Description: register a protocol parser.
* *
* \param name full parser name, e.g. "http.request_line" * \param name full parser name, e.g. "http.request_line"
* \todo do we need recursive, so a "http" and a "request_line" where the engine knows it's actually "http.request_line"... same difference maybe. * \todo do we need recursive, so a "http" and a "request_line" where the engine
* knows it's actually "http.request_line"... same difference maybe.
* \param AppLayerParser pointer to the parser function * \param AppLayerParser pointer to the parser function
* *
* \retval 0 on success * \retval 0 on success
* \retval -1 on error * \retval -1 on error
*/ */
int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags, int (*AppLayerParser)(void *protocol_state, AppLayerParserState *parser_state, uint8_t *input, uint32_t input_len, AppLayerParserResult *output)) { int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags,
int (*AppLayerParser)(void *protocol_state,
AppLayerParserState *parser_state, uint8_t *input,
uint32_t input_len, AppLayerParserResult *output))
{
al_max_parsers++; al_max_parsers++;
@ -478,22 +518,28 @@ int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags, int (*AppLay
al_proto_table[proto].storage_id = StreamL7RegisterModule(); al_proto_table[proto].storage_id = StreamL7RegisterModule();
} }
SCLogDebug("registered %p at proto %" PRIu32 " flags %02X, al_proto_table idx %" PRIu32 ", storage_id %" PRIu32 "", SCLogDebug("registered %p at proto %" PRIu32 " flags %02X, al_proto_table "
AppLayerParser, proto, flags, al_max_parsers, al_proto_table[proto].storage_id); "idx %" PRIu32 ", storage_id %" PRIu32 " %s \n", AppLayerParser, proto,
flags, al_max_parsers, al_proto_table[proto].storage_id, name);
return 0; return 0;
} }
void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void), void (*StateFree)(void *)) { void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void),
void (*StateFree)(void *))
{
al_proto_table[proto].StateAlloc = StateAlloc; al_proto_table[proto].StateAlloc = StateAlloc;
al_proto_table[proto].StateFree = StateFree; al_proto_table[proto].StateFree = StateFree;
} }
uint16_t AlpGetStateIdx(uint16_t proto) { uint16_t AlpGetStateIdx(uint16_t proto)
{
return al_proto_table[proto].storage_id; return al_proto_table[proto].storage_id;
} }
AppLayerParserStateStore *AppLayerParserStateStoreAlloc(void) { AppLayerParserStateStore *AppLayerParserStateStoreAlloc(void)
AppLayerParserStateStore *s = (AppLayerParserStateStore *)malloc(sizeof(AppLayerParserStateStore)); {
AppLayerParserStateStore *s = (AppLayerParserStateStore *)malloc
(sizeof(AppLayerParserStateStore));
if (s == NULL) if (s == NULL)
return NULL; return NULL;
@ -503,7 +549,8 @@ AppLayerParserStateStore *AppLayerParserStateStoreAlloc(void) {
/** \brief free a AppLayerParserStateStore structure /** \brief free a AppLayerParserStateStore structure
* \param s AppLayerParserStateStore structure to free */ * \param s AppLayerParserStateStore structure to free */
void AppLayerParserStateStoreFree(AppLayerParserStateStore *s) { void AppLayerParserStateStoreFree(AppLayerParserStateStore *s)
{
if (s->to_server.store != NULL) if (s->to_server.store != NULL)
free(s->to_server.store); free(s->to_server.store);
if (s->to_client.store != NULL) if (s->to_client.store != NULL)
@ -512,7 +559,8 @@ void AppLayerParserStateStoreFree(AppLayerParserStateStore *s) {
free(s); free(s);
} }
static void AppLayerParserResultCleanup(AppLayerParserResult *result) { static void AppLayerParserResultCleanup(AppLayerParserResult *result)
{
AppLayerParserResultElmt *e = result->head; AppLayerParserResultElmt *e = result->head;
while (e != NULL) { while (e != NULL) {
AppLayerParserResultElmt *next_e = e->next; AppLayerParserResultElmt *next_e = e->next;
@ -527,27 +575,42 @@ static void AppLayerParserResultCleanup(AppLayerParserResult *result) {
} }
} }
static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_state, uint8_t *input, uint32_t input_len, uint16_t parser_idx, uint16_t proto) { static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_state,
uint8_t *input, uint32_t input_len, uint16_t parser_idx,
uint16_t proto)
{
SCEnter();
int retval = 0; int retval = 0;
AppLayerParserResult result = { NULL, NULL, 0 }; AppLayerParserResult result = { NULL, NULL, 0 };
//printf("AppLayerDoParse: parser_idx %" PRIu32 "\n", parser_idx); SCLogDebug("parser_idx %" PRIu32 "", parser_idx);
//PrintRawDataFp(stdout, input,input_len); //PrintRawDataFp(stdout, input,input_len);
/* invoke the parser */ /* invoke the parser */
int r = al_parser_table[parser_idx].AppLayerParser(app_layer_state, parser_state, input, input_len, &result); int r = al_parser_table[parser_idx].AppLayerParser(app_layer_state,
if (r < 0) parser_state, input, input_len, &result);
return -1; if (r < 0) {
if (r == -1) {
AppLayerParserResultCleanup(&result);
SCReturnInt(-1);
} else {
BUG_ON(r); /* this is not supposed to happen!! */
}
}
/* process the result elements */ /* process the result elements */
AppLayerParserResultElmt *e = result.head; AppLayerParserResultElmt *e = result.head;
for (; e != NULL; e = e->next) { for (; e != NULL; e = e->next) {
//printf("AppLayerParse: e %p e->name_idx %" PRIu32 ", e->data_ptr %p, e->data_len %" PRIu32 ", map_size %" PRIu32 "\n", SCLogDebug("e %p e->name_idx %" PRIu32 ", e->data_ptr %p, e->data_len "
// e, e->name_idx, e->data_ptr, e->data_len, al_proto_table[proto].map_size); "%" PRIu32 ", map_size %" PRIu32 "", e, e->name_idx,
e->data_ptr, e->data_len, al_proto_table[proto].map_size);
/* no parser defined for this field. */ /* no parser defined for this field. */
if (e->name_idx >= al_proto_table[proto].map_size || al_proto_table[proto].map[e->name_idx] == NULL) { if (e->name_idx >= al_proto_table[proto].map_size ||
//printf("AppLayerParse: no parser for proto %" PRIu32 ", parser_local_id %" PRIu32 "\n", proto, e->name_idx); al_proto_table[proto].map[e->name_idx] == NULL)
{
SCLogDebug("no parser for proto %" PRIu32 ", parser_local_id "
"%" PRIu32 "", proto, e->name_idx);
continue; continue;
} }
@ -558,7 +621,8 @@ static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_st
parser_state->parse_field = 0; parser_state->parse_field = 0;
parser_state->flags |= APP_LAYER_PARSER_EOF; parser_state->flags |= APP_LAYER_PARSER_EOF;
r = AppLayerDoParse(app_layer_state, parser_state, e->data_ptr, e->data_len, idx, proto); r = AppLayerDoParse(app_layer_state, parser_state, e->data_ptr,
e->data_len, idx, proto);
/* restore */ /* restore */
parser_state->flags &= ~APP_LAYER_PARSER_EOF; parser_state->flags &= ~APP_LAYER_PARSER_EOF;
@ -566,13 +630,17 @@ static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_st
/* bail out on a serious error */ /* bail out on a serious error */
if (r < 0) { if (r < 0) {
if (r == -1) {
retval = -1; retval = -1;
break; break;
} else {
BUG_ON(r);
}
} }
} }
AppLayerParserResultCleanup(&result); AppLayerParserResultCleanup(&result);
return retval; SCReturnInt(retval);
} }
/** /**
@ -588,7 +656,9 @@ static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_st
* \retval -1 error * \retval -1 error
* \retval 0 ok * \retval 0 ok
*/ */
int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_t input_len, char need_lock) { int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input,
uint32_t input_len, char need_lock)
{
SCEnter(); SCEnter();
uint16_t parser_idx = 0; uint16_t parser_idx = 0;
@ -596,12 +666,16 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
TcpSession *ssn = f->protoctx; TcpSession *ssn = f->protoctx;
if (ssn == NULL) { if (ssn == NULL) {
printf("AppLayerParse: no session\n"); SCLogDebug("no TCP session");
goto error; goto error;
} }
/* Get the parser state (if any) */ /* Get the parser state (if any) */
AppLayerParserStateStore *parser_state_store = (AppLayerParserStateStore *)ssn->aldata[app_layer_sid]; AppLayerParserStateStore *parser_state_store = NULL;
if (ssn->aldata != NULL) {
parser_state_store = (AppLayerParserStateStore *)
ssn->aldata[app_layer_sid];
if (parser_state_store == NULL) { if (parser_state_store == NULL) {
parser_state_store = AppLayerParserStateStoreAlloc(); parser_state_store = AppLayerParserStateStoreAlloc();
if (parser_state_store == NULL) if (parser_state_store == NULL)
@ -611,6 +685,10 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
ssn->aldata[app_layer_sid] = (void *)parser_state_store; ssn->aldata[app_layer_sid] = (void *)parser_state_store;
if (need_lock == TRUE) mutex_unlock(&f->m); if (need_lock == TRUE) mutex_unlock(&f->m);
} }
} else {
SCLogDebug("No App Layer Data");
goto error;
}
AppLayerParserState *parser_state = NULL; AppLayerParserState *parser_state = NULL;
if (flags & STREAM_TOSERVER) { if (flags & STREAM_TOSERVER) {
@ -620,7 +698,8 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
parser_state->cur_parser = parser_idx; parser_state->cur_parser = parser_idx;
parser_state->flags |= APP_LAYER_PARSER_USE; parser_state->flags |= APP_LAYER_PARSER_USE;
} else { } else {
//printf("AppLayerParse: using parser %" PRIu32 " we stored before (to_server)\n", parser_state->cur_parser); SCLogDebug("using parser %" PRIu32 " we stored before (to_server)",
parser_state->cur_parser);
parser_idx = parser_state->cur_parser; parser_idx = parser_state->cur_parser;
} }
} else { } else {
@ -630,13 +709,14 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
parser_state->cur_parser = parser_idx; parser_state->cur_parser = parser_idx;
parser_state->flags |= APP_LAYER_PARSER_USE; parser_state->flags |= APP_LAYER_PARSER_USE;
} else { } else {
//printf("AppLayerParse: using parser %" PRIu32 " we stored before (to_client)\n", parser_state->cur_parser); SCLogDebug("using parser %" PRIu32 " we stored before (to_client)",
parser_state->cur_parser);
parser_idx = parser_state->cur_parser; parser_idx = parser_state->cur_parser;
} }
} }
if (parser_idx == 0 || parser_state->flags & APP_LAYER_PARSER_DONE) { if (parser_idx == 0 || parser_state->flags & APP_LAYER_PARSER_DONE) {
//printf("AppLayerParse: no parser for protocol %" PRIu32 "\n", proto); SCLogDebug("no parser for protocol %" PRIu32 "", proto);
SCReturnInt(0); SCReturnInt(0);
} }
@ -660,7 +740,8 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
} }
/* invoke the recursive parser */ /* invoke the recursive parser */
int r = AppLayerDoParse(app_layer_state, parser_state, input, input_len, parser_idx, proto); int r = AppLayerDoParse(app_layer_state, parser_state, input, input_len,
parser_idx, proto);
if (r < 0) if (r < 0)
goto error; goto error;
@ -682,10 +763,44 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
SCReturnInt(0); SCReturnInt(0);
error: error:
if (ssn != NULL) {
char src[16];
char dst[16];
char dst6[46];
char src6[46];
/* Clear the app layer protocol state memory and the given function also
* cleans the parser state memory */
AppLayerParserCleanupState(ssn);
/* Set the no reassembly flag for both the stream in this TcpSession */
StreamTcpSetSessionNoReassemblyFlag(ssn, flags & STREAM_TOCLIENT ? 1 : 0);
StreamTcpSetSessionNoReassemblyFlag(ssn, flags & STREAM_TOSERVER ? 1 : 0);
if (f->src.family == AF_INET) {
inet_ntop(AF_INET, &f->src.addr_data32[0], src,
sizeof (src));
inet_ntop(AF_INET, &f->dst.addr_data32[0], dst,
sizeof (dst));
} else {
inet_ntop(AF_INET6, &f->src.addr_data32[0], src6,
sizeof (src6));
inet_ntop(AF_INET6, &f->dst.addr_data32[0], dst6,
sizeof (dst6));
}
SCLogError(SC_ALPARSER_ERR, "Error occured in parsing \"%s\" app layer "
"protocol, using network protocol %"PRIu8", source IP "
"address %s, destination IP address %s, src port %"PRIu16" and "
"dst port %"PRIu16"", al_proto_table[ssn->alproto].name,
f->proto, src, dst, ntohs(f->sp), ntohs(f->dp));
}
SCReturnInt(-1); SCReturnInt(-1);
} }
void RegisterAppLayerParsers(void) { void RegisterAppLayerParsers(void)
{
/** \todo move to general init function */ /** \todo move to general init function */
memset(&al_proto_table, 0, sizeof(al_proto_table)); memset(&al_proto_table, 0, sizeof(al_proto_table));
memset(&al_parser_table, 0, sizeof(al_parser_table)); memset(&al_parser_table, 0, sizeof(al_parser_table));
@ -697,22 +812,23 @@ void RegisterAppLayerParsers(void) {
al_result_pool = PoolInit(250,10,AlpResultElmtPoolAlloc,NULL,AlpResultElmtPoolFree); al_result_pool = PoolInit(250,10,AlpResultElmtPoolAlloc,NULL,AlpResultElmtPoolFree);
} }
void AppLayerParserCleanupState(TcpSession *ssn) { void AppLayerParserCleanupState(TcpSession *ssn)
{
if (ssn == NULL) { if (ssn == NULL) {
//printf("AppLayerParserCleanupState: no ssn\n"); SCLogDebug("no ssn");
return; return;
} }
AppLayerProto *p = &al_proto_table[ssn->alproto]; AppLayerProto *p = &al_proto_table[ssn->alproto];
if (p == NULL) { if (p == NULL) {
//printf("AppLayerParserCleanupState: no parser state for %"PRIu16"\n", ssn->alproto); SCLogDebug("no parser state for %"PRIu16"", ssn->alproto);
return; return;
} }
/* free the parser protocol state */ /* free the parser protocol state */
if (p->StateFree != NULL) { if (p->StateFree != NULL && ssn->aldata != NULL) {
if (ssn->aldata[p->storage_id] != NULL) { if (ssn->aldata[p->storage_id] != NULL) {
//printf("AppLayerParserCleanupState: calling StateFree\n"); SCLogDebug("calling StateFree");
p->StateFree(ssn->aldata[p->storage_id]); p->StateFree(ssn->aldata[p->storage_id]);
ssn->aldata[p->storage_id] = NULL; ssn->aldata[p->storage_id] = NULL;
} }
@ -720,7 +836,7 @@ void AppLayerParserCleanupState(TcpSession *ssn) {
if (ssn->aldata != NULL) { if (ssn->aldata != NULL) {
if (ssn->aldata[app_layer_sid] != NULL) { if (ssn->aldata[app_layer_sid] != NULL) {
//printf("AppLayerParserCleanupState: calling AppLayerParserStateStoreFree\n"); SCLogDebug("calling AppLayerParserStateStoreFree");
AppLayerParserStateStoreFree(ssn->aldata[app_layer_sid]); AppLayerParserStateStoreFree(ssn->aldata[app_layer_sid]);
ssn->aldata[app_layer_sid] = NULL; ssn->aldata[app_layer_sid] = NULL;
} }
@ -734,7 +850,8 @@ void AppLayerParserCleanupState(TcpSession *ssn) {
* and the global field parser id's. * and the global field parser id's.
* *
*/ */
void AppLayerParsersInitPostProcess(void) { void AppLayerParsersInitPostProcess(void)
{
uint16_t u16 = 0; uint16_t u16 = 0;
/* build local->global mapping */ /* build local->global mapping */
@ -743,10 +860,14 @@ void AppLayerParsersInitPostProcess(void) {
if (al_parser_table[u16].parser_local_id == 0) if (al_parser_table[u16].parser_local_id == 0)
continue; continue;
if (al_parser_table[u16].parser_local_id > al_proto_table[al_parser_table[u16].proto].map_size) if (al_parser_table[u16].parser_local_id >
al_proto_table[al_parser_table[u16].proto].map_size = al_parser_table[u16].parser_local_id; al_proto_table[al_parser_table[u16].proto].map_size)
{
//printf("AppLayerParsersInitPostProcess: map_size %" PRIu32 "\n", al_proto_table[al_parser_table[u16].proto].map_size); al_proto_table[al_parser_table[u16].proto].map_size =
al_parser_table[u16].parser_local_id;
}
SCLogDebug("map_size %" PRIu32 "", al_proto_table
[al_parser_table[u16].proto].map_size);
} }
/* for each proto, alloc the map array */ /* for each proto, alloc the map array */
@ -755,12 +876,15 @@ void AppLayerParsersInitPostProcess(void) {
continue; continue;
al_proto_table[u16].map_size++; al_proto_table[u16].map_size++;
al_proto_table[u16].map = (AppLayerLocalMap **)malloc(al_proto_table[u16].map_size * sizeof(AppLayerLocalMap *)); al_proto_table[u16].map = (AppLayerLocalMap **)malloc
(al_proto_table[u16].map_size *
sizeof(AppLayerLocalMap *));
if (al_proto_table[u16].map == NULL) { if (al_proto_table[u16].map == NULL) {
printf("XXX memory error\n"); SCLogError(SC_ERR_MEM_ALLOC, "memory error");
exit(1); exit(1);
} }
memset(al_proto_table[u16].map, 0, al_proto_table[u16].map_size * sizeof(AppLayerLocalMap *)); memset(al_proto_table[u16].map, 0, al_proto_table[u16].map_size *
sizeof(AppLayerLocalMap *));
uint16_t u = 0; uint16_t u = 0;
for (u = 1; u <= al_max_parsers; u++) { for (u = 1; u <= al_max_parsers; u++) {
@ -771,14 +895,13 @@ void AppLayerParsersInitPostProcess(void) {
if (al_parser_table[u].proto != u16) if (al_parser_table[u].proto != u16)
continue; continue;
//printf("AppLayerParsersInitPostProcess: al_proto_table[%" PRIu32 "].map_size %" PRIu32 ", %p %p\n", u16, al_proto_table[u16].map_size, al_proto_table[u16].map[x], al_proto_table[u16].map);
uint16_t parser_local_id = al_parser_table[u].parser_local_id; uint16_t parser_local_id = al_parser_table[u].parser_local_id;
//printf("AppLayerParsersInitPostProcess: parser_local_id: %" PRIu32 "\n", parser_local_id); SCLogDebug("parser_local_id: %" PRIu32 "", parser_local_id);
if (parser_local_id < al_proto_table[u16].map_size) { if (parser_local_id < al_proto_table[u16].map_size) {
al_proto_table[u16].map[parser_local_id] = malloc(sizeof(AppLayerLocalMap)); al_proto_table[u16].map[parser_local_id] = malloc(sizeof(AppLayerLocalMap));
if (al_proto_table[u16].map[parser_local_id] == NULL) { if (al_proto_table[u16].map[parser_local_id] == NULL) {
printf("XXX memory error\n"); SCLogError(SC_ERR_MEM_ALLOC, "XXX memory error");
exit(1); exit(1);
} }
@ -799,8 +922,121 @@ void AppLayerParsersInitPostProcess(void) {
if (al_proto_table[u16].map[x] == NULL) if (al_proto_table[u16].map[x] == NULL)
continue; continue;
//printf("AppLayerParsersInitPostProcess: al_proto_table[%" PRIu32 "].map[%" PRIu32 "]->parser_id: %" PRIu32 "\n", u16, x, al_proto_table[u16].map[x]->parser_id); SCLogDebug("al_proto_table[%" PRIu32 "].map[%" PRIu32 "]->parser_id:"
" %" PRIu32 "\n", u16, x, al_proto_table[u16].map[x]->parser_id);
} }
} }
} }
/* UNITTESTS*/
#ifdef UNITTESTS
typedef struct TestState_ {
uint8_t test;
}TestState;
/**
* \brief Test parser function to test the memory deallocation of app layer
* parser of occurence of an error.
*/
static int TestProtocolParser(void *test_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
{
return -1;
}
/** \brief Function to allocates the Test protocol state memory
*/
static void *TestProtocolStateAlloc(void)
{
void *s = malloc(sizeof(TestState));
if (s == NULL)
return NULL;
memset(s, 0, sizeof(TestState));
return s;
}
/** \brief Function to free the Test Protocol state memory
*/
static void TestProtocolStateFree(void *s)
{
free(s);
}
/** \test Test the deallocation of app layer parser memory on occurance of
* error in the parsing process.
*/
static int AppLayerParserTest01 (void)
{
int result = 1;
Flow f;
uint8_t testbuf[] = { 0x11 };
uint32_t testlen = sizeof(testbuf);
TcpSession ssn;
struct in_addr addr;
struct in_addr addr1;
Address src;
Address dst;
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
memset(&src, 0, sizeof(src));
memset(&dst, 0, sizeof(dst));
/* Register the Test protocol state and parser functions */
AppLayerRegisterProto("test", ALPROTO_TEST, STREAM_TOSERVER,
TestProtocolParser);
AppLayerRegisterStateFuncs(ALPROTO_TEST, TestProtocolStateAlloc,
TestProtocolStateFree);
ssn.alproto = ALPROTO_TEST;
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
inet_pton(AF_INET, "1.2.3.4", &addr.s_addr);
src.family = AF_INET;
src.addr_data32[0] = addr.s_addr;
inet_pton(AF_INET, "4.3.2.1", &addr1.s_addr);
dst.family = AF_INET;
dst.addr_data32[0] = addr1.s_addr;
f.src = src;
f.dst = dst;
f.sp = htons(20);
f.dp = htons(40);
f.proto = IPPROTO_TCP;
int r = AppLayerParse(&f, ALPROTO_TEST, STREAM_TOSERVER|STREAM_EOF, testbuf,
testlen, FALSE);
if (r != -1) {
printf("returned %" PRId32 ", expected -1: \n", r);
result = 0;
goto end;
}
if (!(ssn.flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY) ||
!(ssn.flags & STREAMTCP_FLAG_NOCLIENT_REASSEMBLY))
{
printf("flags should be set, but they are not !\n");
result = 0;
goto end;
}
if (ssn.aldata != NULL) {
printf("App Layer state has not been cleared\n");
result = 0;
goto end;
}
end:
return result;
}
#endif /* UNITESTS */
void AppLayerParserRegisterTests(void)
{
#ifdef UNITTESTS
UtRegisterTest("AppLayerParserTest01", AppLayerParserTest01, 1);
#endif /* UNITTESTS */
}

@ -97,6 +97,8 @@ uint16_t AlpGetStateIdx(uint16_t);
uint16_t AppLayerGetProtoByName(const char *); uint16_t AppLayerGetProtoByName(const char *);
void AppLayerParserRegisterTests(void);
#include "stream-tcp-private.h" #include "stream-tcp-private.h"
void AppLayerParserCleanupState(TcpSession *); void AppLayerParserCleanupState(TcpSession *);

@ -14,7 +14,9 @@ enum {
ALPROTO_JABBER, ALPROTO_JABBER,
ALPROTO_SMB, ALPROTO_SMB,
ALPROTO_DCERPC, ALPROTO_DCERPC,
#ifdef UNITTESTS
ALPROTO_TEST,
#endif /* UNITESTS */
/* keep last */ /* keep last */
ALPROTO_MAX, ALPROTO_MAX,
}; };

@ -12,6 +12,7 @@
#include "util-print.h" #include "util-print.h"
#include "util-pool.h" #include "util-pool.h"
#include "util-debug.h"
#include "stream-tcp-private.h" #include "stream-tcp-private.h"
#include "stream-tcp-reassemble.h" #include "stream-tcp-reassemble.h"
@ -125,7 +126,9 @@ static int SMBParseAndX(void *smb_state, AppLayerParserState *pstate,
* Determine if this is an SMB AndX Command * Determine if this is an SMB AndX Command
*/ */
static int SMBGetWordCount(void *smb_state, AppLayerParserState *pstate, static int SMBGetWordCount(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
{
SCEnter();
if (input_len) { if (input_len) {
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
sstate->wordcount.wordcount = *(input) * 2; sstate->wordcount.wordcount = *(input) * 2;
@ -133,9 +136,10 @@ static int SMBGetWordCount(void *smb_state, AppLayerParserState *pstate,
sstate->bytecount.bytecountbytes = 0; sstate->bytecount.bytecountbytes = 0;
sstate->andx.isandx = isAndX(sstate); sstate->andx.isandx = isAndX(sstate);
--input_len; --input_len;
return 1; SCLogDebug("Wordcount (%u):", sstate->wordcount.wordcount);
SCReturnInt(1);
} }
return 0; SCReturnInt(0);
} }
/* /*
@ -144,7 +148,9 @@ static int SMBGetWordCount(void *smb_state, AppLayerParserState *pstate,
*/ */
static int SMBGetByteCount(void *smb_state, AppLayerParserState *pstate, static int SMBGetByteCount(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
if (input_len && sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN + if (input_len && sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN +
@ -157,43 +163,55 @@ static int SMBGetByteCount(void *smb_state, AppLayerParserState *pstate,
2 + sstate->wordcount.wordcount) { 2 + sstate->wordcount.wordcount) {
sstate->bytecount.bytecount |= *(p++) << 8; sstate->bytecount.bytecount |= *(p++) << 8;
sstate->bytesprocessed++; sstate->bytesprocessed++;
printf("Bytecount (%u)\n", sstate->bytecount.bytecount); SCLogDebug("Bytecount %u", sstate->bytecount.bytecount);
--input_len; --input_len;
} }
return (p - input); SCReturInt(p - input);
} }
static int SMBParseWordCount(void *smb_state, AppLayerParserState *pstate, static int SMBParseWordCount(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
while (sstate->wordcount.wordcount-- && input_len--) { while (sstate->wordcount.wordcount > 0 && input_len > 0) {
if (sstate->andx.isandx) { if (sstate->andx.isandx) {
SMBParseAndX(smb_state, pstate, input, input_len, output); SMBParseAndX(smb_state, pstate, input, input_len, output);
} }
printf("0x%02x ", *(p++)); SCLogDebug("0x%02x", *(p++));
sstate->wordcount.wordcount--;
input_len--;
} }
printf("\n");
sstate->bytesprocessed += (p - input); sstate->bytesprocessed += (p - input);
return (p - input); SCReturnInt(p - input);
} }
static int SMBParseByteCount(void *smb_state, AppLayerParserState *pstate, static int SMBParseByteCount(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
while (sstate->bytecount.bytecount-- && input_len--) { while (sstate->bytecount.bytecount && input_len) {
printf("0x%02x bytecount %u input_len %u\n", *(p++), SCLogDebug("0x%02x bytecount %u input_len %u", *(p++),
sstate->bytecount.bytecount, input_len); sstate->bytecount.bytecount, input_len);
sstate->wordcount.wordcount--;
input_len--;
} }
printf("\n"); printf("\n");
sstate->bytesprocessed += (p - input); sstate->bytesprocessed += (p - input);
return (p - input);
SCReturnInt(p - input);
} }
#define DEBUG 1 #define DEBUG 1
static int NBSSParseHeader(void *smb_state, AppLayerParserState *pstate, static int NBSSParseHeader(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
@ -209,7 +227,7 @@ static int NBSSParseHeader(void *smb_state, AppLayerParserState *pstate,
sstate->nbss.length |= *(p + 3); sstate->nbss.length |= *(p + 3);
input_len -= NBSS_HDR_LEN; input_len -= NBSS_HDR_LEN;
sstate->bytesprocessed += NBSS_HDR_LEN; sstate->bytesprocessed += NBSS_HDR_LEN;
return NBSS_HDR_LEN; SCReturnInt(NBSS_HDR_LEN);
} else { } else {
sstate->nbss.type = *(p++); sstate->nbss.type = *(p++);
if (!(--input_len)) break; if (!(--input_len)) break;
@ -225,16 +243,18 @@ static int NBSSParseHeader(void *smb_state, AppLayerParserState *pstate,
--input_len; --input_len;
break; break;
default: default:
return -1; SCReturnInt(-1);
break; break;
} }
sstate->bytesprocessed += (p - input); sstate->bytesprocessed += (p - input);
} }
return (p - input); SCReturnInt(p - input);
} }
static int SMBParseHeader(void *smb_state, AppLayerParserState *pstate, static int SMBParseHeader(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
if (input_len) { if (input_len) {
@ -242,8 +262,8 @@ static int SMBParseHeader(void *smb_state, AppLayerParserState *pstate,
case 4: case 4:
if (input_len >= SMB_HDR_LEN) { if (input_len >= SMB_HDR_LEN) {
if (memcmp(p, "\xff\x53\x4d\x42", 4) != 0) { if (memcmp(p, "\xff\x53\x4d\x42", 4) != 0) {
printf("SMB Header did not validate\n"); SCLogDebug("SMB Header did not validate");
return 0; SCReturnInt(0);
} }
sstate->smb.command = *(p + 4); sstate->smb.command = *(p + 4);
sstate->smb.status = *(p + 5) << 24; sstate->smb.status = *(p + 5) << 24;
@ -273,28 +293,28 @@ static int SMBParseHeader(void *smb_state, AppLayerParserState *pstate,
sstate->smb.mid |= *(p + 31); sstate->smb.mid |= *(p + 31);
input_len -= SMB_HDR_LEN; input_len -= SMB_HDR_LEN;
sstate->bytesprocessed += SMB_HDR_LEN; sstate->bytesprocessed += SMB_HDR_LEN;
return SMB_HDR_LEN; SCReturnInt(SMB_HDR_LEN);
break; break;
} else { } else {
//sstate->smb.protocol[0] = *(p++); //sstate->smb.protocol[0] = *(p++);
if (*(p++) != 0xff) if (*(p++) != 0xff)
return 0; SCReturnInt(0);
if (!(--input_len)) break; if (!(--input_len)) break;
} }
case 5: case 5:
//sstate->smb.protocol[1] = *(p++); //sstate->smb.protocol[1] = *(p++);
if (*(p++) != 'S') if (*(p++) != 'S')
return 0; SCReturnInt(0);
if (!(--input_len)) break; if (!(--input_len)) break;
case 6: case 6:
//sstate->smb.protocol[2] = *(p++); //sstate->smb.protocol[2] = *(p++);
if (*(p++) != 'M') if (*(p++) != 'M')
return 0; SCReturnInt(0);
if (!(--input_len)) break; if (!(--input_len)) break;
case 7: case 7:
//sstate->smb.protocol[3] = *(p++); //sstate->smb.protocol[3] = *(p++);
if (*(p++) != 'B') if (*(p++) != 'B')
return 0; SCReturnInt(0);
if (!(--input_len)) break; if (!(--input_len)) break;
case 8: case 8:
sstate->smb.command = *(p++); sstate->smb.command = *(p++);
@ -382,27 +402,31 @@ static int SMBParseHeader(void *smb_state, AppLayerParserState *pstate,
--input_len; --input_len;
break; break;
default: // SHOULD NEVER OCCUR default: // SHOULD NEVER OCCUR
return 0; SCReturnInt(8);
} }
} }
sstate->bytesprocessed += (p - input); sstate->bytesprocessed += (p - input);
return (p - input); SCReturnInt(p - input);
} }
static int SMBParse(void *smb_state, AppLayerParserState *pstate, static int SMBParse(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint32_t retval = 0; uint32_t retval = 0;
uint32_t parsed = 0; uint32_t parsed = 0;
if (pstate == NULL) if (pstate == NULL)
return -1; SCReturnInt(-1);
while (sstate->bytesprocessed < NBSS_HDR_LEN) { while (sstate->bytesprocessed < NBSS_HDR_LEN) {
retval = NBSSParseHeader(smb_state, pstate, input, input_len, output); retval = NBSSParseHeader(smb_state, pstate, input, input_len, output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
printf("\nNBSS Header (%u/%u) Type 0x%02x Length 0x%04x parsed %u input_len %u\n",
SCLogDebug("NBSS Header (%u/%u) Type 0x%02x Length 0x%04x parsed %u input_len %u",
sstate->bytesprocessed, NBSS_HDR_LEN, sstate->nbss.type, sstate->bytesprocessed, NBSS_HDR_LEN, sstate->nbss.type,
sstate->nbss.length, parsed, input_len); sstate->nbss.length, parsed, input_len);
} }
@ -459,7 +483,7 @@ static int SMBParse(void *smb_state, AppLayerParserState *pstate,
} }
pstate->parse_field = 0; pstate->parse_field = 0;
pstate->flags |= APP_LAYER_PARSER_DONE; pstate->flags |= APP_LAYER_PARSER_DONE;
return 1; SCReturnInt(1);
} }
int isAndX(SMBState *smb_state) { int isAndX(SMBState *smb_state) {

@ -45,13 +45,15 @@ static int TLSParseClientContentType(void *tls_state, AppLayerParserState
*pstate, uint8_t *input, uint32_t input_len, *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) AppLayerParserResult *output)
{ {
SCEnter();
TlsState *state = (TlsState *)tls_state; TlsState *state = (TlsState *)tls_state;
if (input == NULL) if (input == NULL)
return 0; SCReturnInt(-1);
if (input_len != 1) { if (input_len != 1) {
return 0; SCReturnInt(-1);
} }
/* check if we received the correct content type */ /* check if we received the correct content type */
@ -62,7 +64,7 @@ static int TLSParseClientContentType(void *tls_state, AppLayerParserState
case TLS_APPLICATION_PROTOCOL: case TLS_APPLICATION_PROTOCOL:
break; break;
default: default:
return 0; SCReturnInt(0);
} }
state->client_content_type = *input; state->client_content_type = *input;
@ -86,7 +88,7 @@ static int TLSParseClientContentType(void *tls_state, AppLayerParserState
if (state->client_content_type == TLS_CHANGE_CIPHER_SPEC) if (state->client_content_type == TLS_CHANGE_CIPHER_SPEC)
state->flags |= TLS_FLAG_CLIENT_CHANGE_CIPHER_SPEC; state->flags |= TLS_FLAG_CLIENT_CHANGE_CIPHER_SPEC;
return 1; SCReturnInt(0);
} }
/** /**
@ -102,10 +104,12 @@ static int TLSParseClientContentType(void *tls_state, AppLayerParserState
static int TLSParseClientVersion(void *tls_state, AppLayerParserState *pstate, static int TLSParseClientVersion(void *tls_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
{ {
SCEnter();
TlsState *state = (TlsState *)tls_state; TlsState *state = (TlsState *)tls_state;
if (input_len != 2) if (input_len != 2)
return 0; SCReturnInt(-1);
/** \todo there must be an easier way to get from uint8_t * to a uint16_t */ /** \todo there must be an easier way to get from uint8_t * to a uint16_t */
struct u16conv_ { struct u16conv_ {
@ -126,7 +130,7 @@ static int TLSParseClientVersion(void *tls_state, AppLayerParserState *pstate,
} }
SCLogDebug("version %04"PRIx16"", state->client_version); SCLogDebug("version %04"PRIx16"", state->client_version);
return 1; SCReturnInt(0);
} }
/** /**
@ -174,7 +178,8 @@ static int TLSParseClientRecord(void *tls_state, AppLayerParserState *pstate,
pstate->parse_field = 0; pstate->parse_field = 0;
SCReturnInt(0); SCReturnInt(0);
} else if (r == -1) { } else if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, r %d", r); SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, "
"r %d", r);
SCReturnInt(-1); SCReturnInt(-1);
} }
break; break;
@ -192,7 +197,8 @@ static int TLSParseClientRecord(void *tls_state, AppLayerParserState *pstate,
pstate->parse_field = 1; pstate->parse_field = 1;
SCReturnInt(0); SCReturnInt(0);
} else if (r == -1) { } else if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, r %d", r); SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, "
"r %d", r);
SCReturnInt(-1); SCReturnInt(-1);
} }
break; break;
@ -205,12 +211,14 @@ static int TLSParseClientRecord(void *tls_state, AppLayerParserState *pstate,
int r = AlpParseFieldBySize(output, pstate, TLS_FIELD_LENGTH, int r = AlpParseFieldBySize(output, pstate, TLS_FIELD_LENGTH,
/* 2 byte field */2, data, data_len, /* 2 byte field */2, data, data_len,
&offset); &offset);
SCLogDebug("AlpParseFieldBySize returned r %d, offset %"PRIu32"", r, offset); SCLogDebug("AlpParseFieldBySize returned r %d, offset %"PRIu32""
, r, offset);
if (r == 0) { if (r == 0) {
pstate->parse_field = 2; pstate->parse_field = 2;
SCReturnInt(0); SCReturnInt(0);
} else if (r == -1) { } else if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, r %d", r); SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, "
"r %d", r);
SCReturnInt(-1); SCReturnInt(-1);
} }
@ -229,7 +237,8 @@ static int TLSParseClientRecord(void *tls_state, AppLayerParserState *pstate,
* is in the data */ * is in the data */
uint32_t record_offset = (offset + record_len); uint32_t record_offset = (offset + record_len);
SCLogDebug("record offset %"PRIu32" (offset %"PRIu32", record_len %"PRIu16")", record_offset, offset, record_len); SCLogDebug("record offset %"PRIu32" (offset %"PRIu32", record_len"
" %"PRIu16")", record_offset, offset, record_len);
/* if our input buffer is bigger than the data up to and /* if our input buffer is bigger than the data up to and
* including the current record, we instruct the parser to * including the current record, we instruct the parser to
@ -294,7 +303,8 @@ static int TLSParseServerRecord(void *tls_state, AppLayerParserState *pstate,
pstate->parse_field = 0; pstate->parse_field = 0;
SCReturnInt(0); SCReturnInt(0);
} else if (r == -1) { } else if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, r %d", r); SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, "
"r %d", r);
SCReturnInt(-1); SCReturnInt(-1);
} }
break; break;
@ -311,7 +321,8 @@ static int TLSParseServerRecord(void *tls_state, AppLayerParserState *pstate,
pstate->parse_field = 1; pstate->parse_field = 1;
SCReturnInt(0); SCReturnInt(0);
} else if (r == -1) { } else if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, r %d", r); SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, "
"r %d", r);
SCReturnInt(-1); SCReturnInt(-1);
} }
break; break;
@ -329,7 +340,8 @@ static int TLSParseServerRecord(void *tls_state, AppLayerParserState *pstate,
pstate->parse_field = 2; pstate->parse_field = 2;
SCReturnInt(0); SCReturnInt(0);
} else if (r == -1) { } else if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, r %d", r); SCLogError(SC_ALPARSER_ERR, "AlpParseFieldBySize failed, "
"r %d", r);
SCReturnInt(-1); SCReturnInt(-1);
} }
@ -348,7 +360,8 @@ static int TLSParseServerRecord(void *tls_state, AppLayerParserState *pstate,
* is in the data */ * is in the data */
uint32_t record_offset = (offset + record_len); uint32_t record_offset = (offset + record_len);
SCLogDebug("record offset %"PRIu32" (offset %"PRIu32", record_len %"PRIu16")", record_offset, offset, record_len); SCLogDebug("record offset %"PRIu32" (offset %"PRIu32", record_len"
" %"PRIu16")", record_offset, offset, record_len);
/* if our input buffer is bigger than the data up to and /* if our input buffer is bigger than the data up to and
* including the current record, we instruct the parser to * including the current record, we instruct the parser to
@ -382,10 +395,11 @@ static int TLSParseServerVersion(void *tls_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) AppLayerParserResult *output)
{ {
SCEnter();
TlsState *state = (TlsState *)tls_state; TlsState *state = (TlsState *)tls_state;
if (input_len != 2) if (input_len != 2)
return 0; SCReturnInt(-1);
/** \todo there must be an easier way to get from uint8_t * to a uint16_t */ /** \todo there must be an easier way to get from uint8_t * to a uint16_t */
struct u16conv_ { struct u16conv_ {
@ -396,7 +410,7 @@ static int TLSParseServerVersion(void *tls_state, AppLayerParserState *pstate,
state->server_version = ntohs(u16conv->u); state->server_version = ntohs(u16conv->u);
SCLogDebug("version %04"PRIx16"", state->server_version); SCLogDebug("version %04"PRIx16"", state->server_version);
return 1; SCReturnInt(0);
} }
/** /**
@ -412,13 +426,14 @@ static int TLSParseServerContentType(void *tls_state, AppLayerParserState *pstat
uint8_t *input, uint32_t input_len, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) AppLayerParserResult *output)
{ {
SCEnter();
TlsState *state = (TlsState *)tls_state; TlsState *state = (TlsState *)tls_state;
if (input == NULL) if (input == NULL)
return 0; SCReturnInt(-1);
if (input_len != 1) { if (input_len != 1) {
return 0; SCReturnInt(-1);
} }
/* check if we received the correct content type */ /* check if we received the correct content type */
@ -429,7 +444,7 @@ static int TLSParseServerContentType(void *tls_state, AppLayerParserState *pstat
case TLS_APPLICATION_PROTOCOL: case TLS_APPLICATION_PROTOCOL:
break; break;
default: default:
return 0; SCReturnInt(0);
} }
state->server_content_type = *input; state->server_content_type = *input;
@ -456,7 +471,7 @@ static int TLSParseServerContentType(void *tls_state, AppLayerParserState *pstat
pstate->flags |= APP_LAYER_PARSER_NO_REASSEMBLY; pstate->flags |= APP_LAYER_PARSER_NO_REASSEMBLY;
} }
return 1; SCReturnInt(0);
} }
/** \brief Function to allocates the TLS state memory /** \brief Function to allocates the TLS state memory
@ -548,7 +563,8 @@ static int TLSParserTest01(void) {
} }
if (tls_state->client_version != TLS_VERSION_10) { if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version); printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ",
TLS_VERSION_10, tls_state->client_version);
result = 0; result = 0;
goto end; goto end;
} }
@ -601,7 +617,8 @@ static int TLSParserTest02(void) {
} }
if (tls_state->client_version != TLS_VERSION_10) { if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version); printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ",
TLS_VERSION_10, tls_state->client_version);
result = 0; result = 0;
goto end; goto end;
} }
@ -663,7 +680,8 @@ static int TLSParserTest03(void) {
} }
if (tls_state->client_version != TLS_VERSION_10) { if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version); printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ",
TLS_VERSION_10, tls_state->client_version);
result = 0; result = 0;
goto end; goto end;
} }
@ -1033,7 +1051,8 @@ static int TLSParserMultimsgTest01(void) {
} }
if (tls_state->client_version != TLS_VERSION_10) { if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version); printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ",
TLS_VERSION_10, tls_state->client_version);
result = 0; result = 0;
goto end; goto end;
} }

@ -471,6 +471,7 @@ int main(int argc, char **argv)
SigGroupHeadRegisterTests(); SigGroupHeadRegisterTests();
SCHInfoRegisterTests(); SCHInfoRegisterTests();
SCRuleVarsRegisterTests(); SCRuleVarsRegisterTests();
AppLayerParserRegisterTests();
if (list_unittests) { if (list_unittests) {
UtListTests(regex_arg); UtListTests(regex_arg);
} }

@ -1218,7 +1218,10 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T
* \param ra_ctx Reassembly thread ctx, contains the queue * \param ra_ctx Reassembly thread ctx, contains the queue
* \retval 0 ok * \retval 0 ok
*/ */
int StreamTcpReassembleProcessAppLayer(TcpReassemblyThreadCtx *ra_ctx) { int StreamTcpReassembleProcessAppLayer(TcpReassemblyThreadCtx *ra_ctx)
{
SCEnter();
int r = 0;
if (ra_ctx != NULL && ra_ctx->stream_q && ra_ctx->stream_q->len > 0) { if (ra_ctx != NULL && ra_ctx->stream_q && ra_ctx->stream_q->len > 0) {
StreamMsg *smsg = NULL; StreamMsg *smsg = NULL;
do { do {
@ -1227,11 +1230,13 @@ int StreamTcpReassembleProcessAppLayer(TcpReassemblyThreadCtx *ra_ctx) {
break; break;
/** Handle the stream msg. No need to use locking, flow is already locked */ /** Handle the stream msg. No need to use locking, flow is already locked */
AppLayerHandleMsg(smsg, FALSE); r = AppLayerHandleMsg(smsg, FALSE);
if (r < 0)
break;
} while (ra_ctx->stream_q->len > 0); } while (ra_ctx->stream_q->len > 0);
} }
return 0; SCReturnInt(r);
} }
int StreamTcpReassembleHandleSegment(TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, Packet *p) { int StreamTcpReassembleHandleSegment(TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, Packet *p) {

@ -1877,12 +1877,14 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, StreamTcpThre
} }
/* flow is and stays locked */ /* flow is and stays locked */
static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt) { static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt)
{
SCEnter();
TcpSession *ssn = (TcpSession *)p->flow->protoctx; TcpSession *ssn = (TcpSession *)p->flow->protoctx;
if (ssn == NULL || ssn->state == TCP_NONE) { if (ssn == NULL || ssn->state == TCP_NONE) {
if (StreamTcpPacketStateNone(tv, p, stt, ssn) == -1) if (StreamTcpPacketStateNone(tv, p, stt, ssn) == -1)
return -1; SCReturnInt(-1);
} else { } else {
/* check if the packet is in right direction, when we missed the /* check if the packet is in right direction, when we missed the
SYN packet and picked up midstream session. */ SYN packet and picked up midstream session. */
@ -1892,39 +1894,39 @@ static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt) {
switch (ssn->state) { switch (ssn->state) {
case TCP_SYN_SENT: case TCP_SYN_SENT:
if(StreamTcpPacketStateSynSent(tv, p, stt, ssn)) if(StreamTcpPacketStateSynSent(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_SYN_RECV: case TCP_SYN_RECV:
if(StreamTcpPacketStateSynRecv(tv, p, stt, ssn)) if(StreamTcpPacketStateSynRecv(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_ESTABLISHED: case TCP_ESTABLISHED:
if(StreamTcpPacketStateEstablished(tv, p, stt, ssn)) if(StreamTcpPacketStateEstablished(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_FIN_WAIT1: case TCP_FIN_WAIT1:
if(StreamTcpPacketStateFinWait1(tv, p, stt, ssn)) if(StreamTcpPacketStateFinWait1(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_FIN_WAIT2: case TCP_FIN_WAIT2:
if(StreamTcpPacketStateFinWait2(tv, p, stt, ssn)) if(StreamTcpPacketStateFinWait2(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_CLOSING: case TCP_CLOSING:
if(StreamTcpPacketStateClosing(tv, p, stt, ssn)) if(StreamTcpPacketStateClosing(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_CLOSE_WAIT: case TCP_CLOSE_WAIT:
if(StreamTcpPacketStateCloseWait(tv, p, stt, ssn)) if(StreamTcpPacketStateCloseWait(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_LAST_ACK: case TCP_LAST_ACK:
if(StreamTcpPakcetStateLastAck(tv, p, stt, ssn)) if(StreamTcpPakcetStateLastAck(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_TIME_WAIT: case TCP_TIME_WAIT:
if(StreamTcpPacketStateTimeWait(tv, p, stt, ssn)) if(StreamTcpPacketStateTimeWait(tv, p, stt, ssn))
return -1; SCReturnInt(-1);
break; break;
case TCP_CLOSED: case TCP_CLOSED:
//printf("StreamTcpPacket: packet received on closed state\n"); //printf("StreamTcpPacket: packet received on closed state\n");
@ -1936,8 +1938,10 @@ static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt) {
} }
/* Process stream smsgs we may have in queue */ /* Process stream smsgs we may have in queue */
StreamTcpReassembleProcessAppLayer(stt->ra_ctx); if (StreamTcpReassembleProcessAppLayer(stt->ra_ctx) < 0)
return 0; SCReturnInt(-1);
SCReturnInt(0);
} }
TmEcode StreamTcp (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) TmEcode StreamTcp (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)

@ -43,6 +43,7 @@ const char * SCErrorToString(SCError err)
CASE_CODE (SC_NUMERIC_VALUE_ERANGE); CASE_CODE (SC_NUMERIC_VALUE_ERANGE);
CASE_CODE (SC_INVALID_NUM_BYTES); CASE_CODE (SC_INVALID_NUM_BYTES);
CASE_CODE (SC_ERR_ARG_LEN_LONG); CASE_CODE (SC_ERR_ARG_LEN_LONG);
CASE_CODE (SC_ALPARSER_ERR);
default: default:
return "UNKNOWN_ERROR"; return "UNKNOWN_ERROR";
} }

Loading…
Cancel
Save