Project

General

Profile

Download (40.2 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
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
function openvpn_create_key() {
98

    
99
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
100
	if (!$fp)
101
		return false;
102

    
103
	$rslt = stream_get_contents($fp);
104
	pclose($fp);
105

    
106
	return $rslt;
107
}
108

    
109
function openvpn_create_dhparams($bits) {
110

    
111
	$fp = popen("/usr/local/bin/openssl dhparam {$bits} 2>/dev/null", "r");
112
	if (!$fp)
113
		return false;
114

    
115
	$rslt = stream_get_contents($fp);
116
	pclose($fp);
117

    
118
	return $rslt;
119
}
120

    
121
function openvpn_vpnid_used($vpnid) {
122
	global $config;
123

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

    
129
	if (is_array($config['openvpn']['openvpn-client']))
130
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
131
			if ($vpnid == $settings['vpnid'])
132
				return true;
133

    
134
	return false;
135
}
136

    
137
function openvpn_vpnid_next() {
138

    
139
	$vpnid = 1;
140
	while(openvpn_vpnid_used($vpnid))
141
		$vpnid++;
142

    
143
	return $vpnid;
144
}
145

    
146
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
147
	global $config;
148

    
149
	if (is_array($config['openvpn']['openvpn-server'])) {
150
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
151
			if (isset($settings['disable']))
152
				continue;
153

    
154
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
155
				continue;
156

    
157
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
158
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
159
				return $settings['vpnid'];
160
		}
161
	}
162

    
163
	if (is_array($config['openvpn']['openvpn-client'])) {
164
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
165
			if (isset($settings['disable']))
166
				continue;
167

    
168
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
169
				continue;
170

    
171
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
172
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
173
				return $settings['vpnid'];
174
		}
175
	}
176

    
177
	return 0;
178
}
179

    
180
function openvpn_port_next($prot, $interface = "wan") {
181

    
182
	$port = 1194;
183
	while(openvpn_port_used($prot, $interface, $port))
184
		$port++;
185
	while(openvpn_port_used($prot, "any", $port))
186
		$port++;
187

    
188
	return $port;
189
}
190

    
191
function openvpn_get_cipherlist() {
192

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

    
205
function openvpn_get_engines() {
206
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
207
	exec("/usr/local/bin/openssl engine -t -c", $openssl_engine_output);
208
	$openssl_engine_output = implode("\n", $openssl_engine_output);
209
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
210
	$openssl_engine_output = explode("\n", $openssl_engine_output);
211

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

    
236
function openvpn_validate_engine($engine) {
237
	$engines = openvpn_get_engines();
238
	return array_key_exists($engine, $engines);
239
}
240

    
241
function openvpn_validate_host($value, $name) {
242
	$value = trim($value);
243
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
244
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
245
	return false;
246
}
247

    
248
function openvpn_validate_port($value, $name) {
249
	$value = trim($value);
250
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
251
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
252
	return false;
253
}
254

    
255
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
256
	$value = trim($value);
257
	$error = false;
258
	if (empty($value))
259
		return false;
260
	$networks = explode(',', $value);
261

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

    
265
	foreach ($networks as $network) {
266
		if ($ipproto == "ipv4")
267
			$error = !openvpn_validate_cidr_ipv4($network);
268
		else
269
			$error = !openvpn_validate_cidr_ipv6($network);
270
		if ($error)
271
			break;
272
	}
273

    
274
	if ($error)
275
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
276
	else
277
		return false;
278
}
279

    
280
function openvpn_validate_cidr_ipv4($value) {
281
	$value = trim($value);
282
	if (!empty($value)) {
283
		list($ip, $mask) = explode('/', $value);
284
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
285
			return false;
286
	}
287
	return true;
288
}
289

    
290
function openvpn_validate_cidr_ipv6($value) {
291
	$value = trim($value);
292
	if (!empty($value)) {
293
		list($ipv6, $prefix) = explode('/', $value);
294
		if (empty($prefix))
295
			$prefix = "128";
296
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0))
297
			return false;
298
	}
299
	return true;
300
}
301

    
302
function openvpn_add_dhcpopts(& $settings, & $conf) {
303

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

    
307
	if (!empty($settings['dns_server1']))
308
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
309
	if (!empty($settings['dns_server2']))
310
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
311
	if (!empty($settings['dns_server3']))
312
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
313
	if (!empty($settings['dns_server4']))
314
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
315

    
316
	if (!empty($settings['ntp_server1']))
317
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
318
	if (!empty($settings['ntp_server2']))
319
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
320

    
321
	if ($settings['netbios_enable']) {
322

    
323
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
324
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
325
		if (!empty($settings['dhcp_nbtscope'])) 
326
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
327

    
328
		if (!empty($settings['wins_server1']))
329
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
330
		if (!empty($settings['wins_server2']))
331
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
332

    
333
		if (!empty($settings['nbdd_server1']))
334
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
335
	}
336

    
337
	if ($settings['gwredir']) 
338
		$conf .= "push \"redirect-gateway def1\"\n";
339
}
340

    
341
function openvpn_add_custom(& $settings, & $conf) {
342

    
343
	if ($settings['custom_options']) {
344

    
345
		$options = explode(';', $settings['custom_options']);
346

    
347
		if (is_array($options)) {
348
			foreach ($options as $option)
349
				$conf .= "$option\n";
350
		} else
351
			$conf .= "{$settings['custom_options']}\n";
352
	}
353
}
354

    
355
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
356
	global $g;
357

    
358
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
359
	openvpn_create_dirs();
360
	file_put_contents($fpath, base64_decode($data));
361
	//chown($fpath, 'nobody');
362
	//chgrp($fpath, 'nobody');
363
	@chmod($fpath, 0600);
364

    
365
	$conf .= "{$directive} {$fpath} {$opt}\n";
366
}
367

    
368
function openvpn_reconfigure($mode, $settings) {
369
	global $g, $config;
370

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

    
382
	$vpnid = $settings['vpnid'];
383
	$mode_id = $mode.$vpnid;
384

    
385
	if (isset($settings['dev_mode']))
386
		$tunname = "{$settings['dev_mode']}{$vpnid}";
387
	else {	/* defaults to tun */
388
		$tunname = "tun{$vpnid}";
389
		$settings['dev_mode'] = "tun";
390
	}
391

    
392
	if ($mode == "server")
393
		$devname = "ovpns{$vpnid}";
394
	else
395
		$devname = "ovpnc{$vpnid}";
396

    
397
	/* is our device already configured */
398
	if (mwexec("/sbin/ifconfig {$devname}", true)) {
399

    
400
		/* create the tap device if required */
401
		if (!file_exists("/dev/{$tunname}"))
402
			exec("/sbin/ifconfig {$tunname} create");
403

    
404
		/* rename the device */
405
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
406

    
407
		/* add the device to the openvpn group */
408
		mwexec("/sbin/ifconfig {$devname} group openvpn");
409
	}
410

    
411
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
412
	$proto = strtolower($settings['protocol']);
413
	if (substr($settings['protocol'], 0, 3) == "TCP")
414
			$proto = "{$proto}-{$mode}";
415
	$dev_mode = $settings['dev_mode'];
416
	$cipher = $settings['crypto'];
417

    
418
	$interface = get_failover_interface($settings['interface']);
419
	$ipaddr = $settings['ipaddr'];
420
	$ipaddrv6 = $settings['ipaddrv6'];
421

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

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

    
471
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
472
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
473
		$conf .= "local {$iface_ip}\n";
474
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
475
		$conf .= "local {$iface_ipv6}\n";
476
	}
477

    
478
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
479
		$conf .= "engine {$settings['engine']}\n";
480

    
481
	// server specific settings
482
	if ($mode == 'server') {
483

    
484
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
485
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
486
		$mask = gen_subnet_mask($cidr);
487

    
488
		// configure tls modes
489
		switch($settings['mode']) {
490
			case 'p2p_tls':
491
			case 'server_tls':
492
			case 'server_user':
493
			case 'server_tls_user':
494
				$conf .= "tls-server\n";
495
				break;
496
		}
497

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

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

    
593
		// The local port to listen on
594
		$conf .= "lport {$settings['local_port']}\n";
595

    
596
		// The management port to listen on
597
		// Use unix socket to overcome the problem on any type of server
598
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
599
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
600

    
601
		if ($settings['maxclients'])
602
			$conf .= "max-clients {$settings['maxclients']}\n";
603

    
604
		// Can we push routes
605
		if ($settings['local_network']) {
606
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
607
		}
608
		if ($settings['local_networkv6']) {
609
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
610
		}
611

    
612
		switch($settings['mode']) {
613
			case 'server_tls':
614
			case 'server_user':
615
			case 'server_tls_user':
616
				// Configure client dhcp options
617
				openvpn_add_dhcpopts($settings, $conf);
618
				if ($settings['client2client'])
619
					$conf .= "client-to-client\n";
620
				break;
621
		}
622
		if (isset($settings['duplicate_cn']))
623
			$conf .= "duplicate-cn\n";
624
	}
625

    
626
	// client specific settings
627

    
628
	if ($mode == 'client') {
629

    
630
		// configure p2p mode
631
		switch($settings['mode']) {
632
			case 'p2p_tls':
633
				$conf .= "tls-client\n";
634
			case 'shared_key':
635
				$conf .= "client\n";
636
				break;
637
		}
638

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

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

    
652
		// The remote server
653
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
654

    
655
		if (!empty($settings['use_shaper']))
656
			$conf .= "shaper {$settings['use_shaper']}\n";
657

    
658
		if (!empty($settings['tunnel_network'])) {
659
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
660
			$mask = gen_subnet_mask($mask);
661
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
662
			if ($settings['dev_mode'] == 'tun')
663
				$conf .= "ifconfig {$ip2} {$ip1}\n";
664
			else
665
				$conf .= "ifconfig {$ip2} {$mask}\n";
666
		}
667

    
668
		if (!empty($settings['tunnel_networkv6'])) {
669
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
670
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
671
			if ($settings['dev_mode'] == 'tun')
672
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
673
			else
674
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
675
		}
676

    
677
		if ($settings['proxy_addr']) {
678
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
679
			if ($settings['proxy_authtype'] != "none") {
680
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
681
				$proxypas = "{$settings['proxy_user']}\n";
682
				$proxypas .= "{$settings['proxy_passwd']}\n";
683
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
684
			}
685
			$conf .= " \n";
686
		}
687
	}
688

    
689
	// Add a remote network route if set, and only for p2p modes.
690
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
691
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
692
	}
693
	// Add a remote network route if set, and only for p2p modes.
694
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
695
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
696
	}
697

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

    
729
	if ($settings['compression'])
730
		$conf .= "comp-lzo\n";
731

    
732
	if ($settings['passtos'])
733
		$conf .= "passtos\n";
734

    
735
	if ($settings['resolve_retry'])
736
		$conf .= "resolv-retry infinite\n";
737

    
738
	if ($settings['dynamic_ip']) {
739
		$conf .= "persist-remote-ip\n";
740
		$conf .= "float\n";
741
	}
742

    
743
	if ($settings['topology_subnet']) {
744
		$conf .= "topology subnet\n";
745
	}
746

    
747
	openvpn_add_custom($settings, $conf);
748

    
749
	openvpn_create_dirs();
750
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
751
	file_put_contents($fpath, $conf);
752
	unset($conf);
753
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
754
	file_put_contents($fpath, $interface);
755
	//chown($fpath, 'nobody');
756
	//chgrp($fpath, 'nobody');
757
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
758
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
759
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
760
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
761
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
762
}
763

    
764
function openvpn_restart($mode, $settings) {
765
	global $g, $config;
766

    
767
	$vpnid = $settings['vpnid'];
768
	$mode_id = $mode.$vpnid;
769

    
770
	/* kill the process if running */
771
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
772
	if (file_exists($pfile)) {
773

    
774
		/* read the pid file */
775
		$pid = rtrim(file_get_contents($pfile));
776
		unlink($pfile);
777

    
778
		/* send a term signal to the process */
779
		posix_kill($pid, SIGTERM);
780

    
781
		/* wait until the process exits */
782
		while(posix_kill($pid, 0))
783
			usleep(250000);
784
	}
785

    
786
	if (isset($settings['disable']))
787
		return;
788

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

    
793
    /* Check if client is bound to a gateway group */    
794
    $a_groups = return_gateway_groups_array();
795
    if (is_array($a_groups[$settings['interface']])) {
796
        /* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
797
        if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
798
            return;
799
    }
800

    
801
	/* start the new process */
802
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
803
	openvpn_clear_route($mode, $settings);
804
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
805

    
806
	if (!$g['booting'])
807
		send_event("filter reload");
808
}
809

    
810
function openvpn_delete($mode, & $settings) {
811
	global $g, $config;
812

    
813
	$vpnid = $settings['vpnid'];
814
	$mode_id = $mode.$vpnid;
815

    
816
	if (isset($settings['dev_mode']))
817
		$tunname = "{$settings['dev_mode']}{$vpnid}";
818
	else {  /* defaults to tun */
819
		$tunname = "tun{$vpnid}";
820
	}
821

    
822
	if ($mode == "server")
823
		$devname = "ovpns{$vpnid}";
824
	else
825
		$devname = "ovpnc{$vpnid}";
826

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

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

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

    
839
	/* remove the device from the openvpn group */
840
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
841

    
842
	/* restore the original adapter name */
843
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
844

    
845
	/* remove the configuration files */
846
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
847
}
848

    
849
function openvpn_cleanup_csc($common_name) {
850
	global $g, $config;
851
	if (empty($common_name))
852
		return;
853
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
854
	if (is_file($fpath))
855
		unlink_if_exists($fpath);
856
	return;
857
}
858

    
859
function openvpn_resync_csc(& $settings) {
860
	global $g, $config;
861

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

    
864
	if (isset($settings['disable'])) {
865
		unlink_if_exists($fpath);
866
		return;
867
	}
868
	openvpn_create_dirs();
869

    
870
	$conf = '';
871
	if ($settings['block'])
872
		$conf .= "disable\n";
873

    
874
	if ($settings['push_reset'])
875
		$conf .= "push-reset\n";
876

    
877
	if (!empty($settings['tunnel_network'])) {
878
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
879
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
880
		$serverip = long2ip32($baselong + 1);
881
		$clientip = long2ip32($baselong + 2);
882
		/* Because this is being pushed, the order from the client's point of view. */
883
		if ($settings['dev_mode'] != 'tap')
884
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
885
		else
886
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
887
	}
888

    
889
	openvpn_add_dhcpopts($settings, $conf);
890

    
891
	if ($settings['gwredir'])
892
		$conf .= "push \"redirect-gateway def1\"\n";
893

    
894
	openvpn_add_custom($settings, $conf);
895

    
896
	file_put_contents($fpath, $conf);
897
	chown($fpath, 'nobody');
898
	chgrp($fpath, 'nobody');
899
}
900

    
901
function openvpn_delete_csc(& $settings) {
902
	global $g, $config;
903

    
904
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
905
	unlink_if_exists($fpath);
906
}
907

    
908
// Resync the configuration and restart the VPN
909
function openvpn_resync($mode, $settings) {
910
	openvpn_reconfigure($mode, $settings);
911
	openvpn_restart($mode, $settings);
912
}
913

    
914
// Resync and restart all VPNs
915
function openvpn_resync_all($interface = "") {
916
	global $g, $config;
917

    
918
	if ($g['platform'] == 'jail')
919
		return;
920
	openvpn_create_dirs();
921

    
922
	if (!is_array($config['openvpn']))
923
		$config['openvpn'] = array();
924

    
925
/*
926
	if (!$config['openvpn']['dh-parameters']) {
927
		echo "Configuring OpenVPN Parameters ...\n";
928
		$dh_parameters = openvpn_create_dhparams(1024);
929
		$dh_parameters = base64_encode($dh_parameters);
930
		$config['openvpn']['dh-parameters'] = $dh_parameters;
931
		write_config("OpenVPN DH parameters");
932
	}
933

    
934
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
935
	if (!file_exists($path_ovdh)) {
936
		$dh_parameters = $config['openvpn']['dh-parameters'];
937
		$dh_parameters = base64_decode($dh_parameters);
938
		file_put_contents($path_ovdh, $dh_parameters);
939
	}
940
*/
941
	if ($interface <> "")
942
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
943
	else
944
		log_error("Resyncing OpenVPN instances."); 
945

    
946
	if (is_array($config['openvpn']['openvpn-server'])) {
947
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
948
			if ($interface <> "" && $interface != $settings['interface'])
949
				continue;
950
			openvpn_resync('server', $settings);
951
		}
952
	}
953

    
954
	if (is_array($config['openvpn']['openvpn-client'])) {
955
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
956
			if ($interface <> "" && $interface != $settings['interface'])
957
				continue;
958
			openvpn_resync('client', $settings);
959
		}
960
	}
961

    
962
	if (is_array($config['openvpn']['openvpn-csc']))
963
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
964
			openvpn_resync_csc($settings);
965

    
966
}
967

    
968
// Resync and restart all VPNs using a gateway group.
969
function openvpn_resync_gwgroup($gwgroupname = "") {
970
	global $g, $config;
971

    
972
	if ($gwgroupname <> "") {
973
		if (is_array($config['openvpn']['openvpn-server'])) {
974
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
975
				if ($gwgroupname == $settings['interface']) {
976
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
977
					openvpn_resync('server', $settings);
978
				}
979
			}
980
		}
981

    
982
		if (is_array($config['openvpn']['openvpn-client'])) {
983
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
984
				if ($gwgroupname == $settings['interface']) {
985
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
986
					openvpn_resync('client', $settings);
987
				}
988
			}
989
		}
990

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

    
993
	} else
994
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
995
}
996

    
997
function openvpn_get_active_servers($type="multipoint") {
998
	global $config, $g;
999

    
1000
	$servers = array();
1001
	if (is_array($config['openvpn']['openvpn-server'])) {
1002
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1003
			if (empty($settings) || isset($settings['disable']))
1004
				continue;
1005

    
1006
			$prot = $settings['protocol'];
1007
			$port = $settings['local_port'];
1008
	
1009
			$server = array();
1010
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1011
			$server['mode'] = $settings['mode'];
1012
			if ($settings['description'])
1013
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1014
			else
1015
				$server['name'] = "Server {$prot}:{$port}";
1016
			$server['conns'] = array();
1017
			$server['vpnid'] = $settings['vpnid'];
1018
			$server['mgmt'] = "server{$server['vpnid']}";
1019
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1020
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1021

    
1022
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1023
				$servers[] = openvpn_get_client_status($server, $socket);
1024
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1025
				$servers[] = openvpn_get_server_status($server, $socket);
1026

    
1027
		}
1028
	}
1029
	return $servers;
1030
}
1031

    
1032
function openvpn_get_server_status($server, $socket) {
1033
	$errval;
1034
	$errstr;
1035
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1036
	if ($fp) {
1037
		stream_set_timeout($fp, 1);
1038

    
1039
		/* send our status request */
1040
		fputs($fp, "status 2\n");
1041

    
1042
		/* recv all response lines */
1043
		while (!feof($fp)) {
1044

    
1045
			/* read the next line */
1046
			$line = fgets($fp, 1024);
1047

    
1048
			$info = stream_get_meta_data($fp);
1049
			if ($info['timed_out'])
1050
				break;
1051

    
1052
			/* parse header list line */
1053
			if (strstr($line, "HEADER"))
1054
				continue;
1055

    
1056
			/* parse end of output line */
1057
			if (strstr($line, "END") || strstr($line, "ERROR"))
1058
				break;
1059

    
1060
			/* parse client list line */
1061
			if (strstr($line, "CLIENT_LIST")) {
1062
				$list = explode(",", $line);
1063
				$conn = array();
1064
				$conn['common_name'] = $list[1];
1065
				$conn['remote_host'] = $list[2];
1066
				$conn['virtual_addr'] = $list[3];
1067
				$conn['bytes_recv'] = $list[4];
1068
				$conn['bytes_sent'] = $list[5];
1069
				$conn['connect_time'] = $list[6];
1070
				$server['conns'][] = $conn;
1071
			}
1072
			/* parse routing table lines */
1073
			if (strstr($line, "ROUTING_TABLE")) {
1074
				$list = explode(",", $line);
1075
				$conn = array();
1076
				$conn['virtual_addr'] = $list[1];
1077
				$conn['common_name'] = $list[2];
1078
				$conn['remote_host'] = $list[3];
1079
				$conn['last_time'] = $list[4];
1080
				$server['routes'][] = $conn;
1081
			}
1082
		}
1083

    
1084
		/* cleanup */
1085
		fclose($fp);
1086
	} else {
1087
		$conn = array();
1088
		$conn['common_name'] = "[error]";
1089
		$conn['remote_host'] = "Unable to contact daemon";
1090
		$conn['virtual_addr'] = "Service not running?";
1091
		$conn['bytes_recv'] = 0;
1092
		$conn['bytes_sent'] = 0;
1093
		$conn['connect_time'] = 0;
1094
		$server['conns'][] = $conn;
1095
	}
1096
	return $server;
1097
}
1098

    
1099
function openvpn_get_active_clients() {
1100
	global $config, $g;
1101

    
1102
	$clients = array();
1103
	if (is_array($config['openvpn']['openvpn-client'])) {
1104
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1105
	
1106
			if (empty($settings) || isset($settings['disable']))
1107
				continue;
1108

    
1109
			$prot = $settings['protocol'];
1110
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1111
	
1112
			$client = array();
1113
			$client['port'] = $settings['local_port'];
1114
			if ($settings['description'])
1115
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1116
			else
1117
				$client['name'] = "Client {$prot}{$port}";
1118
	
1119
			$client['vpnid'] = $settings['vpnid'];
1120
			$client['mgmt'] = "client{$client['vpnid']}";
1121
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1122
			$client['status']="down";
1123

    
1124
			$clients[] = openvpn_get_client_status($client, $socket);
1125
		}
1126
	}
1127
	return $clients;
1128
}
1129

    
1130
function openvpn_get_client_status($client, $socket) {
1131
	$errval;
1132
	$errstr;
1133
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1134
	if ($fp) {
1135
		stream_set_timeout($fp, 1);
1136
		/* send our status request */
1137
		fputs($fp, "state 1\n");
1138

    
1139
		/* recv all response lines */
1140
		while (!feof($fp)) {
1141
			/* read the next line */
1142
			$line = fgets($fp, 1024);
1143

    
1144
			$info = stream_get_meta_data($fp);
1145
			if ($info['timed_out'])
1146
				break;
1147

    
1148
			/* Get the client state */
1149
			if (strstr($line,"CONNECTED")) {
1150
				$client['status']="up";
1151
				$list = explode(",", $line);
1152

    
1153
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1154
				$client['virtual_addr']  = $list[3];
1155
				$client['remote_host'] = $list[4];
1156
			}
1157
			if (strstr($line,"CONNECTING")) {
1158
				$client['status']="connecting";
1159
			}
1160
			if (strstr($line,"ASSIGN_IP")) {
1161
				$client['status']="waiting";
1162
				$list = explode(",", $line);
1163

    
1164
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1165
				$client['virtual_addr']  = $list[3];
1166
			}
1167
			if (strstr($line,"RECONNECTING")) {
1168
				$client['status']="reconnecting";
1169
				$list = explode(",", $line);
1170

    
1171
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1172
				$client['status'] .= "; " . $list[2];
1173
			}
1174
			/* parse end of output line */
1175
			if (strstr($line, "END") || strstr($line, "ERROR"))
1176
				break;
1177
		}
1178

    
1179
		/* If up, get read/write stats */
1180
		if (strcmp($client['status'], "up") == 0) {
1181
			fputs($fp, "status 2\n");
1182
			/* recv all response lines */
1183
			while (!feof($fp)) {
1184
				/* read the next line */
1185
				$line = fgets($fp, 1024);
1186

    
1187
				$info = stream_get_meta_data($fp);
1188
				if ($info['timed_out'])
1189
					break;
1190

    
1191
				if (strstr($line,"TCP/UDP read bytes")) {
1192
					$list = explode(",", $line);
1193
					$client['bytes_recv'] = $list[1];
1194
				}
1195

    
1196
				if (strstr($line,"TCP/UDP write bytes")) {
1197
					$list = explode(",", $line);
1198
					$client['bytes_sent'] = $list[1];
1199
				}
1200

    
1201
				/* parse end of output line */
1202
				if (strstr($line, "END"))
1203
					break;
1204
			}
1205
		}
1206

    
1207
		fclose($fp);
1208

    
1209
	} else {
1210
		$DisplayNote=true;
1211
		$client['remote_host'] = "Unable to contact daemon";
1212
		$client['virtual_addr'] = "Service not running?";
1213
		$client['bytes_recv'] = 0;
1214
		$client['bytes_sent'] = 0;
1215
		$client['connect_time'] = 0;
1216
	}
1217
	return $client;
1218
}
1219

    
1220
function openvpn_refresh_crls() {
1221
	global $g, $config;
1222

    
1223
	openvpn_create_dirs();
1224

    
1225
	if (is_array($config['openvpn']['openvpn-server'])) {
1226
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1227
			if (empty($settings))
1228
				continue;
1229
			if (isset($settings['disable']))
1230
				continue;
1231
			// Write the settings for the keys
1232
			switch($settings['mode']) {
1233
				case 'p2p_tls':
1234
				case 'server_tls':
1235
				case 'server_tls_user':
1236
				case 'server_user':
1237
					if (!empty($settings['crlref'])) {
1238
						$crl = lookup_crl($settings['crlref']);
1239
						crl_update($crl);
1240
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1241
						file_put_contents($fpath, base64_decode($crl['text']));
1242
						@chmod($fpath, 0644);
1243
					}
1244
					break;
1245
			}
1246
		}
1247
	}
1248
}
1249

    
1250
function openvpn_create_dirs() {
1251
	global $g;
1252
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1253
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1254
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1255
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1256
}
1257

    
1258
function openvpn_get_interface_ip($ip, $mask) {
1259
	$baselong = ip2long32($ip) & ip2long($mask);
1260
	$ip1 = long2ip32($baselong + 1);
1261
	$ip2 = long2ip32($baselong + 2);
1262
	return array($ip1, $ip2);
1263
}
1264

    
1265
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1266
	$basev6 = gen_subnetv6($ipv6, $prefix);
1267
	// Is there a better way to do this math?
1268
	$ipv6_arr = explode(':', $basev6);
1269
	$last = hexdec(array_pop($ipv6_arr));
1270
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1271
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1272
	return array($ipv6_1, $ipv6_2);
1273
}
1274

    
1275
function openvpn_clear_route($mode, $settings) {
1276
	if (empty($settings['tunnel_network']))
1277
		return;
1278
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1279
	$mask = gen_subnet_mask($cidr);
1280
	$clear_route = false;
1281

    
1282
	switch($settings['mode']) {
1283
		case 'shared_key':
1284
			$clear_route = true;
1285
			break;
1286
		case 'p2p_tls':
1287
		case 'p2p_shared_key':
1288
			if ($cidr == 30)
1289
				$clear_route = true;
1290
			break;
1291
	}
1292

    
1293
	if ($clear_route && !empty($ip) && !empty($mask)) {
1294
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1295
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1296
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1297
	}
1298
}
1299

    
1300
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false) {
1301
	$routes = "";
1302
	if (empty($value))
1303
		return "";
1304
	$networks = explode(',', $value);
1305

    
1306
	foreach ($networks as $network) {
1307
		if ($ipproto == "ipv4")
1308
			$route = openvpn_gen_route_ipv4($network);
1309
		else
1310
			$route = openvpn_gen_route_ipv6($network);
1311

    
1312
		if ($push)
1313
			$routes .= "push \"{$route}\"\n";
1314
		else
1315
			$routes .= "{$route}\n";
1316
	}
1317
	return $routes;
1318
}
1319

    
1320
function openvpn_gen_route_ipv4($network) {
1321
	list($ip, $mask) = explode('/', trim($network));
1322
	$mask = gen_subnet_mask($mask);
1323
	return "route $ip $mask";
1324
}
1325

    
1326
function openvpn_gen_route_ipv6($network) {
1327
	list($ipv6, $prefix) = explode('/', trim($network));
1328
	if (empty($prefix))
1329
		$prefix = "128";
1330
	return "route-ipv6 ${ipv6}/${prefix}";
1331
}
1332

    
1333
function openvpn_get_settings($mode, $vpnid) {
1334
	global $config;
1335

    
1336
	if (is_array($config['openvpn']['openvpn-server'])) {
1337
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1338
			if (isset($settings['disable']))
1339
				continue;
1340

    
1341
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1342
				return $settings;
1343
		}
1344
	}
1345

    
1346
	if (is_array($config['openvpn']['openvpn-client'])) {
1347
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1348
			if (isset($settings['disable']))
1349
				continue;
1350

    
1351
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1352
				return $settings;
1353
		}
1354
	}
1355

    
1356
	return array();
1357
}
1358

    
1359
function openvpn_restart_by_vpnid($mode, $vpnid) {
1360
	$settings = openvpn_get_settings($mode, $vpnid);
1361
	openvpn_restart($mode, $settings);
1362
}
1363

    
1364
?>
(37-37/66)