app layer htp error handling and fixes for memory leaks and segv

remotes/origin/master-1.0.x
Gurvinder Singh 16 years ago committed by Victor Julien
parent aa653157bf
commit fc2f7f29fa

@ -36,7 +36,7 @@ logging:
# Enable logging to the console. Be a little more verbose than
# default, log info and more critical.
- interface: console
log-level: info
log-level: error
# Log to a file as well. No log level specified so level will be
# set to the default-log-level.

@ -132,7 +132,6 @@ counters.c counter.h \
app-layer.c app-layer.h \
app-layer-detect-proto.c app-layer-detect-proto.h \
app-layer-parser.c app-layer-parser.h \
app-layer-http.c app-layer-http.h \
app-layer-tls.c app-layer-tls.h \
app-layer-smb.c app-layer-smb.h \
app-layer-dcerpc.c app-layer-dcerpc.h \

@ -38,7 +38,7 @@ enum {
};
#if 0
static int DCERPCParseBIND(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
static int DCERPCParseBIND(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock) {
DCERPCState *sstate = (DCERPCState *)dcerpc_state;
uint8_t *p = input;
if (input_len) {
@ -73,14 +73,16 @@ static int DCERPCParseBIND(void *dcerpc_state, AppLayerParserState *pstate, uint
return (p - input);
}
static int DCERPCParseBINDACK(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
static int DCERPCParseBINDACK(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock) {
DCERPCState *sstate = (DCERPCState *)dcerpc_state;
uint8_t *p = input;
return 0;
}
#endif
static int DCERPCParseHeader(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
static int DCERPCParseHeader(Flow *f, void *dcerpc_state, AppLayerParserState
*pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output, char need_lock) {
SCEnter();
DCERPCState *sstate = (DCERPCState *)dcerpc_state;
@ -173,7 +175,7 @@ static int DCERPCParseHeader(void *dcerpc_state, AppLayerParserState *pstate, ui
SCReturnInt(0);
}
static int DCERPCParse(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
static int DCERPCParse(Flow *f, void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock) {
SCEnter();
// DCERPCState *sstate = (DCERPCState *)dcerpc_state;
uint16_t max_fields = 3;

@ -12,7 +12,6 @@
#include "debug.h"
#include "decode.h"
#include "threads.h"
#include <htp/htp.h>
#include "util-print.h"
#include "util-pool.h"
@ -23,11 +22,13 @@
#include "app-layer-protos.h"
#include "app-layer-parser.h"
#include "app-layer-htp.h"
#include "util-binsearch.h"
#include "util-unittest.h"
#include "util-debug.h"
#include "app-layer-htp.h"
#include "util-time.h"
#ifdef DEBUG
static SCMutex htp_state_mem_lock = PTHREAD_MUTEX_INITIALIZER;
@ -66,7 +67,7 @@ static void HTPStateFree(void *s)
/* free the connection parser memory used by HTP library */
if (s != NULL)
if (((HtpState *)(s))->connp != NULL)
htp_connp_destroy(((HtpState *)(s))->connp);
htp_connp_destroy_all(((HtpState *)(s))->connp);
free(s);
#ifdef DEBUG
@ -77,6 +78,21 @@ static void HTPStateFree(void *s)
#endif
}
/**
* \brief Function to convert the IP addresses in to the string
*
* \param f pointer to the flow which contains the IP addresses
* \param remote_addr pointer the string which will contain the remote address
* \param local_addr pointer the string which will contain the local address
*/
void HTPGetIPAddr(Flow *f, int family, char *remote_addr, char *local_addr)
{
inet_ntop(family, (const void *)&f->src.addr_data32[0], remote_addr,
sizeof (remote_addr));
inet_ntop(family, (const void *)&f->dst.addr_data32[0], local_addr,
sizeof (local_addr));
}
/**
* \brief Function to handle the reassembled data from client and feed it to
* the HTP library to process it.
@ -89,18 +105,22 @@ static void HTPStateFree(void *s)
*
* \retval On success returns 1 or on failure returns -1
*/
static int HTPHandleRequestData(void *htp_state, AppLayerParserState *pstate,
static int HTPHandleRequestData(Flow *f, void *htp_state,
AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
AppLayerParserResult *output, char need_lock)
{
SCEnter();
HtpState *hstate = (HtpState *)htp_state;
struct timeval tv;
gettimeofday(&tv, NULL);
/* Open the HTTP connection on receiving the first request */
if (! (hstate->flags & HTP_FLAG_STATE_OPEN)) {
htp_connp_open(hstate->connp, NULL, f->sp, NULL, f->dp, 0);
hstate->flags |= HTP_FLAG_STATE_OPEN;
}
if (htp_connp_req_data(hstate->connp, tv.tv_usec, input, input_len) ==
HTP_ERROR)
if (htp_connp_req_data(hstate->connp, 0, input, input_len) ==
STREAM_STATE_ERROR)
{
/* As work in HTP library is in progress, so it doesn't filled the
last_error field always and it can be null at the moment. So we can't
@ -110,6 +130,14 @@ static int HTPHandleRequestData(void *htp_state, AppLayerParserState *pstate,
SCReturnInt(-1);
}
/* if we the TCP connection is closed, then close the HTTP connection */
if ((pstate->flags & APP_LAYER_PARSER_EOF) &&
! (hstate->flags & HTP_FLAG_STATE_CLOSED))
{
htp_connp_close(hstate->connp, 0);
hstate->flags |= HTP_FLAG_STATE_CLOSED;
}
SCReturnInt(1);
}
@ -125,18 +153,16 @@ static int HTPHandleRequestData(void *htp_state, AppLayerParserState *pstate,
*
* \retval On success returns 1 or on failure returns -1
*/
static int HTPHandleResponseData(void *htp_state, AppLayerParserState *pstate,
static int HTPHandleResponseData(Flow *f, void *htp_state,
AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
AppLayerParserResult *output, char need_lock)
{
SCEnter();
HtpState *hstate = (HtpState *)htp_state;
struct timeval tv;
gettimeofday(&tv, NULL);
if (htp_connp_res_data(hstate->connp, tv.tv_usec, input, input_len) ==
HTP_ERROR)
if (htp_connp_res_data(hstate->connp, 0, input, input_len) ==
STREAM_STATE_ERROR)
{
/* As work in HTP library is in progress, so it doesn't filled the
last_error field always and it can be null at the moment. So we can't
@ -146,9 +172,36 @@ static int HTPHandleResponseData(void *htp_state, AppLayerParserState *pstate,
SCReturnInt(-1);
}
/* if we the TCP connection is closed, then close the HTTP connection */
if ((pstate->flags & APP_LAYER_PARSER_EOF) &&
! (hstate->flags & HTP_FLAG_STATE_CLOSED))
{
htp_connp_close(hstate->connp, 0);
hstate->flags |= HTP_FLAG_STATE_CLOSED;
}
SCReturnInt(1);
}
/**
* \brief Print the stats of the HTTP requests
*/
void HTPAtExitPrintStats(void)
{
#ifdef DEBUG
SCMutexLock(&htp_state_mem_lock);
SCLogDebug("http_state_memcnt %"PRIu64", http_state_memuse %"PRIu64"",
htp_state_memcnt, htp_state_memuse);
SCMutexUnlock(&htp_state_mem_lock);
#endif
}
/** \brief Clears the HTTP server configuration memory used by HTP library */
void HTPFreeConfig(void)
{
htp_config_destroy(cfg);
}
/**
* \brief Register the HTTP protocol and state handling functions to APP layer
* of the engine.
@ -172,7 +225,7 @@ void RegisterHTPParsers(void)
int HTPParserTest01(void) {
int result = 1;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.1\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
" Data is c0oL!";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
@ -215,10 +268,10 @@ int HTPParserTest01(void) {
if (htp_state->connp == NULL || strcmp(bstr_tocstr(h->value), "Victor/1.0")
|| tx->request_method_number != M_POST ||
tx->request_protocol_number != HTTP_1_1)
tx->request_protocol_number != HTTP_1_0)
{
printf("expected header value: Victor/1.0 and got %s: and expected"
" method: POST and got %s, expected protocol number HTTP/1.1"
" method: POST and got %s, expected protocol number HTTP/1.0"
" and got: %s \n", bstr_tocstr(h->value),
bstr_tocstr(tx->request_method),
bstr_tocstr(tx->request_protocol));
@ -386,14 +439,14 @@ end:
int HTPParserTest05(void) {
int result = 1;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.1\r\nUser-Agent: Victor/1.0\r\n\r\n";
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "Post D";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
uint8_t httpbuf3[] = "ata is c0oL!";
uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
uint8_t httpbuf4[] = "HTTP/1.1 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
uint8_t httpbuf4[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
uint8_t httpbuf5[] = "post R";
uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
@ -468,20 +521,20 @@ int HTPParserTest05(void) {
key = table_iterator_next(tx->request_headers, (void **) & h);
if (http_state->connp == NULL || tx->request_method_number != M_POST ||
h == NULL || tx->request_protocol_number != HTTP_1_1)
h == NULL || tx->request_protocol_number != HTTP_1_0)
{
printf("expected method M_POST and got %s: , expected protocol "
"HTTP/1.1 and got %s \n", bstr_tocstr(tx->request_method),
"HTTP/1.0 and got %s \n", bstr_tocstr(tx->request_method),
bstr_tocstr(tx->request_protocol));
result = 0;
goto end;
}
if (tx->response_status_number != 200 ||
h == NULL || tx->request_protocol_number != HTTP_1_1)
h == NULL || tx->request_protocol_number != HTTP_1_0)
{
printf("expected response 200 OK and got %"PRId32" %s: , expected protocol "
"HTTP/1.1 and got %s \n", tx->response_status_number,
"HTTP/1.0 and got %s \n", tx->response_status_number,
bstr_tocstr(tx->response_message),
bstr_tocstr(tx->response_protocol));
result = 0;
@ -491,6 +544,114 @@ end:
return result;
}
/** \test Test proper chunked encoded response body
*/
int HTPParserTest06(void) {
int result = 1;
Flow f;
uint8_t httpbuf1[] = "GET /ld/index.php?id=412784631&cid=0064&version=4&"
"name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
"LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.1 200 OK\r\nDate: Sat, 03 Oct 2009 10:16:02 "
"GMT\r\n"
"Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 "
"OpenSSL/0.9.7a PHP/4.4.7 mod_perl/1.29 "
"FrontPage/5.0.2.2510\r\n"
"X-Powered-By: PHP/4.4.7\r\nTransfer-Encoding: "
"chunked\r\n"
"Content-Type: text/html\r\n\r\n"
"1408\r\n"
"W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
"MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
"CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
"CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
"ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
"Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
"CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
"aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
"d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
"aG9uZTM9DQpsb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
"b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
"YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
"DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
"Cm1vbnRoX2xpbWl0PQ0KW2dyb3VwM10NCnBob25lMT0NCmxvZ2lu"
"MT0NCnBhc3N3b3JkMT0NCnBob25lMj0NCmxvZ2luMj0NCnBhc3N3"
"b3JkMj0NCnBob25lMz0NCmxvZ2luMz0NCnBhc3N3b3JkMz0NCnBo"
"b25lND0NCmxvZ2luND0NCnBhc3N3b3JkND0NCnBob25lNT0NCmxv"
"Z2luNT0NCnBhc3N3b3JkNT0NCnBob25lNj0NCmxvZ2luNj0NCnBh"
"c3N3b3JkNj0NCmNhbGxfdGltZTE9DQpjYWxsX3RpbWUyPQ0KZGF5"
"X2xpbWl0PQ0KbW9udGhfbGltaXQ9DQpbZ3JvdXA0XQ0KcGhvbmUx"
"PQ0KbG9naW4xPQ0KcGFzc3dvcmQxPQ0KcGhvbmUyPQ0KbG9naW4y"
"PQ0KcGFzc3dvcmQyPQ0KcGhvbmUzPQ0KbG9naW4zPQ0KcGFzc3dv"
"cmQzPQ0KcGhvbmU0PQ0KbG9naW40PQ0KcGFzc3dvcmQ0PQ0KcGhv"
"bmU1PQ0KbG9naW41PQ0KcGFzc3dvcmQ1PQ0KcGhvbmU2PQ0KbG9n"
"aW42PQ0KcGFzc3dvcmQ2PQ0KY2FsbF90aW1lMT0NCmNhbGxfdGlt"
"ZTI9DQpkYXlfbGltaXQ9DQptb250aF9saW1pdD0NCltmaWxlc10N"
"Cmxpbms9aHR0cDovLzIwOS4yMDUuMTk2LjE2L2xkL2dldGJvdC5w"
"aHA=0\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START,
httpbuf1, httplen1, FALSE);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOCLIENT|STREAM_START, httpbuf2,
httplen2, FALSE);
if (r != 0) {
printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
HtpState *http_state = ssn.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
if (http_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
htp_tx_t *tx = list_get(http_state->connp->conn->transactions, 0);
bstr *key = NULL;
htp_header_t *h = NULL;
table_iterator_reset(tx->request_headers);
key = table_iterator_next(tx->request_headers, (void **) & h);
if (http_state->connp == NULL || tx->request_method_number != M_GET ||
h == NULL || tx->request_protocol_number != HTTP_1_1)
{
printf("expected method M_GET and got %s: , expected protocol "
"HTTP/1.1 and got %s \n", bstr_tocstr(tx->request_method),
bstr_tocstr(tx->request_protocol));
result = 0;
goto end;
}
if (tx->response_status_number != 200 ||
h == NULL || tx->request_protocol_number != HTTP_1_1)
{
printf("expected response 200 OK and got %"PRId32" %s: , expected proto"
"col HTTP/1.1 and got %s \n", tx->response_status_number,
bstr_tocstr(tx->response_message),
bstr_tocstr(tx->response_protocol));
result = 0;
goto end;
}
end:
return result;
}
//#endif /* UNITTESTS */
/**
* \brief Register the Unit tests for the HTTP protocol
@ -502,6 +663,7 @@ void HTPParserRegisterTests(void) {
UtRegisterTest("HTPParserTest03", HTPParserTest03, 1);
UtRegisterTest("HTPParserTest04", HTPParserTest04, 1);
UtRegisterTest("HTPParserTest05", HTPParserTest05, 1);
UtRegisterTest("HTPParserTest06", HTPParserTest06, 1);
#endif /* UNITTESTS */
}

@ -10,9 +10,15 @@
#include <htp/htp.h>
#define HTP_FLAG_STATE_OPEN 0x01 /**< Flag to indicate that HTTP connection
is open */
#define HTP_FLAG_STATE_CLOSED 0x02 /**< Flag to indicate that HTTP connection
is closed */
typedef struct HtpState_ {
htp_connp_t *connp; /**< Connection parser structure for each connection */
uint8_t flags;
} HtpState;
@ -20,5 +26,7 @@ htp_cfg_t *cfg; /**< Config structure for HTP library */
void RegisterHTPParsers(void);
void HTPParserRegisterTests(void);
void HTPAtExitPrintStats(void);
void HTPFreeConfig(void);
#endif /* _APP_LAYER_HTP_H */

@ -94,8 +94,10 @@ static int AlpStoreField(AppLayerParserResult *output, uint16_t idx,
SCEnter();
AppLayerParserResultElmt *e = AlpGetResultElmt();
if (e == NULL)
if (e == NULL) {
SCLogError(SC_INVALID_ARGUMENT, " App layer pool returned NULL");
SCReturnInt(-1);
}
if (alloc == 1)
e->flags |= ALP_RESULT_ELMT_ALLOC;
@ -124,6 +126,7 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
if (pstate->store_len == 0) {
pstate->store = malloc(input_len);
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory allocation failed!");
SCReturnInt(-1);
}
@ -132,6 +135,7 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
} else {
pstate->store = realloc(pstate->store, (input_len + pstate->store_len));
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory reallocation failed!");
SCReturnInt(-1);
}
@ -142,6 +146,7 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
if (pstate->store_len == 0) {
int r = AlpStoreField(output, field_idx, input, size, /* static mem */0);
if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "Failed to store field value");
SCReturnInt(-1);
}
(*offset) += size;
@ -152,6 +157,7 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
pstate->store = realloc(pstate->store, (diff + pstate->store_len));
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory reallocation failed!");
SCReturnInt(-1);
}
@ -161,6 +167,7 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
int r = AlpStoreField(output, field_idx, pstate->store,
pstate->store_len, /* alloc mem */1);
if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "Failed to store field value");
SCReturnInt(-1);
}
@ -193,6 +200,7 @@ int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate
int r = AlpStoreField(output, field_idx, input, input_len, 0);
if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "Failed to store field value");
SCReturnInt(-1);
}
@ -203,6 +211,7 @@ int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate
/* delimiter field not found, so store the result for the next run */
pstate->store = malloc(input_len);
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory allocation failed!");
SCReturnInt(-1);
}
@ -215,6 +224,7 @@ int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate
pstate->store = realloc(pstate->store, (input_len + pstate->store_len));
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory reallocation failed!");
SCReturnInt(-1);
}
@ -223,6 +233,7 @@ int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate
int r = AlpStoreField(output, field_idx, pstate->store, pstate->store_len, 1);
if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "Failed to store field value");
SCReturnInt(-1);
}
@ -236,6 +247,7 @@ int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate
/* delimiter field not found, so store the result for the next run */
pstate->store = realloc(pstate->store, (input_len + pstate->store_len));
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory reallocation failed!");
SCReturnInt(-1);
}
@ -270,6 +282,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
int r = AlpStoreField(output, field_idx, input, len, 0);
if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "Failed to store field value");
SCReturnInt(-1);
}
(*offset) += (len + delim_len);
@ -285,6 +298,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
/* delimiter field not found, so store the result for the next run */
pstate->store = malloc(input_len);
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory allocation failed!");
SCReturnInt(-1);
}
@ -300,6 +314,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
pstate->store = realloc(pstate->store, (len + pstate->store_len));
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory reallocation failed!");
SCReturnInt(-1);
}
@ -309,6 +324,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
int r = AlpStoreField(output, field_idx, pstate->store,
pstate->store_len, 1);
if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "Failed to store field value");
SCReturnInt(-1);
}
pstate->store = NULL;
@ -326,6 +342,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
pstate->store = realloc(pstate->store, (input_len +
pstate->store_len));
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory reallocation failed!");
SCReturnInt(-1);
}
@ -343,6 +360,8 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
int r = AlpStoreField(output, field_idx,
pstate->store, len, 1);
if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "Failed to store "
"field value");
SCReturnInt(-1);
}
@ -369,6 +388,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
/* delimiter field not found, so store the result for the next run */
pstate->store = realloc(pstate->store, (input_len + pstate->store_len));
if (pstate->store == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Memory reallocation failed!");
SCReturnInt(-1);
}
@ -387,6 +407,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
uint32_t len = ptr - pstate->store;
int r = AlpStoreField(output, field_idx, pstate->store, len, 1);
if (r == -1) {
SCLogError(SC_ALPARSER_ERR, "Failed to store field value");
SCReturnInt(-1);
}
pstate->store = NULL;
@ -454,10 +475,10 @@ uint16_t AppLayerGetProtoByName(const char *name)
* \retval -1 on error
*/
int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id,
int (*AppLayerParser)(void *protocol_state,
int (*AppLayerParser)(Flow *f, void *protocol_state,
AppLayerParserState *parser_state, uint8_t *input,
uint32_t input_len, AppLayerParserResult *output),
char *dependency)
uint32_t input_len, AppLayerParserResult *output,
char need_lock), char *dependency)
{
al_max_parsers++;
@ -490,9 +511,10 @@ int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id,
* \retval -1 on error
*/
int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags,
int (*AppLayerParser)(void *protocol_state,
int (*AppLayerParser)(Flow *f, void *protocol_state,
AppLayerParserState *parser_state, uint8_t *input,
uint32_t input_len, AppLayerParserResult *output))
uint32_t input_len, AppLayerParserResult *output,
char need_lock))
{
al_max_parsers++;
@ -575,9 +597,9 @@ static void AppLayerParserResultCleanup(AppLayerParserResult *result)
}
}
static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_state,
static int AppLayerDoParse(Flow *f, void *app_layer_state, AppLayerParserState *parser_state,
uint8_t *input, uint32_t input_len, uint16_t parser_idx,
uint16_t proto)
uint16_t proto, char need_lock)
{
SCEnter();
int retval = 0;
@ -587,8 +609,9 @@ static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_st
//PrintRawDataFp(stdout, input,input_len);
/* 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(f, app_layer_state,
parser_state, input, input_len, &result,
need_lock);
if (r < 0) {
if (r == -1) {
AppLayerParserResultCleanup(&result);
@ -621,8 +644,8 @@ static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_st
parser_state->parse_field = 0;
parser_state->flags |= APP_LAYER_PARSER_EOF;
r = AppLayerDoParse(app_layer_state, parser_state, e->data_ptr,
e->data_len, idx, proto);
r = AppLayerDoParse(f, app_layer_state, parser_state, e->data_ptr,
e->data_len, idx, proto, need_lock);
/* restore */
parser_state->flags &= ~APP_LAYER_PARSER_EOF;
@ -744,8 +767,8 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input,
}
/* invoke the recursive parser */
int r = AppLayerDoParse(app_layer_state, parser_state, input, input_len,
parser_idx, proto);
int r = AppLayerDoParse(f, app_layer_state, parser_state, input, input_len,
parser_idx, proto, need_lock);
if (r < 0)
goto error;
@ -783,7 +806,6 @@ error:
if (need_lock == TRUE) SCMutexLock(&f->m);
StreamTcpSetSessionNoReassemblyFlag(ssn, flags & STREAM_TOCLIENT ? 1 : 0);
StreamTcpSetSessionNoReassemblyFlag(ssn, flags & STREAM_TOSERVER ? 1 : 0);
if (need_lock == TRUE) SCMutexUnlock(&f->m);
if (f->src.family == AF_INET) {
inet_ntop(AF_INET, (const void*)&f->src.addr_data32[0], src,
@ -809,7 +831,7 @@ error:
"dst port %"PRIu16"", al_proto_table[ssn->alproto].name,
f->proto, src6, dst6, f->sp, f->dp);
}
if (need_lock == TRUE) SCMutexUnlock(&f->m);
}
SCReturnInt(-1);
@ -955,9 +977,9 @@ typedef struct 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,
static int TestProtocolParser(Flow *f, void *test_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
AppLayerParserResult *output, char need_lock)
{
return -1;
}

@ -75,24 +75,41 @@ typedef struct AppLayerParserTableElement_ {
uint16_t proto;
uint16_t parser_local_id; /** local id of the parser in the parser itself. */
uint8_t flags;
int (*AppLayerParser)(void *protocol_state, AppLayerParserState *parser_state, uint8_t *input, uint32_t input_len, AppLayerParserResult *output);
uint16_t max_outputs; /* rationele is that if we know the max outputs of all parsers, we
can statically define our output array to be a certain size */
int (*AppLayerParser)(Flow *f, void *protocol_state, AppLayerParserState
*parser_state, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output, char need_lock);
uint16_t max_outputs; /* rationele is that if we know the max outputs of all
parsers, we can statically define our output array
to be a certain size */
} AppLayerParserTableElement;
/* prototypes */
void AppLayerParsersInitPostProcess(void);
void RegisterAppLayerParsers(void);
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 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);
void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void), void (*StateFree)(void *));
int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_t input_len, char);
int AlpParseFieldBySize(AppLayerParserResult *, AppLayerParserState *, uint16_t, uint32_t, uint8_t *, uint32_t, uint32_t *);
int AlpParseFieldByEOF(AppLayerParserResult *, AppLayerParserState *, uint16_t, uint8_t *, uint32_t);
int AlpParseFieldByDelimiter(AppLayerParserResult *, AppLayerParserState *, uint16_t, const uint8_t *, uint8_t, uint8_t *, uint32_t, uint32_t *);
int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags,
int (*AppLayerParser)(Flow *f, void *protocol_state,
AppLayerParserState *parser_state, uint8_t *input,
uint32_t input_len, AppLayerParserResult *output,
char need_lock));
int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id,
int (*AppLayerParser)(Flow *f, void *protocol_state,
AppLayerParserState *parser_state, uint8_t *input,
uint32_t input_len, AppLayerParserResult *output,
char need_lock), char *dependency);
void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void),
void (*StateFree)(void *));
int AppLayerParse(Flow *, uint8_t proto, uint8_t flags, uint8_t *input,
uint32_t input_len, char);
int AlpParseFieldBySize(AppLayerParserResult *, AppLayerParserState *, uint16_t,
uint32_t, uint8_t *, uint32_t, uint32_t *);
int AlpParseFieldByEOF(AppLayerParserResult *, AppLayerParserState *, uint16_t,
uint8_t *, uint32_t);
int AlpParseFieldByDelimiter(AppLayerParserResult *, AppLayerParserState *,
uint16_t, const uint8_t *, uint8_t, uint8_t *,
uint32_t, uint32_t *);
uint16_t AlpGetStateIdx(uint16_t);
uint16_t AppLayerGetProtoByName(const char *);

@ -99,8 +99,9 @@ void hexdump(const void *buf, size_t len) {
/**
* \brief SMB Write AndX Request Parsing
*/
static int SMBParseWriteAndX(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
/* For WriteAndX we need to get writeandxdataoffset */
static int SMBParseAndX(Flow *f, void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock) {
SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input;
switch (sstate->andx.andxbytesprocessed) {
@ -378,8 +379,8 @@ static int DataParser(void *smb_state, AppLayerParserState *pstate,
* Reset bytecount.bytecountbytes to 0.
* Determine if this is an SMB AndX Command
*/
static int SMBGetWordCount(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
static int SMBGetWordCount(Flow *f, void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock)
{
SCEnter();
if (input_len) {
@ -400,8 +401,8 @@ static int SMBGetWordCount(void *smb_state, AppLayerParserState *pstate,
* is after the first bytecount byte.
*/
static int SMBGetByteCount(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
static int SMBGetByteCount(Flow *f, void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state;
@ -426,8 +427,8 @@ static int SMBGetByteCount(void *smb_state, AppLayerParserState *pstate,
* \brief SMBParseWordCount parses the SMB Wordcount portion of the SMB Transaction.
* until sstate->wordcount.wordcount bytes are parsed.
*/
static int SMBParseWordCount(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
static int SMBParseWordCount(Flow *f, void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state;
@ -462,8 +463,8 @@ static int SMBParseWordCount(void *smb_state, AppLayerParserState *pstate,
* until sstate->bytecount.bytecount bytes are parsed.
*/
static int SMBParseByteCount(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
static int SMBParseByteCount(Flow *f, void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state;
@ -498,8 +499,8 @@ static int SMBParseByteCount(void *smb_state, AppLayerParserState *pstate,
}
#define DEBUG 1
static int NBSSParseHeader(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
static int NBSSParseHeader(Flow *f, void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state;
@ -541,8 +542,8 @@ static int NBSSParseHeader(void *smb_state, AppLayerParserState *pstate,
SCReturnInt(p - input);
}
static int SMBParseHeader(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
static int SMBParseHeader(Flow *f, void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock)
{
SCEnter();
SMBState *sstate = (SMBState *) smb_state;
@ -699,8 +700,8 @@ static int SMBParseHeader(void *smb_state, AppLayerParserState *pstate,
SCReturnInt(p - input);
}
static int SMBParse(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
static int SMBParse(Flow *f, void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock)
{
SCEnter();
@ -712,7 +713,8 @@ static int SMBParse(void *smb_state, AppLayerParserState *pstate,
SCReturnInt(-1);
while (sstate->bytesprocessed < NBSS_HDR_LEN) {
retval = NBSSParseHeader(smb_state, pstate, input, input_len, output);
retval = NBSSParseHeader(f, smb_state, pstate, input, input_len,
output, need_lock);
parsed += retval;
input_len -= retval;
@ -725,7 +727,8 @@ static int SMBParse(void *smb_state, AppLayerParserState *pstate,
case NBSS_SESSION_MESSAGE:
while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN &&
sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN)) {
retval = SMBParseHeader(smb_state, pstate, input + parsed, input_len, output);
retval = SMBParseHeader(f, smb_state, pstate, input +
parsed, input_len, output, need_lock);
parsed += retval;
input_len -= retval;
printf("SMB Header (%u/%u) Command 0x%02x parsed %u input_len %u\n",
@ -735,7 +738,9 @@ static int SMBParse(void *smb_state, AppLayerParserState *pstate,
do {
if (input_len && (sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN)) {
retval = SMBGetWordCount(smb_state, pstate, input + parsed, input_len, output);
retval = SMBGetWordCount(f, smb_state, pstate,
input + parsed, input_len,
output, need_lock);
parsed += retval;
input_len -= retval;
printf("Wordcount (%u) parsed %u input_len %u\n",
@ -745,7 +750,9 @@ static int SMBParse(void *smb_state, AppLayerParserState *pstate,
while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN + SMB_HDR_LEN + 1 &&
sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN + 1
+ sstate->wordcount.wordcount)) {
retval = SMBParseWordCount(smb_state, pstate, input + parsed, input_len, output);
retval = SMBParseWordCount(f, smb_state, pstate,
input + parsed, input_len,
output, need_lock);
parsed += retval;
input_len -= retval;
}
@ -753,7 +760,9 @@ static int SMBParse(void *smb_state, AppLayerParserState *pstate,
while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN + SMB_HDR_LEN +
1 + sstate->wordcount.wordcount && sstate->bytesprocessed < NBSS_HDR_LEN +
SMB_HDR_LEN + 3 + sstate->wordcount.wordcount)) {
retval = SMBGetByteCount(smb_state, pstate, input + parsed, input_len, output);
retval = SMBGetByteCount(f, smb_state, pstate,
input + parsed, input_len,
output, need_lock);
parsed += retval;
input_len -= retval;
}
@ -762,7 +771,9 @@ static int SMBParse(void *smb_state, AppLayerParserState *pstate,
SMB_HDR_LEN + 3 + sstate->wordcount.wordcount &&
sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN + 3
+ sstate->wordcount.wordcount + sstate->bytecount.bytecount)) {
retval = SMBParseByteCount(smb_state, pstate, input + parsed, input_len, output);
retval = SMBParseByteCount(f, smb_state, pstate,
input + parsed, input_len,
output, need_lock);
parsed += retval;
input_len -= retval;
}

@ -41,9 +41,9 @@
* \param input_len Length in bytes of the received content type value
* \param output Pointer to the list of parsed elements
*/
static int TLSParseClientContentType(void *tls_state, AppLayerParserState
static int TLSParseClientContentType(Flow *f, void *tls_state, AppLayerParserState
*pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
AppLayerParserResult *output, char need_lock)
{
SCEnter();
@ -101,8 +101,8 @@ static int TLSParseClientContentType(void *tls_state, AppLayerParserState
* \param input_len Length in bytes of the received version value
* \param output Pointer to the list of parsed elements
*/
static int TLSParseClientVersion(void *tls_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output)
static int TLSParseClientVersion(Flow *f, void *tls_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output, char need_lock)
{
SCEnter();
@ -142,9 +142,9 @@ static int TLSParseClientVersion(void *tls_state, AppLayerParserState *pstate,
* \param input_len Length in bytes of the received data
* \param output Pointer to the list of parsed output elements
*/
static int TLSParseClientRecord(void *tls_state, AppLayerParserState *pstate,
static int TLSParseClientRecord(Flow *f, void *tls_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
AppLayerParserResult *output, char need_lock)
{
SCEnter();
@ -267,9 +267,9 @@ static int TLSParseClientRecord(void *tls_state, AppLayerParserState *pstate,
* \param input_len Length in bytes of the received data
* \param output Pointer to the list of parsed output elements
*/
static int TLSParseServerRecord(void *tls_state, AppLayerParserState *pstate,
static int TLSParseServerRecord(Flow *f, void *tls_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
AppLayerParserResult *output, char need_lock)
{
SCEnter();
@ -391,9 +391,9 @@ static int TLSParseServerRecord(void *tls_state, AppLayerParserState *pstate,
* \param input_len Length in bytes of the received version value
* \param output Pointer to the list of parsed elements
*/
static int TLSParseServerVersion(void *tls_state, AppLayerParserState *pstate,
static int TLSParseServerVersion(Flow *f, void *tls_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
AppLayerParserResult *output, char need_lock)
{
SCEnter();
TlsState *state = (TlsState *)tls_state;
@ -422,9 +422,9 @@ static int TLSParseServerVersion(void *tls_state, AppLayerParserState *pstate,
* \param input_len Length in bytes of the received content type value
* \param output Pointer to the list of parsed elements
*/
static int TLSParseServerContentType(void *tls_state, AppLayerParserState *pstate,
static int TLSParseServerContentType(Flow *f, void *tls_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
AppLayerParserResult *output)
AppLayerParserResult *output, char need_lock)
{
SCEnter();
TlsState *state = (TlsState *)tls_state;

@ -4,6 +4,7 @@
#include "decode.h"
#include "decode-sll.h"
#include "decode-events.h"
#include "util-debug.h"
void DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
@ -18,9 +19,7 @@ void DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u
if (sllh == NULL)
return;
#ifdef DEBUG
printf("DecodeSll: p %p pkt %p sll_protocol %04x\n", p, pkt, ntohs(sllh->sll_protocol));
#endif
SCLogDebug("p %p pkt %p sll_protocol %04x", p, pkt, ntohs(sllh->sll_protocol));
if (ntohs(sllh->sll_protocol) == ETHERNET_TYPE_IP) {
//printf("DecodeSll ip4\n");

@ -691,7 +691,8 @@ int main(int argc, char **argv)
FlowShutdown();
FlowPrintQueueInfo();
StreamTcpFreeConfig(STREAM_VERBOSE);
HTTPAtExitPrintStats();
HTPFreeConfig();
HTPAtExitPrintStats();
/** \todo review whats needed here */
SigGroupCleanup(de_ctx);

Loading…
Cancel
Save