Project

General

Profile

Download (27.1 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
520
	if ($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
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
545
			}
546
			if ($settings['tls']) {
547
				if ($mode == "server") 
548
					$tlsopt = 0;
549
				else
550
					$tlsopt = 1;
551
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
552
			}
553
			break;
554
	}
555

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

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

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

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

    
570
	openvpn_add_custom($settings, $conf);
571

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
674
	openvpn_add_dhcpopts($settings, $conf);
675

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

    
679
	openvpn_add_custom($settings, $conf);
680

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

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

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

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

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

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

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

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

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

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

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

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

    
753
}
754

    
755
function openvpn_get_active_servers() {
756
	global $config, $g;
757

    
758
	$servers = array();
759
	if (is_array($config['openvpn']['openvpn-server'])) {
760
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
761
	
762
			$prot = $settings['protocol'];
763
			$port = $settings['local_port'];
764
	
765
			$server = array();
766
			$server['port'] = $settings['local_port'];
767
			$server['mode'] = $settings['mode'];
768
			if ($settings['description'])
769
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
770
			else
771
				$server['name'] = "Server {$prot}:{$port}";
772
			$server['conns'] = array();
773
	
774
			$vpnid = $settings['vpnid'];
775
                        $mode_id = "server{$vpnid}";
776
			$server['mgmt'] = $mode_id;
777
                        $tcpsrv = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
778
			$errval;
779
			$errstr;
780
	
781
			/* open a tcp connection to the management port of each server */
782
			$fp = @stream_socket_client($tcpsrv, $errval, $errstr, 1);
783
			if ($fp) {
784
				stream_set_timeout($fp, 1);
785
	
786
				/* send our status request */
787
				fputs($fp, "status 2\n");
788
	
789
				/* recv all response lines */
790
				while (!feof($fp)) {
791
	
792
					/* read the next line */
793
					$line = fgets($fp, 1024);
794
	
795
					$info = stream_get_meta_data($fp);
796
					if ($info['timed_out'])
797
						break;
798

    
799
					/* parse header list line */
800
					if (strstr($line, "HEADER"))
801
						continue;
802
	
803
					/* parse end of output line */
804
					if (strstr($line, "END") || strstr($line, "ERROR"))
805
						break;
806
	
807
					/* parse client list line */
808
					if (strstr($line, "CLIENT_LIST")) {
809
						$list = explode(",", $line);
810
						$conn = array();
811
						$conn['common_name'] = $list[1];
812
						$conn['remote_host'] = $list[2];
813
						$conn['virtual_addr'] = $list[3];
814
						$conn['bytes_recv'] = $list[4];
815
						$conn['bytes_sent'] = $list[5];
816
						$conn['connect_time'] = $list[6];
817
						$server['conns'][] = $conn;
818
					}
819
				}
820
	
821
				/* cleanup */
822
				fclose($fp);
823
			} else {
824
				$conn = array();
825
				$conn['common_name'] = "[error]";
826
				$conn['remote_host'] = "Management Daemon Unreachable";
827
				$conn['virtual_addr'] = "";
828
				$conn['bytes_recv'] = 0;
829
				$conn['bytes_sent'] = 0;
830
				$conn['connect_time'] = 0;
831
				$server['conns'][] = $conn;
832
			}
833
	
834
			$servers[] = $server;
835
		}
836
	}
837
	return $servers;
838
}
839

    
840
function openvpn_get_active_clients() {
841
	global $config, $g;
842

    
843
	$clients = array();
844
	if (is_array($config['openvpn']['openvpn-client'])) {
845
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
846
	
847
			$prot = $settings['protocol'];
848
			$port = $settings['local_port'];
849
	
850
			$client = array();
851
			$client['port'] = $settings['local_port'];
852
			if ($settings['description'])
853
				$client['name'] = "{$settings['description']} {$prot}:{$port}";
854
			else
855
				$client['name'] = "Client {$prot}:{$port}";
856
	
857
			$vpnid = $settings['vpnid'];
858
        		$mode_id = "client{$vpnid}";
859
			$client['mgmt'] = $mode_id;
860
			$tcpcli = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
861
			$errval;
862
			$errstr;
863
	
864
			$client['status']="down";
865
	
866
			/* open a tcp connection to the management port of each cli */
867
			$fp = @stream_socket_client($tcpcli, $errval, $errstr, 1);
868
			if ($fp) {
869
				stream_set_timeout($fp, 1);
870
				/* send our status request */
871
				fputs($fp, "state 1\n");
872
	
873
				/* recv all response lines */
874
				while (!feof($fp)) {
875
					/* read the next line */
876
					$line = fgets($fp, 1024);
877
					
878
					$info = stream_get_meta_data($fp);
879
					if ($info['timed_out'])
880
						break;	
881

    
882
					/* Get the client state */
883
					if (strstr($line,"CONNECTED")) {
884
						$client['status']="up";
885
						$list = explode(",", $line);
886
	
887
						$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
888
						$client['virtual_addr']  = $list[3];
889
						$client['remote_host'] = $list[4];
890
					}
891
					/* parse end of output line */
892
					if (strstr($line, "END") || strstr($line, "ERROR"))
893
						break;
894
				}
895
	
896
				/* If up, get read/write stats */
897
				if (strcmp($client['status'], "up") == 0) {
898
					fputs($fp, "status 2\n");
899
					/* recv all response lines */
900
					while (!feof($fp)) {
901
						/* read the next line */
902
						$line = fgets($fp, 1024);
903
	
904
						$info = stream_get_meta_data($fp);
905
						if ($info['timed_out'])
906
							break;	
907

    
908
						if (strstr($line,"TCP/UDP read bytes")) {
909
							$list = explode(",", $line);
910
							$client['bytes_recv'] = $list[1];
911
						}
912
	
913
						if (strstr($line,"TCP/UDP write bytes")) {
914
							$list = explode(",", $line);
915
							$client['bytes_sent'] = $list[1];
916
						}
917
	
918
						/* parse end of output line */
919
						if (strstr($line, "END"))
920
							break;
921
					}
922
				}
923
	
924
				fclose($fp);
925
	
926
			} else {
927
				$DisplayNote=true;
928
				$client['remote_host'] = "No Management Daemon";
929
				$client['virtual_addr'] = "See Note Below";
930
				$client['bytes_recv'] = 0;
931
				$client['bytes_sent'] = 0;
932
				$client['connect_time'] = 0;
933
			}
934
	
935
			$clients[] = $client;
936
		}
937
	}
938
	return $clients;
939
}
940

    
941
function openvpn_refresh_crls() {
942
	global $g, $config;
943

    
944
	if (!file_exists($g['varetc_path']."/openvpn"))
945
		return;
946

    
947
	if (is_array($config['openvpn']['openvpn-server'])) {
948
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
949
			if (empty($settings))
950
				continue;
951
			if (isset($settings['disable']))
952
				continue;
953
			// Write the settings for the keys
954
			switch($settings['mode']) {
955
				case 'p2p_tls':
956
				case 'server_tls':
957
				case 'server_tls_user':
958
				case 'server_user':
959
					if (!empty($settings['crlref'])) {
960
						$crl = lookup_crl($settings['crlref']);
961
						crl_update($crl);
962
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
963
						file_put_contents($fpath, base64_decode($crl['text']));
964
						@chmod($fpath, 0644);
965
					}
966
					break;
967
			}
968
		}
969
	}
970
}
971

    
972
?>
(34-34/61)