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