From 99c47b0c99c26b5439aacc594b2793d16e1fce3e Mon Sep 17 00:00:00 2001 From: Airis777 Date: Fri, 28 Apr 2017 17:22:44 +0400 Subject: [PATCH 1/3] Added support for the flag SameSite --- ngx_http_cookie_flag_filter_module.c | 99 ++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/ngx_http_cookie_flag_filter_module.c b/ngx_http_cookie_flag_filter_module.c index bdadcbf..b0316aa 100644 --- a/ngx_http_cookie_flag_filter_module.c +++ b/ngx_http_cookie_flag_filter_module.c @@ -2,10 +2,16 @@ #include #include +#define NUM_FLAGS 3 +#define MIN_ARGS 3 + typedef struct { ngx_str_t cookie_name; ngx_flag_t httponly; ngx_flag_t secure; + ngx_flag_t samesite; + ngx_flag_t samesite_lax; + ngx_flag_t samesite_strict; } ngx_http_cookie_t; typedef struct { @@ -18,6 +24,40 @@ static char *ngx_http_cookie_flag_filter_merge_loc_conf(ngx_conf_t *cf, void *pa static ngx_int_t ngx_http_cookie_flag_filter_init(ngx_conf_t *cf); static ngx_int_t ngx_http_cookie_flag_filter_append(ngx_http_request_t *r, ngx_http_cookie_t *flag, ngx_table_elt_t *header); static ngx_int_t ngx_http_cookie_flag_filter_handler(ngx_http_request_t *r); +static size_t ngx_char_pos(ngx_str_t str, u_char ch); +static u_char *ngx_get_arg_name(ngx_pool_t *pool, ngx_str_t src); + +static size_t ngx_char_pos(ngx_str_t str, u_char ch) { + + char *pos = NULL; + size_t ind = 0; + pos = strchr((char *) str.data, (int) ch); + if (pos != NULL) { + ind = (size_t) (pos - (char *) str.data); + } + return ind; + +} + +static u_char *ngx_get_arg_name(ngx_pool_t *pool, ngx_str_t src) { + + u_char *dst; + size_t pos; + + pos = ngx_char_pos(src, '='); + + if(pos) { + dst = ngx_pnalloc(pool, pos + 1); + if (dst == NULL) { + return NULL; + } + ngx_memcpy(dst, src.data, pos); + return dst; + } else { + return src.data; + } + +} static ngx_command_t ngx_http_cookie_flag_filter_commands[] = { @@ -73,19 +113,27 @@ ngx_http_cookie_flag_filter_cmd(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_cookie_t *cookie, tmp; ngx_str_t *value; - ngx_uint_t i; + ngx_uint_t i, j; value = cf->args->elts; - if (cf->args->nelts > 4 || cf->args->nelts < 3) { + if (cf->args->nelts > (NUM_FLAGS + 2) || cf->args->nelts < MIN_ARGS) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "The number of arguments is incorrect"); return NGX_CONF_ERROR; } - if (cf->args->nelts == 4) { - if (ngx_strncasecmp(value[2].data, value[3].data, value[3].len) == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Duplicate flag \"%V\" detected", &value[3]); - return NGX_CONF_ERROR; + // check on duplication + if (cf->args->nelts > MIN_ARGS) { + for (i = MIN_ARGS; i < cf->args->nelts; i++) { + for (j = MIN_ARGS - 1; j < i; j++) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "filter http_cookie_flag - comparasion \"%V\" and \"%V\"", &value[i], &value[j]); + u_char *first = ngx_get_arg_name(cf->pool, value[j]); + u_char *second = ngx_get_arg_name(cf->pool, value[i]); + if (ngx_strcasecmp(first, second) == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Duplicate flag \"%s\" (%V) detected", second, &value[i]); + return NGX_CONF_ERROR; + } + } } } @@ -114,6 +162,9 @@ ngx_http_cookie_flag_filter_cmd(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cookie->cookie_name.len = value[1].len; cookie->httponly = 0; cookie->secure = 0; + cookie->samesite = 0; + cookie->samesite_lax = 0; + cookie->samesite_strict = 0; // normalize and check 2nd and 3rd parameters for (i = 2; i < cf->args->nelts; i++) { @@ -121,6 +172,12 @@ ngx_http_cookie_flag_filter_cmd(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cookie->httponly = 1; } else if (ngx_strncasecmp(value[i].data, (u_char *) "secure", 6) == 0 && value[i].len == 6) { cookie->secure = 1; + } else if (ngx_strncasecmp(value[i].data, (u_char *) "samesite", 8) == 0 && value[i].len == 8) { + cookie->samesite = 1; + } else if (ngx_strncasecmp(value[i].data, (u_char *) "samesite=lax", 12) == 0 && value[i].len == 12) { + cookie->samesite_lax = 1; + } else if (ngx_strncasecmp(value[i].data, (u_char *) "samesite=strict", 15) == 0 && value[i].len == 15) { + cookie->samesite_strict = 1; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "The parameter value \"%V\" is incorrect", &value[i]); return NGX_CONF_ERROR; @@ -200,6 +257,36 @@ ngx_http_cookie_flag_filter_append(ngx_http_request_t *r, ngx_http_cookie_t *coo header->value.len = tmp.len; } + if (cookie->samesite == 1 && ngx_strcasestrn(header->value.data, "; SameSite", 10 - 1) == NULL) { + tmp.data = ngx_pnalloc(r->pool, header->value.len + sizeof("; SameSite") - 1); + if (tmp.data == NULL) { + return NGX_ERROR; + } + tmp.len = ngx_sprintf(tmp.data, "%V; SameSite", &header->value) - tmp.data; + header->value.data = tmp.data; + header->value.len = tmp.len; + } + + if (cookie->samesite_lax == 1 && ngx_strcasestrn(header->value.data, "; SameSite=Lax", 14 - 1) == NULL) { + tmp.data = ngx_pnalloc(r->pool, header->value.len + sizeof("; SameSite=Lax") - 1); + if (tmp.data == NULL) { + return NGX_ERROR; + } + tmp.len = ngx_sprintf(tmp.data, "%V; SameSite=Lax", &header->value) - tmp.data; + header->value.data = tmp.data; + header->value.len = tmp.len; + } + + if (cookie->samesite_strict == 1 && ngx_strcasestrn(header->value.data, "; SameSite=Strict", 17 - 1) == NULL) { + tmp.data = ngx_pnalloc(r->pool, header->value.len + sizeof("; SameSite=Strict") - 1); + if (tmp.data == NULL) { + return NGX_ERROR; + } + tmp.len = ngx_sprintf(tmp.data, "%V; SameSite=Strict", &header->value) - tmp.data; + header->value.data = tmp.data; + header->value.len = tmp.len; + } + return NGX_OK; } From af8b529ae15d5de0921c6be6757dba2d598c4bf0 Mon Sep 17 00:00:00 2001 From: Airis777 Date: Thu, 21 Sep 2017 17:37:58 +0400 Subject: [PATCH 2/3] Added SameSite flag to the README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ea3648c..2d0ca59 100644 --- a/README.md +++ b/README.md @@ -34,14 +34,15 @@ Earlier versions is not tested. ```Nginx location / { - set_cookie_flag Secret HttpOnly secure; + set_cookie_flag Secret HttpOnly secure SameSite; set_cookie_flag * HttpOnly; - set_cookie_flag SessionID secure; + set_cookie_flag SessionID SameSite=Lax secure; + set_cookie_flag SiteToken SameSite=Strict; } ``` ## Description -This module for Nginx allows to set the flags "**HttpOnly**" and "**secure**" for cookies in the "*Set-Cookie*" response headers. +This module for Nginx allows to set the flags "**HttpOnly**", "**secure**" and "**SameSite**" for cookies in the "*Set-Cookie*" response headers. The register of letters for the flags doesn't matter as it will be converted to the correct value. The order of cookie declaration among multiple directives doesn't matter too. It is possible to set a default value using symbol "*". In this case flags will be added to the all cookies if no other value for them is overriden. @@ -51,7 +52,7 @@ It is possible to set a default value using symbol "*". In this case flags will -| - --- | --- -**Syntax** | **set_cookie_flag** \ [HttpOnly\|secure] [HttpOnly\|secure]; +**Syntax** | **set_cookie_flag** \ [HttpOnly] [secure] [SameSite\|SameSite=[Lax|Strict]]; **Default** | - **Context** | server, location From 5bdf21fd3b61c87ff60122a3d8f2543c00d312a6 Mon Sep 17 00:00:00 2001 From: Airis777 Date: Thu, 21 Sep 2017 17:43:51 +0400 Subject: [PATCH 3/3] Fixed README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d0ca59..93c3f2a 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ It is possible to set a default value using symbol "*". In this case flags will -| - --- | --- -**Syntax** | **set_cookie_flag** \ [HttpOnly] [secure] [SameSite\|SameSite=[Lax|Strict]]; +**Syntax** | **set_cookie_flag** \ [HttpOnly] [secure] [SameSite\|SameSite=[Lax\|Strict]]; **Default** | - **Context** | server, location