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