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