BUG/MINOR: http-fetch: Extract cookie value even when no cookie name

HTTP sample fetches dealing with the cookies (req/res.cook,
req/res.cook_val and req/res.cook_cnt) must be prepared to be called
without cookie name. For the first two, the first cookie value is
returned, regardless its name. For the last one, all cookies are counted.

To do so, http_extract_cookie_value() may now be called with no cookie
name (cookie_name_l set to 0). In this case, the matching on the cookie
name is ignored and the first value found is returned.

Note this patch also fixes matching on cookie values in ACLs.

This should be backported in all stable versions.

(cherry picked from commit dea7c209f8a77b471323dd97bdc1ac4d7a17b812)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 8cac341124e2b79c2a924ad186a114b39546298e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 02b89eadd7a7ddbaad88c5725b0a215d2d8c1d81)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit a862430878f4435a1a64926e945501d737f7babd)
[cf: Legacy HTTP part fixed too]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/http.c b/src/http.c
index 255b487..1ee891c 100644
--- a/src/http.c
+++ b/src/http.c
@@ -653,6 +653,7 @@
 }
 
 /* Try to find the next occurrence of a cookie name in a cookie header value.
+ * To match on any cookie name, <cookie_name_l> must be set to 0.
  * The lookup begins at <hdr>. The pointer and size of the next occurrence of
  * the cookie value is returned into *value and *value_l, and the function
  * returns a pointer to the next pointer to search from if the value was found.
@@ -730,8 +731,8 @@
 		 * its value between val_beg and val_end.
 		 */
 
-		if (att_end - att_beg == cookie_name_l &&
-		    memcmp(att_beg, cookie_name, cookie_name_l) == 0) {
+		if (cookie_name_l == 0 || (att_end - att_beg == cookie_name_l &&
+		    memcmp(att_beg, cookie_name, cookie_name_l) == 0)) {
 			/* let's return this value and indicate where to go on from */
 			*value = val_beg;
 			*value_l = val_end - val_beg;
diff --git a/src/http_fetch.c b/src/http_fetch.c
index e95f210..b2afdbf 100644
--- a/src/http_fetch.c
+++ b/src/http_fetch.c
@@ -2199,17 +2199,16 @@
  * smp->ctx.a[0] for the in-header position, smp->ctx.a[1] for the
  * end-of-header-value, and smp->ctx.a[2] for the hdr_ctx. Depending on
  * the direction, multiple cookies may be parsed on the same line or not.
- * The cookie name is in args and the name length in args->data.str.len.
- * Accepts exactly 1 argument of type string. If the input options indicate
- * that no iterating is desired, then only last value is fetched if any.
- * The returned sample is of type CSTR. Can be used to parse cookies in other
- * files.
+ * If provided, the searched cookie name is in args, in args->data.str. If
+ * the input options indicate that no iterating is desired, then only last
+ * value is fetched if any. If no cookie name is provided, the first cookie
+ * value found is fetched. The returned sample is of type CSTR.  Can be used
+ * to parse cookies in other files.
  */
 static int smp_fetch_cookie(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
 	/* possible keywords: req.cookie / cookie / cook, res.cookie / scook / set-cookie */
 	struct channel *chn = ((kw[0] == 'c' || kw[2] == 'q') ? SMP_REQ_CHN(smp) : SMP_RES_CHN(smp));
-	int occ = 0;
 	int found = 0;
 
 	if (!args || args->type != ARGT_STR)
@@ -2233,13 +2232,9 @@
 
 		hdr = (!(chn->flags & CF_ISRESP) ? ist("Cookie") : ist("Set-Cookie"));
 
-		if (!occ && !(smp->opt & SMP_OPT_ITERATE))
-			/* no explicit occurrence and single fetch => last cookie by default */
-			occ = -1;
-
-		/* OK so basically here, either we want only one value and it's the
-		 * last one, or we want to iterate over all of them and we fetch the
-		 * next one.
+		/* OK so basically here, either we want only one value or we want to
+		 * iterate over all of them and we fetch the next one. In this last case
+		 * SMP_OPT_ITERATE option is set.
 		 */
 
 		if (!(smp->flags & SMP_F_NOT_LAST)) {
@@ -2273,11 +2268,15 @@
 								  &smp->data.u.str.data);
 			if (smp->ctx.a[0]) {
 				found = 1;
-				if (occ >= 0) {
-					/* one value was returned into smp->data.u.str.{str,len} */
+				if (smp->opt & SMP_OPT_ITERATE) {
+					/* iterate on cookie value */
 					smp->flags |= SMP_F_NOT_LAST;
 					return 1;
 				}
+				if (args->data.str.data == 0) {
+					/* No cookie name, first occurrence returned */
+					break;
+				}
 			}
 			/* if we're looking for last occurrence, let's loop */
 		}
@@ -2308,13 +2307,9 @@
 			hdr_name_len = 10;
 		}
 
-		if (!occ && !(smp->opt & SMP_OPT_ITERATE))
-			/* no explicit occurrence and single fetch => last cookie by default */
-			occ = -1;
-
-		/* OK so basically here, either we want only one value and it's the
-		 * last one, or we want to iterate over all of them and we fetch the
-		 * next one.
+		/* OK so basically here, either we want only one value or we want to
+		 * iterate over all of them and we fetch the next one. In this last case
+		 * SMP_OPT_ITERATE option is set.
 		 */
 
 		sol = ci_head(chn);
@@ -2349,11 +2344,15 @@
 								  &smp->data.u.str.area, &smp->data.u.str.data);
 			if (smp->ctx.a[0]) {
 				found = 1;
-				if (occ >= 0) {
-					/* one value was returned into smp->data.u.str.{str,len} */
+				if (smp->opt & SMP_OPT_ITERATE) {
+					/* iterate on cookie value */
 					smp->flags |= SMP_F_NOT_LAST;
 					return 1;
 				}
+				if (args->data.str.data == 0) {
+					/* No cookie name, first occurrence returned */
+					break;
+				}
 			}
 			/* if we're looking for last occurrence, let's loop */
 		}