Project

General

Profile

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
104
function openvpn_create_key() {
105

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

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

    
113
	return $rslt;
114
}
115

    
116
function openvpn_create_dhparams($bits) {
117

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

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

    
125
	return $rslt;
126
}
127

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

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

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

    
141
	return false;
142
}
143

    
144
function openvpn_vpnid_next() {
145

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

    
150
	return $vpnid;
151
}
152

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

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

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

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

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

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

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

    
184
	return 0;
185
}
186

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

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

    
195
	return $port;
196
}
197

    
198
function openvpn_get_cipherlist() {
199

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

    
212
function openvpn_get_digestlist() {
213

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
634
	// client specific settings
635

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

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

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

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

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

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

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

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

    
685
		if ($settings['proxy_addr']) {
686
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
687
			if ($settings['proxy_authtype'] != "none") {
688
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
689
				$proxypas = "{$settings['proxy_user']}\n";
690
				$proxypas .= "{$settings['proxy_passwd']}\n";
691
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
692
			}
693
			$conf .= " \n";
694
		}
695
	}
696

    
697
	// Add a remote network route if set, and only for p2p modes.
698
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
699
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
700
	}
701
	// Add a remote network route if set, and only for p2p modes.
702
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
703
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
704
	}
705

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

    
737
	if (!empty($settings['compression']))
738
		$conf .= "comp-lzo {$settings['compression']}\n";
739

    
740
	if ($settings['passtos'])
741
		$conf .= "passtos\n";
742

    
743
	if ($settings['resolve_retry'])
744
		$conf .= "resolv-retry infinite\n";
745

    
746
	if ($settings['dynamic_ip']) {
747
		$conf .= "persist-remote-ip\n";
748
		$conf .= "float\n";
749
	}
750

    
751
	if ($settings['topology_subnet']) {
752
		$conf .= "topology subnet\n";
753
	}
754

    
755
	openvpn_add_custom($settings, $conf);
756

    
757
	openvpn_create_dirs();
758
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
759
	file_put_contents($fpath, $conf);
760
	unset($conf);
761
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
762
	file_put_contents($fpath, $interface);
763
	//chown($fpath, 'nobody');
764
	//chgrp($fpath, 'nobody');
765
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
766
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
767
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
768
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
769
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
770
}
771

    
772
function openvpn_restart($mode, $settings) {
773
	global $g, $config;
774

    
775
	$vpnid = $settings['vpnid'];
776
	$mode_id = $mode.$vpnid;
777

    
778
	/* kill the process if running */
779
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
780
	if (file_exists($pfile)) {
781

    
782
		/* read the pid file */
783
		$pid = rtrim(file_get_contents($pfile));
784
		unlink($pfile);
785

    
786
		/* send a term signal to the process */
787
		posix_kill($pid, SIGTERM);
788

    
789
		/* wait until the process exits */
790
		while(posix_kill($pid, 0))
791
			usleep(250000);
792
	}
793

    
794
	if (isset($settings['disable']))
795
		return;
796

    
797
	/* Do not start a client if we are a CARP backup on this vip! */
798
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) == "BACKUP"))
799
		return;
800
		
801
	/* Check if client is bound to a gateway group */    
802
	$a_groups = return_gateway_groups_array();
803
	if (is_array($a_groups[$settings['interface']])) {
804
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
805
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
806
			return;
807
	}
808

    
809
	/* start the new process */
810
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
811
	openvpn_clear_route($mode, $settings);
812
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
813

    
814
	if (!$g['booting'])
815
		send_event("filter reload");
816
}
817

    
818
function openvpn_delete($mode, & $settings) {
819
	global $g, $config;
820

    
821
	$vpnid = $settings['vpnid'];
822
	$mode_id = $mode.$vpnid;
823

    
824
	if (isset($settings['dev_mode']))
825
		$tunname = "{$settings['dev_mode']}{$vpnid}";
826
	else {  /* defaults to tun */
827
		$tunname = "tun{$vpnid}";
828
	}
829

    
830
	if ($mode == "server")
831
		$devname = "ovpns{$vpnid}";
832
	else
833
		$devname = "ovpnc{$vpnid}";
834

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

    
839
		/* read the pid file */
840
		$pid = trim(file_get_contents($pfile));
841
		unlink($pfile);
842

    
843
		/* send a term signal to the process */
844
		posix_kill($pid, SIGTERM);
845
	}
846

    
847
	/* remove the device from the openvpn group */
848
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
849

    
850
	/* restore the original adapter name */
851
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
852

    
853
	/* remove the configuration files */
854
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
855
}
856

    
857
function openvpn_cleanup_csc($common_name) {
858
	global $g, $config;
859
	if (empty($common_name))
860
		return;
861
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
862
	if (is_file($fpath))
863
		unlink_if_exists($fpath);
864
	return;
865
}
866

    
867
function openvpn_resync_csc(& $settings) {
868
	global $g, $config;
869

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

    
872
	if (isset($settings['disable'])) {
873
		unlink_if_exists($fpath);
874
		return;
875
	}
876
	openvpn_create_dirs();
877

    
878
	$conf = '';
879
	if ($settings['block'])
880
		$conf .= "disable\n";
881

    
882
	if ($settings['push_reset'])
883
		$conf .= "push-reset\n";
884

    
885
	if (!empty($settings['tunnel_network'])) {
886
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
887
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
888
		$serverip = long2ip32($baselong + 1);
889
		$clientip = long2ip32($baselong + 2);
890
		/* Because this is being pushed, the order from the client's point of view. */
891
		if ($settings['dev_mode'] != 'tap')
892
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
893
		else
894
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
895
	}
896

    
897
	if ($settings['local_network']) {
898
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
899
	}
900
	if ($settings['local_networkv6']) {
901
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
902
	}
903

    
904
	// Add a remote network iroute if set
905
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
906
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
907
	}
908
	// Add a remote network iroute if set
909
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
910
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
911
	}
912

    
913
	openvpn_add_dhcpopts($settings, $conf);
914

    
915
	if ($settings['gwredir'])
916
		$conf .= "push \"redirect-gateway def1\"\n";
917

    
918
	openvpn_add_custom($settings, $conf);
919

    
920
	file_put_contents($fpath, $conf);
921
	chown($fpath, 'nobody');
922
	chgrp($fpath, 'nobody');
923
}
924

    
925
function openvpn_delete_csc(& $settings) {
926
	global $g, $config;
927

    
928
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
929
	unlink_if_exists($fpath);
930
}
931

    
932
// Resync the configuration and restart the VPN
933
function openvpn_resync($mode, $settings) {
934
	openvpn_reconfigure($mode, $settings);
935
	openvpn_restart($mode, $settings);
936
}
937

    
938
// Resync and restart all VPNs
939
function openvpn_resync_all($interface = "") {
940
	global $g, $config;
941

    
942
	if ($g['platform'] == 'jail')
943
		return;
944
	openvpn_create_dirs();
945

    
946
	if (!is_array($config['openvpn']))
947
		$config['openvpn'] = array();
948

    
949
/*
950
	if (!$config['openvpn']['dh-parameters']) {
951
		echo "Configuring OpenVPN Parameters ...\n";
952
		$dh_parameters = openvpn_create_dhparams(1024);
953
		$dh_parameters = base64_encode($dh_parameters);
954
		$config['openvpn']['dh-parameters'] = $dh_parameters;
955
		write_config("OpenVPN DH parameters");
956
	}
957

    
958
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
959
	if (!file_exists($path_ovdh)) {
960
		$dh_parameters = $config['openvpn']['dh-parameters'];
961
		$dh_parameters = base64_decode($dh_parameters);
962
		file_put_contents($path_ovdh, $dh_parameters);
963
	}
964
*/
965
	if ($interface <> "")
966
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
967
	else
968
		log_error("Resyncing OpenVPN instances."); 
969

    
970
	if (is_array($config['openvpn']['openvpn-server'])) {
971
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
972
			if ($interface <> "" && $interface != $settings['interface'])
973
				continue;
974
			openvpn_resync('server', $settings);
975
		}
976
	}
977

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

    
986
	if (is_array($config['openvpn']['openvpn-csc']))
987
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
988
			openvpn_resync_csc($settings);
989

    
990
}
991

    
992
// Resync and restart all VPNs using a gateway group.
993
function openvpn_resync_gwgroup($gwgroupname = "") {
994
	global $g, $config;
995

    
996
	if ($gwgroupname <> "") {
997
		if (is_array($config['openvpn']['openvpn-server'])) {
998
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
999
				if ($gwgroupname == $settings['interface']) {
1000
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1001
					openvpn_resync('server', $settings);
1002
				}
1003
			}
1004
		}
1005

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

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

    
1017
	} else
1018
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1019
}
1020

    
1021
function openvpn_get_active_servers($type="multipoint") {
1022
	global $config, $g;
1023

    
1024
	$servers = array();
1025
	if (is_array($config['openvpn']['openvpn-server'])) {
1026
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1027
			if (empty($settings) || isset($settings['disable']))
1028
				continue;
1029

    
1030
			$prot = $settings['protocol'];
1031
			$port = $settings['local_port'];
1032
	
1033
			$server = array();
1034
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1035
			$server['mode'] = $settings['mode'];
1036
			if ($settings['description'])
1037
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1038
			else
1039
				$server['name'] = "Server {$prot}:{$port}";
1040
			$server['conns'] = array();
1041
			$server['vpnid'] = $settings['vpnid'];
1042
			$server['mgmt'] = "server{$server['vpnid']}";
1043
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1044
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1045

    
1046
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1047
				$servers[] = openvpn_get_client_status($server, $socket);
1048
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1049
				$servers[] = openvpn_get_server_status($server, $socket);
1050

    
1051
		}
1052
	}
1053
	return $servers;
1054
}
1055

    
1056
function openvpn_get_server_status($server, $socket) {
1057
	$errval;
1058
	$errstr;
1059
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1060
	if ($fp) {
1061
		stream_set_timeout($fp, 1);
1062

    
1063
		/* send our status request */
1064
		fputs($fp, "status 2\n");
1065

    
1066
		/* recv all response lines */
1067
		while (!feof($fp)) {
1068

    
1069
			/* read the next line */
1070
			$line = fgets($fp, 1024);
1071

    
1072
			$info = stream_get_meta_data($fp);
1073
			if ($info['timed_out'])
1074
				break;
1075

    
1076
			/* parse header list line */
1077
			if (strstr($line, "HEADER"))
1078
				continue;
1079

    
1080
			/* parse end of output line */
1081
			if (strstr($line, "END") || strstr($line, "ERROR"))
1082
				break;
1083

    
1084
			/* parse client list line */
1085
			if (strstr($line, "CLIENT_LIST")) {
1086
				$list = explode(",", $line);
1087
				$conn = array();
1088
				$conn['common_name'] = $list[1];
1089
				$conn['remote_host'] = $list[2];
1090
				$conn['virtual_addr'] = $list[3];
1091
				$conn['bytes_recv'] = $list[4];
1092
				$conn['bytes_sent'] = $list[5];
1093
				$conn['connect_time'] = $list[6];
1094
				$server['conns'][] = $conn;
1095
			}
1096
			/* parse routing table lines */
1097
			if (strstr($line, "ROUTING_TABLE")) {
1098
				$list = explode(",", $line);
1099
				$conn = array();
1100
				$conn['virtual_addr'] = $list[1];
1101
				$conn['common_name'] = $list[2];
1102
				$conn['remote_host'] = $list[3];
1103
				$conn['last_time'] = $list[4];
1104
				$server['routes'][] = $conn;
1105
			}
1106
		}
1107

    
1108
		/* cleanup */
1109
		fclose($fp);
1110
	} else {
1111
		$conn = array();
1112
		$conn['common_name'] = "[error]";
1113
		$conn['remote_host'] = "Unable to contact daemon";
1114
		$conn['virtual_addr'] = "Service not running?";
1115
		$conn['bytes_recv'] = 0;
1116
		$conn['bytes_sent'] = 0;
1117
		$conn['connect_time'] = 0;
1118
		$server['conns'][] = $conn;
1119
	}
1120
	return $server;
1121
}
1122

    
1123
function openvpn_get_active_clients() {
1124
	global $config, $g;
1125

    
1126
	$clients = array();
1127
	if (is_array($config['openvpn']['openvpn-client'])) {
1128
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1129
	
1130
			if (empty($settings) || isset($settings['disable']))
1131
				continue;
1132

    
1133
			$prot = $settings['protocol'];
1134
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1135
	
1136
			$client = array();
1137
			$client['port'] = $settings['local_port'];
1138
			if ($settings['description'])
1139
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1140
			else
1141
				$client['name'] = "Client {$prot}{$port}";
1142
	
1143
			$client['vpnid'] = $settings['vpnid'];
1144
			$client['mgmt'] = "client{$client['vpnid']}";
1145
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1146
			$client['status']="down";
1147

    
1148
			$clients[] = openvpn_get_client_status($client, $socket);
1149
		}
1150
	}
1151
	return $clients;
1152
}
1153

    
1154
function openvpn_get_client_status($client, $socket) {
1155
	$errval;
1156
	$errstr;
1157
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1158
	if ($fp) {
1159
		stream_set_timeout($fp, 1);
1160
		/* send our status request */
1161
		fputs($fp, "state 1\n");
1162

    
1163
		/* recv all response lines */
1164
		while (!feof($fp)) {
1165
			/* read the next line */
1166
			$line = fgets($fp, 1024);
1167

    
1168
			$info = stream_get_meta_data($fp);
1169
			if ($info['timed_out'])
1170
				break;
1171

    
1172
			/* Get the client state */
1173
			if (strstr($line,"CONNECTED")) {
1174
				$client['status']="up";
1175
				$list = explode(",", $line);
1176

    
1177
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1178
				$client['virtual_addr']  = $list[3];
1179
				$client['remote_host'] = $list[4];
1180
			}
1181
			if (strstr($line,"CONNECTING")) {
1182
				$client['status']="connecting";
1183
			}
1184
			if (strstr($line,"ASSIGN_IP")) {
1185
				$client['status']="waiting";
1186
				$list = explode(",", $line);
1187

    
1188
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1189
				$client['virtual_addr']  = $list[3];
1190
			}
1191
			if (strstr($line,"RECONNECTING")) {
1192
				$client['status']="reconnecting";
1193
				$list = explode(",", $line);
1194

    
1195
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1196
				$client['status'] .= "; " . $list[2];
1197
			}
1198
			/* parse end of output line */
1199
			if (strstr($line, "END") || strstr($line, "ERROR"))
1200
				break;
1201
		}
1202

    
1203
		/* If up, get read/write stats */
1204
		if (strcmp($client['status'], "up") == 0) {
1205
			fputs($fp, "status 2\n");
1206
			/* recv all response lines */
1207
			while (!feof($fp)) {
1208
				/* read the next line */
1209
				$line = fgets($fp, 1024);
1210

    
1211
				$info = stream_get_meta_data($fp);
1212
				if ($info['timed_out'])
1213
					break;
1214

    
1215
				if (strstr($line,"TCP/UDP read bytes")) {
1216
					$list = explode(",", $line);
1217
					$client['bytes_recv'] = $list[1];
1218
				}
1219

    
1220
				if (strstr($line,"TCP/UDP write bytes")) {
1221
					$list = explode(",", $line);
1222
					$client['bytes_sent'] = $list[1];
1223
				}
1224

    
1225
				/* parse end of output line */
1226
				if (strstr($line, "END"))
1227
					break;
1228
			}
1229
		}
1230

    
1231
		fclose($fp);
1232

    
1233
	} else {
1234
		$DisplayNote=true;
1235
		$client['remote_host'] = "Unable to contact daemon";
1236
		$client['virtual_addr'] = "Service not running?";
1237
		$client['bytes_recv'] = 0;
1238
		$client['bytes_sent'] = 0;
1239
		$client['connect_time'] = 0;
1240
	}
1241
	return $client;
1242
}
1243

    
1244
function openvpn_refresh_crls() {
1245
	global $g, $config;
1246

    
1247
	openvpn_create_dirs();
1248

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

    
1274
function openvpn_create_dirs() {
1275
	global $g;
1276
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1277
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1278
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1279
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1280
}
1281

    
1282
function openvpn_get_interface_ip($ip, $mask) {
1283
	$baselong = ip2long32($ip) & ip2long($mask);
1284
	$ip1 = long2ip32($baselong + 1);
1285
	$ip2 = long2ip32($baselong + 2);
1286
	return array($ip1, $ip2);
1287
}
1288

    
1289
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1290
	$basev6 = gen_subnetv6($ipv6, $prefix);
1291
	// Is there a better way to do this math?
1292
	$ipv6_arr = explode(':', $basev6);
1293
	$last = hexdec(array_pop($ipv6_arr));
1294
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1295
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1296
	return array($ipv6_1, $ipv6_2);
1297
}
1298

    
1299
function openvpn_clear_route($mode, $settings) {
1300
	if (empty($settings['tunnel_network']))
1301
		return;
1302
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1303
	$mask = gen_subnet_mask($cidr);
1304
	$clear_route = false;
1305

    
1306
	switch($settings['mode']) {
1307
		case 'shared_key':
1308
			$clear_route = true;
1309
			break;
1310
		case 'p2p_tls':
1311
		case 'p2p_shared_key':
1312
			if ($cidr == 30)
1313
				$clear_route = true;
1314
			break;
1315
	}
1316

    
1317
	if ($clear_route && !empty($ip) && !empty($mask)) {
1318
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1319
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1320
		/* XXX: Family for route? */
1321
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1322
	}
1323
}
1324

    
1325
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1326
	$routes = "";
1327
	if (empty($value))
1328
		return "";
1329
	$networks = explode(',', $value);
1330

    
1331
	foreach ($networks as $network) {
1332
		if ($ipproto == "ipv4")
1333
			$route = openvpn_gen_route_ipv4($network, $iroute);
1334
		else
1335
			$route = openvpn_gen_route_ipv6($network, $iroute);
1336

    
1337
		if ($push)
1338
			$routes .= "push \"{$route}\"\n";
1339
		else
1340
			$routes .= "{$route}\n";
1341
	}
1342
	return $routes;
1343
}
1344

    
1345
function openvpn_gen_route_ipv4($network, $iroute = false) {
1346
	$i = ($iroute) ? "i" : "";
1347
	list($ip, $mask) = explode('/', trim($network));
1348
	$mask = gen_subnet_mask($mask);
1349
	return "{$i}route $ip $mask";
1350
}
1351

    
1352
function openvpn_gen_route_ipv6($network, $iroute = false) {
1353
	$i = ($iroute) ? "i" : "";
1354
	list($ipv6, $prefix) = explode('/', trim($network));
1355
	if (empty($prefix))
1356
		$prefix = "128";
1357
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1358
}
1359

    
1360
function openvpn_get_settings($mode, $vpnid) {
1361
	global $config;
1362

    
1363
	if (is_array($config['openvpn']['openvpn-server'])) {
1364
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1365
			if (isset($settings['disable']))
1366
				continue;
1367

    
1368
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1369
				return $settings;
1370
		}
1371
	}
1372

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

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

    
1383
	return array();
1384
}
1385

    
1386
function openvpn_restart_by_vpnid($mode, $vpnid) {
1387
	$settings = openvpn_get_settings($mode, $vpnid);
1388
	openvpn_restart($mode, $settings);
1389
}
1390

    
1391
?>
(37-37/67)