aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2014-07-25 23:06:50 +0200
committerReyk Floeter <reyk@esdenera.com>2014-07-25 23:06:50 +0200
commite30ef12693dc3dcdf72573424c839afb10769b70 (patch)
treec24f3231a41a6b7e13372702217289775210e052
parente3e992b54315a4d8e9bf446dab17ebde280903e1 (diff)
downloadhttpd-e30ef12693dc3dcdf72573424c839afb10769b70.tar.gz
httpd-e30ef12693dc3dcdf72573424c839afb10769b70.zip
sync
-rw-r--r--httpd.c11
-rw-r--r--httpd.conf.530
-rw-r--r--httpd.h2
-rw-r--r--server_file.c28
-rw-r--r--server_http.c8
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 <reyk@openbsd.org>
.\"
@@ -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 <reyk@openbsd.org>
@@ -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) {