diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2007-11-22 10:09:54 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2007-11-22 10:09:54 +0000 |
commit | 528448c354fbc39d0ec76390e0abb03bffe3030c (patch) | |
tree | cbb3c2d948302dc744689adcd4383ae90e7ba120 /usr.sbin/relayd | |
parent | e7be2a8e9b2bedf33849efda13e890b933152f0b (diff) |
add (new) "url" protocol action, this can be used to match/filter URL
suffix/prefix expressions like "example.com/index.html?args". a digest
mode allows to match against anonymized SHA1/MD5 digests of
suffix/prefix expressions.
Diffstat (limited to 'usr.sbin/relayd')
-rw-r--r-- | usr.sbin/relayd/parse.y | 47 | ||||
-rw-r--r-- | usr.sbin/relayd/relay.c | 85 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.conf.5 | 32 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 8 |
4 files changed, 162 insertions, 10 deletions
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y index f8e0829996f..86ebc48c691 100644 --- a/usr.sbin/relayd/parse.y +++ b/usr.sbin/relayd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.92 2007/11/21 20:31:03 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.93 2007/11/22 10:09:53 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -123,7 +123,7 @@ typedef struct { %token TIMEOUT CODE DIGEST PORT TAG INTERFACE STYLE RETURN %token VIRTUAL INTERVAL DISABLE STICKYADDR BACKLOG PATH SCRIPT %token SEND EXPECT NOTHING SSL LOADBALANCE ROUNDROBIN CIPHERS COOKIE -%token RELAY LISTEN ON FORWARD TO NAT LOOKUP PREFORK NO MARK MARKED +%token RELAY LISTEN ON FORWARD TO NAT LOOKUP PREFORK NO MARK MARKED URL %token PROTO SESSION CACHE APPEND CHANGE REMOVE FROM FILTER HASH HEADER %token LOG UPDATES ALL DEMOTE NODELAY SACK SOCKET BUFFER QUERYSTR RETRY IP %token ERROR @@ -728,6 +728,8 @@ protoptsl : SSL sslflags if (node.type == NODE_TYPE_COOKIE) pk.key = "Cookie"; + else if (node.type == NODE_TYPE_URL) + pk.key = "Host"; else pk.key = "GET"; if (node.type != NODE_TYPE_HEADER) { @@ -763,6 +765,15 @@ protoptsl : SSL sslflags case NODE_TYPE_COOKIE: pn->flags |= PNFLAG_LOOKUP_COOKIE; break; + case NODE_TYPE_URL: + if (node.flags & + PNFLAG_LOOKUP_URL_DIGEST) + pn->flags |= node.flags & + PNFLAG_LOOKUP_URL_DIGEST; + else + pn->flags |= + PNFLAG_LOOKUP_DIGEST(0); + break; default: break; } @@ -905,6 +916,21 @@ protonode : nodetype APPEND STRING TO STRING marked { free($3); proto->lateconnect++; } + | nodetype EXPECT digest mark { + if (node.type != NODE_TYPE_URL) { + yyerror("digest not supported for this type"); + free($3.digest); + YYERROR; + } + node.action = NODE_ACTION_EXPECT; + node.key = strdup($3.digest); + node.flags |= PNFLAG_LOOKUP_DIGEST($3.type); + node.value = strdup("*"); + if (node.key == NULL || node.value == NULL) + fatal("out of memory"); + free($3.digest); + proto->lateconnect++; + } | nodetype FILTER STRING FROM STRING mark { node.action = NODE_ACTION_FILTER; node.key = strdup($5); @@ -924,6 +950,21 @@ protonode : nodetype APPEND STRING TO STRING marked { free($3); proto->lateconnect++; } + | nodetype FILTER digest mark { + if (node.type != NODE_TYPE_URL) { + yyerror("digest not supported for this type"); + free($3.digest); + YYERROR; + } + node.action = NODE_ACTION_FILTER; + node.key = strdup($3.digest); + node.flags |= PNFLAG_LOOKUP_DIGEST($3.type); + node.value = strdup("*"); + if (node.key == NULL || node.value == NULL) + fatal("out of memory"); + free($3.digest); + proto->lateconnect++; + } | nodetype HASH STRING marked { node.action = NODE_ACTION_HASH; node.key = strdup($3); @@ -963,6 +1004,7 @@ nodetype : HEADER { proto->flags |= F_LOOKUP_PATH; node.type = NODE_TYPE_PATH; } + | URL { node.type = NODE_TYPE_URL; } ; sslcache : NUMBER { @@ -1349,6 +1391,7 @@ lookup(char *s) { "timeout", TIMEOUT }, { "to", TO }, { "updates", UPDATES }, + { "url", URL }, { "virtual", VIRTUAL } }; const struct keywords *p; diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c index 10c2fbc75f6..466e17323f6 100644 --- a/usr.sbin/relayd/relay.c +++ b/usr.sbin/relayd/relay.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relay.c,v 1.64 2007/11/21 20:41:40 reyk Exp $ */ +/* $OpenBSD: relay.c,v 1.65 2007/11/22 10:09:53 reyk Exp $ */ /* * Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org> @@ -91,6 +91,8 @@ int relay_handle_http(struct ctl_relay_event *, struct protonode *, struct protonode *, struct protonode *, int); void relay_read_http(struct bufferevent *, void *); +int relay_lookup_url(struct ctl_relay_event *, + const char *, enum digest_type); int relay_lookup_query(struct ctl_relay_event *); int relay_lookup_cookie(struct ctl_relay_event *, const char *); void relay_read_httpcontent(struct bufferevent *, void *); @@ -284,6 +286,7 @@ void relay_nodedebug(const char *name, struct protonode *pn) { const char *s; + int digest; if (pn->action == NODE_ACTION_NONE) return; @@ -303,6 +306,9 @@ relay_nodedebug(const char *name, struct protonode *pn) case NODE_TYPE_PATH: fprintf(stderr, "path "); break; + case NODE_TYPE_URL: + fprintf(stderr, "url "); + break; } switch (pn->action) { @@ -321,8 +327,10 @@ relay_nodedebug(const char *name, struct protonode *pn) case NODE_ACTION_EXPECT: case NODE_ACTION_FILTER: s = pn->action == NODE_ACTION_EXPECT ? "expect" : "filter"; + digest = pn->flags & PNFLAG_LOOKUP_URL_DIGEST; if (strcmp(pn->value, "*") == 0) - fprintf(stderr, "%s \"%s\"", s, pn->key); + fprintf(stderr, "%s %s\"%s\"", s, + digest ? "digest " : "", pn->key); else fprintf(stderr, "%s \"%s\" from \"%s\"", s, pn->value, pn->key); @@ -1378,7 +1386,24 @@ relay_read_http(struct bufferevent *bev, void *arg) if (cre->dir == RELAY_DIR_RESPONSE) goto handle; - if (pn->flags & PNFLAG_LOOKUP_QUERY) { + if (pn->flags & PNFLAG_LOOKUP_URL) { + /* + * Lookup the URL of type example.com/path?args. + * Either as a plain string or SHA1/MD5 digest. + */ + if ((pn->flags & PNFLAG_LOOKUP_DIGEST(0)) && + relay_lookup_url(cre, pk.value, + DIGEST_NONE) == PN_FAIL) + goto abort; + if ((pn->flags & PNFLAG_LOOKUP_DIGEST(DIGEST_SHA1)) && + relay_lookup_url(cre, pk.value, + DIGEST_SHA1) == PN_FAIL) + goto abort; + if ((pn->flags & PNFLAG_LOOKUP_DIGEST(DIGEST_MD5)) && + relay_lookup_url(cre, pk.value, + DIGEST_MD5) == PN_FAIL) + goto abort; + } else if (pn->flags & PNFLAG_LOOKUP_QUERY) { /* Lookup the HTTP query arguments */ if (relay_lookup_query(cre) == PN_FAIL) goto abort; @@ -1476,6 +1501,60 @@ relay_read_http(struct bufferevent *bev, void *arg) } int +relay_lookup_url(struct ctl_relay_event *cre, const char *str, + enum digest_type type) +{ + struct session *con = (struct session *)cre->con; + struct protonode *proot, *pnv, pkv; + char *val, *md = NULL; + int ret = PN_FAIL; + + if (cre->path == NULL) + return (PN_PASS); + + if (asprintf(&val, "%s%s%s%s", + str, cre->path, + cre->args == NULL ? "" : "?", + cre->args == NULL ? "" : cre->args) == -1) { + relay_close_http(con, 500, "failed to allocate URL"); + return (PN_FAIL); + } + + switch (type) { + case DIGEST_SHA1: + case DIGEST_MD5: + if ((md = digeststr(type, val, strlen(val), NULL)) == NULL) { + relay_close_http(con, 500, "failed to allocate digest"); + goto fail; + } + pkv.key = md; + break; + case DIGEST_NONE: + pkv.key = val; + break; + } + pkv.type = NODE_TYPE_URL; + pkv.value = ""; + + if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL) + goto done; + + PROTONODE_FOREACH(pnv, proot, entry) { + ret = relay_handle_http(cre, proot, pnv, &pkv, 0); + if (ret == PN_FAIL) + goto done; + } + + done: + ret = PN_PASS; + fail: + if (md != NULL) + free(md); + free(val); + return (ret); +} + +int relay_lookup_query(struct ctl_relay_event *cre) { struct session *con = (struct session *)cre->con; diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5 index 844e92c0fd9..23cf9c0f026 100644 --- a/usr.sbin/relayd/relayd.conf.5 +++ b/usr.sbin/relayd/relayd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: relayd.conf.5,v 1.62 2007/11/21 20:24:28 reyk Exp $ +.\" $OpenBSD: relayd.conf.5,v 1.63 2007/11/22 10:09:53 reyk Exp $ .\" .\" Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org> .\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: November 21 2007 $ +.Dd $Mdocdate: November 22 2007 $ .Dt HOSTSTATED.CONF 5 .Os .Sh NAME @@ -553,7 +553,7 @@ will match the path of the requested URL without the hostname and query and the value will match the complete query, for example: .Bd -literal -offset indent -request path filter "*" from "/index.html" +request path filter "/index.html" request path filter "foo=bar*" from "/cgi-bin/t.cgi" .Ed .It Ic query @@ -567,6 +567,18 @@ for example: # Will match /cgi-bin/example.pl?foo=bar&ok=yes request query expect "bar" from "foo" .Ed +.It Ic url +Look up the entity as an URL suffix/prefix expression consisting of a +host name or suffix and a path name or prefix when using the +.Ic http +protocol. +This type is only available with the direction +.Ic request , +for example: +.Bd -literal -offset indent +request url filter "example.com/index.html" +request url filter "example.com/test.cgi?val=1" +.Ed .El .Pp The following actions are available: @@ -604,6 +616,7 @@ If the entity is not present or the value doesn't match, the connection will be dropped. .It Xo .Ic expect +.Op Ic digest .Ar key .Xc Expect an entity @@ -611,6 +624,18 @@ Expect an entity with any possible value. This is the short form of .Ic expect Ar * Ic from Ar key . +.Pp +If the +.Ic digest +keyword is specified, +compare the message digest of the entity against the defined string. +The algorithm used is determined by the string length of the +.Ar key +argument, either SHA1 (40 characters) or MD5 (32 characters). +To compute the digest, use this simple command: +.Bd -literal -offset indent +echo -n "example.com/path/?args" | sha1 +.Ed .It Ic filter Ar value Ic from Ar key Like the .Ic expect Ar .. Ic from @@ -620,6 +645,7 @@ and a matching .Ar value . .It Xo .Ic filter +.Op Ic digest .Ar key .Xc Like the diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h index f3642a3d645..b016a3a5283 100644 --- a/usr.sbin/relayd/relayd.h +++ b/usr.sbin/relayd/relayd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.h,v 1.80 2007/11/21 20:28:38 reyk Exp $ */ +/* $OpenBSD: relayd.h,v 1.81 2007/11/22 10:09:53 reyk Exp $ */ /* * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -437,7 +437,8 @@ enum nodetype { NODE_TYPE_HEADER = 0, NODE_TYPE_QUERY = 1, NODE_TYPE_COOKIE = 2, - NODE_TYPE_PATH = 3 + NODE_TYPE_PATH = 3, + NODE_TYPE_URL = 4 }; #define PNFLAG_MACRO 0x01 @@ -445,6 +446,9 @@ enum nodetype { #define PNFLAG_LOG 0x04 #define PNFLAG_LOOKUP_QUERY 0x08 #define PNFLAG_LOOKUP_COOKIE 0x10 +#define PNFLAG_LOOKUP_URL 0xe0 +#define PNFLAG_LOOKUP_URL_DIGEST 0xc0 +#define PNFLAG_LOOKUP_DIGEST(x) (0x20 << x) enum noderesult { PN_DROP = 0, |