Project

General

Profile

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