Projet

Général

Profil

Télécharger (42,4 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / openvpn.inc @ b1e8e675

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

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

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

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

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

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

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

    
120
function openvpn_create_key() {
121

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

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

    
129
	return $rslt;
130
}
131

    
132
function openvpn_create_dhparams($bits) {
133

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

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

    
141
	return $rslt;
142
}
143

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

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

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

    
157
	return false;
158
}
159

    
160
function openvpn_vpnid_next() {
161

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

    
166
	return $vpnid;
167
}
168

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

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

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

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

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

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

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

    
200
	return 0;
201
}
202

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

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

    
211
	return $port;
212
}
213

    
214
function openvpn_get_cipherlist() {
215

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

    
228
function openvpn_get_digestlist() {
229

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
358
	if ($settings['netbios_enable']) {
359

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

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

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

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

    
378
function openvpn_add_custom(& $settings, & $conf) {
379

    
380
	if ($settings['custom_options']) {
381

    
382
		$options = explode(';', $settings['custom_options']);
383

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

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

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

    
402
	$conf .= "{$directive} {$fpath} {$opt}\n";
403
}
404

    
405
function openvpn_reconfigure($mode, $settings) {
406
	global $g, $config;
407

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

    
419
	$vpnid = $settings['vpnid'];
420
	$mode_id = $mode.$vpnid;
421

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

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

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

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

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

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

    
448
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
449
	$proto = strtolower($settings['protocol']);
450
	if (substr($settings['protocol'], 0, 3) == "TCP")
451
			$proto = "{$proto}-{$mode}";
452
	$dev_mode = $settings['dev_mode'];
453
	$cipher = $settings['crypto'];
454
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
455
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
456

    
457
	$interface = get_failover_interface($settings['interface']);
458
	$ipaddr = $settings['ipaddr'];
459
	$ipaddrv6 = $settings['ipaddrv6'];
460

    
461
	// If a specific ip address (VIP) is requested, use it.
462
	// Otherwise, if a specific interface is requested, use it
463
	// If "any" interface was selected, local directive will be ommited.
464
	if (is_ipaddrv4($ipaddr)) {
465
		$iface_ip=$ipaddr;
466
	} else {
467
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
468
			$iface_ip=get_interface_ip($interface);
469
		}
470
	}
471
	if (is_ipaddrv6($ipaddrv6)) {
472
		$iface_ipv6=$ipaddrv6;
473
	} else {
474
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
475
			$iface_ipv6=get_interface_ipv6($interface);
476
		}
477
	}
478

    
479

    
480
	$conf = "dev {$devname}\n";
481
	if (isset($settings['verbosity_level'])) {
482
		$conf .= "verb {$settings['verbosity_level']}\n";
483
	}
484
		
485
	$conf .= "dev-type {$settings['dev_mode']}\n";
486
	switch($settings['dev_mode']) {
487
		case "tun":
488
			if (!$settings['no_tun_ipv6']) {
489
				$conf .= "tun-ipv6\n";
490
			}
491
			break;
492
	}
493
	$conf .= "dev-node /dev/{$tunname}\n";
494
	$conf .= "writepid {$pfile}\n";
495
	$conf .= "#user nobody\n";
496
	$conf .= "#group nobody\n";
497
	$conf .= "script-security 3\n";
498
	$conf .= "daemon\n";
499
	$conf .= "keepalive 10 60\n";
500
	$conf .= "ping-timer-rem\n";
501
	$conf .= "persist-tun\n";
502
	$conf .= "persist-key\n";
503
	$conf .= "proto {$proto}\n";
504
	$conf .= "cipher {$cipher}\n";
505
	$conf .= "auth {$digest}\n";
506
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
507
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
508
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
509
		switch($settings['mode']) {
510
			case 'server_user':
511
			case 'server_tls_user':
512
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
513
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
514
				break;
515
		}
516
	}
517

    
518
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
519
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
520
		$conf .= "local {$iface_ip}\n";
521
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
522
		$conf .= "local {$iface_ipv6}\n";
523
	}
524

    
525
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
526
		$conf .= "engine {$settings['engine']}\n";
527

    
528
	// server specific settings
529
	if ($mode == 'server') {
530

    
531
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
532
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
533
		$mask = gen_subnet_mask($cidr);
534

    
535
		// configure tls modes
536
		switch($settings['mode']) {
537
			case 'p2p_tls':
538
			case 'server_tls':
539
			case 'server_user':
540
			case 'server_tls_user':
541
				$conf .= "tls-server\n";
542
				break;
543
		}
544

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

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

    
629
		// The local port to listen on
630
		$conf .= "lport {$settings['local_port']}\n";
631

    
632
		// The management port to listen on
633
		// Use unix socket to overcome the problem on any type of server
634
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
635
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
636

    
637
		if ($settings['maxclients'])
638
			$conf .= "max-clients {$settings['maxclients']}\n";
639

    
640
		// Can we push routes
641
		if ($settings['local_network']) {
642
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
643
		}
644
		if ($settings['local_networkv6']) {
645
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
646
		}
647

    
648
		switch($settings['mode']) {
649
			case 'server_tls':
650
			case 'server_user':
651
			case 'server_tls_user':
652
				// Configure client dhcp options
653
				openvpn_add_dhcpopts($settings, $conf);
654
				if ($settings['client2client'])
655
					$conf .= "client-to-client\n";
656
				break;
657
		}
658
		if (isset($settings['duplicate_cn']))
659
			$conf .= "duplicate-cn\n";
660
	}
661

    
662
	// client specific settings
663

    
664
	if ($mode == 'client') {
665

    
666
		// configure p2p mode
667
		switch($settings['mode']) {
668
			case 'p2p_tls':
669
				$conf .= "tls-client\n";
670
			case 'shared_key':
671
				$conf .= "client\n";
672
				break;
673
		}
674

    
675
		// If there is no bind option at all (ip and/or port), add "nobind" directive
676
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
677
		//  ensure a random source port.
678
		if ((empty($iface_ip)) && (!$settings['local_port']))
679
			$conf .= "nobind\n";
680
		elseif ($settings['local_port'])
681
			$conf .= "lport {$settings['local_port']}\n";
682
		else
683
			$conf .= "lport 0\n";
684

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

    
688
		// The remote server
689
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
690

    
691
		if (!empty($settings['use_shaper']))
692
			$conf .= "shaper {$settings['use_shaper']}\n";
693

    
694
		if (!empty($settings['tunnel_network'])) {
695
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
696
			$mask = gen_subnet_mask($mask);
697
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
698
			if ($settings['dev_mode'] == 'tun')
699
				$conf .= "ifconfig {$ip2} {$ip1}\n";
700
			else
701
				$conf .= "ifconfig {$ip2} {$mask}\n";
702
		}
703

    
704
		if (!empty($settings['tunnel_networkv6'])) {
705
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
706
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
707
			if ($settings['dev_mode'] == 'tun')
708
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
709
			else
710
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
711
		}
712

    
713
		if ($settings['auth_user'] && $settings['auth_pass']) {
714
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
715
			$conf .= "auth-user-pass {$up_file}\n";
716
			$userpass = "{$settings['auth_user']}\n";
717
			$userpass .= "{$settings['auth_pass']}\n";
718
			file_put_contents($up_file, $userpass);
719
		}
720
		
721
		if ($settings['proxy_addr']) {
722
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
723
			if ($settings['proxy_authtype'] != "none") {
724
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
725
				$proxypas = "{$settings['proxy_user']}\n";
726
				$proxypas .= "{$settings['proxy_passwd']}\n";
727
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
728
			}
729
			$conf .= " \n";
730
		}
731
	}
732

    
733
	// Add a remote network route if set, and only for p2p modes.
734
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
735
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
736
	}
737
	// Add a remote network route if set, and only for p2p modes.
738
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
739
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
740
	}
741

    
742
	// Write the settings for the keys
743
	switch($settings['mode']) {
744
		case 'p2p_shared_key':
745
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
746
			break;
747
		case 'p2p_tls':
748
		case 'server_tls':
749
		case 'server_tls_user':
750
		case 'server_user':
751
			$ca = lookup_ca($settings['caref']);
752
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
753

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

    
776
	if (!empty($settings['compression']))
777
		$conf .= "comp-lzo {$settings['compression']}\n";
778

    
779
	if ($settings['passtos'])
780
		$conf .= "passtos\n";
781

    
782
	if ($settings['resolve_retry'])
783
		$conf .= "resolv-retry infinite\n";
784

    
785
	if ($settings['dynamic_ip']) {
786
		$conf .= "persist-remote-ip\n";
787
		$conf .= "float\n";
788
	}
789

    
790
	if ($settings['topology_subnet']) {
791
		$conf .= "topology subnet\n";
792
	}
793

    
794
	// New client features
795
	if ($mode == "client") {
796
		// Dont pull routes checkbox
797
		if ($settings['route_no_pull']) {
798
			$conf .= "route-nopull\n";
799
		}
800

    
801
		// Dont add/remove routes checkbox
802
		if ($settings['route_no_exec']) {
803
			$conf .= "route-noexec\n";
804
		}
805
	}
806

    
807
	openvpn_add_custom($settings, $conf);
808

    
809
	openvpn_create_dirs();
810
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
811
	file_put_contents($fpath, $conf);
812
	unset($conf);
813
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
814
	file_put_contents($fpath, $interface);
815
	//chown($fpath, 'nobody');
816
	//chgrp($fpath, 'nobody');
817
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
818
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
819
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
820
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
821
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
822
}
823

    
824
function openvpn_restart($mode, $settings) {
825
	global $g, $config;
826

    
827
	$vpnid = $settings['vpnid'];
828
	$mode_id = $mode.$vpnid;
829

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

    
834
		/* read the pid file */
835
		$pid = rtrim(file_get_contents($pfile));
836
		unlink($pfile);
837

    
838
		/* send a term signal to the process */
839
		posix_kill($pid, SIGTERM);
840

    
841
		/* wait until the process exits */
842
		while(posix_kill($pid, 0))
843
			usleep(250000);
844
	}
845

    
846
	if (isset($settings['disable']))
847
		return;
848

    
849
	/* Do not start a client if we are a CARP backup on this vip! */
850
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) == "BACKUP"))
851
		return;
852
		
853
	/* Check if client is bound to a gateway group */    
854
	$a_groups = return_gateway_groups_array();
855
	if (is_array($a_groups[$settings['interface']])) {
856
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
857
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
858
			return;
859
	}
860

    
861
	/* start the new process */
862
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
863
	openvpn_clear_route($mode, $settings);
864
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
865

    
866
	if (!$g['booting'])
867
		send_event("filter reload");
868
}
869

    
870
function openvpn_delete($mode, & $settings) {
871
	global $g, $config;
872

    
873
	$vpnid = $settings['vpnid'];
874
	$mode_id = $mode.$vpnid;
875

    
876
	if (isset($settings['dev_mode']))
877
		$tunname = "{$settings['dev_mode']}{$vpnid}";
878
	else {  /* defaults to tun */
879
		$tunname = "tun{$vpnid}";
880
	}
881

    
882
	if ($mode == "server")
883
		$devname = "ovpns{$vpnid}";
884
	else
885
		$devname = "ovpnc{$vpnid}";
886

    
887
	/* kill the process if running */
888
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
889
	if (file_exists($pfile)) {
890

    
891
		/* read the pid file */
892
		$pid = trim(file_get_contents($pfile));
893
		unlink($pfile);
894

    
895
		/* send a term signal to the process */
896
		posix_kill($pid, SIGTERM);
897
	}
898

    
899
	/* remove the device from the openvpn group */
900
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
901

    
902
	/* restore the original adapter name */
903
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
904

    
905
	/* remove the configuration files */
906
	array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
907
}
908

    
909
function openvpn_cleanup_csc($common_name) {
910
	global $g, $config;
911
	if (empty($common_name))
912
		return;
913
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
914
	if (is_file($fpath))
915
		unlink_if_exists($fpath);
916
	return;
917
}
918

    
919
function openvpn_resync_csc(& $settings) {
920
	global $g, $config;
921

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

    
924
	if (isset($settings['disable'])) {
925
		unlink_if_exists($fpath);
926
		return;
927
	}
928
	openvpn_create_dirs();
929

    
930
	$conf = '';
931
	if ($settings['block'])
932
		$conf .= "disable\n";
933

    
934
	if ($settings['push_reset'])
935
		$conf .= "push-reset\n";
936

    
937
	if (!empty($settings['tunnel_network'])) {
938
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
939
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
940
		$serverip = long2ip32($baselong + 1);
941
		$clientip = long2ip32($baselong + 2);
942
		/* Because this is being pushed, the order from the client's point of view. */
943
		if ($settings['dev_mode'] != 'tap')
944
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
945
		else
946
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
947
	}
948

    
949
	if ($settings['local_network']) {
950
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
951
	}
952
	if ($settings['local_networkv6']) {
953
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
954
	}
955

    
956
	// Add a remote network iroute if set
957
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
958
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
959
	}
960
	// Add a remote network iroute if set
961
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
962
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
963
	}
964

    
965
	openvpn_add_dhcpopts($settings, $conf);
966

    
967
	if ($settings['gwredir'])
968
		$conf .= "push \"redirect-gateway def1\"\n";
969

    
970
	openvpn_add_custom($settings, $conf);
971

    
972
	file_put_contents($fpath, $conf);
973
	chown($fpath, 'nobody');
974
	chgrp($fpath, 'nobody');
975
}
976

    
977
function openvpn_delete_csc(& $settings) {
978
	global $g, $config;
979

    
980
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
981
	unlink_if_exists($fpath);
982
}
983

    
984
// Resync the configuration and restart the VPN
985
function openvpn_resync($mode, $settings) {
986
	openvpn_reconfigure($mode, $settings);
987
	openvpn_restart($mode, $settings);
988
}
989

    
990
// Resync and restart all VPNs
991
function openvpn_resync_all($interface = "") {
992
	global $g, $config;
993

    
994
	if ($g['platform'] == 'jail')
995
		return;
996
	openvpn_create_dirs();
997

    
998
	if (!is_array($config['openvpn']))
999
		$config['openvpn'] = array();
1000

    
1001
/*
1002
	if (!$config['openvpn']['dh-parameters']) {
1003
		echo "Configuring OpenVPN Parameters ...\n";
1004
		$dh_parameters = openvpn_create_dhparams(1024);
1005
		$dh_parameters = base64_encode($dh_parameters);
1006
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1007
		write_config("OpenVPN DH parameters");
1008
	}
1009

    
1010
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1011
	if (!file_exists($path_ovdh)) {
1012
		$dh_parameters = $config['openvpn']['dh-parameters'];
1013
		$dh_parameters = base64_decode($dh_parameters);
1014
		file_put_contents($path_ovdh, $dh_parameters);
1015
	}
1016
*/
1017
	if ($interface <> "")
1018
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
1019
	else
1020
		log_error("Resyncing OpenVPN instances."); 
1021

    
1022
	if (is_array($config['openvpn']['openvpn-server'])) {
1023
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1024
			if ($interface <> "" && $interface != $settings['interface'])
1025
				continue;
1026
			openvpn_resync('server', $settings);
1027
		}
1028
	}
1029

    
1030
	if (is_array($config['openvpn']['openvpn-client'])) {
1031
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1032
			if ($interface <> "" && $interface != $settings['interface'])
1033
				continue;
1034
			openvpn_resync('client', $settings);
1035
		}
1036
	}
1037

    
1038
	if (is_array($config['openvpn']['openvpn-csc']))
1039
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
1040
			openvpn_resync_csc($settings);
1041

    
1042
}
1043

    
1044
// Resync and restart all VPNs using a gateway group.
1045
function openvpn_resync_gwgroup($gwgroupname = "") {
1046
	global $g, $config;
1047

    
1048
	if ($gwgroupname <> "") {
1049
		if (is_array($config['openvpn']['openvpn-server'])) {
1050
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1051
				if ($gwgroupname == $settings['interface']) {
1052
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1053
					openvpn_resync('server', $settings);
1054
				}
1055
			}
1056
		}
1057

    
1058
		if (is_array($config['openvpn']['openvpn-client'])) {
1059
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1060
				if ($gwgroupname == $settings['interface']) {
1061
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1062
					openvpn_resync('client', $settings);
1063
				}
1064
			}
1065
		}
1066

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

    
1069
	} else
1070
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1071
}
1072

    
1073
function openvpn_get_active_servers($type="multipoint") {
1074
	global $config, $g;
1075

    
1076
	$servers = array();
1077
	if (is_array($config['openvpn']['openvpn-server'])) {
1078
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1079
			if (empty($settings) || isset($settings['disable']))
1080
				continue;
1081

    
1082
			$prot = $settings['protocol'];
1083
			$port = $settings['local_port'];
1084
	
1085
			$server = array();
1086
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1087
			$server['mode'] = $settings['mode'];
1088
			if ($settings['description'])
1089
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1090
			else
1091
				$server['name'] = "Server {$prot}:{$port}";
1092
			$server['conns'] = array();
1093
			$server['vpnid'] = $settings['vpnid'];
1094
			$server['mgmt'] = "server{$server['vpnid']}";
1095
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1096
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1097

    
1098
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1099
				$servers[] = openvpn_get_client_status($server, $socket);
1100
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1101
				$servers[] = openvpn_get_server_status($server, $socket);
1102

    
1103
		}
1104
	}
1105
	return $servers;
1106
}
1107

    
1108
function openvpn_get_server_status($server, $socket) {
1109
	$errval;
1110
	$errstr;
1111
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1112
	if ($fp) {
1113
		stream_set_timeout($fp, 1);
1114

    
1115
		/* send our status request */
1116
		fputs($fp, "status 2\n");
1117

    
1118
		/* recv all response lines */
1119
		while (!feof($fp)) {
1120

    
1121
			/* read the next line */
1122
			$line = fgets($fp, 1024);
1123

    
1124
			$info = stream_get_meta_data($fp);
1125
			if ($info['timed_out'])
1126
				break;
1127

    
1128
			/* parse header list line */
1129
			if (strstr($line, "HEADER"))
1130
				continue;
1131

    
1132
			/* parse end of output line */
1133
			if (strstr($line, "END") || strstr($line, "ERROR"))
1134
				break;
1135

    
1136
			/* parse client list line */
1137
			if (strstr($line, "CLIENT_LIST")) {
1138
				$list = explode(",", $line);
1139
				$conn = array();
1140
				$conn['common_name'] = $list[1];
1141
				$conn['remote_host'] = $list[2];
1142
				$conn['virtual_addr'] = $list[3];
1143
				$conn['bytes_recv'] = $list[4];
1144
				$conn['bytes_sent'] = $list[5];
1145
				$conn['connect_time'] = $list[6];
1146
				$server['conns'][] = $conn;
1147
			}
1148
			/* parse routing table lines */
1149
			if (strstr($line, "ROUTING_TABLE")) {
1150
				$list = explode(",", $line);
1151
				$conn = array();
1152
				$conn['virtual_addr'] = $list[1];
1153
				$conn['common_name'] = $list[2];
1154
				$conn['remote_host'] = $list[3];
1155
				$conn['last_time'] = $list[4];
1156
				$server['routes'][] = $conn;
1157
			}
1158
		}
1159

    
1160
		/* cleanup */
1161
		fclose($fp);
1162
	} else {
1163
		$conn = array();
1164
		$conn['common_name'] = "[error]";
1165
		$conn['remote_host'] = "Unable to contact daemon";
1166
		$conn['virtual_addr'] = "Service not running?";
1167
		$conn['bytes_recv'] = 0;
1168
		$conn['bytes_sent'] = 0;
1169
		$conn['connect_time'] = 0;
1170
		$server['conns'][] = $conn;
1171
	}
1172
	return $server;
1173
}
1174

    
1175
function openvpn_get_active_clients() {
1176
	global $config, $g;
1177

    
1178
	$clients = array();
1179
	if (is_array($config['openvpn']['openvpn-client'])) {
1180
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1181
	
1182
			if (empty($settings) || isset($settings['disable']))
1183
				continue;
1184

    
1185
			$prot = $settings['protocol'];
1186
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1187
	
1188
			$client = array();
1189
			$client['port'] = $settings['local_port'];
1190
			if ($settings['description'])
1191
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1192
			else
1193
				$client['name'] = "Client {$prot}{$port}";
1194
	
1195
			$client['vpnid'] = $settings['vpnid'];
1196
			$client['mgmt'] = "client{$client['vpnid']}";
1197
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1198
			$client['status']="down";
1199

    
1200
			$clients[] = openvpn_get_client_status($client, $socket);
1201
		}
1202
	}
1203
	return $clients;
1204
}
1205

    
1206
function openvpn_get_client_status($client, $socket) {
1207
	$errval;
1208
	$errstr;
1209
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1210
	if ($fp) {
1211
		stream_set_timeout($fp, 1);
1212
		/* send our status request */
1213
		fputs($fp, "state 1\n");
1214

    
1215
		/* recv all response lines */
1216
		while (!feof($fp)) {
1217
			/* read the next line */
1218
			$line = fgets($fp, 1024);
1219

    
1220
			$info = stream_get_meta_data($fp);
1221
			if ($info['timed_out'])
1222
				break;
1223

    
1224
			/* Get the client state */
1225
			if (strstr($line,"CONNECTED")) {
1226
				$client['status']="up";
1227
				$list = explode(",", $line);
1228

    
1229
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1230
				$client['virtual_addr']  = $list[3];
1231
				$client['remote_host'] = $list[4];
1232
			}
1233
			if (strstr($line,"CONNECTING")) {
1234
				$client['status']="connecting";
1235
			}
1236
			if (strstr($line,"ASSIGN_IP")) {
1237
				$client['status']="waiting";
1238
				$list = explode(",", $line);
1239

    
1240
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1241
				$client['virtual_addr']  = $list[3];
1242
			}
1243
			if (strstr($line,"RECONNECTING")) {
1244
				$client['status']="reconnecting";
1245
				$list = explode(",", $line);
1246

    
1247
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1248
				$client['status'] .= "; " . $list[2];
1249
			}
1250
			/* parse end of output line */
1251
			if (strstr($line, "END") || strstr($line, "ERROR"))
1252
				break;
1253
		}
1254

    
1255
		/* If up, get read/write stats */
1256
		if (strcmp($client['status'], "up") == 0) {
1257
			fputs($fp, "status 2\n");
1258
			/* recv all response lines */
1259
			while (!feof($fp)) {
1260
				/* read the next line */
1261
				$line = fgets($fp, 1024);
1262

    
1263
				$info = stream_get_meta_data($fp);
1264
				if ($info['timed_out'])
1265
					break;
1266

    
1267
				if (strstr($line,"TCP/UDP read bytes")) {
1268
					$list = explode(",", $line);
1269
					$client['bytes_recv'] = $list[1];
1270
				}
1271

    
1272
				if (strstr($line,"TCP/UDP write bytes")) {
1273
					$list = explode(",", $line);
1274
					$client['bytes_sent'] = $list[1];
1275
				}
1276

    
1277
				/* parse end of output line */
1278
				if (strstr($line, "END"))
1279
					break;
1280
			}
1281
		}
1282

    
1283
		fclose($fp);
1284

    
1285
	} else {
1286
		$DisplayNote=true;
1287
		$client['remote_host'] = "Unable to contact daemon";
1288
		$client['virtual_addr'] = "Service not running?";
1289
		$client['bytes_recv'] = 0;
1290
		$client['bytes_sent'] = 0;
1291
		$client['connect_time'] = 0;
1292
	}
1293
	return $client;
1294
}
1295

    
1296
function openvpn_refresh_crls() {
1297
	global $g, $config;
1298

    
1299
	openvpn_create_dirs();
1300

    
1301
	if (is_array($config['openvpn']['openvpn-server'])) {
1302
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1303
			if (empty($settings))
1304
				continue;
1305
			if (isset($settings['disable']))
1306
				continue;
1307
			// Write the settings for the keys
1308
			switch($settings['mode']) {
1309
				case 'p2p_tls':
1310
				case 'server_tls':
1311
				case 'server_tls_user':
1312
				case 'server_user':
1313
					if (!empty($settings['crlref'])) {
1314
						$crl = lookup_crl($settings['crlref']);
1315
						crl_update($crl);
1316
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1317
						file_put_contents($fpath, base64_decode($crl['text']));
1318
						@chmod($fpath, 0644);
1319
					}
1320
					break;
1321
			}
1322
		}
1323
	}
1324
}
1325

    
1326
function openvpn_create_dirs() {
1327
	global $g;
1328
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1329
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1330
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1331
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1332
}
1333

    
1334
function openvpn_get_interface_ip($ip, $mask) {
1335
	$baselong = ip2long32($ip) & ip2long($mask);
1336
	$ip1 = long2ip32($baselong + 1);
1337
	$ip2 = long2ip32($baselong + 2);
1338
	return array($ip1, $ip2);
1339
}
1340

    
1341
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1342
	$basev6 = gen_subnetv6($ipv6, $prefix);
1343
	// Is there a better way to do this math?
1344
	$ipv6_arr = explode(':', $basev6);
1345
	$last = hexdec(array_pop($ipv6_arr));
1346
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1347
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1348
	return array($ipv6_1, $ipv6_2);
1349
}
1350

    
1351
function openvpn_clear_route($mode, $settings) {
1352
	if (empty($settings['tunnel_network']))
1353
		return;
1354
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1355
	$mask = gen_subnet_mask($cidr);
1356
	$clear_route = false;
1357

    
1358
	switch($settings['mode']) {
1359
		case 'shared_key':
1360
			$clear_route = true;
1361
			break;
1362
		case 'p2p_tls':
1363
		case 'p2p_shared_key':
1364
			if ($cidr == 30)
1365
				$clear_route = true;
1366
			break;
1367
	}
1368

    
1369
	if ($clear_route && !empty($ip) && !empty($mask)) {
1370
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1371
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1372
		/* XXX: Family for route? */
1373
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1374
	}
1375
}
1376

    
1377
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1378
	$routes = "";
1379
	if (empty($value))
1380
		return "";
1381
	$networks = explode(',', $value);
1382

    
1383
	foreach ($networks as $network) {
1384
		if ($ipproto == "ipv4")
1385
			$route = openvpn_gen_route_ipv4($network, $iroute);
1386
		else
1387
			$route = openvpn_gen_route_ipv6($network, $iroute);
1388

    
1389
		if ($push)
1390
			$routes .= "push \"{$route}\"\n";
1391
		else
1392
			$routes .= "{$route}\n";
1393
	}
1394
	return $routes;
1395
}
1396

    
1397
function openvpn_gen_route_ipv4($network, $iroute = false) {
1398
	$i = ($iroute) ? "i" : "";
1399
	list($ip, $mask) = explode('/', trim($network));
1400
	$mask = gen_subnet_mask($mask);
1401
	return "{$i}route $ip $mask";
1402
}
1403

    
1404
function openvpn_gen_route_ipv6($network, $iroute = false) {
1405
	$i = ($iroute) ? "i" : "";
1406
	list($ipv6, $prefix) = explode('/', trim($network));
1407
	if (empty($prefix))
1408
		$prefix = "128";
1409
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1410
}
1411

    
1412
function openvpn_get_settings($mode, $vpnid) {
1413
	global $config;
1414

    
1415
	if (is_array($config['openvpn']['openvpn-server'])) {
1416
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1417
			if (isset($settings['disable']))
1418
				continue;
1419

    
1420
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1421
				return $settings;
1422
		}
1423
	}
1424

    
1425
	if (is_array($config['openvpn']['openvpn-client'])) {
1426
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1427
			if (isset($settings['disable']))
1428
				continue;
1429

    
1430
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1431
				return $settings;
1432
		}
1433
	}
1434

    
1435
	return array();
1436
}
1437

    
1438
function openvpn_restart_by_vpnid($mode, $vpnid) {
1439
	$settings = openvpn_get_settings($mode, $vpnid);
1440
	openvpn_restart($mode, $settings);
1441
}
1442

    
1443
?>
(38-38/68)