Project

General

Profile

Download (40.8 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/local/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
function openvpn_create_key() {
98

    
99
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
100
	if (!$fp)
101
		return false;
102

    
103
	$rslt = stream_get_contents($fp);
104
	pclose($fp);
105

    
106
	return $rslt;
107
}
108

    
109
function openvpn_create_dhparams($bits) {
110

    
111
	$fp = popen("/usr/local/bin/openssl dhparam {$bits} 2>/dev/null", "r");
112
	if (!$fp)
113
		return false;
114

    
115
	$rslt = stream_get_contents($fp);
116
	pclose($fp);
117

    
118
	return $rslt;
119
}
120

    
121
function openvpn_vpnid_used($vpnid) {
122
	global $config;
123

    
124
	if (is_array($config['openvpn']['openvpn-server']))
125
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
126
			if ($vpnid == $settings['vpnid'])
127
				return true;
128

    
129
	if (is_array($config['openvpn']['openvpn-client']))
130
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
131
			if ($vpnid == $settings['vpnid'])
132
				return true;
133

    
134
	return false;
135
}
136

    
137
function openvpn_vpnid_next() {
138

    
139
	$vpnid = 1;
140
	while(openvpn_vpnid_used($vpnid))
141
		$vpnid++;
142

    
143
	return $vpnid;
144
}
145

    
146
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
147
	global $config;
148

    
149
	if (is_array($config['openvpn']['openvpn-server'])) {
150
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
151
			if (isset($settings['disable']))
152
				continue;
153

    
154
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
155
				continue;
156

    
157
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
158
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
159
				return $settings['vpnid'];
160
		}
161
	}
162

    
163
	if (is_array($config['openvpn']['openvpn-client'])) {
164
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
165
			if (isset($settings['disable']))
166
				continue;
167

    
168
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
169
				continue;
170

    
171
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
172
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
173
				return $settings['vpnid'];
174
		}
175
	}
176

    
177
	return 0;
178
}
179

    
180
function openvpn_port_next($prot, $interface = "wan") {
181

    
182
	$port = 1194;
183
	while(openvpn_port_used($prot, $interface, $port))
184
		$port++;
185
	while(openvpn_port_used($prot, "any", $port))
186
		$port++;
187

    
188
	return $port;
189
}
190

    
191
function openvpn_get_cipherlist() {
192

    
193
	$ciphers = array();
194
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
195
	$cipher_lines = explode("\n", trim($cipher_out));
196
	sort($cipher_lines);
197
	foreach ($cipher_lines as $line) {
198
		$words = explode(' ', $line);
199
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
200
	}
201
	$ciphers["none"] = gettext("None (No Encryption)");
202
	return $ciphers;
203
}
204

    
205
function openvpn_get_digestlist() {
206

    
207
	$digests = array();
208
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
209
	$digest_lines = explode("\n", trim($digest_out));
210
	sort($digest_lines);
211
	foreach ($digest_lines as $line) {
212
		$words = explode(' ', $line);
213
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
214
	}
215
	$digests["none"] = gettext("None (No Authentication)");
216
	return $digests;
217
}
218

    
219
function openvpn_get_engines() {
220
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
221
	exec("/usr/local/bin/openssl engine -t -c", $openssl_engine_output);
222
	$openssl_engine_output = implode("\n", $openssl_engine_output);
223
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
224
	$openssl_engine_output = explode("\n", $openssl_engine_output);
225

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

    
250
function openvpn_validate_engine($engine) {
251
	$engines = openvpn_get_engines();
252
	return array_key_exists($engine, $engines);
253
}
254

    
255
function openvpn_validate_host($value, $name) {
256
	$value = trim($value);
257
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
258
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
259
	return false;
260
}
261

    
262
function openvpn_validate_port($value, $name) {
263
	$value = trim($value);
264
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
265
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
266
	return false;
267
}
268

    
269
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
270
	$value = trim($value);
271
	$error = false;
272
	if (empty($value))
273
		return false;
274
	$networks = explode(',', $value);
275

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

    
279
	foreach ($networks as $network) {
280
		if ($ipproto == "ipv4")
281
			$error = !openvpn_validate_cidr_ipv4($network);
282
		else
283
			$error = !openvpn_validate_cidr_ipv6($network);
284
		if ($error)
285
			break;
286
	}
287

    
288
	if ($error)
289
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
290
	else
291
		return false;
292
}
293

    
294
function openvpn_validate_cidr_ipv4($value) {
295
	$value = trim($value);
296
	if (!empty($value)) {
297
		list($ip, $mask) = explode('/', $value);
298
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
299
			return false;
300
	}
301
	return true;
302
}
303

    
304
function openvpn_validate_cidr_ipv6($value) {
305
	$value = trim($value);
306
	if (!empty($value)) {
307
		list($ipv6, $prefix) = explode('/', $value);
308
		if (empty($prefix))
309
			$prefix = "128";
310
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0))
311
			return false;
312
	}
313
	return true;
314
}
315

    
316
function openvpn_add_dhcpopts(& $settings, & $conf) {
317

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

    
321
	if (!empty($settings['dns_server1']))
322
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
323
	if (!empty($settings['dns_server2']))
324
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
325
	if (!empty($settings['dns_server3']))
326
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
327
	if (!empty($settings['dns_server4']))
328
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
329

    
330
	if (!empty($settings['ntp_server1']))
331
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
332
	if (!empty($settings['ntp_server2']))
333
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
334

    
335
	if ($settings['netbios_enable']) {
336

    
337
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
338
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
339
		if (!empty($settings['dhcp_nbtscope'])) 
340
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
341

    
342
		if (!empty($settings['wins_server1']))
343
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
344
		if (!empty($settings['wins_server2']))
345
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
346

    
347
		if (!empty($settings['nbdd_server1']))
348
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
349
	}
350

    
351
	if ($settings['gwredir']) 
352
		$conf .= "push \"redirect-gateway def1\"\n";
353
}
354

    
355
function openvpn_add_custom(& $settings, & $conf) {
356

    
357
	if ($settings['custom_options']) {
358

    
359
		$options = explode(';', $settings['custom_options']);
360

    
361
		if (is_array($options)) {
362
			foreach ($options as $option)
363
				$conf .= "$option\n";
364
		} else
365
			$conf .= "{$settings['custom_options']}\n";
366
	}
367
}
368

    
369
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
370
	global $g;
371

    
372
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
373
	openvpn_create_dirs();
374
	file_put_contents($fpath, base64_decode($data));
375
	//chown($fpath, 'nobody');
376
	//chgrp($fpath, 'nobody');
377
	@chmod($fpath, 0600);
378

    
379
	$conf .= "{$directive} {$fpath} {$opt}\n";
380
}
381

    
382
function openvpn_reconfigure($mode, $settings) {
383
	global $g, $config;
384

    
385
	if (empty($settings))
386
		return;
387
	if (isset($settings['disable'])) 
388
		return;
389
	openvpn_create_dirs();
390
	/*
391
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
392
	 * we use a vpnid number which is allocated for a particular client
393
	 * or server configuration. ( see openvpn_vpnid_next() )
394
	 */
395

    
396
	$vpnid = $settings['vpnid'];
397
	$mode_id = $mode.$vpnid;
398

    
399
	if (isset($settings['dev_mode']))
400
		$tunname = "{$settings['dev_mode']}{$vpnid}";
401
	else {	/* defaults to tun */
402
		$tunname = "tun{$vpnid}";
403
		$settings['dev_mode'] = "tun";
404
	}
405

    
406
	if ($mode == "server")
407
		$devname = "ovpns{$vpnid}";
408
	else
409
		$devname = "ovpnc{$vpnid}";
410

    
411
	/* is our device already configured */
412
	if (mwexec("/sbin/ifconfig {$devname}", true)) {
413

    
414
		/* create the tap device if required */
415
		if (!file_exists("/dev/{$tunname}"))
416
			exec("/sbin/ifconfig {$tunname} create");
417

    
418
		/* rename the device */
419
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
420

    
421
		/* add the device to the openvpn group */
422
		mwexec("/sbin/ifconfig {$devname} group openvpn");
423
	}
424

    
425
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
426
	$proto = strtolower($settings['protocol']);
427
	if (substr($settings['protocol'], 0, 3) == "TCP")
428
			$proto = "{$proto}-{$mode}";
429
	$dev_mode = $settings['dev_mode'];
430
	$cipher = $settings['crypto'];
431
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
432
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
433

    
434
	$interface = get_failover_interface($settings['interface']);
435
	$ipaddr = $settings['ipaddr'];
436
	$ipaddrv6 = $settings['ipaddrv6'];
437

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

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

    
488
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
489
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
490
		$conf .= "local {$iface_ip}\n";
491
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
492
		$conf .= "local {$iface_ipv6}\n";
493
	}
494

    
495
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
496
		$conf .= "engine {$settings['engine']}\n";
497

    
498
	// server specific settings
499
	if ($mode == 'server') {
500

    
501
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
502
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
503
		$mask = gen_subnet_mask($cidr);
504

    
505
		// configure tls modes
506
		switch($settings['mode']) {
507
			case 'p2p_tls':
508
			case 'server_tls':
509
			case 'server_user':
510
			case 'server_tls_user':
511
				$conf .= "tls-server\n";
512
				break;
513
		}
514

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

    
569
		// configure user auth modes
570
		switch($settings['mode']) {
571
			case 'server_user':
572
				$conf .= "client-cert-not-required\n";
573
			case 'server_tls_user':
574
				/* username-as-common-name is not compatible with server-bridge */
575
				if (stristr($conf, "server-bridge") === false)
576
					$conf .= "username-as-common-name\n";
577
				if (!empty($settings['authmode'])) {
578
					$authcfgs = explode(",", $settings['authmode']);
579
					$sed = "\$authmodes=array(";
580
					$firstsed = 0;
581
					foreach ($authcfgs as $authcfg) {
582
						if ($firstsed > 0)
583
							$sed .= ",";
584
						$firstsed = 1;
585
						$sed .= "\"{$authcfg}\"";
586
					}
587
					$sed .= ");\\\n";
588
					if ($settings['strictusercn'])
589
						$sed .= "\$strictusercn = true;";
590
					$sed .= " \$modeid = \"{$mode_id}\";";
591
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
592
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
593
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
594
				}
595
				break;
596
		}
597
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls')))
598
			$settings['cert_depth'] = 1;
599
		if (is_numeric($settings['cert_depth'])) {
600
			$sed = "";
601
			$cert = lookup_cert($settings['certref']);
602
			$servercn = cert_get_cn($cert['crt']);
603
			$sed .= "\$server_cn = \"{$servercn}\";\\\n";
604
			$sed .= "\$allowed_depth = {$settings['cert_depth']};\\\n";
605
			mwexec("/bin/cat /etc/inc/openvpn.tls-verify.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
606
			mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
607
			$conf .= "tls-verify {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php\n";
608
		}
609

    
610
		// The local port to listen on
611
		$conf .= "lport {$settings['local_port']}\n";
612

    
613
		// The management port to listen on
614
		// Use unix socket to overcome the problem on any type of server
615
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
616
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
617

    
618
		if ($settings['maxclients'])
619
			$conf .= "max-clients {$settings['maxclients']}\n";
620

    
621
		// Can we push routes
622
		if ($settings['local_network']) {
623
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
624
		}
625
		if ($settings['local_networkv6']) {
626
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
627
		}
628

    
629
		switch($settings['mode']) {
630
			case 'server_tls':
631
			case 'server_user':
632
			case 'server_tls_user':
633
				// Configure client dhcp options
634
				openvpn_add_dhcpopts($settings, $conf);
635
				if ($settings['client2client'])
636
					$conf .= "client-to-client\n";
637
				break;
638
		}
639
		if (isset($settings['duplicate_cn']))
640
			$conf .= "duplicate-cn\n";
641
	}
642

    
643
	// client specific settings
644

    
645
	if ($mode == 'client') {
646

    
647
		// configure p2p mode
648
		switch($settings['mode']) {
649
			case 'p2p_tls':
650
				$conf .= "tls-client\n";
651
			case 'shared_key':
652
				$conf .= "client\n";
653
				break;
654
		}
655

    
656
		// If there is no bind option at all (ip and/or port), add "nobind" directive
657
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
658
		//  ensure a random source port.
659
		if ((empty($iface_ip)) && (!$settings['local_port']))
660
			$conf .= "nobind\n";
661
		elseif ($settings['local_port'])
662
			$conf .= "lport {$settings['local_port']}\n";
663
		else
664
			$conf .= "lport 0\n";
665

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

    
669
		// The remote server
670
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
671

    
672
		if (!empty($settings['use_shaper']))
673
			$conf .= "shaper {$settings['use_shaper']}\n";
674

    
675
		if (!empty($settings['tunnel_network'])) {
676
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
677
			$mask = gen_subnet_mask($mask);
678
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
679
			if ($settings['dev_mode'] == 'tun')
680
				$conf .= "ifconfig {$ip2} {$ip1}\n";
681
			else
682
				$conf .= "ifconfig {$ip2} {$mask}\n";
683
		}
684

    
685
		if (!empty($settings['tunnel_networkv6'])) {
686
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
687
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
688
			if ($settings['dev_mode'] == 'tun')
689
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
690
			else
691
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
692
		}
693

    
694
		if ($settings['proxy_addr']) {
695
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
696
			if ($settings['proxy_authtype'] != "none") {
697
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
698
				$proxypas = "{$settings['proxy_user']}\n";
699
				$proxypas .= "{$settings['proxy_passwd']}\n";
700
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
701
			}
702
			$conf .= " \n";
703
		}
704
	}
705

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

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

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

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

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

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

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

    
764
	openvpn_add_custom($settings, $conf);
765

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
862
	/* remove the configuration files */
863
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
864
}
865

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

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

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

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

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

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

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

    
906
	openvpn_add_dhcpopts($settings, $conf);
907

    
908
	if ($settings['gwredir'])
909
		$conf .= "push \"redirect-gateway def1\"\n";
910

    
911
	openvpn_add_custom($settings, $conf);
912

    
913
	file_put_contents($fpath, $conf);
914
	chown($fpath, 'nobody');
915
	chgrp($fpath, 'nobody');
916
}
917

    
918
function openvpn_delete_csc(& $settings) {
919
	global $g, $config;
920

    
921
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
922
	unlink_if_exists($fpath);
923
}
924

    
925
// Resync the configuration and restart the VPN
926
function openvpn_resync($mode, $settings) {
927
	openvpn_reconfigure($mode, $settings);
928
	openvpn_restart($mode, $settings);
929
}
930

    
931
// Resync and restart all VPNs
932
function openvpn_resync_all($interface = "") {
933
	global $g, $config;
934

    
935
	if ($g['platform'] == 'jail')
936
		return;
937
	openvpn_create_dirs();
938

    
939
	if (!is_array($config['openvpn']))
940
		$config['openvpn'] = array();
941

    
942
/*
943
	if (!$config['openvpn']['dh-parameters']) {
944
		echo "Configuring OpenVPN Parameters ...\n";
945
		$dh_parameters = openvpn_create_dhparams(1024);
946
		$dh_parameters = base64_encode($dh_parameters);
947
		$config['openvpn']['dh-parameters'] = $dh_parameters;
948
		write_config("OpenVPN DH parameters");
949
	}
950

    
951
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
952
	if (!file_exists($path_ovdh)) {
953
		$dh_parameters = $config['openvpn']['dh-parameters'];
954
		$dh_parameters = base64_decode($dh_parameters);
955
		file_put_contents($path_ovdh, $dh_parameters);
956
	}
957
*/
958
	if ($interface <> "")
959
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
960
	else
961
		log_error("Resyncing OpenVPN instances."); 
962

    
963
	if (is_array($config['openvpn']['openvpn-server'])) {
964
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
965
			if ($interface <> "" && $interface != $settings['interface'])
966
				continue;
967
			openvpn_resync('server', $settings);
968
		}
969
	}
970

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

    
979
	if (is_array($config['openvpn']['openvpn-csc']))
980
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
981
			openvpn_resync_csc($settings);
982

    
983
}
984

    
985
// Resync and restart all VPNs using a gateway group.
986
function openvpn_resync_gwgroup($gwgroupname = "") {
987
	global $g, $config;
988

    
989
	if ($gwgroupname <> "") {
990
		if (is_array($config['openvpn']['openvpn-server'])) {
991
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
992
				if ($gwgroupname == $settings['interface']) {
993
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
994
					openvpn_resync('server', $settings);
995
				}
996
			}
997
		}
998

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

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

    
1010
	} else
1011
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1012
}
1013

    
1014
function openvpn_get_active_servers($type="multipoint") {
1015
	global $config, $g;
1016

    
1017
	$servers = array();
1018
	if (is_array($config['openvpn']['openvpn-server'])) {
1019
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1020
			if (empty($settings) || isset($settings['disable']))
1021
				continue;
1022

    
1023
			$prot = $settings['protocol'];
1024
			$port = $settings['local_port'];
1025
	
1026
			$server = array();
1027
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1028
			$server['mode'] = $settings['mode'];
1029
			if ($settings['description'])
1030
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1031
			else
1032
				$server['name'] = "Server {$prot}:{$port}";
1033
			$server['conns'] = array();
1034
			$server['vpnid'] = $settings['vpnid'];
1035
			$server['mgmt'] = "server{$server['vpnid']}";
1036
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1037
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1038

    
1039
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1040
				$servers[] = openvpn_get_client_status($server, $socket);
1041
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1042
				$servers[] = openvpn_get_server_status($server, $socket);
1043

    
1044
		}
1045
	}
1046
	return $servers;
1047
}
1048

    
1049
function openvpn_get_server_status($server, $socket) {
1050
	$errval;
1051
	$errstr;
1052
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1053
	if ($fp) {
1054
		stream_set_timeout($fp, 1);
1055

    
1056
		/* send our status request */
1057
		fputs($fp, "status 2\n");
1058

    
1059
		/* recv all response lines */
1060
		while (!feof($fp)) {
1061

    
1062
			/* read the next line */
1063
			$line = fgets($fp, 1024);
1064

    
1065
			$info = stream_get_meta_data($fp);
1066
			if ($info['timed_out'])
1067
				break;
1068

    
1069
			/* parse header list line */
1070
			if (strstr($line, "HEADER"))
1071
				continue;
1072

    
1073
			/* parse end of output line */
1074
			if (strstr($line, "END") || strstr($line, "ERROR"))
1075
				break;
1076

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

    
1101
		/* cleanup */
1102
		fclose($fp);
1103
	} else {
1104
		$conn = array();
1105
		$conn['common_name'] = "[error]";
1106
		$conn['remote_host'] = "Unable to contact daemon";
1107
		$conn['virtual_addr'] = "Service not running?";
1108
		$conn['bytes_recv'] = 0;
1109
		$conn['bytes_sent'] = 0;
1110
		$conn['connect_time'] = 0;
1111
		$server['conns'][] = $conn;
1112
	}
1113
	return $server;
1114
}
1115

    
1116
function openvpn_get_active_clients() {
1117
	global $config, $g;
1118

    
1119
	$clients = array();
1120
	if (is_array($config['openvpn']['openvpn-client'])) {
1121
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1122
	
1123
			if (empty($settings) || isset($settings['disable']))
1124
				continue;
1125

    
1126
			$prot = $settings['protocol'];
1127
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1128
	
1129
			$client = array();
1130
			$client['port'] = $settings['local_port'];
1131
			if ($settings['description'])
1132
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1133
			else
1134
				$client['name'] = "Client {$prot}{$port}";
1135
	
1136
			$client['vpnid'] = $settings['vpnid'];
1137
			$client['mgmt'] = "client{$client['vpnid']}";
1138
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1139
			$client['status']="down";
1140

    
1141
			$clients[] = openvpn_get_client_status($client, $socket);
1142
		}
1143
	}
1144
	return $clients;
1145
}
1146

    
1147
function openvpn_get_client_status($client, $socket) {
1148
	$errval;
1149
	$errstr;
1150
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1151
	if ($fp) {
1152
		stream_set_timeout($fp, 1);
1153
		/* send our status request */
1154
		fputs($fp, "state 1\n");
1155

    
1156
		/* recv all response lines */
1157
		while (!feof($fp)) {
1158
			/* read the next line */
1159
			$line = fgets($fp, 1024);
1160

    
1161
			$info = stream_get_meta_data($fp);
1162
			if ($info['timed_out'])
1163
				break;
1164

    
1165
			/* Get the client state */
1166
			if (strstr($line,"CONNECTED")) {
1167
				$client['status']="up";
1168
				$list = explode(",", $line);
1169

    
1170
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1171
				$client['virtual_addr']  = $list[3];
1172
				$client['remote_host'] = $list[4];
1173
			}
1174
			if (strstr($line,"CONNECTING")) {
1175
				$client['status']="connecting";
1176
			}
1177
			if (strstr($line,"ASSIGN_IP")) {
1178
				$client['status']="waiting";
1179
				$list = explode(",", $line);
1180

    
1181
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1182
				$client['virtual_addr']  = $list[3];
1183
			}
1184
			if (strstr($line,"RECONNECTING")) {
1185
				$client['status']="reconnecting";
1186
				$list = explode(",", $line);
1187

    
1188
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1189
				$client['status'] .= "; " . $list[2];
1190
			}
1191
			/* parse end of output line */
1192
			if (strstr($line, "END") || strstr($line, "ERROR"))
1193
				break;
1194
		}
1195

    
1196
		/* If up, get read/write stats */
1197
		if (strcmp($client['status'], "up") == 0) {
1198
			fputs($fp, "status 2\n");
1199
			/* recv all response lines */
1200
			while (!feof($fp)) {
1201
				/* read the next line */
1202
				$line = fgets($fp, 1024);
1203

    
1204
				$info = stream_get_meta_data($fp);
1205
				if ($info['timed_out'])
1206
					break;
1207

    
1208
				if (strstr($line,"TCP/UDP read bytes")) {
1209
					$list = explode(",", $line);
1210
					$client['bytes_recv'] = $list[1];
1211
				}
1212

    
1213
				if (strstr($line,"TCP/UDP write bytes")) {
1214
					$list = explode(",", $line);
1215
					$client['bytes_sent'] = $list[1];
1216
				}
1217

    
1218
				/* parse end of output line */
1219
				if (strstr($line, "END"))
1220
					break;
1221
			}
1222
		}
1223

    
1224
		fclose($fp);
1225

    
1226
	} else {
1227
		$DisplayNote=true;
1228
		$client['remote_host'] = "Unable to contact daemon";
1229
		$client['virtual_addr'] = "Service not running?";
1230
		$client['bytes_recv'] = 0;
1231
		$client['bytes_sent'] = 0;
1232
		$client['connect_time'] = 0;
1233
	}
1234
	return $client;
1235
}
1236

    
1237
function openvpn_refresh_crls() {
1238
	global $g, $config;
1239

    
1240
	openvpn_create_dirs();
1241

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

    
1267
function openvpn_create_dirs() {
1268
	global $g;
1269
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1270
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1271
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1272
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1273
}
1274

    
1275
function openvpn_get_interface_ip($ip, $mask) {
1276
	$baselong = ip2long32($ip) & ip2long($mask);
1277
	$ip1 = long2ip32($baselong + 1);
1278
	$ip2 = long2ip32($baselong + 2);
1279
	return array($ip1, $ip2);
1280
}
1281

    
1282
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1283
	$basev6 = gen_subnetv6($ipv6, $prefix);
1284
	// Is there a better way to do this math?
1285
	$ipv6_arr = explode(':', $basev6);
1286
	$last = hexdec(array_pop($ipv6_arr));
1287
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1288
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1289
	return array($ipv6_1, $ipv6_2);
1290
}
1291

    
1292
function openvpn_clear_route($mode, $settings) {
1293
	if (empty($settings['tunnel_network']))
1294
		return;
1295
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1296
	$mask = gen_subnet_mask($cidr);
1297
	$clear_route = false;
1298

    
1299
	switch($settings['mode']) {
1300
		case 'shared_key':
1301
			$clear_route = true;
1302
			break;
1303
		case 'p2p_tls':
1304
		case 'p2p_shared_key':
1305
			if ($cidr == 30)
1306
				$clear_route = true;
1307
			break;
1308
	}
1309

    
1310
	if ($clear_route && !empty($ip) && !empty($mask)) {
1311
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1312
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1313
		/* XXX: Family for route? */
1314
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1315
	}
1316
}
1317

    
1318
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false) {
1319
	$routes = "";
1320
	if (empty($value))
1321
		return "";
1322
	$networks = explode(',', $value);
1323

    
1324
	foreach ($networks as $network) {
1325
		if ($ipproto == "ipv4")
1326
			$route = openvpn_gen_route_ipv4($network);
1327
		else
1328
			$route = openvpn_gen_route_ipv6($network);
1329

    
1330
		if ($push)
1331
			$routes .= "push \"{$route}\"\n";
1332
		else
1333
			$routes .= "{$route}\n";
1334
	}
1335
	return $routes;
1336
}
1337

    
1338
function openvpn_gen_route_ipv4($network) {
1339
	list($ip, $mask) = explode('/', trim($network));
1340
	$mask = gen_subnet_mask($mask);
1341
	return "route $ip $mask";
1342
}
1343

    
1344
function openvpn_gen_route_ipv6($network) {
1345
	list($ipv6, $prefix) = explode('/', trim($network));
1346
	if (empty($prefix))
1347
		$prefix = "128";
1348
	return "route-ipv6 ${ipv6}/${prefix}";
1349
}
1350

    
1351
function openvpn_get_settings($mode, $vpnid) {
1352
	global $config;
1353

    
1354
	if (is_array($config['openvpn']['openvpn-server'])) {
1355
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1356
			if (isset($settings['disable']))
1357
				continue;
1358

    
1359
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1360
				return $settings;
1361
		}
1362
	}
1363

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

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

    
1374
	return array();
1375
}
1376

    
1377
function openvpn_restart_by_vpnid($mode, $vpnid) {
1378
	$settings = openvpn_get_settings($mode, $vpnid);
1379
	openvpn_restart($mode, $settings);
1380
}
1381

    
1382
?>
(37-37/66)