GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/httpd/config.c Lines: 110 341 32.3 %
Date: 2017-11-13 Branches: 52 208 25.0 %

Line Branch Exec Source
1
/*	$OpenBSD: config.c,v 1.53 2017/07/19 17:36:25 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
96
	struct privsep	*ps = env->sc_ps;
41
	unsigned int	 what;
42
43
	/* Global configuration */
44
48
	if (privsep_process == PROC_PARENT)
45
48
		env->sc_prefork_server = SERVER_NUMPROC;
46
47
48
	ps->ps_what[PROC_PARENT] = CONFIG_ALL;
48
48
	ps->ps_what[PROC_SERVER] =
49
	    CONFIG_SERVERS|CONFIG_MEDIA|CONFIG_AUTH;
50
48
	ps->ps_what[PROC_LOGGER] = CONFIG_SERVERS;
51
52
	/* Other configuration */
53
48
	what = ps->ps_what[privsep_process];
54
55
48
	if (what & CONFIG_SERVERS) {
56
96
		if ((env->sc_servers =
57
96
		    calloc(1, sizeof(*env->sc_servers))) == NULL)
58
			return (-1);
59
48
		TAILQ_INIT(env->sc_servers);
60
48
	}
61
62
48
	if (what & CONFIG_MEDIA) {
63
96
		if ((env->sc_mediatypes =
64
96
		    calloc(1, sizeof(*env->sc_mediatypes))) == NULL)
65
			return (-1);
66
48
		RB_INIT(env->sc_mediatypes);
67
48
	}
68
69
48
	if (what & CONFIG_AUTH) {
70
96
		if ((env->sc_auth =
71
96
		    calloc(1, sizeof(*env->sc_auth))) == NULL)
72
			return (-1);
73
48
		TAILQ_INIT(env->sc_auth);
74
48
	}
75
76
48
	return (0);
77
48
}
78
79
void
80
config_purge(struct httpd *env, unsigned int reset)
81
{
82
192
	struct privsep		*ps = env->sc_ps;
83
	struct server		*srv;
84
	struct auth		*auth;
85
	unsigned int		 what;
86
87
96
	what = ps->ps_what[privsep_process] & reset;
88
89

144
	if (what & CONFIG_SERVERS && env->sc_servers != NULL) {
90
192
		while ((srv = TAILQ_FIRST(env->sc_servers)) != NULL)
91
48
			server_purge(srv);
92
	}
93
94

192
	if (what & CONFIG_MEDIA && env->sc_mediatypes != NULL)
95
96
		media_purge(env->sc_mediatypes);
96
97

192
	if (what & CONFIG_AUTH && env->sc_auth != NULL) {
98
192
		while ((auth = TAILQ_FIRST(env->sc_auth)) != NULL) {
99
			auth_free(env->sc_auth, auth);
100
			free(auth);
101
		}
102
	}
103
96
}
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
96
	struct privsep		*ps = env->sc_ps;
164
48
	struct server_config	 s;
165
	int			 id;
166
48
	int			 fd, n, m;
167
48
	struct iovec		 iov[6];
168
	size_t			 c;
169
	unsigned int		 what;
170
171
	/* opens listening sockets etc. */
172
48
	if (server_privinit(srv) == -1)
173
		return (-1);
174
175
384
	for (id = 0; id < PROC_MAX; id++) {
176
144
		what = ps->ps_what[id];
177
178

288
		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
96
		memcpy(&s, &srv->srv_conf, sizeof(s));
188
189
		c = 0;
190
96
		iov[c].iov_base = &s;
191
96
		iov[c++].iov_len = sizeof(s);
192
96
		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

144
		if (id == PROC_SERVER &&
198
48
		    (srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) {
199
			/* XXX imsg code will close the fd after 1st call */
200
48
			n = -1;
201
48
			proc_range(ps, id, &n, &m);
202
192
			for (n = 0; n < m; n++) {
203
48
				if (srv->srv_s == -1)
204
					fd = -1;
205
48
				else if ((fd = dup(srv->srv_s)) == -1)
206
					return (-1);
207
144
				if (proc_composev_imsg(ps, id, n,
208
96
				    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
48
				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
48
			config_setserver_tls(env, srv);
226
48
		} else {
227
96
			if (proc_composev(ps, id, IMSG_CFG_SERVER,
228
96
			    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
	}
236
237
	/* Close server socket early to prevent fd exhaustion in the parent. */
238
48
	if (srv->srv_s != -1) {
239
48
		close(srv->srv_s);
240
48
		srv->srv_s = -1;
241
48
	}
242
243
48
	explicit_bzero(&srv->srv_conf.tls_ticket_key,
244
	    sizeof(srv->srv_conf.tls_ticket_key));
245
246
48
	return (0);
247
48
}
248
249
static int
250
config_settls(struct httpd *env, struct server *srv, enum tls_config_type type,
251
    const char *label, uint8_t *data, size_t len)
252
{
253
96
	struct privsep		*ps = env->sc_ps;
254
48
	struct server_config	*srv_conf = &srv->srv_conf;
255
48
	struct tls_config	 tls;
256
48
	struct iovec		 iov[2];
257
	size_t			 c;
258
259
48
	if (data == NULL || len == 0)
260
16
		return (0);
261
262
	DPRINTF("%s: sending tls %s for \"%s[%u]\" to %s fd %d", __func__,
263
	    label, srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
264
	    srv->srv_s);
265
266
32
	memset(&tls, 0, sizeof(tls));
267
32
	tls.id = srv_conf->id;
268
32
	tls.tls_type = type;
269
32
	tls.tls_len = len;
270
32
	tls.tls_chunk_offset = 0;
271
272
128
	while (len > 0) {
273
32
		tls.tls_chunk_len = len;
274
32
		if (tls.tls_chunk_len > (MAX_IMSG_DATA_SIZE - sizeof(tls)))
275
			tls.tls_chunk_len = MAX_IMSG_DATA_SIZE - sizeof(tls);
276
277
		c = 0;
278
32
		iov[c].iov_base = &tls;
279
32
		iov[c++].iov_len = sizeof(tls);
280
32
		iov[c].iov_base = data;
281
32
		iov[c++].iov_len = tls.tls_chunk_len;
282
283
32
		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
32
		tls.tls_chunk_offset += tls.tls_chunk_len;
290
32
		data += tls.tls_chunk_len;
291
32
		len -= tls.tls_chunk_len;
292
	}
293
294
32
	return (0);
295
48
}
296
297
int
298
config_setserver_tls(struct httpd *env, struct server *srv)
299
{
300
96
	struct server_config	*srv_conf = &srv->srv_conf;
301
302
48
	if ((srv_conf->flags & SRVFLAG_TLS) == 0)
303
32
		return (0);
304
305
16
	log_debug("%s: configuring tls for %s", __func__, srv_conf->name);
306
307
48
	if (config_settls(env, srv, TLS_CFG_CERT, "cert", srv_conf->tls_cert,
308
32
	    srv_conf->tls_cert_len) != 0)
309
		return (-1);
310
311
48
	if (config_settls(env, srv, TLS_CFG_KEY, "key", srv_conf->tls_key,
312
32
	    srv_conf->tls_key_len) != 0)
313
		return (-1);
314
315
32
	if (config_settls(env, srv, TLS_CFG_OCSP_STAPLE, "ocsp staple",
316
32
	    srv_conf->tls_ocsp_staple, srv_conf->tls_ocsp_staple_len) != 0)
317
		return (-1);
318
319
16
	return (0);
320
48
}
321
322
int
323
config_getserver_auth(struct httpd *env, struct server_config *srv_conf)
324
{
325
	struct privsep		*ps = env->sc_ps;
326
327
	if ((ps->ps_what[privsep_process] & CONFIG_AUTH) == 0 ||
328
	    (srv_conf->flags & SRVFLAG_AUTH) == 0)
329
		return (0);
330
331
	if ((srv_conf->auth = auth_byid(env->sc_auth,
332
	    srv_conf->auth_id)) == NULL)
333
		return (-1);
334
335
	return (0);
336
}
337
338
int
339
config_getserver_config(struct httpd *env, struct server *srv,
340
    struct imsg *imsg)
341
{
342
#ifdef DEBUG
343
	struct privsep		*ps = env->sc_ps;
344
#endif
345
	struct server_config	*srv_conf, *parent;
346
	uint8_t			*p = imsg->data;
347
	unsigned int		 f;
348
	size_t			 s;
349
350
	if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL)
351
		return (-1);
352
353
	IMSG_SIZE_CHECK(imsg, srv_conf);
354
	memcpy(srv_conf, p, sizeof(*srv_conf));
355
	s = sizeof(*srv_conf);
356
357
	/* Reset these variables to avoid free'ing invalid pointers */
358
	serverconfig_reset(srv_conf);
359
360
	TAILQ_FOREACH(parent, &srv->srv_hosts, entry) {
361
		if (strcmp(parent->name, srv_conf->name) == 0)
362
			break;
363
	}
364
	if (parent == NULL)
365
		parent = &srv->srv_conf;
366
367
	if (config_getserver_auth(env, srv_conf) != 0)
368
		goto fail;
369
370
	/*
371
	 * Get variable-length values for the virtual host.  The tls_* ones
372
	 * aren't needed in the virtual hosts unless we implement SNI.
373
	 */
374
	if (srv_conf->return_uri_len != 0) {
375
		if ((srv_conf->return_uri = get_data(p + s,
376
		    srv_conf->return_uri_len)) == NULL)
377
			goto fail;
378
		s += srv_conf->return_uri_len;
379
	}
380
381
	if (srv_conf->flags & SRVFLAG_LOCATION) {
382
		/* Inherit configuration from the parent */
383
		f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX;
384
		if ((srv_conf->flags & f) == 0) {
385
			srv_conf->flags |= parent->flags & f;
386
			(void)strlcpy(srv_conf->index, parent->index,
387
			    sizeof(srv_conf->index));
388
		}
389
390
		f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX;
391
		if ((srv_conf->flags & f) == 0)
392
			srv_conf->flags |= parent->flags & f;
393
394
		f = SRVFLAG_SOCKET|SRVFLAG_FCGI;
395
		if ((srv_conf->flags & f) == SRVFLAG_FCGI) {
396
			srv_conf->flags |= f;
397
			(void)strlcpy(srv_conf->socket, HTTPD_FCGI_SOCKET,
398
			    sizeof(srv_conf->socket));
399
		}
400
401
		f = SRVFLAG_ROOT;
402
		if ((srv_conf->flags & f) == 0) {
403
			srv_conf->flags |= parent->flags & f;
404
			(void)strlcpy(srv_conf->root, parent->root,
405
			    sizeof(srv_conf->root));
406
		}
407
408
		f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI;
409
		if ((srv_conf->flags & f) == 0)
410
			srv_conf->flags |= parent->flags & f;
411
412
		f = SRVFLAG_LOG|SRVFLAG_NO_LOG;
413
		if ((srv_conf->flags & f) == 0) {
414
			srv_conf->flags |= parent->flags & f;
415
			srv_conf->logformat = parent->logformat;
416
		}
417
418
		f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG;
419
		if ((srv_conf->flags & f) == 0)
420
			srv_conf->flags |= parent->flags & f;
421
422
		f = SRVFLAG_AUTH|SRVFLAG_NO_AUTH;
423
		if ((srv_conf->flags & f) == 0) {
424
			srv_conf->flags |= parent->flags & f;
425
			srv_conf->auth = parent->auth;
426
			srv_conf->auth_id = parent->auth_id;
427
			(void)strlcpy(srv_conf->auth_realm,
428
			    parent->auth_realm,
429
			    sizeof(srv_conf->auth_realm));
430
		}
431
432
		f = SRVFLAG_TLS;
433
		srv_conf->flags |= parent->flags & f;
434
435
		f = SRVFLAG_ACCESS_LOG;
436
		if ((srv_conf->flags & f) == 0) {
437
			srv_conf->flags |= parent->flags & f;
438
			(void)strlcpy(srv_conf->accesslog,
439
			    parent->accesslog,
440
			    sizeof(srv_conf->accesslog));
441
		}
442
443
		f = SRVFLAG_ERROR_LOG;
444
		if ((srv_conf->flags & f) == 0) {
445
			srv_conf->flags |= parent->flags & f;
446
			(void)strlcpy(srv_conf->errorlog,
447
			    parent->errorlog,
448
			    sizeof(srv_conf->errorlog));
449
		}
450
451
		f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK;
452
		if ((srv_conf->flags & f) == 0) {
453
			free(srv_conf->return_uri);
454
			srv_conf->flags |= parent->flags & f;
455
			srv_conf->return_code = parent->return_code;
456
			srv_conf->return_uri_len = parent->return_uri_len;
457
			if (srv_conf->return_uri_len &&
458
			    (srv_conf->return_uri =
459
			    strdup(parent->return_uri)) == NULL)
460
				goto fail;
461
		}
462
463
		f = SRVFLAG_DEFAULT_TYPE;
464
		if ((srv_conf->flags & f) == 0) {
465
			srv_conf->flags |= parent->flags & f;
466
			memcpy(&srv_conf->default_type,
467
			    &parent->default_type, sizeof(struct media_type));
468
		}
469
470
		f = SRVFLAG_SERVER_HSTS;
471
		srv_conf->flags |= parent->flags & f;
472
		srv_conf->hsts_max_age = parent->hsts_max_age;
473
		srv_conf->hsts_flags = parent->hsts_flags;
474
475
		memcpy(&srv_conf->timeout, &parent->timeout,
476
		    sizeof(srv_conf->timeout));
477
		srv_conf->maxrequests = parent->maxrequests;
478
		srv_conf->maxrequestbody = parent->maxrequestbody;
479
480
		DPRINTF("%s: %s %d location \"%s\", "
481
		    "parent \"%s[%u]\", flags: %s",
482
		    __func__, ps->ps_title[privsep_process], ps->ps_instance,
483
		    srv_conf->location, parent->name, parent->id,
484
		    printb_flags(srv_conf->flags, SRVFLAG_BITS));
485
	} else {
486
		/* Add a new "virtual" server */
487
		DPRINTF("%s: %s %d server \"%s[%u]\", parent \"%s[%u]\", "
488
		    "flags: %s", __func__,
489
		    ps->ps_title[privsep_process], ps->ps_instance,
490
		    srv_conf->name, srv_conf->id, parent->name, parent->id,
491
		    printb_flags(srv_conf->flags, SRVFLAG_BITS));
492
	}
493
494
	TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry);
495
496
	return (0);
497
498
 fail:
499
	serverconfig_free(srv_conf);
500
	free(srv_conf);
501
	return (-1);
502
}
503
504
int
505
config_getserver(struct httpd *env, struct imsg *imsg)
506
{
507
#ifdef DEBUG
508
	struct privsep		*ps = env->sc_ps;
509
#endif
510
	struct server		*srv = NULL;
511
	struct server_config	 srv_conf;
512
	uint8_t			*p = imsg->data;
513
	size_t			 s;
514
515
	IMSG_SIZE_CHECK(imsg, &srv_conf);
516
	memcpy(&srv_conf, p, sizeof(srv_conf));
517
	s = sizeof(srv_conf);
518
519
	/* Reset these variables to avoid free'ing invalid pointers */
520
	serverconfig_reset(&srv_conf);
521
522
	if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) {
523
		log_debug("%s: invalid message length", __func__);
524
		goto fail;
525
	}
526
527
	/* Check if server with matching listening socket already exists */
528
	if ((srv = server_byaddr((struct sockaddr *)
529
	    &srv_conf.ss, srv_conf.port)) != NULL) {
530
		/* Add "host" to existing listening server */
531
		if (imsg->fd != -1) {
532
			if (srv->srv_s == -1)
533
				srv->srv_s = imsg->fd;
534
			else
535
				close(imsg->fd);
536
		}
537
		return (config_getserver_config(env, srv, imsg));
538
	}
539
540
	if (srv_conf.flags & SRVFLAG_LOCATION)
541
		fatalx("invalid location");
542
543
	/* Otherwise create a new server */
544
	if ((srv = calloc(1, sizeof(*srv))) == NULL)
545
		goto fail;
546
547
	memcpy(&srv->srv_conf, &srv_conf, sizeof(srv->srv_conf));
548
	srv->srv_s = imsg->fd;
549
550
	if (config_getserver_auth(env, &srv->srv_conf) != 0)
551
		goto fail;
552
553
	SPLAY_INIT(&srv->srv_clients);
554
	TAILQ_INIT(&srv->srv_hosts);
555
556
	TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry);
557
	TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry);
558
559
	DPRINTF("%s: %s %d configuration \"%s[%u]\", flags: %s", __func__,
560
	    ps->ps_title[privsep_process], ps->ps_instance,
561
	    srv->srv_conf.name, srv->srv_conf.id,
562
	    printb_flags(srv->srv_conf.flags, SRVFLAG_BITS));
563
564
	/*
565
	 * Get all variable-length values for the parent server.
566
	 */
567
	if (srv->srv_conf.return_uri_len != 0) {
568
		if ((srv->srv_conf.return_uri = get_data(p + s,
569
		    srv->srv_conf.return_uri_len)) == NULL)
570
			goto fail;
571
		s += srv->srv_conf.return_uri_len;
572
	}
573
574
	return (0);
575
576
 fail:
577
	if (imsg->fd != -1)
578
		close(imsg->fd);
579
	if (srv != NULL)
580
		serverconfig_free(&srv->srv_conf);
581
	free(srv);
582
583
	return (-1);
584
}
585
586
static int
587
config_gettls(struct httpd *env, struct server_config *srv_conf,
588
    struct tls_config *tls_conf, const char *label, uint8_t *data, size_t len,
589
    uint8_t **outdata, size_t *outlen)
590
{
591
#ifdef DEBUG
592
	struct privsep		*ps = env->sc_ps;
593
#endif
594
595
	DPRINTF("%s: %s %d getting tls %s (%zu:%zu@%zu) for \"%s[%u]\"",
596
	    __func__, ps->ps_title[privsep_process], ps->ps_instance, label,
597
	    tls_conf->tls_len, len, tls_conf->tls_chunk_offset, srv_conf->name,
598
	    srv_conf->id);
599
600
	if (tls_conf->tls_chunk_offset == 0) {
601
		free(*outdata);
602
		*outlen = 0;
603
		if ((*outdata = calloc(1, tls_conf->tls_len)) == NULL)
604
			goto fail;
605
		*outlen = tls_conf->tls_len;
606
	}
607
608
	if (*outdata == NULL) {
609
		log_debug("%s: tls config invalid chunk sequence", __func__);
610
		goto fail;
611
	}
612
613
	if (*outlen != tls_conf->tls_len) {
614
		log_debug("%s: tls config length mismatch (%zu != %zu)",
615
		    __func__, *outlen, tls_conf->tls_len);
616
		goto fail;
617
	}
618
619
	if (len > (tls_conf->tls_len - tls_conf->tls_chunk_offset)) {
620
		log_debug("%s: tls config invalid chunk length", __func__);
621
		goto fail;
622
	}
623
624
	memcpy(*outdata + tls_conf->tls_chunk_offset, data, len);
625
626
	return (0);
627
628
 fail:
629
	return (-1);
630
}
631
632
int
633
config_getserver_tls(struct httpd *env, struct imsg *imsg)
634
{
635
	struct server_config	*srv_conf = NULL;
636
	struct tls_config	 tls_conf;
637
	uint8_t			*p = imsg->data;
638
	size_t			 len;
639
640
	IMSG_SIZE_CHECK(imsg, &tls_conf);
641
	memcpy(&tls_conf, p, sizeof(tls_conf));
642
643
	len = tls_conf.tls_chunk_len;
644
645
	if ((IMSG_DATA_SIZE(imsg) - sizeof(tls_conf)) < len) {
646
		log_debug("%s: invalid message length", __func__);
647
		goto fail;
648
	}
649
650
	p += sizeof(tls_conf);
651
652
	if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) {
653
		log_debug("%s: server not found", __func__);
654
		goto fail;
655
	}
656
657
	switch (tls_conf.tls_type) {
658
	case TLS_CFG_CERT:
659
		if (config_gettls(env, srv_conf, &tls_conf, "cert", p, len,
660
		    &srv_conf->tls_cert, &srv_conf->tls_cert_len) != 0)
661
			goto fail;
662
		break;
663
664
	case TLS_CFG_KEY:
665
		if (config_gettls(env, srv_conf, &tls_conf, "key", p, len,
666
		    &srv_conf->tls_key, &srv_conf->tls_key_len) != 0)
667
			goto fail;
668
		break;
669
670
	case TLS_CFG_OCSP_STAPLE:
671
		if (config_gettls(env, srv_conf, &tls_conf, "ocsp staple",
672
		    p, len, &srv_conf->tls_ocsp_staple,
673
		    &srv_conf->tls_ocsp_staple_len) != 0)
674
			goto fail;
675
		break;
676
677
	default:
678
		log_debug("%s: unknown tls config type %i\n",
679
		     __func__, tls_conf.tls_type);
680
		goto fail;
681
	}
682
683
	return (0);
684
685
 fail:
686
	return (-1);
687
}
688
689
int
690
config_setmedia(struct httpd *env, struct media_type *media)
691
{
692
864
	struct privsep		*ps = env->sc_ps;
693
	int			 id;
694
	unsigned int		 what;
695
696
3456
	for (id = 0; id < PROC_MAX; id++) {
697
1296
		what = ps->ps_what[id];
698
699

2160
		if ((what & CONFIG_MEDIA) == 0 || id == privsep_process)
700
			continue;
701
702
		DPRINTF("%s: sending media \"%s\" to %s", __func__,
703
		    media->media_name, ps->ps_title[id]);
704
705
432
		proc_compose(ps, id, IMSG_CFG_MEDIA, media, sizeof(*media));
706
432
	}
707
708
432
	return (0);
709
}
710
711
int
712
config_getmedia(struct httpd *env, struct imsg *imsg)
713
{
714
#ifdef DEBUG
715
	struct privsep		*ps = env->sc_ps;
716
#endif
717
	struct media_type	 media;
718
	uint8_t			*p = imsg->data;
719
720
	IMSG_SIZE_CHECK(imsg, &media);
721
	memcpy(&media, p, sizeof(media));
722
723
	if (media_add(env->sc_mediatypes, &media) == NULL) {
724
		log_debug("%s: failed to add media \"%s\"",
725
		    __func__, media.media_name);
726
		return (-1);
727
	}
728
729
	DPRINTF("%s: %s %d received media \"%s\"", __func__,
730
	    ps->ps_title[privsep_process], ps->ps_instance,
731
	    media.media_name);
732
733
	return (0);
734
}
735
736
int
737
config_setauth(struct httpd *env, struct auth *auth)
738
{
739
	struct privsep		*ps = env->sc_ps;
740
	int			 id;
741
	unsigned int		 what;
742
743
	for (id = 0; id < PROC_MAX; id++) {
744
		what = ps->ps_what[id];
745
746
		if ((what & CONFIG_AUTH) == 0 || id == privsep_process)
747
			continue;
748
749
		DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__,
750
		    auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]);
751
752
		proc_compose(ps, id, IMSG_CFG_AUTH, auth, sizeof(*auth));
753
	}
754
755
	return (0);
756
}
757
758
int
759
config_getauth(struct httpd *env, struct imsg *imsg)
760
{
761
#ifdef DEBUG
762
	struct privsep		*ps = env->sc_ps;
763
#endif
764
	struct auth		 auth;
765
	uint8_t			*p = imsg->data;
766
767
	IMSG_SIZE_CHECK(imsg, &auth);
768
	memcpy(&auth, p, sizeof(auth));
769
770
	if (auth_add(env->sc_auth, &auth) == NULL) {
771
		log_debug("%s: failed to add auth \"%s[%u]\"",
772
		    __func__, auth.auth_htpasswd, auth.auth_id);
773
		return (-1);
774
	}
775
776
	DPRINTF("%s: %s %d received auth \"%s[%u]\"", __func__,
777
	    ps->ps_title[privsep_process], ps->ps_instance,
778
	    auth.auth_htpasswd, auth.auth_id);
779
780
	return (0);
781
}