1/*
2 * Copyright (c) 2007 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23/*
24 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
25 * All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 *    notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 *    notice, this list of conditions and the following disclaimer in the
34 *    documentation and/or other materials provided with the distribution.
35 * 3. Neither the name of the project nor the names of its contributors
36 *    may be used to endorse or promote products derived from this software
37 *    without specific prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49 * SUCH DAMAGE.
50 */
51
52#include "config.h"
53
54#include <sys/types.h>
55#include <sys/param.h>
56#include <sys/socket.h>
57#include <sys/signal.h>
58#include <sys/stat.h>
59#include <sys/un.h>
60
61#include <net/pfkeyv2.h>
62
63#include <netinet/in.h>
64#ifndef HAVE_NETINET6_IPSEC
65#include <netinet/ipsec.h>
66#else
67#include <netinet6/ipsec.h>
68#endif
69
70
71#include <stdlib.h>
72#include <stdio.h>
73#include <string.h>
74#include <errno.h>
75#include <netdb.h>
76#ifdef HAVE_UNISTD_H
77#include <unistd.h>
78#endif
79#ifdef ENABLE_HYBRID
80#include <resolv.h>
81#endif
82
83#include "var.h"
84#include "misc.h"
85#include "vmbuf.h"
86#include "plog.h"
87#include "sockmisc.h"
88#include "debug.h"
89#include "handler.h"
90#include "schedule.h"
91#include "localconf.h"
92#include "remoteconf.h"
93#include "grabmyaddr.h"
94#include "isakmp_var.h"
95#include "isakmp.h"
96#include "oakley.h"
97#include "pfkey.h"
98#include "ipsec_doi.h"
99#include "isakmp_inf.h"
100#ifdef ENABLE_HYBRID
101#include "isakmp_cfg.h"
102#include "isakmp_unity.h"
103#endif
104#include "session.h"
105#include "gcmalloc.h"
106#include "sainfo.h"
107#include "ipsec_doi.h"
108#include "nattraversal.h"
109#include "fsm.h"
110
111#include "vpn_control.h"
112#include "vpn_control_var.h"
113#include "strnames.h"
114#include "ike_session.h"
115#include "ipsecMessageTracer.h"
116
117
118static int vpn_get_ph2pfs (phase1_handle_t *);
119
120int
121vpn_connect(struct bound_addr *srv, int oper)
122{
123	int error = -1;
124	struct sockaddr_storage *dst;
125	struct remoteconf *rmconf;
126	struct sockaddr_storage *remote = NULL;
127	struct sockaddr_storage *local = NULL;
128	u_int16_t port;
129
130	dst = racoon_calloc(1, sizeof(struct sockaddr_storage));	// this should come from the bound_addr parameter
131	if (dst == NULL)
132		goto out;
133	((struct sockaddr_in *)(dst))->sin_len = sizeof(struct sockaddr_in);
134	((struct sockaddr_in *)(dst))->sin_family = AF_INET;
135	((struct sockaddr_in *)(dst))->sin_port = 500;
136	((struct sockaddr_in *)(dst))->sin_addr.s_addr = srv->address;
137
138	/* find appropreate configuration */
139	rmconf = getrmconf(dst);
140	if (rmconf == NULL) {
141		plog(ASL_LEVEL_ERR,
142			"no configuration found "
143			"for %s\n", saddrwop2str((struct sockaddr *)dst));
144		goto out1;
145	}
146
147	/*
148	 * Find the source address
149	 */
150	if (rmconf->forced_local != NULL) {
151		if ((local = dupsaddr(rmconf->forced_local)) == NULL) {
152			plog(ASL_LEVEL_ERR, "failed to duplicate local address\n");
153			goto out1;
154		}
155	} else if ((local = getlocaladdr((struct sockaddr *)dst)) == NULL) {
156		plog(ASL_LEVEL_ERR, "cannot get local address\n");
157		goto out1;
158	}
159
160	/* get remote IP address and port number. */
161	if ((remote = dupsaddr(dst)) == NULL) {
162		plog(ASL_LEVEL_ERR,
163			"failed to duplicate address\n");
164		goto out1;
165	}
166
167	switch (remote->ss_family) {
168	case AF_INET:
169		((struct sockaddr_in *)remote)->sin_port =
170			((struct sockaddr_in *)rmconf->remote)->sin_port;
171		break;
172#ifdef INET6
173	case AF_INET6:
174		((struct sockaddr_in6 *)remote)->sin6_port =
175			((struct sockaddr_in6 *)rmconf->remote)->sin6_port;
176		break;
177#endif
178	default:
179		plog(ASL_LEVEL_ERR,
180			"invalid family: %d\n",
181			remote->ss_family);
182		goto out1;
183		break;
184	}
185
186	port = ntohs(getmyaddrsport(local));
187	if (set_port(local, port) == NULL)
188		goto out1;
189
190	plog(ASL_LEVEL_INFO,
191		"accept a request to establish IKE-SA: "
192		"%s\n", saddrwop2str((struct sockaddr *)remote));
193
194	IPSECLOGASLMSG("IPSec connecting to server %s\n",
195				   saddrwop2str((struct sockaddr *)remote));
196	if (ikev1_ph1begin_i(NULL, rmconf, remote, local, oper) < 0)
197		goto out1;
198	error = 0;
199
200out1:
201	if (dst != NULL)
202		racoon_free(dst);
203	if (local != NULL)
204		racoon_free(local);
205	if (remote != NULL)
206		racoon_free(remote);
207out:
208
209	return error;
210}
211
212int
213vpn_disconnect(struct bound_addr *srv, const char *reason)
214{
215	union {									// Wcast-align fix - force alignment
216        struct sockaddr_storage	ss;
217        struct sockaddr_in  saddr;
218    } u;
219
220	bzero(&u.saddr, sizeof(u.saddr));
221	u.saddr.sin_len = sizeof(u.saddr);
222	u.saddr.sin_addr.s_addr = srv->address;
223	u.saddr.sin_port = 0;
224	u.saddr.sin_family = AF_INET;
225
226	IPSECLOGASLMSG("IPSec disconnecting from server %s\n",
227				   saddrwop2str((struct sockaddr *)&u.ss));
228
229	ike_sessions_stopped_by_controller(&u.ss,
230                                       0,
231                                       reason);
232	if (ike_session_purgephXbydstaddrwop(&u.ss) > 0) {
233		return 0;
234	} else {
235		return -1;
236	}
237}
238
239int
240vpn_start_ph2(struct bound_addr *addr, struct vpnctl_cmd_start_ph2 *pkt)
241{
242	struct vpnctl_sa_selector *selector_ptr;
243	struct vpnctl_algo *algo_ptr, *next_algo;
244	int					i, j, defklen;
245	struct sainfoalg	*new_algo;
246	struct sainfo		*new_sainfo = NULL, *check;
247	u_int16_t			class, algorithm, keylen;
248	phase1_handle_t	*ph1;
249	struct sockaddr_in	saddr;
250
251	struct id {
252		u_int8_t type;		/* ID Type */
253		u_int8_t proto_id;	/* Protocol ID */
254		u_int16_t port;		/* Port */
255		u_int32_t addr;		/* IPv4 address */
256		u_int32_t mask;
257	} *id_ptr;
258
259	/* verify ph1 exists */
260	bzero(&saddr, sizeof(saddr));
261	saddr.sin_len = sizeof(saddr);
262	saddr.sin_addr.s_addr = addr->address;
263	saddr.sin_port = 0;
264	saddr.sin_family = AF_INET;
265	ph1 = ike_session_getph1bydstaddrwop(NULL, (struct sockaddr_storage *)(&saddr));
266	if (ph1 == NULL) {
267		plog(ASL_LEVEL_ERR,
268			"Cannot start Phase 2 - no Phase 1 found.\n");
269		return -1;
270	}
271	if (!FSM_STATE_IS_ESTABLISHED(ph1->status)) {
272		plog(ASL_LEVEL_ERR,
273			 "Cannot start Phase 2 - Phase 1 not established.\n");
274		return -1;
275	}
276
277	selector_ptr = (struct vpnctl_sa_selector *)(pkt + 1);
278	algo_ptr = (struct vpnctl_algo *)(selector_ptr + ntohs(pkt->selector_count));
279
280	for (i = 0; i < ntohs(pkt->selector_count); i++, selector_ptr++) {
281		new_sainfo = create_sainfo();
282		if (new_sainfo == NULL) {
283			plog(ASL_LEVEL_ERR,
284				"Unable to allocate sainfo struct.\n");
285			goto fail;
286		}
287
288		if (ntohl(selector_ptr->src_tunnel_mask) == 0xFFFFFFFF)
289			new_sainfo->idsrc = vmalloc(sizeof(struct id) - sizeof(u_int32_t));
290		else
291			new_sainfo->idsrc = vmalloc(sizeof(struct id));
292		if (new_sainfo->idsrc == NULL) {
293			plog(ASL_LEVEL_ERR,
294				 "Unable to allocate id struct.\n");
295			goto fail;
296		}
297		if (selector_ptr->dst_tunnel_mask == 0xFFFFFFFF)
298			new_sainfo->iddst = vmalloc(sizeof(struct id) - sizeof(u_int32_t));
299		else
300			new_sainfo->iddst = vmalloc(sizeof(struct id));
301		if (new_sainfo->iddst == NULL) {
302			plog(ASL_LEVEL_ERR,
303				 "Unable to allocate id struct.\n");
304			goto fail;
305		}
306
307		id_ptr = ALIGNED_CAST(struct id *)new_sainfo->idsrc->v;
308		if (ntohl(selector_ptr->src_tunnel_mask) == 0xFFFFFFFF)
309			id_ptr->type = IPSECDOI_ID_IPV4_ADDR;
310		else {
311			id_ptr->type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
312			id_ptr->mask = selector_ptr->src_tunnel_mask;
313		}
314		id_ptr->addr = selector_ptr->src_tunnel_address;
315		id_ptr->port = selector_ptr->src_tunnel_port;
316		id_ptr->proto_id = selector_ptr->ul_protocol;
317
318		id_ptr = ALIGNED_CAST(struct id *)new_sainfo->iddst->v;
319		if (selector_ptr->dst_tunnel_mask == 0xFFFFFFFF)
320			id_ptr->type = IPSECDOI_ID_IPV4_ADDR;
321		else {
322			id_ptr->type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
323			id_ptr->mask = selector_ptr->dst_tunnel_mask;
324		}
325		id_ptr->addr = selector_ptr->dst_tunnel_address;
326		id_ptr->port = selector_ptr->dst_tunnel_port;
327		id_ptr->proto_id = selector_ptr->ul_protocol;
328
329		new_sainfo->dynamic = addr->address;
330		new_sainfo->lifetime = ntohl(pkt->lifetime);
331
332		if (ntohs(pkt->pfs_group) != 0) {
333			new_sainfo->pfs_group = algtype2doi(algclass_isakmp_dh, ntohs(pkt->pfs_group));
334			if (new_sainfo->pfs_group == -1) {
335				plog(ASL_LEVEL_ERR, "Invalid dh group specified\n");
336				goto fail;
337			}
338		}
339		for (j = 0, next_algo = algo_ptr; j < ntohs(pkt->algo_count); j++, next_algo++) {
340
341			new_algo = newsainfoalg();
342			if (new_algo == NULL) {
343				plog(ASL_LEVEL_ERR,
344					"Failed to allocate algorithm structure\n");
345				goto fail;
346			}
347
348			class = ntohs(next_algo->algo_class);
349			algorithm = ntohs(next_algo->algo);
350			keylen = ntohs(next_algo->key_len);
351
352			new_algo->alg = algtype2doi(class, algorithm);
353			if (new_algo->alg == -1) {
354				plog(ASL_LEVEL_ERR, "Algorithm mismatched\n");
355				racoon_free(new_algo);
356				goto fail;
357			}
358
359			defklen = default_keylen(class, algorithm);
360			if (defklen == 0) {
361				if (keylen) {
362					plog(ASL_LEVEL_ERR, "keylen not allowed\n");
363					racoon_free(new_algo);
364					goto fail;
365				}
366			} else {
367				if (keylen && check_keylen(class, algorithm, keylen) < 0) {
368					plog(ASL_LEVEL_ERR, "invalid keylen %d\n", keylen);
369					racoon_free(new_algo);
370					goto fail;
371				}
372			}
373
374			if (keylen)
375				new_algo->encklen = keylen;
376			else
377				new_algo->encklen = defklen;
378
379			/* check if it's supported algorithm by kernel */
380			if (!(class == algclass_ipsec_auth && algorithm == algtype_non_auth)
381			 && pk_checkalg(class, algorithm, new_algo->encklen)) {
382				int a = algclass2doi(class);
383				int b = new_algo->alg;
384				if (a == IPSECDOI_ATTR_AUTH)
385					a = IPSECDOI_PROTO_IPSEC_AH;
386				plog(ASL_LEVEL_ERR,
387					"Algorithm %s not supported by the kernel (missing module?)\n", s_ipsecdoi_trns(a, b));
388				racoon_free(new_algo);
389				goto fail;
390			}
391			inssainfoalg(&new_sainfo->algs[class], new_algo);
392		}
393
394		if (new_sainfo->algs[algclass_ipsec_enc] == 0) {
395			plog(ASL_LEVEL_ERR,
396				"No encryption algorithm at %s\n", sainfo2str(new_sainfo));
397			goto fail;
398		}
399		if (new_sainfo->algs[algclass_ipsec_auth] == 0) {
400			plog(ASL_LEVEL_ERR,
401				"No authentication algorithm at %s\n", sainfo2str(new_sainfo));
402			goto fail;
403		}
404		if (new_sainfo->algs[algclass_ipsec_comp] == 0) {
405			plog(ASL_LEVEL_ERR,
406				"No compression algorithm at %s\n", sainfo2str(new_sainfo));
407			goto fail;
408		}
409
410		/* duplicate check */
411		check = getsainfo(new_sainfo->idsrc, new_sainfo->iddst, new_sainfo->id_i, 0);
412		if (check && (!check->idsrc && !new_sainfo->idsrc)) {
413			plog(ASL_LEVEL_ERR, "Duplicated sainfo: %s\n", sainfo2str(new_sainfo));
414			goto fail;
415		}
416		//plog(ASL_LEVEL_DEBUG, "create sainfo: %s\n", sainfo2str(new_sainfo));
417		inssainfo(new_sainfo);
418		new_sainfo = NULL;
419	}
420
421	return 0;
422
423fail:
424	if (new_sainfo)
425		release_sainfo(new_sainfo);
426	flushsainfo_dynamic((u_int32_t)addr->address);
427	return -1;
428}
429
430static int
431vpn_get_ph2pfs(phase1_handle_t *ph1)
432{
433}
434
435
436int
437vpn_get_config(phase1_handle_t *iph1, struct vpnctl_status_phase_change **msg, size_t *msg_size)
438{
439
440	struct vpnctl_modecfg_params *params;
441	struct myaddrs *myaddr;
442	u_int16_t ifname_len, msize;
443	u_int8_t  *cptr;
444
445	*msg = NULL;
446	msize = 0;
447
448	if (((struct sockaddr_in *)iph1->local)->sin_family != AF_INET) {
449		plog(ASL_LEVEL_ERR,
450			"IPv6 not supported for mode config.\n");
451		return -1;
452	}
453
454	if (iph1->mode_cfg->attr_list == NULL)
455		return 1;	/* haven't received configuration yet */
456
457	myaddr = find_myaddr((struct sockaddr *)iph1->local, 0);
458	if (myaddr == NULL) {
459		plog(ASL_LEVEL_ERR,
460			"Unable to find address structure.\n");
461		return -1;
462	}
463
464	msize = sizeof(struct vpnctl_status_phase_change)
465			+ sizeof(struct vpnctl_modecfg_params);
466	msize += iph1->mode_cfg->attr_list->l;
467
468	*msg = racoon_calloc(1, msize);
469	if (*msg == NULL) {
470		plog(ASL_LEVEL_ERR,
471			"Failed to allocate space for message.\n");
472		return -1;
473	}
474
475	(*msg)->hdr.flags = htons(VPNCTL_FLAG_MODECFG_USED);
476	params = (struct vpnctl_modecfg_params *)(*msg + 1);
477	params->outer_local_addr = ((struct sockaddr_in *)iph1->local)->sin_addr.s_addr;
478	params->outer_remote_port = htons(0);
479	params->outer_local_port = htons(0);
480	ifname_len = strlen(myaddr->ifname);
481	memset(&params->ifname, 0, IFNAMSIZ);
482	memcpy(&params->ifname, myaddr->ifname, ifname_len < IFNAMSIZ ? ifname_len : IFNAMSIZ-1);
483	cptr = (u_int8_t *)(params + 1);
484	memcpy(cptr, iph1->mode_cfg->attr_list->v, iph1->mode_cfg->attr_list->l);
485	*msg_size = msize;
486
487	IPSECLOGASLMSG("IPSec Network Configuration established.\n");
488
489	return 0;
490}
491
492int
493vpn_xauth_reply(u_int32_t address, void *attr_list, size_t attr_len)
494{
495
496	struct isakmp_pl_attr *reply;
497	void* attr_ptr;
498	vchar_t *payload = NULL;
499	phase1_handle_t	*iph1;
500	struct sockaddr_in	saddr;
501	int error = -1;
502	int tlen = attr_len;
503	struct isakmp_data *attr;
504	char *dataptr = (char *)attr_list;
505
506	/* find ph1 */
507	bzero(&saddr, sizeof(saddr));
508	saddr.sin_len = sizeof(saddr);
509	saddr.sin_addr.s_addr = address;
510	saddr.sin_port = 0;
511	saddr.sin_family = AF_INET;
512	iph1 = ike_session_getph1bydstaddrwop(NULL, (struct sockaddr_storage *)(&saddr));
513	if (iph1 == NULL) {
514		plog(ASL_LEVEL_ERR,
515			"Cannot reply to xauth request - no ph1 found.\n");
516		goto end;
517	}
518
519	if (iph1->xauth_awaiting_userinput == 0) {
520		plog(ASL_LEVEL_ERR, "Received xauth reply data with no xauth reply pending \n");
521		goto end;
522	}
523
524	/* validate attr lengths */
525	while (tlen > 0)
526	{
527		int tlv;
528
529		attr = (struct isakmp_data *)dataptr;
530		tlv = (attr->type & htons(0x8000)) == 0;
531
532		if (tlv) {
533			tlen -= ntohs(attr->lorv);
534			dataptr += ntohs(attr->lorv);
535		}
536		tlen -= sizeof(u_int32_t);
537		dataptr += sizeof(u_int32_t);
538	}
539	if (tlen != 0) {
540		plog(ASL_LEVEL_ERR, "Invalid auth info received from VPN Control socket.\n");
541		goto end;
542	}
543
544	payload = vmalloc(sizeof(struct isakmp_pl_attr) + attr_len);
545	if (payload == NULL) {
546		plog(ASL_LEVEL_ERR, "Cannot allocate memory for xauth reply\n");
547		goto end;
548	}
549	memset(payload->v, 0, sizeof(reply));
550
551	reply = (struct isakmp_pl_attr *)payload->v;
552	reply->h.len = htons(payload->l);
553	reply->type = ISAKMP_CFG_REPLY;
554	reply->id = iph1->pended_xauth_id;	/* network byte order */
555	iph1->xauth_awaiting_userinput = 0;	/* no longer waiting */
556	attr_ptr = reply + 1;
557	memcpy(attr_ptr, attr_list, attr_len);
558
559	plog(ASL_LEVEL_DEBUG,
560		    "Sending MODE_CFG REPLY\n");
561	error = isakmp_cfg_send(iph1, payload,
562	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0, 0, iph1->xauth_awaiting_userinput_msg);
563	VPTRINIT(iph1->xauth_awaiting_userinput_msg);
564	ike_session_stop_xauth_timer(iph1);
565
566	IPSECLOGASLMSG("IPSec Extended Authentication sent.\n");
567
568end:
569	if (payload)
570		vfree(payload);
571	return error;
572}
573
574int
575vpn_assert(struct sockaddr_storage *src_addr, struct sockaddr_storage *dst_addr)
576{
577	if (ike_session_assert(src_addr, dst_addr)) {
578		plog(ASL_LEVEL_ERR,
579			 "Cannot assert - no matching session.\n");
580		return -1;
581	}
582
583	return 0;
584}
585
586