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 227 sock_elem = racoon_malloc(sizeof(struct vpnctl_socket_elem)); 228 if (sock_elem == NULL) { 229 plog(ASL_LEVEL_ERR, 230 "memory error: %s\n", strerror(errno)); 231 return; //%%%%%% terminate 232 } 233 LIST_INIT(&sock_elem->bound_addresses); 234 235 sock_elem->sock = accept(lcconf->sock_vpncontrol, (struct sockaddr *)&from, &fromlen); 236 if (sock_elem->sock < 0) { 237 plog(ASL_LEVEL_ERR, 238 "failed to accept vpn_control command: %s\n", strerror(errno)); 239 racoon_free(sock_elem); 240 return; //%%%%% terminate 241 } 242 LIST_INSERT_HEAD(&lcconf->vpnctl_comm_socks, sock_elem, chain); 243 244 sock_elem->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, sock_elem->sock, 0, dispatch_get_main_queue()); 245 if (sock_elem->source == NULL) { 246 plog(ASL_LEVEL_ERR, "could not create comm socket source."); 247 racoon_free(sock_elem); 248 return; //%%%%% terminate 249 } 250 dispatch_source_set_event_handler(sock_elem->source, 251 ^{ 252 vpncontrol_comm_handler(sock_elem); 253 }); 254 sock = sock_elem->sock; 255 256 dispatch_source_t the_source = sock_elem->source; 257 dispatch_source_set_cancel_handler(sock_elem->source, 258 ^{ 259 close(sock); 260 dispatch_release(the_source); /* Release the source on cancel */ 261 }); 262 dispatch_resume(sock_elem->source); 263 264 plog(ASL_LEVEL_NOTICE, 265 "accepted connection on vpn control socket.\n"); 266 check_auto_exit(); 267 268 return; 269} 270 271void 272vpncontrol_comm_handler(struct vpnctl_socket_elem *elem) 273{ 274 struct vpnctl_hdr hdr; 275 char *combuf = NULL; 276 ssize_t len; 277 278 /* get buffer length */ 279 while ((len = recv(elem->sock, (char *)&hdr, sizeof(hdr), MSG_PEEK)) < 0) { 280 if (errno == EINTR) 281 continue; 282 plog(ASL_LEVEL_ERR, 283 "failed to recv vpn_control command: %s\n", strerror(errno)); 284 goto end; 285 } 286 if (len == 0) { 287 plog(ASL_LEVEL_DEBUG, 288 "vpn_control socket closed by peer.\n"); 289 /* kill all related connections */ 290 vpncontrol_disconnect_all(elem, ike_session_stopped_by_controller_comm_lost); 291 vpncontrol_close_comm(elem); 292 return; // %%%%%% terminate 293 } 294 295 /* sanity check */ 296 if (len < sizeof(hdr)) { 297 plog(ASL_LEVEL_ERR, 298 "invalid header length of vpn_control command - len=%ld - expected %ld\n", len, sizeof(hdr)); 299 goto end; 300 } 301 302 /* get buffer to receive */ 303 if ((combuf = racoon_malloc(ntohs(hdr.len) + sizeof(hdr))) == 0) { 304 plog(ASL_LEVEL_ERR, 305 "failed to alloc buffer for vpn_control command\n"); 306 goto end; 307 } 308 309 /* get real data */ 310 while ((len = recv(elem->sock, combuf, ntohs(hdr.len) + sizeof(hdr), 0)) < 0) { 311 if (errno == EINTR) 312 continue; 313 plog(ASL_LEVEL_ERR, 314 "failed to recv vpn_control command: %s\n", 315 strerror(errno)); 316 goto end; 317 } 318 319 (void)vpncontrol_process(elem, combuf); 320 321end: 322 if (combuf) 323 racoon_free(combuf); 324 return; 325} 326 327static int 328vpncontrol_process(struct vpnctl_socket_elem *elem, char *combuf) 329{ 330 u_int16_t error = 0; 331 struct vpnctl_hdr *hdr = ALIGNED_CAST(struct vpnctl_hdr *)combuf; 332 333 switch (ntohs(hdr->msg_type)) { 334 335 case VPNCTL_CMD_BIND: 336 { 337 struct vpnctl_cmd_bind *pkt = ALIGNED_CAST(struct vpnctl_cmd_bind *)combuf; 338 struct bound_addr *addr; 339 340 plog(ASL_LEVEL_DEBUG, 341 "received bind command on vpn control socket.\n"); 342 addr = racoon_calloc(1, sizeof(struct bound_addr)); 343 if (addr == NULL) { 344 plog(ASL_LEVEL_ERR, 345 "memory error: %s\n", strerror(errno)); 346 error = -1; 347 break; 348 } 349 if (ntohs(pkt->vers_len)) { 350 addr->version = vmalloc(ntohs(pkt->vers_len)); 351 if (addr->version == NULL) { 352 plog(ASL_LEVEL_ERR, 353 "memory error: %s\n", strerror(errno)); 354 error = -1; 355 break; 356 } 357 memcpy(addr->version->v, pkt + 1, ntohs(pkt->vers_len)); 358 } 359 addr->address = pkt->address; 360 LIST_INSERT_HEAD(&elem->bound_addresses, addr, chain); 361 lcconf->auto_exit_state |= LC_AUTOEXITSTATE_CLIENT; /* client side */ 362 } 363 break; 364 365 case VPNCTL_CMD_UNBIND: 366 { 367 struct vpnctl_cmd_unbind *pkt = ALIGNED_CAST(struct vpnctl_cmd_unbind *)combuf; 368 struct bound_addr *addr; 369 struct bound_addr *t_addr; 370 371 plog(ASL_LEVEL_DEBUG, 372 "received unbind command on vpn control socket.\n"); 373 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 374 if (pkt->address == 0xFFFFFFFF || 375 pkt->address == addr->address) { 376 flushsainfo_dynamic(addr->address); 377 LIST_REMOVE(addr, chain); 378 if (addr->version) 379 vfree(addr->version); 380 racoon_free(addr); 381 } 382 } 383 } 384 break; 385 386 case VPNCTL_CMD_REDIRECT: 387 { 388 struct vpnctl_cmd_redirect *redirect_msg = ALIGNED_CAST(struct vpnctl_cmd_redirect *)combuf; 389 struct redirect *raddr; 390 struct redirect *t_raddr; 391 int found = 0; 392 393 plog(ASL_LEVEL_DEBUG, 394 "received redirect command on vpn control socket - address = %x.\n", ntohl(redirect_msg->redirect_address)); 395 396 LIST_FOREACH_SAFE(raddr, &lcconf->redirect_addresses, chain, t_raddr) { 397 if (raddr->cluster_address == redirect_msg->address) { 398 if (redirect_msg->redirect_address == 0) { 399 LIST_REMOVE(raddr, chain); 400 racoon_free(raddr); 401 } else { 402 raddr->redirect_address = redirect_msg->redirect_address; 403 raddr->force = ntohs(redirect_msg->force); 404 } 405 found = 1; 406 break; 407 } 408 } 409 if (!found) { 410 raddr = racoon_malloc(sizeof(struct redirect)); 411 if (raddr == NULL) { 412 plog(ASL_LEVEL_DEBUG, 413 "cannot allcoate memory for redirect address.\n"); 414 error = -1; 415 break; 416 } 417 raddr->cluster_address = redirect_msg->address; 418 raddr->redirect_address = redirect_msg->redirect_address; 419 raddr->force = ntohs(redirect_msg->force); 420 LIST_INSERT_HEAD(&lcconf->redirect_addresses, raddr, chain); 421 422 } 423 } 424 break; 425 426 case VPNCTL_CMD_PING: 427 break; /* just reply for now */ 428 429 case VPNCTL_CMD_XAUTH_INFO: 430 { 431 struct vpnctl_cmd_xauth_info *pkt = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)combuf; 432 struct bound_addr *addr; 433 struct bound_addr *t_addr; 434 void *attr_list; 435 436 plog(ASL_LEVEL_DEBUG, 437 "received xauth info command vpn control socket.\n"); 438 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 439 if (pkt->address == addr->address) { 440 /* reply to the last xauth request */ 441 attr_list = pkt + 1; 442 error = vpn_xauth_reply(pkt->address, attr_list, ntohs(pkt->hdr.len) - sizeof(u_int32_t)); 443 break; 444 } 445 } 446 } 447 break; 448 449 case VPNCTL_CMD_CONNECT: 450 { 451 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf; 452 struct bound_addr *addr; 453 struct bound_addr *t_addr; 454 455 plog(ASL_LEVEL_DEBUG, 456 "received connect command on vpn control socket.\n"); 457 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 458 if (pkt->address == addr->address) { 459 /* start the connection */ 460 error = vpn_connect(addr, VPN_STARTED_BY_API); 461 break; 462 } 463 } 464 } 465 break; 466 467 case VPNCTL_CMD_DISCONNECT: 468 { 469 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf; 470 struct bound_addr *addr; 471 struct bound_addr *t_addr; 472 473 plog(ASL_LEVEL_DEBUG, 474 "received disconnect command on vpn control socket.\n"); 475 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 476 if (pkt->address == addr->address) { 477 /* stop the connection */ 478 error = vpn_disconnect(addr, ike_session_stopped_by_vpn_disconnect); 479 break; 480 } 481 } 482 } 483 break; 484 485 case VPNCTL_CMD_START_PH2: 486 { 487 struct vpnctl_cmd_start_ph2 *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_ph2 *)combuf; 488 struct bound_addr *addr; 489 struct bound_addr *t_addr; 490 491 plog(ASL_LEVEL_DEBUG, "received start_ph2 command on vpn control socket.\n"); 492 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 493 if (pkt->address == addr->address) { 494 /* start the connection */ 495 error = vpn_start_ph2(addr, pkt); 496 break; 497 } 498 } 499 } 500 break; 501 502 case VPNCTL_CMD_START_DPD: 503 { 504 struct vpnctl_cmd_start_dpd *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_dpd *)combuf; 505 struct bound_addr *srv; 506 struct bound_addr *t_addr; 507 508 plog(ASL_LEVEL_DEBUG, 509 "received start_dpd command on vpn control socket.\n"); 510 LIST_FOREACH_SAFE(srv, &elem->bound_addresses, chain, t_addr) { 511 if (pkt->address == srv->address) { 512 union { // Wcast-align fix - force alignment 513 struct sockaddr_storage ss; 514 struct sockaddr_in addr_in; 515 } daddr; 516 517 bzero(&daddr, sizeof(struct sockaddr_in)); 518 daddr.addr_in.sin_len = sizeof(struct sockaddr_in); 519 daddr.addr_in.sin_addr.s_addr = srv->address; 520 daddr.addr_in.sin_port = 0; 521 daddr.addr_in.sin_family = AF_INET; 522 523 /* start the dpd */ 524 error = ike_session_ph1_force_dpd(&daddr.ss); 525 break; 526 } 527 } 528 } 529 break; 530 531 case VPNCTL_CMD_ASSERT: 532 { 533 struct vpnctl_cmd_assert *pkt = ALIGNED_CAST(struct vpnctl_cmd_assert *)combuf; 534// struct bound_addr *addr; 535// struct bound_addr *t_addr; 536 struct sockaddr_in saddr; 537 struct sockaddr_in daddr; 538 539 plogdump(ASL_LEVEL_DEBUG, pkt, ntohs(hdr->len) + sizeof(struct vpnctl_hdr), "received assert command on vpn control socket.\n"); 540// LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 541// if (pkt->dst_address == addr->address) { 542 bzero(&saddr, sizeof(saddr)); 543 saddr.sin_len = sizeof(saddr); 544 saddr.sin_addr.s_addr = pkt->src_address; 545 saddr.sin_port = 0; 546 saddr.sin_family = AF_INET; 547 bzero(&daddr, sizeof(daddr)); 548 daddr.sin_len = sizeof(daddr); 549 daddr.sin_addr.s_addr = pkt->dst_address; 550 daddr.sin_port = 0; 551 daddr.sin_family = AF_INET; 552 553 error = vpn_assert((struct sockaddr_storage *)&saddr, (struct sockaddr_storage *)&daddr); 554 break; 555// } 556// } 557 } 558 break; 559 560 case VPNCTL_CMD_RECONNECT: 561 { 562 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf; 563 struct bound_addr *addr; 564 struct bound_addr *t_addr; 565 566 plog(ASL_LEVEL_DEBUG, 567 "received reconnect command on vpn control socket.\n"); 568 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 569 if (pkt->address == addr->address) { 570 /* start the connection */ 571 error = vpn_connect(addr, VPN_RESTARTED_BY_API); 572 break; 573 } 574 } 575 } 576 break; 577 578 default: 579 plog(ASL_LEVEL_ERR, 580 "invalid command: %d\n", ntohs(hdr->msg_type)); 581 error = -1; // for now 582 break; 583 } 584 585 hdr->len = 0; 586 hdr->result = htons(error); 587 if (vpncontrol_reply(elem->sock, combuf) < 0) 588 return -1; 589 590 return 0; 591 592} 593 594static int 595vpncontrol_reply(int so, char *combuf) 596{ 597 ssize_t tlen; 598 599 tlen = send(so, combuf, sizeof(struct vpnctl_hdr), 0); 600 if (tlen < 0) { 601 plog(ASL_LEVEL_ERR, 602 "failed to send vpn_control message: %s\n", strerror(errno)); 603 return -1; 604 } 605 606 return 0; 607} 608 609int 610vpncontrol_notify_need_authinfo(phase1_handle_t *iph1, void* attr_list, size_t attr_len) 611{ 612 struct vpnctl_status_need_authinfo *msg = NULL; 613 struct vpnctl_socket_elem *sock_elem; 614 struct bound_addr *bound_addr; 615 size_t msg_size; 616 ssize_t tlen; 617 u_int32_t address; 618 void *ptr; 619 620 if (!iph1) 621 goto end; 622 623 plog(ASL_LEVEL_DEBUG, 624 "sending vpn_control xauth need info status\n"); 625 626 msg = (struct vpnctl_status_need_authinfo *)racoon_malloc(msg_size = sizeof(struct vpnctl_status_need_authinfo) + attr_len); 627 if (msg == NULL) { 628 plog(ASL_LEVEL_ERR, 629 "unable to allocate space for vpn control message.\n"); 630 return -1; 631 } 632 msg->hdr.flags = 0; 633 634 if (iph1->remote->ss_family == AF_INET) 635 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr; 636 else 637 goto end; // for now 638 639 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0; 640 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr)); 641 if (!ike_session_is_client_ph1_rekey(iph1)) { 642 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_AUTHINFO); 643 } else { 644 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_REAUTHINFO); 645 } 646 msg->address = address; 647 ptr = msg + 1; 648 memcpy(ptr, attr_list, attr_len); 649 650 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) { 651 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) { 652 if (bound_addr->address == 0xFFFFFFFF || 653 bound_addr->address == address) { 654 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size); 655 tlen = send(sock_elem->sock, msg, msg_size, 0); 656 if (tlen < 0) { 657 plog(ASL_LEVEL_ERR, 658 "failed to send vpn_control need authinfo status: %s\n", strerror(errno)); 659 } 660 break; 661 } 662 } 663 } 664 665end: 666 if (msg) 667 racoon_free(msg); 668 return 0; 669} 670 671int 672vpncontrol_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) 673{ 674 struct vpnctl_status_failed *msg = NULL; 675 struct vpnctl_socket_elem *sock_elem; 676 struct bound_addr *bound_addr; 677 size_t len; 678 ssize_t tlen; 679 680 len = sizeof(struct vpnctl_status_failed) + data_len; 681 682 msg = (struct vpnctl_status_failed *)racoon_malloc(len); 683 if (msg == NULL) { 684 plog(ASL_LEVEL_DEBUG, 685 "unable to allcate memory for vpn control status message.\n"); 686 return -1; 687 } 688 689 msg->hdr.msg_type = htons(VPNCTL_STATUS_IKE_FAILED); 690 msg->hdr.flags = msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0; 691 msg->hdr.len = htons(len - sizeof(struct vpnctl_hdr)); 692 msg->address = address; 693 msg->ike_code = htons(notify_code); 694 msg->from = htons(from); 695 if (data_len > 0) 696 memcpy(msg->data, data, data_len); 697 plog(ASL_LEVEL_DEBUG, 698 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code, 699 (from == FROM_LOCAL ? "local" : "remote")); 700 701 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) { 702 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) { 703 if (bound_addr->address == 0xFFFFFFFF || 704 bound_addr->address == address) { 705 tlen = send(sock_elem->sock, msg, len, 0); 706 if (tlen < 0) { 707 plog(ASL_LEVEL_ERR, 708 "Unable to send vpn_control ike notify failed: %s\n", strerror(errno)); 709 } 710 break; 711 } 712 } 713 } 714 715 if (msg) 716 racoon_free(msg); 717 return 0; 718} 719 720char * 721vpncontrol_status_2_str(u_int16_t msg_type) 722{ 723 switch (msg_type) { 724 case VPNCTL_STATUS_IKE_FAILED: 725 return "IKE failed"; 726 case VPNCTL_STATUS_PH1_START_US: 727 return "Phase 1 started by us"; 728 case VPNCTL_STATUS_PH1_START_PEER: 729 return "Phase 1 started by peer"; 730 case VPNCTL_STATUS_PH1_ESTABLISHED: 731 return "Phase 1 established"; 732 case VPNCTL_STATUS_PH2_START: 733 return "Phase 2 started"; 734 case VPNCTL_STATUS_PH2_ESTABLISHED: 735 return "Phase 2 established"; 736 case VPNCTL_STATUS_NEED_AUTHINFO: 737 return "Need authentication info"; 738 case VPNCTL_STATUS_NEED_REAUTHINFO: 739 return "Need re-authentication info"; 740 default: 741 return ""; 742 } 743} 744 745 746int 747vpncontrol_notify_phase_change(int start, u_int16_t from, phase1_handle_t *iph1, phase2_handle_t *iph2) 748{ 749 struct vpnctl_status_phase_change *msg; 750 struct vpnctl_socket_elem *sock_elem; 751 struct bound_addr *bound_addr; 752 ssize_t tlen; 753 size_t msg_size; 754 u_int32_t address; 755 756 if (iph1 && !start && iph1->mode_cfg && iph1->mode_cfg->xauth.status != XAUTHST_OK) { 757 if (vpn_get_config(iph1, &msg, &msg_size) == 1) 758 return 0; /* mode config not finished yet */ 759 } else { 760 msg = racoon_malloc(msg_size = sizeof(struct vpnctl_status_phase_change)); 761 msg->hdr.flags = 0; 762 } 763 764 if (msg == NULL) { 765 plog(ASL_LEVEL_ERR, 766 "unable to allocate space for vpn control message.\n"); 767 return -1; 768 } 769 if (iph1) { 770 if (iph1->remote->ss_family == AF_INET) 771 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr; 772 else 773 goto end; // for now 774 msg->hdr.msg_type = htons(start ? 775 (from == FROM_LOCAL ? VPNCTL_STATUS_PH1_START_US : VPNCTL_STATUS_PH1_START_PEER) 776 : VPNCTL_STATUS_PH1_ESTABLISHED); 777 // TODO: indicate version 778 } else { 779 if (iph2->dst->ss_family == AF_INET) 780 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr; 781 else 782 goto end; // for now 783 msg->hdr.msg_type = htons(start ? VPNCTL_STATUS_PH2_START : VPNCTL_STATUS_PH2_ESTABLISHED); 784 // TODO: indicate version 785 } 786 plog(ASL_LEVEL_NOTICE, 787 ">>>>> phase change status = %s\n", vpncontrol_status_2_str(ntohs(msg->hdr.msg_type))); 788 789 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0; 790 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr)); 791 msg->address = address; 792 793 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) { 794 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) { 795 if (bound_addr->address == 0xFFFFFFFF || 796 bound_addr->address == address) { 797 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size); 798 tlen = send(sock_elem->sock, msg, msg_size, 0); 799 if (tlen < 0) { 800 plog(ASL_LEVEL_ERR, 801 "failed to send vpn_control phase change status: %s\n", strerror(errno)); 802 } 803 break; 804 } 805 } 806 } 807 808end: 809 if (msg) 810 racoon_free(msg); 811 return 0; 812} 813 814static int 815vpncontrol_notify_peer_resp (u_int16_t notify_code, u_int32_t address) 816{ 817 struct vpnctl_status_peer_resp msg; 818 struct vpnctl_socket_elem *sock_elem; 819 struct bound_addr *bound_addr; 820 ssize_t tlen; 821 int rc = -1; 822 823 bzero(&msg, sizeof(msg)); 824 msg.hdr.msg_type = htons(VPNCTL_STATUS_PEER_RESP); 825 msg.hdr.cookie = msg.hdr.reserved = msg.hdr.result = 0; 826 msg.hdr.len = htons(sizeof(msg) - sizeof(msg.hdr)); 827 msg.address = address; 828 msg.ike_code = notify_code; 829 plog(ASL_LEVEL_DEBUG, 830 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code, address); 831 832 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) { 833 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) { 834 if (bound_addr->address == 0xFFFFFFFF || 835 bound_addr->address == address) { 836 tlen = send(sock_elem->sock, &msg, sizeof(msg), 0); 837 if (tlen < 0) { 838 plog(ASL_LEVEL_ERR, 839 "unable to send vpn_control status (peer response): %s\n", strerror(errno)); 840 } else { 841 rc = 0; 842 } 843 break; 844 } 845 } 846 } 847 848 return rc; 849} 850 851int 852vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code, phase1_handle_t *iph1) 853{ 854 u_int32_t address; 855 int rc; 856 857 if (iph1 && iph1->parent_session && iph1->parent_session->controller_awaiting_peer_resp) { 858 if (iph1->remote->ss_family == AF_INET) 859 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr; 860 else 861 address = 0; 862 } else { 863 return 0; 864 } 865 866 if ((rc = vpncontrol_notify_peer_resp(notify_code, address)) == 0) { 867 iph1->parent_session->controller_awaiting_peer_resp = 0; 868 } 869 return rc; 870} 871 872int 873vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code, phase2_handle_t *iph2) 874{ 875 u_int32_t address; 876 int rc; 877 878 if (iph2 && iph2->parent_session && iph2->parent_session->controller_awaiting_peer_resp) { 879 if (iph2->dst->ss_family == AF_INET) 880 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr; 881 else 882 address = 0; 883 } else { 884 return 0; 885 } 886 887 if ((rc = vpncontrol_notify_peer_resp(notify_code, address)) == 0) { 888 iph2->parent_session->controller_awaiting_peer_resp = 0; 889 } 890 return rc; 891} 892 893int 894vpncontrol_init(void) 895{ 896 int sock; 897 898 if (vpncontrolsock_path == NULL) { 899 lcconf->sock_vpncontrol = -1; 900 return 0; 901 } 902 903 if ( (lcconf->sock_vpncontrol = checklaunchd()) == 0 ) { 904 memset(&sunaddr, 0, sizeof(sunaddr)); 905 sunaddr.sun_family = AF_UNIX; 906 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), 907 "%s", vpncontrolsock_path); 908 909 lcconf->sock_vpncontrol = socket(AF_UNIX, SOCK_STREAM, 0); 910 if (lcconf->sock_vpncontrol == -1) { 911 plog(ASL_LEVEL_ERR, 912 "socket: %s\n", strerror(errno)); 913 return -1; 914 } 915 916 if (fcntl(lcconf->sock_vpncontrol, F_SETFL, O_NONBLOCK) == -1) { 917 plog(ASL_LEVEL_ERR, "failed to put VPN-Control socket in non-blocking mode\n"); 918 } 919 920 unlink(sunaddr.sun_path); 921 if (bind(lcconf->sock_vpncontrol, (struct sockaddr *)&sunaddr, 922 sizeof(sunaddr)) != 0) { 923 plog(ASL_LEVEL_ERR, 924 "bind(sockname:%s): %s\n", 925 sunaddr.sun_path, strerror(errno)); 926 (void)close(lcconf->sock_vpncontrol); 927 return -1; 928 } 929 930 if (chown(sunaddr.sun_path, vpncontrolsock_owner, vpncontrolsock_group) != 0) { 931 plog(ASL_LEVEL_ERR, 932 "chown(%s, %d, %d): %s\n", 933 sunaddr.sun_path, vpncontrolsock_owner, 934 vpncontrolsock_group, strerror(errno)); 935 (void)close(lcconf->sock_vpncontrol); 936 return -1; 937 } 938 939 if (chmod(sunaddr.sun_path, vpncontrolsock_mode) != 0) { 940 plog(ASL_LEVEL_ERR, 941 "chmod(%s, 0%03o): %s\n", 942 sunaddr.sun_path, vpncontrolsock_mode, strerror(errno)); 943 (void)close(lcconf->sock_vpncontrol); 944 return -1; 945 } 946 947 if (listen(lcconf->sock_vpncontrol, 5) != 0) { 948 plog(ASL_LEVEL_ERR, 949 "listen(sockname:%s): %s\n", 950 sunaddr.sun_path, strerror(errno)); 951 (void)close(lcconf->sock_vpncontrol); 952 return -1; 953 } 954 plog(ASL_LEVEL_DEBUG, 955 "opened %s as racoon management.\n", sunaddr.sun_path); 956 } 957 lcconf->vpncontrol_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_vpncontrol, 0, dispatch_get_main_queue()); 958 if (lcconf->vpncontrol_source == NULL) { 959 plog(ASL_LEVEL_ERR, "could not create vpncontrol socket source."); 960 return -1; 961 } 962 dispatch_source_set_event_handler_f(lcconf->vpncontrol_source, vpncontrol_handler); 963 sock = lcconf->sock_vpncontrol; 964 dispatch_source_set_cancel_handler(lcconf->vpncontrol_source, 965 ^{ 966 close(sock); 967 }); 968 dispatch_resume(lcconf->vpncontrol_source); 969 return 0; 970} 971 972void 973vpncontrol_disconnect_all(struct vpnctl_socket_elem *elem, const char *reason) 974{ 975 struct bound_addr *addr; 976 struct bound_addr *t_addr; 977 978 plog(ASL_LEVEL_DEBUG, 979 "received disconnect all command.\n"); 980 981 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 982 /* stop any connections */ 983 vpn_disconnect(addr, reason); 984 } 985} 986 987void 988vpncontrol_close() 989{ 990 struct vpnctl_socket_elem *elem; 991 struct vpnctl_socket_elem *t_elem; 992 993 plog(ASL_LEVEL_DEBUG, 994 "vpncontrol_close.\n"); 995 996 dispatch_source_cancel(lcconf->vpncontrol_source); 997 lcconf->vpncontrol_source = NULL; 998 999 lcconf->sock_vpncontrol = -1; 1000 LIST_FOREACH_SAFE(elem, &lcconf->vpnctl_comm_socks, chain, t_elem) 1001 vpncontrol_close_comm(elem); 1002} 1003 1004static void 1005vpncontrol_close_comm(struct vpnctl_socket_elem *elem) 1006{ 1007 struct bound_addr *addr; 1008 struct bound_addr *t_addr; 1009 1010 plog(ASL_LEVEL_DEBUG, 1011 "vpncontrol_close_comm.\n"); 1012 1013 LIST_REMOVE(elem, chain); 1014 if (elem->sock != -1) 1015 dispatch_source_cancel(elem->source); 1016 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) { 1017 flushsainfo_dynamic(addr->address); 1018 LIST_REMOVE(addr, chain); 1019 if (addr->version) 1020 vfree(addr->version); 1021 racoon_free(addr); 1022 } 1023 racoon_free(elem); 1024 check_auto_exit(); 1025 1026} 1027 1028int 1029vpn_control_connected(void) 1030{ 1031 if (LIST_EMPTY(&lcconf->vpnctl_comm_socks)) 1032 return 0; 1033 else 1034 return 1; 1035} 1036 1037#endif 1038