GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/iked/config.c Lines: 0 346 0.0 %
Date: 2016-12-06 Branches: 0 194 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: config.c,v 1.42 2016/06/01 11:16:41 patrick Exp $	*/
2
3
/*
4
 * Copyright (c) 2010-2013 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/queue.h>
20
#include <sys/wait.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <unistd.h>
27
#include <string.h>
28
#include <signal.h>
29
#include <errno.h>
30
#include <err.h>
31
#include <pwd.h>
32
#include <event.h>
33
34
#include "iked.h"
35
#include "ikev2.h"
36
37
struct iked_sa *
38
config_new_sa(struct iked *env, int initiator)
39
{
40
	struct iked_sa	*sa;
41
42
	if ((sa = calloc(1, sizeof(*sa))) == NULL)
43
		return (NULL);
44
45
	TAILQ_INIT(&sa->sa_proposals);
46
	TAILQ_INIT(&sa->sa_childsas);
47
	TAILQ_INIT(&sa->sa_flows);
48
	TAILQ_INIT(&sa->sa_requests);
49
	TAILQ_INIT(&sa->sa_responses);
50
	sa->sa_hdr.sh_initiator = initiator;
51
	sa->sa_type = IKED_SATYPE_LOCAL;
52
53
	if (initiator)
54
		sa->sa_hdr.sh_ispi = config_getspi();
55
	else
56
		sa->sa_hdr.sh_rspi = config_getspi();
57
58
	gettimeofday(&sa->sa_timecreated, NULL);
59
	memcpy(&sa->sa_timeused, &sa->sa_timecreated, sizeof(sa->sa_timeused));
60
61
	return (sa);
62
}
63
64
uint64_t
65
config_getspi(void)
66
{
67
	uint64_t	 spi;
68
69
	do {
70
		arc4random_buf(&spi, sizeof spi);
71
	} while (spi == 0);
72
73
	return (spi);
74
}
75
76
void
77
config_free_kex(struct iked_kex *kex)
78
{
79
	if (kex == NULL)
80
		return;
81
82
	ibuf_release(kex->kex_inonce);
83
	ibuf_release(kex->kex_rnonce);
84
85
	if (kex->kex_dhgroup != NULL)
86
		group_free(kex->kex_dhgroup);
87
	ibuf_release(kex->kex_dhiexchange);
88
	ibuf_release(kex->kex_dhrexchange);
89
90
	free(kex);
91
}
92
93
void
94
config_free_sa(struct iked *env, struct iked_sa *sa)
95
{
96
	timer_del(env, &sa->sa_timer);
97
	timer_del(env, &sa->sa_rekey);
98
99
	config_free_proposals(&sa->sa_proposals, 0);
100
	config_free_childsas(env, &sa->sa_childsas, NULL, NULL);
101
	sa_free_flows(env, &sa->sa_flows);
102
103
	if (sa->sa_addrpool) {
104
		(void)RB_REMOVE(iked_addrpool, &env->sc_addrpool, sa);
105
		free(sa->sa_addrpool);
106
	}
107
	if (sa->sa_addrpool6) {
108
		(void)RB_REMOVE(iked_addrpool6, &env->sc_addrpool6, sa);
109
		free(sa->sa_addrpool6);
110
	}
111
112
	if (sa->sa_policy) {
113
		TAILQ_REMOVE(&sa->sa_policy->pol_sapeers, sa, sa_peer_entry);
114
		policy_unref(env, sa->sa_policy);
115
	}
116
117
	ikev2_msg_flushqueue(env, &sa->sa_requests);
118
	ikev2_msg_flushqueue(env, &sa->sa_responses);
119
120
	ibuf_release(sa->sa_inonce);
121
	ibuf_release(sa->sa_rnonce);
122
123
	if (sa->sa_dhgroup != NULL)
124
		group_free(sa->sa_dhgroup);
125
	ibuf_release(sa->sa_dhiexchange);
126
	ibuf_release(sa->sa_dhrexchange);
127
128
	hash_free(sa->sa_prf);
129
	hash_free(sa->sa_integr);
130
	cipher_free(sa->sa_encr);
131
132
	ibuf_release(sa->sa_key_d);
133
	ibuf_release(sa->sa_key_iauth);
134
	ibuf_release(sa->sa_key_rauth);
135
	ibuf_release(sa->sa_key_iencr);
136
	ibuf_release(sa->sa_key_rencr);
137
	ibuf_release(sa->sa_key_iprf);
138
	ibuf_release(sa->sa_key_rprf);
139
140
	ibuf_release(sa->sa_1stmsg);
141
	ibuf_release(sa->sa_2ndmsg);
142
143
	ibuf_release(sa->sa_iid.id_buf);
144
	ibuf_release(sa->sa_rid.id_buf);
145
	ibuf_release(sa->sa_icert.id_buf);
146
	ibuf_release(sa->sa_rcert.id_buf);
147
148
	ibuf_release(sa->sa_eap.id_buf);
149
	free(sa->sa_eapid);
150
	ibuf_release(sa->sa_eapmsk);
151
152
	free(sa);
153
}
154
155
struct iked_policy *
156
config_new_policy(struct iked *env)
157
{
158
	struct iked_policy	*pol;
159
160
	if ((pol = calloc(1, sizeof(*pol))) == NULL)
161
		return (NULL);
162
163
	/* XXX caller does this again */
164
	TAILQ_INIT(&pol->pol_proposals);
165
	TAILQ_INIT(&pol->pol_sapeers);
166
	RB_INIT(&pol->pol_flows);
167
168
	return (pol);
169
}
170
171
void
172
config_free_policy(struct iked *env, struct iked_policy *pol)
173
{
174
	struct iked_sa		*sa;
175
176
	if (pol->pol_flags & IKED_POLICY_REFCNT)
177
		goto remove;
178
179
	TAILQ_REMOVE(&env->sc_policies, pol, pol_entry);
180
181
	TAILQ_FOREACH(sa, &pol->pol_sapeers, sa_peer_entry) {
182
		/* Remove from the policy list, but keep for existing SAs */
183
		if (sa->sa_policy == pol)
184
			policy_ref(env, pol);
185
		else
186
			log_warnx("%s: ERROR: sa_policy %p != pol %p",
187
			    __func__, sa->sa_policy, pol);
188
	}
189
190
	if (pol->pol_refcnt)
191
		return;
192
193
 remove:
194
	config_free_proposals(&pol->pol_proposals, 0);
195
	config_free_flows(env, &pol->pol_flows);
196
	free(pol);
197
}
198
199
struct iked_proposal *
200
config_add_proposal(struct iked_proposals *head, unsigned int id,
201
    unsigned int proto)
202
{
203
	struct iked_proposal	*pp;
204
205
	TAILQ_FOREACH(pp, head, prop_entry) {
206
		if (pp->prop_protoid == proto &&
207
		    pp->prop_id == id)
208
			return (pp);
209
	}
210
211
	if ((pp = calloc(1, sizeof(*pp))) == NULL)
212
		return (NULL);
213
214
	pp->prop_protoid = proto;
215
	pp->prop_id = id;
216
217
	TAILQ_INSERT_TAIL(head, pp, prop_entry);
218
219
	return (pp);
220
}
221
222
void
223
config_free_proposals(struct iked_proposals *head, unsigned int proto)
224
{
225
	struct iked_proposal	*prop, *next;
226
227
	for (prop = TAILQ_FIRST(head); prop != NULL; prop = next) {
228
		next = TAILQ_NEXT(prop, prop_entry);
229
230
		/* Free any proposal or only selected SA proto */
231
		if (proto != 0 && prop->prop_protoid != proto)
232
			continue;
233
234
		log_debug("%s: free %p", __func__, prop);
235
236
		TAILQ_REMOVE(head, prop, prop_entry);
237
		if (prop->prop_nxforms)
238
			free(prop->prop_xforms);
239
		free(prop);
240
	}
241
}
242
243
void
244
config_free_flows(struct iked *env, struct iked_flows *head)
245
{
246
	struct iked_flow	*flow, *next;
247
248
	for (flow = RB_MIN(iked_flows, head); flow != NULL; flow = next) {
249
		next = RB_NEXT(iked_flows, head, flow);
250
		log_debug("%s: free %p", __func__, flow);
251
		RB_REMOVE(iked_flows, head, flow);
252
		flow_free(flow);
253
	}
254
}
255
256
void
257
config_free_childsas(struct iked *env, struct iked_childsas *head,
258
    struct iked_spi *peerspi, struct iked_spi *localspi)
259
{
260
	struct iked_childsa	*csa, *nextcsa;
261
262
	if (localspi != NULL)
263
		bzero(localspi, sizeof(*localspi));
264
265
	for (csa = TAILQ_FIRST(head); csa != NULL; csa = nextcsa) {
266
		nextcsa = TAILQ_NEXT(csa, csa_entry);
267
268
		if (peerspi != NULL) {
269
			/* Only delete matching peer SPIs */
270
			if (peerspi->spi != csa->csa_peerspi)
271
				continue;
272
273
			/* Store assigned local SPI */
274
			if (localspi != NULL && localspi->spi == 0)
275
				memcpy(localspi, &csa->csa_spi,
276
				    sizeof(*localspi));
277
		}
278
		log_debug("%s: free %p", __func__, csa);
279
280
		TAILQ_REMOVE(head, csa, csa_entry);
281
		if (csa->csa_loaded) {
282
			RB_REMOVE(iked_activesas, &env->sc_activesas, csa);
283
			(void)pfkey_sa_delete(env->sc_pfkey, csa);
284
		}
285
		childsa_free(csa);
286
	}
287
}
288
289
struct iked_transform *
290
config_add_transform(struct iked_proposal *prop, unsigned int type,
291
    unsigned int id, unsigned int length, unsigned int keylength)
292
{
293
	struct iked_transform	*xform;
294
	struct iked_constmap	*map = NULL;
295
	int			 score = 1;
296
	unsigned int		 i;
297
298
	switch (type) {
299
	case IKEV2_XFORMTYPE_ENCR:
300
		map = ikev2_xformencr_map;
301
		break;
302
	case IKEV2_XFORMTYPE_PRF:
303
		map = ikev2_xformprf_map;
304
		break;
305
	case IKEV2_XFORMTYPE_INTEGR:
306
		map = ikev2_xformauth_map;
307
		break;
308
	case IKEV2_XFORMTYPE_DH:
309
		map = ikev2_xformdh_map;
310
		break;
311
	case IKEV2_XFORMTYPE_ESN:
312
		map = ikev2_xformesn_map;
313
		break;
314
	default:
315
		log_debug("%s: invalid transform type %d", __func__, type);
316
		return (NULL);
317
	}
318
319
	for (i = 0; i < prop->prop_nxforms; i++) {
320
		xform = prop->prop_xforms + i;
321
		if (xform->xform_type == type &&
322
		    xform->xform_id == id &&
323
		    xform->xform_length == length)
324
			return (xform);
325
	}
326
327
	for (i = 0; i < prop->prop_nxforms; i++) {
328
		xform = prop->prop_xforms + i;
329
		if (xform->xform_type == type) {
330
			switch (type) {
331
			case IKEV2_XFORMTYPE_ENCR:
332
			case IKEV2_XFORMTYPE_INTEGR:
333
				score += 3;
334
				break;
335
			case IKEV2_XFORMTYPE_DH:
336
				score += 2;
337
				break;
338
			default:
339
				score += 1;
340
				break;
341
			}
342
		}
343
	}
344
345
	if ((xform = reallocarray(prop->prop_xforms,
346
	    prop->prop_nxforms + 1, sizeof(*xform))) == NULL) {
347
		return (NULL);
348
	}
349
350
	prop->prop_xforms = xform;
351
	xform = prop->prop_xforms + prop->prop_nxforms++;
352
	bzero(xform, sizeof(*xform));
353
354
	xform->xform_type = type;
355
	xform->xform_id = id;
356
	xform->xform_length = length;
357
	xform->xform_keylength = keylength;
358
	xform->xform_score = score;
359
	xform->xform_map = map;
360
361
	return (xform);
362
}
363
364
struct iked_transform *
365
config_findtransform(struct iked_proposals *props, uint8_t type,
366
    unsigned int proto)
367
{
368
	struct iked_proposal	*prop;
369
	struct iked_transform	*xform;
370
	unsigned int		 i;
371
372
	/* Search of the first transform with the desired type */
373
	TAILQ_FOREACH(prop, props, prop_entry) {
374
		/* Find any proposal or only selected SA proto */
375
		if (proto != 0 && prop->prop_protoid != proto)
376
			continue;
377
		for (i = 0; i < prop->prop_nxforms; i++) {
378
			xform = prop->prop_xforms + i;
379
			if (xform->xform_type == type)
380
				return (xform);
381
		}
382
	}
383
384
	return (NULL);
385
}
386
387
struct iked_user *
388
config_new_user(struct iked *env, struct iked_user *new)
389
{
390
	struct iked_user	*usr, *old;
391
392
	if ((usr = calloc(1, sizeof(*usr))) == NULL)
393
		return (NULL);
394
395
	memcpy(usr, new, sizeof(*usr));
396
397
	if ((old = RB_INSERT(iked_users, &env->sc_users, usr)) != NULL) {
398
		/* Update the password of an existing user*/
399
		memcpy(old, new, sizeof(*old));
400
401
		log_debug("%s: updating user %s", __func__, usr->usr_name);
402
		free(usr);
403
404
		return (old);
405
	}
406
407
	log_debug("%s: inserting new user %s", __func__, usr->usr_name);
408
	return (usr);
409
}
410
411
/*
412
 * Inter-process communication of configuration items.
413
 */
414
415
int
416
config_setcoupled(struct iked *env, unsigned int couple)
417
{
418
	unsigned int	 type;
419
420
	type = couple ? IMSG_CTL_COUPLE : IMSG_CTL_DECOUPLE;
421
	proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0);
422
423
	return (0);
424
}
425
426
int
427
config_getcoupled(struct iked *env, unsigned int type)
428
{
429
	return (pfkey_couple(env->sc_pfkey, &env->sc_sas,
430
	    type == IMSG_CTL_COUPLE ? 1 : 0));
431
}
432
433
int
434
config_setmode(struct iked *env, unsigned int passive)
435
{
436
	unsigned int	 type;
437
438
	type = passive ? IMSG_CTL_PASSIVE : IMSG_CTL_ACTIVE;
439
	proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0);
440
441
	return (0);
442
}
443
444
int
445
config_getmode(struct iked *env, unsigned int type)
446
{
447
	uint8_t		 old;
448
	unsigned char	*mode[] = { "active", "passive" };
449
450
	old = env->sc_passive ? 1 : 0;
451
	env->sc_passive = type == IMSG_CTL_PASSIVE ? 1 : 0;
452
453
	if (old == env->sc_passive)
454
		return (0);
455
456
	log_debug("%s: mode %s -> %s", __func__,
457
	    mode[old], mode[env->sc_passive]);
458
459
	return (0);
460
}
461
462
int
463
config_setreset(struct iked *env, unsigned int mode, enum privsep_procid id)
464
{
465
	proc_compose(&env->sc_ps, id, IMSG_CTL_RESET, &mode, sizeof(mode));
466
	return (0);
467
}
468
469
int
470
config_getreset(struct iked *env, struct imsg *imsg)
471
{
472
	struct iked_policy	*pol, *nextpol;
473
	struct iked_sa		*sa, *nextsa;
474
	struct iked_user	*usr, *nextusr;
475
	unsigned int		 mode;
476
477
	IMSG_SIZE_CHECK(imsg, &mode);
478
	memcpy(&mode, imsg->data, sizeof(mode));
479
480
	if (mode == RESET_ALL || mode == RESET_POLICY) {
481
		log_debug("%s: flushing policies", __func__);
482
		for (pol = TAILQ_FIRST(&env->sc_policies);
483
		    pol != NULL; pol = nextpol) {
484
			nextpol = TAILQ_NEXT(pol, pol_entry);
485
			config_free_policy(env, pol);
486
		}
487
	}
488
489
	if (mode == RESET_ALL || mode == RESET_SA) {
490
		log_debug("%s: flushing SAs", __func__);
491
		for (sa = RB_MIN(iked_sas, &env->sc_sas);
492
		    sa != NULL; sa = nextsa) {
493
			nextsa = RB_NEXT(iked_sas, &env->sc_sas, sa);
494
			RB_REMOVE(iked_sas, &env->sc_sas, sa);
495
			config_free_sa(env, sa);
496
		}
497
	}
498
499
	if (mode == RESET_ALL || mode == RESET_USER) {
500
		log_debug("%s: flushing users", __func__);
501
		for (usr = RB_MIN(iked_users, &env->sc_users);
502
		    usr != NULL; usr = nextusr) {
503
			nextusr = RB_NEXT(iked_users, &env->sc_users, usr);
504
			RB_REMOVE(iked_users, &env->sc_users, usr);
505
			free(usr);
506
		}
507
	}
508
509
	return (0);
510
}
511
512
int
513
config_setsocket(struct iked *env, struct sockaddr_storage *ss,
514
    in_port_t port, enum privsep_procid id)
515
{
516
	int	 s;
517
518
	if ((s = udp_bind((struct sockaddr *)ss, port)) == -1)
519
		return (-1);
520
	proc_compose_imsg(&env->sc_ps, id, -1,
521
	    IMSG_UDP_SOCKET, -1, s, ss, sizeof(*ss));
522
	return (0);
523
}
524
525
int
526
config_getsocket(struct iked *env, struct imsg *imsg,
527
    void (*cb)(int, short, void *))
528
{
529
	struct iked_socket	*sock, **sptr, **nptr;
530
531
	log_debug("%s: received socket fd %d", __func__, imsg->fd);
532
533
	if ((sock = calloc(1, sizeof(*sock))) == NULL)
534
		fatal("config_getsocket: calloc");
535
536
	IMSG_SIZE_CHECK(imsg, &sock->sock_addr);
537
538
	memcpy(&sock->sock_addr, imsg->data, sizeof(sock->sock_addr));
539
	sock->sock_fd = imsg->fd;
540
	sock->sock_env = env;
541
542
	switch (sock->sock_addr.ss_family) {
543
	case AF_INET:
544
		sptr = &env->sc_sock4[0];
545
		nptr = &env->sc_sock4[1];
546
		break;
547
	case AF_INET6:
548
		sptr = &env->sc_sock6[0];
549
		nptr = &env->sc_sock6[1];
550
		break;
551
	default:
552
		fatal("config_getsocket: socket af");
553
		/* NOTREACHED */
554
	}
555
	if (*sptr == NULL)
556
		*sptr = sock;
557
	if (*nptr == NULL &&
558
	    socket_getport((struct sockaddr *)&sock->sock_addr) ==
559
	    IKED_NATT_PORT)
560
		*nptr = sock;
561
562
	event_set(&sock->sock_ev, sock->sock_fd,
563
	    EV_READ|EV_PERSIST, cb, sock);
564
	event_add(&sock->sock_ev, NULL);
565
566
	return (0);
567
}
568
569
int
570
config_setpfkey(struct iked *env, enum privsep_procid id)
571
{
572
	int	 s;
573
574
	if ((s = pfkey_socket()) == -1)
575
		return (-1);
576
	proc_compose_imsg(&env->sc_ps, id, -1,
577
	    IMSG_PFKEY_SOCKET, -1, s, NULL, 0);
578
	return (0);
579
}
580
581
int
582
config_getpfkey(struct iked *env, struct imsg *imsg)
583
{
584
	log_debug("%s: received pfkey fd %d", __func__, imsg->fd);
585
	pfkey_init(env, imsg->fd);
586
	return (0);
587
}
588
589
int
590
config_setuser(struct iked *env, struct iked_user *usr, enum privsep_procid id)
591
{
592
	if (env->sc_opts & IKED_OPT_NOACTION) {
593
		print_user(usr);
594
		return (0);
595
	}
596
597
	proc_compose(&env->sc_ps, id, IMSG_CFG_USER, usr, sizeof(*usr));
598
	return (0);
599
}
600
601
int
602
config_getuser(struct iked *env, struct imsg *imsg)
603
{
604
	struct iked_user	 usr;
605
606
	IMSG_SIZE_CHECK(imsg, &usr);
607
	memcpy(&usr, imsg->data, sizeof(usr));
608
609
	if (config_new_user(env, &usr) == NULL)
610
		return (-1);
611
612
	print_user(&usr);
613
614
	return (0);
615
}
616
617
int
618
config_setpolicy(struct iked *env, struct iked_policy *pol,
619
    enum privsep_procid id)
620
{
621
	struct iked_proposal	*prop;
622
	struct iked_flow	*flow;
623
	struct iked_transform	*xform;
624
	size_t			 size, iovcnt, j, c = 0;
625
	struct iovec		 iov[IOV_MAX];
626
627
	iovcnt = 1;
628
	size = sizeof(*pol);
629
	TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) {
630
		size += (prop->prop_nxforms * sizeof(*xform)) +
631
		    (sizeof(*prop));
632
		iovcnt += prop->prop_nxforms + 1;
633
	}
634
635
	iovcnt += pol->pol_nflows;
636
637
	if (iovcnt > IOV_MAX) {
638
		log_warn("%s: too many proposals/flows", __func__);
639
		return (-1);
640
	}
641
642
	iov[c].iov_base = pol;
643
	iov[c++].iov_len = sizeof(*pol);
644
645
	TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) {
646
		iov[c].iov_base = prop;
647
		iov[c++].iov_len = sizeof(*prop);
648
649
		for (j = 0; j < prop->prop_nxforms; j++) {
650
			xform = prop->prop_xforms + j;
651
652
			iov[c].iov_base = xform;
653
			iov[c++].iov_len = sizeof(*xform);
654
		}
655
	}
656
657
	RB_FOREACH(flow, iked_flows, &pol->pol_flows) {
658
		iov[c].iov_base = flow;
659
		iov[c++].iov_len = sizeof(*flow);
660
	}
661
662
	print_policy(pol);
663
664
	if (env->sc_opts & IKED_OPT_NOACTION)
665
		return (0);
666
667
	if (proc_composev(&env->sc_ps, id, IMSG_CFG_POLICY, iov, iovcnt) == -1)
668
		return (-1);
669
670
	return (0);
671
}
672
673
int
674
config_getpolicy(struct iked *env, struct imsg *imsg)
675
{
676
	struct iked_policy	*pol;
677
	struct iked_proposal	 pp, *prop;
678
	struct iked_transform	 xf, *xform;
679
	struct iked_flow	*flow;
680
	off_t			 offset = 0;
681
	unsigned int		 i, j;
682
	uint8_t			*buf = (uint8_t *)imsg->data;
683
684
	IMSG_SIZE_CHECK(imsg, pol);
685
	log_debug("%s: received policy", __func__);
686
687
	if ((pol = config_new_policy(NULL)) == NULL)
688
		fatal("config_getpolicy: new policy");
689
690
	memcpy(pol, buf, sizeof(*pol));
691
	offset += sizeof(*pol);
692
693
	TAILQ_INIT(&pol->pol_proposals);
694
	TAILQ_INIT(&pol->pol_sapeers);
695
	RB_INIT(&pol->pol_flows);
696
697
	for (i = 0; i < pol->pol_nproposals; i++) {
698
		memcpy(&pp, buf + offset, sizeof(pp));
699
		offset += sizeof(pp);
700
701
		if ((prop = config_add_proposal(&pol->pol_proposals,
702
		    pp.prop_id, pp.prop_protoid)) == NULL)
703
			fatal("config_getpolicy: add proposal");
704
705
		for (j = 0; j < pp.prop_nxforms; j++) {
706
			memcpy(&xf, buf + offset, sizeof(xf));
707
			offset += sizeof(xf);
708
709
			if ((xform = config_add_transform(prop, xf.xform_type,
710
			    xf.xform_id, xf.xform_length,
711
			    xf.xform_keylength)) == NULL)
712
				fatal("config_getpolicy: add transform");
713
		}
714
	}
715
716
	for (i = 0; i < pol->pol_nflows; i++) {
717
		if ((flow = calloc(1, sizeof(*flow))) == NULL)
718
			fatal("config_getpolicy: new flow");
719
720
		memcpy(flow, buf + offset, sizeof(*flow));
721
		offset += sizeof(*flow);
722
723
		if (RB_INSERT(iked_flows, &pol->pol_flows, flow))
724
			free(flow);
725
	}
726
727
	TAILQ_INSERT_TAIL(&env->sc_policies, pol, pol_entry);
728
729
	if (pol->pol_flags & IKED_POLICY_DEFAULT) {
730
		/* Only one default policy, just free/unref the old one */
731
		if (env->sc_defaultcon != NULL)
732
			config_free_policy(env, env->sc_defaultcon);
733
		env->sc_defaultcon = pol;
734
	}
735
736
	return (0);
737
}
738
739
int
740
config_setcompile(struct iked *env, enum privsep_procid id)
741
{
742
	if (env->sc_opts & IKED_OPT_NOACTION)
743
		return (0);
744
745
	proc_compose(&env->sc_ps, id, IMSG_COMPILE, NULL, 0);
746
	return (0);
747
}
748
749
int
750
config_getcompile(struct iked *env, struct imsg *imsg)
751
{
752
	/*
753
	 * Do any necessary steps after configuration, for now we
754
	 * only need to compile the skip steps.
755
	 */
756
	policy_calc_skip_steps(&env->sc_policies);
757
758
	log_debug("%s: compilation done", __func__);
759
	return (0);
760
}
761
762
int
763
config_setocsp(struct iked *env)
764
{
765
	if (env->sc_opts & IKED_OPT_NOACTION)
766
		return (0);
767
	proc_compose(&env->sc_ps, PROC_CERT,
768
	    IMSG_OCSP_URL, env->sc_ocsp_url,
769
	    env->sc_ocsp_url ? strlen(env->sc_ocsp_url) : 0);
770
771
	return (0);
772
}
773
774
int
775
config_getocsp(struct iked *env, struct imsg *imsg)
776
{
777
	free(env->sc_ocsp_url);
778
	if (IMSG_DATA_SIZE(imsg) > 0)
779
		env->sc_ocsp_url = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
780
	else
781
		env->sc_ocsp_url = NULL;
782
	log_debug("%s: ocsp_url %s", __func__,
783
	    env->sc_ocsp_url ? env->sc_ocsp_url : "none");
784
	return (0);
785
}