Project

General

Profile

Download (52 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2 b1ad443d Scott Ullrich
/*
3 09221bc3 Renato Botelho
	openvpn.inc
4 42bb1bee Renato Botelho
5 09221bc3 Renato Botelho
	part of pfSense (https://www.pfsense.org)
6 b1ad443d Scott Ullrich
	Copyright (C) 2006  Fernando Lemos
7 09221bc3 Renato Botelho
	Copyright (c) 2006-2016 Electric Sheep Fencing, LLC.
8 b1ad443d Scott Ullrich
	All rights reserved.
9
10 33ab8aa5 Scott Ullrich
	This file was rewritten from scratch by Fernando Lemos but
11
	*MIGHT* contain code previously written by:
12
13 b1ad443d Scott Ullrich
	Copyright (C) 2005 Peter Allgeyer <allgeyer_AT_web.de>
14
	All rights reserved.
15
16
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
17
	All rights reserved.
18
19
	Redistribution and use in source and binary forms, with or without
20
	modification, are permitted provided that the following conditions are met:
21
22 09221bc3 Renato Botelho
	1. Redistributions of source code must retain the above copyright notice,
23 b1ad443d Scott Ullrich
	   this list of conditions and the following disclaimer.
24
25
	2. Redistributions in binary form must reproduce the above copyright
26 09221bc3 Renato Botelho
	   notice, this list of conditions and the following disclaimer in
27
	   the documentation and/or other materials provided with the
28
	   distribution.
29
30
	3. All advertising materials mentioning features or use of this software
31
	   must display the following acknowledgment:
32
	   "This product includes software developed by the pfSense Project
33
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
34
35
	4. The names "pfSense" and "pfSense Project" must not be used to
36
	   endorse or promote products derived from this software without
37
	   prior written permission. For written permission, please contact
38
	   coreteam@pfsense.org.
39
40
	5. Products derived from this software may not be called "pfSense"
41
	   nor may "pfSense" appear in their names without prior written
42
	   permission of the Electric Sheep Fencing, LLC.
43
44
	6. Redistributions of any form whatsoever must retain the following
45
	   acknowledgment:
46
47
	"This product includes software developed by the pfSense Project
48
	for use in the pfSense software distribution (http://www.pfsense.org/).
49
50
	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
51
	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
54
	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61
	OF THE POSSIBILITY OF SUCH DAMAGE.
62 523855b0 Scott Ullrich
*/
63 6aa3723a Renato Botelho
64 8dc3ef67 Scott Ullrich
require_once('config.inc');
65 32a7a1f6 Ermal Lu?i
require_once("certs.inc");
66 36df0acc Scott Ullrich
require_once('pfsense-utils.inc');
67 c61e4626 Ermal Lu?i
require_once("auth.inc");
68 8dc3ef67 Scott Ullrich
69 f2291484 jim-p
global $openvpn_prots;
70 6714bbdc jim-p
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
71 702a4702 Scott Ullrich
72 f2291484 jim-p
global $openvpn_dev_mode;
73 691fbf14 Ermal Lu?i
$openvpn_dev_mode = array("tun", "tap");
74
75 b9e9903d Dmitriy K.
global $openvpn_verbosity_level;
76
$openvpn_verbosity_level = array(
77 e8c516a0 Phil Davis
	0 =>	gettext("none"),
78
	1 =>	gettext("default"),
79 42bb1bee Renato Botelho
	2 =>	"2",
80 e8c516a0 Phil Davis
	3 =>	gettext("3 (recommended)"),
81 b9e9903d Dmitriy K.
	4 =>	"4",
82
	5 => 	"5",
83
	6 => 	"6",
84
	7 => 	"7",
85
	8 => 	"8",
86
	9 => 	"9",
87
	10 => 	"10",
88
	11 => 	"11"
89 42bb1bee Renato Botelho
);
90 b9e9903d Dmitriy K.
91 42bb1bee Renato Botelho
/*
92 3c11bd3c Matthew Grooms
 * The User Auth mode below is disabled because
93
 * OpenVPN erroneously requires that we provide
94
 * a CA configuration parameter. In this mode,
95
 * clients don't send a certificate so there is
96
 * no need for a CA. If we require that admins
97
 * provide one in the pfSense UI due to a bogus
98
 * requirement imposed by OpenVPN, it could be
99
 * considered very confusing ( I know I was ).
100
 *
101
 * -mgrooms
102
 */
103
104 f2291484 jim-p
global $openvpn_dh_lengths;
105 fe787fc7 Matthew Grooms
$openvpn_dh_lengths = array(
106 bd1a4433 stilez
	1024, 2048, 3072, 4096, 7680, 8192, 15360, 16384
107
);
108 fe787fc7 Matthew Grooms
109 f2291484 jim-p
global $openvpn_cert_depths;
110 98963f27 jim-p
$openvpn_cert_depths = array(
111 e8c516a0 Phil Davis
	1 => gettext("One (Client+Server)"),
112
	2 => gettext("Two (Client+Intermediate+Server)"),
113
	3 => gettext("Three (Client+2xIntermediate+Server)"),
114
	4 => gettext("Four (Client+3xIntermediate+Server)"),
115
	5 => gettext("Five (Client+4xIntermediate+Server)")
116 98963f27 jim-p
);
117
118 f2291484 jim-p
global $openvpn_server_modes;
119 3c11bd3c Matthew Grooms
$openvpn_server_modes = array(
120 4aa02281 Carlos Eduardo Ramos
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
121
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
122
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
123
	'server_user' => gettext("Remote Access ( User Auth )"),
124
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
125 3c11bd3c Matthew Grooms
126 154b0f80 jim-p
global $openvpn_tls_server_modes;
127
$openvpn_tls_server_modes = array('p2p_tls', 'server_tls', 'server_user', 'server_tls_user');
128
129 f2291484 jim-p
global $openvpn_client_modes;
130 3c11bd3c Matthew Grooms
$openvpn_client_modes = array(
131 4aa02281 Carlos Eduardo Ramos
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
132 ef00af3c Phil Davis
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"));
133 3c11bd3c Matthew Grooms
134 edba1982 jim-p
global $openvpn_compression_modes;
135
$openvpn_compression_modes = array(
136 ef00af3c Phil Davis
	'' => gettext("No Preference"),
137
	'no' => gettext("Disabled - No Compression"),
138
	'adaptive' => gettext("Enabled with Adaptive Compression"),
139
	'yes' => gettext("Enabled without Adaptive Compression"));
140 edba1982 jim-p
141 88cfb255 jim-p
global $openvpn_topologies;
142
$openvpn_topologies = array(
143
	'subnet' => gettext("Subnet -- One IP address per client in a common subnet"),
144
	'net30' => gettext("net30 -- Isolated /30 network per client")
145
//	'p2p => gettext("Peer to Peer -- One IP address per client peer-to-peer style. Does not work on Windows.")
146
);
147
148 f4eec250 Phil Davis
function openvpn_build_mode_list() {
149
	global $openvpn_server_modes;
150
151
	$list = array();
152
153 4e322e2c Phil Davis
	foreach ($openvpn_server_modes as $name => $desc) {
154 f4eec250 Phil Davis
		$list[$name] = $desc;
155 4e322e2c Phil Davis
	}
156 f4eec250 Phil Davis
157
	return($list);
158
}
159
160
function openvpn_build_if_list() {
161
	$list = array();
162
163
	$interfaces = get_configured_interface_with_descr();
164 2a5960b0 Luiz Otavio O Souza
	$viplist = get_configured_vip_list();
165
	foreach ($viplist as $vip => $address) {
166
		$interfaces[$vip.'|'.$address] = $address;
167
		if (get_vip_descr($address)) {
168
			$interfaces[$vip.'|'.$address] .= " (";
169
			$interfaces[$vip.'|'.$address] .= get_vip_descr($address);
170
			$interfaces[$vip.'|'.$address] .= ")";
171
		}
172 4e322e2c Phil Davis
	}
173 f4eec250 Phil Davis
174
	$grouplist = return_gateway_groups_array();
175
	foreach ($grouplist as $name => $group) {
176 4e322e2c Phil Davis
		if ($group[0]['vip'] != "") {
177 f4eec250 Phil Davis
			$vipif = $group[0]['vip'];
178 4e322e2c Phil Davis
		} else {
179 f4eec250 Phil Davis
			$vipif = $group[0]['int'];
180 4e322e2c Phil Davis
		}
181 f4eec250 Phil Davis
182
		$interfaces[$name] = "GW Group {$name}";
183
	}
184
185
	$interfaces['lo0'] = "Localhost";
186
	$interfaces['any'] = "any";
187
188 4e322e2c Phil Davis
	foreach ($interfaces as $iface => $ifacename) {
189 f4eec250 Phil Davis
	   $list[$iface] = $ifacename;
190 4e322e2c Phil Davis
	}
191 f4eec250 Phil Davis
192
	return($list);
193
}
194
195
function openvpn_build_crl_list() {
196
	global $a_crl;
197
198
	$list = array('' => 'None');
199
200
	foreach ($a_crl as $crl) {
201
		$caname = "";
202
		$ca = lookup_ca($crl['caref']);
203
204 4e322e2c Phil Davis
		if ($ca) {
205 f4eec250 Phil Davis
			$caname = " (CA: {$ca['descr']})";
206 4e322e2c Phil Davis
		}
207 f4eec250 Phil Davis
208
		$list[$crl['refid']] = $crl['descr'] . $caname;
209
	}
210
211
	return($list);
212
}
213
214 0e9d4a6d jim-p
function openvpn_build_cert_list($include_none = false, $prioritize_server_certs = false) {
215 f4eec250 Phil Davis
	global $a_cert;
216
217
	if ($include_none) {
218 e8c516a0 Phil Davis
		$list = array('' => gettext('None (Username and/or Password required)'));
219 f4eec250 Phil Davis
	} else {
220
		$list = array();
221
	}
222
223 a4ba0282 Stephen Beaver
	$non_server_list = array();
224
225 0e9d4a6d jim-p
	if ($prioritize_server_certs) {
226 e8c516a0 Phil Davis
		$list[' '] = gettext("===== Server Certificates =====");
227
		$non_server_list['  '] = gettext("===== Non-Server Certificates =====");
228 0e9d4a6d jim-p
	}
229
230 f4eec250 Phil Davis
	foreach ($a_cert as $cert) {
231 0e9d4a6d jim-p
		$properties = array();
232
		$propstr = "";
233 f4eec250 Phil Davis
		$ca = lookup_ca($cert['caref']);
234 0e9d4a6d jim-p
		$purpose = cert_get_purpose($cert['crt'], true);
235 f4eec250 Phil Davis
236 0e9d4a6d jim-p
		if ($purpose['server'] == "Yes") {
237 e8c516a0 Phil Davis
			$properties[] = gettext("Server: Yes");
238 0e9d4a6d jim-p
		} elseif ($prioritize_server_certs) {
239 e8c516a0 Phil Davis
			$properties[] = gettext("Server: NO");
240 0e9d4a6d jim-p
		}
241 de1a3167 jim-p
		if ($ca) {
242 e8c516a0 Phil Davis
			$properties[] = sprintf(gettext("CA: %s"), $ca['descr']);
243 de1a3167 jim-p
		}
244 0e9d4a6d jim-p
		if (cert_in_use($cert['refid'])) {
245 e8c516a0 Phil Davis
			$properties[] = gettext("In Use");
246 0e9d4a6d jim-p
		}
247
		if (is_cert_revoked($cert)) {
248 e8c516a0 Phil Davis
			$properties[] = gettext("Revoked");
249 de1a3167 jim-p
		}
250 f4eec250 Phil Davis
251 0e9d4a6d jim-p
		if (!empty($properties)) {
252
			$propstr = " (" . implode(", ", $properties) . ")";
253 de1a3167 jim-p
		}
254 f4eec250 Phil Davis
255 0e9d4a6d jim-p
		if ($prioritize_server_certs) {
256
			if ($purpose['server'] == "Yes") {
257
				$list[$cert['refid']] = $cert['descr'] . $propstr;
258
			} else {
259
				$non_server_list[$cert['refid']] = $cert['descr'] . $propstr;
260
			}
261
		} else {
262
			$list[$cert['refid']] = $cert['descr'] . $propstr;
263 de1a3167 jim-p
		}
264 0e9d4a6d jim-p
	}
265 f4eec250 Phil Davis
266 a4ba0282 Stephen Beaver
	return(array('server' => $list, 'non-server' => $non_server_list));
267 f4eec250 Phil Davis
}
268
269
function openvpn_build_bridge_list() {
270
	$list = array();
271
272
	$serverbridge_interface['none'] = "none";
273
	$serverbridge_interface = array_merge($serverbridge_interface, get_configured_interface_with_descr());
274 2a5960b0 Luiz Otavio O Souza
	$viplist = get_configured_vip_list();
275 f4eec250 Phil Davis
276 2a5960b0 Luiz Otavio O Souza
	foreach ($viplist as $vip => $address) {
277
		$serverbridge_interface[$vip.'|'.$address] = $address;
278 d9901ff4 Chris Buechler
		if (get_vip_descr($address)) {
279 2a5960b0 Luiz Otavio O Souza
			$serverbridge_interface[$vip.'|'.$address] .= " (". get_vip_descr($address) .")";
280 d9901ff4 Chris Buechler
		}
281 4e322e2c Phil Davis
	}
282 f4eec250 Phil Davis
283 4e322e2c Phil Davis
	foreach ($serverbridge_interface as $iface => $ifacename) {
284 f4eec250 Phil Davis
		$list[$iface] = htmlspecialchars($ifacename);
285 4e322e2c Phil Davis
	}
286 f4eec250 Phil Davis
287
	return($list);
288
}
289
290 3c11bd3c Matthew Grooms
function openvpn_create_key() {
291
292
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
293 ef00af3c Phil Davis
	if (!$fp) {
294 3c11bd3c Matthew Grooms
		return false;
295 ef00af3c Phil Davis
	}
296 3c11bd3c Matthew Grooms
297
	$rslt = stream_get_contents($fp);
298
	pclose($fp);
299
300
	return $rslt;
301
}
302 d799787e Matthew Grooms
303 8411b218 Matthew Grooms
function openvpn_create_dhparams($bits) {
304 34bc1324 Matthew Grooms
305 2ec95f1f Renato Botelho
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
306 ef00af3c Phil Davis
	if (!$fp) {
307 34bc1324 Matthew Grooms
		return false;
308 ef00af3c Phil Davis
	}
309 34bc1324 Matthew Grooms
310
	$rslt = stream_get_contents($fp);
311
	pclose($fp);
312
313
	return $rslt;
314
}
315
316 d799787e Matthew Grooms
function openvpn_vpnid_used($vpnid) {
317 8be2d6d3 Ermal Luçi
	global $config;
318
319 ef00af3c Phil Davis
	if (is_array($config['openvpn']['openvpn-server'])) {
320
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
321
			if ($vpnid == $settings['vpnid']) {
322 d799787e Matthew Grooms
				return true;
323 ef00af3c Phil Davis
			}
324
		}
325
	}
326 d799787e Matthew Grooms
327 ef00af3c Phil Davis
	if (is_array($config['openvpn']['openvpn-client'])) {
328
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
329
			if ($vpnid == $settings['vpnid']) {
330 d799787e Matthew Grooms
				return true;
331 ef00af3c Phil Davis
			}
332
		}
333
	}
334 04a6e900 Ermal Luçi
335 d799787e Matthew Grooms
	return false;
336
}
337
338
function openvpn_vpnid_next() {
339
340
	$vpnid = 1;
341 ef00af3c Phil Davis
	while (openvpn_vpnid_used($vpnid)) {
342 d799787e Matthew Grooms
		$vpnid++;
343 ef00af3c Phil Davis
	}
344 d799787e Matthew Grooms
345
	return $vpnid;
346
}
347
348 49b76122 Renato Botelho
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
349 f432e364 Matthew Grooms
	global $config;
350
351 49b76122 Renato Botelho
	if (is_array($config['openvpn']['openvpn-server'])) {
352
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
353 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
354 49b76122 Renato Botelho
				continue;
355 ef00af3c Phil Davis
			}
356 49b76122 Renato Botelho
357 ef00af3c Phil Davis
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
358 49b76122 Renato Botelho
				continue;
359 ef00af3c Phil Davis
			}
360 49b76122 Renato Botelho
361
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
362 ef00af3c Phil Davis
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
363 f432e364 Matthew Grooms
				return $settings['vpnid'];
364 ef00af3c Phil Davis
			}
365 49b76122 Renato Botelho
		}
366
	}
367 f432e364 Matthew Grooms
368 49b76122 Renato Botelho
	if (is_array($config['openvpn']['openvpn-client'])) {
369
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
370 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
371 49b76122 Renato Botelho
				continue;
372 ef00af3c Phil Davis
			}
373 49b76122 Renato Botelho
374 ef00af3c Phil Davis
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
375 49b76122 Renato Botelho
				continue;
376 ef00af3c Phil Davis
			}
377 49b76122 Renato Botelho
378
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
379 ef00af3c Phil Davis
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
380 f432e364 Matthew Grooms
				return $settings['vpnid'];
381 ef00af3c Phil Davis
			}
382 49b76122 Renato Botelho
		}
383
	}
384 f432e364 Matthew Grooms
385
	return 0;
386
}
387
388 49b76122 Renato Botelho
function openvpn_port_next($prot, $interface = "wan") {
389 f432e364 Matthew Grooms
390
	$port = 1194;
391 ef00af3c Phil Davis
	while (openvpn_port_used($prot, $interface, $port)) {
392 49b76122 Renato Botelho
		$port++;
393 ef00af3c Phil Davis
	}
394
	while (openvpn_port_used($prot, "any", $port)) {
395 f432e364 Matthew Grooms
		$port++;
396 ef00af3c Phil Davis
	}
397 f432e364 Matthew Grooms
398
	return $port;
399
}
400
401 d799787e Matthew Grooms
function openvpn_get_cipherlist() {
402
403
	$ciphers = array();
404 5a7cc1f9 Ermal
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
405 d799787e Matthew Grooms
	$cipher_lines = explode("\n", trim($cipher_out));
406
	sort($cipher_lines);
407
	foreach ($cipher_lines as $line) {
408
		$words = explode(' ', $line);
409
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
410 8be2d6d3 Ermal Luçi
	}
411 4aa02281 Carlos Eduardo Ramos
	$ciphers["none"] = gettext("None (No Encryption)");
412 d799787e Matthew Grooms
	return $ciphers;
413
}
414
415 97d5b59b jim-p
function openvpn_get_digestlist() {
416
417
	$digests = array();
418
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
419
	$digest_lines = explode("\n", trim($digest_out));
420
	sort($digest_lines);
421
	foreach ($digest_lines as $line) {
422
		$words = explode(' ', $line);
423
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
424
	}
425
	$digests["none"] = gettext("None (No Authentication)");
426
	return $digests;
427
}
428
429 582c58ae jim-p
function openvpn_get_engines() {
430 e8c516a0 Phil Davis
	$openssl_engines = array('none' => gettext('No Hardware Crypto Acceleration'));
431 2ec95f1f Renato Botelho
	exec("/usr/bin/openssl engine -t -c", $openssl_engine_output);
432 349bf358 jim-p
	$openssl_engine_output = implode("\n", $openssl_engine_output);
433
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
434
	$openssl_engine_output = explode("\n", $openssl_engine_output);
435
436 582c58ae jim-p
	foreach ($openssl_engine_output as $oeo) {
437 349bf358 jim-p
		$keep = true;
438
		$details = explode("|", $oeo);
439
		$engine = array_shift($details);
440 582c58ae jim-p
		$linematch = array();
441 349bf358 jim-p
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
442
		foreach ($details as $dt) {
443 ef00af3c Phil Davis
			if (strpos($dt, "unavailable") !== FALSE) {
444 349bf358 jim-p
				$keep = false;
445 ef00af3c Phil Davis
			}
446
			if (strpos($dt, "available") !== FALSE) {
447 349bf358 jim-p
				continue;
448 ef00af3c Phil Davis
			}
449
			if (strpos($dt, "[") !== FALSE) {
450 349bf358 jim-p
				$ciphers = trim($dt, "[]");
451 ef00af3c Phil Davis
			}
452 349bf358 jim-p
		}
453 ef00af3c Phil Davis
		if (!empty($ciphers)) {
454 349bf358 jim-p
			$ciphers = " - " . $ciphers;
455 ef00af3c Phil Davis
		}
456
		if (strlen($ciphers) > 60) {
457 349bf358 jim-p
			$ciphers = substr($ciphers, 0, 60) . " ... ";
458 ef00af3c Phil Davis
		}
459
		if ($keep) {
460 349bf358 jim-p
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
461 ef00af3c Phil Davis
		}
462 582c58ae jim-p
	}
463
	return $openssl_engines;
464
}
465
466
function openvpn_validate_engine($engine) {
467
	$engines = openvpn_get_engines();
468
	return array_key_exists($engine, $engines);
469
}
470
471 d799787e Matthew Grooms
function openvpn_validate_host($value, $name) {
472
	$value = trim($value);
473 ef00af3c Phil Davis
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value))) {
474 4aa02281 Carlos Eduardo Ramos
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
475 ef00af3c Phil Davis
	}
476 d799787e Matthew Grooms
	return false;
477 8dc3ef67 Scott Ullrich
}
478
479
function openvpn_validate_port($value, $name) {
480
	$value = trim($value);
481 ef00af3c Phil Davis
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535)) {
482 4aa02281 Carlos Eduardo Ramos
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
483 ef00af3c Phil Davis
	}
484 b398bbca Martin Fuchs
	return false;
485 8dc3ef67 Scott Ullrich
}
486
487 a28d40cb jim-p
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
488
	$value = trim($value);
489
	$error = false;
490 ef00af3c Phil Davis
	if (empty($value)) {
491 a28d40cb jim-p
		return false;
492 ef00af3c Phil Davis
	}
493 a28d40cb jim-p
	$networks = explode(',', $value);
494
495 ef00af3c Phil Davis
	if (!$multiple && (count($networks) > 1)) {
496 e8c516a0 Phil Davis
		return sprintf(gettext("The field '%1\$s' must contain a single valid %2\$s CIDR range."), $name, $ipproto);
497 ef00af3c Phil Davis
	}
498 a28d40cb jim-p
499
	foreach ($networks as $network) {
500 ef00af3c Phil Davis
		if ($ipproto == "ipv4") {
501 a28d40cb jim-p
			$error = !openvpn_validate_cidr_ipv4($network);
502 ef00af3c Phil Davis
		} else {
503 a28d40cb jim-p
			$error = !openvpn_validate_cidr_ipv6($network);
504 ef00af3c Phil Davis
		}
505
		if ($error) {
506 a28d40cb jim-p
			break;
507 ef00af3c Phil Davis
		}
508 a28d40cb jim-p
	}
509
510 ef00af3c Phil Davis
	if ($error) {
511 e8c516a0 Phil Davis
		return sprintf(gettext("The field '%1\$s' must contain only valid %2\$s CIDR range(s) separated by commas."), $name, $ipproto);
512 ef00af3c Phil Davis
	} else {
513 a28d40cb jim-p
		return false;
514 ef00af3c Phil Davis
	}
515 a28d40cb jim-p
}
516
517
function openvpn_validate_cidr_ipv4($value) {
518 8dc3ef67 Scott Ullrich
	$value = trim($value);
519
	if (!empty($value)) {
520
		list($ip, $mask) = explode('/', $value);
521 ef00af3c Phil Davis
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0)) {
522 a28d40cb jim-p
			return false;
523 ef00af3c Phil Davis
		}
524 8dc3ef67 Scott Ullrich
	}
525 a28d40cb jim-p
	return true;
526
}
527
528
function openvpn_validate_cidr_ipv6($value) {
529
	$value = trim($value);
530
	if (!empty($value)) {
531
		list($ipv6, $prefix) = explode('/', $value);
532 ef00af3c Phil Davis
		if (empty($prefix)) {
533 a28d40cb jim-p
			$prefix = "128";
534 ef00af3c Phil Davis
		}
535
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0)) {
536 a28d40cb jim-p
			return false;
537 ef00af3c Phil Davis
		}
538 a28d40cb jim-p
	}
539
	return true;
540 afb07cf1 Scott Ullrich
}
541
542 d799787e Matthew Grooms
function openvpn_add_dhcpopts(& $settings, & $conf) {
543 afb07cf1 Scott Ullrich
544 ef00af3c Phil Davis
	if (!empty($settings['dns_domain'])) {
545 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
546 ef00af3c Phil Davis
	}
547 add2e3f7 Scott Ullrich
548 ef00af3c Phil Davis
	if (!empty($settings['dns_server1'])) {
549 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
550 ef00af3c Phil Davis
	}
551
	if (!empty($settings['dns_server2'])) {
552 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
553 ef00af3c Phil Davis
	}
554
	if (!empty($settings['dns_server3'])) {
555 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
556 ef00af3c Phil Davis
	}
557
	if (!empty($settings['dns_server4'])) {
558 d799787e Matthew Grooms
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
559 ef00af3c Phil Davis
	}
560 f9927473 Scott Ullrich
561 ef00af3c Phil Davis
	if (!empty($settings['push_register_dns'])) {
562 c38764dc Dmitriy K.
		$conf .= "push \"register-dns\"\n";
563 ef00af3c Phil Davis
	}
564 c38764dc Dmitriy K.
565 ef00af3c Phil Davis
	if (!empty($settings['ntp_server1'])) {
566 c7f70dbc Chris Buechler
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
567 ef00af3c Phil Davis
	}
568
	if (!empty($settings['ntp_server2'])) {
569 c7f70dbc Chris Buechler
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
570 ef00af3c Phil Davis
	}
571 f9927473 Scott Ullrich
572 d799787e Matthew Grooms
	if ($settings['netbios_enable']) {
573 add2e3f7 Scott Ullrich
574 ef00af3c Phil Davis
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0)) {
575 095a95ae Matthew Grooms
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
576 ef00af3c Phil Davis
		}
577
		if (!empty($settings['dhcp_nbtscope'])) {
578 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
579 ef00af3c Phil Davis
		}
580 8dc3ef67 Scott Ullrich
581 ef00af3c Phil Davis
		if (!empty($settings['wins_server1'])) {
582 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
583 ef00af3c Phil Davis
		}
584
		if (!empty($settings['wins_server2'])) {
585 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
586 ef00af3c Phil Davis
		}
587 add2e3f7 Scott Ullrich
588 ef00af3c Phil Davis
		if (!empty($settings['nbdd_server1'])) {
589 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
590 ef00af3c Phil Davis
		}
591 d799787e Matthew Grooms
	}
592 8dc3ef67 Scott Ullrich
593 ef00af3c Phil Davis
	if ($settings['gwredir']) {
594 d799787e Matthew Grooms
		$conf .= "push \"redirect-gateway def1\"\n";
595 ef00af3c Phil Davis
	}
596 d799787e Matthew Grooms
}
597 24012690 Scott Ullrich
598 d799787e Matthew Grooms
function openvpn_add_custom(& $settings, & $conf) {
599 add2e3f7 Scott Ullrich
600 d799787e Matthew Grooms
	if ($settings['custom_options']) {
601 8dc3ef67 Scott Ullrich
602 d799787e Matthew Grooms
		$options = explode(';', $settings['custom_options']);
603
604
		if (is_array($options)) {
605 ef00af3c Phil Davis
			foreach ($options as $option) {
606 d799787e Matthew Grooms
				$conf .= "$option\n";
607 ef00af3c Phil Davis
			}
608
		} else {
609 d799787e Matthew Grooms
			$conf .= "{$settings['custom_options']}\n";
610 ef00af3c Phil Davis
		}
611 add2e3f7 Scott Ullrich
	}
612
}
613
614 691fbf14 Ermal Lu?i
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
615 d799787e Matthew Grooms
	global $g;
616 add2e3f7 Scott Ullrich
617 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
618 a8f538a8 jim-p
	openvpn_create_dirs();
619 d799787e Matthew Grooms
	file_put_contents($fpath, base64_decode($data));
620 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
621
	//chgrp($fpath, 'nobody');
622 6f27412f Ermal Lu?i
	@chmod($fpath, 0600);
623 d799787e Matthew Grooms
624 691fbf14 Ermal Lu?i
	$conf .= "{$directive} {$fpath} {$opt}\n";
625 4eefa6e8 Scott Ullrich
}
626
627 fc05822b jim-p
function openvpn_reconfigure($mode, $settings) {
628 6293d7ed jim-p
	global $g, $config, $openvpn_tls_server_modes;
629 afb07cf1 Scott Ullrich
630 ef00af3c Phil Davis
	if (empty($settings)) {
631 93a0a028 Ermal Luçi
		return;
632 ef00af3c Phil Davis
	}
633
	if (isset($settings['disable'])) {
634 4eefa6e8 Scott Ullrich
		return;
635 ef00af3c Phil Davis
	}
636 a8f538a8 jim-p
	openvpn_create_dirs();
637 fdd725f0 Ermal Luçi
	/*
638 d799787e Matthew Grooms
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
639
	 * we use a vpnid number which is allocated for a particular client
640
	 * or server configuration. ( see openvpn_vpnid_next() )
641 fdd725f0 Ermal Luçi
	 */
642 8874c692 Ermal Luçi
643 d799787e Matthew Grooms
	$vpnid = $settings['vpnid'];
644
	$mode_id = $mode.$vpnid;
645 8874c692 Ermal Luçi
646 ef00af3c Phil Davis
	if (isset($settings['dev_mode'])) {
647 4936ff53 jim-p
		$tunname = "{$settings['dev_mode']}{$vpnid}";
648 ef00af3c Phil Davis
	} else {
649
		/* defaults to tun */
650 bd7ca506 jim-p
		$tunname = "tun{$vpnid}";
651 4936ff53 jim-p
		$settings['dev_mode'] = "tun";
652 691fbf14 Ermal Lu?i
	}
653
654 ef00af3c Phil Davis
	if ($mode == "server") {
655 bd7ca506 jim-p
		$devname = "ovpns{$vpnid}";
656 ef00af3c Phil Davis
	} else {
657 bd7ca506 jim-p
		$devname = "ovpnc{$vpnid}";
658 ef00af3c Phil Davis
	}
659 8874c692 Ermal Luçi
660 bd7ca506 jim-p
	/* is our device already configured */
661 4a97aa34 Ermal
	if (!does_interface_exist($devname)) {
662 dc408939 Matthew Grooms
663 bd7ca506 jim-p
		/* create the tap device if required */
664 ef00af3c Phil Davis
		if (!file_exists("/dev/{$tunname}")) {
665 873c1701 Renato Botelho
			exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
666 ef00af3c Phil Davis
		}
667 98872d89 Ermal Luçi
668 bd7ca506 jim-p
		/* rename the device */
669 873c1701 Renato Botelho
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
670 095a95ae Matthew Grooms
671 4ab1ffa0 Renato Botelho
		/* add the device to the openvpn group and make sure it's UP*/
672
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn up");
673 da4f91a9 Renato Botelho
674 bd1a6267 Renato Botelho
		$ifname = convert_real_interface_to_friendly_interface_name($devname);
675
		$grouptmp = link_interface_to_group($ifname);
676 ef00af3c Phil Davis
		if (!empty($grouptmp)) {
677 bd1a6267 Renato Botelho
			array_walk($grouptmp, 'interface_group_add_member');
678 ef00af3c Phil Davis
		}
679 bd1a6267 Renato Botelho
		unset($grouptmp, $ifname);
680 dc408939 Matthew Grooms
	}
681 d799787e Matthew Grooms
682 dc408939 Matthew Grooms
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
683 6714bbdc jim-p
	$proto = strtolower($settings['protocol']);
684 ef00af3c Phil Davis
	if (substr($settings['protocol'], 0, 3) == "TCP") {
685 6714bbdc jim-p
			$proto = "{$proto}-{$mode}";
686 ef00af3c Phil Davis
	}
687 4936ff53 jim-p
	$dev_mode = $settings['dev_mode'];
688 c0cf27aa Scott Ullrich
	$cipher = $settings['crypto'];
689 97d5b59b jim-p
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
690
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
691 d799787e Matthew Grooms
692 47c48e28 smos
	$interface = get_failover_interface($settings['interface']);
693 e27bc6cf Phil Davis
	// The IP address in the settings can be an IPv4 or IPv6 address associated with the interface
694 d7a0c22a bcyrill
	$ipaddr = $settings['ipaddr'];
695 d799787e Matthew Grooms
696 67b0902f pierrepomes
	// If a specific ip address (VIP) is requested, use it.
697
	// Otherwise, if a specific interface is requested, use it
698 ef00af3c Phil Davis
	// If "any" interface was selected, local directive will be omitted.
699 97ffc513 Seth Mos
	if (is_ipaddrv4($ipaddr)) {
700 4de8f7ba Phil Davis
		$iface_ip = $ipaddr;
701 3d06e8f0 pierrepomes
	} else {
702 67b0902f pierrepomes
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
703 507af8dd pierrepomes
			$iface_ip=get_interface_ip($interface);
704 67b0902f pierrepomes
		}
705 47c48e28 smos
	}
706 e27bc6cf Phil Davis
	if (is_ipaddrv6($ipaddr)) {
707 6c07db48 Phil Davis
		$iface_ipv6 = $ipaddr;
708 47c48e28 smos
	} else {
709 97ffc513 Seth Mos
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
710
			$iface_ipv6=get_interface_ipv6($interface);
711
		}
712 3d06e8f0 pierrepomes
	}
713 d799787e Matthew Grooms
714 b1e8e675 Dmitriy K.
715
	$conf = "dev {$devname}\n";
716 5b3c0116 Dmitriy K.
	if (isset($settings['verbosity_level'])) {
717 b1e8e675 Dmitriy K.
		$conf .= "verb {$settings['verbosity_level']}\n";
718 5b3c0116 Dmitriy K.
	}
719 42bb1bee Renato Botelho
720 4936ff53 jim-p
	$conf .= "dev-type {$settings['dev_mode']}\n";
721 ef00af3c Phil Davis
	switch ($settings['dev_mode']) {
722 97ffc513 Seth Mos
		case "tun":
723 b9e9903d Dmitriy K.
			if (!$settings['no_tun_ipv6']) {
724
				$conf .= "tun-ipv6\n";
725
			}
726 97ffc513 Seth Mos
			break;
727
	}
728 bd7ca506 jim-p
	$conf .= "dev-node /dev/{$tunname}\n";
729 3c11bd3c Matthew Grooms
	$conf .= "writepid {$pfile}\n";
730
	$conf .= "#user nobody\n";
731
	$conf .= "#group nobody\n";
732 d1014c18 Chris Buechler
	$conf .= "script-security 3\n";
733 3c11bd3c Matthew Grooms
	$conf .= "daemon\n";
734
	$conf .= "keepalive 10 60\n";
735
	$conf .= "ping-timer-rem\n";
736
	$conf .= "persist-tun\n";
737
	$conf .= "persist-key\n";
738
	$conf .= "proto {$proto}\n";
739
	$conf .= "cipher {$cipher}\n";
740 97d5b59b jim-p
	$conf .= "auth {$digest}\n";
741 8d964cea Ermal
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
742
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
743 1492e02c Ermal
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
744 ef00af3c Phil Davis
		switch ($settings['mode']) {
745 a1b9105b jim-p
			case 'server_user':
746
			case 'server_tls_user':
747
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
748
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
749
				break;
750
		}
751 1492e02c Ermal
	}
752 3c11bd3c Matthew Grooms
753 6714bbdc jim-p
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
754
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
755
		$conf .= "local {$iface_ip}\n";
756
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
757
		$conf .= "local {$iface_ipv6}\n";
758 97ffc513 Seth Mos
	}
759 d799787e Matthew Grooms
760 ef00af3c Phil Davis
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none")) {
761 582c58ae jim-p
		$conf .= "engine {$settings['engine']}\n";
762 ef00af3c Phil Davis
	}
763 582c58ae jim-p
764 67b0902f pierrepomes
	// server specific settings
765 8dc3ef67 Scott Ullrich
	if ($mode == 'server') {
766 d799787e Matthew Grooms
767 c228156f jim-p
		list($ip, $cidr) = explode('/', trim($settings['tunnel_network']));
768
		list($ipv6, $prefix) = explode('/', trim($settings['tunnel_networkv6']));
769 5dc6c910 jim-p
		$mask = gen_subnet_mask($cidr);
770 8dc3ef67 Scott Ullrich
771 3c11bd3c Matthew Grooms
		// configure tls modes
772 ef00af3c Phil Davis
		switch ($settings['mode']) {
773 3c11bd3c Matthew Grooms
			case 'p2p_tls':
774
			case 'server_tls':
775 e62e2f8b Ermal Lu?i
			case 'server_user':
776 3c11bd3c Matthew Grooms
			case 'server_tls_user':
777 d799787e Matthew Grooms
				$conf .= "tls-server\n";
778 3c11bd3c Matthew Grooms
				break;
779 8dc3ef67 Scott Ullrich
		}
780 d799787e Matthew Grooms
781 3c11bd3c Matthew Grooms
		// configure p2p/server modes
782 ef00af3c Phil Davis
		switch ($settings['mode']) {
783 6c9cf466 jim-p
			case 'p2p_tls':
784 5dc6c910 jim-p
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
785
				//  use the server directive. It works for a single client without it.
786
				//  See ticket #1417
787 74a556a3 jim-p
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
788 5dc6c910 jim-p
					$conf .= "server {$ip} {$mask}\n";
789 154b0f80 jim-p
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
790 ef00af3c Phil Davis
					if (is_ipaddr($ipv6)) {
791 a0e3ee98 jim-p
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
792 ef00af3c Phil Davis
					}
793 5dc6c910 jim-p
				}
794 3c11bd3c Matthew Grooms
			case 'p2p_shared_key':
795 74a556a3 jim-p
				if (!empty($ip) && !empty($mask)) {
796 30c8a290 Renato Botelho
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
797 ef00af3c Phil Davis
					if ($settings['dev_mode'] == 'tun') {
798 459e9333 jim-p
						$conf .= "ifconfig {$ip1} {$ip2}\n";
799 ef00af3c Phil Davis
					} else {
800 459e9333 jim-p
						$conf .= "ifconfig {$ip1} {$mask}\n";
801 ef00af3c Phil Davis
					}
802 1ab6bdb5 jim-p
				}
803 a0e3ee98 jim-p
				if (!empty($ipv6) && !empty($prefix)) {
804 91c44185 jim-p
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
805 ef00af3c Phil Davis
					if ($settings['dev_mode'] == 'tun') {
806 a0e3ee98 jim-p
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
807 ef00af3c Phil Davis
					} else {
808 60f501ec Phil Davis
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
809 ef00af3c Phil Davis
					}
810 a0e3ee98 jim-p
				}
811 3c11bd3c Matthew Grooms
				break;
812
			case 'server_tls':
813
			case 'server_user':
814
			case 'server_tls_user':
815 74a556a3 jim-p
				if (!empty($ip) && !empty($mask)) {
816 1ab6bdb5 jim-p
					$conf .= "server {$ip} {$mask}\n";
817 ef00af3c Phil Davis
					if (is_ipaddr($ipv6)) {
818 1ab6bdb5 jim-p
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
819 ef00af3c Phil Davis
					}
820 154b0f80 jim-p
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
821 1ab6bdb5 jim-p
				} else {
822
					if ($settings['serverbridge_dhcp']) {
823
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
824
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
825
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
826
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
827
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
828 154b0f80 jim-p
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
829 1ab6bdb5 jim-p
							} else {
830
								$conf .= "mode server\n";
831
							}
832
						} else {
833
							$conf .= "mode server\n";
834
						}
835
					}
836
				}
837 3c11bd3c Matthew Grooms
				break;
838 8dc3ef67 Scott Ullrich
		}
839
840 3c11bd3c Matthew Grooms
		// configure user auth modes
841 ef00af3c Phil Davis
		switch ($settings['mode']) {
842 3c11bd3c Matthew Grooms
			case 'server_user':
843
				$conf .= "client-cert-not-required\n";
844
			case 'server_tls_user':
845 9eced774 jim-p
				/* username-as-common-name is not compatible with server-bridge */
846 ef00af3c Phil Davis
				if (stristr($conf, "server-bridge") === false) {
847 9eced774 jim-p
					$conf .= "username-as-common-name\n";
848 ef00af3c Phil Davis
				}
849 8a47c190 Ermal Lu?i
				if (!empty($settings['authmode'])) {
850 5e28dad4 Ermal
					$strictusercn = "false";
851 ef00af3c Phil Davis
					if ($settings['strictusercn']) {
852 5e28dad4 Ermal
						$strictusercn = "true";
853 ef00af3c Phil Davis
					}
854 57ab9f7d Ermal
					$conf .= "auth-user-pass-verify \"/usr/local/sbin/ovpn_auth_verify user '{$settings['authmode']}' {$strictusercn} {$mode_id}\" via-env\n";
855 e8a58de4 Ermal Lu?i
				}
856 3c11bd3c Matthew Grooms
				break;
857 8dc3ef67 Scott Ullrich
		}
858 ef00af3c Phil Davis
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls'))) {
859 41936acc jim-p
			$settings['cert_depth'] = 1;
860 ef00af3c Phil Davis
		}
861 98963f27 jim-p
		if (is_numeric($settings['cert_depth'])) {
862 ef00af3c Phil Davis
			if (($mode == 'client') && empty($settings['certref'])) {
863 2da48592 jim-p
				$cert = "";
864 ef00af3c Phil Davis
			} else {
865 2da48592 jim-p
				$cert = lookup_cert($settings['certref']);
866
				/* XXX: Seems not used at all! */
867
				$servercn = urlencode(cert_get_cn($cert['crt']));
868
				$conf .= "tls-verify \"/usr/local/sbin/ovpn_auth_verify tls '{$servercn}' {$settings['cert_depth']}\"\n";
869
			}
870 98963f27 jim-p
		}
871 8dc3ef67 Scott Ullrich
872 63084885 Matthew Grooms
		// The local port to listen on
873 d799787e Matthew Grooms
		$conf .= "lport {$settings['local_port']}\n";
874 c0cf27aa Scott Ullrich
875 63084885 Matthew Grooms
		// The management port to listen on
876 71ca2cb2 Ermal
		// Use unix socket to overcome the problem on any type of server
877
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
878
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
879 63084885 Matthew Grooms
880 ef00af3c Phil Davis
		if ($settings['maxclients']) {
881 d799787e Matthew Grooms
			$conf .= "max-clients {$settings['maxclients']}\n";
882 ef00af3c Phil Davis
		}
883 d799787e Matthew Grooms
884 3c11bd3c Matthew Grooms
		// Can we push routes
885
		if ($settings['local_network']) {
886 a28d40cb jim-p
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
887 3c11bd3c Matthew Grooms
		}
888 787de45a Seth Mos
		if ($settings['local_networkv6']) {
889 a28d40cb jim-p
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
890 787de45a Seth Mos
		}
891 3c11bd3c Matthew Grooms
892 ef00af3c Phil Davis
		switch ($settings['mode']) {
893 3c11bd3c Matthew Grooms
			case 'server_tls':
894
			case 'server_user':
895
			case 'server_tls_user':
896 5d8cd81a jim-p
				// Configure client dhcp options
897 3c11bd3c Matthew Grooms
				openvpn_add_dhcpopts($settings, $conf);
898 ef00af3c Phil Davis
				if ($settings['client2client']) {
899 5d8cd81a jim-p
					$conf .= "client-to-client\n";
900 ef00af3c Phil Davis
				}
901 3c11bd3c Matthew Grooms
				break;
902
		}
903 ef00af3c Phil Davis
		if (isset($settings['duplicate_cn'])) {
904 bca35cff jim-p
			$conf .= "duplicate-cn\n";
905 ef00af3c Phil Davis
		}
906 d799787e Matthew Grooms
	}
907
908 3c11bd3c Matthew Grooms
	// client specific settings
909 d799787e Matthew Grooms
910 3c11bd3c Matthew Grooms
	if ($mode == 'client') {
911 d799787e Matthew Grooms
912 3c11bd3c Matthew Grooms
		// configure p2p mode
913 ef00af3c Phil Davis
		switch ($settings['mode']) {
914 3c11bd3c Matthew Grooms
			case 'p2p_tls':
915
				$conf .= "tls-client\n";
916
			case 'shared_key':
917
				$conf .= "client\n";
918
				break;
919
		}
920 d799787e Matthew Grooms
921 e3924384 jim-p
		// If there is no bind option at all (ip and/or port), add "nobind" directive
922 42bb1bee Renato Botelho
		//  Otherwise, use the local port if defined, failing that, use lport 0 to
923 e3924384 jim-p
		//  ensure a random source port.
924 ef00af3c Phil Davis
		if ((empty($iface_ip)) && (!$settings['local_port'])) {
925 e3924384 jim-p
			$conf .= "nobind\n";
926 ef00af3c Phil Davis
		} elseif ($settings['local_port']) {
927 e3924384 jim-p
			$conf .= "lport {$settings['local_port']}\n";
928 ef00af3c Phil Davis
		} else {
929 e3924384 jim-p
			$conf .= "lport 0\n";
930 ef00af3c Phil Davis
		}
931 5708241f jim-p
932 4b887ef4 jim-p
		// Use unix socket to overcome the problem on any type of server
933
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
934 48a458d2 pierrepomes
935 3c11bd3c Matthew Grooms
		// The remote server
936
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
937
938 ef00af3c Phil Davis
		if (!empty($settings['use_shaper'])) {
939 d799787e Matthew Grooms
			$conf .= "shaper {$settings['use_shaper']}\n";
940 ef00af3c Phil Davis
		}
941 ee506044 Scott Ullrich
942 d799787e Matthew Grooms
		if (!empty($settings['tunnel_network'])) {
943 c228156f jim-p
			list($ip, $cidr) = explode('/', trim($settings['tunnel_network']));
944 30c8a290 Renato Botelho
			$mask = gen_subnet_mask($cidr);
945 636918c9 Chris Buechler
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
946 ef00af3c Phil Davis
			if ($settings['dev_mode'] == 'tun') {
947 459e9333 jim-p
				$conf .= "ifconfig {$ip2} {$ip1}\n";
948 ef00af3c Phil Davis
			} else {
949 459e9333 jim-p
				$conf .= "ifconfig {$ip2} {$mask}\n";
950 ef00af3c Phil Davis
			}
951 8dc3ef67 Scott Ullrich
		}
952 d799787e Matthew Grooms
953 a0e3ee98 jim-p
		if (!empty($settings['tunnel_networkv6'])) {
954 c228156f jim-p
			list($ipv6, $prefix) = explode('/', trim($settings['tunnel_networkv6']));
955 91c44185 jim-p
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
956 ef00af3c Phil Davis
			if ($settings['dev_mode'] == 'tun') {
957 a0e3ee98 jim-p
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
958 ef00af3c Phil Davis
			} else {
959 60f501ec Phil Davis
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
960 ef00af3c Phil Davis
			}
961 a0e3ee98 jim-p
		}
962
963 a6d55c23 Chris Buechler
		if (($settings['auth_user'] || $settings['auth_pass']) && $settings['mode'] == "p2p_tls") {
964 5f242576 PiBa-NL
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
965
			$conf .= "auth-user-pass {$up_file}\n";
966 7304c023 Phil Davis
			if ($settings['auth_user']) {
967 4de8f7ba Phil Davis
				$userpass = "{$settings['auth_user']}\n";
968 7304c023 Phil Davis
			} else {
969
				$userpass = "";
970
			}
971
			if ($settings['auth_pass']) {
972 4de8f7ba Phil Davis
				$userpass .= "{$settings['auth_pass']}\n";
973 7304c023 Phil Davis
			}
974
			// If only auth_pass is given, then it acts like a user name and we put a blank line where pass would normally go.
975
			if (!($settings['auth_user'] && $settings['auth_pass'])) {
976
				$userpass .= "\n";
977
			}
978 5f242576 PiBa-NL
			file_put_contents($up_file, $userpass);
979
		}
980 42bb1bee Renato Botelho
981 762a24a3 Ermal Lu?i
		if ($settings['proxy_addr']) {
982
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
983
			if ($settings['proxy_authtype'] != "none") {
984
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
985
				$proxypas = "{$settings['proxy_user']}\n";
986
				$proxypas .= "{$settings['proxy_passwd']}\n";
987
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
988
			}
989
			$conf .= " \n";
990
		}
991 8dc3ef67 Scott Ullrich
	}
992
993 17c98ba9 jim-p
	// Add a remote network route if set, and only for p2p modes.
994 54285411 jim-p
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
995 a28d40cb jim-p
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
996 8dc3ef67 Scott Ullrich
	}
997 4856df9b jim-p
	// Add a remote network route if set, and only for p2p modes.
998 54285411 jim-p
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
999 a28d40cb jim-p
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
1000 4856df9b jim-p
	}
1001 afb07cf1 Scott Ullrich
1002 d799787e Matthew Grooms
	// Write the settings for the keys
1003 ef00af3c Phil Davis
	switch ($settings['mode']) {
1004 3c11bd3c Matthew Grooms
		case 'p2p_shared_key':
1005
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
1006
			break;
1007
		case 'p2p_tls':
1008
		case 'server_tls':
1009
		case 'server_tls_user':
1010 e62e2f8b Ermal Lu?i
		case 'server_user':
1011 3c11bd3c Matthew Grooms
			$ca = lookup_ca($settings['caref']);
1012
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
1013 2da48592 jim-p
1014
			if (!empty($settings['certref'])) {
1015
				$cert = lookup_cert($settings['certref']);
1016
				openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
1017
				openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
1018
			}
1019 ef00af3c Phil Davis
			if ($mode == 'server') {
1020 fe787fc7 Matthew Grooms
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
1021 ef00af3c Phil Davis
			}
1022 6db02381 jim-p
			if (!empty($settings['crlref'])) {
1023
				$crl = lookup_crl($settings['crlref']);
1024 cfcc6994 jim-p
				crl_update($crl);
1025 6db02381 jim-p
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
1026
			}
1027 db746ce2 Ermal Lu?i
			if ($settings['tls']) {
1028 ef00af3c Phil Davis
				if ($mode == "server") {
1029 db746ce2 Ermal Lu?i
					$tlsopt = 0;
1030 ef00af3c Phil Davis
				} else {
1031 db746ce2 Ermal Lu?i
					$tlsopt = 1;
1032 ef00af3c Phil Davis
				}
1033 db746ce2 Ermal Lu?i
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
1034
			}
1035 3c11bd3c Matthew Grooms
			break;
1036 8dc3ef67 Scott Ullrich
	}
1037
1038 ef00af3c Phil Davis
	if (!empty($settings['compression'])) {
1039 edba1982 jim-p
		$conf .= "comp-lzo {$settings['compression']}\n";
1040 ef00af3c Phil Davis
	}
1041 d799787e Matthew Grooms
1042 ef00af3c Phil Davis
	if ($settings['passtos']) {
1043 d799787e Matthew Grooms
		$conf .= "passtos\n";
1044 ef00af3c Phil Davis
	}
1045 d799787e Matthew Grooms
1046 ef00af3c Phil Davis
	if ($settings['resolve_retry']) {
1047 d799787e Matthew Grooms
		$conf .= "resolv-retry infinite\n";
1048 3f1265e4 Chris Buechler
	} else if ($mode == 'client') {
1049 30640018 Chris Buechler
		$conf .= "resolv-retry infinite\n";
1050 ef00af3c Phil Davis
	}
1051 d799787e Matthew Grooms
1052
	if ($settings['dynamic_ip']) {
1053
		$conf .= "persist-remote-ip\n";
1054
		$conf .= "float\n";
1055 8dc3ef67 Scott Ullrich
	}
1056 afb07cf1 Scott Ullrich
1057 ef378560 jim-p
	// If the server is not a TLS server or it has a tunnel network CIDR less than a /30, skip this.
1058 4742e635 Chris Buechler
	if (in_array($settings['mode'], $openvpn_tls_server_modes) && (!empty($ip) && !empty($mask) && ($cidr < 30)) && $settings['dev_mode'] != "tap") {
1059 63646f4d jim-p
		if (empty($settings['topology'])) {
1060
			$settings['topology'] = "subnet";
1061
		}
1062
		$conf .= "topology {$settings['topology']}\n";
1063 ee55ce7d jim-p
	}
1064
1065 b9e9903d Dmitriy K.
	// New client features
1066
	if ($mode == "client") {
1067
		// Dont pull routes checkbox
1068
		if ($settings['route_no_pull']) {
1069
			$conf .= "route-nopull\n";
1070
		}
1071
1072
		// Dont add/remove routes checkbox
1073
		if ($settings['route_no_exec']) {
1074
			$conf .= "route-noexec\n";
1075
		}
1076
	}
1077
1078 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
1079
1080 a8f538a8 jim-p
	openvpn_create_dirs();
1081 938fc5b0 Ermal
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
1082 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
1083 938fc5b0 Ermal
	unset($conf);
1084 be00850b Phil Davis
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
1085
	file_put_contents($fpath, $interface);
1086 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
1087
	//chgrp($fpath, 'nobody');
1088 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
1089 be00850b Phil Davis
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
1090 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
1091
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
1092
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
1093 d799787e Matthew Grooms
}
1094
1095 fc05822b jim-p
function openvpn_restart($mode, $settings) {
1096 d799787e Matthew Grooms
	global $g, $config;
1097
1098
	$vpnid = $settings['vpnid'];
1099
	$mode_id = $mode.$vpnid;
1100
1101 76369bfc Matthew Grooms
	/* kill the process if running */
1102 705c8ec9 Matthew Grooms
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
1103 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
1104 705c8ec9 Matthew Grooms
1105 76369bfc Matthew Grooms
		/* read the pid file */
1106
		$pid = rtrim(file_get_contents($pfile));
1107
		unlink($pfile);
1108 705c8ec9 Matthew Grooms
1109 76369bfc Matthew Grooms
		/* send a term signal to the process */
1110
		posix_kill($pid, SIGTERM);
1111
1112 93ead355 Chris Buechler
		/* wait until the process exits, or timeout and kill it */
1113
		$i = 0;
1114 ef00af3c Phil Davis
		while (posix_kill($pid, 0)) {
1115 76369bfc Matthew Grooms
			usleep(250000);
1116 93ead355 Chris Buechler
			if ($i > 10) {
1117 e8c516a0 Phil Davis
				log_error(sprintf(gettext('OpenVPN ID %1$s PID %2$s still running, killing.'), $mode_id, $pid));
1118 93ead355 Chris Buechler
				posix_kill($pid, SIGKILL);
1119 02a2bffa Chris Buechler
				usleep(500000);
1120 93ead355 Chris Buechler
			}
1121
			$i++;
1122
		}
1123 76369bfc Matthew Grooms
	}
1124 d799787e Matthew Grooms
1125 ef00af3c Phil Davis
	if (isset($settings['disable'])) {
1126 d799787e Matthew Grooms
		return;
1127 ef00af3c Phil Davis
	}
1128 d799787e Matthew Grooms
1129 260f267e jim-p
	/* Do not start a client if we are a CARP backup on this vip! */
1130 ef00af3c Phil Davis
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) != "MASTER")) {
1131 9ea0cb90 jim-p
		return;
1132 ef00af3c Phil Davis
	}
1133 42bb1bee Renato Botelho
1134
	/* Check if client is bound to a gateway group */
1135 330ecea1 Shahid Sheikh
	$a_groups = return_gateway_groups_array();
1136
	if (is_array($a_groups[$settings['interface']])) {
1137 ef00af3c Phil Davis
		/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
1138
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) != "MASTER")) {
1139 330ecea1 Shahid Sheikh
			return;
1140 ef00af3c Phil Davis
		}
1141 330ecea1 Shahid Sheikh
	}
1142 9ea0cb90 jim-p
1143 705c8ec9 Matthew Grooms
	/* start the new process */
1144 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
1145 91c44185 jim-p
	openvpn_clear_route($mode, $settings);
1146 873c1701 Renato Botelho
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
1147 847cd48d Ermal
1148 ef00af3c Phil Davis
	if (!platform_booting()) {
1149 847cd48d Ermal
		send_event("filter reload");
1150 ef00af3c Phil Davis
	}
1151 afb07cf1 Scott Ullrich
}
1152
1153 dc408939 Matthew Grooms
function openvpn_delete($mode, & $settings) {
1154 d799787e Matthew Grooms
	global $g, $config;
1155
1156
	$vpnid = $settings['vpnid'];
1157
	$mode_id = $mode.$vpnid;
1158
1159 ef00af3c Phil Davis
	if (isset($settings['dev_mode'])) {
1160 da601f8e PiBa-NL
		$tunname = "{$settings['dev_mode']}{$vpnid}";
1161 ef00af3c Phil Davis
	} else {
1162
		/* defaults to tun */
1163 da601f8e PiBa-NL
		$tunname = "tun{$vpnid}";
1164
	}
1165
1166 ef00af3c Phil Davis
	if ($mode == "server") {
1167 095a95ae Matthew Grooms
		$devname = "ovpns{$vpnid}";
1168 ef00af3c Phil Davis
	} else {
1169 095a95ae Matthew Grooms
		$devname = "ovpnc{$vpnid}";
1170 ef00af3c Phil Davis
	}
1171 dc408939 Matthew Grooms
1172 76369bfc Matthew Grooms
	/* kill the process if running */
1173 dc408939 Matthew Grooms
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
1174 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
1175 dc408939 Matthew Grooms
1176 76369bfc Matthew Grooms
		/* read the pid file */
1177
		$pid = trim(file_get_contents($pfile));
1178
		unlink($pfile);
1179
1180
		/* send a term signal to the process */
1181
		posix_kill($pid, SIGTERM);
1182
	}
1183 705c8ec9 Matthew Grooms
1184 095a95ae Matthew Grooms
	/* remove the device from the openvpn group */
1185 873c1701 Renato Botelho
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
1186 095a95ae Matthew Grooms
1187 dc408939 Matthew Grooms
	/* restore the original adapter name */
1188 873c1701 Renato Botelho
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
1189 dc408939 Matthew Grooms
1190
	/* remove the configuration files */
1191 8bb47a46 Ermal
	@array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
1192 d799787e Matthew Grooms
}
1193 afb07cf1 Scott Ullrich
1194 dc408939 Matthew Grooms
function openvpn_resync_csc(& $settings) {
1195 154b0f80 jim-p
	global $g, $config, $openvpn_tls_server_modes;
1196 8dc3ef67 Scott Ullrich
1197 154b0f80 jim-p
	$csc_base_path = "{$g['varetc_path']}/openvpn-csc";
1198 8dc3ef67 Scott Ullrich
1199 a1cab2c7 Ermal
	if (isset($settings['disable'])) {
1200 4e5e7540 jim-p
		openvpn_delete_csc($settings);
1201 c876662c Scott Ullrich
		return;
1202
	}
1203 a8f538a8 jim-p
	openvpn_create_dirs();
1204 d799787e Matthew Grooms
1205 154b0f80 jim-p
	if (empty($settings['server_list'])) {
1206
		$csc_server_list = array();
1207
	} else {
1208
		$csc_server_list = explode(",", $settings['server_list']);
1209
	}
1210
1211 8dc3ef67 Scott Ullrich
	$conf = '';
1212 ef00af3c Phil Davis
	if ($settings['block']) {
1213 d799787e Matthew Grooms
		$conf .= "disable\n";
1214 ef00af3c Phil Davis
	}
1215 d799787e Matthew Grooms
1216 ef00af3c Phil Davis
	if ($settings['push_reset']) {
1217 d799787e Matthew Grooms
		$conf .= "push-reset\n";
1218 ef00af3c Phil Davis
	}
1219 d799787e Matthew Grooms
1220 5c427ce7 jim-p
	if ($settings['local_network']) {
1221
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
1222
	}
1223
	if ($settings['local_networkv6']) {
1224
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
1225
	}
1226
1227
	// Add a remote network iroute if set
1228
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
1229
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
1230
	}
1231
	// Add a remote network iroute if set
1232
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
1233
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
1234
	}
1235
1236 d799787e Matthew Grooms
	openvpn_add_dhcpopts($settings, $conf);
1237 8dc3ef67 Scott Ullrich
1238 ef00af3c Phil Davis
	if ($settings['gwredir']) {
1239 d799787e Matthew Grooms
		$conf .= "push \"redirect-gateway def1\"\n";
1240 ef00af3c Phil Davis
	}
1241 6d031071 Martin Fuchs
1242 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
1243 154b0f80 jim-p
	/* Loop through servers, find which ones can use this CSC */
1244
	if (is_array($config['openvpn']['openvpn-server'])) {
1245
		foreach ($config['openvpn']['openvpn-server'] as $serversettings) {
1246
			if (isset($serversettings['disable'])) {
1247
				continue;
1248
			}
1249
			if (in_array($serversettings['mode'], $openvpn_tls_server_modes)) {
1250
				if ($serversettings['vpnid'] && (empty($csc_server_list) || in_array($serversettings['vpnid'], $csc_server_list))) {
1251
					$csc_path = "{$csc_base_path}/server{$serversettings['vpnid']}/" . basename($settings['common_name']);
1252
					$csc_conf = $conf;
1253
1254 cd8f2f2b jim-p
					if (!empty($serversettings['tunnel_network']) && !empty($settings['tunnel_network'])) {
1255 c228156f jim-p
						list($ip, $mask) = explode('/', trim($settings['tunnel_network']));
1256 154b0f80 jim-p
						if (($serversettings['dev_mode'] == 'tap') || ($serversettings['topology'] == "subnet")) {
1257
							$csc_conf .= "ifconfig-push {$ip} " . gen_subnet_mask($mask) . "\n";
1258
						} else {
1259
							/* Because this is being pushed, the order from the client's point of view. */
1260 493e6807 stilez
							$baselong = gen_subnetv4($ip, $mask);
1261
							$serverip = ip_after($baselong, 1);
1262
							$clientip = ip_after($baselong, 2);
1263 154b0f80 jim-p
							$csc_conf .= "ifconfig-push {$clientip} {$serverip}\n";
1264
						}
1265
					}
1266
					file_put_contents($csc_path, $csc_conf);
1267
					chown($csc_path, 'nobody');
1268
					chgrp($csc_path, 'nobody');
1269
				}
1270
			}
1271
		}
1272
	}
1273 d799787e Matthew Grooms
}
1274 8dc3ef67 Scott Ullrich
1275 dc408939 Matthew Grooms
function openvpn_delete_csc(& $settings) {
1276 154b0f80 jim-p
	global $g, $config, $openvpn_tls_server_modes;
1277
	$csc_base_path = "{$g['varetc_path']}/openvpn-csc";
1278
	if (empty($settings['server_list'])) {
1279
		$csc_server_list = array();
1280
	} else {
1281
		$csc_server_list = explode(",", $settings['server_list']);
1282
	}
1283 3c2e5528 Scott Ullrich
1284 154b0f80 jim-p
	/* Loop through servers, find which ones used this CSC */
1285
	if (is_array($config['openvpn']['openvpn-server'])) {
1286
		foreach ($config['openvpn']['openvpn-server'] as $serversettings) {
1287
			if (isset($serversettings['disable'])) {
1288
				continue;
1289
			}
1290
			if (in_array($serversettings['mode'], $openvpn_tls_server_modes)) {
1291
				if ($serversettings['vpnid'] && (empty($csc_server_list) || in_array($serversettings['vpnid'], $csc_server_list))) {
1292
					$csc_path = "{$csc_base_path}/server{$serversettings['vpnid']}/" . basename($settings['common_name']);
1293
					unlink_if_exists($csc_path);
1294
				}
1295
			}
1296
		}
1297
	}
1298 267ab13f Ermal Luçi
}
1299 afb07cf1 Scott Ullrich
1300 24012690 Scott Ullrich
// Resync the configuration and restart the VPN
1301 fc05822b jim-p
function openvpn_resync($mode, $settings) {
1302 dc408939 Matthew Grooms
	openvpn_reconfigure($mode, $settings);
1303
	openvpn_restart($mode, $settings);
1304 afb07cf1 Scott Ullrich
}
1305
1306 add2e3f7 Scott Ullrich
// Resync and restart all VPNs
1307 c7f60193 Ermal
function openvpn_resync_all($interface = "") {
1308 d799787e Matthew Grooms
	global $g, $config;
1309 267ab13f Ermal Luçi
1310 a8f538a8 jim-p
	openvpn_create_dirs();
1311 3cb54b54 Matthew Grooms
1312 ef00af3c Phil Davis
	if (!is_array($config['openvpn'])) {
1313 34bc1324 Matthew Grooms
		$config['openvpn'] = array();
1314 ef00af3c Phil Davis
	}
1315 34bc1324 Matthew Grooms
1316 15b414e6 Matthew Grooms
/*
1317 34bc1324 Matthew Grooms
	if (!$config['openvpn']['dh-parameters']) {
1318
		echo "Configuring OpenVPN Parameters ...\n";
1319 035e4289 Matthew Grooms
		$dh_parameters = openvpn_create_dhparams(1024);
1320 34bc1324 Matthew Grooms
		$dh_parameters = base64_encode($dh_parameters);
1321
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1322 c67dd94e Bill Marquette
		write_config("OpenVPN DH parameters");
1323 34bc1324 Matthew Grooms
	}
1324
1325
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1326
	if (!file_exists($path_ovdh)) {
1327
		$dh_parameters = $config['openvpn']['dh-parameters'];
1328
		$dh_parameters = base64_decode($dh_parameters);
1329
		file_put_contents($path_ovdh, $dh_parameters);
1330
	}
1331 15b414e6 Matthew Grooms
*/
1332 ef00af3c Phil Davis
	if ($interface <> "") {
1333 e8c516a0 Phil Davis
		log_error(sprintf(gettext("Resyncing OpenVPN instances for interface %s."), convert_friendly_interface_to_friendly_descr($interface)));
1334 ef00af3c Phil Davis
	} else {
1335 e8c516a0 Phil Davis
		log_error(gettext("Resyncing OpenVPN instances."));
1336 ef00af3c Phil Davis
	}
1337 34bc1324 Matthew Grooms
1338 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-server'])) {
1339
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1340 ef00af3c Phil Davis
			if ($interface <> "" && $interface != $settings['interface']) {
1341 c7f60193 Ermal
				continue;
1342 ef00af3c Phil Davis
			}
1343 dc408939 Matthew Grooms
			openvpn_resync('server', $settings);
1344 c7f60193 Ermal
		}
1345
	}
1346 5b237745 Scott Ullrich
1347 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-client'])) {
1348
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1349 ef00af3c Phil Davis
			if ($interface <> "" && $interface != $settings['interface']) {
1350 c7f60193 Ermal
				continue;
1351 ef00af3c Phil Davis
			}
1352 dc408939 Matthew Grooms
			openvpn_resync('client', $settings);
1353 c7f60193 Ermal
		}
1354
	}
1355 afb07cf1 Scott Ullrich
1356 ef00af3c Phil Davis
	if (is_array($config['openvpn']['openvpn-csc'])) {
1357
		foreach ($config['openvpn']['openvpn-csc'] as & $settings) {
1358 dc408939 Matthew Grooms
			openvpn_resync_csc($settings);
1359 ef00af3c Phil Davis
		}
1360
	}
1361 afb07cf1 Scott Ullrich
1362 5b237745 Scott Ullrich
}
1363 702a4702 Scott Ullrich
1364 99cc103b Phil Davis
// Resync and restart all VPNs using a gateway group.
1365
function openvpn_resync_gwgroup($gwgroupname = "") {
1366
	global $g, $config;
1367
1368
	if ($gwgroupname <> "") {
1369
		if (is_array($config['openvpn']['openvpn-server'])) {
1370
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1371
				if ($gwgroupname == $settings['interface']) {
1372 e8c516a0 Phil Davis
					log_error(sprintf(gettext('Resyncing OpenVPN for gateway group %1$s server %2$s.'), $gwgroupname, $settings["description"]));
1373 99cc103b Phil Davis
					openvpn_resync('server', $settings);
1374
				}
1375
			}
1376
		}
1377
1378
		if (is_array($config['openvpn']['openvpn-client'])) {
1379
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1380
				if ($gwgroupname == $settings['interface']) {
1381 e8c516a0 Phil Davis
					log_error(sprintf(gettext('Resyncing OpenVPN for gateway group %1$s client %2$s.'), $gwgroupname, $settings["description"]));
1382 99cc103b Phil Davis
					openvpn_resync('client', $settings);
1383
				}
1384
			}
1385
		}
1386
1387
		// Note: no need to resysnc Client Specific (csc) here, as changes to the OpenVPN real interface do not effect these.
1388
1389 ef00af3c Phil Davis
	} else {
1390 e8c516a0 Phil Davis
		log_error(gettext("openvpn_resync_gwgroup called with null gwgroup parameter."));
1391 ef00af3c Phil Davis
	}
1392 99cc103b Phil Davis
}
1393
1394 453d9c96 jim-p
function openvpn_get_active_servers($type="multipoint") {
1395 71ca2cb2 Ermal
	global $config, $g;
1396
1397 53663f57 jim-p
	$servers = array();
1398
	if (is_array($config['openvpn']['openvpn-server'])) {
1399
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1400 ef00af3c Phil Davis
			if (empty($settings) || isset($settings['disable'])) {
1401 6b2dcac5 Ermal
				continue;
1402 ef00af3c Phil Davis
			}
1403 6b2dcac5 Ermal
1404 53663f57 jim-p
			$prot = $settings['protocol'];
1405
			$port = $settings['local_port'];
1406 42bb1bee Renato Botelho
1407 53663f57 jim-p
			$server = array();
1408 95305736 jim-p
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1409 41be629f jim-p
			$server['mode'] = $settings['mode'];
1410 ef00af3c Phil Davis
			if ($settings['description']) {
1411 53663f57 jim-p
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1412 ef00af3c Phil Davis
			} else {
1413 53663f57 jim-p
				$server['name'] = "Server {$prot}:{$port}";
1414 ef00af3c Phil Davis
			}
1415 53663f57 jim-p
			$server['conns'] = array();
1416 2eaa97b9 jim-p
			$server['vpnid'] = $settings['vpnid'];
1417
			$server['mgmt'] = "server{$server['vpnid']}";
1418
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1419 c228156f jim-p
			list($tn, $sm) = explode('/', trim($settings['tunnel_network']));
1420 453d9c96 jim-p
1421 ef00af3c Phil Davis
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30)) && ($type == "p2p")) {
1422 95305736 jim-p
				$servers[] = openvpn_get_client_status($server, $socket);
1423 ef00af3c Phil Davis
			} elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30)) {
1424 95305736 jim-p
				$servers[] = openvpn_get_server_status($server, $socket);
1425 ef00af3c Phil Davis
			}
1426 95305736 jim-p
		}
1427
	}
1428
	return $servers;
1429
}
1430 b0140675 Ermal
1431 95305736 jim-p
function openvpn_get_server_status($server, $socket) {
1432 247c417f Sjon Hortensius
	$errval = null;
1433
	$errstr = null;
1434 95305736 jim-p
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1435
	if ($fp) {
1436
		stream_set_timeout($fp, 1);
1437
1438
		/* send our status request */
1439
		fputs($fp, "status 2\n");
1440
1441
		/* recv all response lines */
1442
		while (!feof($fp)) {
1443
1444
			/* read the next line */
1445
			$line = fgets($fp, 1024);
1446
1447
			$info = stream_get_meta_data($fp);
1448 ef00af3c Phil Davis
			if ($info['timed_out']) {
1449 95305736 jim-p
				break;
1450 ef00af3c Phil Davis
			}
1451 95305736 jim-p
1452
			/* parse header list line */
1453 ef00af3c Phil Davis
			if (strstr($line, "HEADER")) {
1454 95305736 jim-p
				continue;
1455 ef00af3c Phil Davis
			}
1456 95305736 jim-p
1457
			/* parse end of output line */
1458 ef00af3c Phil Davis
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1459 95305736 jim-p
				break;
1460 ef00af3c Phil Davis
			}
1461 95305736 jim-p
1462
			/* parse client list line */
1463
			if (strstr($line, "CLIENT_LIST")) {
1464
				$list = explode(",", $line);
1465 53663f57 jim-p
				$conn = array();
1466 95305736 jim-p
				$conn['common_name'] = $list[1];
1467
				$conn['remote_host'] = $list[2];
1468
				$conn['virtual_addr'] = $list[3];
1469
				$conn['bytes_recv'] = $list[4];
1470
				$conn['bytes_sent'] = $list[5];
1471
				$conn['connect_time'] = $list[6];
1472 53663f57 jim-p
				$server['conns'][] = $conn;
1473
			}
1474 ec970b50 jim-p
			/* parse routing table lines */
1475
			if (strstr($line, "ROUTING_TABLE")) {
1476
				$list = explode(",", $line);
1477
				$conn = array();
1478
				$conn['virtual_addr'] = $list[1];
1479
				$conn['common_name'] = $list[2];
1480
				$conn['remote_host'] = $list[3];
1481
				$conn['last_time'] = $list[4];
1482
				$server['routes'][] = $conn;
1483
			}
1484 53663f57 jim-p
		}
1485 95305736 jim-p
1486
		/* cleanup */
1487
		fclose($fp);
1488
	} else {
1489
		$conn = array();
1490
		$conn['common_name'] = "[error]";
1491 e8c516a0 Phil Davis
		$conn['remote_host'] = gettext("Unable to contact daemon");
1492
		$conn['virtual_addr'] = gettext("Service not running?");
1493 95305736 jim-p
		$conn['bytes_recv'] = 0;
1494
		$conn['bytes_sent'] = 0;
1495
		$conn['connect_time'] = 0;
1496
		$server['conns'][] = $conn;
1497 53663f57 jim-p
	}
1498 95305736 jim-p
	return $server;
1499 53663f57 jim-p
}
1500
1501
function openvpn_get_active_clients() {
1502 71ca2cb2 Ermal
	global $config, $g;
1503
1504 53663f57 jim-p
	$clients = array();
1505
	if (is_array($config['openvpn']['openvpn-client'])) {
1506
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1507 42bb1bee Renato Botelho
1508 ef00af3c Phil Davis
			if (empty($settings) || isset($settings['disable'])) {
1509 6b2dcac5 Ermal
				continue;
1510 ef00af3c Phil Davis
			}
1511 6b2dcac5 Ermal
1512 53663f57 jim-p
			$prot = $settings['protocol'];
1513 95305736 jim-p
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1514 42bb1bee Renato Botelho
1515 53663f57 jim-p
			$client = array();
1516
			$client['port'] = $settings['local_port'];
1517 ef00af3c Phil Davis
			if ($settings['description']) {
1518 95305736 jim-p
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1519 ef00af3c Phil Davis
			} else {
1520 95305736 jim-p
				$client['name'] = "Client {$prot}{$port}";
1521 ef00af3c Phil Davis
			}
1522 42bb1bee Renato Botelho
1523 2eaa97b9 jim-p
			$client['vpnid'] = $settings['vpnid'];
1524
			$client['mgmt'] = "client{$client['vpnid']}";
1525
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1526 53663f57 jim-p
			$client['status']="down";
1527 95305736 jim-p
1528
			$clients[] = openvpn_get_client_status($client, $socket);
1529
		}
1530
	}
1531
	return $clients;
1532
}
1533
1534
function openvpn_get_client_status($client, $socket) {
1535 247c417f Sjon Hortensius
	$errval = null;
1536
	$errstr = null;
1537 95305736 jim-p
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1538
	if ($fp) {
1539
		stream_set_timeout($fp, 1);
1540
		/* send our status request */
1541
		fputs($fp, "state 1\n");
1542
1543
		/* recv all response lines */
1544
		while (!feof($fp)) {
1545
			/* read the next line */
1546
			$line = fgets($fp, 1024);
1547
1548
			$info = stream_get_meta_data($fp);
1549 ef00af3c Phil Davis
			if ($info['timed_out']) {
1550 95305736 jim-p
				break;
1551 ef00af3c Phil Davis
			}
1552 95305736 jim-p
1553
			/* Get the client state */
1554 4de8f7ba Phil Davis
			if (strstr($line, "CONNECTED")) {
1555
				$client['status'] = "up";
1556 95305736 jim-p
				$list = explode(",", $line);
1557
1558 4de8f7ba Phil Davis
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1559
				$client['virtual_addr'] = $list[3];
1560 95305736 jim-p
				$client['remote_host'] = $list[4];
1561
			}
1562 4de8f7ba Phil Davis
			if (strstr($line, "CONNECTING")) {
1563
				$client['status'] = "connecting";
1564 453d9c96 jim-p
			}
1565 4de8f7ba Phil Davis
			if (strstr($line, "ASSIGN_IP")) {
1566
				$client['status'] = "waiting";
1567 453d9c96 jim-p
				$list = explode(",", $line);
1568
1569 4de8f7ba Phil Davis
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1570
				$client['virtual_addr'] = $list[3];
1571 453d9c96 jim-p
			}
1572 4de8f7ba Phil Davis
			if (strstr($line, "RECONNECTING")) {
1573
				$client['status'] = "reconnecting";
1574 453d9c96 jim-p
				$list = explode(",", $line);
1575
1576 4de8f7ba Phil Davis
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1577 453d9c96 jim-p
				$client['status'] .= "; " . $list[2];
1578
			}
1579 95305736 jim-p
			/* parse end of output line */
1580 ef00af3c Phil Davis
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1581 95305736 jim-p
				break;
1582 ef00af3c Phil Davis
			}
1583 95305736 jim-p
		}
1584
1585
		/* If up, get read/write stats */
1586
		if (strcmp($client['status'], "up") == 0) {
1587
			fputs($fp, "status 2\n");
1588
			/* recv all response lines */
1589
			while (!feof($fp)) {
1590
				/* read the next line */
1591
				$line = fgets($fp, 1024);
1592
1593
				$info = stream_get_meta_data($fp);
1594 ef00af3c Phil Davis
				if ($info['timed_out']) {
1595 95305736 jim-p
					break;
1596 ef00af3c Phil Davis
				}
1597 95305736 jim-p
1598 4de8f7ba Phil Davis
				if (strstr($line, "TCP/UDP read bytes")) {
1599 95305736 jim-p
					$list = explode(",", $line);
1600
					$client['bytes_recv'] = $list[1];
1601 53663f57 jim-p
				}
1602 95305736 jim-p
1603 4de8f7ba Phil Davis
				if (strstr($line, "TCP/UDP write bytes")) {
1604 95305736 jim-p
					$list = explode(",", $line);
1605
					$client['bytes_sent'] = $list[1];
1606 53663f57 jim-p
				}
1607 95305736 jim-p
1608
				/* parse end of output line */
1609 ef00af3c Phil Davis
				if (strstr($line, "END")) {
1610 95305736 jim-p
					break;
1611 ef00af3c Phil Davis
				}
1612 53663f57 jim-p
			}
1613
		}
1614 95305736 jim-p
1615
		fclose($fp);
1616
1617
	} else {
1618 e8c516a0 Phil Davis
		$client['remote_host'] = gettext("Unable to contact daemon");
1619
		$client['virtual_addr'] = gettext("Service not running?");
1620 95305736 jim-p
		$client['bytes_recv'] = 0;
1621
		$client['bytes_sent'] = 0;
1622
		$client['connect_time'] = 0;
1623 53663f57 jim-p
	}
1624 95305736 jim-p
	return $client;
1625 53663f57 jim-p
}
1626 8e022a76 jim-p
1627 61fce4a6 Phil Davis
function openvpn_kill_client($port, $remipp) {
1628
	global $g;
1629
1630
	//$tcpsrv = "tcp://127.0.0.1:{$port}";
1631
	$tcpsrv = "unix://{$g['varetc_path']}/openvpn/{$port}.sock";
1632
	$errval = null;
1633
	$errstr = null;
1634
1635
	/* open a tcp connection to the management port of each server */
1636
	$fp = @stream_socket_client($tcpsrv, $errval, $errstr, 1);
1637
	$killed = -1;
1638
	if ($fp) {
1639
		stream_set_timeout($fp, 1);
1640
		fputs($fp, "kill {$remipp}\n");
1641
		while (!feof($fp)) {
1642
			$line = fgets($fp, 1024);
1643
1644
			$info = stream_get_meta_data($fp);
1645
			if ($info['timed_out']) {
1646
				break;
1647
			}
1648
1649
			/* parse header list line */
1650
			if (strpos($line, "INFO:") !== false) {
1651
				continue;
1652
			}
1653
			if (strpos($line, "SUCCESS") !== false) {
1654
				$killed = 0;
1655
			}
1656
			break;
1657
		}
1658
		fclose($fp);
1659
	}
1660
	return $killed;
1661
}
1662
1663 8e022a76 jim-p
function openvpn_refresh_crls() {
1664
	global $g, $config;
1665
1666 a8f538a8 jim-p
	openvpn_create_dirs();
1667 8e022a76 jim-p
1668
	if (is_array($config['openvpn']['openvpn-server'])) {
1669
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1670 ef00af3c Phil Davis
			if (empty($settings)) {
1671 8e022a76 jim-p
				continue;
1672 ef00af3c Phil Davis
			}
1673
			if (isset($settings['disable'])) {
1674 8e022a76 jim-p
				continue;
1675 ef00af3c Phil Davis
			}
1676 8e022a76 jim-p
			// Write the settings for the keys
1677 ef00af3c Phil Davis
			switch ($settings['mode']) {
1678 8e022a76 jim-p
				case 'p2p_tls':
1679
				case 'server_tls':
1680
				case 'server_tls_user':
1681
				case 'server_user':
1682
					if (!empty($settings['crlref'])) {
1683
						$crl = lookup_crl($settings['crlref']);
1684 728003c8 jim-p
						crl_update($crl);
1685 8e022a76 jim-p
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1686
						file_put_contents($fpath, base64_decode($crl['text']));
1687
						@chmod($fpath, 0644);
1688
					}
1689
					break;
1690
			}
1691
		}
1692
	}
1693
}
1694
1695 a8f538a8 jim-p
function openvpn_create_dirs() {
1696 154b0f80 jim-p
	global $g, $config, $openvpn_tls_server_modes;
1697 ef00af3c Phil Davis
	if (!is_dir("{$g['varetc_path']}/openvpn")) {
1698 a8f538a8 jim-p
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1699 ef00af3c Phil Davis
	}
1700
	if (!is_dir("{$g['varetc_path']}/openvpn-csc")) {
1701 a8f538a8 jim-p
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1702 ef00af3c Phil Davis
	}
1703 154b0f80 jim-p
1704
	/* Check for enabled servers and create server-specific CSC dirs */
1705
	if (is_array($config['openvpn']['openvpn-server'])) {
1706
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1707
			if (isset($settings['disable'])) {
1708
				continue;
1709
			}
1710
			if (in_array($settings['mode'], $openvpn_tls_server_modes)) {
1711
				if ($settings['vpnid']) {
1712
					safe_mkdir("{$g['varetc_path']}/openvpn-csc/server{$settings['vpnid']}");
1713
				}
1714
			}
1715
		}
1716
	}
1717 a8f538a8 jim-p
}
1718
1719 30c8a290 Renato Botelho
function openvpn_get_interface_ip($ip, $cidr) {
1720
	$subnet = gen_subnetv4($ip, $cidr);
1721
	$ip1 = ip_after($subnet);
1722
	$ip2 = ip_after($ip1);
1723 91c44185 jim-p
	return array($ip1, $ip2);
1724
}
1725
1726
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1727
	$basev6 = gen_subnetv6($ipv6, $prefix);
1728
	// Is there a better way to do this math?
1729
	$ipv6_arr = explode(':', $basev6);
1730
	$last = hexdec(array_pop($ipv6_arr));
1731 fe9c774d Phil Davis
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1732
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1733 91c44185 jim-p
	return array($ipv6_1, $ipv6_2);
1734
}
1735
1736
function openvpn_clear_route($mode, $settings) {
1737 ef00af3c Phil Davis
	if (empty($settings['tunnel_network'])) {
1738 91c44185 jim-p
		return;
1739 ef00af3c Phil Davis
	}
1740 c228156f jim-p
	list($ip, $cidr) = explode('/', trim($settings['tunnel_network']));
1741 91c44185 jim-p
	$mask = gen_subnet_mask($cidr);
1742 6ca938cf jim-p
	$clear_route = false;
1743
1744 ef00af3c Phil Davis
	switch ($settings['mode']) {
1745 6ca938cf jim-p
		case 'shared_key':
1746
			$clear_route = true;
1747
			break;
1748 91c44185 jim-p
		case 'p2p_tls':
1749
		case 'p2p_shared_key':
1750 ef00af3c Phil Davis
			if ($cidr == 30) {
1751 6ca938cf jim-p
				$clear_route = true;
1752 ef00af3c Phil Davis
			}
1753 91c44185 jim-p
			break;
1754
	}
1755 6ca938cf jim-p
1756 6d0b9fe9 jim-p
	if ($clear_route && !empty($ip) && !empty($mask)) {
1757 30c8a290 Renato Botelho
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
1758 6ca938cf jim-p
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1759 615d7f0a Ermal
		/* XXX: Family for route? */
1760 6ca938cf jim-p
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1761
	}
1762 91c44185 jim-p
}
1763
1764 5c427ce7 jim-p
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1765 a28d40cb jim-p
	$routes = "";
1766 ef00af3c Phil Davis
	if (empty($value)) {
1767 a28d40cb jim-p
		return "";
1768 ef00af3c Phil Davis
	}
1769 a28d40cb jim-p
	$networks = explode(',', $value);
1770
1771
	foreach ($networks as $network) {
1772 ef00af3c Phil Davis
		if ($ipproto == "ipv4") {
1773 5c427ce7 jim-p
			$route = openvpn_gen_route_ipv4($network, $iroute);
1774 ef00af3c Phil Davis
		} else {
1775 5c427ce7 jim-p
			$route = openvpn_gen_route_ipv6($network, $iroute);
1776 ef00af3c Phil Davis
		}
1777 a28d40cb jim-p
1778 ef00af3c Phil Davis
		if ($push) {
1779 a28d40cb jim-p
			$routes .= "push \"{$route}\"\n";
1780 ef00af3c Phil Davis
		} else {
1781 a28d40cb jim-p
			$routes .= "{$route}\n";
1782 ef00af3c Phil Davis
		}
1783 a28d40cb jim-p
	}
1784
	return $routes;
1785
}
1786
1787 5c427ce7 jim-p
function openvpn_gen_route_ipv4($network, $iroute = false) {
1788
	$i = ($iroute) ? "i" : "";
1789 a28d40cb jim-p
	list($ip, $mask) = explode('/', trim($network));
1790
	$mask = gen_subnet_mask($mask);
1791 5c427ce7 jim-p
	return "{$i}route $ip $mask";
1792 a28d40cb jim-p
}
1793
1794 5c427ce7 jim-p
function openvpn_gen_route_ipv6($network, $iroute = false) {
1795
	$i = ($iroute) ? "i" : "";
1796 a28d40cb jim-p
	list($ipv6, $prefix) = explode('/', trim($network));
1797 ef00af3c Phil Davis
	if (empty($prefix)) {
1798 a28d40cb jim-p
		$prefix = "128";
1799 ef00af3c Phil Davis
	}
1800 5c427ce7 jim-p
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1801 a28d40cb jim-p
}
1802
1803 699125b1 jim-p
function openvpn_get_settings($mode, $vpnid) {
1804
	global $config;
1805
1806
	if (is_array($config['openvpn']['openvpn-server'])) {
1807
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1808 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
1809 699125b1 jim-p
				continue;
1810 ef00af3c Phil Davis
			}
1811 699125b1 jim-p
1812 ef00af3c Phil Davis
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1813 699125b1 jim-p
				return $settings;
1814 ef00af3c Phil Davis
			}
1815 699125b1 jim-p
		}
1816
	}
1817
1818
	if (is_array($config['openvpn']['openvpn-client'])) {
1819
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1820 ef00af3c Phil Davis
			if (isset($settings['disable'])) {
1821 699125b1 jim-p
				continue;
1822 ef00af3c Phil Davis
			}
1823 699125b1 jim-p
1824 ef00af3c Phil Davis
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1825 699125b1 jim-p
				return $settings;
1826 ef00af3c Phil Davis
			}
1827 699125b1 jim-p
		}
1828
	}
1829
1830
	return array();
1831
}
1832
1833
function openvpn_restart_by_vpnid($mode, $vpnid) {
1834
	$settings = openvpn_get_settings($mode, $vpnid);
1835
	openvpn_restart($mode, $settings);
1836
}
1837
1838 756720e2 Pierre POMES
?>