diff options
author | reyk <reyk@openbsd.org> | 2018-06-20 16:43:05 +0000 |
---|---|---|
committer | reyk <reyk@openbsd.org> | 2018-06-20 16:43:05 +0000 |
commit | 93038d1479fc7fdf286bf094a46e02a710e8b624 (patch) | |
tree | cdedf3274c0f717807a192c9d0f31804f4e34cbf /usr.sbin/httpd | |
parent | make it possible to do @tag sthg in the same package that does (diff) | |
download | wireguard-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.c | 9 | ||||
-rw-r--r-- | usr.sbin/httpd/httpd.conf.5 | 36 | ||||
-rw-r--r-- | usr.sbin/httpd/httpd.h | 9 | ||||
-rw-r--r-- | usr.sbin/httpd/parse.y | 23 | ||||
-rw-r--r-- | usr.sbin/httpd/server_http.c | 51 |
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); |