Projet

Général

Profil

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

univnautes / etc / inc / openvpn.inc @ 21cd92ac

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

    
42
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/bin/openssl	/sbin/ifconfig
43
	pfSense_MODULE:	openvpn
44

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

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

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

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

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

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

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

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

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

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

    
119
function openvpn_create_key() {
120

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

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

    
128
	return $rslt;
129
}
130

    
131
function openvpn_create_dhparams($bits) {
132

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

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

    
140
	return $rslt;
141
}
142

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

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

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

    
156
	return false;
157
}
158

    
159
function openvpn_vpnid_next() {
160

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

    
165
	return $vpnid;
166
}
167

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

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

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

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

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

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

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

    
199
	return 0;
200
}
201

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

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

    
210
	return $port;
211
}
212

    
213
function openvpn_get_cipherlist() {
214

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

    
227
function openvpn_get_digestlist() {
228

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
352
	if (!empty($settings['push_register_dns']))
353
		$conf .= "push \"register-dns\"\n";
354

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

    
360
	if ($settings['netbios_enable']) {
361

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

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

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

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

    
380
function openvpn_add_custom(& $settings, & $conf) {
381

    
382
	if ($settings['custom_options']) {
383

    
384
		$options = explode(';', $settings['custom_options']);
385

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

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

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

    
404
	$conf .= "{$directive} {$fpath} {$opt}\n";
405
}
406

    
407
function openvpn_reconfigure($mode, $settings) {
408
	global $g, $config;
409

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

    
421
	$vpnid = $settings['vpnid'];
422
	$mode_id = $mode.$vpnid;
423

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

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

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

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

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

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

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

    
459
	$interface = get_failover_interface($settings['interface']);
460
	$ipaddr = $settings['ipaddr'];
461
	$ipaddrv6 = $settings['ipaddrv6'];
462

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

    
481

    
482
	$conf = "dev {$devname}\n";
483
	if (isset($settings['verbosity_level'])) {
484
		$conf .= "verb {$settings['verbosity_level']}\n";
485
	}
486

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

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

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

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

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

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

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

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

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

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

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

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

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

    
664
	// client specific settings
665

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

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

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

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

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

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

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

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

    
715
		if ($settings['auth_user'] && $settings['auth_pass']) {
716
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
717
			$conf .= "auth-user-pass {$up_file}\n";
718
			$userpass = "{$settings['auth_user']}\n";
719
			$userpass .= "{$settings['auth_pass']}\n";
720
			file_put_contents($up_file, $userpass);
721
		}
722

    
723
		if ($settings['proxy_addr']) {
724
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
725
			if ($settings['proxy_authtype'] != "none") {
726
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
727
				$proxypas = "{$settings['proxy_user']}\n";
728
				$proxypas .= "{$settings['proxy_passwd']}\n";
729
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
730
			}
731
			$conf .= " \n";
732
		}
733
	}
734

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

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

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

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

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

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

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

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

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

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

    
809
	openvpn_add_custom($settings, $conf);
810

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

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

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

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

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

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

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

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

    
851
	/* Do not start a client if we are a CARP backup on this vip! */
852
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) == "BACKUP"))
853
		return;
854

    
855
	/* Check if client is bound to a gateway group */
856
	$a_groups = return_gateway_groups_array();
857
	if (is_array($a_groups[$settings['interface']])) {
858
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
859
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
860
			return;
861
	}
862

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
967
	openvpn_add_dhcpopts($settings, $conf);
968

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

    
972
	openvpn_add_custom($settings, $conf);
973

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

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

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

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

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

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

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

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

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

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

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

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

    
1044
}
1045

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

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

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

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

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

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

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

    
1084
			$prot = $settings['protocol'];
1085
			$port = $settings['local_port'];
1086

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1180
	$clients = array();
1181
	if (is_array($config['openvpn']['openvpn-client'])) {
1182
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1183

    
1184
			if (empty($settings) || isset($settings['disable']))
1185
				continue;
1186

    
1187
			$prot = $settings['protocol'];
1188
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1189

    
1190
			$client = array();
1191
			$client['port'] = $settings['local_port'];
1192
			if ($settings['description'])
1193
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1194
			else
1195
				$client['name'] = "Client {$prot}{$port}";
1196

    
1197
			$client['vpnid'] = $settings['vpnid'];
1198
			$client['mgmt'] = "client{$client['vpnid']}";
1199
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1200
			$client['status']="down";
1201

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1285
		fclose($fp);
1286

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

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

    
1301
	openvpn_create_dirs();
1302

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1437
	return array();
1438
}
1439

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

    
1445
?>
(38-38/68)