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(¶ms->ifname, 0, IFNAMSIZ); 482 memcpy(¶ms->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