Projet

Général

Profil

Télécharger (41,8 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / openvpn.inc @ 2da48592

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
/* 
59
 * The User Auth mode below is disabled because
60
 * OpenVPN erroneously requires that we provide
61
 * a CA configuration parameter. In this mode,
62
 * clients don't send a certificate so there is
63
 * no need for a CA. If we require that admins
64
 * provide one in the pfSense UI due to a bogus
65
 * requirement imposed by OpenVPN, it could be
66
 * considered very confusing ( I know I was ).
67
 *
68
 * -mgrooms
69
 */
70

    
71
global $openvpn_dh_lengths;
72
$openvpn_dh_lengths = array(
73
	1024, 2048, 4096 );
74

    
75
global $openvpn_cert_depths;
76
$openvpn_cert_depths = array(
77
	1 => "One (Client+Server)",
78
	2 => "Two (Client+Intermediate+Server)",
79
	3 => "Three (Client+2xIntermediate+Server)",
80
	4 => "Four (Client+3xIntermediate+Server)",
81
	5 => "Five (Client+4xIntermediate+Server)"
82
);
83

    
84
global $openvpn_server_modes;
85
$openvpn_server_modes = array(
86
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
87
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
88
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
89
	'server_user' => gettext("Remote Access ( User Auth )"),
90
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
91

    
92
global $openvpn_client_modes;
93
$openvpn_client_modes = array(
94
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
95
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )") );
96

    
97
global $openvpn_compression_modes;
98
$openvpn_compression_modes = array(
99
	'' =>	gettext("No Preference"),
100
	'no' =>		gettext("Disabled - No Compression"),
101
	'adaptive' =>	gettext("Enabled with Adaptive Compression"),
102
	'yes' =>	gettext("Enabled without Adaptive Compression"));
103

    
104
function openvpn_create_key() {
105

    
106
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
107
	if (!$fp)
108
		return false;
109

    
110
	$rslt = stream_get_contents($fp);
111
	pclose($fp);
112

    
113
	return $rslt;
114
}
115

    
116
function openvpn_create_dhparams($bits) {
117

    
118
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
119
	if (!$fp)
120
		return false;
121

    
122
	$rslt = stream_get_contents($fp);
123
	pclose($fp);
124

    
125
	return $rslt;
126
}
127

    
128
function openvpn_vpnid_used($vpnid) {
129
	global $config;
130

    
131
	if (is_array($config['openvpn']['openvpn-server']))
132
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
133
			if ($vpnid == $settings['vpnid'])
134
				return true;
135

    
136
	if (is_array($config['openvpn']['openvpn-client']))
137
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
138
			if ($vpnid == $settings['vpnid'])
139
				return true;
140

    
141
	return false;
142
}
143

    
144
function openvpn_vpnid_next() {
145

    
146
	$vpnid = 1;
147
	while(openvpn_vpnid_used($vpnid))
148
		$vpnid++;
149

    
150
	return $vpnid;
151
}
152

    
153
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
154
	global $config;
155

    
156
	if (is_array($config['openvpn']['openvpn-server'])) {
157
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
158
			if (isset($settings['disable']))
159
				continue;
160

    
161
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
162
				continue;
163

    
164
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
165
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
166
				return $settings['vpnid'];
167
		}
168
	}
169

    
170
	if (is_array($config['openvpn']['openvpn-client'])) {
171
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
172
			if (isset($settings['disable']))
173
				continue;
174

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

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

    
184
	return 0;
185
}
186

    
187
function openvpn_port_next($prot, $interface = "wan") {
188

    
189
	$port = 1194;
190
	while(openvpn_port_used($prot, $interface, $port))
191
		$port++;
192
	while(openvpn_port_used($prot, "any", $port))
193
		$port++;
194

    
195
	return $port;
196
}
197

    
198
function openvpn_get_cipherlist() {
199

    
200
	$ciphers = array();
201
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
202
	$cipher_lines = explode("\n", trim($cipher_out));
203
	sort($cipher_lines);
204
	foreach ($cipher_lines as $line) {
205
		$words = explode(' ', $line);
206
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
207
	}
208
	$ciphers["none"] = gettext("None (No Encryption)");
209
	return $ciphers;
210
}
211

    
212
function openvpn_get_digestlist() {
213

    
214
	$digests = array();
215
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
216
	$digest_lines = explode("\n", trim($digest_out));
217
	sort($digest_lines);
218
	foreach ($digest_lines as $line) {
219
		$words = explode(' ', $line);
220
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
221
	}
222
	$digests["none"] = gettext("None (No Authentication)");
223
	return $digests;
224
}
225

    
226
function openvpn_get_engines() {
227
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
228
	exec("/usr/bin/openssl engine -t -c", $openssl_engine_output);
229
	$openssl_engine_output = implode("\n", $openssl_engine_output);
230
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
231
	$openssl_engine_output = explode("\n", $openssl_engine_output);
232

    
233
	foreach ($openssl_engine_output as $oeo) {
234
		$keep = true;
235
		$details = explode("|", $oeo);
236
		$engine = array_shift($details);
237
		$linematch = array();
238
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
239
		foreach ($details as $dt) {
240
			if (strpos($dt, "unavailable") !== FALSE)
241
				$keep = false;
242
			if (strpos($dt, "available") !== FALSE)
243
				continue;
244
			if (strpos($dt, "[") !== FALSE)
245
				$ciphers = trim($dt, "[]");
246
		}
247
		if (!empty($ciphers))
248
			$ciphers = " - " . $ciphers;
249
		if (strlen($ciphers) > 60)
250
			$ciphers = substr($ciphers, 0, 60) . " ... ";
251
		if ($keep)
252
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
253
	}
254
	return $openssl_engines;
255
}
256

    
257
function openvpn_validate_engine($engine) {
258
	$engines = openvpn_get_engines();
259
	return array_key_exists($engine, $engines);
260
}
261

    
262
function openvpn_validate_host($value, $name) {
263
	$value = trim($value);
264
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
265
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
266
	return false;
267
}
268

    
269
function openvpn_validate_port($value, $name) {
270
	$value = trim($value);
271
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
272
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
273
	return false;
274
}
275

    
276
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
277
	$value = trim($value);
278
	$error = false;
279
	if (empty($value))
280
		return false;
281
	$networks = explode(',', $value);
282

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

    
286
	foreach ($networks as $network) {
287
		if ($ipproto == "ipv4")
288
			$error = !openvpn_validate_cidr_ipv4($network);
289
		else
290
			$error = !openvpn_validate_cidr_ipv6($network);
291
		if ($error)
292
			break;
293
	}
294

    
295
	if ($error)
296
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
297
	else
298
		return false;
299
}
300

    
301
function openvpn_validate_cidr_ipv4($value) {
302
	$value = trim($value);
303
	if (!empty($value)) {
304
		list($ip, $mask) = explode('/', $value);
305
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
306
			return false;
307
	}
308
	return true;
309
}
310

    
311
function openvpn_validate_cidr_ipv6($value) {
312
	$value = trim($value);
313
	if (!empty($value)) {
314
		list($ipv6, $prefix) = explode('/', $value);
315
		if (empty($prefix))
316
			$prefix = "128";
317
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0))
318
			return false;
319
	}
320
	return true;
321
}
322

    
323
function openvpn_add_dhcpopts(& $settings, & $conf) {
324

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

    
328
	if (!empty($settings['dns_server1']))
329
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
330
	if (!empty($settings['dns_server2']))
331
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
332
	if (!empty($settings['dns_server3']))
333
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
334
	if (!empty($settings['dns_server4']))
335
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
336

    
337
	if (!empty($settings['ntp_server1']))
338
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
339
	if (!empty($settings['ntp_server2']))
340
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
341

    
342
	if ($settings['netbios_enable']) {
343

    
344
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
345
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
346
		if (!empty($settings['dhcp_nbtscope'])) 
347
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
348

    
349
		if (!empty($settings['wins_server1']))
350
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
351
		if (!empty($settings['wins_server2']))
352
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
353

    
354
		if (!empty($settings['nbdd_server1']))
355
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
356
	}
357

    
358
	if ($settings['gwredir']) 
359
		$conf .= "push \"redirect-gateway def1\"\n";
360
}
361

    
362
function openvpn_add_custom(& $settings, & $conf) {
363

    
364
	if ($settings['custom_options']) {
365

    
366
		$options = explode(';', $settings['custom_options']);
367

    
368
		if (is_array($options)) {
369
			foreach ($options as $option)
370
				$conf .= "$option\n";
371
		} else
372
			$conf .= "{$settings['custom_options']}\n";
373
	}
374
}
375

    
376
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
377
	global $g;
378

    
379
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
380
	openvpn_create_dirs();
381
	file_put_contents($fpath, base64_decode($data));
382
	//chown($fpath, 'nobody');
383
	//chgrp($fpath, 'nobody');
384
	@chmod($fpath, 0600);
385

    
386
	$conf .= "{$directive} {$fpath} {$opt}\n";
387
}
388

    
389
function openvpn_reconfigure($mode, $settings) {
390
	global $g, $config;
391

    
392
	if (empty($settings))
393
		return;
394
	if (isset($settings['disable'])) 
395
		return;
396
	openvpn_create_dirs();
397
	/*
398
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
399
	 * we use a vpnid number which is allocated for a particular client
400
	 * or server configuration. ( see openvpn_vpnid_next() )
401
	 */
402

    
403
	$vpnid = $settings['vpnid'];
404
	$mode_id = $mode.$vpnid;
405

    
406
	if (isset($settings['dev_mode']))
407
		$tunname = "{$settings['dev_mode']}{$vpnid}";
408
	else {	/* defaults to tun */
409
		$tunname = "tun{$vpnid}";
410
		$settings['dev_mode'] = "tun";
411
	}
412

    
413
	if ($mode == "server")
414
		$devname = "ovpns{$vpnid}";
415
	else
416
		$devname = "ovpnc{$vpnid}";
417

    
418
	/* is our device already configured */
419
	if (!does_interface_exist($devname)) {
420

    
421
		/* create the tap device if required */
422
		if (!file_exists("/dev/{$tunname}"))
423
			exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
424

    
425
		/* rename the device */
426
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
427

    
428
		/* add the device to the openvpn group */
429
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn");
430
	}
431

    
432
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
433
	$proto = strtolower($settings['protocol']);
434
	if (substr($settings['protocol'], 0, 3) == "TCP")
435
			$proto = "{$proto}-{$mode}";
436
	$dev_mode = $settings['dev_mode'];
437
	$cipher = $settings['crypto'];
438
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
439
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
440

    
441
	$interface = get_failover_interface($settings['interface']);
442
	$ipaddr = $settings['ipaddr'];
443
	$ipaddrv6 = $settings['ipaddrv6'];
444

    
445
	// If a specific ip address (VIP) is requested, use it.
446
	// Otherwise, if a specific interface is requested, use it
447
	// If "any" interface was selected, local directive will be ommited.
448
	if (is_ipaddrv4($ipaddr)) {
449
		$iface_ip=$ipaddr;
450
	} else {
451
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
452
			$iface_ip=get_interface_ip($interface);
453
		}
454
	}
455
	if (is_ipaddrv6($ipaddrv6)) {
456
		$iface_ipv6=$ipaddrv6;
457
	} else {
458
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
459
			$iface_ipv6=get_interface_ipv6($interface);
460
		}
461
	}
462

    
463
	$conf  = "dev {$devname}\n";
464
	$conf .= "dev-type {$settings['dev_mode']}\n";
465
	switch($settings['dev_mode']) {
466
		case "tun":
467
			$conf .= "tun-ipv6\n";
468
			break;
469
	}
470
	$conf .= "dev-node /dev/{$tunname}\n";
471
	$conf .= "writepid {$pfile}\n";
472
	$conf .= "#user nobody\n";
473
	$conf .= "#group nobody\n";
474
	$conf .= "script-security 3\n";
475
	$conf .= "daemon\n";
476
	$conf .= "keepalive 10 60\n";
477
	$conf .= "ping-timer-rem\n";
478
	$conf .= "persist-tun\n";
479
	$conf .= "persist-key\n";
480
	$conf .= "proto {$proto}\n";
481
	$conf .= "cipher {$cipher}\n";
482
	$conf .= "auth {$digest}\n";
483
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
484
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
485
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
486
		switch($settings['mode']) {
487
			case 'server_user':
488
			case 'server_tls_user':
489
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
490
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
491
				break;
492
		}
493
	}
494

    
495
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
496
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
497
		$conf .= "local {$iface_ip}\n";
498
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
499
		$conf .= "local {$iface_ipv6}\n";
500
	}
501

    
502
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
503
		$conf .= "engine {$settings['engine']}\n";
504

    
505
	// server specific settings
506
	if ($mode == 'server') {
507

    
508
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
509
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
510
		$mask = gen_subnet_mask($cidr);
511

    
512
		// configure tls modes
513
		switch($settings['mode']) {
514
			case 'p2p_tls':
515
			case 'server_tls':
516
			case 'server_user':
517
			case 'server_tls_user':
518
				$conf .= "tls-server\n";
519
				break;
520
		}
521

    
522
		// configure p2p/server modes
523
		switch($settings['mode']) {
524
			case 'p2p_tls':
525
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
526
				//  use the server directive. It works for a single client without it.
527
				//  See ticket #1417
528
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
529
					$conf .= "server {$ip} {$mask}\n";
530
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
531
					if(is_ipaddr($ipv6))
532
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
533
				}
534
			case 'p2p_shared_key':
535
				if (!empty($ip) && !empty($mask)) {
536
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
537
					if ($settings['dev_mode'] == 'tun')
538
						$conf .= "ifconfig {$ip1} {$ip2}\n";
539
					else
540
						$conf .= "ifconfig {$ip1} {$mask}\n";
541
				}
542
				if (!empty($ipv6) && !empty($prefix)) {
543
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
544
					if ($settings['dev_mode'] == 'tun')
545
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
546
					else
547
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
548
				}
549
				break;
550
			case 'server_tls':
551
			case 'server_user':
552
			case 'server_tls_user':
553
				if (!empty($ip) && !empty($mask)) {
554
					$conf .= "server {$ip} {$mask}\n";
555
					if(is_ipaddr($ipv6))
556
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
557
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
558
				} else {
559
					if ($settings['serverbridge_dhcp']) {
560
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
561
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
562
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
563
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
564
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
565
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
566
							} else {
567
								$conf .= "mode server\n";
568
							}
569
						} else {
570
							$conf .= "mode server\n";
571
						}
572
					}
573
				}
574
				break;
575
		}
576

    
577
		// configure user auth modes
578
		switch($settings['mode']) {
579
			case 'server_user':
580
				$conf .= "client-cert-not-required\n";
581
			case 'server_tls_user':
582
				/* username-as-common-name is not compatible with server-bridge */
583
				if (stristr($conf, "server-bridge") === false)
584
					$conf .= "username-as-common-name\n";
585
				if (!empty($settings['authmode'])) {
586
					$strictusercn = "false";
587
					if ($settings['strictusercn'])
588
						$strictusercn = "true";
589
					$conf .= "auth-user-pass-verify \"/usr/local/sbin/ovpn_auth_verify user '{$settings['authmode']}' {$strictusercn} {$mode_id}\" via-env\n";
590
				}
591
				break;
592
		}
593
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls')))
594
			$settings['cert_depth'] = 1;
595
		if (is_numeric($settings['cert_depth'])) {
596
			if (($mode == 'client') && empty($settings['certref']))
597
				$cert = "";
598
			else {
599
				$cert = lookup_cert($settings['certref']);
600
				/* XXX: Seems not used at all! */
601
				$servercn = urlencode(cert_get_cn($cert['crt']));
602
				$conf .= "tls-verify \"/usr/local/sbin/ovpn_auth_verify tls '{$servercn}' {$settings['cert_depth']}\"\n";
603
			}
604
		}
605

    
606
		// The local port to listen on
607
		$conf .= "lport {$settings['local_port']}\n";
608

    
609
		// The management port to listen on
610
		// Use unix socket to overcome the problem on any type of server
611
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
612
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
613

    
614
		if ($settings['maxclients'])
615
			$conf .= "max-clients {$settings['maxclients']}\n";
616

    
617
		// Can we push routes
618
		if ($settings['local_network']) {
619
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
620
		}
621
		if ($settings['local_networkv6']) {
622
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
623
		}
624

    
625
		switch($settings['mode']) {
626
			case 'server_tls':
627
			case 'server_user':
628
			case 'server_tls_user':
629
				// Configure client dhcp options
630
				openvpn_add_dhcpopts($settings, $conf);
631
				if ($settings['client2client'])
632
					$conf .= "client-to-client\n";
633
				break;
634
		}
635
		if (isset($settings['duplicate_cn']))
636
			$conf .= "duplicate-cn\n";
637
	}
638

    
639
	// client specific settings
640

    
641
	if ($mode == 'client') {
642

    
643
		// configure p2p mode
644
		switch($settings['mode']) {
645
			case 'p2p_tls':
646
				$conf .= "tls-client\n";
647
			case 'shared_key':
648
				$conf .= "client\n";
649
				break;
650
		}
651

    
652
		// If there is no bind option at all (ip and/or port), add "nobind" directive
653
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
654
		//  ensure a random source port.
655
		if ((empty($iface_ip)) && (!$settings['local_port']))
656
			$conf .= "nobind\n";
657
		elseif ($settings['local_port'])
658
			$conf .= "lport {$settings['local_port']}\n";
659
		else
660
			$conf .= "lport 0\n";
661

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

    
665
		// The remote server
666
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
667

    
668
		if (!empty($settings['use_shaper']))
669
			$conf .= "shaper {$settings['use_shaper']}\n";
670

    
671
		if (!empty($settings['tunnel_network'])) {
672
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
673
			$mask = gen_subnet_mask($mask);
674
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
675
			if ($settings['dev_mode'] == 'tun')
676
				$conf .= "ifconfig {$ip2} {$ip1}\n";
677
			else
678
				$conf .= "ifconfig {$ip2} {$mask}\n";
679
		}
680

    
681
		if (!empty($settings['tunnel_networkv6'])) {
682
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
683
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
684
			if ($settings['dev_mode'] == 'tun')
685
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
686
			else
687
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
688
		}
689

    
690
		if ($settings['auth_user'] && $settings['auth_pass']) {
691
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
692
			$conf .= "auth-user-pass {$up_file}\n";
693
			$userpass = "{$settings['auth_user']}\n";
694
			$userpass .= "{$settings['auth_pass']}\n";
695
			file_put_contents($up_file, $userpass);
696
		}
697
		
698
		if ($settings['proxy_addr']) {
699
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
700
			if ($settings['proxy_authtype'] != "none") {
701
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
702
				$proxypas = "{$settings['proxy_user']}\n";
703
				$proxypas .= "{$settings['proxy_passwd']}\n";
704
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
705
			}
706
			$conf .= " \n";
707
		}
708
	}
709

    
710
	// Add a remote network route if set, and only for p2p modes.
711
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
712
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
713
	}
714
	// Add a remote network route if set, and only for p2p modes.
715
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
716
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
717
	}
718

    
719
	// Write the settings for the keys
720
	switch($settings['mode']) {
721
		case 'p2p_shared_key':
722
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
723
			break;
724
		case 'p2p_tls':
725
		case 'server_tls':
726
		case 'server_tls_user':
727
		case 'server_user':
728
			$ca = lookup_ca($settings['caref']);
729
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
730

    
731
			if (!empty($settings['certref'])) {
732
				$cert = lookup_cert($settings['certref']);
733
				openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
734
				openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
735
			}
736
			if ($mode == 'server')
737
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
738
			if (!empty($settings['crlref'])) {
739
				$crl = lookup_crl($settings['crlref']);
740
				crl_update($crl);
741
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
742
			}
743
			if ($settings['tls']) {
744
				if ($mode == "server") 
745
					$tlsopt = 0;
746
				else
747
					$tlsopt = 1;
748
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
749
			}
750
			break;
751
	}
752

    
753
	if (!empty($settings['compression']))
754
		$conf .= "comp-lzo {$settings['compression']}\n";
755

    
756
	if ($settings['passtos'])
757
		$conf .= "passtos\n";
758

    
759
	if ($settings['resolve_retry'])
760
		$conf .= "resolv-retry infinite\n";
761

    
762
	if ($settings['dynamic_ip']) {
763
		$conf .= "persist-remote-ip\n";
764
		$conf .= "float\n";
765
	}
766

    
767
	if ($settings['topology_subnet']) {
768
		$conf .= "topology subnet\n";
769
	}
770

    
771
	openvpn_add_custom($settings, $conf);
772

    
773
	openvpn_create_dirs();
774
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
775
	file_put_contents($fpath, $conf);
776
	unset($conf);
777
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
778
	file_put_contents($fpath, $interface);
779
	//chown($fpath, 'nobody');
780
	//chgrp($fpath, 'nobody');
781
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
782
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
783
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
784
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
785
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
786
}
787

    
788
function openvpn_restart($mode, $settings) {
789
	global $g, $config;
790

    
791
	$vpnid = $settings['vpnid'];
792
	$mode_id = $mode.$vpnid;
793

    
794
	/* kill the process if running */
795
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
796
	if (file_exists($pfile)) {
797

    
798
		/* read the pid file */
799
		$pid = rtrim(file_get_contents($pfile));
800
		unlink($pfile);
801

    
802
		/* send a term signal to the process */
803
		posix_kill($pid, SIGTERM);
804

    
805
		/* wait until the process exits */
806
		while(posix_kill($pid, 0))
807
			usleep(250000);
808
	}
809

    
810
	if (isset($settings['disable']))
811
		return;
812

    
813
	/* Do not start a client if we are a CARP backup on this vip! */
814
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) == "BACKUP"))
815
		return;
816
		
817
	/* Check if client is bound to a gateway group */    
818
	$a_groups = return_gateway_groups_array();
819
	if (is_array($a_groups[$settings['interface']])) {
820
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
821
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
822
			return;
823
	}
824

    
825
	/* start the new process */
826
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
827
	openvpn_clear_route($mode, $settings);
828
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
829

    
830
	if (!$g['booting'])
831
		send_event("filter reload");
832
}
833

    
834
function openvpn_delete($mode, & $settings) {
835
	global $g, $config;
836

    
837
	$vpnid = $settings['vpnid'];
838
	$mode_id = $mode.$vpnid;
839

    
840
	if (isset($settings['dev_mode']))
841
		$tunname = "{$settings['dev_mode']}{$vpnid}";
842
	else {  /* defaults to tun */
843
		$tunname = "tun{$vpnid}";
844
	}
845

    
846
	if ($mode == "server")
847
		$devname = "ovpns{$vpnid}";
848
	else
849
		$devname = "ovpnc{$vpnid}";
850

    
851
	/* kill the process if running */
852
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
853
	if (file_exists($pfile)) {
854

    
855
		/* read the pid file */
856
		$pid = trim(file_get_contents($pfile));
857
		unlink($pfile);
858

    
859
		/* send a term signal to the process */
860
		posix_kill($pid, SIGTERM);
861
	}
862

    
863
	/* remove the device from the openvpn group */
864
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
865

    
866
	/* restore the original adapter name */
867
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
868

    
869
	/* remove the configuration files */
870
	array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
871
}
872

    
873
function openvpn_cleanup_csc($common_name) {
874
	global $g, $config;
875
	if (empty($common_name))
876
		return;
877
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
878
	if (is_file($fpath))
879
		unlink_if_exists($fpath);
880
	return;
881
}
882

    
883
function openvpn_resync_csc(& $settings) {
884
	global $g, $config;
885

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

    
888
	if (isset($settings['disable'])) {
889
		unlink_if_exists($fpath);
890
		return;
891
	}
892
	openvpn_create_dirs();
893

    
894
	$conf = '';
895
	if ($settings['block'])
896
		$conf .= "disable\n";
897

    
898
	if ($settings['push_reset'])
899
		$conf .= "push-reset\n";
900

    
901
	if (!empty($settings['tunnel_network'])) {
902
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
903
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
904
		$serverip = long2ip32($baselong + 1);
905
		$clientip = long2ip32($baselong + 2);
906
		/* Because this is being pushed, the order from the client's point of view. */
907
		if ($settings['dev_mode'] != 'tap')
908
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
909
		else
910
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
911
	}
912

    
913
	if ($settings['local_network']) {
914
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
915
	}
916
	if ($settings['local_networkv6']) {
917
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
918
	}
919

    
920
	// Add a remote network iroute if set
921
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
922
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
923
	}
924
	// Add a remote network iroute if set
925
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
926
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
927
	}
928

    
929
	openvpn_add_dhcpopts($settings, $conf);
930

    
931
	if ($settings['gwredir'])
932
		$conf .= "push \"redirect-gateway def1\"\n";
933

    
934
	openvpn_add_custom($settings, $conf);
935

    
936
	file_put_contents($fpath, $conf);
937
	chown($fpath, 'nobody');
938
	chgrp($fpath, 'nobody');
939
}
940

    
941
function openvpn_delete_csc(& $settings) {
942
	global $g, $config;
943

    
944
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
945
	unlink_if_exists($fpath);
946
}
947

    
948
// Resync the configuration and restart the VPN
949
function openvpn_resync($mode, $settings) {
950
	openvpn_reconfigure($mode, $settings);
951
	openvpn_restart($mode, $settings);
952
}
953

    
954
// Resync and restart all VPNs
955
function openvpn_resync_all($interface = "") {
956
	global $g, $config;
957

    
958
	if ($g['platform'] == 'jail')
959
		return;
960
	openvpn_create_dirs();
961

    
962
	if (!is_array($config['openvpn']))
963
		$config['openvpn'] = array();
964

    
965
/*
966
	if (!$config['openvpn']['dh-parameters']) {
967
		echo "Configuring OpenVPN Parameters ...\n";
968
		$dh_parameters = openvpn_create_dhparams(1024);
969
		$dh_parameters = base64_encode($dh_parameters);
970
		$config['openvpn']['dh-parameters'] = $dh_parameters;
971
		write_config("OpenVPN DH parameters");
972
	}
973

    
974
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
975
	if (!file_exists($path_ovdh)) {
976
		$dh_parameters = $config['openvpn']['dh-parameters'];
977
		$dh_parameters = base64_decode($dh_parameters);
978
		file_put_contents($path_ovdh, $dh_parameters);
979
	}
980
*/
981
	if ($interface <> "")
982
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
983
	else
984
		log_error("Resyncing OpenVPN instances."); 
985

    
986
	if (is_array($config['openvpn']['openvpn-server'])) {
987
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
988
			if ($interface <> "" && $interface != $settings['interface'])
989
				continue;
990
			openvpn_resync('server', $settings);
991
		}
992
	}
993

    
994
	if (is_array($config['openvpn']['openvpn-client'])) {
995
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
996
			if ($interface <> "" && $interface != $settings['interface'])
997
				continue;
998
			openvpn_resync('client', $settings);
999
		}
1000
	}
1001

    
1002
	if (is_array($config['openvpn']['openvpn-csc']))
1003
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
1004
			openvpn_resync_csc($settings);
1005

    
1006
}
1007

    
1008
// Resync and restart all VPNs using a gateway group.
1009
function openvpn_resync_gwgroup($gwgroupname = "") {
1010
	global $g, $config;
1011

    
1012
	if ($gwgroupname <> "") {
1013
		if (is_array($config['openvpn']['openvpn-server'])) {
1014
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1015
				if ($gwgroupname == $settings['interface']) {
1016
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1017
					openvpn_resync('server', $settings);
1018
				}
1019
			}
1020
		}
1021

    
1022
		if (is_array($config['openvpn']['openvpn-client'])) {
1023
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1024
				if ($gwgroupname == $settings['interface']) {
1025
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1026
					openvpn_resync('client', $settings);
1027
				}
1028
			}
1029
		}
1030

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

    
1033
	} else
1034
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1035
}
1036

    
1037
function openvpn_get_active_servers($type="multipoint") {
1038
	global $config, $g;
1039

    
1040
	$servers = array();
1041
	if (is_array($config['openvpn']['openvpn-server'])) {
1042
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1043
			if (empty($settings) || isset($settings['disable']))
1044
				continue;
1045

    
1046
			$prot = $settings['protocol'];
1047
			$port = $settings['local_port'];
1048
	
1049
			$server = array();
1050
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1051
			$server['mode'] = $settings['mode'];
1052
			if ($settings['description'])
1053
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1054
			else
1055
				$server['name'] = "Server {$prot}:{$port}";
1056
			$server['conns'] = array();
1057
			$server['vpnid'] = $settings['vpnid'];
1058
			$server['mgmt'] = "server{$server['vpnid']}";
1059
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1060
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1061

    
1062
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1063
				$servers[] = openvpn_get_client_status($server, $socket);
1064
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1065
				$servers[] = openvpn_get_server_status($server, $socket);
1066

    
1067
		}
1068
	}
1069
	return $servers;
1070
}
1071

    
1072
function openvpn_get_server_status($server, $socket) {
1073
	$errval;
1074
	$errstr;
1075
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1076
	if ($fp) {
1077
		stream_set_timeout($fp, 1);
1078

    
1079
		/* send our status request */
1080
		fputs($fp, "status 2\n");
1081

    
1082
		/* recv all response lines */
1083
		while (!feof($fp)) {
1084

    
1085
			/* read the next line */
1086
			$line = fgets($fp, 1024);
1087

    
1088
			$info = stream_get_meta_data($fp);
1089
			if ($info['timed_out'])
1090
				break;
1091

    
1092
			/* parse header list line */
1093
			if (strstr($line, "HEADER"))
1094
				continue;
1095

    
1096
			/* parse end of output line */
1097
			if (strstr($line, "END") || strstr($line, "ERROR"))
1098
				break;
1099

    
1100
			/* parse client list line */
1101
			if (strstr($line, "CLIENT_LIST")) {
1102
				$list = explode(",", $line);
1103
				$conn = array();
1104
				$conn['common_name'] = $list[1];
1105
				$conn['remote_host'] = $list[2];
1106
				$conn['virtual_addr'] = $list[3];
1107
				$conn['bytes_recv'] = $list[4];
1108
				$conn['bytes_sent'] = $list[5];
1109
				$conn['connect_time'] = $list[6];
1110
				$server['conns'][] = $conn;
1111
			}
1112
			/* parse routing table lines */
1113
			if (strstr($line, "ROUTING_TABLE")) {
1114
				$list = explode(",", $line);
1115
				$conn = array();
1116
				$conn['virtual_addr'] = $list[1];
1117
				$conn['common_name'] = $list[2];
1118
				$conn['remote_host'] = $list[3];
1119
				$conn['last_time'] = $list[4];
1120
				$server['routes'][] = $conn;
1121
			}
1122
		}
1123

    
1124
		/* cleanup */
1125
		fclose($fp);
1126
	} else {
1127
		$conn = array();
1128
		$conn['common_name'] = "[error]";
1129
		$conn['remote_host'] = "Unable to contact daemon";
1130
		$conn['virtual_addr'] = "Service not running?";
1131
		$conn['bytes_recv'] = 0;
1132
		$conn['bytes_sent'] = 0;
1133
		$conn['connect_time'] = 0;
1134
		$server['conns'][] = $conn;
1135
	}
1136
	return $server;
1137
}
1138

    
1139
function openvpn_get_active_clients() {
1140
	global $config, $g;
1141

    
1142
	$clients = array();
1143
	if (is_array($config['openvpn']['openvpn-client'])) {
1144
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1145
	
1146
			if (empty($settings) || isset($settings['disable']))
1147
				continue;
1148

    
1149
			$prot = $settings['protocol'];
1150
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1151
	
1152
			$client = array();
1153
			$client['port'] = $settings['local_port'];
1154
			if ($settings['description'])
1155
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1156
			else
1157
				$client['name'] = "Client {$prot}{$port}";
1158
	
1159
			$client['vpnid'] = $settings['vpnid'];
1160
			$client['mgmt'] = "client{$client['vpnid']}";
1161
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1162
			$client['status']="down";
1163

    
1164
			$clients[] = openvpn_get_client_status($client, $socket);
1165
		}
1166
	}
1167
	return $clients;
1168
}
1169

    
1170
function openvpn_get_client_status($client, $socket) {
1171
	$errval;
1172
	$errstr;
1173
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1174
	if ($fp) {
1175
		stream_set_timeout($fp, 1);
1176
		/* send our status request */
1177
		fputs($fp, "state 1\n");
1178

    
1179
		/* recv all response lines */
1180
		while (!feof($fp)) {
1181
			/* read the next line */
1182
			$line = fgets($fp, 1024);
1183

    
1184
			$info = stream_get_meta_data($fp);
1185
			if ($info['timed_out'])
1186
				break;
1187

    
1188
			/* Get the client state */
1189
			if (strstr($line,"CONNECTED")) {
1190
				$client['status']="up";
1191
				$list = explode(",", $line);
1192

    
1193
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1194
				$client['virtual_addr']  = $list[3];
1195
				$client['remote_host'] = $list[4];
1196
			}
1197
			if (strstr($line,"CONNECTING")) {
1198
				$client['status']="connecting";
1199
			}
1200
			if (strstr($line,"ASSIGN_IP")) {
1201
				$client['status']="waiting";
1202
				$list = explode(",", $line);
1203

    
1204
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1205
				$client['virtual_addr']  = $list[3];
1206
			}
1207
			if (strstr($line,"RECONNECTING")) {
1208
				$client['status']="reconnecting";
1209
				$list = explode(",", $line);
1210

    
1211
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1212
				$client['status'] .= "; " . $list[2];
1213
			}
1214
			/* parse end of output line */
1215
			if (strstr($line, "END") || strstr($line, "ERROR"))
1216
				break;
1217
		}
1218

    
1219
		/* If up, get read/write stats */
1220
		if (strcmp($client['status'], "up") == 0) {
1221
			fputs($fp, "status 2\n");
1222
			/* recv all response lines */
1223
			while (!feof($fp)) {
1224
				/* read the next line */
1225
				$line = fgets($fp, 1024);
1226

    
1227
				$info = stream_get_meta_data($fp);
1228
				if ($info['timed_out'])
1229
					break;
1230

    
1231
				if (strstr($line,"TCP/UDP read bytes")) {
1232
					$list = explode(",", $line);
1233
					$client['bytes_recv'] = $list[1];
1234
				}
1235

    
1236
				if (strstr($line,"TCP/UDP write bytes")) {
1237
					$list = explode(",", $line);
1238
					$client['bytes_sent'] = $list[1];
1239
				}
1240

    
1241
				/* parse end of output line */
1242
				if (strstr($line, "END"))
1243
					break;
1244
			}
1245
		}
1246

    
1247
		fclose($fp);
1248

    
1249
	} else {
1250
		$DisplayNote=true;
1251
		$client['remote_host'] = "Unable to contact daemon";
1252
		$client['virtual_addr'] = "Service not running?";
1253
		$client['bytes_recv'] = 0;
1254
		$client['bytes_sent'] = 0;
1255
		$client['connect_time'] = 0;
1256
	}
1257
	return $client;
1258
}
1259

    
1260
function openvpn_refresh_crls() {
1261
	global $g, $config;
1262

    
1263
	openvpn_create_dirs();
1264

    
1265
	if (is_array($config['openvpn']['openvpn-server'])) {
1266
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1267
			if (empty($settings))
1268
				continue;
1269
			if (isset($settings['disable']))
1270
				continue;
1271
			// Write the settings for the keys
1272
			switch($settings['mode']) {
1273
				case 'p2p_tls':
1274
				case 'server_tls':
1275
				case 'server_tls_user':
1276
				case 'server_user':
1277
					if (!empty($settings['crlref'])) {
1278
						$crl = lookup_crl($settings['crlref']);
1279
						crl_update($crl);
1280
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1281
						file_put_contents($fpath, base64_decode($crl['text']));
1282
						@chmod($fpath, 0644);
1283
					}
1284
					break;
1285
			}
1286
		}
1287
	}
1288
}
1289

    
1290
function openvpn_create_dirs() {
1291
	global $g;
1292
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1293
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1294
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1295
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1296
}
1297

    
1298
function openvpn_get_interface_ip($ip, $mask) {
1299
	$baselong = ip2long32($ip) & ip2long($mask);
1300
	$ip1 = long2ip32($baselong + 1);
1301
	$ip2 = long2ip32($baselong + 2);
1302
	return array($ip1, $ip2);
1303
}
1304

    
1305
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1306
	$basev6 = gen_subnetv6($ipv6, $prefix);
1307
	// Is there a better way to do this math?
1308
	$ipv6_arr = explode(':', $basev6);
1309
	$last = hexdec(array_pop($ipv6_arr));
1310
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1311
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1312
	return array($ipv6_1, $ipv6_2);
1313
}
1314

    
1315
function openvpn_clear_route($mode, $settings) {
1316
	if (empty($settings['tunnel_network']))
1317
		return;
1318
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1319
	$mask = gen_subnet_mask($cidr);
1320
	$clear_route = false;
1321

    
1322
	switch($settings['mode']) {
1323
		case 'shared_key':
1324
			$clear_route = true;
1325
			break;
1326
		case 'p2p_tls':
1327
		case 'p2p_shared_key':
1328
			if ($cidr == 30)
1329
				$clear_route = true;
1330
			break;
1331
	}
1332

    
1333
	if ($clear_route && !empty($ip) && !empty($mask)) {
1334
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1335
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1336
		/* XXX: Family for route? */
1337
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1338
	}
1339
}
1340

    
1341
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1342
	$routes = "";
1343
	if (empty($value))
1344
		return "";
1345
	$networks = explode(',', $value);
1346

    
1347
	foreach ($networks as $network) {
1348
		if ($ipproto == "ipv4")
1349
			$route = openvpn_gen_route_ipv4($network, $iroute);
1350
		else
1351
			$route = openvpn_gen_route_ipv6($network, $iroute);
1352

    
1353
		if ($push)
1354
			$routes .= "push \"{$route}\"\n";
1355
		else
1356
			$routes .= "{$route}\n";
1357
	}
1358
	return $routes;
1359
}
1360

    
1361
function openvpn_gen_route_ipv4($network, $iroute = false) {
1362
	$i = ($iroute) ? "i" : "";
1363
	list($ip, $mask) = explode('/', trim($network));
1364
	$mask = gen_subnet_mask($mask);
1365
	return "{$i}route $ip $mask";
1366
}
1367

    
1368
function openvpn_gen_route_ipv6($network, $iroute = false) {
1369
	$i = ($iroute) ? "i" : "";
1370
	list($ipv6, $prefix) = explode('/', trim($network));
1371
	if (empty($prefix))
1372
		$prefix = "128";
1373
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1374
}
1375

    
1376
function openvpn_get_settings($mode, $vpnid) {
1377
	global $config;
1378

    
1379
	if (is_array($config['openvpn']['openvpn-server'])) {
1380
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1381
			if (isset($settings['disable']))
1382
				continue;
1383

    
1384
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1385
				return $settings;
1386
		}
1387
	}
1388

    
1389
	if (is_array($config['openvpn']['openvpn-client'])) {
1390
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1391
			if (isset($settings['disable']))
1392
				continue;
1393

    
1394
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1395
				return $settings;
1396
		}
1397
	}
1398

    
1399
	return array();
1400
}
1401

    
1402
function openvpn_restart_by_vpnid($mode, $vpnid) {
1403
	$settings = openvpn_get_settings($mode, $vpnid);
1404
	openvpn_restart($mode, $settings);
1405
}
1406

    
1407
?>
(38-38/68)