xref: /openbsd/usr.sbin/httpd/config.c (revision a342d684)
1 /*	$OpenBSD: config.c,v 1.45 2016/04/28 14:20:11 jsing 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 
53 	/* Other configuration */
54 	what = ps->ps_what[privsep_process];
55 
56 	if (what & CONFIG_SERVERS) {
57 		if ((env->sc_servers =
58 		    calloc(1, sizeof(*env->sc_servers))) == NULL)
59 			return (-1);
60 		TAILQ_INIT(env->sc_servers);
61 	}
62 
63 	if (what & CONFIG_MEDIA) {
64 		if ((env->sc_mediatypes =
65 		    calloc(1, sizeof(*env->sc_mediatypes))) == NULL)
66 			return (-1);
67 		RB_INIT(env->sc_mediatypes);
68 	}
69 
70 	if (what & CONFIG_AUTH) {
71 		if ((env->sc_auth =
72 		    calloc(1, sizeof(*env->sc_auth))) == NULL)
73 			return (-1);
74 		TAILQ_INIT(env->sc_auth);
75 	}
76 
77 	return (0);
78 }
79 
80 void
81 config_purge(struct httpd *env, unsigned int reset)
82 {
83 	struct privsep		*ps = env->sc_ps;
84 	struct server		*srv;
85 	struct auth		*auth;
86 	unsigned int		 what;
87 
88 	what = ps->ps_what[privsep_process] & reset;
89 
90 	if (what & CONFIG_SERVERS && env->sc_servers != NULL) {
91 		while ((srv = TAILQ_FIRST(env->sc_servers)) != NULL)
92 			server_purge(srv);
93 	}
94 
95 	if (what & CONFIG_MEDIA && env->sc_mediatypes != NULL)
96 		media_purge(env->sc_mediatypes);
97 
98 	if (what & CONFIG_AUTH && env->sc_auth != NULL) {
99 		while ((auth = TAILQ_FIRST(env->sc_auth)) != NULL) {
100 			auth_free(env->sc_auth, auth);
101 			free(auth);
102 		}
103 	}
104 }
105 
106 int
107 config_setreset(struct httpd *env, unsigned int reset)
108 {
109 	struct privsep	*ps = env->sc_ps;
110 	int		 id;
111 
112 	for (id = 0; id < PROC_MAX; id++) {
113 		if ((reset & ps->ps_what[id]) == 0 ||
114 		    id == privsep_process)
115 			continue;
116 		proc_compose(ps, id, IMSG_CTL_RESET,
117 		    &reset, sizeof(reset));
118 	}
119 
120 	return (0);
121 }
122 
123 int
124 config_getreset(struct httpd *env, struct imsg *imsg)
125 {
126 	unsigned int	 mode;
127 
128 	IMSG_SIZE_CHECK(imsg, &mode);
129 	memcpy(&mode, imsg->data, sizeof(mode));
130 
131 	config_purge(env, mode);
132 
133 	return (0);
134 }
135 
136 int
137 config_getcfg(struct httpd *env, struct imsg *imsg)
138 {
139 	struct privsep		*ps = env->sc_ps;
140 	struct ctl_flags	 cf;
141 	unsigned int		 what;
142 
143 	if (IMSG_DATA_SIZE(imsg) != sizeof(cf))
144 		return (0); /* ignore */
145 
146 	/* Update runtime flags */
147 	memcpy(&cf, imsg->data, sizeof(cf));
148 	env->sc_opts = cf.cf_opts;
149 	env->sc_flags = cf.cf_flags;
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 
216 			/* Configure TLS if necessary. */
217 			config_settls(env, srv);
218 		} else {
219 			if (proc_composev(ps, id, IMSG_CFG_SERVER,
220 			    iov, c) != 0) {
221 				log_warn("%s: failed to compose "
222 				    "IMSG_CFG_SERVER imsg for `%s'",
223 				    __func__, srv->srv_conf.name);
224 				return (-1);
225 			}
226 		}
227 	}
228 
229 	return (0);
230 }
231 
232 int
233 config_settls(struct httpd *env, struct server *srv)
234 {
235 	struct privsep		*ps = env->sc_ps;
236 	struct server_config	*srv_conf = &srv->srv_conf;
237 	struct tls_config	 tls;
238 	struct iovec		 iov[2];
239 	size_t			 c;
240 
241 	if ((srv_conf->flags & SRVFLAG_TLS) == 0)
242 		return (0);
243 
244 	log_debug("%s: configuring TLS for %s", __func__, srv_conf->name);
245 
246 	if (srv_conf->tls_cert_len != 0) {
247 		DPRINTF("%s: sending TLS cert \"%s[%u]\" to %s fd %d", __func__,
248 		    srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
249 		    srv->srv_s);
250 
251 		memset(&tls, 0, sizeof(tls));
252 		tls.id = srv_conf->id;
253 		tls.tls_cert_len = srv_conf->tls_cert_len;
254 
255 		c = 0;
256 		iov[c].iov_base = &tls;
257 		iov[c++].iov_len = sizeof(tls);
258 		iov[c].iov_base = srv_conf->tls_cert;
259 		iov[c++].iov_len = srv_conf->tls_cert_len;
260 
261 		if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
262 			log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
263 			    "`%s'", __func__, srv_conf->name);
264 			return (-1);
265 		}
266 	}
267 
268 	if (srv_conf->tls_key_len != 0) {
269 		DPRINTF("%s: sending TLS key \"%s[%u]\" to %s fd %d", __func__,
270 		    srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
271 		    srv->srv_s);
272 
273 		memset(&tls, 0, sizeof(tls));
274 		tls.id = srv_conf->id;
275 		tls.tls_key_len = srv_conf->tls_key_len;
276 
277 		c = 0;
278 		iov[c].iov_base = &tls;
279 		iov[c++].iov_len = sizeof(tls);
280 		iov[c].iov_base = srv_conf->tls_key;
281 		iov[c++].iov_len = srv_conf->tls_key_len;
282 
283 		if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
284 			log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
285 			    "`%s'", __func__, srv_conf->name);
286 			return (-1);
287 		}
288 	}
289 
290 	return (0);
291 }
292 
293 int
294 config_getserver_auth(struct httpd *env, struct server_config *srv_conf)
295 {
296 	struct privsep		*ps = env->sc_ps;
297 
298 	if ((ps->ps_what[privsep_process] & CONFIG_AUTH) == 0 ||
299 	    (srv_conf->flags & SRVFLAG_AUTH) == 0)
300 		return (0);
301 
302 	if ((srv_conf->auth = auth_byid(env->sc_auth,
303 	    srv_conf->auth_id)) == NULL)
304 		return (-1);
305 
306 	return (0);
307 }
308 
309 int
310 config_getserver_config(struct httpd *env, struct server *srv,
311     struct imsg *imsg)
312 {
313 #ifdef DEBUG
314 	struct privsep		*ps = env->sc_ps;
315 #endif
316 	struct server_config	*srv_conf, *parent;
317 	uint8_t			*p = imsg->data;
318 	unsigned int		 f;
319 	size_t			 s;
320 
321 	if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL)
322 		return (-1);
323 
324 	IMSG_SIZE_CHECK(imsg, srv_conf);
325 	memcpy(srv_conf, p, sizeof(*srv_conf));
326 	s = sizeof(*srv_conf);
327 
328 	/* Reset these variables to avoid free'ing invalid pointers */
329 	serverconfig_reset(srv_conf);
330 
331 	TAILQ_FOREACH(parent, &srv->srv_hosts, entry) {
332 		if (strcmp(parent->name, srv_conf->name) == 0)
333 			break;
334 	}
335 	if (parent == NULL)
336 		parent = &srv->srv_conf;
337 
338 	if (config_getserver_auth(env, srv_conf) != 0)
339 		goto fail;
340 
341 	/*
342 	 * Get variable-length values for the virtual host.  The tls_* ones
343 	 * aren't needed in the virtual hosts unless we implement SNI.
344 	 */
345 	if (srv_conf->return_uri_len != 0) {
346 		if ((srv_conf->return_uri = get_data(p + s,
347 		    srv_conf->return_uri_len)) == NULL)
348 			goto fail;
349 		s += srv_conf->return_uri_len;
350 	}
351 
352 	if (srv_conf->flags & SRVFLAG_LOCATION) {
353 		/* Inherit configuration from the parent */
354 		f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX;
355 		if ((srv_conf->flags & f) == 0) {
356 			srv_conf->flags |= parent->flags & f;
357 			(void)strlcpy(srv_conf->index, parent->index,
358 			    sizeof(srv_conf->index));
359 		}
360 
361 		f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX;
362 		if ((srv_conf->flags & f) == 0)
363 			srv_conf->flags |= parent->flags & f;
364 
365 		f = SRVFLAG_SOCKET|SRVFLAG_FCGI;
366 		if ((srv_conf->flags & f) == SRVFLAG_FCGI) {
367 			srv_conf->flags |= f;
368 			(void)strlcpy(srv_conf->socket, HTTPD_FCGI_SOCKET,
369 			    sizeof(srv_conf->socket));
370 		}
371 
372 		f = SRVFLAG_ROOT;
373 		if ((srv_conf->flags & f) == 0) {
374 			srv_conf->flags |= parent->flags & f;
375 			(void)strlcpy(srv_conf->root, parent->root,
376 			    sizeof(srv_conf->root));
377 		}
378 
379 		f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI;
380 		if ((srv_conf->flags & f) == 0)
381 			srv_conf->flags |= parent->flags & f;
382 
383 		f = SRVFLAG_LOG|SRVFLAG_NO_LOG;
384 		if ((srv_conf->flags & f) == 0) {
385 			srv_conf->flags |= parent->flags & f;
386 			srv_conf->logformat = parent->logformat;
387 		}
388 
389 		f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG;
390 		if ((srv_conf->flags & f) == 0)
391 			srv_conf->flags |= parent->flags & f;
392 
393 		f = SRVFLAG_AUTH|SRVFLAG_NO_AUTH;
394 		if ((srv_conf->flags & f) == 0) {
395 			srv_conf->flags |= parent->flags & f;
396 			srv_conf->auth = parent->auth;
397 			srv_conf->auth_id = parent->auth_id;
398 			(void)strlcpy(srv_conf->auth_realm,
399 			    parent->auth_realm,
400 			    sizeof(srv_conf->auth_realm));
401 		}
402 
403 		f = SRVFLAG_TLS;
404 		srv_conf->flags |= parent->flags & f;
405 
406 		f = SRVFLAG_ACCESS_LOG;
407 		if ((srv_conf->flags & f) == 0) {
408 			srv_conf->flags |= parent->flags & f;
409 			(void)strlcpy(srv_conf->accesslog,
410 			    parent->accesslog,
411 			    sizeof(srv_conf->accesslog));
412 		}
413 
414 		f = SRVFLAG_ERROR_LOG;
415 		if ((srv_conf->flags & f) == 0) {
416 			srv_conf->flags |= parent->flags & f;
417 			(void)strlcpy(srv_conf->errorlog,
418 			    parent->errorlog,
419 			    sizeof(srv_conf->errorlog));
420 		}
421 
422 		f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK;
423 		if ((srv_conf->flags & f) == 0) {
424 			free(srv_conf->return_uri);
425 			srv_conf->flags |= parent->flags & f;
426 			srv_conf->return_code = parent->return_code;
427 			srv_conf->return_uri_len = parent->return_uri_len;
428 			if (srv_conf->return_uri_len &&
429 			    (srv_conf->return_uri =
430 			    strdup(parent->return_uri)) == NULL)
431 				goto fail;
432 		}
433 
434 		f = SRVFLAG_DEFAULT_TYPE;
435 		if ((srv_conf->flags & f) == 0) {
436 			srv_conf->flags |= parent->flags & f;
437 			memcpy(&srv_conf->default_type,
438 			    &parent->default_type, sizeof(struct media_type));
439 		}
440 
441 		f = SRVFLAG_SERVER_HSTS;
442 		srv_conf->flags |= parent->flags & f;
443 		srv_conf->hsts_max_age = parent->hsts_max_age;
444 		srv_conf->hsts_flags = parent->hsts_flags;
445 
446 		memcpy(&srv_conf->timeout, &parent->timeout,
447 		    sizeof(srv_conf->timeout));
448 		srv_conf->maxrequests = parent->maxrequests;
449 		srv_conf->maxrequestbody = parent->maxrequestbody;
450 
451 		DPRINTF("%s: %s %d location \"%s\", "
452 		    "parent \"%s[%u]\", flags: %s",
453 		    __func__, ps->ps_title[privsep_process], ps->ps_instance,
454 		    srv_conf->location, parent->name, parent->id,
455 		    printb_flags(srv_conf->flags, SRVFLAG_BITS));
456 	} else {
457 		/* Add a new "virtual" server */
458 		DPRINTF("%s: %s %d server \"%s[%u]\", parent \"%s[%u]\", "
459 		    "flags: %s", __func__,
460 		    ps->ps_title[privsep_process], ps->ps_instance,
461 		    srv_conf->name, srv_conf->id, parent->name, parent->id,
462 		    printb_flags(srv_conf->flags, SRVFLAG_BITS));
463 	}
464 
465 	TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry);
466 
467 	return (0);
468 
469  fail:
470 	serverconfig_free(srv_conf);
471 	free(srv_conf);
472 	return (-1);
473 }
474 
475 int
476 config_getserver(struct httpd *env, struct imsg *imsg)
477 {
478 #ifdef DEBUG
479 	struct privsep		*ps = env->sc_ps;
480 #endif
481 	struct server		*srv = NULL;
482 	struct server_config	 srv_conf;
483 	uint8_t			*p = imsg->data;
484 	size_t			 s;
485 
486 	IMSG_SIZE_CHECK(imsg, &srv_conf);
487 	memcpy(&srv_conf, p, sizeof(srv_conf));
488 	s = sizeof(srv_conf);
489 
490 	/* Reset these variables to avoid free'ing invalid pointers */
491 	serverconfig_reset(&srv_conf);
492 
493 	if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) {
494 		log_debug("%s: invalid message length", __func__);
495 		goto fail;
496 	}
497 
498 	/* Check if server with matching listening socket already exists */
499 	if ((srv = server_byaddr((struct sockaddr *)
500 	    &srv_conf.ss, srv_conf.port)) != NULL) {
501 		/* Add "host" to existing listening server */
502 		if (imsg->fd != -1) {
503 			if (srv->srv_s == -1)
504 				srv->srv_s = imsg->fd;
505 			else
506 				close(imsg->fd);
507 		}
508 		return (config_getserver_config(env, srv, imsg));
509 	}
510 
511 	if (srv_conf.flags & SRVFLAG_LOCATION)
512 		fatalx("invalid location");
513 
514 	/* Otherwise create a new server */
515 	if ((srv = calloc(1, sizeof(*srv))) == NULL)
516 		goto fail;
517 
518 	memcpy(&srv->srv_conf, &srv_conf, sizeof(srv->srv_conf));
519 	srv->srv_s = imsg->fd;
520 
521 	if (config_getserver_auth(env, &srv->srv_conf) != 0)
522 		goto fail;
523 
524 	SPLAY_INIT(&srv->srv_clients);
525 	TAILQ_INIT(&srv->srv_hosts);
526 
527 	TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry);
528 	TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry);
529 
530 	DPRINTF("%s: %s %d configuration \"%s[%u]\", flags: %s", __func__,
531 	    ps->ps_title[privsep_process], ps->ps_instance,
532 	    srv->srv_conf.name, srv->srv_conf.id,
533 	    printb_flags(srv->srv_conf.flags, SRVFLAG_BITS));
534 
535 	/*
536 	 * Get all variable-length values for the parent server.
537 	 */
538 	if (srv->srv_conf.return_uri_len != 0) {
539 		if ((srv->srv_conf.return_uri = get_data(p + s,
540 		    srv->srv_conf.return_uri_len)) == NULL)
541 			goto fail;
542 		s += srv->srv_conf.return_uri_len;
543 	}
544 
545 	return (0);
546 
547  fail:
548 	if (imsg->fd != -1)
549 		close(imsg->fd);
550 	if (srv != NULL)
551 		serverconfig_free(&srv->srv_conf);
552 	free(srv);
553 
554 	return (-1);
555 }
556 
557 int
558 config_gettls(struct httpd *env, struct imsg *imsg)
559 {
560 #ifdef DEBUG
561 	struct privsep		*ps = env->sc_ps;
562 #endif
563 	struct server_config	*srv_conf = NULL;
564 	struct tls_config	 tls_conf;
565 	uint8_t			*p = imsg->data;
566 	size_t			 s;
567 
568 	IMSG_SIZE_CHECK(imsg, &tls_conf);
569 	memcpy(&tls_conf, p, sizeof(tls_conf));
570 	s = sizeof(tls_conf);
571 
572 	if ((IMSG_DATA_SIZE(imsg) - s) <
573 	    (tls_conf.tls_cert_len + tls_conf.tls_key_len)) {
574 		log_debug("%s: invalid message length", __func__);
575 		goto fail;
576 	}
577 
578 	if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) {
579 		log_debug("%s: server not found", __func__);
580 		goto fail;
581 	}
582 
583 	DPRINTF("%s: %s %d TLS configuration \"%s[%u]\"", __func__,
584 	    ps->ps_title[privsep_process], ps->ps_instance,
585 	    srv_conf->name, srv->srv_conf.id);
586 
587 	if (tls_conf.tls_cert_len != 0) {
588 		srv_conf->tls_cert_len = tls_conf.tls_cert_len;
589 		if ((srv_conf->tls_cert = get_data(p + s,
590 		    tls_conf.tls_cert_len)) == NULL)
591 			goto fail;
592 		s += tls_conf.tls_cert_len;
593 	}
594 	if (tls_conf.tls_key_len != 0) {
595 		srv_conf->tls_key_len = tls_conf.tls_key_len;
596 		if ((srv_conf->tls_key = get_data(p + s,
597 		    tls_conf.tls_key_len)) == NULL)
598 			goto fail;
599 		s += tls_conf.tls_key_len;
600 	}
601 
602 	return (0);
603 
604  fail:
605 	return (-1);
606 }
607 
608 int
609 config_setmedia(struct httpd *env, struct media_type *media)
610 {
611 	struct privsep		*ps = env->sc_ps;
612 	int			 id;
613 	unsigned int		 what;
614 
615 	for (id = 0; id < PROC_MAX; id++) {
616 		what = ps->ps_what[id];
617 
618 		if ((what & CONFIG_MEDIA) == 0 || id == privsep_process)
619 			continue;
620 
621 		DPRINTF("%s: sending media \"%s\" to %s", __func__,
622 		    media->media_name, ps->ps_title[id]);
623 
624 		proc_compose(ps, id, IMSG_CFG_MEDIA, media, sizeof(*media));
625 	}
626 
627 	return (0);
628 }
629 
630 int
631 config_getmedia(struct httpd *env, struct imsg *imsg)
632 {
633 #ifdef DEBUG
634 	struct privsep		*ps = env->sc_ps;
635 #endif
636 	struct media_type	 media;
637 	uint8_t			*p = imsg->data;
638 
639 	IMSG_SIZE_CHECK(imsg, &media);
640 	memcpy(&media, p, sizeof(media));
641 
642 	if (media_add(env->sc_mediatypes, &media) == NULL) {
643 		log_debug("%s: failed to add media \"%s\"",
644 		    __func__, media.media_name);
645 		return (-1);
646 	}
647 
648 	DPRINTF("%s: %s %d received media \"%s\"", __func__,
649 	    ps->ps_title[privsep_process], ps->ps_instance,
650 	    media.media_name);
651 
652 	return (0);
653 }
654 
655 int
656 config_setauth(struct httpd *env, struct auth *auth)
657 {
658 	struct privsep		*ps = env->sc_ps;
659 	int			 id;
660 	unsigned int		 what;
661 
662 	for (id = 0; id < PROC_MAX; id++) {
663 		what = ps->ps_what[id];
664 
665 		if ((what & CONFIG_AUTH) == 0 || id == privsep_process)
666 			continue;
667 
668 		DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__,
669 		    auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]);
670 
671 		proc_compose(ps, id, IMSG_CFG_AUTH, auth, sizeof(*auth));
672 	}
673 
674 	return (0);
675 }
676 
677 int
678 config_getauth(struct httpd *env, struct imsg *imsg)
679 {
680 #ifdef DEBUG
681 	struct privsep		*ps = env->sc_ps;
682 #endif
683 	struct auth		 auth;
684 	uint8_t			*p = imsg->data;
685 
686 	IMSG_SIZE_CHECK(imsg, &auth);
687 	memcpy(&auth, p, sizeof(auth));
688 
689 	if (auth_add(env->sc_auth, &auth) == NULL) {
690 		log_debug("%s: failed to add auth \"%s[%u]\"",
691 		    __func__, auth.auth_htpasswd, auth.auth_id);
692 		return (-1);
693 	}
694 
695 	DPRINTF("%s: %s %d received auth \"%s[%u]\"", __func__,
696 	    ps->ps_title[privsep_process], ps->ps_instance,
697 	    auth.auth_htpasswd, auth.auth_id);
698 
699 	return (0);
700 }
701