Project

General

Profile

Download (37.3 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
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
53

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

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

    
69
$openvpn_dh_lengths = array(
70
	1024, 2048, 4096 );
71

    
72
$openvpn_cert_depths = array(
73
	1 => "One (Client+Server)",
74
	2 => "Two (Client+Intermediate+Server)",
75
	3 => "Three (Client+2xIntermediate+Server)",
76
	4 => "Four (Client+3xIntermediate+Server)",
77
	5 => "Five (Client+4xIntermediate+Server)"
78
);
79

    
80
$openvpn_server_modes = array(
81
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
82
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
83
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
84
	'server_user' => gettext("Remote Access ( User Auth )"),
85
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
86

    
87
$openvpn_client_modes = array(
88
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
89
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )") );
90

    
91
function openvpn_create_key() {
92

    
93
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
94
	if (!$fp)
95
		return false;
96

    
97
	$rslt = stream_get_contents($fp);
98
	pclose($fp);
99

    
100
	return $rslt;
101
}
102

    
103
function openvpn_create_dhparams($bits) {
104

    
105
	$fp = popen("/usr/local/bin/openssl dhparam {$bits} 2>/dev/null", "r");
106
	if (!$fp)
107
		return false;
108

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

    
112
	return $rslt;
113
}
114

    
115
function openvpn_vpnid_used($vpnid) {
116
	global $config;
117

    
118
	if (is_array($config['openvpn']['openvpn-server']))
119
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
120
			if ($vpnid == $settings['vpnid'])
121
				return true;
122

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

    
128
	return false;
129
}
130

    
131
function openvpn_vpnid_next() {
132

    
133
	$vpnid = 1;
134
	while(openvpn_vpnid_used($vpnid))
135
		$vpnid++;
136

    
137
	return $vpnid;
138
}
139

    
140
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
141
	global $config;
142

    
143
	if (is_array($config['openvpn']['openvpn-server'])) {
144
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
145
			if (isset($settings['disable']))
146
				continue;
147

    
148
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
149
				continue;
150

    
151
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
152
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
153
				return $settings['vpnid'];
154
		}
155
	}
156

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

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

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

    
171
	return 0;
172
}
173

    
174
function openvpn_port_next($prot, $interface = "wan") {
175

    
176
	$port = 1194;
177
	while(openvpn_port_used($prot, $interface, $port))
178
		$port++;
179
	while(openvpn_port_used($prot, "any", $port))
180
		$port++;
181

    
182
	return $port;
183
}
184

    
185
function openvpn_get_cipherlist() {
186

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

    
199
function openvpn_get_engines() {
200
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
201
	exec("/usr/local/bin/openssl engine -t -c", $openssl_engine_output);
202
	$openssl_engine_output = implode("\n", $openssl_engine_output);
203
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
204
	$openssl_engine_output = explode("\n", $openssl_engine_output);
205

    
206
	foreach ($openssl_engine_output as $oeo) {
207
		$keep = true;
208
		$details = explode("|", $oeo);
209
		$engine = array_shift($details);
210
		$linematch = array();
211
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
212
		foreach ($details as $dt) {
213
			if (strpos($dt, "unavailable") !== FALSE)
214
				$keep = false;
215
			if (strpos($dt, "available") !== FALSE)
216
				continue;
217
			if (strpos($dt, "[") !== FALSE)
218
				$ciphers = trim($dt, "[]");
219
		}
220
		if (!empty($ciphers))
221
			$ciphers = " - " . $ciphers;
222
		if (strlen($ciphers) > 60)
223
			$ciphers = substr($ciphers, 0, 60) . " ... ";
224
		if ($keep)
225
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
226
	}
227
	return $openssl_engines;
228
}
229

    
230
function openvpn_validate_engine($engine) {
231
	$engines = openvpn_get_engines();
232
	return array_key_exists($engine, $engines);
233
}
234

    
235
function openvpn_validate_host($value, $name) {
236
	$value = trim($value);
237
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
238
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
239
	return false;
240
}
241

    
242
function openvpn_validate_port($value, $name) {
243
	$value = trim($value);
244
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
245
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
246
	return false;
247
}
248

    
249
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
250
	$value = trim($value);
251
	$error = false;
252
	if (empty($value))
253
		return false;
254
	$networks = explode(',', $value);
255

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

    
259
	foreach ($networks as $network) {
260
		if ($ipproto == "ipv4")
261
			$error = !openvpn_validate_cidr_ipv4($network);
262
		else
263
			$error = !openvpn_validate_cidr_ipv6($network);
264
		if ($error)
265
			break;
266
	}
267

    
268
	if ($error)
269
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
270
	else
271
		return false;
272
}
273

    
274
function openvpn_validate_cidr_ipv4($value) {
275
	$value = trim($value);
276
	if (!empty($value)) {
277
		list($ip, $mask) = explode('/', $value);
278
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
279
			return false;
280
	}
281
	return true;
282
}
283

    
284
function openvpn_validate_cidr_ipv6($value) {
285
	$value = trim($value);
286
	if (!empty($value)) {
287
		list($ipv6, $prefix) = explode('/', $value);
288
		if (empty($prefix))
289
			$prefix = "128";
290
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0))
291
			return false;
292
	}
293
	return true;
294
}
295

    
296
function openvpn_add_dhcpopts(& $settings, & $conf) {
297

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

    
301
	if (!empty($settings['dns_server1']))
302
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
303
	if (!empty($settings['dns_server2']))
304
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
305
	if (!empty($settings['dns_server3']))
306
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
307
	if (!empty($settings['dns_server4']))
308
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
309

    
310
	if (!empty($settings['ntp_server1']))
311
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
312
	if (!empty($settings['ntp_server2']))
313
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
314

    
315
	if ($settings['netbios_enable']) {
316

    
317
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
318
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
319
		if (!empty($settings['dhcp_nbtscope'])) 
320
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
321

    
322
		if (!empty($settings['wins_server1']))
323
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
324
		if (!empty($settings['wins_server2']))
325
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
326

    
327
		if (!empty($settings['nbdd_server1']))
328
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
329
	}
330

    
331
	if ($settings['gwredir']) 
332
		$conf .= "push \"redirect-gateway def1\"\n";
333
}
334

    
335
function openvpn_add_custom(& $settings, & $conf) {
336

    
337
	if ($settings['custom_options']) {
338

    
339
		$options = explode(';', $settings['custom_options']);
340

    
341
		if (is_array($options)) {
342
			foreach ($options as $option)
343
				$conf .= "$option\n";
344
		} else
345
			$conf .= "{$settings['custom_options']}\n";
346
	}
347
}
348

    
349
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
350
	global $g;
351

    
352
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
353
	openvpn_create_dirs();
354
	file_put_contents($fpath, base64_decode($data));
355
	//chown($fpath, 'nobody');
356
	//chgrp($fpath, 'nobody');
357
	@chmod($fpath, 0600);
358

    
359
	$conf .= "{$directive} {$fpath} {$opt}\n";
360
}
361

    
362
function openvpn_reconfigure($mode, $settings) {
363
	global $g, $config;
364

    
365
	if (empty($settings))
366
		return;
367
	if (isset($settings['disable'])) 
368
		return;
369
	openvpn_create_dirs();
370
	/*
371
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
372
	 * we use a vpnid number which is allocated for a particular client
373
	 * or server configuration. ( see openvpn_vpnid_next() )
374
	 */
375

    
376
	$vpnid = $settings['vpnid'];
377
	$mode_id = $mode.$vpnid;
378

    
379
	if (isset($settings['dev_mode']))
380
		$tunname = "{$settings['dev_mode']}{$vpnid}";
381
	else {	/* defaults to tun */
382
		$tunname = "tun{$vpnid}";
383
		$settings['dev_mode'] = "tun";
384
	}
385

    
386
	if ($mode == "server")
387
		$devname = "ovpns{$vpnid}";
388
	else
389
		$devname = "ovpnc{$vpnid}";
390

    
391
	/* is our device already configured */
392
	if (mwexec("/sbin/ifconfig {$devname}", true)) {
393

    
394
		/* create the tap device if required */
395
		if (!file_exists("/dev/{$tunname}"))
396
			exec("/sbin/ifconfig {$tunname} create");
397

    
398
		/* rename the device */
399
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
400

    
401
		/* add the device to the openvpn group */
402
		mwexec("/sbin/ifconfig {$devname} group openvpn");
403
	}
404

    
405
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
406
	$proto = strtolower($settings['protocol']);
407
	if (substr($settings['protocol'], 0, 3) == "TCP")
408
			$proto = "{$proto}-{$mode}";
409
	$dev_mode = $settings['dev_mode'];
410
	$cipher = $settings['crypto'];
411

    
412
	$interface = get_failover_interface($settings['interface']);
413
	$ipaddr = $settings['ipaddr'];
414
	$ipaddrv6 = $settings['ipaddrv6'];
415

    
416
	// If a specific ip address (VIP) is requested, use it.
417
	// Otherwise, if a specific interface is requested, use it
418
	// If "any" interface was selected, local directive will be ommited.
419
	if (is_ipaddrv4($ipaddr)) {
420
		$iface_ip=$ipaddr;
421
	} else {
422
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
423
			$iface_ip=get_interface_ip($interface);
424
		}
425
	}
426
	if (is_ipaddrv6($ipaddrv6)) {
427
		$iface_ipv6=$ipaddrv6;
428
	} else {
429
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
430
			$iface_ipv6=get_interface_ipv6($interface);
431
		}
432
	}
433

    
434
	$conf  = "dev {$devname}\n";
435
	$conf .= "dev-type {$settings['dev_mode']}\n";
436
	switch($settings['dev_mode']) {
437
		case "tun":
438
			$conf .= "tun-ipv6\n";
439
			break;
440
	}
441
	$conf .= "dev-node /dev/{$tunname}\n";
442
	$conf .= "writepid {$pfile}\n";
443
	$conf .= "#user nobody\n";
444
	$conf .= "#group nobody\n";
445
	$conf .= "script-security 3\n";
446
	$conf .= "daemon\n";
447
	$conf .= "keepalive 10 60\n";
448
	$conf .= "ping-timer-rem\n";
449
	$conf .= "persist-tun\n";
450
	$conf .= "persist-key\n";
451
	$conf .= "proto {$proto}\n";
452
	$conf .= "cipher {$cipher}\n";
453
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
454
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
455
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
456
		switch($settings['mode']) {
457
			case 'server_user':
458
			case 'server_tls_user':
459
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
460
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
461
				break;
462
		}
463
	}
464

    
465
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
466
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
467
		$conf .= "local {$iface_ip}\n";
468
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
469
		$conf .= "local {$iface_ipv6}\n";
470
	}
471

    
472
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
473
		$conf .= "engine {$settings['engine']}\n";
474

    
475
	// server specific settings
476
	if ($mode == 'server') {
477

    
478
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
479
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
480
		$mask = gen_subnet_mask($cidr);
481

    
482
		// configure tls modes
483
		switch($settings['mode']) {
484
			case 'p2p_tls':
485
			case 'server_tls':
486
			case 'server_user':
487
			case 'server_tls_user':
488
				$conf .= "tls-server\n";
489
				break;
490
		}
491

    
492
		// configure p2p/server modes
493
		switch($settings['mode']) {
494
			case 'p2p_tls':
495
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
496
				//  use the server directive. It works for a single client without it.
497
				//  See ticket #1417
498
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
499
					$conf .= "server {$ip} {$mask}\n";
500
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
501
					if(is_ipaddr($ipv6))
502
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
503
				}
504
			case 'p2p_shared_key':
505
				if (!empty($ip) && !empty($mask)) {
506
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
507
					if ($settings['dev_mode'] == 'tun')
508
						$conf .= "ifconfig {$ip1} {$ip2}\n";
509
					else
510
						$conf .= "ifconfig {$ip1} {$mask}\n";
511
				}
512
				if (!empty($ipv6) && !empty($prefix)) {
513
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
514
					if ($settings['dev_mode'] == 'tun')
515
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
516
					else
517
						$conf .= "ifconfig {$ipv6_1} {$prefix}\n";
518
				}
519
				break;
520
			case 'server_tls':
521
			case 'server_user':
522
			case 'server_tls_user':
523
				if (!empty($ip) && !empty($mask)) {
524
					$conf .= "server {$ip} {$mask}\n";
525
					if(is_ipaddr($ipv6))
526
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
527
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
528
				} else {
529
					if ($settings['serverbridge_dhcp']) {
530
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
531
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
532
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
533
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
534
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
535
							} else {
536
								$conf .= "mode server\n";
537
							}
538
						} else {
539
							$conf .= "mode server\n";
540
						}
541
					}
542
				}
543
				break;
544
		}
545

    
546
		// configure user auth modes
547
		switch($settings['mode']) {
548
			case 'server_user':
549
				$conf .= "client-cert-not-required\n";
550
			case 'server_tls_user':
551
				/* username-as-common-name is not compatible with server-bridge */
552
				if (stristr($conf, "server-bridge") === false)
553
					$conf .= "username-as-common-name\n";
554
				if (!empty($settings['authmode'])) {
555
					$authcfgs = explode(",", $settings['authmode']);
556
					$sed = "\$authmodes=array(";
557
					$firstsed = 0;
558
					foreach ($authcfgs as $authcfg) {
559
						if ($firstsed > 0)
560
							$sed .= ",";
561
						$firstsed = 1;
562
						$sed .= "\"{$authcfg}\"";
563
					}
564
					$sed .= ");\\\n";
565
					if ($settings['strictusercn'])
566
						$sed .= "\$strictusercn = true;";
567
					$sed .= " \$modeid = \"{$mode_id}\";";
568
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
569
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
570
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
571
				}
572
				break;
573
		}
574
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls')))
575
			$settings['cert_depth'] = 1;
576
		if (is_numeric($settings['cert_depth'])) {
577
			$sed = "";
578
			$cert = lookup_cert($settings['certref']);
579
			$servercn = cert_get_cn($cert['crt']);
580
			$sed .= "\$server_cn = \"{$servercn}\";\\\n";
581
			$sed .= "\$allowed_depth = {$settings['cert_depth']};\\\n";
582
			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");
583
			mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
584
			$conf .= "tls-verify {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php\n";
585
		}
586

    
587
		// The local port to listen on
588
		$conf .= "lport {$settings['local_port']}\n";
589

    
590
		// The management port to listen on
591
		// Use unix socket to overcome the problem on any type of server
592
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
593
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
594

    
595
		if ($settings['maxclients'])
596
			$conf .= "max-clients {$settings['maxclients']}\n";
597

    
598
		// Can we push routes
599
		if ($settings['local_network']) {
600
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
601
		}
602
		if ($settings['local_networkv6']) {
603
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
604
		}
605

    
606
		switch($settings['mode']) {
607
			case 'server_tls':
608
			case 'server_user':
609
			case 'server_tls_user':
610
				// Configure client dhcp options
611
				openvpn_add_dhcpopts($settings, $conf);
612
				if ($settings['client2client'])
613
					$conf .= "client-to-client\n";
614
				break;
615
		}
616
		if (isset($settings['duplicate_cn']))
617
			$conf .= "duplicate-cn\n";
618
	}
619

    
620
	// client specific settings
621

    
622
	if ($mode == 'client') {
623

    
624
		// configure p2p mode
625
		switch($settings['mode']) {
626
			case 'p2p_tls':
627
				$conf .= "tls-client\n";
628
			case 'shared_key':
629
				$conf .= "client\n";
630
				break;
631
		}
632

    
633
		// If there is no bind option at all (ip and/or port), add "nobind" directive
634
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
635
		//  ensure a random source port.
636
		if ((empty($iface_ip)) && (!$settings['local_port']))
637
			$conf .= "nobind\n";
638
		elseif ($settings['local_port'])
639
			$conf .= "lport {$settings['local_port']}\n";
640
		else
641
			$conf .= "lport 0\n";
642

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

    
646
		// The remote server
647
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
648

    
649
		if (!empty($settings['use_shaper']))
650
			$conf .= "shaper {$settings['use_shaper']}\n";
651

    
652
		if (!empty($settings['tunnel_network'])) {
653
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
654
			$mask = gen_subnet_mask($mask);
655
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
656
			if ($settings['dev_mode'] == 'tun')
657
				$conf .= "ifconfig {$ip2} {$ip1}\n";
658
			else
659
				$conf .= "ifconfig {$ip2} {$mask}\n";
660
		}
661

    
662
		if (!empty($settings['tunnel_networkv6'])) {
663
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
664
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
665
			if ($settings['dev_mode'] == 'tun')
666
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
667
			else
668
				$conf .= "ifconfig {$ipv6_2} {$prefix}\n";
669
		}
670

    
671
		if ($settings['proxy_addr']) {
672
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
673
			if ($settings['proxy_authtype'] != "none") {
674
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
675
				$proxypas = "{$settings['proxy_user']}\n";
676
				$proxypas .= "{$settings['proxy_passwd']}\n";
677
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
678
			}
679
			$conf .= " \n";
680
		}
681
	}
682

    
683
	// Add a remote network route if set, and only for p2p modes.
684
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
685
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
686
	}
687
	// Add a remote network route if set, and only for p2p modes.
688
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
689
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
690
	}
691

    
692
	// Write the settings for the keys
693
	switch($settings['mode']) {
694
		case 'p2p_shared_key':
695
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
696
			break;
697
		case 'p2p_tls':
698
		case 'server_tls':
699
		case 'server_tls_user':
700
		case 'server_user':
701
			$ca = lookup_ca($settings['caref']);
702
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
703
			$cert = lookup_cert($settings['certref']);
704
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
705
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
706
			if ($mode == 'server')
707
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
708
			if (!empty($settings['crlref'])) {
709
				$crl = lookup_crl($settings['crlref']);
710
				crl_update($crl);
711
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
712
			}
713
			if ($settings['tls']) {
714
				if ($mode == "server") 
715
					$tlsopt = 0;
716
				else
717
					$tlsopt = 1;
718
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
719
			}
720
			break;
721
	}
722

    
723
	if ($settings['compression'])
724
		$conf .= "comp-lzo\n";
725

    
726
	if ($settings['passtos'])
727
		$conf .= "passtos\n";
728

    
729
	if ($settings['resolve_retry'])
730
		$conf .= "resolv-retry infinite\n";
731

    
732
	if ($settings['dynamic_ip']) {
733
		$conf .= "persist-remote-ip\n";
734
		$conf .= "float\n";
735
	}
736

    
737
	if ($settings['topology_subnet']) {
738
		$conf .= "topology subnet\n";
739
	}
740

    
741
	openvpn_add_custom($settings, $conf);
742

    
743
	openvpn_create_dirs();
744
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
745
	file_put_contents($fpath, $conf);
746
	unset($conf);
747
	//chown($fpath, 'nobody');
748
	//chgrp($fpath, 'nobody');
749
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
750
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
751
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
752
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
753
}
754

    
755
function openvpn_restart($mode, $settings) {
756
	global $g, $config;
757

    
758
	$vpnid = $settings['vpnid'];
759
	$mode_id = $mode.$vpnid;
760

    
761
	/* kill the process if running */
762
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
763
	if (file_exists($pfile)) {
764

    
765
		/* read the pid file */
766
		$pid = rtrim(file_get_contents($pfile));
767
		unlink($pfile);
768

    
769
		/* send a term signal to the process */
770
		posix_kill($pid, SIGTERM);
771

    
772
		/* wait until the process exits */
773
		while(posix_kill($pid, 0))
774
			usleep(250000);
775
	}
776

    
777
	if (isset($settings['disable']))
778
		return;
779

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

    
784
	/* start the new process */
785
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
786
	openvpn_clear_route($mode, $settings);
787
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
788

    
789
	if (!$g['booting'])
790
		send_event("filter reload");
791
}
792

    
793
function openvpn_delete($mode, & $settings) {
794
	global $g, $config;
795

    
796
	$vpnid = $settings['vpnid'];
797
	$mode_id = $mode.$vpnid;
798

    
799
	if (isset($settings['dev_mode']))
800
		$tunname = "{$settings['dev_mode']}{$vpnid}";
801
	else {  /* defaults to tun */
802
		$tunname = "tun{$vpnid}";
803
	}
804

    
805
	if ($mode == "server")
806
		$devname = "ovpns{$vpnid}";
807
	else
808
		$devname = "ovpnc{$vpnid}";
809

    
810
	/* kill the process if running */
811
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
812
	if (file_exists($pfile)) {
813

    
814
		/* read the pid file */
815
		$pid = trim(file_get_contents($pfile));
816
		unlink($pfile);
817

    
818
		/* send a term signal to the process */
819
		posix_kill($pid, SIGTERM);
820
	}
821

    
822
	/* remove the device from the openvpn group */
823
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
824

    
825
	/* restore the original adapter name */
826
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
827

    
828
	/* remove the configuration files */
829
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
830
}
831

    
832
function openvpn_resync_csc(& $settings) {
833
	global $g, $config;
834

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

    
837
	if (isset($settings['disable'])) {
838
		unlink_if_exists($fpath);
839
		return;
840
	}
841
	openvpn_create_dirs();
842

    
843
	$conf = '';
844
	if ($settings['block'])
845
		$conf .= "disable\n";
846

    
847
	if ($settings['push_reset'])
848
		$conf .= "push-reset\n";
849

    
850
	if (!empty($settings['tunnel_network'])) {
851
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
852
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
853
		$serverip = long2ip32($baselong + 1);
854
		$clientip = long2ip32($baselong + 2);
855
		/* Because this is being pushed, the order from the client's point of view. */
856
		if ($settings['dev_mode'] != 'tap')
857
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
858
		else
859
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
860
	}
861

    
862
	openvpn_add_dhcpopts($settings, $conf);
863

    
864
	if ($settings['gwredir'])
865
		$conf .= "push \"redirect-gateway def1\"\n";
866

    
867
	openvpn_add_custom($settings, $conf);
868

    
869
	file_put_contents($fpath, $conf);
870
	chown($fpath, 'nobody');
871
	chgrp($fpath, 'nobody');
872
}
873

    
874
function openvpn_delete_csc(& $settings) {
875
	global $g, $config;
876

    
877
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
878
	unlink_if_exists($fpath);
879
}
880

    
881
// Resync the configuration and restart the VPN
882
function openvpn_resync($mode, $settings) {
883
	openvpn_reconfigure($mode, $settings);
884
	openvpn_restart($mode, $settings);
885
}
886

    
887
// Resync and restart all VPNs
888
function openvpn_resync_all($interface = "") {
889
	global $g, $config;
890

    
891
	if ($g['platform'] == 'jail')
892
		return;
893
	openvpn_create_dirs();
894

    
895
	if (!is_array($config['openvpn']))
896
		$config['openvpn'] = array();
897

    
898
/*
899
	if (!$config['openvpn']['dh-parameters']) {
900
		echo "Configuring OpenVPN Parameters ...\n";
901
		$dh_parameters = openvpn_create_dhparams(1024);
902
		$dh_parameters = base64_encode($dh_parameters);
903
		$config['openvpn']['dh-parameters'] = $dh_parameters;
904
		write_config("OpenVPN DH parameters");
905
	}
906

    
907
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
908
	if (!file_exists($path_ovdh)) {
909
		$dh_parameters = $config['openvpn']['dh-parameters'];
910
		$dh_parameters = base64_decode($dh_parameters);
911
		file_put_contents($path_ovdh, $dh_parameters);
912
	}
913
*/
914
	if ($interface <> "")
915
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
916
	else
917
		log_error("Resyncing OpenVPN instances."); 
918

    
919
	if (is_array($config['openvpn']['openvpn-server'])) {
920
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
921
			if ($interface <> "" && $interface != $settings['interface'])
922
				continue;
923
			openvpn_resync('server', $settings);
924
		}
925
	}
926

    
927
	if (is_array($config['openvpn']['openvpn-client'])) {
928
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
929
			if ($interface <> "" && $interface != $settings['interface'])
930
				continue;
931
			openvpn_resync('client', $settings);
932
		}
933
	}
934

    
935
	if (is_array($config['openvpn']['openvpn-csc']))
936
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
937
			openvpn_resync_csc($settings);
938

    
939
}
940

    
941
function openvpn_get_active_servers($type="multipoint") {
942
	global $config, $g;
943

    
944
	$servers = array();
945
	if (is_array($config['openvpn']['openvpn-server'])) {
946
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
947
			if (empty($settings) || isset($settings['disable']))
948
				continue;
949

    
950
			$prot = $settings['protocol'];
951
			$port = $settings['local_port'];
952
	
953
			$server = array();
954
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
955
			$server['mode'] = $settings['mode'];
956
			if ($settings['description'])
957
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
958
			else
959
				$server['name'] = "Server {$prot}:{$port}";
960
			$server['conns'] = array();
961
	
962
			$vpnid = $settings['vpnid'];
963
			$mode_id = "server{$vpnid}";
964
			$server['mgmt'] = $mode_id;
965
			$socket = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
966
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
967

    
968
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
969
				$servers[] = openvpn_get_client_status($server, $socket);
970
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
971
				$servers[] = openvpn_get_server_status($server, $socket);
972

    
973
		}
974
	}
975
	return $servers;
976
}
977

    
978
function openvpn_get_server_status($server, $socket) {
979
	$errval;
980
	$errstr;
981
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
982
	if ($fp) {
983
		stream_set_timeout($fp, 1);
984

    
985
		/* send our status request */
986
		fputs($fp, "status 2\n");
987

    
988
		/* recv all response lines */
989
		while (!feof($fp)) {
990

    
991
			/* read the next line */
992
			$line = fgets($fp, 1024);
993

    
994
			$info = stream_get_meta_data($fp);
995
			if ($info['timed_out'])
996
				break;
997

    
998
			/* parse header list line */
999
			if (strstr($line, "HEADER"))
1000
				continue;
1001

    
1002
			/* parse end of output line */
1003
			if (strstr($line, "END") || strstr($line, "ERROR"))
1004
				break;
1005

    
1006
			/* parse client list line */
1007
			if (strstr($line, "CLIENT_LIST")) {
1008
				$list = explode(",", $line);
1009
				$conn = array();
1010
				$conn['common_name'] = $list[1];
1011
				$conn['remote_host'] = $list[2];
1012
				$conn['virtual_addr'] = $list[3];
1013
				$conn['bytes_recv'] = $list[4];
1014
				$conn['bytes_sent'] = $list[5];
1015
				$conn['connect_time'] = $list[6];
1016
				$server['conns'][] = $conn;
1017
			}
1018
			/* parse routing table lines */
1019
			if (strstr($line, "ROUTING_TABLE")) {
1020
				$list = explode(",", $line);
1021
				$conn = array();
1022
				$conn['virtual_addr'] = $list[1];
1023
				$conn['common_name'] = $list[2];
1024
				$conn['remote_host'] = $list[3];
1025
				$conn['last_time'] = $list[4];
1026
				$server['routes'][] = $conn;
1027
			}
1028
		}
1029

    
1030
		/* cleanup */
1031
		fclose($fp);
1032
	} else {
1033
		$conn = array();
1034
		$conn['common_name'] = "[error]";
1035
		$conn['remote_host'] = "Management Daemon Unreachable";
1036
		$conn['virtual_addr'] = "";
1037
		$conn['bytes_recv'] = 0;
1038
		$conn['bytes_sent'] = 0;
1039
		$conn['connect_time'] = 0;
1040
		$server['conns'][] = $conn;
1041
	}
1042
	return $server;
1043
}
1044

    
1045
function openvpn_get_active_clients() {
1046
	global $config, $g;
1047

    
1048
	$clients = array();
1049
	if (is_array($config['openvpn']['openvpn-client'])) {
1050
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1051
	
1052
			if (empty($settings) || isset($settings['disable']))
1053
				continue;
1054

    
1055
			$prot = $settings['protocol'];
1056
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1057
	
1058
			$client = array();
1059
			$client['port'] = $settings['local_port'];
1060
			if ($settings['description'])
1061
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1062
			else
1063
				$client['name'] = "Client {$prot}{$port}";
1064
	
1065
			$vpnid = $settings['vpnid'];
1066
			$mode_id = "client{$vpnid}";
1067
			$client['mgmt'] = $mode_id;
1068
			$socket = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
1069
			$client['status']="down";
1070

    
1071
			$clients[] = openvpn_get_client_status($client, $socket);
1072
		}
1073
	}
1074
	return $clients;
1075
}
1076

    
1077
function openvpn_get_client_status($client, $socket) {
1078
	$errval;
1079
	$errstr;
1080
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1081
	if ($fp) {
1082
		stream_set_timeout($fp, 1);
1083
		/* send our status request */
1084
		fputs($fp, "state 1\n");
1085

    
1086
		/* recv all response lines */
1087
		while (!feof($fp)) {
1088
			/* read the next line */
1089
			$line = fgets($fp, 1024);
1090

    
1091
			$info = stream_get_meta_data($fp);
1092
			if ($info['timed_out'])
1093
				break;
1094

    
1095
			/* Get the client state */
1096
			if (strstr($line,"CONNECTED")) {
1097
				$client['status']="up";
1098
				$list = explode(",", $line);
1099

    
1100
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1101
				$client['virtual_addr']  = $list[3];
1102
				$client['remote_host'] = $list[4];
1103
			}
1104
			if (strstr($line,"CONNECTING")) {
1105
				$client['status']="connecting";
1106
			}
1107
			if (strstr($line,"ASSIGN_IP")) {
1108
				$client['status']="waiting";
1109
				$list = explode(",", $line);
1110

    
1111
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1112
				$client['virtual_addr']  = $list[3];
1113
			}
1114
			if (strstr($line,"RECONNECTING")) {
1115
				$client['status']="reconnecting";
1116
				$list = explode(",", $line);
1117

    
1118
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1119
				$client['status'] .= "; " . $list[2];
1120
			}
1121
			/* parse end of output line */
1122
			if (strstr($line, "END") || strstr($line, "ERROR"))
1123
				break;
1124
		}
1125

    
1126
		/* If up, get read/write stats */
1127
		if (strcmp($client['status'], "up") == 0) {
1128
			fputs($fp, "status 2\n");
1129
			/* recv all response lines */
1130
			while (!feof($fp)) {
1131
				/* read the next line */
1132
				$line = fgets($fp, 1024);
1133

    
1134
				$info = stream_get_meta_data($fp);
1135
				if ($info['timed_out'])
1136
					break;
1137

    
1138
				if (strstr($line,"TCP/UDP read bytes")) {
1139
					$list = explode(",", $line);
1140
					$client['bytes_recv'] = $list[1];
1141
				}
1142

    
1143
				if (strstr($line,"TCP/UDP write bytes")) {
1144
					$list = explode(",", $line);
1145
					$client['bytes_sent'] = $list[1];
1146
				}
1147

    
1148
				/* parse end of output line */
1149
				if (strstr($line, "END"))
1150
					break;
1151
			}
1152
		}
1153

    
1154
		fclose($fp);
1155

    
1156
	} else {
1157
		$DisplayNote=true;
1158
		$client['remote_host'] = "No Management Daemon";
1159
		$client['virtual_addr'] = "See Note Below";
1160
		$client['bytes_recv'] = 0;
1161
		$client['bytes_sent'] = 0;
1162
		$client['connect_time'] = 0;
1163
	}
1164
	return $client;
1165
}
1166

    
1167
function openvpn_refresh_crls() {
1168
	global $g, $config;
1169

    
1170
	openvpn_create_dirs();
1171

    
1172
	if (is_array($config['openvpn']['openvpn-server'])) {
1173
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1174
			if (empty($settings))
1175
				continue;
1176
			if (isset($settings['disable']))
1177
				continue;
1178
			// Write the settings for the keys
1179
			switch($settings['mode']) {
1180
				case 'p2p_tls':
1181
				case 'server_tls':
1182
				case 'server_tls_user':
1183
				case 'server_user':
1184
					if (!empty($settings['crlref'])) {
1185
						$crl = lookup_crl($settings['crlref']);
1186
						crl_update($crl);
1187
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1188
						file_put_contents($fpath, base64_decode($crl['text']));
1189
						@chmod($fpath, 0644);
1190
					}
1191
					break;
1192
			}
1193
		}
1194
	}
1195
}
1196

    
1197
function openvpn_create_dirs() {
1198
	global $g;
1199
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1200
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1201
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1202
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1203
}
1204

    
1205
function openvpn_get_interface_ip($ip, $mask) {
1206
	$baselong = ip2long32($ip) & ip2long($mask);
1207
	$ip1 = long2ip32($baselong + 1);
1208
	$ip2 = long2ip32($baselong + 2);
1209
	return array($ip1, $ip2);
1210
}
1211

    
1212
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1213
	$basev6 = gen_subnetv6($ipv6, $prefix);
1214
	// Is there a better way to do this math?
1215
	$ipv6_arr = explode(':', $basev6);
1216
	$last = hexdec(array_pop($ipv6_arr));
1217
	$ipv6_1 = Net_IPv6::compress(implode(':', $ipv6_arr) . ':' . dechex($last + 1));
1218
	$ipv6_2 = Net_IPv6::compress(implode(':', $ipv6_arr) . ':' . dechex($last + 2));
1219
	return array($ipv6_1, $ipv6_2);
1220
}
1221

    
1222
function openvpn_clear_route($mode, $settings) {
1223
	if (empty($settings['tunnel_network']))
1224
		return;
1225
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1226
	$mask = gen_subnet_mask($cidr);
1227
	switch($settings['mode']) {
1228
		case 'p2p_tls':
1229
		case 'p2p_shared_key':
1230
		case 'shared_key':
1231
			if (!empty($ip) && !empty($mask) && ($cidr == 30)) {
1232
				list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1233
				$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1234
				mwexec("/sbin/route -q delete {$ip_to_clear}");
1235
			}
1236
			break;
1237
	}
1238
}
1239

    
1240
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false) {
1241
	$routes = "";
1242
	if (empty($value))
1243
		return "";
1244
	$networks = explode(',', $value);
1245

    
1246
	foreach ($networks as $network) {
1247
		if ($ipproto == "ipv4")
1248
			$route = openvpn_gen_route_ipv4($network);
1249
		else
1250
			$route = openvpn_gen_route_ipv6($network);
1251

    
1252
		if ($push)
1253
			$routes .= "push \"{$route}\"\n";
1254
		else
1255
			$routes .= "{$route}\n";
1256
	}
1257
	return $routes;
1258
}
1259

    
1260
function openvpn_gen_route_ipv4($network) {
1261
	list($ip, $mask) = explode('/', trim($network));
1262
	$mask = gen_subnet_mask($mask);
1263
	return "route $ip $mask";
1264
}
1265

    
1266
function openvpn_gen_route_ipv6($network) {
1267
	list($ipv6, $prefix) = explode('/', trim($network));
1268
	if (empty($prefix))
1269
		$prefix = "128";
1270
	return "route-ipv6 ${ipv6}/${prefix}";
1271
}
1272

    
1273
?>
(37-37/67)