From e30ef12693dc3dcdf72573424c839afb10769b70 Mon Sep 17 00:00:00 2001 From: Reyk Floeter Date: Fri, 25 Jul 2014 23:06:50 +0200 Subject: sync --- httpd.c | 11 +---------- httpd.conf.5 | 30 ++++++++++++++++++++++++++---- httpd.h | 2 +- server_file.c | 28 ++++++++++++---------------- server_http.c | 8 +++++++- 5 files changed, 47 insertions(+), 32 deletions(-) diff --git a/httpd.c b/httpd.c index 22ae5f9..a1a8558 100644 --- a/httpd.c +++ b/httpd.c @@ -466,24 +466,15 @@ canonicalize_host(const char *host, char *name, size_t len) } const char * -canonicalize_path(const char *root, const char *input, char *path, size_t len) +canonicalize_path(const char *input, char *path, size_t len) { const char *i; char *p, *start, *end; - size_t n; /* assuming input starts with '/' and is nul-terminated */ i = input; p = path; - /* prepend root directory, if specified */ - if (root != NULL) { - if ((n = strlcpy(path, root, len)) >= len) - return (NULL); - len -= n; - p += n; - } - if (*input != '/' || len < 3) return (NULL); diff --git a/httpd.conf.5 b/httpd.conf.5 index cbd1004..2cb442f 100644 --- a/httpd.conf.5 +++ b/httpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: httpd.conf.5,v 1.6 2014/07/25 15:47:11 reyk Exp $ +.\" $OpenBSD: httpd.conf.5,v 1.7 2014/07/25 17:49:11 reyk Exp $ .\" .\" Copyright (c) 2014 Reyk Floeter .\" @@ -160,9 +160,9 @@ to the specified extension One or more names can be specified per line. .El .Sh EXAMPLES -The following example will start two pre-forked servers that are -listening on the primary IP address of the network interface that is a -member of the +The following example will start one server that is pre-forked two +times and listening on the primary IP address of the network interface +that is a member of the .Ar egress group. It additionally defines some media types overriding the defaults. @@ -185,6 +185,28 @@ types { } .Ed .Pp +Multiple servers can be configured to support hosting of different domains. +If the same address is repeated multiple times in the +.Ic listen on +statement, +the server will be matched based on the requested host name. +.Bd -literal -offset indent +server "www.a.example.com" { + listen on 203.0.113.1 port 80 + root "/htdocs/www.a.example.com" +} + +server "www.b.example.com" { + listen on 203.0.113.1 port 80 + root "/htdocs/www.b.example.com" +} + +server "intranet.example.com" { + listen on 10.0.0.1 port 80 + root "/htdocs/intranet.example.com" +} +.Ed +.Pp The syntax of the types section is compatible with the format used by .Xr nginx 8 , so it is possible to include its diff --git a/httpd.h b/httpd.h index cc10bfb..f955fe6 100644 --- a/httpd.h +++ b/httpd.h @@ -421,7 +421,7 @@ void event_again(struct event *, int, short, void (*)(int, short, void *), struct timeval *, struct timeval *, void *); const char *canonicalize_host(const char *, char *, size_t); -const char *canonicalize_path(const char *, const char *, char *, size_t); +const char *canonicalize_path(const char *, char *, size_t); void imsg_event_add(struct imsgev *); int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t, pid_t, int, void *, u_int16_t); diff --git a/server_file.c b/server_file.c index c4814a0..a21c48c 100644 --- a/server_file.c +++ b/server_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_file.c,v 1.13 2014/07/25 13:10:18 reyk Exp $ */ +/* $OpenBSD: server_file.c,v 1.14 2014/07/25 20:13:06 reyk Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -54,7 +54,9 @@ int server_file_access(struct http_descriptor *desc, char *path, size_t len, struct stat *st) { + char *newpath; errno = 0; + if (access(path, R_OK) == -1) { goto fail; } else if (stat(path, st) == -1) { @@ -70,13 +72,10 @@ server_file_access(struct http_descriptor *desc, char *path, size_t len, /* Redirect to path with trailing "/" */ if (path[strlen(path) - 1] != '/') { - /* Remove the document root to get the relative URL */ - if (canonicalize_path(NULL, - desc->http_path, path, len) == NULL || - strlcat(path, "/", len) >= len) { - errno = EINVAL; - goto fail; - } + if (asprintf(&newpath, "%s/", desc->http_path) == -1) + return (500); + free(desc->http_path); + desc->http_path = newpath; /* Indicate that the file has been moved */ return (301); @@ -99,10 +98,6 @@ server_file_access(struct http_descriptor *desc, char *path, size_t len, return (0); fail: - /* Remove the document root */ - if (len && canonicalize_path(NULL, desc->http_path, path, len) == NULL) - return (500); - switch (errno) { case ENOENT: return (404); @@ -126,16 +121,17 @@ server_file(struct httpd *env, struct client *clt) char path[MAXPATHLEN]; struct stat st; - if (canonicalize_path(srv_conf->docroot, - desc->http_path, path, sizeof(path)) == NULL) { + /* Request path is already canonicalized */ + if ((size_t)snprintf(path, sizeof(path), "%s/%s", + srv_conf->docroot, desc->http_path) >= sizeof(path)) { /* Do not echo the uncanonicalized path */ - server_abort_http(clt, 500, "invalid request path"); + server_abort_http(clt, 500, desc->http_path); return (-1); } /* Returns HTTP status code on error */ if ((ret = server_file_access(desc, path, sizeof(path), &st)) != 0) { - server_abort_http(clt, ret, path); + server_abort_http(clt, ret, desc->http_path); return (-1); } diff --git a/server_http.c b/server_http.c index 98edb96..58080a4 100644 --- a/server_http.c +++ b/server_http.c @@ -627,13 +627,19 @@ server_close_http(struct client *clt) int server_response(struct httpd *httpd, struct client *clt) { + char path[MAXPATHLEN]; struct http_descriptor *desc = clt->clt_desc; struct server *srv = clt->clt_srv; struct server_config *srv_conf; struct kv *kv, key; int ret; - if (desc->http_path == NULL) + /* Canonicalize the request path */ + if (desc->http_path == NULL || + canonicalize_path(desc->http_path, path, sizeof(path)) == NULL) + goto fail; + free(desc->http_path); + if ((desc->http_path = strdup(path)) == NULL) goto fail; if (strcmp(desc->http_version, "HTTP/1.1") == 0) { -- cgit v1.2.3-54-g00ecf