]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: backend: correctly detect the domain when use_domain_only is used
authorCyril Bonté <cyril.bonte@free.fr>
Sun, 4 Jan 2015 14:17:36 +0000 (15:17 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 4 Jan 2015 18:35:04 +0000 (19:35 +0100)
balance hdr(<name>) provides on option 'use_domain_only' to match only the
domain part in a header (designed for the Host header).

Olivier Fredj reported that the hashes were not the same for
'subdomain.domain.tld' and 'domain.tld'.

This is because the pointer was rewinded one step to far, resulting in a hash
calculated against wrong values :
- '.domai' for 'subdomain.domain.tld'
- ' domai' for 'domain.tld' (beginning with the space in the header line)

Another special case is when no dot can be found in the header : the hash will
be calculated against an empty string.

The patch addresses both cases : 'domain' will be used to compute the hash for
'subdomain.domain.tld', 'domain.tld' and 'domain' (using the whole header value
for the last case).

The fix must be backported to haproxy 1.5 and 1.4.

src/backend.c

index 32e19f91569435dd1ae7b3fa7d319170f3ecacc7..35edf75041422d680941d96447b4ff18d448fcec 100644 (file)
@@ -409,29 +409,33 @@ struct server *get_server_hh(struct session *s)
                hash = gen_hash(px, p, len);
        } else {
                int dohash = 0;
-               p += len - 1;
-               start = end = p;
+               p += len;
                /* special computation, use only main domain name, not tld/host
                 * going back from the end of string, start hashing at first
                 * dot stop at next.
                 * This is designed to work with the 'Host' header, and requires
                 * a special option to activate this.
                 */
+               end = p;
                while (len) {
-                       if (*p == '.') {
-                               if (!dohash) {
-                                       dohash = 1;
-                                       start = end = p - 1;
-                               }
-                               else
+                       if (dohash) {
+                               /* Rewind the pointer until the previous char
+                                * is a dot, this will allow to set the start
+                                * position of the domain. */
+                               if (*(p - 1) == '.')
                                        break;
-                       } else {
-                               if (dohash)
-                                       start--;
                        }
-                       len--;
+                       else if (*p == '.') {
+                               /* The pointer is rewinded to the dot before the
+                                * tld, we memorize the end of the domain and
+                                * can enter the domain processing. */
+                               end = p;
+                               dohash = 1;
+                       }
                        p--;
+                       len--;
                }
+               start = p;
                hash = gen_hash(px, start, (end - start));
        }
        if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL)