/*************************************************************************** * 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 * @brief Tests for various utility functions. * * @author Craig Forbes * @author Ivan Ristic */ #include #include #include TEST(Base64, Single) { EXPECT_EQ(62, htp_base64_decode_single('+')); EXPECT_EQ(63, htp_base64_decode_single('/')); EXPECT_EQ(-1, htp_base64_decode_single(',')); EXPECT_EQ(-1, htp_base64_decode_single(0)); EXPECT_EQ(-1, htp_base64_decode_single('~')); EXPECT_EQ(26, htp_base64_decode_single('a')); EXPECT_EQ(0, htp_base64_decode_single('A')); } TEST(Base64, Decode) { const char *input = "dGhpcyBpcyBhIHRlc3QuLg=="; bstr *out = htp_base64_decode_mem(input, strlen(input)); EXPECT_EQ(0, bstr_cmp_c(out, "this is a test..")); bstr_free(out); } TEST(UtilTest, Separator) { EXPECT_EQ(0, htp_is_separator('a')); EXPECT_EQ(0, htp_is_separator('^')); EXPECT_EQ(0, htp_is_separator('-')); EXPECT_EQ(0, htp_is_separator('_')); EXPECT_EQ(0, htp_is_separator('&')); EXPECT_EQ(1, htp_is_separator('(')); EXPECT_EQ(1, htp_is_separator('\\')); EXPECT_EQ(1, htp_is_separator('/')); EXPECT_EQ(1, htp_is_separator('=')); EXPECT_EQ(1, htp_is_separator('\t')); } TEST(UtilTest, Text) { EXPECT_EQ(1, htp_is_text('\t')); EXPECT_EQ(1, htp_is_text('a')); EXPECT_EQ(1, htp_is_text('~')); EXPECT_EQ(1, htp_is_text(' ')); EXPECT_EQ(0, htp_is_text('\n')); EXPECT_EQ(0, htp_is_text('\r')); EXPECT_EQ(0, htp_is_text('\r')); EXPECT_EQ(0, htp_is_text(31)); } TEST(UtilTest, Token) { EXPECT_EQ(1, htp_is_token('a')); EXPECT_EQ(1, htp_is_token('&')); EXPECT_EQ(1, htp_is_token('+')); EXPECT_EQ(0, htp_is_token('\t')); EXPECT_EQ(0, htp_is_token('\n')); } TEST(UtilTest, Chomp) { char data[100]; size_t len; int result; strcpy(data, "test\r\n"); len = strlen(data); result = htp_chomp((unsigned char *) data, &len); EXPECT_EQ(2, result); EXPECT_EQ(4, len); strcpy(data, "test\r\n\n"); len = strlen(data); result = htp_chomp((unsigned char *) data, &len); EXPECT_EQ(2, result); EXPECT_EQ(4, len); strcpy(data, "test\r\n\r\n"); len = strlen(data); result = htp_chomp((unsigned char *) data, &len); EXPECT_EQ(2, result); EXPECT_EQ(4, len); strcpy(data, "te\nst"); len = strlen(data); result = htp_chomp((unsigned char *) data, &len); EXPECT_EQ(0, result); EXPECT_EQ(5, len); strcpy(data, "foo\n"); len = strlen(data); result = htp_chomp((unsigned char *) data, &len); EXPECT_EQ(1, result); EXPECT_EQ(3, len); strcpy(data, "arfarf"); len = strlen(data); result = htp_chomp((unsigned char *) data, &len); EXPECT_EQ(0, result); EXPECT_EQ(6, len); strcpy(data, ""); len = strlen(data); result = htp_chomp((unsigned char *) data, &len); EXPECT_EQ(0, result); EXPECT_EQ(0, len); } TEST(UtilTest, Space) { EXPECT_EQ(0, htp_is_space('a')); EXPECT_EQ(1, htp_is_space(' ')); EXPECT_EQ(1, htp_is_space('\f')); EXPECT_EQ(1, htp_is_space('\n')); EXPECT_EQ(1, htp_is_space('\r')); EXPECT_EQ(1, htp_is_space('\t')); EXPECT_EQ(1, htp_is_space('\v')); } TEST(UtilTest, Method) { bstr *method = bstr_dup_c("GET"); EXPECT_EQ(HTP_M_GET, htp_convert_method_to_number(method)); bstr_free(method); } TEST(UtilTest, IsLineEmpty) { char data[100]; strcpy(data, "arfarf"); EXPECT_EQ(0, htp_is_line_empty((unsigned char*) data, 6)); strcpy(data, "\r\n"); EXPECT_EQ(1, htp_is_line_empty((unsigned char*) data, 2)); strcpy(data, "\r"); EXPECT_EQ(1, htp_is_line_empty((unsigned char*) data, 1)); EXPECT_EQ(0, htp_is_line_empty((unsigned char*) data, 0)); } TEST(UtilTest, IsLineWhitespace) { char data[100]; strcpy(data, "arfarf"); EXPECT_EQ(0, htp_is_line_whitespace((unsigned char*) data, 6)); strcpy(data, "\r\n"); EXPECT_EQ(1, htp_is_line_whitespace((unsigned char*) data, 2)); strcpy(data, "\r"); EXPECT_EQ(1, htp_is_line_whitespace((unsigned char*) data, 1)); EXPECT_EQ(1, htp_is_line_whitespace((unsigned char*) data, 0)); } TEST(UtilTest, ParsePositiveIntegerWhitespace) { EXPECT_EQ(123, htp_parse_positive_integer_whitespace( (unsigned char*) "123 ", 6, 10)); EXPECT_EQ(123, htp_parse_positive_integer_whitespace( (unsigned char*) " 123", 6, 10)); EXPECT_EQ(123, htp_parse_positive_integer_whitespace( (unsigned char*) " 123 ", 9, 10)); EXPECT_EQ(-1, htp_parse_positive_integer_whitespace( (unsigned char*) "a123", 4, 10)); EXPECT_EQ(-1001, htp_parse_positive_integer_whitespace( (unsigned char*) " \t", 4, 10)); EXPECT_EQ(-1002, htp_parse_positive_integer_whitespace( (unsigned char*) "123b ", 5, 10)); EXPECT_EQ(-1, htp_parse_positive_integer_whitespace( (unsigned char*) " a123 ", 9, 10)); EXPECT_EQ(-1002, htp_parse_positive_integer_whitespace( (unsigned char*) " 123b ", 9, 10)); EXPECT_EQ(0x123, htp_parse_positive_integer_whitespace( (unsigned char*) " 123 ", 9, 16)); } TEST(UtilTest, ParseContentLength) { bstr *str = bstr_dup_c("134"); EXPECT_EQ(134, htp_parse_content_length(str, NULL)); bstr_free(str); } TEST(UtilTest, ParseChunkedLength) { EXPECT_EQ(0x12a5, htp_parse_chunked_length((unsigned char*) "12a5", 4, NULL)); } TEST(UtilTest, IsLineFolded) { EXPECT_EQ(-1, htp_connp_is_line_folded((unsigned char*) "", 0)); EXPECT_EQ(1, htp_connp_is_line_folded((unsigned char*) "\tline", 5)); EXPECT_EQ(1, htp_connp_is_line_folded((unsigned char*) " line", 5)); EXPECT_EQ(0, htp_connp_is_line_folded((unsigned char*) "line ", 5)); } static void free_htp_uri_t(htp_uri_t **urip) { htp_uri_t *uri = *urip; if (uri == NULL) { return; } bstr_free(uri->scheme); bstr_free(uri->username); bstr_free(uri->password); bstr_free(uri->hostname); bstr_free(uri->port); bstr_free(uri->path); bstr_free(uri->query); bstr_free(uri->fragment); free(uri); *urip = NULL; } struct uri_expected { const char *scheme; const char *username; const char *password; const char *hostname; const char *port; const char *path; const char *query; const char *fragment; }; struct uri_test { const char *uri; uri_expected expected; }; bool bstr_equal_c(const bstr *b, const char *c) { if ((c == NULL) || (b == NULL)) { return (c == NULL) && (b == NULL); } else { return (0 == bstr_cmp_c(b, c)); } } void append_message(std::ostream & o, const char *label, const char *expected, bstr *actual) { o << label << " missmatch: "; if (expected != NULL) { o << "'" << expected << "'"; } else { o << ""; } o << " != "; if (actual != NULL) { o << "'"; o.write((const char *) bstr_ptr(actual), bstr_len(actual)); o << "'"; } else { o << ""; } o << std::endl; } static ::testing::AssertionResult UriIsExpected(const char *expected_var, const char *actual_var, const uri_expected &expected, const htp_uri_t *actual) { std::stringstream msg; bool equal = true; if (!bstr_equal_c(actual->scheme, expected.scheme)) { equal = false; append_message(msg, "scheme", expected.scheme, actual->scheme); } if (!bstr_equal_c(actual->username, expected.username)) { equal = false; append_message(msg, "username", expected.username, actual->username); } if (!bstr_equal_c(actual->password, expected.password)) { equal = false; append_message(msg, "password", expected.password, actual->password); } if (!bstr_equal_c(actual->hostname, expected.hostname)) { equal = false; append_message(msg, "hostname", expected.hostname, actual->hostname); } if (!bstr_equal_c(actual->port, expected.port)) { equal = false; append_message(msg, "port", expected.port, actual->port); } if (!bstr_equal_c(actual->path, expected.path)) { equal = false; append_message(msg, "path", expected.path, actual->path); } if (!bstr_equal_c(actual->query, expected.query)) { equal = false; append_message(msg, "query", expected.query, actual->query); } if (!bstr_equal_c(actual->fragment, expected.fragment)) { equal = false; append_message(msg, "fragment", expected.fragment, actual->fragment); } if (equal) { return ::testing::AssertionSuccess(); } else { return ::testing::AssertionFailure() << msg.str(); } } struct uri_test uri_tests[] = { {"http://user:pass@www.example.com:1234/path1/path2?a=b&c=d#frag", {"http", "user", "pass", "www.example.com", "1234", "/path1/path2", "a=b&c=d", "frag"}}, {"http://host.com/path", {"http", NULL, NULL, "host.com", NULL, "/path", NULL, NULL}}, {"http://", {"http", NULL, NULL, NULL, NULL, "//", NULL, NULL}}, {"/path", {NULL, NULL, NULL, NULL, NULL, "/path", NULL, NULL}}, {"://", {"", NULL, NULL, NULL, NULL, "//", NULL, NULL}}, {"", {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}, {"http://user@host.com", {"http", "user", NULL, "host.com", NULL, "", NULL, NULL}}, {NULL, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }} }; TEST(UtilTest, HtpParseUri) { bstr *input = NULL; htp_uri_t *uri = NULL; uri_test *test; input = bstr_dup_c(""); EXPECT_EQ(HTP_OK, htp_parse_uri(input, &uri)); bstr_free(input); free_htp_uri_t(&uri); test = uri_tests; while (test->uri != NULL) { input = bstr_dup_c(test->uri); EXPECT_EQ(HTP_OK, htp_parse_uri(input, &uri)); EXPECT_PRED_FORMAT2(UriIsExpected, test->expected, uri) << "Failed URI = " << test->uri << std::endl; bstr_free(input); free_htp_uri_t(&uri); ++test; } } TEST(UtilTest, ParseHostPort1) { bstr *i = bstr_dup_c("www.example.com"); bstr *host; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(bstr_cmp(i, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(0, flag); bstr_free(host); bstr_free(i); } TEST(UtilTest, ParseHostPort2) { bstr *i = bstr_dup_c(" www.example.com "); bstr *e = bstr_dup_c("www.example.com"); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(0, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort3) { bstr *i = bstr_dup_c(" www.example.com:8001 "); bstr *e = bstr_dup_c("www.example.com"); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(8001, port); ASSERT_EQ(0, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort4) { bstr *i = bstr_dup_c(" www.example.com : 8001 "); bstr *e = bstr_dup_c("www.example.com"); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(8001, port); ASSERT_EQ(0, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort5) { bstr *i = bstr_dup_c("www.example.com."); bstr *e = bstr_dup_c("www.example.com."); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(0, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort6) { bstr *i = bstr_dup_c("www.example.com.:8001"); bstr *e = bstr_dup_c("www.example.com."); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(8001, port); ASSERT_EQ(0, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort7) { bstr *i = bstr_dup_c("www.example.com:"); bstr *e = bstr_dup_c("www.example.com"); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(1, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort8) { bstr *i = bstr_dup_c("www.example.com:ff"); bstr *e = bstr_dup_c("www.example.com"); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(1, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort9) { bstr *i = bstr_dup_c("www.example.com:0"); bstr *e = bstr_dup_c("www.example.com"); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(1, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort10) { bstr *i = bstr_dup_c("www.example.com:65536"); bstr *e = bstr_dup_c("www.example.com"); bstr *host = NULL; int port; int flag = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(1, flag); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort11) { bstr *i = bstr_dup_c("[::1]:8080"); bstr *e = bstr_dup_c("[::1]"); bstr *host = NULL; int port; int invalid = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &invalid)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(8080, port); ASSERT_EQ(0, invalid); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort12) { bstr *i = bstr_dup_c("[::1]:"); bstr *e = bstr_dup_c("[::1]"); bstr *host = NULL; int port; int invalid = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &invalid)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(1, invalid); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort13) { bstr *i = bstr_dup_c("[::1]x"); bstr *e = bstr_dup_c("[::1]"); bstr *host = NULL; int port; int invalid = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &invalid)); ASSERT_TRUE(host != NULL); ASSERT_TRUE(bstr_cmp(e, host) == 0); ASSERT_EQ(-1, port); ASSERT_EQ(1, invalid); bstr_free(host); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseHostPort14) { bstr *i = bstr_dup_c("[::1"); bstr *host = NULL; int port; int invalid = 0; ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &invalid)); ASSERT_TRUE(host == NULL); ASSERT_EQ(-1, port); ASSERT_EQ(1, invalid); bstr_free(host); bstr_free(i); } TEST(UtilTest, ParseContentType1) { bstr *i = bstr_dup_c("multipart/form-data"); bstr *e = bstr_dup_c("multipart/form-data"); bstr *ct = NULL; ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct)); ASSERT_TRUE(ct != NULL); ASSERT_TRUE(bstr_cmp(e, ct) == 0); bstr_free(ct); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseContentType2) { bstr *i = bstr_dup_c("multipart/form-data;boundary=X"); bstr *e = bstr_dup_c("multipart/form-data"); bstr *ct = NULL; ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct)); ASSERT_TRUE(ct != NULL); ASSERT_TRUE(bstr_cmp(e, ct) == 0); bstr_free(ct); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseContentType3) { bstr *i = bstr_dup_c("multipart/form-data boundary=X"); bstr *e = bstr_dup_c("multipart/form-data"); bstr *ct = NULL; ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct)); ASSERT_TRUE(ct != NULL); ASSERT_TRUE(bstr_cmp(e, ct) == 0); bstr_free(ct); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseContentType4) { bstr *i = bstr_dup_c("multipart/form-data,boundary=X"); bstr *e = bstr_dup_c("multipart/form-data"); bstr *ct = NULL; ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct)); ASSERT_TRUE(ct != NULL); ASSERT_TRUE(bstr_cmp(e, ct) == 0); bstr_free(ct); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseContentType5) { bstr *i = bstr_dup_c("multipart/FoRm-data"); bstr *e = bstr_dup_c("multipart/form-data"); bstr *ct = NULL; ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct)); ASSERT_TRUE(ct != NULL); ASSERT_TRUE(bstr_cmp(e, ct) == 0); bstr_free(ct); bstr_free(e); bstr_free(i); } TEST(UtilTest, ParseContentType6) { bstr *i = bstr_dup_c("multipart/form-data\t boundary=X"); bstr *e = bstr_dup_c("multipart/form-data\t"); bstr *ct = NULL; ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct)); ASSERT_TRUE(ct != NULL); ASSERT_TRUE(bstr_cmp(e, ct) == 0); bstr_free(ct); bstr_free(e); bstr_free(i); } TEST(UtilTest, ValidateHostname1) { bstr *i = bstr_dup_c("www.example.com"); ASSERT_EQ(1, htp_validate_hostname(i)); bstr_free(i); } TEST(UtilTest, ValidateHostname2) { bstr *i = bstr_dup_c(".www.example.com"); ASSERT_EQ(0, htp_validate_hostname(i)); bstr_free(i); } TEST(UtilTest, ValidateHostname3) { bstr *i = bstr_dup_c("www..example.com"); ASSERT_EQ(0, htp_validate_hostname(i)); bstr_free(i); } TEST(UtilTest, ValidateHostname4) { bstr *i = bstr_dup_c("www.example.com.."); ASSERT_EQ(0, htp_validate_hostname(i)); bstr_free(i); } TEST(UtilTest, ValidateHostname5) { bstr *i = bstr_dup_c("www example com"); ASSERT_EQ(0, htp_validate_hostname(i)); bstr_free(i); } TEST(UtilTest, ValidateHostname6) { bstr *i = bstr_dup_c(""); ASSERT_EQ(0, htp_validate_hostname(i)); bstr_free(i); } TEST(UtilTest, ValidateHostname7) { // Label over 63 characters. bstr *i = bstr_dup_c("www.exampleexampleexampleexampleexampleexampleexampleexampleexampleexample.com"); ASSERT_EQ(0, htp_validate_hostname(i)); bstr_free(i); } TEST(UtilTest, ValidateHostname8) { bstr *i = bstr_dup_c("www.ExAmplE-1984.com"); ASSERT_EQ(1, htp_validate_hostname(i)); bstr_free(i); } class DecodingTest : public testing::Test { protected: virtual void SetUp() { testing::Test::SetUp(); cfg = htp_config_create(); connp = htp_connp_create(cfg); htp_connp_open(connp, "127.0.0.1", 32768, "127.0.0.1", 80, NULL); tx = htp_connp_tx_create(connp); } virtual void TearDown() { htp_connp_destroy_all(connp); htp_config_destroy(cfg); testing::Test::TearDown(); } htp_connp_t *connp; htp_cfg_t *cfg; htp_tx_t *tx; }; TEST_F(DecodingTest, DecodeUrlencodedInplace1_Identity) { bstr *i = bstr_dup_c("/dest"); bstr *e = bstr_dup_c("/dest"); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace2_Urlencoded) { bstr *i = bstr_dup_c("/%64est"); bstr *e = bstr_dup_c("/dest"); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace3_UrlencodedInvalidPreserve) { bstr *i = bstr_dup_c("/%xxest"); bstr *e = bstr_dup_c("/%xxest"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace4_UrlencodedInvalidRemove) { bstr *i = bstr_dup_c("/%xxest"); bstr *e = bstr_dup_c("/xxest"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace5_UrlencodedInvalidDecode) { bstr *i = bstr_dup_c("/%}9est"); bstr *e = bstr_dup_c("/iest"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace6_UrlencodedInvalidNotEnoughBytes) { bstr *i = bstr_dup_c("/%a"); bstr *e = bstr_dup_c("/%a"); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace7_UrlencodedInvalidNotEnoughBytes) { bstr *i = bstr_dup_c("/%"); bstr *e = bstr_dup_c("/%"); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace8_Uencoded) { bstr *i = bstr_dup_c("/%u0064"); bstr *e = bstr_dup_c("/d"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace9_UencodedDoNotDecode) { bstr *i = bstr_dup_c("/%u0064"); bstr *e = bstr_dup_c("/%u0064"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 0); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace10_UencodedInvalidNotEnoughBytes) { bstr *i = bstr_dup_c("/%u006"); bstr *e = bstr_dup_c("/%u006"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace11_UencodedInvalidPreserve) { bstr *i = bstr_dup_c("/%u006"); bstr *e = bstr_dup_c("/%u006"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace12_UencodedInvalidRemove) { bstr *i = bstr_dup_c("/%uXXXX"); bstr *e = bstr_dup_c("/uXXXX"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace13_UencodedInvalidDecode) { bstr *i = bstr_dup_c("/%u00}9"); bstr *e = bstr_dup_c("/i"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace14_UencodedInvalidPreserve) { bstr *i = bstr_dup_c("/%u00"); bstr *e = bstr_dup_c("/%u00"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace15_UencodedInvalidPreserve) { bstr *i = bstr_dup_c("/%u0"); bstr *e = bstr_dup_c("/%u0"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace16_UencodedInvalidPreserve) { bstr *i = bstr_dup_c("/%u"); bstr *e = bstr_dup_c("/%u"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace17_UrlencodedNul) { bstr *i = bstr_dup_c("/%00"); bstr *e = bstr_dup_mem("/\0", 2); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace18_UrlencodedNulTerminates) { bstr *i = bstr_dup_c("/%00ABC"); bstr *e = bstr_dup_c("/"); htp_config_set_nul_encoded_terminates(cfg, HTP_DECODER_DEFAULTS, 1); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace19_RawNulTerminates) { bstr *i = bstr_dup_mem("/\0ABC", 5); bstr *e = bstr_dup_c("/"); htp_config_set_nul_raw_terminates(cfg, HTP_DECODER_DEFAULTS, 1); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodeUrlencodedInplace20_UencodedBestFit) { bstr *i = bstr_dup_c("/%u0107"); bstr *e = bstr_dup_c("/c"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_tx_urldecode_params_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace1_UrlencodedInvalidNotEnoughBytes) { bstr *i = bstr_dup_c("/%a"); bstr *e = bstr_dup_c("/%a"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace2_UencodedInvalidNotEnoughBytes) { bstr *i = bstr_dup_c("/%uX"); bstr *e = bstr_dup_c("/%uX"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace3_UencodedValid) { bstr *i = bstr_dup_c("/%u0107"); bstr *e = bstr_dup_c("/c"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace4_UencodedInvalidNotHexDigits_Remove) { bstr *i = bstr_dup_c("/%uXXXX"); bstr *e = bstr_dup_c("/uXXXX"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace5_UencodedInvalidNotHexDigits_Preserve) { bstr *i = bstr_dup_c("/%uXXXX"); bstr *e = bstr_dup_c("/%uXXXX"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace6_UencodedInvalidNotHexDigits_Process) { bstr *i = bstr_dup_c("/%u00}9"); bstr *e = bstr_dup_c("/i"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace7_UencodedNul) { bstr *i = bstr_dup_c("/%u0000"); bstr *e = bstr_dup_mem("/\0", 2); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_NUL); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace8_UencodedNotEnough_Remove) { bstr *i = bstr_dup_c("/%uXXX"); bstr *e = bstr_dup_c("/uXXX"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace9_UencodedNotEnough_Preserve) { bstr *i = bstr_dup_c("/%uXXX"); bstr *e = bstr_dup_c("/%uXXX"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace10_UrlencodedNul) { bstr *i = bstr_dup_c("/%00123"); bstr *e = bstr_dup_mem("/\000123", 5); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_NUL); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace11_UrlencodedNul_Terminates) { bstr *i = bstr_dup_c("/%00123"); bstr *e = bstr_dup_mem("/", 1); htp_config_set_nul_encoded_terminates(cfg, HTP_DECODER_DEFAULTS, 1); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_NUL); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace12_EncodedSlash) { bstr *i = bstr_dup_c("/one%2ftwo"); bstr *e = bstr_dup_c("/one%2ftwo"); htp_config_set_path_separators_decode(cfg, HTP_DECODER_DEFAULTS, 0); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_SEPARATOR); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace13_EncodedSlash_Decode) { bstr *i = bstr_dup_c("/one%2ftwo"); bstr *e = bstr_dup_c("/one/two"); htp_config_set_path_separators_decode(cfg, HTP_DECODER_DEFAULTS, 1); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_SEPARATOR); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace14_Urlencoded_Invalid_Preserve) { bstr *i = bstr_dup_c("/%HH"); bstr *e = bstr_dup_c("/%HH"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace15_Urlencoded_Invalid_Remove) { bstr *i = bstr_dup_c("/%HH"); bstr *e = bstr_dup_c("/HH"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace16_Urlencoded_Invalid_Process) { bstr *i = bstr_dup_c("/%}9"); bstr *e = bstr_dup_c("/i"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace17_Urlencoded_NotEnough_Remove) { bstr *i = bstr_dup_c("/%H"); bstr *e = bstr_dup_c("/H"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace18_Urlencoded_NotEnough_Preserve) { bstr *i = bstr_dup_c("/%H"); bstr *e = bstr_dup_c("/%H"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace19_Urlencoded_NotEnough_Process) { bstr *i = bstr_dup_c("/%H"); bstr *e = bstr_dup_c("/%H"); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace20_RawNul1) { bstr *i = bstr_dup_mem("/\000123", 5); bstr *e = bstr_dup_c("/"); htp_config_set_nul_raw_terminates(cfg, HTP_DECODER_DEFAULTS, 1); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace21_RawNul1) { bstr *i = bstr_dup_mem("/\000123", 5); bstr *e = bstr_dup_mem("/\000123", 5); htp_config_set_nul_raw_terminates(cfg, HTP_DECODER_DEFAULTS, 0); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace22_ConvertBackslash1) { bstr *i = bstr_dup_c("/one\\two"); bstr *e = bstr_dup_c("/one/two"); htp_config_set_backslash_convert_slashes(cfg, HTP_DECODER_DEFAULTS, 1); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, DecodePathInplace23_ConvertBackslash2) { bstr *i = bstr_dup_c("/one\\two"); bstr *e = bstr_dup_c("/one\\two"); htp_config_set_backslash_convert_slashes(cfg, HTP_DECODER_DEFAULTS, 0); htp_decode_path_inplace(tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } TEST_F(DecodingTest, InvalidUtf8) { bstr *i = bstr_dup_c("\xf1."); bstr *e = bstr_dup_c("?."); htp_config_set_utf8_convert_bestfit(cfg, HTP_DECODER_URL_PATH, 1); htp_utf8_decode_path_inplace(cfg, tx, i); ASSERT_TRUE(bstr_cmp(i, e) == 0); bstr_free(e); bstr_free(i); } class UrlencodedParser : public testing::Test { protected: virtual void SetUp() { cfg = htp_config_create(); connp = htp_connp_create(cfg); htp_connp_open(connp, "127.0.0.1", 32768, "127.0.0.1", 80, NULL); tx = htp_connp_tx_create(connp); urlenp = htp_urlenp_create(tx); } virtual void TearDown() { htp_urlenp_destroy(urlenp); htp_connp_destroy_all(connp); htp_config_destroy(cfg); } htp_connp_t *connp; htp_cfg_t *cfg; htp_tx_t *tx; htp_urlenp_t *urlenp; }; TEST_F(UrlencodedParser, Empty) { htp_urlenp_parse_complete(urlenp, "", 0); ASSERT_EQ(0, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, EmptyKey1) { htp_urlenp_parse_complete(urlenp, "&", 1); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "", 0); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, EmptyKey2) { htp_urlenp_parse_complete(urlenp, "=&", 2); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "", 0); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, EmptyKey3) { htp_urlenp_parse_complete(urlenp, "=1&", 3); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "", 0); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "1")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, EmptyKeyAndValue) { htp_urlenp_parse_complete(urlenp, "=", 1); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "", 0); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, OnePairEmptyValue) { htp_urlenp_parse_complete(urlenp, "p=", 2); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, OnePair) { htp_urlenp_parse_complete(urlenp, "p=1", 3); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "1")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, TwoPairs) { htp_urlenp_parse_complete(urlenp, "p=1&q=2", 7); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "1")); bstr *q = (bstr *) htp_table_get_mem(urlenp->params, "q", 1); ASSERT_TRUE(q != NULL); ASSERT_EQ(0, bstr_cmp_c(q, "2")); ASSERT_EQ(2, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, KeyNoValue1) { htp_urlenp_parse_complete(urlenp, "p", 1); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, KeyNoValue2) { htp_urlenp_parse_complete(urlenp, "p&", 2); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, KeyNoValue3) { htp_urlenp_parse_complete(urlenp, "p&q", 3); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); bstr *q = (bstr *) htp_table_get_mem(urlenp->params, "q", 1); ASSERT_TRUE(q != NULL); ASSERT_EQ(0, bstr_cmp_c(q, "")); ASSERT_EQ(2, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, KeyNoValue4) { htp_urlenp_parse_complete(urlenp, "p&q=2", 5); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); bstr *q = (bstr *) htp_table_get_mem(urlenp->params, "q", 1); ASSERT_TRUE(q != NULL); ASSERT_EQ(0, bstr_cmp_c(q, "2")); ASSERT_EQ(2, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, Partial1) { htp_urlenp_parse_partial(urlenp, "p", 1); htp_urlenp_finalize(urlenp); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, Partial2) { htp_urlenp_parse_partial(urlenp, "p", 1); htp_urlenp_parse_partial(urlenp, "x", 1); htp_urlenp_finalize(urlenp); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "px", 2); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, Partial3) { htp_urlenp_parse_partial(urlenp, "p", 1); htp_urlenp_parse_partial(urlenp, "x&", 2); htp_urlenp_finalize(urlenp); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "px", 2); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, Partial4) { htp_urlenp_parse_partial(urlenp, "p", 1); htp_urlenp_parse_partial(urlenp, "=", 1); htp_urlenp_finalize(urlenp); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, Partial5) { htp_urlenp_parse_partial(urlenp, "p", 1); htp_urlenp_parse_partial(urlenp, "", 0); htp_urlenp_parse_partial(urlenp, "", 0); htp_urlenp_parse_partial(urlenp, "", 0); htp_urlenp_finalize(urlenp); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "")); ASSERT_EQ(1, htp_table_size(urlenp->params)); } TEST_F(UrlencodedParser, Partial6) { htp_urlenp_parse_partial(urlenp, "px", 2); htp_urlenp_parse_partial(urlenp, "n", 1); htp_urlenp_parse_partial(urlenp, "", 0); htp_urlenp_parse_partial(urlenp, "=", 1); htp_urlenp_parse_partial(urlenp, "1", 1); htp_urlenp_parse_partial(urlenp, "2", 1); htp_urlenp_parse_partial(urlenp, "&", 1); htp_urlenp_parse_partial(urlenp, "qz", 2); htp_urlenp_parse_partial(urlenp, "n", 1); htp_urlenp_parse_partial(urlenp, "", 0); htp_urlenp_parse_partial(urlenp, "=", 1); htp_urlenp_parse_partial(urlenp, "2", 1); htp_urlenp_parse_partial(urlenp, "3", 1); htp_urlenp_parse_partial(urlenp, "&", 1); htp_urlenp_finalize(urlenp); bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "pxn", 3); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(p, "12")); bstr *q = (bstr *) htp_table_get_mem(urlenp->params, "qzn", 3); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, bstr_cmp_c(q, "23")); ASSERT_EQ(2, htp_table_size(urlenp->params)); } TEST(List, Misc) { htp_list_t *l = htp_list_create(16); htp_list_push(l, (void *) "1"); htp_list_push(l, (void *) "2"); htp_list_push(l, (void *) "3"); ASSERT_EQ(3, htp_list_size(l)); char *p = (char *) htp_list_pop(l); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("3", p)); ASSERT_EQ(2, htp_list_size(l)); p = (char *) htp_list_shift(l); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("1", p)); ASSERT_EQ(1, htp_list_size(l)); p = (char *) htp_list_shift(l); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("2", p)); p = (char *) htp_list_shift(l); ASSERT_TRUE(p == NULL); p = (char *) htp_list_pop(l); ASSERT_TRUE(p == NULL); htp_list_destroy(l); } TEST(List, Misc2) { htp_list_t *l = htp_list_create(1); htp_list_push(l, (void *) "1"); char *p = (char *) htp_list_shift(l); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("1", p)); htp_list_push(l, (void *) "2"); p = (char *) htp_list_shift(l); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("2", p)); ASSERT_EQ(0, htp_list_size(l)); htp_list_destroy(l); } TEST(List, Misc3) { htp_list_t *l = htp_list_create(2); htp_list_push(l, (void *) "1"); htp_list_push(l, (void *) "2"); char *p = (char *) htp_list_shift(l); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("1", p)); htp_list_push(l, (void *) "3"); p = (char *) htp_list_get(l, 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("3", p)); ASSERT_EQ(2, htp_list_size(l)); htp_list_replace(l, 1, (void *) "4"); p = (char *) htp_list_pop(l); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("4", p)); htp_list_destroy(l); } TEST(List, Expand1) { htp_list_t *l = htp_list_create(2); htp_list_push(l, (void *) "1"); htp_list_push(l, (void *) "2"); ASSERT_EQ(2, htp_list_size(l)); htp_list_push(l, (void *) "3"); ASSERT_EQ(3, htp_list_size(l)); char *p = (char *) htp_list_get(l, 0); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("1", p)); p = (char *) htp_list_get(l, 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("2", p)); p = (char *) htp_list_get(l, 2); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("3", p)); htp_list_destroy(l); } TEST(List, Expand2) { htp_list_t *l = htp_list_create(2); htp_list_push(l, (void *) "1"); htp_list_push(l, (void *) "2"); ASSERT_EQ(2, htp_list_size(l)); htp_list_shift(l); ASSERT_EQ(1, htp_list_size(l)); htp_list_push(l, (void *) "3"); htp_list_push(l, (void *) "4"); ASSERT_EQ(3, htp_list_size(l)); char *p = (char *) htp_list_get(l, 0); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("2", p)); p = (char *) htp_list_get(l, 1); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("3", p)); p = (char *) htp_list_get(l, 2); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("4", p)); htp_list_destroy(l); } TEST(Table, Misc) { htp_table_t *t = htp_table_create(2); bstr *pkey = bstr_dup_c("p"); bstr *qkey = bstr_dup_c("q"); htp_table_addk(t, pkey, "1"); htp_table_addk(t, qkey, "2"); char *p = (char *) htp_table_get_mem(t, "z", 1); ASSERT_TRUE(p == NULL); p = (char *) htp_table_get(t, pkey); ASSERT_TRUE(p != NULL); ASSERT_EQ(0, strcmp("1", p)); htp_table_clear_ex(t); bstr_free(qkey); bstr_free(pkey); htp_table_destroy(t); } TEST(Util, ExtractQuotedString) { bstr *s; size_t end_offset; htp_status_t rc = htp_extract_quoted_string_as_bstr((unsigned char *) "\"test\"", 6, &s, &end_offset); ASSERT_EQ(HTP_OK, rc); ASSERT_TRUE(s != NULL); ASSERT_EQ(0, bstr_cmp_c(s, "test")); ASSERT_EQ(5, end_offset); bstr_free(s); rc = htp_extract_quoted_string_as_bstr((unsigned char *) "\"te\\\"st\"", 8, &s, &end_offset); ASSERT_EQ(HTP_OK, rc); ASSERT_TRUE(s != NULL); ASSERT_EQ(0, bstr_cmp_c(s, "te\"st")); ASSERT_EQ(7, end_offset); bstr_free(s); } TEST(Util, NormalizeUriPath) { bstr *s = NULL; s = bstr_dup_c("/a/b/c/./../../g"); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "/a/g")); bstr_free(s); s = bstr_dup_c("mid/content=5/../6"); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "mid/6")); bstr_free(s); s = bstr_dup_c("./one"); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "one")); bstr_free(s); s = bstr_dup_c("../one"); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "one")); bstr_free(s); s = bstr_dup_c("."); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "")); bstr_free(s); s = bstr_dup_c(".."); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "")); bstr_free(s); s = bstr_dup_c("one/."); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "one")); bstr_free(s); s = bstr_dup_c("one/.."); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "")); bstr_free(s); s = bstr_dup_c("one/../"); htp_normalize_uri_path_inplace(s); ASSERT_EQ(0, bstr_cmp_c(s, "")); bstr_free(s); } TEST_F(UrlencodedParser, UrlDecode1) { bstr *s = NULL; uint64_t flags; s = bstr_dup_c("/one/tw%u006f/three/%u123"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_PRESERVE_PERCENT); htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags); ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/%u123")); bstr_free(s); s = bstr_dup_c("/one/tw%u006f/three/%uXXXX"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_PRESERVE_PERCENT); htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags); ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/%uXXXX")); bstr_free(s); s = bstr_dup_c("/one/tw%u006f/three/%u123"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_REMOVE_PERCENT); htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags); ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/u123")); bstr_free(s); s = bstr_dup_c("/one/tw%u006f/three/%3"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_REMOVE_PERCENT); htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags); ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/3")); bstr_free(s); s = bstr_dup_c("/one/tw%u006f/three/%3"); htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1); htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_PROCESS_INVALID); htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags); ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/%3")); bstr_free(s); } TEST(UtilTest, HeaderHasToken) { char data[100]; // Basic strcpy(data, "chunked"); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); // Negative strcpy(data, "notchunked"); EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, "chunkednot"); EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, "chunk,ed"); EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, "chunk ed"); EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); // Positive strcpy(data, " notchunked , chunked , yetanother"); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, "chunked,yetanother"); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, "not,chunked"); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, "chunk,chunked"); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, " chunked"); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, "chunked "); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, "chunked,"); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); strcpy(data, ",chunked"); EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked")); }