Projet

Général

Profil

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

univnautes / etc / inc / openvpn.inc @ b9e9903d

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['ntp_server1']))
354
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
355
	if (!empty($settings['ntp_server2']))
356
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
357

    
358
	if ($settings['netbios_enable']) {
359

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

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

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

    
374
	if ($settings['gwredir']) 
375
		$conf .= "push \"redirect-gateway def1\"\n";
376
}
377

    
378
function openvpn_add_custom(& $settings, & $conf) {
379

    
380
	if ($settings['custom_options']) {
381

    
382
		$options = explode(';', $settings['custom_options']);
383

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

    
392
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
393
	global $g;
394

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

    
402
	$conf .= "{$directive} {$fpath} {$opt}\n";
403
}
404

    
405
function openvpn_reconfigure($mode, $settings) {
406
	global $g, $config;
407

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

    
419
	$vpnid = $settings['vpnid'];
420
	$mode_id = $mode.$vpnid;
421

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

    
429
	if ($mode == "server")
430
		$devname = "ovpns{$vpnid}";
431
	else
432
		$devname = "ovpnc{$vpnid}";
433

    
434
	/* is our device already configured */
435
	if (!does_interface_exist($devname)) {
436

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

    
441
		/* rename the device */
442
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
443

    
444
		/* add the device to the openvpn group */
445
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn");
446
	}
447

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

    
457
	$interface = get_failover_interface($settings['interface']);
458
	$ipaddr = $settings['ipaddr'];
459
	$ipaddrv6 = $settings['ipaddrv6'];
460

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

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

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

    
523
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
524
		$conf .= "engine {$settings['engine']}\n";
525

    
526
	// server specific settings
527
	if ($mode == 'server') {
528

    
529
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
530
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
531
		$mask = gen_subnet_mask($cidr);
532

    
533
		// configure tls modes
534
		switch($settings['mode']) {
535
			case 'p2p_tls':
536
			case 'server_tls':
537
			case 'server_user':
538
			case 'server_tls_user':
539
				$conf .= "tls-server\n";
540
				break;
541
		}
542

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

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

    
627
		// The local port to listen on
628
		$conf .= "lport {$settings['local_port']}\n";
629

    
630
		// The management port to listen on
631
		// Use unix socket to overcome the problem on any type of server
632
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
633
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
634

    
635
		if ($settings['maxclients'])
636
			$conf .= "max-clients {$settings['maxclients']}\n";
637

    
638
		// Can we push routes
639
		if ($settings['local_network']) {
640
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
641
		}
642
		if ($settings['local_networkv6']) {
643
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
644
		}
645

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

    
660
	// client specific settings
661

    
662
	if ($mode == 'client') {
663

    
664
		// configure p2p mode
665
		switch($settings['mode']) {
666
			case 'p2p_tls':
667
				$conf .= "tls-client\n";
668
			case 'shared_key':
669
				$conf .= "client\n";
670
				break;
671
		}
672

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

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

    
686
		// The remote server
687
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
688

    
689
		if (!empty($settings['use_shaper']))
690
			$conf .= "shaper {$settings['use_shaper']}\n";
691

    
692
		if (!empty($settings['tunnel_network'])) {
693
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
694
			$mask = gen_subnet_mask($mask);
695
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
696
			if ($settings['dev_mode'] == 'tun')
697
				$conf .= "ifconfig {$ip2} {$ip1}\n";
698
			else
699
				$conf .= "ifconfig {$ip2} {$mask}\n";
700
		}
701

    
702
		if (!empty($settings['tunnel_networkv6'])) {
703
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
704
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
705
			if ($settings['dev_mode'] == 'tun')
706
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
707
			else
708
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
709
		}
710

    
711
		if ($settings['auth_user'] && $settings['auth_pass']) {
712
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
713
			$conf .= "auth-user-pass {$up_file}\n";
714
			$userpass = "{$settings['auth_user']}\n";
715
			$userpass .= "{$settings['auth_pass']}\n";
716
			file_put_contents($up_file, $userpass);
717
		}
718
		
719
		if ($settings['proxy_addr']) {
720
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
721
			if ($settings['proxy_authtype'] != "none") {
722
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
723
				$proxypas = "{$settings['proxy_user']}\n";
724
				$proxypas .= "{$settings['proxy_passwd']}\n";
725
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
726
			}
727
			$conf .= " \n";
728
		}
729
	}
730

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

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

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

    
774
	if (!empty($settings['compression']))
775
		$conf .= "comp-lzo {$settings['compression']}\n";
776

    
777
	if ($settings['passtos'])
778
		$conf .= "passtos\n";
779

    
780
	if ($settings['resolve_retry'])
781
		$conf .= "resolv-retry infinite\n";
782

    
783
	if ($settings['dynamic_ip']) {
784
		$conf .= "persist-remote-ip\n";
785
		$conf .= "float\n";
786
	}
787

    
788
	if ($settings['topology_subnet']) {
789
		$conf .= "topology subnet\n";
790
	}
791

    
792
	// New client features
793
	if ($mode == "client") {
794
		// Dont pull routes checkbox
795
		if ($settings['route_no_pull']) {
796
			$conf .= "route-nopull\n";
797
		}
798

    
799
		// Dont add/remove routes checkbox
800
		if ($settings['route_no_exec']) {
801
			$conf .= "route-noexec\n";
802
		}
803
	}
804

    
805
	openvpn_add_custom($settings, $conf);
806

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

    
822
function openvpn_restart($mode, $settings) {
823
	global $g, $config;
824

    
825
	$vpnid = $settings['vpnid'];
826
	$mode_id = $mode.$vpnid;
827

    
828
	/* kill the process if running */
829
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
830
	if (file_exists($pfile)) {
831

    
832
		/* read the pid file */
833
		$pid = rtrim(file_get_contents($pfile));
834
		unlink($pfile);
835

    
836
		/* send a term signal to the process */
837
		posix_kill($pid, SIGTERM);
838

    
839
		/* wait until the process exits */
840
		while(posix_kill($pid, 0))
841
			usleep(250000);
842
	}
843

    
844
	if (isset($settings['disable']))
845
		return;
846

    
847
	/* Do not start a client if we are a CARP backup on this vip! */
848
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) == "BACKUP"))
849
		return;
850
		
851
	/* Check if client is bound to a gateway group */    
852
	$a_groups = return_gateway_groups_array();
853
	if (is_array($a_groups[$settings['interface']])) {
854
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
855
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
856
			return;
857
	}
858

    
859
	/* start the new process */
860
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
861
	openvpn_clear_route($mode, $settings);
862
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
863

    
864
	if (!$g['booting'])
865
		send_event("filter reload");
866
}
867

    
868
function openvpn_delete($mode, & $settings) {
869
	global $g, $config;
870

    
871
	$vpnid = $settings['vpnid'];
872
	$mode_id = $mode.$vpnid;
873

    
874
	if (isset($settings['dev_mode']))
875
		$tunname = "{$settings['dev_mode']}{$vpnid}";
876
	else {  /* defaults to tun */
877
		$tunname = "tun{$vpnid}";
878
	}
879

    
880
	if ($mode == "server")
881
		$devname = "ovpns{$vpnid}";
882
	else
883
		$devname = "ovpnc{$vpnid}";
884

    
885
	/* kill the process if running */
886
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
887
	if (file_exists($pfile)) {
888

    
889
		/* read the pid file */
890
		$pid = trim(file_get_contents($pfile));
891
		unlink($pfile);
892

    
893
		/* send a term signal to the process */
894
		posix_kill($pid, SIGTERM);
895
	}
896

    
897
	/* remove the device from the openvpn group */
898
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
899

    
900
	/* restore the original adapter name */
901
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
902

    
903
	/* remove the configuration files */
904
	array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
905
}
906

    
907
function openvpn_cleanup_csc($common_name) {
908
	global $g, $config;
909
	if (empty($common_name))
910
		return;
911
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
912
	if (is_file($fpath))
913
		unlink_if_exists($fpath);
914
	return;
915
}
916

    
917
function openvpn_resync_csc(& $settings) {
918
	global $g, $config;
919

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

    
922
	if (isset($settings['disable'])) {
923
		unlink_if_exists($fpath);
924
		return;
925
	}
926
	openvpn_create_dirs();
927

    
928
	$conf = '';
929
	if ($settings['block'])
930
		$conf .= "disable\n";
931

    
932
	if ($settings['push_reset'])
933
		$conf .= "push-reset\n";
934

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

    
947
	if ($settings['local_network']) {
948
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
949
	}
950
	if ($settings['local_networkv6']) {
951
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
952
	}
953

    
954
	// Add a remote network iroute if set
955
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
956
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
957
	}
958
	// Add a remote network iroute if set
959
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
960
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
961
	}
962

    
963
	openvpn_add_dhcpopts($settings, $conf);
964

    
965
	if ($settings['gwredir'])
966
		$conf .= "push \"redirect-gateway def1\"\n";
967

    
968
	openvpn_add_custom($settings, $conf);
969

    
970
	file_put_contents($fpath, $conf);
971
	chown($fpath, 'nobody');
972
	chgrp($fpath, 'nobody');
973
}
974

    
975
function openvpn_delete_csc(& $settings) {
976
	global $g, $config;
977

    
978
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
979
	unlink_if_exists($fpath);
980
}
981

    
982
// Resync the configuration and restart the VPN
983
function openvpn_resync($mode, $settings) {
984
	openvpn_reconfigure($mode, $settings);
985
	openvpn_restart($mode, $settings);
986
}
987

    
988
// Resync and restart all VPNs
989
function openvpn_resync_all($interface = "") {
990
	global $g, $config;
991

    
992
	if ($g['platform'] == 'jail')
993
		return;
994
	openvpn_create_dirs();
995

    
996
	if (!is_array($config['openvpn']))
997
		$config['openvpn'] = array();
998

    
999
/*
1000
	if (!$config['openvpn']['dh-parameters']) {
1001
		echo "Configuring OpenVPN Parameters ...\n";
1002
		$dh_parameters = openvpn_create_dhparams(1024);
1003
		$dh_parameters = base64_encode($dh_parameters);
1004
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1005
		write_config("OpenVPN DH parameters");
1006
	}
1007

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

    
1020
	if (is_array($config['openvpn']['openvpn-server'])) {
1021
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1022
			if ($interface <> "" && $interface != $settings['interface'])
1023
				continue;
1024
			openvpn_resync('server', $settings);
1025
		}
1026
	}
1027

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

    
1036
	if (is_array($config['openvpn']['openvpn-csc']))
1037
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
1038
			openvpn_resync_csc($settings);
1039

    
1040
}
1041

    
1042
// Resync and restart all VPNs using a gateway group.
1043
function openvpn_resync_gwgroup($gwgroupname = "") {
1044
	global $g, $config;
1045

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

    
1056
		if (is_array($config['openvpn']['openvpn-client'])) {
1057
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1058
				if ($gwgroupname == $settings['interface']) {
1059
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1060
					openvpn_resync('client', $settings);
1061
				}
1062
			}
1063
		}
1064

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

    
1067
	} else
1068
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1069
}
1070

    
1071
function openvpn_get_active_servers($type="multipoint") {
1072
	global $config, $g;
1073

    
1074
	$servers = array();
1075
	if (is_array($config['openvpn']['openvpn-server'])) {
1076
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1077
			if (empty($settings) || isset($settings['disable']))
1078
				continue;
1079

    
1080
			$prot = $settings['protocol'];
1081
			$port = $settings['local_port'];
1082
	
1083
			$server = array();
1084
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1085
			$server['mode'] = $settings['mode'];
1086
			if ($settings['description'])
1087
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1088
			else
1089
				$server['name'] = "Server {$prot}:{$port}";
1090
			$server['conns'] = array();
1091
			$server['vpnid'] = $settings['vpnid'];
1092
			$server['mgmt'] = "server{$server['vpnid']}";
1093
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1094
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1095

    
1096
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1097
				$servers[] = openvpn_get_client_status($server, $socket);
1098
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1099
				$servers[] = openvpn_get_server_status($server, $socket);
1100

    
1101
		}
1102
	}
1103
	return $servers;
1104
}
1105

    
1106
function openvpn_get_server_status($server, $socket) {
1107
	$errval;
1108
	$errstr;
1109
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1110
	if ($fp) {
1111
		stream_set_timeout($fp, 1);
1112

    
1113
		/* send our status request */
1114
		fputs($fp, "status 2\n");
1115

    
1116
		/* recv all response lines */
1117
		while (!feof($fp)) {
1118

    
1119
			/* read the next line */
1120
			$line = fgets($fp, 1024);
1121

    
1122
			$info = stream_get_meta_data($fp);
1123
			if ($info['timed_out'])
1124
				break;
1125

    
1126
			/* parse header list line */
1127
			if (strstr($line, "HEADER"))
1128
				continue;
1129

    
1130
			/* parse end of output line */
1131
			if (strstr($line, "END") || strstr($line, "ERROR"))
1132
				break;
1133

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

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

    
1173
function openvpn_get_active_clients() {
1174
	global $config, $g;
1175

    
1176
	$clients = array();
1177
	if (is_array($config['openvpn']['openvpn-client'])) {
1178
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1179
	
1180
			if (empty($settings) || isset($settings['disable']))
1181
				continue;
1182

    
1183
			$prot = $settings['protocol'];
1184
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1185
	
1186
			$client = array();
1187
			$client['port'] = $settings['local_port'];
1188
			if ($settings['description'])
1189
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1190
			else
1191
				$client['name'] = "Client {$prot}{$port}";
1192
	
1193
			$client['vpnid'] = $settings['vpnid'];
1194
			$client['mgmt'] = "client{$client['vpnid']}";
1195
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1196
			$client['status']="down";
1197

    
1198
			$clients[] = openvpn_get_client_status($client, $socket);
1199
		}
1200
	}
1201
	return $clients;
1202
}
1203

    
1204
function openvpn_get_client_status($client, $socket) {
1205
	$errval;
1206
	$errstr;
1207
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1208
	if ($fp) {
1209
		stream_set_timeout($fp, 1);
1210
		/* send our status request */
1211
		fputs($fp, "state 1\n");
1212

    
1213
		/* recv all response lines */
1214
		while (!feof($fp)) {
1215
			/* read the next line */
1216
			$line = fgets($fp, 1024);
1217

    
1218
			$info = stream_get_meta_data($fp);
1219
			if ($info['timed_out'])
1220
				break;
1221

    
1222
			/* Get the client state */
1223
			if (strstr($line,"CONNECTED")) {
1224
				$client['status']="up";
1225
				$list = explode(",", $line);
1226

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

    
1238
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1239
				$client['virtual_addr']  = $list[3];
1240
			}
1241
			if (strstr($line,"RECONNECTING")) {
1242
				$client['status']="reconnecting";
1243
				$list = explode(",", $line);
1244

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

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

    
1261
				$info = stream_get_meta_data($fp);
1262
				if ($info['timed_out'])
1263
					break;
1264

    
1265
				if (strstr($line,"TCP/UDP read bytes")) {
1266
					$list = explode(",", $line);
1267
					$client['bytes_recv'] = $list[1];
1268
				}
1269

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

    
1275
				/* parse end of output line */
1276
				if (strstr($line, "END"))
1277
					break;
1278
			}
1279
		}
1280

    
1281
		fclose($fp);
1282

    
1283
	} else {
1284
		$DisplayNote=true;
1285
		$client['remote_host'] = "Unable to contact daemon";
1286
		$client['virtual_addr'] = "Service not running?";
1287
		$client['bytes_recv'] = 0;
1288
		$client['bytes_sent'] = 0;
1289
		$client['connect_time'] = 0;
1290
	}
1291
	return $client;
1292
}
1293

    
1294
function openvpn_refresh_crls() {
1295
	global $g, $config;
1296

    
1297
	openvpn_create_dirs();
1298

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

    
1324
function openvpn_create_dirs() {
1325
	global $g;
1326
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1327
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1328
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1329
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1330
}
1331

    
1332
function openvpn_get_interface_ip($ip, $mask) {
1333
	$baselong = ip2long32($ip) & ip2long($mask);
1334
	$ip1 = long2ip32($baselong + 1);
1335
	$ip2 = long2ip32($baselong + 2);
1336
	return array($ip1, $ip2);
1337
}
1338

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

    
1349
function openvpn_clear_route($mode, $settings) {
1350
	if (empty($settings['tunnel_network']))
1351
		return;
1352
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1353
	$mask = gen_subnet_mask($cidr);
1354
	$clear_route = false;
1355

    
1356
	switch($settings['mode']) {
1357
		case 'shared_key':
1358
			$clear_route = true;
1359
			break;
1360
		case 'p2p_tls':
1361
		case 'p2p_shared_key':
1362
			if ($cidr == 30)
1363
				$clear_route = true;
1364
			break;
1365
	}
1366

    
1367
	if ($clear_route && !empty($ip) && !empty($mask)) {
1368
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1369
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1370
		/* XXX: Family for route? */
1371
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1372
	}
1373
}
1374

    
1375
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1376
	$routes = "";
1377
	if (empty($value))
1378
		return "";
1379
	$networks = explode(',', $value);
1380

    
1381
	foreach ($networks as $network) {
1382
		if ($ipproto == "ipv4")
1383
			$route = openvpn_gen_route_ipv4($network, $iroute);
1384
		else
1385
			$route = openvpn_gen_route_ipv6($network, $iroute);
1386

    
1387
		if ($push)
1388
			$routes .= "push \"{$route}\"\n";
1389
		else
1390
			$routes .= "{$route}\n";
1391
	}
1392
	return $routes;
1393
}
1394

    
1395
function openvpn_gen_route_ipv4($network, $iroute = false) {
1396
	$i = ($iroute) ? "i" : "";
1397
	list($ip, $mask) = explode('/', trim($network));
1398
	$mask = gen_subnet_mask($mask);
1399
	return "{$i}route $ip $mask";
1400
}
1401

    
1402
function openvpn_gen_route_ipv6($network, $iroute = false) {
1403
	$i = ($iroute) ? "i" : "";
1404
	list($ipv6, $prefix) = explode('/', trim($network));
1405
	if (empty($prefix))
1406
		$prefix = "128";
1407
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1408
}
1409

    
1410
function openvpn_get_settings($mode, $vpnid) {
1411
	global $config;
1412

    
1413
	if (is_array($config['openvpn']['openvpn-server'])) {
1414
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1415
			if (isset($settings['disable']))
1416
				continue;
1417

    
1418
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1419
				return $settings;
1420
		}
1421
	}
1422

    
1423
	if (is_array($config['openvpn']['openvpn-client'])) {
1424
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1425
			if (isset($settings['disable']))
1426
				continue;
1427

    
1428
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1429
				return $settings;
1430
		}
1431
	}
1432

    
1433
	return array();
1434
}
1435

    
1436
function openvpn_restart_by_vpnid($mode, $vpnid) {
1437
	$settings = openvpn_get_settings($mode, $vpnid);
1438
	openvpn_restart($mode, $settings);
1439
}
1440

    
1441
?>
(38-38/68)