Project

General

Profile

Download (49.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	openvpn.inc part of pfSense
4

    
5
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
6
	All rights reserved.
7

    
8
	Copyright (C) 2006  Fernando Lemos
9
	All rights reserved.
10

    
11
	This file was rewritten from scratch by Fernando Lemos but
12
	*MIGHT* contain code previously written by:
13

    
14
	Copyright (C) 2005 Peter Allgeyer <allgeyer_AT_web.de>
15
	All rights reserved.
16

    
17
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
18
	All rights reserved.
19

    
20
	Redistribution and use in source and binary forms, with or without
21
	modification, are permitted provided that the following conditions are met:
22

    
23
	1. Redistributions of source code must retain the above copyright notices,
24
	   this list of conditions and the following disclaimer.
25

    
26
	2. Redistributions in binary form must reproduce the above copyright
27
	   notices, this list of conditions and the following disclaimer in the
28
	   documentation and/or other materials provided with the distribution.
29

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

    
41

    
42
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/bin/openssl	/sbin/ifconfig
43
	pfSense_MODULE:	openvpn
44

    
45
*/
46
require_once('config.inc');
47
require_once("certs.inc");
48
require_once('pfsense-utils.inc');
49
require_once("auth.inc");
50

    
51
global $openvpn_prots;
52
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
53

    
54
global $openvpn_dev_mode;
55
$openvpn_dev_mode = array("tun", "tap");
56

    
57
global $openvpn_verbosity_level;
58
$openvpn_verbosity_level = array(
59
	0 =>	"none",
60
	1 =>	"default",
61
	2 =>	"2",
62
	3 =>	"3 (recommended)",
63
	4 =>	"4",
64
	5 => 	"5",
65
	6 => 	"6",
66
	7 => 	"7",
67
	8 => 	"8",
68
	9 => 	"9",
69
	10 => 	"10",
70
	11 => 	"11"
71
);
72

    
73
/*
74
 * The User Auth mode below is disabled because
75
 * OpenVPN erroneously requires that we provide
76
 * a CA configuration parameter. In this mode,
77
 * clients don't send a certificate so there is
78
 * no need for a CA. If we require that admins
79
 * provide one in the pfSense UI due to a bogus
80
 * requirement imposed by OpenVPN, it could be
81
 * considered very confusing ( I know I was ).
82
 *
83
 * -mgrooms
84
 */
85

    
86
global $openvpn_dh_lengths;
87
$openvpn_dh_lengths = array(
88
	1024, 2048, 4096);
89

    
90
global $openvpn_cert_depths;
91
$openvpn_cert_depths = array(
92
	1 => "One (Client+Server)",
93
	2 => "Two (Client+Intermediate+Server)",
94
	3 => "Three (Client+2xIntermediate+Server)",
95
	4 => "Four (Client+3xIntermediate+Server)",
96
	5 => "Five (Client+4xIntermediate+Server)"
97
);
98

    
99
global $openvpn_server_modes;
100
$openvpn_server_modes = array(
101
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
102
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
103
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
104
	'server_user' => gettext("Remote Access ( User Auth )"),
105
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
106

    
107
global $openvpn_tls_server_modes;
108
$openvpn_tls_server_modes = array('p2p_tls', 'server_tls', 'server_user', 'server_tls_user');
109

    
110
global $openvpn_client_modes;
111
$openvpn_client_modes = array(
112
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
113
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"));
114

    
115
global $openvpn_compression_modes;
116
$openvpn_compression_modes = array(
117
	'' => gettext("No Preference"),
118
	'no' => gettext("Disabled - No Compression"),
119
	'adaptive' => gettext("Enabled with Adaptive Compression"),
120
	'yes' => gettext("Enabled without Adaptive Compression"));
121

    
122
global $openvpn_topologies;
123
$openvpn_topologies = array(
124
	'subnet' => gettext("Subnet -- One IP address per client in a common subnet"),
125
	'net30' => gettext("net30 -- Isolated /30 network per client")
126
//	'p2p => gettext("Peer to Peer -- One IP address per client peer-to-peer style. Does not work on Windows.")
127
);
128

    
129
function openvpn_build_mode_list() {
130
	global $openvpn_server_modes;
131

    
132
	$list = array();
133

    
134
	foreach ($openvpn_server_modes as $name => $desc)
135
		$list[$name] = $desc;
136

    
137
	return($list);
138
}
139

    
140
function openvpn_build_if_list() {
141
	$list = array();
142

    
143
	$interfaces = get_configured_interface_with_descr();
144
	$carplist = get_configured_carp_interface_list();
145

    
146
	foreach ($carplist as $cif => $carpip)
147
		$interfaces[$cif.'|'.$carpip] = $carpip." (".get_vip_descr($carpip).")";
148

    
149
	$aliaslist = get_configured_ip_aliases_list();
150

    
151
	foreach ($aliaslist as $aliasip => $aliasif)
152
		$interfaces[$aliasif.'|'.$aliasip] = $aliasip." (".get_vip_descr($aliasip).")";
153

    
154
	$grouplist = return_gateway_groups_array();
155

    
156
	foreach ($grouplist as $name => $group) {
157
		if($group['ipprotocol'] != inet)
158
			continue;
159

    
160
		if($group[0]['vip'] != "")
161
			$vipif = $group[0]['vip'];
162
		else
163
			$vipif = $group[0]['int'];
164

    
165
		$interfaces[$name] = "GW Group {$name}";
166
	}
167

    
168
	$interfaces['lo0'] = "Localhost";
169
	$interfaces['any'] = "any";
170

    
171
	foreach ($interfaces as $iface => $ifacename)
172
	   $list[$iface] = $ifacename;
173

    
174
	return($list);
175
}
176

    
177
function openvpn_build_crl_list() {
178
	global $a_crl;
179

    
180
	$list = array('' => 'None');
181

    
182
	foreach ($a_crl as $crl) {
183
		$caname = "";
184
		$ca = lookup_ca($crl['caref']);
185

    
186
		if ($ca)
187
			$caname = " (CA: {$ca['descr']})";
188

    
189
		$list[$crl['refid']] = $crl['descr'] . $caname;
190
	}
191

    
192
	return($list);
193
}
194

    
195
function openvpn_build_cert_list($include_none = false) {
196
	global $a_cert;
197

    
198
	if ($include_none) {
199
		$list = array('' => 'None (Username and/or Password required)');
200
	} else {
201
		$list = array();
202
	}
203

    
204
	foreach ($a_cert as $cert) {
205
		$caname = "";
206
		$inuse = "";
207
		$revoked = "";
208
		$ca = lookup_ca($cert['caref']);
209

    
210
		if ($ca) {
211
			$caname = " (CA: {$ca['descr']})";
212
		}
213

    
214
		if ($pconfig['certref'] == $cert['refid']) {
215
			$selected = "selected";
216
		}
217

    
218
		if (cert_in_use($cert['refid'])) {
219
			$inuse = " *In Use";
220
		}
221

    
222
		if (is_cert_revoked($cert)) {
223
			$revoked = " *Revoked";
224
		}
225

    
226
		$list[$cert['refid']] = $cert['descr'] . $caname . $inuse . $revoked;
227
	}
228

    
229
	return($list);
230
}
231

    
232
function openvpn_build_bridge_list() {
233
	$list = array();
234

    
235
	$serverbridge_interface['none'] = "none";
236
	$serverbridge_interface = array_merge($serverbridge_interface, get_configured_interface_with_descr());
237
	$carplist = get_configured_carp_interface_list();
238

    
239
	foreach ($carplist as $cif => $carpip)
240
		$serverbridge_interface[$cif.'|'.$carpip] = $carpip." (".get_vip_descr($carpip).")";
241

    
242
	$aliaslist = get_configured_ip_aliases_list();
243

    
244
	foreach ($aliaslist as $aliasip => $aliasif)
245
		$serverbridge_interface[$aliasif.'|'.$aliasip] = $aliasip." (".get_vip_descr($aliasip).")";
246

    
247
	foreach ($serverbridge_interface as $iface => $ifacename)
248
		$list[$iface] = htmlspecialchars($ifacename);
249

    
250
	return($list);
251
}
252

    
253
function openvpn_create_key() {
254

    
255
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
256
	if (!$fp) {
257
		return false;
258
	}
259

    
260
	$rslt = stream_get_contents($fp);
261
	pclose($fp);
262

    
263
	return $rslt;
264
}
265

    
266
function openvpn_create_dhparams($bits) {
267

    
268
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
269
	if (!$fp) {
270
		return false;
271
	}
272

    
273
	$rslt = stream_get_contents($fp);
274
	pclose($fp);
275

    
276
	return $rslt;
277
}
278

    
279
function openvpn_vpnid_used($vpnid) {
280
	global $config;
281

    
282
	if (is_array($config['openvpn']['openvpn-server'])) {
283
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
284
			if ($vpnid == $settings['vpnid']) {
285
				return true;
286
			}
287
		}
288
	}
289

    
290
	if (is_array($config['openvpn']['openvpn-client'])) {
291
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
292
			if ($vpnid == $settings['vpnid']) {
293
				return true;
294
			}
295
		}
296
	}
297

    
298
	return false;
299
}
300

    
301
function openvpn_vpnid_next() {
302

    
303
	$vpnid = 1;
304
	while (openvpn_vpnid_used($vpnid)) {
305
		$vpnid++;
306
	}
307

    
308
	return $vpnid;
309
}
310

    
311
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
312
	global $config;
313

    
314
	if (is_array($config['openvpn']['openvpn-server'])) {
315
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
316
			if (isset($settings['disable'])) {
317
				continue;
318
			}
319

    
320
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
321
				continue;
322
			}
323

    
324
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
325
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
326
				return $settings['vpnid'];
327
			}
328
		}
329
	}
330

    
331
	if (is_array($config['openvpn']['openvpn-client'])) {
332
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
333
			if (isset($settings['disable'])) {
334
				continue;
335
			}
336

    
337
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
338
				continue;
339
			}
340

    
341
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
342
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
343
				return $settings['vpnid'];
344
			}
345
		}
346
	}
347

    
348
	return 0;
349
}
350

    
351
function openvpn_port_next($prot, $interface = "wan") {
352

    
353
	$port = 1194;
354
	while (openvpn_port_used($prot, $interface, $port)) {
355
		$port++;
356
	}
357
	while (openvpn_port_used($prot, "any", $port)) {
358
		$port++;
359
	}
360

    
361
	return $port;
362
}
363

    
364
function openvpn_get_cipherlist() {
365

    
366
	$ciphers = array();
367
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
368
	$cipher_lines = explode("\n", trim($cipher_out));
369
	sort($cipher_lines);
370
	foreach ($cipher_lines as $line) {
371
		$words = explode(' ', $line);
372
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
373
	}
374
	$ciphers["none"] = gettext("None (No Encryption)");
375
	return $ciphers;
376
}
377

    
378
function openvpn_get_digestlist() {
379

    
380
	$digests = array();
381
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
382
	$digest_lines = explode("\n", trim($digest_out));
383
	sort($digest_lines);
384
	foreach ($digest_lines as $line) {
385
		$words = explode(' ', $line);
386
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
387
	}
388
	$digests["none"] = gettext("None (No Authentication)");
389
	return $digests;
390
}
391

    
392
function openvpn_get_engines() {
393
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
394
	exec("/usr/bin/openssl engine -t -c", $openssl_engine_output);
395
	$openssl_engine_output = implode("\n", $openssl_engine_output);
396
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
397
	$openssl_engine_output = explode("\n", $openssl_engine_output);
398

    
399
	foreach ($openssl_engine_output as $oeo) {
400
		$keep = true;
401
		$details = explode("|", $oeo);
402
		$engine = array_shift($details);
403
		$linematch = array();
404
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
405
		foreach ($details as $dt) {
406
			if (strpos($dt, "unavailable") !== FALSE) {
407
				$keep = false;
408
			}
409
			if (strpos($dt, "available") !== FALSE) {
410
				continue;
411
			}
412
			if (strpos($dt, "[") !== FALSE) {
413
				$ciphers = trim($dt, "[]");
414
			}
415
		}
416
		if (!empty($ciphers)) {
417
			$ciphers = " - " . $ciphers;
418
		}
419
		if (strlen($ciphers) > 60) {
420
			$ciphers = substr($ciphers, 0, 60) . " ... ";
421
		}
422
		if ($keep) {
423
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
424
		}
425
	}
426
	return $openssl_engines;
427
}
428

    
429
function openvpn_validate_engine($engine) {
430
	$engines = openvpn_get_engines();
431
	return array_key_exists($engine, $engines);
432
}
433

    
434
function openvpn_validate_host($value, $name) {
435
	$value = trim($value);
436
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value))) {
437
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
438
	}
439
	return false;
440
}
441

    
442
function openvpn_validate_port($value, $name) {
443
	$value = trim($value);
444
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535)) {
445
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
446
	}
447
	return false;
448
}
449

    
450
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
451
	$value = trim($value);
452
	$error = false;
453
	if (empty($value)) {
454
		return false;
455
	}
456
	$networks = explode(',', $value);
457

    
458
	if (!$multiple && (count($networks) > 1)) {
459
		return sprintf(gettext("The field '%s' must contain a single valid %s CIDR range."), $name, $ipproto);
460
	}
461

    
462
	foreach ($networks as $network) {
463
		if ($ipproto == "ipv4") {
464
			$error = !openvpn_validate_cidr_ipv4($network);
465
		} else {
466
			$error = !openvpn_validate_cidr_ipv6($network);
467
		}
468
		if ($error) {
469
			break;
470
		}
471
	}
472

    
473
	if ($error) {
474
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
475
	} else {
476
		return false;
477
	}
478
}
479

    
480
function openvpn_validate_cidr_ipv4($value) {
481
	$value = trim($value);
482
	if (!empty($value)) {
483
		list($ip, $mask) = explode('/', $value);
484
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0)) {
485
			return false;
486
		}
487
	}
488
	return true;
489
}
490

    
491
function openvpn_validate_cidr_ipv6($value) {
492
	$value = trim($value);
493
	if (!empty($value)) {
494
		list($ipv6, $prefix) = explode('/', $value);
495
		if (empty($prefix)) {
496
			$prefix = "128";
497
		}
498
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0)) {
499
			return false;
500
		}
501
	}
502
	return true;
503
}
504

    
505
function openvpn_add_dhcpopts(& $settings, & $conf) {
506

    
507
	if (!empty($settings['dns_domain'])) {
508
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
509
	}
510

    
511
	if (!empty($settings['dns_server1'])) {
512
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
513
	}
514
	if (!empty($settings['dns_server2'])) {
515
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
516
	}
517
	if (!empty($settings['dns_server3'])) {
518
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
519
	}
520
	if (!empty($settings['dns_server4'])) {
521
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
522
	}
523

    
524
	if (!empty($settings['push_register_dns'])) {
525
		$conf .= "push \"register-dns\"\n";
526
	}
527

    
528
	if (!empty($settings['ntp_server1'])) {
529
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
530
	}
531
	if (!empty($settings['ntp_server2'])) {
532
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
533
	}
534

    
535
	if ($settings['netbios_enable']) {
536

    
537
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0)) {
538
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
539
		}
540
		if (!empty($settings['dhcp_nbtscope'])) {
541
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
542
		}
543

    
544
		if (!empty($settings['wins_server1'])) {
545
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
546
		}
547
		if (!empty($settings['wins_server2'])) {
548
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
549
		}
550

    
551
		if (!empty($settings['nbdd_server1'])) {
552
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
553
		}
554
	}
555

    
556
	if ($settings['gwredir']) {
557
		$conf .= "push \"redirect-gateway def1\"\n";
558
	}
559
}
560

    
561
function openvpn_add_custom(& $settings, & $conf) {
562

    
563
	if ($settings['custom_options']) {
564

    
565
		$options = explode(';', $settings['custom_options']);
566

    
567
		if (is_array($options)) {
568
			foreach ($options as $option) {
569
				$conf .= "$option\n";
570
			}
571
		} else {
572
			$conf .= "{$settings['custom_options']}\n";
573
		}
574
	}
575
}
576

    
577
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
578
	global $g;
579

    
580
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
581
	openvpn_create_dirs();
582
	file_put_contents($fpath, base64_decode($data));
583
	//chown($fpath, 'nobody');
584
	//chgrp($fpath, 'nobody');
585
	@chmod($fpath, 0600);
586

    
587
	$conf .= "{$directive} {$fpath} {$opt}\n";
588
}
589

    
590
function openvpn_reconfigure($mode, $settings) {
591
	global $g, $config, $openvpn_tls_server_modes;
592

    
593
	if (empty($settings)) {
594
		return;
595
	}
596
	if (isset($settings['disable'])) {
597
		return;
598
	}
599
	openvpn_create_dirs();
600
	/*
601
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
602
	 * we use a vpnid number which is allocated for a particular client
603
	 * or server configuration. ( see openvpn_vpnid_next() )
604
	 */
605

    
606
	$vpnid = $settings['vpnid'];
607
	$mode_id = $mode.$vpnid;
608

    
609
	if (isset($settings['dev_mode'])) {
610
		$tunname = "{$settings['dev_mode']}{$vpnid}";
611
	} else {
612
		/* defaults to tun */
613
		$tunname = "tun{$vpnid}";
614
		$settings['dev_mode'] = "tun";
615
	}
616

    
617
	if ($mode == "server") {
618
		$devname = "ovpns{$vpnid}";
619
	} else {
620
		$devname = "ovpnc{$vpnid}";
621
	}
622

    
623
	/* is our device already configured */
624
	if (!does_interface_exist($devname)) {
625

    
626
		/* create the tap device if required */
627
		if (!file_exists("/dev/{$tunname}")) {
628
			exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
629
		}
630

    
631
		/* rename the device */
632
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
633

    
634
		/* add the device to the openvpn group and make sure it's UP*/
635
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn up");
636

    
637
		$ifname = convert_real_interface_to_friendly_interface_name($devname);
638
		$grouptmp = link_interface_to_group($ifname);
639
		if (!empty($grouptmp)) {
640
			array_walk($grouptmp, 'interface_group_add_member');
641
		}
642
		unset($grouptmp, $ifname);
643
	}
644

    
645
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
646
	$proto = strtolower($settings['protocol']);
647
	if (substr($settings['protocol'], 0, 3) == "TCP") {
648
			$proto = "{$proto}-{$mode}";
649
	}
650
	$dev_mode = $settings['dev_mode'];
651
	$cipher = $settings['crypto'];
652
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
653
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
654

    
655
	$interface = get_failover_interface($settings['interface']);
656
	// The IP address in the settings can be an IPv4 or IPv6 address associated with the interface
657
	$ipaddr = $settings['ipaddr'];
658

    
659
	// If a specific ip address (VIP) is requested, use it.
660
	// Otherwise, if a specific interface is requested, use it
661
	// If "any" interface was selected, local directive will be omitted.
662
	if (is_ipaddrv4($ipaddr)) {
663
		$iface_ip = $ipaddr;
664
	} else {
665
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
666
			$iface_ip=get_interface_ip($interface);
667
		}
668
	}
669
	if (is_ipaddrv6($ipaddr)) {
670
		$iface_ipv6 = $ipaddr;
671
	} else {
672
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
673
			$iface_ipv6=get_interface_ipv6($interface);
674
		}
675
	}
676

    
677

    
678
	$conf = "dev {$devname}\n";
679
	if (isset($settings['verbosity_level'])) {
680
		$conf .= "verb {$settings['verbosity_level']}\n";
681
	}
682

    
683
	$conf .= "dev-type {$settings['dev_mode']}\n";
684
	switch ($settings['dev_mode']) {
685
		case "tun":
686
			if (!$settings['no_tun_ipv6']) {
687
				$conf .= "tun-ipv6\n";
688
			}
689
			break;
690
	}
691
	$conf .= "dev-node /dev/{$tunname}\n";
692
	$conf .= "writepid {$pfile}\n";
693
	$conf .= "#user nobody\n";
694
	$conf .= "#group nobody\n";
695
	$conf .= "script-security 3\n";
696
	$conf .= "daemon\n";
697
	$conf .= "keepalive 10 60\n";
698
	$conf .= "ping-timer-rem\n";
699
	$conf .= "persist-tun\n";
700
	$conf .= "persist-key\n";
701
	$conf .= "proto {$proto}\n";
702
	$conf .= "cipher {$cipher}\n";
703
	$conf .= "auth {$digest}\n";
704
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
705
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
706
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
707
		switch ($settings['mode']) {
708
			case 'server_user':
709
			case 'server_tls_user':
710
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
711
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
712
				break;
713
		}
714
	}
715

    
716
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
717
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
718
		$conf .= "local {$iface_ip}\n";
719
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
720
		$conf .= "local {$iface_ipv6}\n";
721
	}
722

    
723
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none")) {
724
		$conf .= "engine {$settings['engine']}\n";
725
	}
726

    
727
	// server specific settings
728
	if ($mode == 'server') {
729

    
730
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
731
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
732
		$mask = gen_subnet_mask($cidr);
733

    
734
		// configure tls modes
735
		switch ($settings['mode']) {
736
			case 'p2p_tls':
737
			case 'server_tls':
738
			case 'server_user':
739
			case 'server_tls_user':
740
				$conf .= "tls-server\n";
741
				break;
742
		}
743

    
744
		// configure p2p/server modes
745
		switch ($settings['mode']) {
746
			case 'p2p_tls':
747
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
748
				//  use the server directive. It works for a single client without it.
749
				//  See ticket #1417
750
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
751
					$conf .= "server {$ip} {$mask}\n";
752
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
753
					if (is_ipaddr($ipv6)) {
754
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
755
					}
756
				}
757
			case 'p2p_shared_key':
758
				if (!empty($ip) && !empty($mask)) {
759
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
760
					if ($settings['dev_mode'] == 'tun') {
761
						$conf .= "ifconfig {$ip1} {$ip2}\n";
762
					} else {
763
						$conf .= "ifconfig {$ip1} {$mask}\n";
764
					}
765
				}
766
				if (!empty($ipv6) && !empty($prefix)) {
767
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
768
					if ($settings['dev_mode'] == 'tun') {
769
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
770
					} else {
771
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
772
					}
773
				}
774
				break;
775
			case 'server_tls':
776
			case 'server_user':
777
			case 'server_tls_user':
778
				if (!empty($ip) && !empty($mask)) {
779
					$conf .= "server {$ip} {$mask}\n";
780
					if (is_ipaddr($ipv6)) {
781
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
782
					}
783
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
784
				} else {
785
					if ($settings['serverbridge_dhcp']) {
786
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
787
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
788
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
789
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
790
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
791
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
792
							} else {
793
								$conf .= "mode server\n";
794
							}
795
						} else {
796
							$conf .= "mode server\n";
797
						}
798
					}
799
				}
800
				break;
801
		}
802

    
803
		// configure user auth modes
804
		switch ($settings['mode']) {
805
			case 'server_user':
806
				$conf .= "client-cert-not-required\n";
807
			case 'server_tls_user':
808
				/* username-as-common-name is not compatible with server-bridge */
809
				if (stristr($conf, "server-bridge") === false) {
810
					$conf .= "username-as-common-name\n";
811
				}
812
				if (!empty($settings['authmode'])) {
813
					$strictusercn = "false";
814
					if ($settings['strictusercn']) {
815
						$strictusercn = "true";
816
					}
817
					$conf .= "auth-user-pass-verify \"/usr/local/sbin/ovpn_auth_verify user '{$settings['authmode']}' {$strictusercn} {$mode_id}\" via-env\n";
818
				}
819
				break;
820
		}
821
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls'))) {
822
			$settings['cert_depth'] = 1;
823
		}
824
		if (is_numeric($settings['cert_depth'])) {
825
			if (($mode == 'client') && empty($settings['certref'])) {
826
				$cert = "";
827
			} else {
828
				$cert = lookup_cert($settings['certref']);
829
				/* XXX: Seems not used at all! */
830
				$servercn = urlencode(cert_get_cn($cert['crt']));
831
				$conf .= "tls-verify \"/usr/local/sbin/ovpn_auth_verify tls '{$servercn}' {$settings['cert_depth']}\"\n";
832
			}
833
		}
834

    
835
		// The local port to listen on
836
		$conf .= "lport {$settings['local_port']}\n";
837

    
838
		// The management port to listen on
839
		// Use unix socket to overcome the problem on any type of server
840
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
841
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
842

    
843
		if ($settings['maxclients']) {
844
			$conf .= "max-clients {$settings['maxclients']}\n";
845
		}
846

    
847
		// Can we push routes
848
		if ($settings['local_network']) {
849
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
850
		}
851
		if ($settings['local_networkv6']) {
852
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
853
		}
854

    
855
		switch ($settings['mode']) {
856
			case 'server_tls':
857
			case 'server_user':
858
			case 'server_tls_user':
859
				// Configure client dhcp options
860
				openvpn_add_dhcpopts($settings, $conf);
861
				if ($settings['client2client']) {
862
					$conf .= "client-to-client\n";
863
				}
864
				break;
865
		}
866
		if (isset($settings['duplicate_cn'])) {
867
			$conf .= "duplicate-cn\n";
868
		}
869
	}
870

    
871
	// client specific settings
872

    
873
	if ($mode == 'client') {
874

    
875
		// configure p2p mode
876
		switch ($settings['mode']) {
877
			case 'p2p_tls':
878
				$conf .= "tls-client\n";
879
			case 'shared_key':
880
				$conf .= "client\n";
881
				break;
882
		}
883

    
884
		// If there is no bind option at all (ip and/or port), add "nobind" directive
885
		//  Otherwise, use the local port if defined, failing that, use lport 0 to
886
		//  ensure a random source port.
887
		if ((empty($iface_ip)) && (!$settings['local_port'])) {
888
			$conf .= "nobind\n";
889
		} elseif ($settings['local_port']) {
890
			$conf .= "lport {$settings['local_port']}\n";
891
		} else {
892
			$conf .= "lport 0\n";
893
		}
894

    
895
		// Use unix socket to overcome the problem on any type of server
896
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
897

    
898
		// The remote server
899
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
900

    
901
		if (!empty($settings['use_shaper'])) {
902
			$conf .= "shaper {$settings['use_shaper']}\n";
903
		}
904

    
905
		if (!empty($settings['tunnel_network'])) {
906
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
907
			$mask = gen_subnet_mask($mask);
908
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
909
			if ($settings['dev_mode'] == 'tun') {
910
				$conf .= "ifconfig {$ip2} {$ip1}\n";
911
			} else {
912
				$conf .= "ifconfig {$ip2} {$mask}\n";
913
			}
914
		}
915

    
916
		if (!empty($settings['tunnel_networkv6'])) {
917
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
918
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
919
			if ($settings['dev_mode'] == 'tun') {
920
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
921
			} else {
922
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
923
			}
924
		}
925

    
926
		if ($settings['auth_user'] || $settings['auth_pass']) {
927
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
928
			$conf .= "auth-user-pass {$up_file}\n";
929
			if ($settings['auth_user']) {
930
				$userpass = "{$settings['auth_user']}\n";
931
			} else {
932
				$userpass = "";
933
			}
934
			if ($settings['auth_pass']) {
935
				$userpass .= "{$settings['auth_pass']}\n";
936
			}
937
			// If only auth_pass is given, then it acts like a user name and we put a blank line where pass would normally go.
938
			if (!($settings['auth_user'] && $settings['auth_pass'])) {
939
				$userpass .= "\n";
940
			}
941
			file_put_contents($up_file, $userpass);
942
		}
943

    
944
		if ($settings['proxy_addr']) {
945
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
946
			if ($settings['proxy_authtype'] != "none") {
947
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
948
				$proxypas = "{$settings['proxy_user']}\n";
949
				$proxypas .= "{$settings['proxy_passwd']}\n";
950
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
951
			}
952
			$conf .= " \n";
953
		}
954
	}
955

    
956
	// Add a remote network route if set, and only for p2p modes.
957
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
958
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
959
	}
960
	// Add a remote network route if set, and only for p2p modes.
961
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
962
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
963
	}
964

    
965
	// Write the settings for the keys
966
	switch ($settings['mode']) {
967
		case 'p2p_shared_key':
968
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
969
			break;
970
		case 'p2p_tls':
971
		case 'server_tls':
972
		case 'server_tls_user':
973
		case 'server_user':
974
			$ca = lookup_ca($settings['caref']);
975
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
976

    
977
			if (!empty($settings['certref'])) {
978
				$cert = lookup_cert($settings['certref']);
979
				openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
980
				openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
981
			}
982
			if ($mode == 'server') {
983
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
984
			}
985
			if (!empty($settings['crlref'])) {
986
				$crl = lookup_crl($settings['crlref']);
987
				crl_update($crl);
988
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
989
			}
990
			if ($settings['tls']) {
991
				if ($mode == "server") {
992
					$tlsopt = 0;
993
				} else {
994
					$tlsopt = 1;
995
				}
996
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
997
			}
998
			break;
999
	}
1000

    
1001
	if (!empty($settings['compression'])) {
1002
		$conf .= "comp-lzo {$settings['compression']}\n";
1003
	}
1004

    
1005
	if ($settings['passtos']) {
1006
		$conf .= "passtos\n";
1007
	}
1008

    
1009
	if ($settings['resolve_retry']) {
1010
		$conf .= "resolv-retry infinite\n";
1011
	} else if ($mode == 'clie} nt') {
1012
		$conf .= "resolv-retry infinite\n";
1013
	}
1014

    
1015
	if ($settings['dynamic_ip']) {
1016
		$conf .= "persist-remote-ip\n";
1017
		$conf .= "float\n";
1018
	}
1019

    
1020
	if (in_array($settings['mode'], $openvpn_tls_server_modes)) {
1021
		if (empty($settings['topology'])) {
1022
			$settings['topology'] = "subnet";
1023
		}
1024
		$conf .= "topology {$settings['topology']}\n";
1025
	}
1026

    
1027
	// New client features
1028
	if ($mode == "client") {
1029
		// Dont pull routes checkbox
1030
		if ($settings['route_no_pull']) {
1031
			$conf .= "route-nopull\n";
1032
		}
1033

    
1034
		// Dont add/remove routes checkbox
1035
		if ($settings['route_no_exec']) {
1036
			$conf .= "route-noexec\n";
1037
		}
1038
	}
1039

    
1040
	openvpn_add_custom($settings, $conf);
1041

    
1042
	openvpn_create_dirs();
1043
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
1044
	file_put_contents($fpath, $conf);
1045
	unset($conf);
1046
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
1047
	file_put_contents($fpath, $interface);
1048
	//chown($fpath, 'nobody');
1049
	//chgrp($fpath, 'nobody');
1050
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
1051
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
1052
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
1053
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
1054
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
1055
}
1056

    
1057
function openvpn_restart($mode, $settings) {
1058
	global $g, $config;
1059

    
1060
	$vpnid = $settings['vpnid'];
1061
	$mode_id = $mode.$vpnid;
1062

    
1063
	/* kill the process if running */
1064
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
1065
	if (file_exists($pfile)) {
1066

    
1067
		/* read the pid file */
1068
		$pid = rtrim(file_get_contents($pfile));
1069
		unlink($pfile);
1070

    
1071
		/* send a term signal to the process */
1072
		posix_kill($pid, SIGTERM);
1073

    
1074
		/* wait until the process exits, or timeout and kill it */
1075
		$i = 0;
1076
		while (posix_kill($pid, 0)) {
1077
			usleep(250000);
1078
			if ($i > 10) {
1079
				log_error("OpenVPN ID $mode_id PID $pid still running, killing.");
1080
				posix_kill($pid, SIGKILL);
1081
				usleep(500000);
1082
			}
1083
			$i++;
1084
		}
1085
	}
1086

    
1087
	if (isset($settings['disable'])) {
1088
		return;
1089
	}
1090

    
1091
	/* Do not start a client if we are a CARP backup on this vip! */
1092
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) != "MASTER")) {
1093
		return;
1094
	}
1095

    
1096
	/* Check if client is bound to a gateway group */
1097
	$a_groups = return_gateway_groups_array();
1098
	if (is_array($a_groups[$settings['interface']])) {
1099
		/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
1100
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) != "MASTER")) {
1101
			return;
1102
		}
1103
	}
1104

    
1105
	/* start the new process */
1106
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
1107
	openvpn_clear_route($mode, $settings);
1108
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
1109

    
1110
	if (!platform_booting()) {
1111
		send_event("filter reload");
1112
	}
1113
}
1114

    
1115
function openvpn_delete($mode, & $settings) {
1116
	global $g, $config;
1117

    
1118
	$vpnid = $settings['vpnid'];
1119
	$mode_id = $mode.$vpnid;
1120

    
1121
	if (isset($settings['dev_mode'])) {
1122
		$tunname = "{$settings['dev_mode']}{$vpnid}";
1123
	} else {
1124
		/* defaults to tun */
1125
		$tunname = "tun{$vpnid}";
1126
	}
1127

    
1128
	if ($mode == "server") {
1129
		$devname = "ovpns{$vpnid}";
1130
	} else {
1131
		$devname = "ovpnc{$vpnid}";
1132
	}
1133

    
1134
	/* kill the process if running */
1135
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
1136
	if (file_exists($pfile)) {
1137

    
1138
		/* read the pid file */
1139
		$pid = trim(file_get_contents($pfile));
1140
		unlink($pfile);
1141

    
1142
		/* send a term signal to the process */
1143
		posix_kill($pid, SIGTERM);
1144
	}
1145

    
1146
	/* remove the device from the openvpn group */
1147
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
1148

    
1149
	/* restore the original adapter name */
1150
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
1151

    
1152
	/* remove the configuration files */
1153
	@array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
1154
}
1155

    
1156
function openvpn_resync_csc(& $settings) {
1157
	global $g, $config, $openvpn_tls_server_modes;
1158

    
1159
	$csc_base_path = "{$g['varetc_path']}/openvpn-csc";
1160

    
1161
	if (isset($settings['disable'])) {
1162
		openvpn_delete_csc($settings);
1163
		return;
1164
	}
1165
	openvpn_create_dirs();
1166

    
1167
	if (empty($settings['server_list'])) {
1168
		$csc_server_list = array();
1169
	} else {
1170
		$csc_server_list = explode(",", $settings['server_list']);
1171
	}
1172

    
1173
	$conf = '';
1174
	if ($settings['block']) {
1175
		$conf .= "disable\n";
1176
	}
1177

    
1178
	if ($settings['push_reset']) {
1179
		$conf .= "push-reset\n";
1180
	}
1181

    
1182
	if ($settings['local_network']) {
1183
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
1184
	}
1185
	if ($settings['local_networkv6']) {
1186
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
1187
	}
1188

    
1189
	// Add a remote network iroute if set
1190
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
1191
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
1192
	}
1193
	// Add a remote network iroute if set
1194
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
1195
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
1196
	}
1197

    
1198
	openvpn_add_dhcpopts($settings, $conf);
1199

    
1200
	if ($settings['gwredir']) {
1201
		$conf .= "push \"redirect-gateway def1\"\n";
1202
	}
1203

    
1204
	openvpn_add_custom($settings, $conf);
1205
	/* Loop through servers, find which ones can use this CSC */
1206
	if (is_array($config['openvpn']['openvpn-server'])) {
1207
		foreach ($config['openvpn']['openvpn-server'] as $serversettings) {
1208
			if (isset($serversettings['disable'])) {
1209
				continue;
1210
			}
1211
			if (in_array($serversettings['mode'], $openvpn_tls_server_modes)) {
1212
				if ($serversettings['vpnid'] && (empty($csc_server_list) || in_array($serversettings['vpnid'], $csc_server_list))) {
1213
					$csc_path = "{$csc_base_path}/server{$serversettings['vpnid']}/" . basename($settings['common_name']);
1214
					$csc_conf = $conf;
1215

    
1216
					if (!empty($serversettings['tunnel_network']) && !empty($settings['tunnel_network'])) {
1217
						list($ip, $mask) = explode('/', $settings['tunnel_network']);
1218
						if (($serversettings['dev_mode'] == 'tap') || ($serversettings['topology'] == "subnet")) {
1219
							$csc_conf .= "ifconfig-push {$ip} " . gen_subnet_mask($mask) . "\n";
1220
						} else {
1221
							/* Because this is being pushed, the order from the client's point of view. */
1222
							$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
1223
							$serverip = long2ip32($baselong + 1);
1224
							$clientip = long2ip32($baselong + 2);
1225
							$csc_conf .= "ifconfig-push {$clientip} {$serverip}\n";
1226
						}
1227
					}
1228
					file_put_contents($csc_path, $csc_conf);
1229
					chown($csc_path, 'nobody');
1230
					chgrp($csc_path, 'nobody');
1231
				}
1232
			}
1233
		}
1234
	}
1235
}
1236

    
1237
function openvpn_delete_csc(& $settings) {
1238
	global $g, $config, $openvpn_tls_server_modes;
1239
	$csc_base_path = "{$g['varetc_path']}/openvpn-csc";
1240
	if (empty($settings['server_list'])) {
1241
		$csc_server_list = array();
1242
	} else {
1243
		$csc_server_list = explode(",", $settings['server_list']);
1244
	}
1245

    
1246
	/* Loop through servers, find which ones used this CSC */
1247
	if (is_array($config['openvpn']['openvpn-server'])) {
1248
		foreach ($config['openvpn']['openvpn-server'] as $serversettings) {
1249
			if (isset($serversettings['disable'])) {
1250
				continue;
1251
			}
1252
			if (in_array($serversettings['mode'], $openvpn_tls_server_modes)) {
1253
				if ($serversettings['vpnid'] && (empty($csc_server_list) || in_array($serversettings['vpnid'], $csc_server_list))) {
1254
					$csc_path = "{$csc_base_path}/server{$serversettings['vpnid']}/" . basename($settings['common_name']);
1255
					unlink_if_exists($csc_path);
1256
				}
1257
			}
1258
		}
1259
	}
1260
}
1261

    
1262
// Resync the configuration and restart the VPN
1263
function openvpn_resync($mode, $settings) {
1264
	openvpn_reconfigure($mode, $settings);
1265
	openvpn_restart($mode, $settings);
1266
}
1267

    
1268
// Resync and restart all VPNs
1269
function openvpn_resync_all($interface = "") {
1270
	global $g, $config;
1271

    
1272
	openvpn_create_dirs();
1273

    
1274
	if (!is_array($config['openvpn'])) {
1275
		$config['openvpn'] = array();
1276
	}
1277

    
1278
/*
1279
	if (!$config['openvpn']['dh-parameters']) {
1280
		echo "Configuring OpenVPN Parameters ...\n";
1281
		$dh_parameters = openvpn_create_dhparams(1024);
1282
		$dh_parameters = base64_encode($dh_parameters);
1283
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1284
		write_config("OpenVPN DH parameters");
1285
	}
1286

    
1287
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1288
	if (!file_exists($path_ovdh)) {
1289
		$dh_parameters = $config['openvpn']['dh-parameters'];
1290
		$dh_parameters = base64_decode($dh_parameters);
1291
		file_put_contents($path_ovdh, $dh_parameters);
1292
	}
1293
*/
1294
	if ($interface <> "") {
1295
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
1296
	} else {
1297
		log_error("Resyncing OpenVPN instances.");
1298
	}
1299

    
1300
	if (is_array($config['openvpn']['openvpn-server'])) {
1301
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1302
			if ($interface <> "" && $interface != $settings['interface']) {
1303
				continue;
1304
			}
1305
			openvpn_resync('server', $settings);
1306
		}
1307
	}
1308

    
1309
	if (is_array($config['openvpn']['openvpn-client'])) {
1310
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1311
			if ($interface <> "" && $interface != $settings['interface']) {
1312
				continue;
1313
			}
1314
			openvpn_resync('client', $settings);
1315
		}
1316
	}
1317

    
1318
	if (is_array($config['openvpn']['openvpn-csc'])) {
1319
		foreach ($config['openvpn']['openvpn-csc'] as & $settings) {
1320
			openvpn_resync_csc($settings);
1321
		}
1322
	}
1323

    
1324
}
1325

    
1326
// Resync and restart all VPNs using a gateway group.
1327
function openvpn_resync_gwgroup($gwgroupname = "") {
1328
	global $g, $config;
1329

    
1330
	if ($gwgroupname <> "") {
1331
		if (is_array($config['openvpn']['openvpn-server'])) {
1332
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1333
				if ($gwgroupname == $settings['interface']) {
1334
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1335
					openvpn_resync('server', $settings);
1336
				}
1337
			}
1338
		}
1339

    
1340
		if (is_array($config['openvpn']['openvpn-client'])) {
1341
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1342
				if ($gwgroupname == $settings['interface']) {
1343
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1344
					openvpn_resync('client', $settings);
1345
				}
1346
			}
1347
		}
1348

    
1349
		// Note: no need to resysnc Client Specific (csc) here, as changes to the OpenVPN real interface do not effect these.
1350

    
1351
	} else {
1352
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter.");
1353
	}
1354
}
1355

    
1356
function openvpn_get_active_servers($type="multipoint") {
1357
	global $config, $g;
1358

    
1359
	$servers = array();
1360
	if (is_array($config['openvpn']['openvpn-server'])) {
1361
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1362
			if (empty($settings) || isset($settings['disable'])) {
1363
				continue;
1364
			}
1365

    
1366
			$prot = $settings['protocol'];
1367
			$port = $settings['local_port'];
1368

    
1369
			$server = array();
1370
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1371
			$server['mode'] = $settings['mode'];
1372
			if ($settings['description']) {
1373
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1374
			} else {
1375
				$server['name'] = "Server {$prot}:{$port}";
1376
			}
1377
			$server['conns'] = array();
1378
			$server['vpnid'] = $settings['vpnid'];
1379
			$server['mgmt'] = "server{$server['vpnid']}";
1380
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1381
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1382

    
1383
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30)) && ($type == "p2p")) {
1384
				$servers[] = openvpn_get_client_status($server, $socket);
1385
			} elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30)) {
1386
				$servers[] = openvpn_get_server_status($server, $socket);
1387
			}
1388
		}
1389
	}
1390
	return $servers;
1391
}
1392

    
1393
function openvpn_get_server_status($server, $socket) {
1394
	$errval = null;
1395
	$errstr = null;
1396
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1397
	if ($fp) {
1398
		stream_set_timeout($fp, 1);
1399

    
1400
		/* send our status request */
1401
		fputs($fp, "status 2\n");
1402

    
1403
		/* recv all response lines */
1404
		while (!feof($fp)) {
1405

    
1406
			/* read the next line */
1407
			$line = fgets($fp, 1024);
1408

    
1409
			$info = stream_get_meta_data($fp);
1410
			if ($info['timed_out']) {
1411
				break;
1412
			}
1413

    
1414
			/* parse header list line */
1415
			if (strstr($line, "HEADER")) {
1416
				continue;
1417
			}
1418

    
1419
			/* parse end of output line */
1420
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1421
				break;
1422
			}
1423

    
1424
			/* parse client list line */
1425
			if (strstr($line, "CLIENT_LIST")) {
1426
				$list = explode(",", $line);
1427
				$conn = array();
1428
				$conn['common_name'] = $list[1];
1429
				$conn['remote_host'] = $list[2];
1430
				$conn['virtual_addr'] = $list[3];
1431
				$conn['bytes_recv'] = $list[4];
1432
				$conn['bytes_sent'] = $list[5];
1433
				$conn['connect_time'] = $list[6];
1434
				$server['conns'][] = $conn;
1435
			}
1436
			/* parse routing table lines */
1437
			if (strstr($line, "ROUTING_TABLE")) {
1438
				$list = explode(",", $line);
1439
				$conn = array();
1440
				$conn['virtual_addr'] = $list[1];
1441
				$conn['common_name'] = $list[2];
1442
				$conn['remote_host'] = $list[3];
1443
				$conn['last_time'] = $list[4];
1444
				$server['routes'][] = $conn;
1445
			}
1446
		}
1447

    
1448
		/* cleanup */
1449
		fclose($fp);
1450
	} else {
1451
		$conn = array();
1452
		$conn['common_name'] = "[error]";
1453
		$conn['remote_host'] = "Unable to contact daemon";
1454
		$conn['virtual_addr'] = "Service not running?";
1455
		$conn['bytes_recv'] = 0;
1456
		$conn['bytes_sent'] = 0;
1457
		$conn['connect_time'] = 0;
1458
		$server['conns'][] = $conn;
1459
	}
1460
	return $server;
1461
}
1462

    
1463
function openvpn_get_active_clients() {
1464
	global $config, $g;
1465

    
1466
	$clients = array();
1467
	if (is_array($config['openvpn']['openvpn-client'])) {
1468
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1469

    
1470
			if (empty($settings) || isset($settings['disable'])) {
1471
				continue;
1472
			}
1473

    
1474
			$prot = $settings['protocol'];
1475
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1476

    
1477
			$client = array();
1478
			$client['port'] = $settings['local_port'];
1479
			if ($settings['description']) {
1480
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1481
			} else {
1482
				$client['name'] = "Client {$prot}{$port}";
1483
			}
1484

    
1485
			$client['vpnid'] = $settings['vpnid'];
1486
			$client['mgmt'] = "client{$client['vpnid']}";
1487
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1488
			$client['status']="down";
1489

    
1490
			$clients[] = openvpn_get_client_status($client, $socket);
1491
		}
1492
	}
1493
	return $clients;
1494
}
1495

    
1496
function openvpn_get_client_status($client, $socket) {
1497
	$errval = null;
1498
	$errstr = null;
1499
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1500
	if ($fp) {
1501
		stream_set_timeout($fp, 1);
1502
		/* send our status request */
1503
		fputs($fp, "state 1\n");
1504

    
1505
		/* recv all response lines */
1506
		while (!feof($fp)) {
1507
			/* read the next line */
1508
			$line = fgets($fp, 1024);
1509

    
1510
			$info = stream_get_meta_data($fp);
1511
			if ($info['timed_out']) {
1512
				break;
1513
			}
1514

    
1515
			/* Get the client state */
1516
			if (strstr($line, "CONNECTED")) {
1517
				$client['status'] = "up";
1518
				$list = explode(",", $line);
1519

    
1520
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1521
				$client['virtual_addr'] = $list[3];
1522
				$client['remote_host'] = $list[4];
1523
			}
1524
			if (strstr($line, "CONNECTING")) {
1525
				$client['status'] = "connecting";
1526
			}
1527
			if (strstr($line, "ASSIGN_IP")) {
1528
				$client['status'] = "waiting";
1529
				$list = explode(",", $line);
1530

    
1531
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1532
				$client['virtual_addr'] = $list[3];
1533
			}
1534
			if (strstr($line, "RECONNECTING")) {
1535
				$client['status'] = "reconnecting";
1536
				$list = explode(",", $line);
1537

    
1538
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1539
				$client['status'] .= "; " . $list[2];
1540
			}
1541
			/* parse end of output line */
1542
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1543
				break;
1544
			}
1545
		}
1546

    
1547
		/* If up, get read/write stats */
1548
		if (strcmp($client['status'], "up") == 0) {
1549
			fputs($fp, "status 2\n");
1550
			/* recv all response lines */
1551
			while (!feof($fp)) {
1552
				/* read the next line */
1553
				$line = fgets($fp, 1024);
1554

    
1555
				$info = stream_get_meta_data($fp);
1556
				if ($info['timed_out']) {
1557
					break;
1558
				}
1559

    
1560
				if (strstr($line, "TCP/UDP read bytes")) {
1561
					$list = explode(",", $line);
1562
					$client['bytes_recv'] = $list[1];
1563
				}
1564

    
1565
				if (strstr($line, "TCP/UDP write bytes")) {
1566
					$list = explode(",", $line);
1567
					$client['bytes_sent'] = $list[1];
1568
				}
1569

    
1570
				/* parse end of output line */
1571
				if (strstr($line, "END")) {
1572
					break;
1573
				}
1574
			}
1575
		}
1576

    
1577
		fclose($fp);
1578

    
1579
	} else {
1580
		$DisplayNote=true;
1581
		$client['remote_host'] = "Unable to contact daemon";
1582
		$client['virtual_addr'] = "Service not running?";
1583
		$client['bytes_recv'] = 0;
1584
		$client['bytes_sent'] = 0;
1585
		$client['connect_time'] = 0;
1586
	}
1587
	return $client;
1588
}
1589

    
1590
function openvpn_refresh_crls() {
1591
	global $g, $config;
1592

    
1593
	openvpn_create_dirs();
1594

    
1595
	if (is_array($config['openvpn']['openvpn-server'])) {
1596
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1597
			if (empty($settings)) {
1598
				continue;
1599
			}
1600
			if (isset($settings['disable'])) {
1601
				continue;
1602
			}
1603
			// Write the settings for the keys
1604
			switch ($settings['mode']) {
1605
				case 'p2p_tls':
1606
				case 'server_tls':
1607
				case 'server_tls_user':
1608
				case 'server_user':
1609
					if (!empty($settings['crlref'])) {
1610
						$crl = lookup_crl($settings['crlref']);
1611
						crl_update($crl);
1612
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1613
						file_put_contents($fpath, base64_decode($crl['text']));
1614
						@chmod($fpath, 0644);
1615
					}
1616
					break;
1617
			}
1618
		}
1619
	}
1620
}
1621

    
1622
function openvpn_create_dirs() {
1623
	global $g, $config, $openvpn_tls_server_modes;
1624
	if (!is_dir("{$g['varetc_path']}/openvpn")) {
1625
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1626
	}
1627
	if (!is_dir("{$g['varetc_path']}/openvpn-csc")) {
1628
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1629
	}
1630

    
1631
	/* Check for enabled servers and create server-specific CSC dirs */
1632
	if (is_array($config['openvpn']['openvpn-server'])) {
1633
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1634
			if (isset($settings['disable'])) {
1635
				continue;
1636
			}
1637
			if (in_array($settings['mode'], $openvpn_tls_server_modes)) {
1638
				if ($settings['vpnid']) {
1639
					safe_mkdir("{$g['varetc_path']}/openvpn-csc/server{$settings['vpnid']}");
1640
				}
1641
			}
1642
		}
1643
	}
1644
}
1645

    
1646
function openvpn_get_interface_ip($ip, $mask) {
1647
	$baselong = ip2long32($ip) & ip2long($mask);
1648
	$ip1 = long2ip32($baselong + 1);
1649
	$ip2 = long2ip32($baselong + 2);
1650
	return array($ip1, $ip2);
1651
}
1652

    
1653
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1654
	$basev6 = gen_subnetv6($ipv6, $prefix);
1655
	// Is there a better way to do this math?
1656
	$ipv6_arr = explode(':', $basev6);
1657
	$last = hexdec(array_pop($ipv6_arr));
1658
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1659
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1660
	return array($ipv6_1, $ipv6_2);
1661
}
1662

    
1663
function openvpn_clear_route($mode, $settings) {
1664
	if (empty($settings['tunnel_network'])) {
1665
		return;
1666
	}
1667
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1668
	$mask = gen_subnet_mask($cidr);
1669
	$clear_route = false;
1670

    
1671
	switch ($settings['mode']) {
1672
		case 'shared_key':
1673
			$clear_route = true;
1674
			break;
1675
		case 'p2p_tls':
1676
		case 'p2p_shared_key':
1677
			if ($cidr == 30) {
1678
				$clear_route = true;
1679
			}
1680
			break;
1681
	}
1682

    
1683
	if ($clear_route && !empty($ip) && !empty($mask)) {
1684
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1685
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1686
		/* XXX: Family for route? */
1687
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1688
	}
1689
}
1690

    
1691
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1692
	$routes = "";
1693
	if (empty($value)) {
1694
		return "";
1695
	}
1696
	$networks = explode(',', $value);
1697

    
1698
	foreach ($networks as $network) {
1699
		if ($ipproto == "ipv4") {
1700
			$route = openvpn_gen_route_ipv4($network, $iroute);
1701
		} else {
1702
			$route = openvpn_gen_route_ipv6($network, $iroute);
1703
		}
1704

    
1705
		if ($push) {
1706
			$routes .= "push \"{$route}\"\n";
1707
		} else {
1708
			$routes .= "{$route}\n";
1709
		}
1710
	}
1711
	return $routes;
1712
}
1713

    
1714
function openvpn_gen_route_ipv4($network, $iroute = false) {
1715
	$i = ($iroute) ? "i" : "";
1716
	list($ip, $mask) = explode('/', trim($network));
1717
	$mask = gen_subnet_mask($mask);
1718
	return "{$i}route $ip $mask";
1719
}
1720

    
1721
function openvpn_gen_route_ipv6($network, $iroute = false) {
1722
	$i = ($iroute) ? "i" : "";
1723
	list($ipv6, $prefix) = explode('/', trim($network));
1724
	if (empty($prefix)) {
1725
		$prefix = "128";
1726
	}
1727
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1728
}
1729

    
1730
function openvpn_get_settings($mode, $vpnid) {
1731
	global $config;
1732

    
1733
	if (is_array($config['openvpn']['openvpn-server'])) {
1734
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1735
			if (isset($settings['disable'])) {
1736
				continue;
1737
			}
1738

    
1739
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1740
				return $settings;
1741
			}
1742
		}
1743
	}
1744

    
1745
	if (is_array($config['openvpn']['openvpn-client'])) {
1746
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1747
			if (isset($settings['disable'])) {
1748
				continue;
1749
			}
1750

    
1751
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1752
				return $settings;
1753
			}
1754
		}
1755
	}
1756

    
1757
	return array();
1758
}
1759

    
1760
function openvpn_restart_by_vpnid($mode, $vpnid) {
1761
	$settings = openvpn_get_settings($mode, $vpnid);
1762
	openvpn_restart($mode, $settings);
1763
}
1764

    
1765
?>
(37-37/65)