2 * Copyright (c) 2007 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
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.
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
54 #include <sys/types.h>
55 #include <sys/param.h>
56 #include <sys/socket.h>
57 #include <sys/signal.h>
61 #include <net/pfkeyv2.h>
63 #include <netinet/in.h>
64 #ifndef HAVE_NETINET6_IPSEC
65 #include <netinet/ipsec.h>
67 #include <netinet6/ipsec.h>
88 #include "localconf.h"
89 #include "remoteconf.h"
90 #include "grabmyaddr.h"
91 #include "isakmp_var.h"
95 #include "ipsec_doi.h"
96 #include "isakmp_inf.h"
98 #include "isakmp_cfg.h"
99 #include "isakmp_unity.h"
102 #include "gcmalloc.h"
104 #include "ipsec_doi.h"
105 #include "nattraversal.h"
108 #include "vpn_control.h"
109 #include "vpn_control_var.h"
110 #include "strnames.h"
111 #include "ike_session.h"
112 #include "ipsecMessageTracer.h"
115 static int vpn_get_ph2pfs (phase1_handle_t
*);
118 vpn_connect(struct bound_addr
*srv
, int oper
)
121 struct sockaddr_storage
*dst
;
122 struct remoteconf
*rmconf
;
123 struct sockaddr_storage
*remote
= NULL
;
124 struct sockaddr_storage
*local
= NULL
;
127 dst
= racoon_calloc(1, sizeof(struct sockaddr_storage
)); // this should come from the bound_addr parameter
130 ((struct sockaddr_in
*)(dst
))->sin_len
= sizeof(struct sockaddr_in
);
131 ((struct sockaddr_in
*)(dst
))->sin_family
= AF_INET
;
132 ((struct sockaddr_in
*)(dst
))->sin_port
= PORT_ISAKMP
;
133 ((struct sockaddr_in
*)(dst
))->sin_addr
.s_addr
= srv
->address
;
135 /* find appropreate configuration */
136 rmconf
= getrmconf(dst
);
137 if (rmconf
== NULL
) {
139 "no configuration found "
140 "for %s\n", saddrwop2str((struct sockaddr
*)dst
));
145 * Find the source address
147 if (rmconf
->forced_local
!= NULL
) {
148 if ((local
= dupsaddr(rmconf
->forced_local
)) == NULL
) {
149 plog(ASL_LEVEL_ERR
, "failed to duplicate local address\n");
152 } else if ((local
= getlocaladdr((struct sockaddr
*)dst
)) == NULL
) {
153 plog(ASL_LEVEL_ERR
, "cannot get local address\n");
157 if (srv
->nat64_prefix
.length
> 0) {
158 memset(dst
, 0, sizeof(*dst
));
159 ((struct sockaddr_in6
*)(dst
))->sin6_len
= sizeof(struct sockaddr_in6
);
160 ((struct sockaddr_in6
*)(dst
))->sin6_family
= AF_INET6
;
161 ((struct sockaddr_in6
*)(dst
))->sin6_port
= PORT_ISAKMP
;
162 nw_nat64_synthesize_v6(&srv
->nat64_prefix
, (struct in_addr
*)&srv
->address
, &((struct sockaddr_in6
*)(dst
))->sin6_addr
);
165 /* get remote IP address and port number. */
166 if ((remote
= dupsaddr(dst
)) == NULL
) {
168 "failed to duplicate address\n");
172 switch (remote
->ss_family
) {
174 ((struct sockaddr_in
*)remote
)->sin_port
=
175 ((struct sockaddr_in
*)rmconf
->remote
)->sin_port
;
179 ((struct sockaddr_in6
*)remote
)->sin6_port
=
180 ((struct sockaddr_in6
*)rmconf
->remote
)->sin6_port
;
185 "invalid family: %d\n",
191 port
= ntohs(getmyaddrsport(local
));
192 if (set_port(local
, port
) == NULL
)
195 plog(ASL_LEVEL_NOTICE
,
196 "accept a request to establish IKE-SA: "
197 "%s\n", saddrwop2str((struct sockaddr
*)remote
));
199 IPSECLOGASLMSG("IPSec connecting to server %s\n",
200 saddrwop2str((struct sockaddr
*)remote
));
201 if (ikev1_ph1begin_i(NULL
, rmconf
, remote
, local
, oper
, &srv
->nat64_prefix
) < 0)
218 vpn_disconnect(struct bound_addr
*srv
, const char *reason
)
220 union { // Wcast-align fix - force alignment
221 struct sockaddr_storage ss
;
222 struct sockaddr_in saddr
;
225 bzero(&u
.saddr
, sizeof(u
.saddr
));
226 u
.saddr
.sin_len
= sizeof(u
.saddr
);
227 u
.saddr
.sin_addr
.s_addr
= srv
->address
;
228 u
.saddr
.sin_port
= 0;
229 u
.saddr
.sin_family
= AF_INET
;
231 IPSECLOGASLMSG("IPSec disconnecting from server %s\n",
232 saddrwop2str((struct sockaddr
*)&u
.ss
));
234 ike_sessions_stopped_by_controller(&u
.ss
,
237 if (ike_session_purgephXbydstaddrwop(&u
.ss
) > 0) {
245 vpn_start_ph2(struct bound_addr
*addr
, struct vpnctl_cmd_start_ph2
*pkt
, size_t pkt_len
)
247 struct vpnctl_sa_selector
*selector_ptr
;
248 struct vpnctl_algo
*algo_ptr
, *next_algo
;
250 struct sainfoalg
*new_algo
;
251 struct sainfo
*new_sainfo
= NULL
, *check
;
252 u_int16_t
class, algorithm
, keylen
;
253 phase1_handle_t
*ph1
;
254 struct sockaddr_in saddr
;
257 u_int8_t type
; /* ID Type */
258 u_int8_t proto_id
; /* Protocol ID */
259 u_int16_t port
; /* Port */
260 u_int32_t addr
; /* IPv4 address */
264 /* verify ph1 exists */
265 bzero(&saddr
, sizeof(saddr
));
266 saddr
.sin_len
= sizeof(saddr
);
267 saddr
.sin_addr
.s_addr
= addr
->address
;
269 saddr
.sin_family
= AF_INET
;
270 ph1
= ike_session_getph1bydstaddrwop(NULL
, ALIGNED_CAST(struct sockaddr_storage
*)(&saddr
));
273 "Cannot start Phase 2 - no Phase 1 found.\n");
276 if (!FSM_STATE_IS_ESTABLISHED(ph1
->status
)) {
278 "Cannot start Phase 2 - Phase 1 not established.\n");
282 selector_ptr
= (struct vpnctl_sa_selector
*)(pkt
+ 1);
283 size_t total_selector_len
= (sizeof(struct vpnctl_sa_selector
) * ntohs(pkt
->selector_count
));
284 if (pkt_len
< (sizeof(struct vpnctl_cmd_start_ph2
) + total_selector_len
)) {
285 plog(ASL_LEVEL_ERR
, "invalid length for vpn ph2 selector - len=%ld - expected %ld\n", pkt_len
, (sizeof(struct vpnctl_cmd_start_ph2
) + total_selector_len
));
289 algo_ptr
= (struct vpnctl_algo
*)(selector_ptr
+ ntohs(pkt
->selector_count
));
290 size_t total_algo_len
= (sizeof(struct vpnctl_algo
) * ntohs(pkt
->algo_count
));
291 if (pkt_len
< (sizeof(struct vpnctl_cmd_start_ph2
) + total_selector_len
+ total_algo_len
)) {
292 plog(ASL_LEVEL_ERR
, "invalid length for vpn ph2 algo - len=%ld - expected %ld\n", pkt_len
, (sizeof(struct vpnctl_cmd_start_ph2
) + total_selector_len
+ total_algo_len
));
296 for (i
= 0; i
< ntohs(pkt
->selector_count
); i
++, selector_ptr
++) {
297 new_sainfo
= create_sainfo();
298 if (new_sainfo
== NULL
) {
300 "Unable to allocate sainfo struct.\n");
304 if (ntohl(selector_ptr
->src_tunnel_mask
) == 0xFFFFFFFF)
305 new_sainfo
->idsrc
= vmalloc(sizeof(struct id
) - sizeof(u_int32_t
));
307 new_sainfo
->idsrc
= vmalloc(sizeof(struct id
));
308 if (new_sainfo
->idsrc
== NULL
) {
310 "Unable to allocate id struct.\n");
313 if (selector_ptr
->dst_tunnel_mask
== 0xFFFFFFFF)
314 new_sainfo
->iddst
= vmalloc(sizeof(struct id
) - sizeof(u_int32_t
));
316 new_sainfo
->iddst
= vmalloc(sizeof(struct id
));
317 if (new_sainfo
->iddst
== NULL
) {
319 "Unable to allocate id struct.\n");
323 id_ptr
= ALIGNED_CAST(struct id
*)new_sainfo
->idsrc
->v
;
324 if (ntohl(selector_ptr
->src_tunnel_mask
) == 0xFFFFFFFF)
325 id_ptr
->type
= IPSECDOI_ID_IPV4_ADDR
;
327 id_ptr
->type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
328 id_ptr
->mask
= selector_ptr
->src_tunnel_mask
;
330 id_ptr
->addr
= selector_ptr
->src_tunnel_address
;
331 id_ptr
->port
= selector_ptr
->src_tunnel_port
;
332 id_ptr
->proto_id
= selector_ptr
->ul_protocol
;
334 id_ptr
= ALIGNED_CAST(struct id
*)new_sainfo
->iddst
->v
;
335 if (selector_ptr
->dst_tunnel_mask
== 0xFFFFFFFF)
336 id_ptr
->type
= IPSECDOI_ID_IPV4_ADDR
;
338 id_ptr
->type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
339 id_ptr
->mask
= selector_ptr
->dst_tunnel_mask
;
341 id_ptr
->addr
= selector_ptr
->dst_tunnel_address
;
342 id_ptr
->port
= selector_ptr
->dst_tunnel_port
;
343 id_ptr
->proto_id
= selector_ptr
->ul_protocol
;
345 new_sainfo
->dynamic
= addr
->address
;
346 new_sainfo
->lifetime
= ntohl(pkt
->lifetime
);
348 if (ntohs(pkt
->pfs_group
) != 0) {
349 new_sainfo
->pfs_group
= algtype2doi(algclass_isakmp_dh
, ntohs(pkt
->pfs_group
));
350 if (new_sainfo
->pfs_group
== -1) {
351 plog(ASL_LEVEL_ERR
, "Invalid dh group specified\n");
355 for (j
= 0, next_algo
= algo_ptr
; j
< ntohs(pkt
->algo_count
); j
++, next_algo
++) {
357 new_algo
= newsainfoalg();
358 if (new_algo
== NULL
) {
360 "Failed to allocate algorithm structure\n");
364 class = ntohs(next_algo
->algo_class
);
365 algorithm
= ntohs(next_algo
->algo
);
366 keylen
= ntohs(next_algo
->key_len
);
368 new_algo
->alg
= algtype2doi(class, algorithm
);
369 if (new_algo
->alg
== -1) {
370 plog(ASL_LEVEL_ERR
, "Algorithm mismatched\n");
371 racoon_free(new_algo
);
375 defklen
= default_keylen(class, algorithm
);
378 plog(ASL_LEVEL_ERR
, "keylen not allowed\n");
379 racoon_free(new_algo
);
383 if (keylen
&& check_keylen(class, algorithm
, keylen
) < 0) {
384 plog(ASL_LEVEL_ERR
, "invalid keylen %d\n", keylen
);
385 racoon_free(new_algo
);
391 new_algo
->encklen
= keylen
;
393 new_algo
->encklen
= defklen
;
395 /* check if it's supported algorithm by kernel */
396 if (!(class == algclass_ipsec_auth
&& algorithm
== algtype_non_auth
)
397 && pk_checkalg(class, algorithm
, new_algo
->encklen
)) {
398 int a
= algclass2doi(class);
399 int b
= new_algo
->alg
;
400 if (a
== IPSECDOI_ATTR_AUTH
)
401 a
= IPSECDOI_PROTO_IPSEC_AH
;
403 "Algorithm %s not supported by the kernel (missing module?)\n", s_ipsecdoi_trns(a
, b
));
404 racoon_free(new_algo
);
407 inssainfoalg(&new_sainfo
->algs
[class], new_algo
);
410 if (new_sainfo
->algs
[algclass_ipsec_enc
] == 0) {
412 "No encryption algorithm at %s\n", sainfo2str(new_sainfo
));
415 if (new_sainfo
->algs
[algclass_ipsec_auth
] == 0) {
417 "No authentication algorithm at %s\n", sainfo2str(new_sainfo
));
420 if (new_sainfo
->algs
[algclass_ipsec_comp
] == 0) {
422 "No compression algorithm at %s\n", sainfo2str(new_sainfo
));
426 /* duplicate check */
427 check
= getsainfo(new_sainfo
->idsrc
, new_sainfo
->iddst
, new_sainfo
->id_i
, 0);
428 if (check
&& (!check
->idsrc
&& !new_sainfo
->idsrc
)) {
429 plog(ASL_LEVEL_ERR
, "Duplicated sainfo: %s\n", sainfo2str(new_sainfo
));
432 //plog(ASL_LEVEL_DEBUG, "create sainfo: %s\n", sainfo2str(new_sainfo));
433 inssainfo(new_sainfo
);
441 release_sainfo(new_sainfo
);
442 flushsainfo_dynamic((u_int32_t
)addr
->address
);
447 vpn_get_ph2pfs(phase1_handle_t
*ph1
)
453 vpn_get_config(phase1_handle_t
*iph1
, struct vpnctl_status_phase_change
**msg
, size_t *msg_size
)
456 struct vpnctl_modecfg_params
*params
;
457 struct myaddrs
*myaddr
;
458 u_int16_t ifname_len
, msize
;
464 /*if (((struct sockaddr_in *)iph1->local)->sin_family != AF_INET) {
466 "IPv6 not supported for mode config.\n");
470 if (iph1
->mode_cfg
->attr_list
== NULL
)
471 return 1; /* haven't received configuration yet */
473 myaddr
= find_myaddr((struct sockaddr
*)iph1
->local
, 0);
474 if (myaddr
== NULL
) {
476 "Unable to find address structure.\n");
480 msize
= sizeof(struct vpnctl_status_phase_change
)
481 + sizeof(struct vpnctl_modecfg_params
);
482 msize
+= iph1
->mode_cfg
->attr_list
->l
;
484 *msg
= racoon_calloc(1, msize
);
487 "Failed to allocate space for message.\n");
491 (*msg
)->hdr
.flags
= htons(VPNCTL_FLAG_MODECFG_USED
);
492 params
= (struct vpnctl_modecfg_params
*)(*msg
+ 1);
493 if (((struct sockaddr_in
*)iph1
->local
)->sin_family
== AF_INET
) {
494 params
->outer_local_addr
= ((struct sockaddr_in
*)iph1
->local
)->sin_addr
.s_addr
;
496 params
->outer_remote_port
= htons(0);
497 params
->outer_local_port
= htons(0);
498 ifname_len
= strlen(myaddr
->ifname
);
499 memset(¶ms
->ifname
, 0, IFNAMSIZ
);
500 memcpy(¶ms
->ifname
, myaddr
->ifname
, ifname_len
< IFNAMSIZ
? ifname_len
: IFNAMSIZ
-1);
501 cptr
= (u_int8_t
*)(params
+ 1);
502 memcpy(cptr
, iph1
->mode_cfg
->attr_list
->v
, iph1
->mode_cfg
->attr_list
->l
);
505 IPSECLOGASLMSG("IPSec Network Configuration established.\n");
511 vpn_xauth_reply(u_int32_t address
, void *attr_list
, size_t attr_len
)
514 struct isakmp_pl_attr
*reply
;
516 vchar_t
*payload
= NULL
;
517 phase1_handle_t
*iph1
;
518 struct sockaddr_in saddr
;
521 struct isakmp_data
*attr
;
522 char *dataptr
= (char *)attr_list
;
525 bzero(&saddr
, sizeof(saddr
));
526 saddr
.sin_len
= sizeof(saddr
);
527 saddr
.sin_addr
.s_addr
= address
;
529 saddr
.sin_family
= AF_INET
;
530 iph1
= ike_session_getph1bydstaddrwop(NULL
, ALIGNED_CAST(struct sockaddr_storage
*)(&saddr
));
533 "Cannot reply to xauth request - no ph1 found.\n");
537 if (iph1
->xauth_awaiting_userinput
== 0) {
538 plog(ASL_LEVEL_ERR
, "Received xauth reply data with no xauth reply pending \n");
542 /* validate attr lengths */
547 attr
= (struct isakmp_data
*)dataptr
;
548 tlv
= (attr
->type
& htons(0x8000)) == 0;
551 tlen
-= ntohs(attr
->lorv
);
552 dataptr
+= ntohs(attr
->lorv
);
554 tlen
-= sizeof(u_int32_t
);
555 dataptr
+= sizeof(u_int32_t
);
558 plog(ASL_LEVEL_ERR
, "Invalid auth info received from VPN Control socket.\n");
562 payload
= vmalloc(sizeof(struct isakmp_pl_attr
) + attr_len
);
563 if (payload
== NULL
) {
564 plog(ASL_LEVEL_ERR
, "Cannot allocate memory for xauth reply\n");
567 memset(payload
->v
, 0, sizeof(reply
));
569 reply
= (struct isakmp_pl_attr
*)payload
->v
;
570 reply
->h
.len
= htons(payload
->l
);
571 reply
->type
= ISAKMP_CFG_REPLY
;
572 reply
->id
= iph1
->pended_xauth_id
; /* network byte order */
573 iph1
->xauth_awaiting_userinput
= 0; /* no longer waiting */
574 attr_ptr
= reply
+ 1;
575 memcpy(attr_ptr
, attr_list
, attr_len
);
577 plog(ASL_LEVEL_DEBUG
,
578 "Sending MODE_CFG REPLY\n");
579 error
= isakmp_cfg_send(iph1
, payload
,
580 ISAKMP_NPTYPE_ATTR
, ISAKMP_FLAG_E
, 0, 0, iph1
->xauth_awaiting_userinput_msg
);
581 VPTRINIT(iph1
->xauth_awaiting_userinput_msg
);
582 ike_session_stop_xauth_timer(iph1
);
584 IPSECLOGASLMSG("IPSec Extended Authentication sent.\n");
593 vpn_assert(struct sockaddr_storage
*src_addr
, struct sockaddr_storage
*dst_addr
)
595 if (ike_session_assert(src_addr
, dst_addr
)) {
597 "Cannot assert - no matching session.\n");