xref: /openbsd-src/usr.sbin/httpd/config.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /*	$OpenBSD: config.c,v 1.61 2020/09/21 09:42:07 tobhe Exp $	*/
2 
3 /*
4  * Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <sys/tree.h>
24 #include <sys/time.h>
25 #include <sys/uio.h>
26 
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <imsg.h>
32 
33 #include "httpd.h"
34 
35 int	 config_getserver_config(struct httpd *, struct server *,
36 	    struct imsg *);
37 int	 config_getserver_auth(struct httpd *, struct server_config *);
38 
39 int
40 config_init(struct httpd *env)
41 {
42 	struct privsep	*ps = env->sc_ps;
43 	unsigned int	 what;
44 
45 	/* Global configuration */
46 	if (privsep_process == PROC_PARENT)
47 		env->sc_prefork_server = SERVER_NUMPROC;
48 
49 	ps->ps_what[PROC_PARENT] = CONFIG_ALL;
50 	ps->ps_what[PROC_SERVER] =
51 	    CONFIG_SERVERS|CONFIG_MEDIA|CONFIG_AUTH;
52 	ps->ps_what[PROC_LOGGER] = CONFIG_SERVERS;
53 
54 	/* Other configuration */
55 	what = ps->ps_what[privsep_process];
56 
57 	if (what & CONFIG_SERVERS) {
58 		if ((env->sc_servers =
59 		    calloc(1, sizeof(*env->sc_servers))) == NULL)
60 			return (-1);
61 		TAILQ_INIT(env->sc_servers);
62 	}
63 
64 	if (what & CONFIG_MEDIA) {
65 		if ((env->sc_mediatypes =
66 		    calloc(1, sizeof(*env->sc_mediatypes))) == NULL)
67 			return (-1);
68 		RB_INIT(env->sc_mediatypes);
69 	}
70 
71 	if (what & CONFIG_AUTH) {
72 		if ((env->sc_auth =
73 		    calloc(1, sizeof(*env->sc_auth))) == NULL)
74 			return (-1);
75 		TAILQ_INIT(env->sc_auth);
76 	}
77 
78 	return (0);
79 }
80 
81 void
82 config_purge(struct httpd *env, unsigned int reset)
83 {
84 	struct privsep		*ps = env->sc_ps;
85 	struct server		*srv;
86 	struct auth		*auth;
87 	unsigned int		 what;
88 
89 	what = ps->ps_what[privsep_process] & reset;
90 
91 	if (what & CONFIG_SERVERS && env->sc_servers != NULL) {
92 		while ((srv = TAILQ_FIRST(env->sc_servers)) != NULL)
93 			server_purge(srv);
94 	}
95 
96 	if (what & CONFIG_MEDIA && env->sc_mediatypes != NULL)
97 		media_purge(env->sc_mediatypes);
98 
99 	if (what & CONFIG_AUTH && env->sc_auth != NULL) {
100 		while ((auth = TAILQ_FIRST(env->sc_auth)) != NULL) {
101 			auth_free(env->sc_auth, auth);
102 			free(auth);
103 		}
104 	}
105 }
106 
107 int
108 config_setreset(struct httpd *env, unsigned int reset)
109 {
110 	struct privsep	*ps = env->sc_ps;
111 	int		 id;
112 
113 	for (id = 0; id < PROC_MAX; id++) {
114 		if ((reset & ps->ps_what[id]) == 0 ||
115 		    id == privsep_process)
116 			continue;
117 		proc_compose(ps, id, IMSG_CTL_RESET,
118 		    &reset, sizeof(reset));
119 	}
120 
121 	return (0);
122 }
123 
124 int
125 config_getreset(struct httpd *env, struct imsg *imsg)
126 {
127 	unsigned int	 mode;
128 
129 	IMSG_SIZE_CHECK(imsg, &mode);
130 	memcpy(&mode, imsg->data, sizeof(mode));
131 
132 	config_purge(env, mode);
133 
134 	return (0);
135 }
136 
137 int
138 config_getcfg(struct httpd *env, struct imsg *imsg)
139 {
140 	struct ctl_flags	 cf;
141 
142 	if (IMSG_DATA_SIZE(imsg) != sizeof(cf))
143 		return (0); /* ignore */
144 
145 	/* Update runtime flags */
146 	memcpy(&cf, imsg->data, sizeof(cf));
147 	env->sc_opts = cf.cf_opts;
148 	env->sc_flags = cf.cf_flags;
149 	memcpy(env->sc_tls_sid, cf.cf_tls_sid, sizeof(env->sc_tls_sid));
150 
151 	if (privsep_process != PROC_PARENT)
152 		proc_compose(env->sc_ps, PROC_PARENT,
153 		    IMSG_CFG_DONE, NULL, 0);
154 
155 	return (0);
156 }
157 
158 int
159 config_setserver(struct httpd *env, struct server *srv)
160 {
161 	struct privsep		*ps = env->sc_ps;
162 	struct server_config	 s;
163 	int			 id;
164 	int			 fd, n, m;
165 	struct iovec		 iov[6];
166 	size_t			 c;
167 	unsigned int		 what;
168 
169 	/* opens listening sockets etc. */
170 	if (server_privinit(srv) == -1)
171 		return (-1);
172 
173 	for (id = 0; id < PROC_MAX; id++) {
174 		what = ps->ps_what[id];
175 
176 		if ((what & CONFIG_SERVERS) == 0 || id == privsep_process)
177 			continue;
178 
179 		DPRINTF("%s: sending %s \"%s[%u]\" to %s fd %d", __func__,
180 		    (srv->srv_conf.flags & SRVFLAG_LOCATION) ?
181 		    "location" : "server",
182 		    srv->srv_conf.name, srv->srv_conf.id,
183 		    ps->ps_title[id], srv->srv_s);
184 
185 		memcpy(&s, &srv->srv_conf, sizeof(s));
186 
187 		c = 0;
188 		iov[c].iov_base = &s;
189 		iov[c++].iov_len = sizeof(s);
190 		if (srv->srv_conf.return_uri_len != 0) {
191 			iov[c].iov_base = srv->srv_conf.return_uri;
192 			iov[c++].iov_len = srv->srv_conf.return_uri_len;
193 		}
194 
195 		if (id == PROC_SERVER &&
196 		    (srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) {
197 			/* XXX imsg code will close the fd after 1st call */
198 			n = -1;
199 			proc_range(ps, id, &n, &m);
200 			for (n = 0; n < m; n++) {
201 				if (srv->srv_s == -1)
202 					fd = -1;
203 				else if ((fd = dup(srv->srv_s)) == -1)
204 					return (-1);
205 				if (proc_composev_imsg(ps, id, n,
206 				    IMSG_CFG_SERVER, -1, fd, iov, c) != 0) {
207 					log_warn("%s: failed to compose "
208 					    "IMSG_CFG_SERVER imsg for `%s'",
209 					    __func__, srv->srv_conf.name);
210 					return (-1);
211 				}
212 
213 				/* Prevent fd exhaustion in the parent. */
214 				if (proc_flush_imsg(ps, id, n) == -1) {
215 					log_warn("%s: failed to flush "
216 					    "IMSG_CFG_SERVER imsg for `%s'",
217 					    __func__, srv->srv_conf.name);
218 					return (-1);
219 				}
220 			}
221 
222 			/* Configure TLS if necessary. */
223 			config_setserver_tls(env, srv);
224 		} else {
225 			if (proc_composev(ps, id, IMSG_CFG_SERVER,
226 			    iov, c) != 0) {
227 				log_warn("%s: failed to compose "
228 				    "IMSG_CFG_SERVER imsg for `%s'",
229 				    __func__, srv->srv_conf.name);
230 				return (-1);
231 			}
232 
233 			/* Configure FCGI parmeters if necessary. */
234 			config_setserver_fcgiparams(env, srv);
235 		}
236 	}
237 
238 	/* Close server socket early to prevent fd exhaustion in the parent. */
239 	if (srv->srv_s != -1) {
240 		close(srv->srv_s);
241 		srv->srv_s = -1;
242 	}
243 
244 	explicit_bzero(&srv->srv_conf.tls_ticket_key,
245 	    sizeof(srv->srv_conf.tls_ticket_key));
246 
247 	return (0);
248 }
249 
250 static int
251 config_settls(struct httpd *env, struct server *srv, enum tls_config_type type,
252     const char *label, uint8_t *data, size_t len)
253 {
254 	struct privsep		*ps = env->sc_ps;
255 	struct server_config	*srv_conf = &srv->srv_conf;
256 	struct tls_config	 tls;
257 	struct iovec		 iov[2];
258 	size_t			 c;
259 
260 	if (data == NULL || len == 0)
261 		return (0);
262 
263 	DPRINTF("%s: sending tls %s for \"%s[%u]\" to %s fd %d", __func__,
264 	    label, srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
265 	    srv->srv_s);
266 
267 	memset(&tls, 0, sizeof(tls));
268 	tls.id = srv_conf->id;
269 	tls.tls_type = type;
270 	tls.tls_len = len;
271 	tls.tls_chunk_offset = 0;
272 
273 	while (len > 0) {
274 		tls.tls_chunk_len = len;
275 		if (tls.tls_chunk_len > (MAX_IMSG_DATA_SIZE - sizeof(tls)))
276 			tls.tls_chunk_len = MAX_IMSG_DATA_SIZE - sizeof(tls);
277 
278 		c = 0;
279 		iov[c].iov_base = &tls;
280 		iov[c++].iov_len = sizeof(tls);
281 		iov[c].iov_base = data;
282 		iov[c++].iov_len = tls.tls_chunk_len;
283 
284 		if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
285 			log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
286 			    "`%s'", __func__, srv_conf->name);
287 			return (-1);
288 		}
289 
290 		tls.tls_chunk_offset += tls.tls_chunk_len;
291 		data += tls.tls_chunk_len;
292 		len -= tls.tls_chunk_len;
293 	}
294 
295 	return (0);
296 }
297 
298 int
299 config_getserver_fcgiparams(struct httpd *env, struct imsg *imsg)
300 {
301 	struct server		*srv;
302 	struct server_config	*srv_conf, *iconf;
303 	struct fastcgi_param	*fp;
304 	uint32_t		 id;
305 	size_t			 c, nc, len;
306 	uint8_t			*p = imsg->data;
307 
308 	len = sizeof(nc) + sizeof(id);
309 	if (IMSG_DATA_SIZE(imsg) < len) {
310 		log_debug("%s: invalid message length", __func__);
311 		return (-1);
312 	}
313 
314 	memcpy(&nc, p, sizeof(nc));	/* number of params */
315 	p += sizeof(nc);
316 
317 	memcpy(&id, p, sizeof(id));	/* server conf id */
318 	srv_conf = serverconfig_byid(id);
319 	p += sizeof(id);
320 
321 	len += nc*sizeof(*fp);
322 	if (IMSG_DATA_SIZE(imsg) < len) {
323 		log_debug("%s: invalid message length", __func__);
324 		return (-1);
325 	}
326 
327 	/* Find associated server config */
328 	TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
329 		if (srv->srv_conf.id == id) {
330 			srv_conf = &srv->srv_conf;
331 			break;
332 		}
333 		TAILQ_FOREACH(iconf, &srv->srv_hosts, entry) {
334 			if (iconf->id == id) {
335 				srv_conf = iconf;
336 				break;
337 			}
338 		}
339 	}
340 
341 	/* Fetch FCGI parameters */
342 	for (c = 0; c < nc; c++) {
343 		if ((fp = calloc(1, sizeof(*fp))) == NULL)
344 			fatalx("fcgiparams out of memory");
345 		memcpy(fp, p, sizeof(*fp));
346 		TAILQ_INSERT_HEAD(&srv_conf->fcgiparams, fp, entry);
347 
348 		p += sizeof(*fp);
349 	}
350 
351 	return (0);
352 }
353 
354 int
355 config_setserver_fcgiparams(struct httpd *env, struct server *srv)
356 {
357 	struct privsep		*ps = env->sc_ps;
358 	struct server_config	*srv_conf = &srv->srv_conf;
359 	struct fastcgi_param	 *fp;
360 	struct iovec		 *iov;
361 	size_t			 c = 0, nc = 0;
362 
363 	DPRINTF("%s: sending fcgiparam for \"%s[%u]\" to %s fd %d", __func__,
364 	    srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
365 	    srv->srv_s);
366 
367 	if (TAILQ_EMPTY(&srv_conf->fcgiparams))	/* nothing to do */
368 		return (0);
369 
370 	TAILQ_FOREACH(fp, &srv_conf->fcgiparams, entry) {
371 		nc++;
372 	}
373 	if ((iov = calloc(nc + 2, sizeof(*iov))) == NULL)
374 		return (-1);
375 
376 	iov[c].iov_base = &nc;			/* number of params */
377 	iov[c++].iov_len = sizeof(nc);
378 	iov[c].iov_base = &srv_conf->id;	/* server config id */
379 	iov[c++].iov_len = sizeof(srv_conf->id);
380 
381 	TAILQ_FOREACH(fp, &srv_conf->fcgiparams, entry) {	/* push FCGI params */
382 		iov[c].iov_base = fp;
383 		iov[c++].iov_len = sizeof(*fp);
384 	}
385 	if (proc_composev(ps, PROC_SERVER, IMSG_CFG_FCGI, iov, c) != 0) {
386 		log_warn("%s: failed to compose IMSG_CFG_FCGI imsg for "
387 		    "`%s'", __func__, srv_conf->name);
388 		free(iov);
389 		return (-1);
390 	}
391 	free(iov);
392 
393 	return (0);
394 }
395 
396 int
397 config_setserver_tls(struct httpd *env, struct server *srv)
398 {
399 	struct server_config	*srv_conf = &srv->srv_conf;
400 
401 	if ((srv_conf->flags & SRVFLAG_TLS) == 0)
402 		return (0);
403 
404 	log_debug("%s: configuring tls for %s", __func__, srv_conf->name);
405 
406 	if (config_settls(env, srv, TLS_CFG_CA, "ca", srv_conf->tls_ca,
407 	    srv_conf->tls_ca_len) != 0)
408 		return (-1);
409 
410 	if (config_settls(env, srv, TLS_CFG_CERT, "cert", srv_conf->tls_cert,
411 	    srv_conf->tls_cert_len) != 0)
412 		return (-1);
413 
414 	if (config_settls(env, srv, TLS_CFG_CRL, "crl", srv_conf->tls_crl,
415 	    srv_conf->tls_crl_len) != 0)
416 		return (-1);
417 
418 	if (config_settls(env, srv, TLS_CFG_KEY, "key", srv_conf->tls_key,
419 	    srv_conf->tls_key_len) != 0)
420 		return (-1);
421 
422 	if (config_settls(env, srv, TLS_CFG_OCSP_STAPLE, "ocsp staple",
423 	    srv_conf->tls_ocsp_staple, srv_conf->tls_ocsp_staple_len) != 0)
424 		return (-1);
425 
426 	return (0);
427 }
428 
429 int
430 config_getserver_auth(struct httpd *env, struct server_config *srv_conf)
431 {
432 	struct privsep		*ps = env->sc_ps;
433 
434 	if ((ps->ps_what[privsep_process] & CONFIG_AUTH) == 0 ||
435 	    (srv_conf->flags & SRVFLAG_AUTH) == 0)
436 		return (0);
437 
438 	if ((srv_conf->auth = auth_byid(env->sc_auth,
439 	    srv_conf->auth_id)) == NULL)
440 		return (-1);
441 
442 	return (0);
443 }
444 
445 int
446 config_getserver_config(struct httpd *env, struct server *srv,
447     struct imsg *imsg)
448 {
449 #ifdef DEBUG
450 	struct privsep		*ps = env->sc_ps;
451 #endif
452 	struct server_config	*srv_conf, *parent;
453 	uint8_t			*p = imsg->data;
454 	unsigned int		 f;
455 	size_t			 s;
456 
457 	if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL)
458 		return (-1);
459 
460 	IMSG_SIZE_CHECK(imsg, srv_conf);
461 	memcpy(srv_conf, p, sizeof(*srv_conf));
462 	s = sizeof(*srv_conf);
463 
464 	/* Reset these variables to avoid free'ing invalid pointers */
465 	serverconfig_reset(srv_conf);
466 
467 	TAILQ_FOREACH(parent, &srv->srv_hosts, entry) {
468 		if (strcmp(parent->name, srv_conf->name) == 0)
469 			break;
470 	}
471 	if (parent == NULL)
472 		parent = &srv->srv_conf;
473 
474 	if (config_getserver_auth(env, srv_conf) != 0)
475 		goto fail;
476 
477 	/*
478 	 * Get variable-length values for the virtual host.  The tls_* ones
479 	 * aren't needed in the virtual hosts unless we implement SNI.
480 	 */
481 	if (srv_conf->return_uri_len != 0) {
482 		if ((srv_conf->return_uri = get_data(p + s,
483 		    srv_conf->return_uri_len)) == NULL)
484 			goto fail;
485 		s += srv_conf->return_uri_len;
486 	}
487 
488 	if (srv_conf->flags & SRVFLAG_LOCATION) {
489 		/* Inherit configuration from the parent */
490 		f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX;
491 		if ((srv_conf->flags & f) == 0) {
492 			srv_conf->flags |= parent->flags & f;
493 			(void)strlcpy(srv_conf->index, parent->index,
494 			    sizeof(srv_conf->index));
495 		}
496 
497 		f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX;
498 		if ((srv_conf->flags & f) == 0)
499 			srv_conf->flags |= parent->flags & f;
500 
501 		f = SRVFLAG_ROOT;
502 		if ((srv_conf->flags & f) == 0) {
503 			srv_conf->flags |= parent->flags & f;
504 			(void)strlcpy(srv_conf->root, parent->root,
505 			    sizeof(srv_conf->root));
506 		}
507 
508 		f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI;
509 		if ((srv_conf->flags & f) == 0)
510 			srv_conf->flags |= parent->flags & f;
511 
512 		f = SRVFLAG_LOG|SRVFLAG_NO_LOG;
513 		if ((srv_conf->flags & f) == 0) {
514 			srv_conf->flags |= parent->flags & f;
515 			srv_conf->logformat = parent->logformat;
516 		}
517 
518 		f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG;
519 		if ((srv_conf->flags & f) == 0)
520 			srv_conf->flags |= parent->flags & f;
521 
522 		f = SRVFLAG_AUTH|SRVFLAG_NO_AUTH;
523 		if ((srv_conf->flags & f) == 0) {
524 			srv_conf->flags |= parent->flags & f;
525 			srv_conf->auth = parent->auth;
526 			srv_conf->auth_id = parent->auth_id;
527 			(void)strlcpy(srv_conf->auth_realm,
528 			    parent->auth_realm,
529 			    sizeof(srv_conf->auth_realm));
530 		}
531 
532 		f = SRVFLAG_TLS;
533 		srv_conf->flags |= parent->flags & f;
534 		srv_conf->tls_flags = parent->tls_flags;
535 
536 		f = SRVFLAG_ACCESS_LOG;
537 		if ((srv_conf->flags & f) == 0) {
538 			srv_conf->flags |= parent->flags & f;
539 			(void)strlcpy(srv_conf->accesslog,
540 			    parent->accesslog,
541 			    sizeof(srv_conf->accesslog));
542 		}
543 
544 		f = SRVFLAG_ERROR_LOG;
545 		if ((srv_conf->flags & f) == 0) {
546 			srv_conf->flags |= parent->flags & f;
547 			(void)strlcpy(srv_conf->errorlog,
548 			    parent->errorlog,
549 			    sizeof(srv_conf->errorlog));
550 		}
551 
552 		f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK;
553 		if ((srv_conf->flags & f) == 0) {
554 			free(srv_conf->return_uri);
555 			srv_conf->flags |= parent->flags & f;
556 			srv_conf->return_code = parent->return_code;
557 			srv_conf->return_uri_len = parent->return_uri_len;
558 			if (srv_conf->return_uri_len &&
559 			    (srv_conf->return_uri =
560 			    strdup(parent->return_uri)) == NULL)
561 				goto fail;
562 		}
563 
564 		f = SRVFLAG_DEFAULT_TYPE;
565 		if ((srv_conf->flags & f) == 0) {
566 			srv_conf->flags |= parent->flags & f;
567 			memcpy(&srv_conf->default_type,
568 			    &parent->default_type, sizeof(struct media_type));
569 		}
570 
571 		f = SRVFLAG_PATH_REWRITE|SRVFLAG_NO_PATH_REWRITE;
572 		if ((srv_conf->flags & f) == 0) {
573 			srv_conf->flags |= parent->flags & f;
574 			(void)strlcpy(srv_conf->path, parent->path,
575 			    sizeof(srv_conf->path));
576 		}
577 
578 		f = SRVFLAG_SERVER_HSTS;
579 		srv_conf->flags |= parent->flags & f;
580 		srv_conf->hsts_max_age = parent->hsts_max_age;
581 		srv_conf->hsts_flags = parent->hsts_flags;
582 
583 		memcpy(&srv_conf->timeout, &parent->timeout,
584 		    sizeof(srv_conf->timeout));
585 		srv_conf->maxrequests = parent->maxrequests;
586 		srv_conf->maxrequestbody = parent->maxrequestbody;
587 
588 		DPRINTF("%s: %s %d location \"%s\", "
589 		    "parent \"%s[%u]\", flags: %s",
590 		    __func__, ps->ps_title[privsep_process], ps->ps_instance,
591 		    srv_conf->location, parent->name, parent->id,
592 		    printb_flags(srv_conf->flags, SRVFLAG_BITS));
593 	} else {
594 		/* Add a new "virtual" server */
595 		DPRINTF("%s: %s %d server \"%s[%u]\", parent \"%s[%u]\", "
596 		    "flags: %s", __func__,
597 		    ps->ps_title[privsep_process], ps->ps_instance,
598 		    srv_conf->name, srv_conf->id, parent->name, parent->id,
599 		    printb_flags(srv_conf->flags, SRVFLAG_BITS));
600 	}
601 
602 	TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry);
603 
604 	return (0);
605 
606  fail:
607 	serverconfig_free(srv_conf);
608 	free(srv_conf);
609 	return (-1);
610 }
611 
612 int
613 config_getserver(struct httpd *env, struct imsg *imsg)
614 {
615 #ifdef DEBUG
616 	struct privsep		*ps = env->sc_ps;
617 #endif
618 	struct server		*srv = NULL;
619 	struct server_config	 srv_conf;
620 	uint8_t			*p = imsg->data;
621 	size_t			 s;
622 
623 	IMSG_SIZE_CHECK(imsg, &srv_conf);
624 	memcpy(&srv_conf, p, sizeof(srv_conf));
625 	s = sizeof(srv_conf);
626 
627 	/* Reset these variables to avoid free'ing invalid pointers */
628 	serverconfig_reset(&srv_conf);
629 
630 	if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) {
631 		log_debug("%s: invalid message length", __func__);
632 		goto fail;
633 	}
634 
635 	/* Check if server with matching listening socket already exists */
636 	if ((srv = server_byaddr((struct sockaddr *)
637 	    &srv_conf.ss, srv_conf.port)) != NULL) {
638 		/* Add "host" to existing listening server */
639 		if (imsg->fd != -1) {
640 			if (srv->srv_s == -1)
641 				srv->srv_s = imsg->fd;
642 			else
643 				close(imsg->fd);
644 		}
645 		return (config_getserver_config(env, srv, imsg));
646 	}
647 
648 	if (srv_conf.flags & SRVFLAG_LOCATION)
649 		fatalx("invalid location");
650 
651 	/* Otherwise create a new server */
652 	if ((srv = calloc(1, sizeof(*srv))) == NULL)
653 		goto fail;
654 
655 	memcpy(&srv->srv_conf, &srv_conf, sizeof(srv->srv_conf));
656 	srv->srv_s = imsg->fd;
657 
658 	if (config_getserver_auth(env, &srv->srv_conf) != 0)
659 		goto fail;
660 
661 	SPLAY_INIT(&srv->srv_clients);
662 	TAILQ_INIT(&srv->srv_hosts);
663 
664 	TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry);
665 	TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry);
666 
667 	DPRINTF("%s: %s %d configuration \"%s[%u]\", flags: %s", __func__,
668 	    ps->ps_title[privsep_process], ps->ps_instance,
669 	    srv->srv_conf.name, srv->srv_conf.id,
670 	    printb_flags(srv->srv_conf.flags, SRVFLAG_BITS));
671 
672 	/*
673 	 * Get all variable-length values for the parent server.
674 	 */
675 	if (srv->srv_conf.return_uri_len != 0) {
676 		if ((srv->srv_conf.return_uri = get_data(p + s,
677 		    srv->srv_conf.return_uri_len)) == NULL)
678 			goto fail;
679 	}
680 
681 	return (0);
682 
683  fail:
684 	if (imsg->fd != -1)
685 		close(imsg->fd);
686 	if (srv != NULL)
687 		serverconfig_free(&srv->srv_conf);
688 	free(srv);
689 
690 	return (-1);
691 }
692 
693 static int
694 config_gettls(struct httpd *env, struct server_config *srv_conf,
695     struct tls_config *tls_conf, const char *label, uint8_t *data, size_t len,
696     uint8_t **outdata, size_t *outlen)
697 {
698 #ifdef DEBUG
699 	struct privsep		*ps = env->sc_ps;
700 #endif
701 
702 	DPRINTF("%s: %s %d getting tls %s (%zu:%zu@%zu) for \"%s[%u]\"",
703 	    __func__, ps->ps_title[privsep_process], ps->ps_instance, label,
704 	    tls_conf->tls_len, len, tls_conf->tls_chunk_offset, srv_conf->name,
705 	    srv_conf->id);
706 
707 	if (tls_conf->tls_chunk_offset == 0) {
708 		free(*outdata);
709 		*outlen = 0;
710 		if ((*outdata = calloc(1, tls_conf->tls_len)) == NULL)
711 			goto fail;
712 		*outlen = tls_conf->tls_len;
713 	}
714 
715 	if (*outdata == NULL) {
716 		log_debug("%s: tls config invalid chunk sequence", __func__);
717 		goto fail;
718 	}
719 
720 	if (*outlen != tls_conf->tls_len) {
721 		log_debug("%s: tls config length mismatch (%zu != %zu)",
722 		    __func__, *outlen, tls_conf->tls_len);
723 		goto fail;
724 	}
725 
726 	if (len > (tls_conf->tls_len - tls_conf->tls_chunk_offset)) {
727 		log_debug("%s: tls config invalid chunk length", __func__);
728 		goto fail;
729 	}
730 
731 	memcpy(*outdata + tls_conf->tls_chunk_offset, data, len);
732 
733 	return (0);
734 
735  fail:
736 	return (-1);
737 }
738 
739 int
740 config_getserver_tls(struct httpd *env, struct imsg *imsg)
741 {
742 	struct server_config	*srv_conf = NULL;
743 	struct tls_config	 tls_conf;
744 	uint8_t			*p = imsg->data;
745 	size_t			 len;
746 
747 	IMSG_SIZE_CHECK(imsg, &tls_conf);
748 	memcpy(&tls_conf, p, sizeof(tls_conf));
749 
750 	len = tls_conf.tls_chunk_len;
751 
752 	if ((IMSG_DATA_SIZE(imsg) - sizeof(tls_conf)) < len) {
753 		log_debug("%s: invalid message length", __func__);
754 		goto fail;
755 	}
756 
757 	p += sizeof(tls_conf);
758 
759 	if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) {
760 		log_debug("%s: server not found", __func__);
761 		goto fail;
762 	}
763 
764 	switch (tls_conf.tls_type) {
765 	case TLS_CFG_CA:
766 		if (config_gettls(env, srv_conf, &tls_conf, "ca", p, len,
767 		    &srv_conf->tls_ca, &srv_conf->tls_ca_len) != 0)
768 			goto fail;
769 		break;
770 
771 	case TLS_CFG_CERT:
772 		if (config_gettls(env, srv_conf, &tls_conf, "cert", p, len,
773 		    &srv_conf->tls_cert, &srv_conf->tls_cert_len) != 0)
774 			goto fail;
775 		break;
776 
777 	case TLS_CFG_CRL:
778 		if (config_gettls(env, srv_conf, &tls_conf, "crl", p, len,
779 		    &srv_conf->tls_crl, &srv_conf->tls_crl_len) != 0)
780 			goto fail;
781 		break;
782 
783 	case TLS_CFG_KEY:
784 		if (config_gettls(env, srv_conf, &tls_conf, "key", p, len,
785 		    &srv_conf->tls_key, &srv_conf->tls_key_len) != 0)
786 			goto fail;
787 		break;
788 
789 	case TLS_CFG_OCSP_STAPLE:
790 		if (config_gettls(env, srv_conf, &tls_conf, "ocsp staple",
791 		    p, len, &srv_conf->tls_ocsp_staple,
792 		    &srv_conf->tls_ocsp_staple_len) != 0)
793 			goto fail;
794 		break;
795 
796 	default:
797 		log_debug("%s: unknown tls config type %i\n",
798 		     __func__, tls_conf.tls_type);
799 		goto fail;
800 	}
801 
802 	return (0);
803 
804  fail:
805 	return (-1);
806 }
807 
808 int
809 config_setmedia(struct httpd *env, struct media_type *media)
810 {
811 	struct privsep		*ps = env->sc_ps;
812 	int			 id;
813 	unsigned int		 what;
814 
815 	for (id = 0; id < PROC_MAX; id++) {
816 		what = ps->ps_what[id];
817 
818 		if ((what & CONFIG_MEDIA) == 0 || id == privsep_process)
819 			continue;
820 
821 		DPRINTF("%s: sending media \"%s\" to %s", __func__,
822 		    media->media_name, ps->ps_title[id]);
823 
824 		proc_compose(ps, id, IMSG_CFG_MEDIA, media, sizeof(*media));
825 	}
826 
827 	return (0);
828 }
829 
830 int
831 config_getmedia(struct httpd *env, struct imsg *imsg)
832 {
833 #ifdef DEBUG
834 	struct privsep		*ps = env->sc_ps;
835 #endif
836 	struct media_type	 media;
837 	uint8_t			*p = imsg->data;
838 
839 	IMSG_SIZE_CHECK(imsg, &media);
840 	memcpy(&media, p, sizeof(media));
841 
842 	if (media_add(env->sc_mediatypes, &media) == NULL) {
843 		log_debug("%s: failed to add media \"%s\"",
844 		    __func__, media.media_name);
845 		return (-1);
846 	}
847 
848 	DPRINTF("%s: %s %d received media \"%s\"", __func__,
849 	    ps->ps_title[privsep_process], ps->ps_instance,
850 	    media.media_name);
851 
852 	return (0);
853 }
854 
855 int
856 config_setauth(struct httpd *env, struct auth *auth)
857 {
858 	struct privsep		*ps = env->sc_ps;
859 	int			 id;
860 	unsigned int		 what;
861 
862 	for (id = 0; id < PROC_MAX; id++) {
863 		what = ps->ps_what[id];
864 
865 		if ((what & CONFIG_AUTH) == 0 || id == privsep_process)
866 			continue;
867 
868 		DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__,
869 		    auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]);
870 
871 		proc_compose(ps, id, IMSG_CFG_AUTH, auth, sizeof(*auth));
872 	}
873 
874 	return (0);
875 }
876 
877 int
878 config_getauth(struct httpd *env, struct imsg *imsg)
879 {
880 #ifdef DEBUG
881 	struct privsep		*ps = env->sc_ps;
882 #endif
883 	struct auth		 auth;
884 	uint8_t			*p = imsg->data;
885 
886 	IMSG_SIZE_CHECK(imsg, &auth);
887 	memcpy(&auth, p, sizeof(auth));
888 
889 	if (auth_add(env->sc_auth, &auth) == NULL) {
890 		log_debug("%s: failed to add auth \"%s[%u]\"",
891 		    __func__, auth.auth_htpasswd, auth.auth_id);
892 		return (-1);
893 	}
894 
895 	DPRINTF("%s: %s %d received auth \"%s[%u]\"", __func__,
896 	    ps->ps_title[privsep_process], ps->ps_instance,
897 	    auth.auth_htpasswd, auth.auth_id);
898 
899 	return (0);
900 }
901