]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/vpn.c
ipsec-146.3.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / vpn.c
CommitLineData
d1e348cf
A
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
d1e348cf 61#include <System/net/pfkeyv2.h>
d1e348cf
A
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 "evt.h"
98#include "pfkey.h"
99#include "ipsec_doi.h"
100#include "admin.h"
101#include "admin_var.h"
102#include "isakmp_inf.h"
103#ifdef ENABLE_HYBRID
104#include "isakmp_cfg.h"
105#include "isakmp_unity.h"
106#endif
107#include "session.h"
108#include "gcmalloc.h"
109#include "sainfo.h"
110#include "ipsec_doi.h"
111#include "nattraversal.h"
112
113#include "vpn_control.h"
114#include "vpn_control_var.h"
115#include "strnames.h"
116#include "ike_session.h"
e8d9021d 117#include "ipsecMessageTracer.h"
d1e348cf
A
118
119
120static int vpn_get_ph2pfs(struct ph1handle *);
121
122int
e8d9021d 123vpn_connect(struct bound_addr *srv, int oper)
d1e348cf
A
124{
125 int error = -1;
126 struct sockaddr *dst;
127 struct remoteconf *rmconf;
128 struct sockaddr *remote = NULL;
129 struct sockaddr *local = NULL;
130 u_int16_t port;
131
132 dst = racoon_calloc(1, sizeof(struct sockaddr)); // this should come from the bound_addr parameter
133 if (dst == NULL)
134 goto out;
135 ((struct sockaddr_in *)(dst))->sin_len = sizeof(struct sockaddr_in);
136 ((struct sockaddr_in *)(dst))->sin_family = AF_INET;
137 ((struct sockaddr_in *)(dst))->sin_port = 500;
138 ((struct sockaddr_in *)(dst))->sin_addr.s_addr = srv->address;
139
140 /*
141 * Find the source address
142 */
143 if ((local = getlocaladdr(dst)) == NULL) {
144 plog(LLV_ERROR, LOCATION, NULL,
145 "cannot get local address\n");
146 goto out1;
147 }
148
149 /* find appropreate configuration */
150 rmconf = getrmconf(dst);
151 if (rmconf == NULL) {
152 plog(LLV_ERROR, LOCATION, NULL,
153 "no configuration found "
154 "for %s\n", saddrwop2str(dst));
155 goto out1;
156 }
157
158 /* get remote IP address and port number. */
159 if ((remote = dupsaddr(dst)) == NULL) {
160 plog(LLV_ERROR, LOCATION, NULL,
161 "failed to duplicate address\n");
162 goto out1;
163 }
164
165 switch (remote->sa_family) {
166 case AF_INET:
167 ((struct sockaddr_in *)remote)->sin_port =
168 ((struct sockaddr_in *)rmconf->remote)->sin_port;
169 break;
170#ifdef INET6
171 case AF_INET6:
172 ((struct sockaddr_in6 *)remote)->sin6_port =
173 ((struct sockaddr_in6 *)rmconf->remote)->sin6_port;
174 break;
175#endif
176 default:
177 plog(LLV_ERROR, LOCATION, NULL,
178 "invalid family: %d\n",
179 remote->sa_family);
180 goto out1;
181 break;
182 }
183
184 port = ntohs(getmyaddrsport(local));
185 if (set_port(local, port) == NULL)
186 goto out1;
187
188 plog(LLV_INFO, LOCATION, NULL,
189 "accept a request to establish IKE-SA: "
190 "%s\n", saddrwop2str(remote));
191
e8d9021d
A
192 IPSECLOGASLMSG("IPSec connecting to server %s\n",
193 saddrwop2str(remote));
194
d1e348cf 195 /* begin ident mode */
e8d9021d 196 if (isakmp_ph1begin_i(rmconf, remote, local, oper) < 0)
d1e348cf
A
197 goto out1;
198
199 error = 0;
200
201out1:
202 if (dst != NULL)
203 racoon_free(dst);
204 if (local != NULL)
205 racoon_free(local);
206 if (remote != NULL)
207 racoon_free(remote);
208out:
209
210 return error;
211}
212
213int
214vpn_disconnect(struct bound_addr *srv)
215{
216 struct sockaddr_in saddr;
217
218 bzero(&saddr, sizeof(saddr));
219 saddr.sin_len = sizeof(saddr);
220 saddr.sin_addr.s_addr = srv->address;
221 saddr.sin_port = 0;
222 saddr.sin_family = AF_INET;
e8d9021d
A
223
224 IPSECLOGASLMSG("IPSec disconnecting from server %s\n",
225 saddrwop2str(&saddr));
226
227 ike_sessions_stopped_by_controller(&saddr,
d1e348cf
A
228 0,
229 ike_session_stopped_by_vpn_disconnect);
230 if (purgephXbydstaddrwop((struct sockaddr *)(&saddr)) > 0) {
231 return 0;
232 } else {
233 return -1;
234 }
235}
236
237int
238vpn_start_ph2(struct bound_addr *addr, struct vpnctl_cmd_start_ph2 *pkt)
239{
240 struct vpnctl_sa_selector *selector_ptr;
241 struct vpnctl_algo *algo_ptr, *next_algo;
242 int i, j, defklen;
243 struct sainfoalg *new_algo;
244 struct sainfo *new_sainfo = NULL, *check;
245 u_int16_t class, algorithm, keylen;
246 struct ph1handle *ph1;
247 struct sockaddr_in saddr;
248
249 struct id {
250 u_int8_t type; /* ID Type */
251 u_int8_t proto_id; /* Protocol ID */
252 u_int16_t port; /* Port */
253 u_int32_t addr; /* IPv4 address */
254 u_int32_t mask;
255 } *id_ptr;
256
257 /* verify ph1 exists */
258 bzero(&saddr, sizeof(saddr));
259 saddr.sin_len = sizeof(saddr);
260 saddr.sin_addr.s_addr = addr->address;
261 saddr.sin_port = 0;
262 saddr.sin_family = AF_INET;
263 ph1 = getph1bydstaddrwop((struct sockaddr *)(&saddr));
264 if (ph1 == NULL) {
265 plog(LLV_ERROR, LOCATION, NULL,
266 "cannot start phase2 - no phase1 found.\n");
267 return -1;
268 }
269 if (ph1->status != PHASE1ST_ESTABLISHED) {
270 plog(LLV_ERROR, LOCATION, NULL,
271 "cannot start phase2 - phase1 not established.\n");
272 return -1;
273 }
274
275 selector_ptr = (struct vpnctl_sa_selector *)(pkt + 1);
276 algo_ptr = (struct vpnctl_algo *)(selector_ptr + ntohs(pkt->selector_count));
277
278 for (i = 0; i < ntohs(pkt->selector_count); i++, selector_ptr++) {
279 new_sainfo = newsainfo();
280 if (new_sainfo == NULL) {
281 plog(LLV_ERROR, LOCATION, NULL,
282 "unable to allocate sainfo struct.\n");
283 goto fail;
284 }
285
286 if (ntohl(selector_ptr->src_tunnel_mask) == 0xFFFFFFFF)
287 new_sainfo->idsrc = vmalloc(sizeof(struct id) - sizeof(u_int32_t));
288 else
289 new_sainfo->idsrc = vmalloc(sizeof(struct id));
290 if (new_sainfo->idsrc == NULL) {
291 plog(LLV_ERROR, LOCATION, NULL,
292 "unable to allocate id struct.\n");
293 goto fail;
294 }
295 if (selector_ptr->dst_tunnel_mask == 0xFFFFFFFF)
296 new_sainfo->iddst = vmalloc(sizeof(struct id) - sizeof(u_int32_t));
297 else
298 new_sainfo->iddst = vmalloc(sizeof(struct id));
299 if (new_sainfo->iddst == NULL) {
300 plog(LLV_ERROR, LOCATION, NULL,
301 "unable to allocate id struct.\n");
302 goto fail;
303 }
304
305 id_ptr = (struct id *)new_sainfo->idsrc->v;
306 if (ntohl(selector_ptr->src_tunnel_mask) == 0xFFFFFFFF)
307 id_ptr->type = IPSECDOI_ID_IPV4_ADDR;
308 else {
309 id_ptr->type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
310 id_ptr->mask = selector_ptr->src_tunnel_mask;
311 }
312 id_ptr->addr = selector_ptr->src_tunnel_address;
313 id_ptr->port = selector_ptr->src_tunnel_port;
314 id_ptr->proto_id = selector_ptr->ul_protocol;
315
316 id_ptr = (struct id *)new_sainfo->iddst->v;
317 if (selector_ptr->dst_tunnel_mask == 0xFFFFFFFF)
318 id_ptr->type = IPSECDOI_ID_IPV4_ADDR;
319 else {
320 id_ptr->type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
321 id_ptr->mask = selector_ptr->dst_tunnel_mask;
322 }
323 id_ptr->addr = selector_ptr->dst_tunnel_address;
324 id_ptr->port = selector_ptr->dst_tunnel_port;
325 id_ptr->proto_id = selector_ptr->ul_protocol;
326
327 new_sainfo->dynamic = addr->address;
328 new_sainfo->lifetime = ntohl(pkt->lifetime);
329
330 if (ntohs(pkt->pfs_group) != 0) {
331 new_sainfo->pfs_group = algtype2doi(algclass_isakmp_dh, ntohs(pkt->pfs_group));
332 if (new_sainfo->pfs_group == -1) {
333 plog(LLV_ERROR, LOCATION, NULL, "invalid dh group specified\n");
334 goto fail;
335 }
336 }
337 for (j = 0, next_algo = algo_ptr; j < ntohs(pkt->algo_count); j++, next_algo++) {
338
339 new_algo = newsainfoalg();
340 if (new_algo == NULL) {
341 plog(LLV_ERROR, LOCATION, NULL,
342 "failed to allocate algorithm structure\n");
343 goto fail;
344 }
345
346 class = ntohs(next_algo->algo_class);
347 algorithm = ntohs(next_algo->algo);
348 keylen = ntohs(next_algo->key_len);
349
350 new_algo->alg = algtype2doi(class, algorithm);
351 if (new_algo->alg == -1) {
352 plog(LLV_ERROR, LOCATION, NULL, "algorithm mismatched\n");
353 racoon_free(new_algo);
354 goto fail;
355 }
356
357 defklen = default_keylen(class, algorithm);
358 if (defklen == 0) {
359 if (keylen) {
360 plog(LLV_ERROR, LOCATION, NULL, "keylen not allowed\n");
361 racoon_free(new_algo);
362 goto fail;
363 }
364 } else {
365 if (keylen && check_keylen(class, algorithm, keylen) < 0) {
366 plog(LLV_ERROR, LOCATION, NULL, "invalid keylen %d\n", keylen);
367 racoon_free(new_algo);
368 goto fail;
369 }
370 }
371
372 if (keylen)
373 new_algo->encklen = keylen;
374 else
375 new_algo->encklen = defklen;
376
377 /* check if it's supported algorithm by kernel */
378 if (!(class == algclass_ipsec_auth && algorithm == algtype_non_auth)
379 && pk_checkalg(class, algorithm, new_algo->encklen)) {
380 int a = algclass2doi(class);
381 int b = new_algo->alg;
382 if (a == IPSECDOI_ATTR_AUTH)
383 a = IPSECDOI_PROTO_IPSEC_AH;
384 plog(LLV_ERROR, LOCATION, NULL,
385 "algorithm %s not supported by the kernel (missing module?)\n", s_ipsecdoi_trns(a, b));
386 racoon_free(new_algo);
387 goto fail;
388 }
389 inssainfoalg(&new_sainfo->algs[class], new_algo);
390 }
391
392 if (new_sainfo->algs[algclass_ipsec_enc] == 0) {
393 plog(LLV_ERROR, LOCATION, NULL,
394 "no encryption algorithm at %s\n", sainfo2str(new_sainfo));
395 goto fail;
396 }
397 if (new_sainfo->algs[algclass_ipsec_auth] == 0) {
398 plog(LLV_ERROR, LOCATION, NULL,
399 "no authentication algorithm at %s\n", sainfo2str(new_sainfo));
400 goto fail;
401 }
402 if (new_sainfo->algs[algclass_ipsec_comp] == 0) {
403 plog(LLV_ERROR, LOCATION, NULL,
404 "no compression algorithm at %s\n", sainfo2str(new_sainfo));
405 goto fail;
406 }
407
408 /* duplicate check */
409 check = getsainfo(new_sainfo->idsrc, new_sainfo->iddst, new_sainfo->id_i, 0);
410 if (check && (!check->idsrc && !new_sainfo->idsrc)) {
411 plog(LLV_ERROR, LOCATION, NULL,"duplicated sainfo: %s\n", sainfo2str(new_sainfo));
412 goto fail;
413 }
414 plog(LLV_DEBUG2, LOCATION, NULL, "create sainfo: %s\n", sainfo2str(new_sainfo));
415 inssainfo(new_sainfo);
416 new_sainfo = NULL;
417 }
418
419 return 0;
420
421fail:
422 if (new_sainfo)
423 delsainfo(new_sainfo);
424 flushsainfo_dynamic(addr);
425 return -1;
426}
427
428static int
429vpn_get_ph2pfs(struct ph1handle *ph1)
430{
431}
432
433
434int
435vpn_get_config(struct ph1handle *iph1, struct vpnctl_status_phase_change **msg, size_t *msg_size)
436{
437
438 struct vpnctl_modecfg_params *params;
439 struct myaddrs *myaddr;
440 u_int16_t ifname_len, msize;
441 u_int8_t *cptr;
442
443 *msg = NULL;
444 msize = 0;
445
446 if (((struct sockaddr_in *)iph1->local)->sin_family != AF_INET) {
447 plog(LLV_ERROR, LOCATION, NULL,
448 "IPv6 not supported for mode config.\n");
449 return -1;
450 }
451
452 if (iph1->mode_cfg->attr_list == NULL)
453 return 1; /* haven't received configuration yet */
454
455 myaddr = find_myaddr(iph1->local, 0);
456 if (myaddr == NULL) {
457 plog(LLV_ERROR, LOCATION, NULL,
458 "unable to find address structure.\n");
459 return -1;
460 }
461
462 msize = sizeof(struct vpnctl_status_phase_change)
463 + sizeof(struct vpnctl_modecfg_params);
464 msize += iph1->mode_cfg->attr_list->l;
465
466 *msg = racoon_calloc(1, msize);
467 if (*msg == NULL) {
468 plog(LLV_ERROR, LOCATION, NULL,
469 "faled to allocate space for message.\n");
470 return -1;
471 }
472
473 (*msg)->hdr.flags = htons(VPNCTL_FLAG_MODECFG_USED);
474 params = (struct vpnctl_modecfg_params *)(*msg + 1);
475 params->outer_local_addr = ((struct sockaddr_in *)iph1->local)->sin_addr.s_addr;
476 params->outer_remote_port = htons(0);
477 params->outer_local_port = htons(0);
478 ifname_len = strlen(myaddr->ifname);
479 memset(&params->ifname, 0, IFNAMSIZ);
480 memcpy(&params->ifname, myaddr->ifname, ifname_len < IFNAMSIZ ? ifname_len : IFNAMSIZ-1);
481 cptr = (u_int8_t *)(params + 1);
482 memcpy(cptr, iph1->mode_cfg->attr_list->v, iph1->mode_cfg->attr_list->l);
483 *msg_size = msize;
484
e8d9021d
A
485 IPSECLOGASLMSG("IPSec Network Configuration established.\n");
486
d1e348cf
A
487 return 0;
488}
489
490
491int
492vpn_xauth_reply(u_int32_t address, void *attr_list, size_t attr_len)
493{
494
495 struct isakmp_pl_attr *reply;
496 void* attr_ptr;
497 vchar_t *payload = NULL;
498 struct ph1handle *iph1;
499 struct sockaddr_in saddr;
500 int error = -1;
501 int tlen = attr_len;
502 struct isakmp_data *attr;
503 char *dataptr = (char *)attr_list;
504
505 /* find ph1 */
506 bzero(&saddr, sizeof(saddr));
507 saddr.sin_len = sizeof(saddr);
508 saddr.sin_addr.s_addr = address;
509 saddr.sin_port = 0;
510 saddr.sin_family = AF_INET;
511 iph1 = getph1bydstaddrwop((struct sockaddr *)(&saddr));
512 if (iph1 == NULL) {
513 plog(LLV_ERROR, LOCATION, NULL,
514 "cannot reply to xauth request - no ph1 found.\n");
515 goto end;
516 }
517
518 if (iph1->xauth_awaiting_userinput == 0) {
519 plog(LLV_ERROR, LOCATION, NULL, "Huh? recvd xauth reply data with no xauth reply pending \n");
520 goto end;
521 }
522
523 /* validate attr lengths */
524 while (tlen > 0)
525 {
526 int tlv;
527
528 attr = (struct isakmp_data *)dataptr;
529 tlv = (attr->type & htons(0x8000)) == 0;
530
531 if (tlv) {
532 tlen -= ntohs(attr->lorv);
533 dataptr += ntohs(attr->lorv);
534 }
535 tlen -= sizeof(u_int32_t);
536 dataptr += sizeof(u_int32_t);
537 }
538 if (tlen != 0) {
539 plog(LLV_ERROR, LOCATION, NULL, "invalid auth info received from VPN Control socket.\n");
540 goto end;
541 }
542
543 payload = vmalloc(sizeof(struct isakmp_pl_attr) + attr_len);
544 if (payload == NULL) {
545 plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory for xauth reply\n");
546 goto end;
547 }
548 memset(payload->v, 0, sizeof(reply));
549
550 reply = (struct isakmp_pl_attr *)payload->v;
551 reply->h.len = htons(payload->l);
552 reply->type = ISAKMP_CFG_REPLY;
553 reply->id = iph1->pended_xauth_id; /* network byte order */
554 iph1->xauth_awaiting_userinput = 0; /* no longer waiting */
555 attr_ptr = reply + 1;
556 memcpy(attr_ptr, attr_list, attr_len);
557
558 plog(LLV_DEBUG, LOCATION, NULL,
559 "Sending MODE_CFG REPLY\n");
560 error = isakmp_cfg_send(iph1, payload,
561 ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0, 0, iph1->xauth_awaiting_userinput_msg);
562 VPTRINIT(iph1->xauth_awaiting_userinput_msg);
563 ike_session_stop_xauth_timer(iph1);
564
e8d9021d
A
565 IPSECLOGASLMSG("IPSec Extended Authentication sent.\n");
566
d1e348cf
A
567end:
568 if (payload)
569 vfree(payload);
570 return error;
571}
572
e8d9021d
A
573int
574vpn_assert(struct sockaddr *src_addr, struct sockaddr *dst_addr)
575{
576 if (ike_session_assert(src_addr, dst_addr)) {
577 plog(LLV_ERROR, LOCATION, NULL,
578 "cannot assert - no matching session.\n");
579 return -1;
580 }
581
582 return 0;
583}