Project

General

Profile

Download (25.9 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_validate_host($value, $name) {
176
	$value = trim($value);
177
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
178
		return "The field '$name' must contain a valid IP address or domain name.";
179
	return false;
180
}
181

    
182
function openvpn_validate_port($value, $name) {
183
	$value = trim($value);
184
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
185
		return "The field '$name' must contain a valid port, ranging from 0 to 65535.";
186
	return false;
187
}
188

    
189
function openvpn_validate_cidr($value, $name) {
190
	$value = trim($value);
191
	if (!empty($value)) {
192
		list($ip, $mask) = explode('/', $value);
193
		if (!is_ipaddr($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
194
			return "The field '$name' must contain a valid CIDR range.";
195
	}
196
	return false;
197
}
198

    
199
function openvpn_add_dhcpopts(& $settings, & $conf) {
200

    
201
	if (!empty($settings['dns_domain'])) 
202
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
203

    
204
	if (!empty($settings['dns_server1']))
205
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
206
	if (!empty($settings['dns_server2']))
207
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
208
	if (!empty($settings['dns_server3']))
209
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
210
	if (!empty($settings['dns_server4']))
211
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
212

    
213
	if (!empty($settings['ntp_server1']))
214
		$conf .= "push \"dhcp-option NTP {$settings['dhcp_ntp']}\"\n";
215
	if (!empty($settings['ntp_server2']))
216
		$conf .= "push \"dhcp-option NTP {$settings['dhcp_ntp']}\"\n";
217

    
218
	if ($settings['netbios_enable']) {
219

    
220
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
221
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
222
		if (!empty($settings['dhcp_nbtscope'])) 
223
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
224

    
225
		if (!empty($settings['wins_server1']))
226
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
227
		if (!empty($settings['wins_server2']))
228
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
229

    
230
		if (!empty($settings['nbdd_server1']))
231
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
232
	}
233

    
234
	if ($settings['gwredir']) 
235
		$conf .= "push \"redirect-gateway def1\"\n";
236
}
237

    
238
function openvpn_add_custom(& $settings, & $conf) {
239

    
240
	if ($settings['custom_options']) {
241

    
242
		$options = explode(';', $settings['custom_options']);
243

    
244
		if (is_array($options)) {
245
			foreach ($options as $option)
246
				$conf .= "$option\n";
247
		} else
248
			$conf .= "{$settings['custom_options']}\n";
249
	}
250
}
251

    
252
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
253
	global $g;
254

    
255
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
256
	file_put_contents($fpath, base64_decode($data));
257
	//chown($fpath, 'nobody');
258
	//chgrp($fpath, 'nobody');
259
	@chmod($fpath, 0600);
260

    
261
	$conf .= "{$directive} {$fpath} {$opt}\n";
262
}
263

    
264
function openvpn_reconfigure($mode,& $settings) {
265
	global $g, $config;
266

    
267
	if (empty($settings))
268
		return;
269
	if (isset($settings['disable'])) 
270
		return;
271

    
272
	/*
273
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
274
	 * we use a vpnid number which is allocated for a particular client
275
	 * or server configuration. ( see openvpn_vpnid_next() )
276
	 */
277

    
278
	$vpnid = $settings['vpnid'];
279
	$mode_id = $mode.$vpnid;
280

    
281
	if (isset($settings['dev_mode']))
282
		$tunname = "{$settings['dev_mode']}{$vpnid}";
283
	else {	/* defaults to tun */
284
		$tunname = "tun{$vpnid}";
285
		$settings['dev_mode'] = "tun";
286
	}
287

    
288
	if ($mode == "server")
289
		$devname = "ovpns{$vpnid}";
290
	else
291
		$devname = "ovpnc{$vpnid}";
292

    
293
	/* is our device already configured */
294
	if (mwexec("/sbin/ifconfig {$devname}")) {
295

    
296
		/* create the tap device if required */
297
		if (!file_exists("/dev/{$tunname}"))
298
			exec("/sbin/ifconfig {$tunname} create");
299

    
300
		/* rename the device */
301
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
302

    
303
		/* add the device to the openvpn group */
304
		mwexec("/sbin/ifconfig {$devname} group openvpn");
305
	}
306

    
307
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
308
	$proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}");
309
	$cipher = $settings['crypto'];
310

    
311
	$interface = $settings['interface'];
312
	$ipaddr = $settings['ipaddr'];
313

    
314
	// If a specific ip address (VIP) is requested, use it.
315
	// Otherwise, if a specific interface is requested, use it
316
	// If "any" interface was selected, local directive will be ommited.
317
	if (!empty($ipaddr)) {
318
		$iface_ip=$ipaddr;
319
	} else {
320
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
321
			$iface_ip=get_interface_ip($interface);
322
		}
323
	}
324

    
325
	$conf  = "dev {$devname}\n";
326
	$conf .= "dev-type {$settings['dev_mode']}\n";
327
	$conf .= "dev-node /dev/{$tunname}\n";
328
	$conf .= "writepid {$pfile}\n";
329
	$conf .= "#user nobody\n";
330
	$conf .= "#group nobody\n";
331
	$conf .= "script-security 3\n";
332
	$conf .= "daemon\n";
333
	$conf .= "keepalive 10 60\n";
334
	$conf .= "ping-timer-rem\n";
335
	$conf .= "persist-tun\n";
336
	$conf .= "persist-key\n";
337
	$conf .= "proto {$proto}\n";
338
	$conf .= "cipher {$cipher}\n";
339
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
340
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
341

    
342
	if (!empty($iface_ip)) {
343
		$conf .= "local {$iface_ip}\n";	
344
	}
345

    
346
	// server specific settings
347
	if ($mode == 'server') {
348

    
349
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
350
		$mask = gen_subnet_mask($mask);
351

    
352
		// configure tls modes
353
		switch($settings['mode']) {
354
			case 'p2p_tls':
355
			case 'server_tls':
356
			case 'server_user':
357
			case 'server_tls_user':
358
				$conf .= "tls-server\n";
359
				break;
360
		}
361

    
362
		// configure p2p/server modes
363
		switch($settings['mode']) {
364
			case 'p2p_tls':
365
			case 'p2p_shared_key':
366
				$baselong = ip2long32($ip) & ip2long($mask);
367
				$ip1 = long2ip32($baselong + 1);
368
				$ip2 = long2ip32($baselong + 2);
369
				$conf .= "ifconfig $ip1 $ip2\n";
370
				break;
371
			case 'server_tls':
372
			case 'server_user':
373
			case 'server_tls_user':
374
				$conf .= "server {$ip} {$mask}\n";
375
				$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
376
				break;
377
		}
378

    
379
		// configure user auth modes
380
		switch($settings['mode']) {
381
			case 'server_user':
382
				$conf .= "client-cert-not-required\n";
383
			case 'server_tls_user':
384
				$conf .= "username-as-common-name\n";
385
				if (!empty($settings['authmode'])) {
386
					$authcfgs = explode(",", $settings['authmode']);
387
					$sed = "\$authmodes=array(";
388
					$firstsed = 0;
389
					foreach ($authcfgs as $authcfg) {
390
						if ($firstsed > 0)
391
							$sed .= ",";
392
						$firstsed = 1;
393
						$sed .= "\"{$authcfg}\"";
394
					}
395
					$sed .= ");\\\n";
396
					if ($settings['strictusercn'])
397
						$sed .= "\$strictusercn = true;";
398
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
399
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
400
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
401
				}
402
				break;
403
		}
404

    
405
		// The local port to listen on
406
		$conf .= "lport {$settings['local_port']}\n";
407

    
408
		// The management port to listen on
409
		// Use unix socket to overcome the problem on any type of server
410
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
411
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
412

    
413
		if ($settings['maxclients'])
414
			$conf .= "max-clients {$settings['maxclients']}\n";
415

    
416
		// Can we push routes
417
		if ($settings['local_network']) {
418
			list($ip, $mask) = explode('/', $settings['local_network']);
419
			$mask = gen_subnet_mask($mask);
420
			$conf .= "push \"route $ip $mask\"\n";
421
		}
422

    
423
		switch($settings['mode']) {
424
			case 'server_tls':
425
			case 'server_user':
426
			case 'server_tls_user':
427
				// Configure client dhcp options
428
				openvpn_add_dhcpopts($settings, $conf);
429
				if ($settings['client2client'])
430
					$conf .= "client-to-client\n";
431
				break;
432
		}
433
	}
434

    
435
	// client specific settings
436

    
437
	if ($mode == 'client') {
438

    
439
		// configure p2p mode
440
		switch($settings['mode']) {
441
			case 'p2p_tls':
442
				$conf .= "tls-client\n";
443
			case 'shared_key':
444
				$conf .= "client\n";
445
				break;
446
		}
447

    
448
		// If there is no bind option at all (ip and/or port), add "nobind" directive
449
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
450
		//  ensure a random source port.
451
		if ((empty($iface_ip)) && (!$settings['local_port']))
452
			$conf .= "nobind\n";
453
		elseif ($settings['local_port'])
454
			$conf .= "lport {$settings['local_port']}\n";
455
		else
456
			$conf .= "lport 0\n";
457

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

    
461
		// The remote server
462
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
463

    
464
		if (!empty($settings['use_shaper']))
465
			$conf .= "shaper {$settings['use_shaper']}\n";
466

    
467
		if (!empty($settings['tunnel_network'])) {
468
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
469
			$mask = gen_subnet_mask($mask);
470
			$baselong = ip2long32($ip) & ip2long($mask);
471
			$ip1 = long2ip32($baselong + 1);
472
			$ip2 = long2ip32($baselong + 2);
473
			$conf .= "ifconfig $ip2 $ip1\n";
474
		}
475

    
476
		if ($settings['proxy_addr']) {
477
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
478
			if ($settings['proxy_authtype'] != "none") {
479
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
480
				$proxypas = "{$settings['proxy_user']}\n";
481
				$proxypas .= "{$settings['proxy_passwd']}\n";
482
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
483
			}
484
			$conf .= " \n";
485
		}
486
	}
487

    
488
	// Add a remote network route if set
489
	if ($settings['remote_network']) {
490
		list($ip, $mask) = explode('/', $settings['remote_network']);
491
		$mask = gen_subnet_mask($mask);
492
		$conf .= "route $ip $mask\n";
493
	}
494

    
495
	// Write the settings for the keys
496
	switch($settings['mode']) {
497
		case 'p2p_shared_key':
498
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
499
			break;
500
		case 'p2p_tls':
501
		case 'server_tls':
502
		case 'server_tls_user':
503
		case 'server_user':
504
			$ca = lookup_ca($settings['caref']);
505
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
506
			$cert = lookup_cert($settings['certref']);
507
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
508
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
509
			if ($mode == 'server')
510
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
511
			if (!empty($settings['crlref'])) {
512
				$crl = lookup_crl($settings['crlref']);
513
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
514
			}
515
			if ($settings['tls']) {
516
				if (stristr($settings['mode'], "server"))
517
					$tlsopt = 0;
518
				else
519
					$tlsopt = 1;
520
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
521
			}
522
			break;
523
	}
524

    
525
	if ($settings['compression'])
526
		$conf .= "comp-lzo\n";
527

    
528
	if ($settings['passtos'])
529
		$conf .= "passtos\n";
530

    
531
	if ($settings['resolve_retry'])
532
		$conf .= "resolv-retry infinite\n";
533

    
534
	if ($settings['dynamic_ip']) {
535
		$conf .= "persist-remote-ip\n";
536
		$conf .= "float\n";
537
	}
538

    
539
	openvpn_add_custom($settings, $conf);
540

    
541
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
542
	file_put_contents($fpath, $conf);
543
	//chown($fpath, 'nobody');
544
	//chgrp($fpath, 'nobody');
545
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
546
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
547
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
548
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
549
}
550

    
551
function openvpn_restart($mode, & $settings) {
552
	global $g, $config;
553

    
554
	$vpnid = $settings['vpnid'];
555
	$mode_id = $mode.$vpnid;
556

    
557
	/* kill the process if running */
558
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
559
	if (file_exists($pfile)) {
560

    
561
		/* read the pid file */
562
		$pid = rtrim(file_get_contents($pfile));
563
		unlink($pfile);
564

    
565
		/* send a term signal to the process */
566
		posix_kill($pid, SIGTERM);
567

    
568
		/* wait until the process exits */
569
		while(posix_kill($pid, 0))
570
			usleep(250000);
571
	}
572

    
573
	if (isset($settings['disable']))
574
		return;
575

    
576
	/* start the new process */
577
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
578
	mwexec_bg("nohup openvpn --config {$fpath}");
579
	send_event("filter reload");
580
}
581

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

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

    
588
	$tunname = "tun{$vpnid}";
589
	if ($mode == "server")
590
		$devname = "ovpns{$vpnid}";
591
	else
592
		$devname = "ovpnc{$vpnid}";
593

    
594
	/* kill the process if running */
595
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
596
	if (file_exists($pfile)) {
597

    
598
		/* read the pid file */
599
		$pid = trim(file_get_contents($pfile));
600
		unlink($pfile);
601

    
602
		/* send a term signal to the process */
603
		posix_kill($pid, SIGTERM);
604
	}
605

    
606
	/* remove the device from the openvpn group */
607
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
608

    
609
	/* restore the original adapter name */
610
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
611

    
612
	/* remove the configuration files */
613
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
614
}
615

    
616
function openvpn_resync_csc(& $settings) {
617
	global $g, $config;
618

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

    
621
	if (isset($settings['disable'])) {
622
		unlink_if_exists($fpath);
623
		return;
624
	}
625

    
626
	$conf = '';
627
	if ($settings['block'])
628
		$conf .= "disable\n";
629

    
630
	if ($settings['push_reset'])
631
		$conf .= "push-reset\n";
632

    
633
	if (!empty($settings['tunnel_network'])) {
634
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
635
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
636
		$ip1 = long2ip32($baselong + 1);
637
		$ip2 = long2ip32($baselong + 2);
638
		$conf .= "ifconfig-push {$ip1} {$ip2}\n";
639
	}
640

    
641
	openvpn_add_dhcpopts($settings, $conf);
642

    
643
	if ($settings['gwredir'])
644
		$conf .= "push \"redirect-gateway def1\"\n";
645

    
646
	openvpn_add_custom($settings, $conf);
647

    
648
	file_put_contents($fpath, $conf);
649
	chown($fpath, 'nobody');
650
	chgrp($fpath, 'nobody');
651
}
652

    
653
function openvpn_delete_csc(& $settings) {
654
	global $g, $config;
655

    
656
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
657
	unlink_if_exists($fpath);
658
}
659

    
660
// Resync the configuration and restart the VPN
661
function openvpn_resync($mode, & $settings) {
662
	openvpn_reconfigure($mode, $settings);
663
	openvpn_restart($mode, $settings);
664
}
665

    
666
// Resync and restart all VPNs
667
function openvpn_resync_all($interface = "") {
668
	global $g, $config;
669

    
670
	// delay our setup until the system
671
	// has a chance to init our paths
672
	if (!file_exists($g['varetc_path']."/openvpn") ||
673
		!file_exists($g['varetc_path']."/openvpn-csc"))
674
		return;
675

    
676
	if (!is_array($config['openvpn']))
677
		$config['openvpn'] = array();
678

    
679
/*
680
	if (!$config['openvpn']['dh-parameters']) {
681
		echo "Configuring OpenVPN Parameters ...\n";
682
		$dh_parameters = openvpn_create_dhparams(1024);
683
		$dh_parameters = base64_encode($dh_parameters);
684
		$config['openvpn']['dh-parameters'] = $dh_parameters;
685
		write_config("OpenVPN DH parameters");
686
	}
687

    
688
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
689
	if (!file_exists($path_ovdh)) {
690
		$dh_parameters = $config['openvpn']['dh-parameters'];
691
		$dh_parameters = base64_decode($dh_parameters);
692
		file_put_contents($path_ovdh, $dh_parameters);
693
	}
694
*/
695
	if ($interface <> "")
696
		log_error("Resyncing openvpn instances configurations for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
697
	else
698
		log_error("Resyncing openvpn instances configurations."); 
699

    
700
	if (is_array($config['openvpn']['openvpn-server'])) {
701
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
702
			if ($interface <> "" && $interface != $settings['interface'])
703
				continue;
704
			openvpn_resync('server', $settings);
705
		}
706
	}
707

    
708
	if (is_array($config['openvpn']['openvpn-client'])) {
709
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
710
			if ($interface <> "" && $interface != $settings['interface'])
711
				continue;
712
			openvpn_resync('client', $settings);
713
		}
714
	}
715

    
716
	if (is_array($config['openvpn']['openvpn-csc']))
717
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
718
			openvpn_resync_csc($settings);
719

    
720
}
721

    
722
function openvpn_get_active_servers() {
723
	global $config, $g;
724

    
725
	$servers = array();
726
	if (is_array($config['openvpn']['openvpn-server'])) {
727
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
728
	
729
			$prot = $settings['protocol'];
730
			$port = $settings['local_port'];
731
	
732
			$server = array();
733
			$server['port'] = $settings['local_port'];
734
			$server['mode'] = $settings['mode'];
735
			if ($settings['description'])
736
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
737
			else
738
				$server['name'] = "Server {$prot}:{$port}";
739
			$server['conns'] = array();
740
	
741
			$vpnid = $settings['vpnid'];
742
                        $mode_id = "server{$vpnid}";
743
			$server['mgmt'] = $mode_id;
744
                        $tcpsrv = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
745
			$errval;
746
			$errstr;
747
	
748
			/* open a tcp connection to the management port of each server */
749
			$fp = @stream_socket_client($tcpsrv, $errval, $errstr, 1);
750
			if ($fp) {
751
				stream_set_timeout($fp, 1);
752
	
753
				/* send our status request */
754
				fputs($fp, "status 2\n");
755
	
756
				/* recv all response lines */
757
				while (!feof($fp)) {
758
	
759
					/* read the next line */
760
					$line = fgets($fp, 1024);
761
	
762
					$info = stream_get_meta_data($fp);
763
					if ($info['timed_out'])
764
						break;
765

    
766
					/* parse header list line */
767
					if (strstr($line, "HEADER"))
768
						continue;
769
	
770
					/* parse end of output line */
771
					if (strstr($line, "END") || strstr($line, "ERROR"))
772
						break;
773
	
774
					/* parse client list line */
775
					if (strstr($line, "CLIENT_LIST")) {
776
						$list = explode(",", $line);
777
						$conn = array();
778
						$conn['common_name'] = $list[1];
779
						$conn['remote_host'] = $list[2];
780
						$conn['virtual_addr'] = $list[3];
781
						$conn['bytes_recv'] = $list[4];
782
						$conn['bytes_sent'] = $list[5];
783
						$conn['connect_time'] = $list[6];
784
						$server['conns'][] = $conn;
785
					}
786
				}
787
	
788
				/* cleanup */
789
				fclose($fp);
790
			} else {
791
				$conn = array();
792
				$conn['common_name'] = "[error]";
793
				$conn['remote_host'] = "Management Daemon Unreachable";
794
				$conn['virtual_addr'] = "";
795
				$conn['bytes_recv'] = 0;
796
				$conn['bytes_sent'] = 0;
797
				$conn['connect_time'] = 0;
798
				$server['conns'][] = $conn;
799
			}
800
	
801
			$servers[] = $server;
802
		}
803
	}
804
	return $servers;
805
}
806

    
807
function openvpn_get_active_clients() {
808
	global $config, $g;
809

    
810
	$clients = array();
811
	if (is_array($config['openvpn']['openvpn-client'])) {
812
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
813
	
814
			$prot = $settings['protocol'];
815
			$port = $settings['local_port'];
816
	
817
			$client = array();
818
			$client['port'] = $settings['local_port'];
819
			if ($settings['description'])
820
				$client['name'] = "{$settings['description']} {$prot}:{$port}";
821
			else
822
				$client['name'] = "Client {$prot}:{$port}";
823
	
824
			$vpnid = $settings['vpnid'];
825
        		$mode_id = "client{$vpnid}";
826
			$client['mgmt'] = $mode_id;
827
			$tcpcli = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
828
			$errval;
829
			$errstr;
830
	
831
			$client['status']="down";
832
	
833
			/* open a tcp connection to the management port of each cli */
834
			$fp = @stream_socket_client($tcpcli, $errval, $errstr, 1);
835
			if ($fp) {
836
				stream_set_timeout($fp, 1);
837
				/* send our status request */
838
				fputs($fp, "state 1\n");
839
	
840
				/* recv all response lines */
841
				while (!feof($fp)) {
842
					/* read the next line */
843
					$line = fgets($fp, 1024);
844
					
845
					$info = stream_get_meta_data($fp);
846
					if ($info['timed_out'])
847
						break;	
848

    
849
					/* Get the client state */
850
					if (strstr($line,"CONNECTED")) {
851
						$client['status']="up";
852
						$list = explode(",", $line);
853
	
854
						$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
855
						$client['virtual_addr']  = $list[3];
856
						$client['remote_host'] = $list[4];
857
					}
858
					/* parse end of output line */
859
					if (strstr($line, "END") || strstr($line, "ERROR"))
860
						break;
861
				}
862
	
863
				/* If up, get read/write stats */
864
				if (strcmp($client['status'], "up") == 0) {
865
					fputs($fp, "status 2\n");
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
						if (strstr($line,"TCP/UDP read bytes")) {
876
							$list = explode(",", $line);
877
							$client['bytes_recv'] = $list[1];
878
						}
879
	
880
						if (strstr($line,"TCP/UDP write bytes")) {
881
							$list = explode(",", $line);
882
							$client['bytes_sent'] = $list[1];
883
						}
884
	
885
						/* parse end of output line */
886
						if (strstr($line, "END"))
887
							break;
888
					}
889
				}
890
	
891
				fclose($fp);
892
	
893
			} else {
894
				$DisplayNote=true;
895
				$client['remote_host'] = "No Management Daemon";
896
				$client['virtual_addr'] = "See Note Below";
897
				$client['bytes_recv'] = 0;
898
				$client['bytes_sent'] = 0;
899
				$client['connect_time'] = 0;
900
			}
901
	
902
			$clients[] = $client;
903
		}
904
	}
905
	return $clients;
906
}
907

    
908
function openvpn_refresh_crls() {
909
	global $g, $config;
910

    
911
	if (!file_exists($g['varetc_path']."/openvpn"))
912
		return;
913

    
914
	if (is_array($config['openvpn']['openvpn-server'])) {
915
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
916
			if (empty($settings))
917
				continue;
918
			if (isset($settings['disable']))
919
				continue;
920
			// Write the settings for the keys
921
			switch($settings['mode']) {
922
				case 'p2p_tls':
923
				case 'server_tls':
924
				case 'server_tls_user':
925
				case 'server_user':
926
					if (!empty($settings['crlref'])) {
927
						$crl = lookup_crl($settings['crlref']);
928
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
929
						file_put_contents($fpath, base64_decode($crl['text']));
930
						@chmod($fpath, 0644);
931
					}
932
					break;
933
			}
934
		}
935
	}
936
}
937

    
938
?>
(29-29/54)