Project

General

Profile

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