Skip to content

Commit 99c47b0

Browse files
committed
Added support for the flag SameSite
1 parent 068d668 commit 99c47b0

File tree

1 file changed

+93
-6
lines changed

1 file changed

+93
-6
lines changed

ngx_http_cookie_flag_filter_module.c

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
#include <ngx_core.h>
33
#include <ngx_http.h>
44

5+
#define NUM_FLAGS 3
6+
#define MIN_ARGS 3
7+
58
typedef struct {
69
ngx_str_t cookie_name;
710
ngx_flag_t httponly;
811
ngx_flag_t secure;
12+
ngx_flag_t samesite;
13+
ngx_flag_t samesite_lax;
14+
ngx_flag_t samesite_strict;
915
} ngx_http_cookie_t;
1016

1117
typedef struct {
@@ -18,6 +24,40 @@ static char *ngx_http_cookie_flag_filter_merge_loc_conf(ngx_conf_t *cf, void *pa
1824
static ngx_int_t ngx_http_cookie_flag_filter_init(ngx_conf_t *cf);
1925
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);
2026
static ngx_int_t ngx_http_cookie_flag_filter_handler(ngx_http_request_t *r);
27+
static size_t ngx_char_pos(ngx_str_t str, u_char ch);
28+
static u_char *ngx_get_arg_name(ngx_pool_t *pool, ngx_str_t src);
29+
30+
static size_t ngx_char_pos(ngx_str_t str, u_char ch) {
31+
32+
char *pos = NULL;
33+
size_t ind = 0;
34+
pos = strchr((char *) str.data, (int) ch);
35+
if (pos != NULL) {
36+
ind = (size_t) (pos - (char *) str.data);
37+
}
38+
return ind;
39+
40+
}
41+
42+
static u_char *ngx_get_arg_name(ngx_pool_t *pool, ngx_str_t src) {
43+
44+
u_char *dst;
45+
size_t pos;
46+
47+
pos = ngx_char_pos(src, '=');
48+
49+
if(pos) {
50+
dst = ngx_pnalloc(pool, pos + 1);
51+
if (dst == NULL) {
52+
return NULL;
53+
}
54+
ngx_memcpy(dst, src.data, pos);
55+
return dst;
56+
} else {
57+
return src.data;
58+
}
59+
60+
}
2161

2262
static ngx_command_t ngx_http_cookie_flag_filter_commands[] = {
2363

@@ -73,19 +113,27 @@ ngx_http_cookie_flag_filter_cmd(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
73113

74114
ngx_http_cookie_t *cookie, tmp;
75115
ngx_str_t *value;
76-
ngx_uint_t i;
116+
ngx_uint_t i, j;
77117

78118
value = cf->args->elts;
79119

80-
if (cf->args->nelts > 4 || cf->args->nelts < 3) {
120+
if (cf->args->nelts > (NUM_FLAGS + 2) || cf->args->nelts < MIN_ARGS) {
81121
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "The number of arguments is incorrect");
82122
return NGX_CONF_ERROR;
83123
}
84124

85-
if (cf->args->nelts == 4) {
86-
if (ngx_strncasecmp(value[2].data, value[3].data, value[3].len) == 0) {
87-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Duplicate flag \"%V\" detected", &value[3]);
88-
return NGX_CONF_ERROR;
125+
// check on duplication
126+
if (cf->args->nelts > MIN_ARGS) {
127+
for (i = MIN_ARGS; i < cf->args->nelts; i++) {
128+
for (j = MIN_ARGS - 1; j < i; j++) {
129+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "filter http_cookie_flag - comparasion \"%V\" and \"%V\"", &value[i], &value[j]);
130+
u_char *first = ngx_get_arg_name(cf->pool, value[j]);
131+
u_char *second = ngx_get_arg_name(cf->pool, value[i]);
132+
if (ngx_strcasecmp(first, second) == 0) {
133+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Duplicate flag \"%s\" (%V) detected", second, &value[i]);
134+
return NGX_CONF_ERROR;
135+
}
136+
}
89137
}
90138
}
91139

@@ -114,13 +162,22 @@ ngx_http_cookie_flag_filter_cmd(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
114162
cookie->cookie_name.len = value[1].len;
115163
cookie->httponly = 0;
116164
cookie->secure = 0;
165+
cookie->samesite = 0;
166+
cookie->samesite_lax = 0;
167+
cookie->samesite_strict = 0;
117168

118169
// normalize and check 2nd and 3rd parameters
119170
for (i = 2; i < cf->args->nelts; i++) {
120171
if (ngx_strncasecmp(value[i].data, (u_char *) "httponly", 8) == 0 && value[i].len == 8) {
121172
cookie->httponly = 1;
122173
} else if (ngx_strncasecmp(value[i].data, (u_char *) "secure", 6) == 0 && value[i].len == 6) {
123174
cookie->secure = 1;
175+
} else if (ngx_strncasecmp(value[i].data, (u_char *) "samesite", 8) == 0 && value[i].len == 8) {
176+
cookie->samesite = 1;
177+
} else if (ngx_strncasecmp(value[i].data, (u_char *) "samesite=lax", 12) == 0 && value[i].len == 12) {
178+
cookie->samesite_lax = 1;
179+
} else if (ngx_strncasecmp(value[i].data, (u_char *) "samesite=strict", 15) == 0 && value[i].len == 15) {
180+
cookie->samesite_strict = 1;
124181
} else {
125182
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "The parameter value \"%V\" is incorrect", &value[i]);
126183
return NGX_CONF_ERROR;
@@ -200,6 +257,36 @@ ngx_http_cookie_flag_filter_append(ngx_http_request_t *r, ngx_http_cookie_t *coo
200257
header->value.len = tmp.len;
201258
}
202259

260+
if (cookie->samesite == 1 && ngx_strcasestrn(header->value.data, "; SameSite", 10 - 1) == NULL) {
261+
tmp.data = ngx_pnalloc(r->pool, header->value.len + sizeof("; SameSite") - 1);
262+
if (tmp.data == NULL) {
263+
return NGX_ERROR;
264+
}
265+
tmp.len = ngx_sprintf(tmp.data, "%V; SameSite", &header->value) - tmp.data;
266+
header->value.data = tmp.data;
267+
header->value.len = tmp.len;
268+
}
269+
270+
if (cookie->samesite_lax == 1 && ngx_strcasestrn(header->value.data, "; SameSite=Lax", 14 - 1) == NULL) {
271+
tmp.data = ngx_pnalloc(r->pool, header->value.len + sizeof("; SameSite=Lax") - 1);
272+
if (tmp.data == NULL) {
273+
return NGX_ERROR;
274+
}
275+
tmp.len = ngx_sprintf(tmp.data, "%V; SameSite=Lax", &header->value) - tmp.data;
276+
header->value.data = tmp.data;
277+
header->value.len = tmp.len;
278+
}
279+
280+
if (cookie->samesite_strict == 1 && ngx_strcasestrn(header->value.data, "; SameSite=Strict", 17 - 1) == NULL) {
281+
tmp.data = ngx_pnalloc(r->pool, header->value.len + sizeof("; SameSite=Strict") - 1);
282+
if (tmp.data == NULL) {
283+
return NGX_ERROR;
284+
}
285+
tmp.len = ngx_sprintf(tmp.data, "%V; SameSite=Strict", &header->value) - tmp.data;
286+
header->value.data = tmp.data;
287+
header->value.len = tmp.len;
288+
}
289+
203290
return NGX_OK;
204291
}
205292

0 commit comments

Comments
 (0)