Fix httpd example config
authortb <tb@openbsd.org>
Mon, 18 Jan 2021 18:47:49 +0000 (18:47 +0000)
committertb <tb@openbsd.org>
Mon, 18 Jan 2021 18:47:49 +0000 (18:47 +0000)
A server configuration yields multiple struct server_config in the
env->sc_servers queue: an actual server ("parent") and one for each
location directive in httpd.conf.  In parent_configure(), the parents
are configured first, then the corresponding locations.

parse.y r1.118 kills the parent if an error is encountered on loading
the TLS keypairs but leaves the locations in the sc_servers queue.
When running the default config without TLS keys already in place, this
then leads to the self-explanatory "invalid location" error message. Its
intention is to indicates the unexpected situation that config_setserver()
encounters a location without an associated server.

Fix this by not only destroying the parent but also removing all of its
locations.

ok jsing

usr.sbin/httpd/parse.y

index 45eaa1a..c3ccf3e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.122 2020/12/30 18:40:22 benno Exp $       */
+/*     $OpenBSD: parse.y,v 1.123 2021/01/18 18:47:49 tb Exp $  */
 
 /*
  * Copyright (c) 2020 Matthias Pressfreund <mpfr@fn.de>
@@ -119,6 +119,7 @@ int          listen_on(const char *, int, struct portrange *);
 int             getservice(char *);
 int             is_if_in_group(const char *, const char *);
 int             get_fastcgi_dest(struct server_config *, const char *, char *);
+void            remove_locations(struct server_config *);
 
 typedef struct {
        union {
@@ -357,6 +358,8 @@ server              : SERVER optmatch STRING        {
                                log_warnx("%s:%d: server \"%s\": failed to "
                                    "load public/private keys", file->name,
                                    yylval.lineno, srv->srv_conf.name);
+
+                               remove_locations(srv_conf);
                                serverconfig_free(srv_conf);
                                srv_conf = NULL;
                                free(srv);
@@ -2490,3 +2493,18 @@ get_fastcgi_dest(struct server_config *xsrv_conf, const char *node, char *port)
 
        return (0);
 }
+
+void
+remove_locations(struct server_config *xsrv_conf)
+{
+       struct server *s, *next;
+
+       TAILQ_FOREACH_SAFE(s, conf->sc_servers, srv_entry, next) {
+               if (!(s->srv_conf.flags & SRVFLAG_LOCATION &&
+                   s->srv_conf.parent_id == xsrv_conf->parent_id))
+                       continue;
+               TAILQ_REMOVE(conf->sc_servers, s, srv_entry);
+               serverconfig_free(&s->srv_conf);
+               free(s);
+       }
+}