Project

General

Profile

Download (27.4 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' => "Peer to Peer ( SSL/TLS )",
76
	'p2p_shared_key' => "Peer to Peer ( Shared Key )",
77
	'server_tls' => "Remote Access ( SSL/TLS )",
78
	'server_user' => "Remote Access ( User Auth )",
79
	'server_tls_user' => "Remote Access ( SSL/TLS + User Auth )");
80

    
81
$openvpn_client_modes = array(
82
	'p2p_tls' => "Peer to Peer ( SSL/TLS )",
83
	'p2p_shared_key' => "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"] = "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 "The field '$name' must contain a valid IP address or domain 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 "The field '$name' must contain a valid port, ranging from 0 to 65535.";
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 "The field '$name' must contain a valid CIDR range.";
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

    
332
	// If a specific ip address (VIP) is requested, use it.
333
	// Otherwise, if a specific interface is requested, use it
334
	// If "any" interface was selected, local directive will be ommited.
335
	if (!empty($ipaddr)) {
336
		$iface_ip=$ipaddr;
337
	} else {
338
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
339
			$iface_ip=get_interface_ip($interface);
340
		}
341
	}
342

    
343
	$conf  = "dev {$devname}\n";
344
	$conf .= "dev-type {$settings['dev_mode']}\n";
345
	$conf .= "dev-node /dev/{$tunname}\n";
346
	$conf .= "writepid {$pfile}\n";
347
	$conf .= "#user nobody\n";
348
	$conf .= "#group nobody\n";
349
	$conf .= "script-security 3\n";
350
	$conf .= "daemon\n";
351
	$conf .= "keepalive 10 60\n";
352
	$conf .= "ping-timer-rem\n";
353
	$conf .= "persist-tun\n";
354
	$conf .= "persist-key\n";
355
	$conf .= "proto {$proto}\n";
356
	$conf .= "cipher {$cipher}\n";
357
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
358
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
359

    
360
	if (!empty($iface_ip)) {
361
		$conf .= "local {$iface_ip}\n";	
362
	}
363

    
364
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
365
		$conf .= "engine {$settings['engine']}\n";
366

    
367
	// server specific settings
368
	if ($mode == 'server') {
369

    
370
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
371
		$mask = gen_subnet_mask($cidr);
372

    
373
		// configure tls modes
374
		switch($settings['mode']) {
375
			case 'p2p_tls':
376
			case 'server_tls':
377
			case 'server_user':
378
			case 'server_tls_user':
379
				$conf .= "tls-server\n";
380
				break;
381
		}
382

    
383
		// configure p2p/server modes
384
		switch($settings['mode']) {
385
			case 'p2p_tls':
386
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
387
				//  use the server directive. It works for a single client without it.
388
				//  See ticket #1417
389
				if ($cidr < 30) {
390
					$conf .= "server {$ip} {$mask}\n";
391
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
392
				}
393
			case 'p2p_shared_key':
394
				$baselong = ip2long32($ip) & ip2long($mask);
395
				$ip1 = long2ip32($baselong + 1);
396
				$ip2 = long2ip32($baselong + 2);
397
				$conf .= "ifconfig $ip1 $ip2\n";
398
				break;
399
			case 'server_tls':
400
			case 'server_user':
401
			case 'server_tls_user':
402
				$conf .= "server {$ip} {$mask}\n";
403
				$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
404
				break;
405
		}
406

    
407
		// configure user auth modes
408
		switch($settings['mode']) {
409
			case 'server_user':
410
				$conf .= "client-cert-not-required\n";
411
			case 'server_tls_user':
412
				$conf .= "username-as-common-name\n";
413
				if (!empty($settings['authmode'])) {
414
					$authcfgs = explode(",", $settings['authmode']);
415
					$sed = "\$authmodes=array(";
416
					$firstsed = 0;
417
					foreach ($authcfgs as $authcfg) {
418
						if ($firstsed > 0)
419
							$sed .= ",";
420
						$firstsed = 1;
421
						$sed .= "\"{$authcfg}\"";
422
					}
423
					$sed .= ");\\\n";
424
					if ($settings['strictusercn'])
425
						$sed .= "\$strictusercn = true;";
426
					$sed .= " \$modeid = \"{$mode_id}\";";
427
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
428
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
429
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
430
				}
431
				break;
432
		}
433

    
434
		// The local port to listen on
435
		$conf .= "lport {$settings['local_port']}\n";
436

    
437
		// The management port to listen on
438
		// Use unix socket to overcome the problem on any type of server
439
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
440
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
441

    
442
		if ($settings['maxclients'])
443
			$conf .= "max-clients {$settings['maxclients']}\n";
444

    
445
		// Can we push routes
446
		if ($settings['local_network']) {
447
			list($ip, $mask) = explode('/', $settings['local_network']);
448
			$mask = gen_subnet_mask($mask);
449
			$conf .= "push \"route $ip $mask\"\n";
450
		}
451

    
452
		switch($settings['mode']) {
453
			case 'server_tls':
454
			case 'server_user':
455
			case 'server_tls_user':
456
				// Configure client dhcp options
457
				openvpn_add_dhcpopts($settings, $conf);
458
				if ($settings['client2client'])
459
					$conf .= "client-to-client\n";
460
				break;
461
		}
462
		if (isset($settings['duplicate_cn']))
463
			$conf .= "duplicate-cn\n";
464
	}
465

    
466
	// client specific settings
467

    
468
	if ($mode == 'client') {
469

    
470
		// configure p2p mode
471
		switch($settings['mode']) {
472
			case 'p2p_tls':
473
				$conf .= "tls-client\n";
474
			case 'shared_key':
475
				$conf .= "client\n";
476
				break;
477
		}
478

    
479
		// If there is no bind option at all (ip and/or port), add "nobind" directive
480
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
481
		//  ensure a random source port.
482
		if ((empty($iface_ip)) && (!$settings['local_port']))
483
			$conf .= "nobind\n";
484
		elseif ($settings['local_port'])
485
			$conf .= "lport {$settings['local_port']}\n";
486
		else
487
			$conf .= "lport 0\n";
488

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

    
492
		// The remote server
493
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
494

    
495
		if (!empty($settings['use_shaper']))
496
			$conf .= "shaper {$settings['use_shaper']}\n";
497

    
498
		if (!empty($settings['tunnel_network'])) {
499
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
500
			$mask = gen_subnet_mask($mask);
501
			$baselong = ip2long32($ip) & ip2long($mask);
502
			$ip1 = long2ip32($baselong + 1);
503
			$ip2 = long2ip32($baselong + 2);
504
			$conf .= "ifconfig $ip2 $ip1\n";
505
		}
506

    
507
		if ($settings['proxy_addr']) {
508
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
509
			if ($settings['proxy_authtype'] != "none") {
510
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
511
				$proxypas = "{$settings['proxy_user']}\n";
512
				$proxypas .= "{$settings['proxy_passwd']}\n";
513
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
514
			}
515
			$conf .= " \n";
516
		}
517
	}
518

    
519
	// Add a remote network route if set, and only for p2p modes.
520
	if ((substr($settings['mode'], 0, 3) == "p2p") && is_subnet($settings['remote_network'])) {
521
		list($ip, $mask) = explode('/', $settings['remote_network']);
522
		$mask = gen_subnet_mask($mask);
523
		$conf .= "route $ip $mask\n";
524
	}
525

    
526
	// Write the settings for the keys
527
	switch($settings['mode']) {
528
		case 'p2p_shared_key':
529
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
530
			break;
531
		case 'p2p_tls':
532
		case 'server_tls':
533
		case 'server_tls_user':
534
		case 'server_user':
535
			$ca = lookup_ca($settings['caref']);
536
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
537
			$cert = lookup_cert($settings['certref']);
538
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
539
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
540
			if ($mode == 'server')
541
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
542
			if (!empty($settings['crlref'])) {
543
				$crl = lookup_crl($settings['crlref']);
544
				crl_update($crl);
545
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
546
			}
547
			if ($settings['tls']) {
548
				if ($mode == "server") 
549
					$tlsopt = 0;
550
				else
551
					$tlsopt = 1;
552
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
553
			}
554
			break;
555
	}
556

    
557
	if ($settings['compression'])
558
		$conf .= "comp-lzo\n";
559

    
560
	if ($settings['passtos'])
561
		$conf .= "passtos\n";
562

    
563
	if ($settings['resolve_retry'])
564
		$conf .= "resolv-retry infinite\n";
565

    
566
	if ($settings['dynamic_ip']) {
567
		$conf .= "persist-remote-ip\n";
568
		$conf .= "float\n";
569
	}
570

    
571
	openvpn_add_custom($settings, $conf);
572

    
573
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
574
	file_put_contents($fpath, $conf);
575
	//chown($fpath, 'nobody');
576
	//chgrp($fpath, 'nobody');
577
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
578
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
579
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
580
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
581
}
582

    
583
function openvpn_restart($mode, $settings) {
584
	global $g, $config;
585

    
586
	$vpnid = $settings['vpnid'];
587
	$mode_id = $mode.$vpnid;
588

    
589
	/* kill the process if running */
590
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
591
	if (file_exists($pfile)) {
592

    
593
		/* read the pid file */
594
		$pid = rtrim(file_get_contents($pfile));
595
		unlink($pfile);
596

    
597
		/* send a term signal to the process */
598
		posix_kill($pid, SIGTERM);
599

    
600
		/* wait until the process exits */
601
		while(posix_kill($pid, 0))
602
			usleep(250000);
603
	}
604

    
605
	if (isset($settings['disable']))
606
		return;
607

    
608
	/* start the new process */
609
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
610
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
611

    
612
	if (!$g['booting'])
613
		send_event("filter reload");
614
}
615

    
616
function openvpn_delete($mode, & $settings) {
617
	global $g, $config;
618

    
619
	$vpnid = $settings['vpnid'];
620
	$mode_id = $mode.$vpnid;
621

    
622
	$tunname = "tun{$vpnid}";
623
	if ($mode == "server")
624
		$devname = "ovpns{$vpnid}";
625
	else
626
		$devname = "ovpnc{$vpnid}";
627

    
628
	/* kill the process if running */
629
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
630
	if (file_exists($pfile)) {
631

    
632
		/* read the pid file */
633
		$pid = trim(file_get_contents($pfile));
634
		unlink($pfile);
635

    
636
		/* send a term signal to the process */
637
		posix_kill($pid, SIGTERM);
638
	}
639

    
640
	/* remove the device from the openvpn group */
641
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
642

    
643
	/* restore the original adapter name */
644
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
645

    
646
	/* remove the configuration files */
647
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
648
}
649

    
650
function openvpn_resync_csc(& $settings) {
651
	global $g, $config;
652

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

    
655
	if (isset($settings['disable'])) {
656
		unlink_if_exists($fpath);
657
		return;
658
	}
659

    
660
	$conf = '';
661
	if ($settings['block'])
662
		$conf .= "disable\n";
663

    
664
	if ($settings['push_reset'])
665
		$conf .= "push-reset\n";
666

    
667
	if (!empty($settings['tunnel_network'])) {
668
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
669
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
670
		$ip1 = long2ip32($baselong + 1);
671
		$ip2 = long2ip32($baselong + 2);
672
		$conf .= "ifconfig-push {$ip1} {$ip2}\n";
673
	}
674

    
675
	openvpn_add_dhcpopts($settings, $conf);
676

    
677
	if ($settings['gwredir'])
678
		$conf .= "push \"redirect-gateway def1\"\n";
679

    
680
	openvpn_add_custom($settings, $conf);
681

    
682
	file_put_contents($fpath, $conf);
683
	chown($fpath, 'nobody');
684
	chgrp($fpath, 'nobody');
685
}
686

    
687
function openvpn_delete_csc(& $settings) {
688
	global $g, $config;
689

    
690
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
691
	unlink_if_exists($fpath);
692
}
693

    
694
// Resync the configuration and restart the VPN
695
function openvpn_resync($mode, $settings) {
696
	openvpn_reconfigure($mode, $settings);
697
	openvpn_restart($mode, $settings);
698
}
699

    
700
// Resync and restart all VPNs
701
function openvpn_resync_all($interface = "") {
702
	global $g, $config;
703

    
704
	// delay our setup until the system
705
	// has a chance to init our paths
706
	if (!file_exists($g['varetc_path']."/openvpn") ||
707
		!file_exists($g['varetc_path']."/openvpn-csc"))
708
		return;
709

    
710
	if (!is_array($config['openvpn']))
711
		$config['openvpn'] = array();
712

    
713
/*
714
	if (!$config['openvpn']['dh-parameters']) {
715
		echo "Configuring OpenVPN Parameters ...\n";
716
		$dh_parameters = openvpn_create_dhparams(1024);
717
		$dh_parameters = base64_encode($dh_parameters);
718
		$config['openvpn']['dh-parameters'] = $dh_parameters;
719
		write_config("OpenVPN DH parameters");
720
	}
721

    
722
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
723
	if (!file_exists($path_ovdh)) {
724
		$dh_parameters = $config['openvpn']['dh-parameters'];
725
		$dh_parameters = base64_decode($dh_parameters);
726
		file_put_contents($path_ovdh, $dh_parameters);
727
	}
728
*/
729
	if ($interface <> "")
730
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
731
	else
732
		log_error("Resyncing OpenVPN instances."); 
733

    
734
	if (is_array($config['openvpn']['openvpn-server'])) {
735
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
736
			if ($interface <> "" && $interface != $settings['interface'])
737
				continue;
738
			openvpn_resync('server', $settings);
739
		}
740
	}
741

    
742
	if (is_array($config['openvpn']['openvpn-client'])) {
743
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
744
			if ($interface <> "" && $interface != $settings['interface'])
745
				continue;
746
			openvpn_resync('client', $settings);
747
		}
748
	}
749

    
750
	if (is_array($config['openvpn']['openvpn-csc']))
751
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
752
			openvpn_resync_csc($settings);
753

    
754
}
755

    
756
function openvpn_get_active_servers($type="ssl") {
757
	global $config, $g;
758

    
759
	$servers = array();
760
	if (is_array($config['openvpn']['openvpn-server'])) {
761
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
762
			if (empty($settings) || isset($settings['disable']))
763
				continue;
764

    
765
			$prot = $settings['protocol'];
766
			$port = $settings['local_port'];
767
	
768
			$server = array();
769
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
770
			$server['mode'] = $settings['mode'];
771
			if ($settings['description'])
772
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
773
			else
774
				$server['name'] = "Server {$prot}:{$port}";
775
			$server['conns'] = array();
776
	
777
			$vpnid = $settings['vpnid'];
778
			$mode_id = "server{$vpnid}";
779
			$server['mgmt'] = $mode_id;
780
			$socket = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
781
			if (($server['mode'] == "p2p_shared_key") && ($type == "sharedkey"))
782
				$servers[] = openvpn_get_client_status($server, $socket);
783
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "ssl"))
784
				$servers[] = openvpn_get_server_status($server, $socket);
785
		}
786
	}
787
	return $servers;
788
}
789

    
790
function openvpn_get_server_status($server, $socket) {
791
	$errval;
792
	$errstr;
793
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
794
	if ($fp) {
795
		stream_set_timeout($fp, 1);
796

    
797
		/* send our status request */
798
		fputs($fp, "status 2\n");
799

    
800
		/* recv all response lines */
801
		while (!feof($fp)) {
802

    
803
			/* read the next line */
804
			$line = fgets($fp, 1024);
805

    
806
			$info = stream_get_meta_data($fp);
807
			if ($info['timed_out'])
808
				break;
809

    
810
			/* parse header list line */
811
			if (strstr($line, "HEADER"))
812
				continue;
813

    
814
			/* parse end of output line */
815
			if (strstr($line, "END") || strstr($line, "ERROR"))
816
				break;
817

    
818
			/* parse client list line */
819
			if (strstr($line, "CLIENT_LIST")) {
820
				$list = explode(",", $line);
821
				$conn = array();
822
				$conn['common_name'] = $list[1];
823
				$conn['remote_host'] = $list[2];
824
				$conn['virtual_addr'] = $list[3];
825
				$conn['bytes_recv'] = $list[4];
826
				$conn['bytes_sent'] = $list[5];
827
				$conn['connect_time'] = $list[6];
828
				$server['conns'][] = $conn;
829
			}
830
		}
831

    
832
		/* cleanup */
833
		fclose($fp);
834
	} else {
835
		$conn = array();
836
		$conn['common_name'] = "[error]";
837
		$conn['remote_host'] = "Management Daemon Unreachable";
838
		$conn['virtual_addr'] = "";
839
		$conn['bytes_recv'] = 0;
840
		$conn['bytes_sent'] = 0;
841
		$conn['connect_time'] = 0;
842
		$server['conns'][] = $conn;
843
	}
844
	return $server;
845
}
846

    
847
function openvpn_get_active_clients() {
848
	global $config, $g;
849

    
850
	$clients = array();
851
	if (is_array($config['openvpn']['openvpn-client'])) {
852
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
853
	
854
			if (empty($settings) || isset($settings['disable']))
855
				continue;
856

    
857
			$prot = $settings['protocol'];
858
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
859
	
860
			$client = array();
861
			$client['port'] = $settings['local_port'];
862
			if ($settings['description'])
863
				$client['name'] = "{$settings['description']} {$prot}{$port}";
864
			else
865
				$client['name'] = "Client {$prot}{$port}";
866
	
867
			$vpnid = $settings['vpnid'];
868
			$mode_id = "client{$vpnid}";
869
			$client['mgmt'] = $mode_id;
870
			$socket = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
871
			$client['status']="down";
872

    
873
			$clients[] = openvpn_get_client_status($client, $socket);
874
		}
875
	}
876
	return $clients;
877
}
878

    
879
function openvpn_get_client_status($client, $socket) {
880
	$errval;
881
	$errstr;
882
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
883
	if ($fp) {
884
		stream_set_timeout($fp, 1);
885
		/* send our status request */
886
		fputs($fp, "state 1\n");
887

    
888
		/* recv all response lines */
889
		while (!feof($fp)) {
890
			/* read the next line */
891
			$line = fgets($fp, 1024);
892

    
893
			$info = stream_get_meta_data($fp);
894
			if ($info['timed_out'])
895
				break;
896

    
897
			/* Get the client state */
898
			if (strstr($line,"CONNECTED")) {
899
				$client['status']="up";
900
				$list = explode(",", $line);
901

    
902
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
903
				$client['virtual_addr']  = $list[3];
904
				$client['remote_host'] = $list[4];
905
			}
906
			/* parse end of output line */
907
			if (strstr($line, "END") || strstr($line, "ERROR"))
908
				break;
909
		}
910

    
911
		/* If up, get read/write stats */
912
		if (strcmp($client['status'], "up") == 0) {
913
			fputs($fp, "status 2\n");
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
				if (strstr($line,"TCP/UDP read bytes")) {
924
					$list = explode(",", $line);
925
					$client['bytes_recv'] = $list[1];
926
				}
927

    
928
				if (strstr($line,"TCP/UDP write bytes")) {
929
					$list = explode(",", $line);
930
					$client['bytes_sent'] = $list[1];
931
				}
932

    
933
				/* parse end of output line */
934
				if (strstr($line, "END"))
935
					break;
936
			}
937
		}
938

    
939
		fclose($fp);
940

    
941
	} else {
942
		$DisplayNote=true;
943
		$client['remote_host'] = "No Management Daemon";
944
		$client['virtual_addr'] = "See Note Below";
945
		$client['bytes_recv'] = 0;
946
		$client['bytes_sent'] = 0;
947
		$client['connect_time'] = 0;
948
	}
949
	return $client;
950
}
951

    
952
function openvpn_refresh_crls() {
953
	global $g, $config;
954

    
955
	if (!file_exists($g['varetc_path']."/openvpn"))
956
		return;
957

    
958
	if (is_array($config['openvpn']['openvpn-server'])) {
959
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
960
			if (empty($settings))
961
				continue;
962
			if (isset($settings['disable']))
963
				continue;
964
			// Write the settings for the keys
965
			switch($settings['mode']) {
966
				case 'p2p_tls':
967
				case 'server_tls':
968
				case 'server_tls_user':
969
				case 'server_user':
970
					if (!empty($settings['crlref'])) {
971
						$crl = lookup_crl($settings['crlref']);
972
						crl_update($crl);
973
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
974
						file_put_contents($fpath, base64_decode($crl['text']));
975
						@chmod($fpath, 0644);
976
					}
977
					break;
978
			}
979
		}
980
	}
981
}
982

    
983
?>
(34-34/61)