diff --git a/oisf.yaml b/oisf.yaml index b4a7b67777..9fa0e41dc9 100644 --- a/oisf.yaml +++ b/oisf.yaml @@ -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. diff --git a/src/Makefile.am b/src/Makefile.am index bd79b65ee2..7da16cba2d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/app-layer-dcerpc.c b/src/app-layer-dcerpc.c index f1d3b81723..22bb1f36c9 100644 --- a/src/app-layer-dcerpc.c +++ b/src/app-layer-dcerpc.c @@ -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; diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 3c5e1e02dc..b0f80fb8bf 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -12,7 +12,6 @@ #include "debug.h" #include "decode.h" #include "threads.h" -#include #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 */ } diff --git a/src/app-layer-htp.h b/src/app-layer-htp.h index 83ae4ba352..ecbd6e704a 100644 --- a/src/app-layer-htp.h +++ b/src/app-layer-htp.h @@ -10,9 +10,15 @@ #include +#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 */ diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index e33482df91..a6d165e603 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -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; } diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 77ab19fdc3..9a44199f28 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -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 *); diff --git a/src/app-layer-smb.c b/src/app-layer-smb.c index b8f444f597..25c4dc9d70 100644 --- a/src/app-layer-smb.c +++ b/src/app-layer-smb.c @@ -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; } diff --git a/src/app-layer-tls.c b/src/app-layer-tls.c index 8dbb72d7f0..0033718f0a 100644 --- a/src/app-layer-tls.c +++ b/src/app-layer-tls.c @@ -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; diff --git a/src/decode-sll.c b/src/decode-sll.c index 4d23011cef..98d00b46bd 100644 --- a/src/decode-sll.c +++ b/src/decode-sll.c @@ -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"); diff --git a/src/eidps.c b/src/eidps.c index b25b8ea9e7..88f718290d 100644 --- a/src/eidps.c +++ b/src/eidps.c @@ -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);