Project

General

Profile

Download (30.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	vpn.inc
4
	Copyright (C) 2004-2006 Scott Ullrich
5
	All rights reserved.
6

    
7
	originally part of m0n0wall (http://m0n0.ch/wall)
8
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
9
	All rights reserved.
10

    
11
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13

    
14
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16

    
17
	2. Redistributions in binary form must reproduce the above copyright
18
	   notice, this list of conditions and the following disclaimer in the
19
	   documentation and/or other materials provided with the distribution.
20

    
21
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32

    
33
/* include all configuration functions */
34
require_once("functions.inc");
35

    
36
/* master setup for vpn (mpd) */
37
function vpn_setup() {
38
	/* start pptpd */
39
	vpn_pptpd_configure();
40

    
41
	/* start pppoe server */
42
	vpn_pppoe_configure();
43
}
44

    
45
function vpn_ipsec_failover_configure() {
46
	global $config, $g;
47

    
48
	$sasyncd_text = "";
49

    
50
	if($config['installedpackages']['sasyncd']['config'] <> "")
51
		foreach($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
52
			$enabled = isset($sasyncd['enable']);
53
			if(!$enabled)
54
				return;
55
			if($sasyncd['peerip'] <> "")
56
				$sasyncd_text .= "peer {$sasyncd['peerip']}\n";
57
			if($sasyncd['interface'])
58
				$sasyncd_text .= "carp interface {$sasyncd['interface']}\n";
59
			if($sasyncd['sharedkey'] <> "")
60
				$sasyncd_text .= "sharedkey {$sasyncd['sharedkey']}\n";
61
			if($sasyncd['mode'] <> "")
62
				$sasyncd_text .= "mode {$sasyncd['mode']}\n";
63
			if($sasyncd['listenon'] <> "")
64
				$sasyncd_text .= "listen on {$sasyncd['listenon']}\n";
65
			if($sasyncd['flushmodesync'] <> "")
66
				$sasyncd_text .= "flushmode sync {$sasyncd['flushmodesync']}\n";
67
		}
68

    
69
	$fd = fopen("{$g['varetc_path']}/sasyncd.conf", "w");
70
	fwrite($fd, $sasyncd_text);
71
	fclose($fd);
72
	chmod("{$g['varetc_path']}/sasyncd.conf", 0600);
73

    
74
	mwexec("killall sasyncd");
75

    
76
	/* launch sasyncd, oh wise one */
77
	/* mwexec_bg("/usr/local/sbin/sasyncd -d -v -v -v"); */
78
}
79

    
80
function find_last_gif_device() {
81
	 	$regs = "";
82
        $last_gif_found = -1;
83
        if (!($fp = popen("/sbin/ifconfig -l", "r"))) return -1;
84
        $ifconfig_data = fread($fp, 4096);
85
        pclose($fp);
86
        $ifconfig_array = split(" ", $ifconfig_data);
87
        foreach ($ifconfig_array as $ifconfig) {
88
                ereg("gif(.)", $ifconfig, $regs);
89
                if($regs[0]) {
90
                        if($regs[0] > $last_gif_found)
91
                                $last_gif_found = $regs[1];
92
                }
93
        }
94
        return $last_gif_found;
95
}
96

    
97
function vpn_ipsec_configure($ipchg = false) {
98
	global $config, $g, $sa, $sn;
99

    
100
	mwexec("/sbin/ifconfig enc0 create");
101
	mwexec("/sbin/ifconfig enc0 up");
102

    
103
	/* get the automatic /etc/ping_hosts.sh ready */
104
	unlink_if_exists("/var/db/ipsecpinghosts");
105
	touch("/var/db/ipsecpinghosts");
106

    
107
	if($g['booting'] == true) {
108
		/* determine if we should load the via padlock module */
109
		$dmesg_boot = `cat /var/log/dmesg.boot | grep CPU`;
110
		if(stristr($dmesg_boot, "ACE") == true) {
111
			//echo "Enabling [VIA Padlock] ...";
112
			//mwexec("/sbin/kldload padlock");
113
			//mwexec("/sbin/sysctl net.inet.ipsec.crypto_support=1");
114
			//mwexec("/usr/local/sbin/setkey -F");
115
			//mwexec("/usr/local/sbin/setkey -FP");
116
			//echo " done.\n";
117
		}
118
	}
119

    
120
	if(isset($config['ipsec']['preferredoldsa'])) {
121
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
122
	} else {
123
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
124
	}
125

    
126
	$number_of_gifs = find_last_gif_device();
127
	for($x=0; $x<$number_of_gifs; $x++) {
128
		mwexec("/sbin/ifconfig gif" . $x . " delete");
129
	}
130

    
131
	$curwanip = get_current_wan_address();
132

    
133
	$syscfg = $config['system'];
134
	$ipseccfg = $config['ipsec'];
135
	$lancfg = $config['interfaces']['lan'];
136
	$lanip = $lancfg['ipaddr'];
137
	$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
138
	$lansn = $lancfg['subnet'];
139

    
140
	if (!isset($ipseccfg['enable'])) {
141
		mwexec("/sbin/ifconfig enc0 down");
142
		mwexec("/sbin/ifconfig enc0 destroy");
143

    
144
		/* kill racoon */
145
		mwexec("/usr/bin/killall racoon");
146

    
147
		/* wait for process to die */
148
		sleep(2);
149

    
150
		/* send a SIGKILL to be sure */
151
		sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
152

    
153
		/* flush SPD and SAD */
154
		mwexec("/usr/local/sbin/setkey -FP");
155
		mwexec("/usr/local/sbin/setkey -F");
156

    
157
		return true;
158
	}
159

    
160
	if ($g['booting']) {
161
		echo "Configuring IPsec VPN... ";
162
	}
163

    
164
	if (isset($ipseccfg['enable'])) {
165

    
166
		/* fastforwarding is not compatible with ipsec tunnels */
167
		system("/sbin/sysctl net.inet.ip.fastforwarding=0 >/dev/null 2>&1");
168

    
169
		if (!$curwanip) {
170
			/* IP address not configured yet, exit */
171
			if ($g['booting'])
172
				echo "done\n";
173
			return 0;
174
		}
175

    
176
		if ((is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel'])) ||
177
				isset($ipseccfg['mobileclients']['enable'])) {
178

    
179
			if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel'])) {
180

    
181
				/* generate spd.conf */
182
				$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
183
				if (!$fd) {
184
					printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
185
					return 1;
186
				}
187

    
188
				$spdconf = "";
189

    
190
				$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
191
				$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
192

    
193
				foreach ($ipseccfg['tunnel'] as $tunnel) {
194

    
195
					if (isset($tunnel['disabled']))
196
						continue;
197

    
198
					$ep = vpn_endpoint_determine($tunnel, $curwanip);
199
					if (!$ep) {
200
						log_error("Could not deterimine VPN endpoint for {$tunnel['descr']}");
201
						continue;	
202
					}
203

    
204
					vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
205

    
206
					if(is_domain($tunnel['remote-gateway'])) {
207
						$tmp = gethostbyname($tunnel['remote-gateway']);
208
						if($tmp)
209
							$tunnel['remote-gateway'] = $tmp;
210
					}
211

    
212
					/* add entry to host pinger */
213
					if ($tunnel['pinghost']) {
214
						$pfd = fopen("/var/db/ipsecpinghosts", "a");
215
						$iflist = array("lan" => "lan", "wan" => "wan");
216
			          	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
217
			          		$iflist['opt' . $i] = "opt{$i}";
218
			            foreach ($iflist as $ifent => $ifname) {
219
			            	$interface_ip = find_interface_ip($config['interfaces'][$ifname]['if']);
220
			            	if (ip_in_subnet($interface_ip, $sa . "/" . $sn))
221
			                	$srcip = find_interface_ip($config['interfaces'][$ifname]['if']);
222
			            }
223
						$dstip = $tunnel['pinghost'];
224
						fwrite($pfd, "$srcip|$dstip|3\n");
225
						fclose($pfd);
226
					}
227
					if(isset($tunnel['creategif'])) {
228
						$number_of_gifs = find_last_gif_device();
229
						$number_of_gifs++;
230
						$curwanip = get_current_wan_address();
231

    
232
						mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $tunnel['remote-gateway']);
233
						mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
234
					}
235

    
236
					$spdconf .= "spdadd {$sa}/{$sn} " .
237
						"{$tunnel['remote-subnet']} any -P out ipsec " .
238
						"{$tunnel['p2']['protocol']}/tunnel/{$ep}-" .
239
						"{$tunnel['remote-gateway']}/unique;\n";
240

    
241
					$spdconf .= "spdadd {$tunnel['remote-subnet']} " .
242
						"{$sa}/{$sn} any -P in ipsec " .
243
						"{$tunnel['p2']['protocol']}/tunnel/{$tunnel['remote-gateway']}-" .
244
						"{$ep}/unique;\n";
245
				
246
					/* static route needed? */
247
					if(preg_match("/^carp/i", $tunnel['interface'])) {
248
						$parentinterface = link_carp_interface_to_parent($tunnel['interface']);
249
					} else {
250
						$parentinterface = $tunnel['interface'];
251
					}
252
					if($parentinterface <> "wan") {
253
						/* add endpoint routes to correct gateway on interface */
254
						if(interface_has_gateway($parentinterface)) {
255
							$gatewayip = get_interface_gateway("$parentinterface");
256
							$interfaceip = $config['interfaces'][$parentinterface]['ipaddr'];
257
							$subnet_bits = $config['interfaces'][$parentinterface]['subnet'];
258
							$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
259
							/* if the remote gateway is in the local subnet, then don't add a route */
260
							if(! ip_in_subnet($tunnel['remote-gateway'], "{$subnet_ip}/{$subnet_bits}")) {
261
								if(is_ipaddr($gatewayip)) {
262
									log_error("IPSEC interface is not WAN but {$tunnel['interface']}, adding static route for VPN endpoint {$tunnel['remote-gateway']} via {$gatewayip}");
263
									mwexec("/sbin/route delete -host {$tunnel['remote-gateway']};/sbin/route add -host {$tunnel['remote-gateway']} {$gatewayip}");
264
								}
265
							}
266
						}
267
					} else {
268
						mwexec("/sbin/route delete -host {$tunnel['remote-gateway']}");
269
					}
270
				}
271

    
272
				fwrite($fd, $spdconf);
273
				fclose($fd);
274
			}
275

    
276
			/* generate racoon.conf */
277
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
278
			if (!$fd) {
279
				printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
280
				return 1;
281
			}
282

    
283
			$racoonconf = "";
284

    
285
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
286
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
287

    
288
			/* generate CA certificates files */
289
			$cacertnum = 0;
290
			if (is_array($ipseccfg['cacert']) && count($ipseccfg['cacert']))
291
				foreach ($ipseccfg['cacert'] as $cacert) {
292
					++$cacertnum;
293
					if (isset($cacert['cert'])) {
294
						$cert = base64_decode($cacert['cert']);
295
						$x509cert = openssl_x509_parse(openssl_x509_read($cert));
296
						if(is_array($x509cert) && isset($x509cert['hash'])) {
297
							$fd1 = fopen("{$g['varetc_path']}/{$x509cert['hash']}.0", "w");
298
							if (!$fd1) {
299
								printf("Error: cannot open {$x509cert['hash']}.0 in vpn.\n");
300
								return 1;
301
							}
302
							chmod("{$g['varetc_path']}/{$x509cert['hash']}.0", 0600);
303
							fwrite($fd1, $cert);
304
							fclose($fd1);
305
						}
306
					}
307
				}
308

    
309
			$tunnelnumber = 0;
310
			if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel']))
311
				foreach ($ipseccfg['tunnel'] as $tunnel) {
312

    
313
				++$tunnelnumber;
314

    
315
				if (isset($tunnel['disabled']))
316
					continue;
317

    
318
				$ep = vpn_endpoint_determine($tunnel, $curwanip);
319
				if (!$ep)
320
					continue;
321

    
322
				vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
323

    
324
				if (isset($tunnel['p1']['myident']['myaddress'])) {
325
					$myidentt = "address";
326
					$myident = $ep;
327
				} else if (isset($tunnel['p1']['myident']['address'])) {
328
					$myidentt = "address";
329
					$myident = $tunnel['p1']['myident']['address'];
330
				} else if (isset($tunnel['p1']['myident']['fqdn'])) {
331
					$myidentt = "fqdn";
332
					$myident = $tunnel['p1']['myident']['fqdn'];
333
				} else if (isset($tunnel['p1']['myident']['ufqdn'])) {
334
					$myidentt = "user_fqdn";
335
					$myident = $tunnel['p1']['myident']['ufqdn'];
336
 				} else if (isset($tunnel['p1']['myident']['dyn_dns'])) {
337
					$myidentt = "dyn_dns";
338
					$myident = gethostbyname($tunnel['p1']['myident']['dyn_dns']);
339
 				}
340

    
341
				if (!($myidentt == "asn1dn" && $myident == "")) {
342
					$myident = " \"".$myident."\"";
343
				}
344
				
345
				$nattline = '';
346
				if (isset($tunnel['natt'])) {
347
					$nattline = "nat_traversal on;";
348
				}
349

    
350
				if (isset($tunnel['p1']['authentication_method'])) {
351
					$authmethod = $tunnel['p1']['authentication_method'];
352
				} else {$authmethod = 'pre_shared_key';}
353

    
354
				$certline = '';
355

    
356
				if ($authmethod == 'rsasig') {
357
					if ($tunnel['p1']['cert'] && $tunnel['p1']['private-key']) {
358
						$cert = base64_decode($tunnel['p1']['cert']);
359
						$private_key = base64_decode($tunnel['p1']['private-key']);
360
					} else {
361
						/* null certificate/key */
362
						$cert = '';
363
						$private_key = '';
364
					}
365

    
366
					if ($tunnel['p1']['peercert'])
367
						$peercert = base64_decode($tunnel['p1']['peercert']);
368
					else
369
						$peercert = '';
370

    
371
					$fd1 = fopen("{$g['varetc_path']}/server{$tunnelnumber}-signed.pem", "w");
372
					if (!$fd1) {
373
						printf("Error: cannot open server{$tunnelnumber}-signed.pem in vpn.\n");
374
						return 1;
375
					}
376
					chmod("{$g['varetc_path']}/server{$tunnelnumber}-signed.pem", 0600);
377
					fwrite($fd1, $cert);
378
					fclose($fd1);
379

    
380
					$fd1 = fopen("{$g['varetc_path']}/server{$tunnelnumber}-key.pem", "w");
381
					if (!$fd1) {
382
						printf("Error: cannot open server{$tunnelnumber}-key.pem in vpn.\n");
383
						return 1;
384
					}
385
					chmod("{$g['varetc_path']}/server{$tunnelnumber}-key.pem", 0600);
386
					fwrite($fd1, $private_key);
387
					fclose($fd1);
388

    
389
					$certline = "certificate_type x509 \"server{$tunnelnumber}-signed.pem\" \"server{$tunnelnumber}-key.pem\";";
390

    
391
					if ($peercert!=''){
392
						$fd1 = fopen("{$g['varetc_path']}/peer{$tunnelnumber}-signed.pem", "w");
393
						if (!$fd1) {
394
							printf("Error: cannot open server{$tunnelnumber}-signed.pem in vpn.\n");
395
							return 1;
396
						}
397
						chmod("{$g['varetc_path']}/peer{$tunnelnumber}-signed.pem", 0600);
398
						fwrite($fd1, $peercert);
399
						fclose($fd1);
400
						$certline .= <<<EOD
401

    
402
	peers_certfile "peer{$tunnelnumber}-signed.pem";
403
EOD;
404
					}
405
				}
406
				$racoonconf .= <<<EOD
407
remote {$tunnel['remote-gateway']} \{
408
	exchange_mode {$tunnel['p1']['mode']};
409
	my_identifier {$myidentt}{$myident};
410
	{$certline}
411
	peers_identifier address {$tunnel['remote-gateway']};
412
	initial_contact on;
413
	#dpd_delay 120;                   # DPD poll every 120 seconds
414
	ike_frag on;
415
	support_proxy on;
416
	proposal_check obey;
417

    
418
	proposal \{
419
		encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
420
		hash_algorithm {$tunnel['p1']['hash-algorithm']};
421
		authentication_method {$authmethod};
422
		dh_group {$tunnel['p1']['dhgroup']};
423

    
424
EOD;
425
				if ($tunnel['p1']['lifetime'])
426
					$racoonconf .= "		lifetime time {$tunnel['p1']['lifetime']} secs;\n";
427

    
428
				$racoonconf .= "	}\n";
429

    
430
				if ($tunnel['p1']['lifetime'])
431
					$racoonconf .= "	lifetime time {$tunnel['p1']['lifetime']} secs;\n";
432

    
433
				$racoonconf .= "}\n\n";
434

    
435
				$p2ealgos = join(",", $tunnel['p2']['encryption-algorithm-option']);
436
				$p2halgos = join(",", $tunnel['p2']['hash-algorithm-option']);
437

    
438
				$racoonconf .= <<<EOD
439
sainfo address {$sa}/{$sn} any address {$tunnel['remote-subnet']} any \{
440
	encryption_algorithm {$p2ealgos};
441
	authentication_algorithm {$p2halgos};
442
	compression_algorithm deflate;
443

    
444
EOD;
445

    
446
				if ($tunnel['p2']['pfsgroup'])
447
					$racoonconf .= "	pfs_group {$tunnel['p2']['pfsgroup']};\n";
448

    
449
				if ($tunnel['p2']['lifetime'])
450
					$racoonconf .= "	lifetime time {$tunnel['p2']['lifetime']} secs;\n";
451

    
452
				$racoonconf .= "}\n\n";
453
			}
454

    
455
			/* mobile clients? */
456
			if (isset($ipseccfg['mobileclients']['enable'])) {
457

    
458
				$tunnel = $ipseccfg['mobileclients'];
459

    
460
				if (isset($tunnel['p1']['myident']['myaddress'])) {
461
					$myidentt = "address";
462
					$myident = $curwanip;
463
				} else if (isset($tunnel['p1']['myident']['address'])) {
464
					$myidentt = "address";
465
					$myident = $tunnel['p1']['myident']['address'];
466
				} else if (isset($tunnel['p1']['myident']['fqdn'])) {
467
					$myidentt = "fqdn";
468
					$myident = $tunnel['p1']['myident']['fqdn'];
469
				} else if (isset($tunnel['p1']['myident']['ufqdn'])) {
470
					$myidentt = "user_fqdn";
471
					$myident = $tunnel['p1']['myident']['ufqdn'];
472
 				}
473

    
474
				if (isset($tunnel['p1']['authentication_method'])) {
475
					$authmethod = $tunnel['p1']['authentication_method'];
476
				} else {$authmethod = 'pre_shared_key';}
477

    
478
				$certline = '';
479
				if ($authmethod == 'rsasig') {
480
					if ($tunnel['p1']['cert'] && $tunnel['p1']['private-key']) {
481
						$cert = base64_decode($tunnel['p1']['cert']);
482
						$private_key = base64_decode($tunnel['p1']['private-key']);
483
					} else {
484
						/* null certificate/key */
485
						$cert = '';
486
						$private_key = '';
487
					}
488

    
489
					if ($tunnel['p1']['peercert'])
490
						$peercert = base64_decode($tunnel['p1']['peercert']);
491
					else
492
						$peercert = '';
493

    
494
					$fd1 = fopen("{$g['varetc_path']}/server-mobile{$tunnelnumber}-signed.pem", "w");
495
					if (!$fd1) {
496
						printf("Error: cannot open server-mobile{$tunnelnumber}-signed.pem in vpn.\n");
497
						return 1;
498
					}
499
					chmod("{$g['varetc_path']}/server-mobile{$tunnelnumber}-signed.pem", 0600);
500
					fwrite($fd1, $cert);
501
					fclose($fd1);
502

    
503
					$fd1 = fopen("{$g['varetc_path']}/server-mobile{$tunnelnumber}-key.pem", "w");
504
					if (!$fd1) {
505
						printf("Error: cannot open server-mobile{$tunnelnumber}-key.pem in vpn.\n");
506
						return 1;
507
					}
508
					chmod("{$g['varetc_path']}/server-mobile{$tunnelnumber}-key.pem", 0600);
509
					fwrite($fd1, $private_key);
510
					fclose($fd1);
511

    
512
					$certline = "certificate_type x509 \"server-mobile{$tunnelnumber}-signed.pem\" \"server-mobile{$tunnelnumber}-key.pem\";";
513
				}
514
				$racoonconf .= <<<EOD
515
remote anonymous \{
516
	exchange_mode {$tunnel['p1']['mode']};
517
	my_identifier {$myidentt}{$myident};	
518
	{$nattline}
519
	{$certline}
520
	initial_contact on;
521
	dpd_delay 120;                   # DPD poll every 120 seconds
522
	ike_frag on;
523
	passive on;
524
	generate_policy on;
525
	support_proxy on;
526
	proposal_check obey;
527

    
528
	proposal \{
529
		encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
530
		hash_algorithm {$tunnel['p1']['hash-algorithm']};
531
		authentication_method {$authmethod};
532
		dh_group {$tunnel['p1']['dhgroup']};
533

    
534
EOD;
535
				if ($tunnel['p1']['lifetime'])
536
					$racoonconf .= "		lifetime time {$tunnel['p1']['lifetime']} secs;\n";
537

    
538
				$racoonconf .= "	}\n";
539

    
540
				if ($tunnel['p1']['lifetime'])
541
					$racoonconf .= "	lifetime time {$tunnel['p1']['lifetime']} secs;\n";
542

    
543
				$racoonconf .= "}\n\n";
544

    
545
				$p2ealgos = join(",", $tunnel['p2']['encryption-algorithm-option']);
546
				$p2halgos = join(",", $tunnel['p2']['hash-algorithm-option']);
547

    
548
				$racoonconf .= <<<EOD
549
sainfo anonymous \{
550
	encryption_algorithm {$p2ealgos};
551
	authentication_algorithm {$p2halgos};
552
	compression_algorithm deflate;
553

    
554
EOD;
555

    
556
				if ($tunnel['p2']['pfsgroup'])
557
					$racoonconf .= "	pfs_group {$tunnel['p2']['pfsgroup']};\n";
558

    
559
				if ($tunnel['p2']['lifetime'])
560
					$racoonconf .= "	lifetime time {$tunnel['p2']['lifetime']} secs;\n";
561

    
562
				$racoonconf .= "}\n\n";
563
			}
564

    
565
			fwrite($fd, $racoonconf);
566
			fclose($fd);
567

    
568
			/* generate psk.txt */
569
			$fd = fopen("{$g['varetc_path']}/psk.txt", "w");
570
			if (!$fd) {
571
				printf("Error: cannot open psk.txt in vpn_ipsec_configure().\n");
572
				return 1;
573
			}
574

    
575
			$pskconf = "";
576

    
577
			if (is_array($ipseccfg['tunnel'])) {
578
				foreach ($ipseccfg['tunnel'] as $tunnel) {
579
					if (isset($tunnel['disabled']))
580
						continue;
581
					$pskconf .= "{$tunnel['remote-gateway']}	 {$tunnel['p1']['pre-shared-key']}\n";
582
				}
583
			}
584

    
585
			/* add PSKs for mobile clients */
586
			if (is_array($ipseccfg['mobilekey'])) {
587
				foreach ($ipseccfg['mobilekey'] as $key) {
588
					$pskconf .= "{$key['ident']}	{$key['pre-shared-key']}\n";
589
				}
590
			}
591

    
592
			fwrite($fd, $pskconf);
593
			fclose($fd);
594
			chmod("{$g['varetc_path']}/psk.txt", 0600);
595

    
596
			if(is_process_running("racoon")) {
597
				/* We are already online, reload */
598
				mwexec("/usr/bin/killall -HUP racoon");
599
				/* flush SPD entries */
600
				mwexec("/usr/local/sbin/setkey -FP");
601
				mwexec("/usr/local/sbin/setkey -F");
602
				/* load SPD */
603
				mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf");
604
				sleep(1);
605
				/* We are already online, reload */
606
				mwexec("/usr/bin/killall -HUP racoon");
607
				sleep(1);
608
				mwexec("/usr/bin/killall -HUP racoon");
609
			} else {
610
				/* start racoon */
611
				mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf");
612
				/* flush SA + SPD entries */
613
				mwexec("/usr/local/sbin/setkey -FP");
614
				mwexec("/usr/local/sbin/setkey -F");
615
				/* load SPD */
616
				mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf");
617
				sleep(1);
618
				/* We are already online, reload */
619
				mwexec("/usr/bin/killall -HUP racoon");
620
				sleep(1);
621
				mwexec("/usr/bin/killall -HUP racoon");
622
			}
623
		}
624
	}
625

    
626
	vpn_ipsec_failover_configure();
627

    
628
	if (!$g['booting']) {
629
		/* reload the filter */
630
		touch("{$g["tmp_path"]}/filter_dirty");
631
	}
632

    
633
	if ($g['booting'])
634
		echo "done\n";
635

    
636
	return 0;
637
}
638

    
639
function vpn_pptpd_configure() {
640
	global $config, $g;
641

    
642
	$syscfg = $config['system'];
643
	$pptpdcfg = $config['pptpd'];
644

    
645
	if ($g['booting']) {
646
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
647
			return 0;
648

    
649
		echo "Configuring PPTP VPN service... ";
650
	} else {
651
		/* kill mpd */
652
		killbypid("{$g['varrun_path']}/mpd-vpn.pid");
653

    
654
		/* wait for process to die */
655
		sleep(3);
656

    
657
		if(is_process_running("mpd -b")) {
658
			killbypid("{$g['varrun_path']}/mpd-vpn.pid");
659
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
660
		}
661

    
662
		/* remove mpd.conf, if it exists */
663
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.conf");
664
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.links");
665
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.secret");
666
	}
667

    
668
	/* make sure mpd-vpn directory exists */
669
	if (!file_exists("{$g['varetc_path']}/mpd-vpn"))
670
		mkdir("{$g['varetc_path']}/mpd-vpn");
671

    
672
	switch ($pptpdcfg['mode']) {
673

    
674
		case 'server':
675

    
676
			/* write mpd.conf */
677
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.conf", "w");
678
			if (!$fd) {
679
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
680
				return 1;
681
			}
682

    
683
			$mpdconf = <<<EOD
684
pptpd:
685

    
686
EOD;
687

    
688
			for ($i = 0; $i < $g['n_pptp_units']; $i++) {
689
				$mpdconf .= "	load pt{$i}\n";
690
			}
691

    
692
			for ($i = 0; $i < $g['n_pptp_units']; $i++) {
693

    
694
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
695
				$ngif = "ng" . ($i+1);
696

    
697
				$mpdconf .= <<<EOD
698

    
699
pt{$i}:
700
	new -i {$ngif} pt{$i} pt{$i}
701
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
702
	load pts
703

    
704
EOD;
705
			}
706

    
707
			$mpdconf .= <<<EOD
708

    
709
pts:
710
	set iface disable on-demand
711
	set iface enable proxy-arp
712
	set iface enable tcpmssfix
713
	set iface idle 1800
714
	set iface up-script /usr/local/sbin/vpn-linkup
715
	set iface down-script /usr/local/sbin/vpn-linkdown
716
	set bundle enable multilink
717
	set bundle enable crypt-reqd
718
	set link yes acfcomp protocomp
719
	set link no pap chap
720
	set link enable chap-msv2
721
	set link mtu 1460
722
	set link keep-alive 10 60
723
	set ipcp yes vjcomp
724
	set bundle enable compression
725
	set ccp yes mppc
726
	set ccp yes mpp-e128
727
	set ccp yes mpp-stateless
728

    
729
EOD;
730

    
731
			if (!isset($pptpdcfg['req128'])) {
732
				$mpdconf .= <<<EOD
733
	set ccp yes mpp-e40
734
	set ccp yes mpp-e56
735

    
736
EOD;
737
			}
738
			if  (isset($pptpdcfg["wins"]))
739
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
740
			if (is_array($pptpdcfg['dnsserver']) && ($pptpdcfg['dnsserver'][0])) {
741
				$mpdconf .= "	set ipcp dns " . join(" ", $pptpdcfg['dnsserver']) . "\n";
742
			} else if (isset($config['dnsmasq']['enable'])) {
743
				$mpdconf .= "	set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
744
				if ($syscfg['dnsserver'][0])
745
					$mpdconf .= " " . $syscfg['dnsserver'][0];
746
				$mpdconf .= "\n";
747
			} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
748
				$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
749
			}
750

    
751
			if (isset($pptpdcfg['radius']['enable'])) {
752
				$mpdconf .= <<<EOD
753
	set radius server {$pptpdcfg['radius']['server']} "{$pptpdcfg['radius']['secret']}"
754
	set radius retries 3
755
	set radius timeout 10
756
	set bundle enable radius-auth
757
	set bundle disable radius-fallback
758

    
759
EOD;
760

    
761
				if (isset($pptpdcfg['radius']['accounting'])) {
762
					$mpdconf .= <<<EOD
763
	set bundle enable radius-acct
764

    
765
EOD;
766
				}
767
			}
768

    
769
			fwrite($fd, $mpdconf);
770
			fclose($fd);
771

    
772
			/* write mpd.links */
773
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.links", "w");
774
			if (!$fd) {
775
				printf("Error: cannot open mpd.links in vpn_pptpd_configure().\n");
776
				return 1;
777
			}
778

    
779
			$mpdlinks = "";
780

    
781
			for ($i = 0; $i < $g['n_pptp_units']; $i++) {
782
				$mpdlinks .= <<<EOD
783

    
784
pt{$i}:
785
	set link type pptp
786
	set pptp enable incoming
787
	set pptp disable originate
788
	set pptp disable windowing
789
	set pptp self 127.0.0.1
790

    
791
EOD;
792
			}
793

    
794
			fwrite($fd, $mpdlinks);
795
			fclose($fd);
796

    
797
			/* write mpd.secret */
798
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.secret", "w");
799
			if (!$fd) {
800
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
801
				return 1;
802
			}
803

    
804
			$mpdsecret = "";
805

    
806
			if (is_array($pptpdcfg['user'])) {
807
				foreach ($pptpdcfg['user'] as $user)
808
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
809
			}
810

    
811
			fwrite($fd, $mpdsecret);
812
			fclose($fd);
813
			chmod("{$g['varetc_path']}/mpd-vpn/mpd.secret", 0600);
814

    
815
			/* fire up mpd */
816
			mwexec("/usr/local/sbin/mpd -b -d {$g['varetc_path']}/mpd-vpn -p {$g['varrun_path']}/mpd-vpn.pid pptpd");
817

    
818
			break;
819

    
820
		case 'redir':
821
			break;
822
	}
823

    
824
	if (!$g['booting']) {
825
		/* reload the filter */
826
		filter_configure();
827
	}
828

    
829
	if ($g['booting'])
830
		echo "done\n";
831

    
832
	return 0;
833
}
834

    
835
function vpn_localnet_determine($adr, &$sa, &$sn) {
836
	global $config, $g;
837

    
838
	if (isset($adr)) {
839
		if ($adr['network']) {
840
			switch ($adr['network']) {
841
				case 'lan':
842
					$sn = $config['interfaces']['lan']['subnet'];
843
					$sa = gen_subnet($config['interfaces']['lan']['ipaddr'], $sn);
844
					break;
845
			}
846
		} else if ($adr['address']) {
847
			list($sa,$sn) = explode("/", $adr['address']);
848
			if (is_null($sn))
849
				$sn = 32;
850
		}
851
	} else {
852
		$sn = $config['interfaces']['lan']['subnet'];
853
		$sa = gen_subnet($config['interfaces']['lan']['ipaddr'], $sn);
854
	}
855
}
856

    
857
function vpn_endpoint_determine($tunnel, $curwanip) {
858
	global $g, $config;
859

    
860
	if(!$tunnel['interface']) {
861
		return null;
862
	}
863
	if(is_ipaddr($curwanip)) {
864
		if(preg_match("/^carp/i", $tunnel['interface'])) {
865
			$iface = $tunnel['interface'];
866
		} else {
867
			if($config['interfaces'][$tunnel['interface']]['ipaddr'] == "pppoe" OR 
868
				$config['interfaces'][$tunnel['interface']]['ipaddr'] == "pptp") {
869
				$iface = "ng0";
870
			} else {
871
				$iface = $config['interfaces'][$tunnel['interface']]['if'];
872
			}
873
		}
874
		$oc = $config['interfaces'][$tunnel['interface']];
875
		/* carp ips, etc */
876
		$ip = find_interface_ip($iface);
877
		if($ip)
878
			return $ip;
879

    
880
		if (isset($oc['enable']) && $oc['if']) {
881
			return $oc['ipaddr'];
882
		}
883
	}
884
	return null;
885
}
886

    
887
function vpn_pppoe_configure() {
888
	global $config, $g;
889

    
890
	$syscfg = $config['system'];
891
	$pppoecfg = $config['pppoe'];
892

    
893
	/* create directory if it does not exist */
894
	if(!is_dir("{$g['varetc_path']}/mpd-vpn"))
895
		mkdir("{$g['varetc_path']}/mpd-vpn");
896

    
897
	if ($g['booting']) {
898
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
899
			return 0;
900

    
901
		echo "Configuring PPPoE VPN service... ";
902
	}
903

    
904
	/* make sure mpd-vpn directory exists */
905
	if (!file_exists("{$g['varetc_path']}/mpd-vpn"))
906
		mkdir("{$g['varetc_path']}/mpd-vpn");
907

    
908
	switch ($pppoecfg['mode']) {
909

    
910
		case 'server':
911

    
912
			$pppoe_interface = filter_translate_type_to_real_interface($pppoecfg['interface']);
913

    
914
			/* write mpd.conf */
915
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.conf", "a");
916
			if (!$fd) {
917
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
918
				return 1;
919
			}
920
			$mpdconf = "\n\n";
921
			$mpdconf .= <<<EOD
922
pppoe:
923

    
924
EOD;
925

    
926
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
927
				$mpdconf .= "	load pppoe{$i}\n";
928
			}
929

    
930
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
931

    
932
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
933
				$ngif = "ng" . ($i+1);
934

    
935
				if(isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['enable'])) {
936
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
937
					$isssue_ip_type .="\n\tset ipcp yes radius-ip";
938
				} else {
939
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
940
				}
941

    
942
				$mpdconf .= <<<EOD
943

    
944
pppoe{$i}:
945
	new -i {$ngif} pppoe{$i} pppoe{$i}
946
	{$isssue_ip_type}
947
	load pppoe_standart
948

    
949
EOD;
950
			}
951

    
952
			$mpdconf .= <<<EOD
953

    
954
pppoe_standart:
955
	set link type pppoe
956
	set pppoe iface {$pppoe_interface}
957
	set pppoe service "*"
958
	set pppoe disable originate
959
	set pppoe enable incoming
960
	set bundle no multilink
961
	set bundle enable compression
962
	set bundle max-logins 1
963
	set iface idle 0
964
	set iface disable on-demand
965
	set iface disable proxy-arp
966
	set iface enable tcpmssfix
967
	set iface mtu 1500
968
	set link no pap chap
969
	set link enable chap
970
	set link keep-alive 60 180
971
	set ipcp yes vjcomp
972
	set ipcp no vjcomp
973
	set link max-redial -1
974
	set link mtu 1492
975
	set link mru 1492
976
	set ccp yes mpp-e40
977
	set ccp yes mpp-e128
978
	set ccp yes mpp-stateless
979
	set link latency 1
980
	#set ipcp dns 10.10.1.3
981
	#set bundle accept encryption
982

    
983
EOD;
984

    
985
			if (isset($config['dnsmasq']['enable'])) {
986
				$mpdconf .= "	set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
987
				if ($syscfg['dnsserver'][0])
988
					$mpdconf .= " " . $syscfg['dnsserver'][0];
989
				$mpdconf .= "\n";
990
			} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
991
				$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
992
			}
993

    
994
			if (isset($pppoecfg['radius']['enable'])) {
995
				$mpdconf .= <<<EOD
996
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
997
	set radius retries 3
998
	set radius timeout 10
999
	set bundle enable radius-auth
1000
	set bundle disable radius-fallback
1001

    
1002
EOD;
1003

    
1004
				if (isset($pppoecfg['radius']['accounting'])) {
1005
					$mpdconf .= <<<EOD
1006
	set bundle enable radius-acct
1007
	set radius acct-update 300
1008
EOD;
1009
				}
1010
			}
1011

    
1012
			fwrite($fd, $mpdconf);
1013
			fclose($fd);
1014

    
1015
			/* write mpd.links */
1016
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.links", "a");
1017
			if (!$fd) {
1018
				printf("Error: cannot open mpd.links in vpn_pppoe_configure().\n");
1019
				return 1;
1020
			}
1021

    
1022
			$mpdlinks = "";
1023

    
1024
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1025
				$mpdlinks .= <<<EOD
1026

    
1027
pppoe:
1028
	set link type pppoe
1029
	set pppoe iface {$pppoe_interface}
1030

    
1031
EOD;
1032
			}
1033

    
1034
			fwrite($fd, $mpdlinks);
1035
			fclose($fd);
1036

    
1037
			/* write mpd.secret */
1038
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.secret", "a");
1039
			if (!$fd) {
1040
				printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1041
				return 1;
1042
			}
1043

    
1044
			$mpdsecret = "\n\n";
1045

    
1046
			if (is_array($pppoecfg['user'])) {
1047
				foreach ($pppoecfg['user'] as $user)
1048
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1049
			}
1050

    
1051
			fwrite($fd, $mpdsecret);
1052
			fclose($fd);
1053
			chmod("{$g['varetc_path']}/mpd-vpn/mpd.secret", 0600);
1054

    
1055
			/* fire up mpd */
1056
			mwexec("/usr/local/sbin/mpd -b -d {$g['varetc_path']}/mpd-vpn -p {$g['varrun_path']}/mpd-vpn.pid pppoe");
1057

    
1058
			break;
1059

    
1060
		case 'redir':
1061
			break;
1062
	}
1063

    
1064
	touch("{$g["tmp_path"]}/filter_dirty");
1065

    
1066
	if ($g['booting'])
1067
		echo "done\n";
1068

    
1069
	return 0;
1070
}
1071

    
1072
/* Forcefully restart IPSEC
1073
 * This is required for when dynamic interfaces reload
1074
 * For all other occasions the normal vpn_ipsec_configure()
1075
 * will gracefully reload the settings without restarting
1076
 */
1077
function vpn_ipsec_force_reload() {
1078
	global $config;
1079
	global $g;
1080

    
1081
	$ipseccfg = $config['ipsec'];
1082

    
1083
	/* kill any ipsec communications regardless when we are invoked */
1084
	mwexec("/sbin/ifconfig enc0 down");
1085
	mwexec("/sbin/ifconfig enc0 destroy");
1086

    
1087
	/* kill racoon */
1088
	mwexec("/usr/bin/killall racoon");
1089

    
1090
	/* wait for process to die */
1091
	sleep(4);
1092

    
1093
	/* send a SIGKILL to be sure */
1094
	sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
1095

    
1096
	/* wait for flushing to finish */
1097
	sleep(1);
1098

    
1099
	/* if ipsec is enabled, start up again */
1100
	if (isset($ipseccfg['enable'])) {
1101
		log_error("Forcefully reloading IPSEC racoon daemon");
1102
		vpn_ipsec_configure();
1103
	}
1104

    
1105
}
1106

    
1107
?>
(22-22/27)