Hi Daniel,

Le 23/08/2017 à 11:50, Daniel Schneller a écrit :
Kindly bumping this during the summer vacation time for potentially new 
recipients :)


On 21. Aug. 2017, at 21:14, Daniel Schneller 
<daniel.schnel...@centerdevice.com> wrote:
Hi!

According to the documentation

  req.cook_cnt([<name>]) : integer
  Returns an integer value representing the number of occurrences of the cookie
  <name> in the request, or all cookies if <name> is not specified.

it should be possible to do something like this to reject a request if it contains 
more than <n> cookies total. I do not know the cookie names in advance. I am 
trying to reject malicious requests with hundreds or thousands of cookies, trying to 
exhaust memory in my backend servers. Tomcat has a maximum number of cookies per 
request setting, but I’d like to reject these before they even get to the backends.

I thought this would work (for n=2):

        frontend fe-test
                bind 0.0.0.0:8070
                http-request deny deny_status 400 if { req.cook_cnt() gt 2 }
                http-request auth realm tomcat
                default_backend be-test


However, it does not work. The count is always 0, hence the ACL always pass >> 
[...]
When I change the ACL to include a cookie name, it works:

        http-request deny deny_status 400 if { req.cook_cnt("C1") gt 2 }
[...]
I tried to figure out what the code does, to see if I am doing something wrong 
and found this in proto_http.c:

------------------------------------------------------------------------------
/* Iterate over all cookies present in a request to count how many occurrences
* match the name in args and args->data.str.len. If <multi> is non-null, then
* multiple cookies may be parsed on the same line. The returned sample is of
* type UINT. Accepts exactly 1 argument of type string.
*/
static int
smp_fetch_cookie_cnt(const struct arg *args, struct sample *smp, const char 
*kw, void *private)
{
        struct http_txn *txn;
        struct hdr_idx *idx;
        struct hdr_ctx ctx;
        const struct http_msg *msg;
        const char *hdr_name;
        int hdr_name_len;
        int cnt;
        char *val_beg, *val_end;
        char *sol;

        if (!args || args->type != ARGT_STR)
                return 0;
------------------------------------------------------------------------------

So without being very C-savvy, this appears to exit early when there is no 
parameter of type string passed in.

I hope someone can shed some light on this. :)

You're right. currently, the code and the documentation don't say the same things.

Can you try the attached patch ?

--
Cyril Bonté
diff --git a/src/proto_http.c b/src/proto_http.c
index 2b9b0d01e..0935f0145 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -11318,8 +11318,8 @@ 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;
@@ -11617,7 +11617,7 @@ smp_fetch_cookie_cnt(const struct arg *args, struct sample *smp, const char *kw,
 	char *val_beg, *val_end;
 	char *sol;
 
-	if (!args || args->type != ARGT_STR)
+	if (!args || (args->type != ARGT_STR && args->type != ARGT_STOP))
 		return 0;
 
 	CHECK_HTTP_MESSAGE_FIRST();

Reply via email to