Project

General

Profile

Download (26.6 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
	$cipher = $settings['crypto'];
327

    
328
	$interface = $settings['interface'];
329
	$ipaddr = $settings['ipaddr'];
330

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

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

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

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

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

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

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

    
382
		// configure p2p/server modes
383
		switch($settings['mode']) {
384
			case 'p2p_tls':
385
			case 'p2p_shared_key':
386
				$baselong = ip2long32($ip) & ip2long($mask);
387
				$ip1 = long2ip32($baselong + 1);
388
				$ip2 = long2ip32($baselong + 2);
389
				$conf .= "ifconfig $ip1 $ip2\n";
390
				break;
391
			case 'server_tls':
392
			case 'server_user':
393
			case 'server_tls_user':
394
				$conf .= "server {$ip} {$mask}\n";
395
				$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
396
				break;
397
		}
398

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

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

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

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

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

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

    
458
	// client specific settings
459

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
562
	openvpn_add_custom($settings, $conf);
563

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
666
	openvpn_add_dhcpopts($settings, $conf);
667

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

    
671
	openvpn_add_custom($settings, $conf);
672

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

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

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

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

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

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

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

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

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

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

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

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

    
745
}
746

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

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

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

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

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

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

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

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

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

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

    
963
?>
(34-34/61)