Project

General

Profile

Download (44.2 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2 b1ad443d Scott Ullrich
/*
3 9a6d6728 Ermal
	openvpn.inc part of pfSense
4 42bb1bee Renato Botelho
5 33ab8aa5 Scott Ullrich
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
6
	All rights reserved.
7 42bb1bee Renato Botelho
8 b1ad443d Scott Ullrich
	Copyright (C) 2006  Fernando Lemos
9
	All rights reserved.
10
11 33ab8aa5 Scott Ullrich
	This file was rewritten from scratch by Fernando Lemos but
12
	*MIGHT* contain code previously written by:
13
14 b1ad443d Scott Ullrich
	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 42bb1bee Renato Botelho
41
42 2ec95f1f Renato Botelho
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/bin/openssl	/sbin/ifconfig
43 523855b0 Scott Ullrich
	pfSense_MODULE:	openvpn
44 b1ad443d Scott Ullrich
45 523855b0 Scott Ullrich
*/
46 8dc3ef67 Scott Ullrich
require_once('config.inc');
47 32a7a1f6 Ermal Lu?i
require_once("certs.inc");
48 36df0acc Scott Ullrich
require_once('pfsense-utils.inc');
49 c61e4626 Ermal Lu?i
require_once("auth.inc");
50 8dc3ef67 Scott Ullrich
51 f2291484 jim-p
global $openvpn_prots;
52 6714bbdc jim-p
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
53 702a4702 Scott Ullrich
54 f2291484 jim-p
global $openvpn_dev_mode;
55 691fbf14 Ermal Lu?i
$openvpn_dev_mode = array("tun", "tap");
56
57 b9e9903d Dmitriy K.
global $openvpn_verbosity_level;
58
$openvpn_verbosity_level = array(
59 42bb1bee Renato Botelho
	0 =>	"none",
60
	1 =>	"default",
61
	2 =>	"2",
62
	3 =>	"3 (recommended)",
63 b9e9903d Dmitriy K.
	4 =>	"4",
64
	5 => 	"5",
65
	6 => 	"6",
66
	7 => 	"7",
67
	8 => 	"8",
68
	9 => 	"9",
69
	10 => 	"10",
70
	11 => 	"11"
71 42bb1bee Renato Botelho
);
72 b9e9903d Dmitriy K.
73 42bb1bee Renato Botelho
/*
74 3c11bd3c Matthew Grooms
 * 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 f2291484 jim-p
global $openvpn_dh_lengths;
87 fe787fc7 Matthew Grooms
$openvpn_dh_lengths = array(
88 ef00af3c Phil Davis
	1024, 2048, 4096);
89 fe787fc7 Matthew Grooms
90 f2291484 jim-p
global $openvpn_cert_depths;
91 98963f27 jim-p
$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 f2291484 jim-p
global $openvpn_server_modes;
100 3c11bd3c Matthew Grooms
$openvpn_server_modes = array(
101 4aa02281 Carlos Eduardo Ramos
	'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 3c11bd3c Matthew Grooms
107 f2291484 jim-p
global $openvpn_client_modes;
108 3c11bd3c Matthew Grooms
$openvpn_client_modes = array(
109 4aa02281 Carlos Eduardo Ramos
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
110 ef00af3c Phil Davis
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"));
111 3c11bd3c Matthew Grooms
112 edba1982 jim-p
global $openvpn_compression_modes;
113
$openvpn_compression_modes = array(
114 ef00af3c Phil Davis
	'' => gettext("No Preference"),
115
	'no' => gettext("Disabled - No Compression"),
116
	'adaptive' => gettext("Enabled with Adaptive Compression"),
117
	'yes' => gettext("Enabled without Adaptive Compression"));
118 edba1982 jim-p
119 3c11bd3c Matthew Grooms
function openvpn_create_key() {
120
121
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
122 ef00af3c Phil Davis
	if (!$fp) {
123 3c11bd3c Matthew Grooms
		return false;
124 ef00af3c Phil Davis
	}
125 3c11bd3c Matthew Grooms
126
	$rslt = stream_get_contents($fp);
127
	pclose($fp);
128
129
	return $rslt;
130
}
131 d799787e Matthew Grooms
132 8411b218 Matthew Grooms
function openvpn_create_dhparams($bits) {
133 34bc1324 Matthew Grooms
134 2ec95f1f Renato Botelho
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
135 ef00af3c Phil Davis
	if (!$fp) {
136 34bc1324 Matthew Grooms
		return false;
137 ef00af3c Phil Davis
	}
138 34bc1324 Matthew Grooms
139
	$rslt = stream_get_contents($fp);
140
	pclose($fp);
141
142
	return $rslt;
143
}
144
145 d799787e Matthew Grooms
function openvpn_vpnid_used($vpnid) {
146 8be2d6d3 Ermal Luçi
	global $config;
147
148 ef00af3c Phil Davis
	if (is_array($config['openvpn']['openvpn-server'])) {
149
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
150
			if ($vpnid == $settings['vpnid']) {
151 d799787e Matthew Grooms
				return true;
152 ef00af3c Phil Davis
			}
153
		}
154
	}
155 d799787e Matthew Grooms
156 ef00af3c Phil Davis
	if (is_array($config['openvpn']['openvpn-client'])) {
157
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
158
			if ($vpnid == $settings['vpnid']) {
159 d799787e Matthew Grooms
				return true;
160 ef00af3c Phil Davis
			}
161
		}
162
	}
163 04a6e900 Ermal Luçi
164 d799787e Matthew Grooms
	return false;
165
}
166
167
function openvpn_vpnid_next() {
168
169
	$vpnid = 1;
170 ef00af3c Phil Davis
	while (openvpn_vpnid_used($vpnid)) {
171 d799787e Matthew Grooms
		$vpnid++;
172 ef00af3c Phil Davis
	}
173 d799787e Matthew Grooms
174
	return $vpnid;
175
}
176
177 49b76122 Renato Botelho
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
178 f432e364 Matthew Grooms
	global $config;
179
180 49b76122 Renato Botelho
	if (is_array($config['openvpn']['openvpn-server'])) {
181
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
182 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
183 49b76122 Renato Botelho
				continue;
184 ef00af3c Phil Davis
			}
185 49b76122 Renato Botelho
186 ef00af3c Phil Davis
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
187 49b76122 Renato Botelho
				continue;
188 ef00af3c Phil Davis
			}
189 49b76122 Renato Botelho
190
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
191 ef00af3c Phil Davis
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
192 f432e364 Matthew Grooms
				return $settings['vpnid'];
193 ef00af3c Phil Davis
			}
194 49b76122 Renato Botelho
		}
195
	}
196 f432e364 Matthew Grooms
197 49b76122 Renato Botelho
	if (is_array($config['openvpn']['openvpn-client'])) {
198
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
199 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
200 49b76122 Renato Botelho
				continue;
201 ef00af3c Phil Davis
			}
202 49b76122 Renato Botelho
203 ef00af3c Phil Davis
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
204 49b76122 Renato Botelho
				continue;
205 ef00af3c Phil Davis
			}
206 49b76122 Renato Botelho
207
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
208 ef00af3c Phil Davis
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
209 f432e364 Matthew Grooms
				return $settings['vpnid'];
210 ef00af3c Phil Davis
			}
211 49b76122 Renato Botelho
		}
212
	}
213 f432e364 Matthew Grooms
214
	return 0;
215
}
216
217 49b76122 Renato Botelho
function openvpn_port_next($prot, $interface = "wan") {
218 f432e364 Matthew Grooms
219
	$port = 1194;
220 ef00af3c Phil Davis
	while (openvpn_port_used($prot, $interface, $port)) {
221 49b76122 Renato Botelho
		$port++;
222 ef00af3c Phil Davis
	}
223
	while (openvpn_port_used($prot, "any", $port)) {
224 f432e364 Matthew Grooms
		$port++;
225 ef00af3c Phil Davis
	}
226 f432e364 Matthew Grooms
227
	return $port;
228
}
229
230 d799787e Matthew Grooms
function openvpn_get_cipherlist() {
231
232
	$ciphers = array();
233 5a7cc1f9 Ermal
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
234 d799787e Matthew Grooms
	$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 8be2d6d3 Ermal Luçi
	}
240 4aa02281 Carlos Eduardo Ramos
	$ciphers["none"] = gettext("None (No Encryption)");
241 d799787e Matthew Grooms
	return $ciphers;
242
}
243
244 97d5b59b jim-p
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 582c58ae jim-p
function openvpn_get_engines() {
259
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
260 2ec95f1f Renato Botelho
	exec("/usr/bin/openssl engine -t -c", $openssl_engine_output);
261 349bf358 jim-p
	$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 582c58ae jim-p
	foreach ($openssl_engine_output as $oeo) {
266 349bf358 jim-p
		$keep = true;
267
		$details = explode("|", $oeo);
268
		$engine = array_shift($details);
269 582c58ae jim-p
		$linematch = array();
270 349bf358 jim-p
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
271
		foreach ($details as $dt) {
272 ef00af3c Phil Davis
			if (strpos($dt, "unavailable") !== FALSE) {
273 349bf358 jim-p
				$keep = false;
274 ef00af3c Phil Davis
			}
275
			if (strpos($dt, "available") !== FALSE) {
276 349bf358 jim-p
				continue;
277 ef00af3c Phil Davis
			}
278
			if (strpos($dt, "[") !== FALSE) {
279 349bf358 jim-p
				$ciphers = trim($dt, "[]");
280 ef00af3c Phil Davis
			}
281 349bf358 jim-p
		}
282 ef00af3c Phil Davis
		if (!empty($ciphers)) {
283 349bf358 jim-p
			$ciphers = " - " . $ciphers;
284 ef00af3c Phil Davis
		}
285
		if (strlen($ciphers) > 60) {
286 349bf358 jim-p
			$ciphers = substr($ciphers, 0, 60) . " ... ";
287 ef00af3c Phil Davis
		}
288
		if ($keep) {
289 349bf358 jim-p
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
290 ef00af3c Phil Davis
		}
291 582c58ae jim-p
	}
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 d799787e Matthew Grooms
function openvpn_validate_host($value, $name) {
301
	$value = trim($value);
302 ef00af3c Phil Davis
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value))) {
303 4aa02281 Carlos Eduardo Ramos
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
304 ef00af3c Phil Davis
	}
305 d799787e Matthew Grooms
	return false;
306 8dc3ef67 Scott Ullrich
}
307
308
function openvpn_validate_port($value, $name) {
309
	$value = trim($value);
310 ef00af3c Phil Davis
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535)) {
311 4aa02281 Carlos Eduardo Ramos
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
312 ef00af3c Phil Davis
	}
313 b398bbca Martin Fuchs
	return false;
314 8dc3ef67 Scott Ullrich
}
315
316 a28d40cb jim-p
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
317
	$value = trim($value);
318
	$error = false;
319 ef00af3c Phil Davis
	if (empty($value)) {
320 a28d40cb jim-p
		return false;
321 ef00af3c Phil Davis
	}
322 a28d40cb jim-p
	$networks = explode(',', $value);
323
324 ef00af3c Phil Davis
	if (!$multiple && (count($networks) > 1)) {
325 a28d40cb jim-p
		return sprintf(gettext("The field '%s' must contain a single valid %s CIDR range."), $name, $ipproto);
326 ef00af3c Phil Davis
	}
327 a28d40cb jim-p
328
	foreach ($networks as $network) {
329 ef00af3c Phil Davis
		if ($ipproto == "ipv4") {
330 a28d40cb jim-p
			$error = !openvpn_validate_cidr_ipv4($network);
331 ef00af3c Phil Davis
		} else {
332 a28d40cb jim-p
			$error = !openvpn_validate_cidr_ipv6($network);
333 ef00af3c Phil Davis
		}
334
		if ($error) {
335 a28d40cb jim-p
			break;
336 ef00af3c Phil Davis
		}
337 a28d40cb jim-p
	}
338
339 ef00af3c Phil Davis
	if ($error) {
340 a28d40cb jim-p
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
341 ef00af3c Phil Davis
	} else {
342 a28d40cb jim-p
		return false;
343 ef00af3c Phil Davis
	}
344 a28d40cb jim-p
}
345
346
function openvpn_validate_cidr_ipv4($value) {
347 8dc3ef67 Scott Ullrich
	$value = trim($value);
348
	if (!empty($value)) {
349
		list($ip, $mask) = explode('/', $value);
350 ef00af3c Phil Davis
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0)) {
351 a28d40cb jim-p
			return false;
352 ef00af3c Phil Davis
		}
353 8dc3ef67 Scott Ullrich
	}
354 a28d40cb jim-p
	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 ef00af3c Phil Davis
		if (empty($prefix)) {
362 a28d40cb jim-p
			$prefix = "128";
363 ef00af3c Phil Davis
		}
364
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0)) {
365 a28d40cb jim-p
			return false;
366 ef00af3c Phil Davis
		}
367 a28d40cb jim-p
	}
368
	return true;
369 afb07cf1 Scott Ullrich
}
370
371 d799787e Matthew Grooms
function openvpn_add_dhcpopts(& $settings, & $conf) {
372 afb07cf1 Scott Ullrich
373 ef00af3c Phil Davis
	if (!empty($settings['dns_domain'])) {
374 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
375 ef00af3c Phil Davis
	}
376 add2e3f7 Scott Ullrich
377 ef00af3c Phil Davis
	if (!empty($settings['dns_server1'])) {
378 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
379 ef00af3c Phil Davis
	}
380
	if (!empty($settings['dns_server2'])) {
381 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
382 ef00af3c Phil Davis
	}
383
	if (!empty($settings['dns_server3'])) {
384 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
385 ef00af3c Phil Davis
	}
386
	if (!empty($settings['dns_server4'])) {
387 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
388 ef00af3c Phil Davis
	}
389 f9927473 Scott Ullrich
390 ef00af3c Phil Davis
	if (!empty($settings['push_register_dns'])) {
391 c38764dc Dmitriy K.
		$conf .= "push \"register-dns\"\n";
392 ef00af3c Phil Davis
	}
393 c38764dc Dmitriy K.
394 ef00af3c Phil Davis
	if (!empty($settings['ntp_server1'])) {
395 c7f70dbc Chris Buechler
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
396 ef00af3c Phil Davis
	}
397
	if (!empty($settings['ntp_server2'])) {
398 c7f70dbc Chris Buechler
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
399 ef00af3c Phil Davis
	}
400 f9927473 Scott Ullrich
401 d799787e Matthew Grooms
	if ($settings['netbios_enable']) {
402 add2e3f7 Scott Ullrich
403 ef00af3c Phil Davis
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0)) {
404 095a95ae Matthew Grooms
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
405 ef00af3c Phil Davis
		}
406
		if (!empty($settings['dhcp_nbtscope'])) {
407 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
408 ef00af3c Phil Davis
		}
409 8dc3ef67 Scott Ullrich
410 ef00af3c Phil Davis
		if (!empty($settings['wins_server1'])) {
411 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
412 ef00af3c Phil Davis
		}
413
		if (!empty($settings['wins_server2'])) {
414 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
415 ef00af3c Phil Davis
		}
416 add2e3f7 Scott Ullrich
417 ef00af3c Phil Davis
		if (!empty($settings['nbdd_server1'])) {
418 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
419 ef00af3c Phil Davis
		}
420 d799787e Matthew Grooms
	}
421 8dc3ef67 Scott Ullrich
422 ef00af3c Phil Davis
	if ($settings['gwredir']) {
423 d799787e Matthew Grooms
		$conf .= "push \"redirect-gateway def1\"\n";
424 ef00af3c Phil Davis
	}
425 d799787e Matthew Grooms
}
426 24012690 Scott Ullrich
427 d799787e Matthew Grooms
function openvpn_add_custom(& $settings, & $conf) {
428 add2e3f7 Scott Ullrich
429 d799787e Matthew Grooms
	if ($settings['custom_options']) {
430 8dc3ef67 Scott Ullrich
431 d799787e Matthew Grooms
		$options = explode(';', $settings['custom_options']);
432
433
		if (is_array($options)) {
434 ef00af3c Phil Davis
			foreach ($options as $option) {
435 d799787e Matthew Grooms
				$conf .= "$option\n";
436 ef00af3c Phil Davis
			}
437
		} else {
438 d799787e Matthew Grooms
			$conf .= "{$settings['custom_options']}\n";
439 ef00af3c Phil Davis
		}
440 add2e3f7 Scott Ullrich
	}
441
}
442
443 691fbf14 Ermal Lu?i
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
444 d799787e Matthew Grooms
	global $g;
445 add2e3f7 Scott Ullrich
446 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
447 a8f538a8 jim-p
	openvpn_create_dirs();
448 d799787e Matthew Grooms
	file_put_contents($fpath, base64_decode($data));
449 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
450
	//chgrp($fpath, 'nobody');
451 6f27412f Ermal Lu?i
	@chmod($fpath, 0600);
452 d799787e Matthew Grooms
453 691fbf14 Ermal Lu?i
	$conf .= "{$directive} {$fpath} {$opt}\n";
454 4eefa6e8 Scott Ullrich
}
455
456 fc05822b jim-p
function openvpn_reconfigure($mode, $settings) {
457 add2e3f7 Scott Ullrich
	global $g, $config;
458 afb07cf1 Scott Ullrich
459 ef00af3c Phil Davis
	if (empty($settings)) {
460 93a0a028 Ermal Luçi
		return;
461 ef00af3c Phil Davis
	}
462
	if (isset($settings['disable'])) {
463 4eefa6e8 Scott Ullrich
		return;
464 ef00af3c Phil Davis
	}
465 a8f538a8 jim-p
	openvpn_create_dirs();
466 fdd725f0 Ermal Luçi
	/*
467 d799787e Matthew Grooms
	 * 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 fdd725f0 Ermal Luçi
	 */
471 8874c692 Ermal Luçi
472 d799787e Matthew Grooms
	$vpnid = $settings['vpnid'];
473
	$mode_id = $mode.$vpnid;
474 8874c692 Ermal Luçi
475 ef00af3c Phil Davis
	if (isset($settings['dev_mode'])) {
476 4936ff53 jim-p
		$tunname = "{$settings['dev_mode']}{$vpnid}";
477 ef00af3c Phil Davis
	} else {
478
		/* defaults to tun */
479 bd7ca506 jim-p
		$tunname = "tun{$vpnid}";
480 4936ff53 jim-p
		$settings['dev_mode'] = "tun";
481 691fbf14 Ermal Lu?i
	}
482
483 ef00af3c Phil Davis
	if ($mode == "server") {
484 bd7ca506 jim-p
		$devname = "ovpns{$vpnid}";
485 ef00af3c Phil Davis
	} else {
486 bd7ca506 jim-p
		$devname = "ovpnc{$vpnid}";
487 ef00af3c Phil Davis
	}
488 8874c692 Ermal Luçi
489 bd7ca506 jim-p
	/* is our device already configured */
490 4a97aa34 Ermal
	if (!does_interface_exist($devname)) {
491 dc408939 Matthew Grooms
492 bd7ca506 jim-p
		/* create the tap device if required */
493 ef00af3c Phil Davis
		if (!file_exists("/dev/{$tunname}")) {
494 873c1701 Renato Botelho
			exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
495 ef00af3c Phil Davis
		}
496 98872d89 Ermal Luçi
497 bd7ca506 jim-p
		/* rename the device */
498 873c1701 Renato Botelho
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
499 095a95ae Matthew Grooms
500 4ab1ffa0 Renato Botelho
		/* add the device to the openvpn group and make sure it's UP*/
501
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn up");
502 da4f91a9 Renato Botelho
503 bd1a6267 Renato Botelho
		$ifname = convert_real_interface_to_friendly_interface_name($devname);
504
		$grouptmp = link_interface_to_group($ifname);
505 ef00af3c Phil Davis
		if (!empty($grouptmp)) {
506 bd1a6267 Renato Botelho
			array_walk($grouptmp, 'interface_group_add_member');
507 ef00af3c Phil Davis
		}
508 bd1a6267 Renato Botelho
		unset($grouptmp, $ifname);
509 dc408939 Matthew Grooms
	}
510 d799787e Matthew Grooms
511 dc408939 Matthew Grooms
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
512 6714bbdc jim-p
	$proto = strtolower($settings['protocol']);
513 ef00af3c Phil Davis
	if (substr($settings['protocol'], 0, 3) == "TCP") {
514 6714bbdc jim-p
			$proto = "{$proto}-{$mode}";
515 ef00af3c Phil Davis
	}
516 4936ff53 jim-p
	$dev_mode = $settings['dev_mode'];
517 c0cf27aa Scott Ullrich
	$cipher = $settings['crypto'];
518 97d5b59b jim-p
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
519
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
520 d799787e Matthew Grooms
521 47c48e28 smos
	$interface = get_failover_interface($settings['interface']);
522 e27bc6cf Phil Davis
	// The IP address in the settings can be an IPv4 or IPv6 address associated with the interface
523 d7a0c22a bcyrill
	$ipaddr = $settings['ipaddr'];
524 d799787e Matthew Grooms
525 67b0902f pierrepomes
	// If a specific ip address (VIP) is requested, use it.
526
	// Otherwise, if a specific interface is requested, use it
527 ef00af3c Phil Davis
	// If "any" interface was selected, local directive will be omitted.
528 97ffc513 Seth Mos
	if (is_ipaddrv4($ipaddr)) {
529 67b0902f pierrepomes
		$iface_ip=$ipaddr;
530 3d06e8f0 pierrepomes
	} else {
531 67b0902f pierrepomes
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
532 507af8dd pierrepomes
			$iface_ip=get_interface_ip($interface);
533 67b0902f pierrepomes
		}
534 47c48e28 smos
	}
535 e27bc6cf Phil Davis
	if (is_ipaddrv6($ipaddr)) {
536
		$iface_ipv6=$ipaddr;
537 47c48e28 smos
	} else {
538 97ffc513 Seth Mos
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
539
			$iface_ipv6=get_interface_ipv6($interface);
540
		}
541 3d06e8f0 pierrepomes
	}
542 d799787e Matthew Grooms
543 b1e8e675 Dmitriy K.
544
	$conf = "dev {$devname}\n";
545 5b3c0116 Dmitriy K.
	if (isset($settings['verbosity_level'])) {
546 b1e8e675 Dmitriy K.
		$conf .= "verb {$settings['verbosity_level']}\n";
547 5b3c0116 Dmitriy K.
	}
548 42bb1bee Renato Botelho
549 4936ff53 jim-p
	$conf .= "dev-type {$settings['dev_mode']}\n";
550 ef00af3c Phil Davis
	switch ($settings['dev_mode']) {
551 97ffc513 Seth Mos
		case "tun":
552 b9e9903d Dmitriy K.
			if (!$settings['no_tun_ipv6']) {
553
				$conf .= "tun-ipv6\n";
554
			}
555 97ffc513 Seth Mos
			break;
556
	}
557 bd7ca506 jim-p
	$conf .= "dev-node /dev/{$tunname}\n";
558 3c11bd3c Matthew Grooms
	$conf .= "writepid {$pfile}\n";
559
	$conf .= "#user nobody\n";
560
	$conf .= "#group nobody\n";
561 d1014c18 Chris Buechler
	$conf .= "script-security 3\n";
562 3c11bd3c Matthew Grooms
	$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 97d5b59b jim-p
	$conf .= "auth {$digest}\n";
570 8d964cea Ermal
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
571
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
572 1492e02c Ermal
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
573 ef00af3c Phil Davis
		switch ($settings['mode']) {
574 a1b9105b jim-p
			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 1492e02c Ermal
	}
581 3c11bd3c Matthew Grooms
582 6714bbdc jim-p
	/* 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 97ffc513 Seth Mos
	}
588 d799787e Matthew Grooms
589 ef00af3c Phil Davis
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none")) {
590 582c58ae jim-p
		$conf .= "engine {$settings['engine']}\n";
591 ef00af3c Phil Davis
	}
592 582c58ae jim-p
593 67b0902f pierrepomes
	// server specific settings
594 8dc3ef67 Scott Ullrich
	if ($mode == 'server') {
595 d799787e Matthew Grooms
596 5dc6c910 jim-p
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
597 97ffc513 Seth Mos
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
598 5dc6c910 jim-p
		$mask = gen_subnet_mask($cidr);
599 8dc3ef67 Scott Ullrich
600 3c11bd3c Matthew Grooms
		// configure tls modes
601 ef00af3c Phil Davis
		switch ($settings['mode']) {
602 3c11bd3c Matthew Grooms
			case 'p2p_tls':
603
			case 'server_tls':
604 e62e2f8b Ermal Lu?i
			case 'server_user':
605 3c11bd3c Matthew Grooms
			case 'server_tls_user':
606 d799787e Matthew Grooms
				$conf .= "tls-server\n";
607 3c11bd3c Matthew Grooms
				break;
608 8dc3ef67 Scott Ullrich
		}
609 d799787e Matthew Grooms
610 3c11bd3c Matthew Grooms
		// configure p2p/server modes
611 ef00af3c Phil Davis
		switch ($settings['mode']) {
612 6c9cf466 jim-p
			case 'p2p_tls':
613 5dc6c910 jim-p
				// 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 74a556a3 jim-p
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
617 5dc6c910 jim-p
					$conf .= "server {$ip} {$mask}\n";
618
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
619 ef00af3c Phil Davis
					if (is_ipaddr($ipv6)) {
620 a0e3ee98 jim-p
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
621 ef00af3c Phil Davis
					}
622 5dc6c910 jim-p
				}
623 3c11bd3c Matthew Grooms
			case 'p2p_shared_key':
624 74a556a3 jim-p
				if (!empty($ip) && !empty($mask)) {
625 91c44185 jim-p
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
626 ef00af3c Phil Davis
					if ($settings['dev_mode'] == 'tun') {
627 459e9333 jim-p
						$conf .= "ifconfig {$ip1} {$ip2}\n";
628 ef00af3c Phil Davis
					} else {
629 459e9333 jim-p
						$conf .= "ifconfig {$ip1} {$mask}\n";
630 ef00af3c Phil Davis
					}
631 1ab6bdb5 jim-p
				}
632 a0e3ee98 jim-p
				if (!empty($ipv6) && !empty($prefix)) {
633 91c44185 jim-p
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
634 ef00af3c Phil Davis
					if ($settings['dev_mode'] == 'tun') {
635 a0e3ee98 jim-p
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
636 ef00af3c Phil Davis
					} else {
637 60f501ec Phil Davis
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
638 ef00af3c Phil Davis
					}
639 a0e3ee98 jim-p
				}
640 3c11bd3c Matthew Grooms
				break;
641
			case 'server_tls':
642
			case 'server_user':
643
			case 'server_tls_user':
644 74a556a3 jim-p
				if (!empty($ip) && !empty($mask)) {
645 1ab6bdb5 jim-p
					$conf .= "server {$ip} {$mask}\n";
646 ef00af3c Phil Davis
					if (is_ipaddr($ipv6)) {
647 1ab6bdb5 jim-p
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
648 ef00af3c Phil Davis
					}
649 1ab6bdb5 jim-p
					$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 cb4f4ea9 jim-p
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
658 1ab6bdb5 jim-p
							} else {
659
								$conf .= "mode server\n";
660
							}
661
						} else {
662
							$conf .= "mode server\n";
663
						}
664
					}
665
				}
666 3c11bd3c Matthew Grooms
				break;
667 8dc3ef67 Scott Ullrich
		}
668
669 3c11bd3c Matthew Grooms
		// configure user auth modes
670 ef00af3c Phil Davis
		switch ($settings['mode']) {
671 3c11bd3c Matthew Grooms
			case 'server_user':
672
				$conf .= "client-cert-not-required\n";
673
			case 'server_tls_user':
674 9eced774 jim-p
				/* username-as-common-name is not compatible with server-bridge */
675 ef00af3c Phil Davis
				if (stristr($conf, "server-bridge") === false) {
676 9eced774 jim-p
					$conf .= "username-as-common-name\n";
677 ef00af3c Phil Davis
				}
678 8a47c190 Ermal Lu?i
				if (!empty($settings['authmode'])) {
679 5e28dad4 Ermal
					$strictusercn = "false";
680 ef00af3c Phil Davis
					if ($settings['strictusercn']) {
681 5e28dad4 Ermal
						$strictusercn = "true";
682 ef00af3c Phil Davis
					}
683 57ab9f7d Ermal
					$conf .= "auth-user-pass-verify \"/usr/local/sbin/ovpn_auth_verify user '{$settings['authmode']}' {$strictusercn} {$mode_id}\" via-env\n";
684 e8a58de4 Ermal Lu?i
				}
685 3c11bd3c Matthew Grooms
				break;
686 8dc3ef67 Scott Ullrich
		}
687 ef00af3c Phil Davis
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls'))) {
688 41936acc jim-p
			$settings['cert_depth'] = 1;
689 ef00af3c Phil Davis
		}
690 98963f27 jim-p
		if (is_numeric($settings['cert_depth'])) {
691 ef00af3c Phil Davis
			if (($mode == 'client') && empty($settings['certref'])) {
692 2da48592 jim-p
				$cert = "";
693 ef00af3c Phil Davis
			} else {
694 2da48592 jim-p
				$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 98963f27 jim-p
		}
700 8dc3ef67 Scott Ullrich
701 63084885 Matthew Grooms
		// The local port to listen on
702 d799787e Matthew Grooms
		$conf .= "lport {$settings['local_port']}\n";
703 c0cf27aa Scott Ullrich
704 63084885 Matthew Grooms
		// The management port to listen on
705 71ca2cb2 Ermal
		// 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 63084885 Matthew Grooms
709 ef00af3c Phil Davis
		if ($settings['maxclients']) {
710 d799787e Matthew Grooms
			$conf .= "max-clients {$settings['maxclients']}\n";
711 ef00af3c Phil Davis
		}
712 d799787e Matthew Grooms
713 3c11bd3c Matthew Grooms
		// Can we push routes
714
		if ($settings['local_network']) {
715 a28d40cb jim-p
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
716 3c11bd3c Matthew Grooms
		}
717 787de45a Seth Mos
		if ($settings['local_networkv6']) {
718 a28d40cb jim-p
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
719 787de45a Seth Mos
		}
720 3c11bd3c Matthew Grooms
721 ef00af3c Phil Davis
		switch ($settings['mode']) {
722 3c11bd3c Matthew Grooms
			case 'server_tls':
723
			case 'server_user':
724
			case 'server_tls_user':
725 5d8cd81a jim-p
				// Configure client dhcp options
726 3c11bd3c Matthew Grooms
				openvpn_add_dhcpopts($settings, $conf);
727 ef00af3c Phil Davis
				if ($settings['client2client']) {
728 5d8cd81a jim-p
					$conf .= "client-to-client\n";
729 ef00af3c Phil Davis
				}
730 3c11bd3c Matthew Grooms
				break;
731
		}
732 ef00af3c Phil Davis
		if (isset($settings['duplicate_cn'])) {
733 bca35cff jim-p
			$conf .= "duplicate-cn\n";
734 ef00af3c Phil Davis
		}
735 d799787e Matthew Grooms
	}
736
737 3c11bd3c Matthew Grooms
	// client specific settings
738 d799787e Matthew Grooms
739 3c11bd3c Matthew Grooms
	if ($mode == 'client') {
740 d799787e Matthew Grooms
741 3c11bd3c Matthew Grooms
		// configure p2p mode
742 ef00af3c Phil Davis
		switch ($settings['mode']) {
743 3c11bd3c Matthew Grooms
			case 'p2p_tls':
744
				$conf .= "tls-client\n";
745
			case 'shared_key':
746
				$conf .= "client\n";
747
				break;
748
		}
749 d799787e Matthew Grooms
750 e3924384 jim-p
		// If there is no bind option at all (ip and/or port), add "nobind" directive
751 42bb1bee Renato Botelho
		//  Otherwise, use the local port if defined, failing that, use lport 0 to
752 e3924384 jim-p
		//  ensure a random source port.
753 ef00af3c Phil Davis
		if ((empty($iface_ip)) && (!$settings['local_port'])) {
754 e3924384 jim-p
			$conf .= "nobind\n";
755 ef00af3c Phil Davis
		} elseif ($settings['local_port']) {
756 e3924384 jim-p
			$conf .= "lport {$settings['local_port']}\n";
757 ef00af3c Phil Davis
		} else {
758 e3924384 jim-p
			$conf .= "lport 0\n";
759 ef00af3c Phil Davis
		}
760 5708241f jim-p
761 4b887ef4 jim-p
		// 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 48a458d2 pierrepomes
764 3c11bd3c Matthew Grooms
		// The remote server
765
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
766
767 ef00af3c Phil Davis
		if (!empty($settings['use_shaper'])) {
768 d799787e Matthew Grooms
			$conf .= "shaper {$settings['use_shaper']}\n";
769 ef00af3c Phil Davis
		}
770 ee506044 Scott Ullrich
771 d799787e Matthew Grooms
		if (!empty($settings['tunnel_network'])) {
772
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
773 8dc3ef67 Scott Ullrich
			$mask = gen_subnet_mask($mask);
774 91c44185 jim-p
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
775 ef00af3c Phil Davis
			if ($settings['dev_mode'] == 'tun') {
776 459e9333 jim-p
				$conf .= "ifconfig {$ip2} {$ip1}\n";
777 ef00af3c Phil Davis
			} else {
778 459e9333 jim-p
				$conf .= "ifconfig {$ip2} {$mask}\n";
779 ef00af3c Phil Davis
			}
780 8dc3ef67 Scott Ullrich
		}
781 d799787e Matthew Grooms
782 a0e3ee98 jim-p
		if (!empty($settings['tunnel_networkv6'])) {
783
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
784 91c44185 jim-p
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
785 ef00af3c Phil Davis
			if ($settings['dev_mode'] == 'tun') {
786 a0e3ee98 jim-p
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
787 ef00af3c Phil Davis
			} else {
788 60f501ec Phil Davis
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
789 ef00af3c Phil Davis
			}
790 a0e3ee98 jim-p
		}
791
792 7304c023 Phil Davis
		if ($settings['auth_user'] || $settings['auth_pass']) {
793 5f242576 PiBa-NL
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
794
			$conf .= "auth-user-pass {$up_file}\n";
795 7304c023 Phil Davis
			if ($settings['auth_user']) {
796
				$userpass = "{$settings['auth_user']}\n";
797
			} else {
798
				$userpass = "";
799
			}
800
			if ($settings['auth_pass']) {
801
				$userpass .= "{$settings['auth_pass']}\n";
802
			}
803
			// If only auth_pass is given, then it acts like a user name and we put a blank line where pass would normally go.
804
			if (!($settings['auth_user'] && $settings['auth_pass'])) {
805
				$userpass .= "\n";
806
			}
807 5f242576 PiBa-NL
			file_put_contents($up_file, $userpass);
808
		}
809 42bb1bee Renato Botelho
810 762a24a3 Ermal Lu?i
		if ($settings['proxy_addr']) {
811
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
812
			if ($settings['proxy_authtype'] != "none") {
813
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
814
				$proxypas = "{$settings['proxy_user']}\n";
815
				$proxypas .= "{$settings['proxy_passwd']}\n";
816
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
817
			}
818
			$conf .= " \n";
819
		}
820 8dc3ef67 Scott Ullrich
	}
821
822 17c98ba9 jim-p
	// Add a remote network route if set, and only for p2p modes.
823 54285411 jim-p
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
824 a28d40cb jim-p
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
825 8dc3ef67 Scott Ullrich
	}
826 4856df9b jim-p
	// Add a remote network route if set, and only for p2p modes.
827 54285411 jim-p
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
828 a28d40cb jim-p
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
829 4856df9b jim-p
	}
830 afb07cf1 Scott Ullrich
831 d799787e Matthew Grooms
	// Write the settings for the keys
832 ef00af3c Phil Davis
	switch ($settings['mode']) {
833 3c11bd3c Matthew Grooms
		case 'p2p_shared_key':
834
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
835
			break;
836
		case 'p2p_tls':
837
		case 'server_tls':
838
		case 'server_tls_user':
839 e62e2f8b Ermal Lu?i
		case 'server_user':
840 3c11bd3c Matthew Grooms
			$ca = lookup_ca($settings['caref']);
841
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
842 2da48592 jim-p
843
			if (!empty($settings['certref'])) {
844
				$cert = lookup_cert($settings['certref']);
845
				openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
846
				openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
847
			}
848 ef00af3c Phil Davis
			if ($mode == 'server') {
849 fe787fc7 Matthew Grooms
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
850 ef00af3c Phil Davis
			}
851 6db02381 jim-p
			if (!empty($settings['crlref'])) {
852
				$crl = lookup_crl($settings['crlref']);
853 cfcc6994 jim-p
				crl_update($crl);
854 6db02381 jim-p
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
855
			}
856 db746ce2 Ermal Lu?i
			if ($settings['tls']) {
857 ef00af3c Phil Davis
				if ($mode == "server") {
858 db746ce2 Ermal Lu?i
					$tlsopt = 0;
859 ef00af3c Phil Davis
				} else {
860 db746ce2 Ermal Lu?i
					$tlsopt = 1;
861 ef00af3c Phil Davis
				}
862 db746ce2 Ermal Lu?i
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
863
			}
864 3c11bd3c Matthew Grooms
			break;
865 8dc3ef67 Scott Ullrich
	}
866
867 ef00af3c Phil Davis
	if (!empty($settings['compression'])) {
868 edba1982 jim-p
		$conf .= "comp-lzo {$settings['compression']}\n";
869 ef00af3c Phil Davis
	}
870 d799787e Matthew Grooms
871 ef00af3c Phil Davis
	if ($settings['passtos']) {
872 d799787e Matthew Grooms
		$conf .= "passtos\n";
873 ef00af3c Phil Davis
	}
874 d799787e Matthew Grooms
875 ef00af3c Phil Davis
	if ($settings['resolve_retry']) {
876 d799787e Matthew Grooms
		$conf .= "resolv-retry infinite\n";
877 ef00af3c Phil Davis
	} else if ($mode == 'clie} nt') {
878 30640018 Chris Buechler
		$conf .= "resolv-retry infinite\n";
879 ef00af3c Phil Davis
	}
880 d799787e Matthew Grooms
881
	if ($settings['dynamic_ip']) {
882
		$conf .= "persist-remote-ip\n";
883
		$conf .= "float\n";
884 8dc3ef67 Scott Ullrich
	}
885 afb07cf1 Scott Ullrich
886 ee55ce7d jim-p
	if ($settings['topology_subnet']) {
887
		$conf .= "topology subnet\n";
888
	}
889
890 b9e9903d Dmitriy K.
	// New client features
891
	if ($mode == "client") {
892
		// Dont pull routes checkbox
893
		if ($settings['route_no_pull']) {
894
			$conf .= "route-nopull\n";
895
		}
896
897
		// Dont add/remove routes checkbox
898
		if ($settings['route_no_exec']) {
899
			$conf .= "route-noexec\n";
900
		}
901
	}
902
903 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
904
905 a8f538a8 jim-p
	openvpn_create_dirs();
906 938fc5b0 Ermal
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
907 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
908 938fc5b0 Ermal
	unset($conf);
909 be00850b Phil Davis
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
910
	file_put_contents($fpath, $interface);
911 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
912
	//chgrp($fpath, 'nobody');
913 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
914 be00850b Phil Davis
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
915 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
916
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
917
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
918 d799787e Matthew Grooms
}
919
920 fc05822b jim-p
function openvpn_restart($mode, $settings) {
921 d799787e Matthew Grooms
	global $g, $config;
922
923
	$vpnid = $settings['vpnid'];
924
	$mode_id = $mode.$vpnid;
925
926 76369bfc Matthew Grooms
	/* kill the process if running */
927 705c8ec9 Matthew Grooms
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
928 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
929 705c8ec9 Matthew Grooms
930 76369bfc Matthew Grooms
		/* read the pid file */
931
		$pid = rtrim(file_get_contents($pfile));
932
		unlink($pfile);
933 705c8ec9 Matthew Grooms
934 76369bfc Matthew Grooms
		/* send a term signal to the process */
935
		posix_kill($pid, SIGTERM);
936
937 93ead355 Chris Buechler
		/* wait until the process exits, or timeout and kill it */
938
		$i = 0;
939 ef00af3c Phil Davis
		while (posix_kill($pid, 0)) {
940 76369bfc Matthew Grooms
			usleep(250000);
941 93ead355 Chris Buechler
			if ($i > 10) {
942
				log_error("OpenVPN ID $mode_id PID $pid still running, killing.");
943
				posix_kill($pid, SIGKILL);
944 02a2bffa Chris Buechler
				usleep(500000);
945 93ead355 Chris Buechler
			}
946
			$i++;
947
		}
948 76369bfc Matthew Grooms
	}
949 d799787e Matthew Grooms
950 ef00af3c Phil Davis
	if (isset($settings['disable'])) {
951 d799787e Matthew Grooms
		return;
952 ef00af3c Phil Davis
	}
953 d799787e Matthew Grooms
954 260f267e jim-p
	/* Do not start a client if we are a CARP backup on this vip! */
955 ef00af3c Phil Davis
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) != "MASTER")) {
956 9ea0cb90 jim-p
		return;
957 ef00af3c Phil Davis
	}
958 42bb1bee Renato Botelho
959
	/* Check if client is bound to a gateway group */
960 330ecea1 Shahid Sheikh
	$a_groups = return_gateway_groups_array();
961
	if (is_array($a_groups[$settings['interface']])) {
962 ef00af3c Phil Davis
		/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
963
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) != "MASTER")) {
964 330ecea1 Shahid Sheikh
			return;
965 ef00af3c Phil Davis
		}
966 330ecea1 Shahid Sheikh
	}
967 9ea0cb90 jim-p
968 705c8ec9 Matthew Grooms
	/* start the new process */
969 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
970 91c44185 jim-p
	openvpn_clear_route($mode, $settings);
971 873c1701 Renato Botelho
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
972 847cd48d Ermal
973 ef00af3c Phil Davis
	if (!platform_booting()) {
974 847cd48d Ermal
		send_event("filter reload");
975 ef00af3c Phil Davis
	}
976 afb07cf1 Scott Ullrich
}
977
978 dc408939 Matthew Grooms
function openvpn_delete($mode, & $settings) {
979 d799787e Matthew Grooms
	global $g, $config;
980
981
	$vpnid = $settings['vpnid'];
982
	$mode_id = $mode.$vpnid;
983
984 ef00af3c Phil Davis
	if (isset($settings['dev_mode'])) {
985 da601f8e PiBa-NL
		$tunname = "{$settings['dev_mode']}{$vpnid}";
986 ef00af3c Phil Davis
	} else {
987
		/* defaults to tun */
988 da601f8e PiBa-NL
		$tunname = "tun{$vpnid}";
989
	}
990
991 ef00af3c Phil Davis
	if ($mode == "server") {
992 095a95ae Matthew Grooms
		$devname = "ovpns{$vpnid}";
993 ef00af3c Phil Davis
	} else {
994 095a95ae Matthew Grooms
		$devname = "ovpnc{$vpnid}";
995 ef00af3c Phil Davis
	}
996 dc408939 Matthew Grooms
997 76369bfc Matthew Grooms
	/* kill the process if running */
998 dc408939 Matthew Grooms
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
999 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
1000 dc408939 Matthew Grooms
1001 76369bfc Matthew Grooms
		/* read the pid file */
1002
		$pid = trim(file_get_contents($pfile));
1003
		unlink($pfile);
1004
1005
		/* send a term signal to the process */
1006
		posix_kill($pid, SIGTERM);
1007
	}
1008 705c8ec9 Matthew Grooms
1009 095a95ae Matthew Grooms
	/* remove the device from the openvpn group */
1010 873c1701 Renato Botelho
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
1011 095a95ae Matthew Grooms
1012 dc408939 Matthew Grooms
	/* restore the original adapter name */
1013 873c1701 Renato Botelho
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
1014 dc408939 Matthew Grooms
1015
	/* remove the configuration files */
1016 8bb47a46 Ermal
	@array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
1017 d799787e Matthew Grooms
}
1018 afb07cf1 Scott Ullrich
1019 de85521a jim-p
function openvpn_cleanup_csc($common_name) {
1020
	global $g, $config;
1021 ef00af3c Phil Davis
	if (empty($common_name)) {
1022 de85521a jim-p
		return;
1023 ef00af3c Phil Davis
	}
1024 de85521a jim-p
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
1025 ef00af3c Phil Davis
	if (is_file($fpath)) {
1026 de85521a jim-p
		unlink_if_exists($fpath);
1027 ef00af3c Phil Davis
	}
1028 de85521a jim-p
	return;
1029
}
1030
1031 dc408939 Matthew Grooms
function openvpn_resync_csc(& $settings) {
1032 8dc3ef67 Scott Ullrich
	global $g, $config;
1033
1034 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
1035 8dc3ef67 Scott Ullrich
1036 a1cab2c7 Ermal
	if (isset($settings['disable'])) {
1037 d799787e Matthew Grooms
		unlink_if_exists($fpath);
1038 c876662c Scott Ullrich
		return;
1039
	}
1040 a8f538a8 jim-p
	openvpn_create_dirs();
1041 d799787e Matthew Grooms
1042 8dc3ef67 Scott Ullrich
	$conf = '';
1043 ef00af3c Phil Davis
	if ($settings['block']) {
1044 d799787e Matthew Grooms
		$conf .= "disable\n";
1045 ef00af3c Phil Davis
	}
1046 d799787e Matthew Grooms
1047 ef00af3c Phil Davis
	if ($settings['push_reset']) {
1048 d799787e Matthew Grooms
		$conf .= "push-reset\n";
1049 ef00af3c Phil Davis
	}
1050 d799787e Matthew Grooms
1051
	if (!empty($settings['tunnel_network'])) {
1052
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
1053 96033063 Erik Fonnesbeck
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
1054 298fe5ae jim-p
		$serverip = long2ip32($baselong + 1);
1055
		$clientip = long2ip32($baselong + 2);
1056
		/* Because this is being pushed, the order from the client's point of view. */
1057 ef00af3c Phil Davis
		if ($settings['dev_mode'] != 'tap') {
1058 d9c96fb1 jim-p
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
1059 ef00af3c Phil Davis
		} else {
1060 e052047d jim-p
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
1061 ef00af3c Phil Davis
		}
1062 8dc3ef67 Scott Ullrich
	}
1063 6d031071 Martin Fuchs
1064 5c427ce7 jim-p
	if ($settings['local_network']) {
1065
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
1066
	}
1067
	if ($settings['local_networkv6']) {
1068
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
1069
	}
1070
1071
	// Add a remote network iroute if set
1072
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
1073
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
1074
	}
1075
	// Add a remote network iroute if set
1076
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
1077
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
1078
	}
1079
1080 d799787e Matthew Grooms
	openvpn_add_dhcpopts($settings, $conf);
1081 8dc3ef67 Scott Ullrich
1082 ef00af3c Phil Davis
	if ($settings['gwredir']) {
1083 d799787e Matthew Grooms
		$conf .= "push \"redirect-gateway def1\"\n";
1084 ef00af3c Phil Davis
	}
1085 6d031071 Martin Fuchs
1086 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
1087 8dc3ef67 Scott Ullrich
1088 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
1089
	chown($fpath, 'nobody');
1090
	chgrp($fpath, 'nobody');
1091
}
1092 8dc3ef67 Scott Ullrich
1093 dc408939 Matthew Grooms
function openvpn_delete_csc(& $settings) {
1094 add2e3f7 Scott Ullrich
	global $g, $config;
1095 3c2e5528 Scott Ullrich
1096 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
1097 d799787e Matthew Grooms
	unlink_if_exists($fpath);
1098 267ab13f Ermal Luçi
}
1099 afb07cf1 Scott Ullrich
1100 24012690 Scott Ullrich
// Resync the configuration and restart the VPN
1101 fc05822b jim-p
function openvpn_resync($mode, $settings) {
1102 dc408939 Matthew Grooms
	openvpn_reconfigure($mode, $settings);
1103
	openvpn_restart($mode, $settings);
1104 afb07cf1 Scott Ullrich
}
1105
1106 add2e3f7 Scott Ullrich
// Resync and restart all VPNs
1107 c7f60193 Ermal
function openvpn_resync_all($interface = "") {
1108 d799787e Matthew Grooms
	global $g, $config;
1109 267ab13f Ermal Luçi
1110 ef00af3c Phil Davis
	if ($g['platform'] == 'jail') {
1111 7734aea6 Andrew Thompson
		return;
1112 ef00af3c Phil Davis
	}
1113 a8f538a8 jim-p
	openvpn_create_dirs();
1114 3cb54b54 Matthew Grooms
1115 ef00af3c Phil Davis
	if (!is_array($config['openvpn'])) {
1116 34bc1324 Matthew Grooms
		$config['openvpn'] = array();
1117 ef00af3c Phil Davis
	}
1118 34bc1324 Matthew Grooms
1119 15b414e6 Matthew Grooms
/*
1120 34bc1324 Matthew Grooms
	if (!$config['openvpn']['dh-parameters']) {
1121
		echo "Configuring OpenVPN Parameters ...\n";
1122 035e4289 Matthew Grooms
		$dh_parameters = openvpn_create_dhparams(1024);
1123 34bc1324 Matthew Grooms
		$dh_parameters = base64_encode($dh_parameters);
1124
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1125 c67dd94e Bill Marquette
		write_config("OpenVPN DH parameters");
1126 34bc1324 Matthew Grooms
	}
1127
1128
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1129
	if (!file_exists($path_ovdh)) {
1130
		$dh_parameters = $config['openvpn']['dh-parameters'];
1131
		$dh_parameters = base64_decode($dh_parameters);
1132
		file_put_contents($path_ovdh, $dh_parameters);
1133
	}
1134 15b414e6 Matthew Grooms
*/
1135 ef00af3c Phil Davis
	if ($interface <> "") {
1136 a82e6d37 Chris Buechler
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
1137 ef00af3c Phil Davis
	} else {
1138 42bb1bee Renato Botelho
		log_error("Resyncing OpenVPN instances.");
1139 ef00af3c Phil Davis
	}
1140 34bc1324 Matthew Grooms
1141 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-server'])) {
1142
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1143 ef00af3c Phil Davis
			if ($interface <> "" && $interface != $settings['interface']) {
1144 c7f60193 Ermal
				continue;
1145 ef00af3c Phil Davis
			}
1146 dc408939 Matthew Grooms
			openvpn_resync('server', $settings);
1147 c7f60193 Ermal
		}
1148
	}
1149 5b237745 Scott Ullrich
1150 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-client'])) {
1151
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1152 ef00af3c Phil Davis
			if ($interface <> "" && $interface != $settings['interface']) {
1153 c7f60193 Ermal
				continue;
1154 ef00af3c Phil Davis
			}
1155 dc408939 Matthew Grooms
			openvpn_resync('client', $settings);
1156 c7f60193 Ermal
		}
1157
	}
1158 afb07cf1 Scott Ullrich
1159 ef00af3c Phil Davis
	if (is_array($config['openvpn']['openvpn-csc'])) {
1160
		foreach ($config['openvpn']['openvpn-csc'] as & $settings) {
1161 dc408939 Matthew Grooms
			openvpn_resync_csc($settings);
1162 ef00af3c Phil Davis
		}
1163
	}
1164 afb07cf1 Scott Ullrich
1165 5b237745 Scott Ullrich
}
1166 702a4702 Scott Ullrich
1167 99cc103b Phil Davis
// Resync and restart all VPNs using a gateway group.
1168
function openvpn_resync_gwgroup($gwgroupname = "") {
1169
	global $g, $config;
1170
1171
	if ($gwgroupname <> "") {
1172
		if (is_array($config['openvpn']['openvpn-server'])) {
1173
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1174
				if ($gwgroupname == $settings['interface']) {
1175
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1176
					openvpn_resync('server', $settings);
1177
				}
1178
			}
1179
		}
1180
1181
		if (is_array($config['openvpn']['openvpn-client'])) {
1182
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1183
				if ($gwgroupname == $settings['interface']) {
1184
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1185
					openvpn_resync('client', $settings);
1186
				}
1187
			}
1188
		}
1189
1190
		// Note: no need to resysnc Client Specific (csc) here, as changes to the OpenVPN real interface do not effect these.
1191
1192 ef00af3c Phil Davis
	} else {
1193 42bb1bee Renato Botelho
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter.");
1194 ef00af3c Phil Davis
	}
1195 99cc103b Phil Davis
}
1196
1197 453d9c96 jim-p
function openvpn_get_active_servers($type="multipoint") {
1198 71ca2cb2 Ermal
	global $config, $g;
1199
1200 53663f57 jim-p
	$servers = array();
1201
	if (is_array($config['openvpn']['openvpn-server'])) {
1202
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1203 ef00af3c Phil Davis
			if (empty($settings) || isset($settings['disable'])) {
1204 6b2dcac5 Ermal
				continue;
1205 ef00af3c Phil Davis
			}
1206 6b2dcac5 Ermal
1207 53663f57 jim-p
			$prot = $settings['protocol'];
1208
			$port = $settings['local_port'];
1209 42bb1bee Renato Botelho
1210 53663f57 jim-p
			$server = array();
1211 95305736 jim-p
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1212 41be629f jim-p
			$server['mode'] = $settings['mode'];
1213 ef00af3c Phil Davis
			if ($settings['description']) {
1214 53663f57 jim-p
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1215 ef00af3c Phil Davis
			} else {
1216 53663f57 jim-p
				$server['name'] = "Server {$prot}:{$port}";
1217 ef00af3c Phil Davis
			}
1218 53663f57 jim-p
			$server['conns'] = array();
1219 2eaa97b9 jim-p
			$server['vpnid'] = $settings['vpnid'];
1220
			$server['mgmt'] = "server{$server['vpnid']}";
1221
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1222 453d9c96 jim-p
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1223
1224 ef00af3c Phil Davis
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30)) && ($type == "p2p")) {
1225 95305736 jim-p
				$servers[] = openvpn_get_client_status($server, $socket);
1226 ef00af3c Phil Davis
			} elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30)) {
1227 95305736 jim-p
				$servers[] = openvpn_get_server_status($server, $socket);
1228 ef00af3c Phil Davis
			}
1229 95305736 jim-p
		}
1230
	}
1231
	return $servers;
1232
}
1233 b0140675 Ermal
1234 95305736 jim-p
function openvpn_get_server_status($server, $socket) {
1235
	$errval;
1236
	$errstr;
1237
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1238
	if ($fp) {
1239
		stream_set_timeout($fp, 1);
1240
1241
		/* send our status request */
1242
		fputs($fp, "status 2\n");
1243
1244
		/* recv all response lines */
1245
		while (!feof($fp)) {
1246
1247
			/* read the next line */
1248
			$line = fgets($fp, 1024);
1249
1250
			$info = stream_get_meta_data($fp);
1251 ef00af3c Phil Davis
			if ($info['timed_out']) {
1252 95305736 jim-p
				break;
1253 ef00af3c Phil Davis
			}
1254 95305736 jim-p
1255
			/* parse header list line */
1256 ef00af3c Phil Davis
			if (strstr($line, "HEADER")) {
1257 95305736 jim-p
				continue;
1258 ef00af3c Phil Davis
			}
1259 95305736 jim-p
1260
			/* parse end of output line */
1261 ef00af3c Phil Davis
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1262 95305736 jim-p
				break;
1263 ef00af3c Phil Davis
			}
1264 95305736 jim-p
1265
			/* parse client list line */
1266
			if (strstr($line, "CLIENT_LIST")) {
1267
				$list = explode(",", $line);
1268 53663f57 jim-p
				$conn = array();
1269 95305736 jim-p
				$conn['common_name'] = $list[1];
1270
				$conn['remote_host'] = $list[2];
1271
				$conn['virtual_addr'] = $list[3];
1272
				$conn['bytes_recv'] = $list[4];
1273
				$conn['bytes_sent'] = $list[5];
1274
				$conn['connect_time'] = $list[6];
1275 53663f57 jim-p
				$server['conns'][] = $conn;
1276
			}
1277 ec970b50 jim-p
			/* parse routing table lines */
1278
			if (strstr($line, "ROUTING_TABLE")) {
1279
				$list = explode(",", $line);
1280
				$conn = array();
1281
				$conn['virtual_addr'] = $list[1];
1282
				$conn['common_name'] = $list[2];
1283
				$conn['remote_host'] = $list[3];
1284
				$conn['last_time'] = $list[4];
1285
				$server['routes'][] = $conn;
1286
			}
1287 53663f57 jim-p
		}
1288 95305736 jim-p
1289
		/* cleanup */
1290
		fclose($fp);
1291
	} else {
1292
		$conn = array();
1293
		$conn['common_name'] = "[error]";
1294 2eaa97b9 jim-p
		$conn['remote_host'] = "Unable to contact daemon";
1295
		$conn['virtual_addr'] = "Service not running?";
1296 95305736 jim-p
		$conn['bytes_recv'] = 0;
1297
		$conn['bytes_sent'] = 0;
1298
		$conn['connect_time'] = 0;
1299
		$server['conns'][] = $conn;
1300 53663f57 jim-p
	}
1301 95305736 jim-p
	return $server;
1302 53663f57 jim-p
}
1303
1304
function openvpn_get_active_clients() {
1305 71ca2cb2 Ermal
	global $config, $g;
1306
1307 53663f57 jim-p
	$clients = array();
1308
	if (is_array($config['openvpn']['openvpn-client'])) {
1309
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1310 42bb1bee Renato Botelho
1311 ef00af3c Phil Davis
			if (empty($settings) || isset($settings['disable'])) {
1312 6b2dcac5 Ermal
				continue;
1313 ef00af3c Phil Davis
			}
1314 6b2dcac5 Ermal
1315 53663f57 jim-p
			$prot = $settings['protocol'];
1316 95305736 jim-p
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1317 42bb1bee Renato Botelho
1318 53663f57 jim-p
			$client = array();
1319
			$client['port'] = $settings['local_port'];
1320 ef00af3c Phil Davis
			if ($settings['description']) {
1321 95305736 jim-p
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1322 ef00af3c Phil Davis
			} else {
1323 95305736 jim-p
				$client['name'] = "Client {$prot}{$port}";
1324 ef00af3c Phil Davis
			}
1325 42bb1bee Renato Botelho
1326 2eaa97b9 jim-p
			$client['vpnid'] = $settings['vpnid'];
1327
			$client['mgmt'] = "client{$client['vpnid']}";
1328
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1329 53663f57 jim-p
			$client['status']="down";
1330 95305736 jim-p
1331
			$clients[] = openvpn_get_client_status($client, $socket);
1332
		}
1333
	}
1334
	return $clients;
1335
}
1336
1337
function openvpn_get_client_status($client, $socket) {
1338
	$errval;
1339
	$errstr;
1340
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1341
	if ($fp) {
1342
		stream_set_timeout($fp, 1);
1343
		/* send our status request */
1344
		fputs($fp, "state 1\n");
1345
1346
		/* recv all response lines */
1347
		while (!feof($fp)) {
1348
			/* read the next line */
1349
			$line = fgets($fp, 1024);
1350
1351
			$info = stream_get_meta_data($fp);
1352 ef00af3c Phil Davis
			if ($info['timed_out']) {
1353 95305736 jim-p
				break;
1354 ef00af3c Phil Davis
			}
1355 95305736 jim-p
1356
			/* Get the client state */
1357
			if (strstr($line,"CONNECTED")) {
1358
				$client['status']="up";
1359
				$list = explode(",", $line);
1360
1361
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1362
				$client['virtual_addr']  = $list[3];
1363
				$client['remote_host'] = $list[4];
1364
			}
1365 453d9c96 jim-p
			if (strstr($line,"CONNECTING")) {
1366
				$client['status']="connecting";
1367
			}
1368
			if (strstr($line,"ASSIGN_IP")) {
1369
				$client['status']="waiting";
1370
				$list = explode(",", $line);
1371
1372
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1373
				$client['virtual_addr']  = $list[3];
1374
			}
1375
			if (strstr($line,"RECONNECTING")) {
1376
				$client['status']="reconnecting";
1377
				$list = explode(",", $line);
1378
1379
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1380
				$client['status'] .= "; " . $list[2];
1381
			}
1382 95305736 jim-p
			/* parse end of output line */
1383 ef00af3c Phil Davis
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1384 95305736 jim-p
				break;
1385 ef00af3c Phil Davis
			}
1386 95305736 jim-p
		}
1387
1388
		/* If up, get read/write stats */
1389
		if (strcmp($client['status'], "up") == 0) {
1390
			fputs($fp, "status 2\n");
1391
			/* recv all response lines */
1392
			while (!feof($fp)) {
1393
				/* read the next line */
1394
				$line = fgets($fp, 1024);
1395
1396
				$info = stream_get_meta_data($fp);
1397 ef00af3c Phil Davis
				if ($info['timed_out']) {
1398 95305736 jim-p
					break;
1399 ef00af3c Phil Davis
				}
1400 95305736 jim-p
1401
				if (strstr($line,"TCP/UDP read bytes")) {
1402
					$list = explode(",", $line);
1403
					$client['bytes_recv'] = $list[1];
1404 53663f57 jim-p
				}
1405 95305736 jim-p
1406
				if (strstr($line,"TCP/UDP write bytes")) {
1407
					$list = explode(",", $line);
1408
					$client['bytes_sent'] = $list[1];
1409 53663f57 jim-p
				}
1410 95305736 jim-p
1411
				/* parse end of output line */
1412 ef00af3c Phil Davis
				if (strstr($line, "END")) {
1413 95305736 jim-p
					break;
1414 ef00af3c Phil Davis
				}
1415 53663f57 jim-p
			}
1416
		}
1417 95305736 jim-p
1418
		fclose($fp);
1419
1420
	} else {
1421
		$DisplayNote=true;
1422 2eaa97b9 jim-p
		$client['remote_host'] = "Unable to contact daemon";
1423
		$client['virtual_addr'] = "Service not running?";
1424 95305736 jim-p
		$client['bytes_recv'] = 0;
1425
		$client['bytes_sent'] = 0;
1426
		$client['connect_time'] = 0;
1427 53663f57 jim-p
	}
1428 95305736 jim-p
	return $client;
1429 53663f57 jim-p
}
1430 8e022a76 jim-p
1431
function openvpn_refresh_crls() {
1432
	global $g, $config;
1433
1434 a8f538a8 jim-p
	openvpn_create_dirs();
1435 8e022a76 jim-p
1436
	if (is_array($config['openvpn']['openvpn-server'])) {
1437
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1438 ef00af3c Phil Davis
			if (empty($settings)) {
1439 8e022a76 jim-p
				continue;
1440 ef00af3c Phil Davis
			}
1441
			if (isset($settings['disable'])) {
1442 8e022a76 jim-p
				continue;
1443 ef00af3c Phil Davis
			}
1444 8e022a76 jim-p
			// Write the settings for the keys
1445 ef00af3c Phil Davis
			switch ($settings['mode']) {
1446 8e022a76 jim-p
				case 'p2p_tls':
1447
				case 'server_tls':
1448
				case 'server_tls_user':
1449
				case 'server_user':
1450
					if (!empty($settings['crlref'])) {
1451
						$crl = lookup_crl($settings['crlref']);
1452 728003c8 jim-p
						crl_update($crl);
1453 8e022a76 jim-p
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1454
						file_put_contents($fpath, base64_decode($crl['text']));
1455
						@chmod($fpath, 0644);
1456
					}
1457
					break;
1458
			}
1459
		}
1460
	}
1461
}
1462
1463 a8f538a8 jim-p
function openvpn_create_dirs() {
1464
	global $g;
1465 ef00af3c Phil Davis
	if (!is_dir("{$g['varetc_path']}/openvpn")) {
1466 a8f538a8 jim-p
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1467 ef00af3c Phil Davis
	}
1468
	if (!is_dir("{$g['varetc_path']}/openvpn-csc")) {
1469 a8f538a8 jim-p
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1470 ef00af3c Phil Davis
	}
1471 a8f538a8 jim-p
}
1472
1473 91c44185 jim-p
function openvpn_get_interface_ip($ip, $mask) {
1474
	$baselong = ip2long32($ip) & ip2long($mask);
1475
	$ip1 = long2ip32($baselong + 1);
1476
	$ip2 = long2ip32($baselong + 2);
1477
	return array($ip1, $ip2);
1478
}
1479
1480
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1481
	$basev6 = gen_subnetv6($ipv6, $prefix);
1482
	// Is there a better way to do this math?
1483
	$ipv6_arr = explode(':', $basev6);
1484
	$last = hexdec(array_pop($ipv6_arr));
1485 fe9c774d Phil Davis
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1486
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1487 91c44185 jim-p
	return array($ipv6_1, $ipv6_2);
1488
}
1489
1490
function openvpn_clear_route($mode, $settings) {
1491 ef00af3c Phil Davis
	if (empty($settings['tunnel_network'])) {
1492 91c44185 jim-p
		return;
1493 ef00af3c Phil Davis
	}
1494 91c44185 jim-p
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1495
	$mask = gen_subnet_mask($cidr);
1496 6ca938cf jim-p
	$clear_route = false;
1497
1498 ef00af3c Phil Davis
	switch ($settings['mode']) {
1499 6ca938cf jim-p
		case 'shared_key':
1500
			$clear_route = true;
1501
			break;
1502 91c44185 jim-p
		case 'p2p_tls':
1503
		case 'p2p_shared_key':
1504 ef00af3c Phil Davis
			if ($cidr == 30) {
1505 6ca938cf jim-p
				$clear_route = true;
1506 ef00af3c Phil Davis
			}
1507 91c44185 jim-p
			break;
1508
	}
1509 6ca938cf jim-p
1510 6d0b9fe9 jim-p
	if ($clear_route && !empty($ip) && !empty($mask)) {
1511 6ca938cf jim-p
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1512
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1513 615d7f0a Ermal
		/* XXX: Family for route? */
1514 6ca938cf jim-p
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1515
	}
1516 91c44185 jim-p
}
1517
1518 5c427ce7 jim-p
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1519 a28d40cb jim-p
	$routes = "";
1520 ef00af3c Phil Davis
	if (empty($value)) {
1521 a28d40cb jim-p
		return "";
1522 ef00af3c Phil Davis
	}
1523 a28d40cb jim-p
	$networks = explode(',', $value);
1524
1525
	foreach ($networks as $network) {
1526 ef00af3c Phil Davis
		if ($ipproto == "ipv4") {
1527 5c427ce7 jim-p
			$route = openvpn_gen_route_ipv4($network, $iroute);
1528 ef00af3c Phil Davis
		} else {
1529 5c427ce7 jim-p
			$route = openvpn_gen_route_ipv6($network, $iroute);
1530 ef00af3c Phil Davis
		}
1531 a28d40cb jim-p
1532 ef00af3c Phil Davis
		if ($push) {
1533 a28d40cb jim-p
			$routes .= "push \"{$route}\"\n";
1534 ef00af3c Phil Davis
		} else {
1535 a28d40cb jim-p
			$routes .= "{$route}\n";
1536 ef00af3c Phil Davis
		}
1537 a28d40cb jim-p
	}
1538
	return $routes;
1539
}
1540
1541 5c427ce7 jim-p
function openvpn_gen_route_ipv4($network, $iroute = false) {
1542
	$i = ($iroute) ? "i" : "";
1543 a28d40cb jim-p
	list($ip, $mask) = explode('/', trim($network));
1544
	$mask = gen_subnet_mask($mask);
1545 5c427ce7 jim-p
	return "{$i}route $ip $mask";
1546 a28d40cb jim-p
}
1547
1548 5c427ce7 jim-p
function openvpn_gen_route_ipv6($network, $iroute = false) {
1549
	$i = ($iroute) ? "i" : "";
1550 a28d40cb jim-p
	list($ipv6, $prefix) = explode('/', trim($network));
1551 ef00af3c Phil Davis
	if (empty($prefix)) {
1552 a28d40cb jim-p
		$prefix = "128";
1553 ef00af3c Phil Davis
	}
1554 5c427ce7 jim-p
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1555 a28d40cb jim-p
}
1556
1557 699125b1 jim-p
function openvpn_get_settings($mode, $vpnid) {
1558
	global $config;
1559
1560
	if (is_array($config['openvpn']['openvpn-server'])) {
1561
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1562 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
1563 699125b1 jim-p
				continue;
1564 ef00af3c Phil Davis
			}
1565 699125b1 jim-p
1566 ef00af3c Phil Davis
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1567 699125b1 jim-p
				return $settings;
1568 ef00af3c Phil Davis
			}
1569 699125b1 jim-p
		}
1570
	}
1571
1572
	if (is_array($config['openvpn']['openvpn-client'])) {
1573
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1574 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
1575 699125b1 jim-p
				continue;
1576 ef00af3c Phil Davis
			}
1577 699125b1 jim-p
1578 ef00af3c Phil Davis
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1579 699125b1 jim-p
				return $settings;
1580 ef00af3c Phil Davis
			}
1581 699125b1 jim-p
		}
1582
	}
1583
1584
	return array();
1585
}
1586
1587
function openvpn_restart_by_vpnid($mode, $vpnid) {
1588
	$settings = openvpn_get_settings($mode, $vpnid);
1589
	openvpn_restart($mode, $settings);
1590
}
1591
1592 756720e2 Pierre POMES
?>