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