1/* 2 * Copyright (c) 2000 Apple Computer, 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/* ----------------------------------------------------------------------------- 25 * 26 * Theory of operation : 27 * 28 * provide helper function for ipsec operations. 29 * 30----------------------------------------------------------------------------- */ 31 32 33/* ----------------------------------------------------------------------------- 34 Includes 35----------------------------------------------------------------------------- */ 36 37#include <unistd.h> 38#include <errno.h> 39#include <fcntl.h> 40#include <sys/wait.h> 41#include <sys/socket.h> 42#include <sys/stat.h> 43#include <sys/sysctl.h> 44#include <netinet/in.h> 45#include <arpa/inet.h> 46#include <sys/ioctl.h> 47#include <net/if.h> 48#include <net/route.h> 49#include <net/if_dl.h> 50#include <netinet6/ipsec.h> 51#include <SystemConfiguration/SCPrivate.h> // for SCLog() 52#include <SystemConfiguration/SystemConfiguration.h> 53#include <SystemConfiguration/SCValidation.h> 54#include <sys/param.h> 55#include <syslog.h> 56#include <netinet/in_var.h> 57#include <sys/kern_event.h> 58 59#include "libpfkey.h" 60#include "cf_utils.h" 61#include "ipsec_utils.h" 62#include "RASSchemaDefinitions.h" 63#include "vpnoptions.h" 64#include "scnc_main.h" 65 66 67/* ----------------------------------------------------------------------------- 68 Definitions 69----------------------------------------------------------------------------- */ 70 71/* a few macros to simplify the code */ 72#define WRITE(t) fprintf(file, "%s%s", TAB_LEVEL[level], t) 73#define TWRITE(t) fprintf(file, "%s", t) 74#define FAIL(e) { *errstr = e; goto fail; } 75#define RACOON_CONFIG_PATH "/var/run/racoon" 76 77/* Wcast-align fix - cast away alignment warning when buffer is aligned */ 78#define ALIGNED_CAST(type) (type)(void *) 79 80/* ----------------------------------------------------------------------------- 81 globals 82----------------------------------------------------------------------------- */ 83 84/* indention level for the racoon file */ 85char *TAB_LEVEL[] = { 86 "", /* level 0 */ 87 " ", /* level 1 */ 88 " ", /* level 2 */ 89 " " /* level 3 */ 90}; 91 92/* ----------------------------------------------------------------------------- 93 Function Prototypes 94----------------------------------------------------------------------------- */ 95 96static int racoon_configure(CFDictionaryRef ipsec_dict, char **errstr, int apply); 97static int configure_sainfo(int level, FILE *file, CFDictionaryRef ipsec_dict, CFDictionaryRef policy, char **errstr); 98static int configure_remote(int level, FILE *file, CFDictionaryRef ipsec_dict, char **errstr); 99static int configure_proposal(int level, FILE *file, CFDictionaryRef ipsec_dict, CFDictionaryRef proposal_dict, char **errstr); 100 101//static void closeall(); 102static int racoon_pid(); 103//static int racoon_is_started(char *filename); 104static int racoon_restart(); 105static service_route_t * get_service_route (struct service *serv, in_addr_t local_addr, in_addr_t dest_addr); 106 107/* ----------------------------------------------------------------------------- 108 Create directories and intermediate directories as required. 109 ----------------------------------------------------------------------------- */ 110int makepath( char *path) 111{ 112 char *c; 113 char *thepath; 114 int slen=0; 115 int done = 0; 116 mode_t oldmask, newmask; 117 struct stat sb; 118 int error=0; 119 120 oldmask = umask(0); 121 newmask = S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH; 122 123 slen = strlen(path); 124 if ( !(thepath = malloc( slen+1) )) 125 return -1; 126 strlcpy( thepath, path, slen+1); 127 c = thepath; 128 if ( *c == '/' ) 129 c++; 130 for( ; !done; c++){ 131 if ( (*c == '/') || ( *c == '\0' )){ 132 if ( *c == '\0' ) 133 done = 1; 134 else 135 *c = '\0'; 136 if ( mkdir( thepath, newmask) ){ 137 if ( errno == EEXIST || errno == EISDIR){ 138 if ( stat(thepath, &sb) < 0){ 139 error = -1; 140 break; 141 } 142 } else { 143 error = -1; 144 break; 145 } 146 } 147 *c = '/'; 148 } 149 } 150 free(thepath); 151 umask(oldmask); 152 return error; 153} 154 155/* ----------------------------------------------------------------------------- 156The base-64 encoding packs three 8-bit bytes into four 7-bit ASCII 157characters. If the number of bytes in the original data isn't divisable 158by three, "=" characters are used to pad the encoded data. The complete 159set of characters used in base-64 are: 160 'A'..'Z' => 00..25 161 'a'..'z' => 26..51 162 '0'..'9' => 52..61 163 '+' => 62 164 '/' => 63 165 '=' => pad 166 167Parameters: 168inputData: the data to convert. 169file: the file itself. 170outputData: the converted output buffer. 171 the caller needs to make sure the buffer is large enough. 172----------------------------------------------------------------------------- */ 173static int EncodeDataUsingBase64(CFDataRef inputData, char *outputData, int maxOutputLen) { 174 static const char __CFPLDataEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 175 176 const uint8_t *bytes = CFDataGetBytePtr(inputData); 177 CFIndex length = CFDataGetLength(inputData); 178 CFIndex i, pos; 179 const uint8_t *p; 180 uint8_t * outp = (uint8_t *)outputData; 181 182 if (maxOutputLen < (length + (length / 3) + (length % 3) + 1)) 183 return 0; 184 185 pos = 0; // position within buf 186 187 for (i = 0, p = bytes; i < length; i++, p++) { 188 /* 3 bytes are encoded as 4 */ 189 switch (i % 3) { 190 case 0: 191 outp[pos++] = __CFPLDataEncodeTable [ ((p[0] >> 2) & 0x3f)]; 192 break; 193 case 1: 194 outp[pos++] = __CFPLDataEncodeTable [ ((((p[-1] << 8) | p[0]) >> 4) & 0x3f)]; 195 break; 196 case 2: 197 outp[pos++] = __CFPLDataEncodeTable [ ((((p[-1] << 8) | p[0]) >> 6) & 0x3f)]; 198 outp[pos++] = __CFPLDataEncodeTable [ (p[0] & 0x3f)]; 199 break; 200 } 201 } 202 203 switch (i % 3) { 204 case 0: 205 break; 206 case 1: 207 outp[pos++] = __CFPLDataEncodeTable [ ((p[-1] << 4) & 0x30)]; 208 outp[pos++] = '='; 209 outp[pos++] = '='; 210 break; 211 case 2: 212 outp[pos++] = __CFPLDataEncodeTable [ ((p[-1] << 2) & 0x3c)]; 213 outp[pos++] = '='; 214 break; 215 } 216 217 outp[pos] = 0; 218 return pos; 219} 220 221/* ----------------------------------------------------------------------------- 222close all file descriptors, usefule in fork/exec operations 223----------------------------------------------------------------------------- */ 224#if 0 225void 226closeall() 227{ 228 int i; 229 230 for (i = getdtablesize() - 1; i >= 0; i--) close(i); 231 open("/dev/null", O_RDWR, 0); 232 dup(0); 233 dup(0); 234 return; 235} 236#endif 237 238/* ----------------------------------------------------------------------------- 239return the pid of racoon process 240----------------------------------------------------------------------------- */ 241int 242racoon_pid() 243{ 244 int pid = 0, err, name[4]; 245 FILE *f; 246 size_t namelen, infolen; 247 struct kinfo_proc info; 248 249 f = fopen("/var/run/racoon.pid", "r"); 250 if (f) { 251 fscanf(f, "%d", &pid); 252 fclose(f); 253 254 /* 255 check the pid is valid, 256 verify if process is running and is racoon 257 */ 258 name[0] = CTL_KERN; 259 name[1] = KERN_PROC; 260 name[2] = KERN_PROC_PID; 261 name[3] = pid; 262 namelen = 4; 263 264 bzero(&info, sizeof(info)); 265 infolen = sizeof(info); 266 267 err = sysctl(name, namelen, &info, &infolen, 0, 0); 268 269 if (err == 0 && !strcmp("racoon", info.kp_proc.p_comm)) { 270 /* process exist and is called racoon */ 271 return pid; 272 } 273 } 274 275 return 0; 276} 277 278/* ----------------------------------------------------------------------------- 279check if racoon is started with the same configuration file 280returns: 281 0: racoon is not started 282 1: racoon is already started with our configuration 283 -1: racoon is already started but with a different configuration 284----------------------------------------------------------------------------- */ 285#if 0 286int 287racoon_is_started(char *filename) 288{ 289 return (racoon_pid() != 0); 290} 291#endif 292 293/* ----------------------------------------------------------------------------- 294sigusr1 racoon to reload configurations 295if racoon was not started, it will be started only if launch is set 296----------------------------------------------------------------------------- */ 297int 298racoon_restart() 299{ 300 int pid = racoon_pid(); 301 302 if (pid) { 303 kill(pid, SIGUSR1); 304 //sleep(1); // no need to wait 305 } 306 307 return 0; 308} 309 310/* ----------------------------------------------------------------------------- 311Terminate racoon process. 312this is not a good idea... 313----------------------------------------------------------------------------- */ 314static int 315racoon_stop() 316{ 317 int pid = racoon_pid(); 318 319 if (pid) 320 kill(pid, SIGTERM); 321 return 0; 322} 323 324/* ----------------------------------------------------------------------------- 325Configure one phase 1 proposal of IPSec 326An IPSec configuration can contain several proposals, 327and this function will be called for each of them 328 329Parameters: 330level: indentation level of the racoon file (make the generated file prettier). 331file: the file itself. 332ipsec_dict: dictionary containing the IPSec configuration. 333errstr: error string returned in case of configuration error. 334 335Return code: 3360 if successful, -1 otherwise. 337----------------------------------------------------------------------------- */ 338int 339configure_proposal(int level, FILE *file, CFDictionaryRef ipsec_dict, CFDictionaryRef proposal_dict, char **errstr) 340{ 341 char text[MAXPATHLEN]; 342 343 /* 344 authentication method is OPTIONAL 345 */ 346 { 347 char str[256]; 348 CFStringRef auth_method = NULL; 349 //CFStringRef prop_method = NULL; 350 u_int32_t xauth_enabled = 0; 351 352 /* get the default/preferred authentication from the ipsec dictionary, if available */ 353 auth_method = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecAuthenticationMethod); 354 GetIntFromDict(ipsec_dict, kRASPropIPSecXAuthEnabled, &xauth_enabled, 0); 355 356#if 0 357 if (proposal_dict) 358 prop_method = CFDictionaryGetValue(proposal_dict, kRASPropIPSecProposalAuthenticationMethod); 359 360 strlcpy(str, "pre_shared_key", sizeof(str)); 361 if (isString(auth_method) || isString(prop_method)) { 362 363 if (CFEqual(isString(prop_method) ? prop_method : auth_method, kRASValIPSecProposalAuthenticationMethodSharedSecret)) 364 strlcpy(str, "pre_shared_key", sizeof(str)); 365 else if (CFEqual(isString(prop_method) ? prop_method : auth_method, kRASValIPSecProposalAuthenticationMethodCertificate)) 366 strlcpy(str, "rsasig", sizeof(str)); 367 else if (CFEqual(isString(prop_method) ? prop_method : auth_method, kRASValIPSecProposalAuthenticationMethodXauthSharedSecretClient)) 368 strlcpy(str, "xauth_psk_client", sizeof(str)); 369 else if (CFEqual(isString(prop_method) ? prop_method : auth_method, kRASValIPSecProposalAuthenticationMethodXauthCertificateClient)) 370 strlcpy(str, "xauth_rsa_client", sizeof(str)); 371 else if (CFEqual(isString(prop_method) ? prop_method : auth_method, kRASValIPSecProposalAuthenticationMethodHybridCertificateClient)) 372 strlcpy(str, "hybrid_rsa_client", sizeof(str)); 373 else 374 FAIL("incorrect authentication method";) 375 } 376#endif 377 strlcpy(str, "pre_shared_key", sizeof(str)); 378 if (isString(auth_method)) { 379 380 if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodSharedSecret)) 381 strlcpy(str, xauth_enabled ? "xauth_psk_client" : "pre_shared_key", sizeof(str)); 382 else if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate)) 383 strlcpy(str, xauth_enabled ? "xauth_rsa_client" : "rsasig", sizeof(str)); 384 else if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodHybrid)) 385 strlcpy(str, "hybrid_rsa_client", sizeof(str)); 386 else 387 FAIL("incorrect authentication method";) 388 } 389 390 snprintf(text, sizeof(text), "authentication_method %s;\n", str); 391 WRITE(text); 392 } 393 394 /* 395 authentication algorithm is OPTIONAL 396 */ 397 { 398 char str[256]; 399 CFStringRef algo; 400 401 strlcpy(str, "sha1", sizeof(str)); 402 if (proposal_dict) { 403 algo = CFDictionaryGetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm); 404 if (isString(algo)) { 405 406 if (CFEqual(algo, kRASValIPSecProposalHashAlgorithmMD5)) 407 strlcpy(str, "md5", sizeof(str)); 408 else if (CFEqual(algo, kRASValIPSecProposalHashAlgorithmSHA1)) 409 strlcpy(str, "sha1", sizeof(str)); 410 else 411 FAIL("incorrect authentication algorithm";) 412 413 } 414 } 415 snprintf(text, sizeof(text), "hash_algorithm %s;\n", str); 416 WRITE(text); 417 } 418 419 /* 420 encryption algorithm is OPTIONAL 421 */ 422 { 423 char str[256]; 424 CFStringRef crypto; 425 426 strlcpy(str, "3des", sizeof(str)); 427 if (proposal_dict) { 428 crypto = CFDictionaryGetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm); 429 if (isString(crypto)) { 430 431 if (CFEqual(crypto, kRASValIPSecProposalEncryptionAlgorithmDES)) 432 strlcpy(str, "des", sizeof(str)); 433 else if (CFEqual(crypto, kRASValIPSecProposalEncryptionAlgorithm3DES)) 434 strlcpy(str, "3des", sizeof(str)); 435 else if (CFEqual(crypto, kRASValIPSecProposalEncryptionAlgorithmAES)) 436 strlcpy(str, "aes", sizeof(str)); 437 else if (CFEqual(crypto, kRASValIPSecProposalEncryptionAlgorithmAES256)) 438 strlcpy(str, "aes 256", sizeof(str)); 439 else 440 FAIL("incorrect encryption algorithm";) 441 442 } 443 } 444 snprintf(text, sizeof(text), "encryption_algorithm %s;\n", str); 445 WRITE(text); 446 } 447 448 /* 449 Lifetime is OPTIONAL 450 */ 451 { 452 u_int32_t lval = 3600; 453 if (proposal_dict) { 454 GetIntFromDict(proposal_dict, kRASPropIPSecProposalLifetime, &lval, 3600); 455 } 456 snprintf(text, sizeof(text), "lifetime time %d sec;\n", lval); 457 WRITE(text); 458 } 459 460 /* 461 DH Group is OPTIONAL 462 */ 463 { 464 u_int32_t lval = 2; 465 if (proposal_dict) { 466 GetIntFromDict(proposal_dict, kRASPropIPSecProposalDHGroup, &lval, 2); 467 } 468 snprintf(text, sizeof(text), "dh_group %d;\n", lval); 469 WRITE(text); 470 } 471 472 return 0; 473 474fail: 475 return -1; 476} 477 478/* ----------------------------------------------------------------------------- 479Configure the phase 1 of IPSec. 480The phase 1 contains things like addresses, authentication, and proposals array. 481 482Parameters: 483level: indentation level of the racoon file (make the generated file prettier). 484file: the file itself. 485filename: the name of the file (NULL if no actual file is to be written) 486ipsec_dict: dictionary containing the IPSec configuration. 487errstr: error string returned in case of configuration error. 488 489Return code: 4900 if successful, -1 otherwise. 491----------------------------------------------------------------------------- */ 492#define CERT_VERIFICATION_OPTION_NONE 0 493#define CERT_VERIFICATION_OPTION_OPEN_DIR 1 494#define CERT_VERIFICATION_OPTION_PEERS_ID 2 495 496int 497configure_remote(int level, FILE *file, CFDictionaryRef ipsec_dict, char **errstr) 498{ 499 char text[MAXPATHLEN]; 500 CFStringRef auth_method = NULL; 501 int cert_verification_option = CERT_VERIFICATION_OPTION_NONE; 502 char *option_str; 503 504 505 /* 506 ipsec domain of interpretion and situation 507 */ 508 WRITE("doi ipsec_doi;\n"); 509 WRITE("situation identity_only;\n"); 510 511 /* get the default/preferred authentication from the ipsec dictionary, if available */ 512 auth_method = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecAuthenticationMethod); 513 if (auth_method == NULL) 514 auth_method = kRASValIPSecAuthenticationMethodSharedSecret; 515 516 /* 517 exchange mode is OPTIONAL, default will be main mode 518 */ 519 { 520 int i, nb; 521 CFArrayRef modes; 522 CFStringRef mode; 523 524 strlcpy(text, "exchange_mode ", sizeof(text)); 525 nb = 0; 526 modes = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecExchangeMode); 527 if (isArray(modes)) { 528 529 nb = CFArrayGetCount(modes); 530 for (i = 0; i < nb && i < 3; i++) { 531 532 mode = CFArrayGetValueAtIndex(modes, i); 533 if (!isString(mode)) 534 continue; 535 536 if (i) 537 strlcat(text, ", ", sizeof(text)); 538 539 if (CFEqual(mode, kRASValIPSecExchangeModeMain)) 540 strlcat(text, "main", sizeof(text)); 541 else if (CFEqual(mode, kRASValIPSecExchangeModeAggressive)) 542 strlcat(text, "aggressive", sizeof(text)); 543 else if (CFEqual(mode, kRASValIPSecExchangeModeBase)) 544 strlcat(text, "base", sizeof(text)); 545 else 546 FAIL("incorrect phase 1 exchange mode"); 547 } 548 } 549 if (nb == 0) { 550 char str[256]; 551 /* default mode is main except if local identifier is defined (and the auth method is shared secret) */ 552 if ((CFEqual(auth_method, kRASValIPSecAuthenticationMethodSharedSecret) || 553 CFEqual(auth_method, kRASValIPSecAuthenticationMethodHybrid)) && 554 GetStrFromDict(ipsec_dict, kRASPropIPSecLocalIdentifier, str, sizeof(str), "")) 555 strlcat(text, "aggressive", sizeof(text)); 556 else 557 strlcat(text, "main", sizeof(text)); 558 } 559 strlcat(text, ";\n", sizeof(text)); 560 WRITE(text); 561 } 562 563 /* 564 get the first authentication method from the proposals 565 verify all proposal have the same authentication method 566 */ 567 { 568#if 0 569 CFArrayRef proposals; 570 int i, nb; 571 CFDictionaryRef proposal; 572 CFStringRef method; 573 574 proposals = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecProposals); 575 if (isArray(proposals)) { 576 577 nb = CFArrayGetCount(proposals); 578 for (i = 0; i < nb; i++) { 579 580 proposal = CFArrayGetValueAtIndex(proposals, i); 581 if (isDictionary(proposal)) { 582 583 method = CFDictionaryGetValue(proposal, kRASPropIPSecProposalAuthenticationMethod); 584 if (isString(method)) { 585 586 if (auth_method == NULL) 587 auth_method = method; 588 else if (!CFEqual(auth_method, method)) 589 FAIL("inconsistent authentication methods"); 590 } 591 } 592 } 593 } 594#endif 595 596 if (!CFEqual(auth_method, kRASValIPSecAuthenticationMethodSharedSecret) 597 && !CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate) 598 && !CFEqual(auth_method, kRASValIPSecAuthenticationMethodHybrid)) 599 FAIL("incorrect authentication method found"); 600 } 601 602 /* 603 local identifier is OPTIONAL 604 if local identifier is not specified, we will configure IKE differently depending 605 on the authentication method used 606 */ 607 { 608 char str[256]; 609 char str1[256]; 610 611 if (GetStrFromDict(ipsec_dict, CFSTR("LocalIdentifierType"), str1, sizeof(str1), "")) { 612 if (!strcmp(str1, "FQDN")) 613 strlcpy(str1, "fqdn", sizeof(str1)); 614 else if (!strcmp(str1, "UserFQDN")) 615 strlcpy(str1, "user_fqdn", sizeof(str1)); 616 else if (!strcmp(str1, "KeyID")) 617 strlcpy(str1, "keyid_use", sizeof(str1)); 618 else if (!strcmp(str1, "Address")) 619 strlcpy(str1, "address", sizeof(str1)); 620 else if (!strcmp(str1, "ASN1DN")) 621 strlcpy(str1, "asn1dn", sizeof(str1)); 622 else 623 strlcpy(str1, "", sizeof(str1)); 624 if (!racoon_validate_cfg_str(str1)) { 625 FAIL("invalid LocalIdentifierType"); 626 } 627 } 628 629 if (GetStrFromDict(ipsec_dict, kRASPropIPSecLocalIdentifier, str, sizeof(str), "")) { 630 if (!racoon_validate_cfg_str(str)) { 631 FAIL("invalid LocalIdentifier"); 632 } 633 snprintf(text, sizeof(text), "my_identifier %s \"%s\";\n", str1[0] ? str1 : "fqdn", str); 634 WRITE(text); 635 } 636 else { 637 if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodSharedSecret) 638 || CFEqual(auth_method, kRASValIPSecAuthenticationMethodHybrid)) { 639 /* 640 use local address 641 */ 642 } 643 else if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate)) { 644 /* 645 use subject name from certificate 646 */ 647 snprintf(text, sizeof(text), "my_identifier asn1dn;\n"); 648 WRITE(text); 649 } 650 } 651 } 652 653 /* 654 remote identifier verification key is OPTIONAL 655 by default we will use the remote address 656 */ 657 { 658 CFStringRef string; 659 char str[256]; 660 661 string = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecIdentifierVerification); 662 if (!isString(string)) 663 string = kRASValIPSecIdentifierVerificationGenerateFromRemoteAddress; 664 665 if (CFEqual(string, kRASValIPSecIdentifierVerificationNone)) { 666 /* 667 no verification, use for test purpose 668 */ 669 WRITE("verify_identifier off;\n"); 670 } 671 else { 672 673 if (CFEqual(string, kRASValIPSecIdentifierVerificationGenerateFromRemoteAddress)) { 674 /* 675 verify using the remote address 676 */ 677 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecRemoteAddress, str, sizeof(str))) 678 FAIL("no remote address found"); 679 snprintf(text, sizeof(text), "peers_identifier address \"%s\";\n", str); 680 WRITE(text); 681 682 if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate)) 683 cert_verification_option = CERT_VERIFICATION_OPTION_PEERS_ID; 684 } 685 else if (CFEqual(string, kRASValIPSecIdentifierVerificationUseRemoteIdentifier)) { 686 /* 687 verify using the explicitely specified remote identifier key 688 */ 689 if (!GetStrFromDict(ipsec_dict, kRASPropIPSecRemoteIdentifier, str, sizeof(str), "")) 690 FAIL("no remote identifier found"); 691 if (!racoon_validate_cfg_str(str)) { 692 FAIL("invalid RemoteIdentifier"); 693 } 694 snprintf(text, sizeof(text), "peers_identifier fqdn \"%s\";\n", str); 695 WRITE(text); 696 697 if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate) || 698 CFEqual(auth_method, kRASValIPSecAuthenticationMethodHybrid)) 699 cert_verification_option = CERT_VERIFICATION_OPTION_PEERS_ID; 700 } 701 else if (CFEqual(string, kRASValIPSecIdentifierVerificationUseOpenDirectory)) { 702 /* 703 verify using open directory (certificates only) 704 */ 705 if (!CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate)) 706 FAIL("open directory can only be used with certificate authentication"); 707 cert_verification_option = CERT_VERIFICATION_OPTION_OPEN_DIR; 708 } 709 else 710 FAIL("incorrect verification method"); 711 712 /* 713 verification is required. 714 if certificates are not used - verify peers identifier against the Id payload in the isakmp packet. 715 otherwise, verification will be done using the Id in the peers certificate. 716 */ 717 snprintf(text, sizeof(text), "verify_identifier %s;\n", (cert_verification_option == CERT_VERIFICATION_OPTION_NONE ? "on" : "off")); 718 WRITE(text); 719 } 720 } 721 722 /* 723 Authentication method parameters 724 */ 725 { 726 char str[256], str1[256]; 727 CFStringRef string; 728 729 /* 730 Shared Secret authentication method 731 */ 732 if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodSharedSecret) 733 || CFEqual(auth_method, kRASValIPSecAuthenticationMethodHybrid)) { 734 735 if (!GetStrFromDict(ipsec_dict, kRASPropIPSecSharedSecret, str, sizeof(str), "")) 736 FAIL("no shared secret found"); 737 if (!racoon_validate_cfg_str(str)) { 738 FAIL("invalid SharedSecret"); 739 } 740 741 /* 742 Shared Secrets are stored in the KeyChain, in the plist or in the racoon keys file 743 */ 744 strlcpy(str1, "use", sizeof(str1)); 745 string = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecSharedSecretEncryption); 746 if (isString(string)) { 747 if (CFEqual(string, kRASValIPSecSharedSecretEncryptionKey)) 748 strlcpy(str1, "key", sizeof(str1)); 749 else if (CFEqual(string, kRASValIPSecSharedSecretEncryptionKeychain)) 750 strlcpy(str1, "keychain", sizeof(str1)); 751 else 752 FAIL("incorrect shared secret encryption found"); 753 } 754 snprintf(text, sizeof(text), "shared_secret %s \"%s\";\n", str1, str); 755 WRITE(text); 756 757 /* 758 Hybrid authentication method only 759 */ 760 if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodHybrid)) { 761 //WRITE("verify_cert on;\n"); // Should we set this?? 762 snprintf(text, sizeof(text), "certificate_verification sec_framework use_peers_identifier;\n"); 763 WRITE(text); 764 } 765 } 766 /* 767 Certificates authentication method 768 */ 769 else if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate)) { 770 771 CFDataRef local_cert; 772 773 /* 774 certificate come from the keychain 775 */ 776 local_cert = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecLocalCertificate); 777 if (isData(local_cert)) { 778 WRITE("certificate_type x509 in_keychain \""); 779 fwrite(text, 1, EncodeDataUsingBase64(local_cert, text, sizeof(text)), file); 780 TWRITE("\";\n"); 781 } 782 else 783 WRITE("certificate_type x509 in_keychain;\n"); 784 785 WRITE("verify_cert on;\n"); 786 if (cert_verification_option == CERT_VERIFICATION_OPTION_OPEN_DIR) 787 option_str = " use_open_dir"; 788 else if (cert_verification_option == CERT_VERIFICATION_OPTION_PEERS_ID) 789 option_str = " use_peers_identifier"; 790 else 791 option_str = ""; 792 snprintf(text, sizeof(text), "certificate_verification sec_framework%s;\n", option_str); 793 WRITE(text); 794 } 795 } 796 797 /* Set forced local address */ 798 { 799 if (CFDictionaryContainsKey(ipsec_dict, kRASPropIPSecForceLocalAddress) && 800 CFDictionaryGetValue(ipsec_dict, kRASPropIPSecForceLocalAddress) == kCFBooleanTrue) { 801 char src_address[32]; 802 GetStrAddrFromDict(ipsec_dict, kRASPropIPSecLocalAddress, src_address, sizeof(src_address)); 803 snprintf(text, sizeof(text), "local_address %s;\n", src_address); 804 WRITE(text); 805 } 806 } 807 808 /* 809 Nonce size key is OPTIONAL 810 */ 811 { 812 u_int32_t lval; 813 GetIntFromDict(ipsec_dict, kRASPropIPSecNonceSize, &lval, 16); 814 snprintf(text, sizeof(text), "nonce_size %d;\n", lval); 815 WRITE(text); 816 } 817 818 /* 819 Enable/Disable nat traversal multiple user support 820 */ 821 { 822 u_int32_t natt_multi_user; 823 824 if (GetIntFromDict(ipsec_dict, kRASPropIPSecNattMultipleUsersEnabled, &natt_multi_user, 0)) { 825 snprintf(text, sizeof(text), "nat_traversal_multi_user %s;\n", natt_multi_user ? "on" : "off"); 826 WRITE(text); 827 } 828 } 829 830 /* 831 Enable/Disable nat traversal keepalive 832 */ 833 { 834 u_int32_t natt_keepalive; 835 836 if (GetIntFromDict(ipsec_dict, kRASPropIPSecNattKeepAliveEnabled, &natt_keepalive, 1)) { 837 snprintf(text, sizeof(text), "nat_traversal_keepalive %s;\n", natt_keepalive ? "on" : "off"); 838 WRITE(text); 839 } 840 } 841 842 /* 843 Enable/Disable Dead Peer Detection 844 */ 845 { 846 int dpd_enabled, dpd_delay, dpd_retry, dpd_maxfail, blackhole_enabled; 847 848 if (GetIntFromDict(ipsec_dict, kRASPropIPSecDeadPeerDetectionEnabled, (u_int32_t *)&dpd_enabled, 0)) { 849 GetIntFromDict(ipsec_dict, kRASPropIPSecDeadPeerDetectionDelay, (u_int32_t *)&dpd_delay, 30); 850 GetIntFromDict(ipsec_dict, kRASPropIPSecDeadPeerDetectionRetry, (u_int32_t *)&dpd_retry, 5); 851 GetIntFromDict(ipsec_dict, kRASPropIPSecDeadPeerDetectionMaxFail, (u_int32_t *)&dpd_maxfail, 5); 852 GetIntFromDict(ipsec_dict, kRASPropIPSecBlackHoleDetectionEnabled, (u_int32_t *)&blackhole_enabled, 1); 853 snprintf(text, sizeof(text), "dpd_delay %d;\n", dpd_delay); 854 WRITE(text); 855 snprintf(text, sizeof(text), "dpd_retry %d;\n", dpd_retry); 856 WRITE(text); 857 snprintf(text, sizeof(text), "dpd_maxfail %d;\n", dpd_maxfail); 858 WRITE(text); 859 snprintf(text, sizeof(text), "dpd_algorithm %s;\n", blackhole_enabled ? "dpd_blackhole_detect" : "dpd_inbound_detect"); 860 WRITE(text); 861 } 862 } 863 864 /* 865 Inactivity timeout 866 */ 867 { 868 int disconnect_on_idle, disconnect_on_idle_timer; 869 870 if (GetIntFromDict(ipsec_dict, kRASPropIPSecDisconnectOnIdle, (u_int32_t *)&disconnect_on_idle, 0) && disconnect_on_idle != 0) { 871 // 2 minutes default 872 GetIntFromDict(ipsec_dict, kRASPropIPSecDisconnectOnIdleTimer, (u_int32_t *)&disconnect_on_idle_timer, 120); 873 // only count outgoing traffic -- direction outbound 874 snprintf(text, sizeof(text), "disconnect_on_idle idle_timeout %d idle_direction idle_outbound;\n", disconnect_on_idle_timer); 875 WRITE(text); 876 } 877 } 878 879 /* 880 other keys 881 */ 882 WRITE("initial_contact on;\n"); 883 WRITE("support_proxy on;\n"); 884 885 /* 886 proposal behavior key is OPTIONAL 887 by default we impose our settings 888 */ 889 { 890 CFStringRef behavior; 891 char str[256]; 892 893 strlcpy(str, "claim", sizeof(str)); 894 behavior = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecProposalsBehavior); 895 if (isString(behavior)) { 896 897 if (CFEqual(behavior, kRASValIPSecProposalsBehaviorClaim)) 898 strlcpy(str, "claim", sizeof(str)); 899 else if (CFEqual(behavior, kRASValIPSecProposalsBehaviorObey)) 900 strlcpy(str, "obey", sizeof(str)); 901 else if (CFEqual(behavior, kRASValIPSecProposalsBehaviorStrict)) 902 strlcpy(str, "strict", sizeof(str)); 903 else if (CFEqual(behavior, kRASValIPSecProposalsBehaviorExact)) 904 strlcpy(str, "exact", sizeof(str)); 905 else 906 FAIL("incorrect proposal behavior"); 907 908 } 909 snprintf(text, sizeof(text), "proposal_check %s;\n", str); 910 WRITE(text); 911 } 912 913 /* 914 XAUTH User Name is OPTIONAL 915 */ 916 { 917 char str[256]; 918 919 if (GetStrFromDict(ipsec_dict, kRASPropIPSecXAuthName, str, sizeof(str), "")) { 920 if (!racoon_validate_cfg_str(str)) { 921 FAIL("invalid XauthName"); 922 } 923 snprintf(text, sizeof(text), "xauth_login \"%s\";\n", str); 924 WRITE(text); 925 } 926 } 927 928 /* 929 ModeConfig is OPTIONAL 930 */ 931 { 932 u_int32_t modeconfig; 933 934 if (GetIntFromDict(ipsec_dict, kRASPropIPSecModeConfigEnabled, &modeconfig, 0)) { 935 snprintf(text, sizeof(text), "mode_cfg %s;\n", modeconfig ? "on" : "off"); 936 WRITE(text); 937 } 938 } 939 940 /* 941 proposal records are OPTIONAL 942 */ 943 { 944 int i = 0, nb = 0; 945 CFArrayRef proposals; 946 CFDictionaryRef proposal = NULL; 947 948 proposals = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecProposals); 949 if (isArray(proposals)) 950 nb = CFArrayGetCount(proposals); 951 952 do { 953 954 if (nb) { 955 proposal = CFArrayGetValueAtIndex(proposals, i); 956 if (!isDictionary(proposal)) 957 FAIL("incorrect phase 1 proposal"); 958 } 959 960 WRITE("\n"); 961 WRITE("proposal {\n"); 962 963 if (configure_proposal(level + 1, file, ipsec_dict, proposal, errstr)) 964 goto fail; 965 966 WRITE("}\n"); 967 968 969 } while (++i < nb); 970 } 971 972 return 0; 973 974fail: 975 976 return -1; 977} 978 979/* ----------------------------------------------------------------------------- 980Configure one phase 2 proposal of IPSec 981An IPSec configuration can contain several proposals, 982and this function will be called for each of them 983 984Parameters: 985level: indentation level of the racoon file (make the generated file prettier). 986file: the file itself. 987ipsec_dict: dictionary containing the IPSec configuration. 988policy: dictionary that uses this proposal, from the Policies array of ipsec_dict. 989errstr: error string returned in case of configuration error. 990 991Return code: 9920 if successful, -1 otherwise. 993----------------------------------------------------------------------------- */ 994int 995configure_sainfo(int level, FILE *file, CFDictionaryRef ipsec_dict, CFDictionaryRef policy, char **errstr) 996{ 997 char text[MAXPATHLEN]; 998 999 /* 1000 Encryption algorithms are OPTIONAL 1001 */ 1002 { 1003 CFArrayRef algos; 1004 int i, nb, found = 0; 1005 1006 strlcpy(text, "encryption_algorithm ", sizeof(text)); 1007 1008 if (policy) { 1009 algos = CFDictionaryGetValue(policy, kRASPropIPSecPolicyEncryptionAlgorithm); 1010 if (isArray(algos)) { 1011 1012 nb = CFArrayGetCount(algos); 1013 if (nb) { 1014 1015 for (i = 0; i < nb; i++) { 1016 1017 CFStringRef algo; 1018 1019 algo = CFArrayGetValueAtIndex(algos, i); 1020 if (!isString(algo)) 1021 continue; 1022 1023 if (found) 1024 strlcat(text, ", ", sizeof(text)); 1025 1026 if (CFEqual(algo, kRASValIPSecPolicyEncryptionAlgorithmDES)) 1027 strlcat(text, "des", sizeof(text)); 1028 else if (CFEqual(algo, kRASValIPSecPolicyEncryptionAlgorithm3DES)) 1029 strlcat(text, "3des", sizeof(text)); 1030 else if (CFEqual(algo, kRASValIPSecPolicyEncryptionAlgorithmAES)) 1031 strlcat(text, "aes", sizeof(text)); 1032 else if (CFEqual(algo, kRASValIPSecPolicyEncryptionAlgorithmAES256)) 1033 strlcat(text, "aes 256", sizeof(text)); 1034 else 1035 FAIL("incorrect encryption algorithm"); 1036 1037 found = 1; 1038 } 1039 1040 } 1041 } 1042 } 1043 if (!found) 1044 strlcat(text, "aes", sizeof(text)); 1045 1046 strlcat(text, ";\n", sizeof(text)); 1047 WRITE(text); 1048 } 1049 1050 /* 1051 Authentication algorithms are OPTIONAL 1052 */ 1053 { 1054 CFArrayRef algos; 1055 int i, nb, found = 0; 1056 1057 strlcpy(text, "authentication_algorithm ", sizeof(text)); 1058 1059 if (policy) { 1060 algos = CFDictionaryGetValue(policy, kRASPropIPSecPolicyHashAlgorithm); 1061 if (isArray(algos)) { 1062 1063 nb = CFArrayGetCount(algos); 1064 if (nb) { 1065 1066 for (i = 0; i < nb; i++) { 1067 1068 CFStringRef algo; 1069 1070 algo = CFArrayGetValueAtIndex(algos, i); 1071 if (!isString(algo)) 1072 continue; 1073 1074 if (found) 1075 strlcat(text, ", ", sizeof(text)); 1076 1077 if (CFEqual(algo, kRASValIPSecPolicyHashAlgorithmSHA1)) 1078 strlcat(text, "hmac_sha1", sizeof(text)); 1079 else if (CFEqual(algo, kRASValIPSecPolicyHashAlgorithmMD5)) 1080 strlcat(text, "hmac_md5", sizeof(text)); 1081 else 1082 FAIL("incorrect authentication algorithm"); 1083 1084 found = 1; 1085 } 1086 1087 } 1088 } 1089 } 1090 if (!found) 1091 strlcat(text, "hmac_sha1", sizeof(text)); 1092 1093 strlcat(text, ";\n", sizeof(text)); 1094 WRITE(text); 1095 } 1096 1097 /* 1098 Compression algorithms are OPTIONAL 1099 */ 1100 { 1101 CFArrayRef algos; 1102 int i, nb, found = 0; 1103 1104 strlcpy(text, "compression_algorithm ", sizeof(text)); 1105 1106 if (policy) { 1107 algos = CFDictionaryGetValue(policy, kRASPropIPSecPolicyCompressionAlgorithm); 1108 if (isArray(algos)) { 1109 1110 nb = CFArrayGetCount(algos); 1111 if (nb) { 1112 1113 for (i = 0; i < nb; i++) { 1114 1115 CFStringRef algo; 1116 1117 algo = CFArrayGetValueAtIndex(algos, i); 1118 if (!isString(algo)) 1119 continue; 1120 1121 if (found) 1122 strlcat(text, ", ", sizeof(text)); 1123 1124 if (CFEqual(algo, kRASValIPSecPolicyCompressionAlgorithmDeflate)) 1125 strlcat(text, "deflate", sizeof(text)); 1126 else 1127 FAIL("incorrect compression algorithm"); 1128 1129 found = 1; 1130 } 1131 } 1132 } 1133 } 1134 if (!found) 1135 strlcat(text, "deflate", sizeof(text)); 1136 1137 strlcat(text, ";\n", sizeof(text)); 1138 WRITE(text); 1139 } 1140 1141 /* 1142 lifetime is OPTIONAL 1143 */ 1144 { 1145 u_int32_t lval = 3600; 1146 if (policy) 1147 GetIntFromDict(policy, kRASPropIPSecPolicyLifetime, &lval, 3600); 1148 snprintf(text, sizeof(text), "lifetime time %d sec;\n", lval); 1149 WRITE(text); 1150 } 1151 1152 /* 1153 PFS Group is OPTIONAL 1154 */ 1155 { 1156 u_int32_t lval = 0; 1157 if (policy) { 1158 if (GetIntFromDict(policy, kRASPropIPSecPolicyPFSGroup, &lval, 0) && lval) { 1159 snprintf(text, sizeof(text), "pfs_group %d;\n", lval); 1160 WRITE(text); 1161 } 1162 } 1163 } 1164 1165 return 0; 1166 1167fail: 1168 1169 return -1; 1170} 1171 1172/* ----------------------------------------------------------------------------- 1173 Specifies the ipsec sub-type in the configuration dictionary 1174 ----------------------------------------------------------------------------- */ 1175void 1176IPSecConfigureVerboseLogging (CFMutableDictionaryRef ipsec_dict, int verbose_logging) 1177{ 1178 CFNumberRef num = CFNumberCreate(0, kCFNumberIntType, &verbose_logging); 1179 CFDictionarySetValue(ipsec_dict, CFSTR("VerboseLogging"), num); 1180 CFRelease(num); 1181} 1182 1183/* ----------------------------------------------------------------------------- 1184----------------------------------------------------------------------------- */ 1185int 1186IPSecApplyConfiguration(CFDictionaryRef ipsec_dict, char **errstr) 1187{ 1188 return racoon_configure(ipsec_dict, errstr, 1); 1189} 1190 1191/* ----------------------------------------------------------------------------- 1192----------------------------------------------------------------------------- */ 1193int 1194IPSecValidateConfiguration(CFDictionaryRef ipsec_dict, char **errstr) 1195{ 1196 return racoon_configure(ipsec_dict, errstr, 0); 1197} 1198 1199/* ----------------------------------------------------------------------------- 1200Configure IKE. 1201It will perform all necessary validation of the ipsec configuration, generate 1202a configuration file (if apply is set) for racoon. 1203This function is very sequential. It will configure all components of an IKE configuration. 1204This will not install kernel policies in the kernel and must be done separately. 1205 1206Parameters: 1207ipsec_dict: dictionary containing the IPSec configuration. 1208errstr: error string returned in case of configuration error. 1209apply: if 1, apply the configuration to racoon, 1210 otherwise, just validate the configuration. 1211 1212Return code: 12130 if successful, -1 otherwise. 1214----------------------------------------------------------------------------- */ 1215int 1216racoon_configure(CFDictionaryRef ipsec_dict, char **errstr, int apply) 1217{ 1218 int level = 0, anonymous; 1219 mode_t mask; 1220 FILE *file = 0; 1221 char filename[256], text[256]; 1222 char text2[256]; 1223 char local_address[32], remote_address[32]; 1224 struct stat sb; 1225 u_int32_t verbose_logging; 1226 1227 filename[0] = 0; 1228 1229 if (!isDictionary(ipsec_dict)) 1230 FAIL("IPSec dictionary not present"); 1231 1232 GetIntFromDict(ipsec_dict, CFSTR("VerboseLogging"), &verbose_logging, 0); 1233 1234 /* 1235 local address is REQUIRED 1236 verify it is defined, not needed in racoon configuration 1237 */ 1238 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecLocalAddress, local_address, sizeof(local_address))) 1239 FAIL("incorrect local address found"); 1240 1241 /* 1242 remote address is REQUIRED 1243 */ 1244 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecRemoteAddress, remote_address, sizeof(remote_address))) 1245 FAIL("incorrect remote address found"); 1246 1247 anonymous = inet_addr(remote_address) == 0; 1248 /* 1249 create the configuration file 1250 make the file only readable by root, so we can stick the shared secret inside 1251 */ 1252 if (apply) { 1253 snprintf(filename, sizeof(filename), RACOON_CONFIG_PATH "/%s.conf", anonymous ? "anonymous" : remote_address); 1254 /* remove any existing leftover, to create with right permissions */ 1255 remove(filename); 1256 if (stat(RACOON_CONFIG_PATH, &sb) != 0 && errno == ENOENT) { 1257 /* Create the path */ 1258 if ( makepath( RACOON_CONFIG_PATH ) ){ 1259 snprintf(text, sizeof(text), "cannot create racoon configuration file path (error %d)", errno); 1260 FAIL(text); 1261 } 1262 } 1263 } 1264 1265 /* 1266 turn off group/other bits to create file rw owner only 1267 */ 1268 mask = umask(S_IRWXG|S_IRWXO); 1269 file = fopen(apply ? filename : "/dev/null" , "w"); 1270 mask = umask(mask); 1271 if (file == NULL) { 1272 snprintf(text, sizeof(text), "cannot create racoon configuration file (error %d)", errno); 1273 FAIL(text); 1274 } 1275 1276 if (verbose_logging) { 1277 WRITE("log debug2;\n"); 1278 WRITE("path logfile \"/var/log/racoon.log\";\n\n"); 1279 } 1280 1281 /* 1282 write the remote record. this is common to all the proposals and sainfo records 1283 */ 1284 1285 /* XXX hack iphone... remove immediately*/ 1286 if (CFDictionaryGetValue(ipsec_dict, CFSTR("UseAnonymousPolicy"))) 1287 anonymous = 1; 1288 1289 { 1290 1291 snprintf(text, sizeof(text), "remote %s {\n", anonymous ? "anonymous" : remote_address); 1292 WRITE(text); 1293 1294 /* 1295 configure now all the remote directives 1296 */ 1297 if (configure_remote(level + 1, file, ipsec_dict, errstr)) 1298 goto fail; 1299 1300 /* end of the remote record */ 1301 WRITE("}\n\n"); 1302 } 1303 1304 /* 1305 * write the sainfo records 1306 */ 1307 1308 { 1309 CFArrayRef policies; 1310 int i, nb; 1311 1312 policies = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecPolicies); 1313 if (!isArray(policies) 1314 || (nb = CFArrayGetCount(policies)) == 0) 1315 //FAIL("no policies found"); 1316 goto no_policy; // do not fail anymore 1317 1318 /* if this is the anonymous configuration, only take the first policy */ 1319 if (anonymous) 1320 nb = 1; 1321 1322 for (i = 0; i < nb; i++) { 1323 1324 CFDictionaryRef policy; 1325 CFStringRef policylevel, policymode; 1326 char local_network[256], remote_network[256]; 1327 u_int32_t local_port, remote_port; 1328 u_int32_t local_prefix, remote_prefix; 1329 u_int32_t protocol, tunnel; 1330 1331 policy = CFArrayGetValueAtIndex(policies, i); 1332 if (!isDictionary(policy)) 1333 FAIL("incorrect policy found"); 1334 1335 /* if policy leve is not specified, None is assumed */ 1336 policylevel = CFDictionaryGetValue(policy, kRASPropIPSecPolicyLevel); 1337 if (!isString(policylevel) || CFEqual(policylevel, kRASValIPSecPolicyLevelNone)) 1338 continue; 1339 else if (CFEqual(policylevel, kRASValIPSecPolicyLevelDiscard)) 1340 continue; 1341 else if (!CFEqual(policylevel, kRASValIPSecPolicyLevelRequire)) 1342 FAIL("incorrect policy level found"); 1343 1344 if (anonymous) { 1345 snprintf(text, sizeof(text), "sainfo anonymous {\n"); 1346 } 1347 else { 1348 /* 1349 IPSec is required for this policy 1350 write the sainfo record 1351 local and remote network are REQUIRED 1352 */ 1353 tunnel = 1; 1354 policymode = CFDictionaryGetValue(policy, kRASPropIPSecPolicyMode); 1355 if (isString(policymode)) { 1356 1357 if (CFEqual(policymode, kRASValIPSecPolicyModeTunnel)) 1358 tunnel = 1; 1359 else if (CFEqual(policymode, kRASValIPSecPolicyModeTransport)) 1360 tunnel = 0; 1361 else 1362 FAIL("incorrect policy type found"); 1363 } 1364 1365 if (tunnel) { 1366 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyLocalAddress, local_network, sizeof(local_network))) 1367 FAIL("incorrect policy local network"); 1368 1369 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyRemoteAddress, remote_network, sizeof(remote_network))) 1370 FAIL("incorrect policy remote network"); 1371 1372 GetIntFromDict(policy, kRASPropIPSecPolicyLocalPrefix, &local_prefix, 24); 1373 if (local_prefix == 0) 1374 FAIL("incorrect policy local prefix"); 1375 1376 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePrefix, &remote_prefix, 24); 1377 if (remote_prefix == 0) 1378 FAIL("incorrect policy remote prefix"); 1379 1380 snprintf(text, sizeof(text), "sainfo address %s/%d 0 address %s/%d 0 {\n", 1381 local_network, local_prefix, 1382 remote_network, remote_prefix); 1383 snprintf(text2, sizeof(text2), "sainfo address %s/%d 0 address %s/%d 0 {\n", 1384 remote_network, remote_prefix, 1385 local_network, local_prefix); 1386 1387 } 1388 else { 1389 1390 GetIntFromDict(policy, kRASPropIPSecPolicyLocalPort, &local_port, 0); 1391 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePort, &remote_port, 0); 1392 GetIntFromDict(policy, kRASPropIPSecPolicyProtocol, &protocol, 0); 1393 1394 snprintf(text, sizeof(text), "sainfo address %s/32 [%d] %d address %s/32 [%d] %d {\n", 1395 local_address, local_port, protocol, 1396 remote_address, remote_port, protocol); 1397 snprintf(text2, sizeof(text2), "sainfo address %s/32 [%d] %d address %s/32 [%d] %d {\n", 1398 remote_address, remote_port, protocol, 1399 local_address, local_port, protocol); 1400 1401 } 1402 } 1403 1404 WRITE(text); 1405 1406 if (configure_sainfo(level + 1, file, ipsec_dict, policy, errstr)) 1407 goto fail; 1408 1409 /* end of the record */ 1410 WRITE("}\n\n"); 1411 1412 if ( !anonymous ){ 1413 /* write bidirectional info */ 1414 WRITE(text2); 1415 1416 if (configure_sainfo(level + 1, file, ipsec_dict, policy, errstr)) 1417 goto fail; 1418 1419 /* end of the record */ 1420 WRITE("}\n\n"); 1421 } 1422 1423 } 1424 1425 no_policy: 1426 ; 1427 1428 } 1429 1430 fclose(file); 1431 1432 /* 1433 * signal racoon 1434 */ 1435 1436 if (apply) { 1437 racoon_restart(); 1438 } 1439 1440 return 0; 1441 1442fail: 1443 1444 if (file) 1445 fclose(file); 1446 if (filename[0]) 1447 remove(filename); 1448 return -1; 1449} 1450 1451 1452/* ----------------------------------------------------------------------------- 1453Unconfigure IPSec. 1454Remove an configuration from IPSec, remove the racoon file and restart racoon.. 1455This will not remove kernel policies in the kernel and must be done separately. 1456 1457Parameters: 1458ipsec_dict: dictionary containing the IPSec configuration. 1459errstr: error string returned in case of configuration error. 1460 1461Return code: 14620 if successful, -1 otherwise. 1463----------------------------------------------------------------------------- */ 1464int 1465IPSecRemoveConfiguration(CFDictionaryRef ipsec_dict, char **errstr) 1466{ 1467 int anonymous; 1468 char filename[256]; 1469 char remote_address[32]; 1470 1471 filename[0] = 0; 1472 1473 if (!isDictionary(ipsec_dict)) 1474 FAIL("IPSec dictionary not present"); 1475 1476 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecRemoteAddress, remote_address, sizeof(remote_address))) 1477 FAIL("incorrect remote address found"); 1478 1479 anonymous = inet_addr(remote_address) == 0; 1480 1481 // don't remove anymous entry ? 1482 if (anonymous) 1483 return 0; 1484 1485 snprintf(filename, sizeof(filename), RACOON_CONFIG_PATH "/%s.conf", remote_address); 1486 remove(filename); 1487 1488 racoon_restart(); 1489 return 0; 1490 1491fail: 1492 1493 return -1; 1494} 1495 1496/* ----------------------------------------------------------------------------- 1497Unconfigure IPSec. 1498Remove an configuration from IPSec, remove the racoon file does not restart racoon. 1499This will not remove kernel policies in the kernel and must be done separately. 1500 1501Parameters: 1502ipsec_dict: dictionary containing the IPSec configuration. 1503errstr: error string returned in case of configuration error. 1504 1505Return code: 15060 if successful, -1 otherwise. 1507----------------------------------------------------------------------------- */ 1508int 1509IPSecRemoveConfigurationFile(CFDictionaryRef ipsec_dict, char **errstr) 1510{ 1511 int anonymous; 1512 char filename[256]; 1513 char remote_address[32]; 1514 1515 filename[0] = 0; 1516 1517 if (!isDictionary(ipsec_dict)) 1518 FAIL("IPSec dictionary not present"); 1519 1520 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecRemoteAddress, remote_address, sizeof(remote_address))) 1521 FAIL("incorrect remote address found"); 1522 1523 anonymous = inet_addr(remote_address) == 0; 1524 1525 // don't remove anymous entry ? 1526 if (anonymous) 1527 return 0; 1528 1529 snprintf(filename, sizeof(filename), RACOON_CONFIG_PATH "/%s.conf", remote_address); 1530 remove(filename); 1531 1532 return 0; 1533 1534fail: 1535 1536 return -1; 1537} 1538 1539/* ----------------------------------------------------------------------------- 1540Kick IPSec racoon when changes have been made before to the configuration files. 1541 1542Parameters: 1543 1544Return code: 15450 if successful, -1 otherwise. 1546----------------------------------------------------------------------------- */ 1547int 1548IPSecKickConfiguration() 1549{ 1550 1551 racoon_restart(); 1552 return 0; 1553} 1554 1555/* ----------------------------------------------------------------------------- 1556Count the number of IPSec kernel policies in the configuration. 1557 1558Parameters: 1559ipsec_dict: dictionary containing the IPSec configuration. 1560 1561Return code: 1562number of policies in the configuration. 1563----------------------------------------------------------------------------- */ 1564int 1565IPSecCountPolicies(CFDictionaryRef ipsec_dict) 1566{ 1567 CFArrayRef policies; 1568 1569 policies = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecPolicies); 1570 if (isArray(policies)) 1571 return CFArrayGetCount(policies); 1572 1573 return 0; 1574} 1575 1576/* ----------------------------------------------------------------------------- 1577Install IPSec kernel policies. 1578This will not configure IKE and must be done separately. 1579 1580Parameters: 1581ipsec_dict: dictionary containing the IPSec configuration. 1582index: -1, install all policies defined in the configuration 1583 otherwise, install only the policy at the specified index. 1584errstr: error string returned in case of configuration error. 1585 1586Return code: 15870 if successful, -1 otherwise. 1588----------------------------------------------------------------------------- */ 1589int 1590IPSecInstallPolicies(CFDictionaryRef ipsec_dict, CFIndex index, char ** errstr) 1591{ 1592 int nread, num_policies = 0, num_drained = 0; 1593 socklen_t nread_size=sizeof(nread); 1594 int s = -1, err, seq = 0, i, nb; 1595 char policystr_in[64], policystr_out[64], src_address[32], dst_address[32], str[32], *msg; 1596 caddr_t policy_in = 0, policy_out = 0; 1597 u_int32_t policylen_in, policylen_out, local_prefix, remote_prefix; 1598 u_int32_t protocol = 0xFF; 1599 CFArrayRef policies; 1600 struct sockaddr_in local_net; 1601 struct sockaddr_in remote_net; 1602 CFIndex start, end; 1603 1604 s = pfkey_open(); 1605 if (s < 0) 1606 FAIL("cannot open a pfkey socket"); 1607 1608 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecLocalAddress, src_address, sizeof(src_address))) 1609 FAIL("incorrect local address"); 1610 1611 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecRemoteAddress, dst_address, sizeof(dst_address))) 1612 FAIL("incorrect remote address"); 1613 1614 policies = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecPolicies); 1615 if (!isArray(policies) 1616 || (nb = CFArrayGetCount(policies)) == 0 1617 || index > nb) 1618 FAIL("no policies found"); 1619 1620 if (index == -1) { 1621 start = 0; 1622 end = nb; 1623 } 1624 else { 1625 start = index; 1626 end = index + 1; 1627 } 1628 for (i = start; i < end; i++) { 1629 1630 int tunnel, in, out; 1631 CFDictionaryRef policy; 1632 CFStringRef policymode, policydirection, policylevel; 1633 1634 policy = CFArrayGetValueAtIndex(policies, i); 1635 if (!isDictionary(policy)) 1636 FAIL("incorrect policy found"); 1637 1638 /* build policies in and out */ 1639 1640 tunnel = 1; 1641 policymode = CFDictionaryGetValue(policy, kRASPropIPSecPolicyMode); 1642 if (isString(policymode)) { 1643 1644 if (CFEqual(policymode, kRASValIPSecPolicyModeTunnel)) 1645 tunnel = 1; 1646 else if (CFEqual(policymode, kRASValIPSecPolicyModeTransport)) 1647 tunnel = 0; 1648 else 1649 FAIL("incorrect policy type found"); 1650 } 1651 1652 /* if policy direction is not specified, in/out is assumed */ 1653 in = out = 1; 1654 policydirection = CFDictionaryGetValue(policy, kRASPropIPSecPolicyDirection); 1655 if (isString(policydirection)) { 1656 1657 if (CFEqual(policydirection, kRASValIPSecPolicyDirectionIn)) 1658 out = 0; 1659 else if (CFEqual(policydirection, kRASValIPSecPolicyDirectionOut)) 1660 in = 0; 1661 else if (!CFEqual(policydirection, kRASValIPSecPolicyDirectionInOut)) 1662 FAIL("incorrect policy direction found"); 1663 } 1664 1665 policylevel = CFDictionaryGetValue(policy, kRASPropIPSecPolicyLevel); 1666 if (!isString(policylevel) || CFEqual(policylevel, kRASValIPSecPolicyLevelNone)) { 1667 snprintf(policystr_out, sizeof(policystr_out), "out none"); 1668 snprintf(policystr_in, sizeof(policystr_in), "in none"); 1669 } 1670 else if (CFEqual(policylevel, kRASValIPSecPolicyLevelUnique)) { 1671 if (tunnel) { 1672 snprintf(policystr_out, sizeof(policystr_out), "out ipsec esp/tunnel/%s-%s/unique", src_address, dst_address); 1673 snprintf(policystr_in, sizeof(policystr_in), "in ipsec esp/tunnel/%s-%s/unique", dst_address, src_address); 1674 } 1675 else { 1676 snprintf(policystr_out, sizeof(policystr_out), "out ipsec esp/transport//unique"); 1677 snprintf(policystr_in, sizeof(policystr_in), "in ipsec esp/transport//unique"); 1678 } 1679 } 1680 else if (CFEqual(policylevel, kRASValIPSecPolicyLevelRequire)) { 1681 if (tunnel) { 1682 snprintf(policystr_out, sizeof(policystr_out), "out ipsec esp/tunnel/%s-%s/require", src_address, dst_address); 1683 snprintf(policystr_in, sizeof(policystr_in), "in ipsec esp/tunnel/%s-%s/require", dst_address, src_address); 1684 } 1685 else { 1686 snprintf(policystr_out, sizeof(policystr_out), "out ipsec esp/transport//require"); 1687 snprintf(policystr_in, sizeof(policystr_in), "in ipsec esp/transport//require"); 1688 } 1689 } 1690 else if (CFEqual(policylevel, kRASValIPSecPolicyLevelDiscard)) { 1691 snprintf(policystr_out, sizeof(policystr_out), "out discard"); 1692 snprintf(policystr_in, sizeof(policystr_in), "in discard"); 1693 } 1694 else 1695 FAIL("incorrect policy level"); 1696 1697 policy_in = ipsec_set_policy(policystr_in, strlen(policystr_in)); 1698 if (policy_in == 0) 1699 FAIL("cannot set policy in"); 1700 1701 policy_out = ipsec_set_policy(policystr_out, strlen(policystr_out)); 1702 if (policy_out == 0) 1703 FAIL("cannot set policy out"); 1704 1705 policylen_in = (ALIGNED_CAST(struct sadb_x_policy *)policy_in)->sadb_x_policy_len << 3; 1706 policylen_out = (ALIGNED_CAST(struct sadb_x_policy *)policy_out)->sadb_x_policy_len << 3; 1707 1708 1709 if (tunnel) { 1710 /* get local and remote networks */ 1711 1712 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyLocalAddress, str, sizeof(str))) 1713 FAIL("incorrect local network"); 1714 1715 local_net.sin_len = sizeof(local_net); 1716 local_net.sin_family = AF_INET; 1717 local_net.sin_port = htons(0); 1718 if (!inet_aton(str, &local_net.sin_addr)) 1719 FAIL("incorrect local network"); 1720 1721 GetIntFromDict(policy, kRASPropIPSecPolicyLocalPrefix, &local_prefix, 24); 1722 1723 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyRemoteAddress, str, sizeof(str))) 1724 FAIL("incorrect remote network0"); 1725 1726 remote_net.sin_len = sizeof(remote_net); 1727 remote_net.sin_family = AF_INET; 1728 remote_net.sin_port = htons(0); 1729 if (!inet_aton(str, &remote_net.sin_addr)) 1730 FAIL("incorrect remote network1"); 1731 1732 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePrefix, &remote_prefix, 24); 1733 1734 } 1735 else { 1736 u_int32_t val; 1737 1738 local_net.sin_len = sizeof(local_net); 1739 local_net.sin_family = AF_INET; 1740 GetIntFromDict(policy, kRASPropIPSecPolicyLocalPort, &val, 0); 1741 local_net.sin_port = htons(val); 1742 if (!inet_aton(src_address, &local_net.sin_addr)) 1743 FAIL("incorrect local address"); 1744 1745 local_prefix = local_net.sin_addr.s_addr ? 32 : 0; 1746 1747 remote_net.sin_len = sizeof(remote_net); 1748 remote_net.sin_family = AF_INET; 1749 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePort, &val, 0); 1750 remote_net.sin_port = htons(val); 1751 if (!inet_aton(dst_address, &remote_net.sin_addr)) 1752 FAIL("incorrect remote address"); 1753 1754 remote_prefix = remote_net.sin_addr.s_addr ? 32 : 0; 1755 1756 GetIntFromDict(policy, kRASPropIPSecPolicyProtocol, &protocol, 0); 1757 1758 } 1759 1760 /* configure kernel policies */ 1761 1762 if (out) { 1763 num_policies++; 1764 err = pfkey_send_spdadd(s, (struct sockaddr *)&local_net, local_prefix, (struct sockaddr *)&remote_net, remote_prefix, protocol, policy_out, policylen_out, seq++); 1765 if (err < 0) 1766 FAIL("cannot add policy out"); 1767 } 1768 1769 if (in) { 1770 num_policies++; 1771 err = pfkey_send_spdadd(s, (struct sockaddr *)&remote_net, remote_prefix, (struct sockaddr *)&local_net, local_prefix, protocol, policy_in, policylen_in, seq++); 1772 if (err < 0) 1773 FAIL("cannot add policy in"); 1774 } 1775 1776 /* Drain the receiving buffer otherwise it's never read. */ 1777 while (((err = getsockopt(s, SOL_SOCKET, SO_NREAD, &nread, &nread_size)) >= 0) && (nread > 0)) { 1778 1779 if ((msg = (char *)pfkey_recv(s))) { 1780 num_drained++; 1781 free(msg); 1782 } 1783 } 1784 1785 free(policy_in); 1786 free(policy_out); 1787 policy_in = 0; 1788 policy_out = 0; 1789 } 1790 1791 1792 SCLog(TRUE, LOG_DEBUG, CFSTR("Number of policies processed successfully: %d (with %d drained).\n"), num_policies, num_drained); 1793 pfkey_close(s); 1794 return 0; 1795 1796fail: 1797 SCLog(TRUE, LOG_ERR, CFSTR("Failed to add policy. Number of policies processed %d (with %d drained).\n"), num_policies, num_drained); 1798 if (policy_in) 1799 free(policy_in); 1800 if (policy_out) 1801 free(policy_out); 1802 if (s != -1) 1803 pfkey_close(s); 1804 return -1; 1805} 1806 1807 1808/* ----------------------------------------------------------------------------- 1809----------------------------------------------------------------------------- */ 1810 1811static void 1812domask(char *dst, uint32_t addr, uint32_t mask) 1813{ 1814 int b, i; 1815 if (!mask) { 1816 *dst = '\0'; 1817 return; 1818 } 1819 i = 0; 1820 for (b = 0; b < 32; b++) 1821 if (mask & (1 << b)) { 1822 int bb; 1823 i = b; 1824 for (bb = b+1; bb < 32; bb++) 1825 if (!(mask & (1 << bb))) { 1826 i = -1; /* noncontig */ 1827 break; 1828 } 1829 break; 1830 } 1831 if (i == -1) 1832 snprintf(dst, sizeof(dst), "&0x%x", mask); 1833 else 1834 snprintf(dst, sizeof(dst), "/%d", 32-i); 1835} 1836 1837static char * 1838netname(uint32_t in, uint32_t mask) 1839{ 1840 static char line[MAXHOSTNAMELEN]; 1841 in = ntohl(in); 1842 mask = ntohl(mask); 1843 1844 if ((in & IN_CLASSA_HOST) == 0) { 1845 snprintf(line, sizeof(line), "%u", (uint8_t)(in >> 24)); 1846 } else if ((in & IN_CLASSB_HOST) == 0) { 1847 snprintf(line, sizeof(line), "%u.%u", 1848 (uint8_t)(in >> 24), (uint8_t)(in >> 16)); 1849 } else if ((in & IN_CLASSC_HOST) == 0) { 1850 snprintf(line, sizeof(line), "%u.%u.%u", 1851 (uint8_t)(in >> 24), (uint8_t)(in >> 16), (uint8_t)(in >> 8)); 1852 } else { 1853 snprintf(line, sizeof(line), "%u.%u.%u.%u", 1854 (uint8_t)(in >> 24), (uint8_t)(in >> 16), (uint8_t)(in >> 8), (uint8_t)(in)); 1855 } 1856 1857 domask(line+strlen(line), in, mask); 1858 return (line); 1859} 1860 1861static int 1862install_remove_routes(struct service *serv, int cmd, CFDictionaryRef ipsec_dict, CFIndex index, char ** errstr, struct in_addr gateway) 1863{ 1864 int s = -1, i, nb; 1865 char src_address[32], dst_address[32], str[32]; 1866 u_int32_t remote_prefix; 1867 CFArrayRef policies; 1868 struct sockaddr_in local_net; 1869 struct sockaddr_in remote_net; 1870 CFIndex start, end; 1871 int len; 1872 int rtm_seq = 0; 1873 1874 struct { 1875 struct rt_msghdr hdr; 1876 struct sockaddr_in dst; 1877 struct sockaddr_in gway; 1878 struct sockaddr_in mask; 1879 } rtmsg; 1880 char remote_addr_str[INET_ADDRSTRLEN]; 1881 char gateway_addr_str[INET_ADDRSTRLEN]; 1882 CFMutableStringRef installedRoutesList = CFStringCreateMutable(kCFAllocatorDefault, 0); 1883 CFIndex installedRoutesListLen = 0; 1884 char *installed_routes_str = NULL; 1885 1886 if (installedRoutesList == NULL) 1887 FAIL("cannot allocate CFString"); 1888 1889 s = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE); 1890 if (s < 0) 1891 FAIL("cannot open a routing socket"); 1892 1893 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecLocalAddress, src_address, sizeof(src_address))) 1894 FAIL("incorrect local address"); 1895 1896 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecRemoteAddress, dst_address, sizeof(dst_address))) 1897 FAIL("incorrect remote address"); 1898 1899 policies = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecPolicies); 1900 if (!isArray(policies) 1901 || (nb = CFArrayGetCount(policies)) == 0 1902 || index > nb) 1903 FAIL("no policies found"); 1904 1905 if (index == -1) { 1906 start = 0; 1907 end = nb; 1908 } 1909 else { 1910 start = index; 1911 end = index + 1; 1912 } 1913 for (i = start; i < end; i++) { 1914 1915 int tunnel, in, out; 1916 CFDictionaryRef policy; 1917 CFStringRef policymode, policydirection, policylevel; 1918 1919 policy = CFArrayGetValueAtIndex(policies, i); 1920 if (!isDictionary(policy)) 1921 FAIL("incorrect policy found"); 1922 1923 /* build policies in and out */ 1924 1925 tunnel = 1; 1926 policymode = CFDictionaryGetValue(policy, kRASPropIPSecPolicyMode); 1927 if (isString(policymode)) { 1928 1929 if (CFEqual(policymode, kRASValIPSecPolicyModeTunnel)) 1930 tunnel = 1; 1931 else if (CFEqual(policymode, kRASValIPSecPolicyModeTransport)) 1932 tunnel = 0; 1933 else 1934 FAIL("incorrect policy type found"); 1935 } 1936 1937 if (tunnel == 0) 1938 continue; // no need for routes for 'tranport' policies 1939 1940 /* if policy direction is not specified, in/out is assumed */ 1941 in = out = 1; 1942 policydirection = CFDictionaryGetValue(policy, kRASPropIPSecPolicyDirection); 1943 if (isString(policydirection)) { 1944 1945 if (CFEqual(policydirection, kRASValIPSecPolicyDirectionIn)) 1946 out = 0; 1947 else if (CFEqual(policydirection, kRASValIPSecPolicyDirectionOut)) 1948 in = 0; 1949 else if (!CFEqual(policydirection, kRASValIPSecPolicyDirectionInOut)) 1950 FAIL("incorrect policy direction found"); 1951 } 1952 1953 if (out == 0) 1954 continue; // no need for routes for 'in' policies 1955 1956 policylevel = CFDictionaryGetValue(policy, kRASPropIPSecPolicyLevel); 1957 if (!isString(policylevel) || CFEqual(policylevel, kRASValIPSecPolicyLevelNone)) 1958 continue; // no need for routes for 'none' policies 1959 1960 if (!CFEqual(policylevel, kRASValIPSecPolicyLevelRequire) && !CFEqual(policylevel, kRASValIPSecPolicyLevelDiscard) && !CFEqual(policylevel, kRASValIPSecPolicyLevelUnique)) 1961 FAIL("incorrect policy level"); 1962 1963 /* get local and remote networks */ 1964 1965 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyLocalAddress, str, sizeof(str))) 1966 FAIL("incorrect local network"); 1967 1968 local_net.sin_len = sizeof(local_net); 1969 local_net.sin_family = AF_INET; 1970 local_net.sin_port = htons(0); 1971 if (!inet_aton(str, &local_net.sin_addr)) 1972 FAIL("incorrect local network"); 1973 1974 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyRemoteAddress, str, sizeof(str))) 1975 FAIL("incorrect remote network0"); 1976 1977 remote_net.sin_len = sizeof(remote_net); 1978 remote_net.sin_family = AF_INET; 1979 remote_net.sin_port = htons(0); 1980 if (!inet_aton(str, &remote_net.sin_addr)) 1981 FAIL("incorrect remote network1"); 1982 1983 // don't try to delete routes that weren't installed 1984 if (cmd == RTM_DELETE) { 1985 service_route_t *p = get_service_route(serv, local_net.sin_addr.s_addr, remote_net.sin_addr.s_addr); 1986 if (!p || !p->installed) { 1987 syslog(LOG_INFO, "ignoring uninstalled route: (address %s, gateway %s)\n", 1988 addr2ascii(AF_INET, &remote_net.sin_addr, sizeof(remote_net.sin_addr), remote_addr_str), 1989 addr2ascii(AF_INET, &gateway, sizeof(gateway), gateway_addr_str)); 1990 continue; 1991 } 1992 } 1993 1994 memset(&rtmsg, 0, sizeof(rtmsg)); 1995 rtmsg.hdr.rtm_type = cmd; 1996 rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC; 1997 rtmsg.hdr.rtm_flags |= RTF_GATEWAY; 1998 rtmsg.hdr.rtm_version = RTM_VERSION; 1999 rtmsg.hdr.rtm_seq = ++rtm_seq; 2000 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY; 2001 rtmsg.dst.sin_len = sizeof(rtmsg.dst); 2002 rtmsg.dst.sin_family = AF_INET; 2003 rtmsg.dst.sin_addr = remote_net.sin_addr; 2004 rtmsg.gway.sin_len = sizeof(rtmsg.gway); 2005 rtmsg.gway.sin_family = AF_INET; 2006 rtmsg.gway.sin_addr = gateway; 2007 rtmsg.mask.sin_len = sizeof(rtmsg.mask); 2008 rtmsg.mask.sin_family = AF_INET; 2009 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePrefix, &remote_prefix, 24); 2010 for (rtmsg.mask.sin_addr.s_addr = 0; remote_prefix; remote_prefix--) 2011 rtmsg.mask.sin_addr.s_addr = (rtmsg.mask.sin_addr.s_addr>>1)|0x80000000; 2012 rtmsg.mask.sin_addr.s_addr = htonl(rtmsg.mask.sin_addr.s_addr); 2013 len = sizeof(rtmsg); 2014 rtmsg.hdr.rtm_msglen = len; 2015 if (write(s, &rtmsg, len) < 0) { 2016 syslog(LOG_ERR, "cannot write on routing socket: %s (address %s, gateway %s)\n", strerror(errno), 2017 addr2ascii(AF_INET, &remote_net.sin_addr, sizeof(remote_net.sin_addr), remote_addr_str), 2018 addr2ascii(AF_INET, &gateway, sizeof(gateway), gateway_addr_str)); //FAIL("cannot write on routing socket", errno); 2019 } else { 2020 // update service to indicate route was installed/not 2021 update_service_route(serv, 2022 local_net.sin_addr.s_addr, 0xFFFFFFFF, 2023 remote_net.sin_addr.s_addr, ntohl(rtmsg.mask.sin_addr.s_addr), 2024 gateway.s_addr, 0, 2025 (cmd == RTM_ADD)); 2026 2027 CFStringAppendFormat(installedRoutesList, 0, CFSTR("%s, "), netname(remote_net.sin_addr.s_addr, rtmsg.mask.sin_addr.s_addr)); 2028 } 2029 2030 } 2031 2032 installedRoutesListLen = CFStringGetLength(installedRoutesList); 2033 if (installedRoutesListLen > 0) { 2034 installed_routes_str = calloc(1, installedRoutesListLen + 1); 2035 if (installed_routes_str) { 2036 CFStringGetCString(installedRoutesList, installed_routes_str, installedRoutesListLen + 1, kCFStringEncodingASCII); 2037 addr2ascii(AF_INET, (struct in_addr *)&gateway, sizeof(gateway), gateway_addr_str); 2038 syslog(LOG_NOTICE, "installed routes: addresses %sgateway %s\n", installed_routes_str, gateway_addr_str); 2039 free (installed_routes_str); 2040 } 2041 } 2042 2043 CFRelease(installedRoutesList); 2044 close(s); 2045 return 0; 2046 2047fail: 2048 if (installedRoutesList) 2049 CFRelease(installedRoutesList); 2050 if (s != -1) 2051 close(s); 2052 return -1; 2053} 2054 2055/* ----------------------------------------------------------------------------- 2056Install IPSec Routes. 2057This will not configure IKE or intall policies, and must be done separately. 2058 2059Parameters: 2060ipsec_dict: dictionary containing the IPSec configuration. 2061index: -1, install all policies defined in the configuration 2062 otherwise, install only the policy at the specified index. 2063errstr: error string returned in case of configuration error. 2064gateway: gateway for the routes 2065 2066Return code: 20670 if successful, -1 otherwise. 2068----------------------------------------------------------------------------- */ 2069int 2070IPSecInstallRoutes(struct service *serv, CFDictionaryRef ipsec_dict, CFIndex index, char ** errstr, struct in_addr gateway) 2071{ 2072 return install_remove_routes(serv, RTM_ADD, ipsec_dict, index, errstr, gateway); 2073} 2074 2075/* ----------------------------------------------------------------------------- 2076Remove IPSec Routes. 2077This will not unconfigure IKE or remove policies, and must be done separately. 2078 2079Parameters: 2080ipsec_dict: dictionary containing the IPSec configuration. 2081index: -1, install all policies defined in the configuration 2082 otherwise, install only the policy at the specified index. 2083errstr: error string returned in case of configuration error. 2084gateway: gateway for the routes 2085 2086Return code: 20870 if successful, -1 otherwise. 2088----------------------------------------------------------------------------- */ 2089int 2090IPSecRemoveRoutes(struct service *serv, CFDictionaryRef ipsec_dict, CFIndex index, char ** errstr, struct in_addr gateway) 2091{ 2092 return install_remove_routes(serv, RTM_DELETE, ipsec_dict, index, errstr, gateway); 2093} 2094 2095/* ----------------------------------------------------------------------------- 2096Remove IPSec kernel policies. 2097This will not unconfigure IKE and must be done separately. 2098 2099Parameters: 2100ipsec_dict: dictionary containing the IPSec configuration. 2101index: -1, remove all policies defined in the configuration 2102 otherwise, remove only the policy at the specified index. 2103errstr: error string returned in case of configuration error. 2104 2105Return code: 21060 if successful, -1 otherwise. 2107----------------------------------------------------------------------------- */ 2108int 2109IPSecRemovePolicies(CFDictionaryRef ipsec_dict, CFIndex index, char ** errstr) 2110{ 2111 int s = -1, err, seq = 0, nb, i; 2112 char policystr_in[64], policystr_out[64], str[32]; 2113 caddr_t policy_in = 0, policy_out = 0; 2114 u_int32_t policylen_in, policylen_out, local_prefix, remote_prefix; 2115 u_int32_t protocol = 0xFF; 2116 CFArrayRef policies; 2117 struct sockaddr_in local_net; 2118 struct sockaddr_in remote_net; 2119 char src_address[32], dst_address[32]; 2120 CFIndex start, end; 2121 2122 s = pfkey_open(); 2123 if (s < 0) 2124 FAIL("cannot open a pfkey socket"); 2125 2126 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecLocalAddress, src_address, sizeof(src_address))) 2127 FAIL("incorrect local address"); 2128 2129 if (!GetStrAddrFromDict(ipsec_dict, kRASPropIPSecRemoteAddress, dst_address, sizeof(dst_address))) 2130 FAIL("incorrect remote address"); 2131 2132 policies = CFDictionaryGetValue(ipsec_dict, kRASPropIPSecPolicies); 2133 if (!isArray(policies) 2134 || (nb = CFArrayGetCount(policies)) == 0 2135 || index > nb) 2136 FAIL("no policies found"); 2137 2138 if (index == -1) { 2139 start = 0; 2140 end = nb; 2141 } 2142 else { 2143 start = index; 2144 end = index + 1; 2145 } 2146 for (i = start; i < end; i++) { 2147 2148 CFDictionaryRef policy; 2149 int tunnel, in, out; 2150 CFStringRef policymode, policydirection; 2151 2152 policy = CFArrayGetValueAtIndex(policies, i); 2153 if (!isDictionary(policy)) 2154 FAIL("incorrect policy found"); 2155 2156 /* build policies in and out */ 2157 2158 tunnel = 1; 2159 policymode = CFDictionaryGetValue(policy, kRASPropIPSecPolicyMode); 2160 if (isString(policymode)) { 2161 2162 if (CFEqual(policymode, kRASValIPSecPolicyModeTunnel)) 2163 tunnel = 1; 2164 else if (CFEqual(policymode, kRASValIPSecPolicyModeTransport)) 2165 tunnel = 0; 2166 else 2167 FAIL("incorrect policy type found"); 2168 } 2169 2170 /* if policy direction is not specified, in/out is assumed */ 2171 in = out = 1; 2172 policydirection = CFDictionaryGetValue(policy, kRASPropIPSecPolicyDirection); 2173 if (isString(policydirection)) { 2174 2175 if (CFEqual(policydirection, kRASValIPSecPolicyDirectionIn)) 2176 out = 0; 2177 else if (CFEqual(policydirection, kRASValIPSecPolicyDirectionOut)) 2178 in = 0; 2179 else if (!CFEqual(policydirection, kRASValIPSecPolicyDirectionInOut)) 2180 FAIL("incorrect policy direction found"); 2181 } 2182 2183 snprintf(policystr_out, sizeof(policystr_out), "out"); 2184 snprintf(policystr_in, sizeof(policystr_in), "in"); 2185 2186 policy_in = ipsec_set_policy(policystr_in, strlen(policystr_in)); 2187 if (policy_in == 0) 2188 FAIL("cannot set policy in"); 2189 2190 policy_out = ipsec_set_policy(policystr_out, strlen(policystr_out)); 2191 if (policy_out == 0) 2192 FAIL("cannot set policy out"); 2193 2194 policylen_in = (ALIGNED_CAST(struct sadb_x_policy *)policy_in)->sadb_x_policy_len << 3; 2195 policylen_out = (ALIGNED_CAST(struct sadb_x_policy *)policy_out)->sadb_x_policy_len << 3; 2196 2197 2198 if (tunnel) { 2199 /* get local and remote networks */ 2200 2201 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyLocalAddress, str, sizeof(str))) 2202 FAIL("incorrect local network"); 2203 2204 local_net.sin_len = sizeof(local_net); 2205 local_net.sin_family = AF_INET; 2206 local_net.sin_port = htons(0); 2207 if (!inet_aton(str, &local_net.sin_addr)) 2208 FAIL("incorrect local network"); 2209 2210 GetIntFromDict(policy, kRASPropIPSecPolicyLocalPrefix, &local_prefix, 24); 2211 2212 if (!GetStrNetFromDict(policy, kRASPropIPSecPolicyRemoteAddress, str, sizeof(str))) 2213 FAIL("incorrect remote network"); 2214 2215 remote_net.sin_len = sizeof(remote_net); 2216 remote_net.sin_family = AF_INET; 2217 remote_net.sin_port = htons(0); 2218 if (!inet_aton(str, &remote_net.sin_addr)) 2219 FAIL("incorrect remote network"); 2220 2221 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePrefix, &remote_prefix, 24); 2222 2223 } 2224 else { 2225 u_int32_t val; 2226 2227 local_net.sin_len = sizeof(local_net); 2228 local_net.sin_family = AF_INET; 2229 GetIntFromDict(policy, kRASPropIPSecPolicyLocalPort, &val, 0); 2230 local_net.sin_port = htons(val); 2231 if (!inet_aton(src_address, &local_net.sin_addr)) 2232 FAIL("incorrect local address"); 2233 2234 local_prefix = local_net.sin_addr.s_addr ? 32 : 0; 2235 2236 remote_net.sin_len = sizeof(remote_net); 2237 remote_net.sin_family = AF_INET; 2238 GetIntFromDict(policy, kRASPropIPSecPolicyRemotePort, &val, 0); 2239 remote_net.sin_port = htons(val); 2240 if (!inet_aton(dst_address, &remote_net.sin_addr)) 2241 FAIL("incorrect remote address"); 2242 2243 remote_prefix = remote_net.sin_addr.s_addr ? 32 : 0; 2244 2245 GetIntFromDict(policy, kRASPropIPSecPolicyProtocol, &protocol, 0); 2246 } 2247 2248 /* unconfigure kernel policies */ 2249 2250 if (out) { 2251 err = pfkey_send_spddelete(s, (struct sockaddr *)&local_net, local_prefix, (struct sockaddr *)&remote_net, remote_prefix, protocol, policy_out, policylen_out, seq++); 2252 if (err < 0) 2253 FAIL("cannot delete policy out"); 2254 } 2255 2256 if (in) { 2257 err = pfkey_send_spddelete(s, (struct sockaddr *)&remote_net, remote_prefix, (struct sockaddr *)&local_net, local_prefix, protocol, policy_in, policylen_in, seq++); 2258 if (err < 0) 2259 FAIL("cannot delete policy in"); 2260 } 2261 2262 free(policy_in); 2263 free(policy_out); 2264 policy_in = 0; 2265 policy_out = 0; 2266 2267 } 2268 2269 pfkey_close(s); 2270 return 0; 2271 2272fail: 2273 if (policy_in) 2274 free(policy_in); 2275 if (policy_out) 2276 free(policy_out); 2277 if (s != -1) 2278 pfkey_close(s); 2279 return -1; 2280} 2281 2282 2283/* ----------------------------------------------------------------------------- 2284Remove security associations. 2285This will not unconfigure IKE or remove policies and must be done separately. 2286 2287Parameters: 2288src: source address of the security association to remove. 2289dst: destination address of the security association to remove. 2290 2291Return code: 22920 if successful, pf_key error otherwise. 2293----------------------------------------------------------------------------- */ 2294int 2295IPSecRemoveSecurityAssociations(struct sockaddr *src, struct sockaddr *dst) 2296{ 2297 int s, err; 2298 2299 s = pfkey_open(); 2300 if (s < 0) 2301 return -1; 2302 2303 err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, src, dst); 2304 if (err < 0) 2305 goto end; 2306 2307 err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, dst, src); 2308 if (err < 0) 2309 goto end; 2310 2311end: 2312 pfkey_close(s); 2313 return err; 2314} 2315 2316/* ----------------------------------------------------------------------------- 2317----------------------------------------------------------------------------- */ 2318#define ROUNDUP(a, size) \ 2319 (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 2320 2321#define NEXT_SA(ap) (ap) = (struct sockaddr *) \ 2322 ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ 2323 sizeof(u_int32_t)) :\ 2324 sizeof(u_int32_t))) 2325 2326/* ----------------------------------------------------------------------------- 2327----------------------------------------------------------------------------- */ 2328static void 2329get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 2330{ 2331 int i; 2332 2333 for (i = 0; i < RTAX_MAX; i++) { 2334 if (addrs & (1 << i)) { 2335 rti_info[i] = sa; 2336 NEXT_SA(sa); 2337 addrs ^= (1 << i); 2338 } else 2339 rti_info[i] = NULL; 2340 } 2341} 2342 2343 2344#define BUFLEN (sizeof(struct rt_msghdr) + 512) /* 8 * sizeof(struct sockaddr_in6) = 192 */ 2345 2346/* ----------------------------------------------------------------------------- 2347----------------------------------------------------------------------------- */ 2348void 2349sockaddr_to_string(const struct sockaddr_storage *address, char *buf, size_t bufLen) 2350{ 2351 bzero(buf, bufLen); 2352 switch (address->ss_family) { 2353 case AF_INET : 2354 (void)inet_ntop(((struct sockaddr_in *)address)->sin_family, 2355 &((struct sockaddr_in *)address)->sin_addr, 2356 buf, 2357 bufLen); 2358 break; 2359 case AF_INET6 : { 2360 (void)inet_ntop(((struct sockaddr_in6 *)address)->sin6_family, 2361 &((struct sockaddr_in6 *)address)->sin6_addr, 2362 buf, 2363 bufLen); 2364 if (((struct sockaddr_in6 *)address)->sin6_scope_id) { 2365 int n; 2366 2367 n = strlen(buf); 2368 if ((n+IF_NAMESIZE+1) <= bufLen) { 2369 buf[n++] = '%'; 2370 if_indextoname(((struct sockaddr_in6 *)address)->sin6_scope_id, &buf[n]); 2371 } 2372 } 2373 break; 2374 } 2375 case AF_LINK : 2376 if (((struct sockaddr_dl *)address)->sdl_len < bufLen) { 2377 bufLen = ((struct sockaddr_dl *)address)->sdl_len; 2378 } else { 2379 bufLen = bufLen - 1; 2380 } 2381 2382 bcopy(((struct sockaddr_dl *)address)->sdl_data, buf, bufLen); 2383 break; 2384 default : 2385 snprintf(buf, bufLen, "unexpected address family %d", address->ss_family); 2386 break; 2387 } 2388} 2389 2390/* ----------------------------------------------------------------------------- 2391For a given destination address, get the source address and interface 2392that will be used to send traffic. 2393 2394Parameters: 2395src: source address we want to know. 2396dst: destination address we will talk to. 2397if_name: interface that will be used. 2398 2399Return code: 24000 if successful, -1 otherwise. 2401----------------------------------------------------------------------------- */ 2402int 2403get_src_address(struct sockaddr *src, const struct sockaddr *dst, char *ifscope, char *if_name) 2404{ 2405 union { // Wcast-align fix - force alignment 2406 struct rt_msghdr rtm; 2407 char buf[BUFLEN]; 2408 } aligned_buf; 2409 u_int ifscope_index; 2410 pid_t pid = getpid(); 2411 int rsock = -1, seq = 0, n; 2412 struct sockaddr *rti_info[RTAX_MAX] __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 2413 struct sockaddr *sa; 2414 struct sockaddr_dl *sdl; 2415 2416 rsock = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE); 2417 if (rsock == -1) 2418 return -1; 2419 2420 bzero(&aligned_buf, sizeof(aligned_buf)); 2421 2422 aligned_buf.rtm.rtm_msglen = sizeof(struct rt_msghdr); 2423 aligned_buf.rtm.rtm_version = RTM_VERSION; 2424 aligned_buf.rtm.rtm_type = RTM_GET_SILENT; 2425 aligned_buf.rtm.rtm_flags = RTF_STATIC|RTF_UP|RTF_HOST|RTF_GATEWAY; 2426 aligned_buf.rtm.rtm_addrs = RTA_DST|RTA_IFP; /* Both destination and device */ 2427 aligned_buf.rtm.rtm_pid = pid; 2428 aligned_buf.rtm.rtm_seq = ++seq; 2429 2430 if (ifscope != NULL) { 2431 ifscope_index = if_nametoindex(ifscope); 2432 aligned_buf.rtm.rtm_flags |= RTF_IFSCOPE; 2433 aligned_buf.rtm.rtm_index = ifscope_index; 2434 } 2435 2436 sa = (struct sockaddr *) (aligned_buf.buf + sizeof(struct rt_msghdr)); 2437 bcopy(dst, sa, dst->sa_len); 2438 aligned_buf.rtm.rtm_msglen += sa->sa_len; 2439 2440 sdl = (struct sockaddr_dl *) ((void *)sa + sa->sa_len); 2441 sdl->sdl_family = AF_LINK; 2442 sdl->sdl_len = sizeof (struct sockaddr_dl); 2443 aligned_buf.rtm.rtm_msglen += sdl->sdl_len; 2444 2445 do { 2446 n = write(rsock, &aligned_buf, aligned_buf.rtm.rtm_msglen); 2447 if (n == -1 && errno != EINTR) { 2448 close(rsock); 2449 return -1; 2450 } 2451 } while (n == -1); 2452 2453 do { 2454 n = read(rsock, (void *)&aligned_buf, sizeof(aligned_buf)); 2455 if (n == -1 && errno != EINTR) { 2456 close(rsock); 2457 return -1; 2458 } 2459 } while (n == -1); 2460 2461 get_rtaddrs(aligned_buf.rtm.rtm_addrs, sa, rti_info); 2462 2463#if 0 2464{ /* DEBUG */ 2465 int i; 2466 char buf[200]; 2467 2468 //SCLog(gSCNCDebug, LOG_DEBUG, CFSTR("rtm_flags = 0x%8.8x"), rtm->rtm_flags); 2469 2470 for (i=0; i<RTAX_MAX; i++) { 2471 if (rti_info[i] != NULL) { 2472 sockaddr_to_string(rti_info[i], buf, sizeof(buf)); 2473 printf("%d: %s\n", i, buf); 2474 } 2475 } 2476} /* DEBUG */ 2477#endif 2478 if (rti_info[RTAX_IFA] == NULL || 2479 src == NULL || 2480 (if_name && rti_info[RTAX_IFP] == NULL)) { 2481 close(rsock); 2482 return -1; 2483 } 2484 2485 if (rti_info[RTAX_IFA]->sa_family == AF_INET6) { 2486 struct sockaddr_in6 *addr6 = ALIGNED_CAST(struct sockaddr_in6 *)rti_info[RTAX_IFA]; 2487 2488 /* XXX: check for link local and scopeid */ 2489 if (IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) { 2490 u_int16_t index; 2491 index = addr6->sin6_addr.__u6_addr.__u6_addr16[1]; 2492 if (index != 0) { 2493 addr6->sin6_addr.__u6_addr.__u6_addr16[1] = 0; 2494 if (addr6->sin6_scope_id == 0) { 2495 addr6->sin6_scope_id = ntohs(index); 2496 } 2497 } 2498 } 2499 } 2500 2501 bcopy(rti_info[RTAX_IFA], src, rti_info[RTAX_IFA]->sa_len); 2502 if (if_name) 2503 strncpy(if_name, ((struct sockaddr_dl *)(void*)rti_info[RTAX_IFP])->sdl_data, IF_NAMESIZE); // Wcast-align fix (void*) - remove warning 2504 2505 close(rsock); 2506 return 0; 2507} 2508 2509/* ----------------------------------------------------------------------------- 2510Get the mtu of an interface. 2511 2512Parameters: 2513if_name: interface we want information about. 2514 2515Return code: 2516mtu for the interface. 2517----------------------------------------------------------------------------- */ 2518u_int32_t 2519get_if_mtu(char *if_name) 2520{ 2521 struct ifreq ifr; 2522 int s; 2523 2524 ifr.ifr_mtu = 1500; 2525 2526 s = socket(AF_INET, SOCK_DGRAM, 0); 2527 if (s >= 0) { 2528 strlcpy(ifr.ifr_name, if_name, sizeof (ifr.ifr_name)); 2529 ioctl(s, SIOCGIFMTU, (caddr_t) &ifr); 2530 close(s); 2531 } 2532 return ifr.ifr_mtu; 2533} 2534 2535/* ----------------------------------------------------------------------------- 2536 Get the media of an interface. 2537 2538 Parameters: 2539 if_name: interface we want information about. 2540 2541 Return code: 2542 media for the interface. 2543 ----------------------------------------------------------------------------- */ 2544u_int32_t 2545get_if_media(char *if_name) 2546{ 2547 struct ifmediareq ifr; 2548 int s, err; 2549 2550 bzero(&ifr, sizeof(ifr)); 2551 2552 s = socket(AF_INET, SOCK_DGRAM, 0); 2553 if (s >= 0) { 2554 strlcpy(ifr.ifm_name, if_name, sizeof (ifr.ifm_name)); 2555 if ((err = ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifr)) < 0) { 2556// syslog(LOG_ERR, "can't get interface '%s' media, err %d", if_name, err); 2557 } 2558 close(s); 2559 } 2560 return ifr.ifm_current; 2561} 2562 2563/* ----------------------------------------------------------------------------- 2564Get the baudrate of an interface. 2565 2566Parameters: 2567if_name: interface we want information about. 2568 2569Return code: 2570baudrate for the interface. 2571----------------------------------------------------------------------------- */ 2572u_int32_t 2573get_if_baudrate(char *if_name) 2574{ 2575 char * buf = NULL; 2576 size_t buf_len = 0; 2577 struct if_msghdr * ifm; 2578 unsigned int if_index; 2579 u_int32_t baudrate = 0; 2580 int mib[6]; 2581 2582 /* get the interface index */ 2583 2584 if_index = if_nametoindex(if_name); 2585 if (if_index == 0) { 2586 goto done; // if unknown interface 2587 } 2588 2589 /* get information for the specified device */ 2590 2591 mib[0] = CTL_NET; 2592 mib[1] = PF_ROUTE; 2593 mib[2] = 0; 2594 mib[3] = AF_LINK; 2595 mib[4] = NET_RT_IFLIST; 2596 mib[5] = if_index; /* ask for exactly one interface */ 2597 2598 if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) < 0) { 2599 goto done; 2600 } 2601 buf = malloc(buf_len); 2602 if (sysctl(mib, 6, buf, &buf_len, NULL, 0) < 0) { 2603 goto done; 2604 } 2605 2606 /* get the baudrate for the interface */ 2607 2608 ifm = ALIGNED_CAST(struct if_msghdr *)buf; 2609 switch (ifm->ifm_type) { 2610 case RTM_IFINFO : { 2611 baudrate = ifm->ifm_data.ifi_baudrate; 2612 break; 2613 } 2614 } 2615 2616done : 2617 2618 if (buf != NULL) 2619 free(buf); 2620 2621 return baudrate; 2622} 2623 2624/* ----------------------------------------------------------------------------- 2625Set the preference for security association, between "Prefer old" or "Prefer new". 2626The kernel is compiled to prefer old associations, which means that if a second 2627association with the same addresses is created while the first one is not expired, 2628then the second one will not be used for outgoing traffic. 2629When we change to prefer the new one, the old one is not used anymore for outgoing 2630traffic. 2631KAME/BSD prefers the old security association. 2632This does not work for VPN servers where we need to always use the most recent 2633association as a client can connect, then disconnect without the server noticing, 2634and reconnect again, creating a new association but with the old one still around. 2635 2636Parameters: 2637oldval: old value returned, to restore later if need. 2638newval: new value to set. 0 to prefer old, 1 to prefer new. 2639 2640Return code: 2641errno 2642----------------------------------------------------------------------------- */ 2643int IPSecSetSecurityAssociationsPreference(int *oldval, int newval) 2644{ 2645 size_t len = sizeof(int); 2646 2647 if (newval != 0 && newval != 1) 2648 return 0; // ignore the command 2649 2650 return sysctlbyname("net.key.prefered_oldsa", oldval, &len, &newval, sizeof(int)); 2651} 2652 2653 2654/* ----------------------------------------------------------------------------- 2655Create a default configuration for the L2TP protocol. 2656L2PT has a defined set of parameters for IPSec, and this function will create a 2657dictionary with all necessary keys. 2658The call will need to complete or adjust the configuration with specific keys 2659like authentications keys, or with more specific parameters. 2660 2661Parameters: 2662src: source address of the configuration. 2663dst: destination address of the configuration. 2664authenticationMethod: SharedSecret or Certificate. 2665isClient: 1 if client, 0 if server. 2666 configuration varies slightly depending on client or server mode. 2667 2668Return code: 2669the configuration dictionary 2670----------------------------------------------------------------------------- */ 2671CFMutableDictionaryRef 2672IPSecCreateL2TPDefaultConfiguration(struct sockaddr_in *src, struct sockaddr_in *dst, char *dst_hostName, CFStringRef authenticationMethod, 2673 int isClient, int natt_multiple_users, CFStringRef identifierVerification) 2674{ 2675 CFStringRef src_string, dst_string, hostname_string = NULL; 2676 CFMutableDictionaryRef ipsec_dict, policy0, policy1 = NULL; 2677 CFMutableArrayRef policy_array, encryption_array, hash_array; 2678 CFMutableDictionaryRef proposal_dict; 2679 CFMutableArrayRef proposal_array; 2680 CFNumberRef src_port_num, dst_port_num, dst_port1_num, proto_num, natt_multiuser_mode = NULL, dhgroup, lifetime; 2681 int zero = 0, one = 1, udpproto = IPPROTO_UDP, val; 2682 struct sockaddr_in *our_address = (struct sockaddr_in *)src; 2683 struct sockaddr_in *peer_address = (struct sockaddr_in *)dst; 2684 2685 /* create the main ipsec dictionary */ 2686 ipsec_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2687 2688 if (dst_hostName) 2689 hostname_string = CFStringCreateWithCString(0, dst_hostName, kCFStringEncodingASCII); 2690 src_string = CFStringCreateWithCString(0, addr2ascii(AF_INET, &our_address->sin_addr, sizeof(our_address->sin_addr), 0), kCFStringEncodingASCII); 2691 dst_string = CFStringCreateWithCString(0, addr2ascii(AF_INET, &peer_address->sin_addr, sizeof(peer_address->sin_addr), 0), kCFStringEncodingASCII); 2692 val = ntohs(our_address->sin_port); /* because there is no uint16 type */ 2693 src_port_num = CFNumberCreate(0, kCFNumberIntType, &val); 2694 val = ntohs(peer_address->sin_port); /* because there is no uint16 type */ 2695 dst_port_num = CFNumberCreate(0, kCFNumberIntType, &val); 2696 dst_port1_num = CFNumberCreate(0, kCFNumberIntType, &zero); 2697 proto_num = CFNumberCreate(0, kCFNumberIntType, &udpproto); 2698 if (!isClient) 2699 natt_multiuser_mode = CFNumberCreate(0, kCFNumberIntType, natt_multiple_users ? &one : &zero); 2700 2701 2702 CFDictionarySetValue(ipsec_dict, kRASPropIPSecAuthenticationMethod, authenticationMethod); 2703 CFDictionarySetValue(ipsec_dict, kRASPropIPSecLocalAddress, src_string); 2704 CFDictionarySetValue(ipsec_dict, kRASPropIPSecRemoteAddress, dst_string); 2705 CFDictionarySetValue(ipsec_dict, kRASPropIPSecProposalsBehavior, isClient ? kRASValIPSecProposalsBehaviorObey : kRASValIPSecProposalsBehaviorClaim); 2706 if (isClient && CFEqual(authenticationMethod, kRASValIPSecAuthenticationMethodCertificate)) { 2707 if (identifierVerification) { 2708 CFDictionarySetValue(ipsec_dict, kRASPropIPSecIdentifierVerification, identifierVerification); 2709 } 2710 else { 2711 if (dst_hostName) { 2712 CFDictionarySetValue(ipsec_dict, kRASPropIPSecRemoteIdentifier, hostname_string); 2713 CFDictionarySetValue(ipsec_dict, kRASPropIPSecIdentifierVerification, kRASValIPSecIdentifierVerificationUseRemoteIdentifier); 2714 } else 2715 CFDictionarySetValue(ipsec_dict, kRASPropIPSecIdentifierVerification, kRASValIPSecIdentifierVerificationGenerateFromRemoteAddress); 2716 } 2717 } else /*server or no certificate */ 2718 CFDictionarySetValue(ipsec_dict, kRASPropIPSecIdentifierVerification, kRASValIPSecIdentifierVerificationNone); 2719 2720 /* if server - set natt multiple user mode */ 2721 if (!isClient) 2722 CFDictionarySetValue(ipsec_dict, kRASPropIPSecNattMultipleUsersEnabled, natt_multiuser_mode); 2723 2724 /* create the phase 1 proposals */ 2725 proposal_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 2726 val = 2; 2727 dhgroup = CFNumberCreate(0, kCFNumberIntType, &val); 2728 val = 3600; 2729 lifetime = CFNumberCreate(0, kCFNumberIntType, &val); 2730 // --- AES-256/SHA1 2731 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2732 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES256); 2733 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmSHA1); 2734 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 2735 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2736 CFArraySetValueAtIndex(proposal_array, 0, proposal_dict); 2737 CFRelease(proposal_dict); 2738 2739 // --- AES-256/MD5 2740 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2741 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES256); 2742 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmMD5); 2743 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 2744 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2745 CFArraySetValueAtIndex(proposal_array, 1, proposal_dict); 2746 CFRelease(proposal_dict); 2747 2748 // --- AES/SHA1 2749 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2750 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES); 2751 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmSHA1); 2752 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 2753 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2754 CFArraySetValueAtIndex(proposal_array, 2, proposal_dict); 2755 CFRelease(proposal_dict); 2756 2757 // --- AES/MD5 2758 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2759 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES); 2760 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmMD5); 2761 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 2762 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2763 CFArraySetValueAtIndex(proposal_array, 3, proposal_dict); 2764 CFRelease(proposal_dict); 2765 2766 // --- 3DES/SHA1 2767 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2768 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithm3DES); 2769 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmSHA1); 2770 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 2771 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2772 CFArraySetValueAtIndex(proposal_array, 4, proposal_dict); 2773 CFRelease(proposal_dict); 2774 2775 // --- 3DES/MD5 2776 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2777 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithm3DES); 2778 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmMD5); 2779 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 2780 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2781 CFArraySetValueAtIndex(proposal_array, 5, proposal_dict); 2782 CFRelease(proposal_dict); 2783 CFRelease(dhgroup); 2784 CFRelease(lifetime); 2785 CFDictionarySetValue(ipsec_dict, kRASPropIPSecProposals, proposal_array); 2786 CFRelease(proposal_array); 2787 2788 /* create the policies */ 2789 policy0 = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2790 CFDictionarySetValue(policy0, kRASPropIPSecPolicyLocalPort, src_port_num); 2791 CFDictionarySetValue(policy0, kRASPropIPSecPolicyRemotePort, dst_port_num); 2792 CFDictionarySetValue(policy0, kRASPropIPSecPolicyProtocol, proto_num); 2793 CFDictionarySetValue(policy0, kRASPropIPSecPolicyMode, kRASValIPSecPolicyModeTransport); 2794 CFDictionarySetValue(policy0, kRASPropIPSecPolicyLevel, kRASValIPSecPolicyLevelRequire); 2795 encryption_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 2796 CFArraySetValueAtIndex(encryption_array, 0, kRASValIPSecPolicyEncryptionAlgorithmAES256); 2797 CFArraySetValueAtIndex(encryption_array, 1, kRASValIPSecPolicyEncryptionAlgorithmAES); 2798 CFArraySetValueAtIndex(encryption_array, 2, kRASValIPSecPolicyEncryptionAlgorithm3DES); 2799 CFDictionarySetValue(policy0, kRASPropIPSecPolicyEncryptionAlgorithm, encryption_array); 2800 CFRelease(encryption_array); 2801 hash_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 2802 CFArraySetValueAtIndex(hash_array, 0, kRASValIPSecPolicyHashAlgorithmSHA1); 2803 CFArraySetValueAtIndex(hash_array, 1, kRASValIPSecPolicyHashAlgorithmMD5); 2804 CFDictionarySetValue(policy0, kRASPropIPSecPolicyHashAlgorithm, hash_array); 2805 CFRelease(hash_array); 2806 2807 if (isClient) { 2808 policy1 = CFDictionaryCreateMutableCopy(0, 0, policy0); 2809 CFDictionarySetValue(policy1, kRASPropIPSecPolicyRemotePort, dst_port1_num); 2810 CFDictionarySetValue(policy1, kRASPropIPSecPolicyDirection, kRASValIPSecPolicyDirectionIn); 2811 } 2812 2813 policy_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 2814 CFArraySetValueAtIndex(policy_array, 0, policy0); 2815 if (isClient) 2816 CFArraySetValueAtIndex(policy_array, 1, policy1); 2817 2818 CFRelease(policy0); 2819 if (isClient) 2820 CFRelease(policy1); 2821 2822 CFDictionarySetValue(ipsec_dict, kRASPropIPSecPolicies, policy_array); 2823 CFRelease(policy_array); 2824 2825 CFRelease(src_string); 2826 CFRelease(dst_string); 2827 CFRelease(src_port_num); 2828 CFRelease(dst_port_num); 2829 CFRelease(dst_port1_num); 2830 CFRelease(proto_num); 2831 if (!isClient) 2832 CFRelease(natt_multiuser_mode); 2833 if (hostname_string) 2834 CFRelease(hostname_string); 2835 2836 return ipsec_dict; 2837} 2838 2839/* ----------------------------------------------------------------------------- 2840Create a default configuration for the Cisco Server connection. 2841L2PT has a defined set of parameters for IPSec, and this function will create a 2842dictionary with all necessary keys. 2843The call will need to complete or adjust the configuration with specific keys 2844like authentications keys, or with more specific parameters. 2845 2846Parameters: 2847src: source address of the configuration. 2848dst: destination address of the configuration. 2849authenticationMethod: SharedSecret or Certificate. 2850isClient: 1 if client, 0 if server. 2851 configuration varies slightly depending on client or server mode. 2852 2853Return code: 2854the configuration dictionary 2855----------------------------------------------------------------------------- */ 2856CFMutableDictionaryRef 2857IPSecCreateCiscoDefaultConfiguration(struct sockaddr_in *src, struct sockaddr_in *dst, CFStringRef dst_hostName, CFStringRef authenticationMethod, 2858 int isClient, int natt_multiple_users, CFStringRef identifierVerification) 2859{ 2860 CFStringRef src_string, dst_string; 2861 CFMutableDictionaryRef ipsec_dict, proposal_dict; 2862 CFMutableArrayRef proposal_array; 2863#if 0 2864 CFMutableDictionaryRef policy0, policy1 = NULL; 2865 CFMutableArrayRef policy_array, encryption_array, hash_array; 2866#endif 2867 CFNumberRef src_port_num, dst_port_num, dst_port1_num, proto_num, natt_multiuser_mode = NULL, cfone = NULL, cfzero = NULL, dhgroup, lifetime, dpd_delay; 2868 int zero = 0, one = 1, anyproto = -1, val, nb; 2869 struct sockaddr_in *our_address = (struct sockaddr_in *)src; 2870 struct sockaddr_in *peer_address = (struct sockaddr_in *)dst; 2871 2872 // remove as soon as we add dh_group 5 to the loop 2873#define ADD_DHGROUP5 1 2874#ifdef ADD_DHGROUP5 2875 int add_group5 = 0, val5 = 5; 2876 CFNumberRef dhgroup5 = NULL; 2877#endif 2878 2879 /* create the main ipsec dictionary */ 2880 ipsec_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2881 2882 src_string = CFStringCreateWithCString(0, addr2ascii(AF_INET, &our_address->sin_addr, sizeof(our_address->sin_addr), 0), kCFStringEncodingASCII); 2883 dst_string = CFStringCreateWithCString(0, addr2ascii(AF_INET, &peer_address->sin_addr, sizeof(peer_address->sin_addr), 0), kCFStringEncodingASCII); 2884 val = ntohs(our_address->sin_port); /* because there is no uint16 type */ 2885 src_port_num = CFNumberCreate(0, kCFNumberIntType, &val); 2886 val = ntohs(peer_address->sin_port); /* because there is no uint16 type */ 2887 dst_port_num = CFNumberCreate(0, kCFNumberIntType, &val); 2888 dst_port1_num = CFNumberCreate(0, kCFNumberIntType, &zero); 2889 proto_num = CFNumberCreate(0, kCFNumberIntType, &anyproto); 2890 if (!isClient) 2891 natt_multiuser_mode = CFNumberCreate(0, kCFNumberIntType, natt_multiple_users ? &one : &zero); 2892 2893 cfzero = CFNumberCreate(0, kCFNumberIntType, &zero); 2894 cfone = CFNumberCreate(0, kCFNumberIntType, &one); 2895 CFDictionarySetValue(ipsec_dict, kRASPropIPSecModeConfigEnabled, cfone); 2896 CFDictionarySetValue(ipsec_dict, kRASPropIPSecXAuthEnabled, cfone); 2897 2898 CFDictionarySetValue(ipsec_dict, kRASPropIPSecLocalAddress, src_string); 2899 CFDictionarySetValue(ipsec_dict, kRASPropIPSecRemoteAddress, dst_string); 2900 CFDictionarySetValue(ipsec_dict, kRASPropIPSecProposalsBehavior, isClient ? kRASValIPSecProposalsBehaviorObey : kRASValIPSecProposalsBehaviorClaim); 2901 if (isClient && CFEqual(authenticationMethod, kRASValIPSecAuthenticationMethodCertificate)) { 2902#ifdef ADD_DHGROUP5 2903 add_group5 = 1; 2904#endif 2905 if (identifierVerification) { 2906 CFDictionarySetValue(ipsec_dict, kRASPropIPSecIdentifierVerification, identifierVerification); 2907 } 2908 else { 2909 if (dst_hostName) { 2910 CFDictionarySetValue(ipsec_dict, kRASPropIPSecRemoteIdentifier, dst_hostName); 2911 CFDictionarySetValue(ipsec_dict, kRASPropIPSecIdentifierVerification, kRASValIPSecIdentifierVerificationUseRemoteIdentifier); 2912 } else 2913 CFDictionarySetValue(ipsec_dict, kRASPropIPSecIdentifierVerification, kRASValIPSecIdentifierVerificationGenerateFromRemoteAddress); 2914 } 2915 } else /*server or no certificate */ 2916 CFDictionarySetValue(ipsec_dict, kRASPropIPSecIdentifierVerification, kRASValIPSecIdentifierVerificationNone); 2917 2918 /* if server - set natt multiple user mode */ 2919 if (!isClient) 2920 CFDictionarySetValue(ipsec_dict, kRASPropIPSecNattMultipleUsersEnabled, natt_multiuser_mode); 2921 2922 /* use dead peer detection blackhole detection */ 2923 CFDictionarySetValue(ipsec_dict, kRASPropIPSecDeadPeerDetectionEnabled, cfone); 2924 CFDictionarySetValue(ipsec_dict, kRASPropIPSecBlackHoleDetectionEnabled, cfone); 2925 val = 20; // 20 seconds dpd with blackhole detection 2926 dpd_delay = CFNumberCreate(0, kCFNumberIntType, &val); 2927 if (dpd_delay) { 2928 CFDictionarySetValue(ipsec_dict, kRASPropIPSecDeadPeerDetectionDelay, dpd_delay); 2929 CFRelease(dpd_delay); 2930 } 2931 2932 /* By default, disable keep alive and let DPD play that role 2933 20 seconds default keepalive kills battery. */ 2934 // CFDictionarySetValue(ipsec_dict, kRASPropIPSecNattKeepAliveEnabled, cfzero); 2935 2936 /* create the phase 1 proposals */ 2937#if 1 2938 //Create all combination of proposals 2939 proposal_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 2940 2941 val = 3600; 2942 lifetime = CFNumberCreate(0, kCFNumberIntType, &val); 2943 2944 nb = 0; 2945 2946 /* should support group 1, 2, and 5 for main monde and only group 2 for aggressive mode 2947 supporting so many proposals could require to turn on ike fragmentation and needs more testing */ 2948 //int i, dh_group[] = { 1, 2, 5, 0 }; 2949 int i, dh_group[] = { 2, 0 }; 2950 2951 for (i = 0; (val = dh_group[i]); i++) { 2952 2953 dhgroup = CFNumberCreate(0, kCFNumberIntType, &val); 2954 2955#ifdef ADD_DHGROUP5 2956 if (add_group5) 2957 dhgroup5 = CFNumberCreate(0, kCFNumberIntType, &val5); 2958#endif 2959 2960 // --- AES256/SHA1 2961#ifdef ADD_DHGROUP5 2962 if (add_group5) { 2963 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2964 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES256); 2965 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmSHA1); 2966 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup5); 2967 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2968 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 2969 CFRelease(proposal_dict); 2970 } 2971#endif 2972 2973 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2974 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES256); 2975 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmSHA1); 2976 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 2977 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2978 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 2979 CFRelease(proposal_dict); 2980 2981 // --- AES/SHA1 2982 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2983 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES); 2984 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmSHA1); 2985 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 2986 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2987 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 2988 CFRelease(proposal_dict); 2989 2990 // --- AES256/MD5 2991#ifdef ADD_DHGROUP5 2992 if (add_group5) { 2993 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2994 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES256); 2995 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmMD5); 2996 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup5); 2997 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 2998 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 2999 CFRelease(proposal_dict); 3000 } 3001#endif 3002 3003 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3004 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES256); 3005 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmMD5); 3006 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 3007 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 3008 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 3009 CFRelease(proposal_dict); 3010 3011 // --- AES/MD5 3012 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3013 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmAES); 3014 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmMD5); 3015 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 3016 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 3017 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 3018 CFRelease(proposal_dict); 3019 3020 // --- 3DES/SHA1 3021 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3022 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithm3DES); 3023 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmSHA1); 3024 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 3025 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 3026 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 3027 CFRelease(proposal_dict); 3028 3029 // --- 3DES/MD5 3030 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3031 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithm3DES); 3032 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmMD5); 3033 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 3034 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 3035 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 3036 CFRelease(proposal_dict); 3037 3038 // --- DES/SHA1 3039 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3040 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmDES); 3041 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmSHA1); 3042 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 3043 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 3044 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 3045 CFRelease(proposal_dict); 3046 3047 // --- DES/MD5 3048 proposal_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3049 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalEncryptionAlgorithm, kRASValIPSecProposalEncryptionAlgorithmDES); 3050 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalHashAlgorithm, kRASValIPSecProposalHashAlgorithmMD5); 3051 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalDHGroup, dhgroup); 3052 CFDictionarySetValue(proposal_dict, kRASPropIPSecProposalLifetime, lifetime); 3053 CFArraySetValueAtIndex(proposal_array, nb++, proposal_dict); 3054 CFRelease(proposal_dict); 3055 3056 // --- 3057 3058 CFRelease(dhgroup); 3059#ifdef ADD_DHGROUP5 3060 if (add_group5) 3061 CFRelease(dhgroup5); 3062#endif 3063 } 3064 3065 CFRelease(lifetime); 3066 3067 CFDictionarySetValue(ipsec_dict, kRASPropIPSecProposals, proposal_array); 3068 CFRelease(proposal_array); 3069 3070#endif 3071 3072 /* create the policies */ 3073#if 0 3074 policy0 = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3075 CFDictionarySetValue(policy0, kRASPropIPSecPolicyLocalPort, src_port_num); 3076 CFDictionarySetValue(policy0, kRASPropIPSecPolicyRemotePort, dst_port_num); 3077 CFDictionarySetValue(policy0, kRASPropIPSecPolicyProtocol, proto_num); 3078 CFDictionarySetValue(policy0, kRASPropIPSecPolicyMode, kRASValIPSecPolicyModeTransport); 3079 CFDictionarySetValue(policy0, kRASPropIPSecPolicyLevel, kRASValIPSecPolicyLevelRequire); 3080 val = 0; 3081 dhgroup = CFNumberCreate(0, kCFNumberIntType, &val); 3082 CFDictionarySetValue(policy0, kRASPropIPSecPolicyPFSGroup, dhgroup); 3083 CFRelease(dhgroup); 3084 val = 3600; 3085 lifetime = CFNumberCreate(0, kCFNumberIntType, &val); 3086 CFDictionarySetValue(policy0, kRASPropIPSecPolicyLifetime, lifetime); 3087 CFRelease(lifetime); 3088 encryption_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 3089 CFArraySetValueAtIndex(encryption_array, 0, kRASValIPSecPolicyEncryptionAlgorithmAES); 3090 CFArraySetValueAtIndex(encryption_array, 1, kRASValIPSecPolicyEncryptionAlgorithm3DES); 3091 CFDictionarySetValue(policy0, kRASPropIPSecPolicyEncryptionAlgorithm, encryption_array); 3092 CFRelease(encryption_array); 3093 hash_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 3094 CFArraySetValueAtIndex(hash_array, 0, kRASValIPSecPolicyHashAlgorithmSHA1); 3095 CFArraySetValueAtIndex(hash_array, 1, kRASValIPSecPolicyHashAlgorithmMD5); 3096 CFDictionarySetValue(policy0, kRASPropIPSecPolicyHashAlgorithm, hash_array); 3097 CFRelease(hash_array); 3098 3099 if (isClient) { 3100 policy1 = CFDictionaryCreateMutableCopy(0, 0, policy0); 3101 CFDictionarySetValue(policy1, kRASPropIPSecPolicyRemotePort, dst_port1_num); 3102 CFDictionarySetValue(policy1, kRASPropIPSecPolicyDirection, kRASValIPSecPolicyDirectionIn); 3103 } 3104 3105 policy_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 3106 CFArraySetValueAtIndex(policy_array, 0, policy0); 3107 if (isClient) 3108 CFArraySetValueAtIndex(policy_array, 1, policy1); 3109 3110 CFRelease(policy0); 3111 if (isClient) 3112 CFRelease(policy1); 3113 3114 CFDictionarySetValue(ipsec_dict, kRASPropIPSecPolicies, policy_array); 3115 CFRelease(policy_array); 3116#endif 3117#if 0 3118/* XXX Hack iPhone create sainfo anonymous until we fix racoon. In this specific case, mode must be "transport" */ 3119 policy0 = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3120 /* XXX */ 3121 CFDictionarySetValue(ipsec_dict, CFSTR("UseAnonymousPolicy"), CFSTR("UseAnonymousPolicy")); 3122 CFDictionarySetValue(policy0, kRASPropIPSecPolicyLocalPort, src_port_num); 3123 CFDictionarySetValue(policy0, kRASPropIPSecPolicyRemotePort, dst_port_num); 3124 CFDictionarySetValue(policy0, kRASPropIPSecPolicyProtocol, proto_num); 3125 CFDictionarySetValue(policy0, kRASPropIPSecPolicyMode, kRASValIPSecPolicyModeTransport); 3126 CFDictionarySetValue(policy0, kRASPropIPSecPolicyLevel, kRASValIPSecPolicyLevelRequire); 3127 val = 0; 3128 dhgroup = CFNumberCreate(0, kCFNumberIntType, &val); 3129 CFDictionarySetValue(policy0, kRASPropIPSecPolicyPFSGroup, dhgroup); 3130 CFRelease(dhgroup); 3131 val = 3600; 3132 lifetime = CFNumberCreate(0, kCFNumberIntType, &val); 3133 CFDictionarySetValue(policy0, kRASPropIPSecPolicyLifetime, lifetime); 3134 CFRelease(lifetime); 3135 encryption_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 3136 CFArraySetValueAtIndex(encryption_array, 0, kRASValIPSecPolicyEncryptionAlgorithmAES); 3137 CFArraySetValueAtIndex(encryption_array, 1, kRASValIPSecPolicyEncryptionAlgorithm3DES); 3138 CFDictionarySetValue(policy0, kRASPropIPSecPolicyEncryptionAlgorithm, encryption_array); 3139 CFRelease(encryption_array); 3140 hash_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 3141 CFArraySetValueAtIndex(hash_array, 0, kRASValIPSecPolicyHashAlgorithmSHA1); 3142 CFArraySetValueAtIndex(hash_array, 1, kRASValIPSecPolicyHashAlgorithmMD5); 3143 CFDictionarySetValue(policy0, kRASPropIPSecPolicyHashAlgorithm, hash_array); 3144 CFRelease(hash_array); 3145 3146 if (isClient) { 3147 policy1 = CFDictionaryCreateMutableCopy(0, 0, policy0); 3148 CFDictionarySetValue(policy1, kRASPropIPSecPolicyRemotePort, dst_port1_num); 3149 CFDictionarySetValue(policy1, kRASPropIPSecPolicyDirection, kRASValIPSecPolicyDirectionIn); 3150 } 3151 3152 policy_array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 3153 CFArraySetValueAtIndex(policy_array, 0, policy0); 3154 if (isClient) 3155 CFArraySetValueAtIndex(policy_array, 1, policy1); 3156 3157 CFRelease(policy0); 3158 if (isClient) 3159 CFRelease(policy1); 3160 3161 CFDictionarySetValue(ipsec_dict, kRASPropIPSecPolicies, policy_array); 3162 CFRelease(policy_array); 3163#endif 3164 3165 CFRelease(src_string); 3166 CFRelease(dst_string); 3167 CFRelease(src_port_num); 3168 CFRelease(dst_port_num); 3169 CFRelease(dst_port1_num); 3170 CFRelease(proto_num); 3171 if (cfone) 3172 CFRelease(cfone); 3173 if (cfzero) 3174 CFRelease(cfzero); 3175 if (!isClient) 3176 CFRelease(natt_multiuser_mode); 3177 3178 return ipsec_dict; 3179} 3180 3181/* ----------------------------------------------------------------------------- 3182IPSecSelfRepair. 3183This is an attempt to have IPSec try to repair itself when things 3184don't work anymore. 3185Tipically, kill and restart racoon... 3186 3187Parameters: 3188 3189Return code: 31900 if successful, -1 otherwise. 3191----------------------------------------------------------------------------- */ 3192int 3193IPSecSelfRepair() 3194{ 3195 racoon_stop(); 3196 3197 return 0; 3198} 3199 3200/* ----------------------------------------------------------------------------- 3201 IPSecFlushAll. 3202 Flush all policies and associations 3203 3204 Parameters: 3205 3206 Return code: 3207 0 if successful, -1 otherwise. 3208 ----------------------------------------------------------------------------- */ 3209int 3210IPSecFlushAll() 3211{ 3212 int s = -1; 3213 3214 s = pfkey_open(); 3215 if (s >= 0) { 3216 pfkey_send_spdflush(s); 3217 pfkey_send_flush(s, SADB_SATYPE_UNSPEC); 3218 pfkey_close(s); 3219 } 3220 3221 return 0; 3222} 3223 3224static char unknown_if_family_str[16]; 3225static char * 3226if_family2ascii (u_int32_t if_family) 3227{ 3228 switch (if_family) { 3229 case APPLE_IF_FAM_LOOPBACK: 3230 return("Loopback"); 3231 case APPLE_IF_FAM_ETHERNET: 3232 return("Ether"); 3233 case APPLE_IF_FAM_SLIP: 3234 return("SLIP"); 3235 case APPLE_IF_FAM_TUN: 3236 return("TUN"); 3237 case APPLE_IF_FAM_VLAN: 3238 return("VLAN"); 3239 case APPLE_IF_FAM_PPP: 3240 return("PPP"); 3241 case APPLE_IF_FAM_PVC: 3242 return("PVC"); 3243 case APPLE_IF_FAM_DISC: 3244 return("DISC"); 3245 case APPLE_IF_FAM_MDECAP: 3246 return("MDECAP"); 3247 case APPLE_IF_FAM_GIF: 3248 return("GIF"); 3249 case APPLE_IF_FAM_FAITH: 3250 return("FAITH"); 3251 case APPLE_IF_FAM_STF: 3252 return("STF"); 3253 case APPLE_IF_FAM_FIREWIRE: 3254 return("FireWire"); 3255 case APPLE_IF_FAM_BOND: 3256 return("Bond"); 3257 default: 3258 snprintf(unknown_if_family_str, sizeof(unknown_if_family_str), "%d", if_family); 3259 return(unknown_if_family_str); 3260 } 3261} 3262 3263void 3264IPSecLogVPNInterfaceAddressEvent (const char *location, 3265 struct kern_event_msg *ev_msg, 3266 int wait_interface_timeout, 3267 char *interface, 3268 struct in_addr *our_address) 3269{ 3270 struct in_addr mask; 3271 char our_addr_str[INET_ADDRSTRLEN]; 3272 3273 if (!ev_msg) { 3274 syslog(LOG_NOTICE, "%s: %d secs TIMEOUT waiting for interface to be reconfigured. previous setting (name: %s, address: %s).", 3275 location, 3276 wait_interface_timeout, 3277 interface, 3278 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str)); 3279 return; 3280 } else { 3281 struct kev_in_data *inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 3282 struct kev_in_collision *inetdata_coll = (struct kev_in_collision *) &ev_msg->event_data[0]; 3283 char new_addr_str[INET_ADDRSTRLEN]; 3284 char new_mask_str[INET_ADDRSTRLEN]; 3285 char dst_addr_str[INET_ADDRSTRLEN]; 3286 3287 mask.s_addr = ntohl(inetdata->ia_subnetmask); 3288 3289 switch (ev_msg->event_code) { 3290 case KEV_INET_NEW_ADDR: 3291 syslog(LOG_NOTICE, "%s: Address added. previous interface setting (name: %s, address: %s), current interface setting (name: %s%d, family: %s, address: %s, subnet: %s, destination: %s).", 3292 location, 3293 interface, 3294 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 3295 inetdata->link_data.if_name, inetdata->link_data.if_unit, 3296 if_family2ascii(inetdata->link_data.if_family), 3297 addr2ascii(AF_INET, &inetdata->ia_addr, sizeof(inetdata->ia_addr), new_addr_str), 3298 addr2ascii(AF_INET, &mask, sizeof(mask), new_mask_str), 3299 addr2ascii(AF_INET, &inetdata->ia_dstaddr, sizeof(inetdata->ia_dstaddr), dst_addr_str)); 3300 break; 3301 case KEV_INET_CHANGED_ADDR: 3302 syslog(LOG_NOTICE, "%s: Address changed. previous interface setting (name: %s, address: %s), current interface setting (name: %s%d, family: %s, address: %s, subnet: %s, destination: %s).", 3303 location, 3304 interface, 3305 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 3306 inetdata->link_data.if_name, inetdata->link_data.if_unit, 3307 if_family2ascii(inetdata->link_data.if_family), 3308 addr2ascii(AF_INET, &inetdata->ia_addr, sizeof(inetdata->ia_addr), new_addr_str), 3309 addr2ascii(AF_INET, &mask, sizeof(mask), new_mask_str), 3310 addr2ascii(AF_INET, &inetdata->ia_dstaddr, sizeof(inetdata->ia_dstaddr), dst_addr_str)); 3311 break; 3312 case KEV_INET_ADDR_DELETED: 3313 syslog(LOG_NOTICE, "%s: Address deleted. previous interface setting (name: %s, address: %s), deleted interface setting (name: %s%d, family: %s, address: %s, subnet: %s, destination: %s).", 3314 location, 3315 interface, 3316 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 3317 inetdata->link_data.if_name, inetdata->link_data.if_unit, 3318 if_family2ascii(inetdata->link_data.if_family), 3319 addr2ascii(AF_INET, &inetdata->ia_addr, sizeof(inetdata->ia_addr), new_addr_str), 3320 addr2ascii(AF_INET, &mask, sizeof(mask), new_mask_str), 3321 addr2ascii(AF_INET, &inetdata->ia_dstaddr, sizeof(inetdata->ia_dstaddr), dst_addr_str)); 3322 break; 3323 case KEV_INET_ARPCOLLISION: 3324 syslog(LOG_NOTICE, "%s: ARP collided. previous interface setting (name: %s, address: %s), conflicting interface setting (name: %s%d, family: %s, address: %s, mac: %x:%x:%x:%x:%x:%x).", 3325 location, 3326 interface, 3327 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 3328 inetdata_coll->link_data.if_name, 3329 inetdata_coll->link_data.if_unit, 3330 if_family2ascii(inetdata_coll->link_data.if_family), 3331 addr2ascii(AF_INET, &inetdata_coll->ia_ipaddr, sizeof(inetdata_coll->ia_ipaddr), new_addr_str), 3332 inetdata_coll->hw_addr[5],inetdata_coll->hw_addr[4],inetdata_coll->hw_addr[3],inetdata_coll->hw_addr[2],inetdata_coll->hw_addr[1],inetdata_coll->hw_addr[0]); 3333 break; 3334 default: 3335 syslog(LOG_NOTICE, "%s: Unknown Address event (%d). previous interface setting (name: %s, address: %s), other interface setting (name: %s%d, family: %s, address: %s, subnet: %s, destination: %s).", 3336 location, 3337 ev_msg->event_code, 3338 interface, 3339 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 3340 inetdata->link_data.if_name, inetdata->link_data.if_unit, 3341 if_family2ascii(inetdata->link_data.if_family), 3342 addr2ascii(AF_INET, &inetdata->ia_addr, sizeof(inetdata->ia_addr), new_addr_str), 3343 addr2ascii(AF_INET, &mask, sizeof(mask), new_mask_str), 3344 addr2ascii(AF_INET, &inetdata->ia_dstaddr, sizeof(inetdata->ia_dstaddr), dst_addr_str)); 3345 break; 3346 } 3347 } 3348} 3349 3350void 3351update_service_route (struct service *serv, 3352 in_addr_t local_addr, 3353 in_addr_t local_mask, 3354 in_addr_t dest_addr, 3355 in_addr_t dest_mask, 3356 in_addr_t gtwy_addr, 3357 uint16_t flags, 3358 int installed) 3359{ 3360 service_route_t *p, *route = NULL; 3361 3362 for (p = serv->u.ipsec.routes; p != NULL; p = p->next) { 3363 if (p->local_address.s_addr == local_addr && 3364 p->local_mask.s_addr == local_mask && 3365 p->dest_address.s_addr == dest_addr && 3366 p->dest_mask.s_addr == dest_mask) { 3367 route = p; 3368 break; 3369 } 3370 } 3371 if (!route) { 3372 if ((route = (__typeof__(route))calloc(1, sizeof(*route))) == 0) { 3373 syslog(LOG_ERR, "%s: no memory\n", __FUNCTION__); 3374 return; 3375 } 3376 route->local_address.s_addr = local_addr; 3377 route->local_mask.s_addr = local_mask; 3378 route->dest_address.s_addr = dest_addr; 3379 route->dest_mask.s_addr = dest_mask; 3380 route->next = serv->u.ipsec.routes; 3381 serv->u.ipsec.routes = route; 3382 } 3383 route->gtwy_address.s_addr = gtwy_addr; 3384 route->flags = flags; 3385 route->installed = installed; 3386 3387} 3388 3389service_route_t * 3390get_service_route (struct service *serv, 3391 in_addr_t local_addr, 3392 in_addr_t dest_addr) 3393{ 3394 service_route_t *p; 3395 3396 for (p = serv->u.ipsec.routes; p != NULL; p = p->next) { 3397 if (p->local_address.s_addr == local_addr && 3398 p->dest_address.s_addr == dest_addr) { 3399 return p; 3400 } 3401 } 3402 return NULL; 3403} 3404 3405void 3406free_service_routes (struct service *serv) 3407{ 3408 service_route_t *p, *save; 3409 3410 for (p = serv->u.ipsec.routes; p != NULL; p = save) { 3411 save = p->next; 3412 free(p); 3413 } 3414 serv->u.ipsec.routes = NULL; 3415} 3416 3417int 3418find_injection(CFStringRef str, CFStringRef invalidStr, CFIndex strLen) 3419{ 3420 CFRange theRange, searchRange; 3421 3422 theRange = CFStringFind(str, invalidStr, 0); 3423 if (theRange.length != 0) { 3424 searchRange.location = theRange.location + theRange.length; // start after the string 3425 searchRange.length = strLen - searchRange.location; 3426 if (CFStringFindWithOptions(str, CFSTR(";"), searchRange, 0, NULL)) 3427 return TRUE; 3428 } 3429 return FALSE; 3430} 3431 3432 3433/* Look for injection attempts in user supplied strings */ 3434int 3435racoon_validate_cfg_str (char *str_buf) 3436{ 3437 3438 CFStringRef theString = NULL; 3439 CFIndex theLength; 3440 3441 theString = CFStringCreateWithCString(NULL, str_buf, kCFStringEncodingUTF8); 3442 if (theString == NULL) 3443 goto failed; 3444 theLength = CFStringGetLength(theString); 3445 3446 if (find_injection(theString, CFSTR("include "), theLength)) 3447 goto failed; 3448 if (find_injection(theString, CFSTR("privsep "), theLength)) 3449 goto failed; 3450 if (find_injection(theString, CFSTR("path "), theLength)) 3451 goto failed; 3452 if (find_injection(theString, CFSTR("timer "), theLength)) 3453 goto failed; 3454 if (find_injection(theString, CFSTR("listen "), theLength)) 3455 goto failed; 3456 if (find_injection(theString, CFSTR("remote "), theLength)) 3457 goto failed; 3458 if (find_injection(theString, CFSTR("sainfo "), theLength)) 3459 goto failed; 3460 CFRelease(theString); 3461 return TRUE; 3462 3463failed: 3464 CFRelease(theString); 3465 return FALSE; // trying to inject additional config data 3466 3467} 3468 3469