Project

General

Profile

Download (28.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, and only for p2p modes.
541
	if ((substr($settings['mode'], 0, 3) == "p2p") && is_subnet($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
	if ($g['platform'] == 'jail')
726
		return;
727
	// delay our setup until the system
728
	// has a chance to init our paths
729
	if (!file_exists($g['varetc_path']."/openvpn") ||
730
		!file_exists($g['varetc_path']."/openvpn-csc"))
731
		return;
732

    
733
	if (!is_array($config['openvpn']))
734
		$config['openvpn'] = array();
735

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

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

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

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

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

    
777
}
778

    
779
function openvpn_get_active_servers($type="multipoint") {
780
	global $config, $g;
781

    
782
	$servers = array();
783
	if (is_array($config['openvpn']['openvpn-server'])) {
784
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
785
			if (empty($settings) || isset($settings['disable']))
786
				continue;
787

    
788
			$prot = $settings['protocol'];
789
			$port = $settings['local_port'];
790
	
791
			$server = array();
792
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
793
			$server['mode'] = $settings['mode'];
794
			if ($settings['description'])
795
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
796
			else
797
				$server['name'] = "Server {$prot}:{$port}";
798
			$server['conns'] = array();
799
	
800
			$vpnid = $settings['vpnid'];
801
			$mode_id = "server{$vpnid}";
802
			$server['mgmt'] = $mode_id;
803
			$socket = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
804
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
805

    
806
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
807
				$servers[] = openvpn_get_client_status($server, $socket);
808
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
809
				$servers[] = openvpn_get_server_status($server, $socket);
810

    
811
		}
812
	}
813
	return $servers;
814
}
815

    
816
function openvpn_get_server_status($server, $socket) {
817
	$errval;
818
	$errstr;
819
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
820
	if ($fp) {
821
		stream_set_timeout($fp, 1);
822

    
823
		/* send our status request */
824
		fputs($fp, "status 2\n");
825

    
826
		/* recv all response lines */
827
		while (!feof($fp)) {
828

    
829
			/* read the next line */
830
			$line = fgets($fp, 1024);
831

    
832
			$info = stream_get_meta_data($fp);
833
			if ($info['timed_out'])
834
				break;
835

    
836
			/* parse header list line */
837
			if (strstr($line, "HEADER"))
838
				continue;
839

    
840
			/* parse end of output line */
841
			if (strstr($line, "END") || strstr($line, "ERROR"))
842
				break;
843

    
844
			/* parse client list line */
845
			if (strstr($line, "CLIENT_LIST")) {
846
				$list = explode(",", $line);
847
				$conn = array();
848
				$conn['common_name'] = $list[1];
849
				$conn['remote_host'] = $list[2];
850
				$conn['virtual_addr'] = $list[3];
851
				$conn['bytes_recv'] = $list[4];
852
				$conn['bytes_sent'] = $list[5];
853
				$conn['connect_time'] = $list[6];
854
				$server['conns'][] = $conn;
855
			}
856
		}
857

    
858
		/* cleanup */
859
		fclose($fp);
860
	} else {
861
		$conn = array();
862
		$conn['common_name'] = "[error]";
863
		$conn['remote_host'] = "Management Daemon Unreachable";
864
		$conn['virtual_addr'] = "";
865
		$conn['bytes_recv'] = 0;
866
		$conn['bytes_sent'] = 0;
867
		$conn['connect_time'] = 0;
868
		$server['conns'][] = $conn;
869
	}
870
	return $server;
871
}
872

    
873
function openvpn_get_active_clients() {
874
	global $config, $g;
875

    
876
	$clients = array();
877
	if (is_array($config['openvpn']['openvpn-client'])) {
878
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
879
	
880
			if (empty($settings) || isset($settings['disable']))
881
				continue;
882

    
883
			$prot = $settings['protocol'];
884
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
885
	
886
			$client = array();
887
			$client['port'] = $settings['local_port'];
888
			if ($settings['description'])
889
				$client['name'] = "{$settings['description']} {$prot}{$port}";
890
			else
891
				$client['name'] = "Client {$prot}{$port}";
892
	
893
			$vpnid = $settings['vpnid'];
894
			$mode_id = "client{$vpnid}";
895
			$client['mgmt'] = $mode_id;
896
			$socket = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
897
			$client['status']="down";
898

    
899
			$clients[] = openvpn_get_client_status($client, $socket);
900
		}
901
	}
902
	return $clients;
903
}
904

    
905
function openvpn_get_client_status($client, $socket) {
906
	$errval;
907
	$errstr;
908
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
909
	if ($fp) {
910
		stream_set_timeout($fp, 1);
911
		/* send our status request */
912
		fputs($fp, "state 1\n");
913

    
914
		/* recv all response lines */
915
		while (!feof($fp)) {
916
			/* read the next line */
917
			$line = fgets($fp, 1024);
918

    
919
			$info = stream_get_meta_data($fp);
920
			if ($info['timed_out'])
921
				break;
922

    
923
			/* Get the client state */
924
			if (strstr($line,"CONNECTED")) {
925
				$client['status']="up";
926
				$list = explode(",", $line);
927

    
928
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
929
				$client['virtual_addr']  = $list[3];
930
				$client['remote_host'] = $list[4];
931
			}
932
			if (strstr($line,"CONNECTING")) {
933
				$client['status']="connecting";
934
			}
935
			if (strstr($line,"ASSIGN_IP")) {
936
				$client['status']="waiting";
937
				$list = explode(",", $line);
938

    
939
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
940
				$client['virtual_addr']  = $list[3];
941
			}
942
			if (strstr($line,"RECONNECTING")) {
943
				$client['status']="reconnecting";
944
				$list = explode(",", $line);
945

    
946
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
947
				$client['status'] .= "; " . $list[2];
948
			}
949
			/* parse end of output line */
950
			if (strstr($line, "END") || strstr($line, "ERROR"))
951
				break;
952
		}
953

    
954
		/* If up, get read/write stats */
955
		if (strcmp($client['status'], "up") == 0) {
956
			fputs($fp, "status 2\n");
957
			/* recv all response lines */
958
			while (!feof($fp)) {
959
				/* read the next line */
960
				$line = fgets($fp, 1024);
961

    
962
				$info = stream_get_meta_data($fp);
963
				if ($info['timed_out'])
964
					break;
965

    
966
				if (strstr($line,"TCP/UDP read bytes")) {
967
					$list = explode(",", $line);
968
					$client['bytes_recv'] = $list[1];
969
				}
970

    
971
				if (strstr($line,"TCP/UDP write bytes")) {
972
					$list = explode(",", $line);
973
					$client['bytes_sent'] = $list[1];
974
				}
975

    
976
				/* parse end of output line */
977
				if (strstr($line, "END"))
978
					break;
979
			}
980
		}
981

    
982
		fclose($fp);
983

    
984
	} else {
985
		$DisplayNote=true;
986
		$client['remote_host'] = "No Management Daemon";
987
		$client['virtual_addr'] = "See Note Below";
988
		$client['bytes_recv'] = 0;
989
		$client['bytes_sent'] = 0;
990
		$client['connect_time'] = 0;
991
	}
992
	return $client;
993
}
994

    
995
function openvpn_refresh_crls() {
996
	global $g, $config;
997

    
998
	if (!file_exists($g['varetc_path']."/openvpn"))
999
		return;
1000

    
1001
	if (is_array($config['openvpn']['openvpn-server'])) {
1002
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1003
			if (empty($settings))
1004
				continue;
1005
			if (isset($settings['disable']))
1006
				continue;
1007
			// Write the settings for the keys
1008
			switch($settings['mode']) {
1009
				case 'p2p_tls':
1010
				case 'server_tls':
1011
				case 'server_tls_user':
1012
				case 'server_user':
1013
					if (!empty($settings['crlref'])) {
1014
						$crl = lookup_crl($settings['crlref']);
1015
						crl_update($crl);
1016
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1017
						file_put_contents($fpath, base64_decode($crl['text']));
1018
						@chmod($fpath, 0644);
1019
					}
1020
					break;
1021
			}
1022
		}
1023
	}
1024
}
1025

    
1026
?>
(34-34/61)