Project

General

Profile

Download (24.8 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2

    
3
/* $Id$ */
4
/*
5
	$RCSfile$
6
	
7
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
8
	All rights reserved.
9
	
10
	Copyright (C) 2006  Fernando Lemos
11
	All rights reserved.
12

    
13
	This file was rewritten from scratch by Fernando Lemos but
14
	*MIGHT* contain code previously written by:
15

    
16
	Copyright (C) 2005 Peter Allgeyer <allgeyer_AT_web.de>
17
	All rights reserved.
18

    
19
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
20
	All rights reserved.
21

    
22
	Redistribution and use in source and binary forms, with or without
23
	modification, are permitted provided that the following conditions are met:
24

    
25
	1. Redistributions of source code must retain the above copyright notices,
26
	   this list of conditions and the following disclaimer.
27

    
28
	2. Redistributions in binary form must reproduce the above copyright
29
	   notices, this list of conditions and the following disclaimer in the
30
	   documentation and/or other materials provided with the distribution.
31

    
32
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
34
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
35
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
36
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
	POSSIBILITY OF SUCH DAMAGE.
42
	
43
	DISABLE_PHP_LINT_CHECKING
44
	
45
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/bin/openssl	/sbin/ifconfig
46
	pfSense_MODULE:	openvpn
47

    
48
*/
49
require_once('config.inc');
50
require_once("certs.inc");
51
require_once('pfsense-utils.inc');
52
require_once("auth.inc");
53

    
54
$openvpn_prots = array("UDP", "TCP");
55

    
56
$openvpn_dev_mode = array("tun", "tap");
57

    
58
/* 
59
 * The User Auth mode below is disabled because
60
 * OpenVPN erroneously requires that we provide
61
 * a CA configuration parameter. In this mode,
62
 * clients don't send a certificate so there is
63
 * no need for a CA. If we require that admins
64
 * provide one in the pfSense UI due to a bogus
65
 * requirement imposed by OpenVPN, it could be
66
 * considered very confusing ( I know I was ).
67
 *
68
 * -mgrooms
69
 */
70

    
71
$openvpn_dh_lengths = array(
72
	1024, 2048, 4096 );
73

    
74
$openvpn_server_modes = array(
75
	'p2p_tls' => "Peer to Peer ( SSL/TLS )",
76
	'p2p_shared_key' => "Peer to Peer ( Shared Key )",
77
	'server_tls' => "Remote Access ( SSL/TLS )",
78
	'server_user' => "Remote Access ( User Auth )",
79
	'server_tls_user' => "Remote Access ( SSL/TLS + User Auth )");
80

    
81
$openvpn_client_modes = array(
82
	'p2p_tls' => "Peer to Peer ( SSL/TLS )",
83
	'p2p_shared_key' => "Peer to Peer ( Shared Key )" );
84

    
85
function openvpn_create_key() {
86

    
87
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
88
	if (!$fp)
89
		return false;
90

    
91
	$rslt = stream_get_contents($fp);
92
	pclose($fp);
93

    
94
	return $rslt;
95
}
96

    
97
function openvpn_create_dhparams($bits) {
98

    
99
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
100
	if (!$fp)
101
		return false;
102

    
103
	$rslt = stream_get_contents($fp);
104
	pclose($fp);
105

    
106
	return $rslt;
107
}
108

    
109
function openvpn_vpnid_used($vpnid) {
110
	global $config;
111

    
112
	if (is_array($config['openvpn']['openvpn-server']))
113
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
114
			if ($vpnid == $settings['vpnid'])
115
				return true;
116

    
117
	if (is_array($config['openvpn']['openvpn-client']))
118
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
119
			if ($vpnid == $settings['vpnid'])
120
				return true;
121

    
122
	return false;
123
}
124

    
125
function openvpn_vpnid_next() {
126

    
127
	$vpnid = 1;
128
	while(openvpn_vpnid_used($vpnid))
129
		$vpnid++;
130

    
131
	return $vpnid;
132
}
133

    
134
function openvpn_port_used($prot, $port) {
135
	global $config;
136

    
137
	if (is_array($config['openvpn']['openvpn-server']))
138
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
139
			if ($port == $settings['local_port'] &&
140
				$prot == $settings['protocol'])
141
				return $settings['vpnid'];
142

    
143
	if (is_array($config['openvpn']['openvpn-client']))
144
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
145
			if ($port == $settings['local_port'] &&
146
				$prot == $settings['protocol'])
147
				return $settings['vpnid'];
148

    
149
	return 0;
150
}
151

    
152
function openvpn_port_next($prot) {
153

    
154
	$port = 1194;
155
	while(openvpn_port_used($prot, $port))
156
		$port++;
157

    
158
	return $port;
159
}
160

    
161
function openvpn_get_cipherlist() {
162

    
163
	$ciphers = array();
164
	$cipher_out = shell_exec('openvpn --show-ciphers | grep "default key" | awk \'{print $1, "(" $2 "-" $3 ")";}\'');
165
	$cipher_lines = explode("\n", trim($cipher_out));
166
	sort($cipher_lines);
167
	foreach ($cipher_lines as $line) {
168
		$words = explode(' ', $line);
169
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
170
	}
171
	$ciphers["none"] = "None (No Encryption)";
172
	return $ciphers;
173
}
174

    
175
function openvpn_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 .= ");";
396
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
397
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
398
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
399
				}
400
				break;
401
		}
402

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

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

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

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

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

    
433
	// client specific settings
434

    
435
	if ($mode == 'client') {
436

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

    
446
		// The port we'll listen at
447
		// If local_port is used, bind the management port
448
		if ($settings['local_port']) {
449
			$conf .= "lport {$settings['local_port']}\n";
450
			// Use unix socket to overcome the problem on any type of server
451
			$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
452
			//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
453
		}
454

    
455
		// If there is no bind option at all (ip and/or port), add "nobind" directive
456
		if ((empty($iface_ip)) && (!$settings['local_port'])) {
457
			$conf .= "nobind\n";
458
		}
459

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

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

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

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

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

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

    
522
	if ($settings['compression'])
523
		$conf .= "comp-lzo\n";
524

    
525
	if ($settings['passtos'])
526
		$conf .= "passtos\n";
527

    
528
	if ($settings['resolve_retry'])
529
		$conf .= "resolv-retry infinite\n";
530

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

    
536
	openvpn_add_custom($settings, $conf);
537

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

    
548
function openvpn_restart($mode, & $settings) {
549
	global $g, $config;
550

    
551
	$vpnid = $settings['vpnid'];
552
	$mode_id = $mode.$vpnid;
553

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

    
558
		/* read the pid file */
559
		$pid = rtrim(file_get_contents($pfile));
560
		unlink($pfile);
561

    
562
		/* send a term signal to the process */
563
		posix_kill($pid, SIGTERM);
564

    
565
		/* wait until the process exits */
566
		while(posix_kill($pid, 0))
567
			usleep(250000);
568
	}
569

    
570
	if (isset($settings['disable']))
571
		return;
572

    
573
	/* start the new process */
574
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
575
	mwexec_bg("nohup openvpn --config {$fpath}");
576
	touch("{$g['tmp_path']}/filter_dirty");
577
}
578

    
579
function openvpn_delete($mode, & $settings) {
580
	global $g, $config;
581

    
582
	$vpnid = $settings['vpnid'];
583
	$mode_id = $mode.$vpnid;
584

    
585
	$tunname = "tun{$vpnid}";
586
	if ($mode == "server")
587
		$devname = "ovpns{$vpnid}";
588
	else
589
		$devname = "ovpnc{$vpnid}";
590

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

    
595
		/* read the pid file */
596
		$pid = trim(file_get_contents($pfile));
597
		unlink($pfile);
598

    
599
		/* send a term signal to the process */
600
		posix_kill($pid, SIGTERM);
601
	}
602

    
603
	/* remove the device from the openvpn group */
604
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
605

    
606
	/* restore the original adapter name */
607
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
608

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

    
613
function openvpn_resync_csc(& $settings) {
614
	global $g, $config;
615

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

    
618
	if (isset($settings['disable'])) {
619
		unlink_if_exists($fpath);
620
		return;
621
	}
622

    
623
	$conf = '';
624
	if ($settings['block'])
625
		$conf .= "disable\n";
626

    
627
	if ($settings['push_reset'])
628
		$conf .= "push-reset\n";
629

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

    
638
	openvpn_add_dhcpopts($settings, $conf);
639

    
640
	if ($settings['gwredir'])
641
		$conf .= "push \"redirect-gateway def1\"\n";
642

    
643
	openvpn_add_custom($settings, $conf);
644

    
645
	file_put_contents($fpath, $conf);
646
	chown($fpath, 'nobody');
647
	chgrp($fpath, 'nobody');
648
}
649

    
650
function openvpn_delete_csc(& $settings) {
651
	global $g, $config;
652

    
653
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
654
	unlink_if_exists($fpath);
655
}
656

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

    
663
// Resync and restart all VPNs
664
function openvpn_resync_all($interface = "") {
665
	global $g, $config;
666

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

    
673
	if (!is_array($config['openvpn']))
674
		$config['openvpn'] = array();
675

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

    
685
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
686
	if (!file_exists($path_ovdh)) {
687
		$dh_parameters = $config['openvpn']['dh-parameters'];
688
		$dh_parameters = base64_decode($dh_parameters);
689
		file_put_contents($path_ovdh, $dh_parameters);
690
	}
691
*/
692

    
693
	if (is_array($config['openvpn']['openvpn-server'])) {
694
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
695
			if (!empty($interface) && $interface != $settings['interface'])
696
				continue;
697
			openvpn_resync('server', $settings);
698
		}
699
	}
700

    
701
	if (is_array($config['openvpn']['openvpn-client'])) {
702
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
703
			if (!empty($interface) && $interface != $settings['interface'])
704
				continue;
705
			openvpn_resync('client', $settings);
706
		}
707
	}
708

    
709
	if (is_array($config['openvpn']['openvpn-csc']))
710
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
711
			openvpn_resync_csc($settings);
712

    
713
}
714

    
715
function openvpn_get_active_servers() {
716
	global $config, $g;
717

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

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

    
800
function openvpn_get_active_clients() {
801
	global $config, $g;
802

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

    
842
					/* Get the client state */
843
					if (strstr($line,"CONNECTED")) {
844
						$client['status']="up";
845
						$list = explode(",", $line);
846
	
847
						$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
848
						$client['virtual_addr']  = $list[3];
849
						$client['remote_host'] = $list[4];
850
					}
851
					/* parse end of output line */
852
					if (strstr($line, "END") || strstr($line, "ERROR"))
853
						break;
854
				}
855
	
856
				/* If up, get read/write stats */
857
				if (strcmp($client['status'], "up") == 0) {
858
					fputs($fp, "status 2\n");
859
					/* recv all response lines */
860
					while (!feof($fp)) {
861
						/* read the next line */
862
						$line = fgets($fp, 1024);
863
	
864
						$info = stream_get_meta_data($fp);
865
						if ($info['timed_out'])
866
							break;	
867

    
868
						if (strstr($line,"TCP/UDP read bytes")) {
869
							$list = explode(",", $line);
870
							$client['bytes_recv'] = $list[1];
871
						}
872
	
873
						if (strstr($line,"TCP/UDP write bytes")) {
874
							$list = explode(",", $line);
875
							$client['bytes_sent'] = $list[1];
876
						}
877
	
878
						/* parse end of output line */
879
						if (strstr($line, "END"))
880
							break;
881
					}
882
				}
883
	
884
				fclose($fp);
885
	
886
			} else {
887
				$DisplayNote=true;
888
				$client['remote_host'] = "No Management Daemon";
889
				$client['virtual_addr'] = "See Note Below";
890
				$client['bytes_recv'] = 0;
891
				$client['bytes_sent'] = 0;
892
				$client['connect_time'] = 0;
893
			}
894
	
895
			$clients[] = $client;
896
		}
897
	}
898
	return $clients;
899
}
900
?>
(29-29/54)