summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2007-11-22 10:09:54 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2007-11-22 10:09:54 +0000
commit528448c354fbc39d0ec76390e0abb03bffe3030c (patch)
treecbb3c2d948302dc744689adcd4383ae90e7ba120 /usr.sbin/relayd
parente7be2a8e9b2bedf33849efda13e890b933152f0b (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.y47
-rw-r--r--usr.sbin/relayd/relay.c85
-rw-r--r--usr.sbin/relayd/relayd.conf.532
-rw-r--r--usr.sbin/relayd/relayd.h8
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,