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#include <stdio.h> 26#include <ctype.h> 27#include <stdlib.h> 28#include <string.h> 29#include <unistd.h> 30#include <signal.h> 31#include <errno.h> 32#include <fcntl.h> 33#include <syslog.h> 34#include <netdb.h> 35#include <paths.h> 36#include <sys/queue.h> 37 38#include <sys/param.h> 39#include <sys/types.h> 40#include <sys/wait.h> 41#include <sys/time.h> 42#include <sys/resource.h> 43#include <sys/stat.h> 44#include <sys/socket.h> 45#include <netinet/in.h> 46#include <arpa/inet.h> 47#include <net/if.h> 48 49#include <CoreFoundation/CoreFoundation.h> 50#include <SystemConfiguration/SystemConfiguration.h> 51#include "../../Family/if_ppplink.h" 52#include "../../Family/ppp_defs.h" 53 54#include "vpnd.h" 55#include "vpnoptions.h" 56#include "vpnplugins.h" 57#include "RASSchemaDefinitions.h" 58#include "cf_utils.h" 59 60static u_char *empty_str = (u_char*)""; 61 62static int process_interface_prefs(struct vpn_params *params); 63static int process_ipv4_prefs(struct vpn_params *params); 64static int process_ipv6_prefs(struct vpn_params *params); 65static int process_dns_prefs(struct vpn_params *params); 66static int process_ppp_prefs(struct vpn_params *params); 67 68//----------------------------------------------------------------------------- 69// process_options 70//----------------------------------------------------------------------------- 71void ppp_process_options(struct vpn_params *params) 72{ 73 74 params->plugin_path = 0; 75 params->serverSubTypeRef = 0; 76 params->server_subtype = PPP_TYPE_OTHER; 77} 78 79// ---------------------------------------------------------------------------- 80// process_prefs 81// ---------------------------------------------------------------------------- 82int ppp_process_prefs(struct vpn_params *params) 83{ 84 85 u_char pathStr[MAXPATHLEN]; 86 u_int32_t len; 87 int i; 88 89 // clear the argument array 90 params->next_arg_index = 0; 91 for (i = 0; i < MAXARG; i++) 92 params->exec_args[i] = 0; 93 94 // add the pppd program name to the exec args 95 addparam(params->exec_args, ¶ms->next_arg_index, PPPD_PRGM); 96 97 // add some general args that are always needed 98 addstrparam(params->exec_args, ¶ms->next_arg_index, "serverid", params->server_id); // server ID 99 addparam(params->exec_args, ¶ms->next_arg_index, "nodetach"); // we don't want pppd to detach. 100 addparam(params->exec_args, ¶ms->next_arg_index, "proxyarp"); // we proxy for the client 101 102 // process the dictionaries 103 if (process_interface_prefs(params)) 104 goto fail; 105 if (process_ipv4_prefs(params)) 106 goto fail; 107 if (process_ipv6_prefs(params)) 108 goto fail; 109 if (process_dns_prefs(params)) 110 goto fail; 111 if (process_ppp_prefs(params)) 112 goto fail; 113 114 // always try to use options defined in /etc/ppp/peers/[service provider] 115 // they can override what have been specified by the prefs file 116 // be careful to the conflicts on options 117 len = sizeof(pathStr); 118 get_str_option(params->serverRef, kRASEntPPP, kRASPropUserDefinedName, pathStr, sizeof(pathStr), &len, empty_str); 119 if (pathStr[0]) 120 addstrparam(params->exec_args, ¶ms->next_arg_index, "call", (char*)pathStr); 121 122 return 0; 123 124fail: 125 if (params->serverSubTypeRef) { 126 CFRelease(params->serverSubTypeRef); 127 params->serverSubTypeRef = 0; 128 } 129 return -1; 130} 131 132//----------------------------------------------------------------------------- 133// process_interface_prefs 134//----------------------------------------------------------------------------- 135static int process_interface_prefs(struct vpn_params *params) 136{ 137 CFDictionaryRef dict; 138 int path_len = 0; 139 140 // get type/subtype of server 141 dict = CFDictionaryGetValue(params->serverRef, kRASEntInterface); 142 143 // get server subtype and check if supported 144 params->serverSubTypeRef = CFDictionaryGetValue(dict, kRASPropInterfaceSubType); 145 if (!isString(params->serverSubTypeRef)) { 146 vpnlog(LOG_ERR, "Incorrect server subtype found\n"); 147 params->serverSubTypeRef = NULL; 148 return -1; 149 } 150 path_len = CFStringGetLength(params->serverSubTypeRef) + 5; 151 params->plugin_path = malloc(path_len); 152 CFStringGetCString(params->serverSubTypeRef, params->plugin_path, 153 path_len, kCFStringEncodingUTF8); 154 strlcat(params->plugin_path, ".ppp", path_len); 155 if (!plugin_exists(params->plugin_path)) { 156 vpnlog(LOG_ERR, "Unsupported plugin '%s'\n", params->plugin_path); 157 params->serverSubTypeRef = NULL; 158 free(params->plugin_path); 159 params->plugin_path = NULL; 160 return -1; 161 } 162 163 // add the vpn protocol plugin parameter to the exec args 164 addstrparam(params->exec_args, ¶ms->next_arg_index, "plugin", params->plugin_path); 165 166 if (CFStringCompare(params->serverSubTypeRef, kRASValInterfaceSubTypePPTP, 0) == kCFCompareEqualTo) 167 params->server_subtype = PPP_TYPE_PPTP; 168 else if (CFStringCompare(params->serverSubTypeRef, kRASValInterfaceSubTypeL2TP, 0) == kCFCompareEqualTo) 169 params->server_subtype = PPP_TYPE_L2TP; 170 else if (CFStringCompare(params->serverSubTypeRef, kRASValInterfaceSubTypePPPoE, 0) == kCFCompareEqualTo) 171 params->server_subtype = PPP_TYPE_PPPoE; 172 else if (CFStringCompare(params->serverSubTypeRef, kRASValInterfaceSubTypePPPSerial, 0) == kCFCompareEqualTo) 173 params->server_subtype = PPP_TYPE_SERIAL; 174 else 175 params->server_subtype = PPP_TYPE_OTHER; 176 177 CFRetain(params->serverSubTypeRef); 178 179 return 0; 180} 181 182//----------------------------------------------------------------------------- 183// process_ipv4_prefs 184//----------------------------------------------------------------------------- 185static int process_ipv4_prefs(struct vpn_params *params) 186{ 187 CFArrayRef array = 0; 188 CFStringRef ipstr = 0, ipstr2 = 0; 189 CFDictionaryRef dict; 190 char str[MAXPATHLEN]; 191 uint32_t i, nb, len; 192 char ipcstr[100], ipcstr2[100], ip_addr[100], ip_addr2[100]; 193 char *ip, *ip2; 194 195 // Check if the IPv4 dictionary is present 196 if ((dict = CFDictionaryGetValue(params->serverRef, kRASEntIPv4)) && isDictionary(dict)) { 197 198 // get server side address 199 len = sizeof(str); 200 get_array_option(params->serverRef, kRASEntIPv4, kRASPropIPv4Addresses, 0, (u_char*)str, sizeof(str), &len, empty_str); 201 if (str[0] == 0) { 202 // get the address of the default interface 203 ipstr = CopyDefaultIPAddress(); 204 if (ipstr) { 205 CFStringGetCString(ipstr, str, sizeof(str), kCFStringEncodingMacRoman); 206 CFRelease(ipstr); 207 ipstr = 0; 208 } 209 } 210 if (str[0]) { 211 strlcat(str, ":", sizeof(str)); 212 addparam(params->exec_args, ¶ms->next_arg_index, str); 213 } 214 215 // build client address list 216 if (isDictionary(dict)) { 217 /* individual ip addresses */ 218 array = CFDictionaryGetValue(dict, kRASPropIPv4DestAddresses); 219 if (isArray(array)) { 220 221 nb = CFArrayGetCount(array); 222 for (i = 0; i < nb; i++) { 223 ipstr = CFArrayGetValueAtIndex(array, i); 224 if (isString(ipstr)) { 225 if (CFStringGetCString(ipstr, ipcstr, sizeof(ipcstr), kCFStringEncodingMacRoman)) { 226 if ((ip = validate_ip_string(ipcstr, ip_addr, sizeof(ip_addr)))) { 227 if (add_address(ip)) { 228 vpnlog(LOG_ERR, "Error while processing ip address %s\n", ip); 229 return -1; 230 } 231 } else 232 vpnlog(LOG_ERR, "Ignoring invalid ip address %s\n", ipcstr); 233 } 234 } 235 } 236 } 237 // ip address ranges 238 array = CFDictionaryGetValue(dict, kRASPropIPv4DestAddressRanges); 239 if (isArray(array)) { 240 if (CFArrayGetCount(array) % 2) 241 vpnlog(LOG_ERR, "Error - ip address ranges must be in pairs\n"); 242 else { 243 nb = CFArrayGetCount(array); 244 for (i = 0; i < nb; i += 2) { 245 ipstr = CFArrayGetValueAtIndex(array, i); 246 ipstr2 = CFArrayGetValueAtIndex(array, i+1); 247 if (isString(ipstr) && isString(ipstr2)) { 248 if (CFStringGetCString(ipstr, ipcstr, sizeof(ipcstr), kCFStringEncodingMacRoman) && 249 CFStringGetCString(ipstr2, ipcstr2, sizeof(ipcstr2), kCFStringEncodingMacRoman)) { 250 ip = validate_ip_string(ipcstr, ip_addr, sizeof(ip_addr)); 251 ip2 = validate_ip_string(ipcstr2, ip_addr2, sizeof(ip_addr2)); 252 if (ip && ip2) { 253 if (add_address_range(ip, ip2)) { 254 vpnlog(LOG_ERR, "Error while processing ip address range %s\n", ip); 255 return -1; 256 } 257 } else 258 vpnlog(LOG_ERR, "Ignoring invalid ip address range %s\n", ipcstr); 259 } 260 } 261 } 262 } 263 } 264 } 265 } 266 267 if (!address_avail()) { 268 vpnlog(LOG_ERR, "No valid client IP addresses\n"); 269 return -1; 270 } 271 272 return 0; 273 274} 275 276 277// ---------------------------------------------------------------------------- 278// process_ipv6_prefs 279// ---------------------------------------------------------------------------- 280static int process_ipv6_prefs(struct vpn_params *params) 281{ 282 CFDictionaryRef dict; 283 284 // Check if the IPv6 dictionary is present 285 if ((dict = CFDictionaryGetValue(params->serverRef, kRASEntIPv6)) && isDictionary(dict)) { 286 addparam(params->exec_args, ¶ms->next_arg_index, "+ipv6"); 287 addparam(params->exec_args, ¶ms->next_arg_index, "ipv6cp-use-persistent"); 288 } 289 return 0; 290} 291 292// ---------------------------------------------------------------------------- 293// process_dns_prefs 294// ---------------------------------------------------------------------------- 295static int process_dns_prefs(struct vpn_params *params) 296{ 297 CFPropertyListRef ref = 0; 298 CFDictionaryRef dict; 299 CFStringRef key = 0; 300 CFArrayRef array; 301 CFStringRef addr; 302 303 char str[OPT_STR_LEN]; 304 int count, i; 305 306 // Check if the IPv4 dictionary is present 307 if (isDictionary(CFDictionaryGetValue(params->serverRef, kRASEntIPv4))) { 308 // get the DNS address array from the plist for from the dynamic store 309 dict = CFDictionaryGetValue(params->serverRef, kSCEntNetDNS); 310 if (isDictionary(dict)) { 311 array = CFDictionaryGetValue(dict, kRASPropDNSOfferedServerAddresses); 312 if (isArray(array)) { 313 count = CFArrayGetCount(array); 314 if (count == 0) { // array is present but empty - get addresses from dynamic store 315 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetDNS); 316 if (key) { 317 ref = SCDynamicStoreCopyValue(params->storeRef, key); 318 if (isDictionary(ref)) { 319 array = CFDictionaryGetValue(ref, kSCPropNetDNSServerAddresses); 320 if (isArray(array)) 321 count = CFArrayGetCount(array); 322 } 323 CFRelease(key); 324 } 325 } 326 327 for (i = 0; i < count && i < 2; i++) { 328 addr = CFArrayGetValueAtIndex(array, i); 329 if (isString(addr)) { 330 str[0] = 0; 331 CFStringGetCString(addr, str, OPT_STR_LEN, kCFStringEncodingUTF8); 332 if (str[0]) 333 addstrparam(params->exec_args, ¶ms->next_arg_index, "ms-dns", str); 334 } 335 } 336 // free items from the store if required 337 if (ref) 338 CFRelease(ref); 339 } 340 } 341 } 342 343 return 0; 344} 345 346// ---------------------------------------------------------------------------- 347// process_ppp_prefs 348// ---------------------------------------------------------------------------- 349static int process_ppp_prefs(struct vpn_params *params) 350{ 351 char pathStr[MAXPATHLEN], optStr[OPT_STR_LEN]; 352 u_int32_t len, lval, lval1, i; 353 CFDictionaryRef dict; 354 CFArrayRef array; 355 CFIndex count; 356 CFStringRef string; 357 int noCCP; 358#define AUTH_BITS_PAP 0x1 359#define AUTH_BITS_CHAP 0x2 360#define AUTH_BITS_MSCHAP1 0x4 361#define AUTH_BITS_MSCHAP2 0x8 362#define AUTH_BITS_EAP 0x10 363 u_int32_t auth_bits = 0; /* none */ 364 365 // 366 // some basic admin options 367 // 368 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPVerboseLogging, &lval, 0); 369 if (lval) 370 addparam(params->exec_args, ¶ms->next_arg_index, "debug"); 371 372 len = sizeof(optStr); 373 get_str_option(params->serverRef, kRASEntPPP, kRASPropPPPLogfile, (u_char*)optStr, sizeof(optStr), &len, empty_str); 374 if (optStr[0]) { 375 // if logfile start with /, it's a full path 376 // otherwise it's relative to the logs folder (convention) 377 // we also strongly advise to name the file with the link number 378 // for example ppplog0 379 // the default path is /var/log 380 // it's useful to have the debug option with the logfile option 381 // with debug option, pppd will log the negociation 382 // debug option is different from kernel debug trace 383 384 snprintf(pathStr, sizeof(pathStr), "%s%s", optStr[0] == '/' ? "" : DIR_LOGS, optStr); 385 addstrparam(params->exec_args, ¶ms->next_arg_index, "logfile", pathStr); 386 } 387 388 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPDisconnectOnIdle, &lval, 0); 389 if (lval) { 390 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPDisconnectOnIdleTimer, &lval, OPT_COMM_IDLETIMER_DEF); 391 if (lval) { 392 addintparam(params->exec_args, ¶ms->next_arg_index, "idle", lval); 393 addparam(params->exec_args, ¶ms->next_arg_index, "noidlesend"); 394 } 395 } 396 397 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPUseSessionTimer, &lval, 0); 398 if (lval) { 399 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPSessionTimer, &lval, OPT_COMM_IDLETIMER_DEF); 400 if (lval) 401 addintparam(params->exec_args, ¶ms->next_arg_index, "maxconnect", lval); 402 } 403 404 // 405 // LCP options 406 // 407 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPEchoEnabled, &lval, 0); 408 if (lval) { 409 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPEchoInterval, &lval, OPT_LCP_ECHOINTERVAL_DEF); 410 if (lval) 411 addintparam(params->exec_args, ¶ms->next_arg_index, "lcp-echo-interval", lval); 412 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPEchoFailure, &lval, OPT_LCP_ECHOINTERVAL_DEF); 413 if (lval) 414 addintparam(params->exec_args, ¶ms->next_arg_index, "lcp-echo-failure", lval); 415 } 416 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPCompressionACField, &lval, OPT_LCP_PCOMP_DEF); 417 if (lval == 0) 418 addparam(params->exec_args, ¶ms->next_arg_index, "noaccomp"); 419 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPCompressionPField, &lval, OPT_LCP_ACCOMP_DEF); 420 if (lval == 0) 421 addparam(params->exec_args, ¶ms->next_arg_index, "nopcomp"); 422 423 switch (params->server_subtype) { 424 case PPP_TYPE_PPPoE: 425 lval = OPT_LCP_MRU_PPPoE_DEF; 426 break; 427 case PPP_TYPE_PPTP: 428 lval = OPT_LCP_MRU_PPTP_DEF; 429 break; 430 case PPP_TYPE_L2TP: 431 lval = OPT_LCP_MRU_L2TP_DEF; 432 break; 433 default: 434 lval = OPT_LCP_MRU_DEF; 435 } 436 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPMRU, &lval, lval); 437 if (lval) 438 addintparam(params->exec_args, ¶ms->next_arg_index, "mru", lval); 439 440 switch (params->server_subtype) { 441 case PPP_TYPE_PPPoE: 442 lval = OPT_LCP_MTU_PPPoE_DEF; 443 break; 444 case PPP_TYPE_PPTP: 445 lval = OPT_LCP_MTU_PPTP_DEF; 446 break; 447 case PPP_TYPE_L2TP: 448 lval = OPT_LCP_MTU_L2TP_DEF; 449 break; 450 default: 451 lval = OPT_LCP_MTU_DEF; 452 } 453 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPMTU, &lval, lval); 454 if (lval) 455 addintparam(params->exec_args, ¶ms->next_arg_index, "mtu", lval); 456 457 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPReceiveACCM, &lval, OPT_LCP_RCACCM_DEF); 458 if (lval) 459 addintparam(params->exec_args, ¶ms->next_arg_index, "asyncmap", lval); 460 else 461 addparam(params->exec_args, ¶ms->next_arg_index, "receive-all"); 462 463 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPLCPReceiveACCM, &lval, OPT_LCP_RCACCM_DEF); 464 if (lval) { 465 pathStr[0] = 0; 466 for (lval1 = 0; lval1 < 32; lval1++) { 467 if ((lval >> lval1) & 1) { 468 snprintf(optStr, sizeof(optStr), "%d,", lval1); 469 strlcat(pathStr, optStr, sizeof(pathStr)); 470 } 471 } 472 pathStr[strlen(pathStr)-1] = 0; // remove last ',' 473 addstrparam(params->exec_args, ¶ms->next_arg_index, "escape", pathStr); 474 } 475 476 // 477 // IPCP options 478 // 479 480 // Check if the IPv4 dictionary is present 481 if (!(dict = CFDictionaryGetValue(params->serverRef, kRASEntIPv4)) 482 || !isDictionary(dict)) { 483 addparam(params->exec_args, ¶ms->next_arg_index, "noip"); 484 } 485 else { 486 487 /* enforce the source ip address filtering */ 488 addintparam(params->exec_args, ¶ms->next_arg_index, "ip-src-address-filter", NPAFMODE_SRC_IN); 489 490 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPIPCPCompressionVJ, &lval, OPT_IPCP_HDRCOMP_DEF); 491 if (lval == 0) 492 addparam(params->exec_args, ¶ms->next_arg_index, "novj"); 493 } 494 495 // 496 // CCP options 497 // 498 noCCP = 1; 499 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPCCPEnabled, &lval, 0); 500 if (lval) { 501 // Fix me : to enforce use of MS-CHAP, refuse any alteration of default auth proto 502 // a dialer specifying PAP or CHAP will works without CCP/MPPE 503 // even if CCP is enabled in the configuration. 504 // Will be revisited when addition compression modules and 505 // authentication modules will be added 506 //&& !ppp_getoptval(ppp, opts, PPP_OPT_AUTH_PROTO, &lval, sizeof(lval), &len, service) 507 //&& (lval == OPT_AUTH_PROTO_DEF)) { 508 if ((dict = CFDictionaryGetValue(params->serverRef, kRASEntPPP)) != 0) { 509 array = CFDictionaryGetValue(dict, kRASPropPPPCCPProtocols); 510 if (isArray(array)) { 511 512 int mppe_found = 0; 513 count = CFArrayGetCount(array); 514 for (i = 0; i < count; i++) { 515 string = CFArrayGetValueAtIndex(array, i); 516 if (CFStringCompare(string, kRASValPPPCCPProtocolsMPPE, 0) == kCFCompareEqualTo) { 517 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPMPPEKeySize128, &lval, 0); 518 if (lval) { 519 mppe_found = 1; 520 addparam(params->exec_args, ¶ms->next_arg_index, "mppe-128"); 521 } 522 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPMPPEKeySize40, &lval, 0); 523 if (lval) { 524 mppe_found = 1; 525 addparam(params->exec_args, ¶ms->next_arg_index, "mppe-40"); 526 } 527 } else 528 vpnlog(LOG_ERR, "Invalid compression type specified - ignored\n"); 529 } 530 if (mppe_found) { 531 noCCP = 0; 532 addparam(params->exec_args, ¶ms->next_arg_index, "mppe-stateless"); 533 } 534 } 535 } 536 } 537 if (noCCP) // no compression protocol 538 addparam(params->exec_args, ¶ms->next_arg_index, "noccp"); 539 540 541 // 542 // ACSP 543 // 544 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPACSPEnabled, &lval, 0); 545 if (lval == 0) 546 addparam(params->exec_args, ¶ms->next_arg_index, "noacsp"); 547 548 get_int_option(params->serverRef, kRASEntPPP, kRASPropPPPInterceptDHCP, &lval, 1); 549 if (lval) 550 addparam(params->exec_args, ¶ms->next_arg_index, "intercept-dhcp"); 551 552 553 // 554 // Authentication 555 // 556 557 auth_bits = 0; 558 dict = CFDictionaryGetValue(params->serverRef, kRASEntPPP); 559 if (isDictionary(dict)) { 560 array = CFDictionaryGetValue(dict, kRASPropPPPAuthenticatorProtocol); 561 if (isArray(array)) { 562 count = CFArrayGetCount(array); 563 564 for (i = 0; i < count; i++) { 565 string = CFArrayGetValueAtIndex(array, i); 566 if (isString(string)) { 567 if (CFStringCompare(string, kRASValPPPAuthProtocolMSCHAP2, 0) == kCFCompareEqualTo) 568 auth_bits |= AUTH_BITS_MSCHAP2; 569 else if (CFStringCompare(string, kRASValPPPAuthProtocolMSCHAP1, 0) == kCFCompareEqualTo) 570 auth_bits |= AUTH_BITS_MSCHAP1; 571 else if (CFStringCompare(string, kRASValPPPAuthProtocolCHAP, 0) == kCFCompareEqualTo) 572 auth_bits |= AUTH_BITS_CHAP; 573 else if (CFStringCompare(string, kRASValPPPAuthProtocolPAP, 0) == kCFCompareEqualTo) 574 auth_bits |= AUTH_BITS_PAP; 575 else if (CFStringCompare(string, kRASValPPPAuthProtocolEAP, 0) == kCFCompareEqualTo) 576 auth_bits |= AUTH_BITS_EAP; 577 else { 578 vpnlog(LOG_ERR, "Unknown authentication type specified\n"); 579 return -1; 580 } 581 } 582 } 583 } 584 } 585 586 if (auth_bits & AUTH_BITS_PAP) 587 addparam(params->exec_args, ¶ms->next_arg_index, "require-pap"); 588 589 if (auth_bits & AUTH_BITS_CHAP) 590 addparam(params->exec_args, ¶ms->next_arg_index, "require-chap"); 591 592 if (auth_bits & AUTH_BITS_MSCHAP1) 593 addparam(params->exec_args, ¶ms->next_arg_index, "require-mschap"); 594 595 if (auth_bits & AUTH_BITS_MSCHAP2) 596 addparam(params->exec_args, ¶ms->next_arg_index, "require-mschap-v2"); 597 598 if (auth_bits & AUTH_BITS_EAP) { 599 600 addparam(params->exec_args, ¶ms->next_arg_index, "require-eap"); 601 602 // add EAP plugins - must be at least one 603 int eapPluginFound = 0; 604 605 i = 0; 606 do { 607 lval = get_array_option(params->serverRef, kRASEntPPP, kRASPropPPPAuthenticatorEAPPlugins, 608 i++, (u_char*)pathStr, sizeof(pathStr), &len, empty_str); 609 if (pathStr[0]) { 610 strlcat(pathStr, ".ppp", sizeof(pathStr)); // add plugin suffix 611 if (!plugin_exists(pathStr)) { 612 vpnlog(LOG_ERR, "EAP plugin '%s' not found\n", pathStr); 613 return -1; 614 } 615 addstrparam(params->exec_args, ¶ms->next_arg_index, "eapplugin", pathStr); 616 eapPluginFound = 1; 617 } 618 } 619 while (lval); 620 621 if (!eapPluginFound) { 622 /* should check if Radius EAP proxy is enabled */ 623 //vpnlog(LOG_ERR, "No EAP authentication plugin(s) specified\n"); 624 //return -1; 625 } 626 } 627 628 629 // 630 // Plugins 631 // 632 633 // add authentication plugins 634 i = 0; 635 do { 636 len = sizeof(pathStr); 637 lval = get_array_option(params->serverRef, kRASEntPPP, kRASPropPPPAuthenticatorPlugins, 638 i++, (u_char*)pathStr, sizeof(pathStr), &len, empty_str); 639 if (pathStr[0]) { 640 strlcat(pathStr, ".ppp", sizeof(pathStr)); // add plugin suffix 641 if (!plugin_exists(pathStr)) { 642 vpnlog(LOG_ERR, "Authentication plugin '%s' not found\n", pathStr); 643 return -1; 644 } 645 addstrparam(params->exec_args, ¶ms->next_arg_index, "plugin", pathStr); 646 } 647 } 648 while (lval); 649 650 // add access control list plugins 651 i = 0; 652 do { 653 len = sizeof(pathStr); 654 lval = get_array_option(params->serverRef, kRASEntPPP, kRASPropPPPAuthenticatorACLPlugins, 655 i++, (u_char*)pathStr, sizeof(pathStr), &len, empty_str); 656 if (pathStr[0]) { 657 strlcat(pathStr, ".ppp", sizeof(pathStr)); // add plugin suffix 658 if (!plugin_exists(pathStr)) { 659 vpnlog(LOG_ERR, "Access Control plugin '%s' not found\n", pathStr); 660 return -1; 661 } 662 addstrparam(params->exec_args, ¶ms->next_arg_index, "plugin2", pathStr); 663 } 664 } 665 while (lval); 666 667 // add any additional plugin we want to load 668 i = 0; 669 do { 670 len = sizeof(pathStr); 671 lval = get_array_option(params->serverRef, kRASEntPPP, kRASPropPPPPlugins, 672 i++, (u_char*)pathStr, sizeof(pathStr), &len, empty_str); 673 if (pathStr[0]) { 674 strlcat(pathStr, ".ppp", sizeof(pathStr)); // add plugin suffix 675 if (!plugin_exists(pathStr)) { 676 vpnlog(LOG_ERR, "Plugin '%s' not found\n", pathStr); 677 return -1; 678 } 679 addstrparam(params->exec_args, ¶ms->next_arg_index, "plugin", pathStr); 680 } 681 } 682 while (lval); 683 684 return 0; 685} 686 687//----------------------------------------------------------------------------- 688// check_conflicts 689//----------------------------------------------------------------------------- 690int ppp_check_conflicts(struct vpn_params *params) 691{ 692 693 CFArrayRef array; 694 CFStringRef pattern, key; 695 CFStringRef type, subtype; 696 CFPropertyListRef ref; 697 int count, i, ret = 0; 698 char str[OPT_STR_LEN]; 699 700 pattern = CFStringCreateWithFormat(0, 0, CFSTR("%@/%@/%@/%s/%@"), kSCDynamicStoreDomainState, 701 kSCCompNetwork, kRASRemoteAccessServer, ".*", kRASEntInterface); 702 703 if (pattern) { 704 if ((array = SCDynamicStoreCopyKeyList(params->storeRef, pattern))) { 705 count = CFArrayGetCount(array); 706 for (i = 0; i < count; i++) { 707 key = CFArrayGetValueAtIndex(array, i); 708 if (key) { 709 ref = SCDynamicStoreCopyValue(params->storeRef, key); 710 if (isDictionary(ref)) { 711 type = CFDictionaryGetValue(ref, kRASPropInterfaceType); 712 subtype = CFDictionaryGetValue(ref, kRASPropInterfaceSubType); 713 if (isString(type) && isString(subtype) && 714 (CFStringCompare(type, kRASValInterfaceTypePPP, 0) == kCFCompareEqualTo) && 715 (CFStringCompare(subtype, params->serverSubTypeRef, 0) == kCFCompareEqualTo)) { 716 CFStringGetCString(subtype, str, OPT_STR_LEN, kCFStringEncodingMacRoman); 717 vpnlog(LOG_ERR, "Server for subtype %s already running - vpnd launch failed.\n", str); 718 ret = -1; 719 CFRelease(ref); 720 break; 721 } 722 } 723 if (ref) 724 CFRelease(ref); 725 } 726 } 727 CFRelease(array); 728 } 729 CFRelease(pattern); 730 } 731 return ret; 732} 733 734//----------------------------------------------------------------------------- 735// kill_orphans 736//----------------------------------------------------------------------------- 737int ppp_kill_orphans(struct vpn_params* params) 738{ 739 740 CFArrayRef array; 741 CFStringRef pattern, key; 742 CFMutableStringRef mutable_key; 743 CFStringRef server_id; 744 CFNumberRef pidRef; 745 CFPropertyListRef interface_dict, ppp_dict; 746 int count, i, pid; 747 int ret = 0; 748 749 pattern = CFStringCreateWithFormat(0, 0, CFSTR("%@/%@/%@/%s/%@"), kSCDynamicStoreDomainState, 750 kSCCompNetwork, kSCCompService, ".*", kSCEntNetInterface); 751 752 if (pattern) { 753 if ((array = SCDynamicStoreCopyKeyList(params->storeRef, pattern))) { 754 count = CFArrayGetCount(array); 755 // for each pppd - check if server id is the same as ours 756 for (i = 0; i < count; i++) { 757 key = CFArrayGetValueAtIndex(array, i); 758 if (key) { 759 interface_dict = SCDynamicStoreCopyValue(params->storeRef, key); 760 if (isDictionary(interface_dict)) { 761 server_id = CFDictionaryGetValue(interface_dict, CFSTR("ServerID")); 762 if (isString(server_id) && CFStringCompare(server_id, params->serverIDRef, 0) == kCFCompareEqualTo) { 763 // server id matches - get the pid and kill it 764 mutable_key = CFStringCreateMutableCopy(0, 0, key); 765 // modify the key to get the PPP dictionary 766 if (CFStringFindAndReplace(mutable_key, kSCEntNetInterface, kSCEntNetPPP, 767 CFRangeMake(0, CFStringGetLength(mutable_key)), kCFCompareBackwards | kCFCompareAnchored)) { 768 ppp_dict = SCDynamicStoreCopyValue(params->storeRef, mutable_key); 769 if (isDictionary(ppp_dict)) { 770 pidRef = CFDictionaryGetValue(ppp_dict, CFSTR("pid")); 771 if (isNumber(pidRef)) 772 if (CFNumberGetValue(pidRef, kCFNumberIntType, &pid)) 773 ret = kill(pid, SIGTERM); 774 } 775 if (ppp_dict) 776 CFRelease(ppp_dict); 777 } 778 if (mutable_key) 779 CFRelease(&mutable_key); 780 } 781 } 782 if (interface_dict) 783 CFRelease(interface_dict); 784 } 785 } 786 CFRelease(array); 787 } 788 CFRelease(pattern); 789 } 790 return ret; 791} 792