summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2014-09-05 10:04:21 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2014-09-05 10:04:21 +0000
commitff19a716a21b4cc58cda483ca2b6001952b9e5b1 (patch)
treedce34e56609205ce34ca7960196a03d94a6a18eb /usr.sbin
parent3d65c5b139f797e9bcc3f7f850b48f67dcda4216 (diff)
Remove a limitation that only allowed to specify a server name once.
The key has been changed to server name + address + port and now it is possible to use the same server name for multiple servers with different addresses, eg. http://www.example.com and https://www.example.com/. OK doug@ florian@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/httpd/config.c71
-rw-r--r--usr.sbin/httpd/httpd.c12
-rw-r--r--usr.sbin/httpd/httpd.h4
-rw-r--r--usr.sbin/httpd/parse.y81
-rw-r--r--usr.sbin/httpd/server.c21
-rw-r--r--usr.sbin/httpd/server_http.c14
6 files changed, 145 insertions, 58 deletions
diff --git a/usr.sbin/httpd/config.c b/usr.sbin/httpd/config.c
index 7ab53b5a817..e5455718247 100644
--- a/usr.sbin/httpd/config.c
+++ b/usr.sbin/httpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.21 2014/08/06 18:21:14 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.22 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -176,8 +176,9 @@ config_setserver(struct httpd *env, struct server *srv)
if ((what & CONFIG_SERVERS) == 0 || id == privsep_process)
continue;
- DPRINTF("%s: sending server %s to %s fd %d", __func__,
- srv->srv_conf.name, ps->ps_title[id], srv->srv_s);
+ DPRINTF("%s: sending server \"%s[%u]\" to %s fd %d", __func__,
+ srv->srv_conf.name, srv->srv_conf.id,
+ ps->ps_title[id], srv->srv_s);
memcpy(&s, &srv->srv_conf, sizeof(s));
@@ -223,7 +224,7 @@ config_getserver_config(struct httpd *env, struct server *srv,
#ifdef DEBUG
struct privsep *ps = env->sc_ps;
#endif
- struct server_config *srv_conf;
+ struct server_config *srv_conf, *parent;
u_int8_t *p = imsg->data;
u_int f;
@@ -233,18 +234,28 @@ config_getserver_config(struct httpd *env, struct server *srv,
IMSG_SIZE_CHECK(imsg, srv_conf);
memcpy(srv_conf, p, sizeof(*srv_conf));
+ /* Reset these variables to avoid free'ing invalid pointers */
+ serverconfig_reset(srv_conf);
+
+ TAILQ_FOREACH(parent, &srv->srv_hosts, entry) {
+ if (strcmp(parent->name, srv_conf->name) == 0)
+ break;
+ }
+ if (parent == NULL)
+ parent = &srv->srv_conf;
+
if (srv_conf->flags & SRVFLAG_LOCATION) {
/* Inherit configuration from the parent */
f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
- (void)strlcpy(srv_conf->index, srv->srv_conf.index,
+ srv_conf->flags |= parent->flags & f;
+ (void)strlcpy(srv_conf->index, parent->index,
sizeof(srv_conf->index));
}
f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX;
if ((srv_conf->flags & f) == 0)
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
f = SRVFLAG_SOCKET|SRVFLAG_FCGI;
if ((srv_conf->flags & f) == SRVFLAG_FCGI) {
@@ -255,59 +266,60 @@ config_getserver_config(struct httpd *env, struct server *srv,
f = SRVFLAG_ROOT;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
- (void)strlcpy(srv_conf->root, srv->srv_conf.root,
+ srv_conf->flags |= parent->flags & f;
+ (void)strlcpy(srv_conf->root, parent->root,
sizeof(srv_conf->root));
}
f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI;
if ((srv_conf->flags & f) == 0)
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
f = SRVFLAG_LOG|SRVFLAG_NO_LOG;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
- srv_conf->logformat = srv->srv_conf.logformat;
+ srv_conf->flags |= parent->flags & f;
+ srv_conf->logformat = parent->logformat;
}
f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG;
if ((srv_conf->flags & f) == 0)
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
f = SRVFLAG_SSL;
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
f = SRVFLAG_ACCESS_LOG;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
(void)strlcpy(srv_conf->accesslog,
- srv->srv_conf.accesslog,
+ parent->accesslog,
sizeof(srv_conf->accesslog));
}
f = SRVFLAG_ERROR_LOG;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
(void)strlcpy(srv_conf->errorlog,
- srv->srv_conf.errorlog,
+ parent->errorlog,
sizeof(srv_conf->errorlog));
}
- memcpy(&srv_conf->timeout, &srv->srv_conf.timeout,
+ memcpy(&srv_conf->timeout, &parent->timeout,
sizeof(srv_conf->timeout));
- srv_conf->maxrequests = srv->srv_conf.maxrequests;
- srv_conf->maxrequestbody = srv->srv_conf.maxrequestbody;
+ srv_conf->maxrequests = parent->maxrequests;
+ srv_conf->maxrequestbody = parent->maxrequestbody;
DPRINTF("%s: %s %d location \"%s\", "
- "parent \"%s\", flags: %s",
+ "parent \"%s[%u]\", flags: %s",
__func__, ps->ps_title[privsep_process], ps->ps_instance,
- srv_conf->location, srv->srv_conf.name,
+ srv_conf->location, parent->name, parent->id,
printb_flags(srv_conf->flags, SRVFLAG_BITS));
} else {
/* Add a new "virtual" server */
- DPRINTF("%s: %s %d server \"%s\", parent \"%s\", flags: %s",
- __func__, ps->ps_title[privsep_process], ps->ps_instance,
- srv_conf->name, srv->srv_conf.name,
+ DPRINTF("%s: %s %d server \"%s[%u]\", parent \"%s[%u]\", "
+ "flags: %s", __func__,
+ ps->ps_title[privsep_process], ps->ps_instance,
+ srv_conf->name, srv_conf->id, parent->name, parent->id,
printb_flags(srv_conf->flags, SRVFLAG_BITS));
}
@@ -331,6 +343,9 @@ config_getserver(struct httpd *env, struct imsg *imsg)
memcpy(&srv_conf, p, sizeof(srv_conf));
s = sizeof(srv_conf);
+ /* Reset these variables to avoid free'ing invalid pointers */
+ serverconfig_reset(&srv_conf);
+
if ((u_int)(IMSG_DATA_SIZE(imsg) - s) <
(srv_conf.ssl_cert_len + srv_conf.ssl_key_len)) {
log_debug("%s: invalid message length", __func__);
@@ -364,9 +379,9 @@ config_getserver(struct httpd *env, struct imsg *imsg)
TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry);
TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry);
- DPRINTF("%s: %s %d configuration \"%s\", flags: %s", __func__,
+ DPRINTF("%s: %s %d configuration \"%s[%u]\", flags: %s", __func__,
ps->ps_title[privsep_process], ps->ps_instance,
- srv->srv_conf.name,
+ srv->srv_conf.name, srv->srv_conf.id,
printb_flags(srv->srv_conf.flags, SRVFLAG_BITS));
if (srv->srv_conf.ssl_cert_len != 0) {
diff --git a/usr.sbin/httpd/httpd.c b/usr.sbin/httpd/httpd.c
index 720d1880d2b..9284eb77c42 100644
--- a/usr.sbin/httpd/httpd.c
+++ b/usr.sbin/httpd/httpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.c,v 1.20 2014/09/01 09:32:43 reyk Exp $ */
+/* $OpenBSD: httpd.c,v 1.21 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -289,10 +289,20 @@ parent_configure(struct httpd *env)
fatal("send media");
}
+ /* First send the servers... */
TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
+ if (srv->srv_conf.flags & SRVFLAG_LOCATION)
+ continue;
if (config_setserver(env, srv) == -1)
fatal("send server");
}
+ /* ...and now send the locations */
+ TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
+ if ((srv->srv_conf.flags & SRVFLAG_LOCATION) == 0)
+ continue;
+ if (config_setserver(env, srv) == -1)
+ fatal("send location");
+ }
/* The servers need to reload their config. */
env->sc_reload = env->sc_prefork_server + 1;
diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h
index 82f90be10b9..5c197cf6936 100644
--- a/usr.sbin/httpd/httpd.h
+++ b/usr.sbin/httpd/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.57 2014/09/02 16:20:41 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.58 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -466,6 +466,8 @@ pid_t server(struct privsep *, struct privsep_proc *);
int server_ssl_load_keypair(struct server *);
int server_privinit(struct server *);
void server_purge(struct server *);
+void serverconfig_free(struct server_config *);
+void serverconfig_reset(struct server_config *);
int server_socket_af(struct sockaddr_storage *, in_port_t);
in_port_t
server_socket_getport(struct sockaddr_storage *);
diff --git a/usr.sbin/httpd/parse.y b/usr.sbin/httpd/parse.y
index 02c75d5c131..9ad77320a61 100644
--- a/usr.sbin/httpd/parse.y
+++ b/usr.sbin/httpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.37 2014/09/04 13:45:17 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.38 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -199,15 +199,6 @@ server : SERVER STRING {
YYACCEPT;
}
- TAILQ_FOREACH(s, conf->sc_servers, srv_entry)
- if (!strcmp(s->srv_conf.name, $2))
- break;
- if (s != NULL) {
- yyerror("server %s defined twice", $2);
- free($2);
- YYERROR;
- }
-
if ((s = calloc(1, sizeof (*s))) == NULL)
fatal("out of memory");
@@ -253,18 +244,49 @@ server : SERVER STRING {
srv_conf = &srv->srv_conf;
SPLAY_INIT(&srv->srv_clients);
- TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
} '{' optnl serveropts_l '}' {
+ struct server *s = NULL;
+
+ TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
+ if ((s->srv_conf.flags &
+ SRVFLAG_LOCATION) == 0 &&
+ strcmp(s->srv_conf.name,
+ srv->srv_conf.name) == 0 &&
+ s->srv_conf.port == srv->srv_conf.port &&
+ sockaddr_cmp(
+ (struct sockaddr *)&s->srv_conf.ss,
+ (struct sockaddr *)&srv->srv_conf.ss,
+ s->srv_conf.prefixlen) == 0)
+ break;
+ }
+ if (s != NULL) {
+ yyerror("server \"%s\" defined twice",
+ srv->srv_conf.name);
+ serverconfig_free(srv_conf);
+ free(srv);
+ YYABORT;
+ }
+
if (srv->srv_conf.ss.ss_family == AF_UNSPEC) {
yyerror("listen address not specified");
- free($2);
+ serverconfig_free(srv_conf);
+ free(srv);
YYERROR;
}
+
if (server_ssl_load_keypair(srv) == -1) {
yyerror("failed to load public/private keys "
"for server %s", srv->srv_conf.name);
+ serverconfig_free(srv_conf);
+ free(srv);
YYERROR;
}
+
+ DPRINTF("adding server \"%s[%u]\"",
+ srv->srv_conf.name, srv->srv_conf.id);
+
+ TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
+
srv = NULL;
srv_conf = NULL;
}
@@ -368,17 +390,6 @@ serveroptsl : LISTEN ON STRING optssl port {
YYACCEPT;
}
- TAILQ_FOREACH(s, conf->sc_servers, srv_entry)
- if (strcmp(s->srv_conf.name,
- srv->srv_conf.name) == 0 &&
- strcmp(s->srv_conf.location, $2) == 0)
- break;
- if (s != NULL) {
- yyerror("location %s defined twice", $2);
- free($2);
- YYERROR;
- }
-
if ((s = calloc(1, sizeof (*s))) == NULL)
fatal("out of memory");
@@ -417,8 +428,30 @@ serveroptsl : LISTEN ON STRING optssl port {
srv = s;
srv_conf = &srv->srv_conf;
SPLAY_INIT(&srv->srv_clients);
- TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
} '{' optnl serveropts_l '}' {
+ struct server *s = NULL;
+
+ TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
+ if ((s->srv_conf.flags & SRVFLAG_LOCATION) &&
+ s->srv_conf.id == srv_conf->id &&
+ strcmp(s->srv_conf.location,
+ srv_conf->location) == 0)
+ break;
+ }
+ if (s != NULL) {
+ yyerror("location \"%s\" defined twice",
+ srv->srv_conf.location);
+ serverconfig_free(srv_conf);
+ free(srv);
+ YYABORT;
+ }
+
+ DPRINTF("adding location \"%s\" for \"%s[%u]\"",
+ srv->srv_conf.location,
+ srv->srv_conf.name, srv->srv_conf.id);
+
+ TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
+
srv = parentsrv;
srv_conf = &parentsrv->srv_conf;
parentsrv = NULL;
diff --git a/usr.sbin/httpd/server.c b/usr.sbin/httpd/server.c
index ed321af5752..e756abb99f9 100644
--- a/usr.sbin/httpd/server.c
+++ b/usr.sbin/httpd/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.41 2014/09/02 16:20:41 reyk Exp $ */
+/* $OpenBSD: server.c,v 1.42 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -285,8 +285,7 @@ server_purge(struct server *srv)
/* It might point to our own "default" entry */
if (srv_conf != &srv->srv_conf) {
- free(srv_conf->ssl_cert);
- free(srv_conf->ssl_key);
+ serverconfig_free(srv_conf);
free(srv_conf);
}
}
@@ -297,6 +296,22 @@ server_purge(struct server *srv)
free(srv);
}
+void
+serverconfig_free(struct server_config *srv_conf)
+{
+ free(srv_conf->ssl_cert_file);
+ free(srv_conf->ssl_cert);
+ free(srv_conf->ssl_key_file);
+ free(srv_conf->ssl_key);
+}
+
+void
+serverconfig_reset(struct server_config *srv_conf)
+{
+ srv_conf->ssl_cert_file = srv_conf->ssl_cert =
+ srv_conf->ssl_key_file = srv_conf->ssl_key = NULL;
+}
+
struct server *
server_byaddr(struct sockaddr *addr, in_port_t port)
{
diff --git a/usr.sbin/httpd/server_http.c b/usr.sbin/httpd/server_http.c
index 3d7abc7fb62..32e08c36a35 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.46 2014/08/29 13:01:46 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.47 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -747,6 +747,12 @@ server_response(struct httpd *httpd, struct client *clt)
if (host != NULL) {
/* XXX maybe better to turn srv_hosts into a tree */
TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
+#ifdef DEBUG
+ if ((srv_conf->flags & SRVFLAG_LOCATION) == 0) {
+ DPRINTF("%s: virtual host \"%s\" host \"%s\"",
+ __func__, srv_conf->name, host->kv_value);
+ }
+#endif
if ((srv_conf->flags & SRVFLAG_LOCATION) == 0 &&
fnmatch(srv_conf->name, host->kv_value,
FNM_CASEFOLD) == 0) {
@@ -796,6 +802,12 @@ server_getlocation(struct client *clt, const char *path)
/* Now search for the location */
TAILQ_FOREACH(location, &srv->srv_hosts, entry) {
+#ifdef DEBUG
+ if (location->flags & SRVFLAG_LOCATION) {
+ DPRINTF("%s: location \"%s\" path \"%s\"",
+ __func__, location->location, path);
+ }
+#endif
if ((location->flags & SRVFLAG_LOCATION) &&
location->id == srv_conf->id &&
fnmatch(location->location, path, FNM_CASEFOLD) == 0) {