summaryrefslogtreecommitdiffstats
path: root/usr.sbin/httpd
diff options
context:
space:
mode:
authorreyk <reyk@openbsd.org>2018-06-20 16:43:05 +0000
committerreyk <reyk@openbsd.org>2018-06-20 16:43:05 +0000
commit93038d1479fc7fdf286bf094a46e02a710e8b624 (patch)
treecdedf3274c0f717807a192c9d0f31804f4e34cbf /usr.sbin/httpd
parentmake it possible to do @tag sthg in the same package that does (diff)
downloadwireguard-openbsd-93038d1479fc7fdf286bf094a46e02a710e8b624.tar.xz
wireguard-openbsd-93038d1479fc7fdf286bf094a46e02a710e8b624.zip
Add support for simple one-off internal rewrites.
For example: location match "/page/(%d+)/.*" { request rewrite "/static/index.php?id=%1&$QUERY_STRING" } Requested by many. Ok benno@
Diffstat (limited to 'usr.sbin/httpd')
-rw-r--r--usr.sbin/httpd/config.c9
-rw-r--r--usr.sbin/httpd/httpd.conf.536
-rw-r--r--usr.sbin/httpd/httpd.h9
-rw-r--r--usr.sbin/httpd/parse.y23
-rw-r--r--usr.sbin/httpd/server_http.c51
5 files changed, 110 insertions, 18 deletions
diff --git a/usr.sbin/httpd/config.c b/usr.sbin/httpd/config.c
index 42ff4a44b51..0b8c251bc3e 100644
--- a/usr.sbin/httpd/config.c
+++ b/usr.sbin/httpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.54 2018/05/19 13:56:56 jsing Exp $ */
+/* $OpenBSD: config.c,v 1.55 2018/06/20 16:43:05 reyk Exp $ */
/*
* Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -476,6 +476,13 @@ config_getserver_config(struct httpd *env, struct server *srv,
&parent->default_type, sizeof(struct media_type));
}
+ f = SRVFLAG_PATH_REWRITE|SRVFLAG_NO_PATH_REWRITE;
+ if ((srv_conf->flags & f) == 0) {
+ srv_conf->flags |= parent->flags & f;
+ (void)strlcpy(srv_conf->path, parent->path,
+ sizeof(srv_conf->path));
+ }
+
f = SRVFLAG_SERVER_HSTS;
srv_conf->flags |= parent->flags & f;
srv_conf->hsts_max_age = parent->hsts_max_age;
diff --git a/usr.sbin/httpd/httpd.conf.5 b/usr.sbin/httpd/httpd.conf.5
index 89837dd0088..f47bc479218 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.100 2018/06/18 06:04:25 jmc Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.101 2018/06/20 16:43:05 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: June 18 2018 $
+.Dd $Mdocdate: June 20 2018 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
@@ -198,6 +198,8 @@ argument can be used with return codes in the 3xx range to send a
.Sq Location:
header for redirection to a specified URI.
.Pp
+It is possible to rewrite the request to redirect it to a different
+external location.
The
.Ar uri
may contain predefined macros that will be expanded at runtime:
@@ -396,10 +398,10 @@ the
using pattern matching instead of shell globbing rules,
see
.Xr patterns 7 .
-The pattern may contain captures that can be used in the
-.Ar uri
-of an enclosed
+The pattern may contain captures that can be used in an enclosed
.Ic block return
+or
+.Ic request rewrite
option.
.It Oo Ic no Oc Ic log Op Ar option
Set the specified logging options.
@@ -462,6 +464,19 @@ in a location.
Configure the options for the request path.
Valid options are:
.Bl -tag -width Ds
+.It Oo Ic no Oc Ic rewrite Ar path
+Enable or disable rewriting of the request.
+Unlike the redirection with
+.Ic block return ,
+this will change the request path internally before
+.Nm httpd
+makes a final decision about the matching location.
+The
+.Ar path
+argument may contain predefined macros that will be expanded at runtime.
+See the
+.Ic block return
+option for the list of supported macros.
.It Ic strip Ar number
Strip
.Ar number
@@ -717,6 +732,17 @@ server "www.example.com" {
listen on 10.0.0.1 port 80
}
.Ed
+The request can also be rewritten with the
+.Ic request rewrite
+directive:
+.Bd -literal -offset indent
+server "example.com" {
+ listen on * port 80
+ location match "/old/(.*)" {
+ request rewrite "/new/%1"
+ }
+}
+.Ed
.Sh SEE ALSO
.Xr htpasswd 1 ,
.Xr patterns 7 ,
diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h
index aff1a6c5e2a..907989c9bfa 100644
--- a/usr.sbin/httpd/httpd.h
+++ b/usr.sbin/httpd/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.137 2018/05/19 13:56:56 jsing Exp $ */
+/* $OpenBSD: httpd.h,v 1.138 2018/06/20 16:43:05 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -398,13 +398,15 @@ SPLAY_HEAD(client_tree, client);
#define SRVFLAG_SERVER_MATCH 0x00200000
#define SRVFLAG_SERVER_HSTS 0x00400000
#define SRVFLAG_DEFAULT_TYPE 0x00800000
+#define SRVFLAG_PATH_REWRITE 0x01000000
+#define SRVFLAG_NO_PATH_REWRITE 0x02000000
#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\23BLOCK\24NO_BLOCK\25LOCATION_MATCH" \
- "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE"
+ "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE\31PATH\32NO_PATH"
#define TCPFLAG_NODELAY 0x01
#define TCPFLAG_NNODELAY 0x02
@@ -470,8 +472,9 @@ struct server_config {
uint32_t parent_id;
char name[HOST_NAME_MAX+1];
char location[HTTPD_LOCATION_MAX];
- char index[PATH_MAX];
char root[PATH_MAX];
+ char path[PATH_MAX];
+ char index[PATH_MAX];
char socket[PATH_MAX];
char accesslog[PATH_MAX];
char errorlog[PATH_MAX];
diff --git a/usr.sbin/httpd/parse.y b/usr.sbin/httpd/parse.y
index 0dc283b2705..49beb33a350 100644
--- a/usr.sbin/httpd/parse.y
+++ b/usr.sbin/httpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.102 2018/06/13 15:08:24 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.103 2018/06/20 16:43:05 reyk Exp $ */
/*
* Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -139,7 +139,7 @@ typedef struct {
%token LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON PORT PREFORK
%token PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TICKET
%token TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD REQUEST
-%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS
+%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE
%token CA CLIENT CRL OPTIONAL
%token <v.string> STRING
%token <v.number> NUMBER
@@ -820,7 +820,23 @@ requestflags_l : requestflags optcommanl requestflags_l
| requestflags optnl
;
-requestflags : STRIP NUMBER {
+requestflags : REWRITE STRING {
+ if (strlcpy(srv->srv_conf.path, $2,
+ sizeof(srv->srv_conf.path)) >=
+ sizeof(srv->srv_conf.path)) {
+ yyerror("request path too long");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ srv->srv_conf.flags |= SRVFLAG_PATH_REWRITE;
+ srv->srv_conf.flags &= ~SRVFLAG_NO_PATH_REWRITE;
+ }
+ | NO REWRITE {
+ srv->srv_conf.flags |= SRVFLAG_NO_PATH_REWRITE;
+ srv->srv_conf.flags &= ~SRVFLAG_PATH_REWRITE;
+ }
+ | STRIP NUMBER {
if ($2 < 0 || $2 > INT_MAX) {
yyerror("invalid strip number");
YYERROR;
@@ -1277,6 +1293,7 @@ lookup(char *s)
{ "request", REQUEST },
{ "requests", REQUESTS },
{ "return", RETURN },
+ { "rewrite", REWRITE },
{ "root", ROOT },
{ "sack", SACK },
{ "server", SERVER },
diff --git a/usr.sbin/httpd/server_http.c b/usr.sbin/httpd/server_http.c
index 5ee51b1925f..4c91dea2d16 100644
--- a/usr.sbin/httpd/server_http.c
+++ b/usr.sbin/httpd/server_http.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: server_http.c,v 1.121 2018/06/15 12:36:05 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.122 2018/06/20 16:43:05 reyk Exp $ */
/*
- * Copyright (c) 2006 - 2017 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006 - 2018 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -1170,13 +1170,16 @@ server_response(struct httpd *httpd, struct client *clt)
struct kv *kv, key, *host;
struct str_find sm;
int portval = -1, ret;
- char *hostval;
+ char *hostval, *query;
const char *errstr = NULL;
- /* Canonicalize the request path */
+ /* Decode the URL */
if (desc->http_path == NULL ||
- url_decode(desc->http_path) == NULL ||
- canonicalize_path(desc->http_path, path, sizeof(path)) == NULL)
+ url_decode(desc->http_path) == NULL)
+ goto fail;
+
+ /* Canonicalize the request path */
+ if (canonicalize_path(desc->http_path, path, sizeof(path)) == NULL)
goto fail;
free(desc->http_path);
if ((desc->http_path = strdup(path)) == NULL)
@@ -1280,6 +1283,42 @@ server_response(struct httpd *httpd, struct client *clt)
/* Now search for the location */
srv_conf = server_getlocation(clt, desc->http_path);
+ /* Optional rewrite */
+ if (srv_conf->flags & SRVFLAG_PATH_REWRITE) {
+ /* Expand macros */
+ if (server_expand_http(clt, srv_conf->path,
+ path, sizeof(path)) == NULL)
+ goto fail;
+
+ /*
+ * Reset and update the query. The updated query must already
+ * be URL encoded - either specified by the user or by using the
+ * original $QUERY_STRING.
+ */
+ free(desc->http_query);
+ desc->http_query = NULL;
+ if ((query = strchr(path, '?')) != NULL) {
+ *query++ = '\0';
+ if ((desc->http_query = strdup(query)) == NULL)
+ goto fail;
+ }
+
+ /* Canonicalize the updated request path */
+ if (canonicalize_path(path,
+ path, sizeof(path)) == NULL)
+ goto fail;
+
+ log_debug("%s: rewrote %s -> %s?%s", __func__,
+ desc->http_path, path, desc->http_query);
+
+ free(desc->http_path);
+ if ((desc->http_path = strdup(path)) == NULL)
+ goto fail;
+
+ /* Now search for the updated location */
+ srv_conf = server_getlocation(clt, desc->http_path);
+ }
+
if (srv_conf->flags & SRVFLAG_BLOCK) {
server_abort_http(clt, srv_conf->return_code,
srv_conf->return_uri);