Project

General

Profile

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

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

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

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

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

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

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

    
461
	// client specific settings
462

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
565
	openvpn_add_custom($settings, $conf);
566

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
669
	openvpn_add_dhcpopts($settings, $conf);
670

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

    
674
	openvpn_add_custom($settings, $conf);
675

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

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

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

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

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

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

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

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

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

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

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

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

    
748
}
749

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

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

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

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

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

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

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

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

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

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

    
967
?>
(34-34/61)