untrusted comment: signature from openbsd 5.9 base secret key
RWQJVNompF3pwf/qINbfnP1TI/AeY3OwUNr+PYljxuvihfhmZTafsVbEMi4ahLOgBpgbf1ews7hM1fOwVXsH3q2AWcnmQGDVhwY=
OpenBSD 5.9 errata 21, Jul 25, 2016:
When signaling an error to an HTTP relay client, the connection can be
terminated prematurely, leading to a crash.
Apply by doing:
signify -Vep /etc/signify/openbsd-59-base.pub -x 021_relayd.patch.sig \
-m - | (cd /usr/src && patch -p0)
And then rebuild and install relayd:
cd /usr/src/usr.sbin/relayd
make obj
make depend
make
make install
Index: usr.sbin/relayd/relay_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay_http.c,v
retrieving revision 1.55
diff -u -p -r1.55 relay_http.c
--- usr.sbin/relayd/relay_http.c 15 Dec 2015 10:36:59 -0000 1.55
+++ usr.sbin/relayd/relay_http.c 21 Jul 2016 11:28:14 -0000
@@ -349,10 +349,20 @@ relay_read_http(struct bufferevent *bev,
}
action = relay_test(proto, cre);
- if (action == RES_FAIL) {
+ switch (action) {
+ case RES_FAIL:
relay_close(con, "filter rule failed");
return;
- } else if (action != RES_PASS) {
+ case RES_BAD:
+ relay_abort_http(con, 400, "Bad Request",
+ con->se_label);
+ return;
+ case RES_INTERNAL:
+ relay_abort_http(con, 500, "Internal Server Error",
+ con->se_label);
+ return;
+ }
+ if (action != RES_PASS) {
relay_abort_http(con, 403, "Forbidden", con->se_label);
return;
}
@@ -698,7 +708,6 @@ _relay_lookup_url(struct ctl_relay_event
int
relay_lookup_url(struct ctl_relay_event *cre, const char *host, struct kv *kv)
{
- struct rsession *con = cre->con;
struct http_descriptor *desc = (struct http_descriptor *)cre->desc;
int i, j, dots;
char *hi[RELAY_MAXLOOKUPLEVELS], *p, *pp, *c, ch;
@@ -714,13 +723,12 @@ relay_lookup_url(struct ctl_relay_event
* developers_guide.html#PerformingLookups
*/
- DPRINTF("%s: session %d: host '%s', path '%s', query '%s'",
- __func__, con->se_id, host, desc->http_path,
+ DPRINTF("%s: host '%s', path '%s', query '%s'",
+ __func__, host, desc->http_path,
desc->http_query == NULL ? "" : desc->http_query);
if (canonicalize_host(host, ph, sizeof(ph)) == NULL) {
- relay_abort_http(con, 400, "invalid host name", 0);
- return (RES_FAIL);
+ return (RES_BAD);
}
bzero(hi, sizeof(hi));
@@ -735,8 +743,7 @@ relay_lookup_url(struct ctl_relay_event
hi[dots] = ph;
if ((pp = strdup(desc->http_path)) == NULL) {
- relay_abort_http(con, 500, "failed to allocate path", 0);
- return (RES_FAIL);
+ return (RES_INTERNAL);
}
for (i = (RELAY_MAXLOOKUPLEVELS - 1); i >= 0; i--) {
if (hi[i] == NULL)
@@ -778,13 +785,11 @@ int
relay_lookup_cookie(struct ctl_relay_event *cre, const char *str,
struct kv *kv)
{
- struct rsession *con = cre->con;
char *val, *ptr, *key, *value;
int ret;
if ((val = strdup(str)) == NULL) {
- relay_abort_http(con, 500, "failed to allocate cookie", 0);
- return (RES_FAIL);
+ return (RES_INTERNAL);
}
for (ptr = val; ptr != NULL && strlen(ptr);) {
@@ -810,9 +815,8 @@ relay_lookup_cookie(struct ctl_relay_eve
if (value[strlen(value) - 1] == '"')
value[strlen(value) - 1] = '\0';
- DPRINTF("%s: session %d: %s = %s, %s = %s : %d",
- __func__, con->se_id,
- key, value, kv->kv_key, kv->kv_value,
+ DPRINTF("%s: key %s = %s, %s = %s : %d",
+ __func__, key, value, kv->kv_key, kv->kv_value,
strcasecmp(kv->kv_key, key));
if (strcasecmp(kv->kv_key, key) == 0 &&
@@ -842,8 +846,7 @@ relay_lookup_query(struct ctl_relay_even
if (desc->http_query == NULL)
return (-1);
if ((val = strdup(desc->http_query)) == NULL) {
- relay_abort_http(cre->con, 500, "failed to allocate query", 0);
- return (-1);
+ return (RES_INTERNAL);
}
ptr = val;
@@ -1228,13 +1231,14 @@ relay_httpquery_test(struct ctl_relay_ev
struct http_descriptor *desc = cre->desc;
struct kv *match = &desc->http_matchquery;
struct kv *kv = &rule->rule_kv[KEY_TYPE_QUERY];
+ int res = 0;
if (cre->dir == RELAY_DIR_RESPONSE || kv->kv_type != KEY_TYPE_QUERY)
return (0);
else if (kv->kv_key == NULL)
return (0);
- else if (relay_lookup_query(cre, kv))
- return (-1);
+ else if ((res = relay_lookup_query(cre, kv)) != 0)
+ return (res);
relay_match(actions, kv, match, NULL);
@@ -1309,6 +1313,7 @@ relay_httpurl_test(struct ctl_relay_even
struct kv *host, key;
struct kv *kv = &rule->rule_kv[KEY_TYPE_URL];
struct kv *match = &desc->http_pathquery;
+ int res;
if (cre->dir == RELAY_DIR_RESPONSE || kv->kv_type != KEY_TYPE_URL ||
kv->kv_key == NULL)
@@ -1323,9 +1328,8 @@ relay_httpurl_test(struct ctl_relay_even
kv->kv_option == KEY_OPTION_LOG &&
fnmatch(kv->kv_key, match->kv_key, FNM_CASEFOLD) != FNM_NOMATCH) {
/* fnmatch url only for logging */
- } else if (relay_lookup_url(cre, host->kv_value, kv) != 0)
- return (-1);
-
+ } else if ((res = relay_lookup_url(cre, host->kv_value, kv)) != 0)
+ return (res);
relay_match(actions, kv, match, NULL);
return (0);
@@ -1338,6 +1342,7 @@ relay_httpcookie_test(struct ctl_relay_e
struct http_descriptor *desc = cre->desc;
struct kv *kv = &rule->rule_kv[KEY_TYPE_COOKIE], key;
struct kv *match = NULL;
+ int res;
if (kv->kv_type != KEY_TYPE_COOKIE)
return (0);
@@ -1364,8 +1369,9 @@ relay_httpcookie_test(struct ctl_relay_e
return (-1);
if (kv->kv_key == NULL || match->kv_value == NULL)
return (0);
- else if (relay_lookup_cookie(cre, match->kv_value, kv) != 0)
- return (-1);
+ else if ((res = relay_lookup_cookie(cre, match->kv_value,
+ kv)) != 0)
+ return (res);
}
relay_match(actions, kv, match, &desc->http_headers);
@@ -1640,6 +1646,7 @@ relay_test(struct protocol *proto, struc
u_int action = RES_PASS;
struct kvlist actions, matches;
struct kv *kv;
+ int res = 0;
con = cre->con;
TAILQ_INIT(&actions);
@@ -1647,8 +1654,10 @@ relay_test(struct protocol *proto, struc
r = TAILQ_FIRST(&proto->rules);
while (r != NULL) {
cnt++;
+
TAILQ_INIT(&matches);
TAILQ_INIT(&r->rule_kvlist);
+
if (r->rule_dir && r->rule_dir != cre->dir)
RELAY_GET_SKIP_STEP(RULE_SKIP_DIR);
else if (proto->type != r->rule_proto)
@@ -1669,13 +1678,13 @@ relay_test(struct protocol *proto, struc
RELAY_GET_NEXT_STEP;
else if (relay_httpheader_test(cre, r, &matches) != 0)
RELAY_GET_NEXT_STEP;
- else if (relay_httpquery_test(cre, r, &matches) != 0)
+ else if ((res = relay_httpquery_test(cre, r, &matches)) != 0)
RELAY_GET_NEXT_STEP;
else if (relay_httppath_test(cre, r, &matches) != 0)
RELAY_GET_NEXT_STEP;
- else if (relay_httpurl_test(cre, r, &matches) != 0)
+ else if ((res = relay_httpurl_test(cre, r, &matches)) != 0)
RELAY_GET_NEXT_STEP;
- else if (relay_httpcookie_test(cre, r, &matches) != 0)
+ else if ((res = relay_httpcookie_test(cre, r, &matches)) != 0)
RELAY_GET_NEXT_STEP;
else {
DPRINTF("%s: session %d: matched rule %d",
@@ -1708,12 +1717,16 @@ relay_test(struct protocol *proto, struc
nextrule:
/* Continue to find last matching policy */
- r = TAILQ_NEXT(r, rule_entry);
+ DPRINTF("%s: session %d, res %d", __func__,
+ con->se_id, res);
+ if (res == RES_BAD || res == RES_INTERNAL)
+ return(res);
+ res = 0;
+ r = TAILQ_NEXT(r, rule_entry);
}
}
- if (rule != NULL &&
- relay_match_actions(cre, rule, NULL, &actions) != 0) {
+ if (rule != NULL && relay_match_actions(cre, rule, NULL, &actions) != 0) {
/* Something bad happened, drop */
action = RES_DROP;
}
Index: usr.sbin/relayd/relayd.h
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.222
diff -u -p -r1.222 relayd.h
--- usr.sbin/relayd/relayd.h 11 Jan 2016 21:31:42 -0000 1.222
+++ usr.sbin/relayd/relayd.h 21 Jul 2016 11:28:14 -0000
@@ -583,7 +583,9 @@ enum prototype {
enum relay_result {
RES_DROP = 0,
RES_PASS = 1,
- RES_FAIL = -1
+ RES_FAIL = -1,
+ RES_BAD = -2,
+ RES_INTERNAL = -3
};
enum rule_action {