]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[BUG] http: fix cookie parser to support spaces and commas in values
authorWilly Tarreau <w@1wt.eu>
Sun, 3 Jan 2010 18:45:54 +0000 (19:45 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 28 Jan 2010 22:16:36 +0000 (23:16 +0100)
The cookie parser could be fooled by spaces or commas in cookie names
and values, causing the persistence cookie not to be matched if located
just after such a cookie. Now spaces found in values are considered as
part of the value, and spaces, commas and semi-colons found in values
or names, are skipped till next cookie name.

This fix must be backported to 1.3.
(cherry picked from commit 305ae859572b81339cc210d9d84b01449fd1d44e)

src/proto_http.c

index 46528b5f39478364f4118210f0ae6434cbdfb3d4..32ac33e432444d4c93252aa8a51cba7a3d150d2a 100644 (file)
@@ -3440,7 +3440,7 @@ void manage_client_side_appsession(struct session *t, const char *buf) {
 void manage_client_side_cookies(struct session *t, struct buffer *req)
 {
        struct http_txn *txn = &t->txn;
-       char *p1, *p2, *p3, *p4;
+       char *p1, *p2, *p3, *p4, *p5;
        char *del_colon, *del_cookie, *colon;
        int app_cookies;
 
@@ -3495,6 +3495,7 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
                
                while (p1 < cur_end) {
                        /* skip spaces and colons, but keep an eye on these ones */
+               resync_name:
                        while (p1 < cur_end) {
                                if (*p1 == ';' || *p1 == ',')
                                        colon = p1;
@@ -3508,8 +3509,14 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
                    
                        /* p1 is at the beginning of the cookie name */
                        p2 = p1;
-                       while (p2 < cur_end && *p2 != '=')
+                       while (p2 < cur_end && *p2 != '=') {
+                               if (*p2 == ',' || *p2 == ';' || isspace((unsigned char)*p2)) {
+                                       /* oops, the cookie name was truncated, resync */
+                                       p1 = p2;
+                                       goto resync_name;
+                               }
                                p2++;
+                       }
 
                        if (p2 == cur_end)
                                break;
@@ -3518,16 +3525,20 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
                        if (p3 == cur_end)
                                break;
                    
-                       p4 = p3;
-                       while (p4 < cur_end && !isspace((unsigned char)*p4) && *p4 != ';' && *p4 != ',')
-                               p4++;
+                       /* parse the value, stripping leading and trailing spaces but keeping insiders. */
+                       p5 = p4 = p3;
+                       while (p5 < cur_end && *p5 != ';' && *p5 != ',') {
+                               if (!isspace((unsigned char)*p5))
+                                       p4 = p5 + 1;
+                               p5++;
+                       }
 
                        /* here, we have the cookie name between p1 and p2,
                         * and its value between p3 and p4.
                         * we can process it :
                         *
-                        * Cookie: NAME=VALUE;
-                        * |      ||   ||    |
+                        * Cookie: NAME=VALUE ;
+                        * |      ||   ||    |+-> p5
                         * |      ||   ||    +--> p4
                         * |      ||   |+-------> p3
                         * |      ||   +--------> p2
@@ -3567,8 +3578,8 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
                                         * have the server ID betweek p3 and delim, and the original cookie between
                                         * delim+1 and p4. Otherwise, delim==p4 :
                                         *
-                                        * Cookie: NAME=SRV~VALUE;
-                                        * |      ||   ||  |     |
+                                        * Cookie: NAME=SRV~VALUE ;
+                                        * |      ||   ||  |     |+-> p5
                                         * |      ||   ||  |     +--> p4
                                         * |      ||   ||  +--------> delim
                                         * |      ||   |+-----------> p3
@@ -3634,6 +3645,7 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
 
                                                delta = buffer_replace2(req, p3, delim + 1, NULL, 0);
                                                p4  += delta;
+                                               p5  += delta;
                                                cur_end += delta;
                                                cur_next += delta;
                                                cur_hdr->len += delta;
@@ -3660,6 +3672,7 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
 
                                                delta = buffer_replace2(req, del_cookie, p1, NULL, 0);
                                                p4  += delta;
+                                               p5  += delta;
                                                cur_end += delta;
                                                cur_next += delta;
                                                cur_hdr->len += delta;
@@ -3682,7 +3695,7 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
                        }
 
                        /* we'll have to look for another cookie ... */
-                       p1 = p4;
+                       p1 = p5;
                } /* while (p1 < cur_end) */
 
                /* There's no more cookie on this line.