Project

General

Profile

Download (43.8 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	openvpn.inc part of pfSense
4

    
5
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
6
	All rights reserved.
7

    
8
	Copyright (C) 2006  Fernando Lemos
9
	All rights reserved.
10

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

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

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

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

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

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

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

    
41

    
42
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/bin/openssl	/sbin/ifconfig
43
	pfSense_MODULE:	openvpn
44

    
45
*/
46
require_once('config.inc');
47
require_once("certs.inc");
48
require_once('pfsense-utils.inc');
49
require_once("auth.inc");
50

    
51
global $openvpn_prots;
52
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
53

    
54
global $openvpn_dev_mode;
55
$openvpn_dev_mode = array("tun", "tap");
56

    
57
global $openvpn_verbosity_level;
58
$openvpn_verbosity_level = array(
59
	0 =>	"none",
60
	1 =>	"default",
61
	2 =>	"2",
62
	3 =>	"3 (recommended)",
63
	4 =>	"4",
64
	5 => 	"5",
65
	6 => 	"6",
66
	7 => 	"7",
67
	8 => 	"8",
68
	9 => 	"9",
69
	10 => 	"10",
70
	11 => 	"11"
71
);
72

    
73
/*
74
 * The User Auth mode below is disabled because
75
 * OpenVPN erroneously requires that we provide
76
 * a CA configuration parameter. In this mode,
77
 * clients don't send a certificate so there is
78
 * no need for a CA. If we require that admins
79
 * provide one in the pfSense UI due to a bogus
80
 * requirement imposed by OpenVPN, it could be
81
 * considered very confusing ( I know I was ).
82
 *
83
 * -mgrooms
84
 */
85

    
86
global $openvpn_dh_lengths;
87
$openvpn_dh_lengths = array(
88
	1024, 2048, 4096);
89

    
90
global $openvpn_cert_depths;
91
$openvpn_cert_depths = array(
92
	1 => "One (Client+Server)",
93
	2 => "Two (Client+Intermediate+Server)",
94
	3 => "Three (Client+2xIntermediate+Server)",
95
	4 => "Four (Client+3xIntermediate+Server)",
96
	5 => "Five (Client+4xIntermediate+Server)"
97
);
98

    
99
global $openvpn_server_modes;
100
$openvpn_server_modes = array(
101
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
102
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
103
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
104
	'server_user' => gettext("Remote Access ( User Auth )"),
105
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
106

    
107
global $openvpn_client_modes;
108
$openvpn_client_modes = array(
109
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
110
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"));
111

    
112
global $openvpn_compression_modes;
113
$openvpn_compression_modes = array(
114
	'' => gettext("No Preference"),
115
	'no' => gettext("Disabled - No Compression"),
116
	'adaptive' => gettext("Enabled with Adaptive Compression"),
117
	'yes' => gettext("Enabled without Adaptive Compression"));
118

    
119
function openvpn_create_key() {
120

    
121
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
122
	if (!$fp) {
123
		return false;
124
	}
125

    
126
	$rslt = stream_get_contents($fp);
127
	pclose($fp);
128

    
129
	return $rslt;
130
}
131

    
132
function openvpn_create_dhparams($bits) {
133

    
134
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
135
	if (!$fp) {
136
		return false;
137
	}
138

    
139
	$rslt = stream_get_contents($fp);
140
	pclose($fp);
141

    
142
	return $rslt;
143
}
144

    
145
function openvpn_vpnid_used($vpnid) {
146
	global $config;
147

    
148
	if (is_array($config['openvpn']['openvpn-server'])) {
149
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
150
			if ($vpnid == $settings['vpnid']) {
151
				return true;
152
			}
153
		}
154
	}
155

    
156
	if (is_array($config['openvpn']['openvpn-client'])) {
157
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
158
			if ($vpnid == $settings['vpnid']) {
159
				return true;
160
			}
161
		}
162
	}
163

    
164
	return false;
165
}
166

    
167
function openvpn_vpnid_next() {
168

    
169
	$vpnid = 1;
170
	while (openvpn_vpnid_used($vpnid)) {
171
		$vpnid++;
172
	}
173

    
174
	return $vpnid;
175
}
176

    
177
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
178
	global $config;
179

    
180
	if (is_array($config['openvpn']['openvpn-server'])) {
181
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
182
			if (isset($settings['disable'])) {
183
				continue;
184
			}
185

    
186
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
187
				continue;
188
			}
189

    
190
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
191
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
192
				return $settings['vpnid'];
193
			}
194
		}
195
	}
196

    
197
	if (is_array($config['openvpn']['openvpn-client'])) {
198
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
199
			if (isset($settings['disable'])) {
200
				continue;
201
			}
202

    
203
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
204
				continue;
205
			}
206

    
207
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
208
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
209
				return $settings['vpnid'];
210
			}
211
		}
212
	}
213

    
214
	return 0;
215
}
216

    
217
function openvpn_port_next($prot, $interface = "wan") {
218

    
219
	$port = 1194;
220
	while (openvpn_port_used($prot, $interface, $port)) {
221
		$port++;
222
	}
223
	while (openvpn_port_used($prot, "any", $port)) {
224
		$port++;
225
	}
226

    
227
	return $port;
228
}
229

    
230
function openvpn_get_cipherlist() {
231

    
232
	$ciphers = array();
233
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
234
	$cipher_lines = explode("\n", trim($cipher_out));
235
	sort($cipher_lines);
236
	foreach ($cipher_lines as $line) {
237
		$words = explode(' ', $line);
238
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
239
	}
240
	$ciphers["none"] = gettext("None (No Encryption)");
241
	return $ciphers;
242
}
243

    
244
function openvpn_get_digestlist() {
245

    
246
	$digests = array();
247
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
248
	$digest_lines = explode("\n", trim($digest_out));
249
	sort($digest_lines);
250
	foreach ($digest_lines as $line) {
251
		$words = explode(' ', $line);
252
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
253
	}
254
	$digests["none"] = gettext("None (No Authentication)");
255
	return $digests;
256
}
257

    
258
function openvpn_get_engines() {
259
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
260
	exec("/usr/bin/openssl engine -t -c", $openssl_engine_output);
261
	$openssl_engine_output = implode("\n", $openssl_engine_output);
262
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
263
	$openssl_engine_output = explode("\n", $openssl_engine_output);
264

    
265
	foreach ($openssl_engine_output as $oeo) {
266
		$keep = true;
267
		$details = explode("|", $oeo);
268
		$engine = array_shift($details);
269
		$linematch = array();
270
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
271
		foreach ($details as $dt) {
272
			if (strpos($dt, "unavailable") !== FALSE) {
273
				$keep = false;
274
			}
275
			if (strpos($dt, "available") !== FALSE) {
276
				continue;
277
			}
278
			if (strpos($dt, "[") !== FALSE) {
279
				$ciphers = trim($dt, "[]");
280
			}
281
		}
282
		if (!empty($ciphers)) {
283
			$ciphers = " - " . $ciphers;
284
		}
285
		if (strlen($ciphers) > 60) {
286
			$ciphers = substr($ciphers, 0, 60) . " ... ";
287
		}
288
		if ($keep) {
289
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
290
		}
291
	}
292
	return $openssl_engines;
293
}
294

    
295
function openvpn_validate_engine($engine) {
296
	$engines = openvpn_get_engines();
297
	return array_key_exists($engine, $engines);
298
}
299

    
300
function openvpn_validate_host($value, $name) {
301
	$value = trim($value);
302
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value))) {
303
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
304
	}
305
	return false;
306
}
307

    
308
function openvpn_validate_port($value, $name) {
309
	$value = trim($value);
310
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535)) {
311
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
312
	}
313
	return false;
314
}
315

    
316
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
317
	$value = trim($value);
318
	$error = false;
319
	if (empty($value)) {
320
		return false;
321
	}
322
	$networks = explode(',', $value);
323

    
324
	if (!$multiple && (count($networks) > 1)) {
325
		return sprintf(gettext("The field '%s' must contain a single valid %s CIDR range."), $name, $ipproto);
326
	}
327

    
328
	foreach ($networks as $network) {
329
		if ($ipproto == "ipv4") {
330
			$error = !openvpn_validate_cidr_ipv4($network);
331
		} else {
332
			$error = !openvpn_validate_cidr_ipv6($network);
333
		}
334
		if ($error) {
335
			break;
336
		}
337
	}
338

    
339
	if ($error) {
340
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
341
	} else {
342
		return false;
343
	}
344
}
345

    
346
function openvpn_validate_cidr_ipv4($value) {
347
	$value = trim($value);
348
	if (!empty($value)) {
349
		list($ip, $mask) = explode('/', $value);
350
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0)) {
351
			return false;
352
		}
353
	}
354
	return true;
355
}
356

    
357
function openvpn_validate_cidr_ipv6($value) {
358
	$value = trim($value);
359
	if (!empty($value)) {
360
		list($ipv6, $prefix) = explode('/', $value);
361
		if (empty($prefix)) {
362
			$prefix = "128";
363
		}
364
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0)) {
365
			return false;
366
		}
367
	}
368
	return true;
369
}
370

    
371
function openvpn_add_dhcpopts(& $settings, & $conf) {
372

    
373
	if (!empty($settings['dns_domain'])) {
374
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
375
	}
376

    
377
	if (!empty($settings['dns_server1'])) {
378
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
379
	}
380
	if (!empty($settings['dns_server2'])) {
381
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
382
	}
383
	if (!empty($settings['dns_server3'])) {
384
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
385
	}
386
	if (!empty($settings['dns_server4'])) {
387
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
388
	}
389

    
390
	if (!empty($settings['push_register_dns'])) {
391
		$conf .= "push \"register-dns\"\n";
392
	}
393

    
394
	if (!empty($settings['ntp_server1'])) {
395
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
396
	}
397
	if (!empty($settings['ntp_server2'])) {
398
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
399
	}
400

    
401
	if ($settings['netbios_enable']) {
402

    
403
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0)) {
404
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
405
		}
406
		if (!empty($settings['dhcp_nbtscope'])) {
407
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
408
		}
409

    
410
		if (!empty($settings['wins_server1'])) {
411
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
412
		}
413
		if (!empty($settings['wins_server2'])) {
414
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
415
		}
416

    
417
		if (!empty($settings['nbdd_server1'])) {
418
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
419
		}
420
	}
421

    
422
	if ($settings['gwredir']) {
423
		$conf .= "push \"redirect-gateway def1\"\n";
424
	}
425
}
426

    
427
function openvpn_add_custom(& $settings, & $conf) {
428

    
429
	if ($settings['custom_options']) {
430

    
431
		$options = explode(';', $settings['custom_options']);
432

    
433
		if (is_array($options)) {
434
			foreach ($options as $option) {
435
				$conf .= "$option\n";
436
			}
437
		} else {
438
			$conf .= "{$settings['custom_options']}\n";
439
		}
440
	}
441
}
442

    
443
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
444
	global $g;
445

    
446
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
447
	openvpn_create_dirs();
448
	file_put_contents($fpath, base64_decode($data));
449
	//chown($fpath, 'nobody');
450
	//chgrp($fpath, 'nobody');
451
	@chmod($fpath, 0600);
452

    
453
	$conf .= "{$directive} {$fpath} {$opt}\n";
454
}
455

    
456
function openvpn_reconfigure($mode, $settings) {
457
	global $g, $config;
458

    
459
	if (empty($settings)) {
460
		return;
461
	}
462
	if (isset($settings['disable'])) {
463
		return;
464
	}
465
	openvpn_create_dirs();
466
	/*
467
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
468
	 * we use a vpnid number which is allocated for a particular client
469
	 * or server configuration. ( see openvpn_vpnid_next() )
470
	 */
471

    
472
	$vpnid = $settings['vpnid'];
473
	$mode_id = $mode.$vpnid;
474

    
475
	if (isset($settings['dev_mode'])) {
476
		$tunname = "{$settings['dev_mode']}{$vpnid}";
477
	} else {
478
		/* defaults to tun */
479
		$tunname = "tun{$vpnid}";
480
		$settings['dev_mode'] = "tun";
481
	}
482

    
483
	if ($mode == "server") {
484
		$devname = "ovpns{$vpnid}";
485
	} else {
486
		$devname = "ovpnc{$vpnid}";
487
	}
488

    
489
	/* is our device already configured */
490
	if (!does_interface_exist($devname)) {
491

    
492
		/* create the tap device if required */
493
		if (!file_exists("/dev/{$tunname}")) {
494
			exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
495
		}
496

    
497
		/* rename the device */
498
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
499

    
500
		/* add the device to the openvpn group and make sure it's UP*/
501
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn up");
502

    
503
		$ifname = convert_real_interface_to_friendly_interface_name($devname);
504
		$grouptmp = link_interface_to_group($ifname);
505
		if (!empty($grouptmp)) {
506
			array_walk($grouptmp, 'interface_group_add_member');
507
		}
508
		unset($grouptmp, $ifname);
509
	}
510

    
511
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
512
	$proto = strtolower($settings['protocol']);
513
	if (substr($settings['protocol'], 0, 3) == "TCP") {
514
			$proto = "{$proto}-{$mode}";
515
	}
516
	$dev_mode = $settings['dev_mode'];
517
	$cipher = $settings['crypto'];
518
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
519
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
520

    
521
	$interface = get_failover_interface($settings['interface']);
522
	$ipaddr = $settings['ipaddr'];
523
	$ipaddrv6 = $settings['ipaddrv6'];
524

    
525
	// If a specific ip address (VIP) is requested, use it.
526
	// Otherwise, if a specific interface is requested, use it
527
	// If "any" interface was selected, local directive will be omitted.
528
	if (is_ipaddrv4($ipaddr)) {
529
		$iface_ip=$ipaddr;
530
	} else {
531
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
532
			$iface_ip=get_interface_ip($interface);
533
		}
534
	}
535
	if (is_ipaddrv6($ipaddrv6)) {
536
		$iface_ipv6=$ipaddrv6;
537
	} else {
538
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
539
			$iface_ipv6=get_interface_ipv6($interface);
540
		}
541
	}
542

    
543

    
544
	$conf = "dev {$devname}\n";
545
	if (isset($settings['verbosity_level'])) {
546
		$conf .= "verb {$settings['verbosity_level']}\n";
547
	}
548

    
549
	$conf .= "dev-type {$settings['dev_mode']}\n";
550
	switch ($settings['dev_mode']) {
551
		case "tun":
552
			if (!$settings['no_tun_ipv6']) {
553
				$conf .= "tun-ipv6\n";
554
			}
555
			break;
556
	}
557
	$conf .= "dev-node /dev/{$tunname}\n";
558
	$conf .= "writepid {$pfile}\n";
559
	$conf .= "#user nobody\n";
560
	$conf .= "#group nobody\n";
561
	$conf .= "script-security 3\n";
562
	$conf .= "daemon\n";
563
	$conf .= "keepalive 10 60\n";
564
	$conf .= "ping-timer-rem\n";
565
	$conf .= "persist-tun\n";
566
	$conf .= "persist-key\n";
567
	$conf .= "proto {$proto}\n";
568
	$conf .= "cipher {$cipher}\n";
569
	$conf .= "auth {$digest}\n";
570
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
571
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
572
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
573
		switch ($settings['mode']) {
574
			case 'server_user':
575
			case 'server_tls_user':
576
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
577
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
578
				break;
579
		}
580
	}
581

    
582
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
583
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
584
		$conf .= "local {$iface_ip}\n";
585
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
586
		$conf .= "local {$iface_ipv6}\n";
587
	}
588

    
589
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none")) {
590
		$conf .= "engine {$settings['engine']}\n";
591
	}
592

    
593
	// server specific settings
594
	if ($mode == 'server') {
595

    
596
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
597
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
598
		$mask = gen_subnet_mask($cidr);
599

    
600
		// configure tls modes
601
		switch ($settings['mode']) {
602
			case 'p2p_tls':
603
			case 'server_tls':
604
			case 'server_user':
605
			case 'server_tls_user':
606
				$conf .= "tls-server\n";
607
				break;
608
		}
609

    
610
		// configure p2p/server modes
611
		switch ($settings['mode']) {
612
			case 'p2p_tls':
613
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
614
				//  use the server directive. It works for a single client without it.
615
				//  See ticket #1417
616
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
617
					$conf .= "server {$ip} {$mask}\n";
618
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
619
					if (is_ipaddr($ipv6)) {
620
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
621
					}
622
				}
623
			case 'p2p_shared_key':
624
				if (!empty($ip) && !empty($mask)) {
625
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
626
					if ($settings['dev_mode'] == 'tun') {
627
						$conf .= "ifconfig {$ip1} {$ip2}\n";
628
					} else {
629
						$conf .= "ifconfig {$ip1} {$mask}\n";
630
					}
631
				}
632
				if (!empty($ipv6) && !empty($prefix)) {
633
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
634
					if ($settings['dev_mode'] == 'tun') {
635
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
636
					} else {
637
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
638
					}
639
				}
640
				break;
641
			case 'server_tls':
642
			case 'server_user':
643
			case 'server_tls_user':
644
				if (!empty($ip) && !empty($mask)) {
645
					$conf .= "server {$ip} {$mask}\n";
646
					if (is_ipaddr($ipv6)) {
647
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
648
					}
649
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
650
				} else {
651
					if ($settings['serverbridge_dhcp']) {
652
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
653
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
654
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
655
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
656
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
657
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
658
							} else {
659
								$conf .= "mode server\n";
660
							}
661
						} else {
662
							$conf .= "mode server\n";
663
						}
664
					}
665
				}
666
				break;
667
		}
668

    
669
		// configure user auth modes
670
		switch ($settings['mode']) {
671
			case 'server_user':
672
				$conf .= "client-cert-not-required\n";
673
			case 'server_tls_user':
674
				/* username-as-common-name is not compatible with server-bridge */
675
				if (stristr($conf, "server-bridge") === false) {
676
					$conf .= "username-as-common-name\n";
677
				}
678
				if (!empty($settings['authmode'])) {
679
					$strictusercn = "false";
680
					if ($settings['strictusercn']) {
681
						$strictusercn = "true";
682
					}
683
					$conf .= "auth-user-pass-verify \"/usr/local/sbin/ovpn_auth_verify user '{$settings['authmode']}' {$strictusercn} {$mode_id}\" via-env\n";
684
				}
685
				break;
686
		}
687
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls'))) {
688
			$settings['cert_depth'] = 1;
689
		}
690
		if (is_numeric($settings['cert_depth'])) {
691
			if (($mode == 'client') && empty($settings['certref'])) {
692
				$cert = "";
693
			} else {
694
				$cert = lookup_cert($settings['certref']);
695
				/* XXX: Seems not used at all! */
696
				$servercn = urlencode(cert_get_cn($cert['crt']));
697
				$conf .= "tls-verify \"/usr/local/sbin/ovpn_auth_verify tls '{$servercn}' {$settings['cert_depth']}\"\n";
698
			}
699
		}
700

    
701
		// The local port to listen on
702
		$conf .= "lport {$settings['local_port']}\n";
703

    
704
		// The management port to listen on
705
		// Use unix socket to overcome the problem on any type of server
706
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
707
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
708

    
709
		if ($settings['maxclients']) {
710
			$conf .= "max-clients {$settings['maxclients']}\n";
711
		}
712

    
713
		// Can we push routes
714
		if ($settings['local_network']) {
715
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
716
		}
717
		if ($settings['local_networkv6']) {
718
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
719
		}
720

    
721
		switch ($settings['mode']) {
722
			case 'server_tls':
723
			case 'server_user':
724
			case 'server_tls_user':
725
				// Configure client dhcp options
726
				openvpn_add_dhcpopts($settings, $conf);
727
				if ($settings['client2client']) {
728
					$conf .= "client-to-client\n";
729
				}
730
				break;
731
		}
732
		if (isset($settings['duplicate_cn'])) {
733
			$conf .= "duplicate-cn\n";
734
		}
735
	}
736

    
737
	// client specific settings
738

    
739
	if ($mode == 'client') {
740

    
741
		// configure p2p mode
742
		switch ($settings['mode']) {
743
			case 'p2p_tls':
744
				$conf .= "tls-client\n";
745
			case 'shared_key':
746
				$conf .= "client\n";
747
				break;
748
		}
749

    
750
		// If there is no bind option at all (ip and/or port), add "nobind" directive
751
		//  Otherwise, use the local port if defined, failing that, use lport 0 to
752
		//  ensure a random source port.
753
		if ((empty($iface_ip)) && (!$settings['local_port'])) {
754
			$conf .= "nobind\n";
755
		} elseif ($settings['local_port']) {
756
			$conf .= "lport {$settings['local_port']}\n";
757
		} else {
758
			$conf .= "lport 0\n";
759
		}
760

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

    
764
		// The remote server
765
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
766

    
767
		if (!empty($settings['use_shaper'])) {
768
			$conf .= "shaper {$settings['use_shaper']}\n";
769
		}
770

    
771
		if (!empty($settings['tunnel_network'])) {
772
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
773
			$mask = gen_subnet_mask($mask);
774
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
775
			if ($settings['dev_mode'] == 'tun') {
776
				$conf .= "ifconfig {$ip2} {$ip1}\n";
777
			} else {
778
				$conf .= "ifconfig {$ip2} {$mask}\n";
779
			}
780
		}
781

    
782
		if (!empty($settings['tunnel_networkv6'])) {
783
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
784
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
785
			if ($settings['dev_mode'] == 'tun') {
786
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
787
			} else {
788
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
789
			}
790
		}
791

    
792
		if ($settings['auth_user'] && $settings['auth_pass']) {
793
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
794
			$conf .= "auth-user-pass {$up_file}\n";
795
			$userpass = "{$settings['auth_user']}\n";
796
			$userpass .= "{$settings['auth_pass']}\n";
797
			file_put_contents($up_file, $userpass);
798
		}
799

    
800
		if ($settings['proxy_addr']) {
801
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
802
			if ($settings['proxy_authtype'] != "none") {
803
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
804
				$proxypas = "{$settings['proxy_user']}\n";
805
				$proxypas .= "{$settings['proxy_passwd']}\n";
806
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
807
			}
808
			$conf .= " \n";
809
		}
810
	}
811

    
812
	// Add a remote network route if set, and only for p2p modes.
813
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
814
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
815
	}
816
	// Add a remote network route if set, and only for p2p modes.
817
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
818
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
819
	}
820

    
821
	// Write the settings for the keys
822
	switch ($settings['mode']) {
823
		case 'p2p_shared_key':
824
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
825
			break;
826
		case 'p2p_tls':
827
		case 'server_tls':
828
		case 'server_tls_user':
829
		case 'server_user':
830
			$ca = lookup_ca($settings['caref']);
831
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
832

    
833
			if (!empty($settings['certref'])) {
834
				$cert = lookup_cert($settings['certref']);
835
				openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
836
				openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
837
			}
838
			if ($mode == 'server') {
839
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
840
			}
841
			if (!empty($settings['crlref'])) {
842
				$crl = lookup_crl($settings['crlref']);
843
				crl_update($crl);
844
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
845
			}
846
			if ($settings['tls']) {
847
				if ($mode == "server") {
848
					$tlsopt = 0;
849
				} else {
850
					$tlsopt = 1;
851
				}
852
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
853
			}
854
			break;
855
	}
856

    
857
	if (!empty($settings['compression'])) {
858
		$conf .= "comp-lzo {$settings['compression']}\n";
859
	}
860

    
861
	if ($settings['passtos']) {
862
		$conf .= "passtos\n";
863
	}
864

    
865
	if ($settings['resolve_retry']) {
866
		$conf .= "resolv-retry infinite\n";
867
	} else if ($mode == 'clie} nt') {
868
		$conf .= "resolv-retry infinite\n";
869
	}
870

    
871
	if ($settings['dynamic_ip']) {
872
		$conf .= "persist-remote-ip\n";
873
		$conf .= "float\n";
874
	}
875

    
876
	if ($settings['topology_subnet']) {
877
		$conf .= "topology subnet\n";
878
	}
879

    
880
	// New client features
881
	if ($mode == "client") {
882
		// Dont pull routes checkbox
883
		if ($settings['route_no_pull']) {
884
			$conf .= "route-nopull\n";
885
		}
886

    
887
		// Dont add/remove routes checkbox
888
		if ($settings['route_no_exec']) {
889
			$conf .= "route-noexec\n";
890
		}
891
	}
892

    
893
	openvpn_add_custom($settings, $conf);
894

    
895
	openvpn_create_dirs();
896
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
897
	file_put_contents($fpath, $conf);
898
	unset($conf);
899
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
900
	file_put_contents($fpath, $interface);
901
	//chown($fpath, 'nobody');
902
	//chgrp($fpath, 'nobody');
903
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
904
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
905
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
906
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
907
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
908
}
909

    
910
function openvpn_restart($mode, $settings) {
911
	global $g, $config;
912

    
913
	$vpnid = $settings['vpnid'];
914
	$mode_id = $mode.$vpnid;
915

    
916
	/* kill the process if running */
917
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
918
	if (file_exists($pfile)) {
919

    
920
		/* read the pid file */
921
		$pid = rtrim(file_get_contents($pfile));
922
		unlink($pfile);
923

    
924
		/* send a term signal to the process */
925
		posix_kill($pid, SIGTERM);
926

    
927
		/* wait until the process exits, or timeout and kill it */
928
		$i = 0;
929
		while (posix_kill($pid, 0)) {
930
			usleep(250000);
931
			if ($i > 10) {
932
				log_error("OpenVPN ID $mode_id PID $pid still running, killing.");
933
				posix_kill($pid, SIGKILL);
934
				usleep(500000);
935
			}
936
			$i++;
937
		}
938
	}
939

    
940
	if (isset($settings['disable'])) {
941
		return;
942
	}
943

    
944
	/* Do not start a client if we are a CARP backup on this vip! */
945
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) != "MASTER")) {
946
		return;
947
	}
948

    
949
	/* Check if client is bound to a gateway group */
950
	$a_groups = return_gateway_groups_array();
951
	if (is_array($a_groups[$settings['interface']])) {
952
		/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
953
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) != "MASTER")) {
954
			return;
955
		}
956
	}
957

    
958
	/* start the new process */
959
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
960
	openvpn_clear_route($mode, $settings);
961
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
962

    
963
	if (!platform_booting()) {
964
		send_event("filter reload");
965
	}
966
}
967

    
968
function openvpn_delete($mode, & $settings) {
969
	global $g, $config;
970

    
971
	$vpnid = $settings['vpnid'];
972
	$mode_id = $mode.$vpnid;
973

    
974
	if (isset($settings['dev_mode'])) {
975
		$tunname = "{$settings['dev_mode']}{$vpnid}";
976
	} else {
977
		/* defaults to tun */
978
		$tunname = "tun{$vpnid}";
979
	}
980

    
981
	if ($mode == "server") {
982
		$devname = "ovpns{$vpnid}";
983
	} else {
984
		$devname = "ovpnc{$vpnid}";
985
	}
986

    
987
	/* kill the process if running */
988
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
989
	if (file_exists($pfile)) {
990

    
991
		/* read the pid file */
992
		$pid = trim(file_get_contents($pfile));
993
		unlink($pfile);
994

    
995
		/* send a term signal to the process */
996
		posix_kill($pid, SIGTERM);
997
	}
998

    
999
	/* remove the device from the openvpn group */
1000
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
1001

    
1002
	/* restore the original adapter name */
1003
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
1004

    
1005
	/* remove the configuration files */
1006
	@array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
1007
}
1008

    
1009
function openvpn_cleanup_csc($common_name) {
1010
	global $g, $config;
1011
	if (empty($common_name)) {
1012
		return;
1013
	}
1014
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
1015
	if (is_file($fpath)) {
1016
		unlink_if_exists($fpath);
1017
	}
1018
	return;
1019
}
1020

    
1021
function openvpn_resync_csc(& $settings) {
1022
	global $g, $config;
1023

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

    
1026
	if (isset($settings['disable'])) {
1027
		unlink_if_exists($fpath);
1028
		return;
1029
	}
1030
	openvpn_create_dirs();
1031

    
1032
	$conf = '';
1033
	if ($settings['block']) {
1034
		$conf .= "disable\n";
1035
	}
1036

    
1037
	if ($settings['push_reset']) {
1038
		$conf .= "push-reset\n";
1039
	}
1040

    
1041
	if (!empty($settings['tunnel_network'])) {
1042
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
1043
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
1044
		$serverip = long2ip32($baselong + 1);
1045
		$clientip = long2ip32($baselong + 2);
1046
		/* Because this is being pushed, the order from the client's point of view. */
1047
		if ($settings['dev_mode'] != 'tap') {
1048
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
1049
		} else {
1050
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
1051
		}
1052
	}
1053

    
1054
	if ($settings['local_network']) {
1055
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
1056
	}
1057
	if ($settings['local_networkv6']) {
1058
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
1059
	}
1060

    
1061
	// Add a remote network iroute if set
1062
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
1063
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
1064
	}
1065
	// Add a remote network iroute if set
1066
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
1067
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
1068
	}
1069

    
1070
	openvpn_add_dhcpopts($settings, $conf);
1071

    
1072
	if ($settings['gwredir']) {
1073
		$conf .= "push \"redirect-gateway def1\"\n";
1074
	}
1075

    
1076
	openvpn_add_custom($settings, $conf);
1077

    
1078
	file_put_contents($fpath, $conf);
1079
	chown($fpath, 'nobody');
1080
	chgrp($fpath, 'nobody');
1081
}
1082

    
1083
function openvpn_delete_csc(& $settings) {
1084
	global $g, $config;
1085

    
1086
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
1087
	unlink_if_exists($fpath);
1088
}
1089

    
1090
// Resync the configuration and restart the VPN
1091
function openvpn_resync($mode, $settings) {
1092
	openvpn_reconfigure($mode, $settings);
1093
	openvpn_restart($mode, $settings);
1094
}
1095

    
1096
// Resync and restart all VPNs
1097
function openvpn_resync_all($interface = "") {
1098
	global $g, $config;
1099

    
1100
	if ($g['platform'] == 'jail') {
1101
		return;
1102
	}
1103
	openvpn_create_dirs();
1104

    
1105
	if (!is_array($config['openvpn'])) {
1106
		$config['openvpn'] = array();
1107
	}
1108

    
1109
/*
1110
	if (!$config['openvpn']['dh-parameters']) {
1111
		echo "Configuring OpenVPN Parameters ...\n";
1112
		$dh_parameters = openvpn_create_dhparams(1024);
1113
		$dh_parameters = base64_encode($dh_parameters);
1114
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1115
		write_config("OpenVPN DH parameters");
1116
	}
1117

    
1118
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1119
	if (!file_exists($path_ovdh)) {
1120
		$dh_parameters = $config['openvpn']['dh-parameters'];
1121
		$dh_parameters = base64_decode($dh_parameters);
1122
		file_put_contents($path_ovdh, $dh_parameters);
1123
	}
1124
*/
1125
	if ($interface <> "") {
1126
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
1127
	} else {
1128
		log_error("Resyncing OpenVPN instances.");
1129
	}
1130

    
1131
	if (is_array($config['openvpn']['openvpn-server'])) {
1132
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1133
			if ($interface <> "" && $interface != $settings['interface']) {
1134
				continue;
1135
			}
1136
			openvpn_resync('server', $settings);
1137
		}
1138
	}
1139

    
1140
	if (is_array($config['openvpn']['openvpn-client'])) {
1141
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1142
			if ($interface <> "" && $interface != $settings['interface']) {
1143
				continue;
1144
			}
1145
			openvpn_resync('client', $settings);
1146
		}
1147
	}
1148

    
1149
	if (is_array($config['openvpn']['openvpn-csc'])) {
1150
		foreach ($config['openvpn']['openvpn-csc'] as & $settings) {
1151
			openvpn_resync_csc($settings);
1152
		}
1153
	}
1154

    
1155
}
1156

    
1157
// Resync and restart all VPNs using a gateway group.
1158
function openvpn_resync_gwgroup($gwgroupname = "") {
1159
	global $g, $config;
1160

    
1161
	if ($gwgroupname <> "") {
1162
		if (is_array($config['openvpn']['openvpn-server'])) {
1163
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1164
				if ($gwgroupname == $settings['interface']) {
1165
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1166
					openvpn_resync('server', $settings);
1167
				}
1168
			}
1169
		}
1170

    
1171
		if (is_array($config['openvpn']['openvpn-client'])) {
1172
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1173
				if ($gwgroupname == $settings['interface']) {
1174
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1175
					openvpn_resync('client', $settings);
1176
				}
1177
			}
1178
		}
1179

    
1180
		// Note: no need to resysnc Client Specific (csc) here, as changes to the OpenVPN real interface do not effect these.
1181

    
1182
	} else {
1183
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter.");
1184
	}
1185
}
1186

    
1187
function openvpn_get_active_servers($type="multipoint") {
1188
	global $config, $g;
1189

    
1190
	$servers = array();
1191
	if (is_array($config['openvpn']['openvpn-server'])) {
1192
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1193
			if (empty($settings) || isset($settings['disable'])) {
1194
				continue;
1195
			}
1196

    
1197
			$prot = $settings['protocol'];
1198
			$port = $settings['local_port'];
1199

    
1200
			$server = array();
1201
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1202
			$server['mode'] = $settings['mode'];
1203
			if ($settings['description']) {
1204
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1205
			} else {
1206
				$server['name'] = "Server {$prot}:{$port}";
1207
			}
1208
			$server['conns'] = array();
1209
			$server['vpnid'] = $settings['vpnid'];
1210
			$server['mgmt'] = "server{$server['vpnid']}";
1211
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1212
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1213

    
1214
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30)) && ($type == "p2p")) {
1215
				$servers[] = openvpn_get_client_status($server, $socket);
1216
			} elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30)) {
1217
				$servers[] = openvpn_get_server_status($server, $socket);
1218
			}
1219
		}
1220
	}
1221
	return $servers;
1222
}
1223

    
1224
function openvpn_get_server_status($server, $socket) {
1225
	$errval;
1226
	$errstr;
1227
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1228
	if ($fp) {
1229
		stream_set_timeout($fp, 1);
1230

    
1231
		/* send our status request */
1232
		fputs($fp, "status 2\n");
1233

    
1234
		/* recv all response lines */
1235
		while (!feof($fp)) {
1236

    
1237
			/* read the next line */
1238
			$line = fgets($fp, 1024);
1239

    
1240
			$info = stream_get_meta_data($fp);
1241
			if ($info['timed_out']) {
1242
				break;
1243
			}
1244

    
1245
			/* parse header list line */
1246
			if (strstr($line, "HEADER")) {
1247
				continue;
1248
			}
1249

    
1250
			/* parse end of output line */
1251
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1252
				break;
1253
			}
1254

    
1255
			/* parse client list line */
1256
			if (strstr($line, "CLIENT_LIST")) {
1257
				$list = explode(",", $line);
1258
				$conn = array();
1259
				$conn['common_name'] = $list[1];
1260
				$conn['remote_host'] = $list[2];
1261
				$conn['virtual_addr'] = $list[3];
1262
				$conn['bytes_recv'] = $list[4];
1263
				$conn['bytes_sent'] = $list[5];
1264
				$conn['connect_time'] = $list[6];
1265
				$server['conns'][] = $conn;
1266
			}
1267
			/* parse routing table lines */
1268
			if (strstr($line, "ROUTING_TABLE")) {
1269
				$list = explode(",", $line);
1270
				$conn = array();
1271
				$conn['virtual_addr'] = $list[1];
1272
				$conn['common_name'] = $list[2];
1273
				$conn['remote_host'] = $list[3];
1274
				$conn['last_time'] = $list[4];
1275
				$server['routes'][] = $conn;
1276
			}
1277
		}
1278

    
1279
		/* cleanup */
1280
		fclose($fp);
1281
	} else {
1282
		$conn = array();
1283
		$conn['common_name'] = "[error]";
1284
		$conn['remote_host'] = "Unable to contact daemon";
1285
		$conn['virtual_addr'] = "Service not running?";
1286
		$conn['bytes_recv'] = 0;
1287
		$conn['bytes_sent'] = 0;
1288
		$conn['connect_time'] = 0;
1289
		$server['conns'][] = $conn;
1290
	}
1291
	return $server;
1292
}
1293

    
1294
function openvpn_get_active_clients() {
1295
	global $config, $g;
1296

    
1297
	$clients = array();
1298
	if (is_array($config['openvpn']['openvpn-client'])) {
1299
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1300

    
1301
			if (empty($settings) || isset($settings['disable'])) {
1302
				continue;
1303
			}
1304

    
1305
			$prot = $settings['protocol'];
1306
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1307

    
1308
			$client = array();
1309
			$client['port'] = $settings['local_port'];
1310
			if ($settings['description']) {
1311
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1312
			} else {
1313
				$client['name'] = "Client {$prot}{$port}";
1314
			}
1315

    
1316
			$client['vpnid'] = $settings['vpnid'];
1317
			$client['mgmt'] = "client{$client['vpnid']}";
1318
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1319
			$client['status']="down";
1320

    
1321
			$clients[] = openvpn_get_client_status($client, $socket);
1322
		}
1323
	}
1324
	return $clients;
1325
}
1326

    
1327
function openvpn_get_client_status($client, $socket) {
1328
	$errval;
1329
	$errstr;
1330
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1331
	if ($fp) {
1332
		stream_set_timeout($fp, 1);
1333
		/* send our status request */
1334
		fputs($fp, "state 1\n");
1335

    
1336
		/* recv all response lines */
1337
		while (!feof($fp)) {
1338
			/* read the next line */
1339
			$line = fgets($fp, 1024);
1340

    
1341
			$info = stream_get_meta_data($fp);
1342
			if ($info['timed_out']) {
1343
				break;
1344
			}
1345

    
1346
			/* Get the client state */
1347
			if (strstr($line,"CONNECTED")) {
1348
				$client['status']="up";
1349
				$list = explode(",", $line);
1350

    
1351
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1352
				$client['virtual_addr']  = $list[3];
1353
				$client['remote_host'] = $list[4];
1354
			}
1355
			if (strstr($line,"CONNECTING")) {
1356
				$client['status']="connecting";
1357
			}
1358
			if (strstr($line,"ASSIGN_IP")) {
1359
				$client['status']="waiting";
1360
				$list = explode(",", $line);
1361

    
1362
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1363
				$client['virtual_addr']  = $list[3];
1364
			}
1365
			if (strstr($line,"RECONNECTING")) {
1366
				$client['status']="reconnecting";
1367
				$list = explode(",", $line);
1368

    
1369
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1370
				$client['status'] .= "; " . $list[2];
1371
			}
1372
			/* parse end of output line */
1373
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1374
				break;
1375
			}
1376
		}
1377

    
1378
		/* If up, get read/write stats */
1379
		if (strcmp($client['status'], "up") == 0) {
1380
			fputs($fp, "status 2\n");
1381
			/* recv all response lines */
1382
			while (!feof($fp)) {
1383
				/* read the next line */
1384
				$line = fgets($fp, 1024);
1385

    
1386
				$info = stream_get_meta_data($fp);
1387
				if ($info['timed_out']) {
1388
					break;
1389
				}
1390

    
1391
				if (strstr($line,"TCP/UDP read bytes")) {
1392
					$list = explode(",", $line);
1393
					$client['bytes_recv'] = $list[1];
1394
				}
1395

    
1396
				if (strstr($line,"TCP/UDP write bytes")) {
1397
					$list = explode(",", $line);
1398
					$client['bytes_sent'] = $list[1];
1399
				}
1400

    
1401
				/* parse end of output line */
1402
				if (strstr($line, "END")) {
1403
					break;
1404
				}
1405
			}
1406
		}
1407

    
1408
		fclose($fp);
1409

    
1410
	} else {
1411
		$DisplayNote=true;
1412
		$client['remote_host'] = "Unable to contact daemon";
1413
		$client['virtual_addr'] = "Service not running?";
1414
		$client['bytes_recv'] = 0;
1415
		$client['bytes_sent'] = 0;
1416
		$client['connect_time'] = 0;
1417
	}
1418
	return $client;
1419
}
1420

    
1421
function openvpn_refresh_crls() {
1422
	global $g, $config;
1423

    
1424
	openvpn_create_dirs();
1425

    
1426
	if (is_array($config['openvpn']['openvpn-server'])) {
1427
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1428
			if (empty($settings)) {
1429
				continue;
1430
			}
1431
			if (isset($settings['disable'])) {
1432
				continue;
1433
			}
1434
			// Write the settings for the keys
1435
			switch ($settings['mode']) {
1436
				case 'p2p_tls':
1437
				case 'server_tls':
1438
				case 'server_tls_user':
1439
				case 'server_user':
1440
					if (!empty($settings['crlref'])) {
1441
						$crl = lookup_crl($settings['crlref']);
1442
						crl_update($crl);
1443
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1444
						file_put_contents($fpath, base64_decode($crl['text']));
1445
						@chmod($fpath, 0644);
1446
					}
1447
					break;
1448
			}
1449
		}
1450
	}
1451
}
1452

    
1453
function openvpn_create_dirs() {
1454
	global $g;
1455
	if (!is_dir("{$g['varetc_path']}/openvpn")) {
1456
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1457
	}
1458
	if (!is_dir("{$g['varetc_path']}/openvpn-csc")) {
1459
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1460
	}
1461
}
1462

    
1463
function openvpn_get_interface_ip($ip, $mask) {
1464
	$baselong = ip2long32($ip) & ip2long($mask);
1465
	$ip1 = long2ip32($baselong + 1);
1466
	$ip2 = long2ip32($baselong + 2);
1467
	return array($ip1, $ip2);
1468
}
1469

    
1470
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1471
	$basev6 = gen_subnetv6($ipv6, $prefix);
1472
	// Is there a better way to do this math?
1473
	$ipv6_arr = explode(':', $basev6);
1474
	$last = hexdec(array_pop($ipv6_arr));
1475
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1476
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1477
	return array($ipv6_1, $ipv6_2);
1478
}
1479

    
1480
function openvpn_clear_route($mode, $settings) {
1481
	if (empty($settings['tunnel_network'])) {
1482
		return;
1483
	}
1484
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1485
	$mask = gen_subnet_mask($cidr);
1486
	$clear_route = false;
1487

    
1488
	switch ($settings['mode']) {
1489
		case 'shared_key':
1490
			$clear_route = true;
1491
			break;
1492
		case 'p2p_tls':
1493
		case 'p2p_shared_key':
1494
			if ($cidr == 30) {
1495
				$clear_route = true;
1496
			}
1497
			break;
1498
	}
1499

    
1500
	if ($clear_route && !empty($ip) && !empty($mask)) {
1501
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1502
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1503
		/* XXX: Family for route? */
1504
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1505
	}
1506
}
1507

    
1508
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1509
	$routes = "";
1510
	if (empty($value)) {
1511
		return "";
1512
	}
1513
	$networks = explode(',', $value);
1514

    
1515
	foreach ($networks as $network) {
1516
		if ($ipproto == "ipv4") {
1517
			$route = openvpn_gen_route_ipv4($network, $iroute);
1518
		} else {
1519
			$route = openvpn_gen_route_ipv6($network, $iroute);
1520
		}
1521

    
1522
		if ($push) {
1523
			$routes .= "push \"{$route}\"\n";
1524
		} else {
1525
			$routes .= "{$route}\n";
1526
		}
1527
	}
1528
	return $routes;
1529
}
1530

    
1531
function openvpn_gen_route_ipv4($network, $iroute = false) {
1532
	$i = ($iroute) ? "i" : "";
1533
	list($ip, $mask) = explode('/', trim($network));
1534
	$mask = gen_subnet_mask($mask);
1535
	return "{$i}route $ip $mask";
1536
}
1537

    
1538
function openvpn_gen_route_ipv6($network, $iroute = false) {
1539
	$i = ($iroute) ? "i" : "";
1540
	list($ipv6, $prefix) = explode('/', trim($network));
1541
	if (empty($prefix)) {
1542
		$prefix = "128";
1543
	}
1544
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1545
}
1546

    
1547
function openvpn_get_settings($mode, $vpnid) {
1548
	global $config;
1549

    
1550
	if (is_array($config['openvpn']['openvpn-server'])) {
1551
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1552
			if (isset($settings['disable'])) {
1553
				continue;
1554
			}
1555

    
1556
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1557
				return $settings;
1558
			}
1559
		}
1560
	}
1561

    
1562
	if (is_array($config['openvpn']['openvpn-client'])) {
1563
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1564
			if (isset($settings['disable'])) {
1565
				continue;
1566
			}
1567

    
1568
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1569
				return $settings;
1570
			}
1571
		}
1572
	}
1573

    
1574
	return array();
1575
}
1576

    
1577
function openvpn_restart_by_vpnid($mode, $vpnid) {
1578
	$settings = openvpn_get_settings($mode, $vpnid);
1579
	openvpn_restart($mode, $settings);
1580
}
1581

    
1582
?>
(38-38/68)