Projet

Général

Profil

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

univnautes / etc / inc / openvpn.inc @ 5b3c0116

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

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

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

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

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

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

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

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

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

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

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

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

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

    
663
	// client specific settings
664

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
808
	openvpn_add_custom($settings, $conf);
809

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
966
	openvpn_add_dhcpopts($settings, $conf);
967

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

    
971
	openvpn_add_custom($settings, $conf);
972

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

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

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

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

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

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

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

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

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

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

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

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

    
1043
}
1044

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1284
		fclose($fp);
1285

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

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

    
1300
	openvpn_create_dirs();
1301

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1436
	return array();
1437
}
1438

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

    
1444
?>
(38-38/68)