1/*
2 * Copyright (c) 2000-2003 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 *  L2TP plugin for vpnd
29 *
30----------------------------------------------------------------------------- */
31
32
33/* -----------------------------------------------------------------------------
34  Includes
35----------------------------------------------------------------------------- */
36
37#include <stdio.h>
38#include <ctype.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42#include <signal.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <syslog.h>
46#include <netdb.h>
47#include <pwd.h>
48#include <setjmp.h>
49#include <sys/param.h>
50#include <sys/types.h>
51#include <sys/wait.h>
52#include <sys/time.h>
53#include <sys/resource.h>
54#include <sys/socket.h>
55#include <sys/stat.h>
56#include <sys/socket.h>
57#include <netinet/in.h>
58#include <arpa/inet.h>
59#include <syslog.h>
60#include <sys/ioctl.h>
61#include <net/if.h>
62#include <net/route.h>
63#include <pthread.h>
64#include <sys/kern_event.h>
65#include <sys/sysctl.h>
66#include <netinet/in_var.h>
67#include <sys/un.h>
68#include <CoreFoundation/CFNumber.h>
69#include <CoreFoundation/CFBundle.h>
70#include <SystemConfiguration/SystemConfiguration.h>
71
72#define APPLE 1
73
74//#include "../L2TP-extension/l2tpk.h"
75#include "../../../Helpers/vpnd/ipsec_utils.h"
76#include "../../../Helpers/vpnd/vpnplugins.h"
77#include "../../../Helpers/vpnd/vpnd.h"
78#include "../../../Helpers/vpnd/RASSchemaDefinitions.h"
79#include "../../../Helpers/vpnd/cf_utils.h"
80#include "l2tp.h"
81
82#include "vpn_control.h"
83
84
85// ----------------------------------------------------------------------------
86//	� Private Globals
87// ----------------------------------------------------------------------------
88#define MAXSECRETLEN	256	/* max length of secret */
89
90static CFBundleRef 		bundle = 0;
91static CFBundleRef 		pppbundle = 0;
92static int 			listen_sockfd = -1;
93static int			opt_noipsec = 0;
94static int 			key_preference = -1;
95static struct sockaddr_in 	listen_address;
96static struct sockaddr_in 	our_address;
97static struct sockaddr_in 	any_address;
98static int			debug = 0;
99static int			racoon_sockfd = -1;
100static int			sick_timeleft = 0;
101static int			ping_timeleft = 0;
102static int			racoon_ping_seed = 0;
103#define IPSEC_SICK_TIME 60 //seconds
104#define IPSEC_PING_TIME 5 //seconds
105#define IPSEC_REPAIR_TIME 10 //seconds
106
107static CFMutableDictionaryRef	ipsec_dict = NULL;
108static CFMutableDictionaryRef	ipsec_settings = NULL;
109
110int l2tpvpn_get_pppd_args(struct vpn_params *params, int reload);
111int l2tpvpn_health_check(int *outfd, int event);
112int l2tpvpn_lb_redirect(struct in_addr *cluster_addr, struct in_addr *redirect_addr);
113int l2tpvpn_listen(void);
114int l2tpvpn_accept(void);
115int l2tpvpn_refuse(void);
116void l2tpvpn_close(void);
117int l2tp_set_delegated_process(int fd, int pid);
118
119static u_long load_kext(char *kext, int byBundleID);
120
121/* -----------------------------------------------------------------------------
122plugin entry point, called by vpnd
123ref is the vpn bundle reference
124pppref is the ppp bundle reference
125bundles can be layout in two different ways
126- As simple vpn bundles (bundle.vpn). the bundle contains the vpn bundle binary.
127- As full ppp bundles (bundle.ppp). The bundle contains the ppp bundle binary,
128and also the vpn kext and the vpn bundle binary in its Plugins directory.
129if a simple vpn bundle was used, pppref will be NULL.
130if a ppp bundle was used, the vpn plugin will be able to get access to the
131Plugins directory and load the vpn kext.
132----------------------------------------------------------------------------- */
133int start(struct vpn_channel* the_vpn_channel, CFBundleRef ref, CFBundleRef pppref, int debug_mode, int log_verbose)
134{
135    char 	name[MAXPATHLEN];
136    CFURLRef	url;
137    size_t		len;
138	int			nb_cpu = 1, nb_threads = 0;
139
140    debug = debug_mode;
141
142    /* first load the kext if we are loaded as part of a ppp bundle */
143    if (pppref) {
144        while ((listen_sockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_L2TP)) < 0)
145            if (errno != EINTR)
146                break;
147        if (listen_sockfd < 0) {
148            vpnlog(LOG_DEBUG, "L2TP plugin: first call to socket failed - attempting to load kext\n");
149            if ((url = CFBundleCopyBundleURL(pppref))) {
150                name[0] = 0;
151                CFURLGetFileSystemRepresentation(url, 0, (UInt8 *)name, MAXPATHLEN - 1);
152                CFRelease(url);
153                strlcat(name, "/", sizeof(name));
154                if ((url = CFBundleCopyBuiltInPlugInsURL(pppref))) {
155                    CFURLGetFileSystemRepresentation(url, 0, (UInt8 *)(name + strlen(name)),
156                                MAXPATHLEN - strlen(name) - strlen(L2TP_NKE) - 1);
157                    CFRelease(url);
158                    strlcat(name, "/", sizeof(name));
159                    strlcat(name, L2TP_NKE, sizeof(name));
160#if !TARGET_OS_EMBEDDED // This file is not built for Embedded
161                    if (!load_kext(name, 0))
162#else
163                    if (!load_kext(L2TP_NKE_ID, 1))
164#endif
165                        while ((listen_sockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_L2TP)) < 0)
166                            if (errno != EINTR)
167                                break;
168                }
169            }
170            if (listen_sockfd < 0) {
171                vpnlog(LOG_ERR, "L2TP plugin: Unable to load L2TP kernel extension\n");
172                return -1;
173            }
174        }
175    }
176
177#if !TARGET_OS_EMBEDDED // This file is not built for Embedded
178	/* increase the number of threads for l2tp to nb cpus - 1 */
179    len = sizeof(int);
180	sysctlbyname("hw.ncpu", &nb_cpu, &len, NULL, 0);
181    if (nb_cpu > 1) {
182		sysctlbyname("net.ppp.l2tp.nb_threads", &nb_threads, &len, 0, 0);
183		if (nb_threads < (nb_cpu - 1)) {
184			nb_threads = nb_cpu - 1;
185			sysctlbyname("net.ppp.l2tp.nb_threads", 0, 0, &nb_threads, sizeof(int));
186		}
187	}
188#endif
189
190    /* retain reference */
191    bundle = ref;
192    CFRetain(bundle);
193
194    pppbundle = pppref;
195    if (pppbundle)
196        CFRetain(pppbundle);
197
198    // hookup our socket handlers
199    bzero(the_vpn_channel, sizeof(struct vpn_channel));
200    the_vpn_channel->get_pppd_args = l2tpvpn_get_pppd_args;
201    the_vpn_channel->listen = l2tpvpn_listen;
202    the_vpn_channel->accept = l2tpvpn_accept;
203    the_vpn_channel->refuse = l2tpvpn_refuse;
204    the_vpn_channel->close = l2tpvpn_close;
205    the_vpn_channel->health_check = l2tpvpn_health_check;
206    the_vpn_channel->lb_redirect = l2tpvpn_lb_redirect;
207
208    return 0;
209}
210
211/* -----------------------------------------------------------------------------
212    l2tpvpn_get_pppd_args
213----------------------------------------------------------------------------- */
214int l2tpvpn_get_pppd_args(struct vpn_params *params, int reload)
215{
216
217    CFStringRef	string;
218    int		noipsec = 0;
219    CFMutableDictionaryRef	dict = NULL;
220
221    if (reload) {
222        noipsec = opt_noipsec;
223    }
224
225    if (params->serverRef) {
226        /* arguments from the preferences file */
227        addstrparam(params->exec_args, &params->next_arg_index, "l2tpmode", "answer");
228
229        string = get_cfstr_option(params->serverRef, kRASEntL2TP, kRASPropL2TPTransport);
230        if (string && CFEqual(string, kRASValL2TPTransportIP)) {
231            addparam(params->exec_args, &params->next_arg_index, "l2tpnoipsec");
232            opt_noipsec = 1;
233        }
234
235		dict = (CFMutableDictionaryRef)CFDictionaryGetValue(params->serverRef, kRASEntIPSec);
236		if (isDictionary(dict)) {
237			/* get the parameters from the IPSec dictionary */
238			dict = CFDictionaryCreateMutableCopy(0, 0, dict);
239		}
240		else {
241			/* get the parameters from the L2TP dictionary */
242			dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
243
244			string = get_cfstr_option(params->serverRef, kRASEntL2TP, kRASPropL2TPIPSecSharedSecretEncryption);
245			if (isString(string))
246				CFDictionarySetValue(dict, kRASPropIPSecSharedSecretEncryption, string);
247
248			string = get_cfstr_option(params->serverRef, kRASEntL2TP, kRASPropL2TPIPSecSharedSecret);
249			if (isString(string))
250				CFDictionarySetValue(dict, kRASPropIPSecSharedSecret, string);
251		}
252
253    } else {
254        /* arguments from command line */
255        if (opt_noipsec)
256            addparam(params->exec_args, &params->next_arg_index, "l2tpnoipsec");
257    }
258
259    if (reload) {
260        if (noipsec != opt_noipsec ||
261            !CFEqual(dict, ipsec_settings)) {
262				vpnlog(LOG_ERR, "reload prefs - IPSec shared secret cannot be changed\n");
263				if (dict)
264					CFRelease(dict);
265				return -1;
266		}
267    }
268
269	if (ipsec_settings)
270		CFRelease(ipsec_settings);
271	ipsec_settings = dict;
272
273    return 0;
274}
275
276/* -----------------------------------------------------------------------------
277    l2tpvpn_health_check
278----------------------------------------------------------------------------- */
279int l2tpvpn_health_check(int *outfd, int event)
280{
281
282	size_t				size;
283	struct	sockaddr_un sun;
284	int					ret = -1, flags;
285
286	char				data[256];
287	struct vpnctl_hdr			*hdr = (struct vpnctl_hdr *)data;
288
289	switch (event) {
290
291		case 0: // periodic check
292
293			// no ipsec, no need for health check
294			if (opt_noipsec) {
295				*outfd = -1;
296				break;
297			}
298
299			if (sick_timeleft) {
300				sick_timeleft--;
301				if (sick_timeleft == 0)
302					goto fail;
303			}
304
305			// racoon socket is already opened, just query racoon
306			if (racoon_sockfd != -1) {
307
308				if (ping_timeleft) {
309					ping_timeleft--;
310					if (ping_timeleft == 0) {
311						// error on racoon socket. racoon exited ?
312						ret = -2; // L2TP is sick, but don't die yet, give it 60 seconds to recover
313						sick_timeleft = IPSEC_SICK_TIME;
314						goto fail;
315					}
316				}
317				else {
318					// query racoon here
319					bzero(hdr, sizeof(struct vpnctl_hdr));
320					hdr->msg_type = htons(VPNCTL_CMD_PING);
321					hdr->cookie = htonl(++racoon_ping_seed);
322					ping_timeleft = IPSEC_PING_TIME;		// give few seconds to get a reply
323					writen(racoon_sockfd, hdr, sizeof(struct vpnctl_hdr));
324				}
325				break;
326			}
327
328			// attempt to kill and restart racoon every 10 seconds
329			if ((sick_timeleft % IPSEC_REPAIR_TIME) == 0) {
330				vpnlog(LOG_ERR, "IPSecSelfRepair\n");
331				IPSecSelfRepair();
332			}
333
334			// racoon socket is not yet opened, so opened it
335			/* open the racoon control socket  */
336			racoon_sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);
337			if (racoon_sockfd < 0) {
338				vpnlog(LOG_ERR, "Unable to create racoon control socket (errno = %d)\n", errno);
339				goto fail;
340			}
341
342			bzero(&sun, sizeof(sun));
343			sun.sun_family = AF_LOCAL;
344			strncpy(sun.sun_path, "/var/run/vpncontrol.sock", sizeof(sun.sun_path));
345
346			if (connect(racoon_sockfd,  (struct sockaddr *)&sun, sizeof(sun)) < 0) {
347				vpnlog(LOG_ERR, "Unable to connect racoon control socket (errno = %d)\n", errno);
348				ret = -2;
349				goto fail;
350			}
351
352			if ((flags = fcntl(racoon_sockfd, F_GETFL)) == -1
353				|| fcntl(racoon_sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
354				vpnlog(LOG_ERR, "Unable to set racoon control socket in non-blocking mode (errno = %d)\n", errno);
355				ret = -2;
356				goto fail;
357			}
358
359			*outfd = racoon_sockfd;
360			sick_timeleft = 0;
361			ping_timeleft = 0;
362			break;
363
364		case 1: // event on racoon fd
365			size = recvfrom (racoon_sockfd, data, sizeof(struct vpnctl_hdr), 0, 0, 0);
366			if (size == 0) {
367				// error on racoon socket. racoon exited ?
368				ret = -2; // L2TP is sick, but don't die yet, give it 60 seconds to recover
369				sick_timeleft = IPSEC_SICK_TIME;
370				ping_timeleft = 0;
371				goto fail;
372			}
373
374			/* read end of packet */
375			if (ntohs(hdr->len)) {
376				size = recvfrom (racoon_sockfd, data + sizeof(struct vpnctl_hdr), ntohs(hdr->len), 0, 0, 0);
377				if (size == 0) {
378					// error on racoon socket. racoon exited ?
379					ret = -2; // L2TP is sick, but don't die yet, give it 60 seconds to recover
380					sick_timeleft = IPSEC_SICK_TIME;
381					ping_timeleft = 0;
382					goto fail;
383				}
384			}
385
386			switch (ntohs(hdr->msg_type)) {
387
388				case VPNCTL_CMD_PING:
389
390					if (racoon_ping_seed == ntohl(hdr->cookie)) {
391						// good !
392						ping_timeleft = 0;
393					//vpnlog(LOG_DEBUG, "receive racoon PING REPLY cookie %d\n", ntohl(hdr->cookie));
394					}
395					break;
396
397				default:
398					/* ignore other messages */
399					//vpnlog(LOG_DEBUG, "receive racoon message type %d, result %d\n", ntohs(hdr->msg_type), ntohs(hdr->result));
400					break;
401
402			}
403			break;
404
405	}
406
407	return 0;
408
409fail:
410	if (racoon_sockfd != -1) {
411		close(racoon_sockfd);
412		racoon_sockfd = -1;
413		*outfd = -1;
414	}
415	return ret;
416}
417
418// ----------------------------------------------------------------------------
419//	notify racoon of the new redirection
420// ----------------------------------------------------------------------------
421int l2tpvpn_lb_redirect(struct in_addr *cluster_addr, struct in_addr *redirect_addr)
422{
423
424	if (racoon_sockfd == -1) {
425		return -1;
426	}
427
428	struct vpnctl_cmd_redirect msg;
429	bzero(&msg, sizeof(msg));
430	msg.hdr.len = htons(sizeof(msg) - sizeof(msg.hdr));
431	msg.hdr.msg_type = htons(VPNCTL_CMD_REDIRECT);
432	msg.address = cluster_addr->s_addr;
433	msg.redirect_address = redirect_addr->s_addr;
434	msg.force = htons(1);
435	writen(racoon_sockfd, &msg, sizeof(msg));
436	return 0;
437}
438
439/* -----------------------------------------------------------------------------
440    system call wrappers
441----------------------------------------------------------------------------- */
442int l2tp_sys_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)
443{
444    while (getsockopt(sockfd, level, optname, optval, optlen) < 0)
445        if (errno != EINTR) {
446            vpnlog(LOG_ERR, "L2TP plugin: error calling getsockopt for option %d (%s)\n", optname, strerror(errno));
447            return -1;
448        }
449    return 0;
450}
451
452int l2tp_sys_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
453{
454    while (setsockopt(sockfd, level, optname, optval, optlen) < 0)
455        if (errno != EINTR) {
456            vpnlog(LOG_ERR, "L2TP plugin: error calling setsockopt for option %d (%s)\n", optname, strerror(errno));
457            return -1;
458        }
459    return 0;
460}
461
462int l2tp_sys_recvfrom(int sockfd, void *buff, size_t nbytes, int flags,
463            struct sockaddr *from, socklen_t *addrlen)
464{
465    while (recvfrom(sockfd, buff, nbytes, flags, from, addrlen) < 0)
466        if (errno != EINTR) {
467            vpnlog(LOG_ERR, "L2TP plugin: error calling recvfrom = %s\n", strerror(errno));
468            return -1;
469        }
470    return 0;
471}
472
473/* -----------------------------------------------------------------------------
474    set_flag
475----------------------------------------------------------------------------- */
476int set_flag(int fd, int set, u_int32_t flag)
477{
478    socklen_t 	optlen;
479    u_int32_t	flags;
480
481    optlen = 4;
482    if (l2tp_sys_getsockopt(fd, PPPPROTO_L2TP, L2TP_OPT_FLAGS, &flags, &optlen) < 0)
483        return -1;
484
485    flags = set ? (flags | flag) : (flags & ~flag);
486    if (l2tp_sys_setsockopt(fd, PPPPROTO_L2TP, L2TP_OPT_FLAGS, &flags, 4) < 0)
487        return -1;
488
489    return 0;
490}
491
492/* -----------------------------------------------------------------------------
493    closeall
494----------------------------------------------------------------------------- */
495static void closeall()
496{
497    int i;
498
499    for (i = getdtablesize() - 1; i >= 0; i--) close(i);
500    open("/dev/null", O_RDWR, 0);
501    dup(0);
502    dup(0);
503    return;
504}
505
506
507/* -----------------------------------------------------------------------------
508    load_kext
509----------------------------------------------------------------------------- */
510u_long load_kext(char *kext, int byBundleID)
511{
512    int pid;
513
514    if ((pid = fork()) < 0)
515        return 1;
516
517    if (pid == 0) {
518        closeall();
519        // PPP kernel extension not loaded, try load it...
520		if (byBundleID)
521			execle("/sbin/kextload", "kextload", "-b", kext, (char *)0, (char *)0);
522		else
523			execle("/sbin/kextload", "kextload", kext, (char *)0, (char *)0);
524        exit(1);
525    }
526
527    while (waitpid(pid, 0, 0) < 0) {
528        if (errno == EINTR)
529            continue;
530       return 1;
531    }
532    return 0;
533}
534
535/* -----------------------------------------------------------------------------
536 ----------------------------------------------------------------------------- */
537int l2tp_set_delegated_process(int fd, int pid)
538{
539    setsockopt(fd, PPPPROTO_L2TP, L2TP_OPT_SETDELEGATEDPID, &pid, sizeof(pid));
540    return 0;
541}
542
543/* -----------------------------------------------------------------------------
544----------------------------------------------------------------------------- */
545int l2tp_set_ouraddress(int fd, struct sockaddr *addr)
546{
547    socklen_t optlen;
548
549    setsockopt(fd, PPPPROTO_L2TP, L2TP_OPT_OURADDRESS, addr, sizeof(*addr));
550    /* get the address to retrieve the actual port used */
551    optlen = sizeof(*addr);
552    getsockopt(fd, PPPPROTO_L2TP, L2TP_OPT_OURADDRESS, addr, &optlen);
553    return 0;
554}
555
556/* -----------------------------------------------------------------------------
557    l2tpvpn_listen - called by vpnd to setup listening socket
558----------------------------------------------------------------------------- */
559int l2tpvpn_listen(void)
560{
561	char *errstr;
562
563    if (listen_sockfd <= 0)
564        return -1;
565
566    //set_flag(listen_sockfd, kerneldebug & 1, L2TP_FLAG_DEBUG);
567    set_flag(listen_sockfd, 1, L2TP_FLAG_CONTROL);
568    set_flag(listen_sockfd, !opt_noipsec, L2TP_FLAG_IPSEC);
569    l2tp_set_delegated_process(listen_sockfd, getpid());  // must be set before calling l2tp_set_ouraddress
570
571    /* unknown src and dst addresses */
572    any_address.sin_len = sizeof(any_address);
573    any_address.sin_family = AF_INET;
574    any_address.sin_port = 0;
575    any_address.sin_addr.s_addr = INADDR_ANY;
576
577    /* bind the socket in the kernel with L2TP port */
578    listen_address.sin_len = sizeof(listen_address);
579    listen_address.sin_family = AF_INET;
580    listen_address.sin_port = htons(L2TP_UDP_PORT);
581    listen_address.sin_addr.s_addr = INADDR_ANY;
582    l2tp_set_ouraddress(listen_sockfd, (struct sockaddr *)&listen_address);
583    our_address = listen_address;
584
585    /* add security policies */
586    if (!opt_noipsec) {
587
588		CFStringRef				auth_method;
589		CFStringRef				string;
590		CFDataRef				data;
591		uint32_t						natt_multiple_users;
592
593		/* get authentication method from the IPSec dict */
594		auth_method = CFDictionaryGetValue(ipsec_settings, kRASPropIPSecAuthenticationMethod);
595		if (!isString(auth_method))
596			auth_method = kRASValIPSecAuthenticationMethodSharedSecret;
597
598		/* get setting for nat traversal multiple user support - default is enabled for server */
599		GetIntFromDict(ipsec_settings, kRASPropIPSecNattMultipleUsersEnabled, &natt_multiple_users, 1);
600
601		ipsec_dict = IPSecCreateL2TPDefaultConfiguration(
602			&our_address, &any_address, NULL,
603			auth_method, 0, natt_multiple_users, 0);
604
605		/* set the authentication information */
606		if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodSharedSecret)) {
607			string = CFDictionaryGetValue(ipsec_settings, kRASPropIPSecSharedSecret);
608			if (isString(string))
609				CFDictionarySetValue(ipsec_dict, kRASPropIPSecSharedSecret, string);
610			else if (isData(string) && ((CFDataGetLength((CFDataRef)string) % sizeof(UniChar)) == 0)) {
611				CFStringEncoding    encoding;
612
613				data = (CFDataRef)string;
614#if     __BIG_ENDIAN__
615				encoding = (*(CFDataGetBytePtr(data) + 1) == 0x00) ? kCFStringEncodingUTF16LE : kCFStringEncodingUTF16BE;
616#else   // __LITTLE_ENDIAN__
617				encoding = (*(CFDataGetBytePtr(data)    ) == 0x00) ? kCFStringEncodingUTF16BE : kCFStringEncodingUTF16LE;
618#endif
619				string = CFStringCreateWithBytes(NULL, (const UInt8 *)CFDataGetBytePtr(data), CFDataGetLength(data), encoding, FALSE);
620				CFDictionarySetValue(ipsec_dict, kRASPropIPSecSharedSecret, string);
621				CFRelease(string);
622			}
623			string = CFDictionaryGetValue(ipsec_settings, kRASPropIPSecSharedSecretEncryption);
624			if (isString(string))
625				CFDictionarySetValue(ipsec_dict, kRASPropIPSecSharedSecretEncryption, string);
626		}
627		else if (CFEqual(auth_method, kRASValIPSecAuthenticationMethodCertificate)) {
628			data = CFDictionaryGetValue(ipsec_settings, kRASPropIPSecLocalCertificate);
629			if (isData(data))
630				CFDictionarySetValue(ipsec_dict, kRASPropIPSecLocalCertificate, data);
631		}
632
633		if (IPSecApplyConfiguration(ipsec_dict, &errstr)
634			|| IPSecInstallPolicies(ipsec_dict, -1, &errstr)) {
635			vpnlog(LOG_ERR, "L2TP plugin: cannot configure secure transport (%s).\n", errstr);
636			IPSecRemoveConfiguration(ipsec_dict, &errstr);
637			CFRelease(ipsec_dict);
638			ipsec_dict = 0;
639			return -1;
640		}
641
642        /* set IPSec Key management to prefer most recent key */
643        if (IPSecSetSecurityAssociationsPreference(&key_preference, 0))
644            vpnlog(LOG_ERR, "L2TP plugin: cannot set IPSec Key management preference (error %d)\n", errno);
645
646		sick_timeleft = IPSEC_SICK_TIME;
647		ping_timeleft = 0;
648
649    }
650
651    return listen_sockfd;
652}
653
654
655/* -----------------------------------------------------------------------------
656    l2tpvpn_accept
657----------------------------------------------------------------------------- */
658int l2tpvpn_accept(void)
659{
660
661    u_int8_t			recv_buf[1500];
662    socklen_t				addrlen;
663    struct sockaddr_in6		from;
664    int 			newSockfd;
665
666    /* we should check if there are too many call from the same IP address
667    in the last xxx minutes, proving a denial of service attack */
668
669    while((newSockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_L2TP)) < 0)
670        if (errno != EINTR) {
671            vpnlog(LOG_ERR, "L2TP plugin: Unable to open L2TP socket during accept\n");
672            return -1;
673        }
674
675    /* accept the call. it will copy the data to the new socket */
676    //set_flag(newSockfd, kerneldebug & 1, L2TP_FLAG_DEBUG);
677    setsockopt(newSockfd, PPPPROTO_L2TP, L2TP_OPT_ACCEPT, 0, 0);
678
679    /* read the duplicated SCCRQ from the listen socket and ignore for now */
680    if (l2tp_sys_recvfrom(listen_sockfd, recv_buf, 1500, MSG_DONTWAIT, (struct sockaddr*)&from, &addrlen) < 0)
681        return -1;
682
683    return newSockfd;
684}
685
686
687/* -----------------------------------------------------------------------------
688    l2tpvpn_refuse - called by vpnd to refuse an incomming connection.
689        return values: 	 -1 		error
690                         socket#	launch pppd with next server address
691                         0 			handled, do nothing
692
693----------------------------------------------------------------------------- */
694int l2tpvpn_refuse(void)
695{
696    u_int8_t			recv_buf[1500];
697    socklen_t				addrlen;
698    struct sockaddr_in6		from;
699    int 			newSockfd;
700
701    /* we should check if there are too many call from the same IP address
702    in the last xxx minutes, proving a denial of service attack */
703
704    /* need t read the packet to empty the socket buffer */
705    while((newSockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_L2TP)) < 0)
706        if (errno != EINTR) {
707            vpnlog(LOG_ERR, "L2TP plugin: Unable to open L2TP socket during refuse\n");
708            return -1;
709        }
710
711    /* accept the call. it will copy the data to the new socket */
712    setsockopt(newSockfd, PPPPROTO_L2TP, L2TP_OPT_ACCEPT, 0, 0);
713    /* and close it right away */
714    close(newSockfd);
715
716    /* read the duplicated SCCRQ from the listen socket and ignore for now */
717    if (l2tp_sys_recvfrom(listen_sockfd, recv_buf, 1500, MSG_DONTWAIT, (struct sockaddr*)&from, &addrlen) < 0)
718        return -1;
719
720    return 0;
721}
722
723/* -----------------------------------------------------------------------------
724    l2tpvpn_close
725----------------------------------------------------------------------------- */
726void l2tpvpn_close(void)
727{
728
729	char *errstr;
730
731	if (racoon_sockfd != -1) {
732		close(racoon_sockfd);
733		racoon_sockfd = -1;
734	}
735
736    if (listen_sockfd != -1) {
737        while (close(listen_sockfd) < 0)
738            if (errno == EINTR)
739                continue;
740        listen_sockfd = -1;
741    }
742
743    /* remove security policies */
744    if (ipsec_dict) {
745        IPSecRemoveConfiguration(ipsec_dict, &errstr);
746        IPSecRemovePolicies(ipsec_dict, -1, &errstr);
747        /* restore IPSec Key management preference */
748        if (IPSecSetSecurityAssociationsPreference(0, key_preference))
749            vpnlog(LOG_ERR, "L2TP plugin: cannot reset IPSec Key management preference (error %d)\n", errno);
750		CFRelease(ipsec_dict);
751		ipsec_dict = NULL;
752    }
753
754	if (ipsec_settings) {
755		CFRelease(ipsec_settings);
756		ipsec_settings = NULL;
757	}
758
759}
760
761
762
763