summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorreyk <reyk@openbsd.org>2015-02-07 01:23:12 +0000
committerreyk <reyk@openbsd.org>2015-02-07 01:23:12 +0000
commitf8932becc4217638045512ac30c17ed5f658d036 (patch)
tree11911a3276f17eb8e39fd0005a6aacb274328d75
parentNew framework that allows hibernate to pass in entropy from it's fresh (diff)
downloadwireguard-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.c32
-rw-r--r--usr.sbin/httpd/httpd.conf.536
-rw-r--r--usr.sbin/httpd/httpd.h10
-rw-r--r--usr.sbin/httpd/parse.y60
-rw-r--r--usr.sbin/httpd/server.c3
-rw-r--r--usr.sbin/httpd/server_http.c13
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);