config.c revision 1.59
1/*	$OpenBSD: config.c,v 1.59 2020/08/14 21:13:15 tobhe Exp $	*/
2
3/*
4 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/queue.h>
21#include <sys/wait.h>
22#include <sys/socket.h>
23#include <sys/uio.h>
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <unistd.h>
28#include <string.h>
29#include <signal.h>
30#include <errno.h>
31#include <err.h>
32#include <pwd.h>
33#include <event.h>
34
35#include <openssl/evp.h>
36#include <openssl/pem.h>
37
38#include "iked.h"
39#include "ikev2.h"
40
41struct iked_sa *
42config_new_sa(struct iked *env, int initiator)
43{
44	struct iked_sa	*sa;
45
46	if ((sa = calloc(1, sizeof(*sa))) == NULL)
47		return (NULL);
48
49	TAILQ_INIT(&sa->sa_proposals);
50	TAILQ_INIT(&sa->sa_childsas);
51	TAILQ_INIT(&sa->sa_flows);
52	TAILQ_INIT(&sa->sa_requests);
53	TAILQ_INIT(&sa->sa_responses);
54	sa->sa_hdr.sh_initiator = initiator;
55	sa->sa_type = IKED_SATYPE_LOCAL;
56
57	if (initiator)
58		sa->sa_hdr.sh_ispi = config_getspi();
59	else
60		sa->sa_hdr.sh_rspi = config_getspi();
61
62	gettimeofday(&sa->sa_timecreated, NULL);
63	memcpy(&sa->sa_timeused, &sa->sa_timecreated, sizeof(sa->sa_timeused));
64
65	return (sa);
66}
67
68uint64_t
69config_getspi(void)
70{
71	uint64_t	 spi;
72
73	do {
74		arc4random_buf(&spi, sizeof spi);
75	} while (spi == 0);
76
77	return (spi);
78}
79
80void
81config_free_kex(struct iked_kex *kex)
82{
83	if (kex == NULL)
84		return;
85
86	ibuf_release(kex->kex_inonce);
87	ibuf_release(kex->kex_rnonce);
88
89	if (kex->kex_dhgroup != NULL)
90		group_free(kex->kex_dhgroup);
91	ibuf_release(kex->kex_dhiexchange);
92	ibuf_release(kex->kex_dhrexchange);
93
94	free(kex);
95}
96
97void
98config_free_fragments(struct iked_frag *frag)
99{
100	size_t i;
101
102	if (frag && frag->frag_arr) {
103		for (i = 0; i < frag->frag_total; i++) {
104			if (frag->frag_arr[i] != NULL)
105				free(frag->frag_arr[i]->frag_data);
106			free(frag->frag_arr[i]);
107		}
108		free(frag->frag_arr);
109		bzero(frag, sizeof(struct iked_frag));
110	}
111}
112
113void
114config_free_sa(struct iked *env, struct iked_sa *sa)
115{
116	timer_del(env, &sa->sa_timer);
117	timer_del(env, &sa->sa_keepalive);
118	timer_del(env, &sa->sa_rekey);
119
120	config_free_fragments(&sa->sa_fragments);
121	config_free_proposals(&sa->sa_proposals, 0);
122	config_free_childsas(env, &sa->sa_childsas, NULL, NULL);
123	sa_free_flows(env, &sa->sa_flows);
124
125	if (sa->sa_addrpool) {
126		(void)RB_REMOVE(iked_addrpool, &env->sc_addrpool, sa);
127		free(sa->sa_addrpool);
128	}
129	if (sa->sa_addrpool6) {
130		(void)RB_REMOVE(iked_addrpool6, &env->sc_addrpool6, sa);
131		free(sa->sa_addrpool6);
132	}
133
134	if (sa->sa_policy) {
135		TAILQ_REMOVE(&sa->sa_policy->pol_sapeers, sa, sa_peer_entry);
136		policy_unref(env, sa->sa_policy);
137	}
138
139	ikev2_msg_flushqueue(env, &sa->sa_requests);
140	ikev2_msg_flushqueue(env, &sa->sa_responses);
141
142	ibuf_release(sa->sa_inonce);
143	ibuf_release(sa->sa_rnonce);
144
145	if (sa->sa_dhgroup != NULL)
146		group_free(sa->sa_dhgroup);
147	ibuf_release(sa->sa_dhiexchange);
148	ibuf_release(sa->sa_dhrexchange);
149
150	ibuf_release(sa->sa_simult);
151
152	hash_free(sa->sa_prf);
153	hash_free(sa->sa_integr);
154	cipher_free(sa->sa_encr);
155
156	ibuf_release(sa->sa_key_d);
157	ibuf_release(sa->sa_key_iauth);
158	ibuf_release(sa->sa_key_rauth);
159	ibuf_release(sa->sa_key_iencr);
160	ibuf_release(sa->sa_key_rencr);
161	ibuf_release(sa->sa_key_iprf);
162	ibuf_release(sa->sa_key_rprf);
163
164	ibuf_release(sa->sa_1stmsg);
165	ibuf_release(sa->sa_2ndmsg);
166
167	ibuf_release(sa->sa_iid.id_buf);
168	ibuf_release(sa->sa_rid.id_buf);
169	ibuf_release(sa->sa_icert.id_buf);
170	ibuf_release(sa->sa_rcert.id_buf);
171	ibuf_release(sa->sa_localauth.id_buf);
172
173	ibuf_release(sa->sa_eap.id_buf);
174	free(sa->sa_eapid);
175	ibuf_release(sa->sa_eapmsk);
176
177	free(sa->sa_tag);
178	free(sa);
179}
180
181struct iked_policy *
182config_new_policy(struct iked *env)
183{
184	struct iked_policy	*pol;
185
186	if ((pol = calloc(1, sizeof(*pol))) == NULL)
187		return (NULL);
188
189	/* XXX caller does this again */
190	TAILQ_INIT(&pol->pol_proposals);
191	TAILQ_INIT(&pol->pol_sapeers);
192	TAILQ_INIT(&pol->pol_tssrc);
193	TAILQ_INIT(&pol->pol_tsdst);
194	RB_INIT(&pol->pol_flows);
195
196	return (pol);
197}
198
199void
200config_free_policy(struct iked *env, struct iked_policy *pol)
201{
202	struct iked_sa		*sa;
203	struct iked_ts	*tsi;
204
205	if (pol->pol_flags & IKED_POLICY_REFCNT)
206		goto remove;
207
208	TAILQ_REMOVE(&env->sc_policies, pol, pol_entry);
209
210	TAILQ_FOREACH(sa, &pol->pol_sapeers, sa_peer_entry) {
211		/* Remove from the policy list, but keep for existing SAs */
212		if (sa->sa_policy == pol)
213			policy_ref(env, pol);
214		else
215			log_warnx("%s: ERROR: sa_policy %p != pol %p",
216			    __func__, sa->sa_policy, pol);
217	}
218
219	if (pol->pol_refcnt)
220		return;
221
222 remove:
223	while ((tsi = TAILQ_FIRST(&pol->pol_tssrc))) {
224		TAILQ_REMOVE(&pol->pol_tssrc, tsi, ts_entry);
225		free(tsi);
226	}
227	while ((tsi = TAILQ_FIRST(&pol->pol_tsdst))) {
228		TAILQ_REMOVE(&pol->pol_tsdst, tsi, ts_entry);
229		free(tsi);
230	}
231	config_free_proposals(&pol->pol_proposals, 0);
232	config_free_flows(env, &pol->pol_flows);
233	free(pol);
234}
235
236struct iked_proposal *
237config_add_proposal(struct iked_proposals *head, unsigned int id,
238    unsigned int proto)
239{
240	struct iked_proposal	*pp;
241
242	TAILQ_FOREACH(pp, head, prop_entry) {
243		if (pp->prop_protoid == proto &&
244		    pp->prop_id == id)
245			return (pp);
246	}
247
248	if ((pp = calloc(1, sizeof(*pp))) == NULL)
249		return (NULL);
250
251	pp->prop_protoid = proto;
252	pp->prop_id = id;
253
254	TAILQ_INSERT_TAIL(head, pp, prop_entry);
255
256	return (pp);
257}
258
259void
260config_free_proposals(struct iked_proposals *head, unsigned int proto)
261{
262	struct iked_proposal	*prop, *proptmp;
263
264	TAILQ_FOREACH_SAFE(prop, head, prop_entry, proptmp) {
265		/* Free any proposal or only selected SA proto */
266		if (proto != 0 && prop->prop_protoid != proto)
267			continue;
268
269		log_debug("%s: free %p", __func__, prop);
270
271		TAILQ_REMOVE(head, prop, prop_entry);
272		if (prop->prop_nxforms)
273			free(prop->prop_xforms);
274		free(prop);
275	}
276}
277
278void
279config_free_flows(struct iked *env, struct iked_flows *head)
280{
281	struct iked_flow	*flow, *next;
282
283	for (flow = RB_MIN(iked_flows, head); flow != NULL; flow = next) {
284		next = RB_NEXT(iked_flows, head, flow);
285		log_debug("%s: free %p", __func__, flow);
286		RB_REMOVE(iked_flows, head, flow);
287		flow_free(flow);
288	}
289}
290
291void
292config_free_childsas(struct iked *env, struct iked_childsas *head,
293    struct iked_spi *peerspi, struct iked_spi *localspi)
294{
295	struct iked_childsa	*csa, *csatmp, *ipcomp;
296
297	if (localspi != NULL)
298		bzero(localspi, sizeof(*localspi));
299
300	TAILQ_FOREACH_SAFE(csa, head, csa_entry, csatmp) {
301		if (peerspi != NULL) {
302			/* Only delete matching peer SPIs */
303			if (peerspi->spi != csa->csa_peerspi)
304				continue;
305
306			/* Store assigned local SPI */
307			if (localspi != NULL && localspi->spi == 0)
308				memcpy(localspi, &csa->csa_spi,
309				    sizeof(*localspi));
310		}
311		log_debug("%s: free %p", __func__, csa);
312
313		TAILQ_REMOVE(head, csa, csa_entry);
314		if (csa->csa_loaded) {
315			RB_REMOVE(iked_activesas, &env->sc_activesas, csa);
316			(void)pfkey_sa_delete(env->sc_pfkey, csa);
317		}
318		if ((ipcomp = csa->csa_bundled) != NULL) {
319			log_debug("%s: free IPCOMP %p", __func__, ipcomp);
320			if (ipcomp->csa_loaded)
321				(void)pfkey_sa_delete(env->sc_pfkey, ipcomp);
322			childsa_free(ipcomp);
323		}
324		childsa_free(csa);
325	}
326}
327
328struct iked_transform *
329config_add_transform(struct iked_proposal *prop, unsigned int type,
330    unsigned int id, unsigned int length, unsigned int keylength)
331{
332	struct iked_transform	*xform;
333	struct iked_constmap	*map = NULL;
334	int			 score = 1;
335	unsigned int		 i;
336
337	switch (type) {
338	case IKEV2_XFORMTYPE_ENCR:
339		map = ikev2_xformencr_map;
340		break;
341	case IKEV2_XFORMTYPE_PRF:
342		map = ikev2_xformprf_map;
343		break;
344	case IKEV2_XFORMTYPE_INTEGR:
345		map = ikev2_xformauth_map;
346		break;
347	case IKEV2_XFORMTYPE_DH:
348		map = ikev2_xformdh_map;
349		break;
350	case IKEV2_XFORMTYPE_ESN:
351		map = ikev2_xformesn_map;
352		break;
353	default:
354		log_debug("%s: invalid transform type %d", __func__, type);
355		return (NULL);
356	}
357
358	for (i = 0; i < prop->prop_nxforms; i++) {
359		xform = prop->prop_xforms + i;
360		if (xform->xform_type == type &&
361		    xform->xform_id == id &&
362		    xform->xform_length == length)
363			return (xform);
364	}
365
366	for (i = 0; i < prop->prop_nxforms; i++) {
367		xform = prop->prop_xforms + i;
368		if (xform->xform_type == type) {
369			switch (type) {
370			case IKEV2_XFORMTYPE_ENCR:
371			case IKEV2_XFORMTYPE_INTEGR:
372				score += 3;
373				break;
374			case IKEV2_XFORMTYPE_DH:
375				score += 2;
376				break;
377			default:
378				score += 1;
379				break;
380			}
381		}
382	}
383
384	if ((xform = reallocarray(prop->prop_xforms,
385	    prop->prop_nxforms + 1, sizeof(*xform))) == NULL) {
386		return (NULL);
387	}
388
389	prop->prop_xforms = xform;
390	xform = prop->prop_xforms + prop->prop_nxforms++;
391	bzero(xform, sizeof(*xform));
392
393	xform->xform_type = type;
394	xform->xform_id = id;
395	xform->xform_length = length;
396	xform->xform_keylength = keylength;
397	xform->xform_score = score;
398	xform->xform_map = map;
399
400	return (xform);
401}
402
403struct iked_transform *
404config_findtransform(struct iked_proposals *props, uint8_t type,
405    unsigned int proto)
406{
407	struct iked_proposal	*prop;
408	struct iked_transform	*xform;
409	unsigned int		 i;
410
411	/* Search of the first transform with the desired type */
412	TAILQ_FOREACH(prop, props, prop_entry) {
413		/* Find any proposal or only selected SA proto */
414		if (proto != 0 && prop->prop_protoid != proto)
415			continue;
416		for (i = 0; i < prop->prop_nxforms; i++) {
417			xform = prop->prop_xforms + i;
418			if (xform->xform_type == type)
419				return (xform);
420		}
421	}
422
423	return (NULL);
424}
425
426struct iked_user *
427config_new_user(struct iked *env, struct iked_user *new)
428{
429	struct iked_user	*usr, *old;
430
431	if ((usr = calloc(1, sizeof(*usr))) == NULL)
432		return (NULL);
433
434	memcpy(usr, new, sizeof(*usr));
435
436	if ((old = RB_INSERT(iked_users, &env->sc_users, usr)) != NULL) {
437		/* Update the password of an existing user*/
438		memcpy(old->usr_pass, new->usr_pass, IKED_PASSWORD_SIZE);
439
440		log_debug("%s: updating user %s", __func__, usr->usr_name);
441		free(usr);
442
443		return (old);
444	}
445
446	log_debug("%s: inserting new user %s", __func__, usr->usr_name);
447	return (usr);
448}
449
450/*
451 * Inter-process communication of configuration items.
452 */
453
454int
455config_setcoupled(struct iked *env, unsigned int couple)
456{
457	unsigned int	 type;
458
459	type = couple ? IMSG_CTL_COUPLE : IMSG_CTL_DECOUPLE;
460	proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0);
461
462	return (0);
463}
464
465int
466config_getcoupled(struct iked *env, unsigned int type)
467{
468	return (pfkey_couple(env->sc_pfkey, &env->sc_sas,
469	    type == IMSG_CTL_COUPLE ? 1 : 0));
470}
471
472int
473config_setmode(struct iked *env, unsigned int passive)
474{
475	unsigned int	 type;
476
477	type = passive ? IMSG_CTL_PASSIVE : IMSG_CTL_ACTIVE;
478	proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0);
479
480	return (0);
481}
482
483int
484config_getmode(struct iked *env, unsigned int type)
485{
486	uint8_t		 old;
487	unsigned char	*mode[] = { "active", "passive" };
488
489	old = env->sc_passive ? 1 : 0;
490	env->sc_passive = type == IMSG_CTL_PASSIVE ? 1 : 0;
491
492	if (old == env->sc_passive)
493		return (0);
494
495	log_debug("%s: mode %s -> %s", __func__,
496	    mode[old], mode[env->sc_passive]);
497
498	return (0);
499}
500
501int
502config_setreset(struct iked *env, unsigned int mode, enum privsep_procid id)
503{
504	proc_compose(&env->sc_ps, id, IMSG_CTL_RESET, &mode, sizeof(mode));
505	return (0);
506}
507
508int
509config_getreset(struct iked *env, struct imsg *imsg)
510{
511	struct iked_policy	*pol, *poltmp;
512	struct iked_sa		*sa, *nextsa;
513	struct iked_user	*usr, *nextusr;
514	unsigned int		 mode;
515
516	IMSG_SIZE_CHECK(imsg, &mode);
517	memcpy(&mode, imsg->data, sizeof(mode));
518
519	if (mode == RESET_ALL || mode == RESET_POLICY) {
520		log_debug("%s: flushing policies", __func__);
521		TAILQ_FOREACH_SAFE(pol, &env->sc_policies, pol_entry, poltmp) {
522			config_free_policy(env, pol);
523		}
524	}
525
526	if (mode == RESET_ALL || mode == RESET_SA) {
527		log_debug("%s: flushing SAs", __func__);
528		for (sa = RB_MIN(iked_sas, &env->sc_sas);
529		    sa != NULL; sa = nextsa) {
530			nextsa = RB_NEXT(iked_sas, &env->sc_sas, sa);
531			/* for RESET_SA we try send a DELETE */
532			if (mode == RESET_ALL ||
533			    ikev2_ike_sa_delete(env, sa) != 0) {
534				RB_REMOVE(iked_sas, &env->sc_sas, sa);
535				config_free_sa(env, sa);
536			}
537		}
538	}
539
540	if (mode == RESET_ALL || mode == RESET_USER) {
541		log_debug("%s: flushing users", __func__);
542		for (usr = RB_MIN(iked_users, &env->sc_users);
543		    usr != NULL; usr = nextusr) {
544			nextusr = RB_NEXT(iked_users, &env->sc_users, usr);
545			RB_REMOVE(iked_users, &env->sc_users, usr);
546			free(usr);
547		}
548	}
549
550	return (0);
551}
552
553/*
554 * The first call of this function sets the UDP socket for IKEv2.
555 * The second call is optional, setting the UDP socket used for NAT-T.
556 */
557int
558config_setsocket(struct iked *env, struct sockaddr_storage *ss,
559    in_port_t port, enum privsep_procid id)
560{
561	int	 s;
562
563	if ((s = udp_bind((struct sockaddr *)ss, port)) == -1)
564		return (-1);
565	proc_compose_imsg(&env->sc_ps, id, -1,
566	    IMSG_UDP_SOCKET, -1, s, ss, sizeof(*ss));
567	return (0);
568}
569
570int
571config_getsocket(struct iked *env, struct imsg *imsg,
572    void (*cb)(int, short, void *))
573{
574	struct iked_socket	*sock, **sock0, **sock1;
575
576	log_debug("%s: received socket fd %d", __func__, imsg->fd);
577
578	if ((sock = calloc(1, sizeof(*sock))) == NULL)
579		fatal("config_getsocket: calloc");
580
581	IMSG_SIZE_CHECK(imsg, &sock->sock_addr);
582
583	memcpy(&sock->sock_addr, imsg->data, sizeof(sock->sock_addr));
584	sock->sock_fd = imsg->fd;
585	sock->sock_env = env;
586
587	switch (sock->sock_addr.ss_family) {
588	case AF_INET:
589		sock0 = &env->sc_sock4[0];
590		sock1 = &env->sc_sock4[1];
591		break;
592	case AF_INET6:
593		sock0 = &env->sc_sock6[0];
594		sock1 = &env->sc_sock6[1];
595		break;
596	default:
597		fatal("config_getsocket: socket af: %u",
598		    sock->sock_addr.ss_family);
599		/* NOTREACHED */
600	}
601	if (*sock0 == NULL)
602		*sock0 = sock;
603	else if (*sock1 == NULL)
604		*sock1 = sock;
605	else
606		fatalx("%s: too many call", __func__);
607
608	event_set(&sock->sock_ev, sock->sock_fd,
609	    EV_READ|EV_PERSIST, cb, sock);
610	event_add(&sock->sock_ev, NULL);
611
612	return (0);
613}
614
615int
616config_setpfkey(struct iked *env, enum privsep_procid id)
617{
618	int	 s;
619
620	if ((s = pfkey_socket()) == -1)
621		return (-1);
622	proc_compose_imsg(&env->sc_ps, id, -1,
623	    IMSG_PFKEY_SOCKET, -1, s, NULL, 0);
624	return (0);
625}
626
627int
628config_getpfkey(struct iked *env, struct imsg *imsg)
629{
630	log_debug("%s: received pfkey fd %d", __func__, imsg->fd);
631	pfkey_init(env, imsg->fd);
632	return (0);
633}
634
635int
636config_setuser(struct iked *env, struct iked_user *usr, enum privsep_procid id)
637{
638	if (env->sc_opts & IKED_OPT_NOACTION) {
639		print_user(usr);
640		return (0);
641	}
642
643	proc_compose(&env->sc_ps, id, IMSG_CFG_USER, usr, sizeof(*usr));
644	return (0);
645}
646
647int
648config_getuser(struct iked *env, struct imsg *imsg)
649{
650	struct iked_user	 usr;
651
652	IMSG_SIZE_CHECK(imsg, &usr);
653	memcpy(&usr, imsg->data, sizeof(usr));
654
655	if (config_new_user(env, &usr) == NULL)
656		return (-1);
657
658	print_user(&usr);
659
660	return (0);
661}
662
663int
664config_setpolicy(struct iked *env, struct iked_policy *pol,
665    enum privsep_procid id)
666{
667	struct iked_proposal	*prop;
668	struct iked_transform	*xform;
669	size_t			 iovcnt, j, c = 0;
670	struct iovec		 iov[IOV_MAX];
671
672	iovcnt = 1;
673	TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) {
674		iovcnt += prop->prop_nxforms + 1;
675	}
676
677	if (iovcnt > IOV_MAX) {
678		log_warn("%s: too many proposals", __func__);
679		return (-1);
680	}
681
682	iov[c].iov_base = pol;
683	iov[c++].iov_len = sizeof(*pol);
684
685	TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) {
686		iov[c].iov_base = prop;
687		iov[c++].iov_len = sizeof(*prop);
688
689		for (j = 0; j < prop->prop_nxforms; j++) {
690			xform = prop->prop_xforms + j;
691
692			iov[c].iov_base = xform;
693			iov[c++].iov_len = sizeof(*xform);
694		}
695	}
696
697	print_policy(pol);
698
699	if (env->sc_opts & IKED_OPT_NOACTION)
700		return (0);
701
702	if (proc_composev(&env->sc_ps, id, IMSG_CFG_POLICY, iov,
703	    iovcnt) == -1) {
704		log_debug("%s: proc_composev failed", __func__);
705		return (-1);
706	}
707
708	return (0);
709}
710
711int
712config_setflow(struct iked *env, struct iked_policy *pol,
713    enum privsep_procid id)
714{
715	struct iked_flow	*flow;
716	struct iovec		 iov[2];
717
718	if (env->sc_opts & IKED_OPT_NOACTION)
719		return (0);
720
721	RB_FOREACH(flow, iked_flows, &pol->pol_flows) {
722		iov[0].iov_base = &pol->pol_id;
723		iov[0].iov_len = sizeof(pol->pol_id);
724		iov[1].iov_base = flow;
725		iov[1].iov_len = sizeof(*flow);
726
727		if (proc_composev(&env->sc_ps, id, IMSG_CFG_FLOW,
728		    iov, 2) == -1) {
729			log_debug("%s: proc_composev failed", __func__);
730			return (-1);
731		}
732	}
733
734	return (0);
735}
736
737int
738config_getpolicy(struct iked *env, struct imsg *imsg)
739{
740	struct iked_policy	*pol;
741	struct iked_proposal	 pp, *prop;
742	struct iked_transform	 xf;
743	off_t			 offset = 0;
744	unsigned int		 i, j;
745	uint8_t			*buf = (uint8_t *)imsg->data;
746
747	IMSG_SIZE_CHECK(imsg, pol);
748	log_debug("%s: received policy", __func__);
749
750	if ((pol = config_new_policy(NULL)) == NULL)
751		fatal("config_getpolicy: new policy");
752
753	memcpy(pol, buf, sizeof(*pol));
754	offset += sizeof(*pol);
755
756	TAILQ_INIT(&pol->pol_tssrc);
757	TAILQ_INIT(&pol->pol_tsdst);
758	TAILQ_INIT(&pol->pol_proposals);
759	TAILQ_INIT(&pol->pol_sapeers);
760	RB_INIT(&pol->pol_flows);
761
762	for (i = 0; i < pol->pol_nproposals; i++) {
763		memcpy(&pp, buf + offset, sizeof(pp));
764		offset += sizeof(pp);
765
766		if ((prop = config_add_proposal(&pol->pol_proposals,
767		    pp.prop_id, pp.prop_protoid)) == NULL)
768			fatal("config_getpolicy: add proposal");
769
770		for (j = 0; j < pp.prop_nxforms; j++) {
771			memcpy(&xf, buf + offset, sizeof(xf));
772			offset += sizeof(xf);
773
774			if (config_add_transform(prop, xf.xform_type,
775			    xf.xform_id, xf.xform_length,
776			    xf.xform_keylength) == NULL)
777				fatal("config_getpolicy: add transform");
778		}
779	}
780
781	/* Flows are sent separately */
782	pol->pol_nflows = 0;
783
784	TAILQ_INSERT_TAIL(&env->sc_policies, pol, pol_entry);
785
786	if (pol->pol_flags & IKED_POLICY_DEFAULT) {
787		/* Only one default policy, just free/unref the old one */
788		if (env->sc_defaultcon != NULL)
789			config_free_policy(env, env->sc_defaultcon);
790		env->sc_defaultcon = pol;
791	}
792
793	return (0);
794}
795
796int
797config_getflow(struct iked *env, struct imsg *imsg)
798{
799	struct iked_policy	*pol;
800	struct iked_flow	*flow;
801	off_t			 offset = 0;
802	unsigned int		 id;
803	uint8_t			*buf = (uint8_t *)imsg->data;
804
805	if (IMSG_DATA_SIZE(imsg) < sizeof(id))
806		fatalx("bad length imsg received");
807
808	memcpy(&id, buf, sizeof(id));
809	offset += sizeof(id);
810
811	TAILQ_FOREACH(pol, &env->sc_policies, pol_entry) {
812		if (pol->pol_id == id)
813			break;
814	}
815	if (pol == NULL) {
816		log_warnx("%s: unknown policy %u", __func__, id);
817		return (-1);
818	}
819
820	if ((flow = calloc(1, sizeof(*flow))) == NULL)
821		fatal("config_getpolicy: new flow");
822
823	memcpy(flow, buf + offset, sizeof(*flow));
824
825	if (RB_INSERT(iked_flows, &pol->pol_flows, flow)) {
826		log_warnx("%s: received duplicate flow", __func__);
827		free(flow);
828		return (-1);
829	}
830	pol->pol_nflows++;
831
832	return (0);
833}
834
835int
836config_setcompile(struct iked *env, enum privsep_procid id)
837{
838	if (env->sc_opts & IKED_OPT_NOACTION)
839		return (0);
840
841	proc_compose(&env->sc_ps, id, IMSG_COMPILE, NULL, 0);
842	return (0);
843}
844
845int
846config_getcompile(struct iked *env, struct imsg *imsg)
847{
848	/*
849	 * Do any necessary steps after configuration, for now we
850	 * only need to compile the skip steps.
851	 */
852	policy_calc_skip_steps(&env->sc_policies);
853
854	log_debug("%s: compilation done", __func__);
855	return (0);
856}
857
858int
859config_setmobike(struct iked *env)
860{
861	unsigned int boolval;
862
863	boolval = env->sc_mobike;
864	proc_compose(&env->sc_ps, PROC_IKEV2, IMSG_CTL_MOBIKE,
865	    &boolval, sizeof(boolval));
866	return (0);
867}
868
869int
870config_getmobike(struct iked *env, struct imsg *imsg)
871{
872	unsigned int boolval;
873
874	IMSG_SIZE_CHECK(imsg, &boolval);
875	memcpy(&boolval, imsg->data, sizeof(boolval));
876	env->sc_mobike = boolval;
877	log_debug("%s: %smobike", __func__, env->sc_mobike ? "" : "no ");
878	return (0);
879}
880
881int
882config_setfragmentation(struct iked *env)
883{
884	unsigned int boolval;
885
886	boolval = env->sc_frag;
887	proc_compose(&env->sc_ps, PROC_IKEV2, IMSG_CTL_FRAGMENTATION,
888	    &boolval, sizeof(boolval));
889	return (0);
890}
891
892int
893config_getfragmentation(struct iked *env, struct imsg *imsg)
894{
895	unsigned int boolval;
896
897	IMSG_SIZE_CHECK(imsg, &boolval);
898	memcpy(&boolval, imsg->data, sizeof(boolval));
899	env->sc_frag = boolval;
900	log_debug("%s: %sfragmentation", __func__, env->sc_frag ? "" : "no ");
901	return (0);
902}
903
904int
905config_setocsp(struct iked *env)
906{
907	if (env->sc_opts & IKED_OPT_NOACTION)
908		return (0);
909	proc_compose(&env->sc_ps, PROC_CERT,
910	    IMSG_OCSP_URL, env->sc_ocsp_url,
911	    env->sc_ocsp_url ? strlen(env->sc_ocsp_url) : 0);
912
913	return (0);
914}
915
916int
917config_getocsp(struct iked *env, struct imsg *imsg)
918{
919	free(env->sc_ocsp_url);
920	if (IMSG_DATA_SIZE(imsg) > 0)
921		env->sc_ocsp_url = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
922	else
923		env->sc_ocsp_url = NULL;
924	log_debug("%s: ocsp_url %s", __func__,
925	    env->sc_ocsp_url ? env->sc_ocsp_url : "none");
926	return (0);
927}
928
929int
930config_setkeys(struct iked *env)
931{
932	FILE			*fp = NULL;
933	EVP_PKEY		*key = NULL;
934	struct iked_id		 privkey;
935	struct iked_id		 pubkey;
936	struct iovec		 iov[2];
937	int			 ret = -1;
938
939	memset(&privkey, 0, sizeof(privkey));
940	memset(&pubkey, 0, sizeof(pubkey));
941
942	/* Read private key */
943	if ((fp = fopen(IKED_PRIVKEY, "r")) == NULL) {
944		log_warn("%s: failed to open private key", __func__);
945		goto done;
946	}
947
948	if ((key = PEM_read_PrivateKey(fp, NULL, NULL, NULL)) == NULL) {
949		log_warnx("%s: failed to read private key", __func__);
950		goto done;
951	}
952
953	if (ca_privkey_serialize(key, &privkey) != 0) {
954		log_warnx("%s: failed to serialize private key", __func__);
955		goto done;
956	}
957	if (ca_pubkey_serialize(key, &pubkey) != 0) {
958		log_warnx("%s: failed to serialize public key", __func__);
959		goto done;
960	}
961
962	iov[0].iov_base = &privkey;
963	iov[0].iov_len = sizeof(privkey);
964	iov[1].iov_base = ibuf_data(privkey.id_buf);
965	iov[1].iov_len = ibuf_length(privkey.id_buf);
966
967	if (proc_composev(&env->sc_ps, PROC_CERT, IMSG_PRIVKEY, iov, 2) == -1) {
968		log_warnx("%s: failed to send private key", __func__);
969		goto done;
970	}
971
972	iov[0].iov_base = &pubkey;
973	iov[0].iov_len = sizeof(pubkey);
974	iov[1].iov_base = ibuf_data(pubkey.id_buf);
975	iov[1].iov_len = ibuf_length(pubkey.id_buf);
976
977	if (proc_composev(&env->sc_ps, PROC_CERT, IMSG_PUBKEY, iov, 2) == -1) {
978		log_warnx("%s: failed to send public key", __func__);
979		goto done;
980	}
981
982	ret = 0;
983 done:
984	if (fp != NULL)
985		fclose(fp);
986
987	ibuf_release(pubkey.id_buf);
988	ibuf_release(privkey.id_buf);
989	EVP_PKEY_free(key);
990
991	return (ret);
992}
993
994int
995config_setnattport(struct iked *env)
996{
997	in_port_t nattport;
998
999	nattport = env->sc_nattport;
1000	proc_compose(&env->sc_ps, PROC_IKEV2, IMSG_CTL_NATTPORT,
1001	    &nattport, sizeof(nattport));
1002	return (0);
1003}
1004
1005int
1006config_getnattport(struct iked *env, struct imsg *imsg)
1007{
1008	in_port_t nattport;
1009
1010	IMSG_SIZE_CHECK(imsg, &nattport);
1011	memcpy(&nattport, imsg->data, sizeof(nattport));
1012	env->sc_nattport = nattport;
1013	log_debug("%s: nattport %u", __func__, env->sc_nattport);
1014	return (0);
1015}
1016
1017int
1018config_getkey(struct iked *env, struct imsg *imsg)
1019{
1020	size_t		 len;
1021	struct iked_id	 id;
1022
1023	len = IMSG_DATA_SIZE(imsg);
1024	if (len <= sizeof(id))
1025		fatalx("%s: invalid key message", __func__);
1026
1027	memcpy(&id, imsg->data, sizeof(id));
1028	if ((id.id_buf = ibuf_new((uint8_t *)imsg->data + sizeof(id),
1029	    len - sizeof(id))) == NULL)
1030		fatalx("%s: failed to get key", __func__);
1031
1032	explicit_bzero(imsg->data, len);
1033	ca_getkey(&env->sc_ps, &id, imsg->hdr.type);
1034
1035	return (0);
1036}
1037