Project

General

Profile

Download (43.8 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 d7a0c22a bcyrill
	$ipaddr = $settings['ipaddr'];
523
	$ipaddrv6 = $settings['ipaddrv6'];
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
	if (is_ipaddrv6($ipaddrv6)) {
536
		$iface_ipv6=$ipaddrv6;
537
	} 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 5f242576 PiBa-NL
		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 42bb1bee Renato Botelho
800 762a24a3 Ermal Lu?i
		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 8dc3ef67 Scott Ullrich
	}
811
812 17c98ba9 jim-p
	// Add a remote network route if set, and only for p2p modes.
813 54285411 jim-p
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
814 a28d40cb jim-p
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
815 8dc3ef67 Scott Ullrich
	}
816 4856df9b jim-p
	// Add a remote network route if set, and only for p2p modes.
817 54285411 jim-p
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
818 a28d40cb jim-p
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
819 4856df9b jim-p
	}
820 afb07cf1 Scott Ullrich
821 d799787e Matthew Grooms
	// Write the settings for the keys
822 ef00af3c Phil Davis
	switch ($settings['mode']) {
823 3c11bd3c Matthew Grooms
		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 e62e2f8b Ermal Lu?i
		case 'server_user':
830 3c11bd3c Matthew Grooms
			$ca = lookup_ca($settings['caref']);
831
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
832 2da48592 jim-p
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 ef00af3c Phil Davis
			if ($mode == 'server') {
839 fe787fc7 Matthew Grooms
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
840 ef00af3c Phil Davis
			}
841 6db02381 jim-p
			if (!empty($settings['crlref'])) {
842
				$crl = lookup_crl($settings['crlref']);
843 cfcc6994 jim-p
				crl_update($crl);
844 6db02381 jim-p
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
845
			}
846 db746ce2 Ermal Lu?i
			if ($settings['tls']) {
847 ef00af3c Phil Davis
				if ($mode == "server") {
848 db746ce2 Ermal Lu?i
					$tlsopt = 0;
849 ef00af3c Phil Davis
				} else {
850 db746ce2 Ermal Lu?i
					$tlsopt = 1;
851 ef00af3c Phil Davis
				}
852 db746ce2 Ermal Lu?i
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
853
			}
854 3c11bd3c Matthew Grooms
			break;
855 8dc3ef67 Scott Ullrich
	}
856
857 ef00af3c Phil Davis
	if (!empty($settings['compression'])) {
858 edba1982 jim-p
		$conf .= "comp-lzo {$settings['compression']}\n";
859 ef00af3c Phil Davis
	}
860 d799787e Matthew Grooms
861 ef00af3c Phil Davis
	if ($settings['passtos']) {
862 d799787e Matthew Grooms
		$conf .= "passtos\n";
863 ef00af3c Phil Davis
	}
864 d799787e Matthew Grooms
865 ef00af3c Phil Davis
	if ($settings['resolve_retry']) {
866 d799787e Matthew Grooms
		$conf .= "resolv-retry infinite\n";
867 ef00af3c Phil Davis
	} else if ($mode == 'clie} nt') {
868 30640018 Chris Buechler
		$conf .= "resolv-retry infinite\n";
869 ef00af3c Phil Davis
	}
870 d799787e Matthew Grooms
871
	if ($settings['dynamic_ip']) {
872
		$conf .= "persist-remote-ip\n";
873
		$conf .= "float\n";
874 8dc3ef67 Scott Ullrich
	}
875 afb07cf1 Scott Ullrich
876 ee55ce7d jim-p
	if ($settings['topology_subnet']) {
877
		$conf .= "topology subnet\n";
878
	}
879
880 b9e9903d Dmitriy K.
	// 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 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
894
895 a8f538a8 jim-p
	openvpn_create_dirs();
896 938fc5b0 Ermal
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
897 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
898 938fc5b0 Ermal
	unset($conf);
899 be00850b Phil Davis
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
900
	file_put_contents($fpath, $interface);
901 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
902
	//chgrp($fpath, 'nobody');
903 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
904 be00850b Phil Davis
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
905 6f27412f Ermal Lu?i
	@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 d799787e Matthew Grooms
}
909
910 fc05822b jim-p
function openvpn_restart($mode, $settings) {
911 d799787e Matthew Grooms
	global $g, $config;
912
913
	$vpnid = $settings['vpnid'];
914
	$mode_id = $mode.$vpnid;
915
916 76369bfc Matthew Grooms
	/* kill the process if running */
917 705c8ec9 Matthew Grooms
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
918 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
919 705c8ec9 Matthew Grooms
920 76369bfc Matthew Grooms
		/* read the pid file */
921
		$pid = rtrim(file_get_contents($pfile));
922
		unlink($pfile);
923 705c8ec9 Matthew Grooms
924 76369bfc Matthew Grooms
		/* send a term signal to the process */
925
		posix_kill($pid, SIGTERM);
926
927 93ead355 Chris Buechler
		/* wait until the process exits, or timeout and kill it */
928
		$i = 0;
929 ef00af3c Phil Davis
		while (posix_kill($pid, 0)) {
930 76369bfc Matthew Grooms
			usleep(250000);
931 93ead355 Chris Buechler
			if ($i > 10) {
932
				log_error("OpenVPN ID $mode_id PID $pid still running, killing.");
933
				posix_kill($pid, SIGKILL);
934 02a2bffa Chris Buechler
				usleep(500000);
935 93ead355 Chris Buechler
			}
936
			$i++;
937
		}
938 76369bfc Matthew Grooms
	}
939 d799787e Matthew Grooms
940 ef00af3c Phil Davis
	if (isset($settings['disable'])) {
941 d799787e Matthew Grooms
		return;
942 ef00af3c Phil Davis
	}
943 d799787e Matthew Grooms
944 260f267e jim-p
	/* Do not start a client if we are a CARP backup on this vip! */
945 ef00af3c Phil Davis
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) != "MASTER")) {
946 9ea0cb90 jim-p
		return;
947 ef00af3c Phil Davis
	}
948 42bb1bee Renato Botelho
949
	/* Check if client is bound to a gateway group */
950 330ecea1 Shahid Sheikh
	$a_groups = return_gateway_groups_array();
951
	if (is_array($a_groups[$settings['interface']])) {
952 ef00af3c Phil Davis
		/* 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 330ecea1 Shahid Sheikh
			return;
955 ef00af3c Phil Davis
		}
956 330ecea1 Shahid Sheikh
	}
957 9ea0cb90 jim-p
958 705c8ec9 Matthew Grooms
	/* start the new process */
959 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
960 91c44185 jim-p
	openvpn_clear_route($mode, $settings);
961 873c1701 Renato Botelho
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
962 847cd48d Ermal
963 ef00af3c Phil Davis
	if (!platform_booting()) {
964 847cd48d Ermal
		send_event("filter reload");
965 ef00af3c Phil Davis
	}
966 afb07cf1 Scott Ullrich
}
967
968 dc408939 Matthew Grooms
function openvpn_delete($mode, & $settings) {
969 d799787e Matthew Grooms
	global $g, $config;
970
971
	$vpnid = $settings['vpnid'];
972
	$mode_id = $mode.$vpnid;
973
974 ef00af3c Phil Davis
	if (isset($settings['dev_mode'])) {
975 da601f8e PiBa-NL
		$tunname = "{$settings['dev_mode']}{$vpnid}";
976 ef00af3c Phil Davis
	} else {
977
		/* defaults to tun */
978 da601f8e PiBa-NL
		$tunname = "tun{$vpnid}";
979
	}
980
981 ef00af3c Phil Davis
	if ($mode == "server") {
982 095a95ae Matthew Grooms
		$devname = "ovpns{$vpnid}";
983 ef00af3c Phil Davis
	} else {
984 095a95ae Matthew Grooms
		$devname = "ovpnc{$vpnid}";
985 ef00af3c Phil Davis
	}
986 dc408939 Matthew Grooms
987 76369bfc Matthew Grooms
	/* kill the process if running */
988 dc408939 Matthew Grooms
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
989 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
990 dc408939 Matthew Grooms
991 76369bfc Matthew Grooms
		/* 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 705c8ec9 Matthew Grooms
999 095a95ae Matthew Grooms
	/* remove the device from the openvpn group */
1000 873c1701 Renato Botelho
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
1001 095a95ae Matthew Grooms
1002 dc408939 Matthew Grooms
	/* restore the original adapter name */
1003 873c1701 Renato Botelho
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
1004 dc408939 Matthew Grooms
1005
	/* remove the configuration files */
1006 8bb47a46 Ermal
	@array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
1007 d799787e Matthew Grooms
}
1008 afb07cf1 Scott Ullrich
1009 de85521a jim-p
function openvpn_cleanup_csc($common_name) {
1010
	global $g, $config;
1011 ef00af3c Phil Davis
	if (empty($common_name)) {
1012 de85521a jim-p
		return;
1013 ef00af3c Phil Davis
	}
1014 de85521a jim-p
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
1015 ef00af3c Phil Davis
	if (is_file($fpath)) {
1016 de85521a jim-p
		unlink_if_exists($fpath);
1017 ef00af3c Phil Davis
	}
1018 de85521a jim-p
	return;
1019
}
1020
1021 dc408939 Matthew Grooms
function openvpn_resync_csc(& $settings) {
1022 8dc3ef67 Scott Ullrich
	global $g, $config;
1023
1024 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
1025 8dc3ef67 Scott Ullrich
1026 a1cab2c7 Ermal
	if (isset($settings['disable'])) {
1027 d799787e Matthew Grooms
		unlink_if_exists($fpath);
1028 c876662c Scott Ullrich
		return;
1029
	}
1030 a8f538a8 jim-p
	openvpn_create_dirs();
1031 d799787e Matthew Grooms
1032 8dc3ef67 Scott Ullrich
	$conf = '';
1033 ef00af3c Phil Davis
	if ($settings['block']) {
1034 d799787e Matthew Grooms
		$conf .= "disable\n";
1035 ef00af3c Phil Davis
	}
1036 d799787e Matthew Grooms
1037 ef00af3c Phil Davis
	if ($settings['push_reset']) {
1038 d799787e Matthew Grooms
		$conf .= "push-reset\n";
1039 ef00af3c Phil Davis
	}
1040 d799787e Matthew Grooms
1041
	if (!empty($settings['tunnel_network'])) {
1042
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
1043 96033063 Erik Fonnesbeck
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
1044 298fe5ae jim-p
		$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 ef00af3c Phil Davis
		if ($settings['dev_mode'] != 'tap') {
1048 d9c96fb1 jim-p
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
1049 ef00af3c Phil Davis
		} else {
1050 e052047d jim-p
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
1051 ef00af3c Phil Davis
		}
1052 8dc3ef67 Scott Ullrich
	}
1053 6d031071 Martin Fuchs
1054 5c427ce7 jim-p
	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 d799787e Matthew Grooms
	openvpn_add_dhcpopts($settings, $conf);
1071 8dc3ef67 Scott Ullrich
1072 ef00af3c Phil Davis
	if ($settings['gwredir']) {
1073 d799787e Matthew Grooms
		$conf .= "push \"redirect-gateway def1\"\n";
1074 ef00af3c Phil Davis
	}
1075 6d031071 Martin Fuchs
1076 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
1077 8dc3ef67 Scott Ullrich
1078 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
1079
	chown($fpath, 'nobody');
1080
	chgrp($fpath, 'nobody');
1081
}
1082 8dc3ef67 Scott Ullrich
1083 dc408939 Matthew Grooms
function openvpn_delete_csc(& $settings) {
1084 add2e3f7 Scott Ullrich
	global $g, $config;
1085 3c2e5528 Scott Ullrich
1086 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
1087 d799787e Matthew Grooms
	unlink_if_exists($fpath);
1088 267ab13f Ermal Luçi
}
1089 afb07cf1 Scott Ullrich
1090 24012690 Scott Ullrich
// Resync the configuration and restart the VPN
1091 fc05822b jim-p
function openvpn_resync($mode, $settings) {
1092 dc408939 Matthew Grooms
	openvpn_reconfigure($mode, $settings);
1093
	openvpn_restart($mode, $settings);
1094 afb07cf1 Scott Ullrich
}
1095
1096 add2e3f7 Scott Ullrich
// Resync and restart all VPNs
1097 c7f60193 Ermal
function openvpn_resync_all($interface = "") {
1098 d799787e Matthew Grooms
	global $g, $config;
1099 267ab13f Ermal Luçi
1100 ef00af3c Phil Davis
	if ($g['platform'] == 'jail') {
1101 7734aea6 Andrew Thompson
		return;
1102 ef00af3c Phil Davis
	}
1103 a8f538a8 jim-p
	openvpn_create_dirs();
1104 3cb54b54 Matthew Grooms
1105 ef00af3c Phil Davis
	if (!is_array($config['openvpn'])) {
1106 34bc1324 Matthew Grooms
		$config['openvpn'] = array();
1107 ef00af3c Phil Davis
	}
1108 34bc1324 Matthew Grooms
1109 15b414e6 Matthew Grooms
/*
1110 34bc1324 Matthew Grooms
	if (!$config['openvpn']['dh-parameters']) {
1111
		echo "Configuring OpenVPN Parameters ...\n";
1112 035e4289 Matthew Grooms
		$dh_parameters = openvpn_create_dhparams(1024);
1113 34bc1324 Matthew Grooms
		$dh_parameters = base64_encode($dh_parameters);
1114
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1115 c67dd94e Bill Marquette
		write_config("OpenVPN DH parameters");
1116 34bc1324 Matthew Grooms
	}
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 15b414e6 Matthew Grooms
*/
1125 ef00af3c Phil Davis
	if ($interface <> "") {
1126 a82e6d37 Chris Buechler
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
1127 ef00af3c Phil Davis
	} else {
1128 42bb1bee Renato Botelho
		log_error("Resyncing OpenVPN instances.");
1129 ef00af3c Phil Davis
	}
1130 34bc1324 Matthew Grooms
1131 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-server'])) {
1132
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1133 ef00af3c Phil Davis
			if ($interface <> "" && $interface != $settings['interface']) {
1134 c7f60193 Ermal
				continue;
1135 ef00af3c Phil Davis
			}
1136 dc408939 Matthew Grooms
			openvpn_resync('server', $settings);
1137 c7f60193 Ermal
		}
1138
	}
1139 5b237745 Scott Ullrich
1140 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-client'])) {
1141
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1142 ef00af3c Phil Davis
			if ($interface <> "" && $interface != $settings['interface']) {
1143 c7f60193 Ermal
				continue;
1144 ef00af3c Phil Davis
			}
1145 dc408939 Matthew Grooms
			openvpn_resync('client', $settings);
1146 c7f60193 Ermal
		}
1147
	}
1148 afb07cf1 Scott Ullrich
1149 ef00af3c Phil Davis
	if (is_array($config['openvpn']['openvpn-csc'])) {
1150
		foreach ($config['openvpn']['openvpn-csc'] as & $settings) {
1151 dc408939 Matthew Grooms
			openvpn_resync_csc($settings);
1152 ef00af3c Phil Davis
		}
1153
	}
1154 afb07cf1 Scott Ullrich
1155 5b237745 Scott Ullrich
}
1156 702a4702 Scott Ullrich
1157 99cc103b Phil Davis
// 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 ef00af3c Phil Davis
	} else {
1183 42bb1bee Renato Botelho
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter.");
1184 ef00af3c Phil Davis
	}
1185 99cc103b Phil Davis
}
1186
1187 453d9c96 jim-p
function openvpn_get_active_servers($type="multipoint") {
1188 71ca2cb2 Ermal
	global $config, $g;
1189
1190 53663f57 jim-p
	$servers = array();
1191
	if (is_array($config['openvpn']['openvpn-server'])) {
1192
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1193 ef00af3c Phil Davis
			if (empty($settings) || isset($settings['disable'])) {
1194 6b2dcac5 Ermal
				continue;
1195 ef00af3c Phil Davis
			}
1196 6b2dcac5 Ermal
1197 53663f57 jim-p
			$prot = $settings['protocol'];
1198
			$port = $settings['local_port'];
1199 42bb1bee Renato Botelho
1200 53663f57 jim-p
			$server = array();
1201 95305736 jim-p
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1202 41be629f jim-p
			$server['mode'] = $settings['mode'];
1203 ef00af3c Phil Davis
			if ($settings['description']) {
1204 53663f57 jim-p
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1205 ef00af3c Phil Davis
			} else {
1206 53663f57 jim-p
				$server['name'] = "Server {$prot}:{$port}";
1207 ef00af3c Phil Davis
			}
1208 53663f57 jim-p
			$server['conns'] = array();
1209 2eaa97b9 jim-p
			$server['vpnid'] = $settings['vpnid'];
1210
			$server['mgmt'] = "server{$server['vpnid']}";
1211
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1212 453d9c96 jim-p
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1213
1214 ef00af3c Phil Davis
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30)) && ($type == "p2p")) {
1215 95305736 jim-p
				$servers[] = openvpn_get_client_status($server, $socket);
1216 ef00af3c Phil Davis
			} elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30)) {
1217 95305736 jim-p
				$servers[] = openvpn_get_server_status($server, $socket);
1218 ef00af3c Phil Davis
			}
1219 95305736 jim-p
		}
1220
	}
1221
	return $servers;
1222
}
1223 b0140675 Ermal
1224 95305736 jim-p
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 ef00af3c Phil Davis
			if ($info['timed_out']) {
1242 95305736 jim-p
				break;
1243 ef00af3c Phil Davis
			}
1244 95305736 jim-p
1245
			/* parse header list line */
1246 ef00af3c Phil Davis
			if (strstr($line, "HEADER")) {
1247 95305736 jim-p
				continue;
1248 ef00af3c Phil Davis
			}
1249 95305736 jim-p
1250
			/* parse end of output line */
1251 ef00af3c Phil Davis
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1252 95305736 jim-p
				break;
1253 ef00af3c Phil Davis
			}
1254 95305736 jim-p
1255
			/* parse client list line */
1256
			if (strstr($line, "CLIENT_LIST")) {
1257
				$list = explode(",", $line);
1258 53663f57 jim-p
				$conn = array();
1259 95305736 jim-p
				$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 53663f57 jim-p
				$server['conns'][] = $conn;
1266
			}
1267 ec970b50 jim-p
			/* 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 53663f57 jim-p
		}
1278 95305736 jim-p
1279
		/* cleanup */
1280
		fclose($fp);
1281
	} else {
1282
		$conn = array();
1283
		$conn['common_name'] = "[error]";
1284 2eaa97b9 jim-p
		$conn['remote_host'] = "Unable to contact daemon";
1285
		$conn['virtual_addr'] = "Service not running?";
1286 95305736 jim-p
		$conn['bytes_recv'] = 0;
1287
		$conn['bytes_sent'] = 0;
1288
		$conn['connect_time'] = 0;
1289
		$server['conns'][] = $conn;
1290 53663f57 jim-p
	}
1291 95305736 jim-p
	return $server;
1292 53663f57 jim-p
}
1293
1294
function openvpn_get_active_clients() {
1295 71ca2cb2 Ermal
	global $config, $g;
1296
1297 53663f57 jim-p
	$clients = array();
1298
	if (is_array($config['openvpn']['openvpn-client'])) {
1299
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1300 42bb1bee Renato Botelho
1301 ef00af3c Phil Davis
			if (empty($settings) || isset($settings['disable'])) {
1302 6b2dcac5 Ermal
				continue;
1303 ef00af3c Phil Davis
			}
1304 6b2dcac5 Ermal
1305 53663f57 jim-p
			$prot = $settings['protocol'];
1306 95305736 jim-p
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1307 42bb1bee Renato Botelho
1308 53663f57 jim-p
			$client = array();
1309
			$client['port'] = $settings['local_port'];
1310 ef00af3c Phil Davis
			if ($settings['description']) {
1311 95305736 jim-p
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1312 ef00af3c Phil Davis
			} else {
1313 95305736 jim-p
				$client['name'] = "Client {$prot}{$port}";
1314 ef00af3c Phil Davis
			}
1315 42bb1bee Renato Botelho
1316 2eaa97b9 jim-p
			$client['vpnid'] = $settings['vpnid'];
1317
			$client['mgmt'] = "client{$client['vpnid']}";
1318
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1319 53663f57 jim-p
			$client['status']="down";
1320 95305736 jim-p
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 ef00af3c Phil Davis
			if ($info['timed_out']) {
1343 95305736 jim-p
				break;
1344 ef00af3c Phil Davis
			}
1345 95305736 jim-p
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 453d9c96 jim-p
			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 95305736 jim-p
			/* parse end of output line */
1373 ef00af3c Phil Davis
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1374 95305736 jim-p
				break;
1375 ef00af3c Phil Davis
			}
1376 95305736 jim-p
		}
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 ef00af3c Phil Davis
				if ($info['timed_out']) {
1388 95305736 jim-p
					break;
1389 ef00af3c Phil Davis
				}
1390 95305736 jim-p
1391
				if (strstr($line,"TCP/UDP read bytes")) {
1392
					$list = explode(",", $line);
1393
					$client['bytes_recv'] = $list[1];
1394 53663f57 jim-p
				}
1395 95305736 jim-p
1396
				if (strstr($line,"TCP/UDP write bytes")) {
1397
					$list = explode(",", $line);
1398
					$client['bytes_sent'] = $list[1];
1399 53663f57 jim-p
				}
1400 95305736 jim-p
1401
				/* parse end of output line */
1402 ef00af3c Phil Davis
				if (strstr($line, "END")) {
1403 95305736 jim-p
					break;
1404 ef00af3c Phil Davis
				}
1405 53663f57 jim-p
			}
1406
		}
1407 95305736 jim-p
1408
		fclose($fp);
1409
1410
	} else {
1411
		$DisplayNote=true;
1412 2eaa97b9 jim-p
		$client['remote_host'] = "Unable to contact daemon";
1413
		$client['virtual_addr'] = "Service not running?";
1414 95305736 jim-p
		$client['bytes_recv'] = 0;
1415
		$client['bytes_sent'] = 0;
1416
		$client['connect_time'] = 0;
1417 53663f57 jim-p
	}
1418 95305736 jim-p
	return $client;
1419 53663f57 jim-p
}
1420 8e022a76 jim-p
1421
function openvpn_refresh_crls() {
1422
	global $g, $config;
1423
1424 a8f538a8 jim-p
	openvpn_create_dirs();
1425 8e022a76 jim-p
1426
	if (is_array($config['openvpn']['openvpn-server'])) {
1427
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1428 ef00af3c Phil Davis
			if (empty($settings)) {
1429 8e022a76 jim-p
				continue;
1430 ef00af3c Phil Davis
			}
1431
			if (isset($settings['disable'])) {
1432 8e022a76 jim-p
				continue;
1433 ef00af3c Phil Davis
			}
1434 8e022a76 jim-p
			// Write the settings for the keys
1435 ef00af3c Phil Davis
			switch ($settings['mode']) {
1436 8e022a76 jim-p
				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 728003c8 jim-p
						crl_update($crl);
1443 8e022a76 jim-p
						$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 a8f538a8 jim-p
function openvpn_create_dirs() {
1454
	global $g;
1455 ef00af3c Phil Davis
	if (!is_dir("{$g['varetc_path']}/openvpn")) {
1456 a8f538a8 jim-p
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1457 ef00af3c Phil Davis
	}
1458
	if (!is_dir("{$g['varetc_path']}/openvpn-csc")) {
1459 a8f538a8 jim-p
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1460 ef00af3c Phil Davis
	}
1461 a8f538a8 jim-p
}
1462
1463 91c44185 jim-p
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 fe9c774d Phil Davis
	$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 91c44185 jim-p
	return array($ipv6_1, $ipv6_2);
1478
}
1479
1480
function openvpn_clear_route($mode, $settings) {
1481 ef00af3c Phil Davis
	if (empty($settings['tunnel_network'])) {
1482 91c44185 jim-p
		return;
1483 ef00af3c Phil Davis
	}
1484 91c44185 jim-p
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1485
	$mask = gen_subnet_mask($cidr);
1486 6ca938cf jim-p
	$clear_route = false;
1487
1488 ef00af3c Phil Davis
	switch ($settings['mode']) {
1489 6ca938cf jim-p
		case 'shared_key':
1490
			$clear_route = true;
1491
			break;
1492 91c44185 jim-p
		case 'p2p_tls':
1493
		case 'p2p_shared_key':
1494 ef00af3c Phil Davis
			if ($cidr == 30) {
1495 6ca938cf jim-p
				$clear_route = true;
1496 ef00af3c Phil Davis
			}
1497 91c44185 jim-p
			break;
1498
	}
1499 6ca938cf jim-p
1500 6d0b9fe9 jim-p
	if ($clear_route && !empty($ip) && !empty($mask)) {
1501 6ca938cf jim-p
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1502
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1503 615d7f0a Ermal
		/* XXX: Family for route? */
1504 6ca938cf jim-p
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1505
	}
1506 91c44185 jim-p
}
1507
1508 5c427ce7 jim-p
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1509 a28d40cb jim-p
	$routes = "";
1510 ef00af3c Phil Davis
	if (empty($value)) {
1511 a28d40cb jim-p
		return "";
1512 ef00af3c Phil Davis
	}
1513 a28d40cb jim-p
	$networks = explode(',', $value);
1514
1515
	foreach ($networks as $network) {
1516 ef00af3c Phil Davis
		if ($ipproto == "ipv4") {
1517 5c427ce7 jim-p
			$route = openvpn_gen_route_ipv4($network, $iroute);
1518 ef00af3c Phil Davis
		} else {
1519 5c427ce7 jim-p
			$route = openvpn_gen_route_ipv6($network, $iroute);
1520 ef00af3c Phil Davis
		}
1521 a28d40cb jim-p
1522 ef00af3c Phil Davis
		if ($push) {
1523 a28d40cb jim-p
			$routes .= "push \"{$route}\"\n";
1524 ef00af3c Phil Davis
		} else {
1525 a28d40cb jim-p
			$routes .= "{$route}\n";
1526 ef00af3c Phil Davis
		}
1527 a28d40cb jim-p
	}
1528
	return $routes;
1529
}
1530
1531 5c427ce7 jim-p
function openvpn_gen_route_ipv4($network, $iroute = false) {
1532
	$i = ($iroute) ? "i" : "";
1533 a28d40cb jim-p
	list($ip, $mask) = explode('/', trim($network));
1534
	$mask = gen_subnet_mask($mask);
1535 5c427ce7 jim-p
	return "{$i}route $ip $mask";
1536 a28d40cb jim-p
}
1537
1538 5c427ce7 jim-p
function openvpn_gen_route_ipv6($network, $iroute = false) {
1539
	$i = ($iroute) ? "i" : "";
1540 a28d40cb jim-p
	list($ipv6, $prefix) = explode('/', trim($network));
1541 ef00af3c Phil Davis
	if (empty($prefix)) {
1542 a28d40cb jim-p
		$prefix = "128";
1543 ef00af3c Phil Davis
	}
1544 5c427ce7 jim-p
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1545 a28d40cb jim-p
}
1546
1547 699125b1 jim-p
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 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
1553 699125b1 jim-p
				continue;
1554 ef00af3c Phil Davis
			}
1555 699125b1 jim-p
1556 ef00af3c Phil Davis
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1557 699125b1 jim-p
				return $settings;
1558 ef00af3c Phil Davis
			}
1559 699125b1 jim-p
		}
1560
	}
1561
1562
	if (is_array($config['openvpn']['openvpn-client'])) {
1563
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1564 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
1565 699125b1 jim-p
				continue;
1566 ef00af3c Phil Davis
			}
1567 699125b1 jim-p
1568 ef00af3c Phil Davis
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1569 699125b1 jim-p
				return $settings;
1570 ef00af3c Phil Davis
			}
1571 699125b1 jim-p
		}
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 756720e2 Pierre POMES
?>