diff options
Diffstat (limited to 'test/main.c')
-rw-r--r-- | test/main.c | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/test/main.c b/test/main.c new file mode 100644 index 0000000..60e2417 --- /dev/null +++ b/test/main.c @@ -0,0 +1,802 @@ +/*************************************************************************** + * 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 <ivanr@webkreator.com> + */ + +#include <dirent.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <time.h> + +#include "../htp/bstr.h" +#include "../htp/htp.h" +#include "test.h" + +char *home = NULL; + +int callback_transaction_start(htp_connp_t *connp) { + printf("-- Callback: transaction_start\n"); +} + +int callback_request_line(htp_connp_t *connp) { + printf("-- Callback: request_line\n"); +} + +int callback_request_headers(htp_connp_t *connp) { + printf("-- Callback: request_headers\n"); + bstr *raw = htp_tx_get_request_headers_raw(connp->in_tx); + fprint_raw_data(stdout, "REQUEST HEADERS RAW 1", bstr_ptr(raw), bstr_len(raw)); +} + +int callback_request_body_data(htp_tx_data_t *d) { + /* + if (d->data != NULL) { + printf("-- Callback: request_body_data\n"); + fprint_raw_data(stdout, __FUNCTION__, d->data, d->len); + } else { + printf("-- Callback: request_body_data (LAST)\n"); + } + */ +} + +int callback_request_trailer(htp_connp_t *connp) { + printf("-- Callback: request_trailer\n"); +} + +int callback_request(htp_connp_t *connp) { + printf("-- Callback: request\n"); +} + +int callback_response_line(htp_connp_t *connp) { + printf("-- Callback: response_line\n"); +} + +int callback_response_headers(htp_connp_t *connp) { + printf("-- Callback: response_headers\n"); +} + +int callback_response_body_data(htp_tx_data_t *d) { + if (d->data != NULL) { + printf("-- Callback: response_body_data\n"); + fprint_raw_data(stdout, __FUNCTION__, d->data, d->len); + } else { + printf("-- Callback: response_body_data (LAST)\n"); + } +} + +int callback_request_file_data(htp_file_data_t *file_data) { + if (file_data->data != NULL) { + printf("-- Callback: request_file_data\n"); + fprint_raw_data(stdout, __FUNCTION__, file_data->data, file_data->len); + } else { + printf("-- Callback: request_file_data (LAST)\n"); + } +} + +int callback_response_trailer(htp_connp_t *connp) { + printf("-- Callback: response_trailer\n"); +} + +int callback_response(htp_connp_t *connp) { + printf("-- Callback: response\n"); +} + +int callback_response_destroy(htp_connp_t *connp) { + htp_tx_destroy(connp->out_tx); + printf("-- Destroyed transaction\n"); +} + +int callback_log(htp_log_t *log) { + htp_print_log(stdout, log); +} + +static void print_tx(htp_connp_t *connp, htp_tx_t *tx) { + char *request_line = bstr_util_strdup_to_c(tx->request_line); + htp_header_t *h_user_agent = htp_table_get_c(tx->request_headers, "user-agent"); + htp_header_t *h_referer = htp_table_get_c(tx->request_headers, "referer"); + char *referer, *user_agent; + char buf[256]; + + time_t t = time(NULL); + struct tm *tmp = localtime(&t); + + strftime(buf, 255, "%d/%b/%Y:%T %z", tmp); + + if (h_user_agent == NULL) user_agent = strdup("-"); + else { + user_agent = bstr_util_strdup_to_c(h_user_agent->value); + } + + if (h_referer == NULL) referer = strdup("-"); + else { + referer = bstr_util_strdup_to_c(h_referer->value); + } + + printf("%s - - [%s] \"%s\" %i %zu \"%s\" \"%s\"\n", connp->conn->client_addr, buf, + request_line, tx->response_status_number, tx->response_message_len, + referer, user_agent); + + free(referer); + free(user_agent); + free(request_line); +} + +static int run_directory(char *dirname, htp_cfg_t *cfg) { + struct dirent *entry; + char buf[1025]; + DIR *d = opendir(dirname); + htp_connp_t *connp; + + if (d == NULL) { + printf("Failed to open directory: %s\n", dirname); + return -1; + } + + while ((entry = readdir(d)) != NULL) { + if (strncmp(entry->d_name, "stream", 6) == 0) { + int rc = test_run(dirname, entry->d_name, cfg, &connp); + + if (rc < 0) { + if (connp != NULL) { + htp_log_t *last_error = htp_connp_get_last_error(connp); + if (last_error != NULL) { + printf(" -- failed: %s\n", last_error->msg); + } else { + printf(" -- failed: ERROR NOT AVAILABLE\n"); + } + + return 0; + } else { + return -1; + } + } else { + printf(" -- %zu transaction(s)\n", htp_list_size(connp->conn->transactions)); + + for (int i = 0, n = htp_list_size(connp->conn->transactions); i < n; i++) { + htp_tx_t *tx = htp_list_get(connp->conn->transactions, i); + + printf(" "); + print_tx(connp, tx); + } + + printf("\n"); + + htp_connp_destroy_all(connp); + } + } + } + + closedir(d); + + return 1; +} + +int main_dir(int argc, char** argv) { + //int main(int argc, char** argv) { + htp_cfg_t *cfg = htp_config_create(); + htp_config_register_log(cfg, callback_log); + htp_config_register_response_complete(cfg, callback_response_destroy); + + run_directory("C:\\http_traces\\run1", cfg); + //run_directory("/home/ivanr/work/traces/run3/", cfg); + + htp_config_destroy(cfg); +} + +#define RUN_TEST(X, Y) \ + {\ + tests++; \ + printf("---------------------------------\n"); \ + printf("Test: " #X "\n"); \ + int rc = X(Y); \ + if (rc < 0) { \ + printf(" Failed with %i\n", rc); \ + failures++; \ + } \ + printf("\n"); \ + } + +/** + * Dummy entry point. + */ +int main(int argc, char** argv) { + return EXIT_SUCCESS; +} + +int main_path_decoding_tests(int argc, char** argv) { + htp_cfg_t *cfg = htp_config_create(); + htp_connp_t *connp = htp_connp_create(cfg); + htp_tx_t *tx = htp_tx_create(connp); + char *str; + bstr *path = NULL; + + // + path = bstr_dup_c("/One\\two///ThRee%2ffive%5csix/se%xxven"); + cfg->path_case_insensitive = 1; + + str = bstr_util_strdup_to_c(path); + printf("Before: %s\n", str); + free(str); + htp_decode_path_inplace(cfg, tx, path); + str = bstr_util_strdup_to_c(path); + printf("After: %s\n\n", str); + free(str); + bstr_free(path); + + // + path = bstr_dup_c("/One\\two///ThRee%2ffive%5csix/se%xxven"); + cfg->path_case_insensitive = 1; + cfg->path_compress_separators = 1; + + str = bstr_util_strdup_to_c(path); + printf("Before: %s\n", str); + free(str); + htp_decode_path_inplace(cfg, tx, path); + str = bstr_util_strdup_to_c(path); + printf("After: %s\n\n", str); + free(str); + bstr_free(path); + + // + path = bstr_dup_c("/One\\two///ThRee%2ffive%5csix/se%xxven"); + cfg->path_case_insensitive = 1; + cfg->path_compress_separators = 1; + cfg->path_backslash_separators = 1; + + str = bstr_util_strdup_to_c(path); + printf("Before: %s\n", str); + free(str); + htp_decode_path_inplace(cfg, tx, path); + str = bstr_util_strdup_to_c(path); + printf("After: %s\n\n", str); + free(str); + bstr_free(path); + + // + path = bstr_dup_c("/One\\two///ThRee%2ffive%5csix/se%xxven"); + cfg->path_case_insensitive = 1; + cfg->path_compress_separators = 1; + cfg->path_backslash_separators = 1; + cfg->path_encoded_separators_decode = 1; + + str = bstr_util_strdup_to_c(path); + printf("Before: %s\n", str); + free(str); + htp_decode_path_inplace(cfg, tx, path); + str = bstr_util_strdup_to_c(path); + printf("After: %s\n\n", str); + free(str); + bstr_free(path); + + // + path = bstr_dup_c("/One\\two///ThRee%2ffive%5csix/se%xxven"); + cfg->path_case_insensitive = 1; + cfg->path_compress_separators = 1; + cfg->path_backslash_separators = 1; + cfg->path_encoded_separators_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_REMOVE_PERCENT; + + str = bstr_util_strdup_to_c(path); + printf("Before: %s\n", str); + free(str); + htp_decode_path_inplace(cfg, tx, path); + str = bstr_util_strdup_to_c(path); + printf("After: %s\n\n", str); + free(str); + bstr_free(path); + + // + path = bstr_dup_c("/One\\two///ThRee%2ffive%5csix/se%xxven/%u0074"); + cfg->path_case_insensitive = 1; + cfg->path_compress_separators = 1; + cfg->path_backslash_separators = 1; + cfg->path_encoded_separators_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PROCESS_INVALID; + + str = bstr_util_strdup_to_c(path); + printf("Before: %s\n", str); + free(str); + htp_decode_path_inplace(cfg, tx, path); + str = bstr_util_strdup_to_c(path); + printf("After: %s\n\n", str); + free(str); + bstr_free(path); + + // + path = bstr_dup_c("/One\\two///ThRee%2ffive%5csix/se%xxven/%u0074%u0100"); + cfg->path_case_insensitive = 1; + cfg->path_compress_separators = 1; + cfg->path_backslash_separators = 1; + cfg->path_encoded_separators_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + cfg->path_u_encoding_decode = 1; + + str = bstr_util_strdup_to_c(path); + printf("Before: %s\n", str); + free(str); + htp_decode_path_inplace(cfg, tx, path); + str = bstr_util_strdup_to_c(path); + printf("After: %s\n\n", str); + free(str); + bstr_free(path); +} + +void encode_utf8_2(uint8_t *data, uint32_t i) { + i = i & 0x7ff; + data[0] = 0xc0 + (i >> 6); + data[1] = 0x80 + (i & 0x3f); +} + +void encode_utf8_3(uint8_t *data, uint32_t i) { + i = i & 0xffff; + data[0] = 0xe0 + (i >> 12); + data[1] = 0x80 + ((i >> 6) & 0x3f); + data[2] = 0x80 + (i & 0x3f); +} + +void encode_utf8_4(uint8_t *data, uint32_t i) { + i = i & 0x10ffff; + data[0] = 0xf0 + (i >> 18); + data[1] = 0x80 + ((i >> 12) & 0x3f); + data[2] = 0x80 + ((i >> 6) & 0x3f); + data[3] = 0x80 + (i & 0x3f); +} + +int main_utf8_decoder_tests(int argc, char** argv) { + htp_cfg_t *cfg = htp_config_create(); + htp_connp_t *connp = htp_connp_create(cfg); + htp_tx_t *tx = htp_tx_create(connp); + + bstr *path = NULL; + + path = bstr_dup_c("//////////"); + uint8_t *data = bstr_ptr(path); + + int i = 0; + + for (i = 0; i < 0x80; i++) { + memset(data, 0x2f, 10); + tx->flags = 0; + encode_utf8_2(data, i); + htp_utf8_validate_path(tx, path); + if (tx->flags != HTP_PATH_UTF8_OVERLONG) { + printf("#2 i %i data %x %x flags %x\n", i, (uint8_t) data[0], (uint8_t) data[1], tx->flags); + } + } + + for (i = 0; i < 0x800; i++) { + memset(data, 0x2f, 10); + tx->flags = 0; + encode_utf8_3(data, i); + htp_utf8_validate_path(tx, path); + if (tx->flags != HTP_PATH_UTF8_OVERLONG) { + printf("#3 i %x data %x %x %x flags %x\n", i, (uint8_t) data[0], (uint8_t) data[1], (uint8_t) data[2], tx->flags); + } + } + + for (i = 0; i < 0x10000; i++) { + memset(data, 0x2f, 10); + tx->flags = 0; + encode_utf8_4(data, i); + htp_utf8_validate_path(tx, path); + if ((i >= 0xff00) && (i <= 0xffff)) { + if (tx->flags != (HTP_PATH_UTF8_OVERLONG | HTP_PATH_HALF_FULL_RANGE)) { + printf("#4 i %x data %x %x %x %x flags %x\n", i, (uint8_t) data[0], (uint8_t) data[1], (uint8_t) data[2], (uint8_t) data[3], tx->flags); + } + } else { + if (tx->flags != HTP_PATH_UTF8_OVERLONG) { + printf("#4 i %x data %x %x %x %x flags %x\n", i, (uint8_t) data[0], (uint8_t) data[1], (uint8_t) data[2], (uint8_t) data[3], tx->flags); + } + } + } + + bstr_free(&path); +} + +#define PATH_DECODE_TEST_BEFORE(NAME) \ + test_name = NAME; \ + tests++; \ + expected_status = 0; \ + expected_flags = -1; \ + success = 0; \ + cfg = htp_config_create(); \ + connp = htp_connp_create(cfg); \ + tx = htp_tx_create(connp); + +#define PATH_DECODE_TEST_AFTER() \ + htp_decode_path_inplace(cfg, tx, input); \ + htp_utf8_decode_path_inplace(cfg, tx, input); \ + if (bstr_cmp(input, expected) == 0) success = 1; \ + printf("[%2i] %s: %s\n", tests, (success == 1 ? "SUCCESS" : "FAILURE"), test_name); \ + if ((success == 0)||((expected_status != 0)&&(expected_status != tx->response_status_expected_number))) { \ + char *s1 = bstr_util_strdup_to_c(input); \ + char *s2 = bstr_util_strdup_to_c(expected); \ + printf(" Output: [%s]\n", s1); \ + printf(" Expected: [%s]\n", s2); \ + if (expected_status != 0) { \ + printf(" Expected status %i; got %i\n", expected_status, tx->response_status_expected_number); \ + } \ + if (expected_flags != -1) { \ + printf(" Expected flags 0x%x; got 0x%x\n", expected_flags, tx->flags); \ + } \ + free(s2); \ + free(s1); \ + failures++; \ + } \ + htp_tx_destroy(tx); \ + htp_config_destroy(cfg); \ + bstr_free(&expected); \ + bstr_free(&input); + +int main_path_tests(int argc, char** argv) { + htp_cfg_t *cfg = NULL; + htp_connp_t *connp = NULL; + htp_tx_t *tx = NULL; + bstr *input = NULL; + bstr *expected = NULL; + int success = 0; + int tests = 0; + int failures = 0; + int expected_status = 0; + int expected_flags = 0; + char *test_name = NULL; + + PATH_DECODE_TEST_BEFORE("URL-decoding"); + input = bstr_dup_c("/%64est"); + expected = bstr_dup_c("/dest"); + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid URL-encoded, preserve %"); + input = bstr_dup_c("/%xxest"); + expected = bstr_dup_c("/%xxest"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid URL-encoded, remove %"); + input = bstr_dup_c("/%xxest"); + expected = bstr_dup_c("/xxest"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_REMOVE_PERCENT; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid URL-encoded (end of string, test 1), preserve %"); + input = bstr_dup_c("/test/%2"); + expected = bstr_dup_c("/test/%2"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid URL-encoded (end of string, test 2), preserve %"); + input = bstr_dup_c("/test/%"); + expected = bstr_dup_c("/test/%"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid URL-encoded, preserve % and 400"); + input = bstr_dup_c("/%xxest"); + expected = bstr_dup_c("/%xxest"); + expected_status = 400; + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + cfg->path_invalid_encoding_unwanted = HTP_UNWANTED_400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("%u decoding (expected not to decode; 400)"); + input = bstr_dup_c("/%u0064"); + expected = bstr_dup_c("/%u0064"); + expected_flags = HTP_PATH_INVALID_ENCODING; + expected_status = 400; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + cfg->path_invalid_encoding_unwanted = HTP_UNWANTED_400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("%u decoding (decode; 400)"); + input = bstr_dup_c("/%u0064"); + expected = bstr_dup_c("/d"); + expected_status = 400; + expected_flags = HTP_PATH_OVERLONG_U; + cfg->path_u_encoding_unwanted = HTP_UNWANTED_400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("%u decoding (also overlong)"); + input = bstr_dup_c("/%u0064"); + expected = bstr_dup_c("/d"); + expected_flags = HTP_PATH_OVERLONG_U; + cfg->path_u_encoding_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid %u decoding, leave; preserve percent"); + input = bstr_dup_c("/%uXXXX---"); + expected = bstr_dup_c("/%uXXXX---"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_u_encoding_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid %u decoding, decode invalid; preserve percent"); + input = bstr_dup_c("/%uXXXX---"); + expected = bstr_dup_c("/?---"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_u_encoding_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PROCESS_INVALID; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid %u decoding, decode invalid; preserve percent; 400"); + input = bstr_dup_c("/%uXXXX---"); + expected = bstr_dup_c("/?---"); + expected_flags = HTP_PATH_INVALID_ENCODING; + expected_status = 400; + cfg->path_u_encoding_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + cfg->path_invalid_encoding_unwanted = HTP_UNWANTED_400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid %u decoding (not enough data 1), preserve percent"); + input = bstr_dup_c("/%u123"); + expected = bstr_dup_c("/%u123"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_u_encoding_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid %u decoding (not enough data 2), preserve percent"); + input = bstr_dup_c("/%u12"); + expected = bstr_dup_c("/%u12"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_u_encoding_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid %u decoding (not enough data 3), preserve percent"); + input = bstr_dup_c("/%u1"); + expected = bstr_dup_c("/%u1"); + expected_flags = HTP_PATH_INVALID_ENCODING; + cfg->path_u_encoding_decode = 1; + cfg->path_invalid_encoding_handling = HTP_URL_DECODE_PRESERVE_PERCENT; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("%u decoding, best-fit mapping"); + input = bstr_dup_c("/%u0107"); + expected = bstr_dup_c("/c"); + cfg->path_u_encoding_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("%u decoding, 404 to UCS-2 characters"); + input = bstr_dup_c("/%u0107"); + expected = bstr_dup_c("/c"); + expected_status = 404; + cfg->path_u_encoding_decode = 1; + cfg->path_unicode_unwanted = HTP_UNWANTED_404; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Forward slash (URL-encoded), not expect to decode"); + input = bstr_dup_c("/one%2ftwo"); + expected = bstr_dup_c("/one%2ftwo"); + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Forward slash (URL-encoded), expect to decode"); + input = bstr_dup_c("/one%2ftwo"); + expected = bstr_dup_c("/one/two"); + cfg->path_encoded_separators_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Forward slash (URL-encoded), expect not do decode and 404"); + input = bstr_dup_c("/one%2ftwo"); + expected = bstr_dup_c("/one%2ftwo"); + expected_status = 404; + cfg->path_encoded_separators_decode = 0; + cfg->path_encoded_separators_unwanted = HTP_UNWANTED_404; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Forward slash (%u-encoded), expect to decode"); + input = bstr_dup_c("/one%u002ftwo"); + expected = bstr_dup_c("/one/two"); + cfg->path_encoded_separators_decode = 1; + cfg->path_u_encoding_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Forward slash (%u-encoded, fullwidth), expect to decode"); + input = bstr_dup_c("/one%uff0ftwo"); + expected = bstr_dup_c("/one/two"); + cfg->path_encoded_separators_decode = 1; + cfg->path_u_encoding_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Backslash (URL-encoded), not a separator; expect to decode"); + input = bstr_dup_c("/one%5ctwo"); + expected = bstr_dup_c("/one\\two"); + cfg->path_encoded_separators_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Backslash (URL-encoded), as path segment separator"); + input = bstr_dup_c("/one%5ctwo"); + expected = bstr_dup_c("/one/two"); + cfg->path_encoded_separators_decode = 1; + cfg->path_backslash_separators = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Backslash (not encoded), as path segment separator"); + input = bstr_dup_c("/one\\two"); + expected = bstr_dup_c("/one/two"); + cfg->path_backslash_separators = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Backslash (%u-encoded), as path segment separator"); + input = bstr_dup_c("/one%u005ctwo"); + expected = bstr_dup_c("/one/two"); + cfg->path_encoded_separators_decode = 1; + cfg->path_backslash_separators = 1; + cfg->path_u_encoding_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Backslash (%u-encoded, fullwidth), as path segment separator"); + input = bstr_dup_c("/one%uff3ctwo"); + expected = bstr_dup_c("/one/two"); + cfg->path_encoded_separators_decode = 1; + cfg->path_backslash_separators = 1; + cfg->path_u_encoding_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid UTF-8 encoding, encoded"); + input = bstr_dup_c("/%f7test"); + expected = bstr_dup_c("/\xf7test"); + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Invalid UTF-8 encoding, encoded (400)"); + input = bstr_dup_c("/%f7test"); + expected = bstr_dup_c("/\xf7test"); + expected_status = 400; + expected_flags = HTP_PATH_UTF8_INVALID; + cfg->path_utf8_invalid_unwanted = HTP_UNWANTED_400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (raw) in path; leave"); + input = bstr_dup_mem("/test\0text", 10); + expected = bstr_dup_mem("/test\0text", 10); + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (raw) in path; terminate path"); + input = bstr_dup_mem("/test\0text", 10); + expected = bstr_dup_c("/test"); + cfg->path_nul_raw_terminates = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (raw) in path; 400"); + input = bstr_dup_mem("/test\0text", 10); + expected = bstr_dup_mem("/test\0text", 10); + cfg->path_nul_raw_unwanted = HTP_UNWANTED_400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (URL-encoded) in path; leave"); + input = bstr_dup_c("/test%00text"); + expected = bstr_dup_mem("/test\0text", 10); + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (URL-encoded) in path; terminate path"); + input = bstr_dup_c("/test%00text"); + expected = bstr_dup_c("/test"); + cfg->path_nul_encoded_terminates = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (URL-encoded) in path; 400"); + input = bstr_dup_c("/test%00text"); + expected = bstr_dup_mem("/test\0text", 10); + cfg->path_nul_encoded_unwanted = HTP_UNWANTED_404; + expected_status = 400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (URL-encoded) in path; 404"); + input = bstr_dup_c("/test%00text"); + expected = bstr_dup_mem("/test\0text", 10); + cfg->path_nul_encoded_unwanted = HTP_UNWANTED_404; + expected_status = 404; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (%u-encoded) in path; terminate path"); + input = bstr_dup_c("/test%00text"); + expected = bstr_dup_c("/test"); + cfg->path_nul_encoded_terminates = 1; + cfg->path_u_encoding_decode = 1; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (%u-encoded) in path; 400"); + input = bstr_dup_c("/test%00text"); + expected = bstr_dup_mem("/test\0text", 10); + cfg->path_nul_encoded_unwanted = HTP_UNWANTED_404; + cfg->path_u_encoding_decode = 1; + expected_status = 400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("NUL byte (%u-encoded) in path; 404"); + input = bstr_dup_c("/test%00text"); + expected = bstr_dup_mem("/test\0text", 10); + cfg->path_nul_encoded_unwanted = HTP_UNWANTED_404; + cfg->path_u_encoding_decode = 1; + expected_status = 404; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Control char in path, encoded (no effect)"); + input = bstr_dup_c("/%01test"); + expected = bstr_dup_c("/\x01test"); + cfg->path_control_chars_unwanted = HTP_UNWANTED_IGNORE; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Control char in path, raw (no effect)"); + input = bstr_dup_c("/\x01test"); + expected = bstr_dup_c("/\x01test"); + cfg->path_control_chars_unwanted = HTP_UNWANTED_IGNORE; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Control char in path, encoded (400)"); + input = bstr_dup_c("/%01test"); + expected = bstr_dup_c("/\x01test"); + expected_status = 400; + cfg->path_control_chars_unwanted = HTP_UNWANTED_400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("Control char in path, raw (400)"); + input = bstr_dup_c("/\x01test"); + expected = bstr_dup_c("/\x01test"); + expected_status = 400; + cfg->path_control_chars_unwanted = HTP_UNWANTED_400; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("UTF-8; overlong 2-byte sequence"); + input = bstr_dup_c("/%c1%b4est"); + expected = bstr_dup_c("/test"); + expected_flags = HTP_PATH_UTF8_OVERLONG; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("UTF-8; overlong 3-byte sequence"); + input = bstr_dup_c("/%e0%81%b4est"); + expected = bstr_dup_c("/test"); + expected_flags = HTP_PATH_UTF8_OVERLONG; + PATH_DECODE_TEST_AFTER(); + + PATH_DECODE_TEST_BEFORE("UTF-8; overlong 4-byte sequence"); + input = bstr_dup_c("/%f0%80%81%b4est"); + expected = bstr_dup_c("/test"); + expected_flags = HTP_PATH_UTF8_OVERLONG; + PATH_DECODE_TEST_AFTER(); + + printf("\n"); + printf("Total tests: %i, %i failure(s).\n", tests, failures); +} |