Project

General

Profile

Download (30.2 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("/sbin/setkey -F");
115
			//mwexec("/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("/sbin/setkey -FP");
155
		mwexec("/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
					$parentinterface = link_carp_interface_to_parent($tunnel['interface']);
248
					if($parentinterface <> "wan") {
249
						/* add endpoint routes to correct gateway on interface */
250
						if(interface_has_gateway($parentinterface)) {
251
							$gatewayip = get_interface_gateway("$parentinterface");
252
							$interfaceip = $config['interfaces'][$parentinterface]['ipaddr'];
253
							$subnet_bits = $config['interfaces'][$parentinterface]['subnet'];
254
							$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
255
							/* if the remote gateway is in the local subnet, then don't add a route */
256
							if(! ip_in_subnet($tunnel['remote-gateway'], "{$subnet_ip}/{$subnet_bits}")) {
257
								if(is_ipaddr($gatewayip)) {
258
									log_error("IPSEC interface is not WAN but {$tunnel['interface']}, adding static route for VPN endpoint {$tunnel['remote-gateway']} via {$gatewayip}");
259
									mwexec("/sbin/route delete -host {$tunnel['remote-gateway']};/sbin/route add -host {$tunnel['remote-gateway']} {$gatewayip}");
260
								}
261
							}
262
						}
263
					} else {
264
						mwexec("/sbin/route delete -host {$tunnel['remote-gateway']}");
265
					}
266
				}
267

    
268
				fwrite($fd, $spdconf);
269
				fclose($fd);
270
			}
271

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

    
279
			$racoonconf = "";
280

    
281
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
282
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
283

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

    
305
			$tunnelnumber = 0;
306
			if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel']))
307
				foreach ($ipseccfg['tunnel'] as $tunnel) {
308

    
309
				++$tunnelnumber;
310

    
311
				if (isset($tunnel['disabled']))
312
					continue;
313

    
314
				$ep = vpn_endpoint_determine($tunnel, $curwanip);
315
				if (!$ep)
316
					continue;
317

    
318
				vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
319

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

    
337
				if (!($myidentt == "asn1dn" && $myident == "")) {
338
					$myident = " \"".$myident."\"";
339
				}
340
				
341
				$nattline = '';
342
				if (isset($tunnel['natt'])) {
343
					$nattline = "nat_traversal on;";
344
				}
345

    
346
				if (isset($tunnel['p1']['authentication_method'])) {
347
					$authmethod = $tunnel['p1']['authentication_method'];
348
				} else {$authmethod = 'pre_shared_key';}
349

    
350
				$certline = '';
351

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

    
362
					if ($tunnel['p1']['peercert'])
363
						$peercert = base64_decode($tunnel['p1']['peercert']);
364
					else
365
						$peercert = '';
366

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

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

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

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

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

    
414
	proposal \{
415
		encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
416
		hash_algorithm {$tunnel['p1']['hash-algorithm']};
417
		authentication_method {$authmethod};
418
		dh_group {$tunnel['p1']['dhgroup']};
419

    
420
EOD;
421
				if ($tunnel['p1']['lifetime'])
422
					$racoonconf .= "		lifetime time {$tunnel['p1']['lifetime']} secs;\n";
423

    
424
				$racoonconf .= "	}\n";
425

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

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

    
431
				$p2ealgos = join(",", $tunnel['p2']['encryption-algorithm-option']);
432
				$p2halgos = join(",", $tunnel['p2']['hash-algorithm-option']);
433

    
434
				$racoonconf .= <<<EOD
435
sainfo address {$sa}/{$sn} any address {$tunnel['remote-subnet']} any \{
436
	encryption_algorithm {$p2ealgos};
437
	authentication_algorithm {$p2halgos};
438
	compression_algorithm deflate;
439

    
440
EOD;
441

    
442
				if ($tunnel['p2']['pfsgroup'])
443
					$racoonconf .= "	pfs_group {$tunnel['p2']['pfsgroup']};\n";
444

    
445
				if ($tunnel['p2']['lifetime'])
446
					$racoonconf .= "	lifetime time {$tunnel['p2']['lifetime']} secs;\n";
447

    
448
				$racoonconf .= "}\n\n";
449
			}
450

    
451
			/* mobile clients? */
452
			if (isset($ipseccfg['mobileclients']['enable'])) {
453

    
454
				$tunnel = $ipseccfg['mobileclients'];
455

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

    
470
				if (isset($tunnel['p1']['authentication_method'])) {
471
					$authmethod = $tunnel['p1']['authentication_method'];
472
				} else {$authmethod = 'pre_shared_key';}
473

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

    
485
					if ($tunnel['p1']['peercert'])
486
						$peercert = base64_decode($tunnel['p1']['peercert']);
487
					else
488
						$peercert = '';
489

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

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

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

    
524
	proposal \{
525
		encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
526
		hash_algorithm {$tunnel['p1']['hash-algorithm']};
527
		authentication_method {$authmethod};
528
		dh_group {$tunnel['p1']['dhgroup']};
529

    
530
EOD;
531
				if ($tunnel['p1']['lifetime'])
532
					$racoonconf .= "		lifetime time {$tunnel['p1']['lifetime']} secs;\n";
533

    
534
				$racoonconf .= "	}\n";
535

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

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

    
541
				$p2ealgos = join(",", $tunnel['p2']['encryption-algorithm-option']);
542
				$p2halgos = join(",", $tunnel['p2']['hash-algorithm-option']);
543

    
544
				$racoonconf .= <<<EOD
545
sainfo anonymous \{
546
	encryption_algorithm {$p2ealgos};
547
	authentication_algorithm {$p2halgos};
548
	compression_algorithm deflate;
549

    
550
EOD;
551

    
552
				if ($tunnel['p2']['pfsgroup'])
553
					$racoonconf .= "	pfs_group {$tunnel['p2']['pfsgroup']};\n";
554

    
555
				if ($tunnel['p2']['lifetime'])
556
					$racoonconf .= "	lifetime time {$tunnel['p2']['lifetime']} secs;\n";
557

    
558
				$racoonconf .= "}\n\n";
559
			}
560

    
561
			fwrite($fd, $racoonconf);
562
			fclose($fd);
563

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

    
571
			$pskconf = "";
572

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

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

    
588
			fwrite($fd, $pskconf);
589
			fclose($fd);
590
			chmod("{$g['varetc_path']}/psk.txt", 0600);
591

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

    
622
	vpn_ipsec_failover_configure();
623

    
624
	if (!$g['booting']) {
625
		/* reload the filter */
626
		touch("{$g["tmp_path"]}/filter_dirty");
627
	}
628

    
629
	if ($g['booting'])
630
		echo "done\n";
631

    
632
	return 0;
633
}
634

    
635
function vpn_pptpd_configure() {
636
	global $config, $g;
637

    
638
	$syscfg = $config['system'];
639
	$pptpdcfg = $config['pptpd'];
640

    
641
	if ($g['booting']) {
642
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
643
			return 0;
644

    
645
		echo "Configuring PPTP VPN service... ";
646
	} else {
647
		/* kill mpd */
648
		killbypid("{$g['varrun_path']}/mpd-vpn.pid");
649

    
650
		/* wait for process to die */
651
		sleep(3);
652

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

    
658
		/* remove mpd.conf, if it exists */
659
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.conf");
660
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.links");
661
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.secret");
662
	}
663

    
664
	/* make sure mpd-vpn directory exists */
665
	if (!file_exists("{$g['varetc_path']}/mpd-vpn"))
666
		mkdir("{$g['varetc_path']}/mpd-vpn");
667

    
668
	switch ($pptpdcfg['mode']) {
669

    
670
		case 'server':
671

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

    
679
			$mpdconf = <<<EOD
680
pptpd:
681

    
682
EOD;
683

    
684
			for ($i = 0; $i < $g['n_pptp_units']; $i++) {
685
				$mpdconf .= "	load pt{$i}\n";
686
			}
687

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

    
690
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
691
				$ngif = "ng" . ($i+1);
692

    
693
				$mpdconf .= <<<EOD
694

    
695
pt{$i}:
696
	new -i {$ngif} pt{$i} pt{$i}
697
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
698
	load pts
699

    
700
EOD;
701
			}
702

    
703
			$mpdconf .= <<<EOD
704

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

    
725
EOD;
726

    
727
			if (!isset($pptpdcfg['req128'])) {
728
				$mpdconf .= <<<EOD
729
	set ccp yes mpp-e40
730
	set ccp yes mpp-e56
731

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

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

    
755
EOD;
756

    
757
				if (isset($pptpdcfg['radius']['accounting'])) {
758
					$mpdconf .= <<<EOD
759
	set bundle enable radius-acct
760

    
761
EOD;
762
				}
763
			}
764

    
765
			fwrite($fd, $mpdconf);
766
			fclose($fd);
767

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

    
775
			$mpdlinks = "";
776

    
777
			for ($i = 0; $i < $g['n_pptp_units']; $i++) {
778
				$mpdlinks .= <<<EOD
779

    
780
pt{$i}:
781
	set link type pptp
782
	set pptp enable incoming
783
	set pptp disable originate
784
	set pptp disable windowing
785
	set pptp self 127.0.0.1
786

    
787
EOD;
788
			}
789

    
790
			fwrite($fd, $mpdlinks);
791
			fclose($fd);
792

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

    
800
			$mpdsecret = "";
801

    
802
			if (is_array($pptpdcfg['user'])) {
803
				foreach ($pptpdcfg['user'] as $user)
804
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
805
			}
806

    
807
			fwrite($fd, $mpdsecret);
808
			fclose($fd);
809
			chmod("{$g['varetc_path']}/mpd-vpn/mpd.secret", 0600);
810

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

    
814
			break;
815

    
816
		case 'redir':
817
			break;
818
	}
819

    
820
	if (!$g['booting']) {
821
		/* reload the filter */
822
		filter_configure();
823
	}
824

    
825
	if ($g['booting'])
826
		echo "done\n";
827

    
828
	return 0;
829
}
830

    
831
function vpn_localnet_determine($adr, &$sa, &$sn) {
832
	global $config, $g;
833

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

    
853
function vpn_endpoint_determine($tunnel, $curwanip) {
854

    
855
	global $g, $config;
856

    
857
	if ((!$tunnel['interface']) || ($tunnel['interface'] == "wan")) {
858
		if ($curwanip)
859
			return $curwanip;
860
		else
861
			return null;
862
	} else if ($tunnel['interface'] == "lan") {
863
		return $config['interfaces']['lan']['ipaddr'];
864
	} else {
865
		$oc = $config['interfaces'][$tunnel['interface']];
866
		/* carp ips, etc */
867
		$ip = find_interface_ip($tunnel['interface']);
868
		if($ip) 
869
			return $ip;
870

    
871
		if (isset($oc['enable']) && $oc['if']) {
872
			return $oc['ipaddr'];
873
		}
874
	}
875

    
876
	return null;
877
}
878

    
879
function vpn_pppoe_configure() {
880
	global $config, $g;
881

    
882
	$syscfg = $config['system'];
883
	$pppoecfg = $config['pppoe'];
884

    
885
	/* create directory if it does not exist */
886
	if(!is_dir("{$g['varetc_path']}/mpd-vpn"))
887
		mkdir("{$g['varetc_path']}/mpd-vpn");
888

    
889
	if ($g['booting']) {
890
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
891
			return 0;
892

    
893
		echo "Configuring PPPoE VPN service... ";
894
	}
895

    
896
	/* make sure mpd-vpn directory exists */
897
	if (!file_exists("{$g['varetc_path']}/mpd-vpn"))
898
		mkdir("{$g['varetc_path']}/mpd-vpn");
899

    
900
	switch ($pppoecfg['mode']) {
901

    
902
		case 'server':
903

    
904
			$pppoe_interface = filter_translate_type_to_real_interface($pppoecfg['interface']);
905

    
906
			/* write mpd.conf */
907
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.conf", "a");
908
			if (!$fd) {
909
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
910
				return 1;
911
			}
912
			$mpdconf = "\n\n";
913
			$mpdconf .= <<<EOD
914
pppoe:
915

    
916
EOD;
917

    
918
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
919
				$mpdconf .= "	load pppoe{$i}\n";
920
			}
921

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

    
924
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
925
				$ngif = "ng" . ($i+1);
926

    
927
				if(isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['enable'])) {
928
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
929
					$isssue_ip_type .="\n\tset ipcp yes radius-ip";
930
				} else {
931
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
932
				}
933

    
934
				$mpdconf .= <<<EOD
935

    
936
pppoe{$i}:
937
	new -i {$ngif} pppoe{$i} pppoe{$i}
938
	{$isssue_ip_type}
939
	load pppoe_standart
940

    
941
EOD;
942
			}
943

    
944
			$mpdconf .= <<<EOD
945

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

    
975
EOD;
976

    
977
			if (isset($config['dnsmasq']['enable'])) {
978
				$mpdconf .= "	set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
979
				if ($syscfg['dnsserver'][0])
980
					$mpdconf .= " " . $syscfg['dnsserver'][0];
981
				$mpdconf .= "\n";
982
			} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
983
				$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
984
			}
985

    
986
			if (isset($pppoecfg['radius']['enable'])) {
987
				$mpdconf .= <<<EOD
988
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
989
	set radius retries 3
990
	set radius timeout 10
991
	set bundle enable radius-auth
992
	set bundle disable radius-fallback
993

    
994
EOD;
995

    
996
				if (isset($pppoecfg['radius']['accounting'])) {
997
					$mpdconf .= <<<EOD
998
	set bundle enable radius-acct
999
	set radius acct-update 300
1000
EOD;
1001
				}
1002
			}
1003

    
1004
			fwrite($fd, $mpdconf);
1005
			fclose($fd);
1006

    
1007
			/* write mpd.links */
1008
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.links", "a");
1009
			if (!$fd) {
1010
				printf("Error: cannot open mpd.links in vpn_pppoe_configure().\n");
1011
				return 1;
1012
			}
1013

    
1014
			$mpdlinks = "";
1015

    
1016
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1017
				$mpdlinks .= <<<EOD
1018

    
1019
pppoe:
1020
	set link type pppoe
1021
	set pppoe iface {$pppoe_interface}
1022

    
1023
EOD;
1024
			}
1025

    
1026
			fwrite($fd, $mpdlinks);
1027
			fclose($fd);
1028

    
1029
			/* write mpd.secret */
1030
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.secret", "a");
1031
			if (!$fd) {
1032
				printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1033
				return 1;
1034
			}
1035

    
1036
			$mpdsecret = "\n\n";
1037

    
1038
			if (is_array($pppoecfg['user'])) {
1039
				foreach ($pppoecfg['user'] as $user)
1040
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1041
			}
1042

    
1043
			fwrite($fd, $mpdsecret);
1044
			fclose($fd);
1045
			chmod("{$g['varetc_path']}/mpd-vpn/mpd.secret", 0600);
1046

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

    
1050
			break;
1051

    
1052
		case 'redir':
1053
			break;
1054
	}
1055

    
1056
	touch("{$g["tmp_path"]}/filter_dirty");
1057

    
1058
	if ($g['booting'])
1059
		echo "done\n";
1060

    
1061
	return 0;
1062
}
1063

    
1064
/* Forcefully restart IPSEC
1065
 * This is required for when dynamic interfaces reload
1066
 * For all other occasions the normal vpn_ipsec_configure()
1067
 * will gracefully reload the settings without restarting
1068
 */
1069
function vpn_ipsec_force_reload() {
1070
	global $config;
1071
	global $g;
1072

    
1073
	$ipseccfg = $config['ipsec'];
1074

    
1075
	/* kill any ipsec communications regardless when we are invoked */
1076
	mwexec("/sbin/ifconfig enc0 down");
1077
	mwexec("/sbin/ifconfig enc0 destroy");
1078

    
1079
	/* kill racoon */
1080
	mwexec("/usr/bin/killall racoon");
1081

    
1082
	/* wait for process to die */
1083
	sleep(4);
1084

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

    
1088
	/* wait for flushing to finish */
1089
	sleep(1);
1090

    
1091
	/* if ipsec is enabled, start up again */
1092
	if (isset($ipseccfg['enable'])) {
1093
		log_error("Forcefully reloading IPSEC racoon daemon");
1094
		vpn_ipsec_configure();
1095
	}
1096

    
1097
}
1098

    
1099
?>
(22-22/27)