Project

General

Profile

Download (39.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	openvpn.inc part of pfSense
4
	
5
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
6
	All rights reserved.
7
	
8
	Copyright (C) 2006  Fernando Lemos
9
	All rights reserved.
10

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

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

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

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

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

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

    
30
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39
	POSSIBILITY OF SUCH DAMAGE.
40
	
41
	DISABLE_PHP_LINT_CHECKING
42
	
43
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/local/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
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
53

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

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

    
69
$openvpn_dh_lengths = array(
70
	1024, 2048, 4096 );
71

    
72
$openvpn_cert_depths = array(
73
	1 => "One (Client+Server)",
74
	2 => "Two (Client+Intermediate+Server)",
75
	3 => "Three (Client+2xIntermediate+Server)",
76
	4 => "Four (Client+3xIntermediate+Server)",
77
	5 => "Five (Client+4xIntermediate+Server)"
78
);
79

    
80
$openvpn_server_modes = array(
81
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
82
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
83
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
84
	'server_user' => gettext("Remote Access ( User Auth )"),
85
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
86

    
87
$openvpn_client_modes = array(
88
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
89
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )") );
90

    
91
function openvpn_create_key() {
92

    
93
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
94
	if (!$fp)
95
		return false;
96

    
97
	$rslt = stream_get_contents($fp);
98
	pclose($fp);
99

    
100
	return $rslt;
101
}
102

    
103
function openvpn_create_dhparams($bits) {
104

    
105
	$fp = popen("/usr/local/bin/openssl dhparam {$bits} 2>/dev/null", "r");
106
	if (!$fp)
107
		return false;
108

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

    
112
	return $rslt;
113
}
114

    
115
function openvpn_vpnid_used($vpnid) {
116
	global $config;
117

    
118
	if (is_array($config['openvpn']['openvpn-server']))
119
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
120
			if ($vpnid == $settings['vpnid'])
121
				return true;
122

    
123
	if (is_array($config['openvpn']['openvpn-client']))
124
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
125
			if ($vpnid == $settings['vpnid'])
126
				return true;
127

    
128
	return false;
129
}
130

    
131
function openvpn_vpnid_next() {
132

    
133
	$vpnid = 1;
134
	while(openvpn_vpnid_used($vpnid))
135
		$vpnid++;
136

    
137
	return $vpnid;
138
}
139

    
140
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
141
	global $config;
142

    
143
	if (is_array($config['openvpn']['openvpn-server'])) {
144
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
145
			if (isset($settings['disable']))
146
				continue;
147

    
148
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
149
				continue;
150

    
151
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
152
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
153
				return $settings['vpnid'];
154
		}
155
	}
156

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

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

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

    
171
	return 0;
172
}
173

    
174
function openvpn_port_next($prot, $interface = "wan") {
175

    
176
	$port = 1194;
177
	while(openvpn_port_used($prot, $interface, $port))
178
		$port++;
179
	while(openvpn_port_used($prot, "any", $port))
180
		$port++;
181

    
182
	return $port;
183
}
184

    
185
function openvpn_get_cipherlist() {
186

    
187
	$ciphers = array();
188
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
189
	$cipher_lines = explode("\n", trim($cipher_out));
190
	sort($cipher_lines);
191
	foreach ($cipher_lines as $line) {
192
		$words = explode(' ', $line);
193
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
194
	}
195
	$ciphers["none"] = gettext("None (No Encryption)");
196
	return $ciphers;
197
}
198

    
199
function openvpn_get_engines() {
200
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
201
	exec("/usr/local/bin/openssl engine -t -c", $openssl_engine_output);
202
	$openssl_engine_output = implode("\n", $openssl_engine_output);
203
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
204
	$openssl_engine_output = explode("\n", $openssl_engine_output);
205

    
206
	foreach ($openssl_engine_output as $oeo) {
207
		$keep = true;
208
		$details = explode("|", $oeo);
209
		$engine = array_shift($details);
210
		$linematch = array();
211
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
212
		foreach ($details as $dt) {
213
			if (strpos($dt, "unavailable") !== FALSE)
214
				$keep = false;
215
			if (strpos($dt, "available") !== FALSE)
216
				continue;
217
			if (strpos($dt, "[") !== FALSE)
218
				$ciphers = trim($dt, "[]");
219
		}
220
		if (!empty($ciphers))
221
			$ciphers = " - " . $ciphers;
222
		if (strlen($ciphers) > 60)
223
			$ciphers = substr($ciphers, 0, 60) . " ... ";
224
		if ($keep)
225
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
226
	}
227
	return $openssl_engines;
228
}
229

    
230
function openvpn_validate_engine($engine) {
231
	$engines = openvpn_get_engines();
232
	return array_key_exists($engine, $engines);
233
}
234

    
235
function openvpn_validate_host($value, $name) {
236
	$value = trim($value);
237
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
238
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
239
	return false;
240
}
241

    
242
function openvpn_validate_port($value, $name) {
243
	$value = trim($value);
244
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
245
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
246
	return false;
247
}
248

    
249
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
250
	$value = trim($value);
251
	$error = false;
252
	if (empty($value))
253
		return false;
254
	$networks = explode(',', $value);
255

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

    
259
	foreach ($networks as $network) {
260
		if ($ipproto == "ipv4")
261
			$error = !openvpn_validate_cidr_ipv4($network);
262
		else
263
			$error = !openvpn_validate_cidr_ipv6($network);
264
		if ($error)
265
			break;
266
	}
267

    
268
	if ($error)
269
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
270
	else
271
		return false;
272
}
273

    
274
function openvpn_validate_cidr_ipv4($value) {
275
	$value = trim($value);
276
	if (!empty($value)) {
277
		list($ip, $mask) = explode('/', $value);
278
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
279
			return false;
280
	}
281
	return true;
282
}
283

    
284
function openvpn_validate_cidr_ipv6($value) {
285
	$value = trim($value);
286
	if (!empty($value)) {
287
		list($ipv6, $prefix) = explode('/', $value);
288
		if (empty($prefix))
289
			$prefix = "128";
290
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0))
291
			return false;
292
	}
293
	return true;
294
}
295

    
296
function openvpn_add_dhcpopts(& $settings, & $conf) {
297

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

    
301
	if (!empty($settings['dns_server1']))
302
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
303
	if (!empty($settings['dns_server2']))
304
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
305
	if (!empty($settings['dns_server3']))
306
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
307
	if (!empty($settings['dns_server4']))
308
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
309

    
310
	if (!empty($settings['ntp_server1']))
311
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
312
	if (!empty($settings['ntp_server2']))
313
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
314

    
315
	if ($settings['netbios_enable']) {
316

    
317
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
318
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
319
		if (!empty($settings['dhcp_nbtscope'])) 
320
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
321

    
322
		if (!empty($settings['wins_server1']))
323
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
324
		if (!empty($settings['wins_server2']))
325
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
326

    
327
		if (!empty($settings['nbdd_server1']))
328
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
329
	}
330

    
331
	if ($settings['gwredir']) 
332
		$conf .= "push \"redirect-gateway def1\"\n";
333
}
334

    
335
function openvpn_add_custom(& $settings, & $conf) {
336

    
337
	if ($settings['custom_options']) {
338

    
339
		$options = explode(';', $settings['custom_options']);
340

    
341
		if (is_array($options)) {
342
			foreach ($options as $option)
343
				$conf .= "$option\n";
344
		} else
345
			$conf .= "{$settings['custom_options']}\n";
346
	}
347
}
348

    
349
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
350
	global $g;
351

    
352
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
353
	openvpn_create_dirs();
354
	file_put_contents($fpath, base64_decode($data));
355
	//chown($fpath, 'nobody');
356
	//chgrp($fpath, 'nobody');
357
	@chmod($fpath, 0600);
358

    
359
	$conf .= "{$directive} {$fpath} {$opt}\n";
360
}
361

    
362
function openvpn_reconfigure($mode, $settings) {
363
	global $g, $config;
364

    
365
	if (empty($settings))
366
		return;
367
	if (isset($settings['disable'])) 
368
		return;
369
	openvpn_create_dirs();
370
	/*
371
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
372
	 * we use a vpnid number which is allocated for a particular client
373
	 * or server configuration. ( see openvpn_vpnid_next() )
374
	 */
375

    
376
	$vpnid = $settings['vpnid'];
377
	$mode_id = $mode.$vpnid;
378

    
379
	if (isset($settings['dev_mode']))
380
		$tunname = "{$settings['dev_mode']}{$vpnid}";
381
	else {	/* defaults to tun */
382
		$tunname = "tun{$vpnid}";
383
		$settings['dev_mode'] = "tun";
384
	}
385

    
386
	if ($mode == "server")
387
		$devname = "ovpns{$vpnid}";
388
	else
389
		$devname = "ovpnc{$vpnid}";
390

    
391
	/* is our device already configured */
392
	if (mwexec("/sbin/ifconfig {$devname}", true)) {
393

    
394
		/* create the tap device if required */
395
		if (!file_exists("/dev/{$tunname}"))
396
			exec("/sbin/ifconfig {$tunname} create");
397

    
398
		/* rename the device */
399
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
400

    
401
		/* add the device to the openvpn group */
402
		mwexec("/sbin/ifconfig {$devname} group openvpn");
403
	}
404

    
405
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
406
	$proto = strtolower($settings['protocol']);
407
	if (substr($settings['protocol'], 0, 3) == "TCP")
408
			$proto = "{$proto}-{$mode}";
409
	$dev_mode = $settings['dev_mode'];
410
	$cipher = $settings['crypto'];
411

    
412
	$interface = get_failover_interface($settings['interface']);
413
	$ipaddr = $settings['ipaddr'];
414
	$ipaddrv6 = $settings['ipaddrv6'];
415

    
416
	// If a specific ip address (VIP) is requested, use it.
417
	// Otherwise, if a specific interface is requested, use it
418
	// If "any" interface was selected, local directive will be ommited.
419
	if (is_ipaddrv4($ipaddr)) {
420
		$iface_ip=$ipaddr;
421
	} else {
422
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
423
			$iface_ip=get_interface_ip($interface);
424
		}
425
	}
426
	if (is_ipaddrv6($ipaddrv6)) {
427
		$iface_ipv6=$ipaddrv6;
428
	} else {
429
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
430
			$iface_ipv6=get_interface_ipv6($interface);
431
		}
432
	}
433

    
434
	$conf  = "dev {$devname}\n";
435
	$conf .= "dev-type {$settings['dev_mode']}\n";
436
	switch($settings['dev_mode']) {
437
		case "tun":
438
			$conf .= "tun-ipv6\n";
439
			break;
440
	}
441
	$conf .= "dev-node /dev/{$tunname}\n";
442
	$conf .= "writepid {$pfile}\n";
443
	$conf .= "#user nobody\n";
444
	$conf .= "#group nobody\n";
445
	$conf .= "script-security 3\n";
446
	$conf .= "daemon\n";
447
	$conf .= "keepalive 10 60\n";
448
	$conf .= "ping-timer-rem\n";
449
	$conf .= "persist-tun\n";
450
	$conf .= "persist-key\n";
451
	$conf .= "proto {$proto}\n";
452
	$conf .= "cipher {$cipher}\n";
453
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
454
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
455
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
456
		switch($settings['mode']) {
457
			case 'server_user':
458
			case 'server_tls_user':
459
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
460
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
461
				break;
462
		}
463
	}
464

    
465
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
466
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
467
		$conf .= "local {$iface_ip}\n";
468
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
469
		$conf .= "local {$iface_ipv6}\n";
470
	}
471

    
472
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
473
		$conf .= "engine {$settings['engine']}\n";
474

    
475
	// server specific settings
476
	if ($mode == 'server') {
477

    
478
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
479
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
480
		$mask = gen_subnet_mask($cidr);
481

    
482
		// configure tls modes
483
		switch($settings['mode']) {
484
			case 'p2p_tls':
485
			case 'server_tls':
486
			case 'server_user':
487
			case 'server_tls_user':
488
				$conf .= "tls-server\n";
489
				break;
490
		}
491

    
492
		// configure p2p/server modes
493
		switch($settings['mode']) {
494
			case 'p2p_tls':
495
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
496
				//  use the server directive. It works for a single client without it.
497
				//  See ticket #1417
498
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
499
					$conf .= "server {$ip} {$mask}\n";
500
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
501
					if(is_ipaddr($ipv6))
502
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
503
				}
504
			case 'p2p_shared_key':
505
				if (!empty($ip) && !empty($mask)) {
506
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
507
					if ($settings['dev_mode'] == 'tun')
508
						$conf .= "ifconfig {$ip1} {$ip2}\n";
509
					else
510
						$conf .= "ifconfig {$ip1} {$mask}\n";
511
				}
512
				if (!empty($ipv6) && !empty($prefix)) {
513
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
514
					if ($settings['dev_mode'] == 'tun')
515
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
516
					else
517
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
518
				}
519
				break;
520
			case 'server_tls':
521
			case 'server_user':
522
			case 'server_tls_user':
523
				if (!empty($ip) && !empty($mask)) {
524
					$conf .= "server {$ip} {$mask}\n";
525
					if(is_ipaddr($ipv6))
526
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
527
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
528
				} else {
529
					if ($settings['serverbridge_dhcp']) {
530
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
531
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
532
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
533
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
534
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
535
							} else {
536
								$conf .= "mode server\n";
537
							}
538
						} else {
539
							$conf .= "mode server\n";
540
						}
541
					}
542
				}
543
				break;
544
		}
545

    
546
		// configure user auth modes
547
		switch($settings['mode']) {
548
			case 'server_user':
549
				$conf .= "client-cert-not-required\n";
550
			case 'server_tls_user':
551
				/* username-as-common-name is not compatible with server-bridge */
552
				if (stristr($conf, "server-bridge") === false)
553
					$conf .= "username-as-common-name\n";
554
				if (!empty($settings['authmode'])) {
555
					$authcfgs = explode(",", $settings['authmode']);
556
					$sed = "\$authmodes=array(";
557
					$firstsed = 0;
558
					foreach ($authcfgs as $authcfg) {
559
						if ($firstsed > 0)
560
							$sed .= ",";
561
						$firstsed = 1;
562
						$sed .= "\"{$authcfg}\"";
563
					}
564
					$sed .= ");\\\n";
565
					if ($settings['strictusercn'])
566
						$sed .= "\$strictusercn = true;";
567
					$sed .= " \$modeid = \"{$mode_id}\";";
568
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
569
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
570
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
571
				}
572
				break;
573
		}
574
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls')))
575
			$settings['cert_depth'] = 1;
576
		if (is_numeric($settings['cert_depth'])) {
577
			$sed = "";
578
			$cert = lookup_cert($settings['certref']);
579
			$servercn = cert_get_cn($cert['crt']);
580
			$sed .= "\$server_cn = \"{$servercn}\";\\\n";
581
			$sed .= "\$allowed_depth = {$settings['cert_depth']};\\\n";
582
			mwexec("/bin/cat /etc/inc/openvpn.tls-verify.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
583
			mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
584
			$conf .= "tls-verify {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php\n";
585
		}
586

    
587
		// The local port to listen on
588
		$conf .= "lport {$settings['local_port']}\n";
589

    
590
		// The management port to listen on
591
		// Use unix socket to overcome the problem on any type of server
592
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
593
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
594

    
595
		if ($settings['maxclients'])
596
			$conf .= "max-clients {$settings['maxclients']}\n";
597

    
598
		// Can we push routes
599
		if ($settings['local_network']) {
600
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
601
		}
602
		if ($settings['local_networkv6']) {
603
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
604
		}
605

    
606
		switch($settings['mode']) {
607
			case 'server_tls':
608
			case 'server_user':
609
			case 'server_tls_user':
610
				// Configure client dhcp options
611
				openvpn_add_dhcpopts($settings, $conf);
612
				if ($settings['client2client'])
613
					$conf .= "client-to-client\n";
614
				break;
615
		}
616
		if (isset($settings['duplicate_cn']))
617
			$conf .= "duplicate-cn\n";
618
	}
619

    
620
	// client specific settings
621

    
622
	if ($mode == 'client') {
623

    
624
		// configure p2p mode
625
		switch($settings['mode']) {
626
			case 'p2p_tls':
627
				$conf .= "tls-client\n";
628
			case 'shared_key':
629
				$conf .= "client\n";
630
				break;
631
		}
632

    
633
		// If there is no bind option at all (ip and/or port), add "nobind" directive
634
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
635
		//  ensure a random source port.
636
		if ((empty($iface_ip)) && (!$settings['local_port']))
637
			$conf .= "nobind\n";
638
		elseif ($settings['local_port'])
639
			$conf .= "lport {$settings['local_port']}\n";
640
		else
641
			$conf .= "lport 0\n";
642

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

    
646
		// The remote server
647
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
648

    
649
		if (!empty($settings['use_shaper']))
650
			$conf .= "shaper {$settings['use_shaper']}\n";
651

    
652
		if (!empty($settings['tunnel_network'])) {
653
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
654
			$mask = gen_subnet_mask($mask);
655
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
656
			if ($settings['dev_mode'] == 'tun')
657
				$conf .= "ifconfig {$ip2} {$ip1}\n";
658
			else
659
				$conf .= "ifconfig {$ip2} {$mask}\n";
660
		}
661

    
662
		if (!empty($settings['tunnel_networkv6'])) {
663
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
664
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
665
			if ($settings['dev_mode'] == 'tun')
666
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
667
			else
668
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
669
		}
670

    
671
		if ($settings['proxy_addr']) {
672
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
673
			if ($settings['proxy_authtype'] != "none") {
674
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
675
				$proxypas = "{$settings['proxy_user']}\n";
676
				$proxypas .= "{$settings['proxy_passwd']}\n";
677
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
678
			}
679
			$conf .= " \n";
680
		}
681
	}
682

    
683
	// Add a remote network route if set, and only for p2p modes.
684
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
685
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
686
	}
687
	// Add a remote network route if set, and only for p2p modes.
688
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
689
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
690
	}
691

    
692
	// Write the settings for the keys
693
	switch($settings['mode']) {
694
		case 'p2p_shared_key':
695
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
696
			break;
697
		case 'p2p_tls':
698
		case 'server_tls':
699
		case 'server_tls_user':
700
		case 'server_user':
701
			$ca = lookup_ca($settings['caref']);
702
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
703
			$cert = lookup_cert($settings['certref']);
704
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
705
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
706
			if ($mode == 'server')
707
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
708
			if (!empty($settings['crlref'])) {
709
				$crl = lookup_crl($settings['crlref']);
710
				crl_update($crl);
711
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
712
			}
713
			if ($settings['tls']) {
714
				if ($mode == "server") 
715
					$tlsopt = 0;
716
				else
717
					$tlsopt = 1;
718
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
719
			}
720
			break;
721
	}
722

    
723
	if ($settings['compression'])
724
		$conf .= "comp-lzo\n";
725

    
726
	if ($settings['passtos'])
727
		$conf .= "passtos\n";
728

    
729
	if ($settings['resolve_retry'])
730
		$conf .= "resolv-retry infinite\n";
731

    
732
	if ($settings['dynamic_ip']) {
733
		$conf .= "persist-remote-ip\n";
734
		$conf .= "float\n";
735
	}
736

    
737
	if ($settings['topology_subnet']) {
738
		$conf .= "topology subnet\n";
739
	}
740

    
741
	openvpn_add_custom($settings, $conf);
742

    
743
	openvpn_create_dirs();
744
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
745
	file_put_contents($fpath, $conf);
746
	unset($conf);
747
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
748
	file_put_contents($fpath, $interface);
749
	//chown($fpath, 'nobody');
750
	//chgrp($fpath, 'nobody');
751
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
752
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
753
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
754
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
755
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
756
}
757

    
758
function openvpn_restart($mode, $settings) {
759
	global $g, $config;
760

    
761
	$vpnid = $settings['vpnid'];
762
	$mode_id = $mode.$vpnid;
763

    
764
	/* kill the process if running */
765
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
766
	if (file_exists($pfile)) {
767

    
768
		/* read the pid file */
769
		$pid = rtrim(file_get_contents($pfile));
770
		unlink($pfile);
771

    
772
		/* send a term signal to the process */
773
		posix_kill($pid, SIGTERM);
774

    
775
		/* wait until the process exits */
776
		while(posix_kill($pid, 0))
777
			usleep(250000);
778
	}
779

    
780
	if (isset($settings['disable']))
781
		return;
782

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

    
787
	/* start the new process */
788
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
789
	openvpn_clear_route($mode, $settings);
790
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
791

    
792
	if (!$g['booting'])
793
		send_event("filter reload");
794
}
795

    
796
function openvpn_delete($mode, & $settings) {
797
	global $g, $config;
798

    
799
	$vpnid = $settings['vpnid'];
800
	$mode_id = $mode.$vpnid;
801

    
802
	if (isset($settings['dev_mode']))
803
		$tunname = "{$settings['dev_mode']}{$vpnid}";
804
	else {  /* defaults to tun */
805
		$tunname = "tun{$vpnid}";
806
	}
807

    
808
	if ($mode == "server")
809
		$devname = "ovpns{$vpnid}";
810
	else
811
		$devname = "ovpnc{$vpnid}";
812

    
813
	/* kill the process if running */
814
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
815
	if (file_exists($pfile)) {
816

    
817
		/* read the pid file */
818
		$pid = trim(file_get_contents($pfile));
819
		unlink($pfile);
820

    
821
		/* send a term signal to the process */
822
		posix_kill($pid, SIGTERM);
823
	}
824

    
825
	/* remove the device from the openvpn group */
826
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
827

    
828
	/* restore the original adapter name */
829
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
830

    
831
	/* remove the configuration files */
832
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
833
}
834

    
835
function openvpn_resync_csc(& $settings) {
836
	global $g, $config;
837

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

    
840
	if (isset($settings['disable'])) {
841
		unlink_if_exists($fpath);
842
		return;
843
	}
844
	openvpn_create_dirs();
845

    
846
	$conf = '';
847
	if ($settings['block'])
848
		$conf .= "disable\n";
849

    
850
	if ($settings['push_reset'])
851
		$conf .= "push-reset\n";
852

    
853
	if (!empty($settings['tunnel_network'])) {
854
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
855
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
856
		$serverip = long2ip32($baselong + 1);
857
		$clientip = long2ip32($baselong + 2);
858
		/* Because this is being pushed, the order from the client's point of view. */
859
		if ($settings['dev_mode'] != 'tap')
860
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
861
		else
862
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
863
	}
864

    
865
	openvpn_add_dhcpopts($settings, $conf);
866

    
867
	if ($settings['gwredir'])
868
		$conf .= "push \"redirect-gateway def1\"\n";
869

    
870
	openvpn_add_custom($settings, $conf);
871

    
872
	file_put_contents($fpath, $conf);
873
	chown($fpath, 'nobody');
874
	chgrp($fpath, 'nobody');
875
}
876

    
877
function openvpn_delete_csc(& $settings) {
878
	global $g, $config;
879

    
880
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
881
	unlink_if_exists($fpath);
882
}
883

    
884
// Resync the configuration and restart the VPN
885
function openvpn_resync($mode, $settings) {
886
	openvpn_reconfigure($mode, $settings);
887
	openvpn_restart($mode, $settings);
888
}
889

    
890
// Resync and restart all VPNs
891
function openvpn_resync_all($interface = "") {
892
	global $g, $config;
893

    
894
	if ($g['platform'] == 'jail')
895
		return;
896
	openvpn_create_dirs();
897

    
898
	if (!is_array($config['openvpn']))
899
		$config['openvpn'] = array();
900

    
901
/*
902
	if (!$config['openvpn']['dh-parameters']) {
903
		echo "Configuring OpenVPN Parameters ...\n";
904
		$dh_parameters = openvpn_create_dhparams(1024);
905
		$dh_parameters = base64_encode($dh_parameters);
906
		$config['openvpn']['dh-parameters'] = $dh_parameters;
907
		write_config("OpenVPN DH parameters");
908
	}
909

    
910
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
911
	if (!file_exists($path_ovdh)) {
912
		$dh_parameters = $config['openvpn']['dh-parameters'];
913
		$dh_parameters = base64_decode($dh_parameters);
914
		file_put_contents($path_ovdh, $dh_parameters);
915
	}
916
*/
917
	if ($interface <> "")
918
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
919
	else
920
		log_error("Resyncing OpenVPN instances."); 
921

    
922
	if (is_array($config['openvpn']['openvpn-server'])) {
923
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
924
			if ($interface <> "" && $interface != $settings['interface'])
925
				continue;
926
			openvpn_resync('server', $settings);
927
		}
928
	}
929

    
930
	if (is_array($config['openvpn']['openvpn-client'])) {
931
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
932
			if ($interface <> "" && $interface != $settings['interface'])
933
				continue;
934
			openvpn_resync('client', $settings);
935
		}
936
	}
937

    
938
	if (is_array($config['openvpn']['openvpn-csc']))
939
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
940
			openvpn_resync_csc($settings);
941

    
942
}
943

    
944
// Resync and restart all VPNs using a gateway group.
945
function openvpn_resync_gwgroup($gwgroupname = "") {
946
	global $g, $config;
947

    
948
	if ($gwgroupname <> "") {
949
		if (is_array($config['openvpn']['openvpn-server'])) {
950
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
951
				if ($gwgroupname == $settings['interface']) {
952
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
953
					openvpn_resync('server', $settings);
954
				}
955
			}
956
		}
957

    
958
		if (is_array($config['openvpn']['openvpn-client'])) {
959
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
960
				if ($gwgroupname == $settings['interface']) {
961
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
962
					openvpn_resync('client', $settings);
963
				}
964
			}
965
		}
966

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

    
969
	} else
970
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
971
}
972

    
973
function openvpn_get_active_servers($type="multipoint") {
974
	global $config, $g;
975

    
976
	$servers = array();
977
	if (is_array($config['openvpn']['openvpn-server'])) {
978
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
979
			if (empty($settings) || isset($settings['disable']))
980
				continue;
981

    
982
			$prot = $settings['protocol'];
983
			$port = $settings['local_port'];
984
	
985
			$server = array();
986
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
987
			$server['mode'] = $settings['mode'];
988
			if ($settings['description'])
989
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
990
			else
991
				$server['name'] = "Server {$prot}:{$port}";
992
			$server['conns'] = array();
993
			$server['vpnid'] = $settings['vpnid'];
994
			$server['mgmt'] = "server{$server['vpnid']}";
995
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
996
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
997

    
998
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
999
				$servers[] = openvpn_get_client_status($server, $socket);
1000
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1001
				$servers[] = openvpn_get_server_status($server, $socket);
1002

    
1003
		}
1004
	}
1005
	return $servers;
1006
}
1007

    
1008
function openvpn_get_server_status($server, $socket) {
1009
	$errval;
1010
	$errstr;
1011
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1012
	if ($fp) {
1013
		stream_set_timeout($fp, 1);
1014

    
1015
		/* send our status request */
1016
		fputs($fp, "status 2\n");
1017

    
1018
		/* recv all response lines */
1019
		while (!feof($fp)) {
1020

    
1021
			/* read the next line */
1022
			$line = fgets($fp, 1024);
1023

    
1024
			$info = stream_get_meta_data($fp);
1025
			if ($info['timed_out'])
1026
				break;
1027

    
1028
			/* parse header list line */
1029
			if (strstr($line, "HEADER"))
1030
				continue;
1031

    
1032
			/* parse end of output line */
1033
			if (strstr($line, "END") || strstr($line, "ERROR"))
1034
				break;
1035

    
1036
			/* parse client list line */
1037
			if (strstr($line, "CLIENT_LIST")) {
1038
				$list = explode(",", $line);
1039
				$conn = array();
1040
				$conn['common_name'] = $list[1];
1041
				$conn['remote_host'] = $list[2];
1042
				$conn['virtual_addr'] = $list[3];
1043
				$conn['bytes_recv'] = $list[4];
1044
				$conn['bytes_sent'] = $list[5];
1045
				$conn['connect_time'] = $list[6];
1046
				$server['conns'][] = $conn;
1047
			}
1048
			/* parse routing table lines */
1049
			if (strstr($line, "ROUTING_TABLE")) {
1050
				$list = explode(",", $line);
1051
				$conn = array();
1052
				$conn['virtual_addr'] = $list[1];
1053
				$conn['common_name'] = $list[2];
1054
				$conn['remote_host'] = $list[3];
1055
				$conn['last_time'] = $list[4];
1056
				$server['routes'][] = $conn;
1057
			}
1058
		}
1059

    
1060
		/* cleanup */
1061
		fclose($fp);
1062
	} else {
1063
		$conn = array();
1064
		$conn['common_name'] = "[error]";
1065
		$conn['remote_host'] = "Unable to contact daemon";
1066
		$conn['virtual_addr'] = "Service not running?";
1067
		$conn['bytes_recv'] = 0;
1068
		$conn['bytes_sent'] = 0;
1069
		$conn['connect_time'] = 0;
1070
		$server['conns'][] = $conn;
1071
	}
1072
	return $server;
1073
}
1074

    
1075
function openvpn_get_active_clients() {
1076
	global $config, $g;
1077

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

    
1085
			$prot = $settings['protocol'];
1086
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1087
	
1088
			$client = array();
1089
			$client['port'] = $settings['local_port'];
1090
			if ($settings['description'])
1091
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1092
			else
1093
				$client['name'] = "Client {$prot}{$port}";
1094
	
1095
			$client['vpnid'] = $settings['vpnid'];
1096
			$client['mgmt'] = "client{$client['vpnid']}";
1097
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1098
			$client['status']="down";
1099

    
1100
			$clients[] = openvpn_get_client_status($client, $socket);
1101
		}
1102
	}
1103
	return $clients;
1104
}
1105

    
1106
function openvpn_get_client_status($client, $socket) {
1107
	$errval;
1108
	$errstr;
1109
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1110
	if ($fp) {
1111
		stream_set_timeout($fp, 1);
1112
		/* send our status request */
1113
		fputs($fp, "state 1\n");
1114

    
1115
		/* recv all response lines */
1116
		while (!feof($fp)) {
1117
			/* read the next line */
1118
			$line = fgets($fp, 1024);
1119

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

    
1124
			/* Get the client state */
1125
			if (strstr($line,"CONNECTED")) {
1126
				$client['status']="up";
1127
				$list = explode(",", $line);
1128

    
1129
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1130
				$client['virtual_addr']  = $list[3];
1131
				$client['remote_host'] = $list[4];
1132
			}
1133
			if (strstr($line,"CONNECTING")) {
1134
				$client['status']="connecting";
1135
			}
1136
			if (strstr($line,"ASSIGN_IP")) {
1137
				$client['status']="waiting";
1138
				$list = explode(",", $line);
1139

    
1140
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1141
				$client['virtual_addr']  = $list[3];
1142
			}
1143
			if (strstr($line,"RECONNECTING")) {
1144
				$client['status']="reconnecting";
1145
				$list = explode(",", $line);
1146

    
1147
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1148
				$client['status'] .= "; " . $list[2];
1149
			}
1150
			/* parse end of output line */
1151
			if (strstr($line, "END") || strstr($line, "ERROR"))
1152
				break;
1153
		}
1154

    
1155
		/* If up, get read/write stats */
1156
		if (strcmp($client['status'], "up") == 0) {
1157
			fputs($fp, "status 2\n");
1158
			/* recv all response lines */
1159
			while (!feof($fp)) {
1160
				/* read the next line */
1161
				$line = fgets($fp, 1024);
1162

    
1163
				$info = stream_get_meta_data($fp);
1164
				if ($info['timed_out'])
1165
					break;
1166

    
1167
				if (strstr($line,"TCP/UDP read bytes")) {
1168
					$list = explode(",", $line);
1169
					$client['bytes_recv'] = $list[1];
1170
				}
1171

    
1172
				if (strstr($line,"TCP/UDP write bytes")) {
1173
					$list = explode(",", $line);
1174
					$client['bytes_sent'] = $list[1];
1175
				}
1176

    
1177
				/* parse end of output line */
1178
				if (strstr($line, "END"))
1179
					break;
1180
			}
1181
		}
1182

    
1183
		fclose($fp);
1184

    
1185
	} else {
1186
		$DisplayNote=true;
1187
		$client['remote_host'] = "Unable to contact daemon";
1188
		$client['virtual_addr'] = "Service not running?";
1189
		$client['bytes_recv'] = 0;
1190
		$client['bytes_sent'] = 0;
1191
		$client['connect_time'] = 0;
1192
	}
1193
	return $client;
1194
}
1195

    
1196
function openvpn_refresh_crls() {
1197
	global $g, $config;
1198

    
1199
	openvpn_create_dirs();
1200

    
1201
	if (is_array($config['openvpn']['openvpn-server'])) {
1202
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1203
			if (empty($settings))
1204
				continue;
1205
			if (isset($settings['disable']))
1206
				continue;
1207
			// Write the settings for the keys
1208
			switch($settings['mode']) {
1209
				case 'p2p_tls':
1210
				case 'server_tls':
1211
				case 'server_tls_user':
1212
				case 'server_user':
1213
					if (!empty($settings['crlref'])) {
1214
						$crl = lookup_crl($settings['crlref']);
1215
						crl_update($crl);
1216
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1217
						file_put_contents($fpath, base64_decode($crl['text']));
1218
						@chmod($fpath, 0644);
1219
					}
1220
					break;
1221
			}
1222
		}
1223
	}
1224
}
1225

    
1226
function openvpn_create_dirs() {
1227
	global $g;
1228
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1229
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1230
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1231
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1232
}
1233

    
1234
function openvpn_get_interface_ip($ip, $mask) {
1235
	$baselong = ip2long32($ip) & ip2long($mask);
1236
	$ip1 = long2ip32($baselong + 1);
1237
	$ip2 = long2ip32($baselong + 2);
1238
	return array($ip1, $ip2);
1239
}
1240

    
1241
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1242
	$basev6 = gen_subnetv6($ipv6, $prefix);
1243
	// Is there a better way to do this math?
1244
	$ipv6_arr = explode(':', $basev6);
1245
	$last = hexdec(array_pop($ipv6_arr));
1246
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1247
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1248
	return array($ipv6_1, $ipv6_2);
1249
}
1250

    
1251
function openvpn_clear_route($mode, $settings) {
1252
	if (empty($settings['tunnel_network']))
1253
		return;
1254
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1255
	$mask = gen_subnet_mask($cidr);
1256
	$clear_route = false;
1257

    
1258
	switch($settings['mode']) {
1259
		case 'shared_key':
1260
			$clear_route = true;
1261
			break;
1262
		case 'p2p_tls':
1263
		case 'p2p_shared_key':
1264
			if ($cidr == 30)
1265
				$clear_route = true;
1266
			break;
1267
	}
1268

    
1269
	if ($clear_route && !empty($ip) && !empty($mask)) {
1270
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1271
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1272
		/* XXX: Family for route? */
1273
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1274
	}
1275
}
1276

    
1277
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false) {
1278
	$routes = "";
1279
	if (empty($value))
1280
		return "";
1281
	$networks = explode(',', $value);
1282

    
1283
	foreach ($networks as $network) {
1284
		if ($ipproto == "ipv4")
1285
			$route = openvpn_gen_route_ipv4($network);
1286
		else
1287
			$route = openvpn_gen_route_ipv6($network);
1288

    
1289
		if ($push)
1290
			$routes .= "push \"{$route}\"\n";
1291
		else
1292
			$routes .= "{$route}\n";
1293
	}
1294
	return $routes;
1295
}
1296

    
1297
function openvpn_gen_route_ipv4($network) {
1298
	list($ip, $mask) = explode('/', trim($network));
1299
	$mask = gen_subnet_mask($mask);
1300
	return "route $ip $mask";
1301
}
1302

    
1303
function openvpn_gen_route_ipv6($network) {
1304
	list($ipv6, $prefix) = explode('/', trim($network));
1305
	if (empty($prefix))
1306
		$prefix = "128";
1307
	return "route-ipv6 ${ipv6}/${prefix}";
1308
}
1309

    
1310
function openvpn_get_settings($mode, $vpnid) {
1311
	global $config;
1312

    
1313
	if (is_array($config['openvpn']['openvpn-server'])) {
1314
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1315
			if (isset($settings['disable']))
1316
				continue;
1317

    
1318
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1319
				return $settings;
1320
		}
1321
	}
1322

    
1323
	if (is_array($config['openvpn']['openvpn-client'])) {
1324
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1325
			if (isset($settings['disable']))
1326
				continue;
1327

    
1328
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1329
				return $settings;
1330
		}
1331
	}
1332

    
1333
	return array();
1334
}
1335

    
1336
function openvpn_restart_by_vpnid($mode, $vpnid) {
1337
	$settings = openvpn_get_settings($mode, $vpnid);
1338
	openvpn_restart($mode, $settings);
1339
}
1340

    
1341
?>
(37-37/66)