7e49db86e52a49a8654505282747dcb5d6befb2a
[openwrt-packages.git] /
1 commit fac50825151ac2abc6b71343e3ffa6e0dc06c53d
2 Author: Christopher Faulet <cfaulet@haproxy.com>
3 Date:   Tue Jan 21 11:06:48 2020 +0100
4
5     MINOR: proxy/http-ana: Add support of extra attributes for the cookie directive
6     
7     It is now possible to insert any attribute when a cookie is inserted by
8     HAProxy. Any value may be set, no check is performed except the syntax validity
9     (CTRL chars and ';' are forbidden). For instance, it may be used to add the
10     SameSite attribute:
11     
12         cookie SRV insert attr "SameSite=Strict"
13     
14     The attr option may be repeated to add several attributes.
15     
16     This patch should fix the issue #361.
17     
18     (cherry picked from commit 2f5339079b884ac8bdde166add1879ebfd9e433b)
19     Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
20
21 diff --git a/doc/configuration.txt b/doc/configuration.txt
22 index 3f381e386..e0dc49880 100644
23 --- a/doc/configuration.txt
24 +++ b/doc/configuration.txt
25 @@ -3255,7 +3255,7 @@ compression offload
26  cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
27                [ postonly ] [ preserve ] [ httponly ] [ secure ]
28                [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
29 -              [ dynamic ]
30 +              [ dynamic ] [ attr <value> ]*
31    Enable cookie-based persistence in a backend.
32    May be used in sections :   defaults | frontend | listen | backend
33                                   yes   |    no    |   yes  |   yes
34 @@ -3414,6 +3414,11 @@ cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
35                The cookie will be regenerated each time the IP address change,
36                and is only generated for IPv4/IPv6.
37  
38 +    attr      This option tells haproxy to add an extra attribute when a
39 +              cookie is inserted. The attribute value can contain any
40 +              characters except control ones or ";". This option may be
41 +              repeated.
42 +
43    There can be only one persistence cookie per HTTP backend, and it can be
44    declared in a defaults section. The value of the cookie will be the value
45    indicated after the "cookie" keyword in a "server" statement. If no cookie
46 diff --git a/include/types/proxy.h b/include/types/proxy.h
47 index 6ea96b3ad..3661c9a0c 100644
48 --- a/include/types/proxy.h
49 +++ b/include/types/proxy.h
50 @@ -338,6 +338,7 @@ struct proxy {
51         int  cookie_len;                        /* strlen(cookie_name), computed only once */
52         char *cookie_domain;                    /* domain used to insert the cookie */
53         char *cookie_name;                      /* name of the cookie to look for */
54 +       char *cookie_attrs;                     /* list of attributes to add to the cookie */
55         char *dyncookie_key;                    /* Secret key used to generate dynamic persistent cookies */
56         unsigned int cookie_maxidle;            /* max idle time for this cookie */
57         unsigned int cookie_maxlife;            /* max life time for this cookie */
58 diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
59 index 9975e4687..b1f5c0790 100644
60 --- a/src/cfgparse-listen.c
61 +++ b/src/cfgparse-listen.c
62 @@ -323,6 +323,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
63                                  curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
64                         curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
65  
66 +                       if (defproxy.cookie_attrs)
67 +                               curproxy->cookie_attrs = strdup(defproxy.cookie_attrs);
68  
69                         if (defproxy.lbprm.arg_str)
70                                 curproxy->lbprm.arg_str = strdup(defproxy.lbprm.arg_str);
71 @@ -473,6 +475,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
72                 free(defproxy.rdp_cookie_name);
73                 free(defproxy.dyncookie_key);
74                 free(defproxy.cookie_domain);
75 +               free(defproxy.cookie_attrs);
76                 free(defproxy.lbprm.arg_str);
77                 free(defproxy.capture_name);
78                 free(defproxy.monitor_uri);
79 @@ -986,9 +989,34 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
80                                         err_code |= ERR_WARN;
81                                 curproxy->ck_opts |= PR_CK_DYNAMIC;
82                         }
83 +                       else if (!strcmp(args[cur_arg], "attr")) {
84 +                               char *val;
85 +                               if (!*args[cur_arg + 1]) {
86 +                                       ha_alert("parsing [%s:%d]: '%s' expects <value> as argument.\n",
87 +                                                file, linenum, args[cur_arg]);
88 +                                       err_code |= ERR_ALERT | ERR_FATAL;
89 +                                       goto out;
90 +                               }
91 +                               val = args[cur_arg + 1];
92 +                               while (*val) {
93 +                                       if (iscntrl(*val) || *val == ';') {
94 +                                               ha_alert("parsing [%s:%d]: character '%%x%02X' is not permitted in attribute value.\n",
95 +                                                        file, linenum, *val);
96 +                                               err_code |= ERR_ALERT | ERR_FATAL;
97 +                                               goto out;
98 +                                       }
99 +                                       val++;
100 +                               }
101 +                               /* don't add ';' for the first attribute */
102 +                               if (!curproxy->cookie_attrs)
103 +                                       curproxy->cookie_attrs = strdup(args[cur_arg + 1]);
104 +                               else
105 +                                       memprintf(&curproxy->cookie_attrs, "%s; %s", curproxy->cookie_attrs, args[cur_arg + 1]);
106 +                               cur_arg++;
107 +                       }
108  
109                         else {
110 -                               ha_alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic' and 'maxlife' options.\n",
111 +                               ha_alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic', 'maxlife' and 'attr' options.\n",
112                                          file, linenum, args[0]);
113                                 err_code |= ERR_ALERT | ERR_FATAL;
114                                 goto out;
115 diff --git a/src/haproxy.c b/src/haproxy.c
116 index f225a13f8..98d6a9a39 100644
117 --- a/src/haproxy.c
118 +++ b/src/haproxy.c
119 @@ -2352,6 +2352,7 @@ void deinit(void)
120                 free(p->check_req);
121                 free(p->cookie_name);
122                 free(p->cookie_domain);
123 +               free(p->cookie_attrs);
124                 free(p->lbprm.arg_str);
125                 free(p->capture_name);
126                 free(p->monitor_uri);
127 diff --git a/src/http_ana.c b/src/http_ana.c
128 index 047ed813a..cb5a60ca9 100644
129 --- a/src/http_ana.c
130 +++ b/src/http_ana.c
131 @@ -2027,6 +2027,9 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
132                 if (s->be->ck_opts & PR_CK_SECURE)
133                         chunk_appendf(&trash, "; Secure");
134  
135 +               if (s->be->cookie_attrs)
136 +                       chunk_appendf(&trash, "; %s", s->be->cookie_attrs);
137 +
138                 if (unlikely(!http_add_header(htx, ist("Set-Cookie"), ist2(trash.area, trash.data))))
139                         goto return_bad_resp;
140  
git clone https://git.99rst.org/PROJECT