Project

General

Profile

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