Project

General

Profile

Download (26.7 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'])
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'])
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('openvpn --show-ciphers | grep "default key" | 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, $mask) = explode('/', $settings['tunnel_network']);
371
		$mask = gen_subnet_mask($mask);
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
				$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
387
			case 'p2p_shared_key':
388
				$baselong = ip2long32($ip) & ip2long($mask);
389
				$ip1 = long2ip32($baselong + 1);
390
				$ip2 = long2ip32($baselong + 2);
391
				$conf .= "ifconfig $ip1 $ip2\n";
392
				break;
393
			case 'server_tls':
394
			case 'server_user':
395
			case 'server_tls_user':
396
				$conf .= "server {$ip} {$mask}\n";
397
				$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
398
				break;
399
		}
400

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

    
428
		// The local port to listen on
429
		$conf .= "lport {$settings['local_port']}\n";
430

    
431
		// The management port to listen on
432
		// Use unix socket to overcome the problem on any type of server
433
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
434
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
435

    
436
		if ($settings['maxclients'])
437
			$conf .= "max-clients {$settings['maxclients']}\n";
438

    
439
		// Can we push routes
440
		if ($settings['local_network']) {
441
			list($ip, $mask) = explode('/', $settings['local_network']);
442
			$mask = gen_subnet_mask($mask);
443
			$conf .= "push \"route $ip $mask\"\n";
444
		}
445

    
446
		switch($settings['mode']) {
447
			case 'server_tls':
448
			case 'server_user':
449
			case 'server_tls_user':
450
				// Configure client dhcp options
451
				openvpn_add_dhcpopts($settings, $conf);
452
				if ($settings['client2client'])
453
					$conf .= "client-to-client\n";
454
				break;
455
		}
456
		if (isset($settings['duplicate_cn']))
457
			$conf .= "duplicate-cn\n";
458
	}
459

    
460
	// client specific settings
461

    
462
	if ($mode == 'client') {
463

    
464
		// configure p2p mode
465
		switch($settings['mode']) {
466
			case 'p2p_tls':
467
				$conf .= "tls-client\n";
468
			case 'shared_key':
469
				$conf .= "client\n";
470
				break;
471
		}
472

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

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

    
486
		// The remote server
487
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
488

    
489
		if (!empty($settings['use_shaper']))
490
			$conf .= "shaper {$settings['use_shaper']}\n";
491

    
492
		if (!empty($settings['tunnel_network'])) {
493
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
494
			$mask = gen_subnet_mask($mask);
495
			$baselong = ip2long32($ip) & ip2long($mask);
496
			$ip1 = long2ip32($baselong + 1);
497
			$ip2 = long2ip32($baselong + 2);
498
			$conf .= "ifconfig $ip2 $ip1\n";
499
		}
500

    
501
		if ($settings['proxy_addr']) {
502
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
503
			if ($settings['proxy_authtype'] != "none") {
504
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
505
				$proxypas = "{$settings['proxy_user']}\n";
506
				$proxypas .= "{$settings['proxy_passwd']}\n";
507
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
508
			}
509
			$conf .= " \n";
510
		}
511
	}
512

    
513
	// Add a remote network route if set
514
	if ($settings['remote_network']) {
515
		list($ip, $mask) = explode('/', $settings['remote_network']);
516
		$mask = gen_subnet_mask($mask);
517
		$conf .= "route $ip $mask\n";
518
	}
519

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

    
550
	if ($settings['compression'])
551
		$conf .= "comp-lzo\n";
552

    
553
	if ($settings['passtos'])
554
		$conf .= "passtos\n";
555

    
556
	if ($settings['resolve_retry'])
557
		$conf .= "resolv-retry infinite\n";
558

    
559
	if ($settings['dynamic_ip']) {
560
		$conf .= "persist-remote-ip\n";
561
		$conf .= "float\n";
562
	}
563

    
564
	openvpn_add_custom($settings, $conf);
565

    
566
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
567
	file_put_contents($fpath, $conf);
568
	//chown($fpath, 'nobody');
569
	//chgrp($fpath, 'nobody');
570
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
571
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
572
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
573
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
574
}
575

    
576
function openvpn_restart($mode, $settings) {
577
	global $g, $config;
578

    
579
	$vpnid = $settings['vpnid'];
580
	$mode_id = $mode.$vpnid;
581

    
582
	/* kill the process if running */
583
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
584
	if (file_exists($pfile)) {
585

    
586
		/* read the pid file */
587
		$pid = rtrim(file_get_contents($pfile));
588
		unlink($pfile);
589

    
590
		/* send a term signal to the process */
591
		posix_kill($pid, SIGTERM);
592

    
593
		/* wait until the process exits */
594
		while(posix_kill($pid, 0))
595
			usleep(250000);
596
	}
597

    
598
	if (isset($settings['disable']))
599
		return;
600

    
601
	/* start the new process */
602
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
603
	mwexec_bg("nohup openvpn --config {$fpath}");
604

    
605
	if (!$g['booting'])
606
		send_event("filter reload");
607
}
608

    
609
function openvpn_delete($mode, & $settings) {
610
	global $g, $config;
611

    
612
	$vpnid = $settings['vpnid'];
613
	$mode_id = $mode.$vpnid;
614

    
615
	$tunname = "tun{$vpnid}";
616
	if ($mode == "server")
617
		$devname = "ovpns{$vpnid}";
618
	else
619
		$devname = "ovpnc{$vpnid}";
620

    
621
	/* kill the process if running */
622
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
623
	if (file_exists($pfile)) {
624

    
625
		/* read the pid file */
626
		$pid = trim(file_get_contents($pfile));
627
		unlink($pfile);
628

    
629
		/* send a term signal to the process */
630
		posix_kill($pid, SIGTERM);
631
	}
632

    
633
	/* remove the device from the openvpn group */
634
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
635

    
636
	/* restore the original adapter name */
637
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
638

    
639
	/* remove the configuration files */
640
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
641
}
642

    
643
function openvpn_resync_csc(& $settings) {
644
	global $g, $config;
645

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

    
648
	if (isset($settings['disable'])) {
649
		unlink_if_exists($fpath);
650
		return;
651
	}
652

    
653
	$conf = '';
654
	if ($settings['block'])
655
		$conf .= "disable\n";
656

    
657
	if ($settings['push_reset'])
658
		$conf .= "push-reset\n";
659

    
660
	if (!empty($settings['tunnel_network'])) {
661
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
662
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
663
		$ip1 = long2ip32($baselong + 1);
664
		$ip2 = long2ip32($baselong + 2);
665
		$conf .= "ifconfig-push {$ip1} {$ip2}\n";
666
	}
667

    
668
	openvpn_add_dhcpopts($settings, $conf);
669

    
670
	if ($settings['gwredir'])
671
		$conf .= "push \"redirect-gateway def1\"\n";
672

    
673
	openvpn_add_custom($settings, $conf);
674

    
675
	file_put_contents($fpath, $conf);
676
	chown($fpath, 'nobody');
677
	chgrp($fpath, 'nobody');
678
}
679

    
680
function openvpn_delete_csc(& $settings) {
681
	global $g, $config;
682

    
683
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
684
	unlink_if_exists($fpath);
685
}
686

    
687
// Resync the configuration and restart the VPN
688
function openvpn_resync($mode, $settings) {
689
	openvpn_reconfigure($mode, $settings);
690
	openvpn_restart($mode, $settings);
691
}
692

    
693
// Resync and restart all VPNs
694
function openvpn_resync_all($interface = "") {
695
	global $g, $config;
696

    
697
	// delay our setup until the system
698
	// has a chance to init our paths
699
	if (!file_exists($g['varetc_path']."/openvpn") ||
700
		!file_exists($g['varetc_path']."/openvpn-csc"))
701
		return;
702

    
703
	if (!is_array($config['openvpn']))
704
		$config['openvpn'] = array();
705

    
706
/*
707
	if (!$config['openvpn']['dh-parameters']) {
708
		echo "Configuring OpenVPN Parameters ...\n";
709
		$dh_parameters = openvpn_create_dhparams(1024);
710
		$dh_parameters = base64_encode($dh_parameters);
711
		$config['openvpn']['dh-parameters'] = $dh_parameters;
712
		write_config("OpenVPN DH parameters");
713
	}
714

    
715
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
716
	if (!file_exists($path_ovdh)) {
717
		$dh_parameters = $config['openvpn']['dh-parameters'];
718
		$dh_parameters = base64_decode($dh_parameters);
719
		file_put_contents($path_ovdh, $dh_parameters);
720
	}
721
*/
722
	if ($interface <> "")
723
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
724
	else
725
		log_error("Resyncing OpenVPN instances."); 
726

    
727
	if (is_array($config['openvpn']['openvpn-server'])) {
728
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
729
			if ($interface <> "" && $interface != $settings['interface'])
730
				continue;
731
			openvpn_resync('server', $settings);
732
		}
733
	}
734

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

    
743
	if (is_array($config['openvpn']['openvpn-csc']))
744
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
745
			openvpn_resync_csc($settings);
746

    
747
}
748

    
749
function openvpn_get_active_servers() {
750
	global $config, $g;
751

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

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

    
834
function openvpn_get_active_clients() {
835
	global $config, $g;
836

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

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

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

    
935
function openvpn_refresh_crls() {
936
	global $g, $config;
937

    
938
	if (!file_exists($g['varetc_path']."/openvpn"))
939
		return;
940

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

    
965
?>
(34-34/61)