22#include <ngx_core.h>
33#include <ngx_http.h>
44
5+ #define NUM_FLAGS 3
6+ #define MIN_ARGS 3
7+
58typedef 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
1117typedef struct {
@@ -18,6 +24,40 @@ static char *ngx_http_cookie_flag_filter_merge_loc_conf(ngx_conf_t *cf, void *pa
1824static ngx_int_t ngx_http_cookie_flag_filter_init (ngx_conf_t * cf );
1925static ngx_int_t ngx_http_cookie_flag_filter_append (ngx_http_request_t * r , ngx_http_cookie_t * flag , ngx_table_elt_t * header );
2026static 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
2262static 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