From ff19a716a21b4cc58cda483ca2b6001952b9e5b1 Mon Sep 17 00:00:00 2001 From: Reyk Floeter Date: Fri, 5 Sep 2014 10:04:21 +0000 Subject: 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@ --- usr.sbin/httpd/config.c | 71 +++++++++++++++++++++++--------------- usr.sbin/httpd/httpd.c | 12 ++++++- usr.sbin/httpd/httpd.h | 4 ++- usr.sbin/httpd/parse.y | 81 +++++++++++++++++++++++++++++++------------- usr.sbin/httpd/server.c | 21 ++++++++++-- usr.sbin/httpd/server_http.c | 14 +++++++- 6 files changed, 145 insertions(+), 58 deletions(-) (limited to 'usr.sbin') 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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) { -- cgit v1.2.3