Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
martinhsv authored Apr 26, 2022
2 parents 7b8d7de + 1c32794 commit 755011c
Show file tree
Hide file tree
Showing 21 changed files with 331 additions and 75 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ addons:
- liblmdb-dev

env:
- VER_NGINX=1.17.6
- VER_NGINX=1.16.1
- VER_NGINX=1.21.0
- VER_NGINX=1.20.1

before_script:
- cd ..
Expand Down
12 changes: 11 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
v1.0.x - YYYY-MMM-DD (To be released)
-------------------------------------
--------------------

- Support http protocol versions besides 0.9, 1.0, 1.1, 2.0
[Issue #224 - @HQuest, @martinhsv]
- Support for building with nginx configured with PCRE2
[Issue #260 - @defanator]

v1.0.2 - 2021-Jun-02
--------------------

- Fix auditlog in case of internal redirect
[Issue #90 - @AirisX, @defanator]
- Fix nginx sends response without headers
[Issue #238 - @airween, @defanator]
- Fix nginx not clearing body cache (caused by incomplete fix for #187)
[Issue #216 - @krewi1, @martinhsv]
- Fix config setting not respected: client_body_in_file_only on
Expand Down
8 changes: 6 additions & 2 deletions src/ngx_http_modsecurity_body_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
return ngx_http_next_body_filter(r, in);
}

if (ctx->intervention_triggered) {
return ngx_http_next_body_filter(r, in);
}

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
mcf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity_module);
if (mcf != NULL && mcf->sanity_checks_enabled != NGX_CONF_UNSET)
Expand Down Expand Up @@ -141,7 +145,7 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
int ret;

msc_append_response_body(ctx->modsec_transaction, data, chain->buf->last - data);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
if (ret > 0) {
return ngx_http_filter_finalize_request(r,
&ngx_http_modsecurity_module, ret);
Expand All @@ -159,7 +163,7 @@ 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);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
if (ret > 0) {
return ret;
}
Expand Down
13 changes: 10 additions & 3 deletions src/ngx_http_modsecurity_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

#define MODSECURITY_NGINX_MAJOR "1"
#define MODSECURITY_NGINX_MINOR "0"
#define MODSECURITY_NGINX_PATCHLEVEL "1"
#define MODSECURITY_NGINX_PATCHLEVEL "2"
#define MODSECURITY_NGINX_TAG ""
#define MODSECURITY_NGINX_TAG_NUM "100"

Expand Down Expand Up @@ -97,6 +97,8 @@ typedef struct {
unsigned waiting_more_body:1;
unsigned body_requested:1;
unsigned processed:1;
unsigned logged:1;
unsigned intervention_triggered:1;
} ngx_http_modsecurity_ctx_t;


Expand Down Expand Up @@ -135,11 +137,16 @@ typedef struct {
extern ngx_module_t ngx_http_modsecurity_module;

/* ngx_http_modsecurity_module.c */
int ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_request_t *r);
int ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_request_t *r, ngx_int_t early_log);
ngx_http_modsecurity_ctx_t *ngx_http_modsecurity_create_ctx(ngx_http_request_t *r);
char *ngx_str_to_char(ngx_str_t a, ngx_pool_t *p);
#if (NGX_PCRE2)
#define ngx_http_modsecurity_pcre_malloc_init(x) NULL
#define ngx_http_modsecurity_pcre_malloc_done(x) (void)x
#else
ngx_pool_t *ngx_http_modsecurity_pcre_malloc_init(ngx_pool_t *pool);
void ngx_http_modsecurity_pcre_malloc_done(ngx_pool_t *old_pool);
#endif

/* ngx_http_modsecurity_body_filter.c */
ngx_int_t ngx_http_modsecurity_body_filter_init(void);
Expand All @@ -149,7 +156,7 @@ ngx_int_t ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *i
ngx_int_t ngx_http_modsecurity_header_filter_init(void);
ngx_int_t ngx_http_modsecurity_header_filter(ngx_http_request_t *r);
#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
int ngx_http_modescurity_store_ctx_header(ngx_http_request_t *r, ngx_str_t *name, ngx_str_t *value);
int ngx_http_modsecurity_store_ctx_header(ngx_http_request_t *r, ngx_str_t *name, ngx_str_t *value);
#endif

/* ngx_http_modsecurity_log.c */
Expand Down
32 changes: 18 additions & 14 deletions src/ngx_http_modsecurity_header_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ ngx_http_modsecurity_header_out_t ngx_http_modsecurity_headers_out[] = {

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
int
ngx_http_modescurity_store_ctx_header(ngx_http_request_t *r, ngx_str_t *name, ngx_str_t *value)
ngx_http_modsecurity_store_ctx_header(ngx_http_request_t *r, ngx_str_t *name, ngx_str_t *value)
{
ngx_http_modsecurity_ctx_t *ctx;
ngx_http_modsecurity_conf_t *mcf;
Expand Down Expand Up @@ -167,7 +167,7 @@ ngx_http_modsecurity_resolv_header_server(ngx_http_request_t *r, ngx_str_t name,
}

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name, &value);
ngx_http_modsecurity_store_ctx_header(r, &name, &value);
#endif

return msc_add_n_response_header(ctx->modsec_transaction,
Expand Down Expand Up @@ -196,7 +196,7 @@ ngx_http_modsecurity_resolv_header_date(ngx_http_request_t *r, ngx_str_t name, o
}

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name, &date);
ngx_http_modsecurity_store_ctx_header(r, &name, &date);
#endif

return msc_add_n_response_header(ctx->modsec_transaction,
Expand All @@ -223,7 +223,7 @@ ngx_http_modsecurity_resolv_header_content_length(ngx_http_request_t *r, ngx_str
value.len = strlen(buf);

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name, &value);
ngx_http_modsecurity_store_ctx_header(r, &name, &value);
#endif
return msc_add_n_response_header(ctx->modsec_transaction,
(const unsigned char *) name.data,
Expand All @@ -247,7 +247,7 @@ ngx_http_modsecurity_resolv_header_content_type(ngx_http_request_t *r, ngx_str_t
{

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name, &r->headers_out.content_type);
ngx_http_modsecurity_store_ctx_header(r, &name, &r->headers_out.content_type);
#endif

return msc_add_n_response_header(ctx->modsec_transaction,
Expand Down Expand Up @@ -280,7 +280,7 @@ ngx_http_modsecurity_resolv_header_last_modified(ngx_http_request_t *r, ngx_str_
value.len = (int)(p-buf);

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name, &value);
ngx_http_modsecurity_store_ctx_header(r, &name, &value);
#endif

return msc_add_n_response_header(ctx->modsec_transaction,
Expand Down Expand Up @@ -316,7 +316,7 @@ ngx_http_modsecurity_resolv_header_connection(ngx_http_request_t *r, ngx_str_t n
value.len = strlen((char *)buf);

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name2, &value);
ngx_http_modsecurity_store_ctx_header(r, &name2, &value);
#endif

msc_add_n_response_header(ctx->modsec_transaction,
Expand All @@ -333,7 +333,7 @@ ngx_http_modsecurity_resolv_header_connection(ngx_http_request_t *r, ngx_str_t n
value.len = strlen(connection);

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name, &value);
ngx_http_modsecurity_store_ctx_header(r, &name, &value);
#endif

return msc_add_n_response_header(ctx->modsec_transaction,
Expand All @@ -354,7 +354,7 @@ ngx_http_modsecurity_resolv_header_transfer_encoding(ngx_http_request_t *r, ngx_
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name, &value);
ngx_http_modsecurity_store_ctx_header(r, &name, &value);
#endif

return msc_add_n_response_header(ctx->modsec_transaction,
Expand All @@ -381,7 +381,7 @@ ngx_http_modsecurity_resolv_header_vary(ngx_http_request_t *r, ngx_str_t name, o
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &name, &value);
ngx_http_modsecurity_store_ctx_header(r, &name, &value);
#endif

return msc_add_n_response_header(ctx->modsec_transaction,
Expand Down Expand Up @@ -430,6 +430,10 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r)
return ngx_http_next_header_filter(r);
}

if (ctx->intervention_triggered) {
return ngx_http_next_header_filter(r);
}

/* XXX: can it happen ? already processed i mean */
/* XXX: check behaviour on 'ModSecurity off' */

Expand Down Expand Up @@ -488,7 +492,7 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r)
}

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &data[i].key, &data[i].value);
ngx_http_modsecurity_store_ctx_header(r, &data[i].key, &data[i].value);
#endif

/*
Expand Down Expand Up @@ -522,12 +526,12 @@ 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);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
if (r->error_page) {
return ngx_http_next_header_filter(r);
}
}
if (ret > 0) {
return ret;
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity_module, ret);
}

/*
Expand Down
5 changes: 5 additions & 0 deletions src/ngx_http_modsecurity_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ ngx_http_modsecurity_log_handler(ngx_http_request_t *r)
return NGX_ERROR;
}

if (ctx->logged) {
dd("already logged earlier");
return NGX_OK;
}

dd("calling msc_process_logging for %p", ctx);
old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool);
msc_process_logging(ctx->modsec_transaction);
Expand Down
27 changes: 25 additions & 2 deletions src/ngx_http_modsecurity_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static void ngx_http_modsecurity_cleanup_rules(void *data);
* https://github.com/openresty/lua-nginx-module/blob/master/src/ngx_http_lua_pcrefix.c
*/

#if !(NGX_PCRE2)
static void *(*old_pcre_malloc)(size_t);
static void (*old_pcre_free)(void *ptr);
static ngx_pool_t *ngx_http_modsec_pcre_pool = NULL;
Expand Down Expand Up @@ -103,6 +104,7 @@ ngx_http_modsecurity_pcre_malloc_done(ngx_pool_t *old_pool)
pcre_free = old_pcre_free;
}
}
#endif

/*
* ngx_string's are not null-terminated in common case, so we need to convert
Expand Down Expand Up @@ -130,17 +132,24 @@ ngx_inline char *ngx_str_to_char(ngx_str_t a, ngx_pool_t *p)


ngx_inline int
ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_request_t *r)
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;
Expand Down Expand Up @@ -192,14 +201,28 @@ ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_re
r->headers_out.location->hash = 1;

#if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS)
ngx_http_modescurity_store_ctx_header(r, &location->key, &location->value);
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.");
Expand Down
8 changes: 6 additions & 2 deletions src/ngx_http_modsecurity_pre_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}

if (ctx->intervention_triggered) {
return NGX_DECLINED;
}

if (ctx->waiting_more_body == 1)
{
dd("waiting for more data before proceed. / count: %d",
Expand Down Expand Up @@ -189,7 +193,7 @@ ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r)
* it may ask for a intervention in consequence of that.
*
*/
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
if (ret > 0) {
return ret;
}
Expand All @@ -208,7 +212,7 @@ ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r)
msc_process_request_body(ctx->modsec_transaction);
ngx_http_modsecurity_pcre_malloc_done(old_pool);

ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
if (r->error_page) {
return NGX_DECLINED;
}
Expand Down
9 changes: 6 additions & 3 deletions src/ngx_http_modsecurity_rewrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,9 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r)
*
*/
dd("Processing intervention with the connection information filled in");
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 1);
if (ret > 0) {
ctx->intervention_triggered = 1;
return ret;
}

Expand Down Expand Up @@ -163,8 +164,9 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r)
ngx_http_modsecurity_pcre_malloc_done(old_pool);

dd("Processing intervention with the transaction information filled in (uri, method and version)");
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 1);
if (ret > 0) {
ctx->intervention_triggered = 1;
return ret;
}

Expand Down Expand Up @@ -211,11 +213,12 @@ 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);
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 1);
if (r->error_page) {
return NGX_DECLINED;
}
if (ret > 0) {
ctx->intervention_triggered = 1;
return ret;
}
}
Expand Down
Loading

0 comments on commit 755011c

Please sign in to comment.