Project

General

Profile

Download (31.1 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_cert_depths = array(
75
	1 => "One (Client+Server)",
76
	2 => "Two (Client+Intermediate+Server)",
77
	3 => "Three (Client+2xIntermediate+Server)",
78
	4 => "Four (Client+3xIntermediate+Server)",
79
	5 => "Five (Client+4xIntermediate+Server)"
80
);
81

    
82
$openvpn_server_modes = array(
83
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
84
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
85
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
86
	'server_user' => gettext("Remote Access ( User Auth )"),
87
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
88

    
89
$openvpn_client_modes = array(
90
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
91
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )") );
92

    
93
function openvpn_create_key() {
94

    
95
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
96
	if (!$fp)
97
		return false;
98

    
99
	$rslt = stream_get_contents($fp);
100
	pclose($fp);
101

    
102
	return $rslt;
103
}
104

    
105
function openvpn_create_dhparams($bits) {
106

    
107
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
108
	if (!$fp)
109
		return false;
110

    
111
	$rslt = stream_get_contents($fp);
112
	pclose($fp);
113

    
114
	return $rslt;
115
}
116

    
117
function openvpn_vpnid_used($vpnid) {
118
	global $config;
119

    
120
	if (is_array($config['openvpn']['openvpn-server']))
121
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
122
			if ($vpnid == $settings['vpnid'])
123
				return true;
124

    
125
	if (is_array($config['openvpn']['openvpn-client']))
126
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
127
			if ($vpnid == $settings['vpnid'])
128
				return true;
129

    
130
	return false;
131
}
132

    
133
function openvpn_vpnid_next() {
134

    
135
	$vpnid = 1;
136
	while(openvpn_vpnid_used($vpnid))
137
		$vpnid++;
138

    
139
	return $vpnid;
140
}
141

    
142
function openvpn_port_used($prot, $port) {
143
	global $config;
144

    
145
	if (is_array($config['openvpn']['openvpn-server']))
146
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
147
			if ($port == $settings['local_port'] &&
148
				$prot == $settings['protocol'] && !isset($settings['disable']))
149
				return $settings['vpnid'];
150

    
151
	if (is_array($config['openvpn']['openvpn-client']))
152
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
153
			if ($port == $settings['local_port'] &&
154
				$prot == $settings['protocol'] && !isset($settings['disable']))
155
				return $settings['vpnid'];
156

    
157
	return 0;
158
}
159

    
160
function openvpn_port_next($prot) {
161

    
162
	$port = 1194;
163
	while(openvpn_port_used($prot, $port))
164
		$port++;
165

    
166
	return $port;
167
}
168

    
169
function openvpn_get_cipherlist() {
170

    
171
	$ciphers = array();
172
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
173
	$cipher_lines = explode("\n", trim($cipher_out));
174
	sort($cipher_lines);
175
	foreach ($cipher_lines as $line) {
176
		$words = explode(' ', $line);
177
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
178
	}
179
	$ciphers["none"] = gettext("None (No Encryption)");
180
	return $ciphers;
181
}
182

    
183
function openvpn_get_engines() {
184
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
185
	exec("/usr/bin/openssl engine", $openssl_engine_output);
186
	foreach ($openssl_engine_output as $oeo) {
187
		$linematch = array();
188
		preg_match("/\((.*)\)\s(.*)/", $oeo, $linematch);
189
		if ($linematch[1] != "dynamic")
190
			$openssl_engines[$linematch[1]] = $linematch[2];
191
	}
192
	return $openssl_engines;
193
}
194

    
195
function openvpn_validate_engine($engine) {
196
	$engines = openvpn_get_engines();
197
	return array_key_exists($engine, $engines);
198
}
199

    
200
function openvpn_validate_host($value, $name) {
201
	$value = trim($value);
202
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
203
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
204
	return false;
205
}
206

    
207
function openvpn_validate_port($value, $name) {
208
	$value = trim($value);
209
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
210
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
211
	return false;
212
}
213

    
214
function openvpn_validate_cidr($value, $name) {
215
	$value = trim($value);
216
	if (!empty($value)) {
217
		list($ip, $mask) = explode('/', $value);
218
		if (!is_ipaddr($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
219
			return sprintf(gettext("The field '%s' must contain a valid CIDR range."), $name);
220
	}
221
	return false;
222
}
223

    
224
function openvpn_add_dhcpopts(& $settings, & $conf) {
225

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

    
229
	if (!empty($settings['dns_server1']))
230
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
231
	if (!empty($settings['dns_server2']))
232
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
233
	if (!empty($settings['dns_server3']))
234
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
235
	if (!empty($settings['dns_server4']))
236
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
237

    
238
	if (!empty($settings['ntp_server1']))
239
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
240
	if (!empty($settings['ntp_server2']))
241
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
242

    
243
	if ($settings['netbios_enable']) {
244

    
245
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
246
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
247
		if (!empty($settings['dhcp_nbtscope'])) 
248
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
249

    
250
		if (!empty($settings['wins_server1']))
251
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
252
		if (!empty($settings['wins_server2']))
253
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
254

    
255
		if (!empty($settings['nbdd_server1']))
256
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
257
	}
258

    
259
	if ($settings['gwredir']) 
260
		$conf .= "push \"redirect-gateway def1\"\n";
261
}
262

    
263
function openvpn_add_custom(& $settings, & $conf) {
264

    
265
	if ($settings['custom_options']) {
266

    
267
		$options = explode(';', $settings['custom_options']);
268

    
269
		if (is_array($options)) {
270
			foreach ($options as $option)
271
				$conf .= "$option\n";
272
		} else
273
			$conf .= "{$settings['custom_options']}\n";
274
	}
275
}
276

    
277
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
278
	global $g;
279

    
280
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
281
	file_put_contents($fpath, base64_decode($data));
282
	//chown($fpath, 'nobody');
283
	//chgrp($fpath, 'nobody');
284
	@chmod($fpath, 0600);
285

    
286
	$conf .= "{$directive} {$fpath} {$opt}\n";
287
}
288

    
289
function openvpn_reconfigure($mode, $settings) {
290
	global $g, $config;
291

    
292
	if (empty($settings))
293
		return;
294
	if (isset($settings['disable'])) 
295
		return;
296

    
297
	/*
298
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
299
	 * we use a vpnid number which is allocated for a particular client
300
	 * or server configuration. ( see openvpn_vpnid_next() )
301
	 */
302

    
303
	$vpnid = $settings['vpnid'];
304
	$mode_id = $mode.$vpnid;
305

    
306
	if (isset($settings['dev_mode']))
307
		$tunname = "{$settings['dev_mode']}{$vpnid}";
308
	else {	/* defaults to tun */
309
		$tunname = "tun{$vpnid}";
310
		$settings['dev_mode'] = "tun";
311
	}
312

    
313
	if ($mode == "server")
314
		$devname = "ovpns{$vpnid}";
315
	else
316
		$devname = "ovpnc{$vpnid}";
317

    
318
	/* is our device already configured */
319
	if (mwexec("/sbin/ifconfig {$devname}")) {
320

    
321
		/* create the tap device if required */
322
		if (!file_exists("/dev/{$tunname}"))
323
			exec("/sbin/ifconfig {$tunname} create");
324

    
325
		/* rename the device */
326
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
327

    
328
		/* add the device to the openvpn group */
329
		mwexec("/sbin/ifconfig {$devname} group openvpn");
330
	}
331

    
332
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
333
	$proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}");
334
	$dev_mode = $settings['dev_mode'];
335
	$cipher = $settings['crypto'];
336

    
337
	$interface = $settings['interface'];
338
	$ipaddr = $settings['ipaddr'];
339
	$ipaddrv6 = $settings['ipaddrv6'];
340

    
341
	// If a specific ip address (VIP) is requested, use it.
342
	// Otherwise, if a specific interface is requested, use it
343
	// If "any" interface was selected, local directive will be ommited.
344
	if (is_ipaddrv4($ipaddr)) {
345
		$iface_ip=$ipaddr;
346
	} elseif (is_ipaddrv6($ipaddrv6)) {
347
		$iface_ipv6=$ipaddrv6;
348
	} else {
349
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
350
			$iface_ip=get_interface_ip($interface);
351
		}
352
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
353
			$iface_ipv6=get_interface_ipv6($interface);
354
		}
355
	}
356

    
357
	$conf  = "dev {$devname}\n";
358
	$conf .= "dev-type {$settings['dev_mode']}\n";
359
	switch($settings['dev_mode']) {
360
		case "tun":
361
			$conf .= "tun-ipv6\n";
362
			break;
363
	}
364
	$conf .= "dev-node /dev/{$tunname}\n";
365
	$conf .= "writepid {$pfile}\n";
366
	$conf .= "#user nobody\n";
367
	$conf .= "#group nobody\n";
368
	$conf .= "script-security 3\n";
369
	$conf .= "daemon\n";
370
	$conf .= "keepalive 10 60\n";
371
	$conf .= "ping-timer-rem\n";
372
	$conf .= "persist-tun\n";
373
	$conf .= "persist-key\n";
374
	$conf .= "proto {$proto}\n";
375
	$conf .= "cipher {$cipher}\n";
376
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
377
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
378

    
379
	if (is_ipaddrv4($iface_ip)) {
380
		$conf .= "local {$iface_ip}\n";	
381
	}
382
	if (is_ipaddrv6($iface_ipv6)) {
383
		// $conf .= "local {$iface_ipv6}\n";	
384
	}
385

    
386
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
387
		$conf .= "engine {$settings['engine']}\n";
388

    
389
	// server specific settings
390
	if ($mode == 'server') {
391

    
392
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
393
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
394
		$mask = gen_subnet_mask($cidr);
395

    
396
		// configure tls modes
397
		switch($settings['mode']) {
398
			case 'p2p_tls':
399
			case 'server_tls':
400
			case 'server_user':
401
			case 'server_tls_user':
402
				$conf .= "tls-server\n";
403
				break;
404
		}
405

    
406
		// configure p2p/server modes
407
		switch($settings['mode']) {
408
			case 'p2p_tls':
409
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
410
				//  use the server directive. It works for a single client without it.
411
				//  See ticket #1417
412
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
413
					$conf .= "server {$ip} {$mask}\n";
414
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
415
				}
416
			case 'p2p_shared_key':
417
				if (!empty($ip) && !empty($mask)) {
418
					$baselong = ip2long32($ip) & ip2long($mask);
419
					$ip1 = long2ip32($baselong + 1);
420
					$ip2 = long2ip32($baselong + 2);
421
					if ($settings['dev_mode'] == 'tun')
422
						$conf .= "ifconfig {$ip1} {$ip2}\n";
423
					else
424
						$conf .= "ifconfig {$ip1} {$mask}\n";
425
				}
426
				break;
427
			case 'server_tls':
428
			case 'server_user':
429
			case 'server_tls_user':
430
				if (!empty($ip) && !empty($mask)) {
431
					$conf .= "server {$ip} {$mask}\n";
432
					if(is_ipaddr($ipv6))
433
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
434
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
435
				} else {
436
					if ($settings['serverbridge_dhcp']) {
437
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
438
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
439
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
440
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
441
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
442
							} else {
443
								$conf .= "mode server\n";
444
							}
445
						} else {
446
							$conf .= "mode server\n";
447
						}
448
					}
449
				}
450
				break;
451
		}
452

    
453
		// configure user auth modes
454
		switch($settings['mode']) {
455
			case 'server_user':
456
				$conf .= "client-cert-not-required\n";
457
			case 'server_tls_user':
458
				/* username-as-common-name is not compatible with server-bridge */
459
				if (stristr($conf, "server-bridge") === false)
460
					$conf .= "username-as-common-name\n";
461
				if (!empty($settings['authmode'])) {
462
					$authcfgs = explode(",", $settings['authmode']);
463
					$sed = "\$authmodes=array(";
464
					$firstsed = 0;
465
					foreach ($authcfgs as $authcfg) {
466
						if ($firstsed > 0)
467
							$sed .= ",";
468
						$firstsed = 1;
469
						$sed .= "\"{$authcfg}\"";
470
					}
471
					$sed .= ");\\\n";
472
					if ($settings['strictusercn'])
473
						$sed .= "\$strictusercn = true;";
474
					$sed .= " \$modeid = \"{$mode_id}\";";
475
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
476
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
477
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
478
				}
479
				break;
480
		}
481
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls')))
482
			$settings['cert_depth'] = 1;
483
		if (is_numeric($settings['cert_depth'])) {
484
			$sed = "";
485
			$cert = lookup_cert($settings['certref']);
486
			$servercn = cert_get_cn($cert['crt']);
487
			$sed .= "\$server_cn = \"{$servercn}\";\\\n";
488
			$sed .= "\$allowed_depth = {$settings['cert_depth']};\\\n";
489
			mwexec("/bin/cat /etc/inc/openvpn.tls-verify.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
490
			mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
491
			$conf .= "tls-verify {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php\n";
492
		}
493

    
494
		// The local port to listen on
495
		$conf .= "lport {$settings['local_port']}\n";
496

    
497
		// The management port to listen on
498
		// Use unix socket to overcome the problem on any type of server
499
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
500
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
501

    
502
		if ($settings['maxclients'])
503
			$conf .= "max-clients {$settings['maxclients']}\n";
504

    
505
		// Can we push routes
506
		if ($settings['local_network']) {
507
			list($ip, $mask) = explode('/', $settings['local_network']);
508
			$mask = gen_subnet_mask($mask);
509
			$conf .= "push \"route $ip $mask\"\n";
510
		}
511
		if ($settings['local_networkv6']) {
512
			list($ipv6, $prefix) = explode('/', $settings['local_networkv6']);
513
			$conf .= "push \"route-ipv6 $ipv6/$prefix\"\n";
514
		}
515

    
516
		switch($settings['mode']) {
517
			case 'server_tls':
518
			case 'server_user':
519
			case 'server_tls_user':
520
				// Configure client dhcp options
521
				openvpn_add_dhcpopts($settings, $conf);
522
				if ($settings['client2client'])
523
					$conf .= "client-to-client\n";
524
				break;
525
		}
526
		if (isset($settings['duplicate_cn']))
527
			$conf .= "duplicate-cn\n";
528
	}
529

    
530
	// client specific settings
531

    
532
	if ($mode == 'client') {
533

    
534
		// configure p2p mode
535
		switch($settings['mode']) {
536
			case 'p2p_tls':
537
				$conf .= "tls-client\n";
538
			case 'shared_key':
539
				$conf .= "client\n";
540
				break;
541
		}
542

    
543
		// If there is no bind option at all (ip and/or port), add "nobind" directive
544
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
545
		//  ensure a random source port.
546
		if ((empty($iface_ip)) && (!$settings['local_port']))
547
			$conf .= "nobind\n";
548
		elseif ($settings['local_port'])
549
			$conf .= "lport {$settings['local_port']}\n";
550
		else
551
			$conf .= "lport 0\n";
552

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

    
556
		// The remote server
557
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
558

    
559
		if (!empty($settings['use_shaper']))
560
			$conf .= "shaper {$settings['use_shaper']}\n";
561

    
562
		if (!empty($settings['tunnel_network'])) {
563
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
564
			$mask = gen_subnet_mask($mask);
565
			$baselong = ip2long32($ip) & ip2long($mask);
566
			$ip1 = long2ip32($baselong + 1);
567
			$ip2 = long2ip32($baselong + 2);
568
			if ($settings['dev_mode'] == 'tun')
569
				$conf .= "ifconfig {$ip2} {$ip1}\n";
570
			else
571
				$conf .= "ifconfig {$ip2} {$mask}\n";
572
		}
573

    
574
		if ($settings['proxy_addr']) {
575
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
576
			if ($settings['proxy_authtype'] != "none") {
577
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
578
				$proxypas = "{$settings['proxy_user']}\n";
579
				$proxypas .= "{$settings['proxy_passwd']}\n";
580
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
581
			}
582
			$conf .= " \n";
583
		}
584
	}
585

    
586
	// Add a remote network route if set, and only for p2p modes.
587
	if ((substr($settings['mode'], 0, 3) == "p2p") && is_subnet($settings['remote_network'])) {
588
		list($ip, $mask) = explode('/', $settings['remote_network']);
589
		$mask = gen_subnet_mask($mask);
590
		$conf .= "route $ip $mask\n";
591
	}
592

    
593
	// Write the settings for the keys
594
	switch($settings['mode']) {
595
		case 'p2p_shared_key':
596
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
597
			break;
598
		case 'p2p_tls':
599
		case 'server_tls':
600
		case 'server_tls_user':
601
		case 'server_user':
602
			$ca = lookup_ca($settings['caref']);
603
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
604
			$cert = lookup_cert($settings['certref']);
605
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
606
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
607
			if ($mode == 'server')
608
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
609
			if (!empty($settings['crlref'])) {
610
				$crl = lookup_crl($settings['crlref']);
611
				crl_update($crl);
612
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
613
			}
614
			if ($settings['tls']) {
615
				if ($mode == "server") 
616
					$tlsopt = 0;
617
				else
618
					$tlsopt = 1;
619
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
620
			}
621
			break;
622
	}
623

    
624
	if ($settings['compression'])
625
		$conf .= "comp-lzo\n";
626

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

    
630
	if ($settings['resolve_retry'])
631
		$conf .= "resolv-retry infinite\n";
632

    
633
	if ($settings['dynamic_ip']) {
634
		$conf .= "persist-remote-ip\n";
635
		$conf .= "float\n";
636
	}
637

    
638
	openvpn_add_custom($settings, $conf);
639

    
640
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
641
	file_put_contents($fpath, $conf);
642
	//chown($fpath, 'nobody');
643
	//chgrp($fpath, 'nobody');
644
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
645
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
646
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
647
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
648
}
649

    
650
function openvpn_restart($mode, $settings) {
651
	global $g, $config;
652

    
653
	$vpnid = $settings['vpnid'];
654
	$mode_id = $mode.$vpnid;
655

    
656
	/* kill the process if running */
657
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
658
	if (file_exists($pfile)) {
659

    
660
		/* read the pid file */
661
		$pid = rtrim(file_get_contents($pfile));
662
		unlink($pfile);
663

    
664
		/* send a term signal to the process */
665
		posix_kill($pid, SIGTERM);
666

    
667
		/* wait until the process exits */
668
		while(posix_kill($pid, 0))
669
			usleep(250000);
670
	}
671

    
672
	if (isset($settings['disable']))
673
		return;
674

    
675
	/* start the new process */
676
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
677
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
678

    
679
	if (!$g['booting'])
680
		send_event("filter reload");
681
}
682

    
683
function openvpn_delete($mode, & $settings) {
684
	global $g, $config;
685

    
686
	$vpnid = $settings['vpnid'];
687
	$mode_id = $mode.$vpnid;
688

    
689
	$tunname = "tun{$vpnid}";
690
	if ($mode == "server")
691
		$devname = "ovpns{$vpnid}";
692
	else
693
		$devname = "ovpnc{$vpnid}";
694

    
695
	/* kill the process if running */
696
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
697
	if (file_exists($pfile)) {
698

    
699
		/* read the pid file */
700
		$pid = trim(file_get_contents($pfile));
701
		unlink($pfile);
702

    
703
		/* send a term signal to the process */
704
		posix_kill($pid, SIGTERM);
705
	}
706

    
707
	/* remove the device from the openvpn group */
708
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
709

    
710
	/* restore the original adapter name */
711
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
712

    
713
	/* remove the configuration files */
714
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
715
}
716

    
717
function openvpn_resync_csc(& $settings) {
718
	global $g, $config;
719

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

    
722
	if (isset($settings['disable'])) {
723
		unlink_if_exists($fpath);
724
		return;
725
	}
726

    
727
	$conf = '';
728
	if ($settings['block'])
729
		$conf .= "disable\n";
730

    
731
	if ($settings['push_reset'])
732
		$conf .= "push-reset\n";
733

    
734
	if (!empty($settings['tunnel_network'])) {
735
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
736
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
737
		$serverip = long2ip32($baselong + 1);
738
		$clientip = long2ip32($baselong + 2);
739
		/* Because this is being pushed, the order from the client's point of view. */
740
		if ($settings['dev_mode'] == 'tun')
741
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
742
		else
743
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
744
	}
745

    
746
	openvpn_add_dhcpopts($settings, $conf);
747

    
748
	if ($settings['gwredir'])
749
		$conf .= "push \"redirect-gateway def1\"\n";
750

    
751
	openvpn_add_custom($settings, $conf);
752

    
753
	file_put_contents($fpath, $conf);
754
	chown($fpath, 'nobody');
755
	chgrp($fpath, 'nobody');
756
}
757

    
758
function openvpn_delete_csc(& $settings) {
759
	global $g, $config;
760

    
761
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
762
	unlink_if_exists($fpath);
763
}
764

    
765
// Resync the configuration and restart the VPN
766
function openvpn_resync($mode, $settings) {
767
	openvpn_reconfigure($mode, $settings);
768
	openvpn_restart($mode, $settings);
769
}
770

    
771
// Resync and restart all VPNs
772
function openvpn_resync_all($interface = "") {
773
	global $g, $config;
774

    
775
	if ($g['platform'] == 'jail')
776
		return;
777
	// delay our setup until the system
778
	// has a chance to init our paths
779
	if (!file_exists($g['varetc_path']."/openvpn") ||
780
		!file_exists($g['varetc_path']."/openvpn-csc"))
781
		return;
782

    
783
	if (!is_array($config['openvpn']))
784
		$config['openvpn'] = array();
785

    
786
/*
787
	if (!$config['openvpn']['dh-parameters']) {
788
		echo "Configuring OpenVPN Parameters ...\n";
789
		$dh_parameters = openvpn_create_dhparams(1024);
790
		$dh_parameters = base64_encode($dh_parameters);
791
		$config['openvpn']['dh-parameters'] = $dh_parameters;
792
		write_config("OpenVPN DH parameters");
793
	}
794

    
795
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
796
	if (!file_exists($path_ovdh)) {
797
		$dh_parameters = $config['openvpn']['dh-parameters'];
798
		$dh_parameters = base64_decode($dh_parameters);
799
		file_put_contents($path_ovdh, $dh_parameters);
800
	}
801
*/
802
	if ($interface <> "")
803
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
804
	else
805
		log_error("Resyncing OpenVPN instances."); 
806

    
807
	if (is_array($config['openvpn']['openvpn-server'])) {
808
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
809
			if ($interface <> "" && $interface != $settings['interface'])
810
				continue;
811
			openvpn_resync('server', $settings);
812
		}
813
	}
814

    
815
	if (is_array($config['openvpn']['openvpn-client'])) {
816
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
817
			if ($interface <> "" && $interface != $settings['interface'])
818
				continue;
819
			openvpn_resync('client', $settings);
820
		}
821
	}
822

    
823
	if (is_array($config['openvpn']['openvpn-csc']))
824
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
825
			openvpn_resync_csc($settings);
826

    
827
}
828

    
829
function openvpn_get_active_servers($type="multipoint") {
830
	global $config, $g;
831

    
832
	$servers = array();
833
	if (is_array($config['openvpn']['openvpn-server'])) {
834
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
835
			if (empty($settings) || isset($settings['disable']))
836
				continue;
837

    
838
			$prot = $settings['protocol'];
839
			$port = $settings['local_port'];
840
	
841
			$server = array();
842
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
843
			$server['mode'] = $settings['mode'];
844
			if ($settings['description'])
845
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
846
			else
847
				$server['name'] = "Server {$prot}:{$port}";
848
			$server['conns'] = array();
849
	
850
			$vpnid = $settings['vpnid'];
851
			$mode_id = "server{$vpnid}";
852
			$server['mgmt'] = $mode_id;
853
			$socket = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
854
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
855

    
856
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
857
				$servers[] = openvpn_get_client_status($server, $socket);
858
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
859
				$servers[] = openvpn_get_server_status($server, $socket);
860

    
861
		}
862
	}
863
	return $servers;
864
}
865

    
866
function openvpn_get_server_status($server, $socket) {
867
	$errval;
868
	$errstr;
869
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
870
	if ($fp) {
871
		stream_set_timeout($fp, 1);
872

    
873
		/* send our status request */
874
		fputs($fp, "status 2\n");
875

    
876
		/* recv all response lines */
877
		while (!feof($fp)) {
878

    
879
			/* read the next line */
880
			$line = fgets($fp, 1024);
881

    
882
			$info = stream_get_meta_data($fp);
883
			if ($info['timed_out'])
884
				break;
885

    
886
			/* parse header list line */
887
			if (strstr($line, "HEADER"))
888
				continue;
889

    
890
			/* parse end of output line */
891
			if (strstr($line, "END") || strstr($line, "ERROR"))
892
				break;
893

    
894
			/* parse client list line */
895
			if (strstr($line, "CLIENT_LIST")) {
896
				$list = explode(",", $line);
897
				$conn = array();
898
				$conn['common_name'] = $list[1];
899
				$conn['remote_host'] = $list[2];
900
				$conn['virtual_addr'] = $list[3];
901
				$conn['bytes_recv'] = $list[4];
902
				$conn['bytes_sent'] = $list[5];
903
				$conn['connect_time'] = $list[6];
904
				$server['conns'][] = $conn;
905
			}
906
		}
907

    
908
		/* cleanup */
909
		fclose($fp);
910
	} else {
911
		$conn = array();
912
		$conn['common_name'] = "[error]";
913
		$conn['remote_host'] = "Management Daemon Unreachable";
914
		$conn['virtual_addr'] = "";
915
		$conn['bytes_recv'] = 0;
916
		$conn['bytes_sent'] = 0;
917
		$conn['connect_time'] = 0;
918
		$server['conns'][] = $conn;
919
	}
920
	return $server;
921
}
922

    
923
function openvpn_get_active_clients() {
924
	global $config, $g;
925

    
926
	$clients = array();
927
	if (is_array($config['openvpn']['openvpn-client'])) {
928
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
929
	
930
			if (empty($settings) || isset($settings['disable']))
931
				continue;
932

    
933
			$prot = $settings['protocol'];
934
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
935
	
936
			$client = array();
937
			$client['port'] = $settings['local_port'];
938
			if ($settings['description'])
939
				$client['name'] = "{$settings['description']} {$prot}{$port}";
940
			else
941
				$client['name'] = "Client {$prot}{$port}";
942
	
943
			$vpnid = $settings['vpnid'];
944
			$mode_id = "client{$vpnid}";
945
			$client['mgmt'] = $mode_id;
946
			$socket = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
947
			$client['status']="down";
948

    
949
			$clients[] = openvpn_get_client_status($client, $socket);
950
		}
951
	}
952
	return $clients;
953
}
954

    
955
function openvpn_get_client_status($client, $socket) {
956
	$errval;
957
	$errstr;
958
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
959
	if ($fp) {
960
		stream_set_timeout($fp, 1);
961
		/* send our status request */
962
		fputs($fp, "state 1\n");
963

    
964
		/* recv all response lines */
965
		while (!feof($fp)) {
966
			/* read the next line */
967
			$line = fgets($fp, 1024);
968

    
969
			$info = stream_get_meta_data($fp);
970
			if ($info['timed_out'])
971
				break;
972

    
973
			/* Get the client state */
974
			if (strstr($line,"CONNECTED")) {
975
				$client['status']="up";
976
				$list = explode(",", $line);
977

    
978
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
979
				$client['virtual_addr']  = $list[3];
980
				$client['remote_host'] = $list[4];
981
			}
982
			if (strstr($line,"CONNECTING")) {
983
				$client['status']="connecting";
984
			}
985
			if (strstr($line,"ASSIGN_IP")) {
986
				$client['status']="waiting";
987
				$list = explode(",", $line);
988

    
989
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
990
				$client['virtual_addr']  = $list[3];
991
			}
992
			if (strstr($line,"RECONNECTING")) {
993
				$client['status']="reconnecting";
994
				$list = explode(",", $line);
995

    
996
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
997
				$client['status'] .= "; " . $list[2];
998
			}
999
			/* parse end of output line */
1000
			if (strstr($line, "END") || strstr($line, "ERROR"))
1001
				break;
1002
		}
1003

    
1004
		/* If up, get read/write stats */
1005
		if (strcmp($client['status'], "up") == 0) {
1006
			fputs($fp, "status 2\n");
1007
			/* recv all response lines */
1008
			while (!feof($fp)) {
1009
				/* read the next line */
1010
				$line = fgets($fp, 1024);
1011

    
1012
				$info = stream_get_meta_data($fp);
1013
				if ($info['timed_out'])
1014
					break;
1015

    
1016
				if (strstr($line,"TCP/UDP read bytes")) {
1017
					$list = explode(",", $line);
1018
					$client['bytes_recv'] = $list[1];
1019
				}
1020

    
1021
				if (strstr($line,"TCP/UDP write bytes")) {
1022
					$list = explode(",", $line);
1023
					$client['bytes_sent'] = $list[1];
1024
				}
1025

    
1026
				/* parse end of output line */
1027
				if (strstr($line, "END"))
1028
					break;
1029
			}
1030
		}
1031

    
1032
		fclose($fp);
1033

    
1034
	} else {
1035
		$DisplayNote=true;
1036
		$client['remote_host'] = "No Management Daemon";
1037
		$client['virtual_addr'] = "See Note Below";
1038
		$client['bytes_recv'] = 0;
1039
		$client['bytes_sent'] = 0;
1040
		$client['connect_time'] = 0;
1041
	}
1042
	return $client;
1043
}
1044

    
1045
function openvpn_refresh_crls() {
1046
	global $g, $config;
1047

    
1048
	if (!file_exists($g['varetc_path']."/openvpn"))
1049
		return;
1050

    
1051
	if (is_array($config['openvpn']['openvpn-server'])) {
1052
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1053
			if (empty($settings))
1054
				continue;
1055
			if (isset($settings['disable']))
1056
				continue;
1057
			// Write the settings for the keys
1058
			switch($settings['mode']) {
1059
				case 'p2p_tls':
1060
				case 'server_tls':
1061
				case 'server_tls_user':
1062
				case 'server_user':
1063
					if (!empty($settings['crlref'])) {
1064
						$crl = lookup_crl($settings['crlref']);
1065
						crl_update($crl);
1066
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1067
						file_put_contents($fpath, base64_decode($crl['text']));
1068
						@chmod($fpath, 0644);
1069
					}
1070
					break;
1071
			}
1072
		}
1073
	}
1074
}
1075

    
1076
?>
(35-35/64)