/*************************************************************************** * Copyright (c) 2009-2010 Open Information Security Foundation * Copyright (c) 2010-2013 Qualys, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of the Qualys, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /** * @file * * @author Ivan Ristic */ #include #include #include #include "test.h" class ConnectionParsing : public testing::Test { protected: virtual void SetUp() { home = getenv("srcdir"); if (home == NULL) { fprintf(stderr, "This program needs environment variable 'srcdir' set."); exit(EXIT_FAILURE); } cfg = htp_config_create(); htp_config_set_server_personality(cfg, HTP_SERVER_APACHE_2); htp_config_register_urlencoded_parser(cfg); htp_config_register_multipart_parser(cfg); } virtual void TearDown() { htp_connp_destroy_all(connp); htp_config_destroy(cfg); } htp_connp_t *connp; htp_cfg_t *cfg; char *home; }; TEST_F(ConnectionParsing, AdHoc) { int rc = test_run(home, "00-adhoc.t", cfg, &connp); ASSERT_GE(rc, 0); } TEST_F(ConnectionParsing, Get) { int rc = test_run(home, "01-get.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "/?p=%20")); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->query != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->query, "p=%20")); htp_param_t *p = htp_tx_req_get_param(tx, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p->value, " ")); } TEST_F(ConnectionParsing, ApacheHeaderParsing) { int rc = test_run(home, "02-header-test-apache2.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(9, htp_table_size(tx->request_headers)); // Check every header int count = 0; bstr *key = NULL; htp_header_t *h = NULL; for (int i = 0, n = htp_table_size(tx->request_headers); i < n; i++) { h = (htp_header_t *) htp_table_get_index(tx->request_headers, i, &key); switch (count) { case 0: ASSERT_EQ(0, bstr_cmp_c(h->name, "Invalid-Folding")); ASSERT_EQ(0, bstr_cmp_c(h->value, "1")); break; case 1: ASSERT_EQ(0, bstr_cmp_c(h->name, "Valid-Folding")); ASSERT_EQ(0, bstr_cmp_c(h->value, "2 2")); break; case 2: ASSERT_EQ(0, bstr_cmp_c(h->name, "Normal-Header")); ASSERT_EQ(0, bstr_cmp_c(h->value, "3")); break; case 3: ASSERT_EQ(0, bstr_cmp_c(h->name, "Invalid Header Name")); ASSERT_EQ(0, bstr_cmp_c(h->value, "4")); break; case 4: ASSERT_EQ(0, bstr_cmp_c(h->name, "Same-Name-Headers")); ASSERT_EQ(0, bstr_cmp_c(h->value, "5, 6")); break; case 5: ASSERT_EQ(0, bstr_cmp_c(h->name, "Empty-Value-Header")); ASSERT_EQ(0, bstr_cmp_c(h->value, "")); break; case 6: ASSERT_EQ(0, bstr_cmp_c(h->name, "")); ASSERT_EQ(0, bstr_cmp_c(h->value, "8, ")); break; case 7: ASSERT_EQ(0, bstr_cmp_c(h->name, "Header-With-LWS-After")); ASSERT_EQ(0, bstr_cmp_c(h->value, "9")); break; case 8: ASSERT_EQ(0, bstr_cmp_c(h->name, "Header-With-NUL")); ASSERT_EQ(0, bstr_cmp_c_nocasenorzero(h->value, "BEFOREAFTER")); break; } count++; } } TEST_F(ConnectionParsing, PostUrlencoded) { int rc = test_run(home, "03-post-urlencoded.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx1 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx1 != NULL); htp_param_t *p = htp_tx_req_get_param(tx1, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p->value, "0123456789")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx1->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx1->response_progress); htp_header_t *h = (htp_header_t *)htp_table_get_c(tx1->response_headers, "Server"); ASSERT_TRUE(h != NULL); ASSERT_TRUE(h->value != NULL); ASSERT_EQ(0, bstr_cmp_c(h->value, "Apache")); htp_tx_t *tx2 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx2 != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx2->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx2->response_progress); h = (htp_header_t *)htp_table_get_c(tx2->response_headers, "Server"); ASSERT_TRUE(h != NULL); ASSERT_TRUE(h->value != NULL); ASSERT_EQ(0, bstr_cmp_c(h->value, "Apache")); } TEST_F(ConnectionParsing, PostUrlencodedChunked) { int rc = test_run(home, "04-post-urlencoded-chunked.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); htp_param_t *p = htp_tx_req_get_param(tx, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p->value, "0123456789")); ASSERT_EQ(25, tx->request_message_len); ASSERT_EQ(12, tx->request_entity_len); } TEST_F(ConnectionParsing, Expect) { int rc = test_run(home, "05-expect.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); // The interim header from the 100 response should not be among the final headers. htp_header_t *h = (htp_header_t *) htp_table_get_c(tx->request_headers, "Header1"); ASSERT_TRUE(h == NULL); } TEST_F(ConnectionParsing, UriNormal) { int rc = test_run(home, "06-uri-normal.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); } TEST_F(ConnectionParsing, PipelinedConn) { int rc = test_run(home, "07-pipelined-connection.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); ASSERT_TRUE(connp->conn->flags & HTP_CONN_PIPELINED); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); } TEST_F(ConnectionParsing, NotPipelinedConn) { int rc = test_run(home, "08-not-pipelined-connection.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); ASSERT_FALSE(connp->conn->flags & HTP_CONN_PIPELINED); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_FALSE(tx->flags & HTP_MULTI_PACKET_HEAD); } TEST_F(ConnectionParsing, MultiPacketRequest) { int rc = test_run(home, "09-multi-packet-request-head.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_MULTI_PACKET_HEAD); } TEST_F(ConnectionParsing, HeaderHostParsing) { int rc = test_run(home, "10-host-in-headers.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(4, htp_list_size(connp->conn->transactions)); htp_tx_t *tx1 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx1 != NULL); ASSERT_TRUE(tx1->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx1->request_hostname, "www.example.com")); htp_tx_t *tx2 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx2 != NULL); ASSERT_TRUE(tx2->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx2->request_hostname, "www.example.com.")); htp_tx_t *tx3 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 2); ASSERT_TRUE(tx3 != NULL); ASSERT_TRUE(tx3->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx3->request_hostname, "www.example.com")); htp_tx_t *tx4 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 3); ASSERT_TRUE(tx4 != NULL); ASSERT_TRUE(tx4->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx4->request_hostname, "www.example.com")); } TEST_F(ConnectionParsing, ResponseWithoutContentLength) { int rc = test_run(home, "11-response-stream-closure.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); } TEST_F(ConnectionParsing, FailedConnectRequest) { int rc = test_run(home, "12-connect-request.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "CONNECT")); ASSERT_EQ(405, tx->response_status_number); } TEST_F(ConnectionParsing, CompressedResponseContentType) { int rc = test_run(home, "13-compressed-response-gzip-ct.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(187, tx->response_message_len); ASSERT_EQ(225, tx->response_entity_len); } TEST_F(ConnectionParsing, CompressedResponseChunked) { int rc = test_run(home, "14-compressed-response-gzip-chunked.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(28261, tx->response_message_len); ASSERT_EQ(159590, tx->response_entity_len); } TEST_F(ConnectionParsing, SuccessfulConnectRequest) { int rc = test_run(home, "15-connect-complete.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); // TODO: Update the test_run() function to provide better // simulation of real traffic. At the moment, it does not // invoke inbound parsing after outbound parsing returns // HTP_DATA_OTHER, which is why the check below fails. //ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "CONNECT")); ASSERT_EQ(200, tx->response_status_number); } TEST_F(ConnectionParsing, ConnectRequestWithExtraData) { int rc = test_run(home, "16-connect-extra.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx1 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx1 != NULL); ASSERT_TRUE(htp_tx_is_complete(tx1)); htp_tx_t *tx2 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx2 != NULL); ASSERT_TRUE(htp_tx_is_complete(tx2)); } TEST_F(ConnectionParsing, Multipart) { int rc = test_run(home, "17-multipart-1.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); htp_param_t *field1 = htp_tx_req_get_param(tx, "field1", 6); ASSERT_TRUE(field1 != NULL); ASSERT_EQ(0, bstr_cmp_c(field1->value, "0123456789")); htp_param_t *field2 = htp_tx_req_get_param(tx, "field2", 6); ASSERT_TRUE(field2 != NULL); ASSERT_EQ(0, bstr_cmp_c(field2->value, "9876543210")); } TEST_F(ConnectionParsing, CompressedResponseDeflate) { int rc = test_run(home, "18-compressed-response-deflate.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(755, tx->response_message_len); ASSERT_EQ(1433, tx->response_entity_len); } TEST_F(ConnectionParsing, UrlEncoded) { int rc = test_run(home, "19-urlencoded-test.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "POST")); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "/?p=1&q=2")); htp_param_t *body_p = htp_tx_req_get_param_ex(tx, HTP_SOURCE_BODY, "p", 1); ASSERT_TRUE(body_p != NULL); ASSERT_EQ(0, bstr_cmp_c(body_p->value, "3")); htp_param_t *body_q = htp_tx_req_get_param_ex(tx, HTP_SOURCE_BODY, "q", 1); ASSERT_TRUE(body_q != NULL); ASSERT_EQ(0, bstr_cmp_c(body_q->value, "4")); htp_param_t *body_z = htp_tx_req_get_param_ex(tx, HTP_SOURCE_BODY, "z", 1); ASSERT_TRUE(body_z != NULL); ASSERT_EQ(0, bstr_cmp_c(body_z->value, "5")); } TEST_F(ConnectionParsing, AmbiguousHost) { int rc = test_run(home, "20-ambiguous-host.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(5, htp_list_size(connp->conn->transactions)); htp_tx_t *tx1 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx1 != NULL); ASSERT_TRUE(htp_tx_is_complete(tx1)); ASSERT_FALSE(tx1->flags & HTP_HOST_AMBIGUOUS); htp_tx_t *tx2 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx2 != NULL); ASSERT_TRUE(htp_tx_is_complete(tx2)); ASSERT_TRUE(tx2->flags & HTP_HOST_AMBIGUOUS); ASSERT_TRUE(tx2->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx2->request_hostname, "example.com")); htp_tx_t *tx3 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 2); ASSERT_TRUE(tx3 != NULL); ASSERT_TRUE(htp_tx_is_complete(tx3)); ASSERT_FALSE(tx3->flags & HTP_HOST_AMBIGUOUS); ASSERT_TRUE(tx3->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx3->request_hostname, "www.example.com")); ASSERT_EQ(8001, tx3->request_port_number); htp_tx_t *tx4 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 3); ASSERT_TRUE(tx4 != NULL); ASSERT_TRUE(htp_tx_is_complete(tx4)); ASSERT_TRUE(tx4->flags & HTP_HOST_AMBIGUOUS); ASSERT_TRUE(tx4->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx4->request_hostname, "www.example.com")); ASSERT_EQ(8002, tx4->request_port_number); htp_tx_t *tx5 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 4); ASSERT_TRUE(tx5 != NULL); ASSERT_TRUE(htp_tx_is_complete(tx5)); ASSERT_FALSE(tx5->flags & HTP_HOST_AMBIGUOUS); ASSERT_TRUE(tx5->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx5->request_hostname, "www.example.com")); ASSERT_EQ(80, tx5->request_port_number); } TEST_F(ConnectionParsing, Http_0_9) { int rc = test_run(home, "21-http09.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); ASSERT_FALSE(connp->conn->flags & HTP_CONN_HTTP_0_9_EXTRA); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); } TEST_F(ConnectionParsing, PhpParamProcessing) { cfg->parameter_processor = htp_php_parameter_processor; int rc = test_run(home, "22-php-param-processing.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); htp_param_t *p1 = htp_tx_req_get_param(tx, "p_q_", 4); ASSERT_TRUE(p1 != NULL); ASSERT_EQ(0, bstr_cmp_c(p1->value, "1")); htp_param_t *p2 = htp_tx_req_get_param(tx, "q", 1); ASSERT_TRUE(p2 != NULL); ASSERT_EQ(0, bstr_cmp_c(p2->value, "2")); htp_param_t *p3 = htp_tx_req_get_param(tx, "z_w", 3); ASSERT_TRUE(p3 != NULL); ASSERT_EQ(0, bstr_cmp_c(p3->value, "3")); } TEST_F(ConnectionParsing, Http11HostMissing) { int rc = test_run(home, "22-http_1_1-host_missing", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_HOST_MISSING); } TEST_F(ConnectionParsing, Http_0_9_Multiple) { int rc = test_run(home, "23-http09-multiple.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); } TEST_F(ConnectionParsing, Http_0_9_Explicit) { int rc = test_run(home, "24-http09-explicit.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, tx->is_protocol_0_9); } TEST_F(ConnectionParsing, SmallChunks) { int rc = test_run(home, "25-small-chunks.t", cfg, &connp); ASSERT_GE(rc, 0); } static int ConnectionParsing_RequestHeaderData_REQUEST_HEADER_DATA(htp_tx_data_t *d) { static int counter = 0; switch (counter) { case 0: if (!((d->len == 11) && (memcmp(d->data, "User-Agent:", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 0"); counter = -1; } break; case 1: if (!((d->len == 5) && (memcmp(d->data, " Test", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 1"); counter = -1; } break; case 2: if (!((d->len == 5) && (memcmp(d->data, " User", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 2"); counter = -1; } break; case 3: if (!((d->len == 30) && (memcmp(d->data, " Agent\nHost: www.example.com\n\n", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 3"); counter = -1; } break; default: if (counter >= 0) { SCOPED_TRACE("Seen more than 4 chunks"); counter = -1; } break; } if (counter >= 0) { counter++; } htp_tx_set_user_data(d->tx, &counter); return HTP_OK; } TEST_F(ConnectionParsing, RequestHeaderData) { htp_config_register_request_header_data(cfg, ConnectionParsing_RequestHeaderData_REQUEST_HEADER_DATA); int rc = test_run(home, "26-request-headers-raw.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); int *counter = (int *) htp_tx_get_user_data(tx); ASSERT_TRUE(counter != NULL); ASSERT_EQ(4, *counter); } static int ConnectionParsing_RequestTrailerData_REQUEST_TRAILER_DATA(htp_tx_data_t *d) { static int counter = 0; switch (counter) { case 0: if (!((d->len == 7) && (memcmp(d->data, "Cookie:", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 0"); counter = -1; } break; case 1: if (!((d->len == 6) && (memcmp(d->data, " 2\r\n\r\n", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 1"); counter = -2; } break; default: if (counter >= 0) { SCOPED_TRACE("Seen more than 4 chunks"); counter = -3; } break; } if (counter >= 0) { counter++; } htp_tx_set_user_data(d->tx, &counter); return HTP_OK; } TEST_F(ConnectionParsing, RequestTrailerData) { htp_config_register_request_trailer_data(cfg, ConnectionParsing_RequestTrailerData_REQUEST_TRAILER_DATA); int rc = test_run(home, "27-request-trailer-raw.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); int *counter = (int *) htp_tx_get_user_data(tx); ASSERT_TRUE(counter != NULL); ASSERT_EQ(2, *counter); } static int ConnectionParsing_ResponseHeaderData_RESPONSE_HEADER_DATA(htp_tx_data_t *d) { static int counter = 0; switch (counter) { case 0: if (!((d->len == 5) && (memcmp(d->data, "Date:", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 0"); counter = -1; } break; case 1: if (!((d->len == 5) && (memcmp(d->data, " Mon,", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 1"); counter = -2; } break; case 2: if (!((d->len == 34) && (memcmp(d->data, " 31 Aug 2009 20:25:50 GMT\r\nServer:", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 2"); counter = -3; } break; case 3: if (!((d->len == 83) && (memcmp(d->data, " Apache\r\nConnection: close\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\n\r\n", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 3"); counter = -4; } break; default: if (counter >= 0) { SCOPED_TRACE("Seen more than 4 chunks"); counter = -5; } break; } if (counter >= 0) { counter++; } htp_tx_set_user_data(d->tx, &counter); return HTP_OK; } TEST_F(ConnectionParsing, ResponseHeaderData) { htp_config_register_response_header_data(cfg, ConnectionParsing_ResponseHeaderData_RESPONSE_HEADER_DATA); int rc = test_run(home, "28-response-headers-raw.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); int *counter = (int *) htp_tx_get_user_data(tx); ASSERT_TRUE(counter != NULL); ASSERT_EQ(4, *counter); } static int ConnectionParsing_ResponseTrailerData_RESPONSE_TRAILER_DATA(htp_tx_data_t *d) { static int counter = 0; switch (counter) { case 0: if (!((d->len == 11) && (memcmp(d->data, "Set-Cookie:", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 0"); counter = -1; } break; case 1: if (!((d->len == 6) && (memcmp(d->data, " name=", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 1"); counter = -2; } break; case 2: if (!((d->len == 22) && (memcmp(d->data, "value\r\nAnother-Header:", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 1"); counter = -3; } break; case 3: if (!((d->len == 17) && (memcmp(d->data, " Header-Value\r\n\r\n", d->len) == 0))) { SCOPED_TRACE("Mismatch in chunk 1"); counter = -4; } break; default: if (counter >= 0) { SCOPED_TRACE("Seen more than 4 chunks"); counter = -5; } break; } if (counter >= 0) { counter++; } htp_tx_set_user_data(d->tx, &counter); return HTP_OK; } TEST_F(ConnectionParsing, ResponseTrailerData) { htp_config_register_response_trailer_data(cfg, ConnectionParsing_ResponseTrailerData_RESPONSE_TRAILER_DATA); int rc = test_run(home, "29-response-trailer-raw.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); int *counter = (int *) htp_tx_get_user_data(tx); ASSERT_TRUE(counter != NULL); ASSERT_EQ(4, *counter); } TEST_F(ConnectionParsing, GetIPv6) { int rc = test_run(home, "30-get-ipv6.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->request_method != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_TRUE(tx->request_uri != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "http://[::1]:8080/?p=%20")); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->hostname, "[::1]")); ASSERT_EQ(8080, tx->parsed_uri->port_number); ASSERT_TRUE(tx->parsed_uri->query != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->query, "p=%20")); htp_param_t *p = htp_tx_req_get_param(tx, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_TRUE(p->value != NULL); ASSERT_EQ(0, bstr_cmp_c(p->value, " ")); } TEST_F(ConnectionParsing, GetRequestLineNul) { int rc = test_run(home, "31-get-request-line-nul.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->request_uri != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "/?p=%20")); } TEST_F(ConnectionParsing, InvalidHostname1) { int rc = test_run(home, "32-invalid-hostname.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_HOSTH_INVALID); ASSERT_TRUE(tx->flags & HTP_HOSTU_INVALID); ASSERT_TRUE(tx->flags & HTP_HOST_INVALID); } TEST_F(ConnectionParsing, InvalidHostname2) { int rc = test_run(home, "33-invalid-hostname.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_FALSE(tx->flags & HTP_HOSTH_INVALID); ASSERT_TRUE(tx->flags & HTP_HOSTU_INVALID); ASSERT_TRUE(tx->flags & HTP_HOST_INVALID); } TEST_F(ConnectionParsing, InvalidHostname3) { int rc = test_run(home, "34-invalid-hostname.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_HOSTH_INVALID); ASSERT_FALSE(tx->flags & HTP_HOSTU_INVALID); ASSERT_TRUE(tx->flags & HTP_HOST_INVALID); } TEST_F(ConnectionParsing, API_connp_get_connection) { int rc = test_run(home, "34-invalid-hostname.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(connp->conn, htp_connp_get_connection(connp)); } TEST_F(ConnectionParsing, EarlyResponse) { int rc = test_run(home, "35-early-response.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); } TEST_F(ConnectionParsing, InvalidRequest1) { int rc = test_run(home, "36-invalid-request-1-invalid-c-l.t", cfg, &connp); ASSERT_LT(rc, 0); // Expect error. htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_HEADERS, tx->request_progress); ASSERT_TRUE(tx->flags & HTP_REQUEST_INVALID); ASSERT_TRUE(tx->flags & HTP_REQUEST_INVALID_C_L); ASSERT_TRUE(tx->request_hostname != NULL); } TEST_F(ConnectionParsing, InvalidRequest2) { int rc = test_run(home, "37-invalid-request-2-t-e-and-c-l.t", cfg, &connp); ASSERT_GE(rc, 0); // No error, flags only. htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_TRUE(tx->flags & HTP_REQUEST_SMUGGLING); ASSERT_TRUE(tx->request_hostname != NULL); } TEST_F(ConnectionParsing, InvalidRequest3) { int rc = test_run(home, "38-invalid-request-3-invalid-t-e.t", cfg, &connp); ASSERT_LT(rc, 0); // Expect error. htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_HEADERS, tx->request_progress); ASSERT_TRUE(tx->flags & HTP_REQUEST_INVALID); ASSERT_TRUE(tx->flags & HTP_REQUEST_INVALID_T_E); ASSERT_TRUE(tx->request_hostname != NULL); } TEST_F(ConnectionParsing, AutoDestroyCrash) { htp_config_set_tx_auto_destroy(cfg, 1); int rc = test_run(home, "39-auto-destroy-crash.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(4, htp_list_size(connp->conn->transactions)); } TEST_F(ConnectionParsing, AuthBasic) { int rc = test_run(home, "40-auth-basic.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_AUTH_BASIC, tx->request_auth_type); ASSERT_TRUE(tx->request_auth_username != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_auth_username, "ivanr")); ASSERT_TRUE(tx->request_auth_password != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_auth_password, "secret")); } TEST_F(ConnectionParsing, AuthDigest) { int rc = test_run(home, "41-auth-digest.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_AUTH_DIGEST, tx->request_auth_type); ASSERT_TRUE(tx->request_auth_username != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_auth_username, "ivanr")); ASSERT_TRUE(tx->request_auth_password == NULL); } TEST_F(ConnectionParsing, AuthBearer) { int rc = test_run(home, "100-auth-bearer.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_AUTH_BEARER, tx->request_auth_type); ASSERT_TRUE(tx->request_auth_username == NULL); ASSERT_TRUE(tx->request_auth_password == NULL); } TEST_F(ConnectionParsing, Unknown_MethodOnly) { int rc = test_run(home, "42-unknown-method_only.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_TRUE(tx->request_method != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "HELLO")); ASSERT_TRUE(tx->request_uri == NULL); ASSERT_EQ(1, tx->is_protocol_0_9); } TEST_F(ConnectionParsing, InvalidProtocol) { int rc = test_run(home, "43-invalid-protocol.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_PROTOCOL_INVALID, tx->request_protocol_number); } TEST_F(ConnectionParsing, AuthBasicInvalid) { int rc = test_run(home, "44-auth-basic-invalid.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_AUTH_BASIC, tx->request_auth_type); ASSERT_TRUE(tx->request_auth_username == NULL); ASSERT_TRUE(tx->request_auth_password == NULL); ASSERT_TRUE(tx->flags & HTP_AUTH_INVALID); } TEST_F(ConnectionParsing, AuthDigestUnquotedUsername) { int rc = test_run(home, "45-auth-digest-unquoted-username.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_AUTH_DIGEST, tx->request_auth_type); ASSERT_TRUE(tx->request_auth_username == NULL); ASSERT_TRUE(tx->request_auth_password == NULL); ASSERT_TRUE(tx->flags & HTP_AUTH_INVALID); } TEST_F(ConnectionParsing, AuthDigestInvalidUsername1) { int rc = test_run(home, "46-auth-digest-invalid-username.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_AUTH_DIGEST, tx->request_auth_type); ASSERT_TRUE(tx->request_auth_username == NULL); ASSERT_TRUE(tx->request_auth_password == NULL); ASSERT_TRUE(tx->flags & HTP_AUTH_INVALID); } TEST_F(ConnectionParsing, AuthUnrecognized) { int rc = test_run(home, "47-auth-unrecognized.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_AUTH_UNRECOGNIZED, tx->request_auth_type); ASSERT_TRUE(tx->request_auth_username == NULL); ASSERT_TRUE(tx->request_auth_password == NULL); } TEST_F(ConnectionParsing, InvalidResponseHeaders1) { int rc = test_run(home, "48-invalid-response-headers-1.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); ASSERT_EQ(8, htp_table_size(tx->response_headers)); htp_header_t *h_empty = (htp_header_t *) htp_table_get_c(tx->response_headers, ""); ASSERT_TRUE(h_empty != NULL); ASSERT_EQ(0, bstr_cmp_c(h_empty->value, "No Colon")); ASSERT_TRUE(h_empty->flags & HTP_FIELD_INVALID); ASSERT_TRUE(h_empty->flags & HTP_FIELD_UNPARSEABLE); htp_header_t *h_lws = (htp_header_t *) htp_table_get_c(tx->response_headers, "Lws"); ASSERT_TRUE(h_lws != NULL); ASSERT_EQ(0, bstr_cmp_c(h_lws->value, "After Header Name")); ASSERT_TRUE(h_lws->flags & HTP_FIELD_INVALID); htp_header_t *h_nottoken = (htp_header_t *) htp_table_get_c(tx->response_headers, "Header@Name"); ASSERT_TRUE(h_nottoken != NULL); ASSERT_EQ(0, bstr_cmp_c(h_nottoken->value, "Not Token")); ASSERT_TRUE(h_nottoken->flags & HTP_FIELD_INVALID); } TEST_F(ConnectionParsing, InvalidResponseHeaders2) { int rc = test_run(home, "49-invalid-response-headers-2.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); ASSERT_EQ(6, htp_table_size(tx->response_headers)); htp_header_t *h_empty = (htp_header_t *) htp_table_get_c(tx->response_headers, ""); ASSERT_TRUE(h_empty != NULL); ASSERT_EQ(0, bstr_cmp_c(h_empty->value, "Empty Name")); ASSERT_TRUE(h_empty->flags & HTP_FIELD_INVALID); } TEST_F(ConnectionParsing, Util) { int rc = test_run(home, "50-util.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); char *in_state = htp_connp_in_state_as_string(tx->connp); ASSERT_TRUE(in_state != NULL); char *out_state = htp_connp_out_state_as_string(tx->connp); ASSERT_TRUE(out_state != NULL); char *request_progress = htp_tx_request_progress_as_string(tx); ASSERT_TRUE(request_progress != NULL); char *response_progress = htp_tx_response_progress_as_string(tx); ASSERT_TRUE(response_progress != NULL); FILE *null = fopen("/dev/null", "w"); ASSERT_TRUE(null != NULL); fprint_bstr(null, "test", NULL); fprint_bstr(null, "test", tx->request_line); fprint_raw_data(null, "test", bstr_ptr(tx->request_line), bstr_len(tx->request_line)); fprint_raw_data_ex(null, "test", bstr_ptr(tx->request_line), 0, bstr_len(tx->request_line)); // Message too long. tx->connp->cfg->log_level = HTP_LOG_ERROR; char long_message[1300]; for (size_t i = 0; i < 1299; i++) { long_message[i] = 'X'; } long_message[1299] = '\0'; htp_log(tx->connp, __FILE__, __LINE__, HTP_LOG_ERROR, 0, long_message); ASSERT_TRUE(tx->connp->last_error != NULL); ASSERT_TRUE(tx->connp->last_error->msg != NULL); ASSERT_EQ(1023, strlen(tx->connp->last_error->msg)); ASSERT_EQ('+', tx->connp->last_error->msg[1022]); // A message that should not be logged. size_t log_message_count = htp_list_size(tx->connp->conn->messages); tx->connp->cfg->log_level = HTP_LOG_NONE; htp_log(tx->connp, __FILE__, __LINE__, HTP_LOG_ERROR, 0, "Log message"); ASSERT_EQ(log_message_count, htp_list_size(tx->connp->conn->messages)); } TEST_F(ConnectionParsing, GetIPv6Invalid) { int rc = test_run(home, "51-get-ipv6-invalid.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->request_method != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_TRUE(tx->request_uri != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "http://[::1:8080/?p=%20")); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->hostname, "[::1:8080")); } TEST_F(ConnectionParsing, InvalidPath) { int rc = test_run(home, "52-invalid-path.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->request_method != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_TRUE(tx->request_uri != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "invalid/path?p=%20")); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->path != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->path, "invalid/path")); } TEST_F(ConnectionParsing, PathUtf8_None) { int rc = test_run(home, "53-path-utf8-none.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_FALSE(tx->flags & HTP_PATH_UTF8_VALID); ASSERT_FALSE(tx->flags & HTP_PATH_UTF8_OVERLONG); ASSERT_FALSE(tx->flags & HTP_PATH_HALF_FULL_RANGE); } TEST_F(ConnectionParsing, PathUtf8_Valid) { int rc = test_run(home, "54-path-utf8-valid.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_VALID); } TEST_F(ConnectionParsing, PathUtf8_Overlong2) { int rc = test_run(home, "55-path-utf8-overlong-2.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_OVERLONG); } TEST_F(ConnectionParsing, PathUtf8_Overlong3) { int rc = test_run(home, "56-path-utf8-overlong-3.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_OVERLONG); } TEST_F(ConnectionParsing, PathUtf8_Overlong4) { int rc = test_run(home, "57-path-utf8-overlong-4.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_OVERLONG); } TEST_F(ConnectionParsing, PathUtf8_Invalid) { int rc = test_run(home, "58-path-utf8-invalid.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_INVALID); ASSERT_FALSE(tx->flags & HTP_PATH_UTF8_VALID); } TEST_F(ConnectionParsing, PathUtf8_FullWidth) { int rc = test_run(home, "59-path-utf8-fullwidth.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_HALF_FULL_RANGE); } TEST_F(ConnectionParsing, PathUtf8_Decode_Valid) { htp_config_set_utf8_convert_bestfit(cfg, HTP_DECODER_URL_PATH, 1); int rc = test_run(home, "54-path-utf8-valid.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->path != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->path, "/Ristic.txt")); } TEST_F(ConnectionParsing, PathUtf8_Decode_Overlong2) { htp_config_set_utf8_convert_bestfit(cfg, HTP_DECODER_URL_PATH, 1); int rc = test_run(home, "55-path-utf8-overlong-2.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_OVERLONG); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->path != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->path, "/&.txt")); } TEST_F(ConnectionParsing, PathUtf8_Decode_Overlong3) { htp_config_set_utf8_convert_bestfit(cfg, HTP_DECODER_URL_PATH, 1); int rc = test_run(home, "56-path-utf8-overlong-3.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_OVERLONG); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->path != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->path, "/&.txt")); } TEST_F(ConnectionParsing, PathUtf8_Decode_Overlong4) { htp_config_set_utf8_convert_bestfit(cfg, HTP_DECODER_URL_PATH, 1); int rc = test_run(home, "57-path-utf8-overlong-4.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_OVERLONG); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->path != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->path, "/&.txt")); } TEST_F(ConnectionParsing, PathUtf8_Decode_Invalid) { htp_config_set_utf8_convert_bestfit(cfg, HTP_DECODER_URL_PATH, 1); int rc = test_run(home, "58-path-utf8-invalid.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_UTF8_INVALID); ASSERT_FALSE(tx->flags & HTP_PATH_UTF8_VALID); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->path != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->path, "/Ristic?.txt")); } TEST_F(ConnectionParsing, PathUtf8_Decode_FullWidth) { htp_config_set_utf8_convert_bestfit(cfg, HTP_DECODER_URL_PATH, 1); int rc = test_run(home, "59-path-utf8-fullwidth.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->flags & HTP_PATH_HALF_FULL_RANGE); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->path != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->path, "/&.txt")); } TEST_F(ConnectionParsing, RequestCookies) { int rc = test_run(home, "60-request-cookies.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(3, htp_table_size(tx->request_cookies)); bstr *key = NULL; bstr *value = NULL; value = (bstr *) htp_table_get_index(tx->request_cookies, 0, &key); ASSERT_TRUE(key != NULL); ASSERT_TRUE(value != NULL); ASSERT_EQ(0, bstr_cmp_c(key, "p")); ASSERT_EQ(0, bstr_cmp_c(value, "1")); value = (bstr *) htp_table_get_index(tx->request_cookies, 1, &key); ASSERT_TRUE(key != NULL); ASSERT_TRUE(value != NULL); ASSERT_EQ(0, bstr_cmp_c(key, "q")); ASSERT_EQ(0, bstr_cmp_c(value, "2")); value = (bstr *) htp_table_get_index(tx->request_cookies, 2, &key); ASSERT_TRUE(key != NULL); ASSERT_TRUE(value != NULL); ASSERT_EQ(0, bstr_cmp_c(key, "z")); ASSERT_EQ(0, bstr_cmp_c(value, "")); } TEST_F(ConnectionParsing, EmptyLineBetweenRequests) { int rc = test_run(home, "61-empty-line-between-requests.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx != NULL); /*part of previous request body ASSERT_EQ(1, tx->request_ignored_lines);*/ } TEST_F(ConnectionParsing, PostNoBody) { int rc = test_run(home, "62-post-no-body.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx1 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx1 != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx1->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx1->response_progress); htp_tx_t *tx2 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx2 != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx2->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx2->response_progress); } TEST_F(ConnectionParsing, PostChunkedInvalid1) { int rc = test_run(home, "63-post-chunked-invalid-1.t", cfg, &connp); ASSERT_LT(rc, 0); // Expect error. } TEST_F(ConnectionParsing, PostChunkedInvalid2) { int rc = test_run(home, "64-post-chunked-invalid-2.t", cfg, &connp); ASSERT_LT(rc, 0); // Expect error. } TEST_F(ConnectionParsing, PostChunkedInvalid3) { int rc = test_run(home, "65-post-chunked-invalid-3.t", cfg, &connp); ASSERT_LT(rc, 0); // Expect error. } TEST_F(ConnectionParsing, PostChunkedSplitChunk) { int rc = test_run(home, "66-post-chunked-split-chunk.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); htp_param_t *p = htp_tx_req_get_param(tx, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_TRUE(p->value != NULL); ASSERT_EQ(0, bstr_cmp_c(p->value, "0123456789")); } TEST_F(ConnectionParsing, LongRequestLine1) { int rc = test_run(home, "67-long-request-line.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "/0123456789/0123456789/")); } TEST_F(ConnectionParsing, LongRequestLine2) { htp_config_set_field_limits(cfg, 0, 16); int rc = test_run(home, "67-long-request-line.t", cfg, &connp); ASSERT_LT(rc, 0); // Expect error. htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_LINE, tx->request_progress); } TEST_F(ConnectionParsing, InvalidRequestHeader) { int rc = test_run(home, "68-invalid-request-header.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); htp_header_t *h = (htp_header_t *) htp_table_get_c(tx->request_headers, "Header-With-NUL"); ASSERT_TRUE(h != NULL); ASSERT_EQ(0, bstr_cmp_c_nocasenorzero(h->value, "BEFORE AFTER")); } TEST_F(ConnectionParsing, TestGenericPersonality) { htp_config_set_server_personality(cfg, HTP_SERVER_IDS); int rc = test_run(home, "02-header-test-apache2.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); } TEST_F(ConnectionParsing, LongResponseHeader) { htp_config_set_field_limits(cfg, 0, 16); int rc = test_run(home, "69-long-response-header.t", cfg, &connp); ASSERT_LT(rc, 0); // Expect error. htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); //error first ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_HEADERS, tx->response_progress); } TEST_F(ConnectionParsing, ResponseInvalidChunkLength) { int rc = test_run(home, "70-response-invalid-chunk-length.t", cfg, &connp); ASSERT_EQ(rc, 1); // Expect success as we're very liberal } TEST_F(ConnectionParsing, ResponseSplitChunk) { int rc = test_run(home, "71-response-split-chunk.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } TEST_F(ConnectionParsing, ResponseBody) { int rc = test_run(home, "72-response-split-body.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } TEST_F(ConnectionParsing, ResponseContainsTeAndCl) { int rc = test_run(home, "73-response-te-and-cl.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); ASSERT_TRUE(tx->flags & HTP_REQUEST_SMUGGLING); } TEST_F(ConnectionParsing, ResponseMultipleCl) { int rc = test_run(home, "74-response-multiple-cl.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); ASSERT_TRUE(tx->flags & HTP_REQUEST_SMUGGLING); htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers, "Content-Length"); ASSERT_TRUE(h != NULL); ASSERT_TRUE(h->value != NULL); ASSERT_TRUE(h->flags & HTP_FIELD_REPEATED); ASSERT_EQ(0, bstr_cmp_c(h->value, "12")); } TEST_F(ConnectionParsing, ResponseMultipleClMismatch) { int rc = test_run(home, "88-response-multiple-cl-mismatch.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); ASSERT_TRUE(tx->flags & HTP_REQUEST_SMUGGLING); htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers, "Content-Length"); ASSERT_TRUE(h != NULL); ASSERT_TRUE(h->value != NULL); ASSERT_TRUE(h->flags & HTP_FIELD_REPEATED); ASSERT_EQ(0, bstr_cmp_c(h->value, "12")); ASSERT_EQ(2, htp_list_size(tx->conn->messages)); htp_log_t *log = (htp_log_t *) htp_list_get(tx->conn->messages, 1); ASSERT_TRUE(log != NULL); ASSERT_EQ(0, strcmp(log->msg, "Ambiguous response C-L value")); ASSERT_EQ(HTP_LOG_WARNING, log->level); } TEST_F(ConnectionParsing, ResponseInvalidCl) { int rc = test_run(home, "75-response-invalid-cl.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); ASSERT_FALSE(tx->flags & HTP_REQUEST_SMUGGLING); } TEST_F(ConnectionParsing, ResponseNoBody) { int rc = test_run(home, "76-response-no-body.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx1 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx1 != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx1->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx1->response_progress); htp_header_t *h = (htp_header_t *)htp_table_get_c(tx1->response_headers, "Server"); ASSERT_TRUE(h != NULL); ASSERT_TRUE(h->value != NULL); ASSERT_EQ(0, bstr_cmp_c(h->value, "Apache")); htp_tx_t *tx2 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx2 != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx2->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx2->response_progress); ASSERT_TRUE(tx1 != tx2); } TEST_F(ConnectionParsing, ResponseFoldedHeaders) { int rc = test_run(home, "77-response-folded-headers.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx1 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx1 != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx1->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx1->response_progress); htp_header_t *h = (htp_header_t *)htp_table_get_c(tx1->response_headers, "Server"); ASSERT_TRUE(h != NULL); ASSERT_TRUE(h->value != NULL); ASSERT_EQ(0, bstr_cmp_c(h->value, "Apache Server")); htp_tx_t *tx2 = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx2 != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx2->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx2->response_progress); } TEST_F(ConnectionParsing, ResponseNoStatusHeaders) { int rc = test_run(home, "78-response-no-status-headers.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } TEST_F(ConnectionParsing, ConnectInvalidHostport) { int rc = test_run(home, "79-connect-invalid-hostport.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); } TEST_F(ConnectionParsing, HostnameInvalid1) { int rc = test_run(home, "80-hostname-invalid-1.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); } TEST_F(ConnectionParsing, HostnameInvalid2) { int rc = test_run(home, "81-hostname-invalid-2.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); } TEST_F(ConnectionParsing, Put) { int rc = test_run(home, "82-put.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_hostname, "www.example.com")); } TEST_F(ConnectionParsing, AuthDigestInvalidUsername2) { int rc = test_run(home, "83-auth-digest-invalid-username-2.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_AUTH_DIGEST, tx->request_auth_type); ASSERT_TRUE(tx->request_auth_username == NULL); ASSERT_TRUE(tx->request_auth_password == NULL); ASSERT_TRUE(tx->flags & HTP_AUTH_INVALID); } TEST_F(ConnectionParsing, ResponseNoStatusHeaders2) { int rc = test_run(home, "84-response-no-status-headers-2.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } /* TEST_F(ConnectionParsing, ZeroByteRequestTimeout) { int rc = test_run(home, "85-zero-byte-request-timeout.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_NOT_STARTED, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } */ TEST_F(ConnectionParsing, PartialRequestTimeout) { int rc = test_run(home, "86-partial-request-timeout.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } TEST_F(ConnectionParsing, IncorrectHostAmbiguousWarning) { int rc = test_run(home, "87-issue-55-incorrect-host-ambiguous-warning.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(tx->parsed_uri_raw != NULL); ASSERT_TRUE(tx->parsed_uri_raw->port != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri_raw->port, "443")); ASSERT_TRUE(tx->parsed_uri_raw->hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri_raw->hostname, "www.example.com")); ASSERT_EQ(443, tx->parsed_uri_raw->port_number); ASSERT_TRUE(tx->request_hostname != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_hostname, "www.example.com")); ASSERT_FALSE(tx->flags & HTP_HOST_AMBIGUOUS); } TEST_F(ConnectionParsing, GetWhitespace) { int rc = test_run(home, "89-get-whitespace.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, " GET")); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "/?p=%20")); ASSERT_TRUE(tx->parsed_uri != NULL); ASSERT_TRUE(tx->parsed_uri->query != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->parsed_uri->query, "p=%20")); htp_param_t *p = htp_tx_req_get_param(tx, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p->value, " ")); } TEST_F(ConnectionParsing, RequestUriTooLarge) { int rc = test_run(home, "90-request-uri-too-large.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } TEST_F(ConnectionParsing, RequestInvalid) { int rc = test_run(home, "91-request-unexpected-body.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "POST")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_NOT_STARTED, tx->response_progress); } TEST_F(ConnectionParsing, Http_0_9_MethodOnly) { int rc = test_run(home, "92-http_0_9-method_only.t", cfg, &connp); ASSERT_GE(rc, 0); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_TRUE(tx->request_method != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_EQ(0, bstr_cmp_c(tx->request_uri, "/")); ASSERT_EQ(1, tx->is_protocol_0_9); } TEST_F(ConnectionParsing, CompressedResponseDeflateAsGzip) { int rc = test_run(home, "93-compressed-response-deflateasgzip.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(755, tx->response_message_len); ASSERT_EQ(1433, tx->response_entity_len); } TEST_F(ConnectionParsing, CompressedResponseMultiple) { int rc = test_run(home, "94-compressed-response-multiple.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(51, tx->response_message_len); ASSERT_EQ(25, tx->response_entity_len); } TEST_F(ConnectionParsing, CompressedResponseGzipAsDeflate) { int rc = test_run(home, "95-compressed-response-gzipasdeflate.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(187, tx->response_message_len); ASSERT_EQ(225, tx->response_entity_len); } #ifdef HAVE_LIBLZMA TEST_F(ConnectionParsing, CompressedResponseLzma) { int rc = test_run(home, "96-compressed-response-lzma.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_TRUE(htp_tx_is_complete(tx)); ASSERT_EQ(90, tx->response_message_len); ASSERT_EQ(68, tx->response_entity_len); } #endif TEST_F(ConnectionParsing, RequestsCut) { int rc = test_run(home, "97-requests-cut.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); } TEST_F(ConnectionParsing, ResponsesCut) { int rc = test_run(home, "98-responses-cut.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(200, tx->response_status_number); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(200, tx->response_status_number); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } TEST_F(ConnectionParsing, Expect100) { int rc = test_run(home, "99-expect-100.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(2, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "PUT")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(401, tx->response_status_number); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1); ASSERT_TRUE(tx != NULL); ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "POST")); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(200, tx->response_status_number); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); } // emplace_back needs at least C++ 11 #if __cplusplus > 199711L struct ResponseBodyDataCallback { std::vector data; }; static int callback_RESPONSE_BODY_DATA(htp_tx_data_t *d) { struct ResponseBodyDataCallback *user_data = (struct ResponseBodyDataCallback *) htp_tx_get_user_data(d->tx); if (!user_data) { user_data = new ResponseBodyDataCallback(); htp_tx_set_user_data(d->tx, user_data); } if(d->data) user_data->data.emplace_back(std::string(reinterpret_cast(d->data), d->len)); return HTP_OK; } TEST_F(ConnectionParsing, ResponseBodyData) { htp_config_register_response_body_data(cfg, callback_RESPONSE_BODY_DATA); int rc = test_run(home, "100-response-body-data.t", cfg, &connp); ASSERT_GE(rc, 0); ASSERT_EQ(1, htp_list_size(connp->conn->transactions)); htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0); ASSERT_TRUE(tx != NULL); ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress); ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress); struct ResponseBodyDataCallback *user_data = (struct ResponseBodyDataCallback *) htp_tx_get_user_data(tx); ASSERT_TRUE(user_data); ASSERT_EQ(3, user_data->data.size()); EXPECT_EQ("1\n", user_data->data[0]); EXPECT_EQ("23\n", user_data->data[1]); EXPECT_EQ("4", user_data->data[2]); delete user_data; } #endif