Project

General

Profile

Download (41.1 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2 b1ad443d Scott Ullrich
/*
3 9a6d6728 Ermal
	openvpn.inc part of pfSense
4 33ab8aa5 Scott Ullrich
	
5
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
6
	All rights reserved.
7
	
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 523855b0 Scott Ullrich
	
41
	DISABLE_PHP_LINT_CHECKING
42
	
43 dae707f5 jim-p
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/local/bin/openssl	/sbin/ifconfig
44 523855b0 Scott Ullrich
	pfSense_MODULE:	openvpn
45 b1ad443d Scott Ullrich
46 523855b0 Scott Ullrich
*/
47 8dc3ef67 Scott Ullrich
require_once('config.inc');
48 32a7a1f6 Ermal Lu?i
require_once("certs.inc");
49 36df0acc Scott Ullrich
require_once('pfsense-utils.inc');
50 c61e4626 Ermal Lu?i
require_once("auth.inc");
51 8dc3ef67 Scott Ullrich
52 f2291484 jim-p
global $openvpn_prots;
53 6714bbdc jim-p
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
54 702a4702 Scott Ullrich
55 f2291484 jim-p
global $openvpn_dev_mode;
56 691fbf14 Ermal Lu?i
$openvpn_dev_mode = array("tun", "tap");
57
58 3c11bd3c Matthew Grooms
/* 
59
 * The User Auth mode below is disabled because
60
 * OpenVPN erroneously requires that we provide
61
 * a CA configuration parameter. In this mode,
62
 * clients don't send a certificate so there is
63
 * no need for a CA. If we require that admins
64
 * provide one in the pfSense UI due to a bogus
65
 * requirement imposed by OpenVPN, it could be
66
 * considered very confusing ( I know I was ).
67
 *
68
 * -mgrooms
69
 */
70
71 f2291484 jim-p
global $openvpn_dh_lengths;
72 fe787fc7 Matthew Grooms
$openvpn_dh_lengths = array(
73
	1024, 2048, 4096 );
74
75 f2291484 jim-p
global $openvpn_cert_depths;
76 98963f27 jim-p
$openvpn_cert_depths = array(
77
	1 => "One (Client+Server)",
78
	2 => "Two (Client+Intermediate+Server)",
79
	3 => "Three (Client+2xIntermediate+Server)",
80
	4 => "Four (Client+3xIntermediate+Server)",
81
	5 => "Five (Client+4xIntermediate+Server)"
82
);
83
84 f2291484 jim-p
global $openvpn_server_modes;
85 3c11bd3c Matthew Grooms
$openvpn_server_modes = array(
86 4aa02281 Carlos Eduardo Ramos
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
87
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
88
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
89
	'server_user' => gettext("Remote Access ( User Auth )"),
90
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
91 3c11bd3c Matthew Grooms
92 f2291484 jim-p
global $openvpn_client_modes;
93 3c11bd3c Matthew Grooms
$openvpn_client_modes = array(
94 4aa02281 Carlos Eduardo Ramos
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
95
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )") );
96 3c11bd3c Matthew Grooms
97 edba1982 jim-p
global $openvpn_compression_modes;
98
$openvpn_compression_modes = array(
99 9ed52990 jim-p
	'' =>	gettext("No Preference"),
100 edba1982 jim-p
	'no' =>		gettext("Disabled - No Compression"),
101
	'adaptive' =>	gettext("Enabled with Adaptive Compression"),
102
	'yes' =>	gettext("Enabled without Adaptive Compression"));
103
104 3c11bd3c Matthew Grooms
function openvpn_create_key() {
105
106
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
107
	if (!$fp)
108
		return false;
109
110
	$rslt = stream_get_contents($fp);
111
	pclose($fp);
112
113
	return $rslt;
114
}
115 d799787e Matthew Grooms
116 8411b218 Matthew Grooms
function openvpn_create_dhparams($bits) {
117 34bc1324 Matthew Grooms
118 dae707f5 jim-p
	$fp = popen("/usr/local/bin/openssl dhparam {$bits} 2>/dev/null", "r");
119 34bc1324 Matthew Grooms
	if (!$fp)
120
		return false;
121
122
	$rslt = stream_get_contents($fp);
123
	pclose($fp);
124
125
	return $rslt;
126
}
127
128 d799787e Matthew Grooms
function openvpn_vpnid_used($vpnid) {
129 8be2d6d3 Ermal Luçi
	global $config;
130
131 d799787e Matthew Grooms
	if (is_array($config['openvpn']['openvpn-server']))
132 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
133 f432e364 Matthew Grooms
			if ($vpnid == $settings['vpnid'])
134 d799787e Matthew Grooms
				return true;
135
136
	if (is_array($config['openvpn']['openvpn-client']))
137 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
138 f432e364 Matthew Grooms
			if ($vpnid == $settings['vpnid'])
139 d799787e Matthew Grooms
				return true;
140 04a6e900 Ermal Luçi
141 d799787e Matthew Grooms
	return false;
142
}
143
144
function openvpn_vpnid_next() {
145
146
	$vpnid = 1;
147
	while(openvpn_vpnid_used($vpnid))
148
		$vpnid++;
149
150
	return $vpnid;
151
}
152
153 49b76122 Renato Botelho
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
154 f432e364 Matthew Grooms
	global $config;
155
156 49b76122 Renato Botelho
	if (is_array($config['openvpn']['openvpn-server'])) {
157
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
158
			if (isset($settings['disable']))
159
				continue;
160
161
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
162
				continue;
163
164
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
165
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
166 f432e364 Matthew Grooms
				return $settings['vpnid'];
167 49b76122 Renato Botelho
		}
168
	}
169 f432e364 Matthew Grooms
170 49b76122 Renato Botelho
	if (is_array($config['openvpn']['openvpn-client'])) {
171
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
172
			if (isset($settings['disable']))
173
				continue;
174
175
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid'])
176
				continue;
177
178
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
179
				($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any"))
180 f432e364 Matthew Grooms
				return $settings['vpnid'];
181 49b76122 Renato Botelho
		}
182
	}
183 f432e364 Matthew Grooms
184
	return 0;
185
}
186
187 49b76122 Renato Botelho
function openvpn_port_next($prot, $interface = "wan") {
188 f432e364 Matthew Grooms
189
	$port = 1194;
190 49b76122 Renato Botelho
	while(openvpn_port_used($prot, $interface, $port))
191
		$port++;
192
	while(openvpn_port_used($prot, "any", $port))
193 f432e364 Matthew Grooms
		$port++;
194
195
	return $port;
196
}
197
198 d799787e Matthew Grooms
function openvpn_get_cipherlist() {
199
200
	$ciphers = array();
201 5a7cc1f9 Ermal
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
202 d799787e Matthew Grooms
	$cipher_lines = explode("\n", trim($cipher_out));
203
	sort($cipher_lines);
204
	foreach ($cipher_lines as $line) {
205
		$words = explode(' ', $line);
206
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
207 8be2d6d3 Ermal Luçi
	}
208 4aa02281 Carlos Eduardo Ramos
	$ciphers["none"] = gettext("None (No Encryption)");
209 d799787e Matthew Grooms
	return $ciphers;
210
}
211
212 97d5b59b jim-p
function openvpn_get_digestlist() {
213
214
	$digests = array();
215
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
216
	$digest_lines = explode("\n", trim($digest_out));
217
	sort($digest_lines);
218
	foreach ($digest_lines as $line) {
219
		$words = explode(' ', $line);
220
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
221
	}
222
	$digests["none"] = gettext("None (No Authentication)");
223
	return $digests;
224
}
225
226 582c58ae jim-p
function openvpn_get_engines() {
227
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
228 349bf358 jim-p
	exec("/usr/local/bin/openssl engine -t -c", $openssl_engine_output);
229
	$openssl_engine_output = implode("\n", $openssl_engine_output);
230
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
231
	$openssl_engine_output = explode("\n", $openssl_engine_output);
232
233 582c58ae jim-p
	foreach ($openssl_engine_output as $oeo) {
234 349bf358 jim-p
		$keep = true;
235
		$details = explode("|", $oeo);
236
		$engine = array_shift($details);
237 582c58ae jim-p
		$linematch = array();
238 349bf358 jim-p
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
239
		foreach ($details as $dt) {
240
			if (strpos($dt, "unavailable") !== FALSE)
241
				$keep = false;
242
			if (strpos($dt, "available") !== FALSE)
243
				continue;
244
			if (strpos($dt, "[") !== FALSE)
245
				$ciphers = trim($dt, "[]");
246
		}
247
		if (!empty($ciphers))
248
			$ciphers = " - " . $ciphers;
249
		if (strlen($ciphers) > 60)
250
			$ciphers = substr($ciphers, 0, 60) . " ... ";
251
		if ($keep)
252
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
253 582c58ae jim-p
	}
254
	return $openssl_engines;
255
}
256
257
function openvpn_validate_engine($engine) {
258
	$engines = openvpn_get_engines();
259
	return array_key_exists($engine, $engines);
260
}
261
262 d799787e Matthew Grooms
function openvpn_validate_host($value, $name) {
263
	$value = trim($value);
264 3e2bd5de Ermal Lu?i
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
265 4aa02281 Carlos Eduardo Ramos
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
266 d799787e Matthew Grooms
	return false;
267 8dc3ef67 Scott Ullrich
}
268
269
function openvpn_validate_port($value, $name) {
270
	$value = trim($value);
271 3e2bd5de Ermal Lu?i
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
272 4aa02281 Carlos Eduardo Ramos
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
273 b398bbca Martin Fuchs
	return false;
274 8dc3ef67 Scott Ullrich
}
275
276 a28d40cb jim-p
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
277
	$value = trim($value);
278
	$error = false;
279
	if (empty($value))
280
		return false;
281
	$networks = explode(',', $value);
282
283
	if (!$multiple && (count($networks) > 1))
284
		return sprintf(gettext("The field '%s' must contain a single valid %s CIDR range."), $name, $ipproto);
285
286
	foreach ($networks as $network) {
287
		if ($ipproto == "ipv4")
288
			$error = !openvpn_validate_cidr_ipv4($network);
289
		else
290
			$error = !openvpn_validate_cidr_ipv6($network);
291
		if ($error)
292
			break;
293
	}
294
295
	if ($error)
296
		return sprintf(gettext("The field '%s' must contain only valid %s CIDR range(s) separated by commas."), $name, $ipproto);
297
	else
298
		return false;
299
}
300
301
function openvpn_validate_cidr_ipv4($value) {
302 8dc3ef67 Scott Ullrich
	$value = trim($value);
303
	if (!empty($value)) {
304
		list($ip, $mask) = explode('/', $value);
305 a28d40cb jim-p
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
306
			return false;
307 8dc3ef67 Scott Ullrich
	}
308 a28d40cb jim-p
	return true;
309
}
310
311
function openvpn_validate_cidr_ipv6($value) {
312
	$value = trim($value);
313
	if (!empty($value)) {
314
		list($ipv6, $prefix) = explode('/', $value);
315
		if (empty($prefix))
316
			$prefix = "128";
317
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0))
318
			return false;
319
	}
320
	return true;
321 afb07cf1 Scott Ullrich
}
322
323 d799787e Matthew Grooms
function openvpn_add_dhcpopts(& $settings, & $conf) {
324 afb07cf1 Scott Ullrich
325 d799787e Matthew Grooms
	if (!empty($settings['dns_domain'])) 
326
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
327 add2e3f7 Scott Ullrich
328 d799787e Matthew Grooms
	if (!empty($settings['dns_server1']))
329
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
330
	if (!empty($settings['dns_server2']))
331
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
332
	if (!empty($settings['dns_server3']))
333
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
334
	if (!empty($settings['dns_server4']))
335
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
336 f9927473 Scott Ullrich
337 d799787e Matthew Grooms
	if (!empty($settings['ntp_server1']))
338 c7f70dbc Chris Buechler
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
339 d799787e Matthew Grooms
	if (!empty($settings['ntp_server2']))
340 c7f70dbc Chris Buechler
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
341 f9927473 Scott Ullrich
342 d799787e Matthew Grooms
	if ($settings['netbios_enable']) {
343 add2e3f7 Scott Ullrich
344 095a95ae Matthew Grooms
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
345
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
346
		if (!empty($settings['dhcp_nbtscope'])) 
347 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
348 8dc3ef67 Scott Ullrich
349 d799787e Matthew Grooms
		if (!empty($settings['wins_server1']))
350
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
351
		if (!empty($settings['wins_server2']))
352
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
353 add2e3f7 Scott Ullrich
354 d799787e Matthew Grooms
		if (!empty($settings['nbdd_server1']))
355
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
356
	}
357 8dc3ef67 Scott Ullrich
358 d799787e Matthew Grooms
	if ($settings['gwredir']) 
359
		$conf .= "push \"redirect-gateway def1\"\n";
360
}
361 24012690 Scott Ullrich
362 d799787e Matthew Grooms
function openvpn_add_custom(& $settings, & $conf) {
363 add2e3f7 Scott Ullrich
364 d799787e Matthew Grooms
	if ($settings['custom_options']) {
365 8dc3ef67 Scott Ullrich
366 d799787e Matthew Grooms
		$options = explode(';', $settings['custom_options']);
367
368
		if (is_array($options)) {
369
			foreach ($options as $option)
370
				$conf .= "$option\n";
371
		} else
372
			$conf .= "{$settings['custom_options']}\n";
373 add2e3f7 Scott Ullrich
	}
374
}
375
376 691fbf14 Ermal Lu?i
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
377 d799787e Matthew Grooms
	global $g;
378 add2e3f7 Scott Ullrich
379 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
380 a8f538a8 jim-p
	openvpn_create_dirs();
381 d799787e Matthew Grooms
	file_put_contents($fpath, base64_decode($data));
382 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
383
	//chgrp($fpath, 'nobody');
384 6f27412f Ermal Lu?i
	@chmod($fpath, 0600);
385 d799787e Matthew Grooms
386 691fbf14 Ermal Lu?i
	$conf .= "{$directive} {$fpath} {$opt}\n";
387 4eefa6e8 Scott Ullrich
}
388
389 fc05822b jim-p
function openvpn_reconfigure($mode, $settings) {
390 add2e3f7 Scott Ullrich
	global $g, $config;
391 afb07cf1 Scott Ullrich
392 93a0a028 Ermal Luçi
	if (empty($settings))
393
		return;
394 a1cab2c7 Ermal
	if (isset($settings['disable'])) 
395 4eefa6e8 Scott Ullrich
		return;
396 a8f538a8 jim-p
	openvpn_create_dirs();
397 fdd725f0 Ermal Luçi
	/*
398 d799787e Matthew Grooms
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
399
	 * we use a vpnid number which is allocated for a particular client
400
	 * or server configuration. ( see openvpn_vpnid_next() )
401 fdd725f0 Ermal Luçi
	 */
402 8874c692 Ermal Luçi
403 d799787e Matthew Grooms
	$vpnid = $settings['vpnid'];
404
	$mode_id = $mode.$vpnid;
405 8874c692 Ermal Luçi
406 4936ff53 jim-p
	if (isset($settings['dev_mode']))
407
		$tunname = "{$settings['dev_mode']}{$vpnid}";
408 bd7ca506 jim-p
	else {	/* defaults to tun */
409
		$tunname = "tun{$vpnid}";
410 4936ff53 jim-p
		$settings['dev_mode'] = "tun";
411 691fbf14 Ermal Lu?i
	}
412
413 bd7ca506 jim-p
	if ($mode == "server")
414
		$devname = "ovpns{$vpnid}";
415
	else
416
		$devname = "ovpnc{$vpnid}";
417 8874c692 Ermal Luçi
418 bd7ca506 jim-p
	/* is our device already configured */
419 1bc783b6 bcyrill
	if (mwexec("/sbin/ifconfig {$devname}", true)) {
420 dc408939 Matthew Grooms
421 bd7ca506 jim-p
		/* create the tap device if required */
422
		if (!file_exists("/dev/{$tunname}"))
423
			exec("/sbin/ifconfig {$tunname} create");
424 98872d89 Ermal Luçi
425 bd7ca506 jim-p
		/* rename the device */
426
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
427 095a95ae Matthew Grooms
428 bd7ca506 jim-p
		/* add the device to the openvpn group */
429
		mwexec("/sbin/ifconfig {$devname} group openvpn");
430 dc408939 Matthew Grooms
	}
431 d799787e Matthew Grooms
432 dc408939 Matthew Grooms
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
433 6714bbdc jim-p
	$proto = strtolower($settings['protocol']);
434
	if (substr($settings['protocol'], 0, 3) == "TCP")
435
			$proto = "{$proto}-{$mode}";
436 4936ff53 jim-p
	$dev_mode = $settings['dev_mode'];
437 c0cf27aa Scott Ullrich
	$cipher = $settings['crypto'];
438 97d5b59b jim-p
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
439
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
440 d799787e Matthew Grooms
441 47c48e28 smos
	$interface = get_failover_interface($settings['interface']);
442 d7a0c22a bcyrill
	$ipaddr = $settings['ipaddr'];
443
	$ipaddrv6 = $settings['ipaddrv6'];
444 d799787e Matthew Grooms
445 67b0902f pierrepomes
	// If a specific ip address (VIP) is requested, use it.
446
	// Otherwise, if a specific interface is requested, use it
447
	// If "any" interface was selected, local directive will be ommited.
448 97ffc513 Seth Mos
	if (is_ipaddrv4($ipaddr)) {
449 67b0902f pierrepomes
		$iface_ip=$ipaddr;
450 3d06e8f0 pierrepomes
	} else {
451 67b0902f pierrepomes
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
452 507af8dd pierrepomes
			$iface_ip=get_interface_ip($interface);
453 67b0902f pierrepomes
		}
454 47c48e28 smos
	}
455
	if (is_ipaddrv6($ipaddrv6)) {
456
		$iface_ipv6=$ipaddrv6;
457
	} else {
458 97ffc513 Seth Mos
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
459
			$iface_ipv6=get_interface_ipv6($interface);
460
		}
461 3d06e8f0 pierrepomes
	}
462 d799787e Matthew Grooms
463 bd7ca506 jim-p
	$conf  = "dev {$devname}\n";
464 4936ff53 jim-p
	$conf .= "dev-type {$settings['dev_mode']}\n";
465 97ffc513 Seth Mos
	switch($settings['dev_mode']) {
466
		case "tun":
467
			$conf .= "tun-ipv6\n";
468
			break;
469
	}
470 bd7ca506 jim-p
	$conf .= "dev-node /dev/{$tunname}\n";
471 3c11bd3c Matthew Grooms
	$conf .= "writepid {$pfile}\n";
472
	$conf .= "#user nobody\n";
473
	$conf .= "#group nobody\n";
474 d1014c18 Chris Buechler
	$conf .= "script-security 3\n";
475 3c11bd3c Matthew Grooms
	$conf .= "daemon\n";
476
	$conf .= "keepalive 10 60\n";
477
	$conf .= "ping-timer-rem\n";
478
	$conf .= "persist-tun\n";
479
	$conf .= "persist-key\n";
480
	$conf .= "proto {$proto}\n";
481
	$conf .= "cipher {$cipher}\n";
482 97d5b59b jim-p
	$conf .= "auth {$digest}\n";
483 8d964cea Ermal
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
484
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
485 1492e02c Ermal
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
486 a1b9105b jim-p
		switch($settings['mode']) {
487
			case 'server_user':
488
			case 'server_tls_user':
489
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
490
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
491
				break;
492
		}
493 1492e02c Ermal
	}
494 3c11bd3c Matthew Grooms
495 6714bbdc jim-p
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
496
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
497
		$conf .= "local {$iface_ip}\n";
498
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
499
		$conf .= "local {$iface_ipv6}\n";
500 97ffc513 Seth Mos
	}
501 d799787e Matthew Grooms
502 582c58ae jim-p
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
503
		$conf .= "engine {$settings['engine']}\n";
504
505 67b0902f pierrepomes
	// server specific settings
506 8dc3ef67 Scott Ullrich
	if ($mode == 'server') {
507 d799787e Matthew Grooms
508 5dc6c910 jim-p
		list($ip, $cidr) = explode('/', $settings['tunnel_network']);
509 97ffc513 Seth Mos
		list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
510 5dc6c910 jim-p
		$mask = gen_subnet_mask($cidr);
511 8dc3ef67 Scott Ullrich
512 3c11bd3c Matthew Grooms
		// configure tls modes
513
		switch($settings['mode']) {
514
			case 'p2p_tls':
515
			case 'server_tls':
516 e62e2f8b Ermal Lu?i
			case 'server_user':
517 3c11bd3c Matthew Grooms
			case 'server_tls_user':
518 d799787e Matthew Grooms
				$conf .= "tls-server\n";
519 3c11bd3c Matthew Grooms
				break;
520 8dc3ef67 Scott Ullrich
		}
521 d799787e Matthew Grooms
522 3c11bd3c Matthew Grooms
		// configure p2p/server modes
523
		switch($settings['mode']) {
524 6c9cf466 jim-p
			case 'p2p_tls':
525 5dc6c910 jim-p
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
526
				//  use the server directive. It works for a single client without it.
527
				//  See ticket #1417
528 74a556a3 jim-p
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
529 5dc6c910 jim-p
					$conf .= "server {$ip} {$mask}\n";
530
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
531 a0e3ee98 jim-p
					if(is_ipaddr($ipv6))
532
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
533 5dc6c910 jim-p
				}
534 3c11bd3c Matthew Grooms
			case 'p2p_shared_key':
535 74a556a3 jim-p
				if (!empty($ip) && !empty($mask)) {
536 91c44185 jim-p
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
537 459e9333 jim-p
					if ($settings['dev_mode'] == 'tun')
538
						$conf .= "ifconfig {$ip1} {$ip2}\n";
539
					else
540
						$conf .= "ifconfig {$ip1} {$mask}\n";
541 1ab6bdb5 jim-p
				}
542 a0e3ee98 jim-p
				if (!empty($ipv6) && !empty($prefix)) {
543 91c44185 jim-p
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
544 a0e3ee98 jim-p
					if ($settings['dev_mode'] == 'tun')
545
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
546
					else
547 60f501ec Phil Davis
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
548 a0e3ee98 jim-p
				}
549 3c11bd3c Matthew Grooms
				break;
550
			case 'server_tls':
551
			case 'server_user':
552
			case 'server_tls_user':
553 74a556a3 jim-p
				if (!empty($ip) && !empty($mask)) {
554 1ab6bdb5 jim-p
					$conf .= "server {$ip} {$mask}\n";
555
					if(is_ipaddr($ipv6))
556
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
557
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
558
				} else {
559
					if ($settings['serverbridge_dhcp']) {
560
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
561
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
562
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
563
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
564
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
565
							} else {
566
								$conf .= "mode server\n";
567
							}
568
						} else {
569
							$conf .= "mode server\n";
570
						}
571
					}
572
				}
573 3c11bd3c Matthew Grooms
				break;
574 8dc3ef67 Scott Ullrich
		}
575
576 3c11bd3c Matthew Grooms
		// configure user auth modes
577
		switch($settings['mode']) {
578
			case 'server_user':
579
				$conf .= "client-cert-not-required\n";
580
			case 'server_tls_user':
581 9eced774 jim-p
				/* username-as-common-name is not compatible with server-bridge */
582
				if (stristr($conf, "server-bridge") === false)
583
					$conf .= "username-as-common-name\n";
584 8a47c190 Ermal Lu?i
				if (!empty($settings['authmode'])) {
585
					$authcfgs = explode(",", $settings['authmode']);
586
					$sed = "\$authmodes=array(";
587
					$firstsed = 0;
588
					foreach ($authcfgs as $authcfg) {
589
						if ($firstsed > 0)
590
							$sed .= ",";
591
						$firstsed = 1;
592
						$sed .= "\"{$authcfg}\"";
593
					}
594 8901958c jim-p
					$sed .= ");\\\n";
595 53d41b68 Erik Fonnesbeck
					if ($settings['strictusercn'])
596 befad728 Ermal
						$sed .= "\$strictusercn = true;";
597 1bab0df1 jim-p
					$sed .= " \$modeid = \"{$mode_id}\";";
598 8a47c190 Ermal Lu?i
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
599
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
600
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
601 e8a58de4 Ermal Lu?i
				}
602 3c11bd3c Matthew Grooms
				break;
603 8dc3ef67 Scott Ullrich
		}
604 41936acc jim-p
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls')))
605
			$settings['cert_depth'] = 1;
606 98963f27 jim-p
		if (is_numeric($settings['cert_depth'])) {
607
			$sed = "";
608
			$cert = lookup_cert($settings['certref']);
609
			$servercn = cert_get_cn($cert['crt']);
610
			$sed .= "\$server_cn = \"{$servercn}\";\\\n";
611
			$sed .= "\$allowed_depth = {$settings['cert_depth']};\\\n";
612
			mwexec("/bin/cat /etc/inc/openvpn.tls-verify.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
613
			mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php");
614
			$conf .= "tls-verify {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php\n";
615
		}
616 8dc3ef67 Scott Ullrich
617 63084885 Matthew Grooms
		// The local port to listen on
618 d799787e Matthew Grooms
		$conf .= "lport {$settings['local_port']}\n";
619 c0cf27aa Scott Ullrich
620 63084885 Matthew Grooms
		// The management port to listen on
621 71ca2cb2 Ermal
		// Use unix socket to overcome the problem on any type of server
622
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
623
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
624 63084885 Matthew Grooms
625 3c11bd3c Matthew Grooms
		if ($settings['maxclients'])
626 d799787e Matthew Grooms
			$conf .= "max-clients {$settings['maxclients']}\n";
627
628 3c11bd3c Matthew Grooms
		// Can we push routes
629
		if ($settings['local_network']) {
630 a28d40cb jim-p
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
631 3c11bd3c Matthew Grooms
		}
632 787de45a Seth Mos
		if ($settings['local_networkv6']) {
633 a28d40cb jim-p
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
634 787de45a Seth Mos
		}
635 3c11bd3c Matthew Grooms
636
		switch($settings['mode']) {
637
			case 'server_tls':
638
			case 'server_user':
639
			case 'server_tls_user':
640 5d8cd81a jim-p
				// Configure client dhcp options
641 3c11bd3c Matthew Grooms
				openvpn_add_dhcpopts($settings, $conf);
642 5d8cd81a jim-p
				if ($settings['client2client'])
643
					$conf .= "client-to-client\n";
644 3c11bd3c Matthew Grooms
				break;
645
		}
646 bca35cff jim-p
		if (isset($settings['duplicate_cn']))
647
			$conf .= "duplicate-cn\n";
648 d799787e Matthew Grooms
	}
649
650 3c11bd3c Matthew Grooms
	// client specific settings
651 d799787e Matthew Grooms
652 3c11bd3c Matthew Grooms
	if ($mode == 'client') {
653 d799787e Matthew Grooms
654 3c11bd3c Matthew Grooms
		// configure p2p mode
655
		switch($settings['mode']) {
656
			case 'p2p_tls':
657
				$conf .= "tls-client\n";
658
			case 'shared_key':
659
				$conf .= "client\n";
660
				break;
661
		}
662 d799787e Matthew Grooms
663 e3924384 jim-p
		// If there is no bind option at all (ip and/or port), add "nobind" directive
664
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
665
		//  ensure a random source port.
666
		if ((empty($iface_ip)) && (!$settings['local_port']))
667
			$conf .= "nobind\n";
668
		elseif ($settings['local_port'])
669
			$conf .= "lport {$settings['local_port']}\n";
670
		else
671
			$conf .= "lport 0\n";
672 5708241f jim-p
673 4b887ef4 jim-p
		// Use unix socket to overcome the problem on any type of server
674
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
675 48a458d2 pierrepomes
676 3c11bd3c Matthew Grooms
		// The remote server
677
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
678
679 d799787e Matthew Grooms
		if (!empty($settings['use_shaper']))
680
			$conf .= "shaper {$settings['use_shaper']}\n";
681 ee506044 Scott Ullrich
682 d799787e Matthew Grooms
		if (!empty($settings['tunnel_network'])) {
683
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
684 8dc3ef67 Scott Ullrich
			$mask = gen_subnet_mask($mask);
685 91c44185 jim-p
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
686 459e9333 jim-p
			if ($settings['dev_mode'] == 'tun')
687
				$conf .= "ifconfig {$ip2} {$ip1}\n";
688
			else
689
				$conf .= "ifconfig {$ip2} {$mask}\n";
690 8dc3ef67 Scott Ullrich
		}
691 d799787e Matthew Grooms
692 a0e3ee98 jim-p
		if (!empty($settings['tunnel_networkv6'])) {
693
			list($ipv6, $prefix) = explode('/', $settings['tunnel_networkv6']);
694 91c44185 jim-p
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
695 a0e3ee98 jim-p
			if ($settings['dev_mode'] == 'tun')
696
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
697
			else
698 60f501ec Phil Davis
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
699 a0e3ee98 jim-p
		}
700
701 762a24a3 Ermal Lu?i
		if ($settings['proxy_addr']) {
702
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
703
			if ($settings['proxy_authtype'] != "none") {
704
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
705
				$proxypas = "{$settings['proxy_user']}\n";
706
				$proxypas .= "{$settings['proxy_passwd']}\n";
707
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
708
			}
709
			$conf .= " \n";
710
		}
711 8dc3ef67 Scott Ullrich
	}
712
713 17c98ba9 jim-p
	// Add a remote network route if set, and only for p2p modes.
714 54285411 jim-p
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
715 a28d40cb jim-p
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
716 8dc3ef67 Scott Ullrich
	}
717 4856df9b jim-p
	// Add a remote network route if set, and only for p2p modes.
718 54285411 jim-p
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
719 a28d40cb jim-p
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
720 4856df9b jim-p
	}
721 afb07cf1 Scott Ullrich
722 d799787e Matthew Grooms
	// Write the settings for the keys
723 3c11bd3c Matthew Grooms
	switch($settings['mode']) {
724
		case 'p2p_shared_key':
725
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
726
			break;
727
		case 'p2p_tls':
728
		case 'server_tls':
729
		case 'server_tls_user':
730 e62e2f8b Ermal Lu?i
		case 'server_user':
731 3c11bd3c Matthew Grooms
			$ca = lookup_ca($settings['caref']);
732
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
733
			$cert = lookup_cert($settings['certref']);
734
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
735
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
736
			if ($mode == 'server')
737 fe787fc7 Matthew Grooms
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
738 6db02381 jim-p
			if (!empty($settings['crlref'])) {
739
				$crl = lookup_crl($settings['crlref']);
740 cfcc6994 jim-p
				crl_update($crl);
741 6db02381 jim-p
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
742
			}
743 db746ce2 Ermal Lu?i
			if ($settings['tls']) {
744 756720e2 Pierre POMES
				if ($mode == "server") 
745 db746ce2 Ermal Lu?i
					$tlsopt = 0;
746
				else
747
					$tlsopt = 1;
748
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
749
			}
750 3c11bd3c Matthew Grooms
			break;
751 8dc3ef67 Scott Ullrich
	}
752
753 edba1982 jim-p
	if (!empty($settings['compression']))
754
		$conf .= "comp-lzo {$settings['compression']}\n";
755 d799787e Matthew Grooms
756
	if ($settings['passtos'])
757
		$conf .= "passtos\n";
758
759
	if ($settings['resolve_retry'])
760
		$conf .= "resolv-retry infinite\n";
761
762
	if ($settings['dynamic_ip']) {
763
		$conf .= "persist-remote-ip\n";
764
		$conf .= "float\n";
765 8dc3ef67 Scott Ullrich
	}
766 afb07cf1 Scott Ullrich
767 ee55ce7d jim-p
	if ($settings['topology_subnet']) {
768
		$conf .= "topology subnet\n";
769
	}
770
771 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
772
773 a8f538a8 jim-p
	openvpn_create_dirs();
774 938fc5b0 Ermal
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
775 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
776 938fc5b0 Ermal
	unset($conf);
777 be00850b Phil Davis
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
778
	file_put_contents($fpath, $interface);
779 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
780
	//chgrp($fpath, 'nobody');
781 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
782 be00850b Phil Davis
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
783 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
784
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
785
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
786 d799787e Matthew Grooms
}
787
788 fc05822b jim-p
function openvpn_restart($mode, $settings) {
789 d799787e Matthew Grooms
	global $g, $config;
790
791
	$vpnid = $settings['vpnid'];
792
	$mode_id = $mode.$vpnid;
793
794 76369bfc Matthew Grooms
	/* kill the process if running */
795 705c8ec9 Matthew Grooms
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
796 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
797 705c8ec9 Matthew Grooms
798 76369bfc Matthew Grooms
		/* read the pid file */
799
		$pid = rtrim(file_get_contents($pfile));
800
		unlink($pfile);
801 705c8ec9 Matthew Grooms
802 76369bfc Matthew Grooms
		/* send a term signal to the process */
803
		posix_kill($pid, SIGTERM);
804
805
		/* wait until the process exits */
806
		while(posix_kill($pid, 0))
807
			usleep(250000);
808
	}
809 d799787e Matthew Grooms
810 a1cab2c7 Ermal
	if (isset($settings['disable']))
811 d799787e Matthew Grooms
		return;
812
813 260f267e jim-p
	/* Do not start a client if we are a CARP backup on this vip! */
814
	if (($mode == "client") && strstr($settings['interface'], "_vip") && (get_carp_interface_status($settings['interface']) == "BACKUP"))
815 9ea0cb90 jim-p
		return;
816 330ecea1 Shahid Sheikh
		
817
	/* Check if client is bound to a gateway group */    
818
	$a_groups = return_gateway_groups_array();
819
	if (is_array($a_groups[$settings['interface']])) {
820
	/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
821
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) == "BACKUP"))
822
			return;
823
	}
824 9ea0cb90 jim-p
825 705c8ec9 Matthew Grooms
	/* start the new process */
826 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
827 91c44185 jim-p
	openvpn_clear_route($mode, $settings);
828 5a7cc1f9 Ermal
	mwexec_bg("/usr/local/sbin/openvpn --config {$fpath}");
829 847cd48d Ermal
830
	if (!$g['booting'])
831
		send_event("filter reload");
832 afb07cf1 Scott Ullrich
}
833
834 dc408939 Matthew Grooms
function openvpn_delete($mode, & $settings) {
835 d799787e Matthew Grooms
	global $g, $config;
836
837
	$vpnid = $settings['vpnid'];
838
	$mode_id = $mode.$vpnid;
839
840 da601f8e PiBa-NL
	if (isset($settings['dev_mode']))
841
		$tunname = "{$settings['dev_mode']}{$vpnid}";
842
	else {  /* defaults to tun */
843
		$tunname = "tun{$vpnid}";
844
	}
845
846 095a95ae Matthew Grooms
	if ($mode == "server")
847
		$devname = "ovpns{$vpnid}";
848
	else
849
		$devname = "ovpnc{$vpnid}";
850 dc408939 Matthew Grooms
851 76369bfc Matthew Grooms
	/* kill the process if running */
852 dc408939 Matthew Grooms
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
853 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
854 dc408939 Matthew Grooms
855 76369bfc Matthew Grooms
		/* read the pid file */
856
		$pid = trim(file_get_contents($pfile));
857
		unlink($pfile);
858
859
		/* send a term signal to the process */
860
		posix_kill($pid, SIGTERM);
861
	}
862 705c8ec9 Matthew Grooms
863 095a95ae Matthew Grooms
	/* remove the device from the openvpn group */
864
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
865
866 dc408939 Matthew Grooms
	/* restore the original adapter name */
867
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
868
869
	/* remove the configuration files */
870
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
871 d799787e Matthew Grooms
}
872 afb07cf1 Scott Ullrich
873 de85521a jim-p
function openvpn_cleanup_csc($common_name) {
874
	global $g, $config;
875
	if (empty($common_name))
876
		return;
877
	$fpath = "{$g['varetc_path']}/openvpn-csc/" . basename($common_name);
878
	if (is_file($fpath))
879
		unlink_if_exists($fpath);
880
	return;
881
}
882
883 dc408939 Matthew Grooms
function openvpn_resync_csc(& $settings) {
884 8dc3ef67 Scott Ullrich
	global $g, $config;
885
886 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
887 8dc3ef67 Scott Ullrich
888 a1cab2c7 Ermal
	if (isset($settings['disable'])) {
889 d799787e Matthew Grooms
		unlink_if_exists($fpath);
890 c876662c Scott Ullrich
		return;
891
	}
892 a8f538a8 jim-p
	openvpn_create_dirs();
893 d799787e Matthew Grooms
894 8dc3ef67 Scott Ullrich
	$conf = '';
895 d799787e Matthew Grooms
	if ($settings['block'])
896
		$conf .= "disable\n";
897
898
	if ($settings['push_reset'])
899
		$conf .= "push-reset\n";
900
901
	if (!empty($settings['tunnel_network'])) {
902
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
903 96033063 Erik Fonnesbeck
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
904 298fe5ae jim-p
		$serverip = long2ip32($baselong + 1);
905
		$clientip = long2ip32($baselong + 2);
906
		/* Because this is being pushed, the order from the client's point of view. */
907 d9c96fb1 jim-p
		if ($settings['dev_mode'] != 'tap')
908
			$conf .= "ifconfig-push {$clientip} {$serverip}\n";
909 e052047d jim-p
		else
910
			$conf .= "ifconfig-push {$clientip} {$mask}\n";
911 8dc3ef67 Scott Ullrich
	}
912 6d031071 Martin Fuchs
913 d799787e Matthew Grooms
	openvpn_add_dhcpopts($settings, $conf);
914 8dc3ef67 Scott Ullrich
915 d799787e Matthew Grooms
	if ($settings['gwredir'])
916
		$conf .= "push \"redirect-gateway def1\"\n";
917 6d031071 Martin Fuchs
918 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
919 8dc3ef67 Scott Ullrich
920 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
921
	chown($fpath, 'nobody');
922
	chgrp($fpath, 'nobody');
923
}
924 8dc3ef67 Scott Ullrich
925 dc408939 Matthew Grooms
function openvpn_delete_csc(& $settings) {
926 add2e3f7 Scott Ullrich
	global $g, $config;
927 3c2e5528 Scott Ullrich
928 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
929 d799787e Matthew Grooms
	unlink_if_exists($fpath);
930 267ab13f Ermal Luçi
}
931 afb07cf1 Scott Ullrich
932 24012690 Scott Ullrich
// Resync the configuration and restart the VPN
933 fc05822b jim-p
function openvpn_resync($mode, $settings) {
934 dc408939 Matthew Grooms
	openvpn_reconfigure($mode, $settings);
935
	openvpn_restart($mode, $settings);
936 afb07cf1 Scott Ullrich
}
937
938 add2e3f7 Scott Ullrich
// Resync and restart all VPNs
939 c7f60193 Ermal
function openvpn_resync_all($interface = "") {
940 d799787e Matthew Grooms
	global $g, $config;
941 267ab13f Ermal Luçi
942 7734aea6 Andrew Thompson
	if ($g['platform'] == 'jail')
943
		return;
944 a8f538a8 jim-p
	openvpn_create_dirs();
945 3cb54b54 Matthew Grooms
946 34bc1324 Matthew Grooms
	if (!is_array($config['openvpn']))
947
		$config['openvpn'] = array();
948
949 15b414e6 Matthew Grooms
/*
950 34bc1324 Matthew Grooms
	if (!$config['openvpn']['dh-parameters']) {
951
		echo "Configuring OpenVPN Parameters ...\n";
952 035e4289 Matthew Grooms
		$dh_parameters = openvpn_create_dhparams(1024);
953 34bc1324 Matthew Grooms
		$dh_parameters = base64_encode($dh_parameters);
954
		$config['openvpn']['dh-parameters'] = $dh_parameters;
955 c67dd94e Bill Marquette
		write_config("OpenVPN DH parameters");
956 34bc1324 Matthew Grooms
	}
957
958
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
959
	if (!file_exists($path_ovdh)) {
960
		$dh_parameters = $config['openvpn']['dh-parameters'];
961
		$dh_parameters = base64_decode($dh_parameters);
962
		file_put_contents($path_ovdh, $dh_parameters);
963
	}
964 15b414e6 Matthew Grooms
*/
965 739c9efd Ermal
	if ($interface <> "")
966 a82e6d37 Chris Buechler
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
967 739c9efd Ermal
	else
968 a82e6d37 Chris Buechler
		log_error("Resyncing OpenVPN instances."); 
969 34bc1324 Matthew Grooms
970 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-server'])) {
971
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
972 739c9efd Ermal
			if ($interface <> "" && $interface != $settings['interface'])
973 c7f60193 Ermal
				continue;
974 dc408939 Matthew Grooms
			openvpn_resync('server', $settings);
975 c7f60193 Ermal
		}
976
	}
977 5b237745 Scott Ullrich
978 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-client'])) {
979
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
980 739c9efd Ermal
			if ($interface <> "" && $interface != $settings['interface'])
981 c7f60193 Ermal
				continue;
982 dc408939 Matthew Grooms
			openvpn_resync('client', $settings);
983 c7f60193 Ermal
		}
984
	}
985 afb07cf1 Scott Ullrich
986 d799787e Matthew Grooms
	if (is_array($config['openvpn']['openvpn-csc']))
987 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
988
			openvpn_resync_csc($settings);
989 afb07cf1 Scott Ullrich
990 5b237745 Scott Ullrich
}
991 702a4702 Scott Ullrich
992 99cc103b Phil Davis
// Resync and restart all VPNs using a gateway group.
993
function openvpn_resync_gwgroup($gwgroupname = "") {
994
	global $g, $config;
995
996
	if ($gwgroupname <> "") {
997
		if (is_array($config['openvpn']['openvpn-server'])) {
998
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
999
				if ($gwgroupname == $settings['interface']) {
1000
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " server " . $settings["description"] . ".");
1001
					openvpn_resync('server', $settings);
1002
				}
1003
			}
1004
		}
1005
1006
		if (is_array($config['openvpn']['openvpn-client'])) {
1007
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1008
				if ($gwgroupname == $settings['interface']) {
1009
					log_error("Resyncing OpenVPN for gateway group " . $gwgroupname . " client " . $settings["description"] . ".");
1010
					openvpn_resync('client', $settings);
1011
				}
1012
			}
1013
		}
1014
1015
		// Note: no need to resysnc Client Specific (csc) here, as changes to the OpenVPN real interface do not effect these.
1016
1017
	} else
1018
		log_error("openvpn_resync_gwgroup called with null gwgroup parameter."); 
1019
}
1020
1021 453d9c96 jim-p
function openvpn_get_active_servers($type="multipoint") {
1022 71ca2cb2 Ermal
	global $config, $g;
1023
1024 53663f57 jim-p
	$servers = array();
1025
	if (is_array($config['openvpn']['openvpn-server'])) {
1026
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1027 6b2dcac5 Ermal
			if (empty($settings) || isset($settings['disable']))
1028
				continue;
1029
1030 53663f57 jim-p
			$prot = $settings['protocol'];
1031
			$port = $settings['local_port'];
1032
	
1033
			$server = array();
1034 95305736 jim-p
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1035 41be629f jim-p
			$server['mode'] = $settings['mode'];
1036 53663f57 jim-p
			if ($settings['description'])
1037
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1038
			else
1039
				$server['name'] = "Server {$prot}:{$port}";
1040
			$server['conns'] = array();
1041 2eaa97b9 jim-p
			$server['vpnid'] = $settings['vpnid'];
1042
			$server['mgmt'] = "server{$server['vpnid']}";
1043
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1044 453d9c96 jim-p
			list($tn, $sm) = explode('/', $settings['tunnel_network']);
1045
1046
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30) ) && ($type == "p2p"))
1047 95305736 jim-p
				$servers[] = openvpn_get_client_status($server, $socket);
1048 453d9c96 jim-p
			elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30))
1049 95305736 jim-p
				$servers[] = openvpn_get_server_status($server, $socket);
1050 453d9c96 jim-p
1051 95305736 jim-p
		}
1052
	}
1053
	return $servers;
1054
}
1055 b0140675 Ermal
1056 95305736 jim-p
function openvpn_get_server_status($server, $socket) {
1057
	$errval;
1058
	$errstr;
1059
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1060
	if ($fp) {
1061
		stream_set_timeout($fp, 1);
1062
1063
		/* send our status request */
1064
		fputs($fp, "status 2\n");
1065
1066
		/* recv all response lines */
1067
		while (!feof($fp)) {
1068
1069
			/* read the next line */
1070
			$line = fgets($fp, 1024);
1071
1072
			$info = stream_get_meta_data($fp);
1073
			if ($info['timed_out'])
1074
				break;
1075
1076
			/* parse header list line */
1077
			if (strstr($line, "HEADER"))
1078
				continue;
1079
1080
			/* parse end of output line */
1081
			if (strstr($line, "END") || strstr($line, "ERROR"))
1082
				break;
1083
1084
			/* parse client list line */
1085
			if (strstr($line, "CLIENT_LIST")) {
1086
				$list = explode(",", $line);
1087 53663f57 jim-p
				$conn = array();
1088 95305736 jim-p
				$conn['common_name'] = $list[1];
1089
				$conn['remote_host'] = $list[2];
1090
				$conn['virtual_addr'] = $list[3];
1091
				$conn['bytes_recv'] = $list[4];
1092
				$conn['bytes_sent'] = $list[5];
1093
				$conn['connect_time'] = $list[6];
1094 53663f57 jim-p
				$server['conns'][] = $conn;
1095
			}
1096 ec970b50 jim-p
			/* parse routing table lines */
1097
			if (strstr($line, "ROUTING_TABLE")) {
1098
				$list = explode(",", $line);
1099
				$conn = array();
1100
				$conn['virtual_addr'] = $list[1];
1101
				$conn['common_name'] = $list[2];
1102
				$conn['remote_host'] = $list[3];
1103
				$conn['last_time'] = $list[4];
1104
				$server['routes'][] = $conn;
1105
			}
1106 53663f57 jim-p
		}
1107 95305736 jim-p
1108
		/* cleanup */
1109
		fclose($fp);
1110
	} else {
1111
		$conn = array();
1112
		$conn['common_name'] = "[error]";
1113 2eaa97b9 jim-p
		$conn['remote_host'] = "Unable to contact daemon";
1114
		$conn['virtual_addr'] = "Service not running?";
1115 95305736 jim-p
		$conn['bytes_recv'] = 0;
1116
		$conn['bytes_sent'] = 0;
1117
		$conn['connect_time'] = 0;
1118
		$server['conns'][] = $conn;
1119 53663f57 jim-p
	}
1120 95305736 jim-p
	return $server;
1121 53663f57 jim-p
}
1122
1123
function openvpn_get_active_clients() {
1124 71ca2cb2 Ermal
	global $config, $g;
1125
1126 53663f57 jim-p
	$clients = array();
1127
	if (is_array($config['openvpn']['openvpn-client'])) {
1128
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1129
	
1130 6b2dcac5 Ermal
			if (empty($settings) || isset($settings['disable']))
1131
				continue;
1132
1133 53663f57 jim-p
			$prot = $settings['protocol'];
1134 95305736 jim-p
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1135 53663f57 jim-p
	
1136
			$client = array();
1137
			$client['port'] = $settings['local_port'];
1138
			if ($settings['description'])
1139 95305736 jim-p
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1140 53663f57 jim-p
			else
1141 95305736 jim-p
				$client['name'] = "Client {$prot}{$port}";
1142 53663f57 jim-p
	
1143 2eaa97b9 jim-p
			$client['vpnid'] = $settings['vpnid'];
1144
			$client['mgmt'] = "client{$client['vpnid']}";
1145
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1146 53663f57 jim-p
			$client['status']="down";
1147 95305736 jim-p
1148
			$clients[] = openvpn_get_client_status($client, $socket);
1149
		}
1150
	}
1151
	return $clients;
1152
}
1153
1154
function openvpn_get_client_status($client, $socket) {
1155
	$errval;
1156
	$errstr;
1157
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1158
	if ($fp) {
1159
		stream_set_timeout($fp, 1);
1160
		/* send our status request */
1161
		fputs($fp, "state 1\n");
1162
1163
		/* recv all response lines */
1164
		while (!feof($fp)) {
1165
			/* read the next line */
1166
			$line = fgets($fp, 1024);
1167
1168
			$info = stream_get_meta_data($fp);
1169
			if ($info['timed_out'])
1170
				break;
1171
1172
			/* Get the client state */
1173
			if (strstr($line,"CONNECTED")) {
1174
				$client['status']="up";
1175
				$list = explode(",", $line);
1176
1177
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1178
				$client['virtual_addr']  = $list[3];
1179
				$client['remote_host'] = $list[4];
1180
			}
1181 453d9c96 jim-p
			if (strstr($line,"CONNECTING")) {
1182
				$client['status']="connecting";
1183
			}
1184
			if (strstr($line,"ASSIGN_IP")) {
1185
				$client['status']="waiting";
1186
				$list = explode(",", $line);
1187
1188
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1189
				$client['virtual_addr']  = $list[3];
1190
			}
1191
			if (strstr($line,"RECONNECTING")) {
1192
				$client['status']="reconnecting";
1193
				$list = explode(",", $line);
1194
1195
				$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
1196
				$client['status'] .= "; " . $list[2];
1197
			}
1198 95305736 jim-p
			/* parse end of output line */
1199
			if (strstr($line, "END") || strstr($line, "ERROR"))
1200
				break;
1201
		}
1202
1203
		/* If up, get read/write stats */
1204
		if (strcmp($client['status'], "up") == 0) {
1205
			fputs($fp, "status 2\n");
1206
			/* recv all response lines */
1207
			while (!feof($fp)) {
1208
				/* read the next line */
1209
				$line = fgets($fp, 1024);
1210
1211
				$info = stream_get_meta_data($fp);
1212
				if ($info['timed_out'])
1213
					break;
1214
1215
				if (strstr($line,"TCP/UDP read bytes")) {
1216
					$list = explode(",", $line);
1217
					$client['bytes_recv'] = $list[1];
1218 53663f57 jim-p
				}
1219 95305736 jim-p
1220
				if (strstr($line,"TCP/UDP write bytes")) {
1221
					$list = explode(",", $line);
1222
					$client['bytes_sent'] = $list[1];
1223 53663f57 jim-p
				}
1224 95305736 jim-p
1225
				/* parse end of output line */
1226
				if (strstr($line, "END"))
1227
					break;
1228 53663f57 jim-p
			}
1229
		}
1230 95305736 jim-p
1231
		fclose($fp);
1232
1233
	} else {
1234
		$DisplayNote=true;
1235 2eaa97b9 jim-p
		$client['remote_host'] = "Unable to contact daemon";
1236
		$client['virtual_addr'] = "Service not running?";
1237 95305736 jim-p
		$client['bytes_recv'] = 0;
1238
		$client['bytes_sent'] = 0;
1239
		$client['connect_time'] = 0;
1240 53663f57 jim-p
	}
1241 95305736 jim-p
	return $client;
1242 53663f57 jim-p
}
1243 8e022a76 jim-p
1244
function openvpn_refresh_crls() {
1245
	global $g, $config;
1246
1247 a8f538a8 jim-p
	openvpn_create_dirs();
1248 8e022a76 jim-p
1249
	if (is_array($config['openvpn']['openvpn-server'])) {
1250
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1251
			if (empty($settings))
1252
				continue;
1253
			if (isset($settings['disable']))
1254
				continue;
1255
			// Write the settings for the keys
1256
			switch($settings['mode']) {
1257
				case 'p2p_tls':
1258
				case 'server_tls':
1259
				case 'server_tls_user':
1260
				case 'server_user':
1261
					if (!empty($settings['crlref'])) {
1262
						$crl = lookup_crl($settings['crlref']);
1263 728003c8 jim-p
						crl_update($crl);
1264 8e022a76 jim-p
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1265
						file_put_contents($fpath, base64_decode($crl['text']));
1266
						@chmod($fpath, 0644);
1267
					}
1268
					break;
1269
			}
1270
		}
1271
	}
1272
}
1273
1274 a8f538a8 jim-p
function openvpn_create_dirs() {
1275
	global $g;
1276
	if (!is_dir("{$g['varetc_path']}/openvpn"))
1277
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1278
	if (!is_dir("{$g['varetc_path']}/openvpn-csc"))
1279
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1280
}
1281
1282 91c44185 jim-p
function openvpn_get_interface_ip($ip, $mask) {
1283
	$baselong = ip2long32($ip) & ip2long($mask);
1284
	$ip1 = long2ip32($baselong + 1);
1285
	$ip2 = long2ip32($baselong + 2);
1286
	return array($ip1, $ip2);
1287
}
1288
1289
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1290
	$basev6 = gen_subnetv6($ipv6, $prefix);
1291
	// Is there a better way to do this math?
1292
	$ipv6_arr = explode(':', $basev6);
1293
	$last = hexdec(array_pop($ipv6_arr));
1294 fe9c774d Phil Davis
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1295
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1296 91c44185 jim-p
	return array($ipv6_1, $ipv6_2);
1297
}
1298
1299
function openvpn_clear_route($mode, $settings) {
1300
	if (empty($settings['tunnel_network']))
1301
		return;
1302
	list($ip, $cidr) = explode('/', $settings['tunnel_network']);
1303
	$mask = gen_subnet_mask($cidr);
1304 6ca938cf jim-p
	$clear_route = false;
1305
1306 91c44185 jim-p
	switch($settings['mode']) {
1307 6ca938cf jim-p
		case 'shared_key':
1308
			$clear_route = true;
1309
			break;
1310 91c44185 jim-p
		case 'p2p_tls':
1311
		case 'p2p_shared_key':
1312 6d0b9fe9 jim-p
			if ($cidr == 30)
1313 6ca938cf jim-p
				$clear_route = true;
1314 91c44185 jim-p
			break;
1315
	}
1316 6ca938cf jim-p
1317 6d0b9fe9 jim-p
	if ($clear_route && !empty($ip) && !empty($mask)) {
1318 6ca938cf jim-p
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $mask);
1319
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1320 615d7f0a Ermal
		/* XXX: Family for route? */
1321 6ca938cf jim-p
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1322
	}
1323 91c44185 jim-p
}
1324
1325 a28d40cb jim-p
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false) {
1326
	$routes = "";
1327
	if (empty($value))
1328
		return "";
1329
	$networks = explode(',', $value);
1330
1331
	foreach ($networks as $network) {
1332
		if ($ipproto == "ipv4")
1333
			$route = openvpn_gen_route_ipv4($network);
1334
		else
1335
			$route = openvpn_gen_route_ipv6($network);
1336
1337
		if ($push)
1338
			$routes .= "push \"{$route}\"\n";
1339
		else
1340
			$routes .= "{$route}\n";
1341
	}
1342
	return $routes;
1343
}
1344
1345
function openvpn_gen_route_ipv4($network) {
1346
	list($ip, $mask) = explode('/', trim($network));
1347
	$mask = gen_subnet_mask($mask);
1348
	return "route $ip $mask";
1349
}
1350
1351
function openvpn_gen_route_ipv6($network) {
1352
	list($ipv6, $prefix) = explode('/', trim($network));
1353
	if (empty($prefix))
1354
		$prefix = "128";
1355
	return "route-ipv6 ${ipv6}/${prefix}";
1356
}
1357
1358 699125b1 jim-p
function openvpn_get_settings($mode, $vpnid) {
1359
	global $config;
1360
1361
	if (is_array($config['openvpn']['openvpn-server'])) {
1362
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1363
			if (isset($settings['disable']))
1364
				continue;
1365
1366
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1367
				return $settings;
1368
		}
1369
	}
1370
1371
	if (is_array($config['openvpn']['openvpn-client'])) {
1372
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1373
			if (isset($settings['disable']))
1374
				continue;
1375
1376
			if ($vpnid != 0 && $vpnid == $settings['vpnid'])
1377
				return $settings;
1378
		}
1379
	}
1380
1381
	return array();
1382
}
1383
1384
function openvpn_restart_by_vpnid($mode, $vpnid) {
1385
	$settings = openvpn_get_settings($mode, $vpnid);
1386
	openvpn_restart($mode, $settings);
1387
}
1388
1389 756720e2 Pierre POMES
?>