Project

General

Profile

Download (27.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2

    
3
/* $Id$ */
4
/*
5
	$RCSfile$
6
	
7
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
8
	All rights reserved.
9
	
10
	Copyright (C) 2006  Fernando Lemos
11
	All rights reserved.
12

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

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

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

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

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

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

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

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

    
54
$openvpn_prots = array("UDP", "TCP");
55

    
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
$openvpn_dh_lengths = array(
72
	1024, 2048, 4096 );
73

    
74
$openvpn_server_modes = array(
75
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
76
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
77
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
78
	'server_user' => gettext("Remote Access ( User Auth )"),
79
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
80

    
81
$openvpn_client_modes = array(
82
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
83
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )") );
84

    
85
function openvpn_create_key() {
86

    
87
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
88
	if (!$fp)
89
		return false;
90

    
91
	$rslt = stream_get_contents($fp);
92
	pclose($fp);
93

    
94
	return $rslt;
95
}
96

    
97
function openvpn_create_dhparams($bits) {
98

    
99
	$fp = popen("/usr/bin/openssl dhparam {$bits} 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_vpnid_used($vpnid) {
110
	global $config;
111

    
112
	if (is_array($config['openvpn']['openvpn-server']))
113
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
114
			if ($vpnid == $settings['vpnid'])
115
				return true;
116

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

    
122
	return false;
123
}
124

    
125
function openvpn_vpnid_next() {
126

    
127
	$vpnid = 1;
128
	while(openvpn_vpnid_used($vpnid))
129
		$vpnid++;
130

    
131
	return $vpnid;
132
}
133

    
134
function openvpn_port_used($prot, $port) {
135
	global $config;
136

    
137
	if (is_array($config['openvpn']['openvpn-server']))
138
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
139
			if ($port == $settings['local_port'] &&
140
				$prot == $settings['protocol'] && !isset($settings['disable']))
141
				return $settings['vpnid'];
142

    
143
	if (is_array($config['openvpn']['openvpn-client']))
144
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
145
			if ($port == $settings['local_port'] &&
146
				$prot == $settings['protocol'] && !isset($settings['disable']))
147
				return $settings['vpnid'];
148

    
149
	return 0;
150
}
151

    
152
function openvpn_port_next($prot) {
153

    
154
	$port = 1194;
155
	while(openvpn_port_used($prot, $port))
156
		$port++;
157

    
158
	return $port;
159
}
160

    
161
function openvpn_get_cipherlist() {
162

    
163
	$ciphers = array();
164
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
165
	$cipher_lines = explode("\n", trim($cipher_out));
166
	sort($cipher_lines);
167
	foreach ($cipher_lines as $line) {
168
		$words = explode(' ', $line);
169
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
170
	}
171
	$ciphers["none"] = gettext("None (No Encryption)");
172
	return $ciphers;
173
}
174

    
175
function openvpn_get_engines() {
176
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
177
	exec("/usr/bin/openssl engine", $openssl_engine_output);
178
	foreach ($openssl_engine_output as $oeo) {
179
		$linematch = array();
180
		preg_match("/\((.*)\)\s(.*)/", $oeo, $linematch);
181
		if ($linematch[1] != "dynamic")
182
			$openssl_engines[$linematch[1]] = $linematch[2];
183
	}
184
	return $openssl_engines;
185
}
186

    
187
function openvpn_validate_engine($engine) {
188
	$engines = openvpn_get_engines();
189
	return array_key_exists($engine, $engines);
190
}
191

    
192
function openvpn_validate_host($value, $name) {
193
	$value = trim($value);
194
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
195
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
196
	return false;
197
}
198

    
199
function openvpn_validate_port($value, $name) {
200
	$value = trim($value);
201
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
202
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
203
	return false;
204
}
205

    
206
function openvpn_validate_cidr($value, $name) {
207
	$value = trim($value);
208
	if (!empty($value)) {
209
		list($ip, $mask) = explode('/', $value);
210
		if (!is_ipaddr($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
211
			return sprintf(gettext("The field '%s' must contain a valid CIDR range."), $name);
212
	}
213
	return false;
214
}
215

    
216
function openvpn_add_dhcpopts(& $settings, & $conf) {
217

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

    
221
	if (!empty($settings['dns_server1']))
222
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
223
	if (!empty($settings['dns_server2']))
224
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
225
	if (!empty($settings['dns_server3']))
226
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
227
	if (!empty($settings['dns_server4']))
228
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
229

    
230
	if (!empty($settings['ntp_server1']))
231
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
232
	if (!empty($settings['ntp_server2']))
233
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
234

    
235
	if ($settings['netbios_enable']) {
236

    
237
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
238
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
239
		if (!empty($settings['dhcp_nbtscope'])) 
240
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
241

    
242
		if (!empty($settings['wins_server1']))
243
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
244
		if (!empty($settings['wins_server2']))
245
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
246

    
247
		if (!empty($settings['nbdd_server1']))
248
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
249
	}
250

    
251
	if ($settings['gwredir']) 
252
		$conf .= "push \"redirect-gateway def1\"\n";
253
}
254

    
255
function openvpn_add_custom(& $settings, & $conf) {
256

    
257
	if ($settings['custom_options']) {
258

    
259
		$options = explode(';', $settings['custom_options']);
260

    
261
		if (is_array($options)) {
262
			foreach ($options as $option)
263
				$conf .= "$option\n";
264
		} else
265
			$conf .= "{$settings['custom_options']}\n";
266
	}
267
}
268

    
269
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
270
	global $g;
271

    
272
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
273
	file_put_contents($fpath, base64_decode($data));
274
	//chown($fpath, 'nobody');
275
	//chgrp($fpath, 'nobody');
276
	@chmod($fpath, 0600);
277

    
278
	$conf .= "{$directive} {$fpath} {$opt}\n";
279
}
280

    
281
function openvpn_reconfigure($mode, $settings) {
282
	global $g, $config;
283

    
284
	if (empty($settings))
285
		return;
286
	if (isset($settings['disable'])) 
287
		return;
288

    
289
	/*
290
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
291
	 * we use a vpnid number which is allocated for a particular client
292
	 * or server configuration. ( see openvpn_vpnid_next() )
293
	 */
294

    
295
	$vpnid = $settings['vpnid'];
296
	$mode_id = $mode.$vpnid;
297

    
298
	if (isset($settings['dev_mode']))
299
		$tunname = "{$settings['dev_mode']}{$vpnid}";
300
	else {	/* defaults to tun */
301
		$tunname = "tun{$vpnid}";
302
		$settings['dev_mode'] = "tun";
303
	}
304

    
305
	if ($mode == "server")
306
		$devname = "ovpns{$vpnid}";
307
	else
308
		$devname = "ovpnc{$vpnid}";
309

    
310
	/* is our device already configured */
311
	if (mwexec("/sbin/ifconfig {$devname}")) {
312

    
313
		/* create the tap device if required */
314
		if (!file_exists("/dev/{$tunname}"))
315
			exec("/sbin/ifconfig {$tunname} create");
316

    
317
		/* rename the device */
318
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
319

    
320
		/* add the device to the openvpn group */
321
		mwexec("/sbin/ifconfig {$devname} group openvpn");
322
	}
323

    
324
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
325
	$proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}");
326
	$dev_mode = $settings['dev_mode'];
327
	$cipher = $settings['crypto'];
328

    
329
	$interface = $settings['interface'];
330
	$ipaddr = $settings['ipaddr'];
331
	$ipaddrv6 = $settings['ipaddrv6'];
332

    
333
	// If a specific ip address (VIP) is requested, use it.
334
	// Otherwise, if a specific interface is requested, use it
335
	// If "any" interface was selected, local directive will be ommited.
336
	if (is_ipaddrv4($ipaddr)) {
337
		$iface_ip=$ipaddr;
338
	} elseif (is_ipaddrv6($ipaddrv6)) {
339
		$iface_ipv6=$ipaddrv6;
340
	} else {
341
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
342
			$iface_ip=get_interface_ip($interface);
343
		}
344
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
345
			$iface_ipv6=get_interface_ipv6($interface);
346
		}
347
	}
348

    
349
	$conf  = "dev {$devname}\n";
350
	$conf .= "dev-type {$settings['dev_mode']}\n";
351
	switch($settings['dev_mode']) {
352
		case "tun":
353
			$conf .= "tun-ipv6\n";
354
			break;
355
	}
356
	$conf .= "dev-node /dev/{$tunname}\n";
357
	$conf .= "writepid {$pfile}\n";
358
	$conf .= "#user nobody\n";
359
	$conf .= "#group nobody\n";
360
	$conf .= "script-security 3\n";
361
	$conf .= "daemon\n";
362
	$conf .= "keepalive 10 60\n";
363
	$conf .= "ping-timer-rem\n";
364
	$conf .= "persist-tun\n";
365
	$conf .= "persist-key\n";
366
	$conf .= "proto {$proto}\n";
367
	$conf .= "cipher {$cipher}\n";
368
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
369
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
370

    
371
	if (is_ipaddrv4($iface_ip)) {
372
		$conf .= "local {$iface_ip}\n";	
373
	}
374
	if (is_ipaddrv6($iface_ipv6)) {
375
		// $conf .= "local {$iface_ipv6}\n";	
376
	}
377

    
378
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
379
		$conf .= "engine {$settings['engine']}\n";
380

    
381
	// server specific settings
382
	if ($mode == 'server') {
383

    
384
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
385
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
386
		$mask = gen_subnet_mask($cidr);
387

    
388
		// configure tls modes
389
		switch($settings['mode']) {
390
			case 'p2p_tls':
391
			case 'server_tls':
392
			case 'server_user':
393
			case 'server_tls_user':
394
				$conf .= "tls-server\n";
395
				break;
396
		}
397

    
398
		// configure p2p/server modes
399
		switch($settings['mode']) {
400
			case 'p2p_tls':
401
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
402
				//  use the server directive. It works for a single client without it.
403
				//  See ticket #1417
404
				if ($cidr < 30) {
405
					$conf .= "server {$ip} {$mask}\n";
406
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
407
				}
408
			case 'p2p_shared_key':
409
				$baselong = ip2long32($ip) & ip2long($mask);
410
				$ip1 = long2ip32($baselong + 1);
411
				$ip2 = long2ip32($baselong + 2);
412
				$conf .= "ifconfig $ip1 $ip2\n";
413
				break;
414
			case 'server_tls':
415
			case 'server_user':
416
			case 'server_tls_user':
417
				$conf .= "server {$ip} {$mask}\n";
418
				if(is_ipaddr($ipv6))
419
					$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
420
				$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
421
				break;
422
		}
423

    
424
		// configure user auth modes
425
		switch($settings['mode']) {
426
			case 'server_user':
427
				$conf .= "client-cert-not-required\n";
428
			case 'server_tls_user':
429
				$conf .= "username-as-common-name\n";
430
				if (!empty($settings['authmode'])) {
431
					$authcfgs = explode(",", $settings['authmode']);
432
					$sed = "\$authmodes=array(";
433
					$firstsed = 0;
434
					foreach ($authcfgs as $authcfg) {
435
						if ($firstsed > 0)
436
							$sed .= ",";
437
						$firstsed = 1;
438
						$sed .= "\"{$authcfg}\"";
439
					}
440
					$sed .= ");\\\n";
441
					if ($settings['strictusercn'])
442
						$sed .= "\$strictusercn = true;";
443
					$sed .= " \$modeid = \"{$mode_id}\";";
444
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
445
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
446
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
447
				}
448
				break;
449
		}
450

    
451
		// The local port to listen on
452
		$conf .= "lport {$settings['local_port']}\n";
453

    
454
		// The management port to listen on
455
		// Use unix socket to overcome the problem on any type of server
456
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
457
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
458

    
459
		if ($settings['maxclients'])
460
			$conf .= "max-clients {$settings['maxclients']}\n";
461

    
462
		// Can we push routes
463
		if ($settings['local_network']) {
464
			list($ip, $mask) = explode('/', $settings['local_network']);
465
			$mask = gen_subnet_mask($mask);
466
			$conf .= "push \"route $ip $mask\"\n";
467
		}
468
		if ($settings['local_networkv6']) {
469
			list($ipv6, $prefix) = explode('/', $settings['local_networkv6']);
470
			$conf .= "push \"route-ipv6 $ipv6/$prefix\"\n";
471
		}
472

    
473
		switch($settings['mode']) {
474
			case 'server_tls':
475
			case 'server_user':
476
			case 'server_tls_user':
477
				// Configure client dhcp options
478
				openvpn_add_dhcpopts($settings, $conf);
479
				if ($settings['client2client'])
480
					$conf .= "client-to-client\n";
481
				break;
482
		}
483
		if (isset($settings['duplicate_cn']))
484
			$conf .= "duplicate-cn\n";
485
	}
486

    
487
	// client specific settings
488

    
489
	if ($mode == 'client') {
490

    
491
		// configure p2p mode
492
		switch($settings['mode']) {
493
			case 'p2p_tls':
494
				$conf .= "tls-client\n";
495
			case 'shared_key':
496
				$conf .= "client\n";
497
				break;
498
		}
499

    
500
		// If there is no bind option at all (ip and/or port), add "nobind" directive
501
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
502
		//  ensure a random source port.
503
		if ((empty($iface_ip)) && (!$settings['local_port']))
504
			$conf .= "nobind\n";
505
		elseif ($settings['local_port'])
506
			$conf .= "lport {$settings['local_port']}\n";
507
		else
508
			$conf .= "lport 0\n";
509

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

    
513
		// The remote server
514
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
515

    
516
		if (!empty($settings['use_shaper']))
517
			$conf .= "shaper {$settings['use_shaper']}\n";
518

    
519
		if (!empty($settings['tunnel_network'])) {
520
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
521
			$mask = gen_subnet_mask($mask);
522
			$baselong = ip2long32($ip) & ip2long($mask);
523
			$ip1 = long2ip32($baselong + 1);
524
			$ip2 = long2ip32($baselong + 2);
525
			$conf .= "ifconfig $ip2 $ip1\n";
526
		}
527

    
528
		if ($settings['proxy_addr']) {
529
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
530
			if ($settings['proxy_authtype'] != "none") {
531
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
532
				$proxypas = "{$settings['proxy_user']}\n";
533
				$proxypas .= "{$settings['proxy_passwd']}\n";
534
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
535
			}
536
			$conf .= " \n";
537
		}
538
	}
539

    
540
	// Add a remote network route if set
541
	if ($settings['remote_network']) {
542
		list($ip, $mask) = explode('/', $settings['remote_network']);
543
		$mask = gen_subnet_mask($mask);
544
		$conf .= "route $ip $mask\n";
545
	}
546

    
547
	// Write the settings for the keys
548
	switch($settings['mode']) {
549
		case 'p2p_shared_key':
550
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
551
			break;
552
		case 'p2p_tls':
553
		case 'server_tls':
554
		case 'server_tls_user':
555
		case 'server_user':
556
			$ca = lookup_ca($settings['caref']);
557
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
558
			$cert = lookup_cert($settings['certref']);
559
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
560
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
561
			if ($mode == 'server')
562
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
563
			if (!empty($settings['crlref'])) {
564
				$crl = lookup_crl($settings['crlref']);
565
				crl_update($crl);
566
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
567
			}
568
			if ($settings['tls']) {
569
				if ($mode == "server") 
570
					$tlsopt = 0;
571
				else
572
					$tlsopt = 1;
573
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
574
			}
575
			break;
576
	}
577

    
578
	if ($settings['compression'])
579
		$conf .= "comp-lzo\n";
580

    
581
	if ($settings['passtos'])
582
		$conf .= "passtos\n";
583

    
584
	if ($settings['resolve_retry'])
585
		$conf .= "resolv-retry infinite\n";
586

    
587
	if ($settings['dynamic_ip']) {
588
		$conf .= "persist-remote-ip\n";
589
		$conf .= "float\n";
590
	}
591

    
592
	openvpn_add_custom($settings, $conf);
593

    
594
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
595
	file_put_contents($fpath, $conf);
596
	//chown($fpath, 'nobody');
597
	//chgrp($fpath, 'nobody');
598
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
599
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
600
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
601
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
602
}
603

    
604
function openvpn_restart($mode, $settings) {
605
	global $g, $config;
606

    
607
	$vpnid = $settings['vpnid'];
608
	$mode_id = $mode.$vpnid;
609

    
610
	/* kill the process if running */
611
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
612
	if (file_exists($pfile)) {
613

    
614
		/* read the pid file */
615
		$pid = rtrim(file_get_contents($pfile));
616
		unlink($pfile);
617

    
618
		/* send a term signal to the process */
619
		posix_kill($pid, SIGTERM);
620

    
621
		/* wait until the process exits */
622
		while(posix_kill($pid, 0))
623
			usleep(250000);
624
	}
625

    
626
	if (isset($settings['disable']))
627
		return;
628

    
629
	/* start the new process */
630
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
631
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
632

    
633
	if (!$g['booting'])
634
		send_event("filter reload");
635
}
636

    
637
function openvpn_delete($mode, & $settings) {
638
	global $g, $config;
639

    
640
	$vpnid = $settings['vpnid'];
641
	$mode_id = $mode.$vpnid;
642

    
643
	$tunname = "tun{$vpnid}";
644
	if ($mode == "server")
645
		$devname = "ovpns{$vpnid}";
646
	else
647
		$devname = "ovpnc{$vpnid}";
648

    
649
	/* kill the process if running */
650
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
651
	if (file_exists($pfile)) {
652

    
653
		/* read the pid file */
654
		$pid = trim(file_get_contents($pfile));
655
		unlink($pfile);
656

    
657
		/* send a term signal to the process */
658
		posix_kill($pid, SIGTERM);
659
	}
660

    
661
	/* remove the device from the openvpn group */
662
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
663

    
664
	/* restore the original adapter name */
665
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
666

    
667
	/* remove the configuration files */
668
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
669
}
670

    
671
function openvpn_resync_csc(& $settings) {
672
	global $g, $config;
673

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

    
676
	if (isset($settings['disable'])) {
677
		unlink_if_exists($fpath);
678
		return;
679
	}
680

    
681
	$conf = '';
682
	if ($settings['block'])
683
		$conf .= "disable\n";
684

    
685
	if ($settings['push_reset'])
686
		$conf .= "push-reset\n";
687

    
688
	if (!empty($settings['tunnel_network'])) {
689
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
690
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
691
		$ip1 = long2ip32($baselong + 1);
692
		$ip2 = long2ip32($baselong + 2);
693
		$conf .= "ifconfig-push {$ip1} {$ip2}\n";
694
	}
695

    
696
	openvpn_add_dhcpopts($settings, $conf);
697

    
698
	if ($settings['gwredir'])
699
		$conf .= "push \"redirect-gateway def1\"\n";
700

    
701
	openvpn_add_custom($settings, $conf);
702

    
703
	file_put_contents($fpath, $conf);
704
	chown($fpath, 'nobody');
705
	chgrp($fpath, 'nobody');
706
}
707

    
708
function openvpn_delete_csc(& $settings) {
709
	global $g, $config;
710

    
711
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
712
	unlink_if_exists($fpath);
713
}
714

    
715
// Resync the configuration and restart the VPN
716
function openvpn_resync($mode, $settings) {
717
	openvpn_reconfigure($mode, $settings);
718
	openvpn_restart($mode, $settings);
719
}
720

    
721
// Resync and restart all VPNs
722
function openvpn_resync_all($interface = "") {
723
	global $g, $config;
724

    
725
	// delay our setup until the system
726
	// has a chance to init our paths
727
	if (!file_exists($g['varetc_path']."/openvpn") ||
728
		!file_exists($g['varetc_path']."/openvpn-csc"))
729
		return;
730

    
731
	if (!is_array($config['openvpn']))
732
		$config['openvpn'] = array();
733

    
734
/*
735
	if (!$config['openvpn']['dh-parameters']) {
736
		echo "Configuring OpenVPN Parameters ...\n";
737
		$dh_parameters = openvpn_create_dhparams(1024);
738
		$dh_parameters = base64_encode($dh_parameters);
739
		$config['openvpn']['dh-parameters'] = $dh_parameters;
740
		write_config("OpenVPN DH parameters");
741
	}
742

    
743
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
744
	if (!file_exists($path_ovdh)) {
745
		$dh_parameters = $config['openvpn']['dh-parameters'];
746
		$dh_parameters = base64_decode($dh_parameters);
747
		file_put_contents($path_ovdh, $dh_parameters);
748
	}
749
*/
750
	if ($interface <> "")
751
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
752
	else
753
		log_error("Resyncing OpenVPN instances."); 
754

    
755
	if (is_array($config['openvpn']['openvpn-server'])) {
756
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
757
			if ($interface <> "" && $interface != $settings['interface'])
758
				continue;
759
			openvpn_resync('server', $settings);
760
		}
761
	}
762

    
763
	if (is_array($config['openvpn']['openvpn-client'])) {
764
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
765
			if ($interface <> "" && $interface != $settings['interface'])
766
				continue;
767
			openvpn_resync('client', $settings);
768
		}
769
	}
770

    
771
	if (is_array($config['openvpn']['openvpn-csc']))
772
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
773
			openvpn_resync_csc($settings);
774

    
775
}
776

    
777
function openvpn_get_active_servers() {
778
	global $config, $g;
779

    
780
	$servers = array();
781
	if (is_array($config['openvpn']['openvpn-server'])) {
782
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
783
	
784
			$prot = $settings['protocol'];
785
			$port = $settings['local_port'];
786
	
787
			$server = array();
788
			$server['port'] = $settings['local_port'];
789
			$server['mode'] = $settings['mode'];
790
			if ($settings['description'])
791
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
792
			else
793
				$server['name'] = "Server {$prot}:{$port}";
794
			$server['conns'] = array();
795
	
796
			$vpnid = $settings['vpnid'];
797
                        $mode_id = "server{$vpnid}";
798
			$server['mgmt'] = $mode_id;
799
                        $tcpsrv = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
800
			$errval;
801
			$errstr;
802
	
803
			/* open a tcp connection to the management port of each server */
804
			$fp = @stream_socket_client($tcpsrv, $errval, $errstr, 1);
805
			if ($fp) {
806
				stream_set_timeout($fp, 1);
807
	
808
				/* send our status request */
809
				fputs($fp, "status 2\n");
810
	
811
				/* recv all response lines */
812
				while (!feof($fp)) {
813
	
814
					/* read the next line */
815
					$line = fgets($fp, 1024);
816
	
817
					$info = stream_get_meta_data($fp);
818
					if ($info['timed_out'])
819
						break;
820

    
821
					/* parse header list line */
822
					if (strstr($line, "HEADER"))
823
						continue;
824
	
825
					/* parse end of output line */
826
					if (strstr($line, "END") || strstr($line, "ERROR"))
827
						break;
828
	
829
					/* parse client list line */
830
					if (strstr($line, "CLIENT_LIST")) {
831
						$list = explode(",", $line);
832
						$conn = array();
833
						$conn['common_name'] = $list[1];
834
						$conn['remote_host'] = $list[2];
835
						$conn['virtual_addr'] = $list[3];
836
						$conn['bytes_recv'] = $list[4];
837
						$conn['bytes_sent'] = $list[5];
838
						$conn['connect_time'] = $list[6];
839
						$server['conns'][] = $conn;
840
					}
841
				}
842
	
843
				/* cleanup */
844
				fclose($fp);
845
			} else {
846
				$conn = array();
847
				$conn['common_name'] = "[error]";
848
				$conn['remote_host'] = "Management Daemon Unreachable";
849
				$conn['virtual_addr'] = "";
850
				$conn['bytes_recv'] = 0;
851
				$conn['bytes_sent'] = 0;
852
				$conn['connect_time'] = 0;
853
				$server['conns'][] = $conn;
854
			}
855
	
856
			$servers[] = $server;
857
		}
858
	}
859
	return $servers;
860
}
861

    
862
function openvpn_get_active_clients() {
863
	global $config, $g;
864

    
865
	$clients = array();
866
	if (is_array($config['openvpn']['openvpn-client'])) {
867
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
868
	
869
			$prot = $settings['protocol'];
870
			$port = $settings['local_port'];
871
	
872
			$client = array();
873
			$client['port'] = $settings['local_port'];
874
			if ($settings['description'])
875
				$client['name'] = "{$settings['description']} {$prot}:{$port}";
876
			else
877
				$client['name'] = "Client {$prot}:{$port}";
878
	
879
			$vpnid = $settings['vpnid'];
880
        		$mode_id = "client{$vpnid}";
881
			$client['mgmt'] = $mode_id;
882
			$tcpcli = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
883
			$errval;
884
			$errstr;
885
	
886
			$client['status']="down";
887
	
888
			/* open a tcp connection to the management port of each cli */
889
			$fp = @stream_socket_client($tcpcli, $errval, $errstr, 1);
890
			if ($fp) {
891
				stream_set_timeout($fp, 1);
892
				/* send our status request */
893
				fputs($fp, "state 1\n");
894
	
895
				/* recv all response lines */
896
				while (!feof($fp)) {
897
					/* read the next line */
898
					$line = fgets($fp, 1024);
899
					
900
					$info = stream_get_meta_data($fp);
901
					if ($info['timed_out'])
902
						break;	
903

    
904
					/* Get the client state */
905
					if (strstr($line,"CONNECTED")) {
906
						$client['status']="up";
907
						$list = explode(",", $line);
908
	
909
						$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
910
						$client['virtual_addr']  = $list[3];
911
						$client['remote_host'] = $list[4];
912
					}
913
					/* parse end of output line */
914
					if (strstr($line, "END") || strstr($line, "ERROR"))
915
						break;
916
				}
917
	
918
				/* If up, get read/write stats */
919
				if (strcmp($client['status'], "up") == 0) {
920
					fputs($fp, "status 2\n");
921
					/* recv all response lines */
922
					while (!feof($fp)) {
923
						/* read the next line */
924
						$line = fgets($fp, 1024);
925
	
926
						$info = stream_get_meta_data($fp);
927
						if ($info['timed_out'])
928
							break;	
929

    
930
						if (strstr($line,"TCP/UDP read bytes")) {
931
							$list = explode(",", $line);
932
							$client['bytes_recv'] = $list[1];
933
						}
934
	
935
						if (strstr($line,"TCP/UDP write bytes")) {
936
							$list = explode(",", $line);
937
							$client['bytes_sent'] = $list[1];
938
						}
939
	
940
						/* parse end of output line */
941
						if (strstr($line, "END"))
942
							break;
943
					}
944
				}
945
	
946
				fclose($fp);
947
	
948
			} else {
949
				$DisplayNote=true;
950
				$client['remote_host'] = "No Management Daemon";
951
				$client['virtual_addr'] = "See Note Below";
952
				$client['bytes_recv'] = 0;
953
				$client['bytes_sent'] = 0;
954
				$client['connect_time'] = 0;
955
			}
956
	
957
			$clients[] = $client;
958
		}
959
	}
960
	return $clients;
961
}
962

    
963
function openvpn_refresh_crls() {
964
	global $g, $config;
965

    
966
	if (!file_exists($g['varetc_path']."/openvpn"))
967
		return;
968

    
969
	if (is_array($config['openvpn']['openvpn-server'])) {
970
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
971
			if (empty($settings))
972
				continue;
973
			if (isset($settings['disable']))
974
				continue;
975
			// Write the settings for the keys
976
			switch($settings['mode']) {
977
				case 'p2p_tls':
978
				case 'server_tls':
979
				case 'server_tls_user':
980
				case 'server_user':
981
					if (!empty($settings['crlref'])) {
982
						$crl = lookup_crl($settings['crlref']);
983
						crl_update($crl);
984
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
985
						file_put_contents($fpath, base64_decode($crl['text']));
986
						@chmod($fpath, 0644);
987
					}
988
					break;
989
			}
990
		}
991
	}
992
}
993

    
994
?>
(34-34/61)