diff options
author | 2015-02-07 01:23:12 +0000 | |
---|---|---|
committer | 2015-02-07 01:23:12 +0000 | |
commit | f8932becc4217638045512ac30c17ed5f658d036 (patch) | |
tree | 11911a3276f17eb8e39fd0005a6aacb274328d75 | |
parent | New framework that allows hibernate to pass in entropy from it's fresh (diff) | |
download | wireguard-openbsd-f8932becc4217638045512ac30c17ed5f658d036.tar.xz wireguard-openbsd-f8932becc4217638045512ac30c17ed5f658d036.zip |
Add support for blocking, dropping, and redirecting requests.
OK florian@
-rw-r--r-- | usr.sbin/httpd/config.c | 32 | ||||
-rw-r--r-- | usr.sbin/httpd/httpd.conf.5 | 36 | ||||
-rw-r--r-- | usr.sbin/httpd/httpd.h | 10 | ||||
-rw-r--r-- | usr.sbin/httpd/parse.y | 60 | ||||
-rw-r--r-- | usr.sbin/httpd/server.c | 3 | ||||
-rw-r--r-- | usr.sbin/httpd/server_http.c | 13 |
6 files changed, 143 insertions, 11 deletions
diff --git a/usr.sbin/httpd/config.c b/usr.sbin/httpd/config.c index 2cf17e64675..e3dd94f0148 100644 --- a/usr.sbin/httpd/config.c +++ b/usr.sbin/httpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.33 2015/02/05 10:46:17 reyk Exp $ */ +/* $OpenBSD: config.c,v 1.34 2015/02/07 01:23:12 reyk Exp $ */ /* * Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org> @@ -189,6 +189,10 @@ config_setserver(struct httpd *env, struct server *srv) c = 0; iov[c].iov_base = &s; iov[c++].iov_len = sizeof(s); + if (srv->srv_conf.return_uri_len != 0) { + iov[c].iov_base = srv->srv_conf.return_uri; + iov[c++].iov_len = srv->srv_conf.return_uri_len; + } if (srv->srv_conf.tls_cert_len != 0) { iov[c].iov_base = srv->srv_conf.tls_cert; iov[c++].iov_len = srv->srv_conf.tls_cert_len; @@ -246,12 +250,14 @@ config_getserver_config(struct httpd *env, struct server *srv, struct server_config *srv_conf, *parent; u_int8_t *p = imsg->data; u_int f; + size_t s; if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL) return (-1); IMSG_SIZE_CHECK(imsg, srv_conf); memcpy(srv_conf, p, sizeof(*srv_conf)); + s = sizeof(*srv_conf); /* Reset these variables to avoid free'ing invalid pointers */ serverconfig_reset(srv_conf); @@ -336,6 +342,24 @@ config_getserver_config(struct httpd *env, struct server *srv, sizeof(srv_conf->errorlog)); } + f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK; + if ((srv_conf->flags & f) == 0) { + srv_conf->flags |= parent->flags & f; + srv_conf->return_code = parent->return_code; + srv_conf->return_uri_len = parent->return_uri_len; + if (srv_conf->return_uri_len && + (srv_conf->return_uri = + strdup(parent->return_uri)) == NULL) + goto fail; + } else { + if (srv_conf->return_uri_len != 0) { + if ((srv_conf->return_uri = get_data(p + s, + srv_conf->return_uri_len)) == NULL) + goto fail; + s += srv_conf->return_uri_len; + } + } + memcpy(&srv_conf->timeout, &parent->timeout, sizeof(srv_conf->timeout)); srv_conf->maxrequests = parent->maxrequests; @@ -426,6 +450,12 @@ config_getserver(struct httpd *env, struct imsg *imsg) srv->srv_conf.name, srv->srv_conf.id, printb_flags(srv->srv_conf.flags, SRVFLAG_BITS)); + if (srv->srv_conf.return_uri_len != 0) { + if ((srv->srv_conf.return_uri = get_data(p + s, + srv->srv_conf.return_uri_len)) == NULL) + goto fail; + s += srv->srv_conf.return_uri_len; + } if (srv->srv_conf.tls_cert_len != 0) { if ((srv->srv_conf.tls_cert = get_data(p + s, srv->srv_conf.tls_cert_len)) == NULL) diff --git a/usr.sbin/httpd/httpd.conf.5 b/usr.sbin/httpd/httpd.conf.5 index f40273ce8fb..d5afe6de15c 100644 --- a/usr.sbin/httpd/httpd.conf.5 +++ b/usr.sbin/httpd/httpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: httpd.conf.5,v 1.47 2015/01/19 19:37:50 reyk Exp $ +.\" $OpenBSD: httpd.conf.5,v 1.48 2015/02/07 01:23:12 reyk Exp $ .\" .\" Copyright (c) 2014, 2015 Reyk Floeter <reyk@openbsd.org> .\" @@ -14,7 +14,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: January 19 2015 $ +.Dd $Mdocdate: February 7 2015 $ .Dt HTTPD.CONF 5 .Os .Sh NAME @@ -150,6 +150,20 @@ and must be readable by the www user. Use the .Ic no authenticate directive to disable authentication in a location. +.It Ic block drop +Drop the connection without sending an error page. +.It Ic block Op Ic return Ar code Op uri +Close the connection and send an error page. +If the optional return code is not specified, +.Xr httpd 8 +denies access with a +.Sq 404 Forbidden +response. +The optional +.Ar uri +argument can be used with return codes in the 3xx range to send a +.Sq Location: +header for redirection to a specified URI. .It Ic connection Ar option Set the specified options and limits for HTTP connections. Valid options are: @@ -261,6 +275,10 @@ Enable or disable logging to .Xr syslog 3 instead of the log files. .El +.It Ic pass +Disable any previous +.Ic block +in a location. .It Ic root Ar option Configure the document root and options for the request path. Valid options are: @@ -440,6 +458,20 @@ server "intranet.example.com" { } .Ed .Pp +Simple redirections can be configured with the +.Ic block +directive: +.Bd -literal -offset indent +server "example.com" { + listen on 10.0.0.1 port 80 + block return 301 "http://www.example.com/" +} + +server "www.example.com" { + listen on 10.0.0.1 port 80 +} +.Ed +.Pp The syntax of the types section is also compatible with the format used by nginx, so it is possible to include its .Pa mime.types diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h index 9573fc4d491..d2f64699470 100644 --- a/usr.sbin/httpd/httpd.h +++ b/usr.sbin/httpd/httpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.h,v 1.74 2015/02/06 13:05:20 reyk Exp $ */ +/* $OpenBSD: httpd.h,v 1.75 2015/02/07 01:23:12 reyk Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org> @@ -337,12 +337,14 @@ SPLAY_HEAD(client_tree, client); #define SRVFLAG_ERROR_LOG 0x00008000 #define SRVFLAG_AUTH 0x00010000 #define SRVFLAG_NO_AUTH 0x00020000 +#define SRVFLAG_BLOCK 0x00040000 +#define SRVFLAG_NO_BLOCK 0x00080000 #define SRVFLAG_BITS \ "\10\01INDEX\02NO_INDEX\03AUTO_INDEX\04NO_AUTO_INDEX" \ "\05ROOT\06LOCATION\07FCGI\10NO_FCGI\11LOG\12NO_LOG\13SOCKET" \ "\14SYSLOG\15NO_SYSLOG\16TLS\17ACCESS_LOG\20ERROR_LOG" \ - "\21AUTH\22NO_AUTH" + "\21AUTH\22NO_AUTH\23BLOCK\24NO_BLOCK" #define TCPFLAG_NODELAY 0x01 #define TCPFLAG_NNODELAY 0x02 @@ -421,6 +423,10 @@ struct server_config { u_int32_t auth_id; struct auth *auth; + int return_code; + char *return_uri; + off_t return_uri_len; + TAILQ_ENTRY(server_config) entry; }; TAILQ_HEAD(serverhosts, server_config); diff --git a/usr.sbin/httpd/parse.y b/usr.sbin/httpd/parse.y index 53cf124c1f3..daf61c2055d 100644 --- a/usr.sbin/httpd/parse.y +++ b/usr.sbin/httpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.60 2015/02/06 13:05:20 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.61 2015/02/07 01:23:12 reyk Exp $ */ /* * Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org> @@ -133,13 +133,13 @@ typedef struct { %token COMBINED CONNECTION DIRECTORY ERR FCGI INDEX IP KEY LISTEN LOCATION %token LOG LOGDIR MAXIMUM NO NODELAY ON PORT PREFORK REQUEST REQUESTS ROOT %token SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TIMEOUT TLS TYPES -%token ERROR INCLUDE AUTHENTICATE WITH +%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS %token <v.string> STRING %token <v.number> NUMBER %type <v.port> port %type <v.number> opttls %type <v.tv> timeout -%type <v.string> numberstring +%type <v.string> numberstring optstring %type <v.auth> authopts %% @@ -439,6 +439,7 @@ serveroptsl : LISTEN ON STRING opttls port { | logformat | fastcgi | authenticate + | filter | LOCATION STRING { struct server *s; @@ -798,6 +799,50 @@ logstyle : COMMON { } ; +filter : block RETURN NUMBER optstring { + if ($3 <= 0 || server_httperror_byid($3) == NULL) { + yyerror("invalid return code: %lld", $3); + free($4); + YYERROR; + } + srv_conf->return_code = $3; + + if ($4 != NULL) { + /* Only for 3xx redirection headers */ + if ($3 < 300 || $3 > 399) { + yyerror("invalid return code for " + "location URI"); + free($4); + YYERROR; + } + srv_conf->return_uri = $4; + srv_conf->return_uri_len = strlen($4) + 1; + } + } + | block DROP { + /* No return code, silently drop the connection */ + srv_conf->return_code = 0; + } + | block { + /* Forbidden */ + srv_conf->return_code = 403; + } + | PASS { + srv_conf->flags &= ~SRVFLAG_BLOCK; + srv_conf->flags |= SRVFLAG_NO_BLOCK; + } + ; + +block : BLOCK { + srv_conf->flags &= ~SRVFLAG_NO_BLOCK; + srv_conf->flags |= SRVFLAG_BLOCK; + } + ; + +optstring : /* empty */ { $$ = NULL; } + | STRING { $$ = $1; } + ; + tcpip : TCP '{' optnl tcpflags_l '}' | TCP tcpflags ; @@ -995,6 +1040,7 @@ lookup(char *s) { "authenticate", AUTHENTICATE}, { "auto", AUTO }, { "backlog", BACKLOG }, + { "block", BLOCK }, { "body", BODY }, { "buffer", BUFFER }, { "certificate", CERTIFICATE }, @@ -1004,6 +1050,7 @@ lookup(char *s) { "common", COMMON }, { "connection", CONNECTION }, { "directory", DIRECTORY }, + { "drop", DROP }, { "error", ERR }, { "fastcgi", FCGI }, { "include", INCLUDE }, @@ -1018,10 +1065,12 @@ lookup(char *s) { "no", NO }, { "nodelay", NODELAY }, { "on", ON }, + { "pass", PASS }, { "port", PORT }, { "prefork", PREFORK }, { "request", REQUEST }, { "requests", REQUESTS }, + { "return", RETURN }, { "root", ROOT }, { "sack", SACK }, { "server", SERVER }, @@ -1810,6 +1859,11 @@ server_inherit(struct server *src, const char *name, dst->srv_conf.tls_cert = NULL; dst->srv_conf.tls_key = NULL; + if (src->srv_conf.return_uri != NULL && + (dst->srv_conf.return_uri = + strdup(src->srv_conf.return_uri)) == NULL) + fatal("out of memory"); + dst->srv_conf.id = ++last_server_id; dst->srv_conf.parent_id = dst->srv_conf.id; dst->srv_s = -1; diff --git a/usr.sbin/httpd/server.c b/usr.sbin/httpd/server.c index 15e14539a27..46f2e5cc73b 100644 --- a/usr.sbin/httpd/server.c +++ b/usr.sbin/httpd/server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server.c,v 1.54 2015/01/21 22:21:05 reyk Exp $ */ +/* $OpenBSD: server.c,v 1.55 2015/02/07 01:23:12 reyk Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org> @@ -324,6 +324,7 @@ server_purge(struct server *srv) void serverconfig_free(struct server_config *srv_conf) { + free(srv_conf->return_uri); free(srv_conf->tls_cert_file); free(srv_conf->tls_cert); free(srv_conf->tls_key_file); diff --git a/usr.sbin/httpd/server_http.c b/usr.sbin/httpd/server_http.c index 7c1fc383851..d5acb05737f 100644 --- a/usr.sbin/httpd/server_http.c +++ b/usr.sbin/httpd/server_http.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_http.c,v 1.71 2015/02/06 13:05:20 reyk Exp $ */ +/* $OpenBSD: server_http.c,v 1.72 2015/02/07 01:23:12 reyk Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org> @@ -736,6 +736,11 @@ server_abort_http(struct client *clt, u_int code, const char *msg) char tmbuf[32], hbuf[128]; int bodylen; + if (code == 0) { + server_close(clt, "dropped"); + return; + } + if ((httperr = server_httperror_byid(code)) == NULL) httperr = "Unknown Error"; @@ -957,7 +962,11 @@ server_response(struct httpd *httpd, struct client *clt) /* Now search for the location */ srv_conf = server_getlocation(clt, desc->http_path); - if (srv_conf->flags & SRVFLAG_AUTH && + if (srv_conf->flags & SRVFLAG_BLOCK) { + server_abort_http(clt, srv_conf->return_code, + srv_conf->return_uri); + return (-1); + } else if (srv_conf->flags & SRVFLAG_AUTH && server_http_authenticate(srv_conf, clt) == -1) { server_abort_http(clt, 401, srv_conf->auth_realm); return (-1); |