From 26ac576c3bce2ff7720bbf784372dd5202befd49 Mon Sep 17 00:00:00 2001 From: Artur Date: Mon, 16 May 2022 13:59:40 +0200 Subject: [PATCH 01/10] Fixes after review --- .vscode/c_cpp_properties.json | 22 +++ .vscode/settings.json | 13 ++ config | 3 +- config.orig | 192 +++++++++++++++++++++++ src/ngx_http_modsecurity_body_filter.c | 4 +- src/ngx_http_modsecurity_common.h | 2 +- src/ngx_http_modsecurity_header_filter.c | 6 +- src/ngx_http_modsecurity_log.c | 4 +- src/ngx_http_modsecurity_module.c | 132 ++++++++++++++-- src/ngx_http_modsecurity_pre_access.c | 7 +- src/ngx_http_modsecurity_rewrite.c | 4 +- 11 files changed, 363 insertions(+), 26 deletions(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json create mode 100644 config.orig diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..d19345a --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,22 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "${workspaceFolder}/**", + "/Users/artur.mackowiak/Projects/Pluton/waf_software/ModSecurity-nginx/**", + "/Users/artur.mackowiak/Projects/Pluton/waf_software/nginx/**", + "/Users/artur.mackowiak/Projects/Pluton/waf_software/ModSecurity/**" + ], + "defines": [], + "macFrameworkPath": [ + "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks" + ], + "compilerPath": "/usr/bin/clang", + "cStandard": "c17", + "cppStandard": "c++98", + "intelliSenseMode": "macos-clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c754962 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "files.associations": { + "ngx_http_modsecurity_common.h": "c", + "ddebug.h": "c", + "ngx_config.h": "c", + "iterator": "c", + "ngx_core.h": "c", + "stack": "c", + "random": "c", + "chrono": "c", + "ctime": "c" + } +} \ No newline at end of file diff --git a/config b/config index c6e7467..440fc24 100644 --- a/config +++ b/config @@ -93,7 +93,8 @@ ngx_addon_name=ngx_http_modsecurity_module # # For static compilation HTTP_FILTER_MODULES will be patched later. -modsecurity_dependency="ngx_http_postpone_filter_module \ +modsecurity_dependency="ngx_http_link_func_module \ + ngx_http_postpone_filter_module \ ngx_http_ssi_filter_module \ ngx_http_charset_filter_module \ ngx_http_xslt_filter_module \ diff --git a/config.orig b/config.orig new file mode 100644 index 0000000..c6e7467 --- /dev/null +++ b/config.orig @@ -0,0 +1,192 @@ +# vim: filetype=sh + +# If $NGX_IGNORE_RPATH is set to "YES", we will ignore explicit +# library path specification on resulting binary, allowing libmodsecurity.so +# to be relocated across configured library pathes (adjust /etc/ld.so.conf +# or set $LD_LIBRARY_PATH environment variable to manage them) +# +# $YAJL_LIB variable may need to be populated in case of non-standard +# path of libyajl.so's installation + +ngx_feature_name= +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_libs="-lmodsecurity" +ngx_feature_test='printf("hello");' +ngx_modsecurity_opt_I= +ngx_modsecurity_opt_L= + +YAJL_EXTRA= +if test -n "$YAJL_LIB"; then + YAJL_EXTRA="-L$YAJL_LIB -lyajl" +fi + +# If $MODSECURITY_INC is specified, lets use it. Otherwise lets try +# the default paths +# +if [ -n "$MODSECURITY_INC" -o -n "$MODSECURITY_LIB" ]; then + # explicitly set ModSecurity lib path + ngx_feature="ModSecurity library in \"$MODSECURITY_LIB\" and \"$MODSECURITY_INC\" (specified by the MODSECURITY_LIB and MODSECURITY_INC env)" + ngx_feature_path="$MODSECURITY_INC" + ngx_modsecurity_opt_I="-I$MODSECURITY_INC" + ngx_modsecurity_opt_L="-L$MODSECURITY_LIB $YAJL_EXTRA" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R$MODSECURITY_LIB -L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" + elif [ "$NGX_IGNORE_RPATH" != "YES" -a $NGX_SYSTEM = "Linux" ]; then + ngx_feature_libs="-Wl,-rpath,$MODSECURITY_LIB -L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" + else + ngx_feature_libs="-L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" + fi + + . auto/feature + + if [ $ngx_found = no ]; then + cat << END + $0: error: ngx_http_modsecurity_module requires the ModSecurity library and MODSECURITY_LIB is defined as "$MODSECURITY_LIB" and MODSECURITY_INC (path for modsecurity.h) "$MODSECURITY_INC", but we cannot find ModSecurity there. +END + exit 1 + fi +else + # auto-discovery + ngx_feature="ModSecurity library" + ngx_feature_libs="-lmodsecurity" + + . auto/feature + + if [ $ngx_found = no ]; then + ngx_feature="ModSecurity library in /usr/local/modsecurity" + ngx_feature_path="/usr/local/modsecurity/include" + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/usr/local/modsecurity/lib -L/usr/local/modsecurity/lib -lmodsecurity" + elif [ "$NGX_IGNORE_RPATH" != "YES" -a $NGX_SYSTEM = "Linux" ]; then + ngx_feature_libs="-Wl,-rpath,/usr/local/modsecurity/lib -L/usr/local/modsecurity/lib -lmodsecurity" + else + ngx_feature_libs="-L/usr/local/modsecurity/lib -lmodsecurity" + fi + + . auto/feature + + fi +fi + + + +if [ $ngx_found = no ]; then + cat << END + $0: error: ngx_http_modsecurity_module requires the ModSecurity library. +END + exit 1 +fi + + +ngx_addon_name=ngx_http_modsecurity_module + +# We must place ngx_http_modsecurity_module after ngx_http_gzip_filter_module +# in load order list to be able to read response body before it gets compressed +# (for filter modules later initialization means earlier execution). +# +# Nginx implements load ordering only for dynamic modules and only a BEFORE part +# of "ngx_module_order". So we list all of the modules that come after +# ngx_http_gzip_filter_module as a BEFORE dependency for +# ngx_http_modsecurity_module. +# +# For static compilation HTTP_FILTER_MODULES will be patched later. + +modsecurity_dependency="ngx_http_postpone_filter_module \ + ngx_http_ssi_filter_module \ + ngx_http_charset_filter_module \ + ngx_http_xslt_filter_module \ + ngx_http_image_filter_module \ + ngx_http_sub_filter_module \ + ngx_http_addition_filter_module \ + ngx_http_gunzip_filter_module \ + ngx_http_userid_filter_module \ + ngx_http_headers_filter_module \ + ngx_http_copy_filter_module" + + +if test -n "$ngx_module_link"; then + ngx_module_type=HTTP_FILTER + ngx_module_name="$ngx_addon_name" + ngx_module_srcs="$ngx_addon_dir/src/ngx_http_modsecurity_module.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_pre_access.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_header_filter.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_body_filter.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_log.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_rewrite.c \ + " + ngx_module_deps="$ngx_addon_dir/src/ddebug.h \ + $ngx_addon_dir/src/ngx_http_modsecurity_common.h \ + " + ngx_module_libs="$ngx_feature_libs" + ngx_module_incs="$ngx_feature_path" + + ngx_module_order="ngx_http_chunked_filter_module \ + ngx_http_v2_filter_module \ + ngx_http_range_header_filter_module \ + ngx_http_gzip_filter_module \ + $ngx_module_name \ + $modsecurity_dependency"; + + . auto/module +else + CFLAGS="$ngx_modsecurity_opt_I $CFLAGS" + NGX_LD_OPT="$ngx_modsecurity_opt_L $NGX_LD_OPT" + + CORE_INCS="$CORE_INCS $ngx_feature_path" + CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + + HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_modsecurity_module" + NGX_ADDON_SRCS="\ + $NGX_ADDON_SRCS \ + $ngx_addon_dir/src/ngx_http_modsecurity_module.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_pre_access.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_header_filter.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_body_filter.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_log.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_rewrite.c \ + " + + NGX_ADDON_DEPS="\ + $NGX_ADDON_DEPS \ + $ngx_addon_dir/src/ddebug.h \ + $ngx_addon_dir/src/ngx_http_modsecurity_common.h \ + " +fi + +# +# Nginx does not provide reliable way to introduce our module into required +# place in static ($ngx_module_link=ADDON) compilation mode, so we must +# explicitly update module "ordering rules". +# +if [ "$ngx_module_link" != DYNAMIC ] ; then + # Reposition modsecurity module to satisfy $modsecurity_dependency + # (this mimics dependency resolution made by ngx_add_module() function + # though less optimal in terms of computational complexity). + modules= + found= + for module in $HTTP_FILTER_MODULES; do + # skip our module name from the original list + if [ "$module" = "$ngx_addon_name" ]; then + continue + fi + if [ -z "${found}" ]; then + for item in $modsecurity_dependency; do + if [ "$module" = "$item" ]; then + modules="${modules} $ngx_addon_name" + found=1 + break + fi + done + fi + modules="${modules} $module" + done + if [ -z "${found}" ]; then + # This must never happen since ngx_http_copy_filter_module must be in HTTP_FILTER_MODULES + # and we stated dependency on it in $modsecurity_dependency + echo "$0: error: cannot reposition modsecurity module in HTTP_FILTER_MODULES list" + exit 1 + fi + HTTP_FILTER_MODULES="${modules}" +fi diff --git a/src/ngx_http_modsecurity_body_filter.c b/src/ngx_http_modsecurity_body_filter.c index 268d17d..29b1f98 100644 --- a/src/ngx_http_modsecurity_body_filter.c +++ b/src/ngx_http_modsecurity_body_filter.c @@ -156,8 +156,8 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in) if (is_request_processed) { ngx_pool_t *old_pool; - struct timeval start_tv; - ngx_gettimeofday(&start_tv); + struct timespec start_tv; + (void) clock_gettime(CLOCK_MONOTONIC, &start_tv); old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool); msc_process_response_body(ctx->modsec_transaction); diff --git a/src/ngx_http_modsecurity_common.h b/src/ngx_http_modsecurity_common.h index dc3e5a8..8282606 100644 --- a/src/ngx_http_modsecurity_common.h +++ b/src/ngx_http_modsecurity_common.h @@ -169,6 +169,6 @@ ngx_int_t ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r); /* ngx_http_modsecurity_rewrite.c */ ngx_int_t ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r); -ngx_msec_int_t ngx_http_modsecurity_compute_processing_time(struct timeval tv); +ngx_msec_int_t ngx_http_modsecurity_compute_processing_time(struct timespec tv); #endif /* _NGX_HTTP_MODSECURITY_COMMON_H_INCLUDED_ */ diff --git a/src/ngx_http_modsecurity_header_filter.c b/src/ngx_http_modsecurity_header_filter.c index 0c8df9b..0524a07 100644 --- a/src/ngx_http_modsecurity_header_filter.c +++ b/src/ngx_http_modsecurity_header_filter.c @@ -446,8 +446,8 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r) return ngx_http_next_header_filter(r); } - struct timeval start_tv; - ngx_gettimeofday(&start_tv); + struct timespec start_tv; + (void) clock_gettime(CLOCK_MONOTONIC, &start_tv); /* * Lets ask nginx to keep the response body in memory @@ -527,7 +527,7 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r) #endif old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool); - msc_process_response_headers(ctx->modsec_transaction, status, http_response_ver); + msc_process_response_headers(ctx->modsec_transaction, status, http_response_ver); ngx_http_modsecurity_pcre_malloc_done(old_pool); ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0); diff --git a/src/ngx_http_modsecurity_log.c b/src/ngx_http_modsecurity_log.c index 3a62a12..2b1f363 100644 --- a/src/ngx_http_modsecurity_log.c +++ b/src/ngx_http_modsecurity_log.c @@ -71,8 +71,8 @@ ngx_http_modsecurity_log_handler(ngx_http_request_t *r) dd("already logged earlier"); return NGX_OK; } - struct timeval start_tv; - ngx_gettimeofday(&start_tv); + struct timespec start_tv; + (void) clock_gettime(CLOCK_MONOTONIC, &start_tv); dd("calling msc_process_logging for %p", ctx); old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool); diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index da69ec3..aea9702 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -20,6 +20,7 @@ #include "ngx_http_modsecurity_common.h" #include "stdio.h" +#include "string.h" #include #include #include @@ -32,6 +33,9 @@ static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf); static char *ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child); static void ngx_http_modsecurity_cleanup_instance(void *data); static void ngx_http_modsecurity_cleanup_rules(void *data); +static ngx_table_elt_t * search_headers(ngx_list_part_t *part, u_char *name, size_t len); +static ngx_int_t add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers); +static void free_headers(AdditionalHeader *iterator); static ngx_int_t ngx_http_modsecurity_req_headers_phase_time(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -163,9 +167,14 @@ ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_re if (msc_intervention(transaction, &intervention) == 0) { dd("nothing to do"); + add_headers(msc_get_additional_req_headers(transaction), r->pool, &(r->headers_in.headers)); + add_headers(msc_get_additional_resp_headers(transaction), r->pool, &(r->headers_out.headers)); return 0; } + add_headers(msc_get_additional_req_headers(transaction), r->pool, &(r->headers_in.headers)); + add_headers(msc_get_additional_resp_headers(transaction), r->pool, &(r->headers_out.headers)); + log = intervention.log; if (intervention.log == NULL) { log = "(no log message was specified)"; @@ -542,25 +551,25 @@ ngx_module_t ngx_http_modsecurity_module = { static ngx_http_variable_t ngx_http_modsecurity_vars[] = { { ngx_string("modsecurity_req_headers_phase_time"), NULL, ngx_http_modsecurity_req_headers_phase_time, 0, - NGX_HTTP_VAR_NOCACHEABLE, 0 }, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("modsecurity_req_body_phase_time"), NULL, ngx_http_modsecurity_req_body_phase_time, 0, - NGX_HTTP_VAR_NOCACHEABLE, 0 }, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("modsecurity_resp_headers_phase_time"), NULL, ngx_http_modsecurity_resp_headers_phase_time, 0, - NGX_HTTP_VAR_NOCACHEABLE, 0 }, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("modsecurity_resp_body_phase_time"), NULL, ngx_http_modsecurity_resp_body_phase_time, 0, - NGX_HTTP_VAR_NOCACHEABLE, 0 }, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("modsecurity_logging_phase_time"), NULL, ngx_http_modsecurity_logging_phase_time, 0, - NGX_HTTP_VAR_NOCACHEABLE, 0 }, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, - ngx_http_null_variable + { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -816,6 +825,109 @@ ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } +static ngx_int_t +add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers) +{ + AdditionalHeader *header_from_modsecurity; + header_from_modsecurity = iterator; + dd("Debug - ADD HEADER: key - pointer : \"%p\"", header_from_modsecurity); + while(header_from_modsecurity != NULL) { + ngx_table_elt_t *header = NULL; + header = search_headers(&headers->part, (u_char *)header_from_modsecurity->key, strlen(header_from_modsecurity->key)); + + if (header == NULL) { + header = ngx_list_push(headers); + if (header == NULL) { + free_headers(iterator); + return NGX_ERROR; + } + header->key.data = ngx_pnalloc(pool, strlen(header_from_modsecurity->key)+1); + if (header->key.data == NULL) { + free_headers(iterator); + return NGX_ERROR; + } + header->key.len = strlen(header_from_modsecurity->key); + ngx_cpystrn(header->key.data, (u_char *)header_from_modsecurity->key, header->key.len+1); + } else if((strlen(header_from_modsecurity->value) == header->value.len) && (ngx_strcmp(&header->value.data, header_from_modsecurity->value) == 0)) { + header_from_modsecurity = header_from_modsecurity->next; + continue; + } + + dd("Debug - ADD HEADER: key: \"%s\"", header_from_modsecurity->key); + dd("Debug - ADD HEADER: value: \"%s\"", header_from_modsecurity->value); + header->value.data = ngx_pnalloc(pool, strlen(header_from_modsecurity->value)+1); + if (header->value.data == NULL) { + free_headers(iterator); + return NGX_ERROR; + } + header->value.len = strlen(header_from_modsecurity->value); + ngx_cpystrn(header->value.data, (u_char *)header_from_modsecurity->value, header->value.len+1); + header->hash = ngx_hash_key_lc(header->value.data, strlen(header_from_modsecurity->value)); + header_from_modsecurity = header_from_modsecurity->next; + }; + free_headers(iterator); + return NGX_OK; +} + +static void +free_headers(AdditionalHeader *iterator) { + AdditionalHeader* current; + while(iterator != NULL) { + current = iterator; + iterator = current->next; + free(current->key); + free(current->value); + free(current); + } +} + +static ngx_table_elt_t * +search_headers(ngx_list_part_t *part, u_char *name, size_t len) { + ngx_table_elt_t *h; + ngx_uint_t i; + + /* + Get the first part of the list. There is usual only one part. + */ + h = part->elts; + + /* + Headers list array may consist of more than one part, + so loop through all of it + */ + for (i = 0; /* void */ ; i++) { + if (i >= part->nelts) { + if (part->next == NULL) { + /* The last part, search is done. */ + break; + } + + part = part->next; + h = part->elts; + i = 0; + } + + /* + Just compare the lengths and then the names case insensitively. + */ + if (len != h[i].key.len || ngx_strcasecmp(name, h[i].key.data) != 0) { + /* This header doesn't match. */ + continue; + } + + /* + Ta-da, we got one! + Note, we'v stop the search at the first matched header + while more then one header may fit. + */ + return &h[i]; + } + + /* + No headers was found + */ + return NULL; +} static void ngx_http_modsecurity_cleanup_instance(void *data) @@ -946,10 +1058,10 @@ ngx_http_modsecurity_time_variable(ngx_http_request_t *r, ngx_msec_int_t -ngx_http_modsecurity_compute_processing_time(struct timeval tv) { - struct timeval current_tv; - ngx_gettimeofday(¤t_tv); - return (ngx_msec_int_t) ((current_tv.tv_sec - tv.tv_sec) * 1000000 + (current_tv.tv_usec - tv.tv_usec)); +ngx_http_modsecurity_compute_processing_time(struct timespec tv) { + struct timespec current_tv; + (void) clock_gettime(CLOCK_MONOTONIC, ¤t_tv); + return (ngx_msec_int_t) ((current_tv.tv_sec - tv.tv_sec) * 1000000000 + (current_tv.tv_nsec - tv.tv_nsec)); }; /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/ngx_http_modsecurity_pre_access.c b/src/ngx_http_modsecurity_pre_access.c index 5fcf5d6..41370ae 100644 --- a/src/ngx_http_modsecurity_pre_access.c +++ b/src/ngx_http_modsecurity_pre_access.c @@ -140,8 +140,8 @@ ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r) int ret = 0; int already_inspected = 0; - struct timeval start_tv; - ngx_gettimeofday(&start_tv); + struct timespec start_tv; + (void) clock_gettime(CLOCK_MONOTONIC, &start_tv); dd("request body is ready to be processed"); @@ -212,11 +212,8 @@ ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r) /* XXX: once more -- is body can be modified ? content-length need to be adjusted ? */ old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool); - msc_process_request_body(ctx->modsec_transaction); - ctx->req_body_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv); - ngx_http_modsecurity_pcre_malloc_done(old_pool); ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0); diff --git a/src/ngx_http_modsecurity_rewrite.c b/src/ngx_http_modsecurity_rewrite.c index 7739802..3723991 100644 --- a/src/ngx_http_modsecurity_rewrite.c +++ b/src/ngx_http_modsecurity_rewrite.c @@ -51,9 +51,9 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r) if (ctx == NULL) { int ret = 0; - struct timeval start_tv; + struct timespec start_tv; - ngx_gettimeofday(&start_tv); + (void) clock_gettime(CLOCK_MONOTONIC, &start_tv); ngx_connection_t *connection = r->connection; /** From 481e4637a732332a53275e29418f911be7027130 Mon Sep 17 00:00:00 2001 From: Artur Date: Mon, 16 May 2022 14:00:29 +0200 Subject: [PATCH 02/10] Fixes after review --- .vscode/c_cpp_properties.json | 22 ---------------------- .vscode/settings.json | 13 ------------- 2 files changed, 35 deletions(-) delete mode 100644 .vscode/c_cpp_properties.json delete mode 100644 .vscode/settings.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index d19345a..0000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": [ - "${workspaceFolder}/**", - "/Users/artur.mackowiak/Projects/Pluton/waf_software/ModSecurity-nginx/**", - "/Users/artur.mackowiak/Projects/Pluton/waf_software/nginx/**", - "/Users/artur.mackowiak/Projects/Pluton/waf_software/ModSecurity/**" - ], - "defines": [], - "macFrameworkPath": [ - "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks" - ], - "compilerPath": "/usr/bin/clang", - "cStandard": "c17", - "cppStandard": "c++98", - "intelliSenseMode": "macos-clang-x64" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index c754962..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "files.associations": { - "ngx_http_modsecurity_common.h": "c", - "ddebug.h": "c", - "ngx_config.h": "c", - "iterator": "c", - "ngx_core.h": "c", - "stack": "c", - "random": "c", - "chrono": "c", - "ctime": "c" - } -} \ No newline at end of file From 811d9a0d4cea3f01a5863eff166be3e178b131bc Mon Sep 17 00:00:00 2001 From: Artur Date: Tue, 17 May 2022 13:36:29 +0200 Subject: [PATCH 03/10] Fixes after review --- config.orig | 192 ------------------------------ config.rej | 12 ++ src/ngx_http_modsecurity_module.c | 40 ++++--- 3 files changed, 35 insertions(+), 209 deletions(-) delete mode 100644 config.orig create mode 100644 config.rej diff --git a/config.orig b/config.orig deleted file mode 100644 index c6e7467..0000000 --- a/config.orig +++ /dev/null @@ -1,192 +0,0 @@ -# vim: filetype=sh - -# If $NGX_IGNORE_RPATH is set to "YES", we will ignore explicit -# library path specification on resulting binary, allowing libmodsecurity.so -# to be relocated across configured library pathes (adjust /etc/ld.so.conf -# or set $LD_LIBRARY_PATH environment variable to manage them) -# -# $YAJL_LIB variable may need to be populated in case of non-standard -# path of libyajl.so's installation - -ngx_feature_name= -ngx_feature_run=no -ngx_feature_incs="#include " -ngx_feature_libs="-lmodsecurity" -ngx_feature_test='printf("hello");' -ngx_modsecurity_opt_I= -ngx_modsecurity_opt_L= - -YAJL_EXTRA= -if test -n "$YAJL_LIB"; then - YAJL_EXTRA="-L$YAJL_LIB -lyajl" -fi - -# If $MODSECURITY_INC is specified, lets use it. Otherwise lets try -# the default paths -# -if [ -n "$MODSECURITY_INC" -o -n "$MODSECURITY_LIB" ]; then - # explicitly set ModSecurity lib path - ngx_feature="ModSecurity library in \"$MODSECURITY_LIB\" and \"$MODSECURITY_INC\" (specified by the MODSECURITY_LIB and MODSECURITY_INC env)" - ngx_feature_path="$MODSECURITY_INC" - ngx_modsecurity_opt_I="-I$MODSECURITY_INC" - ngx_modsecurity_opt_L="-L$MODSECURITY_LIB $YAJL_EXTRA" - - if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R$MODSECURITY_LIB -L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" - elif [ "$NGX_IGNORE_RPATH" != "YES" -a $NGX_SYSTEM = "Linux" ]; then - ngx_feature_libs="-Wl,-rpath,$MODSECURITY_LIB -L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" - else - ngx_feature_libs="-L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" - fi - - . auto/feature - - if [ $ngx_found = no ]; then - cat << END - $0: error: ngx_http_modsecurity_module requires the ModSecurity library and MODSECURITY_LIB is defined as "$MODSECURITY_LIB" and MODSECURITY_INC (path for modsecurity.h) "$MODSECURITY_INC", but we cannot find ModSecurity there. -END - exit 1 - fi -else - # auto-discovery - ngx_feature="ModSecurity library" - ngx_feature_libs="-lmodsecurity" - - . auto/feature - - if [ $ngx_found = no ]; then - ngx_feature="ModSecurity library in /usr/local/modsecurity" - ngx_feature_path="/usr/local/modsecurity/include" - if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/usr/local/modsecurity/lib -L/usr/local/modsecurity/lib -lmodsecurity" - elif [ "$NGX_IGNORE_RPATH" != "YES" -a $NGX_SYSTEM = "Linux" ]; then - ngx_feature_libs="-Wl,-rpath,/usr/local/modsecurity/lib -L/usr/local/modsecurity/lib -lmodsecurity" - else - ngx_feature_libs="-L/usr/local/modsecurity/lib -lmodsecurity" - fi - - . auto/feature - - fi -fi - - - -if [ $ngx_found = no ]; then - cat << END - $0: error: ngx_http_modsecurity_module requires the ModSecurity library. -END - exit 1 -fi - - -ngx_addon_name=ngx_http_modsecurity_module - -# We must place ngx_http_modsecurity_module after ngx_http_gzip_filter_module -# in load order list to be able to read response body before it gets compressed -# (for filter modules later initialization means earlier execution). -# -# Nginx implements load ordering only for dynamic modules and only a BEFORE part -# of "ngx_module_order". So we list all of the modules that come after -# ngx_http_gzip_filter_module as a BEFORE dependency for -# ngx_http_modsecurity_module. -# -# For static compilation HTTP_FILTER_MODULES will be patched later. - -modsecurity_dependency="ngx_http_postpone_filter_module \ - ngx_http_ssi_filter_module \ - ngx_http_charset_filter_module \ - ngx_http_xslt_filter_module \ - ngx_http_image_filter_module \ - ngx_http_sub_filter_module \ - ngx_http_addition_filter_module \ - ngx_http_gunzip_filter_module \ - ngx_http_userid_filter_module \ - ngx_http_headers_filter_module \ - ngx_http_copy_filter_module" - - -if test -n "$ngx_module_link"; then - ngx_module_type=HTTP_FILTER - ngx_module_name="$ngx_addon_name" - ngx_module_srcs="$ngx_addon_dir/src/ngx_http_modsecurity_module.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_pre_access.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_header_filter.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_body_filter.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_log.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_rewrite.c \ - " - ngx_module_deps="$ngx_addon_dir/src/ddebug.h \ - $ngx_addon_dir/src/ngx_http_modsecurity_common.h \ - " - ngx_module_libs="$ngx_feature_libs" - ngx_module_incs="$ngx_feature_path" - - ngx_module_order="ngx_http_chunked_filter_module \ - ngx_http_v2_filter_module \ - ngx_http_range_header_filter_module \ - ngx_http_gzip_filter_module \ - $ngx_module_name \ - $modsecurity_dependency"; - - . auto/module -else - CFLAGS="$ngx_modsecurity_opt_I $CFLAGS" - NGX_LD_OPT="$ngx_modsecurity_opt_L $NGX_LD_OPT" - - CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_modsecurity_module" - NGX_ADDON_SRCS="\ - $NGX_ADDON_SRCS \ - $ngx_addon_dir/src/ngx_http_modsecurity_module.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_pre_access.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_header_filter.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_body_filter.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_log.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_rewrite.c \ - " - - NGX_ADDON_DEPS="\ - $NGX_ADDON_DEPS \ - $ngx_addon_dir/src/ddebug.h \ - $ngx_addon_dir/src/ngx_http_modsecurity_common.h \ - " -fi - -# -# Nginx does not provide reliable way to introduce our module into required -# place in static ($ngx_module_link=ADDON) compilation mode, so we must -# explicitly update module "ordering rules". -# -if [ "$ngx_module_link" != DYNAMIC ] ; then - # Reposition modsecurity module to satisfy $modsecurity_dependency - # (this mimics dependency resolution made by ngx_add_module() function - # though less optimal in terms of computational complexity). - modules= - found= - for module in $HTTP_FILTER_MODULES; do - # skip our module name from the original list - if [ "$module" = "$ngx_addon_name" ]; then - continue - fi - if [ -z "${found}" ]; then - for item in $modsecurity_dependency; do - if [ "$module" = "$item" ]; then - modules="${modules} $ngx_addon_name" - found=1 - break - fi - done - fi - modules="${modules} $module" - done - if [ -z "${found}" ]; then - # This must never happen since ngx_http_copy_filter_module must be in HTTP_FILTER_MODULES - # and we stated dependency on it in $modsecurity_dependency - echo "$0: error: cannot reposition modsecurity module in HTTP_FILTER_MODULES list" - exit 1 - fi - HTTP_FILTER_MODULES="${modules}" -fi diff --git a/config.rej b/config.rej new file mode 100644 index 0000000..5ad326f --- /dev/null +++ b/config.rej @@ -0,0 +1,12 @@ +--- config ++++ config +@@ -93,7 +93,8 @@ ngx_addon_name=ngx_http_modsecurity_module + # + # For static compilation HTTP_FILTER_MODULES will be patched later. + +-modsecurity_dependency="ngx_http_postpone_filter_module \ ++modsecurity_dependency="ngx_http_link_func_module \ ++ ngx_http_postpone_filter_module \ + ngx_http_ssi_filter_module \ + ngx_http_charset_filter_module \ + diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index aea9702..862b2b3 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -37,15 +37,7 @@ static ngx_table_elt_t * search_headers(ngx_list_part_t *part, u_char *name, siz static ngx_int_t add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers); static void free_headers(AdditionalHeader *iterator); -static ngx_int_t ngx_http_modsecurity_req_headers_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_modsecurity_req_body_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_modsecurity_resp_headers_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_modsecurity_resp_body_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_modsecurity_logging_phase_time(ngx_http_request_t *r, +static ngx_int_t ngx_http_modsecurity_phase_time(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_modsecurity_time_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data, ngx_msec_int_t usec); @@ -550,23 +542,23 @@ ngx_module_t ngx_http_modsecurity_module = { static ngx_http_variable_t ngx_http_modsecurity_vars[] = { { ngx_string("modsecurity_req_headers_phase_time"), NULL, - ngx_http_modsecurity_req_headers_phase_time, 0, + ngx_http_modsecurity_phase_time, 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("modsecurity_req_body_phase_time"), NULL, - ngx_http_modsecurity_req_body_phase_time, 0, + ngx_http_modsecurity_phase_time, 1, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("modsecurity_resp_headers_phase_time"), NULL, - ngx_http_modsecurity_resp_headers_phase_time, 0, + ngx_http_modsecurity_phase_time, 2, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("modsecurity_resp_body_phase_time"), NULL, - ngx_http_modsecurity_resp_body_phase_time, 0, + ngx_http_modsecurity_phase_time, 3, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("modsecurity_logging_phase_time"), NULL, - ngx_http_modsecurity_logging_phase_time, 0, + ngx_http_modsecurity_phase_time, 4, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, { ngx_null_string, NULL, NULL, 0, 0, 0 } @@ -962,16 +954,30 @@ ngx_http_modsecurity_cleanup_rules(void *data) static ngx_int_t -ngx_http_modsecurity_req_headers_phase_time(ngx_http_request_t *r, +ngx_http_modsecurity_phase_time(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_modsecurity_ctx_t *ctx; + ngx_msec_int_t phase_time; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); if (ctx == NULL) { return NGX_ERROR; } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_headers_phase_time); + + if (data == 0) { + phase_time = ctx->req_headers_phase_time; + } else if (data == 1) { + phase_time = ctx->req_body_phase_time; + } else if (data == 2) { + phase_time = ctx->resp_headers_phase_time; + } else if (data == 3) { + phase_time = ctx->resp_body_phase_time; + } else if (data == 4) { + phase_time = ctx->logging_phase_time; + } + + return ngx_http_modsecurity_time_variable(r, v, data, ctx->phase_time); } @@ -1045,7 +1051,7 @@ ngx_http_modsecurity_time_variable(ngx_http_request_t *r, if(usec == -1) { v->len = ngx_sprintf(p, "-") - p; } else { - v->len = ngx_sprintf(p, "%T.%06M", (time_t) usec / 1000000, usec % 1000000) - p; + v->len = ngx_sprintf(p, "%T.%06M", (time_t) nsec / 1000000000, nsec % 1000000000) - p; } v->valid = 1; From f7cff0635e87f6cc9187d8e4accf255414bcaa4b Mon Sep 17 00:00:00 2001 From: Artur Mackowiak Date: Wed, 18 May 2022 10:30:17 +0200 Subject: [PATCH 04/10] Fixes after review --- config.orig | 192 +++++ src/ngx_http_modsecurity_module.c | 28 +- src/ngx_http_modsecurity_module.c.orig | 961 +++++++++++++++++++++++++ src/ngx_http_modsecurity_module.c.rej | 144 ++++ 4 files changed, 1311 insertions(+), 14 deletions(-) create mode 100644 config.orig create mode 100644 src/ngx_http_modsecurity_module.c.orig create mode 100644 src/ngx_http_modsecurity_module.c.rej diff --git a/config.orig b/config.orig new file mode 100644 index 0000000..c6e7467 --- /dev/null +++ b/config.orig @@ -0,0 +1,192 @@ +# vim: filetype=sh + +# If $NGX_IGNORE_RPATH is set to "YES", we will ignore explicit +# library path specification on resulting binary, allowing libmodsecurity.so +# to be relocated across configured library pathes (adjust /etc/ld.so.conf +# or set $LD_LIBRARY_PATH environment variable to manage them) +# +# $YAJL_LIB variable may need to be populated in case of non-standard +# path of libyajl.so's installation + +ngx_feature_name= +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_libs="-lmodsecurity" +ngx_feature_test='printf("hello");' +ngx_modsecurity_opt_I= +ngx_modsecurity_opt_L= + +YAJL_EXTRA= +if test -n "$YAJL_LIB"; then + YAJL_EXTRA="-L$YAJL_LIB -lyajl" +fi + +# If $MODSECURITY_INC is specified, lets use it. Otherwise lets try +# the default paths +# +if [ -n "$MODSECURITY_INC" -o -n "$MODSECURITY_LIB" ]; then + # explicitly set ModSecurity lib path + ngx_feature="ModSecurity library in \"$MODSECURITY_LIB\" and \"$MODSECURITY_INC\" (specified by the MODSECURITY_LIB and MODSECURITY_INC env)" + ngx_feature_path="$MODSECURITY_INC" + ngx_modsecurity_opt_I="-I$MODSECURITY_INC" + ngx_modsecurity_opt_L="-L$MODSECURITY_LIB $YAJL_EXTRA" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R$MODSECURITY_LIB -L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" + elif [ "$NGX_IGNORE_RPATH" != "YES" -a $NGX_SYSTEM = "Linux" ]; then + ngx_feature_libs="-Wl,-rpath,$MODSECURITY_LIB -L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" + else + ngx_feature_libs="-L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" + fi + + . auto/feature + + if [ $ngx_found = no ]; then + cat << END + $0: error: ngx_http_modsecurity_module requires the ModSecurity library and MODSECURITY_LIB is defined as "$MODSECURITY_LIB" and MODSECURITY_INC (path for modsecurity.h) "$MODSECURITY_INC", but we cannot find ModSecurity there. +END + exit 1 + fi +else + # auto-discovery + ngx_feature="ModSecurity library" + ngx_feature_libs="-lmodsecurity" + + . auto/feature + + if [ $ngx_found = no ]; then + ngx_feature="ModSecurity library in /usr/local/modsecurity" + ngx_feature_path="/usr/local/modsecurity/include" + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/usr/local/modsecurity/lib -L/usr/local/modsecurity/lib -lmodsecurity" + elif [ "$NGX_IGNORE_RPATH" != "YES" -a $NGX_SYSTEM = "Linux" ]; then + ngx_feature_libs="-Wl,-rpath,/usr/local/modsecurity/lib -L/usr/local/modsecurity/lib -lmodsecurity" + else + ngx_feature_libs="-L/usr/local/modsecurity/lib -lmodsecurity" + fi + + . auto/feature + + fi +fi + + + +if [ $ngx_found = no ]; then + cat << END + $0: error: ngx_http_modsecurity_module requires the ModSecurity library. +END + exit 1 +fi + + +ngx_addon_name=ngx_http_modsecurity_module + +# We must place ngx_http_modsecurity_module after ngx_http_gzip_filter_module +# in load order list to be able to read response body before it gets compressed +# (for filter modules later initialization means earlier execution). +# +# Nginx implements load ordering only for dynamic modules and only a BEFORE part +# of "ngx_module_order". So we list all of the modules that come after +# ngx_http_gzip_filter_module as a BEFORE dependency for +# ngx_http_modsecurity_module. +# +# For static compilation HTTP_FILTER_MODULES will be patched later. + +modsecurity_dependency="ngx_http_postpone_filter_module \ + ngx_http_ssi_filter_module \ + ngx_http_charset_filter_module \ + ngx_http_xslt_filter_module \ + ngx_http_image_filter_module \ + ngx_http_sub_filter_module \ + ngx_http_addition_filter_module \ + ngx_http_gunzip_filter_module \ + ngx_http_userid_filter_module \ + ngx_http_headers_filter_module \ + ngx_http_copy_filter_module" + + +if test -n "$ngx_module_link"; then + ngx_module_type=HTTP_FILTER + ngx_module_name="$ngx_addon_name" + ngx_module_srcs="$ngx_addon_dir/src/ngx_http_modsecurity_module.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_pre_access.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_header_filter.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_body_filter.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_log.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_rewrite.c \ + " + ngx_module_deps="$ngx_addon_dir/src/ddebug.h \ + $ngx_addon_dir/src/ngx_http_modsecurity_common.h \ + " + ngx_module_libs="$ngx_feature_libs" + ngx_module_incs="$ngx_feature_path" + + ngx_module_order="ngx_http_chunked_filter_module \ + ngx_http_v2_filter_module \ + ngx_http_range_header_filter_module \ + ngx_http_gzip_filter_module \ + $ngx_module_name \ + $modsecurity_dependency"; + + . auto/module +else + CFLAGS="$ngx_modsecurity_opt_I $CFLAGS" + NGX_LD_OPT="$ngx_modsecurity_opt_L $NGX_LD_OPT" + + CORE_INCS="$CORE_INCS $ngx_feature_path" + CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + + HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_modsecurity_module" + NGX_ADDON_SRCS="\ + $NGX_ADDON_SRCS \ + $ngx_addon_dir/src/ngx_http_modsecurity_module.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_pre_access.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_header_filter.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_body_filter.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_log.c \ + $ngx_addon_dir/src/ngx_http_modsecurity_rewrite.c \ + " + + NGX_ADDON_DEPS="\ + $NGX_ADDON_DEPS \ + $ngx_addon_dir/src/ddebug.h \ + $ngx_addon_dir/src/ngx_http_modsecurity_common.h \ + " +fi + +# +# Nginx does not provide reliable way to introduce our module into required +# place in static ($ngx_module_link=ADDON) compilation mode, so we must +# explicitly update module "ordering rules". +# +if [ "$ngx_module_link" != DYNAMIC ] ; then + # Reposition modsecurity module to satisfy $modsecurity_dependency + # (this mimics dependency resolution made by ngx_add_module() function + # though less optimal in terms of computational complexity). + modules= + found= + for module in $HTTP_FILTER_MODULES; do + # skip our module name from the original list + if [ "$module" = "$ngx_addon_name" ]; then + continue + fi + if [ -z "${found}" ]; then + for item in $modsecurity_dependency; do + if [ "$module" = "$item" ]; then + modules="${modules} $ngx_addon_name" + found=1 + break + fi + done + fi + modules="${modules} $module" + done + if [ -z "${found}" ]; then + # This must never happen since ngx_http_copy_filter_module must be in HTTP_FILTER_MODULES + # and we stated dependency on it in $modsecurity_dependency + echo "$0: error: cannot reposition modsecurity module in HTTP_FILTER_MODULES list" + exit 1 + fi + HTTP_FILTER_MODULES="${modules}" +fi diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index 862b2b3..4834d3f 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -958,26 +958,26 @@ ngx_http_modsecurity_phase_time(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_modsecurity_ctx_t *ctx; - ngx_msec_int_t phase_time; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); if (ctx == NULL) { return NGX_ERROR; } - if (data == 0) { - phase_time = ctx->req_headers_phase_time; - } else if (data == 1) { - phase_time = ctx->req_body_phase_time; - } else if (data == 2) { - phase_time = ctx->resp_headers_phase_time; - } else if (data == 3) { - phase_time = ctx->resp_body_phase_time; - } else if (data == 4) { - phase_time = ctx->logging_phase_time; + switch(data) { + case 0: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_headers_phase_time); + case 1: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_body_phase_time); + case 2: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_headers_phase_time); + case 3: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_body_phase_time); + case 4: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->logging_phase_time); } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->phase_time); + return -1; } @@ -1051,7 +1051,7 @@ ngx_http_modsecurity_time_variable(ngx_http_request_t *r, if(usec == -1) { v->len = ngx_sprintf(p, "-") - p; } else { - v->len = ngx_sprintf(p, "%T.%06M", (time_t) nsec / 1000000000, nsec % 1000000000) - p; + v->len = ngx_sprintf(p, "%T.%06M", (time_t) usec / 1000000, usec % 1000000) - p; } v->valid = 1; @@ -1067,7 +1067,7 @@ ngx_msec_int_t ngx_http_modsecurity_compute_processing_time(struct timespec tv) { struct timespec current_tv; (void) clock_gettime(CLOCK_MONOTONIC, ¤t_tv); - return (ngx_msec_int_t) ((current_tv.tv_sec - tv.tv_sec) * 1000000000 + (current_tv.tv_nsec - tv.tv_nsec)); + return (ngx_msec_int_t) ((current_tv.tv_sec - tv.tv_sec) * 1000000 + (current_tv.tv_nsec - tv.tv_nsec) / 1000); }; /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/ngx_http_modsecurity_module.c.orig b/src/ngx_http_modsecurity_module.c.orig new file mode 100644 index 0000000..b6c8d19 --- /dev/null +++ b/src/ngx_http_modsecurity_module.c.orig @@ -0,0 +1,961 @@ +/* + * ModSecurity connector for nginx, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#ifndef MODSECURITY_DDEBUG +#define MODSECURITY_DDEBUG 0 +#endif +#include "ddebug.h" + +#include "ngx_http_modsecurity_common.h" +#include "stdio.h" +#include +#include +#include + +static ngx_int_t ngx_http_modsecurity_init(ngx_conf_t *cf); +static ngx_int_t ngx_http_modsecurity_add_variables(ngx_conf_t *cf); +static void *ngx_http_modsecurity_create_main_conf(ngx_conf_t *cf); +static char *ngx_http_modsecurity_init_main_conf(ngx_conf_t *cf, void *conf); +static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf); +static char *ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child); +static void ngx_http_modsecurity_cleanup_instance(void *data); +static void ngx_http_modsecurity_cleanup_rules(void *data); + +static ngx_int_t ngx_http_modsecurity_phase_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_modsecurity_time_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data, ngx_msec_int_t usec); + +/* + * PCRE malloc/free workaround, based on + * https://github.com/openresty/lua-nginx-module/blob/master/src/ngx_http_lua_pcrefix.c + */ + +static void *(*old_pcre_malloc)(size_t); +static void (*old_pcre_free)(void *ptr); +static ngx_pool_t *ngx_http_modsec_pcre_pool = NULL; + +static void * +ngx_http_modsec_pcre_malloc(size_t size) +{ + if (ngx_http_modsec_pcre_pool) { + return ngx_palloc(ngx_http_modsec_pcre_pool, size); + } + + fprintf(stderr, "error: modsec pcre malloc failed due to empty pcre pool"); + + return NULL; +} + +static void +ngx_http_modsec_pcre_free(void *ptr) +{ + if (ngx_http_modsec_pcre_pool) { + ngx_pfree(ngx_http_modsec_pcre_pool, ptr); + return; + } + +#if 0 + /* this may happen when called from cleanup handlers */ + fprintf(stderr, "error: modsec pcre free failed due to empty pcre pool"); +#endif + + return; +} + +ngx_pool_t * +ngx_http_modsecurity_pcre_malloc_init(ngx_pool_t *pool) +{ + ngx_pool_t *old_pool; + + if (pcre_malloc != ngx_http_modsec_pcre_malloc) { + ngx_http_modsec_pcre_pool = pool; + + old_pcre_malloc = pcre_malloc; + old_pcre_free = pcre_free; + + pcre_malloc = ngx_http_modsec_pcre_malloc; + pcre_free = ngx_http_modsec_pcre_free; + + return NULL; + } + + old_pool = ngx_http_modsec_pcre_pool; + ngx_http_modsec_pcre_pool = pool; + + return old_pool; +} + +void +ngx_http_modsecurity_pcre_malloc_done(ngx_pool_t *old_pool) +{ + ngx_http_modsec_pcre_pool = old_pool; + + if (old_pool == NULL) { + pcre_malloc = old_pcre_malloc; + pcre_free = old_pcre_free; + } +} + +/* + * ngx_string's are not null-terminated in common case, so we need to convert + * them into null-terminated ones before passing to ModSecurity + */ +ngx_inline char *ngx_str_to_char(ngx_str_t a, ngx_pool_t *p) +{ + char *str = NULL; + + if (a.len == 0) { + return NULL; + } + + str = ngx_pnalloc(p, a.len+1); + if (str == NULL) { + dd("failed to allocate memory to convert space ngx_string to C string"); + /* We already returned NULL for an empty string, so return -1 here to indicate allocation error */ + return (char *)-1; + } + ngx_memcpy(str, a.data, a.len); + str[a.len] = '\0'; + + return str; +} + + +ngx_inline int +ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_request_t *r, ngx_int_t early_log) +{ + char *log = NULL; + ModSecurityIntervention intervention; + intervention.status = 200; + intervention.url = NULL; + intervention.log = NULL; + intervention.disruptive = 0; + ngx_http_modsecurity_ctx_t *ctx = NULL; + + dd("processing intervention"); + + ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); + if (ctx == NULL) + { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (msc_intervention(transaction, &intervention) == 0) { + dd("nothing to do"); + return 0; + } + + log = intervention.log; + if (intervention.log == NULL) { + log = "(no log message was specified)"; + } + + ngx_log_error(NGX_LOG_ERR, (ngx_log_t *)r->connection->log, 0, "%s", log); + + if (intervention.log != NULL) { + free(intervention.log); + } + + if (intervention.url != NULL) + { + dd("intervention -- redirecting to: %s with status code: %d", intervention.url, intervention.status); + + if (r->header_sent) + { + dd("Headers are already sent. Cannot perform the redirection at this point."); + return -1; + } + + /** + * Not sure if it sane to do this indepent of the phase + * but, here we go... + * + * This code cames from: http/ngx_http_special_response.c + * function: ngx_http_send_error_page + * src/http/ngx_http_core_module.c + * From src/http/ngx_http_core_module.c (line 1910) i learnt + * that location->hash should be set to 1. + * + */ + ngx_http_clear_location(r); + ngx_str_t a = ngx_string(""); + + a.data = (unsigned char *)intervention.url; + a.len = strlen(intervention.url); + + ngx_table_elt_t *location = NULL; + location = ngx_list_push(&r->headers_out.headers); + ngx_str_set(&location->key, "Location"); + location->value = a; + r->headers_out.location = location; + r->headers_out.location->hash = 1; + +#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) + ngx_http_modsecurity_store_ctx_header(r, &location->key, &location->value); +#endif + + return intervention.status; + } + + if (intervention.status != 200) + { + /** + * FIXME: this will bring proper response code to audit log in case + * when e.g. error_page redirect was triggered, but there still won't be another + * required pieces like response headers etc. + * + */ + msc_update_status_code(ctx->modsec_transaction, intervention.status); + + if (early_log) { + dd("intervention -- calling log handler manually with code: %d", intervention.status); + ngx_http_modsecurity_log_handler(r); + ctx->logged = 1; + } + + if (r->header_sent) + { + dd("Headers are already sent. Cannot perform the redirection at this point."); + return -1; + } + dd("intervention -- returning code: %d", intervention.status); + return intervention.status; + } + return 0; +} + + +void +ngx_http_modsecurity_cleanup(void *data) +{ + ngx_http_modsecurity_ctx_t *ctx; + + ctx = (ngx_http_modsecurity_ctx_t *) data; + + msc_transaction_cleanup(ctx->modsec_transaction); + +#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) + /* + * Purge stored context headers. Memory allocated for individual stored header + * name/value pair will be freed automatically when r->pool is destroyed. + */ + ngx_array_destroy(ctx->sanity_headers_out); +#endif +} + + +ngx_inline ngx_http_modsecurity_ctx_t * +ngx_http_modsecurity_create_ctx(ngx_http_request_t *r) +{ + ngx_str_t s; + ngx_pool_cleanup_t *cln; + ngx_http_modsecurity_ctx_t *ctx; + ngx_http_modsecurity_conf_t *mcf; + ngx_http_modsecurity_main_conf_t *mmcf; + + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_modsecurity_ctx_t)); + if (ctx == NULL) + { + dd("failed to allocate memory for the context."); + return NULL; + } + + ctx->req_headers_phase_time = -1; + ctx->req_body_phase_time = -1; + ctx->resp_headers_phase_time = -1; + ctx->resp_body_phase_time = -1; + ctx->logging_phase_time = -1; + + mmcf = ngx_http_get_module_main_conf(r, ngx_http_modsecurity_module); + mcf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity_module); + + dd("creating transaction with the following rules: '%p' -- ms: '%p'", mcf->rules_set, mmcf->modsec); + + if (mcf->transaction_id) { + if (ngx_http_complex_value(r, mcf->transaction_id, &s) != NGX_OK) { + return NGX_CONF_ERROR; + } + ctx->modsec_transaction = msc_new_transaction_with_id(mmcf->modsec, mcf->rules_set, (char *) s.data, r->connection->log); + + } else { + ctx->modsec_transaction = msc_new_transaction(mmcf->modsec, mcf->rules_set, r->connection->log); + } + + dd("transaction created"); + + ngx_http_set_ctx(r, ctx, ngx_http_modsecurity_module); + + cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_modsecurity_ctx_t)); + if (cln == NULL) + { + dd("failed to create the ModSecurity context cleanup"); + return NGX_CONF_ERROR; + } + cln->handler = ngx_http_modsecurity_cleanup; + cln->data = ctx; + +#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) + ctx->sanity_headers_out = ngx_array_create(r->pool, 12, sizeof(ngx_http_modsecurity_header_t)); + if (ctx->sanity_headers_out == NULL) { + return NGX_CONF_ERROR; + } +#endif + + return ctx; +} + + +char * +ngx_conf_set_rules(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + int res; + char *rules; + ngx_str_t *value; + const char *error; + ngx_pool_t *old_pool; + ngx_http_modsecurity_conf_t *mcf = conf; + ngx_http_modsecurity_main_conf_t *mmcf; + + value = cf->args->elts; + rules = ngx_str_to_char(value[1], cf->pool); + + if (rules == (char *)-1) { + return NGX_CONF_ERROR; + } + + old_pool = ngx_http_modsecurity_pcre_malloc_init(cf->pool); + res = msc_rules_add(mcf->rules_set, rules, &error); + ngx_http_modsecurity_pcre_malloc_done(old_pool); + + if (res < 0) { + dd("Failed to load the rules: '%s' - reason: '%s'", rules, error); + return strdup(error); + } + + mmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_modsecurity_module); + mmcf->rules_inline += res; + + return NGX_CONF_OK; +} + + +char * +ngx_conf_set_rules_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + int res; + char *rules_set; + ngx_str_t *value; + const char *error; + ngx_pool_t *old_pool; + ngx_http_modsecurity_conf_t *mcf = conf; + ngx_http_modsecurity_main_conf_t *mmcf; + + value = cf->args->elts; + rules_set = ngx_str_to_char(value[1], cf->pool); + + if (rules_set == (char *)-1) { + return NGX_CONF_ERROR; + } + + old_pool = ngx_http_modsecurity_pcre_malloc_init(cf->pool); + res = msc_rules_add_file(mcf->rules_set, rules_set, &error); + ngx_http_modsecurity_pcre_malloc_done(old_pool); + + if (res < 0) { + dd("Failed to load the rules from: '%s' - reason: '%s'", rules_set, error); + return strdup(error); + } + + mmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_modsecurity_module); + mmcf->rules_file += res; + + return NGX_CONF_OK; +} + + +char * +ngx_conf_set_rules_remote(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + int res; + ngx_str_t *value; + const char *error; + const char *rules_remote_key, *rules_remote_server; + ngx_pool_t *old_pool; + ngx_http_modsecurity_conf_t *mcf = conf; + ngx_http_modsecurity_main_conf_t *mmcf; + + value = cf->args->elts; + rules_remote_key = ngx_str_to_char(value[1], cf->pool); + rules_remote_server = ngx_str_to_char(value[2], cf->pool); + + if (rules_remote_server == (char *)-1) { + return NGX_CONF_ERROR; + } + + if (rules_remote_key == (char *)-1) { + return NGX_CONF_ERROR; + } + + old_pool = ngx_http_modsecurity_pcre_malloc_init(cf->pool); + res = msc_rules_add_remote(mcf->rules_set, rules_remote_key, rules_remote_server, &error); + ngx_http_modsecurity_pcre_malloc_done(old_pool); + + if (res < 0) { + dd("Failed to load the rules from: '%s' - reason: '%s'", rules_remote_server, error); + return strdup(error); + } + + mmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_modsecurity_module); + mmcf->rules_remote += res; + + return NGX_CONF_OK; +} + + +char *ngx_conf_set_transaction_id(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + ngx_str_t *value; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; + ngx_http_modsecurity_conf_t *mcf = conf; + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + ccv.zero = 1; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + mcf->transaction_id = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (mcf->transaction_id == NULL) { + return NGX_CONF_ERROR; + } + + *mcf->transaction_id = cv; + + return NGX_CONF_OK; +} + + +static ngx_command_t ngx_http_modsecurity_commands[] = { + { + ngx_string("modsecurity"), + NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_modsecurity_conf_t, enable), + NULL + }, + { + ngx_string("modsecurity_rules"), + NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_rules, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_modsecurity_conf_t, enable), + NULL + }, + { + ngx_string("modsecurity_rules_file"), + NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_rules_file, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_modsecurity_conf_t, enable), + NULL + }, + { + ngx_string("modsecurity_rules_remote"), + NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, + ngx_conf_set_rules_remote, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_modsecurity_conf_t, enable), + NULL + }, + { + ngx_string("modsecurity_transaction_id"), + NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_1MORE, + ngx_conf_set_transaction_id, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL + }, + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_modsecurity_ctx = { + ngx_http_modsecurity_add_variables, /* preconfiguration */ + ngx_http_modsecurity_init, /* postconfiguration */ + + ngx_http_modsecurity_create_main_conf, /* create main configuration */ + ngx_http_modsecurity_init_main_conf, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_modsecurity_create_conf, /* create location configuration */ + ngx_http_modsecurity_merge_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_modsecurity_module = { + NGX_MODULE_V1, + &ngx_http_modsecurity_ctx, /* module context */ + ngx_http_modsecurity_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_http_variable_t ngx_http_modsecurity_vars[] = { + { ngx_string("modsecurity_req_headers_phase_time"), NULL, + ngx_http_modsecurity_phase_time, 0, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_string("modsecurity_req_body_phase_time"), NULL, + ngx_http_modsecurity_phase_time, 1, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_string("modsecurity_resp_headers_phase_time"), NULL, + ngx_http_modsecurity_phase_time, 2, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_string("modsecurity_resp_body_phase_time"), NULL, + ngx_http_modsecurity_phase_time, 3, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_string("modsecurity_logging_phase_time"), NULL, + ngx_http_modsecurity_phase_time, 4, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + +static ngx_int_t +ngx_http_modsecurity_init(ngx_conf_t *cf) +{ + ngx_http_handler_pt *h_rewrite; + ngx_http_handler_pt *h_preaccess; + ngx_http_handler_pt *h_log; + ngx_http_core_main_conf_t *cmcf; + int rc = 0; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + if (cmcf == NULL) + { + dd("We are not sure how this returns, NGINX doesn't seem to think it will ever be null"); + return NGX_ERROR; + } + /** + * + * Seems like we cannot do this very same thing with + * NGX_HTTP_FIND_CONFIG_PHASE. it does not seems to + * be an array. Our next option is the REWRITE. + * + * TODO: check if we can hook prior to NGX_HTTP_REWRITE_PHASE phase. + * + */ + h_rewrite = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); + if (h_rewrite == NULL) + { + dd("Not able to create a new NGX_HTTP_REWRITE_PHASE handle"); + return NGX_ERROR; + } + *h_rewrite = ngx_http_modsecurity_rewrite_handler; + + /** + * + * Processing the request body on the preaccess phase. + * + * TODO: check if hook into separated phases is the best thing to do. + * + */ + h_preaccess = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); + if (h_preaccess == NULL) + { + dd("Not able to create a new NGX_HTTP_PREACCESS_PHASE handle"); + return NGX_ERROR; + } + *h_preaccess = ngx_http_modsecurity_pre_access_handler; + + /** + * Process the log phase. + * + * TODO: check if the log phase happens like it happens on Apache. + * check if last phase will not hold the request. + * + */ + h_log = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); + if (h_log == NULL) + { + dd("Not able to create a new NGX_HTTP_LOG_PHASE handle"); + return NGX_ERROR; + } + *h_log = ngx_http_modsecurity_log_handler; + + + rc = ngx_http_modsecurity_header_filter_init(); + if (rc != NGX_OK) { + return rc; + } + + rc = ngx_http_modsecurity_body_filter_init(); + if (rc != NGX_OK) { + return rc; + } + + return NGX_OK; +} + +static ngx_int_t +ngx_http_modsecurity_add_variables(ngx_conf_t *cf) { + ngx_http_variable_t *var, *v; + + for (v = ngx_http_modsecurity_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +}; + + +static void * +ngx_http_modsecurity_create_main_conf(ngx_conf_t *cf) +{ + ngx_pool_cleanup_t *cln; + ngx_http_modsecurity_main_conf_t *conf; + + conf = (ngx_http_modsecurity_main_conf_t *) ngx_pcalloc(cf->pool, + sizeof(ngx_http_modsecurity_main_conf_t)); + + if (conf == NULL) + { + return NGX_CONF_ERROR; + } + + /* + * set by ngx_pcalloc(): + * + * conf->modsec = NULL; + * conf->pool = NULL; + * conf->rules_inline = 0; + * conf->rules_file = 0; + * conf->rules_remote = 0; + */ + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NGX_CONF_ERROR; + } + + cln->handler = ngx_http_modsecurity_cleanup_instance; + cln->data = conf; + + conf->pool = cf->pool; + + /* Create our ModSecurity instance */ + conf->modsec = msc_init(); + if (conf->modsec == NULL) + { + dd("failed to create the ModSecurity instance"); + return NGX_CONF_ERROR; + } + + /* Provide our connector information to LibModSecurity */ + msc_set_connector_info(conf->modsec, MODSECURITY_NGINX_WHOAMI); + msc_set_log_cb(conf->modsec, ngx_http_modsecurity_log); + + dd ("main conf created at: '%p', instance is: '%p'", conf, conf->modsec); + + return conf; +} + + +static char * +ngx_http_modsecurity_init_main_conf(ngx_conf_t *cf, void *conf) +{ + ngx_http_modsecurity_main_conf_t *mmcf; + mmcf = (ngx_http_modsecurity_main_conf_t *) conf; + + ngx_log_error(NGX_LOG_NOTICE, cf->log, 0, + "%s (rules loaded inline/local/remote: %ui/%ui/%ui)", + MODSECURITY_NGINX_WHOAMI, mmcf->rules_inline, + mmcf->rules_file, mmcf->rules_remote); + + return NGX_CONF_OK; +} + + +static void * +ngx_http_modsecurity_create_conf(ngx_conf_t *cf) +{ + ngx_pool_cleanup_t *cln; + ngx_http_modsecurity_conf_t *conf; + + conf = (ngx_http_modsecurity_conf_t *) ngx_pcalloc(cf->pool, + sizeof(ngx_http_modsecurity_conf_t)); + + if (conf == NULL) + { + dd("Failed to allocate space for ModSecurity configuration"); + return NGX_CONF_ERROR; + } + + /* + * set by ngx_pcalloc(): + * + * conf->enable = 0; + * conf->sanity_checks_enabled = 0; + * conf->rules_set = NULL; + * conf->pool = NULL; + * conf->transaction_id = NULL; + */ + + conf->enable = NGX_CONF_UNSET; + conf->rules_set = msc_create_rules_set(); + conf->pool = cf->pool; + conf->transaction_id = NGX_CONF_UNSET_PTR; +#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) + conf->sanity_checks_enabled = NGX_CONF_UNSET; +#endif + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + dd("failed to create the ModSecurity configuration cleanup"); + return NGX_CONF_ERROR; + } + + cln->handler = ngx_http_modsecurity_cleanup_rules; + cln->data = conf; + + dd ("conf created at: '%p'", conf); + + return conf; +} + + +static char * +ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_modsecurity_conf_t *p = parent; + ngx_http_modsecurity_conf_t *c = child; +#if defined(MODSECURITY_DDEBUG) && (MODSECURITY_DDEBUG) + ngx_http_core_loc_conf_t *clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); +#endif + int rules; + const char *error = NULL; + + dd("merging loc config [%s] - parent: '%p' child: '%p'", + ngx_str_to_char(clcf->name, cf->pool), parent, + child); + + dd(" state - parent: '%d' child: '%d'", + (int) c->enable, (int) p->enable); + + ngx_conf_merge_value(c->enable, p->enable, 0); + ngx_conf_merge_ptr_value(c->transaction_id, p->transaction_id, NULL); +#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) + ngx_conf_merge_value(c->sanity_checks_enabled, p->sanity_checks_enabled, 0); +#endif + +#if defined(MODSECURITY_DDEBUG) && (MODSECURITY_DDEBUG) + dd("PARENT RULES"); + msc_rules_dump(p->rules_set); + dd("CHILD RULES"); + msc_rules_dump(c->rules_set); +#endif + rules = msc_rules_merge(c->rules_set, p->rules_set, &error); + + if (rules < 0) { + return strdup(error); + } + +#if defined(MODSECURITY_DDEBUG) && (MODSECURITY_DDEBUG) + dd("NEW CHILD RULES"); + msc_rules_dump(c->rules_set); +#endif + return NGX_CONF_OK; +} + + +static void +ngx_http_modsecurity_cleanup_instance(void *data) +{ + ngx_pool_t *old_pool; + ngx_http_modsecurity_main_conf_t *mmcf; + + mmcf = (ngx_http_modsecurity_main_conf_t *) data; + + dd("deleting a main conf -- instance is: \"%p\"", mmcf->modsec); + + old_pool = ngx_http_modsecurity_pcre_malloc_init(mmcf->pool); + msc_cleanup(mmcf->modsec); + ngx_http_modsecurity_pcre_malloc_done(old_pool); +} + + +static void +ngx_http_modsecurity_cleanup_rules(void *data) +{ + ngx_pool_t *old_pool; + ngx_http_modsecurity_conf_t *mcf; + + mcf = (ngx_http_modsecurity_conf_t *) data; + + dd("deleting a loc conf -- RuleSet is: \"%p\"", mcf->rules_set); + + old_pool = ngx_http_modsecurity_pcre_malloc_init(mcf->pool); + msc_rules_cleanup(mcf->rules_set); + ngx_http_modsecurity_pcre_malloc_done(old_pool); +} + + +static ngx_int_t +ngx_http_modsecurity_phase_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_modsecurity_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); + if (ctx == NULL) { + return NGX_ERROR; + } + + switch(data) { + case 0: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_headers_phase_time); + case 1: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_body_phase_time); + case 2: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_headers_phase_time); + case 3: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_body_phase_time); + case 4: + return ngx_http_modsecurity_time_variable(r, v, data, ctx->logging_phase_time); + } + + return -1; +} + + +static ngx_int_t +ngx_http_modsecurity_req_body_phase_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_modsecurity_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); + if (ctx == NULL) { + return NGX_ERROR; + } + return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_body_phase_time); +} + + +static ngx_int_t +ngx_http_modsecurity_resp_headers_phase_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_modsecurity_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); + if (ctx == NULL) { + return NGX_ERROR; + } + return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_headers_phase_time); +} + + +static ngx_int_t +ngx_http_modsecurity_resp_body_phase_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_modsecurity_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); + if (ctx == NULL) { + return NGX_ERROR; + } + return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_body_phase_time); +} + + +static ngx_int_t +ngx_http_modsecurity_logging_phase_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_modsecurity_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); + if (ctx == NULL) { + return NGX_ERROR; + } + return ngx_http_modsecurity_time_variable(r, v, data, ctx->logging_phase_time); +} + + +static ngx_int_t +ngx_http_modsecurity_time_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data, ngx_msec_int_t usec) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 7); + if (p == NULL) { + return NGX_ERROR; + } + + if(usec == -1) { + v->len = ngx_sprintf(p, "-") - p; + } else { + v->len = ngx_sprintf(p, "%T.%06M", (time_t) usec / 1000000, usec % 1000000) - p; + } + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +ngx_msec_int_t +ngx_http_modsecurity_compute_processing_time(struct timespec tv) { + struct timespec current_tv; + (void) clock_gettime(CLOCK_MONOTONIC, ¤t_tv); + return (ngx_msec_int_t) ((current_tv.tv_sec - tv.tv_sec) * 1000000 + (current_tv.tv_nsec - tv.tv_nsec) / 1000); +}; + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/ngx_http_modsecurity_module.c.rej b/src/ngx_http_modsecurity_module.c.rej new file mode 100644 index 0000000..f2d9aab --- /dev/null +++ b/src/ngx_http_modsecurity_module.c.rej @@ -0,0 +1,144 @@ +--- src/ngx_http_modsecurity_module.c ++++ src/ngx_http_modsecurity_module.c +@@ -20,6 +20,7 @@ + + #include "ngx_http_modsecurity_common.h" + #include "stdio.h" ++#include "string.h" + #include + #include + #include +@@ -31,6 +32,9 @@ static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf); + static char *ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child); + static void ngx_http_modsecurity_cleanup_instance(void *data); + static void ngx_http_modsecurity_cleanup_rules(void *data); ++static ngx_table_elt_t * search_headers(ngx_list_part_t *part, u_char *name, size_t len); ++static ngx_int_t add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers); ++static void free_headers(AdditionalHeader *iterator); + + + /* +@@ -150,9 +154,14 @@ ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_re + + if (msc_intervention(transaction, &intervention) == 0) { + dd("nothing to do"); ++ add_headers(msc_get_additional_req_headers(transaction), r->pool, &(r->headers_in.headers)); ++ add_headers(msc_get_additional_resp_headers(transaction), r->pool, &(r->headers_out.headers)); + return 0; + } + ++ add_headers(msc_get_additional_req_headers(transaction), r->pool, &(r->headers_in.headers)); ++ add_headers(msc_get_additional_resp_headers(transaction), r->pool, &(r->headers_out.headers)); ++ + log = intervention.log; + if (intervention.log == NULL) { + log = "(no log message was specified)"; +@@ -787,5 +796,108 @@ ngx_http_modsecurity_cleanup_rules(void *data) + ngx_http_modsecurity_pcre_malloc_done(old_pool); + } + ++static ngx_int_t ++add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers) ++{ ++ AdditionalHeader *header_from_modsecurity; ++ header_from_modsecurity = iterator; ++ dd("Debug - ADD HEADER: key - pointer : \"%p\"", header_from_modsecurity); ++ while(header_from_modsecurity != NULL) { ++ ngx_table_elt_t *header = NULL; ++ header = search_headers(&headers->part, (u_char *)header_from_modsecurity->key, strlen(header_from_modsecurity->key)); ++ ++ if (header == NULL) { ++ header = ngx_list_push(headers); ++ if (header == NULL) { ++ free_headers(iterator); ++ return NGX_ERROR; ++ } ++ header->key.data = ngx_pnalloc(pool, strlen(header_from_modsecurity->key)+1); ++ if (header->key.data == NULL) { ++ free_headers(iterator); ++ return NGX_ERROR; ++ } ++ header->key.len = strlen(header_from_modsecurity->key); ++ ngx_cpystrn(header->key.data, (u_char *)header_from_modsecurity->key, header->key.len+1); ++ } else if((strlen(header_from_modsecurity->value) == header->value.len) && (ngx_strcmp(&header->value.data, header_from_modsecurity->value) == 0)) { ++ header_from_modsecurity = header_from_modsecurity->next; ++ continue; ++ } ++ ++ dd("Debug - ADD HEADER: key: \"%s\"", header_from_modsecurity->key); ++ dd("Debug - ADD HEADER: value: \"%s\"", header_from_modsecurity->value); ++ header->value.data = ngx_pnalloc(pool, strlen(header_from_modsecurity->value)+1); ++ if (header->value.data == NULL) { ++ free_headers(iterator); ++ return NGX_ERROR; ++ } ++ header->value.len = strlen(header_from_modsecurity->value); ++ ngx_cpystrn(header->value.data, (u_char *)header_from_modsecurity->value, header->value.len+1); ++ header->hash = ngx_hash_key_lc(header->value.data, strlen(header_from_modsecurity->value)); ++ header_from_modsecurity = header_from_modsecurity->next; ++ }; ++ free_headers(iterator); ++ return NGX_OK; ++} ++ ++static void ++free_headers(AdditionalHeader *iterator) { ++ AdditionalHeader* current; ++ while(iterator != NULL) { ++ current = iterator; ++ iterator = current->next; ++ free(current->key); ++ free(current->value); ++ free(current); ++ } ++} ++ ++static ngx_table_elt_t * ++search_headers(ngx_list_part_t *part, u_char *name, size_t len) { ++ ngx_table_elt_t *h; ++ ngx_uint_t i; ++ ++ /* ++ Get the first part of the list. There is usual only one part. ++ */ ++ h = part->elts; ++ ++ /* ++ Headers list array may consist of more than one part, ++ so loop through all of it ++ */ ++ for (i = 0; /* void */ ; i++) { ++ if (i >= part->nelts) { ++ if (part->next == NULL) { ++ /* The last part, search is done. */ ++ break; ++ } ++ ++ part = part->next; ++ h = part->elts; ++ i = 0; ++ } ++ ++ /* ++ Just compare the lengths and then the names case insensitively. ++ */ ++ if (len != h[i].key.len || ngx_strcasecmp(name, h[i].key.data) != 0) { ++ /* This header doesn't match. */ ++ continue; ++ } ++ ++ /* ++ Ta-da, we got one! ++ Note, we'v stop the search at the first matched header ++ while more then one header may fit. ++ */ ++ return &h[i]; ++ } ++ ++ /* ++ No headers was found ++ */ ++ return NULL; ++} + + From 55b41d09a718df3aee6437482587f9af1ea8e20f Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 18 May 2022 12:55:31 +0200 Subject: [PATCH 05/10] Fixes after review --- config | 3 +- config.orig | 192 ----- config.rej | 12 - src/ngx_http_modsecurity_body_filter.c | 2 +- src/ngx_http_modsecurity_header_filter.c | 3 +- src/ngx_http_modsecurity_module.c | 161 ---- src/ngx_http_modsecurity_module.c.orig | 961 ----------------------- src/ngx_http_modsecurity_module.c.rej | 144 ---- src/ngx_http_modsecurity_rewrite.c | 3 +- 9 files changed, 4 insertions(+), 1477 deletions(-) delete mode 100644 config.orig delete mode 100644 config.rej delete mode 100644 src/ngx_http_modsecurity_module.c.orig delete mode 100644 src/ngx_http_modsecurity_module.c.rej diff --git a/config b/config index 440fc24..c6e7467 100644 --- a/config +++ b/config @@ -93,8 +93,7 @@ ngx_addon_name=ngx_http_modsecurity_module # # For static compilation HTTP_FILTER_MODULES will be patched later. -modsecurity_dependency="ngx_http_link_func_module \ - ngx_http_postpone_filter_module \ +modsecurity_dependency="ngx_http_postpone_filter_module \ ngx_http_ssi_filter_module \ ngx_http_charset_filter_module \ ngx_http_xslt_filter_module \ diff --git a/config.orig b/config.orig deleted file mode 100644 index c6e7467..0000000 --- a/config.orig +++ /dev/null @@ -1,192 +0,0 @@ -# vim: filetype=sh - -# If $NGX_IGNORE_RPATH is set to "YES", we will ignore explicit -# library path specification on resulting binary, allowing libmodsecurity.so -# to be relocated across configured library pathes (adjust /etc/ld.so.conf -# or set $LD_LIBRARY_PATH environment variable to manage them) -# -# $YAJL_LIB variable may need to be populated in case of non-standard -# path of libyajl.so's installation - -ngx_feature_name= -ngx_feature_run=no -ngx_feature_incs="#include " -ngx_feature_libs="-lmodsecurity" -ngx_feature_test='printf("hello");' -ngx_modsecurity_opt_I= -ngx_modsecurity_opt_L= - -YAJL_EXTRA= -if test -n "$YAJL_LIB"; then - YAJL_EXTRA="-L$YAJL_LIB -lyajl" -fi - -# If $MODSECURITY_INC is specified, lets use it. Otherwise lets try -# the default paths -# -if [ -n "$MODSECURITY_INC" -o -n "$MODSECURITY_LIB" ]; then - # explicitly set ModSecurity lib path - ngx_feature="ModSecurity library in \"$MODSECURITY_LIB\" and \"$MODSECURITY_INC\" (specified by the MODSECURITY_LIB and MODSECURITY_INC env)" - ngx_feature_path="$MODSECURITY_INC" - ngx_modsecurity_opt_I="-I$MODSECURITY_INC" - ngx_modsecurity_opt_L="-L$MODSECURITY_LIB $YAJL_EXTRA" - - if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R$MODSECURITY_LIB -L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" - elif [ "$NGX_IGNORE_RPATH" != "YES" -a $NGX_SYSTEM = "Linux" ]; then - ngx_feature_libs="-Wl,-rpath,$MODSECURITY_LIB -L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" - else - ngx_feature_libs="-L$MODSECURITY_LIB -lmodsecurity $YAJL_EXTRA" - fi - - . auto/feature - - if [ $ngx_found = no ]; then - cat << END - $0: error: ngx_http_modsecurity_module requires the ModSecurity library and MODSECURITY_LIB is defined as "$MODSECURITY_LIB" and MODSECURITY_INC (path for modsecurity.h) "$MODSECURITY_INC", but we cannot find ModSecurity there. -END - exit 1 - fi -else - # auto-discovery - ngx_feature="ModSecurity library" - ngx_feature_libs="-lmodsecurity" - - . auto/feature - - if [ $ngx_found = no ]; then - ngx_feature="ModSecurity library in /usr/local/modsecurity" - ngx_feature_path="/usr/local/modsecurity/include" - if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/usr/local/modsecurity/lib -L/usr/local/modsecurity/lib -lmodsecurity" - elif [ "$NGX_IGNORE_RPATH" != "YES" -a $NGX_SYSTEM = "Linux" ]; then - ngx_feature_libs="-Wl,-rpath,/usr/local/modsecurity/lib -L/usr/local/modsecurity/lib -lmodsecurity" - else - ngx_feature_libs="-L/usr/local/modsecurity/lib -lmodsecurity" - fi - - . auto/feature - - fi -fi - - - -if [ $ngx_found = no ]; then - cat << END - $0: error: ngx_http_modsecurity_module requires the ModSecurity library. -END - exit 1 -fi - - -ngx_addon_name=ngx_http_modsecurity_module - -# We must place ngx_http_modsecurity_module after ngx_http_gzip_filter_module -# in load order list to be able to read response body before it gets compressed -# (for filter modules later initialization means earlier execution). -# -# Nginx implements load ordering only for dynamic modules and only a BEFORE part -# of "ngx_module_order". So we list all of the modules that come after -# ngx_http_gzip_filter_module as a BEFORE dependency for -# ngx_http_modsecurity_module. -# -# For static compilation HTTP_FILTER_MODULES will be patched later. - -modsecurity_dependency="ngx_http_postpone_filter_module \ - ngx_http_ssi_filter_module \ - ngx_http_charset_filter_module \ - ngx_http_xslt_filter_module \ - ngx_http_image_filter_module \ - ngx_http_sub_filter_module \ - ngx_http_addition_filter_module \ - ngx_http_gunzip_filter_module \ - ngx_http_userid_filter_module \ - ngx_http_headers_filter_module \ - ngx_http_copy_filter_module" - - -if test -n "$ngx_module_link"; then - ngx_module_type=HTTP_FILTER - ngx_module_name="$ngx_addon_name" - ngx_module_srcs="$ngx_addon_dir/src/ngx_http_modsecurity_module.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_pre_access.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_header_filter.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_body_filter.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_log.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_rewrite.c \ - " - ngx_module_deps="$ngx_addon_dir/src/ddebug.h \ - $ngx_addon_dir/src/ngx_http_modsecurity_common.h \ - " - ngx_module_libs="$ngx_feature_libs" - ngx_module_incs="$ngx_feature_path" - - ngx_module_order="ngx_http_chunked_filter_module \ - ngx_http_v2_filter_module \ - ngx_http_range_header_filter_module \ - ngx_http_gzip_filter_module \ - $ngx_module_name \ - $modsecurity_dependency"; - - . auto/module -else - CFLAGS="$ngx_modsecurity_opt_I $CFLAGS" - NGX_LD_OPT="$ngx_modsecurity_opt_L $NGX_LD_OPT" - - CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_modsecurity_module" - NGX_ADDON_SRCS="\ - $NGX_ADDON_SRCS \ - $ngx_addon_dir/src/ngx_http_modsecurity_module.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_pre_access.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_header_filter.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_body_filter.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_log.c \ - $ngx_addon_dir/src/ngx_http_modsecurity_rewrite.c \ - " - - NGX_ADDON_DEPS="\ - $NGX_ADDON_DEPS \ - $ngx_addon_dir/src/ddebug.h \ - $ngx_addon_dir/src/ngx_http_modsecurity_common.h \ - " -fi - -# -# Nginx does not provide reliable way to introduce our module into required -# place in static ($ngx_module_link=ADDON) compilation mode, so we must -# explicitly update module "ordering rules". -# -if [ "$ngx_module_link" != DYNAMIC ] ; then - # Reposition modsecurity module to satisfy $modsecurity_dependency - # (this mimics dependency resolution made by ngx_add_module() function - # though less optimal in terms of computational complexity). - modules= - found= - for module in $HTTP_FILTER_MODULES; do - # skip our module name from the original list - if [ "$module" = "$ngx_addon_name" ]; then - continue - fi - if [ -z "${found}" ]; then - for item in $modsecurity_dependency; do - if [ "$module" = "$item" ]; then - modules="${modules} $ngx_addon_name" - found=1 - break - fi - done - fi - modules="${modules} $module" - done - if [ -z "${found}" ]; then - # This must never happen since ngx_http_copy_filter_module must be in HTTP_FILTER_MODULES - # and we stated dependency on it in $modsecurity_dependency - echo "$0: error: cannot reposition modsecurity module in HTTP_FILTER_MODULES list" - exit 1 - fi - HTTP_FILTER_MODULES="${modules}" -fi diff --git a/config.rej b/config.rej deleted file mode 100644 index 5ad326f..0000000 --- a/config.rej +++ /dev/null @@ -1,12 +0,0 @@ ---- config -+++ config -@@ -93,7 +93,8 @@ ngx_addon_name=ngx_http_modsecurity_module - # - # For static compilation HTTP_FILTER_MODULES will be patched later. - --modsecurity_dependency="ngx_http_postpone_filter_module \ -+modsecurity_dependency="ngx_http_link_func_module \ -+ ngx_http_postpone_filter_module \ - ngx_http_ssi_filter_module \ - ngx_http_charset_filter_module \ - diff --git a/src/ngx_http_modsecurity_body_filter.c b/src/ngx_http_modsecurity_body_filter.c index 29b1f98..04a2b4c 100644 --- a/src/ngx_http_modsecurity_body_filter.c +++ b/src/ngx_http_modsecurity_body_filter.c @@ -165,8 +165,8 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in) /* XXX: I don't get how body from modsec being transferred to nginx's buffer. If so - after adjusting of nginx's XXX: body we can proceed to adjust body size (content-length). see xslt_body_filter() for example */ - ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0); ctx->resp_body_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv); + ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0); if (ret > 0) { return ret; } diff --git a/src/ngx_http_modsecurity_header_filter.c b/src/ngx_http_modsecurity_header_filter.c index 0524a07..6c2f4e1 100644 --- a/src/ngx_http_modsecurity_header_filter.c +++ b/src/ngx_http_modsecurity_header_filter.c @@ -529,9 +529,8 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r) old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool); msc_process_response_headers(ctx->modsec_transaction, status, http_response_ver); ngx_http_modsecurity_pcre_malloc_done(old_pool); - ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0); - ctx->resp_headers_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv); + ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0); if (r->error_page) { return ngx_http_next_header_filter(r); diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index 4834d3f..ca7efc4 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -817,110 +817,6 @@ ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } -static ngx_int_t -add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers) -{ - AdditionalHeader *header_from_modsecurity; - header_from_modsecurity = iterator; - dd("Debug - ADD HEADER: key - pointer : \"%p\"", header_from_modsecurity); - while(header_from_modsecurity != NULL) { - ngx_table_elt_t *header = NULL; - header = search_headers(&headers->part, (u_char *)header_from_modsecurity->key, strlen(header_from_modsecurity->key)); - - if (header == NULL) { - header = ngx_list_push(headers); - if (header == NULL) { - free_headers(iterator); - return NGX_ERROR; - } - header->key.data = ngx_pnalloc(pool, strlen(header_from_modsecurity->key)+1); - if (header->key.data == NULL) { - free_headers(iterator); - return NGX_ERROR; - } - header->key.len = strlen(header_from_modsecurity->key); - ngx_cpystrn(header->key.data, (u_char *)header_from_modsecurity->key, header->key.len+1); - } else if((strlen(header_from_modsecurity->value) == header->value.len) && (ngx_strcmp(&header->value.data, header_from_modsecurity->value) == 0)) { - header_from_modsecurity = header_from_modsecurity->next; - continue; - } - - dd("Debug - ADD HEADER: key: \"%s\"", header_from_modsecurity->key); - dd("Debug - ADD HEADER: value: \"%s\"", header_from_modsecurity->value); - header->value.data = ngx_pnalloc(pool, strlen(header_from_modsecurity->value)+1); - if (header->value.data == NULL) { - free_headers(iterator); - return NGX_ERROR; - } - header->value.len = strlen(header_from_modsecurity->value); - ngx_cpystrn(header->value.data, (u_char *)header_from_modsecurity->value, header->value.len+1); - header->hash = ngx_hash_key_lc(header->value.data, strlen(header_from_modsecurity->value)); - header_from_modsecurity = header_from_modsecurity->next; - }; - free_headers(iterator); - return NGX_OK; -} - -static void -free_headers(AdditionalHeader *iterator) { - AdditionalHeader* current; - while(iterator != NULL) { - current = iterator; - iterator = current->next; - free(current->key); - free(current->value); - free(current); - } -} - -static ngx_table_elt_t * -search_headers(ngx_list_part_t *part, u_char *name, size_t len) { - ngx_table_elt_t *h; - ngx_uint_t i; - - /* - Get the first part of the list. There is usual only one part. - */ - h = part->elts; - - /* - Headers list array may consist of more than one part, - so loop through all of it - */ - for (i = 0; /* void */ ; i++) { - if (i >= part->nelts) { - if (part->next == NULL) { - /* The last part, search is done. */ - break; - } - - part = part->next; - h = part->elts; - i = 0; - } - - /* - Just compare the lengths and then the names case insensitively. - */ - if (len != h[i].key.len || ngx_strcasecmp(name, h[i].key.data) != 0) { - /* This header doesn't match. */ - continue; - } - - /* - Ta-da, we got one! - Note, we'v stop the search at the first matched header - while more then one header may fit. - */ - return &h[i]; - } - - /* - No headers was found - */ - return NULL; -} - static void ngx_http_modsecurity_cleanup_instance(void *data) { @@ -936,7 +832,6 @@ ngx_http_modsecurity_cleanup_instance(void *data) ngx_http_modsecurity_pcre_malloc_done(old_pool); } - static void ngx_http_modsecurity_cleanup_rules(void *data) { @@ -981,62 +876,6 @@ ngx_http_modsecurity_phase_time(ngx_http_request_t *r, } -static ngx_int_t -ngx_http_modsecurity_req_body_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_body_phase_time); -} - - -static ngx_int_t -ngx_http_modsecurity_resp_headers_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_headers_phase_time); -} - - -static ngx_int_t -ngx_http_modsecurity_resp_body_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_body_phase_time); -} - - -static ngx_int_t -ngx_http_modsecurity_logging_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->logging_phase_time); -} - - static ngx_int_t ngx_http_modsecurity_time_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data, ngx_msec_int_t usec) diff --git a/src/ngx_http_modsecurity_module.c.orig b/src/ngx_http_modsecurity_module.c.orig deleted file mode 100644 index b6c8d19..0000000 --- a/src/ngx_http_modsecurity_module.c.orig +++ /dev/null @@ -1,961 +0,0 @@ -/* - * ModSecurity connector for nginx, http://www.modsecurity.org/ - * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) - * - * You may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * If any of the files related to licensing are missing or if you have any - * other questions related to licensing please contact Trustwave Holdings, Inc. - * directly using the email address security@modsecurity.org. - * - */ - -#ifndef MODSECURITY_DDEBUG -#define MODSECURITY_DDEBUG 0 -#endif -#include "ddebug.h" - -#include "ngx_http_modsecurity_common.h" -#include "stdio.h" -#include -#include -#include - -static ngx_int_t ngx_http_modsecurity_init(ngx_conf_t *cf); -static ngx_int_t ngx_http_modsecurity_add_variables(ngx_conf_t *cf); -static void *ngx_http_modsecurity_create_main_conf(ngx_conf_t *cf); -static char *ngx_http_modsecurity_init_main_conf(ngx_conf_t *cf, void *conf); -static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf); -static char *ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child); -static void ngx_http_modsecurity_cleanup_instance(void *data); -static void ngx_http_modsecurity_cleanup_rules(void *data); - -static ngx_int_t ngx_http_modsecurity_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_modsecurity_time_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data, ngx_msec_int_t usec); - -/* - * PCRE malloc/free workaround, based on - * https://github.com/openresty/lua-nginx-module/blob/master/src/ngx_http_lua_pcrefix.c - */ - -static void *(*old_pcre_malloc)(size_t); -static void (*old_pcre_free)(void *ptr); -static ngx_pool_t *ngx_http_modsec_pcre_pool = NULL; - -static void * -ngx_http_modsec_pcre_malloc(size_t size) -{ - if (ngx_http_modsec_pcre_pool) { - return ngx_palloc(ngx_http_modsec_pcre_pool, size); - } - - fprintf(stderr, "error: modsec pcre malloc failed due to empty pcre pool"); - - return NULL; -} - -static void -ngx_http_modsec_pcre_free(void *ptr) -{ - if (ngx_http_modsec_pcre_pool) { - ngx_pfree(ngx_http_modsec_pcre_pool, ptr); - return; - } - -#if 0 - /* this may happen when called from cleanup handlers */ - fprintf(stderr, "error: modsec pcre free failed due to empty pcre pool"); -#endif - - return; -} - -ngx_pool_t * -ngx_http_modsecurity_pcre_malloc_init(ngx_pool_t *pool) -{ - ngx_pool_t *old_pool; - - if (pcre_malloc != ngx_http_modsec_pcre_malloc) { - ngx_http_modsec_pcre_pool = pool; - - old_pcre_malloc = pcre_malloc; - old_pcre_free = pcre_free; - - pcre_malloc = ngx_http_modsec_pcre_malloc; - pcre_free = ngx_http_modsec_pcre_free; - - return NULL; - } - - old_pool = ngx_http_modsec_pcre_pool; - ngx_http_modsec_pcre_pool = pool; - - return old_pool; -} - -void -ngx_http_modsecurity_pcre_malloc_done(ngx_pool_t *old_pool) -{ - ngx_http_modsec_pcre_pool = old_pool; - - if (old_pool == NULL) { - pcre_malloc = old_pcre_malloc; - pcre_free = old_pcre_free; - } -} - -/* - * ngx_string's are not null-terminated in common case, so we need to convert - * them into null-terminated ones before passing to ModSecurity - */ -ngx_inline char *ngx_str_to_char(ngx_str_t a, ngx_pool_t *p) -{ - char *str = NULL; - - if (a.len == 0) { - return NULL; - } - - str = ngx_pnalloc(p, a.len+1); - if (str == NULL) { - dd("failed to allocate memory to convert space ngx_string to C string"); - /* We already returned NULL for an empty string, so return -1 here to indicate allocation error */ - return (char *)-1; - } - ngx_memcpy(str, a.data, a.len); - str[a.len] = '\0'; - - return str; -} - - -ngx_inline int -ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_request_t *r, ngx_int_t early_log) -{ - char *log = NULL; - ModSecurityIntervention intervention; - intervention.status = 200; - intervention.url = NULL; - intervention.log = NULL; - intervention.disruptive = 0; - ngx_http_modsecurity_ctx_t *ctx = NULL; - - dd("processing intervention"); - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) - { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (msc_intervention(transaction, &intervention) == 0) { - dd("nothing to do"); - return 0; - } - - log = intervention.log; - if (intervention.log == NULL) { - log = "(no log message was specified)"; - } - - ngx_log_error(NGX_LOG_ERR, (ngx_log_t *)r->connection->log, 0, "%s", log); - - if (intervention.log != NULL) { - free(intervention.log); - } - - if (intervention.url != NULL) - { - dd("intervention -- redirecting to: %s with status code: %d", intervention.url, intervention.status); - - if (r->header_sent) - { - dd("Headers are already sent. Cannot perform the redirection at this point."); - return -1; - } - - /** - * Not sure if it sane to do this indepent of the phase - * but, here we go... - * - * This code cames from: http/ngx_http_special_response.c - * function: ngx_http_send_error_page - * src/http/ngx_http_core_module.c - * From src/http/ngx_http_core_module.c (line 1910) i learnt - * that location->hash should be set to 1. - * - */ - ngx_http_clear_location(r); - ngx_str_t a = ngx_string(""); - - a.data = (unsigned char *)intervention.url; - a.len = strlen(intervention.url); - - ngx_table_elt_t *location = NULL; - location = ngx_list_push(&r->headers_out.headers); - ngx_str_set(&location->key, "Location"); - location->value = a; - r->headers_out.location = location; - r->headers_out.location->hash = 1; - -#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) - ngx_http_modsecurity_store_ctx_header(r, &location->key, &location->value); -#endif - - return intervention.status; - } - - if (intervention.status != 200) - { - /** - * FIXME: this will bring proper response code to audit log in case - * when e.g. error_page redirect was triggered, but there still won't be another - * required pieces like response headers etc. - * - */ - msc_update_status_code(ctx->modsec_transaction, intervention.status); - - if (early_log) { - dd("intervention -- calling log handler manually with code: %d", intervention.status); - ngx_http_modsecurity_log_handler(r); - ctx->logged = 1; - } - - if (r->header_sent) - { - dd("Headers are already sent. Cannot perform the redirection at this point."); - return -1; - } - dd("intervention -- returning code: %d", intervention.status); - return intervention.status; - } - return 0; -} - - -void -ngx_http_modsecurity_cleanup(void *data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = (ngx_http_modsecurity_ctx_t *) data; - - msc_transaction_cleanup(ctx->modsec_transaction); - -#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) - /* - * Purge stored context headers. Memory allocated for individual stored header - * name/value pair will be freed automatically when r->pool is destroyed. - */ - ngx_array_destroy(ctx->sanity_headers_out); -#endif -} - - -ngx_inline ngx_http_modsecurity_ctx_t * -ngx_http_modsecurity_create_ctx(ngx_http_request_t *r) -{ - ngx_str_t s; - ngx_pool_cleanup_t *cln; - ngx_http_modsecurity_ctx_t *ctx; - ngx_http_modsecurity_conf_t *mcf; - ngx_http_modsecurity_main_conf_t *mmcf; - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_modsecurity_ctx_t)); - if (ctx == NULL) - { - dd("failed to allocate memory for the context."); - return NULL; - } - - ctx->req_headers_phase_time = -1; - ctx->req_body_phase_time = -1; - ctx->resp_headers_phase_time = -1; - ctx->resp_body_phase_time = -1; - ctx->logging_phase_time = -1; - - mmcf = ngx_http_get_module_main_conf(r, ngx_http_modsecurity_module); - mcf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity_module); - - dd("creating transaction with the following rules: '%p' -- ms: '%p'", mcf->rules_set, mmcf->modsec); - - if (mcf->transaction_id) { - if (ngx_http_complex_value(r, mcf->transaction_id, &s) != NGX_OK) { - return NGX_CONF_ERROR; - } - ctx->modsec_transaction = msc_new_transaction_with_id(mmcf->modsec, mcf->rules_set, (char *) s.data, r->connection->log); - - } else { - ctx->modsec_transaction = msc_new_transaction(mmcf->modsec, mcf->rules_set, r->connection->log); - } - - dd("transaction created"); - - ngx_http_set_ctx(r, ctx, ngx_http_modsecurity_module); - - cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_modsecurity_ctx_t)); - if (cln == NULL) - { - dd("failed to create the ModSecurity context cleanup"); - return NGX_CONF_ERROR; - } - cln->handler = ngx_http_modsecurity_cleanup; - cln->data = ctx; - -#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) - ctx->sanity_headers_out = ngx_array_create(r->pool, 12, sizeof(ngx_http_modsecurity_header_t)); - if (ctx->sanity_headers_out == NULL) { - return NGX_CONF_ERROR; - } -#endif - - return ctx; -} - - -char * -ngx_conf_set_rules(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - int res; - char *rules; - ngx_str_t *value; - const char *error; - ngx_pool_t *old_pool; - ngx_http_modsecurity_conf_t *mcf = conf; - ngx_http_modsecurity_main_conf_t *mmcf; - - value = cf->args->elts; - rules = ngx_str_to_char(value[1], cf->pool); - - if (rules == (char *)-1) { - return NGX_CONF_ERROR; - } - - old_pool = ngx_http_modsecurity_pcre_malloc_init(cf->pool); - res = msc_rules_add(mcf->rules_set, rules, &error); - ngx_http_modsecurity_pcre_malloc_done(old_pool); - - if (res < 0) { - dd("Failed to load the rules: '%s' - reason: '%s'", rules, error); - return strdup(error); - } - - mmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_modsecurity_module); - mmcf->rules_inline += res; - - return NGX_CONF_OK; -} - - -char * -ngx_conf_set_rules_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - int res; - char *rules_set; - ngx_str_t *value; - const char *error; - ngx_pool_t *old_pool; - ngx_http_modsecurity_conf_t *mcf = conf; - ngx_http_modsecurity_main_conf_t *mmcf; - - value = cf->args->elts; - rules_set = ngx_str_to_char(value[1], cf->pool); - - if (rules_set == (char *)-1) { - return NGX_CONF_ERROR; - } - - old_pool = ngx_http_modsecurity_pcre_malloc_init(cf->pool); - res = msc_rules_add_file(mcf->rules_set, rules_set, &error); - ngx_http_modsecurity_pcre_malloc_done(old_pool); - - if (res < 0) { - dd("Failed to load the rules from: '%s' - reason: '%s'", rules_set, error); - return strdup(error); - } - - mmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_modsecurity_module); - mmcf->rules_file += res; - - return NGX_CONF_OK; -} - - -char * -ngx_conf_set_rules_remote(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - int res; - ngx_str_t *value; - const char *error; - const char *rules_remote_key, *rules_remote_server; - ngx_pool_t *old_pool; - ngx_http_modsecurity_conf_t *mcf = conf; - ngx_http_modsecurity_main_conf_t *mmcf; - - value = cf->args->elts; - rules_remote_key = ngx_str_to_char(value[1], cf->pool); - rules_remote_server = ngx_str_to_char(value[2], cf->pool); - - if (rules_remote_server == (char *)-1) { - return NGX_CONF_ERROR; - } - - if (rules_remote_key == (char *)-1) { - return NGX_CONF_ERROR; - } - - old_pool = ngx_http_modsecurity_pcre_malloc_init(cf->pool); - res = msc_rules_add_remote(mcf->rules_set, rules_remote_key, rules_remote_server, &error); - ngx_http_modsecurity_pcre_malloc_done(old_pool); - - if (res < 0) { - dd("Failed to load the rules from: '%s' - reason: '%s'", rules_remote_server, error); - return strdup(error); - } - - mmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_modsecurity_module); - mmcf->rules_remote += res; - - return NGX_CONF_OK; -} - - -char *ngx_conf_set_transaction_id(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_str_t *value; - ngx_http_complex_value_t cv; - ngx_http_compile_complex_value_t ccv; - ngx_http_modsecurity_conf_t *mcf = conf; - - value = cf->args->elts; - - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - - ccv.cf = cf; - ccv.value = &value[1]; - ccv.complex_value = &cv; - ccv.zero = 1; - - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { - return NGX_CONF_ERROR; - } - - mcf->transaction_id = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); - if (mcf->transaction_id == NULL) { - return NGX_CONF_ERROR; - } - - *mcf->transaction_id = cv; - - return NGX_CONF_OK; -} - - -static ngx_command_t ngx_http_modsecurity_commands[] = { - { - ngx_string("modsecurity"), - NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_modsecurity_conf_t, enable), - NULL - }, - { - ngx_string("modsecurity_rules"), - NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_rules, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_modsecurity_conf_t, enable), - NULL - }, - { - ngx_string("modsecurity_rules_file"), - NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_rules_file, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_modsecurity_conf_t, enable), - NULL - }, - { - ngx_string("modsecurity_rules_remote"), - NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, - ngx_conf_set_rules_remote, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_modsecurity_conf_t, enable), - NULL - }, - { - ngx_string("modsecurity_transaction_id"), - NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_1MORE, - ngx_conf_set_transaction_id, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL - }, - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_modsecurity_ctx = { - ngx_http_modsecurity_add_variables, /* preconfiguration */ - ngx_http_modsecurity_init, /* postconfiguration */ - - ngx_http_modsecurity_create_main_conf, /* create main configuration */ - ngx_http_modsecurity_init_main_conf, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_http_modsecurity_create_conf, /* create location configuration */ - ngx_http_modsecurity_merge_conf /* merge location configuration */ -}; - - -ngx_module_t ngx_http_modsecurity_module = { - NGX_MODULE_V1, - &ngx_http_modsecurity_ctx, /* module context */ - ngx_http_modsecurity_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_http_variable_t ngx_http_modsecurity_vars[] = { - { ngx_string("modsecurity_req_headers_phase_time"), NULL, - ngx_http_modsecurity_phase_time, 0, - NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, - - { ngx_string("modsecurity_req_body_phase_time"), NULL, - ngx_http_modsecurity_phase_time, 1, - NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, - - { ngx_string("modsecurity_resp_headers_phase_time"), NULL, - ngx_http_modsecurity_phase_time, 2, - NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, - - { ngx_string("modsecurity_resp_body_phase_time"), NULL, - ngx_http_modsecurity_phase_time, 3, - NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, - - { ngx_string("modsecurity_logging_phase_time"), NULL, - ngx_http_modsecurity_phase_time, 4, - NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, - - { ngx_null_string, NULL, NULL, 0, 0, 0 } -}; - - -static ngx_int_t -ngx_http_modsecurity_init(ngx_conf_t *cf) -{ - ngx_http_handler_pt *h_rewrite; - ngx_http_handler_pt *h_preaccess; - ngx_http_handler_pt *h_log; - ngx_http_core_main_conf_t *cmcf; - int rc = 0; - - cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - if (cmcf == NULL) - { - dd("We are not sure how this returns, NGINX doesn't seem to think it will ever be null"); - return NGX_ERROR; - } - /** - * - * Seems like we cannot do this very same thing with - * NGX_HTTP_FIND_CONFIG_PHASE. it does not seems to - * be an array. Our next option is the REWRITE. - * - * TODO: check if we can hook prior to NGX_HTTP_REWRITE_PHASE phase. - * - */ - h_rewrite = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); - if (h_rewrite == NULL) - { - dd("Not able to create a new NGX_HTTP_REWRITE_PHASE handle"); - return NGX_ERROR; - } - *h_rewrite = ngx_http_modsecurity_rewrite_handler; - - /** - * - * Processing the request body on the preaccess phase. - * - * TODO: check if hook into separated phases is the best thing to do. - * - */ - h_preaccess = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); - if (h_preaccess == NULL) - { - dd("Not able to create a new NGX_HTTP_PREACCESS_PHASE handle"); - return NGX_ERROR; - } - *h_preaccess = ngx_http_modsecurity_pre_access_handler; - - /** - * Process the log phase. - * - * TODO: check if the log phase happens like it happens on Apache. - * check if last phase will not hold the request. - * - */ - h_log = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); - if (h_log == NULL) - { - dd("Not able to create a new NGX_HTTP_LOG_PHASE handle"); - return NGX_ERROR; - } - *h_log = ngx_http_modsecurity_log_handler; - - - rc = ngx_http_modsecurity_header_filter_init(); - if (rc != NGX_OK) { - return rc; - } - - rc = ngx_http_modsecurity_body_filter_init(); - if (rc != NGX_OK) { - return rc; - } - - return NGX_OK; -} - -static ngx_int_t -ngx_http_modsecurity_add_variables(ngx_conf_t *cf) { - ngx_http_variable_t *var, *v; - - for (v = ngx_http_modsecurity_vars; v->name.len; v++) { - var = ngx_http_add_variable(cf, &v->name, v->flags); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = v->get_handler; - var->data = v->data; - } - - return NGX_OK; -}; - - -static void * -ngx_http_modsecurity_create_main_conf(ngx_conf_t *cf) -{ - ngx_pool_cleanup_t *cln; - ngx_http_modsecurity_main_conf_t *conf; - - conf = (ngx_http_modsecurity_main_conf_t *) ngx_pcalloc(cf->pool, - sizeof(ngx_http_modsecurity_main_conf_t)); - - if (conf == NULL) - { - return NGX_CONF_ERROR; - } - - /* - * set by ngx_pcalloc(): - * - * conf->modsec = NULL; - * conf->pool = NULL; - * conf->rules_inline = 0; - * conf->rules_file = 0; - * conf->rules_remote = 0; - */ - - cln = ngx_pool_cleanup_add(cf->pool, 0); - if (cln == NULL) { - return NGX_CONF_ERROR; - } - - cln->handler = ngx_http_modsecurity_cleanup_instance; - cln->data = conf; - - conf->pool = cf->pool; - - /* Create our ModSecurity instance */ - conf->modsec = msc_init(); - if (conf->modsec == NULL) - { - dd("failed to create the ModSecurity instance"); - return NGX_CONF_ERROR; - } - - /* Provide our connector information to LibModSecurity */ - msc_set_connector_info(conf->modsec, MODSECURITY_NGINX_WHOAMI); - msc_set_log_cb(conf->modsec, ngx_http_modsecurity_log); - - dd ("main conf created at: '%p', instance is: '%p'", conf, conf->modsec); - - return conf; -} - - -static char * -ngx_http_modsecurity_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_http_modsecurity_main_conf_t *mmcf; - mmcf = (ngx_http_modsecurity_main_conf_t *) conf; - - ngx_log_error(NGX_LOG_NOTICE, cf->log, 0, - "%s (rules loaded inline/local/remote: %ui/%ui/%ui)", - MODSECURITY_NGINX_WHOAMI, mmcf->rules_inline, - mmcf->rules_file, mmcf->rules_remote); - - return NGX_CONF_OK; -} - - -static void * -ngx_http_modsecurity_create_conf(ngx_conf_t *cf) -{ - ngx_pool_cleanup_t *cln; - ngx_http_modsecurity_conf_t *conf; - - conf = (ngx_http_modsecurity_conf_t *) ngx_pcalloc(cf->pool, - sizeof(ngx_http_modsecurity_conf_t)); - - if (conf == NULL) - { - dd("Failed to allocate space for ModSecurity configuration"); - return NGX_CONF_ERROR; - } - - /* - * set by ngx_pcalloc(): - * - * conf->enable = 0; - * conf->sanity_checks_enabled = 0; - * conf->rules_set = NULL; - * conf->pool = NULL; - * conf->transaction_id = NULL; - */ - - conf->enable = NGX_CONF_UNSET; - conf->rules_set = msc_create_rules_set(); - conf->pool = cf->pool; - conf->transaction_id = NGX_CONF_UNSET_PTR; -#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) - conf->sanity_checks_enabled = NGX_CONF_UNSET; -#endif - - cln = ngx_pool_cleanup_add(cf->pool, 0); - if (cln == NULL) { - dd("failed to create the ModSecurity configuration cleanup"); - return NGX_CONF_ERROR; - } - - cln->handler = ngx_http_modsecurity_cleanup_rules; - cln->data = conf; - - dd ("conf created at: '%p'", conf); - - return conf; -} - - -static char * -ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_http_modsecurity_conf_t *p = parent; - ngx_http_modsecurity_conf_t *c = child; -#if defined(MODSECURITY_DDEBUG) && (MODSECURITY_DDEBUG) - ngx_http_core_loc_conf_t *clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); -#endif - int rules; - const char *error = NULL; - - dd("merging loc config [%s] - parent: '%p' child: '%p'", - ngx_str_to_char(clcf->name, cf->pool), parent, - child); - - dd(" state - parent: '%d' child: '%d'", - (int) c->enable, (int) p->enable); - - ngx_conf_merge_value(c->enable, p->enable, 0); - ngx_conf_merge_ptr_value(c->transaction_id, p->transaction_id, NULL); -#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) - ngx_conf_merge_value(c->sanity_checks_enabled, p->sanity_checks_enabled, 0); -#endif - -#if defined(MODSECURITY_DDEBUG) && (MODSECURITY_DDEBUG) - dd("PARENT RULES"); - msc_rules_dump(p->rules_set); - dd("CHILD RULES"); - msc_rules_dump(c->rules_set); -#endif - rules = msc_rules_merge(c->rules_set, p->rules_set, &error); - - if (rules < 0) { - return strdup(error); - } - -#if defined(MODSECURITY_DDEBUG) && (MODSECURITY_DDEBUG) - dd("NEW CHILD RULES"); - msc_rules_dump(c->rules_set); -#endif - return NGX_CONF_OK; -} - - -static void -ngx_http_modsecurity_cleanup_instance(void *data) -{ - ngx_pool_t *old_pool; - ngx_http_modsecurity_main_conf_t *mmcf; - - mmcf = (ngx_http_modsecurity_main_conf_t *) data; - - dd("deleting a main conf -- instance is: \"%p\"", mmcf->modsec); - - old_pool = ngx_http_modsecurity_pcre_malloc_init(mmcf->pool); - msc_cleanup(mmcf->modsec); - ngx_http_modsecurity_pcre_malloc_done(old_pool); -} - - -static void -ngx_http_modsecurity_cleanup_rules(void *data) -{ - ngx_pool_t *old_pool; - ngx_http_modsecurity_conf_t *mcf; - - mcf = (ngx_http_modsecurity_conf_t *) data; - - dd("deleting a loc conf -- RuleSet is: \"%p\"", mcf->rules_set); - - old_pool = ngx_http_modsecurity_pcre_malloc_init(mcf->pool); - msc_rules_cleanup(mcf->rules_set); - ngx_http_modsecurity_pcre_malloc_done(old_pool); -} - - -static ngx_int_t -ngx_http_modsecurity_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - - switch(data) { - case 0: - return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_headers_phase_time); - case 1: - return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_body_phase_time); - case 2: - return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_headers_phase_time); - case 3: - return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_body_phase_time); - case 4: - return ngx_http_modsecurity_time_variable(r, v, data, ctx->logging_phase_time); - } - - return -1; -} - - -static ngx_int_t -ngx_http_modsecurity_req_body_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_body_phase_time); -} - - -static ngx_int_t -ngx_http_modsecurity_resp_headers_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_headers_phase_time); -} - - -static ngx_int_t -ngx_http_modsecurity_resp_body_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_body_phase_time); -} - - -static ngx_int_t -ngx_http_modsecurity_logging_phase_time(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_modsecurity_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); - if (ctx == NULL) { - return NGX_ERROR; - } - return ngx_http_modsecurity_time_variable(r, v, data, ctx->logging_phase_time); -} - - -static ngx_int_t -ngx_http_modsecurity_time_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data, ngx_msec_int_t usec) -{ - u_char *p; - - p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 7); - if (p == NULL) { - return NGX_ERROR; - } - - if(usec == -1) { - v->len = ngx_sprintf(p, "-") - p; - } else { - v->len = ngx_sprintf(p, "%T.%06M", (time_t) usec / 1000000, usec % 1000000) - p; - } - - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = p; - - return NGX_OK; -} - - -ngx_msec_int_t -ngx_http_modsecurity_compute_processing_time(struct timespec tv) { - struct timespec current_tv; - (void) clock_gettime(CLOCK_MONOTONIC, ¤t_tv); - return (ngx_msec_int_t) ((current_tv.tv_sec - tv.tv_sec) * 1000000 + (current_tv.tv_nsec - tv.tv_nsec) / 1000); -}; - -/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/ngx_http_modsecurity_module.c.rej b/src/ngx_http_modsecurity_module.c.rej deleted file mode 100644 index f2d9aab..0000000 --- a/src/ngx_http_modsecurity_module.c.rej +++ /dev/null @@ -1,144 +0,0 @@ ---- src/ngx_http_modsecurity_module.c -+++ src/ngx_http_modsecurity_module.c -@@ -20,6 +20,7 @@ - - #include "ngx_http_modsecurity_common.h" - #include "stdio.h" -+#include "string.h" - #include - #include - #include -@@ -31,6 +32,9 @@ static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf); - static char *ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child); - static void ngx_http_modsecurity_cleanup_instance(void *data); - static void ngx_http_modsecurity_cleanup_rules(void *data); -+static ngx_table_elt_t * search_headers(ngx_list_part_t *part, u_char *name, size_t len); -+static ngx_int_t add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers); -+static void free_headers(AdditionalHeader *iterator); - - - /* -@@ -150,9 +154,14 @@ ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_re - - if (msc_intervention(transaction, &intervention) == 0) { - dd("nothing to do"); -+ add_headers(msc_get_additional_req_headers(transaction), r->pool, &(r->headers_in.headers)); -+ add_headers(msc_get_additional_resp_headers(transaction), r->pool, &(r->headers_out.headers)); - return 0; - } - -+ add_headers(msc_get_additional_req_headers(transaction), r->pool, &(r->headers_in.headers)); -+ add_headers(msc_get_additional_resp_headers(transaction), r->pool, &(r->headers_out.headers)); -+ - log = intervention.log; - if (intervention.log == NULL) { - log = "(no log message was specified)"; -@@ -787,5 +796,108 @@ ngx_http_modsecurity_cleanup_rules(void *data) - ngx_http_modsecurity_pcre_malloc_done(old_pool); - } - -+static ngx_int_t -+add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers) -+{ -+ AdditionalHeader *header_from_modsecurity; -+ header_from_modsecurity = iterator; -+ dd("Debug - ADD HEADER: key - pointer : \"%p\"", header_from_modsecurity); -+ while(header_from_modsecurity != NULL) { -+ ngx_table_elt_t *header = NULL; -+ header = search_headers(&headers->part, (u_char *)header_from_modsecurity->key, strlen(header_from_modsecurity->key)); -+ -+ if (header == NULL) { -+ header = ngx_list_push(headers); -+ if (header == NULL) { -+ free_headers(iterator); -+ return NGX_ERROR; -+ } -+ header->key.data = ngx_pnalloc(pool, strlen(header_from_modsecurity->key)+1); -+ if (header->key.data == NULL) { -+ free_headers(iterator); -+ return NGX_ERROR; -+ } -+ header->key.len = strlen(header_from_modsecurity->key); -+ ngx_cpystrn(header->key.data, (u_char *)header_from_modsecurity->key, header->key.len+1); -+ } else if((strlen(header_from_modsecurity->value) == header->value.len) && (ngx_strcmp(&header->value.data, header_from_modsecurity->value) == 0)) { -+ header_from_modsecurity = header_from_modsecurity->next; -+ continue; -+ } -+ -+ dd("Debug - ADD HEADER: key: \"%s\"", header_from_modsecurity->key); -+ dd("Debug - ADD HEADER: value: \"%s\"", header_from_modsecurity->value); -+ header->value.data = ngx_pnalloc(pool, strlen(header_from_modsecurity->value)+1); -+ if (header->value.data == NULL) { -+ free_headers(iterator); -+ return NGX_ERROR; -+ } -+ header->value.len = strlen(header_from_modsecurity->value); -+ ngx_cpystrn(header->value.data, (u_char *)header_from_modsecurity->value, header->value.len+1); -+ header->hash = ngx_hash_key_lc(header->value.data, strlen(header_from_modsecurity->value)); -+ header_from_modsecurity = header_from_modsecurity->next; -+ }; -+ free_headers(iterator); -+ return NGX_OK; -+} -+ -+static void -+free_headers(AdditionalHeader *iterator) { -+ AdditionalHeader* current; -+ while(iterator != NULL) { -+ current = iterator; -+ iterator = current->next; -+ free(current->key); -+ free(current->value); -+ free(current); -+ } -+} -+ -+static ngx_table_elt_t * -+search_headers(ngx_list_part_t *part, u_char *name, size_t len) { -+ ngx_table_elt_t *h; -+ ngx_uint_t i; -+ -+ /* -+ Get the first part of the list. There is usual only one part. -+ */ -+ h = part->elts; -+ -+ /* -+ Headers list array may consist of more than one part, -+ so loop through all of it -+ */ -+ for (i = 0; /* void */ ; i++) { -+ if (i >= part->nelts) { -+ if (part->next == NULL) { -+ /* The last part, search is done. */ -+ break; -+ } -+ -+ part = part->next; -+ h = part->elts; -+ i = 0; -+ } -+ -+ /* -+ Just compare the lengths and then the names case insensitively. -+ */ -+ if (len != h[i].key.len || ngx_strcasecmp(name, h[i].key.data) != 0) { -+ /* This header doesn't match. */ -+ continue; -+ } -+ -+ /* -+ Ta-da, we got one! -+ Note, we'v stop the search at the first matched header -+ while more then one header may fit. -+ */ -+ return &h[i]; -+ } -+ -+ /* -+ No headers was found -+ */ -+ return NULL; -+} - - diff --git a/src/ngx_http_modsecurity_rewrite.c b/src/ngx_http_modsecurity_rewrite.c index 3723991..6300575 100644 --- a/src/ngx_http_modsecurity_rewrite.c +++ b/src/ngx_http_modsecurity_rewrite.c @@ -208,9 +208,8 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r) msc_process_request_headers(ctx->modsec_transaction); ngx_http_modsecurity_pcre_malloc_done(old_pool); dd("Processing intervention with the request headers information filled in"); - ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 1); - ctx->req_headers_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv); + ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 1); if (r->error_page) { return NGX_DECLINED; From 38ec2e3636d079e28631f4a0f826b84518695090 Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 18 May 2022 12:56:17 +0200 Subject: [PATCH 06/10] Fixes after review --- src/ngx_http_modsecurity_module.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index ca7efc4..5b3c6cc 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -34,8 +34,6 @@ static char *ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void static void ngx_http_modsecurity_cleanup_instance(void *data); static void ngx_http_modsecurity_cleanup_rules(void *data); static ngx_table_elt_t * search_headers(ngx_list_part_t *part, u_char *name, size_t len); -static ngx_int_t add_headers(AdditionalHeader *iterator, ngx_pool_t *pool, ngx_list_t *headers); -static void free_headers(AdditionalHeader *iterator); static ngx_int_t ngx_http_modsecurity_phase_time(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); From 6ec6bbbee497e94144c87f5c3a9dd7ac42adb6dc Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 18 May 2022 12:58:07 +0200 Subject: [PATCH 07/10] Fixes after review --- src/ngx_http_modsecurity_module.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index 5b3c6cc..b51c06e 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -157,14 +157,9 @@ ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_re if (msc_intervention(transaction, &intervention) == 0) { dd("nothing to do"); - add_headers(msc_get_additional_req_headers(transaction), r->pool, &(r->headers_in.headers)); - add_headers(msc_get_additional_resp_headers(transaction), r->pool, &(r->headers_out.headers)); return 0; } - add_headers(msc_get_additional_req_headers(transaction), r->pool, &(r->headers_in.headers)); - add_headers(msc_get_additional_resp_headers(transaction), r->pool, &(r->headers_out.headers)); - log = intervention.log; if (intervention.log == NULL) { log = "(no log message was specified)"; From aeb530781c88e08865396c1173f11cbbe1f2094b Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 18 May 2022 12:59:37 +0200 Subject: [PATCH 08/10] Fixes after review --- src/ngx_http_modsecurity_module.c | 3 ++- src/ngx_http_modsecurity_rewrite.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index b51c06e..5ae4d50 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -33,7 +33,6 @@ static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf); static char *ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child); static void ngx_http_modsecurity_cleanup_instance(void *data); static void ngx_http_modsecurity_cleanup_rules(void *data); -static ngx_table_elt_t * search_headers(ngx_list_part_t *part, u_char *name, size_t len); static ngx_int_t ngx_http_modsecurity_phase_time(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -810,6 +809,7 @@ ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } + static void ngx_http_modsecurity_cleanup_instance(void *data) { @@ -825,6 +825,7 @@ ngx_http_modsecurity_cleanup_instance(void *data) ngx_http_modsecurity_pcre_malloc_done(old_pool); } + static void ngx_http_modsecurity_cleanup_rules(void *data) { diff --git a/src/ngx_http_modsecurity_rewrite.c b/src/ngx_http_modsecurity_rewrite.c index 6300575..dd018a7 100644 --- a/src/ngx_http_modsecurity_rewrite.c +++ b/src/ngx_http_modsecurity_rewrite.c @@ -220,5 +220,6 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r) } } + return NGX_DECLINED; } From bb939a197e2b442a1757ea0ab2b43e63fb6f54ba Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 18 May 2022 13:03:25 +0200 Subject: [PATCH 09/10] Fixes after review --- src/ngx_http_modsecurity_module.c | 4 ++-- src/ngx_http_modsecurity_rewrite.c | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index 5ae4d50..627ede3 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -864,9 +864,9 @@ ngx_http_modsecurity_phase_time(ngx_http_request_t *r, return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_body_phase_time); case 4: return ngx_http_modsecurity_time_variable(r, v, data, ctx->logging_phase_time); + default: + return -1; } - - return -1; } diff --git a/src/ngx_http_modsecurity_rewrite.c b/src/ngx_http_modsecurity_rewrite.c index dd018a7..42ed1bd 100644 --- a/src/ngx_http_modsecurity_rewrite.c +++ b/src/ngx_http_modsecurity_rewrite.c @@ -52,7 +52,6 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r) { int ret = 0; struct timespec start_tv; - (void) clock_gettime(CLOCK_MONOTONIC, &start_tv); ngx_connection_t *connection = r->connection; @@ -210,7 +209,6 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r) dd("Processing intervention with the request headers information filled in"); ctx->req_headers_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv); ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 1); - if (r->error_page) { return NGX_DECLINED; } From d386de97fa7ddc868ce779c42278c0df1ae24698 Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 18 May 2022 13:04:46 +0200 Subject: [PATCH 10/10] Fixes after review --- src/ngx_http_modsecurity_header_filter.c | 1 - src/ngx_http_modsecurity_module.c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/ngx_http_modsecurity_header_filter.c b/src/ngx_http_modsecurity_header_filter.c index 6c2f4e1..69b64fe 100644 --- a/src/ngx_http_modsecurity_header_filter.c +++ b/src/ngx_http_modsecurity_header_filter.c @@ -531,7 +531,6 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r) ngx_http_modsecurity_pcre_malloc_done(old_pool); ctx->resp_headers_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv); ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0); - if (r->error_page) { return ngx_http_next_header_filter(r); } diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index 627ede3..993c537 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -20,7 +20,6 @@ #include "ngx_http_modsecurity_common.h" #include "stdio.h" -#include "string.h" #include #include #include