Projet

Général

Profil

Télécharger (41,6 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / openvpn.inc @ 34bb5eb0

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

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

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

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

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

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

    
104
function openvpn_create_key() {
105

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

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

    
113
	return $rslt;
114
}
115

    
116
function openvpn_create_dhparams($bits) {
117

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

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

    
125
	return $rslt;
126
}
127

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

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

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

    
141
	return false;
142
}
143

    
144
function openvpn_vpnid_next() {
145

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

    
150
	return $vpnid;
151
}
152

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

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

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

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

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

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

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

    
184
	return 0;
185
}
186

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

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

    
195
	return $port;
196
}
197

    
198
function openvpn_get_cipherlist() {
199

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

    
212
function openvpn_get_digestlist() {
213

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
634
	// client specific settings
635

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

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

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

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

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

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

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

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

    
685
		if ($settings['auth_user'] && $settings['auth_pass']) {
686
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
687
			$conf .= "auth-user-pass {$up_file}\n";
688
			$userpass = "{$settings['auth_user']}\n";
689
			$userpass .= "{$settings['auth_pass']}\n";
690
			file_put_contents($up_file, $userpass);
691
		}
692
		
693
		if ($settings['proxy_addr']) {
694
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
695
			if ($settings['proxy_authtype'] != "none") {
696
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
697
				$proxypas = "{$settings['proxy_user']}\n";
698
				$proxypas .= "{$settings['proxy_passwd']}\n";
699
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
700
			}
701
			$conf .= " \n";
702
		}
703
	}
704

    
705
	// Add a remote network route if set, and only for p2p modes.
706
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
707
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
708
	}
709
	// Add a remote network route if set, and only for p2p modes.
710
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
711
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
712
	}
713

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

    
745
	if (!empty($settings['compression']))
746
		$conf .= "comp-lzo {$settings['compression']}\n";
747

    
748
	if ($settings['passtos'])
749
		$conf .= "passtos\n";
750

    
751
	if ($settings['resolve_retry'])
752
		$conf .= "resolv-retry infinite\n";
753

    
754
	if ($settings['dynamic_ip']) {
755
		$conf .= "persist-remote-ip\n";
756
		$conf .= "float\n";
757
	}
758

    
759
	if ($settings['topology_subnet']) {
760
		$conf .= "topology subnet\n";
761
	}
762

    
763
	openvpn_add_custom($settings, $conf);
764

    
765
	openvpn_create_dirs();
766
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
767
	file_put_contents($fpath, $conf);
768
	unset($conf);
769
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
770
	file_put_contents($fpath, $interface);
771
	//chown($fpath, 'nobody');
772
	//chgrp($fpath, 'nobody');
773
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
774
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
775
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
776
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
777
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
778
}
779

    
780
function openvpn_restart($mode, $settings) {
781
	global $g, $config;
782

    
783
	$vpnid = $settings['vpnid'];
784
	$mode_id = $mode.$vpnid;
785

    
786
	/* kill the process if running */
787
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
788
	if (file_exists($pfile)) {
789

    
790
		/* read the pid file */
791
		$pid = rtrim(file_get_contents($pfile));
792
		unlink($pfile);
793

    
794
		/* send a term signal to the process */
795
		posix_kill($pid, SIGTERM);
796

    
797
		/* wait until the process exits */
798
		while(posix_kill($pid, 0))
799
			usleep(250000);
800
	}
801

    
802
	if (isset($settings['disable']))
803
		return;
804

    
805
	/* Do not start a client if we are a CARP backup on this vip! */
806
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) == "BACKUP"))
807
		return;
808
		
809
	/* Check if client is bound to a gateway group */    
810
	$a_groups = return_gateway_groups_array();
811
	if (is_array($a_groups[$settings['interface']])) {
812
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
813
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
814
			return;
815
	}
816

    
817
	/* start the new process */
818
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
819
	openvpn_clear_route($mode, $settings);
820
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
821

    
822
	if (!$g['booting'])
823
		send_event("filter reload");
824
}
825

    
826
function openvpn_delete($mode, & $settings) {
827
	global $g, $config;
828

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

    
832
	if (isset($settings['dev_mode']))
833
		$tunname = "{$settings['dev_mode']}{$vpnid}";
834
	else {  /* defaults to tun */
835
		$tunname = "tun{$vpnid}";
836
	}
837

    
838
	if ($mode == "server")
839
		$devname = "ovpns{$vpnid}";
840
	else
841
		$devname = "ovpnc{$vpnid}";
842

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

    
847
		/* read the pid file */
848
		$pid = trim(file_get_contents($pfile));
849
		unlink($pfile);
850

    
851
		/* send a term signal to the process */
852
		posix_kill($pid, SIGTERM);
853
	}
854

    
855
	/* remove the device from the openvpn group */
856
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
857

    
858
	/* restore the original adapter name */
859
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
860

    
861
	/* remove the configuration files */
862
	array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
863
}
864

    
865
function openvpn_cleanup_csc($common_name) {
866
	global $g, $config;
867
	if (empty($common_name))
868
		return;
869
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
870
	if (is_file($fpath))
871
		unlink_if_exists($fpath);
872
	return;
873
}
874

    
875
function openvpn_resync_csc(& $settings) {
876
	global $g, $config;
877

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

    
880
	if (isset($settings['disable'])) {
881
		unlink_if_exists($fpath);
882
		return;
883
	}
884
	openvpn_create_dirs();
885

    
886
	$conf = '';
887
	if ($settings['block'])
888
		$conf .= "disable\n";
889

    
890
	if ($settings['push_reset'])
891
		$conf .= "push-reset\n";
892

    
893
	if (!empty($settings['tunnel_network'])) {
894
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
895
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
896
		$serverip = long2ip32($baselong + 1);
897
		$clientip = long2ip32($baselong + 2);
898
		/* Because this is being pushed, the order from the client's point of view. */
899
		if ($settings['dev_mode'] != 'tap')
900
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
901
		else
902
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
903
	}
904

    
905
	if ($settings['local_network']) {
906
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
907
	}
908
	if ($settings['local_networkv6']) {
909
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
910
	}
911

    
912
	// Add a remote network iroute if set
913
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
914
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
915
	}
916
	// Add a remote network iroute if set
917
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
918
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
919
	}
920

    
921
	openvpn_add_dhcpopts($settings, $conf);
922

    
923
	if ($settings['gwredir'])
924
		$conf .= "push \"redirect-gateway def1\"\n";
925

    
926
	openvpn_add_custom($settings, $conf);
927

    
928
	file_put_contents($fpath, $conf);
929
	chown($fpath, 'nobody');
930
	chgrp($fpath, 'nobody');
931
}
932

    
933
function openvpn_delete_csc(& $settings) {
934
	global $g, $config;
935

    
936
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
937
	unlink_if_exists($fpath);
938
}
939

    
940
// Resync the configuration and restart the VPN
941
function openvpn_resync($mode, $settings) {
942
	openvpn_reconfigure($mode, $settings);
943
	openvpn_restart($mode, $settings);
944
}
945

    
946
// Resync and restart all VPNs
947
function openvpn_resync_all($interface = "") {
948
	global $g, $config;
949

    
950
	if ($g['platform'] == 'jail')
951
		return;
952
	openvpn_create_dirs();
953

    
954
	if (!is_array($config['openvpn']))
955
		$config['openvpn'] = array();
956

    
957
/*
958
	if (!$config['openvpn']['dh-parameters']) {
959
		echo "Configuring OpenVPN Parameters ...\n";
960
		$dh_parameters = openvpn_create_dhparams(1024);
961
		$dh_parameters = base64_encode($dh_parameters);
962
		$config['openvpn']['dh-parameters'] = $dh_parameters;
963
		write_config("OpenVPN DH parameters");
964
	}
965

    
966
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
967
	if (!file_exists($path_ovdh)) {
968
		$dh_parameters = $config['openvpn']['dh-parameters'];
969
		$dh_parameters = base64_decode($dh_parameters);
970
		file_put_contents($path_ovdh, $dh_parameters);
971
	}
972
*/
973
	if ($interface <> "")
974
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
975
	else
976
		log_error("Resyncing OpenVPN instances."); 
977

    
978
	if (is_array($config['openvpn']['openvpn-server'])) {
979
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
980
			if ($interface <> "" && $interface != $settings['interface'])
981
				continue;
982
			openvpn_resync('server', $settings);
983
		}
984
	}
985

    
986
	if (is_array($config['openvpn']['openvpn-client'])) {
987
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
988
			if ($interface <> "" && $interface != $settings['interface'])
989
				continue;
990
			openvpn_resync('client', $settings);
991
		}
992
	}
993

    
994
	if (is_array($config['openvpn']['openvpn-csc']))
995
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
996
			openvpn_resync_csc($settings);
997

    
998
}
999

    
1000
// Resync and restart all VPNs using a gateway group.
1001
function openvpn_resync_gwgroup($gwgroupname = "") {
1002
	global $g, $config;
1003

    
1004
	if ($gwgroupname <> "") {
1005
		if (is_array($config['openvpn']['openvpn-server'])) {
1006
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1007
				if ($gwgroupname == $settings['interface']) {
1008
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1009
					openvpn_resync('server', $settings);
1010
				}
1011
			}
1012
		}
1013

    
1014
		if (is_array($config['openvpn']['openvpn-client'])) {
1015
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1016
				if ($gwgroupname == $settings['interface']) {
1017
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1018
					openvpn_resync('client', $settings);
1019
				}
1020
			}
1021
		}
1022

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

    
1025
	} else
1026
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1027
}
1028

    
1029
function openvpn_get_active_servers($type="multipoint") {
1030
	global $config, $g;
1031

    
1032
	$servers = array();
1033
	if (is_array($config['openvpn']['openvpn-server'])) {
1034
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1035
			if (empty($settings) || isset($settings['disable']))
1036
				continue;
1037

    
1038
			$prot = $settings['protocol'];
1039
			$port = $settings['local_port'];
1040
	
1041
			$server = array();
1042
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1043
			$server['mode'] = $settings['mode'];
1044
			if ($settings['description'])
1045
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1046
			else
1047
				$server['name'] = "Server {$prot}:{$port}";
1048
			$server['conns'] = array();
1049
			$server['vpnid'] = $settings['vpnid'];
1050
			$server['mgmt'] = "server{$server['vpnid']}";
1051
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1052
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1053

    
1054
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1055
				$servers[] = openvpn_get_client_status($server, $socket);
1056
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1057
				$servers[] = openvpn_get_server_status($server, $socket);
1058

    
1059
		}
1060
	}
1061
	return $servers;
1062
}
1063

    
1064
function openvpn_get_server_status($server, $socket) {
1065
	$errval;
1066
	$errstr;
1067
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1068
	if ($fp) {
1069
		stream_set_timeout($fp, 1);
1070

    
1071
		/* send our status request */
1072
		fputs($fp, "status 2\n");
1073

    
1074
		/* recv all response lines */
1075
		while (!feof($fp)) {
1076

    
1077
			/* read the next line */
1078
			$line = fgets($fp, 1024);
1079

    
1080
			$info = stream_get_meta_data($fp);
1081
			if ($info['timed_out'])
1082
				break;
1083

    
1084
			/* parse header list line */
1085
			if (strstr($line, "HEADER"))
1086
				continue;
1087

    
1088
			/* parse end of output line */
1089
			if (strstr($line, "END") || strstr($line, "ERROR"))
1090
				break;
1091

    
1092
			/* parse client list line */
1093
			if (strstr($line, "CLIENT_LIST")) {
1094
				$list = explode(",", $line);
1095
				$conn = array();
1096
				$conn['common_name'] = $list[1];
1097
				$conn['remote_host'] = $list[2];
1098
				$conn['virtual_addr'] = $list[3];
1099
				$conn['bytes_recv'] = $list[4];
1100
				$conn['bytes_sent'] = $list[5];
1101
				$conn['connect_time'] = $list[6];
1102
				$server['conns'][] = $conn;
1103
			}
1104
			/* parse routing table lines */
1105
			if (strstr($line, "ROUTING_TABLE")) {
1106
				$list = explode(",", $line);
1107
				$conn = array();
1108
				$conn['virtual_addr'] = $list[1];
1109
				$conn['common_name'] = $list[2];
1110
				$conn['remote_host'] = $list[3];
1111
				$conn['last_time'] = $list[4];
1112
				$server['routes'][] = $conn;
1113
			}
1114
		}
1115

    
1116
		/* cleanup */
1117
		fclose($fp);
1118
	} else {
1119
		$conn = array();
1120
		$conn['common_name'] = "[error]";
1121
		$conn['remote_host'] = "Unable to contact daemon";
1122
		$conn['virtual_addr'] = "Service not running?";
1123
		$conn['bytes_recv'] = 0;
1124
		$conn['bytes_sent'] = 0;
1125
		$conn['connect_time'] = 0;
1126
		$server['conns'][] = $conn;
1127
	}
1128
	return $server;
1129
}
1130

    
1131
function openvpn_get_active_clients() {
1132
	global $config, $g;
1133

    
1134
	$clients = array();
1135
	if (is_array($config['openvpn']['openvpn-client'])) {
1136
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1137
	
1138
			if (empty($settings) || isset($settings['disable']))
1139
				continue;
1140

    
1141
			$prot = $settings['protocol'];
1142
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1143
	
1144
			$client = array();
1145
			$client['port'] = $settings['local_port'];
1146
			if ($settings['description'])
1147
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1148
			else
1149
				$client['name'] = "Client {$prot}{$port}";
1150
	
1151
			$client['vpnid'] = $settings['vpnid'];
1152
			$client['mgmt'] = "client{$client['vpnid']}";
1153
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1154
			$client['status']="down";
1155

    
1156
			$clients[] = openvpn_get_client_status($client, $socket);
1157
		}
1158
	}
1159
	return $clients;
1160
}
1161

    
1162
function openvpn_get_client_status($client, $socket) {
1163
	$errval;
1164
	$errstr;
1165
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1166
	if ($fp) {
1167
		stream_set_timeout($fp, 1);
1168
		/* send our status request */
1169
		fputs($fp, "state 1\n");
1170

    
1171
		/* recv all response lines */
1172
		while (!feof($fp)) {
1173
			/* read the next line */
1174
			$line = fgets($fp, 1024);
1175

    
1176
			$info = stream_get_meta_data($fp);
1177
			if ($info['timed_out'])
1178
				break;
1179

    
1180
			/* Get the client state */
1181
			if (strstr($line,"CONNECTED")) {
1182
				$client['status']="up";
1183
				$list = explode(",", $line);
1184

    
1185
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1186
				$client['virtual_addr']  = $list[3];
1187
				$client['remote_host'] = $list[4];
1188
			}
1189
			if (strstr($line,"CONNECTING")) {
1190
				$client['status']="connecting";
1191
			}
1192
			if (strstr($line,"ASSIGN_IP")) {
1193
				$client['status']="waiting";
1194
				$list = explode(",", $line);
1195

    
1196
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1197
				$client['virtual_addr']  = $list[3];
1198
			}
1199
			if (strstr($line,"RECONNECTING")) {
1200
				$client['status']="reconnecting";
1201
				$list = explode(",", $line);
1202

    
1203
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1204
				$client['status'] .= "; " . $list[2];
1205
			}
1206
			/* parse end of output line */
1207
			if (strstr($line, "END") || strstr($line, "ERROR"))
1208
				break;
1209
		}
1210

    
1211
		/* If up, get read/write stats */
1212
		if (strcmp($client['status'], "up") == 0) {
1213
			fputs($fp, "status 2\n");
1214
			/* recv all response lines */
1215
			while (!feof($fp)) {
1216
				/* read the next line */
1217
				$line = fgets($fp, 1024);
1218

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

    
1223
				if (strstr($line,"TCP/UDP read bytes")) {
1224
					$list = explode(",", $line);
1225
					$client['bytes_recv'] = $list[1];
1226
				}
1227

    
1228
				if (strstr($line,"TCP/UDP write bytes")) {
1229
					$list = explode(",", $line);
1230
					$client['bytes_sent'] = $list[1];
1231
				}
1232

    
1233
				/* parse end of output line */
1234
				if (strstr($line, "END"))
1235
					break;
1236
			}
1237
		}
1238

    
1239
		fclose($fp);
1240

    
1241
	} else {
1242
		$DisplayNote=true;
1243
		$client['remote_host'] = "Unable to contact daemon";
1244
		$client['virtual_addr'] = "Service not running?";
1245
		$client['bytes_recv'] = 0;
1246
		$client['bytes_sent'] = 0;
1247
		$client['connect_time'] = 0;
1248
	}
1249
	return $client;
1250
}
1251

    
1252
function openvpn_refresh_crls() {
1253
	global $g, $config;
1254

    
1255
	openvpn_create_dirs();
1256

    
1257
	if (is_array($config['openvpn']['openvpn-server'])) {
1258
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1259
			if (empty($settings))
1260
				continue;
1261
			if (isset($settings['disable']))
1262
				continue;
1263
			// Write the settings for the keys
1264
			switch($settings['mode']) {
1265
				case 'p2p_tls':
1266
				case 'server_tls':
1267
				case 'server_tls_user':
1268
				case 'server_user':
1269
					if (!empty($settings['crlref'])) {
1270
						$crl = lookup_crl($settings['crlref']);
1271
						crl_update($crl);
1272
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1273
						file_put_contents($fpath, base64_decode($crl['text']));
1274
						@chmod($fpath, 0644);
1275
					}
1276
					break;
1277
			}
1278
		}
1279
	}
1280
}
1281

    
1282
function openvpn_create_dirs() {
1283
	global $g;
1284
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1285
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1286
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1287
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1288
}
1289

    
1290
function openvpn_get_interface_ip($ip, $mask) {
1291
	$baselong = ip2long32($ip) & ip2long($mask);
1292
	$ip1 = long2ip32($baselong + 1);
1293
	$ip2 = long2ip32($baselong + 2);
1294
	return array($ip1, $ip2);
1295
}
1296

    
1297
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1298
	$basev6 = gen_subnetv6($ipv6, $prefix);
1299
	// Is there a better way to do this math?
1300
	$ipv6_arr = explode(':', $basev6);
1301
	$last = hexdec(array_pop($ipv6_arr));
1302
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1303
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1304
	return array($ipv6_1, $ipv6_2);
1305
}
1306

    
1307
function openvpn_clear_route($mode, $settings) {
1308
	if (empty($settings['tunnel_network']))
1309
		return;
1310
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1311
	$mask = gen_subnet_mask($cidr);
1312
	$clear_route = false;
1313

    
1314
	switch($settings['mode']) {
1315
		case 'shared_key':
1316
			$clear_route = true;
1317
			break;
1318
		case 'p2p_tls':
1319
		case 'p2p_shared_key':
1320
			if ($cidr == 30)
1321
				$clear_route = true;
1322
			break;
1323
	}
1324

    
1325
	if ($clear_route && !empty($ip) && !empty($mask)) {
1326
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1327
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1328
		/* XXX: Family for route? */
1329
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1330
	}
1331
}
1332

    
1333
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1334
	$routes = "";
1335
	if (empty($value))
1336
		return "";
1337
	$networks = explode(',', $value);
1338

    
1339
	foreach ($networks as $network) {
1340
		if ($ipproto == "ipv4")
1341
			$route = openvpn_gen_route_ipv4($network, $iroute);
1342
		else
1343
			$route = openvpn_gen_route_ipv6($network, $iroute);
1344

    
1345
		if ($push)
1346
			$routes .= "push \"{$route}\"\n";
1347
		else
1348
			$routes .= "{$route}\n";
1349
	}
1350
	return $routes;
1351
}
1352

    
1353
function openvpn_gen_route_ipv4($network, $iroute = false) {
1354
	$i = ($iroute) ? "i" : "";
1355
	list($ip, $mask) = explode('/', trim($network));
1356
	$mask = gen_subnet_mask($mask);
1357
	return "{$i}route $ip $mask";
1358
}
1359

    
1360
function openvpn_gen_route_ipv6($network, $iroute = false) {
1361
	$i = ($iroute) ? "i" : "";
1362
	list($ipv6, $prefix) = explode('/', trim($network));
1363
	if (empty($prefix))
1364
		$prefix = "128";
1365
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1366
}
1367

    
1368
function openvpn_get_settings($mode, $vpnid) {
1369
	global $config;
1370

    
1371
	if (is_array($config['openvpn']['openvpn-server'])) {
1372
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1373
			if (isset($settings['disable']))
1374
				continue;
1375

    
1376
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1377
				return $settings;
1378
		}
1379
	}
1380

    
1381
	if (is_array($config['openvpn']['openvpn-client'])) {
1382
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1383
			if (isset($settings['disable']))
1384
				continue;
1385

    
1386
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1387
				return $settings;
1388
		}
1389
	}
1390

    
1391
	return array();
1392
}
1393

    
1394
function openvpn_restart_by_vpnid($mode, $vpnid) {
1395
	$settings = openvpn_get_settings($mode, $vpnid);
1396
	openvpn_restart($mode, $settings);
1397
}
1398

    
1399
?>
(37-37/67)