Project

General

Profile

Download (39.8 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
	/* start the new process */
794
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
795
	openvpn_clear_route($mode, $settings);
796
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
797

    
798
	if (!$g['booting'])
799
		send_event("filter reload");
800
}
801

    
802
function openvpn_delete($mode, & $settings) {
803
	global $g, $config;
804

    
805
	$vpnid = $settings['vpnid'];
806
	$mode_id = $mode.$vpnid;
807

    
808
	if (isset($settings['dev_mode']))
809
		$tunname = "{$settings['dev_mode']}{$vpnid}";
810
	else {  /* defaults to tun */
811
		$tunname = "tun{$vpnid}";
812
	}
813

    
814
	if ($mode == "server")
815
		$devname = "ovpns{$vpnid}";
816
	else
817
		$devname = "ovpnc{$vpnid}";
818

    
819
	/* kill the process if running */
820
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
821
	if (file_exists($pfile)) {
822

    
823
		/* read the pid file */
824
		$pid = trim(file_get_contents($pfile));
825
		unlink($pfile);
826

    
827
		/* send a term signal to the process */
828
		posix_kill($pid, SIGTERM);
829
	}
830

    
831
	/* remove the device from the openvpn group */
832
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
833

    
834
	/* restore the original adapter name */
835
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
836

    
837
	/* remove the configuration files */
838
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
839
}
840

    
841
function openvpn_cleanup_csc($common_name) {
842
	global $g, $config;
843
	if (empty($common_name))
844
		return;
845
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
846
	if (is_file($fpath))
847
		unlink_if_exists($fpath);
848
	return;
849
}
850

    
851
function openvpn_resync_csc(& $settings) {
852
	global $g, $config;
853

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

    
856
	if (isset($settings['disable'])) {
857
		unlink_if_exists($fpath);
858
		return;
859
	}
860
	openvpn_create_dirs();
861

    
862
	$conf = '';
863
	if ($settings['block'])
864
		$conf .= "disable\n";
865

    
866
	if ($settings['push_reset'])
867
		$conf .= "push-reset\n";
868

    
869
	if (!empty($settings['tunnel_network'])) {
870
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
871
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
872
		$serverip = long2ip32($baselong + 1);
873
		$clientip = long2ip32($baselong + 2);
874
		/* Because this is being pushed, the order from the client's point of view. */
875
		if ($settings['dev_mode'] != 'tap')
876
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
877
		else
878
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
879
	}
880

    
881
	openvpn_add_dhcpopts($settings, $conf);
882

    
883
	if ($settings['gwredir'])
884
		$conf .= "push \"redirect-gateway def1\"\n";
885

    
886
	openvpn_add_custom($settings, $conf);
887

    
888
	file_put_contents($fpath, $conf);
889
	chown($fpath, 'nobody');
890
	chgrp($fpath, 'nobody');
891
}
892

    
893
function openvpn_delete_csc(& $settings) {
894
	global $g, $config;
895

    
896
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
897
	unlink_if_exists($fpath);
898
}
899

    
900
// Resync the configuration and restart the VPN
901
function openvpn_resync($mode, $settings) {
902
	openvpn_reconfigure($mode, $settings);
903
	openvpn_restart($mode, $settings);
904
}
905

    
906
// Resync and restart all VPNs
907
function openvpn_resync_all($interface = "") {
908
	global $g, $config;
909

    
910
	if ($g['platform'] == 'jail')
911
		return;
912
	openvpn_create_dirs();
913

    
914
	if (!is_array($config['openvpn']))
915
		$config['openvpn'] = array();
916

    
917
/*
918
	if (!$config['openvpn']['dh-parameters']) {
919
		echo "Configuring OpenVPN Parameters ...\n";
920
		$dh_parameters = openvpn_create_dhparams(1024);
921
		$dh_parameters = base64_encode($dh_parameters);
922
		$config['openvpn']['dh-parameters'] = $dh_parameters;
923
		write_config("OpenVPN DH parameters");
924
	}
925

    
926
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
927
	if (!file_exists($path_ovdh)) {
928
		$dh_parameters = $config['openvpn']['dh-parameters'];
929
		$dh_parameters = base64_decode($dh_parameters);
930
		file_put_contents($path_ovdh, $dh_parameters);
931
	}
932
*/
933
	if ($interface <> "")
934
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
935
	else
936
		log_error("Resyncing OpenVPN instances."); 
937

    
938
	if (is_array($config['openvpn']['openvpn-server'])) {
939
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
940
			if ($interface <> "" && $interface != $settings['interface'])
941
				continue;
942
			openvpn_resync('server', $settings);
943
		}
944
	}
945

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

    
954
	if (is_array($config['openvpn']['openvpn-csc']))
955
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
956
			openvpn_resync_csc($settings);
957

    
958
}
959

    
960
// Resync and restart all VPNs using a gateway group.
961
function openvpn_resync_gwgroup($gwgroupname = "") {
962
	global $g, $config;
963

    
964
	if ($gwgroupname <> "") {
965
		if (is_array($config['openvpn']['openvpn-server'])) {
966
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
967
				if ($gwgroupname == $settings['interface']) {
968
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
969
					openvpn_resync('server', $settings);
970
				}
971
			}
972
		}
973

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

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

    
985
	} else
986
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
987
}
988

    
989
function openvpn_get_active_servers($type="multipoint") {
990
	global $config, $g;
991

    
992
	$servers = array();
993
	if (is_array($config['openvpn']['openvpn-server'])) {
994
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
995
			if (empty($settings) || isset($settings['disable']))
996
				continue;
997

    
998
			$prot = $settings['protocol'];
999
			$port = $settings['local_port'];
1000
	
1001
			$server = array();
1002
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1003
			$server['mode'] = $settings['mode'];
1004
			if ($settings['description'])
1005
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1006
			else
1007
				$server['name'] = "Server {$prot}:{$port}";
1008
			$server['conns'] = array();
1009
			$server['vpnid'] = $settings['vpnid'];
1010
			$server['mgmt'] = "server{$server['vpnid']}";
1011
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1012
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1013

    
1014
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1015
				$servers[] = openvpn_get_client_status($server, $socket);
1016
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1017
				$servers[] = openvpn_get_server_status($server, $socket);
1018

    
1019
		}
1020
	}
1021
	return $servers;
1022
}
1023

    
1024
function openvpn_get_server_status($server, $socket) {
1025
	$errval;
1026
	$errstr;
1027
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1028
	if ($fp) {
1029
		stream_set_timeout($fp, 1);
1030

    
1031
		/* send our status request */
1032
		fputs($fp, "status 2\n");
1033

    
1034
		/* recv all response lines */
1035
		while (!feof($fp)) {
1036

    
1037
			/* read the next line */
1038
			$line = fgets($fp, 1024);
1039

    
1040
			$info = stream_get_meta_data($fp);
1041
			if ($info['timed_out'])
1042
				break;
1043

    
1044
			/* parse header list line */
1045
			if (strstr($line, "HEADER"))
1046
				continue;
1047

    
1048
			/* parse end of output line */
1049
			if (strstr($line, "END") || strstr($line, "ERROR"))
1050
				break;
1051

    
1052
			/* parse client list line */
1053
			if (strstr($line, "CLIENT_LIST")) {
1054
				$list = explode(",", $line);
1055
				$conn = array();
1056
				$conn['common_name'] = $list[1];
1057
				$conn['remote_host'] = $list[2];
1058
				$conn['virtual_addr'] = $list[3];
1059
				$conn['bytes_recv'] = $list[4];
1060
				$conn['bytes_sent'] = $list[5];
1061
				$conn['connect_time'] = $list[6];
1062
				$server['conns'][] = $conn;
1063
			}
1064
			/* parse routing table lines */
1065
			if (strstr($line, "ROUTING_TABLE")) {
1066
				$list = explode(",", $line);
1067
				$conn = array();
1068
				$conn['virtual_addr'] = $list[1];
1069
				$conn['common_name'] = $list[2];
1070
				$conn['remote_host'] = $list[3];
1071
				$conn['last_time'] = $list[4];
1072
				$server['routes'][] = $conn;
1073
			}
1074
		}
1075

    
1076
		/* cleanup */
1077
		fclose($fp);
1078
	} else {
1079
		$conn = array();
1080
		$conn['common_name'] = "[error]";
1081
		$conn['remote_host'] = "Unable to contact daemon";
1082
		$conn['virtual_addr'] = "Service not running?";
1083
		$conn['bytes_recv'] = 0;
1084
		$conn['bytes_sent'] = 0;
1085
		$conn['connect_time'] = 0;
1086
		$server['conns'][] = $conn;
1087
	}
1088
	return $server;
1089
}
1090

    
1091
function openvpn_get_active_clients() {
1092
	global $config, $g;
1093

    
1094
	$clients = array();
1095
	if (is_array($config['openvpn']['openvpn-client'])) {
1096
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1097
	
1098
			if (empty($settings) || isset($settings['disable']))
1099
				continue;
1100

    
1101
			$prot = $settings['protocol'];
1102
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1103
	
1104
			$client = array();
1105
			$client['port'] = $settings['local_port'];
1106
			if ($settings['description'])
1107
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1108
			else
1109
				$client['name'] = "Client {$prot}{$port}";
1110
	
1111
			$client['vpnid'] = $settings['vpnid'];
1112
			$client['mgmt'] = "client{$client['vpnid']}";
1113
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1114
			$client['status']="down";
1115

    
1116
			$clients[] = openvpn_get_client_status($client, $socket);
1117
		}
1118
	}
1119
	return $clients;
1120
}
1121

    
1122
function openvpn_get_client_status($client, $socket) {
1123
	$errval;
1124
	$errstr;
1125
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1126
	if ($fp) {
1127
		stream_set_timeout($fp, 1);
1128
		/* send our status request */
1129
		fputs($fp, "state 1\n");
1130

    
1131
		/* recv all response lines */
1132
		while (!feof($fp)) {
1133
			/* read the next line */
1134
			$line = fgets($fp, 1024);
1135

    
1136
			$info = stream_get_meta_data($fp);
1137
			if ($info['timed_out'])
1138
				break;
1139

    
1140
			/* Get the client state */
1141
			if (strstr($line,"CONNECTED")) {
1142
				$client['status']="up";
1143
				$list = explode(",", $line);
1144

    
1145
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1146
				$client['virtual_addr']  = $list[3];
1147
				$client['remote_host'] = $list[4];
1148
			}
1149
			if (strstr($line,"CONNECTING")) {
1150
				$client['status']="connecting";
1151
			}
1152
			if (strstr($line,"ASSIGN_IP")) {
1153
				$client['status']="waiting";
1154
				$list = explode(",", $line);
1155

    
1156
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1157
				$client['virtual_addr']  = $list[3];
1158
			}
1159
			if (strstr($line,"RECONNECTING")) {
1160
				$client['status']="reconnecting";
1161
				$list = explode(",", $line);
1162

    
1163
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1164
				$client['status'] .= "; " . $list[2];
1165
			}
1166
			/* parse end of output line */
1167
			if (strstr($line, "END") || strstr($line, "ERROR"))
1168
				break;
1169
		}
1170

    
1171
		/* If up, get read/write stats */
1172
		if (strcmp($client['status'], "up") == 0) {
1173
			fputs($fp, "status 2\n");
1174
			/* recv all response lines */
1175
			while (!feof($fp)) {
1176
				/* read the next line */
1177
				$line = fgets($fp, 1024);
1178

    
1179
				$info = stream_get_meta_data($fp);
1180
				if ($info['timed_out'])
1181
					break;
1182

    
1183
				if (strstr($line,"TCP/UDP read bytes")) {
1184
					$list = explode(",", $line);
1185
					$client['bytes_recv'] = $list[1];
1186
				}
1187

    
1188
				if (strstr($line,"TCP/UDP write bytes")) {
1189
					$list = explode(",", $line);
1190
					$client['bytes_sent'] = $list[1];
1191
				}
1192

    
1193
				/* parse end of output line */
1194
				if (strstr($line, "END"))
1195
					break;
1196
			}
1197
		}
1198

    
1199
		fclose($fp);
1200

    
1201
	} else {
1202
		$DisplayNote=true;
1203
		$client['remote_host'] = "Unable to contact daemon";
1204
		$client['virtual_addr'] = "Service not running?";
1205
		$client['bytes_recv'] = 0;
1206
		$client['bytes_sent'] = 0;
1207
		$client['connect_time'] = 0;
1208
	}
1209
	return $client;
1210
}
1211

    
1212
function openvpn_refresh_crls() {
1213
	global $g, $config;
1214

    
1215
	openvpn_create_dirs();
1216

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

    
1242
function openvpn_create_dirs() {
1243
	global $g;
1244
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1245
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1246
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1247
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1248
}
1249

    
1250
function openvpn_get_interface_ip($ip, $mask) {
1251
	$baselong = ip2long32($ip) & ip2long($mask);
1252
	$ip1 = long2ip32($baselong + 1);
1253
	$ip2 = long2ip32($baselong + 2);
1254
	return array($ip1, $ip2);
1255
}
1256

    
1257
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1258
	$basev6 = gen_subnetv6($ipv6, $prefix);
1259
	// Is there a better way to do this math?
1260
	$ipv6_arr = explode(':', $basev6);
1261
	$last = hexdec(array_pop($ipv6_arr));
1262
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1263
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1264
	return array($ipv6_1, $ipv6_2);
1265
}
1266

    
1267
function openvpn_clear_route($mode, $settings) {
1268
	if (empty($settings['tunnel_network']))
1269
		return;
1270
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1271
	$mask = gen_subnet_mask($cidr);
1272
	$clear_route = false;
1273

    
1274
	switch($settings['mode']) {
1275
		case 'shared_key':
1276
			$clear_route = true;
1277
			break;
1278
		case 'p2p_tls':
1279
		case 'p2p_shared_key':
1280
			if ($cidr == 30)
1281
				$clear_route = true;
1282
			break;
1283
	}
1284

    
1285
	if ($clear_route && !empty($ip) && !empty($mask)) {
1286
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1287
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1288
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1289
	}
1290
}
1291

    
1292
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false) {
1293
	$routes = "";
1294
	if (empty($value))
1295
		return "";
1296
	$networks = explode(',', $value);
1297

    
1298
	foreach ($networks as $network) {
1299
		if ($ipproto == "ipv4")
1300
			$route = openvpn_gen_route_ipv4($network);
1301
		else
1302
			$route = openvpn_gen_route_ipv6($network);
1303

    
1304
		if ($push)
1305
			$routes .= "push \"{$route}\"\n";
1306
		else
1307
			$routes .= "{$route}\n";
1308
	}
1309
	return $routes;
1310
}
1311

    
1312
function openvpn_gen_route_ipv4($network) {
1313
	list($ip, $mask) = explode('/', trim($network));
1314
	$mask = gen_subnet_mask($mask);
1315
	return "route $ip $mask";
1316
}
1317

    
1318
function openvpn_gen_route_ipv6($network) {
1319
	list($ipv6, $prefix) = explode('/', trim($network));
1320
	if (empty($prefix))
1321
		$prefix = "128";
1322
	return "route-ipv6 ${ipv6}/${prefix}";
1323
}
1324

    
1325
function openvpn_get_settings($mode, $vpnid) {
1326
	global $config;
1327

    
1328
	if (is_array($config['openvpn']['openvpn-server'])) {
1329
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1330
			if (isset($settings['disable']))
1331
				continue;
1332

    
1333
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1334
				return $settings;
1335
		}
1336
	}
1337

    
1338
	if (is_array($config['openvpn']['openvpn-client'])) {
1339
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1340
			if (isset($settings['disable']))
1341
				continue;
1342

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

    
1348
	return array();
1349
}
1350

    
1351
function openvpn_restart_by_vpnid($mode, $vpnid) {
1352
	$settings = openvpn_get_settings($mode, $vpnid);
1353
	openvpn_restart($mode, $settings);
1354
}
1355

    
1356
?>
(37-37/66)