Projet

Général

Profil

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

univnautes / etc / inc / openvpn.inc @ e9490019

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
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
566
							} else {
567
								$conf .= "mode server\n";
568
							}
569
						} else {
570
							$conf .= "mode server\n";
571
						}
572
					}
573
				}
574
				break;
575
		}
576

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

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

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

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

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

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

    
635
	// client specific settings
636

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
764
	openvpn_add_custom($settings, $conf);
765

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
922
	openvpn_add_dhcpopts($settings, $conf);
923

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

    
927
	openvpn_add_custom($settings, $conf);
928

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

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

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

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

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

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

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

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

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

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

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

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

    
999
}
1000

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1240
		fclose($fp);
1241

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

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

    
1256
	openvpn_create_dirs();
1257

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1392
	return array();
1393
}
1394

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

    
1400
?>
(38-38/68)