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