Project

General

Profile

Download (31.3 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
	/* Do not start if we are a CARP backup on this vip! */
676
	if ((substr($settings['interface'], 0, 3) == "vip") && (get_carp_interface_status($settings['interface']) == "BACKUP"))
677
		return;
678

    
679
	/* start the new process */
680
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
681
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
682

    
683
	if (!$g['booting'])
684
		send_event("filter reload");
685
}
686

    
687
function openvpn_delete($mode, & $settings) {
688
	global $g, $config;
689

    
690
	$vpnid = $settings['vpnid'];
691
	$mode_id = $mode.$vpnid;
692

    
693
	$tunname = "tun{$vpnid}";
694
	if ($mode == "server")
695
		$devname = "ovpns{$vpnid}";
696
	else
697
		$devname = "ovpnc{$vpnid}";
698

    
699
	/* kill the process if running */
700
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
701
	if (file_exists($pfile)) {
702

    
703
		/* read the pid file */
704
		$pid = trim(file_get_contents($pfile));
705
		unlink($pfile);
706

    
707
		/* send a term signal to the process */
708
		posix_kill($pid, SIGTERM);
709
	}
710

    
711
	/* remove the device from the openvpn group */
712
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
713

    
714
	/* restore the original adapter name */
715
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
716

    
717
	/* remove the configuration files */
718
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
719
}
720

    
721
function openvpn_resync_csc(& $settings) {
722
	global $g, $config;
723

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

    
726
	if (isset($settings['disable'])) {
727
		unlink_if_exists($fpath);
728
		return;
729
	}
730

    
731
	$conf = '';
732
	if ($settings['block'])
733
		$conf .= "disable\n";
734

    
735
	if ($settings['push_reset'])
736
		$conf .= "push-reset\n";
737

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

    
750
	openvpn_add_dhcpopts($settings, $conf);
751

    
752
	if ($settings['gwredir'])
753
		$conf .= "push \"redirect-gateway def1\"\n";
754

    
755
	openvpn_add_custom($settings, $conf);
756

    
757
	file_put_contents($fpath, $conf);
758
	chown($fpath, 'nobody');
759
	chgrp($fpath, 'nobody');
760
}
761

    
762
function openvpn_delete_csc(& $settings) {
763
	global $g, $config;
764

    
765
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
766
	unlink_if_exists($fpath);
767
}
768

    
769
// Resync the configuration and restart the VPN
770
function openvpn_resync($mode, $settings) {
771
	openvpn_reconfigure($mode, $settings);
772
	openvpn_restart($mode, $settings);
773
}
774

    
775
// Resync and restart all VPNs
776
function openvpn_resync_all($interface = "") {
777
	global $g, $config;
778

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

    
787
	if (!is_array($config['openvpn']))
788
		$config['openvpn'] = array();
789

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

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

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

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

    
827
	if (is_array($config['openvpn']['openvpn-csc']))
828
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
829
			openvpn_resync_csc($settings);
830

    
831
}
832

    
833
function openvpn_get_active_servers($type="multipoint") {
834
	global $config, $g;
835

    
836
	$servers = array();
837
	if (is_array($config['openvpn']['openvpn-server'])) {
838
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
839
			if (empty($settings) || isset($settings['disable']))
840
				continue;
841

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

    
860
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
861
				$servers[] = openvpn_get_client_status($server, $socket);
862
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
863
				$servers[] = openvpn_get_server_status($server, $socket);
864

    
865
		}
866
	}
867
	return $servers;
868
}
869

    
870
function openvpn_get_server_status($server, $socket) {
871
	$errval;
872
	$errstr;
873
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
874
	if ($fp) {
875
		stream_set_timeout($fp, 1);
876

    
877
		/* send our status request */
878
		fputs($fp, "status 2\n");
879

    
880
		/* recv all response lines */
881
		while (!feof($fp)) {
882

    
883
			/* read the next line */
884
			$line = fgets($fp, 1024);
885

    
886
			$info = stream_get_meta_data($fp);
887
			if ($info['timed_out'])
888
				break;
889

    
890
			/* parse header list line */
891
			if (strstr($line, "HEADER"))
892
				continue;
893

    
894
			/* parse end of output line */
895
			if (strstr($line, "END") || strstr($line, "ERROR"))
896
				break;
897

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

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

    
927
function openvpn_get_active_clients() {
928
	global $config, $g;
929

    
930
	$clients = array();
931
	if (is_array($config['openvpn']['openvpn-client'])) {
932
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
933
	
934
			if (empty($settings) || isset($settings['disable']))
935
				continue;
936

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

    
953
			$clients[] = openvpn_get_client_status($client, $socket);
954
		}
955
	}
956
	return $clients;
957
}
958

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

    
968
		/* recv all response lines */
969
		while (!feof($fp)) {
970
			/* read the next line */
971
			$line = fgets($fp, 1024);
972

    
973
			$info = stream_get_meta_data($fp);
974
			if ($info['timed_out'])
975
				break;
976

    
977
			/* Get the client state */
978
			if (strstr($line,"CONNECTED")) {
979
				$client['status']="up";
980
				$list = explode(",", $line);
981

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

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

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

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

    
1016
				$info = stream_get_meta_data($fp);
1017
				if ($info['timed_out'])
1018
					break;
1019

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

    
1025
				if (strstr($line,"TCP/UDP write bytes")) {
1026
					$list = explode(",", $line);
1027
					$client['bytes_sent'] = $list[1];
1028
				}
1029

    
1030
				/* parse end of output line */
1031
				if (strstr($line, "END"))
1032
					break;
1033
			}
1034
		}
1035

    
1036
		fclose($fp);
1037

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

    
1049
function openvpn_refresh_crls() {
1050
	global $g, $config;
1051

    
1052
	if (!file_exists($g['varetc_path']."/openvpn"))
1053
		return;
1054

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

    
1080
?>
(35-35/64)