Projet

Général

Profil

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

univnautes / etc / inc / openvpn.inc @ 0e678da7

1
<?php
2
/*
3
	openvpn.inc part of pfSense
4
	
5
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
6
	All rights reserved.
7
	
8
	Copyright (C) 2006  Fernando Lemos
9
	All rights reserved.
10

    
11
	This file was rewritten from scratch by Fernando Lemos but
12
	*MIGHT* contain code previously written by:
13

    
14
	Copyright (C) 2005 Peter Allgeyer <allgeyer_AT_web.de>
15
	All rights reserved.
16

    
17
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
18
	All rights reserved.
19

    
20
	Redistribution and use in source and binary forms, with or without
21
	modification, are permitted provided that the following conditions are met:
22

    
23
	1. Redistributions of source code must retain the above copyright notices,
24
	   this list of conditions and the following disclaimer.
25

    
26
	2. Redistributions in binary form must reproduce the above copyright
27
	   notices, this list of conditions and the following disclaimer in the
28
	   documentation and/or other materials provided with the distribution.
29

    
30
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39
	POSSIBILITY OF SUCH DAMAGE.
40
	
41
	DISABLE_PHP_LINT_CHECKING
42
	
43
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/bin/openssl	/sbin/ifconfig
44
	pfSense_MODULE:	openvpn
45

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

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

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

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

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

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

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

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

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

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

    
120
function openvpn_create_key() {
121

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

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

    
129
	return $rslt;
130
}
131

    
132
function openvpn_create_dhparams($bits) {
133

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

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

    
141
	return $rslt;
142
}
143

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

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

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

    
157
	return false;
158
}
159

    
160
function openvpn_vpnid_next() {
161

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

    
166
	return $vpnid;
167
}
168

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

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

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

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

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

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

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

    
200
	return 0;
201
}
202

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

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

    
211
	return $port;
212
}
213

    
214
function openvpn_get_cipherlist() {
215

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

    
228
function openvpn_get_digestlist() {
229

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
521
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
522
		$conf .= "engine {$settings['engine']}\n";
523

    
524
	// server specific settings
525
	if ($mode == 'server') {
526

    
527
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
528
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
529
		$mask = gen_subnet_mask($cidr);
530

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

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

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

    
625
		// The local port to listen on
626
		$conf .= "lport {$settings['local_port']}\n";
627

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

    
633
		if ($settings['maxclients'])
634
			$conf .= "max-clients {$settings['maxclients']}\n";
635

    
636
		// Can we push routes
637
		if ($settings['local_network']) {
638
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
639
		}
640
		if ($settings['local_networkv6']) {
641
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
642
		}
643

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

    
658
	// client specific settings
659

    
660
	if ($mode == 'client') {
661

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

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

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

    
684
		// The remote server
685
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
686

    
687
		if (!empty($settings['use_shaper']))
688
			$conf .= "shaper {$settings['use_shaper']}\n";
689

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

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

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

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

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

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

    
772
	if (!empty($settings['compression']))
773
		$conf .= "comp-lzo {$settings['compression']}\n";
774

    
775
	if ($settings['passtos'])
776
		$conf .= "passtos\n";
777

    
778
	if ($settings['resolve_retry'])
779
		$conf .= "resolv-retry infinite\n";
780

    
781
	if ($settings['dynamic_ip']) {
782
		$conf .= "persist-remote-ip\n";
783
		$conf .= "float\n";
784
	}
785

    
786
	if ($settings['topology_subnet']) {
787
		$conf .= "topology subnet\n";
788
	}
789

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

    
797
		// Dont add/remove routes checkbox
798
		if ($settings['route_no_exec']) {
799
			$conf .= "route-noexec\n";
800
		}
801
	}
802

    
803
	openvpn_add_custom($settings, $conf);
804

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

    
820
function openvpn_restart($mode, $settings) {
821
	global $g, $config;
822

    
823
	$vpnid = $settings['vpnid'];
824
	$mode_id = $mode.$vpnid;
825

    
826
	/* kill the process if running */
827
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
828
	if (file_exists($pfile)) {
829

    
830
		/* read the pid file */
831
		$pid = rtrim(file_get_contents($pfile));
832
		unlink($pfile);
833

    
834
		/* send a term signal to the process */
835
		posix_kill($pid, SIGTERM);
836

    
837
		/* wait until the process exits */
838
		while(posix_kill($pid, 0))
839
			usleep(250000);
840
	}
841

    
842
	if (isset($settings['disable']))
843
		return;
844

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

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

    
862
	if (!$g['booting'])
863
		send_event("filter reload");
864
}
865

    
866
function openvpn_delete($mode, & $settings) {
867
	global $g, $config;
868

    
869
	$vpnid = $settings['vpnid'];
870
	$mode_id = $mode.$vpnid;
871

    
872
	if (isset($settings['dev_mode']))
873
		$tunname = "{$settings['dev_mode']}{$vpnid}";
874
	else {  /* defaults to tun */
875
		$tunname = "tun{$vpnid}";
876
	}
877

    
878
	if ($mode == "server")
879
		$devname = "ovpns{$vpnid}";
880
	else
881
		$devname = "ovpnc{$vpnid}";
882

    
883
	/* kill the process if running */
884
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
885
	if (file_exists($pfile)) {
886

    
887
		/* read the pid file */
888
		$pid = trim(file_get_contents($pfile));
889
		unlink($pfile);
890

    
891
		/* send a term signal to the process */
892
		posix_kill($pid, SIGTERM);
893
	}
894

    
895
	/* remove the device from the openvpn group */
896
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
897

    
898
	/* restore the original adapter name */
899
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
900

    
901
	/* remove the configuration files */
902
	array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
903
}
904

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

    
915
function openvpn_resync_csc(& $settings) {
916
	global $g, $config;
917

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

    
920
	if (isset($settings['disable'])) {
921
		unlink_if_exists($fpath);
922
		return;
923
	}
924
	openvpn_create_dirs();
925

    
926
	$conf = '';
927
	if ($settings['block'])
928
		$conf .= "disable\n";
929

    
930
	if ($settings['push_reset'])
931
		$conf .= "push-reset\n";
932

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

    
945
	if ($settings['local_network']) {
946
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
947
	}
948
	if ($settings['local_networkv6']) {
949
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
950
	}
951

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

    
961
	openvpn_add_dhcpopts($settings, $conf);
962

    
963
	if ($settings['gwredir'])
964
		$conf .= "push \"redirect-gateway def1\"\n";
965

    
966
	openvpn_add_custom($settings, $conf);
967

    
968
	file_put_contents($fpath, $conf);
969
	chown($fpath, 'nobody');
970
	chgrp($fpath, 'nobody');
971
}
972

    
973
function openvpn_delete_csc(& $settings) {
974
	global $g, $config;
975

    
976
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
977
	unlink_if_exists($fpath);
978
}
979

    
980
// Resync the configuration and restart the VPN
981
function openvpn_resync($mode, $settings) {
982
	openvpn_reconfigure($mode, $settings);
983
	openvpn_restart($mode, $settings);
984
}
985

    
986
// Resync and restart all VPNs
987
function openvpn_resync_all($interface = "") {
988
	global $g, $config;
989

    
990
	if ($g['platform'] == 'jail')
991
		return;
992
	openvpn_create_dirs();
993

    
994
	if (!is_array($config['openvpn']))
995
		$config['openvpn'] = array();
996

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

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

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

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

    
1034
	if (is_array($config['openvpn']['openvpn-csc']))
1035
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
1036
			openvpn_resync_csc($settings);
1037

    
1038
}
1039

    
1040
// Resync and restart all VPNs using a gateway group.
1041
function openvpn_resync_gwgroup($gwgroupname = "") {
1042
	global $g, $config;
1043

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

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

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

    
1065
	} else
1066
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1067
}
1068

    
1069
function openvpn_get_active_servers($type="multipoint") {
1070
	global $config, $g;
1071

    
1072
	$servers = array();
1073
	if (is_array($config['openvpn']['openvpn-server'])) {
1074
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1075
			if (empty($settings) || isset($settings['disable']))
1076
				continue;
1077

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

    
1094
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1095
				$servers[] = openvpn_get_client_status($server, $socket);
1096
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1097
				$servers[] = openvpn_get_server_status($server, $socket);
1098

    
1099
		}
1100
	}
1101
	return $servers;
1102
}
1103

    
1104
function openvpn_get_server_status($server, $socket) {
1105
	$errval;
1106
	$errstr;
1107
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1108
	if ($fp) {
1109
		stream_set_timeout($fp, 1);
1110

    
1111
		/* send our status request */
1112
		fputs($fp, "status 2\n");
1113

    
1114
		/* recv all response lines */
1115
		while (!feof($fp)) {
1116

    
1117
			/* read the next line */
1118
			$line = fgets($fp, 1024);
1119

    
1120
			$info = stream_get_meta_data($fp);
1121
			if ($info['timed_out'])
1122
				break;
1123

    
1124
			/* parse header list line */
1125
			if (strstr($line, "HEADER"))
1126
				continue;
1127

    
1128
			/* parse end of output line */
1129
			if (strstr($line, "END") || strstr($line, "ERROR"))
1130
				break;
1131

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

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

    
1171
function openvpn_get_active_clients() {
1172
	global $config, $g;
1173

    
1174
	$clients = array();
1175
	if (is_array($config['openvpn']['openvpn-client'])) {
1176
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1177
	
1178
			if (empty($settings) || isset($settings['disable']))
1179
				continue;
1180

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

    
1196
			$clients[] = openvpn_get_client_status($client, $socket);
1197
		}
1198
	}
1199
	return $clients;
1200
}
1201

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

    
1211
		/* recv all response lines */
1212
		while (!feof($fp)) {
1213
			/* read the next line */
1214
			$line = fgets($fp, 1024);
1215

    
1216
			$info = stream_get_meta_data($fp);
1217
			if ($info['timed_out'])
1218
				break;
1219

    
1220
			/* Get the client state */
1221
			if (strstr($line,"CONNECTED")) {
1222
				$client['status']="up";
1223
				$list = explode(",", $line);
1224

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

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

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

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

    
1259
				$info = stream_get_meta_data($fp);
1260
				if ($info['timed_out'])
1261
					break;
1262

    
1263
				if (strstr($line,"TCP/UDP read bytes")) {
1264
					$list = explode(",", $line);
1265
					$client['bytes_recv'] = $list[1];
1266
				}
1267

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

    
1273
				/* parse end of output line */
1274
				if (strstr($line, "END"))
1275
					break;
1276
			}
1277
		}
1278

    
1279
		fclose($fp);
1280

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

    
1292
function openvpn_refresh_crls() {
1293
	global $g, $config;
1294

    
1295
	openvpn_create_dirs();
1296

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

    
1322
function openvpn_create_dirs() {
1323
	global $g;
1324
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1325
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1326
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1327
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1328
}
1329

    
1330
function openvpn_get_interface_ip($ip, $mask) {
1331
	$baselong = ip2long32($ip) & ip2long($mask);
1332
	$ip1 = long2ip32($baselong + 1);
1333
	$ip2 = long2ip32($baselong + 2);
1334
	return array($ip1, $ip2);
1335
}
1336

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

    
1347
function openvpn_clear_route($mode, $settings) {
1348
	if (empty($settings['tunnel_network']))
1349
		return;
1350
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1351
	$mask = gen_subnet_mask($cidr);
1352
	$clear_route = false;
1353

    
1354
	switch($settings['mode']) {
1355
		case 'shared_key':
1356
			$clear_route = true;
1357
			break;
1358
		case 'p2p_tls':
1359
		case 'p2p_shared_key':
1360
			if ($cidr == 30)
1361
				$clear_route = true;
1362
			break;
1363
	}
1364

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

    
1373
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1374
	$routes = "";
1375
	if (empty($value))
1376
		return "";
1377
	$networks = explode(',', $value);
1378

    
1379
	foreach ($networks as $network) {
1380
		if ($ipproto == "ipv4")
1381
			$route = openvpn_gen_route_ipv4($network, $iroute);
1382
		else
1383
			$route = openvpn_gen_route_ipv6($network, $iroute);
1384

    
1385
		if ($push)
1386
			$routes .= "push \"{$route}\"\n";
1387
		else
1388
			$routes .= "{$route}\n";
1389
	}
1390
	return $routes;
1391
}
1392

    
1393
function openvpn_gen_route_ipv4($network, $iroute = false) {
1394
	$i = ($iroute) ? "i" : "";
1395
	list($ip, $mask) = explode('/', trim($network));
1396
	$mask = gen_subnet_mask($mask);
1397
	return "{$i}route $ip $mask";
1398
}
1399

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

    
1408
function openvpn_get_settings($mode, $vpnid) {
1409
	global $config;
1410

    
1411
	if (is_array($config['openvpn']['openvpn-server'])) {
1412
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1413
			if (isset($settings['disable']))
1414
				continue;
1415

    
1416
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1417
				return $settings;
1418
		}
1419
	}
1420

    
1421
	if (is_array($config['openvpn']['openvpn-client'])) {
1422
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1423
			if (isset($settings['disable']))
1424
				continue;
1425

    
1426
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1427
				return $settings;
1428
		}
1429
	}
1430

    
1431
	return array();
1432
}
1433

    
1434
function openvpn_restart_by_vpnid($mode, $vpnid) {
1435
	$settings = openvpn_get_settings($mode, $vpnid);
1436
	openvpn_restart($mode, $settings);
1437
}
1438

    
1439
?>
(38-38/68)