GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/relayd/config.c Lines: 219 513 42.7 %
Date: 2017-11-13 Branches: 112 342 32.7 %

Line Branch Exec Source
1
/*	$OpenBSD: config.c,v 1.33 2017/09/14 08:59:54 jsg Exp $	*/
2
3
/*
4
 * Copyright (c) 2011 - 2014 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/time.h>
22
#include <sys/uio.h>
23
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <unistd.h>
27
#include <limits.h>
28
#include <string.h>
29
#include <imsg.h>
30
31
#include "relayd.h"
32
33
int
34
config_init(struct relayd *env)
35
{
36
1112
	struct privsep	*ps = env->sc_ps;
37
	u_int		 what;
38
39
	/* Global configuration */
40
556
	if (privsep_process == PROC_PARENT) {
41
556
		env->sc_conf.timeout.tv_sec = CHECK_TIMEOUT / 1000;
42
556
		env->sc_conf.timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
43
556
		env->sc_conf.interval.tv_sec = CHECK_INTERVAL;
44
556
		env->sc_conf.interval.tv_usec = 0;
45
556
		env->sc_conf.prefork_relay = RELAY_NUMPROC;
46
556
		env->sc_conf.statinterval.tv_sec = RELAY_STATINTERVAL;
47
556
	}
48
49
556
	ps->ps_what[PROC_PARENT] = CONFIG_ALL;
50
556
	ps->ps_what[PROC_PFE] = CONFIG_ALL & ~CONFIG_PROTOS;
51
556
	ps->ps_what[PROC_HCE] = CONFIG_TABLES;
52
556
	ps->ps_what[PROC_CA] = CONFIG_RELAYS;
53
556
	ps->ps_what[PROC_RELAY] = CONFIG_RELAYS|
54
	    CONFIG_TABLES|CONFIG_PROTOS|CONFIG_CA_ENGINE;
55
56
	/* Other configuration */
57
556
	what = ps->ps_what[privsep_process];
58
556
	if (what & CONFIG_TABLES) {
59
1112
		if ((env->sc_tables =
60
1112
		    calloc(1, sizeof(*env->sc_tables))) == NULL)
61
			return (-1);
62
556
		TAILQ_INIT(env->sc_tables);
63
64
556
		memset(&env->sc_empty_table, 0, sizeof(env->sc_empty_table));
65
556
		env->sc_empty_table.conf.id = EMPTY_TABLE;
66
556
		env->sc_empty_table.conf.flags |= F_DISABLE;
67
556
		(void)strlcpy(env->sc_empty_table.conf.name, "empty",
68
		    sizeof(env->sc_empty_table.conf.name));
69
70
556
	}
71
556
	if (what & CONFIG_RDRS) {
72
1112
		if ((env->sc_rdrs =
73
1112
		    calloc(1, sizeof(*env->sc_rdrs))) == NULL)
74
			return (-1);
75
556
		TAILQ_INIT(env->sc_rdrs);
76
77
556
	}
78
556
	if (what & CONFIG_RELAYS) {
79
1112
		if ((env->sc_relays =
80
1112
		    calloc(1, sizeof(*env->sc_relays))) == NULL)
81
			return (-1);
82
556
		TAILQ_INIT(env->sc_relays);
83
1112
		if ((env->sc_pkeys =
84
1112
		    calloc(1, sizeof(*env->sc_pkeys))) == NULL)
85
			return (-1);
86
556
		TAILQ_INIT(env->sc_pkeys);
87
556
	}
88
556
	if (what & CONFIG_PROTOS) {
89
1112
		if ((env->sc_protos =
90
1112
		    calloc(1, sizeof(*env->sc_protos))) == NULL)
91
			return (-1);
92
556
		TAILQ_INIT(env->sc_protos);
93
94
556
		bzero(&env->sc_proto_default, sizeof(env->sc_proto_default));
95
556
		env->sc_proto_default.id = EMPTY_ID;
96
556
		env->sc_proto_default.flags = F_USED;
97
556
		env->sc_proto_default.tcpflags = TCPFLAG_DEFAULT;
98
556
		env->sc_proto_default.tcpbacklog = RELAY_BACKLOG;
99
556
		env->sc_proto_default.tlsflags = TLSFLAG_DEFAULT;
100
556
		(void)strlcpy(env->sc_proto_default.tlsciphers,
101
		    TLSCIPHERS_DEFAULT,
102
		    sizeof(env->sc_proto_default.tlsciphers));
103
556
		(void)strlcpy(env->sc_proto_default.tlsecdhcurve,
104
		    TLSECDHCURVE_DEFAULT,
105
		    sizeof(env->sc_proto_default.tlsecdhcurve));
106
556
		(void)strlcpy(env->sc_proto_default.tlsdhparams,
107
		    TLSDHPARAM_DEFAULT,
108
		    sizeof(env->sc_proto_default.tlsdhparams));
109
556
		env->sc_proto_default.type = RELAY_PROTO_TCP;
110
556
		(void)strlcpy(env->sc_proto_default.name, "default",
111
		    sizeof(env->sc_proto_default.name));
112
556
	}
113
556
	if (what & CONFIG_RTS) {
114
1112
		if ((env->sc_rts =
115
1112
		    calloc(1, sizeof(*env->sc_rts))) == NULL)
116
			return (-1);
117
556
		TAILQ_INIT(env->sc_rts);
118
556
	}
119
556
	if (what & CONFIG_ROUTES) {
120
1112
		if ((env->sc_routes =
121
1112
		    calloc(1, sizeof(*env->sc_routes))) == NULL)
122
			return (-1);
123
556
		TAILQ_INIT(env->sc_routes);
124
556
	}
125
126
556
	return (0);
127
556
}
128
129
void
130
config_purge(struct relayd *env, u_int reset)
131
{
132
2192
	struct privsep		*ps = env->sc_ps;
133
	struct table		*table;
134
	struct rdr		*rdr;
135
	struct address		*virt;
136
	struct protocol		*proto;
137
	struct relay_rule	*rule;
138
	struct relay		*rlay;
139
	struct netroute		*nr;
140
	struct router		*rt;
141
	struct ca_pkey		*pkey;
142
	u_int			 what;
143
144
1096
	what = ps->ps_what[privsep_process] & reset;
145
146

2192
	if (what & CONFIG_TABLES && env->sc_tables != NULL) {
147
2208
		while ((table = TAILQ_FIRST(env->sc_tables)) != NULL)
148
8
			purge_table(env, env->sc_tables, table);
149
1096
		env->sc_tablecount = 0;
150
1096
	}
151

2192
	if (what & CONFIG_RDRS && env->sc_rdrs != NULL) {
152
2192
		while ((rdr = TAILQ_FIRST(env->sc_rdrs)) != NULL) {
153
			TAILQ_REMOVE(env->sc_rdrs, rdr, entry);
154
			while ((virt = TAILQ_FIRST(&rdr->virts)) != NULL) {
155
				TAILQ_REMOVE(&rdr->virts, virt, entry);
156
				free(virt);
157
			}
158
			free(rdr);
159
		}
160
1096
		env->sc_rdrcount = 0;
161
1096
	}
162

1644
	if (what & CONFIG_RELAYS && env->sc_pkeys != NULL) {
163
1096
		while ((pkey = TAILQ_FIRST(env->sc_pkeys)) != NULL) {
164
			TAILQ_REMOVE(env->sc_pkeys, pkey, pkey_entry);
165
			free(pkey);
166
		}
167
	}
168

1644
	if (what & CONFIG_RELAYS && env->sc_relays != NULL) {
169
2192
		while ((rlay = TAILQ_FIRST(env->sc_relays)) != NULL)
170
548
			purge_relay(env, rlay);
171
548
		env->sc_relaycount = 0;
172
548
	}
173

2192
	if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
174
3288
		while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
175
1644
			TAILQ_REMOVE(env->sc_protos, proto, entry);
176
2720
			while ((rule = TAILQ_FIRST(&proto->rules)) != NULL)
177
812
				rule_delete(&proto->rules, rule);
178
548
			proto->rulecount = 0;
179
		}
180
	}
181

2192
	if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
182
2192
		while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
183
			TAILQ_REMOVE(env->sc_protos, proto, entry);
184
			free(proto->style);
185
			free(proto->tlscapass);
186
			free(proto);
187
		}
188
1096
		env->sc_protocount = 0;
189
1096
	}
190

2192
	if (what & CONFIG_RTS && env->sc_rts != NULL) {
191
2192
		while ((rt = TAILQ_FIRST(env->sc_rts)) != NULL) {
192
			TAILQ_REMOVE(env->sc_rts, rt, rt_entry);
193
			while ((nr = TAILQ_FIRST(&rt->rt_netroutes)) != NULL) {
194
				TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
195
				TAILQ_REMOVE(env->sc_routes, nr, nr_route);
196
				free(nr);
197
				env->sc_routecount--;
198
			}
199
			free(rt);
200
		}
201
1096
		env->sc_routercount = 0;
202
1096
	}
203

2192
	if (what & CONFIG_ROUTES && env->sc_routes != NULL) {
204
2192
		while ((nr = TAILQ_FIRST(env->sc_routes)) != NULL) {
205
			if ((rt = nr->nr_router) != NULL)
206
				TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
207
			TAILQ_REMOVE(env->sc_routes, nr, nr_route);
208
			free(nr);
209
		}
210
1096
		env->sc_routecount = 0;
211
1096
	}
212
1096
}
213
214
int
215
config_setreset(struct relayd *env, u_int reset)
216
{
217
	struct privsep	*ps = env->sc_ps;
218
	int		 id;
219
220
	for (id = 0; id < PROC_MAX; id++) {
221
		if ((reset & ps->ps_what[id]) == 0 ||
222
		    id == privsep_process)
223
			continue;
224
		proc_compose(ps, id, IMSG_CTL_RESET, &reset, sizeof(reset));
225
	}
226
227
	return (0);
228
}
229
230
int
231
config_getreset(struct relayd *env, struct imsg *imsg)
232
{
233
	u_int		 mode;
234
235
	IMSG_SIZE_CHECK(imsg, &mode);
236
	memcpy(&mode, imsg->data, sizeof(mode));
237
238
	config_purge(env, mode);
239
240
	return (0);
241
}
242
243
int
244
config_getcfg(struct relayd *env, struct imsg *imsg)
245
{
246
	struct privsep		*ps = env->sc_ps;
247
	struct table		*tb;
248
	struct host		*h, *ph;
249
	u_int			 what;
250
251
	if (IMSG_DATA_SIZE(imsg) != sizeof(struct relayd_config))
252
		return (0); /* ignore */
253
254
	/* Update runtime flags */
255
	memcpy(&env->sc_conf, imsg->data, sizeof(env->sc_conf));
256
257
	what = ps->ps_what[privsep_process];
258
259
	if (what & CONFIG_TABLES) {
260
		/* Update the tables */
261
		TAILQ_FOREACH(tb, env->sc_tables, entry) {
262
			TAILQ_FOREACH(h, &tb->hosts, entry) {
263
				if (h->conf.parentid && (ph = host_find(env,
264
				    h->conf.parentid)) != NULL) {
265
					SLIST_INSERT_HEAD(&ph->children,
266
					    h, child);
267
				}
268
			}
269
		}
270
	}
271
272
	if (env->sc_conf.flags & (F_TLS|F_TLSCLIENT)) {
273
		ssl_init(env);
274
		if (what & CONFIG_CA_ENGINE)
275
			ca_engine_init(env);
276
		if (tls_init() == -1)
277
			fatalx("unable to initialize TLS");
278
	}
279
280
	if (privsep_process != PROC_PARENT)
281
		proc_compose(env->sc_ps, PROC_PARENT, IMSG_CFG_DONE, NULL, 0);
282
283
	return (0);
284
}
285
286
int
287
config_settable(struct relayd *env, struct table *tb)
288
{
289
16
	struct privsep	*ps = env->sc_ps;
290
	struct host	*host;
291
	int		 id, c;
292
8
	struct iovec	 iov[2];
293
294
96
	for (id = 0; id < PROC_MAX; id++) {
295

72
		if ((ps->ps_what[id] & CONFIG_TABLES) == 0 ||
296
32
		    id == privsep_process)
297
			continue;
298
299
		/* XXX need to send table to pfe for control socket */
300

32
		if (id == PROC_HCE && tb->conf.check == CHECK_NOCHECK)
301
			continue;
302
303
		DPRINTF("%s: sending table %s %d to %s", __func__,
304
		    tb->conf.name, tb->conf.id, env->sc_ps->ps_title[id]);
305
306
		c = 0;
307
16
		iov[c].iov_base = &tb->conf;
308
16
		iov[c++].iov_len = sizeof(tb->conf);
309
16
		if (tb->sendbuf != NULL) {
310
			iov[c].iov_base = tb->sendbuf;
311
			iov[c++].iov_len = strlen(tb->sendbuf);
312
		}
313
314
16
		proc_composev(ps, id, IMSG_CFG_TABLE, iov, c);
315
316
64
		TAILQ_FOREACH(host, &tb->hosts, entry) {
317
16
			proc_compose(ps, id, IMSG_CFG_HOST,
318
16
			    &host->conf, sizeof(host->conf));
319
		}
320
	}
321
322
8
	return (0);
323
8
}
324
325
int
326
config_gettable(struct relayd *env, struct imsg *imsg)
327
{
328
	struct table		*tb;
329
	size_t			 sb;
330
	u_int8_t		*p = imsg->data;
331
	size_t			 s;
332
333
	if ((tb = calloc(1, sizeof(*tb))) == NULL)
334
		return (-1);
335
336
	IMSG_SIZE_CHECK(imsg, &tb->conf);
337
	memcpy(&tb->conf, p, sizeof(tb->conf));
338
	s = sizeof(tb->conf);
339
340
	sb = IMSG_DATA_SIZE(imsg) - s;
341
	if (sb > 0) {
342
		if ((tb->sendbuf = get_string(p + s, sb)) == NULL) {
343
			free(tb);
344
			return (-1);
345
		}
346
	}
347
348
	TAILQ_INIT(&tb->hosts);
349
	TAILQ_INSERT_TAIL(env->sc_tables, tb, entry);
350
351
	env->sc_tablecount++;
352
353
	DPRINTF("%s: %s %d received table %d (%s)", __func__,
354
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
355
	    tb->conf.id, tb->conf.name);
356
357
	return (0);
358
}
359
360
int
361
config_gethost(struct relayd *env, struct imsg *imsg)
362
{
363
	struct table		*tb;
364
	struct host		*host;
365
366
	if ((host = calloc(1, sizeof(*host))) == NULL)
367
		return (-1);
368
369
	IMSG_SIZE_CHECK(imsg, &host->conf);
370
	memcpy(&host->conf, imsg->data, sizeof(host->conf));
371
372
	if (host_find(env, host->conf.id) != NULL) {
373
		log_debug("%s: host %d already exists",
374
		    __func__, host->conf.id);
375
		free(host);
376
		return (-1);
377
	}
378
379
	if ((tb = table_find(env, host->conf.tableid)) == NULL) {
380
		log_debug("%s: "
381
		    "received host for unknown table %d", __func__,
382
		    host->conf.tableid);
383
		free(host);
384
		return (-1);
385
	}
386
387
	host->tablename = tb->conf.name;
388
	host->cte.s = -1;
389
390
	SLIST_INIT(&host->children);
391
	TAILQ_INSERT_TAIL(&tb->hosts, host, entry);
392
	TAILQ_INSERT_TAIL(&env->sc_hosts, host, globalentry);
393
394
	DPRINTF("%s: %s %d received host %s for table %s", __func__,
395
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
396
	    host->conf.name, tb->conf.name);
397
398
	return (0);
399
}
400
401
int
402
config_setrdr(struct relayd *env, struct rdr *rdr)
403
{
404
	struct privsep	*ps = env->sc_ps;
405
	struct address	*virt;
406
	int		 id;
407
408
	for (id = 0; id < PROC_MAX; id++) {
409
		if ((ps->ps_what[id] & CONFIG_RDRS) == 0 ||
410
		    id == privsep_process)
411
			continue;
412
413
		DPRINTF("%s: sending rdr %s to %s", __func__,
414
		    rdr->conf.name, ps->ps_title[id]);
415
416
		proc_compose(ps, id, IMSG_CFG_RDR,
417
		    &rdr->conf, sizeof(rdr->conf));
418
419
		TAILQ_FOREACH(virt, &rdr->virts, entry) {
420
			virt->rdrid = rdr->conf.id;
421
			proc_compose(ps, id, IMSG_CFG_VIRT,
422
			    virt, sizeof(*virt));
423
		}
424
	}
425
426
	return (0);
427
}
428
429
int
430
config_getrdr(struct relayd *env, struct imsg *imsg)
431
{
432
	struct rdr		*rdr;
433
434
	if ((rdr = calloc(1, sizeof(*rdr))) == NULL)
435
		return (-1);
436
437
	IMSG_SIZE_CHECK(imsg, &rdr->conf);
438
	memcpy(&rdr->conf, imsg->data, sizeof(rdr->conf));
439
440
	if ((rdr->table = table_find(env, rdr->conf.table_id)) == NULL) {
441
		log_debug("%s: table not found", __func__);
442
		free(rdr);
443
		return (-1);
444
	}
445
	if ((rdr->backup = table_find(env, rdr->conf.backup_id)) == NULL) {
446
		rdr->conf.backup_id = EMPTY_TABLE;
447
		rdr->backup = &env->sc_empty_table;
448
	}
449
450
	TAILQ_INIT(&rdr->virts);
451
	TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry);
452
453
	env->sc_rdrcount++;
454
455
	DPRINTF("%s: %s %d received rdr %s", __func__,
456
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
457
	    rdr->conf.name);
458
459
	return (0);
460
}
461
462
int
463
config_getvirt(struct relayd *env, struct imsg *imsg)
464
{
465
	struct rdr	*rdr;
466
	struct address	*virt;
467
468
	IMSG_SIZE_CHECK(imsg, virt);
469
470
	if ((virt = calloc(1, sizeof(*virt))) == NULL)
471
		return (-1);
472
	memcpy(virt, imsg->data, sizeof(*virt));
473
474
	if ((rdr = rdr_find(env, virt->rdrid)) == NULL) {
475
		log_debug("%s: rdr not found", __func__);
476
		free(virt);
477
		return (-1);
478
	}
479
480
	TAILQ_INSERT_TAIL(&rdr->virts, virt, entry);
481
482
	DPRINTF("%s: %s %d received address for rdr %s", __func__,
483
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
484
	    rdr->conf.name);
485
486
	return (0);
487
}
488
489
int
490
config_setrt(struct relayd *env, struct router *rt)
491
{
492
	struct privsep	*ps = env->sc_ps;
493
	struct netroute	*nr;
494
	int		 id;
495
496
	for (id = 0; id < PROC_MAX; id++) {
497
		if ((ps->ps_what[id] & CONFIG_RTS) == 0 ||
498
		    id == privsep_process)
499
			continue;
500
501
		DPRINTF("%s: sending router %s to %s tbl %d", __func__,
502
		    rt->rt_conf.name, ps->ps_title[id], rt->rt_conf.gwtable);
503
504
		proc_compose(ps, id, IMSG_CFG_ROUTER,
505
		    &rt->rt_conf, sizeof(rt->rt_conf));
506
507
		TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry) {
508
			proc_compose(ps, id, IMSG_CFG_ROUTE,
509
			    &nr->nr_conf, sizeof(nr->nr_conf));
510
		}
511
	}
512
513
	return (0);
514
}
515
516
int
517
config_getrt(struct relayd *env, struct imsg *imsg)
518
{
519
	struct router		*rt;
520
521
	if ((rt = calloc(1, sizeof(*rt))) == NULL)
522
		return (-1);
523
524
	IMSG_SIZE_CHECK(imsg, &rt->rt_conf);
525
	memcpy(&rt->rt_conf, imsg->data, sizeof(rt->rt_conf));
526
527
	if ((rt->rt_gwtable = table_find(env, rt->rt_conf.gwtable)) == NULL) {
528
		log_debug("%s: table not found", __func__);
529
		free(rt);
530
		return (-1);
531
	}
532
533
	TAILQ_INIT(&rt->rt_netroutes);
534
	TAILQ_INSERT_TAIL(env->sc_rts, rt, rt_entry);
535
536
	env->sc_routercount++;
537
538
	DPRINTF("%s: %s %d received router %s", __func__,
539
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
540
	    rt->rt_conf.name);
541
542
	return (0);
543
}
544
545
int
546
config_getroute(struct relayd *env, struct imsg *imsg)
547
{
548
	struct router		*rt;
549
	struct netroute		*nr;
550
551
	if ((nr = calloc(1, sizeof(*nr))) == NULL)
552
		return (-1);
553
554
	IMSG_SIZE_CHECK(imsg, &nr->nr_conf);
555
	memcpy(&nr->nr_conf, imsg->data, sizeof(nr->nr_conf));
556
557
	if (route_find(env, nr->nr_conf.id) != NULL) {
558
		log_debug("%s: route %d already exists",
559
		    __func__, nr->nr_conf.id);
560
		free(nr);
561
		return (-1);
562
	}
563
564
	if ((rt = router_find(env, nr->nr_conf.routerid)) == NULL) {
565
		log_debug("%s: received route for unknown router", __func__);
566
		free(nr);
567
		return (-1);
568
	}
569
570
	nr->nr_router = rt;
571
572
	TAILQ_INSERT_TAIL(env->sc_routes, nr, nr_route);
573
	TAILQ_INSERT_TAIL(&rt->rt_netroutes, nr, nr_entry);
574
575
	env->sc_routecount++;
576
577
	DPRINTF("%s: %s %d received route %d for router %s", __func__,
578
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
579
	    nr->nr_conf.id, rt->rt_conf.name);
580
581
	return (0);
582
}
583
584
int
585
config_setproto(struct relayd *env, struct protocol *proto)
586
{
587
1096
	struct privsep		*ps = env->sc_ps;
588
	int			 id;
589
548
	struct iovec		 iov[IOV_MAX];
590
	size_t			 c;
591
592
6576
	for (id = 0; id < PROC_MAX; id++) {
593

3836
		if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
594
1096
		    id == privsep_process)
595
			continue;
596
597
		DPRINTF("%s: sending protocol %s to %s", __func__,
598
		    proto->name, ps->ps_title[id]);
599
600
		c = 0;
601
548
		iov[c].iov_base = proto;
602
548
		iov[c++].iov_len = sizeof(*proto);
603
604
548
		if (proto->style != NULL) {
605
			iov[c].iov_base = proto->style;
606
			iov[c++].iov_len = strlen(proto->style) + 1;
607
		}
608
609
548
		proc_composev(ps, id, IMSG_CFG_PROTO, iov, c);
610
548
	}
611
612
548
	return (0);
613
548
}
614
615
int
616
config_setrule(struct relayd *env, struct protocol *proto)
617
{
618
1096
	struct privsep		*ps = env->sc_ps;
619
	struct relay_rule	*rule;
620
548
	struct iovec		 iov[IOV_MAX];
621
	int			 id;
622
	size_t			 c, i;
623
624
6576
	for (id = 0; id < PROC_MAX; id++) {
625

3836
		if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
626
1096
		    id == privsep_process)
627
			continue;
628
629
		DPRINTF("%s: sending rules %s to %s", __func__,
630
		    proto->name, ps->ps_title[id]);
631
632
		/* Now send all the rules */
633
2720
		TAILQ_FOREACH(rule, &proto->rules, rule_entry) {
634
812
			rule->rule_protoid = proto->id;
635
812
			bzero(&rule->rule_ctl, sizeof(rule->rule_ctl));
636
			c = 0;
637
812
			iov[c].iov_base = rule;
638
812
			iov[c++].iov_len = sizeof(*rule);
639
9744
			for (i = 1; i < KEY_TYPE_MAX; i++) {
640
4060
				if (rule->rule_kv[i].kv_key != NULL) {
641
748
					rule->rule_ctl.kvlen[i].key =
642
748
					    strlen(rule->rule_kv[i].kv_key);
643
748
					iov[c].iov_base =
644
748
					    rule->rule_kv[i].kv_key;
645
748
					iov[c++].iov_len =
646
748
					    rule->rule_ctl.kvlen[i].key;
647
748
				} else
648
3312
					rule->rule_ctl.kvlen[i].key = -1;
649
4060
				if (rule->rule_kv[i].kv_value != NULL) {
650
724
					rule->rule_ctl.kvlen[i].value =
651
724
					    strlen(rule->rule_kv[i].kv_value);
652
724
					iov[c].iov_base =
653
724
					    rule->rule_kv[i].kv_value;
654
724
					iov[c++].iov_len =
655
724
					    rule->rule_ctl.kvlen[i].value;
656
724
				} else
657
3336
					rule->rule_ctl.kvlen[i].value = -1;
658
			}
659
660
812
			proc_composev(ps, id, IMSG_CFG_RULE, iov, c);
661
		}
662
	}
663
664
548
	return (0);
665
548
}
666
667
int
668
config_getproto(struct relayd *env, struct imsg *imsg)
669
{
670
	struct protocol		*proto;
671
	size_t			 styl;
672
	size_t			 s;
673
	u_int8_t		*p = imsg->data;
674
675
	if ((proto = calloc(1, sizeof(*proto))) == NULL)
676
		return (-1);
677
678
	IMSG_SIZE_CHECK(imsg, proto);
679
	memcpy(proto, p, sizeof(*proto));
680
	s = sizeof(*proto);
681
682
	styl = IMSG_DATA_SIZE(imsg) - s;
683
	proto->style = NULL;
684
	if (styl > 0) {
685
		if ((proto->style = get_string(p + s, styl - 1)) == NULL) {
686
			free(proto);
687
			return (-1);
688
		}
689
	}
690
691
	TAILQ_INIT(&proto->rules);
692
	proto->tlscapass = NULL;
693
694
	TAILQ_INSERT_TAIL(env->sc_protos, proto, entry);
695
696
	env->sc_protocount++;
697
698
	DPRINTF("%s: %s %d received protocol %s", __func__,
699
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
700
	    proto->name);
701
702
	return (0);
703
}
704
705
int
706
config_getrule(struct relayd *env, struct imsg *imsg)
707
{
708
	struct protocol		*proto;
709
	struct relay_rule	*rule;
710
	size_t			 s, i;
711
	u_int8_t		*p = imsg->data;
712
	ssize_t			 len;
713
714
	if ((rule = calloc(1, sizeof(*rule))) == NULL)
715
		return (-1);
716
717
	IMSG_SIZE_CHECK(imsg, rule);
718
	memcpy(rule, p, sizeof(*rule));
719
	s = sizeof(*rule);
720
	len = IMSG_DATA_SIZE(imsg) - s;
721
722
	if ((proto = proto_find(env, rule->rule_protoid)) == NULL) {
723
		free(rule);
724
		return (-1);
725
	}
726
727
#define GETKV(_n, _f)	{						\
728
	if (rule->rule_ctl.kvlen[_n]._f >= 0) {				\
729
		/* Also accept "empty" 0-length strings */		\
730
		if ((len < rule->rule_ctl.kvlen[_n]._f) ||		\
731
		    (rule->rule_kv[_n].kv_##_f =			\
732
		    get_string(p + s,					\
733
		    rule->rule_ctl.kvlen[_n]._f)) == NULL) {		\
734
			free(rule);					\
735
			return (-1);					\
736
		}							\
737
		s += rule->rule_ctl.kvlen[_n]._f;			\
738
		len -= rule->rule_ctl.kvlen[_n]._f;			\
739
									\
740
		DPRINTF("%s: %s %s (len %ld, option %d): %s", __func__,	\
741
		    #_n, #_f, rule->rule_ctl.kvlen[_n]._f,		\
742
		    rule->rule_kv[_n].kv_option,			\
743
		    rule->rule_kv[_n].kv_##_f);				\
744
	}								\
745
}
746
747
	memset(&rule->rule_kv[0], 0, sizeof(struct kv));
748
	for (i = 1; i < KEY_TYPE_MAX; i++) {
749
		TAILQ_INIT(&rule->rule_kv[i].kv_children);
750
		GETKV(i, key);
751
		GETKV(i, value);
752
	}
753
754
	if (rule->rule_labelname[0])
755
		rule->rule_label = label_name2id(rule->rule_labelname);
756
757
	if (rule->rule_tagname[0])
758
		rule->rule_tag = tag_name2id(rule->rule_tagname);
759
760
	if (rule->rule_taggedname[0])
761
		rule->rule_tagged = tag_name2id(rule->rule_taggedname);
762
763
	rule->rule_id = proto->rulecount++;
764
765
	TAILQ_INSERT_TAIL(&proto->rules, rule, rule_entry);
766
767
	DPRINTF("%s: %s %d received rule %u for protocol %s", __func__,
768
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
769
	    rule->rule_id, proto->name);
770
771
	return (0);
772
}
773
774
int
775
config_setrelay(struct relayd *env, struct relay *rlay)
776
{
777
1096
	struct privsep		*ps = env->sc_ps;
778
548
	struct ctl_relaytable	 crt;
779
	struct relay_table	*rlt;
780
548
	struct relay_config	 rl;
781
	int			 id;
782
548
	int			 fd, n, m;
783
548
	struct iovec		 iov[6];
784
	size_t			 c;
785
	u_int			 what;
786
787
	/* opens listening sockets etc. */
788
548
	if (relay_privinit(rlay) == -1)
789
		return (-1);
790
791
6576
	for (id = 0; id < PROC_MAX; id++) {
792
2740
		what = ps->ps_what[id];
793
794

4932
		if ((what & CONFIG_RELAYS) == 0 || id == privsep_process)
795
			continue;
796
797
		DPRINTF("%s: sending relay %s to %s fd %d", __func__,
798
		    rlay->rl_conf.name, ps->ps_title[id], rlay->rl_s);
799
800
1644
		memcpy(&rl, &rlay->rl_conf, sizeof(rl));
801
802
		c = 0;
803
1644
		iov[c].iov_base = &rl;
804
1644
		iov[c++].iov_len = sizeof(rl);
805
1644
		if (rl.tls_cert_len) {
806
396
			iov[c].iov_base = rlay->rl_tls_cert;
807
396
			iov[c++].iov_len = rl.tls_cert_len;
808
396
		}
809

2192
		if ((what & CONFIG_CA_ENGINE) == 0 &&
810
548
		    rl.tls_key_len) {
811
132
			iov[c].iov_base = rlay->rl_tls_key;
812
132
			iov[c++].iov_len = rl.tls_key_len;
813
132
		} else
814
1512
			rl.tls_key_len = 0;
815
1644
		if (rl.tls_ca_len) {
816
			iov[c].iov_base = rlay->rl_tls_ca;
817
			iov[c++].iov_len = rl.tls_ca_len;
818
		}
819
1644
		if (rl.tls_cacert_len) {
820
48
			iov[c].iov_base = rlay->rl_tls_cacert;
821
48
			iov[c++].iov_len = rl.tls_cacert_len;
822
48
		}
823

2192
		if ((what & CONFIG_CA_ENGINE) == 0 &&
824
548
		    rl.tls_cakey_len) {
825
16
			iov[c].iov_base = rlay->rl_tls_cakey;
826
16
			iov[c++].iov_len = rl.tls_cakey_len;
827
16
		} else
828
1628
			rl.tls_cakey_len = 0;
829
830
1644
		if (id == PROC_RELAY) {
831
			/* XXX imsg code will close the fd after 1st call */
832
548
			n = -1;
833
548
			proc_range(ps, id, &n, &m);
834
2192
			for (n = 0; n < m; n++) {
835
548
				if ((fd = dup(rlay->rl_s)) == -1)
836
					return (-1);
837
1644
				if (proc_composev_imsg(ps, id, n,
838
1096
				    IMSG_CFG_RELAY, -1, fd, iov, c) != 0) {
839
					log_warn("%s: failed to compose "
840
					    "IMSG_CFG_RELAY imsg for `%s'",
841
					    __func__, rlay->rl_conf.name);
842
					return (-1);
843
				}
844
845
				/* Prevent fd exhaustion in the parent. */
846
548
				if (proc_flush_imsg(ps, id, n) == -1) {
847
					log_warn("%s: failed to flush "
848
					    "IMSG_CFG_RELAY imsg for `%s'",
849
					    __func__, rlay->rl_conf.name);
850
					return (-1);
851
				}
852
			}
853
		} else {
854
2192
			if (proc_composev(ps, id,
855
2192
			    IMSG_CFG_RELAY, iov, c) != 0) {
856
				log_warn("%s: failed to compose "
857
				    "IMSG_CFG_RELAY imsg for `%s'",
858
				    __func__, rlay->rl_conf.name);
859
				return (-1);
860
			}
861
		}
862
863
1644
		if ((what & CONFIG_TABLES) == 0)
864
			continue;
865
866
		/* Now send the tables associated to this relay */
867
2224
		TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
868
16
			crt.id = rlt->rlt_table->conf.id;
869
16
			crt.relayid = rlay->rl_conf.id;
870
16
			crt.mode = rlt->rlt_mode;
871
16
			crt.flags = rlt->rlt_flags;
872
873
			c = 0;
874
16
			iov[c].iov_base = &crt;
875
16
			iov[c++].iov_len = sizeof(crt);
876
877
16
			proc_composev(ps, id, IMSG_CFG_RELAY_TABLE, iov, c);
878
		}
879
	}
880
881
	/* Close server socket early to prevent fd exhaustion in the parent. */
882
548
	if (rlay->rl_s != -1) {
883
548
		close(rlay->rl_s);
884
548
		rlay->rl_s = -1;
885
548
	}
886
887
548
	return (0);
888
548
}
889
890
int
891
config_getrelay(struct relayd *env, struct imsg *imsg)
892
{
893
	struct privsep		*ps = env->sc_ps;
894
	struct relay		*rlay;
895
	u_int8_t		*p = imsg->data;
896
	size_t			 s;
897
898
	if ((rlay = calloc(1, sizeof(*rlay))) == NULL)
899
		return (-1);
900
901
	IMSG_SIZE_CHECK(imsg, &rlay->rl_conf);
902
	memcpy(&rlay->rl_conf, p, sizeof(rlay->rl_conf));
903
	s = sizeof(rlay->rl_conf);
904
905
	rlay->rl_s = imsg->fd;
906
907
	if (ps->ps_what[privsep_process] & CONFIG_PROTOS) {
908
		if (rlay->rl_conf.proto == EMPTY_ID)
909
			rlay->rl_proto = &env->sc_proto_default;
910
		else if ((rlay->rl_proto =
911
		    proto_find(env, rlay->rl_conf.proto)) == NULL) {
912
			log_debug("%s: unknown protocol", __func__);
913
			goto fail;
914
		}
915
	}
916
917
	if ((off_t)(IMSG_DATA_SIZE(imsg) - s) <
918
	    (rlay->rl_conf.tls_cert_len +
919
	    rlay->rl_conf.tls_key_len +
920
	    rlay->rl_conf.tls_ca_len +
921
	    rlay->rl_conf.tls_cacert_len +
922
	    rlay->rl_conf.tls_cakey_len)) {
923
		log_debug("%s: invalid message length", __func__);
924
		goto fail;
925
	}
926
927
	if (rlay->rl_conf.tls_cert_len) {
928
		if ((rlay->rl_tls_cert = get_data(p + s,
929
		    rlay->rl_conf.tls_cert_len)) == NULL)
930
			goto fail;
931
		s += rlay->rl_conf.tls_cert_len;
932
	}
933
	if (rlay->rl_conf.tls_key_len) {
934
		if ((rlay->rl_tls_key = get_data(p + s,
935
		    rlay->rl_conf.tls_key_len)) == NULL)
936
			goto fail;
937
		s += rlay->rl_conf.tls_key_len;
938
	}
939
	if (rlay->rl_conf.tls_ca_len) {
940
		if ((rlay->rl_tls_ca = get_data(p + s,
941
		    rlay->rl_conf.tls_ca_len)) == NULL)
942
			goto fail;
943
		s += rlay->rl_conf.tls_ca_len;
944
	}
945
	if (rlay->rl_conf.tls_cacert_len) {
946
		if ((rlay->rl_tls_cacert = get_data(p + s,
947
		    rlay->rl_conf.tls_cacert_len)) == NULL)
948
			goto fail;
949
		s += rlay->rl_conf.tls_cacert_len;
950
	}
951
	if (rlay->rl_conf.tls_cakey_len) {
952
		if ((rlay->rl_tls_cakey = get_data(p + s,
953
		    rlay->rl_conf.tls_cakey_len)) == NULL)
954
			goto fail;
955
		s += rlay->rl_conf.tls_cakey_len;
956
	}
957
958
	TAILQ_INIT(&rlay->rl_tables);
959
	TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry);
960
961
	env->sc_relaycount++;
962
963
	DPRINTF("%s: %s %d received relay %s", __func__,
964
	    ps->ps_title[privsep_process], ps->ps_instance,
965
	    rlay->rl_conf.name);
966
967
	return (0);
968
969
 fail:
970
	free(rlay->rl_tls_cert);
971
	free(rlay->rl_tls_key);
972
	free(rlay->rl_tls_ca);
973
	close(rlay->rl_s);
974
	free(rlay);
975
	return (-1);
976
}
977
978
int
979
config_getrelaytable(struct relayd *env, struct imsg *imsg)
980
{
981
	struct relay_table	*rlt = NULL;
982
	struct ctl_relaytable	 crt;
983
	struct relay		*rlay;
984
	struct table		*table;
985
	u_int8_t		*p = imsg->data;
986
987
	IMSG_SIZE_CHECK(imsg, &crt);
988
	memcpy(&crt, p, sizeof(crt));
989
990
	if ((rlay = relay_find(env, crt.relayid)) == NULL) {
991
		log_debug("%s: unknown relay", __func__);
992
		goto fail;
993
	}
994
995
	if ((table = table_find(env, crt.id)) == NULL) {
996
		log_debug("%s: unknown table", __func__);
997
		goto fail;
998
	}
999
1000
	if ((rlt = calloc(1, sizeof(*rlt))) == NULL)
1001
		goto fail;
1002
1003
	rlt->rlt_table = table;
1004
	rlt->rlt_mode = crt.mode;
1005
	rlt->rlt_flags = crt.flags;
1006
1007
	TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
1008
1009
	DPRINTF("%s: %s %d received relay table %s for relay %s", __func__,
1010
	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
1011
	    table->conf.name, rlay->rl_conf.name);
1012
1013
	return (0);
1014
1015
 fail:
1016
	free(rlt);
1017
	return (-1);
1018
}