[MINOR] Allow to specify a domain for a cookie
This patch allows to specify a domain used when inserting a cookie providing a session stickiness. Usefull for example with wildcard domains. The patch adds one new variable to the struct proxy: cookiedomain. When set the domain is appended to a Set-Cookie header. Domain name is validated using the new invalid_domainchar() function. It is basically invalid_char() limited to [A-Za-z0-9_.-]. Yes, the test is too trivial and does not cover all wrong situations, but the main purpose is to detect most common mistakes, not intentional abuses. The underscore ("_") character is not RFC-valid but as it is often (mis)used so I decided to allow it.
This commit is contained in:
parent
1fb6c87cce
commit
efe3b6f524
@ -1087,7 +1087,7 @@ contimeout <timeout>
|
||||
"timeout server", "contimeout".
|
||||
|
||||
|
||||
cookie <name> [ rewrite|insert|prefix ] [ indirect ] [ nocache ] [ postonly ]
|
||||
cookie <name> [ rewrite|insert|prefix ] [ indirect ] [ nocache ] [ postonly ] [domain <domain>]
|
||||
Enable cookie-based persistence in a backend.
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
yes | no | yes | yes
|
||||
@ -1167,6 +1167,10 @@ cookie <name> [ rewrite|insert|prefix ] [ indirect ] [ nocache ] [ postonly ]
|
||||
persistence cookie in the cache.
|
||||
See also the "insert" and "nocache" options.
|
||||
|
||||
domain This option allows to specify the domain at which a cookie is
|
||||
inserted. It requires exactly one paramater: a valid domain
|
||||
name.
|
||||
|
||||
There can be only one persistence cookie per HTTP backend, and it can be
|
||||
declared in a defaults section. The value of the cookie will be the value
|
||||
indicated after the "cookie" keyword in a "server" statement. If no cookie
|
||||
|
@ -135,6 +135,13 @@ extern int ishex(char s);
|
||||
*/
|
||||
extern const char *invalid_char(const char *name);
|
||||
|
||||
/*
|
||||
* Checks <domainname> for invalid characters. Valid chars are [A-Za-z0-9_.-].
|
||||
* If an invalid character is found, a pointer to it is returned.
|
||||
* If everything is fine, NULL is returned.
|
||||
*/
|
||||
extern const char *invalid_domainchar(const char *name);
|
||||
|
||||
/*
|
||||
* converts <str> to a struct sockaddr_un* which is locally allocated.
|
||||
* The format is "/path", where "/path" is a path to a UNIX domain socket.
|
||||
|
@ -161,6 +161,7 @@ struct proxy {
|
||||
void (*server_drop_conn)(struct server *);/* to be called when connection is dropped */
|
||||
} lbprm; /* LB parameters for all algorithms */
|
||||
|
||||
char *cookiedomain; /* domain used to insert the cookie */
|
||||
char *cookie_name; /* name of the cookie to look for */
|
||||
int cookie_len; /* strlen(cookie_name), computed only once */
|
||||
char *url_param_name; /* name of the URL parameter used for hashing */
|
||||
|
@ -895,8 +895,33 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
|
||||
else if (!strcmp(args[cur_arg], "prefix")) {
|
||||
curproxy->options |= PR_O_COOK_PFX;
|
||||
}
|
||||
else if (!strcmp(args[cur_arg], "domain")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
|
||||
file, linenum, args[cur_arg]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
|
||||
/* rfc2109, 4.3.2 Rejecting Cookies */
|
||||
Alert("parsing [%s:%d]: domain '%s' contains no embedded"
|
||||
" dots or does not start with a dot.\n",
|
||||
file, linenum, args[cur_arg + 1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = invalid_domainchar(args[cur_arg + 1]);
|
||||
if (err) {
|
||||
Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
|
||||
file, linenum, *err, args[cur_arg + 1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
curproxy->cookiedomain = strdup(args[cur_arg + 1]);
|
||||
cur_arg++;
|
||||
}
|
||||
else {
|
||||
Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
|
||||
Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
|
||||
file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
@ -3222,6 +3222,9 @@ int process_srv(struct session *t)
|
||||
t->be->cookie_name,
|
||||
t->srv->cookie ? t->srv->cookie : "; Expires=Thu, 01-Jan-1970 00:00:01 GMT");
|
||||
|
||||
if (t->be->cookiedomain)
|
||||
len += sprintf(trash+len, "; domain=%s", t->be->cookiedomain);
|
||||
|
||||
if (unlikely(http_header_add_tail2(rep, &txn->rsp, &txn->hdr_idx,
|
||||
trash, len)) < 0)
|
||||
goto return_bad_resp;
|
||||
|
@ -140,6 +140,27 @@ const char *invalid_char(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks <domainname> for invalid characters. Valid chars are [A-Za-z0-9_.-].
|
||||
* If an invalid character is found, a pointer to it is returned.
|
||||
* If everything is fine, NULL is returned.
|
||||
*/
|
||||
const char *invalid_domainchar(const char *name) {
|
||||
|
||||
if (!*name)
|
||||
return name;
|
||||
|
||||
while (*name) {
|
||||
if (!isalnum((int)*name) && *name != '.' &&
|
||||
*name != '_' && *name != '-')
|
||||
return name;
|
||||
|
||||
name++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* converts <str> to a struct sockaddr_in* which is locally allocated.
|
||||
* The format is "addr:port", where "addr" can be a dotted IPv4 address,
|
||||
|
Loading…
x
Reference in New Issue
Block a user