summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Zimmermann <chrisz@cvs.openbsd.org>2015-01-04 22:23:59 +0000
committerChristopher Zimmermann <chrisz@cvs.openbsd.org>2015-01-04 22:23:59 +0000
commitd1fa0d8334e328d235fa361c0b206e72743efb4e (patch)
treedb6d8eaaaf7b9b0fbf3ff96e545ad50d5a59d1d2
parented8449679004b2c44dd7c0339c9e10794a5a1358 (diff)
add new url stripping option:
strip number Strip number path components from the beginning of the request URI before looking up the stripped-down URI at the document root. reviewed with much patience and OK by reyk@
-rw-r--r--usr.sbin/httpd/httpd.conf.515
-rw-r--r--usr.sbin/httpd/httpd.h5
-rw-r--r--usr.sbin/httpd/parse.y42
-rw-r--r--usr.sbin/httpd/server_fcgi.c29
-rw-r--r--usr.sbin/httpd/server_file.c17
-rw-r--r--usr.sbin/httpd/server_http.c17
6 files changed, 92 insertions, 33 deletions
diff --git a/usr.sbin/httpd/httpd.conf.5 b/usr.sbin/httpd/httpd.conf.5
index ff0152acc2a..b582385ddb7 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.41 2015/01/03 15:49:18 reyk Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.42 2015/01/04 22:23:58 chrisz Exp $
.\"
.\" Copyright (c) 2014 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 3 2015 $
+.Dd $Mdocdate: January 4 2015 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
@@ -250,7 +250,10 @@ Enable or disable logging to
.Xr syslog 3
instead of the log files.
.El
-.It Ic root Ar directory
+.It Ic root Ar option
+Valid options are:
+.Bl -tag -width Ds
+.It Ar directory
Set the document root of the server.
The
.Ar directory
@@ -260,6 +263,12 @@ root directory of
.Nm httpd .
If not specified, it defaults to
.Pa /htdocs .
+.It Ic strip Ar number
+Strip
+.Ar number
+path components from the beginning of the request URI before
+looking up the stripped-down URI at the document root.
+.El
.It Ic tcp Ar option
Enable or disable the specified TCP/IP options; see
.Xr tcp 4
diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h
index 3bcd4b703a3..12aa1a101e9 100644
--- a/usr.sbin/httpd/httpd.h
+++ b/usr.sbin/httpd/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.65 2015/01/02 19:09:52 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.66 2015/01/04 22:23:58 chrisz Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -385,6 +385,7 @@ struct server_config {
char *tls_key_file;
u_int32_t flags;
+ int strip;
u_int8_t tcpflags;
int tcpbufsiz;
int tcpbacklog;
@@ -524,6 +525,8 @@ int server_response_http(struct client *, u_int, struct media_type *,
void server_reset_http(struct client *);
void server_close_http(struct client *);
int server_response(struct httpd *, struct client *);
+const char *
+ server_root_strip(const char *, int);
struct server_config *
server_getlocation(struct client *, const char *);
const char *
diff --git a/usr.sbin/httpd/parse.y b/usr.sbin/httpd/parse.y
index e8f9b1016d2..5a9616c88dc 100644
--- a/usr.sbin/httpd/parse.y
+++ b/usr.sbin/httpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.49 2015/01/03 23:54:25 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.50 2015/01/04 22:23:58 chrisz Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -130,7 +130,7 @@ typedef struct {
%token ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT CIPHERS COMMON
%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 STYLE SYSLOG TCP TIMEOUT TLS TYPES
+%token SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TIMEOUT TLS TYPES
%token ERROR INCLUDE
%token <v.string> STRING
%token <v.number> NUMBER
@@ -434,17 +434,8 @@ serveroptsl : LISTEN ON STRING opttls port {
YYERROR;
}
} tls
- | ROOT STRING {
- if (strlcpy(srv->srv_conf.root, $2,
- sizeof(srv->srv_conf.root)) >=
- sizeof(srv->srv_conf.root)) {
- yyerror("document root too long");
- free($2);
- YYERROR;
- }
- free($2);
- srv->srv_conf.flags |= SRVFLAG_ROOT;
- }
+ | ROOT rootflags
+ | ROOT '{' rootflags_l '}'
| DIRECTORY dirflags
| DIRECTORY '{' dirflags_l '}'
| logformat
@@ -625,6 +616,30 @@ tlsopts : CERTIFICATE STRING {
}
;
+rootflags_l : rootflags comma rootflags_l
+ | rootflags
+ ;
+
+rootflags : STRING {
+ if (strlcpy(srv->srv_conf.root, $1,
+ sizeof(srv->srv_conf.root)) >=
+ sizeof(srv->srv_conf.root)) {
+ yyerror("document root too long");
+ free($1);
+ YYERROR;
+ }
+ free($1);
+ srv->srv_conf.flags |= SRVFLAG_ROOT;
+ }
+ | STRIP NUMBER {
+ if ($2 < 0 || $2 > INT_MAX) {
+ yyerror("invalid strip number");
+ YYERROR;
+ }
+ srv->srv_conf.strip = $2;
+ }
+ ;
+
dirflags_l : dirflags comma dirflags_l
| dirflags
;
@@ -962,6 +977,7 @@ lookup(char *s)
{ "sack", SACK },
{ "server", SERVER },
{ "socket", SOCKET },
+ { "strip", STRIP },
{ "style", STYLE },
{ "syslog", SYSLOG },
{ "tcp", TCP },
diff --git a/usr.sbin/httpd/server_fcgi.c b/usr.sbin/httpd/server_fcgi.c
index 842214e9ccf..a6055cd157e 100644
--- a/usr.sbin/httpd/server_fcgi.c
+++ b/usr.sbin/httpd/server_fcgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_fcgi.c,v 1.43 2014/12/21 00:54:49 guenther Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.44 2015/01/04 22:23:58 chrisz Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
@@ -101,8 +101,8 @@ server_fcgi(struct httpd *env, struct client *clt)
size_t scriptlen;
int pathlen;
int fd = -1, ret;
- const char *errstr = NULL;
- char *str, *p, *script = NULL;
+ const char *stripped, *p, *alias, *errstr = NULL;
+ char *str, *script = NULL;
if (srv_conf->socket[0] == ':') {
struct sockaddr_storage ss;
@@ -190,9 +190,13 @@ server_fcgi(struct httpd *env, struct client *clt)
h->type = FCGI_PARAMS;
h->content_len = param.total_len = 0;
- if ((pathlen = asprintf(&script, "%s%s", srv_conf->root,
- desc->http_path_alias != NULL ?
- desc->http_path_alias : desc->http_path)) == -1) {
+ alias = desc->http_path_alias != NULL
+ ? desc->http_path_alias
+ : desc->http_path;
+
+ stripped = server_root_strip(alias, srv_conf->strip);
+ if ((pathlen = asprintf(&script, "%s%s", srv_conf->root, stripped))
+ == -1) {
errstr = "failed to get script name";
goto fail;
}
@@ -213,8 +217,17 @@ server_fcgi(struct httpd *env, struct client *clt)
script[scriptlen] = '\0';
}
- if (fcgi_add_param(&param, "SCRIPT_NAME",
- script + strlen(srv_conf->root), clt) == -1) {
+ /*
+ * calculate length of http SCRIPT_NAME:
+ * add length of stripped prefix,
+ * subtract length of prepended local root
+ */
+ scriptlen += (stripped - alias) - strlen(srv_conf->root);
+ if ((str = strndup(alias, scriptlen)) == NULL)
+ goto fail;
+ ret = fcgi_add_param(&param, "SCRIPT_NAME", str, clt);
+ free(str);
+ if (ret == -1) {
errstr = "failed to encode param";
goto fail;
}
diff --git a/usr.sbin/httpd/server_file.c b/usr.sbin/httpd/server_file.c
index c2eca71c858..6167bdb2304 100644
--- a/usr.sbin/httpd/server_file.c
+++ b/usr.sbin/httpd/server_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_file.c,v 1.43 2015/01/01 14:15:02 reyk Exp $ */
+/* $OpenBSD: server_file.c,v 1.44 2015/01/04 22:23:58 chrisz Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -150,17 +150,19 @@ server_file(struct httpd *env, struct client *clt)
struct http_descriptor *desc = clt->clt_descreq;
struct server_config *srv_conf = clt->clt_srv_conf;
char path[MAXPATHLEN];
- const char *errstr = NULL;
+ const char *stripped, *errstr = NULL;
int ret = 500;
if (srv_conf->flags & SRVFLAG_FCGI)
return (server_fcgi(env, clt));
/* Request path is already canonicalized */
- if ((size_t)snprintf(path, sizeof(path), "%s%s",
- srv_conf->root,
+ stripped = server_root_strip(
desc->http_path_alias != NULL ?
- desc->http_path_alias : desc->http_path) >= sizeof(path)) {
+ desc->http_path_alias : desc->http_path,
+ srv_conf->strip);
+ if ((size_t)snprintf(path, sizeof(path), "%s%s",
+ srv_conf->root, stripped) >= sizeof(path)) {
errstr = desc->http_path;
goto abort;
}
@@ -276,7 +278,7 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
int code = 500;
struct evbuffer *evb = NULL;
struct media_type *media;
- const char *style;
+ const char *stripped, *style;
struct tm tm;
time_t t, dir_mtime;
@@ -286,8 +288,9 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
}
/* Request path is already canonicalized */
+ stripped = server_root_strip(desc->http_path, srv_conf->strip);
if ((size_t)snprintf(path, sizeof(path), "%s%s",
- srv_conf->root, desc->http_path) >= sizeof(path))
+ srv_conf->root, stripped) >= sizeof(path))
goto abort;
/* Now open the file, should be readable or we have another problem */
diff --git a/usr.sbin/httpd/server_http.c b/usr.sbin/httpd/server_http.c
index 3a5d84e7ada..d83c7b4556a 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.58 2015/01/01 14:15:02 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.59 2015/01/04 22:23:58 chrisz Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -887,6 +887,21 @@ server_response(struct httpd *httpd, struct client *clt)
return (-1);
}
+const char *
+server_root_strip(const char *path, int n)
+{
+ const char *p;
+
+ /* Strip strip leading directories. Leading '/' is ignored. */
+ for (; n > 0 && *path != '\0'; n--)
+ if ((p = strchr(++path, '/')) == NULL)
+ path = strchr(path, '\0');
+ else
+ path = p;
+
+ return (path);
+}
+
struct server_config *
server_getlocation(struct client *clt, const char *path)
{