Projet

Général

Profil

Télécharger (42,5 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / openvpn.inc @ c38764dc

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
	DISABLE_PHP_LINT_CHECKING
42

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

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

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

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

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

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

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

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

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

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

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

    
120
function openvpn_create_key() {
121

    
122
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
123
	if (!$fp)
124
		return false;
125

    
126
	$rslt = stream_get_contents($fp);
127
	pclose($fp);
128

    
129
	return $rslt;
130
}
131

    
132
function openvpn_create_dhparams($bits) {
133

    
134
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
135
	if (!$fp)
136
		return false;
137

    
138
	$rslt = stream_get_contents($fp);
139
	pclose($fp);
140

    
141
	return $rslt;
142
}
143

    
144
function openvpn_vpnid_used($vpnid) {
145
	global $config;
146

    
147
	if (is_array($config['openvpn']['openvpn-server']))
148
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
149
			if ($vpnid == $settings['vpnid'])
150
				return true;
151

    
152
	if (is_array($config['openvpn']['openvpn-client']))
153
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
154
			if ($vpnid == $settings['vpnid'])
155
				return true;
156

    
157
	return false;
158
}
159

    
160
function openvpn_vpnid_next() {
161

    
162
	$vpnid = 1;
163
	while(openvpn_vpnid_used($vpnid))
164
		$vpnid++;
165

    
166
	return $vpnid;
167
}
168

    
169
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
170
	global $config;
171

    
172
	if (is_array($config['openvpn']['openvpn-server'])) {
173
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
174
			if (isset($settings['disable']))
175
				continue;
176

    
177
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
178
				continue;
179

    
180
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
181
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
182
				return $settings['vpnid'];
183
		}
184
	}
185

    
186
	if (is_array($config['openvpn']['openvpn-client'])) {
187
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
188
			if (isset($settings['disable']))
189
				continue;
190

    
191
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
192
				continue;
193

    
194
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
195
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
196
				return $settings['vpnid'];
197
		}
198
	}
199

    
200
	return 0;
201
}
202

    
203
function openvpn_port_next($prot, $interface = "wan") {
204

    
205
	$port = 1194;
206
	while(openvpn_port_used($prot, $interface, $port))
207
		$port++;
208
	while(openvpn_port_used($prot, "any", $port))
209
		$port++;
210

    
211
	return $port;
212
}
213

    
214
function openvpn_get_cipherlist() {
215

    
216
	$ciphers = array();
217
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
218
	$cipher_lines = explode("\n", trim($cipher_out));
219
	sort($cipher_lines);
220
	foreach ($cipher_lines as $line) {
221
		$words = explode(' ', $line);
222
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
223
	}
224
	$ciphers["none"] = gettext("None (No Encryption)");
225
	return $ciphers;
226
}
227

    
228
function openvpn_get_digestlist() {
229

    
230
	$digests = array();
231
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
232
	$digest_lines = explode("\n", trim($digest_out));
233
	sort($digest_lines);
234
	foreach ($digest_lines as $line) {
235
		$words = explode(' ', $line);
236
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
237
	}
238
	$digests["none"] = gettext("None (No Authentication)");
239
	return $digests;
240
}
241

    
242
function openvpn_get_engines() {
243
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
244
	exec("/usr/bin/openssl engine -t -c", $openssl_engine_output);
245
	$openssl_engine_output = implode("\n", $openssl_engine_output);
246
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
247
	$openssl_engine_output = explode("\n", $openssl_engine_output);
248

    
249
	foreach ($openssl_engine_output as $oeo) {
250
		$keep = true;
251
		$details = explode("|", $oeo);
252
		$engine = array_shift($details);
253
		$linematch = array();
254
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
255
		foreach ($details as $dt) {
256
			if (strpos($dt, "unavailable") !== FALSE)
257
				$keep = false;
258
			if (strpos($dt, "available") !== FALSE)
259
				continue;
260
			if (strpos($dt, "[") !== FALSE)
261
				$ciphers = trim($dt, "[]");
262
		}
263
		if (!empty($ciphers))
264
			$ciphers = " - " . $ciphers;
265
		if (strlen($ciphers) > 60)
266
			$ciphers = substr($ciphers, 0, 60) . " ... ";
267
		if ($keep)
268
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
269
	}
270
	return $openssl_engines;
271
}
272

    
273
function openvpn_validate_engine($engine) {
274
	$engines = openvpn_get_engines();
275
	return array_key_exists($engine, $engines);
276
}
277

    
278
function openvpn_validate_host($value, $name) {
279
	$value = trim($value);
280
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
281
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
282
	return false;
283
}
284

    
285
function openvpn_validate_port($value, $name) {
286
	$value = trim($value);
287
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
288
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
289
	return false;
290
}
291

    
292
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
293
	$value = trim($value);
294
	$error = false;
295
	if (empty($value))
296
		return false;
297
	$networks = explode(',', $value);
298

    
299
	if (!$multiple && (count($networks) > 1))
300
		return sprintf(gettext("The field '%s' must contain a single valid %s CIDR range."), $name, $ipproto);
301

    
302
	foreach ($networks as $network) {
303
		if ($ipproto == "ipv4")
304
			$error = !openvpn_validate_cidr_ipv4($network);
305
		else
306
			$error = !openvpn_validate_cidr_ipv6($network);
307
		if ($error)
308
			break;
309
	}
310

    
311
	if ($error)
312
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
313
	else
314
		return false;
315
}
316

    
317
function openvpn_validate_cidr_ipv4($value) {
318
	$value = trim($value);
319
	if (!empty($value)) {
320
		list($ip, $mask) = explode('/', $value);
321
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
322
			return false;
323
	}
324
	return true;
325
}
326

    
327
function openvpn_validate_cidr_ipv6($value) {
328
	$value = trim($value);
329
	if (!empty($value)) {
330
		list($ipv6, $prefix) = explode('/', $value);
331
		if (empty($prefix))
332
			$prefix = "128";
333
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0))
334
			return false;
335
	}
336
	return true;
337
}
338

    
339
function openvpn_add_dhcpopts(& $settings, & $conf) {
340

    
341
	if (!empty($settings['dns_domain']))
342
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
343

    
344
	if (!empty($settings['dns_server1']))
345
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
346
	if (!empty($settings['dns_server2']))
347
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
348
	if (!empty($settings['dns_server3']))
349
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
350
	if (!empty($settings['dns_server4']))
351
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
352

    
353
	if (!empty($settings['push_register_dns']))
354
		$conf .= "push \"register-dns\"\n";
355

    
356
	if (!empty($settings['ntp_server1']))
357
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
358
	if (!empty($settings['ntp_server2']))
359
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
360

    
361
	if ($settings['netbios_enable']) {
362

    
363
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
364
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
365
		if (!empty($settings['dhcp_nbtscope']))
366
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
367

    
368
		if (!empty($settings['wins_server1']))
369
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
370
		if (!empty($settings['wins_server2']))
371
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
372

    
373
		if (!empty($settings['nbdd_server1']))
374
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
375
	}
376

    
377
	if ($settings['gwredir'])
378
		$conf .= "push \"redirect-gateway def1\"\n";
379
}
380

    
381
function openvpn_add_custom(& $settings, & $conf) {
382

    
383
	if ($settings['custom_options']) {
384

    
385
		$options = explode(';', $settings['custom_options']);
386

    
387
		if (is_array($options)) {
388
			foreach ($options as $option)
389
				$conf .= "$option\n";
390
		} else
391
			$conf .= "{$settings['custom_options']}\n";
392
	}
393
}
394

    
395
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
396
	global $g;
397

    
398
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
399
	openvpn_create_dirs();
400
	file_put_contents($fpath, base64_decode($data));
401
	//chown($fpath, 'nobody');
402
	//chgrp($fpath, 'nobody');
403
	@chmod($fpath, 0600);
404

    
405
	$conf .= "{$directive} {$fpath} {$opt}\n";
406
}
407

    
408
function openvpn_reconfigure($mode, $settings) {
409
	global $g, $config;
410

    
411
	if (empty($settings))
412
		return;
413
	if (isset($settings['disable']))
414
		return;
415
	openvpn_create_dirs();
416
	/*
417
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
418
	 * we use a vpnid number which is allocated for a particular client
419
	 * or server configuration. ( see openvpn_vpnid_next() )
420
	 */
421

    
422
	$vpnid = $settings['vpnid'];
423
	$mode_id = $mode.$vpnid;
424

    
425
	if (isset($settings['dev_mode']))
426
		$tunname = "{$settings['dev_mode']}{$vpnid}";
427
	else {	/* defaults to tun */
428
		$tunname = "tun{$vpnid}";
429
		$settings['dev_mode'] = "tun";
430
	}
431

    
432
	if ($mode == "server")
433
		$devname = "ovpns{$vpnid}";
434
	else
435
		$devname = "ovpnc{$vpnid}";
436

    
437
	/* is our device already configured */
438
	if (!does_interface_exist($devname)) {
439

    
440
		/* create the tap device if required */
441
		if (!file_exists("/dev/{$tunname}"))
442
			exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
443

    
444
		/* rename the device */
445
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
446

    
447
		/* add the device to the openvpn group */
448
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn");
449
	}
450

    
451
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
452
	$proto = strtolower($settings['protocol']);
453
	if (substr($settings['protocol'], 0, 3) == "TCP")
454
			$proto = "{$proto}-{$mode}";
455
	$dev_mode = $settings['dev_mode'];
456
	$cipher = $settings['crypto'];
457
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
458
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
459

    
460
	$interface = get_failover_interface($settings['interface']);
461
	$ipaddr = $settings['ipaddr'];
462
	$ipaddrv6 = $settings['ipaddrv6'];
463

    
464
	// If a specific ip address (VIP) is requested, use it.
465
	// Otherwise, if a specific interface is requested, use it
466
	// If "any" interface was selected, local directive will be ommited.
467
	if (is_ipaddrv4($ipaddr)) {
468
		$iface_ip=$ipaddr;
469
	} else {
470
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
471
			$iface_ip=get_interface_ip($interface);
472
		}
473
	}
474
	if (is_ipaddrv6($ipaddrv6)) {
475
		$iface_ipv6=$ipaddrv6;
476
	} else {
477
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
478
			$iface_ipv6=get_interface_ipv6($interface);
479
		}
480
	}
481

    
482

    
483
	$conf = "dev {$devname}\n";
484
	if (isset($settings['verbosity_level'])) {
485
		$conf .= "verb {$settings['verbosity_level']}\n";
486
	}
487

    
488
	$conf .= "dev-type {$settings['dev_mode']}\n";
489
	switch($settings['dev_mode']) {
490
		case "tun":
491
			if (!$settings['no_tun_ipv6']) {
492
				$conf .= "tun-ipv6\n";
493
			}
494
			break;
495
	}
496
	$conf .= "dev-node /dev/{$tunname}\n";
497
	$conf .= "writepid {$pfile}\n";
498
	$conf .= "#user nobody\n";
499
	$conf .= "#group nobody\n";
500
	$conf .= "script-security 3\n";
501
	$conf .= "daemon\n";
502
	$conf .= "keepalive 10 60\n";
503
	$conf .= "ping-timer-rem\n";
504
	$conf .= "persist-tun\n";
505
	$conf .= "persist-key\n";
506
	$conf .= "proto {$proto}\n";
507
	$conf .= "cipher {$cipher}\n";
508
	$conf .= "auth {$digest}\n";
509
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
510
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
511
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
512
		switch($settings['mode']) {
513
			case 'server_user':
514
			case 'server_tls_user':
515
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
516
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
517
				break;
518
		}
519
	}
520

    
521
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
522
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
523
		$conf .= "local {$iface_ip}\n";
524
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
525
		$conf .= "local {$iface_ipv6}\n";
526
	}
527

    
528
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
529
		$conf .= "engine {$settings['engine']}\n";
530

    
531
	// server specific settings
532
	if ($mode == 'server') {
533

    
534
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
535
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
536
		$mask = gen_subnet_mask($cidr);
537

    
538
		// configure tls modes
539
		switch($settings['mode']) {
540
			case 'p2p_tls':
541
			case 'server_tls':
542
			case 'server_user':
543
			case 'server_tls_user':
544
				$conf .= "tls-server\n";
545
				break;
546
		}
547

    
548
		// configure p2p/server modes
549
		switch($settings['mode']) {
550
			case 'p2p_tls':
551
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
552
				//  use the server directive. It works for a single client without it.
553
				//  See ticket #1417
554
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
555
					$conf .= "server {$ip} {$mask}\n";
556
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
557
					if(is_ipaddr($ipv6))
558
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
559
				}
560
			case 'p2p_shared_key':
561
				if (!empty($ip) && !empty($mask)) {
562
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
563
					if ($settings['dev_mode'] == 'tun')
564
						$conf .= "ifconfig {$ip1} {$ip2}\n";
565
					else
566
						$conf .= "ifconfig {$ip1} {$mask}\n";
567
				}
568
				if (!empty($ipv6) && !empty($prefix)) {
569
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
570
					if ($settings['dev_mode'] == 'tun')
571
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
572
					else
573
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
574
				}
575
				break;
576
			case 'server_tls':
577
			case 'server_user':
578
			case 'server_tls_user':
579
				if (!empty($ip) && !empty($mask)) {
580
					$conf .= "server {$ip} {$mask}\n";
581
					if(is_ipaddr($ipv6))
582
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
583
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
584
				} else {
585
					if ($settings['serverbridge_dhcp']) {
586
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
587
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
588
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
589
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
590
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
591
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
592
							} else {
593
								$conf .= "mode server\n";
594
							}
595
						} else {
596
							$conf .= "mode server\n";
597
						}
598
					}
599
				}
600
				break;
601
		}
602

    
603
		// configure user auth modes
604
		switch($settings['mode']) {
605
			case 'server_user':
606
				$conf .= "client-cert-not-required\n";
607
			case 'server_tls_user':
608
				/* username-as-common-name is not compatible with server-bridge */
609
				if (stristr($conf, "server-bridge") === false)
610
					$conf .= "username-as-common-name\n";
611
				if (!empty($settings['authmode'])) {
612
					$strictusercn = "false";
613
					if ($settings['strictusercn'])
614
						$strictusercn = "true";
615
					$conf .= "auth-user-pass-verify \"/usr/local/sbin/ovpn_auth_verify user '{$settings['authmode']}' {$strictusercn} {$mode_id}\" via-env\n";
616
				}
617
				break;
618
		}
619
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls')))
620
			$settings['cert_depth'] = 1;
621
		if (is_numeric($settings['cert_depth'])) {
622
			if (($mode == 'client') && empty($settings['certref']))
623
				$cert = "";
624
			else {
625
				$cert = lookup_cert($settings['certref']);
626
				/* XXX: Seems not used at all! */
627
				$servercn = urlencode(cert_get_cn($cert['crt']));
628
				$conf .= "tls-verify \"/usr/local/sbin/ovpn_auth_verify tls '{$servercn}' {$settings['cert_depth']}\"\n";
629
			}
630
		}
631

    
632
		// The local port to listen on
633
		$conf .= "lport {$settings['local_port']}\n";
634

    
635
		// The management port to listen on
636
		// Use unix socket to overcome the problem on any type of server
637
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
638
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
639

    
640
		if ($settings['maxclients'])
641
			$conf .= "max-clients {$settings['maxclients']}\n";
642

    
643
		// Can we push routes
644
		if ($settings['local_network']) {
645
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
646
		}
647
		if ($settings['local_networkv6']) {
648
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
649
		}
650

    
651
		switch($settings['mode']) {
652
			case 'server_tls':
653
			case 'server_user':
654
			case 'server_tls_user':
655
				// Configure client dhcp options
656
				openvpn_add_dhcpopts($settings, $conf);
657
				if ($settings['client2client'])
658
					$conf .= "client-to-client\n";
659
				break;
660
		}
661
		if (isset($settings['duplicate_cn']))
662
			$conf .= "duplicate-cn\n";
663
	}
664

    
665
	// client specific settings
666

    
667
	if ($mode == 'client') {
668

    
669
		// configure p2p mode
670
		switch($settings['mode']) {
671
			case 'p2p_tls':
672
				$conf .= "tls-client\n";
673
			case 'shared_key':
674
				$conf .= "client\n";
675
				break;
676
		}
677

    
678
		// If there is no bind option at all (ip and/or port), add "nobind" directive
679
		//  Otherwise, use the local port if defined, failing that, use lport 0 to
680
		//  ensure a random source port.
681
		if ((empty($iface_ip)) && (!$settings['local_port']))
682
			$conf .= "nobind\n";
683
		elseif ($settings['local_port'])
684
			$conf .= "lport {$settings['local_port']}\n";
685
		else
686
			$conf .= "lport 0\n";
687

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

    
691
		// The remote server
692
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
693

    
694
		if (!empty($settings['use_shaper']))
695
			$conf .= "shaper {$settings['use_shaper']}\n";
696

    
697
		if (!empty($settings['tunnel_network'])) {
698
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
699
			$mask = gen_subnet_mask($mask);
700
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
701
			if ($settings['dev_mode'] == 'tun')
702
				$conf .= "ifconfig {$ip2} {$ip1}\n";
703
			else
704
				$conf .= "ifconfig {$ip2} {$mask}\n";
705
		}
706

    
707
		if (!empty($settings['tunnel_networkv6'])) {
708
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
709
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
710
			if ($settings['dev_mode'] == 'tun')
711
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
712
			else
713
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
714
		}
715

    
716
		if ($settings['auth_user'] && $settings['auth_pass']) {
717
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
718
			$conf .= "auth-user-pass {$up_file}\n";
719
			$userpass = "{$settings['auth_user']}\n";
720
			$userpass .= "{$settings['auth_pass']}\n";
721
			file_put_contents($up_file, $userpass);
722
		}
723

    
724
		if ($settings['proxy_addr']) {
725
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
726
			if ($settings['proxy_authtype'] != "none") {
727
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
728
				$proxypas = "{$settings['proxy_user']}\n";
729
				$proxypas .= "{$settings['proxy_passwd']}\n";
730
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
731
			}
732
			$conf .= " \n";
733
		}
734
	}
735

    
736
	// Add a remote network route if set, and only for p2p modes.
737
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
738
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
739
	}
740
	// Add a remote network route if set, and only for p2p modes.
741
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
742
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
743
	}
744

    
745
	// Write the settings for the keys
746
	switch($settings['mode']) {
747
		case 'p2p_shared_key':
748
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
749
			break;
750
		case 'p2p_tls':
751
		case 'server_tls':
752
		case 'server_tls_user':
753
		case 'server_user':
754
			$ca = lookup_ca($settings['caref']);
755
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
756

    
757
			if (!empty($settings['certref'])) {
758
				$cert = lookup_cert($settings['certref']);
759
				openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
760
				openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
761
			}
762
			if ($mode == 'server')
763
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
764
			if (!empty($settings['crlref'])) {
765
				$crl = lookup_crl($settings['crlref']);
766
				crl_update($crl);
767
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
768
			}
769
			if ($settings['tls']) {
770
				if ($mode == "server")
771
					$tlsopt = 0;
772
				else
773
					$tlsopt = 1;
774
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
775
			}
776
			break;
777
	}
778

    
779
	if (!empty($settings['compression']))
780
		$conf .= "comp-lzo {$settings['compression']}\n";
781

    
782
	if ($settings['passtos'])
783
		$conf .= "passtos\n";
784

    
785
	if ($settings['resolve_retry'])
786
		$conf .= "resolv-retry infinite\n";
787

    
788
	if ($settings['dynamic_ip']) {
789
		$conf .= "persist-remote-ip\n";
790
		$conf .= "float\n";
791
	}
792

    
793
	if ($settings['topology_subnet']) {
794
		$conf .= "topology subnet\n";
795
	}
796

    
797
	// New client features
798
	if ($mode == "client") {
799
		// Dont pull routes checkbox
800
		if ($settings['route_no_pull']) {
801
			$conf .= "route-nopull\n";
802
		}
803

    
804
		// Dont add/remove routes checkbox
805
		if ($settings['route_no_exec']) {
806
			$conf .= "route-noexec\n";
807
		}
808
	}
809

    
810
	openvpn_add_custom($settings, $conf);
811

    
812
	openvpn_create_dirs();
813
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
814
	file_put_contents($fpath, $conf);
815
	unset($conf);
816
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
817
	file_put_contents($fpath, $interface);
818
	//chown($fpath, 'nobody');
819
	//chgrp($fpath, 'nobody');
820
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
821
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
822
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
823
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
824
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
825
}
826

    
827
function openvpn_restart($mode, $settings) {
828
	global $g, $config;
829

    
830
	$vpnid = $settings['vpnid'];
831
	$mode_id = $mode.$vpnid;
832

    
833
	/* kill the process if running */
834
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
835
	if (file_exists($pfile)) {
836

    
837
		/* read the pid file */
838
		$pid = rtrim(file_get_contents($pfile));
839
		unlink($pfile);
840

    
841
		/* send a term signal to the process */
842
		posix_kill($pid, SIGTERM);
843

    
844
		/* wait until the process exits */
845
		while(posix_kill($pid, 0))
846
			usleep(250000);
847
	}
848

    
849
	if (isset($settings['disable']))
850
		return;
851

    
852
	/* Do not start a client if we are a CARP backup on this vip! */
853
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) == "BACKUP"))
854
		return;
855

    
856
	/* Check if client is bound to a gateway group */
857
	$a_groups = return_gateway_groups_array();
858
	if (is_array($a_groups[$settings['interface']])) {
859
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
860
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
861
			return;
862
	}
863

    
864
	/* start the new process */
865
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
866
	openvpn_clear_route($mode, $settings);
867
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
868

    
869
	if (!$g['booting'])
870
		send_event("filter reload");
871
}
872

    
873
function openvpn_delete($mode, & $settings) {
874
	global $g, $config;
875

    
876
	$vpnid = $settings['vpnid'];
877
	$mode_id = $mode.$vpnid;
878

    
879
	if (isset($settings['dev_mode']))
880
		$tunname = "{$settings['dev_mode']}{$vpnid}";
881
	else {  /* defaults to tun */
882
		$tunname = "tun{$vpnid}";
883
	}
884

    
885
	if ($mode == "server")
886
		$devname = "ovpns{$vpnid}";
887
	else
888
		$devname = "ovpnc{$vpnid}";
889

    
890
	/* kill the process if running */
891
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
892
	if (file_exists($pfile)) {
893

    
894
		/* read the pid file */
895
		$pid = trim(file_get_contents($pfile));
896
		unlink($pfile);
897

    
898
		/* send a term signal to the process */
899
		posix_kill($pid, SIGTERM);
900
	}
901

    
902
	/* remove the device from the openvpn group */
903
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
904

    
905
	/* restore the original adapter name */
906
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
907

    
908
	/* remove the configuration files */
909
	@array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
910
}
911

    
912
function openvpn_cleanup_csc($common_name) {
913
	global $g, $config;
914
	if (empty($common_name))
915
		return;
916
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
917
	if (is_file($fpath))
918
		unlink_if_exists($fpath);
919
	return;
920
}
921

    
922
function openvpn_resync_csc(& $settings) {
923
	global $g, $config;
924

    
925
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
926

    
927
	if (isset($settings['disable'])) {
928
		unlink_if_exists($fpath);
929
		return;
930
	}
931
	openvpn_create_dirs();
932

    
933
	$conf = '';
934
	if ($settings['block'])
935
		$conf .= "disable\n";
936

    
937
	if ($settings['push_reset'])
938
		$conf .= "push-reset\n";
939

    
940
	if (!empty($settings['tunnel_network'])) {
941
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
942
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
943
		$serverip = long2ip32($baselong + 1);
944
		$clientip = long2ip32($baselong + 2);
945
		/* Because this is being pushed, the order from the client's point of view. */
946
		if ($settings['dev_mode'] != 'tap')
947
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
948
		else
949
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
950
	}
951

    
952
	if ($settings['local_network']) {
953
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
954
	}
955
	if ($settings['local_networkv6']) {
956
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
957
	}
958

    
959
	// Add a remote network iroute if set
960
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
961
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
962
	}
963
	// Add a remote network iroute if set
964
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
965
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
966
	}
967

    
968
	openvpn_add_dhcpopts($settings, $conf);
969

    
970
	if ($settings['gwredir'])
971
		$conf .= "push \"redirect-gateway def1\"\n";
972

    
973
	openvpn_add_custom($settings, $conf);
974

    
975
	file_put_contents($fpath, $conf);
976
	chown($fpath, 'nobody');
977
	chgrp($fpath, 'nobody');
978
}
979

    
980
function openvpn_delete_csc(& $settings) {
981
	global $g, $config;
982

    
983
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
984
	unlink_if_exists($fpath);
985
}
986

    
987
// Resync the configuration and restart the VPN
988
function openvpn_resync($mode, $settings) {
989
	openvpn_reconfigure($mode, $settings);
990
	openvpn_restart($mode, $settings);
991
}
992

    
993
// Resync and restart all VPNs
994
function openvpn_resync_all($interface = "") {
995
	global $g, $config;
996

    
997
	if ($g['platform'] == 'jail')
998
		return;
999
	openvpn_create_dirs();
1000

    
1001
	if (!is_array($config['openvpn']))
1002
		$config['openvpn'] = array();
1003

    
1004
/*
1005
	if (!$config['openvpn']['dh-parameters']) {
1006
		echo "Configuring OpenVPN Parameters ...\n";
1007
		$dh_parameters = openvpn_create_dhparams(1024);
1008
		$dh_parameters = base64_encode($dh_parameters);
1009
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1010
		write_config("OpenVPN DH parameters");
1011
	}
1012

    
1013
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1014
	if (!file_exists($path_ovdh)) {
1015
		$dh_parameters = $config['openvpn']['dh-parameters'];
1016
		$dh_parameters = base64_decode($dh_parameters);
1017
		file_put_contents($path_ovdh, $dh_parameters);
1018
	}
1019
*/
1020
	if ($interface <> "")
1021
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
1022
	else
1023
		log_error("Resyncing OpenVPN instances.");
1024

    
1025
	if (is_array($config['openvpn']['openvpn-server'])) {
1026
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1027
			if ($interface <> "" && $interface != $settings['interface'])
1028
				continue;
1029
			openvpn_resync('server', $settings);
1030
		}
1031
	}
1032

    
1033
	if (is_array($config['openvpn']['openvpn-client'])) {
1034
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1035
			if ($interface <> "" && $interface != $settings['interface'])
1036
				continue;
1037
			openvpn_resync('client', $settings);
1038
		}
1039
	}
1040

    
1041
	if (is_array($config['openvpn']['openvpn-csc']))
1042
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
1043
			openvpn_resync_csc($settings);
1044

    
1045
}
1046

    
1047
// Resync and restart all VPNs using a gateway group.
1048
function openvpn_resync_gwgroup($gwgroupname = "") {
1049
	global $g, $config;
1050

    
1051
	if ($gwgroupname <> "") {
1052
		if (is_array($config['openvpn']['openvpn-server'])) {
1053
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1054
				if ($gwgroupname == $settings['interface']) {
1055
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1056
					openvpn_resync('server', $settings);
1057
				}
1058
			}
1059
		}
1060

    
1061
		if (is_array($config['openvpn']['openvpn-client'])) {
1062
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1063
				if ($gwgroupname == $settings['interface']) {
1064
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1065
					openvpn_resync('client', $settings);
1066
				}
1067
			}
1068
		}
1069

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

    
1072
	} else
1073
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter.");
1074
}
1075

    
1076
function openvpn_get_active_servers($type="multipoint") {
1077
	global $config, $g;
1078

    
1079
	$servers = array();
1080
	if (is_array($config['openvpn']['openvpn-server'])) {
1081
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1082
			if (empty($settings) || isset($settings['disable']))
1083
				continue;
1084

    
1085
			$prot = $settings['protocol'];
1086
			$port = $settings['local_port'];
1087

    
1088
			$server = array();
1089
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1090
			$server['mode'] = $settings['mode'];
1091
			if ($settings['description'])
1092
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1093
			else
1094
				$server['name'] = "Server {$prot}:{$port}";
1095
			$server['conns'] = array();
1096
			$server['vpnid'] = $settings['vpnid'];
1097
			$server['mgmt'] = "server{$server['vpnid']}";
1098
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1099
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1100

    
1101
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1102
				$servers[] = openvpn_get_client_status($server, $socket);
1103
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1104
				$servers[] = openvpn_get_server_status($server, $socket);
1105

    
1106
		}
1107
	}
1108
	return $servers;
1109
}
1110

    
1111
function openvpn_get_server_status($server, $socket) {
1112
	$errval;
1113
	$errstr;
1114
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1115
	if ($fp) {
1116
		stream_set_timeout($fp, 1);
1117

    
1118
		/* send our status request */
1119
		fputs($fp, "status 2\n");
1120

    
1121
		/* recv all response lines */
1122
		while (!feof($fp)) {
1123

    
1124
			/* read the next line */
1125
			$line = fgets($fp, 1024);
1126

    
1127
			$info = stream_get_meta_data($fp);
1128
			if ($info['timed_out'])
1129
				break;
1130

    
1131
			/* parse header list line */
1132
			if (strstr($line, "HEADER"))
1133
				continue;
1134

    
1135
			/* parse end of output line */
1136
			if (strstr($line, "END") || strstr($line, "ERROR"))
1137
				break;
1138

    
1139
			/* parse client list line */
1140
			if (strstr($line, "CLIENT_LIST")) {
1141
				$list = explode(",", $line);
1142
				$conn = array();
1143
				$conn['common_name'] = $list[1];
1144
				$conn['remote_host'] = $list[2];
1145
				$conn['virtual_addr'] = $list[3];
1146
				$conn['bytes_recv'] = $list[4];
1147
				$conn['bytes_sent'] = $list[5];
1148
				$conn['connect_time'] = $list[6];
1149
				$server['conns'][] = $conn;
1150
			}
1151
			/* parse routing table lines */
1152
			if (strstr($line, "ROUTING_TABLE")) {
1153
				$list = explode(",", $line);
1154
				$conn = array();
1155
				$conn['virtual_addr'] = $list[1];
1156
				$conn['common_name'] = $list[2];
1157
				$conn['remote_host'] = $list[3];
1158
				$conn['last_time'] = $list[4];
1159
				$server['routes'][] = $conn;
1160
			}
1161
		}
1162

    
1163
		/* cleanup */
1164
		fclose($fp);
1165
	} else {
1166
		$conn = array();
1167
		$conn['common_name'] = "[error]";
1168
		$conn['remote_host'] = "Unable to contact daemon";
1169
		$conn['virtual_addr'] = "Service not running?";
1170
		$conn['bytes_recv'] = 0;
1171
		$conn['bytes_sent'] = 0;
1172
		$conn['connect_time'] = 0;
1173
		$server['conns'][] = $conn;
1174
	}
1175
	return $server;
1176
}
1177

    
1178
function openvpn_get_active_clients() {
1179
	global $config, $g;
1180

    
1181
	$clients = array();
1182
	if (is_array($config['openvpn']['openvpn-client'])) {
1183
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1184

    
1185
			if (empty($settings) || isset($settings['disable']))
1186
				continue;
1187

    
1188
			$prot = $settings['protocol'];
1189
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1190

    
1191
			$client = array();
1192
			$client['port'] = $settings['local_port'];
1193
			if ($settings['description'])
1194
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1195
			else
1196
				$client['name'] = "Client {$prot}{$port}";
1197

    
1198
			$client['vpnid'] = $settings['vpnid'];
1199
			$client['mgmt'] = "client{$client['vpnid']}";
1200
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1201
			$client['status']="down";
1202

    
1203
			$clients[] = openvpn_get_client_status($client, $socket);
1204
		}
1205
	}
1206
	return $clients;
1207
}
1208

    
1209
function openvpn_get_client_status($client, $socket) {
1210
	$errval;
1211
	$errstr;
1212
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1213
	if ($fp) {
1214
		stream_set_timeout($fp, 1);
1215
		/* send our status request */
1216
		fputs($fp, "state 1\n");
1217

    
1218
		/* recv all response lines */
1219
		while (!feof($fp)) {
1220
			/* read the next line */
1221
			$line = fgets($fp, 1024);
1222

    
1223
			$info = stream_get_meta_data($fp);
1224
			if ($info['timed_out'])
1225
				break;
1226

    
1227
			/* Get the client state */
1228
			if (strstr($line,"CONNECTED")) {
1229
				$client['status']="up";
1230
				$list = explode(",", $line);
1231

    
1232
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1233
				$client['virtual_addr']  = $list[3];
1234
				$client['remote_host'] = $list[4];
1235
			}
1236
			if (strstr($line,"CONNECTING")) {
1237
				$client['status']="connecting";
1238
			}
1239
			if (strstr($line,"ASSIGN_IP")) {
1240
				$client['status']="waiting";
1241
				$list = explode(",", $line);
1242

    
1243
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1244
				$client['virtual_addr']  = $list[3];
1245
			}
1246
			if (strstr($line,"RECONNECTING")) {
1247
				$client['status']="reconnecting";
1248
				$list = explode(",", $line);
1249

    
1250
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1251
				$client['status'] .= "; " . $list[2];
1252
			}
1253
			/* parse end of output line */
1254
			if (strstr($line, "END") || strstr($line, "ERROR"))
1255
				break;
1256
		}
1257

    
1258
		/* If up, get read/write stats */
1259
		if (strcmp($client['status'], "up") == 0) {
1260
			fputs($fp, "status 2\n");
1261
			/* recv all response lines */
1262
			while (!feof($fp)) {
1263
				/* read the next line */
1264
				$line = fgets($fp, 1024);
1265

    
1266
				$info = stream_get_meta_data($fp);
1267
				if ($info['timed_out'])
1268
					break;
1269

    
1270
				if (strstr($line,"TCP/UDP read bytes")) {
1271
					$list = explode(",", $line);
1272
					$client['bytes_recv'] = $list[1];
1273
				}
1274

    
1275
				if (strstr($line,"TCP/UDP write bytes")) {
1276
					$list = explode(",", $line);
1277
					$client['bytes_sent'] = $list[1];
1278
				}
1279

    
1280
				/* parse end of output line */
1281
				if (strstr($line, "END"))
1282
					break;
1283
			}
1284
		}
1285

    
1286
		fclose($fp);
1287

    
1288
	} else {
1289
		$DisplayNote=true;
1290
		$client['remote_host'] = "Unable to contact daemon";
1291
		$client['virtual_addr'] = "Service not running?";
1292
		$client['bytes_recv'] = 0;
1293
		$client['bytes_sent'] = 0;
1294
		$client['connect_time'] = 0;
1295
	}
1296
	return $client;
1297
}
1298

    
1299
function openvpn_refresh_crls() {
1300
	global $g, $config;
1301

    
1302
	openvpn_create_dirs();
1303

    
1304
	if (is_array($config['openvpn']['openvpn-server'])) {
1305
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1306
			if (empty($settings))
1307
				continue;
1308
			if (isset($settings['disable']))
1309
				continue;
1310
			// Write the settings for the keys
1311
			switch($settings['mode']) {
1312
				case 'p2p_tls':
1313
				case 'server_tls':
1314
				case 'server_tls_user':
1315
				case 'server_user':
1316
					if (!empty($settings['crlref'])) {
1317
						$crl = lookup_crl($settings['crlref']);
1318
						crl_update($crl);
1319
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1320
						file_put_contents($fpath, base64_decode($crl['text']));
1321
						@chmod($fpath, 0644);
1322
					}
1323
					break;
1324
			}
1325
		}
1326
	}
1327
}
1328

    
1329
function openvpn_create_dirs() {
1330
	global $g;
1331
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1332
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1333
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1334
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1335
}
1336

    
1337
function openvpn_get_interface_ip($ip, $mask) {
1338
	$baselong = ip2long32($ip) & ip2long($mask);
1339
	$ip1 = long2ip32($baselong + 1);
1340
	$ip2 = long2ip32($baselong + 2);
1341
	return array($ip1, $ip2);
1342
}
1343

    
1344
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1345
	$basev6 = gen_subnetv6($ipv6, $prefix);
1346
	// Is there a better way to do this math?
1347
	$ipv6_arr = explode(':', $basev6);
1348
	$last = hexdec(array_pop($ipv6_arr));
1349
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1350
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1351
	return array($ipv6_1, $ipv6_2);
1352
}
1353

    
1354
function openvpn_clear_route($mode, $settings) {
1355
	if (empty($settings['tunnel_network']))
1356
		return;
1357
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1358
	$mask = gen_subnet_mask($cidr);
1359
	$clear_route = false;
1360

    
1361
	switch($settings['mode']) {
1362
		case 'shared_key':
1363
			$clear_route = true;
1364
			break;
1365
		case 'p2p_tls':
1366
		case 'p2p_shared_key':
1367
			if ($cidr == 30)
1368
				$clear_route = true;
1369
			break;
1370
	}
1371

    
1372
	if ($clear_route && !empty($ip) && !empty($mask)) {
1373
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1374
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1375
		/* XXX: Family for route? */
1376
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1377
	}
1378
}
1379

    
1380
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1381
	$routes = "";
1382
	if (empty($value))
1383
		return "";
1384
	$networks = explode(',', $value);
1385

    
1386
	foreach ($networks as $network) {
1387
		if ($ipproto == "ipv4")
1388
			$route = openvpn_gen_route_ipv4($network, $iroute);
1389
		else
1390
			$route = openvpn_gen_route_ipv6($network, $iroute);
1391

    
1392
		if ($push)
1393
			$routes .= "push \"{$route}\"\n";
1394
		else
1395
			$routes .= "{$route}\n";
1396
	}
1397
	return $routes;
1398
}
1399

    
1400
function openvpn_gen_route_ipv4($network, $iroute = false) {
1401
	$i = ($iroute) ? "i" : "";
1402
	list($ip, $mask) = explode('/', trim($network));
1403
	$mask = gen_subnet_mask($mask);
1404
	return "{$i}route $ip $mask";
1405
}
1406

    
1407
function openvpn_gen_route_ipv6($network, $iroute = false) {
1408
	$i = ($iroute) ? "i" : "";
1409
	list($ipv6, $prefix) = explode('/', trim($network));
1410
	if (empty($prefix))
1411
		$prefix = "128";
1412
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1413
}
1414

    
1415
function openvpn_get_settings($mode, $vpnid) {
1416
	global $config;
1417

    
1418
	if (is_array($config['openvpn']['openvpn-server'])) {
1419
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1420
			if (isset($settings['disable']))
1421
				continue;
1422

    
1423
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1424
				return $settings;
1425
		}
1426
	}
1427

    
1428
	if (is_array($config['openvpn']['openvpn-client'])) {
1429
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1430
			if (isset($settings['disable']))
1431
				continue;
1432

    
1433
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1434
				return $settings;
1435
		}
1436
	}
1437

    
1438
	return array();
1439
}
1440

    
1441
function openvpn_restart_by_vpnid($mode, $vpnid) {
1442
	$settings = openvpn_get_settings($mode, $vpnid);
1443
	openvpn_restart($mode, $settings);
1444
}
1445

    
1446
?>
(38-38/68)