Le 13/11/2020 à 11:27, Maciej Zdeb a écrit :
Fixed warnings during compilation and fixed req.cook() which should return first and not last value when no cookie name specified.


Thanks Maciej,

I slightly updated your patch though. I changed the commit message to add details and simplified smp_fetch_cookie() function. I also updated the comments. I didn't want to bother you with that. hope it's ok for you ? Let me known if you want to rework the patch instead.

I also added another fix to support the sample fetches without the parentheses. 'req.cook()' and 'req.cook' must do the same.

--
Christopher Faulet
>From dd31af7efe576e4d594bd985ea24766fce5ef9a8 Mon Sep 17 00:00:00 2001
From: Maciej Zdeb <mac...@zdeb.pl>
Date: Fri, 13 Nov 2020 09:38:06 +0000
Subject: [PATCH 1/2] 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.
---
 src/http.c       |  5 +++--
 src/http_fetch.c | 29 ++++++++++++++---------------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/http.c b/src/http.c
index bb99c5098..22a5a1418 100644
--- a/src/http.c
+++ b/src/http.c
@@ -651,6 +651,7 @@ char *http_find_cookie_value_end(char *s, const char *e)
 }
 
 /* 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.
@@ -728,8 +729,8 @@ char *http_extract_cookie_value(char *hdr, const char *hdr_end,
 		 * 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 170d86c23..7938fb29c 100644
--- a/src/http_fetch.c
+++ b/src/http_fetch.c
@@ -1566,11 +1566,11 @@ static int smp_fetch_capture_res_ver(const struct arg *args, struct sample *smp,
  * 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)
 {
@@ -1580,7 +1580,6 @@ static int smp_fetch_cookie(const struct arg *args, struct sample *smp, const ch
 	struct htx *htx = smp_prefetch_htx(smp, chn, check, 1);
 	struct http_hdr_ctx *ctx = smp->ctx.a[2];
 	struct ist hdr;
-	int occ = 0;
 	int found = 0;
 
 	if (!args || args->type != ARGT_STR)
@@ -1598,13 +1597,9 @@ static int smp_fetch_cookie(const struct arg *args, struct sample *smp, const ch
 
 	hdr = (!(check || (chn && 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)) {
@@ -1638,11 +1633,15 @@ static int smp_fetch_cookie(const struct arg *args, struct sample *smp, const ch
 							  &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 */
+				return 1;
+			}
 		}
 		/* if we're looking for last occurrence, let's loop */
 	}
-- 
2.26.2

>From c999f71527f0740a0a437389dba0731f5539c255 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfau...@haproxy.com>
Date: Fri, 13 Nov 2020 13:41:04 +0100
Subject: [PATCH 2/2] BUG/MINOR: http-fetch: Fix calls w/o parentheses of the
 cookie sample fetches

req.cook, req.cook_val, req.cook_cnt and and their response counterparts may be
called without cookie name. In this case, empty parentheses may be used, or no
parentheses at all. In both, the result must be the same. But only the first one
works. The second one always returns a failure. This patch fixes this bug.

Note that on old versions (< 2.2), both cases fail.

This patch must be backported in all stable versions.
---
 src/http_fetch.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/src/http_fetch.c b/src/http_fetch.c
index 7938fb29c..e12a424b7 100644
--- a/src/http_fetch.c
+++ b/src/http_fetch.c
@@ -1580,10 +1580,14 @@ static int smp_fetch_cookie(const struct arg *args, struct sample *smp, const ch
 	struct htx *htx = smp_prefetch_htx(smp, chn, check, 1);
 	struct http_hdr_ctx *ctx = smp->ctx.a[2];
 	struct ist hdr;
+	char *cook = NULL;
+	size_t cook_l = 0;
 	int found = 0;
 
-	if (!args || args->type != ARGT_STR)
-		return 0;
+	if (args && args->type == ARGT_STR) {
+		cook = args->data.str.area;
+		cook_l = args->data.str.data;
+	}
 
 	if (!ctx) {
 		/* first call */
@@ -1617,7 +1621,7 @@ static int smp_fetch_cookie(const struct arg *args, struct sample *smp, const ch
 			if (!http_find_header(htx, hdr, ctx, 0))
 				goto out;
 
-			if (ctx->value.len < args->data.str.data + 1)
+			if (ctx->value.len < cook_l + 1)
 				continue;
 
 			smp->ctx.a[0] = ctx->value.ptr;
@@ -1627,7 +1631,7 @@ static int smp_fetch_cookie(const struct arg *args, struct sample *smp, const ch
 		smp->data.type = SMP_T_STR;
 		smp->flags |= SMP_F_CONST;
 		smp->ctx.a[0] = http_extract_cookie_value(smp->ctx.a[0], smp->ctx.a[1],
-							  args->data.str.area, args->data.str.data,
+							  cook, cook_l,
 							  (smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ,
 							  &smp->data.u.str.area,
 							  &smp->data.u.str.data);
@@ -1678,10 +1682,14 @@ static int smp_fetch_cookie_cnt(const struct arg *args, struct sample *smp, cons
 	struct http_hdr_ctx ctx;
 	struct ist hdr;
 	char *val_beg, *val_end;
+	char *cook = NULL;
+	size_t cook_l = 0;
 	int cnt;
 
-	if (!args || args->type != ARGT_STR)
-		return 0;
+	if (args && args->type == ARGT_STR){
+		cook = args->data.str.area;
+		cook_l = args->data.str.data;
+	}
 
 	if (!htx)
 		return 0;
@@ -1697,7 +1705,7 @@ static int smp_fetch_cookie_cnt(const struct arg *args, struct sample *smp, cons
 			if (!http_find_header(htx, hdr, &ctx, 0))
 				break;
 
-			if (ctx.value.len < args->data.str.data + 1)
+			if (ctx.value.len < cook_l + 1)
 				continue;
 
 			val_beg = ctx.value.ptr;
@@ -1707,7 +1715,7 @@ static int smp_fetch_cookie_cnt(const struct arg *args, struct sample *smp, cons
 		smp->data.type = SMP_T_STR;
 		smp->flags |= SMP_F_CONST;
 		while ((val_beg = http_extract_cookie_value(val_beg, val_end,
-							    args->data.str.area, args->data.str.data,
+							    cook, cook_l,
 							    (smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ,
 							    &smp->data.u.str.area,
 							    &smp->data.u.str.data))) {
-- 
2.26.2

Reply via email to