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

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

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

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

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

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

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

    
459
	// client specific settings
460

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
563
	openvpn_add_custom($settings, $conf);
564

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
667
	openvpn_add_dhcpopts($settings, $conf);
668

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

    
672
	openvpn_add_custom($settings, $conf);
673

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

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

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

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

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

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

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

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

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

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

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

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

    
746
}
747

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

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

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

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

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

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

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

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

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

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

    
964
?>
(34-34/61)