xref: /openbsd/sbin/iked/config.c (revision 264ca280)
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 }
786