]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] added several ACL criteria and matches
authorWilly Tarreau <w@1wt.eu>
Sun, 6 May 2007 22:55:35 +0000 (00:55 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2007 21:24:50 +0000 (23:24 +0200)
Many ACL criteria have been added. Some others are still commented out
because some functions are still missing.

src/client.c
src/proto_http.c

index 2754b91f7220ce32d16eba2c1ae120f6158fb0ab..113708efd00ba1b9fd410d0a5453da1cbc191495 100644 (file)
@@ -24,6 +24,7 @@
 #include <common/config.h>
 #include <common/time.h>
 
+#include <types/acl.h>
 #include <types/backend.h>
 #include <types/buffers.h>
 #include <types/global.h>
@@ -33,6 +34,7 @@
 #include <types/server.h>
 #include <types/session.h>
 
+#include <proto/acl.h>
 #include <proto/buffers.h>
 #include <proto/client.h>
 #include <proto/fd.h>
@@ -448,6 +450,65 @@ int event_accept(int fd) {
 
 
 
+/************************************************************************/
+/*             All supported keywords must be declared here.            */
+/************************************************************************/
+
+/* set test->ptr to point to the source IPv4/IPv6 address and test->i to the family */
+static int acl_fetch_src(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test)
+{
+       test->i = l4->cli_addr.ss_family;
+       if (test->i == AF_INET)
+               test->ptr = (void *)&((struct sockaddr_in *)&l4->cli_addr)->sin_addr;
+       else
+               test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->cli_addr))->sin6_addr;
+       test->flags = ACL_TEST_F_READ_ONLY;
+       return 1;
+}
+
+
+/* set test->i to the connexion's source port */
+static int acl_fetch_sport(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test)
+{
+       if (l4->cli_addr.ss_family == AF_INET)
+               test->i = ntohs(((struct sockaddr_in *)&l4->cli_addr)->sin_port);
+       else
+               test->i = ntohs(((struct sockaddr_in6 *)(&l4->cli_addr))->sin6_port);
+       test->flags = 0;
+       return 1;
+}
+
+/* set test->i to the number of connexions to the proxy */
+static int acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test)
+{
+       test->i = px->feconn;
+       return 1;
+}
+
+
+/* Note: must not be declared <const> as its list will be overwritten */
+static struct acl_kw_list acl_kws = {{ },{
+       { "src_port",   acl_parse_range, acl_fetch_sport,  acl_match_range },
+#if 0
+       { "src",        acl_parse_ip,    acl_fetch_src,    acl_match_ip    },
+       { "dst",        acl_parse_ip,    acl_fetch_dst,    acl_match_ip    },
+
+       { "dst_port",   acl_parse_range, acl_fetch_dport,  acl_match_range },
+
+       { "src_limit",  acl_parse_int,   acl_fetch_sconn,  acl_match_max   },
+#endif
+       { "dst_limit",  acl_parse_int,   acl_fetch_dconn,  acl_match_max   },
+       { NULL, NULL, NULL, NULL },
+}};
+
+
+__attribute__((constructor))
+static void __client_init(void)
+{
+       acl_register_keywords(&acl_kws);
+}
+
+
 /*
  * Local variables:
  *  c-indent-level: 8
index 4540fd4d84d7dec10687d0a34333856f424da589..706ef464078c96ddab966ff59cf1b705824e9afa 100644 (file)
@@ -34,6 +34,7 @@
 #include <common/uri_auth.h>
 #include <common/version.h>
 
+#include <types/acl.h>
 #include <types/capture.h>
 #include <types/client.h>
 #include <types/global.h>
@@ -42,6 +43,7 @@
 #include <types/proxy.h>
 #include <types/server.h>
 
+#include <proto/acl.h>
 #include <proto/backend.h>
 #include <proto/buffers.h>
 #include <proto/fd.h>
@@ -5124,6 +5126,217 @@ void debug_hdr(const char *dir, struct session *t, const char *start, const char
 }
 
 
+/************************************************************************/
+/*        The code below is dedicated to ACL parsing and matching       */
+/************************************************************************/
+
+
+
+
+/* 1. Check on METHOD
+ * We use the pre-parsed method if it is known, and store its number as an
+ * integer. If it is unknown, we use the pointer and the length.
+ */
+static int acl_parse_meth(const char *text, struct acl_pattern *pattern)
+{
+       int len, meth;
+
+       len  = strlen(text);
+       meth = find_http_meth(text, len);
+
+       pattern->val.i = meth;
+       if (meth == HTTP_METH_OTHER) {
+               pattern->ptr.str = strdup(text);
+               if (!pattern->ptr.str)
+                       return 0;
+               pattern->len = len;
+       }
+       return 1;
+}
+
+static int acl_fetch_meth(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test)
+{
+       int meth;
+       struct http_txn *txn = l7;
+
+       meth = txn->meth;
+       test->i = meth;
+       if (meth == HTTP_METH_OTHER) {
+               test->len = txn->req.sl.rq.m_l;
+               test->ptr = txn->req.sol;
+       }
+       test->flags = ACL_TEST_F_READ_ONLY | ACL_TEST_F_VOL_1ST;
+       return 1;
+}
+
+static int acl_match_meth(struct acl_test *test, struct acl_pattern *pattern)
+{
+       if (test->i != pattern->val.i)
+               return 0;
+
+       if (test->i != HTTP_METH_OTHER)
+               return 1;
+
+       /* Other method, we must compare the strings */
+       if (pattern->len != test->len)
+               return 0;
+       if (strncmp(pattern->ptr.str, test->ptr, test->len) != 0)
+               return 0;
+       return 1;
+}
+
+/* 2. Check on Request/Status Version
+ * We simply compare strings here.
+ */
+static int acl_parse_ver(const char *text, struct acl_pattern *pattern)
+{
+       pattern->ptr.str = strdup(text);
+       if (!pattern->ptr.str)
+               return 0;
+       pattern->len = strlen(text);
+       return 1;
+}
+
+static int acl_fetch_rqver(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test)
+{
+       struct http_txn *txn = l7;
+       char *ptr;
+       int len;
+
+       len = txn->req.sl.rq.v_l;
+       ptr = txn->req.sol + txn->req.sl.rq.v - txn->req.som;
+
+       while ((len-- > 0) && (*ptr++ != '/'));
+       if (len <= 0)
+               return 0;
+
+       test->ptr = ptr;
+       test->len = len;
+
+       test->flags = ACL_TEST_F_READ_ONLY | ACL_TEST_F_VOL_1ST;
+       return 1;
+}
+
+static int acl_fetch_stver(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test)
+{
+       struct http_txn *txn = l7;
+       char *ptr;
+       int len;
+
+       len = txn->rsp.sl.st.v_l;
+       ptr = txn->rsp.sol;
+
+       while ((len-- > 0) && (*ptr++ != '/'));
+       if (len <= 0)
+               return 0;
+
+       test->ptr = ptr;
+       test->len = len;
+
+       test->flags = ACL_TEST_F_READ_ONLY | ACL_TEST_F_VOL_1ST;
+       return 1;
+}
+
+/* 3. Check on Status Code. We manipulate integers here. */
+static int acl_fetch_stcode(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test)
+{
+       struct http_txn *txn = l7;
+       char *ptr;
+       int len;
+
+       len = txn->rsp.sl.st.c_l;
+       ptr = txn->rsp.sol + txn->rsp.sl.st.c - txn->rsp.som;
+
+       test->i = __strl2ui(ptr, len);
+       test->flags = ACL_TEST_F_VOL_1ST;
+       return 1;
+}
+
+/* 4. Check on URL/URI. A pointer to the URI is stored. */
+static int acl_fetch_url(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test)
+{
+       struct http_txn *txn = l7;
+
+       test->len = txn->req.sl.rq.u_l;
+       test->ptr = txn->req.sol + txn->req.sl.rq.u;
+
+       test->flags = ACL_TEST_F_READ_ONLY | ACL_TEST_F_VOL_1ST;
+       return 1;
+}
+
+
+
+/************************************************************************/
+/*             All supported keywords must be declared here.            */
+/************************************************************************/
+
+/* Note: must not be declared <const> as its list will be overwritten */
+static struct acl_kw_list acl_kws = {{ },{
+       { "method",     acl_parse_meth,  acl_fetch_meth,   acl_match_meth },
+       { "req_ver",    acl_parse_ver,   acl_fetch_rqver,  acl_match_str  },
+       { "resp_ver",   acl_parse_ver,   acl_fetch_stver,  acl_match_str  },
+       { "status",     acl_parse_range, acl_fetch_stcode, acl_match_range },
+
+       { "url",        acl_parse_str,   acl_fetch_url,    acl_match_str   },
+       { "url_beg",    acl_parse_str,   acl_fetch_url,    acl_match_beg   },
+       { "url_end",    acl_parse_str,   acl_fetch_url,    acl_match_end   },
+       { "url_sub",    acl_parse_str,   acl_fetch_url,    acl_match_sub   },
+       { "url_dir",    acl_parse_str,   acl_fetch_url,    acl_match_dir   },
+       { "url_dom",    acl_parse_str,   acl_fetch_url,    acl_match_dom   },
+       { NULL, NULL, NULL, NULL },
+#if 0
+       { "url_reg",    acl_parse_reg,   acl_fetch_url,    acl_match_reg   },
+
+       { "line",       acl_parse_str,   acl_fetch_line,   acl_match_str   },
+       { "line_reg",   acl_parse_reg,   acl_fetch_line,   acl_match_reg   },
+       { "line_beg",   acl_parse_str,   acl_fetch_line,   acl_match_beg   },
+       { "line_end",   acl_parse_str,   acl_fetch_line,   acl_match_end   },
+       { "line_sub",   acl_parse_str,   acl_fetch_line,   acl_match_sub   },
+       { "line_dir",   acl_parse_str,   acl_fetch_line,   acl_match_dir   },
+       { "line_dom",   acl_parse_str,   acl_fetch_line,   acl_match_dom   },
+
+       { "path",       acl_parse_str,   acl_fetch_path,   acl_match_str   },
+       { "path_reg",   acl_parse_reg,   acl_fetch_path,   acl_match_reg   },
+       { "path_beg",   acl_parse_str,   acl_fetch_path,   acl_match_beg   },
+       { "path_end",   acl_parse_str,   acl_fetch_path,   acl_match_end   },
+       { "path_sub",   acl_parse_str,   acl_fetch_path,   acl_match_sub   },
+       { "path_dir",   acl_parse_str,   acl_fetch_path,   acl_match_dir   },
+       { "path_dom",   acl_parse_str,   acl_fetch_path,   acl_match_dom   },
+
+       { "hdr",        acl_parse_str,   acl_fetch_hdr,    acl_match_str   },
+       { "hdr_reg",    acl_parse_reg,   acl_fetch_hdr,    acl_match_reg   },
+       { "hdr_beg",    acl_parse_str,   acl_fetch_hdr,    acl_match_beg   },
+       { "hdr_end",    acl_parse_str,   acl_fetch_hdr,    acl_match_end   },
+       { "hdr_sub",    acl_parse_str,   acl_fetch_hdr,    acl_match_sub   },
+       { "hdr_dir",    acl_parse_str,   acl_fetch_hdr,    acl_match_dir   },
+       { "hdr_dom",    acl_parse_str,   acl_fetch_hdr,    acl_match_dom   },
+       { "hdr_pst",    acl_parse_none,  acl_fetch_hdr,    acl_match_pst   },
+
+       { "cook",       acl_parse_str,   acl_fetch_cook,   acl_match_str   },
+       { "cook_reg",   acl_parse_reg,   acl_fetch_cook,   acl_match_reg   },
+       { "cook_beg",   acl_parse_str,   acl_fetch_cook,   acl_match_beg   },
+       { "cook_end",   acl_parse_str,   acl_fetch_cook,   acl_match_end   },
+       { "cook_sub",   acl_parse_str,   acl_fetch_cook,   acl_match_sub   },
+       { "cook_dir",   acl_parse_str,   acl_fetch_cook,   acl_match_dir   },
+       { "cook_dom",   acl_parse_str,   acl_fetch_cook,   acl_match_dom   },
+       { "cook_pst",   acl_parse_none,  acl_fetch_cook,   acl_match_pst   },
+
+       { "auth_user",  acl_parse_str,   acl_fetch_user,   acl_match_str   },
+       { "auth_regex", acl_parse_reg,   acl_fetch_user,   acl_match_reg   },
+       { "auth_clear", acl_parse_str,   acl_fetch_auth,   acl_match_str   },
+       { "auth_md5",   acl_parse_str,   acl_fetch_auth,   acl_match_md5   },
+       { NULL, NULL, NULL, NULL },
+#endif
+}};
+
+
+__attribute__((constructor))
+static void __http_protocol_init(void)
+{
+       acl_register_keywords(&acl_kws);
+}
+
+
 /*
  * Local variables:
  *  c-indent-level: 8