]> git.kaiwu.me - haproxy.git/commitdiff
[MINOR] Allow to specify a domain for a cookie
authorKrzysztof Piotr Oledzki <ole@ans.pl>
Fri, 23 May 2008 21:49:32 +0000 (23:49 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 3 Dec 2009 22:53:24 +0000 (23:53 +0100)
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.
(cherry picked from commit efe3b6f524c5cc6328233941ca44247993342d71)

doc/configuration.txt
include/common/standard.h
include/types/proxy.h
src/cfgparse.c
src/proto_http.c
src/standard.c

index 9c489e58b1335a20a8b2f40ea5dbec4555e2d0da..9f4c7e144a07366ebd3de83bb866cff9b9df46a9 100644 (file)
@@ -1116,7 +1116,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
@@ -1196,6 +1196,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
index 2a2c8f66c301254772ded0fe438ee818675af964..892f516e52a23f4f597714ee0b1506b7db1ddf83 100644 (file)
@@ -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.
index 091be57e2eb2e45b511d2ab851e2f9638152727f..6c366b8e869f6ade9b23a1bebd516691500496c9 100644 (file)
@@ -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 */
index 196954a4302154bc6b13296842699ce42ecc6e5a..99ffc0abbaaf6a83e517c8ecde042cd1cebccecd 100644 (file)
@@ -907,8 +907,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;
                        }
index d7a3277869d3760e995a6f31d8d59b160eee665d..95505b67aab6e2076e83c11c26276b070ded4203 100644 (file)
@@ -3220,6 +3220,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;
index d419db97229dafc6817f7e70766e95633236f524..895d0b69c6ed8b155d6c34274bd9af178793a6bd 100644 (file)
@@ -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,