1/* 2 * Copyright (c) 2000, 2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* ----------------------------------------------------------------------------- 25includes 26----------------------------------------------------------------------------- */ 27 28#include <fcntl.h> 29#include <unistd.h> 30#include <netdb.h> 31#include <netdb_async.h> 32#include <sys/param.h> 33#include <sys/socket.h> 34#include <sys/ioctl.h> 35#include "sys/syslog.h" 36#include <paths.h> 37#include <net/if.h> 38#include <net/if_media.h> 39#include <net/ndrv.h> 40#include <net/if_dl.h> 41#include <net/if_utun.h> 42#include <netinet/ip.h> 43#include <netinet/ip_icmp.h> 44#include <arpa/inet.h> 45#include <net/route.h> 46#include <mach/mach_time.h> 47#include <mach/mach.h> 48#include <mach/message.h> 49#include <mach/boolean.h> 50#include <mach/mach_error.h> 51#include <servers/bootstrap.h> 52#include <notify.h> 53#include <sys/kern_control.h> 54#include <sys/sys_domain.h> 55#include <netinet/in_var.h> 56#include <ifaddrs.h> 57#include <sys/sysctl.h> 58 59#include <CoreFoundation/CFUserNotification.h> 60#include <SystemConfiguration/SystemConfiguration.h> 61#include <SystemConfiguration/SCDPlugin.h> 62#include <SystemConfiguration/SCPrivate.h> // for SCLog() 63#include <mach/task_special_ports.h> 64#include "pppcontroller_types.h" 65#include "pppcontroller.h" 66#include <SystemConfiguration/SCValidation.h> 67#include <SystemConfiguration/SCPreferences.h> 68#include <sys/un.h> 69 70#include "scnc_client.h" 71#include "scnc_main.h" 72#include "ipsec_manager.h" 73#include "ipsec_utils.h" 74#include "scnc_utils.h" 75#include "scnc_cache.h" 76#include "cf_utils.h" 77#include "PPPControllerPriv.h" 78#include "controller_options.h" 79 80//#include <IPSec/IPSec.h> 81//#include <IPSec/IPSecSchemaDefinitions.h> 82 83#include "../Helpers/vpnd/RASSchemaDefinitions.h" 84#include "../Helpers/vpnd/ipsec_utils.h" 85 86#include "sessionTracer.h" 87 88 89 90/* ----------------------------------------------------------------------------- 91globals 92----------------------------------------------------------------------------- */ 93 94enum { 95 do_nothing = 0, 96 do_process, 97 do_close, 98 do_error 99}; 100 101enum { 102 dialog_default_type = 0, 103 dialog_has_disconnect_type = 1, 104 dialog_cert_fixme_type = 2 105}; 106 107#define TIMEOUT_INITIAL_CONTACT 10 /* give 10 second to establish contact with server */ 108#define TIMEOUT_PHASE1 30 /* give 30 second to complete phase 1 */ 109#define TIMEOUT_PHASE2 30 /* give 30 second to complete phase 2 (to accomodate larger cfgs on slower devices) */ 110#define TIMEOUT_PHASE2_PING 1 /* sends ping every second until phase 2 starts */ 111#define TIMEOUT_ASSERT_IDLE 3 /* allow 3 seconds after assert for traffic to trigger rekeys */ 112 113#define MAX_PHASE2_PING 15 /* give up after 15 pings */ 114 115#define TIMEOUT_INTERFACE_CHANGE 20 /* give 20 second to address to come back */ 116 117#define XAUTH_FIRST_TIME 0x8000 118#define XAUTH_NEED_USERNAME 0x0001 119#define XAUTH_NEED_PASSWORD 0x0002 120#define XAUTH_NEED_PASSCODE 0x0004 121#define XAUTH_NEED_ANSWER 0x0008 122#define XAUTH_NEED_NEXT_PIN 0x0010 123#define XAUTH_NEED_XAUTH_INFO 0x0020 124#define XAUTH_MUST_PROMPT 0x0040 125#define XAUTH_DID_PROMPT 0x0080 126 127#define DISPLAY_RE_ENROLL_ALERT_INTERVAL 15*60 /* how much should lapse before displaying re-enroll alert again */ 128 129#define IPSEC_STATUS_IS_CLIENT_CERTIFICATE_INVALID(s) ((s == IPSEC_CLIENT_CERTIFICATE_PREMATURE) || \ 130 (s == IPSEC_CLIENT_CERTIFICATE_EXPIRED) || \ 131 (s == IPSEC_CLIENT_CERTIFICATE_ERROR)) 132 133struct isakmp_xauth { 134 u_int16_t type; 135 CFStringRef str; 136}; 137 138 139#if TARGET_OS_EMBEDDED 140// extra CFUserNotification keys 141static CFStringRef const SBUserNotificationTextAutocapitalizationType = CFSTR("SBUserNotificationTextAutocapitalizationType"); 142static CFStringRef const SBUserNotificationTextAutocorrectionType = CFSTR("SBUserNotificationTextAutocorrectionType"); 143static CFStringRef const SBUserNotificationGroupsTextFields = CFSTR("SBUserNotificationGroupsTextFields"); 144#endif 145 146/* ----------------------------------------------------------------------------- 147Forward declarations 148----------------------------------------------------------------------------- */ 149 150static void ipsec_log(int level, CFStringRef format, ...) CF_FORMAT_FUNCTION(2, 3); 151static void ipsec_updatephase(struct service *serv, int phase); 152static void display_notification(struct service *serv, CFStringRef message, int errnum, int dialog_type); 153static void racoon_timer(CFRunLoopTimerRef timer, void *info); 154static int racoon_restart(struct service *serv, struct sockaddr_in *address); 155static int racoon_resolve(struct service *serv); 156static bool mode_config_is_default(struct service *serv); 157static void install_mode_config(struct service *serv, Boolean installConfig, Boolean installPolicies); 158static void uninstall_mode_config(struct service *serv, Boolean uninstallPolicies); 159static int unassert_mode_config(struct service *serv); 160static int ask_user_xauth(struct service *serv, char* message); 161static boolean_t checkpassword(struct service *serv, int must_prompt); 162int readn(int ref, void *data, int len); 163int writen(int ref, void *data, int len); 164 165int racoon_send_cmd_start_ph2(int fd, u_int32_t address, CFDictionaryRef ipsec_dict); 166int racoon_send_cmd_assert(struct service *serv); 167int racoon_send_cmd_xauthinfo(int fd, u_int32_t address, struct isakmp_xauth *isakmp_array, int isakmp_nb); 168int racoon_send_cmd_start_dpd(int fd, u_int32_t address) ; 169 170void 171ipsec_log(int level, CFStringRef format, ...) 172{ 173 if (ne_sm_bridge_is_logging_at_level(level)) { 174 va_list args; 175 va_start(args, format); 176 if (!ne_sm_bridge_logv(level, format, args)) { 177 SCLoggerVLog(NULL, level, format, args); 178 } 179 va_end(args); 180 } 181} 182 183 184/* ----------------------------------------------------------------------------- 185 ----------------------------------------------------------------------------- */ 186int ipsec_init_things() 187{ 188 189 // TO DO: save each configuration and remove them upon configd restart, 190 // in case they are leftover after a crash. 191 192#if TARGET_OS_EMBEDDED 193 // currently only VPN uses IPSec on embedded 194 // Do not flush SAs, so as to not interfere with other configurations 195 //IPSecFlushAll(); 196#endif /* TARGET_OS_EMBEDDED */ 197 198 return 0; 199} 200 201/* ----------------------------------------------------------------------------- 202get the ipsec string corresponding to the ike error 203----------------------------------------------------------------------------- */ 204char *ipsec_error_to_str(int ike_code) 205{ 206 switch (ike_code) { 207 case VPNCTL_NTYPE_INVALID_PAYLOAD_TYPE: return "Invalid payload type"; 208 case VPNCTL_NTYPE_DOI_NOT_SUPPORTED: return "DOI not supported"; 209 case VPNCTL_NTYPE_SITUATION_NOT_SUPPORTED: return "Situation not supported"; 210 case VPNCTL_NTYPE_INVALID_COOKIE: return "Invalid cookie"; 211 case VPNCTL_NTYPE_INVALID_MAJOR_VERSION: return "Invalid major version"; 212 case VPNCTL_NTYPE_INVALID_MINOR_VERSION: return "Invalid minor version"; 213 case VPNCTL_NTYPE_INVALID_EXCHANGE_TYPE: return "Invalid exchange type"; 214 case VPNCTL_NTYPE_INVALID_FLAGS: return "Invalid flags"; 215 case VPNCTL_NTYPE_INVALID_MESSAGE_ID: return "Invalid message id"; 216 case VPNCTL_NTYPE_INVALID_PROTOCOL_ID: return "Invalid protocol id"; 217 case VPNCTL_NTYPE_INVALID_SPI: return "Invalid SPI"; 218 case VPNCTL_NTYPE_INVALID_TRANSFORM_ID: return "Invalid transform id"; 219 case VPNCTL_NTYPE_ATTRIBUTES_NOT_SUPPORTED: return "Attributes not supported"; 220 case VPNCTL_NTYPE_NO_PROPOSAL_CHOSEN: return "No proposal chosen"; 221 case VPNCTL_NTYPE_BAD_PROPOSAL_SYNTAX: return "Bad proposal syntax"; 222 case VPNCTL_NTYPE_PAYLOAD_MALFORMED: return "Payload malformed"; 223 case VPNCTL_NTYPE_INVALID_KEY_INFORMATION: return "Invalid key information"; 224 case VPNCTL_NTYPE_INVALID_ID_INFORMATION: return "Invalid id information"; 225 case VPNCTL_NTYPE_INVALID_CERT_ENCODING: return "Invalid cert encoding"; 226 case VPNCTL_NTYPE_INVALID_CERTIFICATE: return "Invalid certificate"; 227 case VPNCTL_NTYPE_BAD_CERT_REQUEST_SYNTAX: return "Bad cert request syntax"; 228 case VPNCTL_NTYPE_INVALID_CERT_AUTHORITY: return "Invalid cert authority"; 229 case VPNCTL_NTYPE_INVALID_HASH_INFORMATION: return "Invalid hash information"; 230 case VPNCTL_NTYPE_AUTHENTICATION_FAILED: return "Authentication Failed"; 231 case VPNCTL_NTYPE_INVALID_SIGNATURE: return "Invalid signature"; 232 case VPNCTL_NTYPE_ADDRESS_NOTIFICATION: return "Address notification"; 233 case VPNCTL_NTYPE_NOTIFY_SA_LIFETIME: return "Notify SA lifetime"; 234 case VPNCTL_NTYPE_CERTIFICATE_UNAVAILABLE: return "Certificate unavailable"; 235 case VPNCTL_NTYPE_UNSUPPORTED_EXCHANGE_TYPE: return "Unsupported exchange type"; 236 case VPNCTL_NTYPE_UNEQUAL_PAYLOAD_LENGTHS: return "Unequal payload lengths"; 237 case VPNCTL_NTYPE_LOAD_BALANCE: return "Load balance"; 238 case VPNCTL_NTYPE_PEER_DEAD: return "Dead Peer"; 239 case VPNCTL_NTYPE_PH1_DELETE: return "Phase 1 Delete"; 240 case VPNCTL_NTYPE_IDLE_TIMEOUT: return "Idle Timeout"; 241 case VPNCTL_NTYPE_LOCAL_CERT_PREMATURE: return "Certificate premature"; 242 case VPNCTL_NTYPE_LOCAL_CERT_EXPIRED: return "Certificate expired"; 243 case VPNCTL_NTYPE_PEER_CERT_PREMATURE: return "Server certificate premature"; 244 case VPNCTL_NTYPE_PEER_CERT_EXPIRED: return "Server certificate expired"; 245 case VPNCTL_NTYPE_PEER_CERT_INVALID_SUBJNAME: return "Server certificate subjectName invalid"; 246 case VPNCTL_NTYPE_PEER_CERT_INVALID_SUBJALTNAME: return "Server certificate subjectAltName invalid"; 247 case VPNCTL_NTYPE_INTERNAL_ERROR: return "Internal error"; 248 } 249 return "Unknown error"; 250} 251 252/* ----------------------------------------------------------------------------- 253get the ipsec generic error corresponding to the ike error 254----------------------------------------------------------------------------- */ 255u_int32_t ipsec_error_to_status(struct service *serv, int from, int ike_code) 256{ 257 switch (ike_code) { 258 case VPNCTL_NTYPE_INVALID_PAYLOAD_TYPE: 259 case VPNCTL_NTYPE_DOI_NOT_SUPPORTED: 260 case VPNCTL_NTYPE_SITUATION_NOT_SUPPORTED: 261 case VPNCTL_NTYPE_INVALID_COOKIE: 262 case VPNCTL_NTYPE_INVALID_MAJOR_VERSION: 263 case VPNCTL_NTYPE_INVALID_MINOR_VERSION: 264 case VPNCTL_NTYPE_INVALID_EXCHANGE_TYPE: 265 case VPNCTL_NTYPE_INVALID_FLAGS: 266 case VPNCTL_NTYPE_INVALID_MESSAGE_ID: 267 case VPNCTL_NTYPE_INVALID_PROTOCOL_ID: 268 case VPNCTL_NTYPE_INVALID_SPI: 269 case VPNCTL_NTYPE_INVALID_TRANSFORM_ID: 270 case VPNCTL_NTYPE_ATTRIBUTES_NOT_SUPPORTED: 271 case VPNCTL_NTYPE_NO_PROPOSAL_CHOSEN: 272 case VPNCTL_NTYPE_BAD_PROPOSAL_SYNTAX: 273 case VPNCTL_NTYPE_PAYLOAD_MALFORMED: 274 case VPNCTL_NTYPE_INVALID_KEY_INFORMATION: 275 case VPNCTL_NTYPE_INVALID_ID_INFORMATION: 276 case VPNCTL_NTYPE_INVALID_CERT_ENCODING: 277 case VPNCTL_NTYPE_BAD_CERT_REQUEST_SYNTAX: 278 case VPNCTL_NTYPE_UNSUPPORTED_EXCHANGE_TYPE: 279 case VPNCTL_NTYPE_UNEQUAL_PAYLOAD_LENGTHS: 280 case VPNCTL_NTYPE_INTERNAL_ERROR: 281 return IPSEC_NEGOTIATION_ERROR; 282 283 case VPNCTL_NTYPE_INVALID_HASH_INFORMATION: 284 return IPSEC_SHAREDSECRET_ERROR; 285 286 case VPNCTL_NTYPE_CERTIFICATE_UNAVAILABLE: 287 return IPSEC_NOCERTIFICATE_ERROR; 288 289 case VPNCTL_NTYPE_INVALID_SIGNATURE: 290 case VPNCTL_NTYPE_INVALID_CERTIFICATE: 291 case VPNCTL_NTYPE_INVALID_CERT_AUTHORITY: 292 return (from == FROM_REMOTE ? IPSEC_CLIENT_CERTIFICATE_ERROR : IPSEC_SERVER_CERTIFICATE_ERROR); 293 294 case VPNCTL_NTYPE_AUTHENTICATION_FAILED: 295 return IPSEC_XAUTH_ERROR; 296 297 case VPNCTL_NTYPE_ADDRESS_NOTIFICATION: 298 case VPNCTL_NTYPE_NOTIFY_SA_LIFETIME: 299 case VPNCTL_NTYPE_LOAD_BALANCE: 300 case VPNCTL_NTYPE_PEER_DEAD: 301 case VPNCTL_NTYPE_IDLE_TIMEOUT: 302 return IPSEC_NO_ERROR; 303 304 case VPNCTL_NTYPE_PH1_DELETE: 305 return IPSEC_NO_ERROR; 306 307 case VPNCTL_NTYPE_LOCAL_CERT_PREMATURE: 308 return IPSEC_CLIENT_CERTIFICATE_PREMATURE; 309 310 case VPNCTL_NTYPE_LOCAL_CERT_EXPIRED: 311 return IPSEC_CLIENT_CERTIFICATE_EXPIRED; 312 313 case VPNCTL_NTYPE_PEER_CERT_PREMATURE: 314 return IPSEC_SERVER_CERTIFICATE_PREMATURE; 315 316 case VPNCTL_NTYPE_PEER_CERT_EXPIRED: 317 return IPSEC_SERVER_CERTIFICATE_EXPIRED; 318 319 case VPNCTL_NTYPE_PEER_CERT_INVALID_SUBJNAME: 320 case VPNCTL_NTYPE_PEER_CERT_INVALID_SUBJALTNAME: 321 return IPSEC_SERVER_CERTIFICATE_INVALID_ID; 322 323 } 324 return IPSEC_GENERIC_ERROR; 325} 326 327/* ----------------------------------------------------------------------------- 328get the ipsec string corresponding to the message type 329----------------------------------------------------------------------------- */ 330char *ipsec_msgtype_to_str(int msgtype) 331{ 332 switch (msgtype) { 333 case VPNCTL_CMD_BIND: return "VPNCTL_CMD_BIND"; 334 case VPNCTL_CMD_UNBIND: return "VPNCTL_CMD_UNBIND"; 335 case VPNCTL_CMD_REDIRECT: return "VPNCTL_CMD_REDIRECT"; 336 case VPNCTL_CMD_PING: return "VPNCTL_CMD_PING"; 337 case VPNCTL_CMD_CONNECT: return "VPNCTL_CMD_CONNECT"; 338 case VPNCTL_CMD_DISCONNECT: return "VPNCTL_CMD_DISCONNECT"; 339 case VPNCTL_CMD_START_PH2: return "VPNCTL_CMD_START_PH2"; 340 case VPNCTL_CMD_XAUTH_INFO: return "VPNCTL_CMD_XAUTH_INFO"; 341 case VPNCTL_CMD_ASSERT: return "VPNCTL_CMD_ASSERT"; 342 case VPNCTL_CMD_RECONNECT: return "VPNCTL_CMD_RECONNECT"; 343 case VPNCTL_STATUS_IKE_FAILED: return "VPNCTL_STATUS_IKE_FAILED"; 344 case VPNCTL_STATUS_PH1_START_US: return "VPNCTL_STATUS_PH1_START_US"; 345 case VPNCTL_STATUS_PH1_START_PEER: return "VPNCTL_STATUS_PH1_START_PEER"; 346 case VPNCTL_STATUS_PH1_ESTABLISHED: return "VPNCTL_STATUS_PH1_ESTABLISHED"; 347 case VPNCTL_STATUS_PH2_START: return "VPNCTL_STATUS_PH2_START"; 348 case VPNCTL_STATUS_PH2_ESTABLISHED: return "VPNCTL_STATUS_PH2_ESTABLISHED"; 349 case VPNCTL_STATUS_NEED_AUTHINFO: return "VPNCTL_STATUS_NEED_AUTHINFO"; 350 case VPNCTL_STATUS_NEED_REAUTHINFO: return "VPNCTL_STATUS_NEED_REAUTHINFO"; 351 } 352 return "Unknown message type"; 353} 354 355/* ----------------------------------------------------------------------------- 356get the ipsec string corresponding to the message type 357----------------------------------------------------------------------------- */ 358char *ipsec_xauthtype_to_str(int msgtype) 359{ 360 switch (msgtype) { 361 case XAUTH_TYPE: return "XAUTH_TYPE"; 362 case XAUTH_USER_NAME: return "XAUTH_USER_NAME"; 363 case XAUTH_USER_PASSWORD: return "XAUTH_USER_PASSWORD"; 364 case XAUTH_PASSCODE: return "XAUTH_PASSCODE"; 365 case XAUTH_MESSAGE: return "XAUTH_MESSAGE"; 366 case XAUTH_CHALLENGE: return "XAUTH_CHALLENGE"; 367 case XAUTH_DOMAIN: return "XAUTH_DOMAIN"; 368 case XAUTH_STATUS: return "XAUTH_STATUS"; 369 case XAUTH_NEXT_PIN: return "XAUTH_NEXT_PIN"; 370 case XAUTH_ANSWER: return "XAUTH_ANSWER"; 371 } 372 return "XAUTH_TYPE unknown type"; 373} 374 375/* ----------------------------------------------------------------------------- 376get the ipsec string corresponding to the message type 377----------------------------------------------------------------------------- */ 378char *ipsec_modecfgtype_to_str(int msgtype) 379{ 380 switch (msgtype) { 381 382 case INTERNAL_IP4_ADDRESS: return "INTERNAL_IP4_ADDRESS"; 383 case INTERNAL_IP4_NETMASK: return "INTERNAL_IP4_NETMASK"; 384 case INTERNAL_IP4_DNS: return "INTERNAL_IP4_DNS"; 385 case INTERNAL_IP4_NBNS: return "INTERNAL_IP4_NBNS"; 386 case INTERNAL_ADDRESS_EXPIRY: return "INTERNAL_ADDRESS_EXPIRY"; 387 case INTERNAL_IP4_DHCP: return "INTERNAL_IP4_DHCP"; 388 case APPLICATION_VERSION: return "APPLICATION_VERSION"; 389 case INTERNAL_IP6_ADDRESS: return "INTERNAL_IP6_ADDRESS"; 390 case INTERNAL_IP6_NETMASK: return "INTERNAL_IP6_NETMASK"; 391 case INTERNAL_IP6_DNS: return "INTERNAL_IP6_DNS"; 392 case INTERNAL_IP6_NBNS: return "INTERNAL_IP6_NBNS"; 393 case INTERNAL_IP6_DHCP: return "INTERNAL_IP6_DHCP"; 394 case INTERNAL_IP4_SUBNET: return "INTERNAL_IP4_SUBNET"; 395 case SUPPORTED_ATTRIBUTES: return "SUPPORTED_ATTRIBUTES"; 396 case INTERNAL_IP6_SUBNET: return "INTERNAL_IP6_SUBNET"; 397 398 } 399 return "MODECFG_TYPE unknown type"; 400} 401 402 403/* ----------------------------------------------------------------------------- 404----------------------------------------------------------------------------- */ 405u_int16_t ipsec_subtype(CFStringRef subtypeRef) 406{ 407 408 return 0; 409} 410 411/* ----------------------------------------------------------------------------- 412an interface structure needs to be created 413----------------------------------------------------------------------------- */ 414int ipsec_new_service(struct service *serv) 415{ 416 417 serv->u.ipsec.phase = IPSEC_IDLE; 418 serv->u.ipsec.controlfd = -1; 419 serv->u.ipsec.kernctl_sock = -1; 420 serv->u.ipsec.eventfd = -1; 421 serv->u.ipsec.routes = NULL; 422 return 0; 423} 424 425/* ----------------------------------------------------------------------------- 426an interface is come down, dispose the structure 427----------------------------------------------------------------------------- */ 428int ipsec_dispose_service(struct service *serv) 429{ 430 431 if (serv->u.ipsec.phase != IPSEC_IDLE) 432 return 1; 433 free_service_routes(serv); 434 my_CFRelease(&serv->systemprefs); 435 return 0; 436} 437 438/* ----------------------------------------------------------------------------- 439changed for this service occured in configd cache 440----------------------------------------------------------------------------- */ 441int ipsec_setup_service(struct service *serv) 442{ 443 444 u_int32_t lval; 445 446 /* get some general setting flags first */ 447 serv->flags &= ~( 448 FLAG_SETUP_ONTRAFFIC + 449 FLAG_SETUP_DISCONNECTONLOGOUT + 450 FLAG_SETUP_DISCONNECTONSLEEP + 451 FLAG_SETUP_PREVENTIDLESLEEP + 452 FLAG_SETUP_DISCONNECTONFASTUSERSWITCH + 453 FLAG_SETUP_ONDEMAND + 454 FLAG_DARKWAKE + 455 FLAG_SETUP_PERSISTCONNECTION + 456 FLAG_SETUP_DISCONNECTONWAKE); 457 458 serv->flags |= ( 459 FLAG_ALERTERRORS + 460 FLAG_ALERTPASSWORDS); 461 462 my_CFRelease(&serv->systemprefs); 463 if (serv->ne_sm_bridge != NULL) { 464 serv->systemprefs = ne_sm_bridge_copy_configuration(serv->ne_sm_bridge); 465 } else { 466 serv->systemprefs = copyEntity(gDynamicStore, kSCDynamicStoreDomainSetup, serv->serviceID, kSCEntNetIPSec); 467 } 468 if (serv->systemprefs == NULL) { 469 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Cannot copy IPSec dictionary from setup")); 470 ipsec_stop(serv, 0); 471 return -1; 472 } 473 474 /* Currently, OnDemand imples network detection */ 475 lval = 0; 476 getNumber(serv->systemprefs, kSCPropNetIPSecOnDemandEnabled, &lval); 477 if (lval) 478 serv->flags |= (FLAG_SETUP_ONDEMAND | FLAG_SETUP_NETWORKDETECTION); 479 else if (CFDictionaryGetValue(serv->systemprefs, kSCPropNetVPNOnDemandRules)) { 480 if (controller_options_is_useVODDisconnectRulesWhenVODDisabled()) 481 serv->flags |= FLAG_SETUP_NETWORKDETECTION; 482 } 483 484 lval = 0; 485 getNumber(serv->systemprefs, CFSTR("DisconnectOnLogout"), &lval); 486 if (lval) serv->flags |= FLAG_SETUP_DISCONNECTONLOGOUT; 487 488 lval = 0; 489 getNumber(serv->systemprefs, CFSTR("DisconnectOnSleep"), &lval); 490 if (lval) serv->flags |= FLAG_SETUP_DISCONNECTONSLEEP; 491 492 lval = 0; 493 getNumber(serv->systemprefs, CFSTR("PreventIdleSleep"), &lval); 494 if (lval) serv->flags |= FLAG_SETUP_PREVENTIDLESLEEP; 495 496 /* if the DisconnectOnFastUserSwitch key does not exist, use DisconnectOnLogout */ 497 lval = (serv->flags & FLAG_SETUP_DISCONNECTONLOGOUT); 498 getNumber(serv->systemprefs, CFSTR("DisconnectOnFastUserSwitch"), &lval); 499 if (lval) serv->flags |= FLAG_SETUP_DISCONNECTONFASTUSERSWITCH; 500 501 /* "disconnect on wake" is enabled by default for IPSec */ 502 lval = 1; 503 serv->sleepwaketimeout = 0; 504 getNumber(serv->systemprefs, kSCPropNetIPSecDisconnectOnWake, &lval); 505 if (lval) { 506 serv->flags |= FLAG_SETUP_DISCONNECTONWAKE; 507 getNumber(serv->systemprefs, kSCPropNetIPSecDisconnectOnWakeTimer, &serv->sleepwaketimeout); 508 } 509 510 lval = 1; 511 getNumber(serv->systemprefs, CFSTR("AlertEnable"), &lval); 512 if (!lval) serv->flags &= ~(FLAG_ALERTERRORS + FLAG_ALERTPASSWORDS); 513 514 /* enable "ConnectionPersist" */ 515 lval = 0; 516 getNumber(serv->systemprefs, CFSTR("ConnectionPersist"), &lval); 517 if (lval) serv->flags |= FLAG_SETUP_PERSISTCONNECTION; 518 519#if TARGET_OS_EMBEDDED 520 if (CFDictionaryContainsKey(serv->systemprefs, CFSTR("ProfileIdentifier"))) { 521 my_CFRelease(&serv->profileIdentifier); 522 serv->profileIdentifier = my_CFRetain(CFDictionaryGetValue(serv->systemprefs, CFSTR("ProfileIdentifier"))); 523 } 524#endif 525 526 return 0; 527} 528 529/* ----------------------------------------------------------------------------- 530----------------------------------------------------------------------------- */ 531static void merge_ipsec_dict(const void *key, const void *value, void *context) 532{ 533 /* ignore some of the keys */ 534 535 /* remote address was resolved elsewhere */ 536 if (CFStringCompare(key, kRASPropIPSecRemoteAddress, 0) == kCFCompareEqualTo) 537 return; 538 539 /* merge everything else */ 540 CFDictionarySetValue((CFMutableDictionaryRef)context, key, value); 541} 542 543/* ----------------------------------------------------------------------------- 544----------------------------------------------------------------------------- */ 545void ipsec_user_notification_callback(struct service *serv, CFUserNotificationRef userNotification, CFOptionFlags responseFlags) 546{ 547 548 if ((responseFlags & 3) != kCFUserNotificationDefaultResponse) { 549 switch (serv->u.ipsec.phase) { 550 case IPSEC_IDLE: 551 if (IPSEC_STATUS_IS_CLIENT_CERTIFICATE_INVALID(serv->u.ipsec.laststatus)) { 552#if TARGET_OS_EMBEDDED 553 if (serv->ne_sm_bridge) { 554 ne_sm_bridge_start_profile_janitor(serv->ne_sm_bridge, serv->profileIdentifier); 555 } else { 556 start_profile_janitor(serv); 557 } 558#endif 559 } 560 return; 561 default: 562 // user cancelled 563 ipsec_stop(serv, 0); 564 return; 565 566 } 567 } 568 569#if TARGET_OS_EMBEDDED 570 if (serv->u.ipsec.phase != IPSEC_PHASE1AUTH) 571 return; 572#else 573 if (serv->u.ipsec.phase != IPSEC_PHASE1AUTH && 574 serv->u.ipsec.phase != IPSEC_RUNNING) 575 return; 576#endif 577 578 struct isakmp_xauth isakmp_array[2]; /* max 2 attributes currently supported simultaneously */ 579 int isakmp_nb = 0; 580 581 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_ANSWER) { 582 isakmp_array[isakmp_nb].type = XAUTH_ANSWER; 583 isakmp_array[isakmp_nb].str = CFUserNotificationGetResponseValue(userNotification, kCFUserNotificationTextFieldValuesKey, isakmp_nb); 584 isakmp_nb++; 585 } 586 else if (serv->u.ipsec.xauth_flags & XAUTH_NEED_NEXT_PIN) { 587 isakmp_array[isakmp_nb].type = XAUTH_NEXT_PIN; 588 isakmp_array[isakmp_nb].str = CFUserNotificationGetResponseValue(userNotification, kCFUserNotificationTextFieldValuesKey, isakmp_nb); 589 isakmp_nb++; 590 } 591 else { 592 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_USERNAME) { 593 isakmp_array[isakmp_nb].type = XAUTH_USER_NAME; 594 isakmp_array[isakmp_nb].str = CFUserNotificationGetResponseValue(userNotification, kCFUserNotificationTextFieldValuesKey, isakmp_nb); 595 isakmp_nb++; 596 } 597 598 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_PASSCODE) { 599 isakmp_array[isakmp_nb].type = XAUTH_PASSCODE; 600 isakmp_array[isakmp_nb].str = CFUserNotificationGetResponseValue(userNotification, kCFUserNotificationTextFieldValuesKey, isakmp_nb); 601 isakmp_nb++; 602 } 603 else if (serv->u.ipsec.xauth_flags & XAUTH_NEED_PASSWORD) { 604 isakmp_array[isakmp_nb].type = XAUTH_USER_PASSWORD; 605 isakmp_array[isakmp_nb].str = CFUserNotificationGetResponseValue(userNotification, kCFUserNotificationTextFieldValuesKey, isakmp_nb); 606 isakmp_nb++; 607 } 608 } 609 610 // note: isakmp_nb can be 0. for exmple, sometime the server just pushes a message information, and we just need to acknowledge 611#if TARGET_OS_EMBEDDED 612 if (serv->u.ipsec.timerref) { 613 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_PHASE1); 614 } 615 ipsec_updatephase(serv, IPSEC_PHASE1); 616#else 617 if (serv->u.ipsec.phase == IPSEC_PHASE1AUTH) { 618 if (serv->u.ipsec.timerref) { 619 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_PHASE1); 620 } 621 ipsec_updatephase(serv, IPSEC_PHASE1); 622 } 623#endif /* TARGET_OS_EMBEDDED */ 624 racoon_send_cmd_xauthinfo(serv->u.ipsec.controlfd, serv->u.ipsec.peer_address.sin_addr.s_addr, isakmp_array, isakmp_nb); 625 626} 627 628/* ----------------------------------------------------------------------------- 629 ----------------------------------------------------------------------------- */ 630static boolean_t checkpassword(struct service *serv, int must_prompt) 631{ 632 int pref_must_prompt; 633 Boolean ok; 634 Boolean didrestart = FALSE; 635 Boolean needauthinfo = FALSE; 636 637 pref_must_prompt = (serv->u.ipsec.xauth_flags & XAUTH_MUST_PROMPT) ? 1 : 0; 638 if (must_prompt != pref_must_prompt) { 639 needauthinfo = (serv->u.ipsec.xauth_flags & XAUTH_NEED_XAUTH_INFO) ? TRUE : FALSE; 640 641 if (serv->ne_sm_bridge == NULL) { 642 ok = UpdatePasswordPrefs(serv->serviceID, serv->typeRef, kSCNetworkInterfacePasswordTypeIPSecXAuth, 643 kSCPropNetIPSecXAuthPasswordEncryption, must_prompt ? kSCValNetIPSecXAuthPasswordEncryptionPrompt : NULL, 644 CFSTR("IPSec Controller")); 645 } else { 646 ne_sm_bridge_clear_saved_password(serv->ne_sm_bridge, kSCPropNetIPSecXAuthPassword); 647 ok = TRUE; 648 } 649 650 if (ok) { 651 // update current config 652 if (must_prompt) { 653 serv->u.ipsec.xauth_flags |= XAUTH_MUST_PROMPT; 654 CFDictionarySetValue(serv->u.ipsec.config, kSCPropNetIPSecXAuthPasswordEncryption, kSCValNetIPSecXAuthPasswordEncryptionPrompt); 655 } else { 656 serv->u.ipsec.xauth_flags &= ~XAUTH_MUST_PROMPT; 657 CFDictionaryRemoveValue( serv->u.ipsec.config, kSCPropNetIPSecXAuthPasswordEncryption); 658 } 659 } 660 661 if ( needauthinfo && (serv->u.ipsec.xauth_flags & XAUTH_MUST_PROMPT) 662 && !(serv->u.ipsec.xauth_flags & XAUTH_DID_PROMPT)) { 663 /* policy changed from "ok to save" to "do not save" 664 if the connection was established using a saved password, 665 then disconnect, and reconnect to make sure the user is prompted */ 666 667 racoon_restart(serv, &serv->u.ipsec.peer_address); 668 didrestart = TRUE; 669 } 670 } 671 return didrestart; 672} 673 674/* ----------------------------------------------------------------------------- 675 ----------------------------------------------------------------------------- */ 676static CFStringRef copy_decrypted_password(struct service *serv) 677{ 678#if !TARGET_OS_EMBEDDED 679 SCNetworkInterfaceRef interface = NULL; 680 SCNetworkServiceRef service = NULL; 681 SCPreferencesRef prefs = NULL; 682#endif 683 CFStringRef decryptedpasswd = NULL; 684 CFStringRef passwdencryption = NULL; 685 686 passwdencryption = CFDictionaryGetValue(serv->u.ipsec.config, kSCPropNetIPSecXAuthPasswordEncryption); 687 passwdencryption = isA_CFString(passwdencryption); 688 if (passwdencryption) { 689 if (CFStringCompare(passwdencryption, kSCValNetIPSecXAuthPasswordEncryptionKeychain, 0) == kCFCompareEqualTo) { 690#if TARGET_OS_EMBEDDED 691 // TO DO: 692 // currently, password is given inline in SCNetworkConnectionStart 693 // needs t implement keychain support later 694#else 695 prefs = SCPreferencesCreate(NULL, CFSTR("CopyPassword"), NULL); 696 if (prefs == NULL) { 697 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: SCPreferencesCreate fails")); 698 goto done; 699 } 700 // get the service 701 service = SCNetworkServiceCopy(prefs, serv->serviceID); 702 if (service == NULL) { 703 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: SCNetworkServiceCopy fails")); 704 goto done; 705 } 706 // get the interface associated with the service 707 interface = SCNetworkServiceGetInterface(service); 708 if ((interface == NULL) || !CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypeIPSec)) { 709 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: interface not IPSec")); 710 goto done; 711 } 712 CFDataRef passworddata = SCNetworkInterfaceCopyPassword( interface, kSCNetworkInterfacePasswordTypeIPSecXAuth); 713 if (passworddata) { 714 CFIndex passworddatalen = CFDataGetLength(passworddata); 715 if ((decryptedpasswd = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(passworddata), passworddatalen, kCFStringEncodingUTF8, FALSE))) 716 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: decrypted password %s"), decryptedpasswd ? (CFStringGetCStringPtr(decryptedpasswd,kCFStringEncodingMacRoman)) : "NULL"); 717 else 718 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot decrypt password")); 719 CFRelease(passworddata); 720 } 721#endif 722 } 723 } 724 else { 725 decryptedpasswd = CFDictionaryGetValue(serv->u.ipsec.config, kSCPropNetIPSecXAuthPassword); 726 decryptedpasswd = isA_CFString(decryptedpasswd); 727 if (decryptedpasswd) 728 CFRetain(decryptedpasswd); 729 } 730 731#if !TARGET_OS_EMBEDDED 732done: 733 if (prefs != NULL) { 734 CFRelease(prefs); 735 } 736 if (service != NULL) { 737 CFRelease(service); 738 } 739#endif 740 return (CFStringRef)decryptedpasswd; 741} 742 743/* ----------------------------------------------------------------------------- 744----------------------------------------------------------------------------- */ 745static 746int ask_user_xauth(struct service *serv, char* message) 747{ 748 CFStringRef msg = NULL; 749 CFMutableDictionaryRef dict = NULL; 750 SInt32 err; 751 CFOptionFlags flags; 752 CFMutableArrayRef array; 753 CFIndex secure_field = 0; 754 int ret = 0; 755#if TARGET_OS_EMBEDDED 756 int nbfields = 0; 757#endif 758 759 if ((serv->flags & FLAG_ALERTPASSWORDS) == 0) 760 return -1; 761 762#if !TARGET_OS_EMBEDDED 763 if (serv->flags & FLAG_DARKWAKE) 764 return -1; 765#endif 766 767 /* first, remove any pending notification, if any */ 768 if (serv->userNotificationRef) { 769 CFUserNotificationCancel(serv->userNotificationRef); 770 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), serv->userNotificationRLS, kCFRunLoopDefaultMode); 771 my_CFRelease(&serv->userNotificationRef); 772 my_CFRelease(&serv->userNotificationRLS); 773 } 774 775 if (message) 776 msg = CFStringCreateWithFormat(0, 0, CFSTR("%s"), message); 777 else 778 msg = CFStringCreateWithFormat(0, 0, CFSTR("Enter your user authentication")); 779 780 if (!msg && !CFStringGetLength(msg)) 781 goto fail; 782 783 dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 784 if (!dict) 785 goto fail; 786 787 if (gIconURLRef) 788 CFDictionaryAddValue(dict, kCFUserNotificationIconURLKey, gIconURLRef); 789 if (gBundleURLRef) 790 CFDictionaryAddValue(dict, kCFUserNotificationLocalizationURLKey, gBundleURLRef); 791 792 CFDictionaryAddValue(dict, kCFUserNotificationAlertMessageKey, msg); 793 CFDictionaryAddValue(dict, kCFUserNotificationAlertHeaderKey, CFSTR("VPN Connection")); 794 CFDictionaryAddValue(dict, kCFUserNotificationAlternateButtonTitleKey, CFSTR("Cancel")); 795 796 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 797 if (array) { 798 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_ANSWER) { 799 CFArrayAppendValue(array, CFSTR("Answer")); 800 } 801 else if (serv->u.ipsec.xauth_flags & XAUTH_NEED_NEXT_PIN) { 802 CFArrayAppendValue(array, CFSTR("Next PIN")); 803 secure_field = 1; 804 } 805 else { 806 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_USERNAME) { 807 CFArrayAppendValue(array, CFSTR("Account")); 808 } 809 810 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_PASSCODE) { 811 CFArrayAppendValue(array, CFSTR("Passcode")); 812 secure_field = (serv->u.ipsec.xauth_flags & XAUTH_NEED_USERNAME) ? 2 : 1; 813 } 814 else if (serv->u.ipsec.xauth_flags & XAUTH_NEED_PASSWORD) { 815 CFArrayAppendValue(array, CFSTR("Password")); 816 secure_field = (serv->u.ipsec.xauth_flags & XAUTH_NEED_USERNAME) ? 2 : 1; 817 } 818 } 819 820#if TARGET_OS_EMBEDDED 821 nbfields = CFArrayGetCount(array); 822#endif 823 CFDictionaryAddValue(dict, kCFUserNotificationTextFieldTitlesKey, array); 824 CFRelease(array); 825 } 826 827 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_USERNAME) { 828 CFStringRef username = CFDictionaryGetValue(serv->u.ipsec.config, kRASPropIPSecXAuthName); 829 if (isString(username)) { 830 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 831 if (array) { 832 CFArrayAppendValue(array, username); 833 834 // for some reason, CFUsernotification wants to have both values present in the array, in order to display the first one. 835 if (serv->u.ipsec.xauth_flags & (XAUTH_NEED_PASSWORD | XAUTH_NEED_PASSCODE)) { 836 CFArrayAppendValue(array, CFSTR("")); 837 } 838 839 CFDictionaryAddValue(dict, kCFUserNotificationTextFieldValuesKey, array); 840 CFRelease(array); 841 } 842 } 843 } 844 845#if TARGET_OS_EMBEDDED 846 if (nbfields > 0) { 847 CFMutableArrayRef autoCapsTypes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 848 CFMutableArrayRef autoCorrectionTypes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 849 int i, zero = 0, one = 1; 850 CFNumberRef zeroRef = CFNumberCreate(NULL, kCFNumberIntType, &zero); 851 CFNumberRef oneRef = CFNumberCreate(NULL, kCFNumberIntType, &one); 852 853 if (autoCapsTypes && autoCorrectionTypes && zeroRef && oneRef) { 854 for(i = 0; i < nbfields; i++) { 855 // no auto caps or autocorrection for any of our fields 856 CFArrayAppendValue(autoCapsTypes, zeroRef); 857 CFArrayAppendValue(autoCorrectionTypes, oneRef); 858 } 859 CFDictionarySetValue(dict, SBUserNotificationTextAutocapitalizationType, autoCapsTypes); 860 CFDictionarySetValue(dict, SBUserNotificationTextAutocorrectionType, autoCorrectionTypes); 861 } 862 my_CFRelease(&autoCapsTypes); 863 my_CFRelease(&autoCorrectionTypes); 864 my_CFRelease(&zeroRef); 865 my_CFRelease(&oneRef); 866 867 // make CFUN prettier 868 CFDictionarySetValue(dict, SBUserNotificationGroupsTextFields, kCFBooleanTrue); 869 } 870#endif 871 872 flags = 0; 873 if (secure_field) 874 flags = CFUserNotificationSecureTextField(secure_field - 1); 875 876 serv->userNotificationRef = CFUserNotificationCreate(NULL, 150 /* 2 min 30 sec */, flags, &err, dict); 877 if (!serv->userNotificationRef) 878 goto fail; 879 880 serv->userNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, serv->userNotificationRef, 881 user_notification_callback, 0); 882 if (!serv->userNotificationRLS) { 883 my_CFRelease(&serv->userNotificationRef); 884 goto fail; 885 } 886 CFRunLoopAddSource(CFRunLoopGetCurrent(), serv->userNotificationRLS, kCFRunLoopDefaultMode); 887 888done: 889 my_CFRelease(&dict); 890 my_CFRelease(&msg); 891 return ret; 892 893fail: 894 ret = -1; 895 goto done; 896} 897 898 899/* ----------------------------------------------------------------------------- 900----------------------------------------------------------------------------- */ 901static int process_xauth_need_info(struct service *serv) 902{ 903 char *message = NULL; 904 struct vpnctl_cmd_xauth_info *cmd_xauth_info; 905 906 cmd_xauth_info = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)serv->u.ipsec.msg; 907 908 char *xauth_data = (char*)serv->u.ipsec.msg + sizeof(struct vpnctl_cmd_xauth_info); 909 int xauth_data_len = ntohs(serv->u.ipsec.msghdr.len) - (sizeof(struct vpnctl_cmd_xauth_info) - sizeof(struct vpnctl_hdr)); 910 911 int tlen = xauth_data_len; 912 struct isakmp_data *attr; 913 char *dataptr = xauth_data; 914 915 serv->u.ipsec.xauth_flags &= ~(XAUTH_NEED_USERNAME | XAUTH_NEED_PASSWORD | XAUTH_NEED_PASSCODE | XAUTH_NEED_ANSWER); 916 serv->u.ipsec.xauth_flags |= XAUTH_NEED_XAUTH_INFO; 917 918 while (tlen > 0) 919 { 920 int tlv; 921 u_int16_t type; 922 923 attr = ALIGNED_CAST(struct isakmp_data *)dataptr; 924 type = ntohs(attr->type) & 0x7FFF; 925 tlv = (type == ntohs(attr->type)); 926 927 switch (type) 928 { 929 case XAUTH_TYPE: 930 switch (ntohs(attr->lorv)) { 931 case XAUTH_TYPE_GENERIC: 932 break; 933 default: 934 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Received unsupported Xauth Type (value %d)"), ntohs(attr->lorv)); 935 goto fail; 936 } 937 break; 938 case XAUTH_USER_NAME: 939 serv->u.ipsec.xauth_flags |= XAUTH_NEED_USERNAME; 940 serv->u.ipsec.xauth_flags &= ~(XAUTH_NEED_NEXT_PIN + XAUTH_NEED_ANSWER); 941 break; 942 case XAUTH_USER_PASSWORD: 943 serv->u.ipsec.xauth_flags |= XAUTH_NEED_PASSWORD; 944 serv->u.ipsec.xauth_flags &= ~(XAUTH_NEED_PASSCODE + XAUTH_NEED_NEXT_PIN + XAUTH_NEED_ANSWER); 945 break; 946 case XAUTH_PASSCODE: 947 serv->u.ipsec.xauth_flags |= XAUTH_NEED_PASSCODE; 948 serv->u.ipsec.xauth_flags &= ~(XAUTH_NEED_PASSWORD + XAUTH_NEED_NEXT_PIN + XAUTH_NEED_ANSWER); 949 break; 950 case XAUTH_MESSAGE: 951 if (message) // we've already seen that attribute 952 break; 953 message = malloc(ntohs(attr->lorv) + 1); 954 if (message) { 955 bcopy(dataptr + sizeof(u_int32_t), message, ntohs(attr->lorv)); 956 message[ntohs(attr->lorv)] = 0; 957 } 958 break; 959 case XAUTH_CHALLENGE: 960 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Received unsupported Xauth Challenge")); 961 goto fail; 962 break; 963 case XAUTH_DOMAIN: 964 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Ignoring unsupported Xauth Domain")); 965 break; 966 case XAUTH_STATUS: 967 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Received unsupported Xauth Status")); 968 goto fail; 969 break; 970 case XAUTH_NEXT_PIN: 971 serv->u.ipsec.xauth_flags |= XAUTH_NEED_NEXT_PIN; 972 serv->u.ipsec.xauth_flags &= ~(XAUTH_NEED_USERNAME + XAUTH_NEED_PASSWORD + XAUTH_NEED_PASSCODE + XAUTH_NEED_ANSWER); 973 break; 974 case XAUTH_ANSWER: 975 serv->u.ipsec.xauth_flags |= XAUTH_NEED_ANSWER; 976 serv->u.ipsec.xauth_flags &= ~(XAUTH_NEED_USERNAME + XAUTH_NEED_PASSWORD + XAUTH_NEED_PASSCODE + XAUTH_NEED_NEXT_PIN); 977 break; 978 default: 979 break; 980 } 981 982 983 if (tlv) { 984 tlen -= ntohs(attr->lorv); 985 dataptr += ntohs(attr->lorv); 986 } 987 988 tlen -= sizeof(u_int32_t); 989 dataptr += sizeof(u_int32_t); 990 991 } 992 993 if (serv->u.ipsec.xauth_flags & XAUTH_FIRST_TIME || serv->u.ipsec.phase == IPSEC_RUNNING) { 994 995 serv->u.ipsec.xauth_flags &= ~(XAUTH_FIRST_TIME); 996 997 // first time, use credential info from the prefs if they were available 998 // additional times, assume failure and re-prompt 999 1000 if (!(serv->u.ipsec.xauth_flags & XAUTH_MUST_PROMPT)) { 1001 1002 CFStringRef username = NULL; 1003 CFStringRef password = NULL; 1004 int has_info = 0; 1005 1006 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_USERNAME) { 1007 username = CFDictionaryGetValue(serv->u.ipsec.config, kRASPropIPSecXAuthName); 1008 has_info = isString(username) && CFStringGetLength(username); 1009 } 1010 1011 if (has_info || !(serv->u.ipsec.xauth_flags & XAUTH_NEED_USERNAME)) { 1012 if (serv->u.ipsec.xauth_flags & (XAUTH_NEED_PASSWORD | XAUTH_NEED_PASSCODE)) { 1013 if (serv->ne_sm_bridge == NULL) { 1014 password = copy_decrypted_password(serv); 1015 } else { 1016 password = ne_sm_bridge_copy_password_from_keychain(serv->ne_sm_bridge, kSCPropNetIPSecXAuthPassword); 1017 } 1018 has_info = isString(password) && CFStringGetLength(password); 1019 } 1020 } 1021 1022 if (has_info) { 1023 1024 struct isakmp_xauth isakmp_array[2]; /* max 2 attributes currently supported simultaneously */ 1025 int isakmp_nb = 0; 1026 1027 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_USERNAME) { 1028 isakmp_array[isakmp_nb].type = XAUTH_USER_NAME; 1029 isakmp_array[isakmp_nb].str = username; 1030 isakmp_nb++; 1031 } 1032 1033 if (serv->u.ipsec.xauth_flags & XAUTH_NEED_PASSCODE) { 1034 isakmp_array[isakmp_nb].type = XAUTH_PASSCODE; 1035 isakmp_array[isakmp_nb].str = password; 1036 isakmp_nb++; 1037 } 1038 else if (serv->u.ipsec.xauth_flags & XAUTH_NEED_PASSWORD) { 1039 isakmp_array[isakmp_nb].type = XAUTH_USER_PASSWORD; 1040 isakmp_array[isakmp_nb].str = password; 1041 isakmp_nb++; 1042 } 1043 1044#if TARGET_OS_EMBEDDED 1045 if (serv->u.ipsec.timerref) { 1046 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_PHASE1); 1047 } 1048 ipsec_updatephase(serv, IPSEC_PHASE1); 1049#else 1050 if (serv->u.ipsec.phase == IPSEC_PHASE1AUTH) { 1051 if (serv->u.ipsec.timerref) { 1052 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_PHASE1); 1053 } 1054 ipsec_updatephase(serv, IPSEC_PHASE1); 1055 } 1056#endif /* TARGET_OS_EMBEDDED */ 1057 racoon_send_cmd_xauthinfo(serv->u.ipsec.controlfd, serv->u.ipsec.peer_address.sin_addr.s_addr, isakmp_array, isakmp_nb); 1058 if (password) 1059 CFRelease(password); 1060 goto done; 1061 } 1062 1063 if (password) 1064 CFRelease(password); 1065 } 1066 } 1067 1068 if (ask_user_xauth(serv, message)) 1069 goto fail; 1070 1071 serv->u.ipsec.xauth_flags |= XAUTH_DID_PROMPT; 1072 1073done: 1074 if (message) 1075 free(message); 1076 return 0; 1077 1078fail: 1079 serv->u.ipsec.xauth_flags = 0; 1080 if (message) 1081 free(message); 1082 return 1; 1083} 1084 1085/* ----------------------------------------------------------------------------- 1086----------------------------------------------------------------------------- */ 1087static void print_racoon_msg(struct service *serv) 1088{ 1089 struct vpnctl_status_phase_change *phase_change_status; 1090 struct vpnctl_status_failed *failed_status; 1091 struct vpnctl_cmd_xauth_info *cmd_xauth_info; 1092 struct vpnctl_cmd_bind *cmd_bind; 1093 struct vpnctl_status_peer_resp *peer_resp; 1094 struct in_addr addr; 1095 1096#if 0 1097 char *rawdata = serv->u.ipsec.msg; 1098 int i; 1099 1100 printf("Header = 0x"); 1101 for (i= 0; i < sizeof(struct vpnctl_hdr); i++) { 1102 printf("%02X ", rawdata[i]); 1103 } 1104 printf("\nData = 0x"); 1105 for (i= 0; i < ntohs(serv->u.ipsec.msghdr.len); i++) { 1106 printf("%02X ", rawdata[i + sizeof(struct vpnctl_hdr)]); 1107 } 1108 printf("\n"); 1109#endif 1110 1111 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ====================================================")); 1112 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: Process Message:")); 1113 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: msg_type = 0x%x (%s)"), ntohs(serv->u.ipsec.msghdr.msg_type), ipsec_msgtype_to_str(ntohs(serv->u.ipsec.msghdr.msg_type))); 1114 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: flags = 0x%x %s"), ntohs(serv->u.ipsec.msghdr.flags), (ntohs(serv->u.ipsec.msghdr.flags) & VPNCTL_FLAG_MODECFG_USED) ? "MODE CONFIG USED" : ""); 1115 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: cookie = 0x%x"), ntohl(serv->u.ipsec.msghdr.cookie)); 1116 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: reserved = 0x%x"), ntohl(serv->u.ipsec.msghdr.reserved)); 1117 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: result = 0x%x"), ntohs(serv->u.ipsec.msghdr.result)); 1118 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: len = %d"), ntohs(serv->u.ipsec.msghdr.len)); 1119 1120 1121 switch (ntohs(serv->u.ipsec.msghdr.msg_type)) { 1122 // BIND/UNBIND/CONNECT share the same structure 1123 case VPNCTL_CMD_BIND: 1124 case VPNCTL_CMD_UNBIND: 1125 case VPNCTL_CMD_CONNECT: 1126 case VPNCTL_CMD_RECONNECT: 1127 case VPNCTL_CMD_DISCONNECT: 1128 cmd_bind = ALIGNED_CAST(struct vpnctl_cmd_bind *)serv->u.ipsec.msg; 1129 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ----------------------------")); 1130 addr.s_addr = cmd_bind->address; 1131 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: address = %s"), inet_ntoa(addr)); 1132 break; 1133 1134 case VPNCTL_CMD_XAUTH_INFO: 1135 cmd_xauth_info = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)serv->u.ipsec.msg; 1136 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ----------------------------")); 1137 addr.s_addr = cmd_xauth_info->address; 1138 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: address = %s"), inet_ntoa(addr)); 1139 break; 1140 1141 case VPNCTL_STATUS_IKE_FAILED: 1142 failed_status = ALIGNED_CAST(struct vpnctl_status_failed *)serv->u.ipsec.msg; 1143 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ----------------------------")); 1144 addr.s_addr = failed_status->address; 1145 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: address = %s"), inet_ntoa(addr)); 1146 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ike_code = %d 0x%x (%s)"), ntohs(failed_status->ike_code), ntohs(failed_status->ike_code), ipsec_error_to_str(ntohs(failed_status->ike_code))); 1147 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: from = %d"), ntohs(failed_status->from)); 1148 1149 switch (ntohs(failed_status->ike_code)) { 1150 case VPNCTL_NTYPE_LOAD_BALANCE: 1151 addr.s_addr = *ALIGNED_CAST(u_int32_t*)failed_status->data; 1152 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: redirect address = %s"), inet_ntoa(addr)); 1153 break; 1154 } 1155 1156 break; 1157 1158 case VPNCTL_STATUS_PH1_START_US: 1159 break; 1160 1161 case VPNCTL_STATUS_PH1_START_PEER: 1162 break; 1163 1164 case VPNCTL_STATUS_PH1_ESTABLISHED: 1165 phase_change_status = ALIGNED_CAST(struct vpnctl_status_phase_change *)serv->u.ipsec.msg; 1166 addr.s_addr = phase_change_status->address; 1167 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: address = %s"), inet_ntoa(addr)); 1168 if (ntohs(phase_change_status->hdr.flags) & VPNCTL_FLAG_MODECFG_USED) { 1169 char *modecfg_data = (char*)serv->u.ipsec.msg + sizeof(struct vpnctl_status_phase_change) + sizeof(struct vpnctl_modecfg_params); 1170 int modecfg_data_len = ntohs(serv->u.ipsec.msghdr.len) - ((sizeof(struct vpnctl_status_phase_change) + sizeof(struct vpnctl_modecfg_params)) - sizeof(struct vpnctl_hdr)); 1171 struct vpnctl_modecfg_params *modecfg = ALIGNED_CAST(struct vpnctl_modecfg_params *)(void*)(serv->u.ipsec.msg + sizeof(struct vpnctl_status_phase_change)); 1172 addr.s_addr = modecfg->outer_local_addr; 1173 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: outer_local_addr = %s"), inet_ntoa(addr)); 1174 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: outer_remote_port = %d"), ntohs(modecfg->outer_remote_port)); 1175 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: outer_local_port = %d"), ntohs(modecfg->outer_local_port)); 1176 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ifname = %s"), modecfg->ifname); 1177 1178 int tlen = modecfg_data_len; 1179 char *dataptr = modecfg_data; 1180 1181 while (tlen > 0) 1182 { 1183 int tlv; 1184 u_int16_t type; 1185 struct isakmp_data attr; 1186 1187 memcpy(&attr, dataptr, sizeof(attr)); // Wcast-align fix - memcpy for unaligned access 1188 type = ntohs(attr.type) & 0x7FFF; 1189 tlv = (type == ntohs(attr.type)); 1190 1191 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ModeConfig Attribute Type = %d (%s)"), type, ipsec_modecfgtype_to_str(type)); 1192 if (tlv) { 1193 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ModeConfig Attribute Length = %d Value = ..."), ntohs(attr.lorv)); 1194 1195 tlen -= ntohs(attr.lorv); 1196 dataptr += ntohs(attr.lorv); 1197 } 1198 else { 1199 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ModeConfig Attribute Value = %d"), ntohs(attr.lorv)); 1200 } 1201 1202 tlen -= sizeof(u_int32_t); 1203 dataptr += sizeof(u_int32_t); 1204 1205 } 1206 } 1207 break; 1208 1209 case VPNCTL_STATUS_PH2_START: 1210 break; 1211 1212 case VPNCTL_STATUS_PH2_ESTABLISHED: 1213 break; 1214 1215 case VPNCTL_STATUS_NEED_AUTHINFO: 1216#if !TARGET_OS_EMBEDDED 1217 case VPNCTL_STATUS_NEED_REAUTHINFO: 1218#endif /* !TARGET_OS_EMBEDDED */ 1219 cmd_xauth_info = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)serv->u.ipsec.msg; 1220 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ----------------------------")); 1221 addr.s_addr = cmd_xauth_info->address; 1222 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: address = %s"), inet_ntoa(addr)); 1223 1224 char *xauth_data = (char*)serv->u.ipsec.msg + sizeof(struct vpnctl_cmd_xauth_info); 1225 int xauth_data_len = ntohs(serv->u.ipsec.msghdr.len) - (sizeof(struct vpnctl_cmd_xauth_info) - sizeof(struct vpnctl_hdr)); 1226 1227 int tlen = xauth_data_len; 1228 char *dataptr = xauth_data; 1229 1230 while (tlen > 0) 1231 { 1232 int tlv; 1233 u_int16_t type; 1234 struct isakmp_data attr; 1235 1236 memcpy(&attr, dataptr, sizeof(attr)); // Wcast-align fix - memcpy for unaligned access 1237 type = ntohs(attr.type) & 0x7FFF; 1238 tlv = (type == ntohs(attr.type)); 1239 1240 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: XAuth Attribute Type = %d (%s)"), type, ipsec_xauthtype_to_str(type)); 1241 if (tlv) { 1242 if (type == XAUTH_MESSAGE) { 1243 char *message = malloc(ntohs(attr.lorv) + 1); 1244 if (message) { 1245 bcopy(dataptr + sizeof(u_int32_t), message, ntohs(attr.lorv)); 1246 message[ntohs(attr.lorv)] = 0; 1247 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: XAuth Attribute Value = %s"), message); 1248 free(message); 1249 } 1250 } 1251 else 1252 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: XAuth Attribute Length = %d Value = ..."), ntohs(attr.lorv)); 1253 1254 tlen -= ntohs(attr.lorv); 1255 dataptr += ntohs(attr.lorv); 1256 } 1257 else { 1258 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: XAuth Attribute Value = %d"), ntohs(attr.lorv)); 1259 } 1260 1261 tlen -= sizeof(u_int32_t); 1262 dataptr += sizeof(u_int32_t); 1263 1264 } 1265 break; 1266 1267 case VPNCTL_STATUS_PEER_RESP: 1268 peer_resp = ALIGNED_CAST(__typeof__(peer_resp))serv->u.ipsec.msg; 1269 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ----------------------------")); 1270 addr.s_addr = peer_resp->address; 1271 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: response from address = %s"), inet_ntoa(addr)); 1272 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ike_code = %d"), ntohs(peer_resp->ike_code)); 1273 break; 1274 1275 default: 1276 /* ignore other messages */ 1277 break; 1278 } 1279 1280 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ====================================================")); 1281 1282} 1283 1284/* ----------------------------------------------------------------------------- 1285----------------------------------------------------------------------------- */ 1286static void process_racoon_msg(struct service *serv) 1287{ 1288 struct vpnctl_status_phase_change *phase_change_status; 1289 struct vpnctl_status_failed *failed_status; 1290 struct vpnctl_status_peer_resp *peer_resp; 1291 struct sockaddr_in redirect_addr; 1292 struct in_addr peer_addr; 1293 1294 1295 if (gSCNCVerbose) 1296 print_racoon_msg(serv); 1297 1298 switch (ntohs(serv->u.ipsec.msghdr.msg_type)) { 1299 case VPNCTL_STATUS_IKE_FAILED: 1300 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: IKE FAILED. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1301 failed_status = ALIGNED_CAST(struct vpnctl_status_failed *)serv->u.ipsec.msg; 1302 1303 switch (ntohs(failed_status->ike_code)) { 1304 1305 case VPNCTL_NTYPE_LOAD_BALANCE: 1306 bzero(&redirect_addr, sizeof(redirect_addr)); 1307 redirect_addr.sin_len = sizeof(redirect_addr); 1308 redirect_addr.sin_family = AF_INET; 1309 redirect_addr.sin_port = htons(0); 1310 redirect_addr.sin_addr.s_addr = *ALIGNED_CAST(u_int32_t*)failed_status->data; 1311 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: connection redirected to server '%s'..."), inet_ntoa(redirect_addr.sin_addr)); 1312 racoon_restart(serv, &redirect_addr); 1313 break; 1314 1315 default: 1316 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: connection failed <IKE Error %d (0x%x) %s>"), ntohs(failed_status->ike_code), ntohs(failed_status->ike_code), ipsec_error_to_str(ntohs(failed_status->ike_code))); 1317 serv->u.ipsec.laststatus = ipsec_error_to_status(serv, ntohs(failed_status->from), ntohs(failed_status->ike_code)); 1318 1319 /* after phase 2, an authenticaion error is because the peer is disconnecting us */ 1320 if ((serv->u.ipsec.laststatus == IPSEC_XAUTH_ERROR) && (serv->u.ipsec.phase >= IPSEC_PHASE2)) 1321 serv->u.ipsec.laststatus = IPSEC_PEERDISCONNECT_ERROR; 1322 ipsec_stop(serv, 0); 1323 break; 1324 } 1325 1326 break; 1327 1328 case VPNCTL_STATUS_PH1_START_US: 1329 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: PH1 STARTUS. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1330 if (serv->u.ipsec.phase == IPSEC_INITIALIZE) { 1331 ipsec_updatephase(serv, IPSEC_CONTACT); 1332 } else if (IPSEC_IS_ASSERTED_IDLE(serv->u.ipsec) || 1333 IPSEC_IS_ASSERTED_INITIALIZE(serv->u.ipsec)) { 1334 if (IPSEC_IS_ASSERTED_IDLE(serv->u.ipsec) && serv->u.ipsec.timerref) { 1335 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_INITIAL_CONTACT); 1336 } 1337 IPSEC_ASSERT_CONTACT(serv->u.ipsec); 1338 } 1339 break; 1340 1341 case VPNCTL_STATUS_PH1_START_PEER: 1342 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: PH1 STARTPEER. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1343 if (serv->u.ipsec.phase != IPSEC_CONTACT && !IPSEC_IS_ASSERTED_CONTACT(serv->u.ipsec)) 1344 break; 1345 if (serv->u.ipsec.timerref) { 1346 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_PHASE1); 1347 } 1348 if (serv->u.ipsec.phase == IPSEC_CONTACT) { 1349 ipsec_updatephase(serv, IPSEC_PHASE1); 1350 } else if (IPSEC_IS_ASSERTED_CONTACT(serv->u.ipsec)) { 1351 IPSEC_ASSERT_PHASE1(serv->u.ipsec); 1352 } 1353 break; 1354 1355 case VPNCTL_STATUS_NEED_AUTHINFO: 1356 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: AUTHINFO. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1357 if (serv->u.ipsec.phase != IPSEC_PHASE1 && !IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) 1358 break; 1359 if (serv->u.ipsec.phase == IPSEC_PHASE1) { 1360 ipsec_updatephase(serv, IPSEC_PHASE1AUTH); 1361 } else if (IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) { 1362 // disconnect if we have to prompt user 1363 if (serv->u.ipsec.xauth_flags & XAUTH_MUST_PROMPT) { 1364 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: session asserting but XAuth dialog required, so connection aborted")); 1365 ipsec_stop(serv, 0); 1366 break; 1367 } 1368 } 1369 if (serv->u.ipsec.timerref) { 1370 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, FAR_FUTURE); 1371 } 1372 IPSECLOGASLMSG("IPSec requesting Extended Authentication.\n"); 1373 1374 if (process_xauth_need_info(serv)) { 1375 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: XAuth authentication failed")); 1376 ipsec_stop(serv, 0); 1377 } 1378 break; 1379 1380 case VPNCTL_STATUS_PH1_ESTABLISHED: 1381 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: PH1 ESTABLISHED. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1382 if (serv->u.ipsec.phase != IPSEC_PHASE1 && !IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) 1383 break; 1384 if (serv->u.ipsec.phase == IPSEC_PHASE1) { 1385 phase_change_status = ALIGNED_CAST(struct vpnctl_status_phase_change *)serv->u.ipsec.msg; 1386 bool requestedInstall = false; 1387 if (serv->ne_sm_bridge != NULL) { 1388 if (serv->u.ipsec.modecfg_msg != NULL) { 1389 my_Deallocate(serv->u.ipsec.modecfg_msg, serv->u.ipsec.modecfg_msglen); 1390 serv->u.ipsec.modecfg_msg = NULL; 1391 } 1392 serv->u.ipsec.modecfg_msglen = serv->u.ipsec.msgtotallen + 1; 1393 serv->u.ipsec.modecfg_msg = my_Allocate(serv->u.ipsec.modecfg_msglen); 1394 memcpy(serv->u.ipsec.modecfg_msg, serv->u.ipsec.msg, serv->u.ipsec.modecfg_msglen); 1395 requestedInstall = ne_sm_bridge_request_install(serv->ne_sm_bridge, mode_config_is_default(serv)); 1396 install_mode_config(serv, FALSE, TRUE); 1397 } 1398 if (!requestedInstall) { 1399 if (ntohs(phase_change_status->hdr.flags) & VPNCTL_FLAG_MODECFG_USED) { 1400 install_mode_config(serv, TRUE, TRUE); 1401 } 1402 } 1403 serv->u.ipsec.ping_count = MAX_PHASE2_PING; 1404 if (serv->u.ipsec.timerref) { 1405 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_PHASE2_PING); 1406 } 1407 serv->connecttime = mach_absolute_time() * gTimeScaleSeconds; 1408 serv->connectionslepttime = 0; 1409 } else if (IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) { 1410 if (unassert_mode_config(serv)) { 1411 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: unassert failed")); 1412 ipsec_stop(serv, 0); 1413 break; 1414 } 1415 } 1416 IPSECLOGASLMSG("IPSec Phase1 established.\n"); 1417 break; 1418 1419 case VPNCTL_STATUS_PH2_START: 1420 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: PH2 START. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1421 if (serv->u.ipsec.phase != IPSEC_PHASE1 && !IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) 1422 break; 1423 if (serv->u.ipsec.phase == IPSEC_PHASE1) { 1424 if (serv->u.ipsec.timerref) { 1425 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_PHASE2); 1426 } 1427 ipsec_updatephase(serv, IPSEC_PHASE2); 1428 } else if (IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) { 1429 IPSEC_ASSERT_PHASE2(serv->u.ipsec); 1430 } 1431 break; 1432 1433 case VPNCTL_STATUS_PH2_ESTABLISHED: 1434 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: PH2 ESTABLISHED. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1435 if (serv->u.ipsec.phase != IPSEC_PHASE2 && !IPSEC_IS_ASSERTED_PHASE2(serv->u.ipsec)) 1436 break; 1437 if (serv->u.ipsec.timerref) { 1438 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.timerref, kCFRunLoopCommonModes); 1439 } 1440 my_CFRelease(&serv->u.ipsec.timerref); 1441 if (serv->u.ipsec.phase == IPSEC_PHASE2) { 1442 if (serv->u.ipsec.banner && !(serv->flags & FLAG_ONDEMAND)) { 1443 display_notification(serv, serv->u.ipsec.banner, 0, dialog_has_disconnect_type); 1444 my_CFRelease(&serv->u.ipsec.banner); 1445 } 1446 SESSIONTRACERESTABLISHED(serv); 1447 } else if (IPSEC_IS_ASSERTED_PHASE2(serv->u.ipsec)) { 1448 IPSEC_UNASSERT(serv->u.ipsec); 1449 } 1450 ipsec_updatephase(serv, IPSEC_RUNNING); 1451 serv->was_running = 1; 1452 IPSECLOGASLMSG("IPSec Phase2 established.\n"); 1453 break; 1454 1455#if !TARGET_OS_EMBEDDED 1456 case VPNCTL_STATUS_NEED_REAUTHINFO: 1457 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: REAUTHINFO. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1458 if (serv->u.ipsec.phase != IPSEC_RUNNING && !IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) 1459 break; 1460 1461 IPSECLOGASLMSG("IPSec requesting Extended Authentication.\n"); 1462 1463 // disconnect if we have to prompt user 1464 if (serv->u.ipsec.xauth_flags & XAUTH_MUST_PROMPT) { 1465 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: XAuth reauthentication dialog required, so connection aborted")); 1466 ipsec_stop(serv, 0); 1467 } else if (process_xauth_need_info(serv)) { 1468 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: XAuth reauthentication failed")); 1469 ipsec_stop(serv, 0); 1470 } 1471 break; 1472#endif /* !TARGET_OS_EMBEDDED */ 1473 1474 case VPNCTL_STATUS_PEER_RESP: 1475 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: PEER RESP. phase %d, assert %d"), serv->u.ipsec.phase, serv->u.ipsec.asserted); 1476 peer_resp = ALIGNED_CAST(__typeof__(peer_resp))serv->u.ipsec.msg; 1477 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ----------------------------")); 1478 peer_addr.s_addr = peer_resp->address; 1479 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: response from address = %s"), inet_ntoa(peer_addr)); 1480 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ike_code = %d"), ntohs(peer_resp->ike_code)); 1481 if (!serv->u.ipsec.awaiting_peer_resp) { 1482 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: unsolicited peer response notification")); 1483 } 1484 serv->u.ipsec.awaiting_peer_resp = 0; 1485 break; 1486 1487 default: 1488 /* ignore other messages */ 1489 break; 1490 } 1491} 1492 1493int ipsec_install(struct service *serv) 1494{ 1495 install_mode_config(serv, TRUE, FALSE); 1496 return 0; 1497} 1498 1499int ipsec_uninstall(struct service *serv) 1500{ 1501 uninstall_mode_config(serv, FALSE); 1502 return 0; 1503} 1504 1505 1506/* ---------------------------------------------------------------------------- 1507 ----------------------------------------------------------------------------- */ 1508int ipsec_ondemand_add_service_data(struct service *serv, CFMutableDictionaryRef ondemand_dict) 1509{ 1510 CFArrayRef array; 1511 CFStringRef string; 1512 1513 array = CFDictionaryGetValue(serv->systemprefs, kSCPropNetIPSecOnDemandMatchDomainsAlways); 1514 if (isArray(array)) 1515 CFDictionarySetValue(ondemand_dict, kSCNetworkConnectionOnDemandMatchDomainsAlways, array); 1516 array = CFDictionaryGetValue(serv->systemprefs, kSCPropNetIPSecOnDemandMatchDomainsOnRetry); 1517 if (isArray(array)) 1518 CFDictionarySetValue(ondemand_dict, kSCNetworkConnectionOnDemandMatchDomainsOnRetry, array); 1519 array = CFDictionaryGetValue(serv->systemprefs, kSCPropNetIPSecOnDemandMatchDomainsNever); 1520 if (isArray(array)) 1521 CFDictionarySetValue(ondemand_dict, kSCNetworkConnectionOnDemandMatchDomainsNever, array); 1522 1523 string = CFDictionaryGetValue(serv->systemprefs, kRASPropIPSecRemoteAddress); 1524 if (isString(string)) 1525 CFDictionarySetValue(ondemand_dict, kSCNetworkConnectionOnDemandRemoteAddress, string); 1526 1527 return 0; 1528} 1529/* ----------------------------------------------------------------------------- 1530----------------------------------------------------------------------------- */ 1531static int 1532racoon_trigger_phase2(char *ifname, struct in_addr *ping) 1533{ 1534 struct icmp *icp; 1535 int cc, i, j, nbping; 1536 struct sockaddr_in whereto; /* who to ping */ 1537 uint8_t data[256] __attribute__ ((aligned (4))); 1538 int s, ifindex; 1539 1540 s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 1541 if (s < 0) 1542 return -1; 1543 1544 ifindex = if_nametoindex(ifname); 1545 setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex)); 1546 1547 whereto.sin_family = AF_INET; /* Internet address family */ 1548 whereto.sin_port = 0; /* Source port */ 1549 whereto.sin_addr.s_addr = ping->s_addr; /* Dest. address */ 1550 1551 icp = ALIGNED_CAST(struct icmp *)data; 1552 icp->icmp_type = ICMP_ECHO; 1553 icp->icmp_code = 0; 1554 icp->icmp_cksum = 0; 1555 icp->icmp_seq = htons(0); 1556 icp->icmp_id = 0; /* ID */ 1557 1558 cc = ICMP_MINLEN; 1559 1560 size_t len = sizeof(int); 1561 if (sysctlbyname("net.key.blockacq_count", &nbping, &len, 0, 0)) 1562 nbping = 10; 1563 1564 for (j = 0; j <= nbping; j++) { 1565 i = sendto(s, data, cc, 0, (struct sockaddr *)&whereto, sizeof(whereto)); 1566 if (i < cc) { 1567 close(s); 1568 return -1; 1569 } 1570 } 1571 close(s); 1572 return 0; 1573} 1574 1575static Boolean add_ipv4_route (CFMutableArrayRef routesArray, uint32_t address, uint32_t netmask, uint32_t gateway, Boolean isExcludedRoute, char * delegateInterfaceName) 1576{ 1577 CFStringRef string = NULL; 1578 struct in_addr addr; 1579 1580 if (!isA_CFArray(routesArray)) 1581 { 1582 return FALSE; 1583 } 1584 1585 CFMutableDictionaryRef newRouteDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1586 if (!isA_CFDictionary(newRouteDictionary)) 1587 { 1588 return FALSE; 1589 } 1590 1591 addr.s_addr = address; 1592 if ((string = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 1593 CFDictionarySetValue(newRouteDictionary, kSCPropNetIPv4RouteDestinationAddress, string); 1594 my_CFRelease(&string); 1595 } 1596 1597 if (netmask) { 1598 addr.s_addr = netmask; 1599 if ((string = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 1600 CFDictionarySetValue(newRouteDictionary, kSCPropNetIPv4RouteSubnetMask, string); 1601 my_CFRelease(&string); 1602 } 1603 } 1604 1605 if (gateway) { 1606 addr.s_addr = gateway; 1607 if ((string = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 1608 CFDictionarySetValue(newRouteDictionary, kSCPropNetIPv4RouteGatewayAddress, string); 1609 my_CFRelease(&string); 1610 } 1611 } 1612 1613 if (isExcludedRoute && delegateInterfaceName) { 1614 if ((string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), delegateInterfaceName))) { 1615 CFDictionarySetValue(newRouteDictionary, kSCPropNetIPv4RouteInterfaceName, string); 1616 CFRelease(string); 1617 } 1618 } 1619 1620 CFArrayAppendValue(routesArray, newRouteDictionary); 1621 my_CFRelease(&newRouteDictionary); 1622 1623 return TRUE; 1624} 1625 1626 1627static CFArrayRef create_ipv4_route_array(struct service *serv, CFDictionaryRef ipsec_dict, struct in_addr gateway) 1628{ 1629 CFMutableArrayRef routesArray = NULL; 1630 int i, nb; 1631 CFArrayRef policies = NULL; 1632 struct sockaddr_in remote_net; 1633 char str[32]; 1634 u_int32_t remote_prefix; 1635 1636 routesArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 1637 1638 policies = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecPolicies); 1639 if (!isA_CFArray(policies) || (nb = CFArrayGetCount(policies)) == 0) { 1640 goto done; 1641 } 1642 1643 for (i = 0; i < nb; i++) { 1644 CFDictionaryRef policy; 1645 CFStringRef policymode, policydirection, policylevel; 1646 1647 policy = CFArrayGetValueAtIndex(policies, i); 1648 if (!isDictionary(policy)) { 1649 continue; 1650 } 1651 1652 /* build policies in and out */ 1653 1654 policymode = CFDictionaryGetValue(policy, kRASPropIPSecPolicyMode); 1655 if (!isA_CFString(policymode) || !CFEqual(policymode, kRASValIPSecPolicyModeTunnel)) { 1656 continue; 1657 } 1658 1659 /* if policy direction is not specified, in/out is assumed */ 1660 policydirection = CFDictionaryGetValue(policy, kRASPropIPSecPolicyDirection); 1661 if (!isA_CFString(policydirection) || (!CFEqual(policydirection, kRASValIPSecPolicyDirectionOut) && !CFEqual(policydirection, kRASValIPSecPolicyDirectionInOut))) { 1662 continue; 1663 } 1664 1665 policylevel = CFDictionaryGetValue(policy, kRASPropIPSecPolicyLevel); 1666 if (!isA_CFString(policylevel) || CFEqual(policylevel, kRASValIPSecPolicyLevelNone)) { 1667 continue; // no need for routes for 'none' policies 1668 } 1669 1670 if (!CFEqual(policylevel, kRASValIPSecPolicyLevelRequire) && !CFEqual(policylevel, kRASValIPSecPolicyLevelDiscard) && !CFEqual(policylevel, kRASValIPSecPolicyLevelUnique)) { 1671 continue; 1672 } 1673 1674 /* get remote network */ 1675 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyRemoteAddress, str, sizeof(str))) { 1676 continue; 1677 } 1678 remote_net.sin_len = sizeof(remote_net); 1679 remote_net.sin_family = AF_INET; 1680 remote_net.sin_port = htons(0); 1681 if (!inet_aton(str, &remote_net.sin_addr)) { 1682 continue; 1683 } 1684 1685 uint32_t mask = 0; 1686 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePrefix, &remote_prefix, 24); 1687 for (mask = 0; remote_prefix; remote_prefix--) { 1688 mask = (mask >> 1) | 0x80000000; 1689 } 1690 mask = htonl(mask); 1691 1692 add_ipv4_route(routesArray, remote_net.sin_addr.s_addr, mask, gateway.s_addr, FALSE, NULL); 1693 } 1694 1695done: 1696 return routesArray; 1697} 1698 1699/* ----------------------------------------------------------------------------- 1700----------------------------------------------------------------------------- */ 1701static void uninstall_mode_config(struct service *serv, Boolean uninstallPolicies) 1702{ 1703 CFMutableArrayRef dicts_to_remove; 1704 int error = 0; 1705 char *errorstr; 1706 1707 if (serv->u.ipsec.modecfg_installed) { 1708 dicts_to_remove = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1709 CFArrayAppendValue(dicts_to_remove, kSCEntNetIPv4); 1710 if (serv->u.ipsec.dummy_ipv6_installed) { 1711 CFArrayAppendValue(dicts_to_remove, kSCEntNetIPv6); 1712 serv->u.ipsec.dummy_ipv6_installed = 0; 1713 } 1714 CFArrayAppendValue(dicts_to_remove, kSCEntNetDNS); 1715 /* Unpublish all-at-once */ 1716 unpublish_multiple_dicts(gDynamicStore, serv->serviceID, dicts_to_remove, TRUE); 1717 my_CFRelease(&dicts_to_remove); 1718 1719 if (serv->u.ipsec.modecfg_defaultroute) { 1720 // don't need that since we unplished the whole dictionary 1721 // unpublish_dictentry(gDynamicStore, serv->serviceID, kSCEntNetIPv4, kSCPropNetOverridePrimary); 1722 serv->u.ipsec.modecfg_defaultroute = 0; 1723 } 1724 1725 my_CFRelease(&serv->u.ipsec.banner); 1726 1727 serv->u.ipsec.modecfg_installed = 0; 1728 } 1729 if (serv->u.ipsec.modecfg_policies_installed && uninstallPolicies) { 1730 if (serv->u.ipsec.modecfg_policies) { 1731 error = IPSecRemovePolicies(serv->u.ipsec.modecfg_policies, -1, &errorstr); 1732 if (error) 1733 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Cannot remove mode config policies, error '%s'"), errorstr); 1734 my_CFRelease(&serv->u.ipsec.modecfg_policies); 1735 } 1736 1737 IPSecRemoveSecurityAssociations((struct sockaddr *)&serv->u.ipsec.our_address, (struct sockaddr *)&serv->u.ipsec.peer_address); 1738 1739 clear_ifaddr(serv->if_name, serv->u.ipsec.inner_local_addr, 0xFFFFFFFF); 1740 my_close(serv->u.ipsec.kernctl_sock); 1741 serv->u.ipsec.kernctl_sock = -1; 1742 1743 free_service_routes(serv); 1744 serv->u.ipsec.modecfg_policies_installed = 0; 1745 } 1746} 1747 1748static void format_routes_for_cache (struct service *serv, struct in_addr *included_address_gateway, int isdefault) 1749{ 1750 CFMutableDataRef includedRouteAddressData = CFDataCreateMutable(kCFAllocatorDefault, 0); 1751 CFMutableDataRef includedRouteMaskData = CFDataCreateMutable(kCFAllocatorDefault, 0); 1752 CFMutableDataRef excludedRouteAddressData = CFDataCreateMutable(kCFAllocatorDefault, 0); 1753 CFMutableDataRef excludedRouteMaskData = CFDataCreateMutable(kCFAllocatorDefault, 0); 1754 service_route_t *route = NULL; 1755 1756 if (includedRouteAddressData == NULL || 1757 includedRouteMaskData == NULL || 1758 excludedRouteAddressData == NULL || 1759 excludedRouteMaskData == NULL) { 1760 goto done; 1761 } 1762 1763 for (route = serv->u.ipsec.routes; route != NULL; route = route->next) { 1764 if (route->gtwy_address.s_addr == included_address_gateway->s_addr) { 1765 CFDataAppendBytes(includedRouteAddressData, (uint8_t*)&route->dest_address, sizeof(struct in_addr)); 1766 CFDataAppendBytes(includedRouteMaskData, (uint8_t*)&route->dest_mask, sizeof(struct in_addr)); 1767 } else { 1768 CFDataAppendBytes(excludedRouteAddressData, (uint8_t*)&route->dest_address, sizeof(struct in_addr)); 1769 CFDataAppendBytes(excludedRouteMaskData, (uint8_t*)&route->dest_mask, sizeof(struct in_addr)); 1770 } 1771 } 1772 1773 /* Send info to cache */ 1774 CFMutableDictionaryRef routesDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1775 if (routesDict) { 1776 CFMutableDictionaryRef ipv4RoutesDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1777 if (ipv4RoutesDict) { 1778 if (CFDataGetLength(includedRouteAddressData)) { 1779 CFMutableDictionaryRef includedRoutesDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1780 if (includedRoutesDict) { 1781 CFDictionaryAddValue(includedRoutesDict, kSCNetworkConnectionNetworkInfoAddresses, includedRouteAddressData); 1782 CFDictionaryAddValue(includedRoutesDict, kSCNetworkConnectionNetworkInfoMasks, includedRouteMaskData); 1783 CFDictionaryAddValue(ipv4RoutesDict, kSCNetworkConnectionNetworkInfoIncludedRoutes, includedRoutesDict); 1784 CFRelease(includedRoutesDict); 1785 } 1786 } 1787 1788 if (CFDataGetLength(excludedRouteAddressData)) { 1789 CFMutableDictionaryRef excludedRoutesDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1790 if (excludedRoutesDict) { 1791 CFDictionaryAddValue(excludedRoutesDict, kSCNetworkConnectionNetworkInfoAddresses, excludedRouteAddressData); 1792 CFDictionaryAddValue(excludedRoutesDict, kSCNetworkConnectionNetworkInfoMasks, excludedRouteMaskData); 1793 CFDictionaryAddValue(ipv4RoutesDict, kSCNetworkConnectionNetworkInfoExcludedRoutes, excludedRoutesDict); 1794 CFRelease(excludedRoutesDict); 1795 } 1796 } 1797 1798 CFDictionaryAddValue(routesDict, kSCNetworkConnectionNetworkInfoIPv4, ipv4RoutesDict); 1799 CFRelease(ipv4RoutesDict); 1800 } 1801 scnc_cache_routing_table(serv, routesDict, FALSE, (isdefault != 0)); 1802 CFRelease(routesDict); 1803 } 1804 1805done: 1806 my_CFRelease(&includedRouteAddressData); 1807 my_CFRelease(&includedRouteMaskData); 1808 my_CFRelease(&excludedRouteAddressData); 1809 my_CFRelease(&excludedRouteMaskData); 1810} 1811 1812static bool mode_config_is_default(struct service *serv) 1813{ 1814 bool isdefault = true; 1815 struct isakmp_data attr; 1816 char *modecfg_data = (char*)serv->u.ipsec.msg + sizeof(struct vpnctl_status_phase_change) + sizeof(struct vpnctl_modecfg_params); 1817 int modecfg_data_len = ntohs(serv->u.ipsec.msghdr.len) - ((sizeof(struct vpnctl_status_phase_change) + sizeof(struct vpnctl_modecfg_params)) - sizeof(struct vpnctl_hdr)); 1818 int tlen = modecfg_data_len; 1819 char *dataptr = modecfg_data; 1820 1821 while (tlen > 0) 1822 { 1823 int tlv; 1824 u_int16_t type; 1825 1826 memcpy(&attr, dataptr, sizeof(attr)); // Wcast-align fix - memcpy for unaligned access 1827 type = ntohs(attr.type) & 0x7FFF; 1828 tlv = (type == ntohs(attr.type)); 1829 1830 1831 if (type == UNITY_SPLIT_INCLUDE) { 1832 isdefault = false; 1833 break; 1834 } 1835 1836 if (tlv) { 1837 tlen -= ntohs(attr.lorv); 1838 dataptr += ntohs(attr.lorv); 1839 } 1840 1841 tlen -= sizeof(u_int32_t); 1842 dataptr += sizeof(u_int32_t); 1843 } 1844 1845 return isdefault; 1846} 1847 1848/* ----------------------------------------------------------------------------- 1849----------------------------------------------------------------------------- */ 1850static void install_mode_config(struct service *serv, Boolean installConfig, Boolean installPolicies) 1851{ 1852 struct in_addr addr, mask, local_addr, remote_addr; 1853 char *data; 1854 CFDictionaryRef dict = NULL; 1855 CFMutableArrayRef dicts_to_publish = NULL, dict_names_to_publish = NULL; 1856 int error, isdefault = 1, len, data_len; 1857 char *errorstr; 1858 u_int32_t dns, prefix, local_prefix, remote_prefix; 1859 u_int32_t internal_ip4_address, internal_ip4_netmask; 1860 CFStringRef strRef, domain_name = NULL; 1861 CFMutableArrayRef split_dns_array = NULL, dns_array = NULL; 1862 int must_prompt; 1863 int unity_splitdns_name_i = 0, unity_split_include_i = 0, unity_local_lan_i = 0, unity_browser_i = 0; 1864 1865 serv->u.ipsec.ping_addr.s_addr = 0; 1866 1867 u_int8_t *modecfg_msg = serv->u.ipsec.modecfg_msg; 1868 u_int32_t modecfg_msglen = serv->u.ipsec.modecfg_msglen; 1869 struct vpnctl_hdr *ctl_hdr = (struct vpnctl_hdr *)modecfg_msg; 1870 if (modecfg_msg == NULL) { 1871 modecfg_msg = serv->u.ipsec.msg; 1872 modecfg_msglen = serv->u.ipsec.msglen; 1873 ctl_hdr = &serv->u.ipsec.msghdr; 1874 } 1875 1876 if (modecfg_msg == NULL) { 1877 return; 1878 } 1879 1880 struct vpnctl_status_phase_change *phase_change_status = ALIGNED_CAST(struct vpnctl_status_phase_change *)modecfg_msg; 1881 struct vpnctl_modecfg_params *modecfg = ALIGNED_CAST(struct vpnctl_modecfg_params *)(modecfg_msg + sizeof(struct vpnctl_status_phase_change)); 1882 1883 char *modecfg_data = (char*)modecfg_msg + sizeof(struct vpnctl_status_phase_change) + sizeof(struct vpnctl_modecfg_params); 1884 int modecfg_data_len = ntohs(ctl_hdr->len) - ((sizeof(struct vpnctl_status_phase_change) + sizeof(struct vpnctl_modecfg_params)) - sizeof(struct vpnctl_hdr)); 1885 1886 CFMutableArrayRef policies_array; 1887 CFMutableDictionaryRef policies, policy; 1888 1889 internal_ip4_address = htonl(0); 1890 internal_ip4_netmask = htonl(0xFFFFFFFF); 1891 1892 /* first pass, get mandatory parameters */ 1893 1894 int tlen = modecfg_data_len; 1895 char *dataptr = modecfg_data; 1896 struct isakmp_data attr; 1897 1898 IPSECLOGASLMSG("IPSec Network Configuration started.\n"); 1899 1900 while (tlen > 0) 1901 { 1902 int tlv; 1903 u_int16_t type; 1904 1905 memcpy(&attr, dataptr, sizeof(attr)); // Wcast-align fix - memcpy for unbaligned access 1906 type = ntohs(attr.type) & 0x7FFF; 1907 tlv = (type == ntohs(attr.type)); 1908 1909 switch (type) 1910 { 1911 case INTERNAL_IP4_ADDRESS: 1912 // Wcast-align fix - memcpy for unaligned access 1913 memcpy(&internal_ip4_address, dataptr + sizeof(u_int32_t), sizeof(internal_ip4_address)); // network byte order 1914 addr.s_addr = internal_ip4_address; 1915 IPSECLOGASLMSG("IPSec Network Configuration: INTERNAL-IP4-ADDRESS = %s.\n", 1916 inet_ntoa(addr)); 1917 break; 1918 1919 case INTERNAL_IP4_NETMASK: 1920 // Wcast-align fix - memcpy for unaligned access 1921 memcpy(&internal_ip4_netmask, dataptr + sizeof(u_int32_t), sizeof(internal_ip4_netmask)); // network byte order 1922 addr.s_addr = internal_ip4_netmask; 1923 IPSECLOGASLMSG("IPSec Network Configuration: INTERNAL-IP4-MASK = %s.\n", 1924 inet_ntoa(addr)); 1925 break; 1926 1927 default: 1928 break; 1929 } 1930 1931 if (tlv) { 1932 tlen -= ntohs(attr.lorv); 1933 dataptr += ntohs(attr.lorv); 1934 } 1935 1936 tlen -= sizeof(u_int32_t); 1937 dataptr += sizeof(u_int32_t); 1938 1939 } 1940 1941 if (internal_ip4_address == htonl(0)) { 1942 // ip address is missing 1943 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Internal IP Address missing from Mode Config packet ")); 1944 return; 1945 } 1946 1947 policies = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1948 policies_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1949 1950 addr.s_addr = modecfg->outer_local_addr; 1951 AddString(policies, kRASPropIPSecLocalAddress, inet_ntoa(addr)); 1952 addr.s_addr = phase_change_status->address; 1953 AddString(policies, kRASPropIPSecRemoteAddress, inet_ntoa(addr)); 1954 1955 /* second pass, get optional parameters */ 1956 1957 tlen = modecfg_data_len; 1958 dataptr = modecfg_data; 1959 1960 while (tlen > 0) 1961 { 1962 int tlv; 1963 u_int16_t type; 1964 1965 memcpy(&attr, dataptr, sizeof(attr)); // Wcast-align fix - memcpy for unaligned access 1966 type = ntohs(attr.type) & 0x7FFF; 1967 tlv = (type == ntohs(attr.type)); 1968 1969 switch (type) 1970 { 1971 case INTERNAL_IP4_DNS: 1972 if (!dns_array) 1973 dns_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1974 1975 if (!dns_array) 1976 break; 1977 1978 memcpy(&dns, dataptr + sizeof(u_int32_t), sizeof(u_int32_t)); // Wcast-align fix - memcpy for unaligned access 1979 strRef = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&dns)); 1980 if (!strRef) 1981 break; 1982 1983 CFArrayAppendValue(dns_array, strRef); 1984 IPSECLOGASLMSG("IPSec Network Configuration: INTERNAL-IP4-DNS = %s.\n", 1985 CFStringGetCStringPtr(strRef, kCFStringEncodingMacRoman)); 1986 CFRelease(strRef); 1987 break; 1988 1989 1990 default: 1991 break; 1992 } 1993 1994 1995 if (tlv) { 1996 tlen -= ntohs(attr.lorv); 1997 dataptr += ntohs(attr.lorv); 1998 } 1999 2000 tlen -= sizeof(u_int32_t); 2001 dataptr += sizeof(u_int32_t); 2002 2003 } 2004 2005 2006 if (isdefault) { 2007 // default route 2008 policy = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2009 2010 CFDictionarySetValue(policy, kRASPropIPSecPolicyMode, kRASValIPSecPolicyModeTunnel); 2011 CFDictionarySetValue(policy, kRASPropIPSecPolicyDirection, kRASValIPSecPolicyDirectionInOut); 2012 CFDictionarySetValue(policy, kRASPropIPSecPolicyLevel, kRASValIPSecPolicyLevelRequire); 2013 2014 addr.s_addr = internal_ip4_address; 2015 AddString(policy, kRASPropIPSecPolicyLocalAddress, inet_ntoa(addr)); 2016 mask.s_addr = ntohl(0xFFFFFFFF /* internal_ip4_netmask */); // VPN client should use 255.255.255.255 2017 for (prefix = 0; mask.s_addr; mask.s_addr<<=1, prefix++); 2018 AddNumber(policy, kRASPropIPSecPolicyLocalPrefix, prefix); 2019 IPSECLOGASLMSG("IPSec Network Configuration: DEFAULT-ROUTE = local-address %s/%d.\n", 2020 inet_ntoa(addr), prefix); 2021 2022 serv->u.ipsec.ping_addr.s_addr = internal_ip4_address; // will ping our own address, it will hit the (internal_ip4_address --> any) policy 2023 2024 CFDictionarySetValue(policy, kRASPropIPSecPolicyRemoteAddress, CFSTR("0.0.0.0")); 2025 AddNumber(policy, kRASPropIPSecPolicyRemotePrefix, 0); 2026 2027 update_service_route(serv, internal_ip4_address, 0xFFFFFFFF, 0, 0, 0, 0, 0); 2028 2029 CFArrayAppendValue(policies_array, policy); 2030 CFRelease(policy); 2031 } 2032 2033 2034 CFDictionarySetValue(policies, kRASPropIPSecPolicies, policies_array); 2035 CFRelease(policies_array); 2036 2037 if (installPolicies) { 2038 ipsec_log(LOG_DEBUG, CFSTR("IPSec Controller: Mode Config Policies %@"), policies); 2039 2040 if ((error = IPSecInstallPolicies(policies, -1, &errorstr)) < 0) { 2041 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: IPSecInstallPolicies failed '%s'"), errorstr); 2042 CFRelease(policies); 2043 goto fail; 2044 } 2045 serv->u.ipsec.modecfg_policies = (CFMutableDictionaryRef)my_CFRetain(policies); 2046 serv->u.ipsec.modecfg_defaultroute = isdefault; 2047 2048 serv->u.ipsec.inner_local_addr = internal_ip4_address; 2049 serv->u.ipsec.inner_local_mask = internal_ip4_netmask; 2050 2051 /* create the virtual interface */ 2052 serv->u.ipsec.kernctl_sock = create_tun_interface(serv->if_name, sizeof(serv->if_name), &serv->if_index, UTUN_FLAGS_NO_INPUT + UTUN_FLAGS_NO_OUTPUT, 0); 2053 if (serv->u.ipsec.kernctl_sock == -1) { 2054 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot create tunnel interface")); 2055 goto fail; 2056 } 2057 2058 if (set_tun_delegate(serv->u.ipsec.kernctl_sock, serv->u.ipsec.lower_interface)) { 2059 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot set delegate interface for tunnel interface")); 2060 goto fail; 2061 } 2062 2063 set_ifmtu(serv->if_name, 1280); 2064 set_ifaddr(serv->if_name, internal_ip4_address, internal_ip4_address,internal_ip4_netmask); 2065 2066 if ((error = racoon_send_cmd_start_ph2(serv->u.ipsec.controlfd, serv->u.ipsec.peer_address.sin_addr.s_addr, policies)) != 0) { 2067 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: racoon_send_cmd_start_ph2 failed '%s'"), errorstr); 2068 goto fail; 2069 } 2070 racoon_trigger_phase2(serv->if_name, &serv->u.ipsec.ping_addr); 2071 } 2072 2073 if (installConfig) { 2074 SCNetworkReachabilityRef ref; 2075 SCNetworkConnectionFlags flags; 2076 bool is_peer_local; 2077 struct sockaddr_in ip_zeros; 2078 2079 bzero(&ip_zeros, sizeof(ip_zeros)); 2080 ip_zeros.sin_len = sizeof(ip_zeros); 2081 ip_zeros.sin_family = AF_INET; 2082 2083 /* check if is peer on our local subnet */ 2084 ref = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&serv->u.ipsec.peer_address); 2085 is_peer_local = SCNetworkReachabilityGetFlags(ref, &flags) && (flags & kSCNetworkFlagsIsDirect); 2086 2087#if TARGET_OS_EMBEDDED 2088 if (serv->u.ipsec.lower_interface[0]) { 2089 // Mark interface as cellular based on NWI 2090 serv->u.ipsec.lower_interface_cellular = interface_is_cellular(serv->u.ipsec.lower_interface); 2091 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: lower interface (%s) is%s cellular"), serv->u.ipsec.lower_interface, serv->u.ipsec.lower_interface_cellular ? "" : " not"); 2092 } else { 2093 /* Mark interface as cellular based on reachability */ 2094 serv->u.ipsec.lower_interface_cellular = SCNetworkReachabilityGetFlags(ref, &flags) && (flags & kSCNetworkReachabilityFlagsIsWWAN); 2095 } 2096#endif 2097 2098 CFRelease(ref); 2099 2100 CFArrayRef includedRoutes = NULL; 2101 CFMutableArrayRef excludedRoutes = NULL; 2102 2103 if (is_peer_local 2104 || (serv->u.ipsec.lower_gateway.sin_addr.s_addr == 0)) { 2105 2106 if (serv->u.ipsec.lower_interface[0]) { 2107 /* subnet route */ 2108 excludedRoutes = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 2109 add_ipv4_route(excludedRoutes, serv->u.ipsec.peer_address.sin_addr.s_addr, INADDR_BROADCAST, 0, TRUE, serv->u.ipsec.lower_interface); 2110 } 2111 } 2112 else { 2113 /* host route */ 2114 excludedRoutes = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 2115 add_ipv4_route(excludedRoutes, serv->u.ipsec.peer_address.sin_addr.s_addr, INADDR_BROADCAST, serv->u.ipsec.lower_gateway.sin_addr.s_addr, TRUE, NULL); 2116 } 2117 2118 if (!isdefault) { 2119 addr.s_addr = internal_ip4_address; 2120 if ((includedRoutes = create_ipv4_route_array(serv, policies, addr)) == NULL) { 2121 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: create_ipv4_route_array failed")); 2122 } 2123 } 2124 2125 if (!serv->ne_sm_bridge) { 2126 format_routes_for_cache(serv, &addr, isdefault); 2127 } 2128 2129 dicts_to_publish = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2130 dict_names_to_publish = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2131 2132 dict = create_stateaddr(gDynamicStore, serv->serviceID, serv->if_name, serv->u.ipsec.peer_address.sin_addr.s_addr, internal_ip4_address,internal_ip4_address, internal_ip4_netmask, isdefault, includedRoutes, excludedRoutes); 2133 my_CFRelease(&includedRoutes); 2134 my_CFRelease(&excludedRoutes); 2135 if (dict) { 2136 CFArrayAppendValue(dict_names_to_publish, kSCEntNetIPv4); 2137 CFArrayAppendValue(dicts_to_publish, dict); 2138 CFRelease(dict); 2139 } 2140 2141 if (isdefault) { 2142 dict = create_ipv6_dummy_primary(serv->if_name); 2143 if (dict) { 2144 serv->u.ipsec.dummy_ipv6_installed = 1; 2145 CFArrayAppendValue(dict_names_to_publish, kSCEntNetIPv6); 2146 CFArrayAppendValue(dicts_to_publish, dict); 2147 CFRelease(dict); 2148 } 2149 } 2150 2151 if (dns_array) { 2152 2153 // add split dns array if only domain name was provided by the server 2154 if (!split_dns_array && domain_name) { 2155 split_dns_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2156 if (split_dns_array) { 2157 CFArrayAppendValue(split_dns_array, domain_name); 2158 } 2159 } 2160 2161 dict = create_dns(gDynamicStore, serv->serviceID, dns_array, domain_name, split_dns_array, FALSE); 2162 if (dict) { 2163 CFArrayAppendValue(dict_names_to_publish, kSCEntNetDNS); 2164 CFArrayAppendValue(dicts_to_publish, dict); 2165 CFRelease(dict); 2166 } 2167 } 2168 2169 2170 if (serv->ne_sm_bridge != NULL) { 2171 ne_sm_bridge_filter_state_dictionaries(serv->ne_sm_bridge, dict_names_to_publish, dicts_to_publish); 2172 } 2173 2174 /* Publish all-at-once */ 2175 publish_multiple_dicts(gDynamicStore, serv->serviceID,dict_names_to_publish, dicts_to_publish); 2176 ipsec_log(LOG_DEBUG, CFSTR("IPSec Controller: Published dictionaries to dynamic store.")); 2177 } 2178 my_CFRelease(&split_dns_array); 2179 my_CFRelease(&domain_name); 2180 my_CFRelease(&dns_array); 2181 my_CFRelease(&dicts_to_publish); 2182 my_CFRelease(&dict_names_to_publish); 2183 my_CFRelease(&policies); 2184 2185 if (installConfig) { 2186 serv->u.ipsec.modecfg_installed = 1; 2187 } 2188 if (installPolicies) { 2189 serv->u.ipsec.modecfg_policies_installed = 1; 2190 } 2191 2192 IPSECLOGASLMSG("IPSec Network Configuration established.\n"); 2193 2194 return; 2195 2196fail: 2197 my_CFRelease(&split_dns_array); 2198 my_CFRelease(&domain_name); 2199 my_CFRelease(&dns_array); 2200 my_CFRelease(&serv->u.ipsec.banner); 2201 my_CFRelease(&dicts_to_publish); 2202 my_CFRelease(&dict_names_to_publish); 2203 my_CFRelease(&policies); 2204 2205 if (serv->u.ipsec.modecfg_policies) { 2206 error = IPSecRemovePolicies(serv->u.ipsec.modecfg_policies, -1, &errorstr); 2207 my_CFRelease(&serv->u.ipsec.modecfg_policies); 2208 2209 } 2210 if (serv->u.ipsec.modecfg_defaultroute) { 2211 // don't need that since we unpublished the whole dictionary 2212 // unpublish_dictentry(gDynamicStore, serv->serviceID, kSCEntNetIPv4, kSCPropNetOverridePrimary); 2213 serv->u.ipsec.modecfg_defaultroute = 0; 2214 } 2215 2216 my_close(serv->u.ipsec.kernctl_sock); 2217 serv->u.ipsec.kernctl_sock = -1; 2218} 2219 2220/* ----------------------------------------------------------------------------- 2221----------------------------------------------------------------------------- */ 2222static int unassert_mode_config(struct service *serv) 2223{ 2224 if (serv->u.ipsec.modecfg_installed) { 2225 /* we already have a config, so if phase1 is asserted-established stop timer and let racoon take care of the IPSec SAs rekeys */ 2226 if (IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) { 2227 if (serv->u.ipsec.timerref) { 2228 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.timerref, kCFRunLoopCommonModes); 2229 } 2230 my_CFRelease(&serv->u.ipsec.timerref); 2231 } 2232 return 0; 2233 } 2234 return -1; 2235} 2236 2237/* ----------------------------------------------------------------------------- 2238 ----------------------------------------------------------------------------- */ 2239int racoon_send_cmd_reconnect(int fd, u_int32_t address) 2240{ 2241 u_int8_t data[256] __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 2242 struct vpnctl_cmd_connect *cmd_reconnect = ALIGNED_CAST(struct vpnctl_cmd_connect *)data; 2243 2244 bzero(cmd_reconnect, sizeof(struct vpnctl_cmd_connect)); 2245 cmd_reconnect->hdr.len = htons(sizeof(*cmd_reconnect) - sizeof(cmd_reconnect->hdr)); 2246 cmd_reconnect->hdr.msg_type = htons(VPNCTL_CMD_RECONNECT); 2247 cmd_reconnect->address = address; 2248 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: sending RECONNECT to racoon control socket")); 2249 write(fd, cmd_reconnect, sizeof(*cmd_reconnect)); 2250 return 0; 2251} 2252 2253/* ----------------------------------------------------------------------------- 2254----------------------------------------------------------------------------- */ 2255static 2256void racoon_timer(CFRunLoopTimerRef timer, void *info) 2257{ 2258 struct service *serv = info; 2259 struct sockaddr_in address; 2260 CFRange range; 2261 CFDataRef dataref; 2262 2263 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_timer expired")); 2264 2265 /* if no contact, try next server */ 2266 if (serv->u.ipsec.phase == IPSEC_INITIALIZE || serv->u.ipsec.phase == IPSEC_CONTACT) { 2267 2268 if (serv->u.ipsec.resolvedAddress && 2269 (serv->u.ipsec.next_address < CFArrayGetCount(serv->u.ipsec.resolvedAddress))) { 2270 2271 dataref = CFArrayGetValueAtIndex(serv->u.ipsec.resolvedAddress, serv->u.ipsec.next_address); 2272 serv->u.ipsec.next_address++; 2273 2274 bzero(&address, sizeof(address)); 2275 range.location = 0; 2276 range.length = sizeof(address); 2277 CFDataGetBytes(dataref, range, (UInt8 *)&address); 2278 2279 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_timer call racoon_restart")); 2280 racoon_restart(serv, &address); 2281 return; 2282 } 2283 } 2284 2285 /* need to resend ping ? */ 2286 if (serv->u.ipsec.phase == IPSEC_PHASE1 || IPSEC_IS_ASSERTED_PHASE1(serv->u.ipsec)) { 2287 2288 if (serv->u.ipsec.ping_count > 0) { 2289 serv->u.ipsec.ping_count--; 2290 //printf("timer_resend ping, addr = 0x%s\n", inet_ntoa(serv->u.ipsec.ping_addr)); 2291 racoon_trigger_phase2(serv->if_name, &serv->u.ipsec.ping_addr); 2292 if (serv->u.ipsec.timerref) { 2293 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_PHASE2_PING); 2294 } 2295 return; 2296 } 2297 } 2298 2299 /* need to continue assert ? */ 2300 if (IPSEC_IS_ASSERTED_IDLE(serv->u.ipsec)) { 2301 racoon_send_cmd_reconnect(serv->u.ipsec.controlfd, serv->u.ipsec.peer_address.sin_addr.s_addr); 2302 IPSEC_ASSERT_INITIALIZE(serv->u.ipsec); 2303 if (serv->u.ipsec.timerref) { 2304 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_INITIAL_CONTACT); 2305 } 2306 return; 2307 } 2308 2309 switch (serv->u.ipsec.phase) { 2310 case IPSEC_INITIALIZE: 2311 serv->u.ipsec.laststatus = IPSEC_CONFIGURATION_ERROR; 2312 break; 2313 case IPSEC_CONTACT: 2314 serv->u.ipsec.laststatus = IPSEC_CONNECTION_ERROR; 2315 break; 2316 default: 2317 serv->u.ipsec.laststatus = IPSEC_NEGOTIATION_ERROR; 2318 break; 2319 } 2320 ipsec_stop(serv, 0); 2321 2322} 2323 2324static u_int32_t get_interface_timeout (u_int32_t interface_media) 2325{ 2326 u_int32_t scaled_interface_timeout = TIMEOUT_INTERFACE_CHANGE; 2327#if !TARGET_OS_EMBEDDED 2328 // increase the timeout if we're waiting for a wireless interface 2329 if (IFM_TYPE(interface_media) == IFM_IEEE80211) { 2330 scaled_interface_timeout = (TIMEOUT_INTERFACE_CHANGE << 2); 2331 } 2332#endif /* !iPhone */ 2333 ipsec_log(LOG_INFO, CFSTR("getting interface (media %x) timeout for ipsec: %d secs"), interface_media, scaled_interface_timeout); 2334 return scaled_interface_timeout; 2335} 2336 2337/* ----------------------------------------------------------------------------- 2338----------------------------------------------------------------------------- */ 2339static 2340void event_timer(CFRunLoopTimerRef timer, void *info) 2341{ 2342 struct service *serv = info; 2343 2344 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: Network change event timer expired")); 2345 2346 IPSecLogVPNInterfaceAddressEvent(__FUNCTION__, NULL, serv->u.ipsec.timeout_lower_interface_change, serv->u.ipsec.lower_interface, &serv->u.ipsec.our_address.sin_addr); 2347 2348 serv->u.ipsec.laststatus = IPSEC_NETWORKCHANGE_ERROR; 2349 ipsec_stop(serv, 0); 2350 2351} 2352 2353 2354/* ----------------------------------------------------------------------------- 2355----------------------------------------------------------------------------- */ 2356static 2357void racoon_callback(CFSocketRef inref, CFSocketCallBackType type, 2358 CFDataRef address, const void *data, void *info) 2359{ 2360 int s = CFSocketGetNative(inref); 2361 int action = do_nothing; 2362 ssize_t n; 2363 struct service *serv = info; 2364 2365 /* first read the header part of the message */ 2366 if (serv->u.ipsec.msglen < sizeof(struct vpnctl_hdr)) { 2367 n = readn(s, &((u_int8_t *)&serv->u.ipsec.msghdr)[serv->u.ipsec.msglen], sizeof(struct vpnctl_hdr) - serv->u.ipsec.msglen); 2368 switch (n) { 2369 case -1: 2370// ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, failed to read header, closing")); 2371 action = do_close; 2372 break; 2373 default: 2374 serv->u.ipsec.msglen += n; 2375 if (serv->u.ipsec.msglen == sizeof(struct vpnctl_hdr)) { 2376 2377 serv->u.ipsec.msgtotallen = serv->u.ipsec.msglen + ntohs(serv->u.ipsec.msghdr.len); 2378 serv->u.ipsec.msg = my_Allocate(serv->u.ipsec.msgtotallen + 1); 2379 if (serv->u.ipsec.msg == 0) 2380 action = do_error; 2381 else { 2382 bcopy(&serv->u.ipsec.msghdr, serv->u.ipsec.msg, sizeof(struct vpnctl_hdr)); 2383 // let's end the message with a null byte 2384 serv->u.ipsec.msg[serv->u.ipsec.msgtotallen] = 0; 2385 } 2386#if 0 2387 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, header =")); 2388 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, msg_type = 0x%x"), serv->u.ipsec.msghdr.msg_type); 2389 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, flags = 0x%x"), serv->u.ipsec.msghdr.flags); 2390 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, cookie = 0x%x"), serv->u.ipsec.msghdr.cookie); 2391 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, reserved = 0x%x"), serv->u.ipsec.msghdr.reserved); 2392 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, result = 0x%x"), serv->u.ipsec.msghdr.result); 2393 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, len = %d"), serv->u.ipsec.msghdr.len); 2394#endif 2395 } 2396 } 2397 } 2398 2399 /* first read the data part of the message */ 2400 if (serv->u.ipsec.msglen >= sizeof(struct vpnctl_hdr)) { 2401// ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, len to read = %d"), serv->u.ipsec.msgtotallen - serv->u.ipsec.msglen); 2402 2403 n = readn(s, &serv->u.ipsec.msg[serv->u.ipsec.msglen], serv->u.ipsec.msgtotallen - serv->u.ipsec.msglen); 2404 switch (n) { 2405 case -1: 2406 // ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_callback, failed to read payload, closing")); 2407 action = do_close; 2408 break; 2409 default: 2410 serv->u.ipsec.msglen += n; 2411 if (serv->u.ipsec.msglen == serv->u.ipsec.msgtotallen) { 2412 action = do_process; 2413 } 2414 } 2415 } 2416 2417 /* perform action */ 2418 switch (action) { 2419 case do_nothing: 2420 break; 2421 case do_error: 2422 case do_close: 2423 /* connection closed by client */ 2424 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: connection closed by client, call ipsec_stop")); 2425 serv->u.ipsec.laststatus = IPSEC_GENERIC_ERROR; 2426 ipsec_stop(serv, 0); 2427 break; 2428 2429 case do_process: 2430 // process client request 2431 process_racoon_msg(serv); 2432 my_Deallocate(serv->u.ipsec.msg, serv->u.ipsec.msgtotallen + 1); 2433 serv->u.ipsec.msg = 0; 2434 serv->u.ipsec.msglen = 0; 2435 serv->u.ipsec.msgtotallen = 0; 2436 break; 2437 } 2438} 2439 2440static int 2441IPSecCheckVPNInterfaceOrServiceUnrecoverable (SCDynamicStoreRef dynamicStoreRef, 2442 const char *location, 2443 struct kern_event_msg *ev_msg, 2444 char *interface_buf) 2445{ 2446 //SCDynamicStoreRef dynamicStoreRef = (SCDynamicStoreRef)dynamicStore; 2447 2448 // return 1, if this is a delete event, and; 2449 // TODO: add support for IPv6 <rdar://problem/5920237> 2450 // walk Setup:/Network/Service/* and check if there are service entries referencing this interface. e.g. Setup:/Network/Service/44DB8790-0177-4F17-8D4E-37F9413D1D87/Interface:DeviceName == interface, other_serv_found = 1 2451 // Setup:/Network/Interface/"interface"/AirPort:'PowerEnable' == 0 || Setup:/Network/Interface/"interface"/IPv4 is missing, interf_down = 1 2452 if (!dynamicStoreRef) 2453 syslog(LOG_DEBUG, "%s: invalid SCDynamicStore reference", location); 2454 2455 if (dynamicStoreRef && 2456 (ev_msg->event_code == KEV_INET_ADDR_DELETED || ev_msg->event_code == KEV_INET_CHANGED_ADDR)) { 2457 CFStringRef interf_key; 2458 CFMutableArrayRef interf_keys; 2459 CFStringRef pattern; 2460 CFMutableArrayRef patterns; 2461 CFDictionaryRef dict = NULL; 2462 CFIndex i; 2463 const void * keys_q[128]; 2464 const void ** keys = keys_q; 2465 const void * values_q[128]; 2466 const void ** values = values_q; 2467 CFIndex n; 2468 CFStringRef vpn_if; 2469 int other_serv_found = 0, interf_down = 0; 2470 2471 vpn_if = CFStringCreateWithCStringNoCopy(NULL, 2472 interface_buf, 2473 kCFStringEncodingASCII, 2474 kCFAllocatorNull); 2475 if (!vpn_if) { 2476 // if we could not initialize interface CFString 2477 syslog(LOG_NOTICE, "%s: failed to initialize interface CFString", location); 2478 goto done; 2479 } 2480 2481 interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2482 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2483 // get Setup:/Network/Interface/<vpn_if>/Airport 2484 interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 2485 kSCDynamicStoreDomainSetup, 2486 vpn_if, 2487 kSCEntNetAirPort); 2488 CFArrayAppendValue(interf_keys, interf_key); 2489 CFRelease(interf_key); 2490 // get State:/Network/Interface/<vpn_if>/Airport 2491 interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 2492 kSCDynamicStoreDomainState, 2493 vpn_if, 2494 kSCEntNetAirPort); 2495 CFArrayAppendValue(interf_keys, interf_key); 2496 CFRelease(interf_key); 2497 // get Setup:/Network/Service/*/Interface 2498 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 2499 kSCDynamicStoreDomainSetup, 2500 kSCCompAnyRegex, 2501 kSCEntNetInterface); 2502 CFArrayAppendValue(patterns, pattern); 2503 CFRelease(pattern); 2504 // get Setup:/Network/Service/*/IPv4 2505 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 2506 kSCDynamicStoreDomainSetup, 2507 kSCCompAnyRegex, 2508 kSCEntNetIPv4); 2509 CFArrayAppendValue(patterns, pattern); 2510 CFRelease(pattern); 2511 dict = SCDynamicStoreCopyMultiple(dynamicStoreRef, interf_keys, patterns); 2512 CFRelease(interf_keys); 2513 CFRelease(patterns); 2514 2515 if (!dict) { 2516 // if we could not access the SCDynamicStore 2517 syslog(LOG_NOTICE, "%s: failed to initialize SCDynamicStore dictionary", location); 2518 CFRelease(vpn_if); 2519 goto done; 2520 } 2521 // look for the service which matches the provided prefixes 2522 n = CFDictionaryGetCount(dict); 2523 if (n <= 0) { 2524 syslog(LOG_NOTICE, "%s: empty SCDynamicStore dictionary", location); 2525 CFRelease(vpn_if); 2526 goto done; 2527 } 2528 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 2529 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 2530 values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 2531 } 2532 CFDictionaryGetKeysAndValues(dict, keys, values); 2533 for (i=0; i < n; i++) { 2534 CFStringRef s_key = (CFStringRef)keys[i]; 2535 CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; 2536 CFStringRef s_if; 2537 2538 if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { 2539 continue; 2540 } 2541 2542 if (CFStringHasSuffix(s_key, kSCEntNetInterface)) { 2543 // is a Service Interface entity 2544 s_if = CFDictionaryGetValue(s_dict, kSCPropNetInterfaceDeviceName); 2545 if (isA_CFString(s_if) && CFEqual(vpn_if, s_if)) { 2546 CFArrayRef components; 2547 CFStringRef serviceIDRef = NULL, serviceKey = NULL; 2548 CFPropertyListRef serviceRef = NULL; 2549 2550 other_serv_found = 1; 2551 // extract service ID 2552 components = CFStringCreateArrayBySeparatingStrings(NULL, s_key, CFSTR("/")); 2553 if (CFArrayGetCount(components) > 3) { 2554 serviceIDRef = CFArrayGetValueAtIndex(components, 3); 2555 //if (new key) Setup:/Network/Service/service_id/IPv4 is missing, then interf_down = 1 2556 serviceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainSetup, serviceIDRef, kSCEntNetIPv4); 2557 if (!serviceKey || 2558 !(serviceRef = CFDictionaryGetValue(dict, serviceKey))) { 2559 syslog(LOG_NOTICE, "%s: detected disabled IPv4 Config", location); 2560 interf_down = 1; 2561 } 2562 if (serviceKey) CFRelease(serviceKey); 2563 } 2564 if (components) CFRelease(components); 2565 if (interf_down) break; 2566 } 2567 continue; 2568 } else if (CFStringHasSuffix(s_key, kSCEntNetAirPort)) { 2569 // Interface/<vpn_if>/Airport entity 2570 if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainSetup)) { 2571 CFBooleanRef powerEnable = CFDictionaryGetValue(s_dict, SC_AIRPORT_POWERENABLED_KEY); 2572 if (isA_CFBoolean(powerEnable) && 2573 CFEqual(powerEnable, kCFBooleanFalse)) { 2574 syslog(LOG_NOTICE, "%s: detected AirPort, PowerEnable == FALSE", location); 2575 interf_down = 1; 2576 break; 2577 } 2578 } else if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainState)) { 2579 UInt16 temp; 2580 CFNumberRef airStatus = CFDictionaryGetValue(s_dict, SC_AIRPORT_POWERSTATUS_KEY); 2581 if (isA_CFNumber(airStatus) && 2582 CFNumberGetValue(airStatus, kCFNumberShortType, &temp)) { 2583 if (temp ==0) { 2584 syslog(LOG_NOTICE, "%s: detected AirPort, PowerStatus == 0", location); 2585 } 2586 } 2587 } 2588 continue; 2589 } 2590 } 2591 if (vpn_if) CFRelease(vpn_if); 2592 if (keys != keys_q) { 2593 CFAllocatorDeallocate(NULL, keys); 2594 CFAllocatorDeallocate(NULL, values); 2595 } 2596 done : 2597 if (dict) CFRelease(dict); 2598 2599 return (other_serv_found == 0 || interf_down == 1); 2600 } 2601 return 0; 2602} 2603 2604static int 2605IPSecCheckVPNInterfaceAddressChange (int transport_down, 2606 struct kern_event_msg *ev_msg, 2607 char *interface_buf, 2608 struct in_addr *our_address, 2609 struct service *serv) 2610{ 2611 struct kev_in_data *inetdata; 2612 2613 /* if transport is still down: ignore deletes, and check if the underlying interface's address has changed (ignore link-local addresses) */ 2614 if (transport_down && 2615 (ev_msg->event_code == KEV_INET_NEW_ADDR || ev_msg->event_code == KEV_INET_CHANGED_ADDR)) { 2616 inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 2617#if 0 2618 syslog(LOG_NOTICE, "%s: checking for interface address change. underlying %s, old-addr %x, new-addr %x\n", 2619 __FUNCTION__, interface_buf, our_address->s_addr, inetdata->ia_addr.s_addr); 2620#endif 2621 /* check if address changed */ 2622 if (our_address->s_addr != inetdata->ia_addr.s_addr && 2623 !IN_LINKLOCAL(ntohl(inetdata->ia_addr.s_addr))) { 2624 return 1; 2625 } 2626 // check to see if network has changed (despite the address) 2627 if (DID_VPN_LOCATIONCHANGE(serv)) { 2628 syslog(LOG_NOTICE, "%s: the underlying interface has changed networks\n", 2629 __FUNCTION__); 2630 return 1; 2631 } 2632 } 2633 2634 return 0; 2635} 2636 2637static int 2638IPSecCheckVPNInterfaceAddressAlternate (int transport_down, 2639 struct kern_event_msg *ev_msg, 2640 char *interface_buf) 2641{ 2642 struct kev_in_data *inetdata; 2643 2644 /* if transport is still down: ignore deletes, and check if any interface address has alternative address */ 2645 if (transport_down && 2646 (ev_msg->event_code == KEV_INET_NEW_ADDR || ev_msg->event_code == KEV_INET_CHANGED_ADDR)) { 2647 inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 2648#if 0 2649 syslog(LOG_NOTICE, "%s: checking for alternate interface. underlying %s, new-addr %x\n", 2650 __FUNCTION__, interface_buf, inetdata->ia_addr.s_addr); 2651#endif 2652 /* check if address changed */ 2653 if (!IN_LINKLOCAL(ntohl(inetdata->ia_addr.s_addr))) { 2654 return 1; 2655 } 2656 } 2657 2658 return 0; 2659} 2660 2661void 2662ipsec_network_event(struct service *serv, struct kern_event_msg *ev_msg) 2663{ 2664 CFRunLoopTimerContext context = { 0, serv, NULL, NULL, NULL }; 2665 int found; 2666 struct ifaddrs *ifap = NULL; 2667 char ev_if[32]; 2668 struct kev_in_data *inetdata; 2669 2670 inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 2671 IPSecLogVPNInterfaceAddressEvent(__FUNCTION__, ev_msg, serv->u.ipsec.timeout_lower_interface_change, serv->u.ipsec.lower_interface, &serv->u.ipsec.our_address.sin_addr); 2672 2673 // If the configuration is On Demand, switch from Cell to WiFi 2674 if (serv->ne_sm_bridge != NULL && 2675 serv->flags & FLAG_SETUP_ONDEMAND && 2676 serv->u.ipsec.lower_interface_cellular) { 2677 Boolean hasPrimaryInterface = FALSE; 2678 Boolean isCellular = primary_interface_is_cellular(&hasPrimaryInterface); 2679 if (hasPrimaryInterface && !isCellular) { 2680 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: Disconnecting tunnel over cellular in favor of better interface")); 2681 serv->u.ipsec.laststatus = IPSEC_NETWORKCHANGE_ERROR; 2682 ipsec_stop(serv, 0); 2683 return; 2684 } 2685 } 2686 2687 switch (ev_msg->event_code) { 2688 case KEV_INET_NEW_ADDR: 2689 case KEV_INET_CHANGED_ADDR: 2690 case KEV_INET_ADDR_DELETED: 2691 snprintf(ev_if, sizeof(ev_if), "%s%d", inetdata->link_data.if_name, inetdata->link_data.if_unit); 2692 // check if changes occured on the interface we are using 2693 if (!strncmp(ev_if, serv->u.ipsec.lower_interface, sizeof(serv->u.ipsec.lower_interface))) { 2694 if (inetdata->link_data.if_family == APPLE_IF_FAM_PPP) { 2695 // disconnect immediately 2696 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: Network changed on underlying PPP interface")); 2697 serv->u.ipsec.laststatus = IPSEC_NETWORKCHANGE_ERROR; 2698 ipsec_stop(serv, 0); 2699 } 2700 else { 2701 2702 /* check if address still exist */ 2703 found = 0; 2704 if (getifaddrs(&ifap) == 0) { 2705 struct ifaddrs *ifa; 2706 for (ifa = ifap; ifa && !found ; ifa = ifa->ifa_next) { 2707 found = (ifa->ifa_name 2708 && ifa->ifa_addr 2709 && !strncmp(ifa->ifa_name, serv->u.ipsec.lower_interface, sizeof(serv->u.ipsec.lower_interface)) 2710 && ifa->ifa_addr->sa_family == AF_INET 2711 && (ALIGNED_CAST(struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == serv->u.ipsec.our_address.sin_addr.s_addr); 2712 } 2713 freeifaddrs(ifap); 2714 } 2715 2716 if (found) { 2717 // no meaningful change, or address came back. Cancel timer if it was on. 2718 if (serv->u.ipsec.interface_timerref) { 2719 ipsec_updatephase(serv, IPSEC_RUNNING); 2720 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Network changed, address came back on underlying interface, cancel timer")); 2721 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.interface_timerref, kCFRunLoopCommonModes); 2722 my_CFRelease(&serv->u.ipsec.interface_timerref); 2723 2724 // check to see if network has changed (despite the address) 2725 if (DISCONNECT_VPN_IFLOCATIONCHANGED(serv)) { 2726 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: the underlying interface %s network changed."), 2727 serv->u.ipsec.lower_interface); 2728 serv->u.ipsec.laststatus = IPSEC_NETWORKCHANGE_ERROR; 2729 ipsec_stop(serv, 0); 2730 break; 2731 } 2732 if (serv->flags & FLAG_ONDEMAND) { 2733 racoon_send_cmd_start_dpd(serv->u.ipsec.controlfd, serv->u.ipsec.peer_address.sin_addr.s_addr); 2734 serv->u.ipsec.awaiting_peer_resp = 1; 2735 } else { 2736 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: asserting connection")); 2737 racoon_send_cmd_assert(serv); 2738 } 2739 } 2740 } 2741 else { 2742 // quick exit if there has been an unrecoverable change in interface/service 2743 if (IPSecCheckVPNInterfaceOrServiceUnrecoverable(gDynamicStore, 2744 __FUNCTION__, 2745 ev_msg, 2746 serv->u.ipsec.lower_interface)) 2747 { 2748 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: the underlying interface/service has changed unrecoverably.")); 2749 serv->u.ipsec.laststatus = IPSEC_NETWORKCHANGE_ERROR; 2750 ipsec_stop(serv, 0); 2751 break; 2752 } 2753 2754 // no address, arm timer if not there 2755 if (!serv->u.ipsec.interface_timerref) { 2756 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Network changed, address disappeared on underlying interface, install timer %d secs"), serv->u.ipsec.timeout_lower_interface_change); 2757 serv->u.ipsec.interface_timerref = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + serv->u.ipsec.timeout_lower_interface_change, FAR_FUTURE, 0, 0, event_timer, &context); 2758 if (!serv->u.ipsec.interface_timerref) { 2759 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Network changed, cannot create RunLoop timer")); 2760 // disconnect immediately 2761 serv->u.ipsec.laststatus = IPSEC_NETWORKCHANGE_ERROR; 2762 ipsec_stop(serv, 0); 2763 break; 2764 } 2765 ipsec_updatephase(serv, IPSEC_WAITING); 2766 CFRunLoopAddTimer(CFRunLoopGetCurrent(), serv->u.ipsec.interface_timerref, kCFRunLoopCommonModes); 2767 if (serv->u.ipsec.port_mapping_timerref) { 2768 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.port_mapping_timerref, kCFRunLoopCommonModes); 2769 my_CFRelease(&serv->u.ipsec.port_mapping_timerref); 2770 } 2771 (void)DISCONNECT_VPN_IFLOCATIONCHANGED(serv); 2772 } else { 2773 // transport is still down: check if there was a valid address change 2774 if (IPSecCheckVPNInterfaceAddressChange(serv->u.ipsec.phase == IPSEC_WAITING, 2775 /* && serv->u.ipsec.interface_timerref, */ 2776 ev_msg, 2777 serv->u.ipsec.lower_interface, 2778 &serv->u.ipsec.our_address.sin_addr, 2779 serv)) 2780 { 2781 // disconnect immediately 2782 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: the underlying interface %s address changed."), 2783 serv->u.ipsec.lower_interface); 2784 serv->u.ipsec.laststatus = IPSEC_NETWORKCHANGE_ERROR; 2785 ipsec_stop(serv, 0); 2786 } else { 2787 (void)DISCONNECT_VPN_IFLOCATIONCHANGED(serv); 2788 } 2789 } 2790 } 2791 } 2792 } else { 2793 if (IPSecCheckVPNInterfaceAddressAlternate((serv->u.ipsec.phase == IPSEC_WAITING && serv->u.ipsec.interface_timerref), ev_msg, serv->u.ipsec.lower_interface)) 2794 { 2795 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: an alternative interface %s was detected while the underlying interface %s was down."), ev_if, serv->u.ipsec.lower_interface); 2796 serv->u.ipsec.laststatus = IPSEC_NETWORKCHANGE_ERROR; 2797 ipsec_stop(serv, 0); 2798 } 2799 } 2800 break; 2801 } 2802} 2803 2804/* ----------------------------------------------------------------------------- 2805----------------------------------------------------------------------------- */ 2806static 2807void event_callback(CFSocketRef inref, CFSocketCallBackType type, 2808 CFDataRef address, const void *data, void *info) 2809{ 2810 int s = CFSocketGetNative(inref); 2811 struct service *serv = info; 2812 char buf[256] __attribute__ ((aligned(4))); // Wcast-align fix - force alignment 2813 struct kern_event_msg *ev_msg; 2814 2815 if (recv(s, &buf, sizeof(buf), 0) != -1) { 2816 ev_msg = ALIGNED_CAST(struct kern_event_msg *) &buf; 2817 ipsec_network_event(serv, ev_msg); 2818 } 2819} 2820 2821/* ----------------------------------------------------------------------------- 2822----------------------------------------------------------------------------- */ 2823static int racoon_create_socket(struct service *serv) 2824{ 2825 int flags; 2826 CFRunLoopSourceRef rls; 2827 CFSocketContext context = { 0, serv, NULL, NULL, NULL }; 2828 struct sockaddr_un sun; 2829 2830 serv->u.ipsec.controlfd = socket(PF_LOCAL, SOCK_STREAM, 0); 2831 if (serv->u.ipsec.controlfd < 0) { 2832 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot create racoon control socket (errno = %d) "), errno); 2833 goto fail; 2834 } 2835 2836 bzero(&sun, sizeof(sun)); 2837 sun.sun_family = AF_LOCAL; 2838 strncpy(sun.sun_path, "/var/run/vpncontrol.sock", sizeof(sun.sun_path)); 2839 2840 if (connect(serv->u.ipsec.controlfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) { 2841 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot connect racoon control socket (errno = %d)"), errno); 2842 goto fail; 2843 } 2844 2845 if ((flags = fcntl(serv->u.ipsec.controlfd, F_GETFL)) == -1 2846 || fcntl(serv->u.ipsec.controlfd, F_SETFL, flags | O_NONBLOCK) == -1) { 2847 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Couldn't set client socket in non-blocking mode, errno = %d"), errno); 2848 } 2849 2850 if ((serv->u.ipsec.controlref = CFSocketCreateWithNative(NULL, serv->u.ipsec.controlfd, 2851 kCFSocketReadCallBack, racoon_callback, &context)) == 0) { 2852 goto fail; 2853 } 2854 if ((rls = CFSocketCreateRunLoopSource(NULL, serv->u.ipsec.controlref, 0)) == 0) 2855 goto fail; 2856 2857 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 2858 CFRelease(rls); 2859 2860 return 0; 2861 2862fail: 2863 if (serv->u.ipsec.controlref) { 2864 CFSocketInvalidate(serv->u.ipsec.controlref); 2865 CFRelease(serv->u.ipsec.controlref); 2866 } 2867 else 2868 if (serv->u.ipsec.controlfd >= 0) { 2869 close(serv->u.ipsec.controlfd); 2870 } 2871 serv->u.ipsec.controlref = 0; 2872 serv->u.ipsec.controlfd = -1; 2873 2874 return -1; 2875} 2876 2877/* ----------------------------------------------------------------------------- 2878----------------------------------------------------------------------------- */ 2879static 2880void dns_start_query_cf_callback(CFMachPortRef port, void *msg, CFIndex size, void *info) 2881{ 2882 struct service *serv = (struct service *)info; 2883 2884 if (port != serv->u.ipsec.dnsPort) { 2885 // we've received a callback on the async DNS port but since the 2886 // associated CFMachPort doesn't match than the request must have 2887 // already been cancelled. 2888 return; 2889 } 2890 2891 CFMachPortInvalidate(serv->u.ipsec.dnsPort); 2892 CFRelease(serv->u.ipsec.dnsPort); 2893 serv->u.ipsec.dnsPort = NULL; 2894 2895 getaddrinfo_async_handle_reply(msg); 2896 return; 2897} 2898 2899/* ----------------------------------------------------------------------------- 2900----------------------------------------------------------------------------- */ 2901static 2902void dns_start_query_callback(int32_t status, struct addrinfo *res, void *context) 2903{ 2904 struct service *serv = (struct service *)context; 2905 struct addrinfo *resP; 2906 CFDataRef dataref; 2907 struct sockaddr_in address; 2908 2909 if ((status == 0) && (res != NULL)) { 2910 2911 CFMutableArrayRef addresses; 2912 CFRange range; 2913 2914 addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2915 range.location = 0; 2916 range.length = 0; 2917 2918 for (resP = res; resP; resP = resP->ai_next) { 2919 CFDataRef newAddress; 2920 2921 /* make sure it will fit... */ 2922 if (resP->ai_addr->sa_len > sizeof(struct sockaddr_in)) 2923 continue; 2924 2925 newAddress = CFDataCreate(NULL, (void *)resP->ai_addr, resP->ai_addr->sa_len); 2926 if (newAddress != NULL) { 2927 if (!CFArrayContainsValue(addresses, range, newAddress)) { 2928 CFArrayAppendValue(addresses, newAddress); 2929 range.length++; 2930 } 2931 CFRelease(newAddress); 2932 } 2933 } 2934 2935 /* save the resolved address[es] */ 2936 my_CFRelease(&serv->u.ipsec.resolvedAddress); 2937 serv->u.ipsec.resolvedAddress = addresses; 2938 serv->u.ipsec.resolvedAddressError = NETDB_SUCCESS; 2939 2940 ipsec_log(LOG_DEBUG, CFSTR("IPSec Controller: dns reply: resolvedAddress %@"), serv->u.ipsec.resolvedAddress); 2941 2942 if (!CFArrayGetCount(serv->u.ipsec.resolvedAddress)) { 2943 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: dns reply: no IPv4 address in reply")); 2944 goto fail; 2945 } 2946 2947 /* get the first address and start racoon */ 2948 dataref = CFArrayGetValueAtIndex(serv->u.ipsec.resolvedAddress, 0); 2949 if (!dataref || CFDataGetLength(dataref) < sizeof(address)) { 2950 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: dns reply: failed to get elem %d from addr array"), 2951 serv->u.ipsec.next_address); 2952 goto fail; 2953 } 2954 bzero(&address, sizeof(address)); 2955 range.location = 0; 2956 range.length = sizeof(address); 2957 CFDataGetBytes(dataref, range, (UInt8 *)&address); 2958 serv->u.ipsec.next_address = 1; 2959 2960 racoon_restart(serv, &address); 2961 goto done; 2962 } 2963 else { 2964 2965 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: dns reply: getaddrinfo() failed: %s"), gai_strerror(status)); 2966 goto fail; 2967 } 2968 2969fail: 2970 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: dns reply: Stopping service")); 2971 serv->u.ipsec.laststatus = IPSEC_RESOLVEADDRESS_ERROR; 2972 ipsec_stop(serv, 0); 2973 /* save the error associated with the attempt to resolve the name */ 2974 serv->u.ipsec.resolvedAddress = CFRetain(kCFNull); 2975 serv->u.ipsec.resolvedAddressError = status; 2976 2977done: 2978 ipsec_log(LOG_DEBUG, CFSTR("IPSec Controller: dns reply: done")); 2979 if (res != NULL) 2980 freeaddrinfo(res); 2981 2982} 2983 2984/* ----------------------------------------------------------------------------- 2985----------------------------------------------------------------------------- */ 2986static 2987int dns_start_query(struct service *serv, char *name) 2988{ 2989 int error; 2990 struct addrinfo hints; 2991 mach_port_t port; 2992 CFMachPortContext context = { 0, serv, NULL, NULL, NULL }; 2993 CFRunLoopSourceRef rls; 2994 2995 gettimeofday(&serv->u.ipsec.dnsQueryStart, NULL); 2996 2997 bzero(&hints, sizeof(hints)); 2998 hints.ai_flags = AI_ADDRCONFIG; 2999 hints.ai_family = PF_INET; /* only IPv4 */ 3000#ifdef AI_PARALLEL 3001 hints.ai_flags |= AI_PARALLEL; 3002#endif /* AI_PARALLEL */ 3003 3004 error = getaddrinfo_async_start(&port, name, NULL, &hints, 3005 dns_start_query_callback, (void *)serv); 3006 if (error != 0) { 3007 /* save the error associated with the attempt to resolve the name */ 3008 dns_start_query_callback(error, NULL, (void *)serv); 3009 return -1; 3010 } 3011 3012 serv->u.ipsec.dnsPort = _SC_CFMachPortCreateWithPort("PPPController/DNS", port, dns_start_query_cf_callback, &context); 3013 if ( serv->u.ipsec.dnsPort ){ 3014 rls = CFMachPortCreateRunLoopSource(NULL, serv->u.ipsec.dnsPort, 0); 3015 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopCommonModes); 3016 CFRelease(rls); 3017 } 3018 3019 return 0; 3020} 3021 3022/* ----------------------------------------------------------------------------- 3023----------------------------------------------------------------------------- */ 3024int racoon_send_cmd_xauthinfo(int fd, u_int32_t address, struct isakmp_xauth *isakmp_array, int isakmp_nb) 3025{ 3026 u_int8_t *data, *p; 3027 struct vpnctl_cmd_xauth_info *cmd_xauth_info; 3028 int i, totlen = sizeof(struct vpnctl_cmd_xauth_info); 3029 3030 for (i = 0; i < isakmp_nb; i++) { 3031 totlen += sizeof(u_int32_t) + (isakmp_array[i].str ? CFStringGetLength(isakmp_array[i].str) : 0); 3032 } 3033 3034 data = malloc(totlen); 3035 if (!data) { 3036 return -1; 3037 } 3038 3039 cmd_xauth_info = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)data; 3040 bzero(cmd_xauth_info, sizeof(struct vpnctl_cmd_xauth_info)); 3041 cmd_xauth_info->hdr.msg_type = htons(VPNCTL_CMD_XAUTH_INFO); 3042 cmd_xauth_info->hdr.len = htons(totlen - sizeof(struct vpnctl_hdr)); 3043 cmd_xauth_info->address = address; 3044 3045 p = data + sizeof(struct vpnctl_cmd_xauth_info); 3046 3047 for (i = 0; i < isakmp_nb; i++) { 3048 struct isakmp_data d; 3049 3050 CFIndex olen, len = (isakmp_array[i].str ? CFStringGetLength(isakmp_array[i].str) : 0); 3051 CFRange range; 3052 range.location = 0; 3053 range.length = len; 3054 3055 d.type = htons(isakmp_array[i].type); 3056 d.lorv = htons(len); 3057 memcpy(p, &d, sizeof(struct isakmp_data)); // Wcast-align fix - memcpy for unaligned access 3058 p += sizeof(u_int32_t); // skip isakmp_data 3059 if (len) { 3060 CFStringGetBytes(isakmp_array[i].str, range, kCFStringEncodingUTF8, 0, false, p, len, &olen); 3061 p += len; 3062 } 3063 } 3064 3065 write(fd, data, totlen); 3066 3067 IPSECLOGASLMSG("IPSec sending Extended Authentication.\n"); 3068 3069 free(data); 3070 return 0; 3071} 3072 3073 3074/* ----------------------------------------------------------------------------- 3075----------------------------------------------------------------------------- */ 3076int racoon_send_cmd_connect(int fd, u_int32_t address) 3077{ 3078 u_int8_t data[256] __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 3079 struct vpnctl_cmd_connect *cmd_connect = ALIGNED_CAST(struct vpnctl_cmd_connect *)data; 3080 3081 bzero(cmd_connect, sizeof(struct vpnctl_cmd_connect)); 3082 cmd_connect->hdr.len = htons(sizeof(struct vpnctl_cmd_connect) - sizeof(struct vpnctl_hdr)); 3083 cmd_connect->hdr.msg_type = htons(VPNCTL_CMD_CONNECT); 3084 cmd_connect->address = address; 3085 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: sending CONNECT to racoon control socket")); 3086 write(fd, cmd_connect, sizeof(struct vpnctl_cmd_connect)); 3087 IPSECLOGASLMSG("IPSec Phase1 starting.\n"); // connect command triggers phase1 3088 return 0; 3089} 3090 3091/* ----------------------------------------------------------------------------- 3092----------------------------------------------------------------------------- */ 3093int racoon_send_cmd_disconnect(int fd, u_int32_t address) 3094{ 3095 u_int8_t data[256] __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 3096 struct vpnctl_cmd_connect *cmd_connect = ALIGNED_CAST(struct vpnctl_cmd_connect *)data; 3097 3098 bzero(cmd_connect, sizeof(struct vpnctl_cmd_connect)); 3099 cmd_connect->hdr.len = htons(sizeof(struct vpnctl_cmd_connect) - sizeof(struct vpnctl_hdr)); 3100 cmd_connect->hdr.msg_type = htons(VPNCTL_CMD_DISCONNECT); 3101 cmd_connect->address = address; 3102 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: sending DISCONNECT to racoon control socket, address 0x%x"), ntohl(address)); 3103 write(fd, cmd_connect, sizeof(struct vpnctl_cmd_connect)); 3104 return 0; 3105} 3106 3107/* ----------------------------------------------------------------------------- 3108 ----------------------------------------------------------------------------- */ 3109int racoon_send_cmd_start_dpd(int fd, u_int32_t address) 3110{ 3111 u_int8_t data[256] __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 3112 struct vpnctl_cmd_start_dpd *cmd_start_dpd = ALIGNED_CAST(struct vpnctl_cmd_start_dpd *)data; 3113 3114 bzero(cmd_start_dpd, sizeof(struct vpnctl_cmd_start_dpd)); 3115 cmd_start_dpd->hdr.len = htons(sizeof(struct vpnctl_cmd_start_dpd) - sizeof(struct vpnctl_hdr)); 3116 cmd_start_dpd->hdr.msg_type = htons(VPNCTL_CMD_START_DPD); 3117 cmd_start_dpd->address = address; 3118 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: sending START_DPD to racoon control socket")); 3119 write(fd, cmd_start_dpd, sizeof(struct vpnctl_cmd_start_dpd)); 3120 return 0; 3121} 3122 3123 3124/* ----------------------------------------------------------------------------- 3125----------------------------------------------------------------------------- */ 3126int racoon_send_cmd_bind(int fd, u_int32_t address, char *version) 3127{ 3128 u_int8_t data[256] __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 3129 struct vpnctl_cmd_bind *cmd_bind = ALIGNED_CAST(struct vpnctl_cmd_bind *)data; 3130 int vers_len = 0; 3131 3132 if (version) 3133 vers_len = strlen(version); 3134 3135 bzero(cmd_bind, sizeof(struct vpnctl_cmd_bind)); 3136 cmd_bind->hdr.len = htons(sizeof(struct vpnctl_cmd_bind) - sizeof(struct vpnctl_hdr) + vers_len); 3137 cmd_bind->hdr.msg_type = htons(VPNCTL_CMD_BIND); 3138 cmd_bind->address = address; 3139 cmd_bind->vers_len = htons(vers_len); 3140 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: sending BIND to racoon control socket")); 3141 write(fd, cmd_bind, sizeof(struct vpnctl_cmd_bind)); 3142 if (vers_len) 3143 write(fd, version, vers_len); 3144 return 0; 3145} 3146 3147/* ----------------------------------------------------------------------------- 3148----------------------------------------------------------------------------- */ 3149int racoon_send_cmd_unbind(int fd, u_int32_t address) 3150{ 3151 u_int8_t data[256] __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 3152 struct vpnctl_cmd_unbind *cmd_unbind = ALIGNED_CAST(struct vpnctl_cmd_unbind *)data; 3153 3154 bzero(cmd_unbind, sizeof(struct vpnctl_cmd_unbind)); 3155 cmd_unbind->hdr.len = htons(sizeof(struct vpnctl_cmd_unbind) - sizeof(struct vpnctl_hdr)); 3156 cmd_unbind->hdr.msg_type = htons(VPNCTL_CMD_UNBIND); 3157 cmd_unbind->address = address; 3158 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: sending UNBIND to racoon control socket")); 3159 write(fd, cmd_unbind, sizeof(struct vpnctl_cmd_unbind)); 3160 return 0; 3161} 3162 3163/* ----------------------------------------------------------------------------- 3164----------------------------------------------------------------------------- */ 3165int racoon_send_cmd_start_ph2(int fd, u_int32_t address, CFDictionaryRef ipsec_dict) 3166{ 3167 u_int8_t *p; 3168 struct vpnctl_cmd_start_ph2 *cmd_start_ph2 = NULL; 3169 struct vpnctl_algo *algo; 3170 int policy_count; 3171 u_int16_t selector_count = 0; 3172 int nb, i; 3173 char src_address[32], dst_address[32], str[32]; 3174 u_int32_t remote_address; 3175 CFArrayRef policies; 3176 CFIndex start, end; 3177 size_t bufsiz, msglen; 3178 char *errstr = '\0'; 3179 3180#define NB_ALGOS 6 3181 3182 policy_count = IPSecCountPolicies(ipsec_dict); 3183 if (policy_count <= 0) { 3184 errstr = "cannot create ph2 config - no policies found"; 3185 goto fail; 3186 } 3187 3188 /* allocate max space needed - adjust len later */ 3189 bufsiz = sizeof(struct vpnctl_cmd_start_ph2) + ((policy_count * sizeof(struct vpnctl_sa_selector)) * 2) + (NB_ALGOS * sizeof(struct vpnctl_algo)); 3190 cmd_start_ph2 = malloc(bufsiz); 3191 if (cmd_start_ph2 == NULL) { 3192 errstr = "out of memory"; 3193 goto fail; 3194 } 3195 3196 bzero(cmd_start_ph2, bufsiz); 3197 cmd_start_ph2->hdr.msg_type = htons(VPNCTL_CMD_START_PH2); 3198 cmd_start_ph2->address = address; 3199 3200 /* XXX let use default for now */ 3201 cmd_start_ph2->lifetime = htonl(3600); 3202 cmd_start_ph2->selector_count = 0; 3203 cmd_start_ph2->algo_count = htons(NB_ALGOS); 3204 3205 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecLocalAddress, src_address, sizeof(src_address))) { 3206 errstr = "incorrect local address"; 3207 goto fail; 3208 } 3209 3210 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecRemoteAddress, dst_address, sizeof(dst_address))) { 3211 errstr = "incorrect remote address"; 3212 goto fail; 3213 } 3214 3215 if (!inet_aton(dst_address, (struct in_addr *)&remote_address)) { 3216 errstr = "invalid remote address"; 3217 goto fail; 3218 } 3219 3220 if (remote_address != address) { 3221 errstr = "remote address mismatch"; 3222 goto fail; 3223 } 3224 3225 policies = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecPolicies); 3226 if (!isArray(policies) || (nb = CFArrayGetCount(policies)) == 0) { 3227 errstr = "no policy found"; 3228 goto fail; 3229 } 3230 3231 start = 0; 3232 end = nb; 3233 3234 p = ((u_int8_t *)(cmd_start_ph2)) + sizeof(struct vpnctl_cmd_start_ph2); 3235 3236 for (i = start; i < end; i++) { 3237 3238 int tunnel, in, out; 3239 CFDictionaryRef policy; 3240 CFStringRef policymode, policydirection, policylevel; 3241 struct in_addr local_net_address, remote_net_address; 3242 u_int16_t local_net_port, remote_net_port; 3243 u_int32_t local_prefix, remote_prefix, local_mask, remote_mask; 3244 u_int32_t protocol; 3245 struct vpnctl_sa_selector *sa; 3246 3247 protocol = 0xFF; 3248 3249 policy = CFArrayGetValueAtIndex(policies, i); 3250 if (!isDictionary(policy)) { 3251 errstr = "incorrect policy found"; 3252 goto fail; 3253 } 3254 3255 /* build policies in and out */ 3256 3257 tunnel = 1; 3258 policymode = CFDictionaryGetValue(policy, kRASPropIPSecPolicyMode); 3259 if (isString(policymode)) { 3260 3261 if (CFEqual(policymode, kRASValIPSecPolicyModeTunnel)) 3262 tunnel = 1; 3263 else if (CFEqual(policymode, kRASValIPSecPolicyModeTransport)) 3264 tunnel = 0; 3265 else { 3266 errstr = "incorrect policy type found"; 3267 goto fail; 3268 } 3269 } 3270 3271 /* if policy direction is not specified, in/out is assumed */ 3272 in = out = 1; 3273 policydirection = CFDictionaryGetValue(policy, kRASPropIPSecPolicyDirection); 3274 if (isString(policydirection)) { 3275 3276 if (CFEqual(policydirection, kRASValIPSecPolicyDirectionIn)) 3277 out = 0; 3278 else if (CFEqual(policydirection, kRASValIPSecPolicyDirectionOut)) 3279 in = 0; 3280 else if (!CFEqual(policydirection, kRASValIPSecPolicyDirectionInOut)) { 3281 errstr = "incorrect policy direction found"; 3282 goto fail; 3283 } 3284 } 3285 3286 policylevel = CFDictionaryGetValue(policy, kRASPropIPSecPolicyLevel); 3287 if (!isString(policylevel) || 3288 (!CFEqual(policylevel, kRASValIPSecPolicyLevelUnique) && !CFEqual(policylevel, kRASValIPSecPolicyLevelRequire))) 3289 continue; 3290 3291 if (tunnel) { 3292 3293 int j; 3294 3295 /* get local and remote networks */ 3296 3297 if (!GetStrAddrFromDict(policy, kRASPropIPSecPolicyLocalAddress, str, sizeof(str))) { 3298 errstr = "incorrect local network"; 3299 goto fail; 3300 } 3301 3302 local_net_port = htons(0); 3303 if (!inet_aton(str, &local_net_address)) { 3304 errstr = "incorrect local network"; 3305 goto fail; 3306 } 3307 3308 GetIntFromDict(policy, kRASPropIPSecPolicyLocalPrefix, &local_prefix, 32); 3309 for (j = 0, local_mask = 0; j < local_prefix; j++) 3310 local_mask = (local_mask >> 1) | 0x80000000; 3311 3312 if (!GetStrAddrFromDict(policy, kRASPropIPSecPolicyRemoteAddress, str, sizeof(str))) { 3313 errstr = "incorrect remote network"; 3314 goto fail; 3315 } 3316 3317 remote_net_port = htons(0); 3318 if (!inet_aton(str, &remote_net_address)) { 3319 errstr = "incorrect remote network"; 3320 goto fail; 3321 } 3322 3323 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePrefix, &remote_prefix, 32); 3324 for (j = 0, remote_mask = 0; j < remote_prefix; j++) 3325 remote_mask = (remote_mask >> 1) | 0x80000000; 3326 3327 } 3328 else { 3329 u_int32_t val; 3330 3331 GetIntFromDict(policy, kRASPropIPSecPolicyLocalPort, &val, 0); 3332 local_net_port = htons(val); 3333 if (!inet_aton(src_address, &local_net_address)) { 3334 errstr = "incorrect local address"; 3335 goto fail; 3336 } 3337 3338 local_mask = local_net_address.s_addr ? 0xFFFFFFFF : 0; 3339 3340 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePort, &val, 0); 3341 remote_net_port = htons(val); 3342 if (!inet_aton(dst_address, &remote_net_address)) { 3343 errstr = "incorrect remote address"; 3344 goto fail; 3345 } 3346 3347 remote_mask = remote_net_address.s_addr ? 0xFFFFFFFF : 0; 3348 3349 GetIntFromDict(policy, kRASPropIPSecPolicyProtocol, &protocol, 0); 3350 3351 } 3352 3353 /* setup phase2 command */ 3354 3355 if (out) { 3356 sa = ALIGNED_CAST(struct vpnctl_sa_selector *)p; 3357 sa->src_tunnel_address = local_net_address.s_addr; 3358 sa->src_tunnel_mask = htonl(local_mask); 3359 sa->src_tunnel_port = local_net_port; 3360 sa->dst_tunnel_address = remote_net_address.s_addr; 3361 sa->dst_tunnel_mask = htonl(remote_mask); 3362 sa->dst_tunnel_port = remote_net_port; 3363 sa->ul_protocol = htons((u_int16_t)protocol); 3364 selector_count++; 3365 p += sizeof(struct vpnctl_sa_selector); 3366 } 3367 3368 if (in) { 3369 sa = ALIGNED_CAST(struct vpnctl_sa_selector *)p; 3370 sa->dst_tunnel_address = local_net_address.s_addr; 3371 sa->dst_tunnel_mask = htonl(local_mask); 3372 sa->dst_tunnel_port = local_net_port; 3373 sa->src_tunnel_address = remote_net_address.s_addr; 3374 sa->src_tunnel_mask = htonl(remote_mask); 3375 sa->src_tunnel_port = remote_net_port; 3376 sa->ul_protocol = htons((u_int16_t)protocol); 3377 selector_count++; 3378 p += sizeof(struct vpnctl_sa_selector); 3379 } 3380 } 3381 cmd_start_ph2->selector_count = htons(selector_count); 3382 3383 algo = ALIGNED_CAST(struct vpnctl_algo *)p; 3384 algo->algo_class = htons(algclass_ipsec_enc); 3385 algo->algo = htons(algtype_aes); 3386 algo->key_len = htons(256); 3387 3388 p += sizeof(struct vpnctl_algo); 3389 algo = ALIGNED_CAST(struct vpnctl_algo *)p; 3390 algo->algo_class = htons(algclass_ipsec_enc); 3391 algo->algo = htons(algtype_aes); 3392 algo->key_len = htons(0); 3393 3394 p += sizeof(struct vpnctl_algo); 3395 algo = ALIGNED_CAST(struct vpnctl_algo *)p; 3396 algo->algo_class = htons(algclass_ipsec_enc); 3397 algo->algo = htons(algtype_3des); 3398 algo->key_len = htons(0); 3399 3400 p += sizeof(struct vpnctl_algo); 3401 algo = ALIGNED_CAST(struct vpnctl_algo *)p; 3402 algo->algo_class = htons(algclass_ipsec_auth); 3403 algo->algo = htons(algtype_hmac_sha1); 3404 algo->key_len = htons(0); 3405 3406 p += sizeof(struct vpnctl_algo); 3407 algo = ALIGNED_CAST(struct vpnctl_algo *)p; 3408 algo->algo_class = htons(algclass_ipsec_auth); 3409 algo->algo = htons(algtype_hmac_md5); 3410 algo->key_len = htons(0); 3411 3412 p += sizeof(struct vpnctl_algo); 3413 algo = ALIGNED_CAST(struct vpnctl_algo *)p; 3414 algo->algo_class = htons(algclass_ipsec_comp); 3415 algo->algo = htons(algtype_deflate); 3416 algo->key_len = htons(0); 3417 3418 msglen = sizeof(struct vpnctl_cmd_start_ph2) + 3419 (selector_count * sizeof(struct vpnctl_sa_selector)) + 3420 (NB_ALGOS * sizeof(struct vpnctl_algo)); 3421 cmd_start_ph2->hdr.len = htons(msglen - sizeof(struct vpnctl_hdr)); 3422 3423 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: sending START_PH2 to racoon control socket")); 3424 write(fd, cmd_start_ph2, msglen); 3425 IPSECLOGASLMSG("IPSec Phase2 starting.\n"); 3426 3427 free(cmd_start_ph2); 3428 return 0; 3429 3430fail: 3431 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: failed to start phase2 - '%s'"), errstr); 3432 if (cmd_start_ph2) 3433 free(cmd_start_ph2); 3434 return -1; 3435} 3436 3437/* ----------------------------------------------------------------------------- 3438 ----------------------------------------------------------------------------- */ 3439int racoon_send_cmd_assert (struct service *serv) 3440{ 3441 struct vpnctl_cmd_assert msg; 3442 CFRunLoopTimerContext context = { 0, serv, NULL, NULL, NULL }; 3443 3444 bzero(&msg, sizeof(msg)); 3445 msg.hdr.msg_type = htons(VPNCTL_CMD_ASSERT); 3446 msg.src_address = serv->u.ipsec.our_address.sin_addr.s_addr; 3447 msg.dst_address = serv->u.ipsec.peer_address.sin_addr.s_addr; 3448 msg.hdr.len = htons(sizeof(msg) - sizeof(msg.hdr));; 3449 3450 write(serv->u.ipsec.controlfd, &msg, sizeof(msg)); 3451 serv->u.ipsec.ping_count = 0; 3452 3453 IPSEC_ASSERT_IDLE(serv->u.ipsec); 3454 if (!serv->u.ipsec.timerref) { 3455 serv->u.ipsec.timerref = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + TIMEOUT_ASSERT_IDLE, FAR_FUTURE, 0, 0, racoon_timer, &context); 3456 if (!serv->u.ipsec.timerref) { 3457 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: assert cannot create RunLoop timer")); 3458 goto fail; 3459 } 3460 CFRunLoopAddTimer(CFRunLoopGetCurrent(), serv->u.ipsec.timerref, kCFRunLoopCommonModes); 3461 } else { 3462 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_ASSERT_IDLE); 3463 } 3464 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: wait for %d secs before forcing SAs to rekey"), TIMEOUT_ASSERT_IDLE); 3465 return 0; 3466 3467fail: 3468 if (serv->u.ipsec.laststatus == IPSEC_NO_ERROR) 3469 serv->u.ipsec.laststatus = IPSEC_GENERIC_ERROR; 3470 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: ASSERT failed")); 3471 ipsec_stop(serv, 0); 3472 return -1; 3473} 3474 3475/* ----------------------------------------------------------------------------- 3476----------------------------------------------------------------------------- */ 3477 3478static 3479int racoon_restart(struct service *serv, struct sockaddr_in *address) 3480{ 3481 char *errorstr; 3482 int error, need_kick = 0, found; 3483 CFStringRef string; 3484 CFRunLoopTimerContext context = { 0, serv, NULL, NULL, NULL }; 3485 CFDictionaryRef userdict = 0; 3486 Boolean using_temp_xauth_name = FALSE; 3487 CFTypeRef value; 3488 3489 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: racoon_restart...")); 3490 3491 /* unconfigure ipsec first */ 3492 if (serv->u.ipsec.policies_installed) { 3493 error = IPSecRemovePolicies(serv->u.ipsec.config, -1, &errorstr); 3494 if (error) 3495 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Cannot remove policies, error '%s'"), errorstr); 3496 3497 IPSecRemoveSecurityAssociations((struct sockaddr *)&serv->u.ipsec.our_address, (struct sockaddr *)&serv->u.ipsec.peer_address); 3498 serv->u.ipsec.policies_installed = 0; 3499 } 3500 if (serv->ne_sm_bridge != NULL) { 3501 ne_sm_bridge_request_uninstall(serv->ne_sm_bridge); 3502 } 3503 uninstall_mode_config(serv, TRUE); 3504 3505 if (serv->u.ipsec.config_applied) { 3506 // just remove the file, as will kill kick racoon with the config of the load balancing adress 3507 // this is to avoid useless sighup of racoon 3508 error = IPSecRemoveConfigurationFile(serv->u.ipsec.config, &errorstr); 3509 if (error) 3510 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Cannot remove configuration, error '%s'"), errorstr); 3511 serv->u.ipsec.config_applied = 0; 3512 need_kick = 1; 3513 } 3514 3515 serv->u.ipsec.ping_count = 0; 3516 3517 CLEAR_VPN_PORTMAPPING(serv); 3518 3519 /* then try new address */ 3520 bcopy(address, &serv->u.ipsec.peer_address, sizeof(serv->u.ipsec.peer_address)); 3521 3522 bool useBoundInterface = FALSE; 3523 if (serv->connectopts) { 3524 if (GetStrFromDict(serv->connectopts, CFSTR(NESessionStartOptionOutgoingInterface), serv->u.ipsec.lower_interface, sizeof(serv->u.ipsec.lower_interface), "")) { 3525 useBoundInterface = TRUE; 3526 } 3527 } 3528 3529 if (get_src_address((struct sockaddr *)&serv->u.ipsec.our_address, (struct sockaddr *)&serv->u.ipsec.peer_address, useBoundInterface ? serv->u.ipsec.lower_interface : NULL, NULL)) { 3530 serv->u.ipsec.laststatus = IPSEC_NOLOCALNETWORK_ERROR; 3531 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot get our local address...")); 3532 goto fail; 3533 } 3534 3535 if (!useBoundInterface) { 3536 copyGateway(gDynamicStore, AF_INET, 3537 serv->u.ipsec.lower_interface, sizeof(serv->u.ipsec.lower_interface), 3538 (struct sockaddr *)&serv->u.ipsec.lower_gateway, sizeof(serv->u.ipsec.lower_gateway)); 3539 } 3540 3541#if !TARGET_OS_EMBEDDED 3542 serv->u.ipsec.lower_interface_media = get_if_media(serv->u.ipsec.lower_interface); 3543 serv->u.ipsec.timeout_lower_interface_change = get_interface_timeout(serv->u.ipsec.lower_interface_media); 3544#else 3545 serv->u.ipsec.lower_interface_media = 0; 3546 serv->u.ipsec.timeout_lower_interface_change = get_interface_timeout(0); 3547#endif /* !iPhone */ 3548 3549 // check to see if interface is captive: if so, bail if the interface is not ready. 3550 if (check_interface_captive_and_not_ready(gDynamicStore, serv->u.ipsec.lower_interface)) { 3551 // TODO: perhaps we should wait for a few seconds? 3552 goto fail; 3553 } 3554 3555 TRACK_VPN_LOCATION(serv); 3556 3557 /* if retry, then change src/dst address, otherwise create the config */ 3558 if (!serv->u.ipsec.config) { 3559 3560 CFStringRef auth_method; 3561 auth_method = CFDictionaryGetValue(serv->systemprefs, kRASPropIPSecAuthenticationMethod); 3562 if (!isString(auth_method) || CFEqual(auth_method, kRASValIPSecAuthenticationMethodSharedSecret)) { 3563 auth_method = kRASValIPSecAuthenticationMethodSharedSecret; 3564 3565 } 3566 else if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate)) { 3567 serv->flags |= FLAG_USECERTIFICATE; 3568#if 0 3569 /* need to check for share secret at some point in the path */ 3570 certificate = CFDictionaryGetValue(useripsec_dict, kRASPropIPSecLocalCertificate); 3571 if (!isData(certificate)) { 3572 devstatus = EXIT_L2TP_NOCERTIFICATE; 3573 error("L2TP: no user certificate found.\n"); 3574 goto fail; 3575 } 3576#endif 3577 } 3578 3579 CFStringRef verify_id; 3580 verify_id = CFDictionaryGetValue(serv->systemprefs, kRASPropIPSecIdentifierVerification); 3581 if (verify_id && !isString(verify_id)) { 3582#if 0 3583 /* need to check correct value */ 3584 error("L2TP: incorrect identifier verification found.\n"); 3585 goto fail; 3586#endif 3587 } 3588 3589 3590 /* now create the default config */ 3591 CFStringRef remote_address = CFDictionaryGetValue(serv->systemprefs, kRASPropIPSecRemoteAddress); 3592 3593 serv->u.ipsec.config = IPSecCreateCiscoDefaultConfiguration(&serv->u.ipsec.our_address, 3594 &serv->u.ipsec.peer_address, cfstring_is_ip(remote_address) ? NULL : remote_address, auth_method, 3595 1, 0, verify_id); 3596 if (!serv->u.ipsec.config) { 3597 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot create IPSec dictionary...")); 3598 goto fail; 3599 } 3600 3601 /* merge the system config prefs into the default dictionary */ 3602 CFDictionaryApplyFunction(serv->systemprefs, merge_ipsec_dict, serv->u.ipsec.config); 3603 3604 if (useBoundInterface) { 3605 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecForceLocalAddress, kCFBooleanTrue); 3606 } 3607 3608 // by default, want to configure idle time out when connecting OnDemand 3609 if (serv->flags & FLAG_ONDEMAND) { 3610 CFNumberRef num; 3611 int val; 3612 3613 val = 1; 3614 if ((num = CFNumberCreate(NULL, kCFNumberIntType, &val))) { 3615 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecDisconnectOnIdle, num); 3616 CFRelease(num); 3617 } 3618 val = 120; // 2 minutes by default 3619 if ((num = CFNumberCreate(NULL, kCFNumberIntType, &val))) { 3620 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecDisconnectOnIdleTimer, num); 3621 CFRelease(num); 3622 } 3623 } 3624 3625 if (serv->connectopts && (userdict = CFDictionaryGetValue(serv->connectopts, kSCEntNetIPSec))) { 3626 3627 value = CFDictionaryGetValue(userdict, kRASPropIPSecXAuthName); 3628 if (isString(value)) 3629 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecXAuthName, value); 3630 3631 value = CFDictionaryGetValue(userdict, kRASPropIPSecXAuthPassword); 3632 if (isString(value)) 3633 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecXAuthPassword, value); 3634 } 3635 3636 3637 /* Change to Hybrid authentication if applicable */ 3638 #define IPSecLocalIdentifierHybridSuffix CFSTR("[hybrid]") 3639 value = CFDictionaryGetValue(serv->u.ipsec.config, kRASPropIPSecLocalIdentifier); 3640 if (isString(value) && CFStringHasSuffix(value, IPSecLocalIdentifierHybridSuffix)) { 3641 CFStringRef value1 = CFStringCreateWithSubstring(NULL, value, CFRangeMake(0, CFStringGetLength(value) - CFStringGetLength(IPSecLocalIdentifierHybridSuffix))); 3642 if (value1) { 3643 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecLocalIdentifier, value1); 3644 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecAuthenticationMethod, kRASValIPSecAuthenticationMethodHybrid); 3645 CFRelease(value1); 3646 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecRemoteIdentifier, remote_address); 3647 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecIdentifierVerification, kRASValIPSecIdentifierVerificationUseRemoteIdentifier); 3648 } 3649 } 3650 3651 /* Complete shared secret, with defaut convention "serviceID.SS" if necessary */ 3652 if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodSharedSecret)) { 3653 3654 found = 0; 3655 /* first check is secret is available in the prefs */ 3656 CFStringRef secret_string = CFDictionaryGetValue(serv->u.ipsec.config, kRASPropIPSecSharedSecret); 3657 if (isString(secret_string)) { 3658 /* secret or secret keychain is in the prefs, leave it alone */ 3659 found = 1; 3660 } 3661 else { 3662 /* encryption is not specified, and secret was missing. check connect options */ 3663 if (serv->connectopts && userdict != NULL) { 3664 CFStringRef secret_string = CFDictionaryGetValue(userdict, kRASPropIPSecSharedSecret); 3665 if (isString(secret_string)) { 3666 found = 1; 3667 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecSharedSecret, secret_string); 3668 CFDictionaryRemoveValue(serv->u.ipsec.config, kRASPropIPSecSharedSecretEncryption); 3669 } 3670 } 3671 else { 3672 /* secret is not in the prefs, check for encryption pref */ 3673 CFStringRef secret_encryption_string = CFDictionaryGetValue(serv->u.ipsec.config, kRASPropIPSecSharedSecretEncryption); 3674 if (my_CFEqual(secret_encryption_string, kRASValIPSecSharedSecretEncryptionKeychain)) { 3675 /* encryption is KeyChain. Create a default secret key for the key chain */ 3676 secret_string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@.SS"), serv->serviceID); 3677 if (secret_string) { 3678 found = 1; 3679 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecSharedSecret, secret_string); 3680 CFRelease(secret_string); 3681 } 3682 } 3683 } 3684 } 3685 3686 if (!found) { 3687 serv->u.ipsec.laststatus = IPSEC_NOSHAREDSECRET_ERROR; 3688 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: incorrect shared secret found.")); 3689 goto fail; 3690 } 3691 3692 } 3693 } 3694 else { 3695 string = CFStringCreateWithCString(0, addr2ascii(AF_INET, &serv->u.ipsec.our_address.sin_addr, sizeof(serv->u.ipsec.our_address.sin_addr), 0), kCFStringEncodingASCII); 3696 if (string) { 3697 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecLocalAddress, string); 3698 CFRelease(string); 3699 } 3700 string = CFStringCreateWithCString(0, addr2ascii(AF_INET, &serv->u.ipsec.peer_address.sin_addr, sizeof(serv->u.ipsec.peer_address.sin_addr), 0), kCFStringEncodingASCII); 3701 if (string) { 3702 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecRemoteAddress, string); 3703 CFRelease(string); 3704 } 3705 if (useBoundInterface) { 3706 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecForceLocalAddress, kCFBooleanTrue); 3707 } 3708 } 3709 3710 ipsec_log(LOG_DEBUG, CFSTR("IPSec Controller: Complete IPsec dictionary %@"), serv->u.ipsec.config); 3711 3712 /* Temporarily add in XAuthName if missing when creating the racoon conf file */ 3713 if (!CFDictionaryContainsKey(serv->u.ipsec.config, kRASPropIPSecXAuthName)) { 3714 CFDictionarySetValue(serv->u.ipsec.config, kRASPropIPSecXAuthName, CFSTR(" ")); 3715 using_temp_xauth_name = TRUE; 3716 } 3717 error = IPSecApplyConfiguration(serv->u.ipsec.config, &errorstr); 3718 if (using_temp_xauth_name) { 3719 CFDictionaryRemoveValue(serv->u.ipsec.config, kRASPropIPSecXAuthName); 3720 } 3721 if (error) { 3722 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Cannot apply configuration, error '%s'"), errorstr); 3723 serv->u.ipsec.laststatus = IPSEC_CONFIGURATION_ERROR; 3724 goto fail; 3725 } 3726 3727 serv->u.ipsec.config_applied = 1; 3728 need_kick = 0; 3729 3730 /* Install policies and trigger racoon */ 3731 if (IPSecCountPolicies(serv->u.ipsec.config)) { 3732 error = IPSecInstallPolicies(serv->u.ipsec.config, -1, &errorstr); 3733 if (error) { 3734 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Cannot install policies, error '%s'"), errorstr); 3735 serv->u.ipsec.laststatus = IPSEC_CONFIGURATION_ERROR; 3736 goto fail; 3737 } 3738 3739 serv->u.ipsec.policies_installed = 1; 3740 } 3741 3742 /* open and connect to the racoon control socket */ 3743 if (serv->u.ipsec.controlfd == -1) { 3744 if (racoon_create_socket(serv) < 0) { 3745 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot create racoon control socket")); 3746 serv->u.ipsec.laststatus = IPSEC_RACOONCONTROL_ERROR; 3747 goto fail; 3748 } 3749 } 3750 else { 3751 racoon_send_cmd_unbind(serv->u.ipsec.controlfd, htonl(0xFFFFFFFF)); 3752 } 3753 3754 SET_VPN_PORTMAPPING(serv); 3755 3756 racoon_send_cmd_bind(serv->u.ipsec.controlfd, serv->u.ipsec.peer_address.sin_addr.s_addr, gIPSecAppVersion); 3757 racoon_send_cmd_connect(serv->u.ipsec.controlfd, serv->u.ipsec.peer_address.sin_addr.s_addr); 3758 3759 if (!serv->u.ipsec.timerref) { 3760 serv->u.ipsec.timerref = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + TIMEOUT_INITIAL_CONTACT, FAR_FUTURE, 0, 0, racoon_timer, &context); 3761 if (!serv->u.ipsec.timerref) { 3762 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot create RunLoop timer")); 3763 goto fail; 3764 } 3765 CFRunLoopAddTimer(CFRunLoopGetCurrent(), serv->u.ipsec.timerref, kCFRunLoopCommonModes); 3766 } 3767 else { 3768 CFRunLoopTimerSetNextFireDate(serv->u.ipsec.timerref, CFAbsoluteTimeGetCurrent() + TIMEOUT_INITIAL_CONTACT); 3769 } 3770 return 0; 3771 3772fail: 3773 if (serv->u.ipsec.laststatus == IPSEC_NO_ERROR) 3774 serv->u.ipsec.laststatus = IPSEC_GENERIC_ERROR; 3775 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: restart failed")); 3776 if (need_kick) 3777 IPSecKickConfiguration(); 3778 ipsec_stop(serv, 0); 3779 return serv->u.ipsec.laststatus; 3780} 3781 3782 3783#if TARGET_OS_EMBEDDED 3784/* ----------------------------------------------------------------------------- 3785 ----------------------------------------------------------------------------- */ 3786void ipsec_cellular_event(struct service *serv, int event) 3787{ 3788 switch (event) { 3789 case CELLULAR_BRINGUP_SUCCESS_EVENT: 3790 racoon_resolve(serv); 3791 break; 3792 case CELLULAR_BRINGUP_FATAL_FAILURE_EVENT: 3793 case CELLULAR_BRINGUP_NETWORK_FAILURE_EVENT: 3794 serv->u.ipsec.laststatus = IPSEC_EDGE_ACTIVATION_ERROR; 3795 ipsec_stop(serv, 0); 3796 break; 3797 } 3798} 3799#endif 3800 3801/* ----------------------------------------------------------------------------- 3802 ----------------------------------------------------------------------------- */ 3803int racoon_resolve(struct service *serv) 3804{ 3805 char remoteaddress[255]; 3806 3807 GetStrFromDict (serv->systemprefs, kRASPropIPSecRemoteAddress, remoteaddress, sizeof(remoteaddress), ""); 3808 3809 serv->u.ipsec.peer_address.sin_len = sizeof(serv->u.ipsec.peer_address); 3810 serv->u.ipsec.peer_address.sin_family = AF_INET; 3811 serv->u.ipsec.peer_address.sin_port = htons(0); 3812 if (!inet_aton(remoteaddress, &serv->u.ipsec.peer_address.sin_addr)) { 3813 if (dns_start_query(serv, remoteaddress)) { 3814 serv->u.ipsec.laststatus = IPSEC_RESOLVEADDRESS_ERROR; 3815 goto fail; 3816 } 3817 return 0; 3818 } 3819 3820 return racoon_restart(serv, &serv->u.ipsec.peer_address); 3821 3822fail: 3823 if (serv->u.ipsec.laststatus == IPSEC_NO_ERROR) 3824 serv->u.ipsec.laststatus = IPSEC_GENERIC_ERROR; 3825 3826 ipsec_stop(serv, 0); 3827 return serv->u.ipsec.laststatus; 3828} 3829 3830/* ----------------------------------------------------------------------------- 3831 ----------------------------------------------------------------------------- */ 3832int ipsec_start(struct service *serv, CFDictionaryRef options, uid_t uid, gid_t gid, mach_port_t bootstrap, u_int8_t onTraffic, u_int8_t onDemand) 3833{ 3834 char remoteaddress[255]; 3835 3836 if (serv->initialized == FALSE) { 3837 serv->u.ipsec.laststatus = IPSEC_CONFIGURATION_ERROR; 3838 display_notification(serv, NULL, serv->u.ipsec.laststatus, dialog_default_type); 3839 return serv->u.ipsec.laststatus; 3840 } 3841 3842 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ipsec_start, ondemand flag = %d"), onDemand); 3843 3844 switch (serv->u.ipsec.phase) { 3845 case IPSEC_IDLE: 3846 break; 3847 3848 default: 3849 if (my_CFEqual(options, serv->connectopts)) { 3850 // notify client, so at least then can get the status if they were waiting got it 3851 phase_changed(serv, serv->u.ipsec.phase); 3852 return 0; 3853 } 3854 return EIO; // not the right time to dial 3855 } 3856 3857 /* check for pending cert invalid alert */ 3858 if (serv->userNotificationRef) { 3859 if ( onDemand ){ 3860 if (IPSEC_STATUS_IS_CLIENT_CERTIFICATE_INVALID(serv->u.ipsec.laststatus)){ 3861 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: ipsec_start fails cert validity, returns error %d "), serv->u.ipsec.laststatus); 3862 return serv->u.ipsec.laststatus; 3863 } 3864 } 3865 CFUserNotificationCancel(serv->userNotificationRef); 3866 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), serv->userNotificationRLS, kCFRunLoopDefaultMode); 3867 my_CFRelease(&serv->userNotificationRef); 3868 my_CFRelease(&serv->userNotificationRLS); 3869 } 3870 3871 ipsec_updatephase(serv, IPSEC_INITIALIZE); 3872 IPSEC_UNASSERT(serv->u.ipsec); 3873 serv->was_running = 0; 3874 service_started(serv); 3875 serv->u.ipsec.laststatus = IPSEC_NO_ERROR; 3876 serv->u.ipsec.resolvedAddress = 0; 3877 serv->u.ipsec.resolvedAddressError = NETDB_SUCCESS; 3878 serv->u.ipsec.next_address = 0; 3879 serv->u.ipsec.ping_count = 0; 3880 serv->u.ipsec.awaiting_peer_resp = 0; 3881 3882 serv->connectopts = options; 3883 my_CFRetain(serv->connectopts); 3884 3885 serv->uid = uid; 3886 serv->gid = gid; 3887 3888 scnc_bootstrap_retain(serv, bootstrap); 3889 3890 if (onDemand) 3891 serv->flags |= FLAG_ONDEMAND; 3892 else 3893 serv->flags &= ~FLAG_ONDEMAND; 3894 serv->flags &= ~FLAG_USECERTIFICATE; 3895 3896 ipsec_log(LOG_DEBUG, CFSTR("IPSec Controller: IPSec System Prefs %@"), serv->systemprefs); 3897 3898#if DEBUG /* connectopts can contain cleartext passwords */ 3899 ipsec_log(LOG_DEBUG, CFSTR("IPSec Controller: IPSec User Options %@"), serv->connectopts); 3900#endif 3901 3902 /* build the peer address */ 3903 if (!GetStrFromDict (serv->systemprefs, kRASPropIPSecRemoteAddress, remoteaddress, sizeof(remoteaddress), "")) { 3904 serv->u.ipsec.laststatus = IPSEC_NOSERVERADDRESS_ERROR; 3905 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot find RemoteAddress ...")); 3906 goto fail; 3907 } 3908 if (!racoon_validate_cfg_str(remoteaddress)) { 3909 serv->u.ipsec.laststatus = IPSEC_NOSERVERADDRESS_ERROR; 3910 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: invalid RemoteAddress ...")); 3911 goto fail; 3912 } 3913 3914 IPSECLOGASLMSG("IPSec connecting to server %s\n", remoteaddress); 3915 3916 { 3917 serv->u.ipsec.xauth_flags = XAUTH_FIRST_TIME; 3918 // force prompt if necessary 3919 CFStringRef encryption = CFDictionaryGetValue(serv->systemprefs, kSCPropNetIPSecXAuthPasswordEncryption); 3920 if (isString(encryption) 3921 && CFStringCompare(encryption, kSCValNetIPSecXAuthPasswordEncryptionPrompt, 0) == kCFCompareEqualTo) { 3922 serv->u.ipsec.xauth_flags |= XAUTH_MUST_PROMPT; 3923 } 3924 } 3925 3926 if (serv->ne_sm_bridge == NULL) { 3927 /* open the kernel event socket */ 3928 if (serv->u.ipsec.eventfd == -1) { 3929 if (event_create_socket(serv, &serv->u.ipsec.eventfd, &serv->u.ipsec.eventref, event_callback, FALSE) < 0) { 3930 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: cannot create event socket")); 3931 goto fail; 3932 } 3933 } 3934 } 3935 3936#if TARGET_OS_EMBEDDED 3937 { 3938 /* first, bring up Cellular */ 3939 int need_cellular = FALSE; 3940 SCNetworkReachabilityRef ref = NULL; 3941 SCNetworkConnectionFlags flags = 0; 3942 struct sockaddr_in peer_address; /* the other side IP address */ 3943 3944 // we don't want a synchronous dns request to happen. 3945 // checking for default route is enough 3946 bzero(&peer_address, sizeof(peer_address)); 3947 peer_address.sin_len = sizeof(peer_address); 3948 peer_address.sin_family = AF_INET; 3949 ref = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&peer_address); 3950 //ref = SCNetworkReachabilityCreateWithName(NULL, remoteaddress); 3951 if (ref) { 3952 3953 if (SCNetworkReachabilityGetFlags(ref, &flags)) { 3954 if ((flags & kSCNetworkReachabilityFlagsReachable) && 3955 (flags & kSCNetworkReachabilityFlagsConnectionRequired) && 3956 (flags & kSCNetworkReachabilityFlagsIsWWAN)) { 3957 need_cellular = TRUE; 3958 } 3959 3960 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ipsec_start reachability flags = 0x%x, need_cellular = %d"), flags, need_cellular); 3961 } 3962 CFRelease(ref); 3963 } 3964 3965 int enabled = 1; 3966 CFNumberRef numref = CFDictionaryGetValue(serv->systemprefs, kRASPropIPSecNattKeepAliveEnabled); 3967 numref = isA_CFNumber(numref); 3968 if (numref) 3969 CFNumberGetValue(numref, kCFNumberIntType, &enabled); 3970 3971 if (enabled) { 3972 int timer = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 0 : 60; 3973 3974 numref = CFDictionaryGetValue(serv->systemprefs, kRASPropIPSecNattKeepAliveTimer); 3975 numref = isA_CFNumber(numref); 3976 if (numref) 3977 CFNumberGetValue(numref, kCFNumberIntType, &timer); 3978 3979 size_t oldlen = sizeof(gNattKeepAliveInterval); 3980 sysctlbyname("net.key.natt_keepalive_interval", &gNattKeepAliveInterval, &oldlen, &timer, sizeof(int)); 3981 } 3982 3983 if (need_cellular) { 3984 if (!bringup_cellular(serv)) { 3985 // cannot bring cellular up 3986 serv->u.ipsec.laststatus = IPSEC_EDGE_ACTIVATION_ERROR; 3987 goto fail; 3988 } 3989 3990 // cellular connection in progress 3991 return 0; 3992 } 3993 } 3994#endif 3995 3996 return racoon_resolve(serv); 3997 3998fail: 3999 if (serv->u.ipsec.laststatus == IPSEC_NO_ERROR) 4000 serv->u.ipsec.laststatus = IPSEC_GENERIC_ERROR; 4001 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: ipsec_start failed")); 4002 ipsec_stop(serv, 0); 4003 return serv->u.ipsec.laststatus; 4004} 4005 4006// XXX 4007int ipsec_getstatus_hack_notify(struct service *serv) 4008{ 4009 SCNetworkConnectionStatus status = PPP_IDLE; 4010 4011 switch (serv->u.ipsec.phase) { 4012 case IPSEC_INITIALIZE: 4013 case IPSEC_CONTACT: 4014 case IPSEC_PHASE1: 4015 case IPSEC_PHASE1AUTH: 4016 case IPSEC_PHASE2: 4017 status = PPP_ESTABLISH; 4018 break; 4019 case IPSEC_TERMINATE: 4020 status = PPP_TERMINATE; 4021 break; 4022 case IPSEC_RUNNING: 4023 status = PPP_RUNNING; 4024 break; 4025 case IPSEC_IDLE: 4026 default: 4027 status = PPP_IDLE; 4028 } 4029 return status; 4030} 4031 4032/* ----------------------------------------------------------------------------- 4033phase change for this config occured 4034----------------------------------------------------------------------------- */ 4035static 4036void ipsec_updatephase(struct service *serv, int phase) 4037{ 4038 4039 /* check for new state */ 4040 if (phase == serv->u.ipsec.phase) 4041 return; 4042 4043 serv->u.ipsec.phase = phase; 4044 4045 phase_changed(serv, phase); 4046 publish_dictnumentry(gDynamicStore, serv->serviceID, kSCEntNetIPSec, kSCPropNetIPSecStatus, phase); 4047} 4048 4049/* ----------------------------------------------------------------------------- 4050 detects disconnects caused by recoverable errors and flags the connection for 4051 auto reconnect (i.e. persistence) and avoid UI dialog 4052 ----------------------------------------------------------------------------- */ 4053static void 4054ipsec_check_for_disconnect_by_recoverable_error (struct service *serv, u_int32_t *flags) 4055{ 4056#if !TARGET_OS_EMBEDDED 4057 if (serv->was_running && 4058 !serv->persist_connect && 4059 (serv->flags & (FLAG_FREE | FLAG_ONTRAFFIC | FLAG_ONDEMAND | FLAG_CONNECT | FLAG_SETUP_PERSISTCONNECTION)) == FLAG_SETUP_PERSISTCONNECTION && 4060 (serv->connecttime && serv->establishtime) && 4061 serv->u.ipsec.laststatus && serv->u.ipsec.laststatus != IPSEC_PEERDISCONNECT_ERROR) { 4062 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: %d disconnected with status %d. Will try reconnect shortly."), 4063 serv->u.ipsec.phase, serv->u.ipsec.laststatus); 4064 // prevent error dialog from popping up during this disconnect 4065 *flags = (serv->flags | FLAG_ALERTERRORS); 4066 serv->flags &= ~FLAG_ALERTERRORS; 4067 serv->persist_connect = 1; 4068 } 4069#endif 4070} 4071 4072static int 4073ipsec_persist_connection (struct service *serv, u_int32_t flags) 4074{ 4075#if !TARGET_OS_EMBEDDED 4076 u_int32_t laststatus = 0; 4077 4078 if (serv->persist_connect) { 4079 ipsec_updatephase(serv, IPSEC_INITIALIZE); 4080 IPSEC_UNASSERT(serv->u.ipsec); 4081 serv->flags |= flags; 4082 laststatus = serv->u.ipsec.laststatus; 4083 serv->u.ipsec.laststatus = IPSEC_NO_ERROR; 4084 serv->u.ipsec.next_address = 1; 4085 serv->u.ipsec.ping_count = 0; 4086 serv->u.ipsec.awaiting_peer_resp = 0; 4087 if (serv->u.ipsec.msg) { 4088 my_Deallocate(serv->u.ipsec.msg, serv->u.ipsec.msgtotallen + 1); 4089 serv->u.ipsec.msg = 0; 4090 } 4091 serv->u.ipsec.msglen = 0; 4092 serv->u.ipsec.msgtotallen = 0; 4093 if (serv->u.ipsec.modecfg_msg != NULL) { 4094 my_Deallocate(serv->u.ipsec.modecfg_msg, serv->u.ipsec.modecfg_msglen); 4095 serv->u.ipsec.modecfg_msg = NULL; 4096 } 4097 serv->u.ipsec.modecfg_msglen = 0; 4098 if (serv->u.ipsec.timerref) { 4099 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.timerref, kCFRunLoopCommonModes); 4100 my_CFRelease(&serv->u.ipsec.timerref); 4101 } 4102 if (serv->u.ipsec.interface_timerref) { 4103 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.interface_timerref, kCFRunLoopCommonModes); 4104 my_CFRelease(&serv->u.ipsec.interface_timerref); 4105 } 4106 if (serv->u.ipsec.port_mapping_timerref) { 4107 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.port_mapping_timerref, kCFRunLoopCommonModes); 4108 my_CFRelease(&serv->u.ipsec.port_mapping_timerref); 4109 } 4110 my_CFRelease(&serv->u.ipsec.port_mapping_timerrun); 4111 4112 ipsec_log(LOG_NOTICE, CFSTR("IPSec Controller: reconnecting")); 4113 my_CFRelease(&serv->connection_nid); 4114 my_CFRelease(&serv->connection_nap); 4115 racoon_restart(serv, &serv->u.ipsec.peer_address); 4116 serv->persist_connect = 0; 4117 return TRUE; 4118 } 4119#endif 4120 return FALSE; 4121} 4122 4123/* ----------------------------------------------------------------------------- 4124----------------------------------------------------------------------------- */ 4125int ipsec_stop(struct service *serv, int signal) 4126{ 4127 char *errorstr; 4128 int error; 4129 u_int32_t flags = 0; 4130 4131 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ipsec_stop")); 4132 4133 SESSIONTRACERSTOP(serv); 4134 STOP_TRACKING_VPN_LOCATION(serv); 4135 4136 if (serv->u.ipsec.phase == IPSEC_PHASE1AUTH) { 4137 /* first, remove any pending authentication dialog */ 4138 if (serv->userNotificationRef) { 4139 CFUserNotificationCancel(serv->userNotificationRef); 4140 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), serv->userNotificationRLS, kCFRunLoopDefaultMode); 4141 my_CFRelease(&serv->userNotificationRef); 4142 my_CFRelease(&serv->userNotificationRLS); 4143 } 4144 } 4145 4146 // anticipate next phase 4147 switch (serv->u.ipsec.phase) { 4148 4149 case IPSEC_IDLE: 4150 case IPSEC_TERMINATE: 4151 /* special-case disconnect transitions? */ 4152 ipsec_check_for_disconnect_by_recoverable_error(serv, &flags); 4153 return 0; 4154 4155 case IPSEC_WAITING: 4156 case IPSEC_RUNNING: 4157 /* special-case disconnect transitions? */ 4158 ipsec_check_for_disconnect_by_recoverable_error(serv, &flags); 4159 default: 4160 ipsec_updatephase(serv, IPSEC_TERMINATE); 4161 } 4162 4163 IPSECLOGASLMSG("IPSec disconnecting from server %s\n", inet_ntoa(serv->u.ipsec.peer_address.sin_addr)); 4164 4165 if (serv->u.ipsec.dnsPort) { 4166 mach_port_t mp = CFMachPortGetPort(serv->u.ipsec.dnsPort); 4167 CFMachPortInvalidate(serv->u.ipsec.dnsPort); 4168 CFRelease(serv->u.ipsec.dnsPort); 4169 serv->u.ipsec.dnsPort = NULL; 4170 getaddrinfo_async_cancel(mp); 4171 } 4172 4173 if (serv->u.ipsec.controlfd != -1) { 4174 racoon_send_cmd_disconnect(serv->u.ipsec.controlfd, serv->u.ipsec.peer_address.sin_addr.s_addr); 4175 } 4176 4177 if (ipsec_persist_connection(serv, flags) == TRUE) { 4178 return 0; 4179 } 4180 4181 if (serv->u.ipsec.policies_installed) { 4182 error = IPSecRemovePolicies(serv->u.ipsec.config, -1, &errorstr); 4183 if (error) 4184 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Cannot remove policies, error '%s'"), errorstr); 4185 4186 IPSecRemoveSecurityAssociations((struct sockaddr *)&serv->u.ipsec.our_address, (struct sockaddr *)&serv->u.ipsec.peer_address); 4187 4188 serv->u.ipsec.policies_installed = 0; 4189 } 4190 if (serv->ne_sm_bridge != NULL) { 4191 ne_sm_bridge_request_uninstall(serv->ne_sm_bridge); 4192 } 4193 uninstall_mode_config(serv, TRUE); 4194 4195 if (serv->u.ipsec.config_applied) { 4196 error = IPSecRemoveConfiguration(serv->u.ipsec.config, &errorstr); 4197 if (error) 4198 ipsec_log(LOG_ERR, CFSTR("IPSec Controller: Cannot remove configuration, error '%s'"), errorstr); 4199 serv->u.ipsec.config_applied = 0; 4200 } 4201 4202 if (serv->u.ipsec.msg) { 4203 my_Deallocate(serv->u.ipsec.msg, serv->u.ipsec.msgtotallen + 1); 4204 serv->u.ipsec.msg = 0; 4205 } 4206 serv->u.ipsec.msglen = 0; 4207 serv->u.ipsec.msgtotallen = 0; 4208 4209 if (serv->u.ipsec.modecfg_msg != NULL) { 4210 my_Deallocate(serv->u.ipsec.modecfg_msg, serv->u.ipsec.modecfg_msglen); 4211 serv->u.ipsec.modecfg_msg = NULL; 4212 } 4213 serv->u.ipsec.modecfg_msglen = 0; 4214 4215 serv->uid = 0; 4216 serv->gid = 0; 4217 serv->bootstrap = 0; 4218 4219 serv->u.ipsec.ping_count = 0; 4220 4221 serv->u.ipsec.lower_interface[0] = 0; 4222 serv->u.ipsec.lower_interface_cellular = FALSE; 4223 4224 my_CFRelease(&serv->u.ipsec.resolvedAddress); 4225 serv->u.ipsec.resolvedAddress = 0; 4226 4227 if (serv->u.ipsec.controlref) { 4228 4229 CFSocketInvalidate(serv->u.ipsec.controlref); 4230 my_CFRelease(&serv->u.ipsec.controlref); 4231 } 4232 else if (serv->u.ipsec.controlfd) { 4233 close(serv->u.ipsec.controlfd); 4234 } 4235 serv->u.ipsec.controlfd = -1; 4236 4237 if (serv->u.ipsec.eventref) { 4238 4239 CFSocketInvalidate(serv->u.ipsec.eventref); 4240 my_CFRelease(&serv->u.ipsec.eventref); 4241 } 4242 else if (serv->u.ipsec.eventfd) { 4243 close(serv->u.ipsec.eventfd); 4244 } 4245 serv->u.ipsec.eventfd = -1; 4246 4247 scnc_bootstrap_dealloc(serv); 4248 scnc_ausession_dealloc(serv); 4249 4250 my_CFRelease(&serv->connectopts); 4251 my_CFRelease(&serv->u.ipsec.config); 4252 4253 if (serv->u.ipsec.timerref) { 4254 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.timerref, kCFRunLoopCommonModes); 4255 my_CFRelease(&serv->u.ipsec.timerref); 4256 } 4257 4258 if (serv->u.ipsec.interface_timerref) { 4259 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.interface_timerref, kCFRunLoopCommonModes); 4260 my_CFRelease(&serv->u.ipsec.interface_timerref); 4261 } 4262 4263#if TARGET_OS_EMBEDDED 4264 if (gNattKeepAliveInterval != -1) { 4265 int newval = gNattKeepAliveInterval; 4266 sysctlbyname("net.key.natt_keepalive_interval", 0, 0, &newval, sizeof(newval)); 4267 gNattKeepAliveInterval = -1; 4268 } 4269#endif 4270 4271 if (serv->u.ipsec.port_mapping_timerref) { 4272 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), serv->u.ipsec.port_mapping_timerref, kCFRunLoopCommonModes); 4273 my_CFRelease(&serv->u.ipsec.port_mapping_timerref); 4274 } 4275 my_CFRelease(&serv->u.ipsec.port_mapping_timerrun); 4276 4277 if (IPSEC_STATUS_IS_CLIENT_CERTIFICATE_INVALID(serv->u.ipsec.laststatus)) { 4278#if TARGET_OS_EMBEDDED 4279 if (serv->profileIdentifier) { 4280 CFStringRef msg = CFStringCreateWithFormat(0, 0, CFSTR("IPSec Error %d, Re-enroll"), serv->u.ipsec.laststatus); 4281 if (msg) { 4282 display_notification(serv, msg, 0, dialog_cert_fixme_type); 4283 CFRelease(msg); 4284 } 4285 } 4286 else 4287#endif 4288 display_notification(serv, NULL, serv->u.ipsec.laststatus, dialog_default_type); 4289 } 4290 else { 4291 if (!(serv->flags & FLAG_ONDEMAND) 4292 && (serv->u.ipsec.laststatus != IPSEC_NO_ERROR)) 4293 display_notification(serv, NULL, serv->u.ipsec.laststatus, dialog_default_type); 4294 } 4295 4296 ipsec_updatephase(serv, IPSEC_IDLE); 4297 cleanup_dynamicstore((void *)serv); 4298 IPSEC_UNASSERT(serv->u.ipsec); 4299 CLEAR_VPN_PORTMAPPING(serv); 4300 serv->persist_connect = 0; 4301 serv->was_running = 0; 4302 service_ended(serv); 4303 4304 if (serv->ne_sm_bridge != NULL) { 4305 allow_dispose(serv); 4306 } 4307 4308 return 0; 4309} 4310 4311/* ----------------------------------------------------------------------------- 4312----------------------------------------------------------------------------- */ 4313int ipsec_getstatus(struct service *serv) 4314{ 4315 SCNetworkConnectionStatus status = kSCNetworkConnectionDisconnected; 4316 4317 switch (serv->u.ipsec.phase) { 4318 case IPSEC_INITIALIZE: 4319 case IPSEC_CONTACT: 4320 case IPSEC_PHASE1: 4321 case IPSEC_PHASE1AUTH: 4322 case IPSEC_PHASE2: 4323 status = kSCNetworkConnectionConnecting; 4324 break; 4325 case IPSEC_WAITING: 4326 case IPSEC_TERMINATE: 4327 status = kSCNetworkConnectionDisconnecting; 4328 break; 4329 case IPSEC_RUNNING: 4330 status = kSCNetworkConnectionConnected; 4331 break; 4332 case IPSEC_IDLE: 4333 default: 4334 status = kSCNetworkConnectionDisconnected; 4335 } 4336 4337 if (gSCNCVerbose) { 4338 ipsec_log(LOG_INFO, CFSTR("IPSec Controller: ipsec_getstatus = %s"), 4339 status == kSCNetworkConnectionDisconnected ? "Disconnected" : 4340 (status == kSCNetworkConnectionConnecting ? "Connecting" : 4341 (status == kSCNetworkConnectionDisconnecting ? "Disconnecting" : 4342 (status == kSCNetworkConnectionConnected ? "Connected" : 4343 ("Unknown" ))))); 4344 } 4345 4346 return status; 4347} 4348 4349/* ----------------------------------------------------------------------------- 4350----------------------------------------------------------------------------- */ 4351int ipsec_copyextendedstatus(struct service *serv, CFDictionaryRef *statusdict) 4352{ 4353 CFMutableDictionaryRef dict = NULL; 4354 CFMutableDictionaryRef ipsecdict = NULL; 4355 char *addrstr; 4356 int error = 0; 4357 4358 *statusdict = NULL; 4359 4360 if ((dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) { 4361 error = ENOMEM; 4362 goto fail; 4363 } 4364 4365 /* create and add IPSec dictionary */ 4366 if ((ipsecdict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) { 4367 error = ENOMEM; 4368 goto fail; 4369 } 4370 4371 AddNumber(ipsecdict, kSCPropNetIPSecStatus, serv->u.ipsec.phase); 4372 4373 if (serv->u.ipsec.phase != IPSEC_IDLE 4374 && (addrstr = inet_ntoa(serv->u.ipsec.peer_address.sin_addr))) { 4375 AddString(ipsecdict, kRASPropIPSecRemoteAddress, addrstr); 4376 } 4377 4378 switch (serv->u.ipsec.phase) { 4379 case IPSEC_RUNNING: 4380 if (serv->ne_sm_bridge != NULL) { 4381 AddNumber64(ipsecdict, kSCPropNetIPSecConnectTime, ne_sm_bridge_get_connect_time(serv->ne_sm_bridge)); 4382 } else { 4383 AddNumber(ipsecdict, kSCPropNetIPSecConnectTime, serv->connecttime); 4384 } 4385 break; 4386 4387 default: 4388 AddNumber(ipsecdict, CFSTR("LastCause"), serv->u.ipsec.laststatus); 4389 } 4390 CFDictionaryAddValue(dict, kSCEntNetIPSec, ipsecdict); 4391 4392 /* create and add IPv4 dictionary */ 4393 if (serv->u.ipsec.phase == IPSEC_RUNNING) { 4394 CFMutableDictionaryRef ipv4dict = (CFMutableDictionaryRef)copyEntity(gDynamicStore, kSCDynamicStoreDomainState, serv->serviceID, kSCEntNetIPv4); 4395 if (ipv4dict) { 4396 CFDictionaryAddValue(dict, kSCEntNetIPv4, ipv4dict); 4397 CFRelease(ipv4dict); 4398 } 4399 } 4400 4401 AddNumber(dict, kSCNetworkConnectionStatus, ipsec_getstatus(serv)); 4402 4403 ipsec_log(LOG_DEBUG, CFSTR("IPSec Controller: Copy Extended Status %@"), dict); 4404 4405 *statusdict = CFRetain(dict); 4406 4407fail: 4408 my_CFRelease(&ipsecdict); 4409 my_CFRelease(&dict); 4410 return error; 4411} 4412 4413/* ----------------------------------------------------------------------------- 4414----------------------------------------------------------------------------- */ 4415int ipsec_getconnectdata(struct service *serv, CFDictionaryRef *options, int all) 4416{ 4417 CFDictionaryRef opts; 4418 CFMutableDictionaryRef mdict = NULL; 4419 CFDictionaryRef dict; 4420 int err = 0; 4421 4422 *options = NULL; 4423 4424 /* return saved data */ 4425 opts = serv->connectopts; 4426 4427 if (opts == 0) { 4428 // no data 4429 return 0; 4430 } 4431 4432 if (!all) { 4433 /* special code to remove secret information */ 4434 4435 mdict = CFDictionaryCreateMutableCopy(0, 0, opts); 4436 if (mdict == 0) { 4437 // no data 4438 return 0; 4439 } 4440 4441 dict = CFDictionaryGetValue(mdict, kSCEntNetIPSec); 4442 if (dict && (CFGetTypeID(dict) == CFDictionaryGetTypeID())) { 4443 CFMutableDictionaryRef mdict1 = CFDictionaryCreateMutableCopy(0, 0, dict); 4444 if (mdict1) { 4445 CFDictionaryRemoveValue(mdict1, kSCPropNetIPSecSharedSecret); 4446 CFDictionarySetValue(mdict, kSCEntNetIPSec, mdict1); 4447 CFRelease(mdict1); 4448 } 4449 } 4450 *options = CFRetain(mdict); 4451 } else { 4452 *options = CFRetain(opts); 4453 } 4454 4455 my_CFRelease(&mdict); 4456 return err; 4457} 4458 4459/* ----------------------------------------------------------------------------- 4460----------------------------------------------------------------------------- */ 4461int ipsec_copystatistics(struct service *serv, CFDictionaryRef *statsdict) 4462{ 4463 CFMutableDictionaryRef dict = NULL; 4464 CFMutableDictionaryRef ipsecdict = NULL; 4465 int error = 0; 4466 4467 *statsdict = NULL; 4468 4469 if (serv->u.ipsec.phase != IPSEC_RUNNING) 4470 return EINVAL; 4471 4472 if ((dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) { 4473 error = ENOMEM; 4474 goto fail; 4475 } 4476 4477 /* create and add IPSec dictionary */ 4478 if ((ipsecdict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) { 4479 error = ENOMEM; 4480 goto fail; 4481 } 4482 4483 AddNumber(ipsecdict, kSCNetworkConnectionBytesIn, 0); 4484 AddNumber(ipsecdict, kSCNetworkConnectionBytesOut, 0); 4485 AddNumber(ipsecdict, kSCNetworkConnectionPacketsIn, 0); 4486 AddNumber(ipsecdict, kSCNetworkConnectionPacketsOut, 0); 4487 AddNumber(ipsecdict, kSCNetworkConnectionErrorsIn, 0); 4488 AddNumber(ipsecdict, kSCNetworkConnectionErrorsOut, 0); 4489 4490 CFDictionaryAddValue(dict, kSCEntNetIPSec, ipsecdict); 4491 4492 *statsdict = CFRetain(dict); 4493 4494fail: 4495 my_CFRelease(&ipsecdict); 4496 my_CFRelease(&dict); 4497 return error; 4498} 4499 4500void ipsec_device_lock(struct service *serv) 4501{ 4502} 4503 4504void ipsec_device_unlock(struct service *serv) 4505{ 4506 serv->u.ipsec.has_displayed_reenroll_alert = FALSE; 4507} 4508 4509/* ----------------------------------------------------------------------------- 4510user has looged out 4511need to check the disconnect on logout flag for the ipsec interfaces 4512----------------------------------------------------------------------------- */ 4513void ipsec_log_out(struct service *serv) 4514{ 4515 if (serv->u.ipsec.phase != IPSEC_IDLE 4516 && (serv->flags & FLAG_SETUP_DISCONNECTONLOGOUT)) 4517 scnc_stop(serv, 0, SIGTERM, SCNC_STOP_USER_LOGOUT); 4518} 4519 4520/* ----------------------------------------------------------------------------- 4521user has logged in 4522----------------------------------------------------------------------------- */ 4523void ipsec_log_in(struct service *serv) 4524{ 4525} 4526 4527/* ----------------------------------------------------------------------------- 4528user has switched 4529need to check the disconnect on logout flags for the ppp interfaces 4530----------------------------------------------------------------------------- */ 4531void ipsec_log_switch(struct service *serv) 4532{ 4533 4534 switch (serv->u.ipsec.phase) { 4535 case IPSEC_IDLE: 4536 break; 4537 4538 default: 4539 if (serv->flags & FLAG_SETUP_DISCONNECTONFASTUSERSWITCH) 4540 scnc_stop(serv, 0, SIGTERM, SCNC_STOP_USER_SWITCH); 4541 } 4542} 4543 4544/* ----------------------------------------------------------------------------- 4545ipv4 state has changed 4546----------------------------------------------------------------------------- */ 4547void ipsec_ipv4_state_changed(struct service *serv) 4548{ 4549} 4550 4551/* ----------------------------------------------------------------------------- 4552system is asking permission to sleep 4553return if sleep is authorized 4554----------------------------------------------------------------------------- */ 4555int ipsec_can_sleep(struct service *serv) 4556{ 4557 4558 // I refuse idle sleep if ppp is connected 4559 if (serv->u.ipsec.phase == IPSEC_RUNNING 4560 && (serv->flags & FLAG_SETUP_PREVENTIDLESLEEP)) 4561 return 0; 4562 4563 return 1; 4564} 4565 4566/* ----------------------------------------------------------------------------- 4567system is going to sleep 4568disconnect services and return if a delay is needed 4569----------------------------------------------------------------------------- */ 4570int ipsec_will_sleep(struct service *serv, int checking) 4571{ 4572 if (serv->u.ipsec.phase != IPSEC_IDLE && (serv->flags & FLAG_SETUP_DISCONNECTONSLEEP) && !checking) { 4573 scnc_stop(serv, 0, SIGTERM, SCNC_STOP_SYS_SLEEP); 4574 } 4575 4576 return 0; 4577} 4578 4579/* ----------------------------------------------------------------------------- 4580system is waking up 4581----------------------------------------------------------------------------- */ 4582void ipsec_wake_up(struct service *serv) 4583{ 4584 if (serv->u.ipsec.phase == IPSEC_RUNNING || 4585 serv->u.ipsec.phase == IPSEC_WAITING) { 4586 if (DISCONNECT_VPN_IFOVERSLEPT(__FUNCTION__, serv, (char *)serv->if_name)) { 4587 return; 4588 } else if (DISCONNECT_VPN_IFLOCATIONCHANGED(serv)) { 4589 return; 4590 } 4591 } 4592} 4593 4594/* ----------------------------------------------------------------------------- 4595----------------------------------------------------------------------------- */ 4596static 4597void display_notification(struct service *serv, CFStringRef message, int errnum, int dialog_type) 4598{ 4599 CFStringRef msg = NULL; 4600 CFMutableDictionaryRef dict = NULL; 4601 SInt32 err; 4602 4603 if ((serv->flags & FLAG_ALERTERRORS) == 0) 4604 return; 4605 4606 if (message) 4607 msg = message; 4608 else { 4609 // filter out the following messages 4610 switch (errnum) { 4611 case IPSEC_NO_ERROR: /* IPSec Error 0 */ 4612 return; 4613 case IPSEC_NETWORKCHANGE_ERROR: /* IPSec Error 15 */ 4614 return; 4615#if TARGET_OS_EMBEDDED 4616 /* Errors 16, 17, 19 are not displayed on embedded os */ 4617 case IPSEC_PEERDISCONNECT_ERROR: /* IPSec Error 16 */ 4618 case IPSEC_PEERDEADETECTION_ERROR: /* IPSec Error 17 */ 4619 case IPSEC_IDLETIMEOUT_ERROR: /* IPSec Error 19 */ 4620 return; 4621#endif 4622 } 4623 msg = CFStringCreateWithFormat(0, 0, CFSTR("IPSec Error %d"), errnum); 4624 } 4625 4626 if (!msg || !CFStringGetLength(msg)) 4627 goto done; 4628 4629 /* Are we trying to display the re-enrolling alert */ 4630 if ((dialog_type == dialog_cert_fixme_type) && (serv->flags & FLAG_ONDEMAND)){ 4631 /* check the last time we displayed this */ 4632 if (serv->u.ipsec.has_displayed_reenroll_alert){ 4633 goto done; 4634 } 4635 } 4636 dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 4637 if (!dict) 4638 goto done; 4639 4640 if (gIconURLRef) 4641 CFDictionaryAddValue(dict, kCFUserNotificationIconURLKey, gIconURLRef); 4642 if (gBundleURLRef) 4643 CFDictionaryAddValue(dict, kCFUserNotificationLocalizationURLKey, gBundleURLRef); 4644 4645 CFDictionaryAddValue(dict, kCFUserNotificationAlertMessageKey, msg); 4646 CFDictionaryAddValue(dict, kCFUserNotificationAlertHeaderKey, CFSTR("VPN Connection")); 4647 4648 switch (dialog_type) { 4649 case dialog_has_disconnect_type: 4650 CFDictionaryAddValue(dict, kCFUserNotificationAlternateButtonTitleKey, CFSTR("Disconnect")); 4651 break; 4652 case dialog_cert_fixme_type: 4653 CFDictionaryAddValue(dict, kCFUserNotificationDefaultButtonTitleKey, CFSTR("Ignore")); 4654 CFDictionaryAddValue(dict, kCFUserNotificationAlternateButtonTitleKey, CFSTR("Settings")); 4655 serv->u.ipsec.has_displayed_reenroll_alert = TRUE; 4656 break; 4657 } 4658 4659 if (serv->userNotificationRef) { 4660 err = CFUserNotificationUpdate(serv->userNotificationRef, 0, kCFUserNotificationNoteAlertLevel, dict); 4661 } 4662 else { 4663 serv->userNotificationRef = CFUserNotificationCreate(NULL, 0, kCFUserNotificationNoteAlertLevel, &err, dict); 4664 if (!serv->userNotificationRef) 4665 goto done; 4666 4667 serv->userNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, serv->userNotificationRef, 4668 user_notification_callback, 0); 4669 if (!serv->userNotificationRLS) { 4670 my_CFRelease(&serv->userNotificationRef); 4671 goto done; 4672 } 4673 CFRunLoopAddSource(CFRunLoopGetCurrent(), serv->userNotificationRLS, kCFRunLoopDefaultMode); 4674 } 4675 4676 4677done: 4678 my_CFRelease(&dict); 4679 if (!message) 4680 my_CFRelease(&msg); 4681} 4682 4683