Project

General

Profile

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

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

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

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

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

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

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

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

    
46
*/
47
require_once('config.inc');
48
require_once("certs.inc");
49
require_once('pfsense-utils.inc');
50
require_once("auth.inc");
51

    
52
global $openvpn_prots;
53
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
54

    
55
global $openvpn_dev_mode;
56
$openvpn_dev_mode = array("tun", "tap");
57

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

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

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

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

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

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

    
104
function openvpn_create_key() {
105

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

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

    
113
	return $rslt;
114
}
115

    
116
function openvpn_create_dhparams($bits) {
117

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

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

    
125
	return $rslt;
126
}
127

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

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

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

    
141
	return false;
142
}
143

    
144
function openvpn_vpnid_next() {
145

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

    
150
	return $vpnid;
151
}
152

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

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

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

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

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

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

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

    
184
	return 0;
185
}
186

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

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

    
195
	return $port;
196
}
197

    
198
function openvpn_get_cipherlist() {
199

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

    
212
function openvpn_get_digestlist() {
213

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
601
		// The local port to listen on
602
		$conf .= "lport {$settings['local_port']}\n";
603

    
604
		// The management port to listen on
605
		// Use unix socket to overcome the problem on any type of server
606
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
607
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
608

    
609
		if ($settings['maxclients'])
610
			$conf .= "max-clients {$settings['maxclients']}\n";
611

    
612
		// Can we push routes
613
		if ($settings['local_network']) {
614
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
615
		}
616
		if ($settings['local_networkv6']) {
617
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
618
		}
619

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

    
634
	// client specific settings
635

    
636
	if ($mode == 'client') {
637

    
638
		// configure p2p mode
639
		switch($settings['mode']) {
640
			case 'p2p_tls':
641
				$conf .= "tls-client\n";
642
			case 'shared_key':
643
				$conf .= "client\n";
644
				break;
645
		}
646

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

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

    
660
		// The remote server
661
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
662

    
663
		if (!empty($settings['use_shaper']))
664
			$conf .= "shaper {$settings['use_shaper']}\n";
665

    
666
		if (!empty($settings['tunnel_network'])) {
667
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
668
			$mask = gen_subnet_mask($mask);
669
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
670
			if ($settings['dev_mode'] == 'tun')
671
				$conf .= "ifconfig {$ip2} {$ip1}\n";
672
			else
673
				$conf .= "ifconfig {$ip2} {$mask}\n";
674
		}
675

    
676
		if (!empty($settings['tunnel_networkv6'])) {
677
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
678
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
679
			if ($settings['dev_mode'] == 'tun')
680
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
681
			else
682
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
683
		}
684

    
685
		if ($settings['proxy_addr']) {
686
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
687
			if ($settings['proxy_authtype'] != "none") {
688
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
689
				$proxypas = "{$settings['proxy_user']}\n";
690
				$proxypas .= "{$settings['proxy_passwd']}\n";
691
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
692
			}
693
			$conf .= " \n";
694
		}
695
	}
696

    
697
	// Add a remote network route if set, and only for p2p modes.
698
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
699
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
700
	}
701
	// Add a remote network route if set, and only for p2p modes.
702
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
703
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
704
	}
705

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

    
737
	if (!empty($settings['compression']))
738
		$conf .= "comp-lzo {$settings['compression']}\n";
739

    
740
	if ($settings['passtos'])
741
		$conf .= "passtos\n";
742

    
743
	if ($settings['resolve_retry'])
744
		$conf .= "resolv-retry infinite\n";
745

    
746
	if ($settings['dynamic_ip']) {
747
		$conf .= "persist-remote-ip\n";
748
		$conf .= "float\n";
749
	}
750

    
751
	if ($settings['topology_subnet']) {
752
		$conf .= "topology subnet\n";
753
	}
754

    
755
	openvpn_add_custom($settings, $conf);
756

    
757
	openvpn_create_dirs();
758
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
759
	file_put_contents($fpath, $conf);
760
	unset($conf);
761
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
762
	file_put_contents($fpath, $interface);
763
	//chown($fpath, 'nobody');
764
	//chgrp($fpath, 'nobody');
765
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
766
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
767
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
768
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
769
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
770
}
771

    
772
function openvpn_restart($mode, $settings) {
773
	global $g, $config;
774

    
775
	$vpnid = $settings['vpnid'];
776
	$mode_id = $mode.$vpnid;
777

    
778
	/* kill the process if running */
779
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
780
	if (file_exists($pfile)) {
781

    
782
		/* read the pid file */
783
		$pid = rtrim(file_get_contents($pfile));
784
		unlink($pfile);
785

    
786
		/* send a term signal to the process */
787
		posix_kill($pid, SIGTERM);
788

    
789
		/* wait until the process exits */
790
		while(posix_kill($pid, 0))
791
			usleep(250000);
792
	}
793

    
794
	if (isset($settings['disable']))
795
		return;
796

    
797
	/* Do not start a client if we are a CARP backup on this vip! */
798
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) == "BACKUP"))
799
		return;
800
		
801
	/* Check if client is bound to a gateway group */    
802
	$a_groups = return_gateway_groups_array();
803
	if (is_array($a_groups[$settings['interface']])) {
804
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
805
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
806
			return;
807
	}
808

    
809
	/* start the new process */
810
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
811
	openvpn_clear_route($mode, $settings);
812
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
813

    
814
	if (!$g['booting'])
815
		send_event("filter reload");
816
}
817

    
818
function openvpn_delete($mode, & $settings) {
819
	global $g, $config;
820

    
821
	$vpnid = $settings['vpnid'];
822
	$mode_id = $mode.$vpnid;
823

    
824
	if (isset($settings['dev_mode']))
825
		$tunname = "{$settings['dev_mode']}{$vpnid}";
826
	else {  /* defaults to tun */
827
		$tunname = "tun{$vpnid}";
828
	}
829

    
830
	if ($mode == "server")
831
		$devname = "ovpns{$vpnid}";
832
	else
833
		$devname = "ovpnc{$vpnid}";
834

    
835
	/* kill the process if running */
836
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
837
	if (file_exists($pfile)) {
838

    
839
		/* read the pid file */
840
		$pid = trim(file_get_contents($pfile));
841
		unlink($pfile);
842

    
843
		/* send a term signal to the process */
844
		posix_kill($pid, SIGTERM);
845
	}
846

    
847
	/* remove the device from the openvpn group */
848
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
849

    
850
	/* restore the original adapter name */
851
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
852

    
853
	/* remove the configuration files */
854
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
855
}
856

    
857
function openvpn_cleanup_csc($common_name) {
858
	global $g, $config;
859
	if (empty($common_name))
860
		return;
861
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
862
	if (is_file($fpath))
863
		unlink_if_exists($fpath);
864
	return;
865
}
866

    
867
function openvpn_resync_csc(& $settings) {
868
	global $g, $config;
869

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

    
872
	if (isset($settings['disable'])) {
873
		unlink_if_exists($fpath);
874
		return;
875
	}
876
	openvpn_create_dirs();
877

    
878
	$conf = '';
879
	if ($settings['block'])
880
		$conf .= "disable\n";
881

    
882
	if ($settings['push_reset'])
883
		$conf .= "push-reset\n";
884

    
885
	if (!empty($settings['tunnel_network'])) {
886
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
887
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
888
		$serverip = long2ip32($baselong + 1);
889
		$clientip = long2ip32($baselong + 2);
890
		/* Because this is being pushed, the order from the client's point of view. */
891
		if ($settings['dev_mode'] != 'tap')
892
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
893
		else
894
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
895
	}
896

    
897
	openvpn_add_dhcpopts($settings, $conf);
898

    
899
	if ($settings['gwredir'])
900
		$conf .= "push \"redirect-gateway def1\"\n";
901

    
902
	openvpn_add_custom($settings, $conf);
903

    
904
	file_put_contents($fpath, $conf);
905
	chown($fpath, 'nobody');
906
	chgrp($fpath, 'nobody');
907
}
908

    
909
function openvpn_delete_csc(& $settings) {
910
	global $g, $config;
911

    
912
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
913
	unlink_if_exists($fpath);
914
}
915

    
916
// Resync the configuration and restart the VPN
917
function openvpn_resync($mode, $settings) {
918
	openvpn_reconfigure($mode, $settings);
919
	openvpn_restart($mode, $settings);
920
}
921

    
922
// Resync and restart all VPNs
923
function openvpn_resync_all($interface = "") {
924
	global $g, $config;
925

    
926
	if ($g['platform'] == 'jail')
927
		return;
928
	openvpn_create_dirs();
929

    
930
	if (!is_array($config['openvpn']))
931
		$config['openvpn'] = array();
932

    
933
/*
934
	if (!$config['openvpn']['dh-parameters']) {
935
		echo "Configuring OpenVPN Parameters ...\n";
936
		$dh_parameters = openvpn_create_dhparams(1024);
937
		$dh_parameters = base64_encode($dh_parameters);
938
		$config['openvpn']['dh-parameters'] = $dh_parameters;
939
		write_config("OpenVPN DH parameters");
940
	}
941

    
942
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
943
	if (!file_exists($path_ovdh)) {
944
		$dh_parameters = $config['openvpn']['dh-parameters'];
945
		$dh_parameters = base64_decode($dh_parameters);
946
		file_put_contents($path_ovdh, $dh_parameters);
947
	}
948
*/
949
	if ($interface <> "")
950
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
951
	else
952
		log_error("Resyncing OpenVPN instances."); 
953

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

    
962
	if (is_array($config['openvpn']['openvpn-client'])) {
963
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
964
			if ($interface <> "" && $interface != $settings['interface'])
965
				continue;
966
			openvpn_resync('client', $settings);
967
		}
968
	}
969

    
970
	if (is_array($config['openvpn']['openvpn-csc']))
971
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
972
			openvpn_resync_csc($settings);
973

    
974
}
975

    
976
// Resync and restart all VPNs using a gateway group.
977
function openvpn_resync_gwgroup($gwgroupname = "") {
978
	global $g, $config;
979

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

    
990
		if (is_array($config['openvpn']['openvpn-client'])) {
991
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
992
				if ($gwgroupname == $settings['interface']) {
993
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
994
					openvpn_resync('client', $settings);
995
				}
996
			}
997
		}
998

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

    
1001
	} else
1002
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1003
}
1004

    
1005
function openvpn_get_active_servers($type="multipoint") {
1006
	global $config, $g;
1007

    
1008
	$servers = array();
1009
	if (is_array($config['openvpn']['openvpn-server'])) {
1010
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1011
			if (empty($settings) || isset($settings['disable']))
1012
				continue;
1013

    
1014
			$prot = $settings['protocol'];
1015
			$port = $settings['local_port'];
1016
	
1017
			$server = array();
1018
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1019
			$server['mode'] = $settings['mode'];
1020
			if ($settings['description'])
1021
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1022
			else
1023
				$server['name'] = "Server {$prot}:{$port}";
1024
			$server['conns'] = array();
1025
			$server['vpnid'] = $settings['vpnid'];
1026
			$server['mgmt'] = "server{$server['vpnid']}";
1027
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1028
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1029

    
1030
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1031
				$servers[] = openvpn_get_client_status($server, $socket);
1032
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1033
				$servers[] = openvpn_get_server_status($server, $socket);
1034

    
1035
		}
1036
	}
1037
	return $servers;
1038
}
1039

    
1040
function openvpn_get_server_status($server, $socket) {
1041
	$errval;
1042
	$errstr;
1043
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1044
	if ($fp) {
1045
		stream_set_timeout($fp, 1);
1046

    
1047
		/* send our status request */
1048
		fputs($fp, "status 2\n");
1049

    
1050
		/* recv all response lines */
1051
		while (!feof($fp)) {
1052

    
1053
			/* read the next line */
1054
			$line = fgets($fp, 1024);
1055

    
1056
			$info = stream_get_meta_data($fp);
1057
			if ($info['timed_out'])
1058
				break;
1059

    
1060
			/* parse header list line */
1061
			if (strstr($line, "HEADER"))
1062
				continue;
1063

    
1064
			/* parse end of output line */
1065
			if (strstr($line, "END") || strstr($line, "ERROR"))
1066
				break;
1067

    
1068
			/* parse client list line */
1069
			if (strstr($line, "CLIENT_LIST")) {
1070
				$list = explode(",", $line);
1071
				$conn = array();
1072
				$conn['common_name'] = $list[1];
1073
				$conn['remote_host'] = $list[2];
1074
				$conn['virtual_addr'] = $list[3];
1075
				$conn['bytes_recv'] = $list[4];
1076
				$conn['bytes_sent'] = $list[5];
1077
				$conn['connect_time'] = $list[6];
1078
				$server['conns'][] = $conn;
1079
			}
1080
			/* parse routing table lines */
1081
			if (strstr($line, "ROUTING_TABLE")) {
1082
				$list = explode(",", $line);
1083
				$conn = array();
1084
				$conn['virtual_addr'] = $list[1];
1085
				$conn['common_name'] = $list[2];
1086
				$conn['remote_host'] = $list[3];
1087
				$conn['last_time'] = $list[4];
1088
				$server['routes'][] = $conn;
1089
			}
1090
		}
1091

    
1092
		/* cleanup */
1093
		fclose($fp);
1094
	} else {
1095
		$conn = array();
1096
		$conn['common_name'] = "[error]";
1097
		$conn['remote_host'] = "Unable to contact daemon";
1098
		$conn['virtual_addr'] = "Service not running?";
1099
		$conn['bytes_recv'] = 0;
1100
		$conn['bytes_sent'] = 0;
1101
		$conn['connect_time'] = 0;
1102
		$server['conns'][] = $conn;
1103
	}
1104
	return $server;
1105
}
1106

    
1107
function openvpn_get_active_clients() {
1108
	global $config, $g;
1109

    
1110
	$clients = array();
1111
	if (is_array($config['openvpn']['openvpn-client'])) {
1112
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1113
	
1114
			if (empty($settings) || isset($settings['disable']))
1115
				continue;
1116

    
1117
			$prot = $settings['protocol'];
1118
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1119
	
1120
			$client = array();
1121
			$client['port'] = $settings['local_port'];
1122
			if ($settings['description'])
1123
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1124
			else
1125
				$client['name'] = "Client {$prot}{$port}";
1126
	
1127
			$client['vpnid'] = $settings['vpnid'];
1128
			$client['mgmt'] = "client{$client['vpnid']}";
1129
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1130
			$client['status']="down";
1131

    
1132
			$clients[] = openvpn_get_client_status($client, $socket);
1133
		}
1134
	}
1135
	return $clients;
1136
}
1137

    
1138
function openvpn_get_client_status($client, $socket) {
1139
	$errval;
1140
	$errstr;
1141
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1142
	if ($fp) {
1143
		stream_set_timeout($fp, 1);
1144
		/* send our status request */
1145
		fputs($fp, "state 1\n");
1146

    
1147
		/* recv all response lines */
1148
		while (!feof($fp)) {
1149
			/* read the next line */
1150
			$line = fgets($fp, 1024);
1151

    
1152
			$info = stream_get_meta_data($fp);
1153
			if ($info['timed_out'])
1154
				break;
1155

    
1156
			/* Get the client state */
1157
			if (strstr($line,"CONNECTED")) {
1158
				$client['status']="up";
1159
				$list = explode(",", $line);
1160

    
1161
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1162
				$client['virtual_addr']  = $list[3];
1163
				$client['remote_host'] = $list[4];
1164
			}
1165
			if (strstr($line,"CONNECTING")) {
1166
				$client['status']="connecting";
1167
			}
1168
			if (strstr($line,"ASSIGN_IP")) {
1169
				$client['status']="waiting";
1170
				$list = explode(",", $line);
1171

    
1172
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1173
				$client['virtual_addr']  = $list[3];
1174
			}
1175
			if (strstr($line,"RECONNECTING")) {
1176
				$client['status']="reconnecting";
1177
				$list = explode(",", $line);
1178

    
1179
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1180
				$client['status'] .= "; " . $list[2];
1181
			}
1182
			/* parse end of output line */
1183
			if (strstr($line, "END") || strstr($line, "ERROR"))
1184
				break;
1185
		}
1186

    
1187
		/* If up, get read/write stats */
1188
		if (strcmp($client['status'], "up") == 0) {
1189
			fputs($fp, "status 2\n");
1190
			/* recv all response lines */
1191
			while (!feof($fp)) {
1192
				/* read the next line */
1193
				$line = fgets($fp, 1024);
1194

    
1195
				$info = stream_get_meta_data($fp);
1196
				if ($info['timed_out'])
1197
					break;
1198

    
1199
				if (strstr($line,"TCP/UDP read bytes")) {
1200
					$list = explode(",", $line);
1201
					$client['bytes_recv'] = $list[1];
1202
				}
1203

    
1204
				if (strstr($line,"TCP/UDP write bytes")) {
1205
					$list = explode(",", $line);
1206
					$client['bytes_sent'] = $list[1];
1207
				}
1208

    
1209
				/* parse end of output line */
1210
				if (strstr($line, "END"))
1211
					break;
1212
			}
1213
		}
1214

    
1215
		fclose($fp);
1216

    
1217
	} else {
1218
		$DisplayNote=true;
1219
		$client['remote_host'] = "Unable to contact daemon";
1220
		$client['virtual_addr'] = "Service not running?";
1221
		$client['bytes_recv'] = 0;
1222
		$client['bytes_sent'] = 0;
1223
		$client['connect_time'] = 0;
1224
	}
1225
	return $client;
1226
}
1227

    
1228
function openvpn_refresh_crls() {
1229
	global $g, $config;
1230

    
1231
	openvpn_create_dirs();
1232

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

    
1258
function openvpn_create_dirs() {
1259
	global $g;
1260
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1261
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1262
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1263
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1264
}
1265

    
1266
function openvpn_get_interface_ip($ip, $mask) {
1267
	$baselong = ip2long32($ip) & ip2long($mask);
1268
	$ip1 = long2ip32($baselong + 1);
1269
	$ip2 = long2ip32($baselong + 2);
1270
	return array($ip1, $ip2);
1271
}
1272

    
1273
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1274
	$basev6 = gen_subnetv6($ipv6, $prefix);
1275
	// Is there a better way to do this math?
1276
	$ipv6_arr = explode(':', $basev6);
1277
	$last = hexdec(array_pop($ipv6_arr));
1278
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1279
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1280
	return array($ipv6_1, $ipv6_2);
1281
}
1282

    
1283
function openvpn_clear_route($mode, $settings) {
1284
	if (empty($settings['tunnel_network']))
1285
		return;
1286
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1287
	$mask = gen_subnet_mask($cidr);
1288
	$clear_route = false;
1289

    
1290
	switch($settings['mode']) {
1291
		case 'shared_key':
1292
			$clear_route = true;
1293
			break;
1294
		case 'p2p_tls':
1295
		case 'p2p_shared_key':
1296
			if ($cidr == 30)
1297
				$clear_route = true;
1298
			break;
1299
	}
1300

    
1301
	if ($clear_route && !empty($ip) && !empty($mask)) {
1302
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1303
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1304
		/* XXX: Family for route? */
1305
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1306
	}
1307
}
1308

    
1309
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false) {
1310
	$routes = "";
1311
	if (empty($value))
1312
		return "";
1313
	$networks = explode(',', $value);
1314

    
1315
	foreach ($networks as $network) {
1316
		if ($ipproto == "ipv4")
1317
			$route = openvpn_gen_route_ipv4($network);
1318
		else
1319
			$route = openvpn_gen_route_ipv6($network);
1320

    
1321
		if ($push)
1322
			$routes .= "push \"{$route}\"\n";
1323
		else
1324
			$routes .= "{$route}\n";
1325
	}
1326
	return $routes;
1327
}
1328

    
1329
function openvpn_gen_route_ipv4($network) {
1330
	list($ip, $mask) = explode('/', trim($network));
1331
	$mask = gen_subnet_mask($mask);
1332
	return "route $ip $mask";
1333
}
1334

    
1335
function openvpn_gen_route_ipv6($network) {
1336
	list($ipv6, $prefix) = explode('/', trim($network));
1337
	if (empty($prefix))
1338
		$prefix = "128";
1339
	return "route-ipv6 ${ipv6}/${prefix}";
1340
}
1341

    
1342
function openvpn_get_settings($mode, $vpnid) {
1343
	global $config;
1344

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

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

    
1355
	if (is_array($config['openvpn']['openvpn-client'])) {
1356
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1357
			if (isset($settings['disable']))
1358
				continue;
1359

    
1360
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1361
				return $settings;
1362
		}
1363
	}
1364

    
1365
	return array();
1366
}
1367

    
1368
function openvpn_restart_by_vpnid($mode, $vpnid) {
1369
	$settings = openvpn_get_settings($mode, $vpnid);
1370
	openvpn_restart($mode, $settings);
1371
}
1372

    
1373
?>
(37-37/66)