Project

General

Profile

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