From: Victor Julien Date: Sat, 11 Jul 2015 09:43:34 +0000 (+0200) Subject: http: add test for plain http over connect X-Git-Tag: suricata-3.0RC1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1075ee2f29f523676b7a24ef1628e991931784c;p=thirdparty%2Fsuricata.git http: add test for plain http over connect --- diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 4deef34759..e8da88eb8c 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -6117,6 +6117,354 @@ end: return result; } +/** \test CONNECT with plain text HTTP being tunneled */ +int HTPParserTest17(void) +{ + int result = 0; + Flow *f = NULL; + HtpState *http_state = NULL; + /* CONNECT setup */ + uint8_t httpbuf1[] = "CONNECT abc:443 HTTP/1.1\r\nUser-Agent: Victor/1.0\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint8_t httpbuf2[] = "HTTP/1.1 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + /* plain text HTTP */ + uint8_t httpbuf3[] = "GET / HTTP/1.1\r\nUser-Agent: Victor/1.0\r\n\r\n"; + 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"; + uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */ + TcpSession ssn; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + memset(&ssn, 0, sizeof(ssn)); + + f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80); + if (f == NULL) + goto end; + f->protoctx = &ssn; + f->proto = IPPROTO_TCP; + + StreamTcpInitConfig(TRUE); + + SCMutexLock(&f->m); + int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START, + httpbuf1, httplen1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOCLIENT|STREAM_START, httpbuf2, + httplen2); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER, + httpbuf3, httplen3); + if (r != 0) { + printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOCLIENT, httpbuf4, + httplen4); + if (r != 0) { + printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + + SCMutexUnlock(&f->m); + + http_state = f->alstate; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + htp_tx_t *tx = HTPStateGetTx(http_state, 0); + if (tx == NULL) + goto end; + htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL); + if (tx->request_method_number != HTP_M_CONNECT || + h == NULL || tx->request_protocol_number != HTP_PROTOCOL_1_1) + { + printf("expected method M_POST and got %s: , expected protocol " + "HTTP/1.1 and got %s \n", bstr_util_strdup_to_c(tx->request_method), + bstr_util_strdup_to_c(tx->request_protocol)); + goto end; + } + + if (tx->response_status_number != 200) { + printf("expected response 200 OK and got %"PRId32" %s: , expected protocol " + "HTTP/1.1 and got %s \n", tx->response_status_number, + bstr_util_strdup_to_c(tx->response_message), + bstr_util_strdup_to_c(tx->response_protocol)); + goto end; + } + + tx = HTPStateGetTx(http_state, 1); + if (tx == NULL) + goto end; + h = htp_table_get_index(tx->request_headers, 0, NULL); + if (tx->request_method_number != HTP_M_GET || + h == NULL || tx->request_protocol_number != HTP_PROTOCOL_1_1) + { + printf("expected method M_GET and got %s: , expected protocol " + "HTTP/1.1 and got %s \n", bstr_util_strdup_to_c(tx->request_method), + bstr_util_strdup_to_c(tx->request_protocol)); + goto end; + } + + if (tx->response_status_number != 200) { + printf("expected response 200 OK and got %"PRId32" %s: , expected protocol " + "HTTP/1.1 and got %s \n", tx->response_status_number, + bstr_util_strdup_to_c(tx->response_message), + bstr_util_strdup_to_c(tx->response_protocol)); + goto end; + } + result = 1; +end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); + StreamTcpFreeConfig(TRUE); + if (http_state != NULL) + HTPStateFree(http_state); + UTHFreeFlow(f); + return result; +} + +/** \test CONNECT with plain text HTTP being tunneled */ +int HTPParserTest18(void) +{ + int result = 0; + Flow *f = NULL; + HtpState *http_state = NULL; + /* CONNECT setup */ + uint8_t httpbuf1[] = "CONNECT abc:443 HTTP/1.1\r\nUser-Agent: Victor/1.0\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint8_t httpbuf2[] = "HTTP/1.1 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + /* plain text HTTP */ + uint8_t httpbuf3[] = "GE"; + uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */ + uint8_t httpbuf4[] = "T / HTTP/1.1\r\nUser-Agent: Victor/1.0\r\n\r\n"; + uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */ + uint8_t httpbuf5[] = "HTTP/1.1 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; + uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */ + TcpSession ssn; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + memset(&ssn, 0, sizeof(ssn)); + + f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80); + if (f == NULL) + goto end; + f->protoctx = &ssn; + f->proto = IPPROTO_TCP; + + StreamTcpInitConfig(TRUE); + + SCMutexLock(&f->m); + int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START, + httpbuf1, httplen1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOCLIENT|STREAM_START, httpbuf2, + httplen2); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER, + httpbuf3, httplen3); + if (r != 0) { + printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER, + httpbuf4, httplen4); + if (r != 0) { + printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + + + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOCLIENT, httpbuf5, + httplen5); + if (r != 0) { + printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + + SCMutexUnlock(&f->m); + + http_state = f->alstate; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + htp_tx_t *tx = HTPStateGetTx(http_state, 0); + if (tx == NULL) + goto end; + htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL); + if (tx->request_method_number != HTP_M_CONNECT || + h == NULL || tx->request_protocol_number != HTP_PROTOCOL_1_1) + { + printf("expected method M_POST and got %s: , expected protocol " + "HTTP/1.1 and got %s \n", bstr_util_strdup_to_c(tx->request_method), + bstr_util_strdup_to_c(tx->request_protocol)); + goto end; + } + + if (tx->response_status_number != 200) { + printf("expected response 200 OK and got %"PRId32" %s: , expected protocol " + "HTTP/1.1 and got %s \n", tx->response_status_number, + bstr_util_strdup_to_c(tx->response_message), + bstr_util_strdup_to_c(tx->response_protocol)); + goto end; + } + + tx = HTPStateGetTx(http_state, 1); + if (tx == NULL) + goto end; + h = htp_table_get_index(tx->request_headers, 0, NULL); + if (tx->request_method_number != HTP_M_GET || + h == NULL || tx->request_protocol_number != HTP_PROTOCOL_1_1) + { + printf("expected method M_GET and got %s: , expected protocol " + "HTTP/1.1 and got %s \n", bstr_util_strdup_to_c(tx->request_method), + bstr_util_strdup_to_c(tx->request_protocol)); + goto end; + } + + if (tx->response_status_number != 200) { + printf("expected response 200 OK and got %"PRId32" %s: , expected protocol " + "HTTP/1.1 and got %s \n", tx->response_status_number, + bstr_util_strdup_to_c(tx->response_message), + bstr_util_strdup_to_c(tx->response_protocol)); + goto end; + } + result = 1; +end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); + StreamTcpFreeConfig(TRUE); + if (http_state != NULL) + HTPStateFree(http_state); + UTHFreeFlow(f); + return result; +} + +/** \test CONNECT with TLS content (start of it at least) */ +int HTPParserTest19(void) +{ + int result = 0; + Flow *f = NULL; + HtpState *http_state = NULL; + /* CONNECT setup */ + uint8_t httpbuf1[] = "CONNECT abc:443 HTTP/1.1\r\nUser-Agent: Victor/1.0\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint8_t httpbuf2[] = "HTTP/1.1 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + /* start of TLS/SSL */ + uint8_t httpbuf3[] = "\x16\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; + uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */ + TcpSession ssn; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + memset(&ssn, 0, sizeof(ssn)); + + f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80); + if (f == NULL) + goto end; + f->protoctx = &ssn; + f->proto = IPPROTO_TCP; + + StreamTcpInitConfig(TRUE); + + SCMutexLock(&f->m); + int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START, + httpbuf1, httplen1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOCLIENT|STREAM_START, httpbuf2, + httplen2); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER, + httpbuf3, httplen3); + if (r != 0) { + printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); + SCMutexUnlock(&f->m); + goto end; + } + + SCMutexUnlock(&f->m); + + http_state = f->alstate; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + htp_tx_t *tx = HTPStateGetTx(http_state, 0); + if (tx == NULL) + goto end; + htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL); + if (tx->request_method_number != HTP_M_CONNECT || + h == NULL || tx->request_protocol_number != HTP_PROTOCOL_1_1) + { + printf("expected method M_POST and got %s: , expected protocol " + "HTTP/1.1 and got %s \n", bstr_util_strdup_to_c(tx->request_method), + bstr_util_strdup_to_c(tx->request_protocol)); + goto end; + } + + if (tx->response_status_number != 200) { + printf("expected response 200 OK and got %"PRId32" %s: , expected protocol " + "HTTP/1.1 and got %s \n", tx->response_status_number, + bstr_util_strdup_to_c(tx->response_message), + bstr_util_strdup_to_c(tx->response_protocol)); + goto end; + } + + /* no new tx should have been set up for the tunneled data */ + tx = HTPStateGetTx(http_state, 1); + if (tx != NULL) + goto end; + + result = 1; +end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); + StreamTcpFreeConfig(TRUE); + if (http_state != NULL) + HTPStateFree(http_state); + UTHFreeFlow(f); + return result; +} + #endif /* UNITTESTS */ /** @@ -6163,6 +6511,9 @@ void HTPParserRegisterTests(void) UtRegisterTest("HTPParserTest14", HTPParserTest14, 1); UtRegisterTest("HTPParserTest15", HTPParserTest15, 1); UtRegisterTest("HTPParserTest16", HTPParserTest16, 1); + UtRegisterTest("HTPParserTest17", HTPParserTest17, 1); + UtRegisterTest("HTPParserTest18", HTPParserTest18, 1); + UtRegisterTest("HTPParserTest19", HTPParserTest19, 1); HTPFileParserRegisterTests(); HTPXFFParserRegisterTests();