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();