Project

General

Profile

Download (43 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

    
42
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/bin/openssl	/sbin/ifconfig
43
	pfSense_MODULE:	openvpn
44

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

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

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

    
57
global $openvpn_verbosity_level;
58
$openvpn_verbosity_level = array(
59
	0 =>	"none",
60
	1 =>	"default",
61
	2 =>	"2",
62
	3 =>	"3 (recommended)",
63
	4 =>	"4",
64
	5 => 	"5",
65
	6 => 	"6",
66
	7 => 	"7",
67
	8 => 	"8",
68
	9 => 	"9",
69
	10 => 	"10",
70
	11 => 	"11"
71
);
72

    
73
/*
74
 * The User Auth mode below is disabled because
75
 * OpenVPN erroneously requires that we provide
76
 * a CA configuration parameter. In this mode,
77
 * clients don't send a certificate so there is
78
 * no need for a CA. If we require that admins
79
 * provide one in the pfSense UI due to a bogus
80
 * requirement imposed by OpenVPN, it could be
81
 * considered very confusing ( I know I was ).
82
 *
83
 * -mgrooms
84
 */
85

    
86
global $openvpn_dh_lengths;
87
$openvpn_dh_lengths = array(
88
	1024, 2048, 4096 );
89

    
90
global $openvpn_cert_depths;
91
$openvpn_cert_depths = array(
92
	1 => "One (Client+Server)",
93
	2 => "Two (Client+Intermediate+Server)",
94
	3 => "Three (Client+2xIntermediate+Server)",
95
	4 => "Four (Client+3xIntermediate+Server)",
96
	5 => "Five (Client+4xIntermediate+Server)"
97
);
98

    
99
global $openvpn_server_modes;
100
$openvpn_server_modes = array(
101
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
102
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
103
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
104
	'server_user' => gettext("Remote Access ( User Auth )"),
105
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
106

    
107
global $openvpn_client_modes;
108
$openvpn_client_modes = array(
109
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
110
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )") );
111

    
112
global $openvpn_compression_modes;
113
$openvpn_compression_modes = array(
114
	'' =>	gettext("No Preference"),
115
	'no' =>		gettext("Disabled - No Compression"),
116
	'adaptive' =>	gettext("Enabled with Adaptive Compression"),
117
	'yes' =>	gettext("Enabled without Adaptive Compression"));
118

    
119
function openvpn_create_key() {
120

    
121
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
122
	if (!$fp)
123
		return false;
124

    
125
	$rslt = stream_get_contents($fp);
126
	pclose($fp);
127

    
128
	return $rslt;
129
}
130

    
131
function openvpn_create_dhparams($bits) {
132

    
133
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
134
	if (!$fp)
135
		return false;
136

    
137
	$rslt = stream_get_contents($fp);
138
	pclose($fp);
139

    
140
	return $rslt;
141
}
142

    
143
function openvpn_vpnid_used($vpnid) {
144
	global $config;
145

    
146
	if (is_array($config['openvpn']['openvpn-server']))
147
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
148
			if ($vpnid == $settings['vpnid'])
149
				return true;
150

    
151
	if (is_array($config['openvpn']['openvpn-client']))
152
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
153
			if ($vpnid == $settings['vpnid'])
154
				return true;
155

    
156
	return false;
157
}
158

    
159
function openvpn_vpnid_next() {
160

    
161
	$vpnid = 1;
162
	while(openvpn_vpnid_used($vpnid))
163
		$vpnid++;
164

    
165
	return $vpnid;
166
}
167

    
168
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
169
	global $config;
170

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

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

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

    
185
	if (is_array($config['openvpn']['openvpn-client'])) {
186
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
187
			if (isset($settings['disable']))
188
				continue;
189

    
190
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
191
				continue;
192

    
193
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
194
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
195
				return $settings['vpnid'];
196
		}
197
	}
198

    
199
	return 0;
200
}
201

    
202
function openvpn_port_next($prot, $interface = "wan") {
203

    
204
	$port = 1194;
205
	while(openvpn_port_used($prot, $interface, $port))
206
		$port++;
207
	while(openvpn_port_used($prot, "any", $port))
208
		$port++;
209

    
210
	return $port;
211
}
212

    
213
function openvpn_get_cipherlist() {
214

    
215
	$ciphers = array();
216
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
217
	$cipher_lines = explode("\n", trim($cipher_out));
218
	sort($cipher_lines);
219
	foreach ($cipher_lines as $line) {
220
		$words = explode(' ', $line);
221
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
222
	}
223
	$ciphers["none"] = gettext("None (No Encryption)");
224
	return $ciphers;
225
}
226

    
227
function openvpn_get_digestlist() {
228

    
229
	$digests = array();
230
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
231
	$digest_lines = explode("\n", trim($digest_out));
232
	sort($digest_lines);
233
	foreach ($digest_lines as $line) {
234
		$words = explode(' ', $line);
235
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
236
	}
237
	$digests["none"] = gettext("None (No Authentication)");
238
	return $digests;
239
}
240

    
241
function openvpn_get_engines() {
242
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
243
	exec("/usr/bin/openssl engine -t -c", $openssl_engine_output);
244
	$openssl_engine_output = implode("\n", $openssl_engine_output);
245
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
246
	$openssl_engine_output = explode("\n", $openssl_engine_output);
247

    
248
	foreach ($openssl_engine_output as $oeo) {
249
		$keep = true;
250
		$details = explode("|", $oeo);
251
		$engine = array_shift($details);
252
		$linematch = array();
253
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
254
		foreach ($details as $dt) {
255
			if (strpos($dt, "unavailable") !== FALSE)
256
				$keep = false;
257
			if (strpos($dt, "available") !== FALSE)
258
				continue;
259
			if (strpos($dt, "[") !== FALSE)
260
				$ciphers = trim($dt, "[]");
261
		}
262
		if (!empty($ciphers))
263
			$ciphers = " - " . $ciphers;
264
		if (strlen($ciphers) > 60)
265
			$ciphers = substr($ciphers, 0, 60) . " ... ";
266
		if ($keep)
267
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
268
	}
269
	return $openssl_engines;
270
}
271

    
272
function openvpn_validate_engine($engine) {
273
	$engines = openvpn_get_engines();
274
	return array_key_exists($engine, $engines);
275
}
276

    
277
function openvpn_validate_host($value, $name) {
278
	$value = trim($value);
279
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
280
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
281
	return false;
282
}
283

    
284
function openvpn_validate_port($value, $name) {
285
	$value = trim($value);
286
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
287
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
288
	return false;
289
}
290

    
291
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
292
	$value = trim($value);
293
	$error = false;
294
	if (empty($value))
295
		return false;
296
	$networks = explode(',', $value);
297

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

    
301
	foreach ($networks as $network) {
302
		if ($ipproto == "ipv4")
303
			$error = !openvpn_validate_cidr_ipv4($network);
304
		else
305
			$error = !openvpn_validate_cidr_ipv6($network);
306
		if ($error)
307
			break;
308
	}
309

    
310
	if ($error)
311
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
312
	else
313
		return false;
314
}
315

    
316
function openvpn_validate_cidr_ipv4($value) {
317
	$value = trim($value);
318
	if (!empty($value)) {
319
		list($ip, $mask) = explode('/', $value);
320
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
321
			return false;
322
	}
323
	return true;
324
}
325

    
326
function openvpn_validate_cidr_ipv6($value) {
327
	$value = trim($value);
328
	if (!empty($value)) {
329
		list($ipv6, $prefix) = explode('/', $value);
330
		if (empty($prefix))
331
			$prefix = "128";
332
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0))
333
			return false;
334
	}
335
	return true;
336
}
337

    
338
function openvpn_add_dhcpopts(& $settings, & $conf) {
339

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

    
343
	if (!empty($settings['dns_server1']))
344
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
345
	if (!empty($settings['dns_server2']))
346
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
347
	if (!empty($settings['dns_server3']))
348
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
349
	if (!empty($settings['dns_server4']))
350
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
351

    
352
	if (!empty($settings['push_register_dns']))
353
		$conf .= "push \"register-dns\"\n";
354

    
355
	if (!empty($settings['ntp_server1']))
356
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
357
	if (!empty($settings['ntp_server2']))
358
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
359

    
360
	if ($settings['netbios_enable']) {
361

    
362
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
363
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
364
		if (!empty($settings['dhcp_nbtscope']))
365
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
366

    
367
		if (!empty($settings['wins_server1']))
368
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
369
		if (!empty($settings['wins_server2']))
370
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
371

    
372
		if (!empty($settings['nbdd_server1']))
373
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
374
	}
375

    
376
	if ($settings['gwredir'])
377
		$conf .= "push \"redirect-gateway def1\"\n";
378
}
379

    
380
function openvpn_add_custom(& $settings, & $conf) {
381

    
382
	if ($settings['custom_options']) {
383

    
384
		$options = explode(';', $settings['custom_options']);
385

    
386
		if (is_array($options)) {
387
			foreach ($options as $option)
388
				$conf .= "$option\n";
389
		} else
390
			$conf .= "{$settings['custom_options']}\n";
391
	}
392
}
393

    
394
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
395
	global $g;
396

    
397
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
398
	openvpn_create_dirs();
399
	file_put_contents($fpath, base64_decode($data));
400
	//chown($fpath, 'nobody');
401
	//chgrp($fpath, 'nobody');
402
	@chmod($fpath, 0600);
403

    
404
	$conf .= "{$directive} {$fpath} {$opt}\n";
405
}
406

    
407
function openvpn_reconfigure($mode, $settings) {
408
	global $g, $config;
409

    
410
	if (empty($settings))
411
		return;
412
	if (isset($settings['disable']))
413
		return;
414
	openvpn_create_dirs();
415
	/*
416
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
417
	 * we use a vpnid number which is allocated for a particular client
418
	 * or server configuration. ( see openvpn_vpnid_next() )
419
	 */
420

    
421
	$vpnid = $settings['vpnid'];
422
	$mode_id = $mode.$vpnid;
423

    
424
	if (isset($settings['dev_mode']))
425
		$tunname = "{$settings['dev_mode']}{$vpnid}";
426
	else {	/* defaults to tun */
427
		$tunname = "tun{$vpnid}";
428
		$settings['dev_mode'] = "tun";
429
	}
430

    
431
	if ($mode == "server")
432
		$devname = "ovpns{$vpnid}";
433
	else
434
		$devname = "ovpnc{$vpnid}";
435

    
436
	/* is our device already configured */
437
	if (!does_interface_exist($devname)) {
438

    
439
		/* create the tap device if required */
440
		if (!file_exists("/dev/{$tunname}"))
441
			exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
442

    
443
		/* rename the device */
444
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
445

    
446
		/* add the device to the openvpn group */
447
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn");
448

    
449
		$ifname = convert_real_interface_to_friendly_interface_name($devname);
450
		$grouptmp = link_interface_to_group($ifname);
451
		if (!empty($grouptmp))
452
			array_walk($grouptmp, 'interface_group_add_member');
453
		unset($grouptmp, $ifname);
454
	}
455

    
456
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
457
	$proto = strtolower($settings['protocol']);
458
	if (substr($settings['protocol'], 0, 3) == "TCP")
459
			$proto = "{$proto}-{$mode}";
460
	$dev_mode = $settings['dev_mode'];
461
	$cipher = $settings['crypto'];
462
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
463
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
464

    
465
	$interface = get_failover_interface($settings['interface']);
466
	$ipaddr = $settings['ipaddr'];
467
	$ipaddrv6 = $settings['ipaddrv6'];
468

    
469
	// If a specific ip address (VIP) is requested, use it.
470
	// Otherwise, if a specific interface is requested, use it
471
	// If "any" interface was selected, local directive will be ommited.
472
	if (is_ipaddrv4($ipaddr)) {
473
		$iface_ip=$ipaddr;
474
	} else {
475
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
476
			$iface_ip=get_interface_ip($interface);
477
		}
478
	}
479
	if (is_ipaddrv6($ipaddrv6)) {
480
		$iface_ipv6=$ipaddrv6;
481
	} else {
482
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
483
			$iface_ipv6=get_interface_ipv6($interface);
484
		}
485
	}
486

    
487

    
488
	$conf = "dev {$devname}\n";
489
	if (isset($settings['verbosity_level'])) {
490
		$conf .= "verb {$settings['verbosity_level']}\n";
491
	}
492

    
493
	$conf .= "dev-type {$settings['dev_mode']}\n";
494
	switch($settings['dev_mode']) {
495
		case "tun":
496
			if (!$settings['no_tun_ipv6']) {
497
				$conf .= "tun-ipv6\n";
498
			}
499
			break;
500
	}
501
	$conf .= "dev-node /dev/{$tunname}\n";
502
	$conf .= "writepid {$pfile}\n";
503
	$conf .= "#user nobody\n";
504
	$conf .= "#group nobody\n";
505
	$conf .= "script-security 3\n";
506
	$conf .= "daemon\n";
507
	$conf .= "keepalive 10 60\n";
508
	$conf .= "ping-timer-rem\n";
509
	$conf .= "persist-tun\n";
510
	$conf .= "persist-key\n";
511
	$conf .= "proto {$proto}\n";
512
	$conf .= "cipher {$cipher}\n";
513
	$conf .= "auth {$digest}\n";
514
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
515
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
516
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
517
		switch($settings['mode']) {
518
			case 'server_user':
519
			case 'server_tls_user':
520
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
521
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
522
				break;
523
		}
524
	}
525

    
526
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
527
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
528
		$conf .= "local {$iface_ip}\n";
529
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
530
		$conf .= "local {$iface_ipv6}\n";
531
	}
532

    
533
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
534
		$conf .= "engine {$settings['engine']}\n";
535

    
536
	// server specific settings
537
	if ($mode == 'server') {
538

    
539
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
540
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
541
		$mask = gen_subnet_mask($cidr);
542

    
543
		// configure tls modes
544
		switch($settings['mode']) {
545
			case 'p2p_tls':
546
			case 'server_tls':
547
			case 'server_user':
548
			case 'server_tls_user':
549
				$conf .= "tls-server\n";
550
				break;
551
		}
552

    
553
		// configure p2p/server modes
554
		switch($settings['mode']) {
555
			case 'p2p_tls':
556
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
557
				//  use the server directive. It works for a single client without it.
558
				//  See ticket #1417
559
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
560
					$conf .= "server {$ip} {$mask}\n";
561
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
562
					if(is_ipaddr($ipv6))
563
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
564
				}
565
			case 'p2p_shared_key':
566
				if (!empty($ip) && !empty($mask)) {
567
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
568
					if ($settings['dev_mode'] == 'tun')
569
						$conf .= "ifconfig {$ip1} {$ip2}\n";
570
					else
571
						$conf .= "ifconfig {$ip1} {$mask}\n";
572
				}
573
				if (!empty($ipv6) && !empty($prefix)) {
574
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
575
					if ($settings['dev_mode'] == 'tun')
576
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
577
					else
578
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
579
				}
580
				break;
581
			case 'server_tls':
582
			case 'server_user':
583
			case 'server_tls_user':
584
				if (!empty($ip) && !empty($mask)) {
585
					$conf .= "server {$ip} {$mask}\n";
586
					if(is_ipaddr($ipv6))
587
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
588
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
589
				} else {
590
					if ($settings['serverbridge_dhcp']) {
591
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
592
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
593
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
594
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
595
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
596
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
597
							} else {
598
								$conf .= "mode server\n";
599
							}
600
						} else {
601
							$conf .= "mode server\n";
602
						}
603
					}
604
				}
605
				break;
606
		}
607

    
608
		// configure user auth modes
609
		switch($settings['mode']) {
610
			case 'server_user':
611
				$conf .= "client-cert-not-required\n";
612
			case 'server_tls_user':
613
				/* username-as-common-name is not compatible with server-bridge */
614
				if (stristr($conf, "server-bridge") === false)
615
					$conf .= "username-as-common-name\n";
616
				if (!empty($settings['authmode'])) {
617
					$strictusercn = "false";
618
					if ($settings['strictusercn'])
619
						$strictusercn = "true";
620
					$conf .= "auth-user-pass-verify \"/usr/local/sbin/ovpn_auth_verify user '{$settings['authmode']}' {$strictusercn} {$mode_id}\" via-env\n";
621
				}
622
				break;
623
		}
624
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls')))
625
			$settings['cert_depth'] = 1;
626
		if (is_numeric($settings['cert_depth'])) {
627
			if (($mode == 'client') && empty($settings['certref']))
628
				$cert = "";
629
			else {
630
				$cert = lookup_cert($settings['certref']);
631
				/* XXX: Seems not used at all! */
632
				$servercn = urlencode(cert_get_cn($cert['crt']));
633
				$conf .= "tls-verify \"/usr/local/sbin/ovpn_auth_verify tls '{$servercn}' {$settings['cert_depth']}\"\n";
634
			}
635
		}
636

    
637
		// The local port to listen on
638
		$conf .= "lport {$settings['local_port']}\n";
639

    
640
		// The management port to listen on
641
		// Use unix socket to overcome the problem on any type of server
642
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
643
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
644

    
645
		if ($settings['maxclients'])
646
			$conf .= "max-clients {$settings['maxclients']}\n";
647

    
648
		// Can we push routes
649
		if ($settings['local_network']) {
650
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
651
		}
652
		if ($settings['local_networkv6']) {
653
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
654
		}
655

    
656
		switch($settings['mode']) {
657
			case 'server_tls':
658
			case 'server_user':
659
			case 'server_tls_user':
660
				// Configure client dhcp options
661
				openvpn_add_dhcpopts($settings, $conf);
662
				if ($settings['client2client'])
663
					$conf .= "client-to-client\n";
664
				break;
665
		}
666
		if (isset($settings['duplicate_cn']))
667
			$conf .= "duplicate-cn\n";
668
	}
669

    
670
	// client specific settings
671

    
672
	if ($mode == 'client') {
673

    
674
		// configure p2p mode
675
		switch($settings['mode']) {
676
			case 'p2p_tls':
677
				$conf .= "tls-client\n";
678
			case 'shared_key':
679
				$conf .= "client\n";
680
				break;
681
		}
682

    
683
		// If there is no bind option at all (ip and/or port), add "nobind" directive
684
		//  Otherwise, use the local port if defined, failing that, use lport 0 to
685
		//  ensure a random source port.
686
		if ((empty($iface_ip)) && (!$settings['local_port']))
687
			$conf .= "nobind\n";
688
		elseif ($settings['local_port'])
689
			$conf .= "lport {$settings['local_port']}\n";
690
		else
691
			$conf .= "lport 0\n";
692

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

    
696
		// The remote server
697
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
698

    
699
		if (!empty($settings['use_shaper']))
700
			$conf .= "shaper {$settings['use_shaper']}\n";
701

    
702
		if (!empty($settings['tunnel_network'])) {
703
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
704
			$mask = gen_subnet_mask($mask);
705
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
706
			if ($settings['dev_mode'] == 'tun')
707
				$conf .= "ifconfig {$ip2} {$ip1}\n";
708
			else
709
				$conf .= "ifconfig {$ip2} {$mask}\n";
710
		}
711

    
712
		if (!empty($settings['tunnel_networkv6'])) {
713
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
714
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
715
			if ($settings['dev_mode'] == 'tun')
716
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
717
			else
718
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
719
		}
720

    
721
		if ($settings['auth_user'] && $settings['auth_pass']) {
722
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
723
			$conf .= "auth-user-pass {$up_file}\n";
724
			$userpass = "{$settings['auth_user']}\n";
725
			$userpass .= "{$settings['auth_pass']}\n";
726
			file_put_contents($up_file, $userpass);
727
		}
728

    
729
		if ($settings['proxy_addr']) {
730
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
731
			if ($settings['proxy_authtype'] != "none") {
732
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
733
				$proxypas = "{$settings['proxy_user']}\n";
734
				$proxypas .= "{$settings['proxy_passwd']}\n";
735
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
736
			}
737
			$conf .= " \n";
738
		}
739
	}
740

    
741
	// Add a remote network route if set, and only for p2p modes.
742
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
743
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
744
	}
745
	// Add a remote network route if set, and only for p2p modes.
746
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
747
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
748
	}
749

    
750
	// Write the settings for the keys
751
	switch($settings['mode']) {
752
		case 'p2p_shared_key':
753
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
754
			break;
755
		case 'p2p_tls':
756
		case 'server_tls':
757
		case 'server_tls_user':
758
		case 'server_user':
759
			$ca = lookup_ca($settings['caref']);
760
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
761

    
762
			if (!empty($settings['certref'])) {
763
				$cert = lookup_cert($settings['certref']);
764
				openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
765
				openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
766
			}
767
			if ($mode == 'server')
768
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
769
			if (!empty($settings['crlref'])) {
770
				$crl = lookup_crl($settings['crlref']);
771
				crl_update($crl);
772
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
773
			}
774
			if ($settings['tls']) {
775
				if ($mode == "server")
776
					$tlsopt = 0;
777
				else
778
					$tlsopt = 1;
779
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
780
			}
781
			break;
782
	}
783

    
784
	if (!empty($settings['compression']))
785
		$conf .= "comp-lzo {$settings['compression']}\n";
786

    
787
	if ($settings['passtos'])
788
		$conf .= "passtos\n";
789

    
790
	if ($settings['resolve_retry'])
791
		$conf .= "resolv-retry infinite\n";
792
	else if ($mode == 'client')
793
		$conf .= "resolv-retry infinite\n";
794

    
795
	if ($settings['dynamic_ip']) {
796
		$conf .= "persist-remote-ip\n";
797
		$conf .= "float\n";
798
	}
799

    
800
	if ($settings['topology_subnet']) {
801
		$conf .= "topology subnet\n";
802
	}
803

    
804
	// New client features
805
	if ($mode == "client") {
806
		// Dont pull routes checkbox
807
		if ($settings['route_no_pull']) {
808
			$conf .= "route-nopull\n";
809
		}
810

    
811
		// Dont add/remove routes checkbox
812
		if ($settings['route_no_exec']) {
813
			$conf .= "route-noexec\n";
814
		}
815
	}
816

    
817
	openvpn_add_custom($settings, $conf);
818

    
819
	openvpn_create_dirs();
820
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
821
	file_put_contents($fpath, $conf);
822
	unset($conf);
823
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
824
	file_put_contents($fpath, $interface);
825
	//chown($fpath, 'nobody');
826
	//chgrp($fpath, 'nobody');
827
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
828
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
829
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
830
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
831
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
832
}
833

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

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

    
840
	/* kill the process if running */
841
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
842
	if (file_exists($pfile)) {
843

    
844
		/* read the pid file */
845
		$pid = rtrim(file_get_contents($pfile));
846
		unlink($pfile);
847

    
848
		/* send a term signal to the process */
849
		posix_kill($pid, SIGTERM);
850

    
851
		/* wait until the process exits, or timeout and kill it */
852
		$i = 0;
853
		while(posix_kill($pid, 0)) {
854
			usleep(250000);
855
			if ($i > 10) {
856
				log_error("OpenVPN ID $mode_id PID $pid still running, killing.");
857
				posix_kill($pid, SIGKILL);
858
				usleep(500000);
859
			}
860
			$i++;
861
		}
862
	}
863

    
864
	if (isset($settings['disable']))
865
		return;
866

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

    
871
	/* Check if client is bound to a gateway group */
872
	$a_groups = return_gateway_groups_array();
873
	if (is_array($a_groups[$settings['interface']])) {
874
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
875
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
876
			return;
877
	}
878

    
879
	/* start the new process */
880
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
881
	openvpn_clear_route($mode, $settings);
882
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
883

    
884
	if (!platform_booting())
885
		send_event("filter reload");
886
}
887

    
888
function openvpn_delete($mode, & $settings) {
889
	global $g, $config;
890

    
891
	$vpnid = $settings['vpnid'];
892
	$mode_id = $mode.$vpnid;
893

    
894
	if (isset($settings['dev_mode']))
895
		$tunname = "{$settings['dev_mode']}{$vpnid}";
896
	else {  /* defaults to tun */
897
		$tunname = "tun{$vpnid}";
898
	}
899

    
900
	if ($mode == "server")
901
		$devname = "ovpns{$vpnid}";
902
	else
903
		$devname = "ovpnc{$vpnid}";
904

    
905
	/* kill the process if running */
906
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
907
	if (file_exists($pfile)) {
908

    
909
		/* read the pid file */
910
		$pid = trim(file_get_contents($pfile));
911
		unlink($pfile);
912

    
913
		/* send a term signal to the process */
914
		posix_kill($pid, SIGTERM);
915
	}
916

    
917
	/* remove the device from the openvpn group */
918
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
919

    
920
	/* restore the original adapter name */
921
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
922

    
923
	/* remove the configuration files */
924
	@array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
925
}
926

    
927
function openvpn_cleanup_csc($common_name) {
928
	global $g, $config;
929
	if (empty($common_name))
930
		return;
931
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
932
	if (is_file($fpath))
933
		unlink_if_exists($fpath);
934
	return;
935
}
936

    
937
function openvpn_resync_csc(& $settings) {
938
	global $g, $config;
939

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

    
942
	if (isset($settings['disable'])) {
943
		unlink_if_exists($fpath);
944
		return;
945
	}
946
	openvpn_create_dirs();
947

    
948
	$conf = '';
949
	if ($settings['block'])
950
		$conf .= "disable\n";
951

    
952
	if ($settings['push_reset'])
953
		$conf .= "push-reset\n";
954

    
955
	if (!empty($settings['tunnel_network'])) {
956
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
957
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
958
		$serverip = long2ip32($baselong + 1);
959
		$clientip = long2ip32($baselong + 2);
960
		/* Because this is being pushed, the order from the client's point of view. */
961
		if ($settings['dev_mode'] != 'tap')
962
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
963
		else
964
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
965
	}
966

    
967
	if ($settings['local_network']) {
968
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
969
	}
970
	if ($settings['local_networkv6']) {
971
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
972
	}
973

    
974
	// Add a remote network iroute if set
975
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
976
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
977
	}
978
	// Add a remote network iroute if set
979
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
980
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
981
	}
982

    
983
	openvpn_add_dhcpopts($settings, $conf);
984

    
985
	if ($settings['gwredir'])
986
		$conf .= "push \"redirect-gateway def1\"\n";
987

    
988
	openvpn_add_custom($settings, $conf);
989

    
990
	file_put_contents($fpath, $conf);
991
	chown($fpath, 'nobody');
992
	chgrp($fpath, 'nobody');
993
}
994

    
995
function openvpn_delete_csc(& $settings) {
996
	global $g, $config;
997

    
998
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
999
	unlink_if_exists($fpath);
1000
}
1001

    
1002
// Resync the configuration and restart the VPN
1003
function openvpn_resync($mode, $settings) {
1004
	openvpn_reconfigure($mode, $settings);
1005
	openvpn_restart($mode, $settings);
1006
}
1007

    
1008
// Resync and restart all VPNs
1009
function openvpn_resync_all($interface = "") {
1010
	global $g, $config;
1011

    
1012
	if ($g['platform'] == 'jail')
1013
		return;
1014
	openvpn_create_dirs();
1015

    
1016
	if (!is_array($config['openvpn']))
1017
		$config['openvpn'] = array();
1018

    
1019
/*
1020
	if (!$config['openvpn']['dh-parameters']) {
1021
		echo "Configuring OpenVPN Parameters ...\n";
1022
		$dh_parameters = openvpn_create_dhparams(1024);
1023
		$dh_parameters = base64_encode($dh_parameters);
1024
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1025
		write_config("OpenVPN DH parameters");
1026
	}
1027

    
1028
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1029
	if (!file_exists($path_ovdh)) {
1030
		$dh_parameters = $config['openvpn']['dh-parameters'];
1031
		$dh_parameters = base64_decode($dh_parameters);
1032
		file_put_contents($path_ovdh, $dh_parameters);
1033
	}
1034
*/
1035
	if ($interface <> "")
1036
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
1037
	else
1038
		log_error("Resyncing OpenVPN instances.");
1039

    
1040
	if (is_array($config['openvpn']['openvpn-server'])) {
1041
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1042
			if ($interface <> "" && $interface != $settings['interface'])
1043
				continue;
1044
			openvpn_resync('server', $settings);
1045
		}
1046
	}
1047

    
1048
	if (is_array($config['openvpn']['openvpn-client'])) {
1049
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1050
			if ($interface <> "" && $interface != $settings['interface'])
1051
				continue;
1052
			openvpn_resync('client', $settings);
1053
		}
1054
	}
1055

    
1056
	if (is_array($config['openvpn']['openvpn-csc']))
1057
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
1058
			openvpn_resync_csc($settings);
1059

    
1060
}
1061

    
1062
// Resync and restart all VPNs using a gateway group.
1063
function openvpn_resync_gwgroup($gwgroupname = "") {
1064
	global $g, $config;
1065

    
1066
	if ($gwgroupname <> "") {
1067
		if (is_array($config['openvpn']['openvpn-server'])) {
1068
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1069
				if ($gwgroupname == $settings['interface']) {
1070
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1071
					openvpn_resync('server', $settings);
1072
				}
1073
			}
1074
		}
1075

    
1076
		if (is_array($config['openvpn']['openvpn-client'])) {
1077
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1078
				if ($gwgroupname == $settings['interface']) {
1079
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1080
					openvpn_resync('client', $settings);
1081
				}
1082
			}
1083
		}
1084

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

    
1087
	} else
1088
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter.");
1089
}
1090

    
1091
function openvpn_get_active_servers($type="multipoint") {
1092
	global $config, $g;
1093

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

    
1100
			$prot = $settings['protocol'];
1101
			$port = $settings['local_port'];
1102

    
1103
			$server = array();
1104
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1105
			$server['mode'] = $settings['mode'];
1106
			if ($settings['description'])
1107
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1108
			else
1109
				$server['name'] = "Server {$prot}:{$port}";
1110
			$server['conns'] = array();
1111
			$server['vpnid'] = $settings['vpnid'];
1112
			$server['mgmt'] = "server{$server['vpnid']}";
1113
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1114
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1115

    
1116
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1117
				$servers[] = openvpn_get_client_status($server, $socket);
1118
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1119
				$servers[] = openvpn_get_server_status($server, $socket);
1120

    
1121
		}
1122
	}
1123
	return $servers;
1124
}
1125

    
1126
function openvpn_get_server_status($server, $socket) {
1127
	$errval;
1128
	$errstr;
1129
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1130
	if ($fp) {
1131
		stream_set_timeout($fp, 1);
1132

    
1133
		/* send our status request */
1134
		fputs($fp, "status 2\n");
1135

    
1136
		/* recv all response lines */
1137
		while (!feof($fp)) {
1138

    
1139
			/* read the next line */
1140
			$line = fgets($fp, 1024);
1141

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

    
1146
			/* parse header list line */
1147
			if (strstr($line, "HEADER"))
1148
				continue;
1149

    
1150
			/* parse end of output line */
1151
			if (strstr($line, "END") || strstr($line, "ERROR"))
1152
				break;
1153

    
1154
			/* parse client list line */
1155
			if (strstr($line, "CLIENT_LIST")) {
1156
				$list = explode(",", $line);
1157
				$conn = array();
1158
				$conn['common_name'] = $list[1];
1159
				$conn['remote_host'] = $list[2];
1160
				$conn['virtual_addr'] = $list[3];
1161
				$conn['bytes_recv'] = $list[4];
1162
				$conn['bytes_sent'] = $list[5];
1163
				$conn['connect_time'] = $list[6];
1164
				$server['conns'][] = $conn;
1165
			}
1166
			/* parse routing table lines */
1167
			if (strstr($line, "ROUTING_TABLE")) {
1168
				$list = explode(",", $line);
1169
				$conn = array();
1170
				$conn['virtual_addr'] = $list[1];
1171
				$conn['common_name'] = $list[2];
1172
				$conn['remote_host'] = $list[3];
1173
				$conn['last_time'] = $list[4];
1174
				$server['routes'][] = $conn;
1175
			}
1176
		}
1177

    
1178
		/* cleanup */
1179
		fclose($fp);
1180
	} else {
1181
		$conn = array();
1182
		$conn['common_name'] = "[error]";
1183
		$conn['remote_host'] = "Unable to contact daemon";
1184
		$conn['virtual_addr'] = "Service not running?";
1185
		$conn['bytes_recv'] = 0;
1186
		$conn['bytes_sent'] = 0;
1187
		$conn['connect_time'] = 0;
1188
		$server['conns'][] = $conn;
1189
	}
1190
	return $server;
1191
}
1192

    
1193
function openvpn_get_active_clients() {
1194
	global $config, $g;
1195

    
1196
	$clients = array();
1197
	if (is_array($config['openvpn']['openvpn-client'])) {
1198
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1199

    
1200
			if (empty($settings) || isset($settings['disable']))
1201
				continue;
1202

    
1203
			$prot = $settings['protocol'];
1204
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1205

    
1206
			$client = array();
1207
			$client['port'] = $settings['local_port'];
1208
			if ($settings['description'])
1209
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1210
			else
1211
				$client['name'] = "Client {$prot}{$port}";
1212

    
1213
			$client['vpnid'] = $settings['vpnid'];
1214
			$client['mgmt'] = "client{$client['vpnid']}";
1215
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1216
			$client['status']="down";
1217

    
1218
			$clients[] = openvpn_get_client_status($client, $socket);
1219
		}
1220
	}
1221
	return $clients;
1222
}
1223

    
1224
function openvpn_get_client_status($client, $socket) {
1225
	$errval;
1226
	$errstr;
1227
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1228
	if ($fp) {
1229
		stream_set_timeout($fp, 1);
1230
		/* send our status request */
1231
		fputs($fp, "state 1\n");
1232

    
1233
		/* recv all response lines */
1234
		while (!feof($fp)) {
1235
			/* read the next line */
1236
			$line = fgets($fp, 1024);
1237

    
1238
			$info = stream_get_meta_data($fp);
1239
			if ($info['timed_out'])
1240
				break;
1241

    
1242
			/* Get the client state */
1243
			if (strstr($line,"CONNECTED")) {
1244
				$client['status']="up";
1245
				$list = explode(",", $line);
1246

    
1247
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1248
				$client['virtual_addr']  = $list[3];
1249
				$client['remote_host'] = $list[4];
1250
			}
1251
			if (strstr($line,"CONNECTING")) {
1252
				$client['status']="connecting";
1253
			}
1254
			if (strstr($line,"ASSIGN_IP")) {
1255
				$client['status']="waiting";
1256
				$list = explode(",", $line);
1257

    
1258
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1259
				$client['virtual_addr']  = $list[3];
1260
			}
1261
			if (strstr($line,"RECONNECTING")) {
1262
				$client['status']="reconnecting";
1263
				$list = explode(",", $line);
1264

    
1265
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1266
				$client['status'] .= "; " . $list[2];
1267
			}
1268
			/* parse end of output line */
1269
			if (strstr($line, "END") || strstr($line, "ERROR"))
1270
				break;
1271
		}
1272

    
1273
		/* If up, get read/write stats */
1274
		if (strcmp($client['status'], "up") == 0) {
1275
			fputs($fp, "status 2\n");
1276
			/* recv all response lines */
1277
			while (!feof($fp)) {
1278
				/* read the next line */
1279
				$line = fgets($fp, 1024);
1280

    
1281
				$info = stream_get_meta_data($fp);
1282
				if ($info['timed_out'])
1283
					break;
1284

    
1285
				if (strstr($line,"TCP/UDP read bytes")) {
1286
					$list = explode(",", $line);
1287
					$client['bytes_recv'] = $list[1];
1288
				}
1289

    
1290
				if (strstr($line,"TCP/UDP write bytes")) {
1291
					$list = explode(",", $line);
1292
					$client['bytes_sent'] = $list[1];
1293
				}
1294

    
1295
				/* parse end of output line */
1296
				if (strstr($line, "END"))
1297
					break;
1298
			}
1299
		}
1300

    
1301
		fclose($fp);
1302

    
1303
	} else {
1304
		$DisplayNote=true;
1305
		$client['remote_host'] = "Unable to contact daemon";
1306
		$client['virtual_addr'] = "Service not running?";
1307
		$client['bytes_recv'] = 0;
1308
		$client['bytes_sent'] = 0;
1309
		$client['connect_time'] = 0;
1310
	}
1311
	return $client;
1312
}
1313

    
1314
function openvpn_refresh_crls() {
1315
	global $g, $config;
1316

    
1317
	openvpn_create_dirs();
1318

    
1319
	if (is_array($config['openvpn']['openvpn-server'])) {
1320
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1321
			if (empty($settings))
1322
				continue;
1323
			if (isset($settings['disable']))
1324
				continue;
1325
			// Write the settings for the keys
1326
			switch($settings['mode']) {
1327
				case 'p2p_tls':
1328
				case 'server_tls':
1329
				case 'server_tls_user':
1330
				case 'server_user':
1331
					if (!empty($settings['crlref'])) {
1332
						$crl = lookup_crl($settings['crlref']);
1333
						crl_update($crl);
1334
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1335
						file_put_contents($fpath, base64_decode($crl['text']));
1336
						@chmod($fpath, 0644);
1337
					}
1338
					break;
1339
			}
1340
		}
1341
	}
1342
}
1343

    
1344
function openvpn_create_dirs() {
1345
	global $g;
1346
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1347
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1348
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1349
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1350
}
1351

    
1352
function openvpn_get_interface_ip($ip, $mask) {
1353
	$baselong = ip2long32($ip) & ip2long($mask);
1354
	$ip1 = long2ip32($baselong + 1);
1355
	$ip2 = long2ip32($baselong + 2);
1356
	return array($ip1, $ip2);
1357
}
1358

    
1359
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1360
	$basev6 = gen_subnetv6($ipv6, $prefix);
1361
	// Is there a better way to do this math?
1362
	$ipv6_arr = explode(':', $basev6);
1363
	$last = hexdec(array_pop($ipv6_arr));
1364
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1365
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1366
	return array($ipv6_1, $ipv6_2);
1367
}
1368

    
1369
function openvpn_clear_route($mode, $settings) {
1370
	if (empty($settings['tunnel_network']))
1371
		return;
1372
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1373
	$mask = gen_subnet_mask($cidr);
1374
	$clear_route = false;
1375

    
1376
	switch($settings['mode']) {
1377
		case 'shared_key':
1378
			$clear_route = true;
1379
			break;
1380
		case 'p2p_tls':
1381
		case 'p2p_shared_key':
1382
			if ($cidr == 30)
1383
				$clear_route = true;
1384
			break;
1385
	}
1386

    
1387
	if ($clear_route && !empty($ip) && !empty($mask)) {
1388
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1389
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1390
		/* XXX: Family for route? */
1391
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1392
	}
1393
}
1394

    
1395
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1396
	$routes = "";
1397
	if (empty($value))
1398
		return "";
1399
	$networks = explode(',', $value);
1400

    
1401
	foreach ($networks as $network) {
1402
		if ($ipproto == "ipv4")
1403
			$route = openvpn_gen_route_ipv4($network, $iroute);
1404
		else
1405
			$route = openvpn_gen_route_ipv6($network, $iroute);
1406

    
1407
		if ($push)
1408
			$routes .= "push \"{$route}\"\n";
1409
		else
1410
			$routes .= "{$route}\n";
1411
	}
1412
	return $routes;
1413
}
1414

    
1415
function openvpn_gen_route_ipv4($network, $iroute = false) {
1416
	$i = ($iroute) ? "i" : "";
1417
	list($ip, $mask) = explode('/', trim($network));
1418
	$mask = gen_subnet_mask($mask);
1419
	return "{$i}route $ip $mask";
1420
}
1421

    
1422
function openvpn_gen_route_ipv6($network, $iroute = false) {
1423
	$i = ($iroute) ? "i" : "";
1424
	list($ipv6, $prefix) = explode('/', trim($network));
1425
	if (empty($prefix))
1426
		$prefix = "128";
1427
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1428
}
1429

    
1430
function openvpn_get_settings($mode, $vpnid) {
1431
	global $config;
1432

    
1433
	if (is_array($config['openvpn']['openvpn-server'])) {
1434
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1435
			if (isset($settings['disable']))
1436
				continue;
1437

    
1438
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1439
				return $settings;
1440
		}
1441
	}
1442

    
1443
	if (is_array($config['openvpn']['openvpn-client'])) {
1444
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1445
			if (isset($settings['disable']))
1446
				continue;
1447

    
1448
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1449
				return $settings;
1450
		}
1451
	}
1452

    
1453
	return array();
1454
}
1455

    
1456
function openvpn_restart_by_vpnid($mode, $vpnid) {
1457
	$settings = openvpn_get_settings($mode, $vpnid);
1458
	openvpn_restart($mode, $settings);
1459
}
1460

    
1461
?>
(38-38/68)