]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: acl/pattern: switch rdp_cookie functions stack up-down
authorWilly Tarreau <w@1wt.eu>
Mon, 23 Apr 2012 21:13:20 +0000 (23:13 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 18:57:16 +0000 (20:57 +0200)
Previously, both pattern, backend and persist_rdp_cookie would build fake
ACL expressions to fetch an RDP cookie by calling acl_fetch_rdp_cookie().

Now we switch roles. The RDP cookie fetch function is provided as a sample
fetch function that all others rely on, including ACL. The code is exactly
the same, only the args handling moved from expr->args to args. The code
was moved to proto_tcp.c, but probably that a dedicated file would be more
suited to content handling.

include/proto/acl.h
include/proto/backend.h
include/proto/proto_tcp.h
src/acl.c
src/backend.c
src/proto_tcp.c

index 998ac4362093af1b612d2d3007a17cdc5a485150..131d79985846d57ab21d9b2c86806798a0644184 100644 (file)
@@ -177,10 +177,6 @@ int acl_fetch_nothing(struct proxy *px, struct session *l4, void *l7, int dir,
 /* always return false */
 int acl_match_nothing(struct sample *smp, struct acl_pattern *pattern);
 
-/* Fetch the RDP cookie identified in the expression. */
-int acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
-                         struct acl_expr *expr, struct sample *smp);
-
 /* Checks that the pattern matches the end of the tested string. */
 int acl_match_end(struct sample *smp, struct acl_pattern *pattern);
 
index c8322b8eba6dba444b8bec55cc230335268ad881..b4dfc835c36d5fed0fbe1252105ddf1cb9a4872a 100644 (file)
@@ -37,6 +37,7 @@ int srv_redispatch_connect(struct session *t);
 const char *backend_lb_algo_str(int algo);
 int backend_parse_balance(const char **args, char *err,
                          int errlen, struct proxy *curproxy);
+int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit);
 
 int be_downtime(struct proxy *px);
 void recount_servers(struct proxy *px);
index 1665f151f55908963c6b2143c44be8ad7f4395f7..91573e9596daa756531b605b3d6b3bda9a8b6aee 100644 (file)
@@ -33,8 +33,8 @@ void tcpv6_add_listener(struct listener *listener);
 int tcp_connect_server(struct stream_interface *si);
 int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit);
 int tcp_inspect_response(struct session *s, struct buffer *rep, int an_bit);
-int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit);
 int tcp_exec_req_rules(struct session *s);
+int smp_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir, const struct arg *args, struct sample *smp);
 
 /* Converts the TCP source address to a stick_table key usable for table
  * lookups. Returns either NULL if the source cannot be converted (eg: not
index 5d86a3e1a1f49489ad314838417dfe7f1c7f6044..36b53070c317f20f8879477f5262f496abc2a371 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -453,118 +453,6 @@ acl_fetch_ssl_hello_sni(struct proxy *px, struct session *l4, void *l7, int dir,
        return 0;
 }
 
-/* Fetch the RDP cookie identified in the expression.
- * Note: this decoder only works with non-wrapping data.
- * Accepts either 0 or 1 argument. Argument is a string (cookie name), other
- * types will lead to undefined behaviour.
- */
-int
-acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
-                     struct acl_expr *expr, struct sample *smp)
-{
-       int bleft;
-       const unsigned char *data;
-
-       if (!l4 || !l4->req)
-               return 0;
-
-       smp->flags = 0;
-       smp->type = SMP_T_CSTR;
-
-       bleft = l4->req->i;
-       if (bleft <= 11)
-               goto too_short;
-
-       data = (const unsigned char *)l4->req->p + 11;
-       bleft -= 11;
-
-       if (bleft <= 7)
-               goto too_short;
-
-       if (strncasecmp((const char *)data, "Cookie:", 7) != 0)
-               goto not_cookie;
-
-       data += 7;
-       bleft -= 7;
-
-       while (bleft > 0 && *data == ' ') {
-               data++;
-               bleft--;
-       }
-
-       if (expr->args) {
-
-               if (bleft <= expr->args->data.str.len)
-                       goto too_short;
-
-               if ((data[expr->args->data.str.len] != '=') ||
-                   strncasecmp(expr->args->data.str.str, (const char *)data, expr->args->data.str.len) != 0)
-                       goto not_cookie;
-
-               data += expr->args->data.str.len + 1;
-               bleft -= expr->args->data.str.len + 1;
-       } else {
-               while (bleft > 0 && *data != '=') {
-                       if (*data == '\r' || *data == '\n')
-                               goto not_cookie;
-                       data++;
-                       bleft--;
-               }
-
-               if (bleft < 1)
-                       goto too_short;
-
-               if (*data != '=')
-                       goto not_cookie;
-
-               data++;
-               bleft--;
-       }
-
-       /* data points to cookie value */
-       smp->data.str.str = (char *)data;
-       smp->data.str.len = 0;
-
-       while (bleft > 0 && *data != '\r') {
-               data++;
-               bleft--;
-       }
-
-       if (bleft < 2)
-               goto too_short;
-
-       if (data[0] != '\r' || data[1] != '\n')
-               goto not_cookie;
-
-       smp->data.str.len = (char *)data - smp->data.str.str;
-       smp->flags = SMP_F_VOLATILE;
-       return 1;
-
- too_short:
-       smp->flags = SMP_F_MAY_CHANGE;
- not_cookie:
-       return 0;
-}
-
-static int
-acl_fetch_rdp_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
-                         struct acl_expr *expr, struct sample *smp)
-{
-       int ret;
-
-       ret = acl_fetch_rdp_cookie(px, l4, l7, dir, expr, smp);
-
-       if (smp->flags & SMP_F_MAY_CHANGE)
-               return 0;
-
-       smp->flags = SMP_F_VOLATILE;
-       smp->type = SMP_T_UINT;
-       smp->data.uint = ret;
-
-       return 1;
-}
-
-
 /*
  * These functions are exported and may be used by any other component.
  */
@@ -2159,8 +2047,6 @@ static struct acl_kw_list acl_kws = {{ },{
        { "always_true",         acl_parse_nothing,    acl_fetch_true,           acl_match_nothing, ACL_USE_NOTHING, 0 },
        { "rep_ssl_hello_type",  acl_parse_int,        acl_fetch_ssl_hello_type, acl_match_int,     ACL_USE_L6RTR_VOLATILE, 0 },
        { "req_len",             acl_parse_int,        acl_fetch_req_len,        acl_match_int,     ACL_USE_L6REQ_VOLATILE, 0 },
-       { "req_rdp_cookie",      acl_parse_str,        acl_fetch_rdp_cookie,     acl_match_str,     ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
-       { "req_rdp_cookie_cnt",  acl_parse_int,        acl_fetch_rdp_cookie_cnt, acl_match_int,     ACL_USE_L6REQ_VOLATILE, ARG1(0,STR) },
        { "req_ssl_hello_type",  acl_parse_int,        acl_fetch_ssl_hello_type, acl_match_int,     ACL_USE_L6REQ_VOLATILE, 0 },
        { "req_ssl_sni",         acl_parse_str,        acl_fetch_ssl_hello_sni,  acl_match_str,     ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, 0 },
        { "req_ssl_ver",         acl_parse_dotted_ver, acl_fetch_req_ssl_ver,    acl_match_int,     ACL_USE_L6REQ_VOLATILE, 0 },
index fc8f22fa2dcd3bc4ab0d46da73c9eee69d8e1f28..c0c2412679f1714407f2348b9f4d5d7c21ede3b6 100644 (file)
@@ -402,7 +402,6 @@ struct server *get_server_rch(struct session *s)
        unsigned long    len;
        const char      *p;
        int              ret;
-       struct acl_expr  expr;
        struct sample    smp;
        struct arg       args[2];
 
@@ -410,7 +409,6 @@ struct server *get_server_rch(struct session *s)
        if (px->lbprm.tot_weight == 0)
                return NULL;
 
-       memset(&expr, 0, sizeof(expr));
        memset(&smp, 0, sizeof(smp));
 
        args[0].type = ARGT_STR;
@@ -418,9 +416,7 @@ struct server *get_server_rch(struct session *s)
        args[0].data.str.len = px->hh_len;
        args[1].type = ARGT_STOP;
 
-       expr.args = args;
-
-       ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &smp);
+       ret = smp_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, args, &smp);
        len = smp.data.str.len;
 
        if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || len == 0)
@@ -1113,7 +1109,6 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
 {
        struct proxy    *px   = s->be;
        int              ret;
-       struct acl_expr  expr;
        struct sample    smp;
        struct server *srv = px->srv;
        struct sockaddr_in addr;
@@ -1132,7 +1127,6 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
        if (s->flags & SN_ASSIGNED)
                goto no_cookie;
 
-       memset(&expr, 0, sizeof(expr));
        memset(&smp, 0, sizeof(smp));
 
        args[0].type = ARGT_STR;
@@ -1140,9 +1134,7 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
        args[0].data.str.len = s->be->rdp_cookie_len;
        args[1].type = ARGT_STOP;
 
-       expr.args = args;
-
-       ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &smp);
+       ret = smp_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, args, &smp);
        if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || smp.data.str.len == 0)
                goto no_cookie;
 
index bd46de29c0d05f470a2405578ef790769614e983..317a5f37a151475a123dfc2ce33eb068413d2753 100644 (file)
@@ -1247,10 +1247,146 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
 }
 
 
+/************************************************************************/
+/*       All supported sample fetch functios must be declared here      */
+/************************************************************************/
+
+/* Fetch the request RDP cookie identified in the args, or any cookie if no arg
+ * is passed. It is usable both for ACL and for patterns. Note: this decoder
+ * only works with non-wrapping data. Accepts either 0 or 1 argument. Argument
+ * is a string (cookie name), other types will lead to undefined behaviour.
+ */
+int
+smp_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
+                     const struct arg *args, struct sample *smp)
+{
+       int bleft;
+       const unsigned char *data;
+
+       if (!l4 || !l4->req)
+               return 0;
+
+       smp->flags = 0;
+       smp->type = SMP_T_CSTR;
+
+       bleft = l4->req->i;
+       if (bleft <= 11)
+               goto too_short;
+
+       data = (const unsigned char *)l4->req->p + 11;
+       bleft -= 11;
+
+       if (bleft <= 7)
+               goto too_short;
+
+       if (strncasecmp((const char *)data, "Cookie:", 7) != 0)
+               goto not_cookie;
+
+       data += 7;
+       bleft -= 7;
+
+       while (bleft > 0 && *data == ' ') {
+               data++;
+               bleft--;
+       }
+
+       if (args) {
+
+               if (bleft <= args->data.str.len)
+                       goto too_short;
+
+               if ((data[args->data.str.len] != '=') ||
+                   strncasecmp(args->data.str.str, (const char *)data, args->data.str.len) != 0)
+                       goto not_cookie;
+
+               data += args->data.str.len + 1;
+               bleft -= args->data.str.len + 1;
+       } else {
+               while (bleft > 0 && *data != '=') {
+                       if (*data == '\r' || *data == '\n')
+                               goto not_cookie;
+                       data++;
+                       bleft--;
+               }
+
+               if (bleft < 1)
+                       goto too_short;
+
+               if (*data != '=')
+                       goto not_cookie;
+
+               data++;
+               bleft--;
+       }
+
+       /* data points to cookie value */
+       smp->data.str.str = (char *)data;
+       smp->data.str.len = 0;
+
+       while (bleft > 0 && *data != '\r') {
+               data++;
+               bleft--;
+       }
+
+       if (bleft < 2)
+               goto too_short;
+
+       if (data[0] != '\r' || data[1] != '\n')
+               goto not_cookie;
+
+       smp->data.str.len = (char *)data - smp->data.str.str;
+       smp->flags = SMP_F_VOLATILE;
+       return 1;
+
+ too_short:
+       smp->flags = SMP_F_MAY_CHANGE;
+ not_cookie:
+       return 0;
+}
+
+static int
+pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
+                         const struct arg *arg_p, struct sample *smp)
+{
+       int ret;
+
+       /* sample type set by smp_fetch_rdp_cookie() */
+       ret = smp_fetch_rdp_cookie(px, l4, NULL, ACL_DIR_REQ, arg_p, smp);
+       if (ret == 0 || (smp->flags & SMP_F_MAY_CHANGE) || smp->data.str.len == 0)
+               return 0;
+       return 1;
+}
+
 /************************************************************************/
 /*           All supported ACL keywords must be declared here.          */
 /************************************************************************/
 
+static int
+acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
+                     struct acl_expr *expr, struct sample *smp)
+{
+       return smp_fetch_rdp_cookie(px, l4, l7, dir, expr->args, smp);
+}
+
+/* returns either 1 or 0 depending on whether an RDP cookie is found or not */
+static int
+acl_fetch_rdp_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
+                         struct acl_expr *expr, struct sample *smp)
+{
+       int ret;
+
+       ret = smp_fetch_rdp_cookie(px, l4, l7, dir, expr->args, smp);
+
+       if (smp->flags & SMP_F_MAY_CHANGE)
+               return 0;
+
+       smp->flags = SMP_F_VOLATILE;
+       smp->type = SMP_T_UINT;
+       smp->data.uint = ret;
+       return 1;
+}
+
+
 /* copy the source IPv4/v6 address into temp_pattern */
 static int
 acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -1472,34 +1608,6 @@ pattern_fetch_payload(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-static int
-pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
-                         const struct arg *arg_p, struct sample *smp)
-{
-       int ret;
-       struct acl_expr  expr;
-       struct arg       args[2];
-
-       if (!l4)
-               return 0;
-
-       memset(&expr, 0, sizeof(expr));
-       memset(smp, 0, sizeof(*smp));
-
-       args[0].type = ARGT_STR;
-       args[0].data.str.str = arg_p[0].data.str.str;
-       args[0].data.str.len = arg_p[0].data.str.len;
-       args[1].type = ARGT_STOP;
-
-       expr.args = args;
-
-       /* type set by acl_fetch_rdp_cookie */
-       ret = acl_fetch_rdp_cookie(px, l4, NULL, ACL_DIR_REQ, &expr, smp);
-       if (ret == 0 || (smp->flags & SMP_F_MAY_CHANGE) || smp->data.str.len == 0)
-               return 0;
-       return 1;
-}
-
 /* This function is used to validate the arguments passed to a "payload" fetch
  * keyword. This keyword expects two positive integers, with the second one
  * being strictly positive. It is assumed that the types are already the correct
@@ -1556,6 +1664,8 @@ static struct cfg_kw_list cfg_kws = {{ },{
 static struct acl_kw_list acl_kws = {{ },{
        { "dst",        acl_parse_ip,    acl_fetch_dst,      acl_match_ip,  ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP, 0 },
        { "dst_port",   acl_parse_int,   acl_fetch_dport,    acl_match_int, ACL_USE_TCP_PERMANENT, 0  },
+       { "req_rdp_cookie",     acl_parse_str, acl_fetch_rdp_cookie,     acl_match_str, ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
+       { "req_rdp_cookie_cnt", acl_parse_int, acl_fetch_rdp_cookie_cnt, acl_match_int, ACL_USE_L6REQ_VOLATILE, ARG1(0,STR) },
        { "src",        acl_parse_ip,    acl_fetch_src,      acl_match_ip,  ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP, 0 },
        { "src_port",   acl_parse_int,   acl_fetch_sport,    acl_match_int, ACL_USE_TCP_PERMANENT, 0  },
        { NULL, NULL, NULL, NULL },