1/* $Id: vpn_control.c,v 1.17.2.4 2005/07/12 11:49:44 manubsd Exp $ */ 2 3/* 4 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 5 * 6 * @APPLE_LICENSE_HEADER_START@ 7 * 8 * The contents of this file constitute Original Code as defined in and 9 * are subject to the Apple Public Source License Version 1.1 (the 10 * "License"). You may not use this file except in compliance with the 11 * License. Please obtain a copy of the License at 12 * http://www.apple.com/publicsource and read it before using this file. 13 * 14 * This Original Code and all software distributed under the License are 15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25/* 26 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 3. Neither the name of the project nor the names of its contributors 38 * may be used to endorse or promote products derived from this software 39 * without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 */ 53 54//#define LION_TEST 1 55 56 57#include "config.h" 58 59#include <sys/types.h> 60#include <sys/param.h> 61#include <sys/socket.h> 62#include <sys/signal.h> 63#include <sys/stat.h> 64#include <sys/un.h> 65 66#include <net/pfkeyv2.h> 67 68#include <netinet/in.h> 69#ifndef HAVE_NETINET6_IPSEC 70#include <netinet/ipsec.h> 71#else 72#include <netinet6/ipsec.h> 73#endif 74 75 76#include <stdlib.h> 77#include <stdio.h> 78#include <string.h> 79#include <errno.h> 80#include <netdb.h> 81#ifdef HAVE_UNISTD_H 82#include <unistd.h> 83#endif 84#include <launch.h> 85#ifndef LION_TEST 86#include <launch_priv.h> 87#endif 88#include <fcntl.h> 89 90#include "var.h" 91#include "misc.h" 92#include "vmbuf.h" 93#include "plog.h" 94#include "sockmisc.h" 95#include "debug.h" 96 97#include "schedule.h" 98#include "localconf.h" 99#include "remoteconf.h" 100#include "grabmyaddr.h" 101#include "isakmp_var.h" 102#include "isakmp.h" 103#include "oakley.h" 104#include "handler.h" 105#include "pfkey.h" 106#include "ipsec_doi.h" 107#include "vpn_control.h" 108#include "vpn_control_var.h" 109#include "isakmp_inf.h" 110#include "session.h" 111#include "gcmalloc.h" 112#include "isakmp_cfg.h" 113#include "sainfo.h" 114 115#ifdef ENABLE_VPNCONTROL_PORT 116char *vpncontrolsock_path = VPNCONTROLSOCK_PATH; 117uid_t vpncontrolsock_owner = 0; 118gid_t vpncontrolsock_group = 0; 119mode_t vpncontrolsock_mode = 0600; 120 121static struct sockaddr_un sunaddr; 122static int vpncontrol_process (struct vpnctl_socket_elem *, char *); 123static int vpncontrol_reply (int, char *); 124static void vpncontrol_close_comm (struct vpnctl_socket_elem *); 125static int checklaunchd (void); 126extern int vpn_get_config (phase1_handle_t *, struct vpnctl_status_phase_change **, size_t *); 127extern int vpn_xauth_reply (u_int32_t, void *, size_t); 128 129 130int 131checklaunchd() 132{ 133 launch_data_t checkin_response = NULL; 134#ifdef LION_TEST 135 launch_data_t checkin_request = NULL; 136#endif 137 launch_data_t sockets_dict, listening_fd_array; 138 launch_data_t listening_fd; 139 struct sockaddr_storage fdsockaddr; 140 socklen_t fdsockaddrlen = sizeof(fdsockaddr); 141 int socketct; 142 int i; 143 int listenerct; 144 int returnval = 0; 145 int fd; 146 147 /* check in with launchd */ 148#ifdef LION_TEST 149 if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) { 150#else 151 if ((checkin_response = launch_socket_service_check_in()) == NULL) { 152#endif 153 plog(ASL_LEVEL_ERR, 154 "failed to launch_socket_service_check_in.\n"); 155 goto done; 156 } 157#ifdef LION_TEST 158 if ((checkin_response = launch_msg(checkin_request)) == NULL) { 159 plog(ASL_LEVEL_ERR, "failed to launch_msg.\n"); 160 goto done; 161 } 162#endif 163 if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) { 164 plog(ASL_LEVEL_ERR, 165 "launch_data_get_type error %d\n", 166 launch_data_get_errno(checkin_response)); 167 goto done; 168 } 169 if ( (sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS)) == NULL){ 170 plog(ASL_LEVEL_ERR, 171 "failed to launch_data_dict_lookup.\n"); 172 goto done; 173 } 174 if ( !(socketct = launch_data_dict_get_count(sockets_dict))){ 175 plog(ASL_LEVEL_ERR, 176 "launch_data_dict_get_count returns no socket defined.\n"); 177 goto done; 178 } 179 180 if ( (listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners")) == NULL ){ 181 plog(ASL_LEVEL_ERR, 182 "failed to launch_data_dict_lookup.\n"); 183 goto done; 184 } 185 listenerct = launch_data_array_get_count(listening_fd_array); 186 for (i = 0; i < listenerct; i++) { 187 listening_fd = launch_data_array_get_index(listening_fd_array, i); 188 fd = launch_data_get_fd( listening_fd ); 189 if ( getsockname( fd , (struct sockaddr *)&fdsockaddr, &fdsockaddrlen)){ 190 continue; 191 } 192 193 /* Is this the VPN control socket? */ 194 if ( fdsockaddr.ss_family == AF_UNIX && 195 (!(strcmp(vpncontrolsock_path, ((struct sockaddr_un *)&fdsockaddr)->sun_path)))) 196 { 197 plog(ASL_LEVEL_INFO, 198 "found launchd socket.\n"); 199 returnval = fd; 200 break; 201 } 202 } 203 // TODO: check if we have any leaked fd 204 if ( listenerct == i){ 205 plog(ASL_LEVEL_ERR, 206 "failed to find launchd socket\n"); 207 returnval = 0; 208 } 209 210done: 211 if (checkin_response) 212 launch_data_free(checkin_response); 213 return(returnval); 214} 215 216 217void 218vpncontrol_handler(void *unused) 219{ 220 struct sockaddr_storage from; 221 socklen_t fromlen = sizeof(from); 222 int sock; 223 224 struct vpnctl_socket_elem *sock_elem; 225 226 sock_elem = racoon_malloc(sizeof(struct vpnctl_socket_elem)); 227 if (sock_elem == NULL) { 228 plog(ASL_LEVEL_ERR, 229 "memory error: %s\n", strerror(errno)); 230 return; //%%%%%% terminate 231 } 232 LIST_INIT(&sock_elem->bound_addresses); 233 234 sock_elem->sock = accept(lcconf->sock_vpncontrol, (struct sockaddr *)&from, &fromlen); 235 if (sock_elem->sock < 0) { 236 plog(ASL_LEVEL_ERR, 237 "failed to accept vpn_control command: %s\n", strerror(errno)); 238 racoon_free(sock_elem); 239 return; //%%%%% terminate 240 } 241 LIST_INSERT_HEAD(&lcconf->vpnctl_comm_socks, sock_elem, chain); 242 243 sock_elem->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, sock_elem->sock, 0, dispatch_get_main_queue()); 244 if (sock_elem->source == NULL) { 245 plog(ASL_LEVEL_ERR, "could not create comm socket source."); 246 racoon_free(sock_elem); 247 return; //%%%%% terminate 248 } 249 dispatch_source_set_event_handler(sock_elem->source, 250 ^{ 251 vpncontrol_comm_handler(sock_elem); 252 }); 253 sock = sock_elem->sock; 254 255 dispatch_source_t the_source = sock_elem->source; 256 dispatch_source_set_cancel_handler(sock_elem->source, 257 ^{ 258 close(sock); 259 dispatch_release(the_source); /* Release the source on cancel */ 260 }); 261 dispatch_resume(sock_elem->source); 262 263 plog(ASL_LEVEL_NOTICE, 264 "accepted connection on vpn control socket.\n"); 265 check_auto_exit(); 266 267 return; 268} 269 270void 271vpncontrol_comm_handler(struct vpnctl_socket_elem *elem) 272{ 273 struct vpnctl_hdr hdr; 274 char *combuf = NULL; 275 ssize_t len; 276 277 /* get buffer length */ 278 while ((len = recv(elem->sock, (char *)&hdr, sizeof(hdr), MSG_PEEK)) < 0) { 279 if (errno == EINTR) 280 continue; 281 plog(ASL_LEVEL_ERR, 282 "failed to recv vpn_control command: %s\n", strerror(errno)); 283 goto end; 284 } 285 if (len == 0) { 286 plog(ASL_LEVEL_DEBUG, 287 "vpn_control socket closed by peer.\n"); 288 /* kill all related connections */ 289 vpncontrol_disconnect_all(elem, ike_session_stopped_by_controller_comm_lost); 290 vpncontrol_close_comm(elem); 291 return; // %%%%%% terminate 292 } 293 294 /* sanity check */ 295 if (len < sizeof(hdr)) { 296 plog(ASL_LEVEL_ERR, 297 "invalid header length of vpn_control command - len=%ld - expected %ld\n", len, sizeof(hdr)); 298 goto end; 299 } 300 301 /* get buffer to receive */ 302 if ((combuf = racoon_malloc(ntohs(hdr.len) + sizeof(hdr))) == 0) { 303 plog(ASL_LEVEL_ERR, 304 "failed to alloc buffer for vpn_control command\n"); 305 goto end; 306 } 307 308 /* get real data */ 309 while ((len = recv(elem->sock, combuf, ntohs(hdr.len) + sizeof(hdr), 0)) < 0) { 310 if (errno == EINTR) 311 continue; 312 plog(ASL_LEVEL_ERR, 313 "failed to recv vpn_control command: %s\n", 314 strerror(errno)); 315 goto end; 316 } 317 318 (void)vpncontrol_process(elem, combuf); 319 320end: 321 if (combuf) 322 racoon_free(combuf); 323 return; 324} 325 326static int 327vpncontrol_process(struct vpnctl_socket_elem *elem, char *combuf) 328{ 329 u_int16_t error = 0; 330 struct vpnctl_hdr *hdr = ALIGNED_CAST(struct vpnctl_hdr *)combuf; 331 332 switch (ntohs(hdr->msg_type)) { 333 334 case VPNCTL_CMD_BIND: 335 { 336 struct vpnctl_cmd_bind *pkt = ALIGNED_CAST(struct vpnctl_cmd_bind *)combuf; 337 struct bound_addr *addr; 338 339 plog(ASL_LEVEL_DEBUG, 340 "received bind command on vpn control socket.\n"); 341 addr = racoon_calloc(1, sizeof(struct bound_addr)); 342 if (addr == NULL) { 343 plog(ASL_LEVEL_ERR, 344 "memory error: %s\n", strerror(errno)); 345 error = -1; 346 break; 347 } 348 if (ntohs(pkt->vers_len)) { 349 addr->version = vmalloc(ntohs(pkt->vers_len)); 350 if (addr->version == NULL) { 351 plog(ASL_LEVEL_ERR, 352 "memory error: %s\n", strerror(errno)); 353 error = -1; 354 break; 355 } 356 memcpy(addr->version->v, pkt + 1, ntohs(pkt->vers_len)); 357 } 358 addr->address = pkt->address; 359 LIST_INSERT_HEAD(&elem->bound_addresses, addr, chain); 360 lcconf->auto_exit_state |= LC_AUTOEXITSTATE_CLIENT; /* client side */ 361 } 362 break; 363 364 case VPNCTL_CMD_UNBIND: 365 { 366 struct vpnctl_cmd_unbind *pkt = ALIGNED_CAST(struct vpnctl_cmd_unbind *)combuf; 367 struct bound_addr *addr; 368 struct bound_addr *t_addr; 369 370 plog(ASL_LEVEL_DEBUG, 371 "received unbind command on vpn control socket.\n"); 372 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 373 if (pkt->address == 0xFFFFFFFF || 374 pkt->address == addr->address) { 375 flushsainfo_dynamic(addr->address); 376 LIST_REMOVE(addr, chain); 377 if (addr->version) 378 vfree(addr->version); 379 racoon_free(addr); 380 } 381 } 382 } 383 break; 384 385 case VPNCTL_CMD_REDIRECT: 386 { 387 struct vpnctl_cmd_redirect *redirect_msg = ALIGNED_CAST(struct vpnctl_cmd_redirect *)combuf; 388 struct redirect *raddr; 389 struct redirect *t_raddr; 390 int found = 0; 391 392 plog(ASL_LEVEL_DEBUG, 393 "received redirect command on vpn control socket - address = %x.\n", ntohl(redirect_msg->redirect_address)); 394 395 LIST_FOREACH_SAFE(raddr, &lcconf->redirect_addresses, chain, t_raddr) { 396 if (raddr->cluster_address == redirect_msg->address) { 397 if (redirect_msg->redirect_address == 0) { 398 LIST_REMOVE(raddr, chain); 399 racoon_free(raddr); 400 } else { 401 raddr->redirect_address = redirect_msg->redirect_address; 402 raddr->force = ntohs(redirect_msg->force); 403 } 404 found = 1; 405 break; 406 } 407 } 408 if (!found) { 409 raddr = racoon_malloc(sizeof(struct redirect)); 410 if (raddr == NULL) { 411 plog(ASL_LEVEL_DEBUG, 412 "cannot allcoate memory for redirect address.\n"); 413 error = -1; 414 break; 415 } 416 raddr->cluster_address = redirect_msg->address; 417 raddr->redirect_address = redirect_msg->redirect_address; 418 raddr->force = ntohs(redirect_msg->force); 419 LIST_INSERT_HEAD(&lcconf->redirect_addresses, raddr, chain); 420 421 } 422 } 423 break; 424 425 case VPNCTL_CMD_PING: 426 break; /* just reply for now */ 427 428 case VPNCTL_CMD_XAUTH_INFO: 429 { 430 struct vpnctl_cmd_xauth_info *pkt = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)combuf; 431 struct bound_addr *addr; 432 struct bound_addr *t_addr; 433 void *attr_list; 434 435 plog(ASL_LEVEL_DEBUG, 436 "received xauth info command vpn control socket.\n"); 437 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 438 if (pkt->address == addr->address) { 439 /* reply to the last xauth request */ 440 attr_list = pkt + 1; 441 error = vpn_xauth_reply(pkt->address, attr_list, ntohs(pkt->hdr.len) - sizeof(u_int32_t)); 442 break; 443 } 444 } 445 } 446 break; 447 448 case VPNCTL_CMD_CONNECT: 449 { 450 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf; 451 struct bound_addr *addr; 452 struct bound_addr *t_addr; 453 454 plog(ASL_LEVEL_DEBUG, 455 "received connect command on vpn control socket.\n"); 456 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 457 if (pkt->address == addr->address) { 458 /* start the connection */ 459 error = vpn_connect(addr, VPN_STARTED_BY_API); 460 break; 461 } 462 } 463 } 464 break; 465 466 case VPNCTL_CMD_DISCONNECT: 467 { 468 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf; 469 struct bound_addr *addr; 470 struct bound_addr *t_addr; 471 472 plog(ASL_LEVEL_DEBUG, 473 "received disconnect command on vpn control socket.\n"); 474 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 475 if (pkt->address == addr->address) { 476 /* stop the connection */ 477 error = vpn_disconnect(addr, ike_session_stopped_by_vpn_disconnect); 478 break; 479 } 480 } 481 } 482 break; 483 484 case VPNCTL_CMD_START_PH2: 485 { 486 struct vpnctl_cmd_start_ph2 *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_ph2 *)combuf; 487 struct bound_addr *addr; 488 struct bound_addr *t_addr; 489 490 plog(ASL_LEVEL_DEBUG, "received start_ph2 command on vpn control socket.\n"); 491 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 492 if (pkt->address == addr->address) { 493 /* start the connection */ 494 error = vpn_start_ph2(addr, pkt); 495 break; 496 } 497 } 498 } 499 break; 500 501 case VPNCTL_CMD_START_DPD: 502 { 503 struct vpnctl_cmd_start_dpd *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_dpd *)combuf; 504 struct bound_addr *srv; 505 struct bound_addr *t_addr; 506 507 plog(ASL_LEVEL_DEBUG, 508 "received start_dpd command on vpn control socket.\n"); 509 LIST_FOREACH_SAFE(srv, &elem->bound_addresses, chain, t_addr) { 510 if (pkt->address == srv->address) { 511 union { // Wcast-align fix - force alignment 512 struct sockaddr_storage ss; 513 struct sockaddr_in addr_in; 514 } daddr; 515 516 bzero(&daddr, sizeof(struct sockaddr_in)); 517 daddr.addr_in.sin_len = sizeof(struct sockaddr_in); 518 daddr.addr_in.sin_addr.s_addr = srv->address; 519 daddr.addr_in.sin_port = 0; 520 daddr.addr_in.sin_family = AF_INET; 521 522 /* start the dpd */ 523 error = ike_session_ph1_force_dpd(&daddr.ss); 524 break; 525 } 526 } 527 } 528 break; 529 530 case VPNCTL_CMD_ASSERT: 531 { 532 struct vpnctl_cmd_assert *pkt = ALIGNED_CAST(struct vpnctl_cmd_assert *)combuf; 533// struct bound_addr *addr; 534// struct bound_addr *t_addr; 535 struct sockaddr_in saddr; 536 struct sockaddr_in daddr; 537 538 plogdump(ASL_LEVEL_DEBUG, pkt, ntohs(hdr->len) + sizeof(struct vpnctl_hdr), "received assert command on vpn control socket.\n"); 539// LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 540// if (pkt->dst_address == addr->address) { 541 bzero(&saddr, sizeof(saddr)); 542 saddr.sin_len = sizeof(saddr); 543 saddr.sin_addr.s_addr = pkt->src_address; 544 saddr.sin_port = 0; 545 saddr.sin_family = AF_INET; 546 bzero(&daddr, sizeof(daddr)); 547 daddr.sin_len = sizeof(daddr); 548 daddr.sin_addr.s_addr = pkt->dst_address; 549 daddr.sin_port = 0; 550 daddr.sin_family = AF_INET; 551 552 error = vpn_assert((struct sockaddr_storage *)&saddr, (struct sockaddr_storage *)&daddr); 553 break; 554// } 555// } 556 } 557 break; 558 559 case VPNCTL_CMD_RECONNECT: 560 { 561 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf; 562 struct bound_addr *addr; 563 struct bound_addr *t_addr; 564 565 plog(ASL_LEVEL_DEBUG, 566 "received reconnect command on vpn control socket.\n"); 567 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 568 if (pkt->address == addr->address) { 569 /* start the connection */ 570 error = vpn_connect(addr, VPN_RESTARTED_BY_API); 571 break; 572 } 573 } 574 } 575 break; 576 577 default: 578 plog(ASL_LEVEL_ERR, 579 "invalid command: %d\n", ntohs(hdr->msg_type)); 580 error = -1; // for now 581 break; 582 } 583 584 hdr->len = 0; 585 hdr->result = htons(error); 586 if (vpncontrol_reply(elem->sock, combuf) < 0) 587 return -1; 588 589 return 0; 590 591} 592 593static int 594vpncontrol_reply(int so, char *combuf) 595{ 596 ssize_t tlen; 597 598 tlen = send(so, combuf, sizeof(struct vpnctl_hdr), 0); 599 if (tlen < 0) { 600 plog(ASL_LEVEL_ERR, 601 "failed to send vpn_control message: %s\n", strerror(errno)); 602 return -1; 603 } 604 605 return 0; 606} 607 608int 609vpncontrol_notify_need_authinfo(phase1_handle_t *iph1, void* attr_list, size_t attr_len) 610{ 611 struct vpnctl_status_need_authinfo *msg = NULL; 612 struct vpnctl_socket_elem *sock_elem; 613 struct bound_addr *bound_addr; 614 size_t msg_size; 615 ssize_t tlen; 616 u_int32_t address; 617 void *ptr; 618 619 if (!iph1) 620 goto end; 621 622 plog(ASL_LEVEL_DEBUG, 623 "sending vpn_control xauth need info status\n"); 624 625 msg = (struct vpnctl_status_need_authinfo *)racoon_malloc(msg_size = sizeof(struct vpnctl_status_need_authinfo) + attr_len); 626 if (msg == NULL) { 627 plog(ASL_LEVEL_ERR, 628 "unable to allocate space for vpn control message.\n"); 629 return -1; 630 } 631 msg->hdr.flags = 0; 632 633 if (iph1->remote->ss_family == AF_INET) 634 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr; 635 else 636 goto end; // for now 637 638 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0; 639 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr)); 640 if (!ike_session_is_client_ph1_rekey(iph1)) { 641 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_AUTHINFO); 642 } else { 643 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_REAUTHINFO); 644 } 645 msg->address = address; 646 ptr = msg + 1; 647 memcpy(ptr, attr_list, attr_len); 648 649 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) { 650 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) { 651 if (bound_addr->address == 0xFFFFFFFF || 652 bound_addr->address == address) { 653 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size); 654 tlen = send(sock_elem->sock, msg, msg_size, 0); 655 if (tlen < 0) { 656 plog(ASL_LEVEL_ERR, 657 "failed to send vpn_control need authinfo status: %s\n", strerror(errno)); 658 } 659 break; 660 } 661 } 662 } 663 664end: 665 if (msg) 666 racoon_free(msg); 667 return 0; 668} 669 670int 671vpncontrol_notify_ike_failed(u_int16_t notify_code, u_int16_t from, u_int32_t address, u_int16_t data_len, u_int8_t *data) 672{ 673 struct vpnctl_status_failed *msg = NULL; 674 struct vpnctl_socket_elem *sock_elem; 675 struct bound_addr *bound_addr; 676 size_t len; 677 ssize_t tlen; 678 679 len = sizeof(struct vpnctl_status_failed) + data_len; 680 681 msg = (struct vpnctl_status_failed *)racoon_malloc(len); 682 if (msg == NULL) { 683 plog(ASL_LEVEL_DEBUG, 684 "unable to allcate memory for vpn control status message.\n"); 685 return -1; 686 } 687 688 msg->hdr.msg_type = htons(VPNCTL_STATUS_IKE_FAILED); 689 msg->hdr.flags = msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0; 690 msg->hdr.len = htons(len - sizeof(struct vpnctl_hdr)); 691 msg->address = address; 692 msg->ike_code = htons(notify_code); 693 msg->from = htons(from); 694 if (data_len > 0) 695 memcpy(msg->data, data, data_len); 696 plog(ASL_LEVEL_DEBUG, 697 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code, 698 (from == FROM_LOCAL ? "local" : "remote")); 699 700 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) { 701 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) { 702 if (bound_addr->address == 0xFFFFFFFF || 703 bound_addr->address == address) { 704 tlen = send(sock_elem->sock, msg, len, 0); 705 if (tlen < 0) { 706 plog(ASL_LEVEL_ERR, 707 "Unable to send vpn_control ike notify failed: %s\n", strerror(errno)); 708 } 709 break; 710 } 711 } 712 } 713 714 if (msg) 715 racoon_free(msg); 716 return 0; 717} 718 719char * 720vpncontrol_status_2_str(u_int16_t msg_type) 721{ 722 switch (msg_type) { 723 case VPNCTL_STATUS_IKE_FAILED: 724 return "IKE failed"; 725 case VPNCTL_STATUS_PH1_START_US: 726 return "Phase 1 started by us"; 727 case VPNCTL_STATUS_PH1_START_PEER: 728 return "Phase 1 started by peer"; 729 case VPNCTL_STATUS_PH1_ESTABLISHED: 730 return "Phase 1 established"; 731 case VPNCTL_STATUS_PH2_START: 732 return "Phase 2 started"; 733 case VPNCTL_STATUS_PH2_ESTABLISHED: 734 return "Phase 2 established"; 735 case VPNCTL_STATUS_NEED_AUTHINFO: 736 return "Need authentication info"; 737 case VPNCTL_STATUS_NEED_REAUTHINFO: 738 return "Need re-authentication info"; 739 default: 740 return ""; 741 } 742} 743 744 745int 746vpncontrol_notify_phase_change(int start, u_int16_t from, phase1_handle_t *iph1, phase2_handle_t *iph2) 747{ 748 struct vpnctl_status_phase_change *msg; 749 struct vpnctl_socket_elem *sock_elem; 750 struct bound_addr *bound_addr; 751 ssize_t tlen; 752 size_t msg_size; 753 u_int32_t address; 754 755 if (iph1 && !start && iph1->mode_cfg && iph1->mode_cfg->xauth.status != XAUTHST_OK) { 756 if (vpn_get_config(iph1, &msg, &msg_size) == 1) 757 return 0; /* mode config not finished yet */ 758 } else { 759 msg = racoon_malloc(msg_size = sizeof(struct vpnctl_status_phase_change)); 760 msg->hdr.flags = 0; 761 } 762 763 if (msg == NULL) { 764 plog(ASL_LEVEL_ERR, 765 "unable to allocate space for vpn control message.\n"); 766 return -1; 767 } 768 if (iph1) { 769 if (iph1->remote->ss_family == AF_INET) 770 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr; 771 else 772 goto end; // for now 773 msg->hdr.msg_type = htons(start ? 774 (from == FROM_LOCAL ? VPNCTL_STATUS_PH1_START_US : VPNCTL_STATUS_PH1_START_PEER) 775 : VPNCTL_STATUS_PH1_ESTABLISHED); 776 // TODO: indicate version 777 } else { 778 if (iph2->dst->ss_family == AF_INET) 779 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr; 780 else 781 goto end; // for now 782 msg->hdr.msg_type = htons(start ? VPNCTL_STATUS_PH2_START : VPNCTL_STATUS_PH2_ESTABLISHED); 783 // TODO: indicate version 784 } 785 plog(ASL_LEVEL_NOTICE, 786 ">>>>> phase change status = %s\n", vpncontrol_status_2_str(ntohs(msg->hdr.msg_type))); 787 788 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0; 789 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr)); 790 msg->address = address; 791 792 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) { 793 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) { 794 if (bound_addr->address == 0xFFFFFFFF || 795 bound_addr->address == address) { 796 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size); 797 tlen = send(sock_elem->sock, msg, msg_size, 0); 798 if (tlen < 0) { 799 plog(ASL_LEVEL_ERR, 800 "failed to send vpn_control phase change status: %s\n", strerror(errno)); 801 } 802 break; 803 } 804 } 805 } 806 807end: 808 if (msg) 809 racoon_free(msg); 810 return 0; 811} 812 813static int 814vpncontrol_notify_peer_resp (u_int16_t notify_code, u_int32_t address) 815{ 816 struct vpnctl_status_peer_resp msg; 817 struct vpnctl_socket_elem *sock_elem; 818 struct bound_addr *bound_addr; 819 ssize_t tlen; 820 int rc = -1; 821 822 bzero(&msg, sizeof(msg)); 823 msg.hdr.msg_type = htons(VPNCTL_STATUS_PEER_RESP); 824 msg.hdr.cookie = msg.hdr.reserved = msg.hdr.result = 0; 825 msg.hdr.len = htons(sizeof(msg) - sizeof(msg.hdr)); 826 msg.address = address; 827 msg.ike_code = notify_code; 828 plog(ASL_LEVEL_DEBUG, 829 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code, address); 830 831 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) { 832 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) { 833 if (bound_addr->address == 0xFFFFFFFF || 834 bound_addr->address == address) { 835 tlen = send(sock_elem->sock, &msg, sizeof(msg), 0); 836 if (tlen < 0) { 837 plog(ASL_LEVEL_ERR, 838 "unable to send vpn_control status (peer response): %s\n", strerror(errno)); 839 } else { 840 rc = 0; 841 } 842 break; 843 } 844 } 845 } 846 847 return rc; 848} 849 850int 851vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code, phase1_handle_t *iph1) 852{ 853 u_int32_t address; 854 int rc; 855 856 if (iph1 && iph1->parent_session && iph1->parent_session->controller_awaiting_peer_resp) { 857 if (iph1->remote->ss_family == AF_INET) 858 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr; 859 else 860 address = 0; 861 } else { 862 return 0; 863 } 864 865 if ((rc = vpncontrol_notify_peer_resp(notify_code, address)) == 0) { 866 iph1->parent_session->controller_awaiting_peer_resp = 0; 867 } 868 return rc; 869} 870 871int 872vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code, phase2_handle_t *iph2) 873{ 874 u_int32_t address; 875 int rc; 876 877 if (iph2 && iph2->parent_session && iph2->parent_session->controller_awaiting_peer_resp) { 878 if (iph2->dst->ss_family == AF_INET) 879 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr; 880 else 881 address = 0; 882 } else { 883 return 0; 884 } 885 886 if ((rc = vpncontrol_notify_peer_resp(notify_code, address)) == 0) { 887 iph2->parent_session->controller_awaiting_peer_resp = 0; 888 } 889 return rc; 890} 891 892int 893vpncontrol_init(void) 894{ 895 int sock; 896 897 if (vpncontrolsock_path == NULL) { 898 lcconf->sock_vpncontrol = -1; 899 return 0; 900 } 901 902 if ( (lcconf->sock_vpncontrol = checklaunchd()) == 0 ) { 903 memset(&sunaddr, 0, sizeof(sunaddr)); 904 sunaddr.sun_family = AF_UNIX; 905 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), 906 "%s", vpncontrolsock_path); 907 908 lcconf->sock_vpncontrol = socket(AF_UNIX, SOCK_STREAM, 0); 909 if (lcconf->sock_vpncontrol == -1) { 910 plog(ASL_LEVEL_ERR, 911 "socket: %s\n", strerror(errno)); 912 return -1; 913 } 914 915 if (fcntl(lcconf->sock_vpncontrol, F_SETFL, O_NONBLOCK) == -1) { 916 plog(ASL_LEVEL_ERR, "failed to put VPN-Control socket in non-blocking mode\n"); 917 } 918 919 unlink(sunaddr.sun_path); 920 if (bind(lcconf->sock_vpncontrol, (struct sockaddr *)&sunaddr, 921 sizeof(sunaddr)) != 0) { 922 plog(ASL_LEVEL_ERR, 923 "bind(sockname:%s): %s\n", 924 sunaddr.sun_path, strerror(errno)); 925 (void)close(lcconf->sock_vpncontrol); 926 return -1; 927 } 928 929 if (chown(sunaddr.sun_path, vpncontrolsock_owner, vpncontrolsock_group) != 0) { 930 plog(ASL_LEVEL_ERR, 931 "chown(%s, %d, %d): %s\n", 932 sunaddr.sun_path, vpncontrolsock_owner, 933 vpncontrolsock_group, strerror(errno)); 934 (void)close(lcconf->sock_vpncontrol); 935 return -1; 936 } 937 938 if (chmod(sunaddr.sun_path, vpncontrolsock_mode) != 0) { 939 plog(ASL_LEVEL_ERR, 940 "chmod(%s, 0%03o): %s\n", 941 sunaddr.sun_path, vpncontrolsock_mode, strerror(errno)); 942 (void)close(lcconf->sock_vpncontrol); 943 return -1; 944 } 945 946 if (listen(lcconf->sock_vpncontrol, 5) != 0) { 947 plog(ASL_LEVEL_ERR, 948 "listen(sockname:%s): %s\n", 949 sunaddr.sun_path, strerror(errno)); 950 (void)close(lcconf->sock_vpncontrol); 951 return -1; 952 } 953 plog(ASL_LEVEL_DEBUG, 954 "opened %s as racoon management.\n", sunaddr.sun_path); 955 } 956 lcconf->vpncontrol_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_vpncontrol, 0, dispatch_get_main_queue()); 957 if (lcconf->vpncontrol_source == NULL) { 958 plog(ASL_LEVEL_ERR, "could not create vpncontrol socket source."); 959 return -1; 960 } 961 dispatch_source_set_event_handler_f(lcconf->vpncontrol_source, vpncontrol_handler); 962 sock = lcconf->sock_vpncontrol; 963 dispatch_source_set_cancel_handler(lcconf->vpncontrol_source, 964 ^{ 965 close(sock); 966 }); 967 dispatch_resume(lcconf->vpncontrol_source); 968 return 0; 969} 970 971void 972vpncontrol_disconnect_all(struct vpnctl_socket_elem *elem, const char *reason) 973{ 974 struct bound_addr *addr; 975 struct bound_addr *t_addr; 976 977 plog(ASL_LEVEL_DEBUG, 978 "received disconnect all command.\n"); 979 980 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 981 /* stop any connections */ 982 vpn_disconnect(addr, reason); 983 } 984} 985 986void 987vpncontrol_close() 988{ 989 struct vpnctl_socket_elem *elem; 990 struct vpnctl_socket_elem *t_elem; 991 992 plog(ASL_LEVEL_DEBUG, 993 "vpncontrol_close.\n"); 994 995 dispatch_source_cancel(lcconf->vpncontrol_source); 996 lcconf->vpncontrol_source = NULL; 997 998 lcconf->sock_vpncontrol = -1; 999 LIST_FOREACH_SAFE(elem, &lcconf->vpnctl_comm_socks, chain, t_elem) 1000 vpncontrol_close_comm(elem); 1001} 1002 1003static void 1004vpncontrol_close_comm(struct vpnctl_socket_elem *elem) 1005{ 1006 struct bound_addr *addr; 1007 struct bound_addr *t_addr; 1008 1009 plog(ASL_LEVEL_DEBUG, 1010 "vpncontrol_close_comm.\n"); 1011 1012 LIST_REMOVE(elem, chain); 1013 if (elem->sock != -1) 1014 dispatch_source_cancel(elem->source); 1015 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 1016 flushsainfo_dynamic(addr->address); 1017 LIST_REMOVE(addr, chain); 1018 if (addr->version) 1019 vfree(addr->version); 1020 racoon_free(addr); 1021 } 1022 racoon_free(elem); 1023 check_auto_exit(); 1024} 1025 1026int 1027vpn_control_connected(void) 1028{ 1029 if (LIST_EMPTY(&lcconf->vpnctl_comm_socks)) 1030 return 0; 1031 else 1032 return 1; 1033} 1034 1035#endif 1036