Project

General

Profile

Download (40.8 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2
/*
3
	openvpn.inc
4
	
5
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
6 afb07cf1 Scott Ullrich
	Copyright (C) 2005 Peter Allgeyer (allgeyer@web.de).
7 5b237745 Scott Ullrich
	All rights reserved.
8
	
9
	Redistribution and use in source and binary forms, with or without
10
	modification, are permitted provided that the following conditions are met:
11
	
12
	1. Redistributions of source code must retain the above copyright notice,
13
	   this list of conditions and the following disclaimer.
14
	
15
	2. Redistributions in binary form must reproduce the above copyright
16
	   notice, this list of conditions and the following disclaimer in the
17
	   documentation and/or other materials provided with the distribution.
18
	
19
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
	POSSIBILITY OF SUCH DAMAGE.
29
*/
30
	
31
/* include all configuration functions */
32
require_once("globals.inc");
33
require_once("config.inc");
34
require_once("functions.inc");
35
36 3c2e5528 Scott Ullrich
function ovpn_configure($reconfigure) {
37 5b237745 Scott Ullrich
	global $config;
38
	if (is_array($config['ovpn']['server']))
39 afb07cf1 Scott Ullrich
		ovpn_server_crl_add();
40
		ovpn_server_ccd_add();
41 3c2e5528 Scott Ullrich
		ovpn_config_server($reconfigure);
42 5b237745 Scott Ullrich
	if (is_array($config['ovpn']['client']))
43
		ovpn_config_client();
44
	return;
45
}
46
47
function ovpn_link_tap() {
48
	/* Add a reference to the tap KLM.  If ref count = 1, load it */
49
	global $g;
50
	
51
	if (!is_file($g['vardb_path'] ."/ovpn_tap_link")){
52
		$link_count = 1;
53
		mwexec("/sbin/kldload if_tap");
54
		$fd = fopen($g['vardb_path'] ."/ovpn_tap_link", 'w');
55
	}
56
	return true;
57
}
58
59
function ovpn_unlink_tap() {
60
	/* Remove a reference to the tap KLM.  If ref count = 0, unload it */
61
	global $g;
62
	
63
	if (!is_file($g['vardb_path'] ."/ovpn_tap_link"))
64
		return false;  //no file, no links so why are we called?
65
		
66
	$fd = fopen($g['vardb_path'] ."/ovpn_tap_link", 'r+');
67 afb07cf1 Scott Ullrich
	$link_count = fread($fd, filesize($g['vardb_path'] ."/ovpn_tap_link"));
68
	$link_count--;
69 5b237745 Scott Ullrich
	fwrite($fd, $link_count);
70
	fclose($fd);
71
		
72
	if ($link_count == 0)
73
		mwexec("/sbin/kldunload if_tap");
74
	return true;
75
}
76
77
/*****************************/	
78 3c2e5528 Scott Ullrich
/*  Server related functions */
79
/*****************************/
80 5b237745 Scott Ullrich
81 3c2e5528 Scott Ullrich
/* Configure the server */
82
function ovpn_config_server($reconfigure) {
83 afb07cf1 Scott Ullrich
	global $config, $g, $d_ovpnsrvdirty_path;
84 3c2e5528 Scott Ullrich
85 2fe54e17 Scott Ullrich
	if($config['ovpn']['server']['tunnel'])
86 3c2e5528 Scott Ullrich
	foreach ($config['ovpn']['server']['tunnel'] as $id => $server) {
87
		/* get tunnel interface */
88
		$tun = $server['tun_iface'];
89
			
90
		if (isset($server['enable'])) {
91
92 afb07cf1 Scott Ullrich
			if ($g['booting']) {
93 3c2e5528 Scott Ullrich
				echo "Starting OpenVPN server $id... ";
94
95 afb07cf1 Scott Ullrich
				/* define configuration options */
96
				ovpn_srv_config_generate($id);
97
98
				/* Start the openvpn daemon */
99
				mwexec("/usr/local/sbin/openvpn {$g['varetc_path']}/ovpn_srv_{$tun}.conf");
100
101
				/* Send the boot message */
102
				echo "done\n";
103
104
				/* next server */
105
				continue;
106
			}
107 4f8e387d Scott Ullrich
			/* restart openvpn daemon if pf is restarted, but not on boot, hence the else if */
108
			else if ( $reconfigure == "pfreload") {
109
				ovpn_server_kill($tun);
110
				mwexec("/usr/local/sbin/openvpn {$g['varetc_path']}/ovpn_srv_{$tun}.conf");
111
				continue;
112
			}
113 afb07cf1 Scott Ullrich
114 3c2e5528 Scott Ullrich
			/* send SIGUSR1 to running openvpn daemon */
115
			if ( $reconfigure == "true" && isset($server['dynip'])) {
116
				sigkillbypid($g['varrun_path']."/ovpn_srv_{$tun}.pid", "SIGUSR1");
117
				continue;
118
			}
119
120 afb07cf1 Scott Ullrich
			/* read dirtyfile */
121
			if (is_readable($d_ovpnsrvdirty_path))
122
				$lines = file($d_ovpnsrvdirty_path);
123
124
			/* reconfigure server */
125 bc5dc421 Scott Ullrich
			if (is_array($lines) && in_array($tun . "\n", $lines)) {
126 afb07cf1 Scott Ullrich
127
				/* kill running server */
128
				ovpn_server_kill($tun);
129
130
				/* remove old certs & keys */
131
				ovpn_server_certs_del($tun);
132 3c2e5528 Scott Ullrich
133 afb07cf1 Scott Ullrich
				/* define configuration options */
134
				ovpn_srv_config_generate($id);
135 707e9964 Scott Ullrich
			}
136
137 3c2e5528 Scott Ullrich
			/* Start the openvpn daemon */
138 afb07cf1 Scott Ullrich
			if (!is_readable("{$g['varrun_path']}/ovpn_srv_{$tun}.pid"))
139
				mwexec("/usr/local/sbin/openvpn {$g['varetc_path']}/ovpn_srv_{$tun}.conf");
140 3c2e5528 Scott Ullrich
141 afb07cf1 Scott Ullrich
			/* next server */
142
			continue;
143 3c2e5528 Scott Ullrich
		}
144
145 afb07cf1 Scott Ullrich
		/* server disabled */
146
		if (!$g['booting']) {
147
			/* kill running server */
148
			ovpn_server_kill($tun);
149
150
			/* Remove old certs & keys */
151
			ovpn_server_certs_del($tun);
152
153
			/* stop any processes, unload the tap module */
154
			//if ($server['type'] == "tap")
155
			//	ovpn_unlink_tap();
156 5b237745 Scott Ullrich
		}
157
	}
158
	return 0;
159
}
160
161 3c2e5528 Scott Ullrich
/* Kill off a running server process */
162 afb07cf1 Scott Ullrich
function ovpn_server_certs_del($tun) {
163 3c2e5528 Scott Ullrich
	global $g;
164
	
165
	/* Remove old certs & keys */
166
	unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem");
167
	unlink_if_exists("{$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem");
168
	unlink_if_exists("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem");
169
	unlink_if_exists("{$g['vardb_path']}/ovpn_dh_{$tun}.pem");
170 707e9964 Scott Ullrich
	unlink_if_exists("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem");
171 afb07cf1 Scott Ullrich
	unlink_if_exists("{$g['varetc_path']}/ovpn_srv_up_{$tun}.sh");
172
	unlink_if_exists("{$g['varetc_path']}/ovpn_srv_{$tun}.conf");
173 3c2e5528 Scott Ullrich
174
	return 0;
175
}
176
177 afb07cf1 Scott Ullrich
/* Kill off a running server process */
178
function ovpn_server_kill($tun) {
179
	global $g;
180
181
	/* kill running server */
182
	killbypid("{$g['varrun_path']}/ovpn_srv_{$tun}.pid");
183
}
184
185 5b237745 Scott Ullrich
/* Generate the config for a OpenVPN server */
186 3c2e5528 Scott Ullrich
function ovpn_srv_config_generate($id) {
187 5b237745 Scott Ullrich
	global $config, $g;
188 3c2e5528 Scott Ullrich
	$server = $config['ovpn']['server']['tunnel'][$id];
189
190 4f8e387d Scott Ullrich
	/* mount filesystem for read/write */
191
	conf_mount_rw();
192
193 3c2e5528 Scott Ullrich
	/* get tunnel interface */
194
	$tun = $server['tun_iface'];
195
196 707e9964 Scott Ullrich
	/* get optional interface name */
197
	$iface = ovpn_get_opt_interface($tun);
198
199 afb07cf1 Scott Ullrich
	/* Copy the TLS-Server certs & keys to disk */
200
	if ($server['authentication_method'] != "pre_shared_key" ) {
201
202
		$fd = fopen("{$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem", "w");
203
		if ($fd) {
204
			fwrite($fd, base64_decode($server['ca_cert'])."\n");
205
			fclose($fd);	
206
		}
207
208
		$fd = fopen("{$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem", "w");
209
		if ($fd) {
210
			fwrite($fd, base64_decode($server['srv_cert'])."\n");
211
			fclose($fd);	
212
		}
213
214
		touch ("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem");
215
		chmod ("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem", 0600);
216
		$fd = fopen("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem", "w");
217
		if ($fd) {
218
			fwrite($fd, base64_decode($server['srv_key'])."\n");
219
			fclose($fd);	
220
		}
221
222
		$fd = fopen("{$g['vardb_path']}/ovpn_dh_{$tun}.pem", "w");
223
		if ($fd) {
224
			fwrite($fd, base64_decode($server['dh_param'])."\n");
225
			fclose($fd);	
226
		}
227
	}
228
229
	if ($server['authentication_method'] == "pre_shared_key" || isset($server['tlsauth'])) {
230
		touch ("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem");
231
		chmod ("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem", 0600);
232
		$fd = fopen("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem", "w");
233
		if ($fd) {
234
			fwrite($fd, base64_decode($server['pre-shared-key'])."\n");
235
			fclose($fd);	
236
		}
237
	}
238
239
	$fd = fopen("{$g['varetc_path']}/ovpn_srv_{$tun}.conf", "w");
240
	if (!$fd) {
241
		printf("Error: cannot open ovpn_srv_{$tun}.conf in ovpn_srv_config_generate($id).\n");
242
		return 1;
243
	}
244
245 5b237745 Scott Ullrich
	/* First the generic stuff:
246
		- We are a server
247
		- We will run without privilege
248
	*/
249 afb07cf1 Scott Ullrich
	$ovpn_config = "";
250
	$ovpn_config .= <<<EOD
251
daemon
252
user nobody
253
group nobody
254
verb {$server['verb']}
255
persist-tun
256
persist-key
257
status /var/log/openvpn_{$tun}.log 60
258
writepid {$g['varrun_path']}/ovpn_srv_{$tun}.pid
259
dev {$server['tun_iface']}
260
port {$server['port']}
261
cipher {$server['crypto']}
262
263
EOD;
264 3c2e5528 Scott Ullrich
265 a068feb2 Scott Ullrich
	/* Set protocol being used (p = udp (default), tcp-server) */
266 afb07cf1 Scott Ullrich
	if ($server['proto'] == "tcp")
267
		$ovpn_config .= "proto tcp-server\n";
268
269 5b237745 Scott Ullrich
	/* Interface binding - 1 or all */
270 afb07cf1 Scott Ullrich
	if ($server['bind_iface'] != 'all')
271 5b237745 Scott Ullrich
		if ($ipaddr = ovpn_get_ip($server['bind_iface']))
272 afb07cf1 Scott Ullrich
			$ovpn_config .= "local {$ipaddr}\n";
273 3c2e5528 Scott Ullrich
274
	/* are we using dynamic ip addresses? */
275
	if (isset($server['dynip']))
276 afb07cf1 Scott Ullrich
		$ovpn_config .= "persist-remote-ip\n";
277
278 bc5dc421 Scott Ullrich
	/* LZO compression (off by default) */
279
	if (isset($server['comp_method'])) {
280
		switch ($server['comp_method']) {
281
282
			case 'lzo':
283
				$ovpn_config .= "comp-lzo\n";
284
				break;
285
			case 'noadapt':
286
				$ovpn_config .= "comp-lzo\n" . "comp-noadapt\n";
287
				break;
288
		}
289
	}
290
291 5b237745 Scott Ullrich
	/* Client to client routing (off by default) */
292
	if (isset($server['cli2cli']))
293 afb07cf1 Scott Ullrich
		$ovpn_config .= "client-to-client\n";
294 707e9964 Scott Ullrich
295 afb07cf1 Scott Ullrich
	/* Limit server to a maximum of n concurrent clients. */
296
	if (!empty($server['maxcli']))
297
		$ovpn_config .= "max-clients {$server['maxcli']}\n";
298 707e9964 Scott Ullrich
299 afb07cf1 Scott Ullrich
	/* Authentication method */
300
	if ($server['authentication_method'] != "pre_shared_key") {
301 707e9964 Scott Ullrich
302 afb07cf1 Scott Ullrich
		$ovpn_config .= <<<EOD
303
client-config-dir {$g['vardb_path']}/ccd
304
ca {$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem
305
cert {$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem
306
key {$g['vardb_path']}/ovpn_srv_key_{$tun}.pem
307
dh {$g['vardb_path']}/ovpn_dh_{$tun}.pem
308
309
EOD;
310
311
		/* CRL list */
312
		if (isset($server['crlname']) &&
313
		    is_readable("{$g['vardb_path']}/{$server['crlname']}.crl.pem")) {
314
			$ovpn_config .= "crl-verify {$g['vardb_path']}/{$server['crlname']}.crl.pem\n";
315 707e9964 Scott Ullrich
		}
316 afb07cf1 Scott Ullrich
317
		/* TLS auth */
318
		if (isset($server['tlsauth']))
319
			$ovpn_config .= "tls-auth {$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem 0\n";
320
321
		/* bridging enabled? */
322
		if ($server['bridge'] && $server['type'] == "tap") {
323
			if ($server['method'] == "ovpn") {
324
				$netmask = gen_subnet_mask($config['interfaces'][$server['bridge']]['subnet']);
325
				$ovpn_config .= "server-bridge {$server['gateway']} {$netmask} {$server['range_from']} {$server['range_to']}\n";
326
			} else {
327
				$ovpn_config .= <<<EOD
328
mode server
329
tls-server
330
331
EOD;
332
			}
333
334
			$lastdigits = substr($tun, 3) + 2;
335
			$ovpn_srv_up = "/sbin/ifconfig " . $tun . " 127.0.0." . $lastdigits . "/32\n";
336
337
			$fdo = fopen("{$g['varetc_path']}/ovpn_srv_up_{$tun}.sh", "w");
338
			if ($fdo) {
339
				fwrite($fdo, $ovpn_srv_up);
340
				fclose($fdo);	
341
				chmod ("{$g['varetc_path']}/ovpn_srv_up_{$tun}.sh", 0755);
342
				$ovpn_config .= "up /var/etc/ovpn_srv_up_{$tun}.sh\n";
343
			}
344
345
		} else {
346
			/* Not bridged, can be tun or tap, doesn't matter */
347
			$netmask = gen_subnet_mask($server['prefix']);
348
349
			if ($server['method'] == "ovpn") {
350
				/* new --server macro simplifies config */
351
				$ovpn_config .= "server {$server['ipblock']} {$netmask}\n";
352
			} else {
353
				$ovpn_config .= <<<EOD
354
mode server
355
tls-server
356
ifconfig {$server['ipblock']} {$netmask}
357
358
EOD;
359
			}
360
		} /* end bridging */
361
362
		/* Duplicate CNs */
363
		if (isset($server['dupcn']))
364
			$ovpn_config .= "duplicate-cn\n";
365
366 bc5dc421 Scott Ullrich
		$push_options = "";
367
	
368
		/* Client push - redirect gateway */
369
		if (isset($server['psh_options']['redir']))  {
370
			if (isset($server['psh_options']['redir_loc']))
371
				$push_config .= "push \"redirect-gateway local\"\n";
372
			else
373
				$push_config .= "push \"redirect-gateway\"\n";
374
		}
375
376
		/* Client push - route delay */
377
		if (isset($server['psh_options']['rte_delay']))
378
			$push_config .= "push \"route-delay {$server['psh_options']['rte_delay_int']}\"\n";
379
380
		/* Client push - ping (note we set both server and client) */
381
		if (isset ($server['psh_options']['ping'])){
382
			$conflict = true;
383
			$interval = $server['psh_options']['ping_int'];
384
			$ovpn_config .= "ping {$server['psh_options']['ping_int']}\n ";
385
			$push_config .= "push \"ping {$server['psh_options']['ping_int']}\"\n";
386
		}
387
388
		/* Client push - ping-restart (note server uses 2 x client interval) */
389
		if (isset ($server['psh_options']['pingrst'])){
390
			$conflict = true;
391
			$interval = $server['psh_options']['pingrst_int'];
392
			$ovpn_config .= "ping-restart " . ($interval * 2) . "\n";
393
			$push_config .= "push \"ping-restart $interval\"\n";
394
		}
395
	
396
		/* Client push - ping-exit (set on client) */
397
		if (isset ($server['psh_options']['pingexit'])){
398
			$conflict = true;
399
			$ovpn_config .= "ping-exit {$server['psh_options']['pingexit_int']}\n";
400
			$push_config .= "push \"ping-exit {$server['psh_options']['pingexit_int']}\"\n";
401
		}
402
403
		/* Client push - inactive (set on client) */
404
		if (isset ($server['psh_options']['inact'])){
405
			$ovpn_config .= "inactive {$server['psh_options']['inact_int']}\n";
406
			$push_config .= "push \"inactive {$server['psh_options']['inact_int']}\"\n";
407
		}
408
409
		if (isset($server['client-to-client']))
410
			$push_config .= "push \"route {$network} {$netmask}\"\n";
411
412
		if (isset($push_config))
413
			$ovpn_config .= $push_config;
414
415 707e9964 Scott Ullrich
	} else {
416 afb07cf1 Scott Ullrich
		/* 'authentication_method' == "pre_shared_key" */
417
		$network = gen_subnet($server['lipaddr'], $server['netmask']);
418
		$netmask = gen_subnet_mask($server['netmask']);
419 707e9964 Scott Ullrich
420 afb07cf1 Scott Ullrich
		$ovpn_config .= "secret {$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem 0\n";
421
422
		if (strstr($server['type'], "tun")) {
423
			$ovpn_config .= "ifconfig {$server['lipaddr']} {$server['ripaddr']}\n";
424
			$ovpn_config .= "route {$network} {$netmask}\n";
425
		} else {
426
			$ovpn_config .= "ifconfig {$server['lipaddr']} {$netmask}\n";
427
		}
428
429
	} /* end authentication_method */
430
431 707e9964 Scott Ullrich
	if (!isset($conflict))
432 afb07cf1 Scott Ullrich
		$ovpn_config .= "keepalive 10 60\n";
433
434
	/* Expert mode paramters */
435
	if (isset($server['expertmode_enabled']) && is_array($server['expertmode'])) {
436
		$ovpn_config .= ";begin expertmode\n";
437
		foreach ($server['expertmode']['option'] as $option) {
438
			$ovpn_config .= "{$option}\n";
439
		}
440
		$ovpn_config .= ";end expertmode\n";
441
	}
442
443
	fwrite($fd, $ovpn_config);
444
	fclose($fd);
445 3c2e5528 Scott Ullrich
446 4f8e387d Scott Ullrich
	/* return from filesystem read/write mode and mount read-only */
447
	conf_mount_ro();
448
449 5b237745 Scott Ullrich
	//trigger_error("OVPN: $ovpn_config", E_USER_NOTICE);
450
}
451
452
/* Define an OVPN Server tunnel interface in the interfaces array and assign a name */
453
function ovpn_server_iface(){
454 767a716e Scott Ullrich
	global $config, $g, $bridge_configure, $filter_configure;
455 afb07cf1 Scott Ullrich
456
	unset($filter_configure);
457
	unset($bridge_configure);
458 5b237745 Scott Ullrich
	
459 3c2e5528 Scott Ullrich
	foreach ($config['ovpn']['server']['tunnel'] as $id => $server) {
460
		if (isset($server['enable'])) {
461
462
			/* get tunnel interface */
463
			$tun = $server['tun_iface'];
464
			
465
			$i = 1;
466
			while (true) {
467
				$ifname = 'opt' . $i;
468
				if (is_array($config['interfaces'][$ifname])) {
469
					if ((isset($config['interfaces'][$ifname]['ovpn']))
470
					     && ($config['interfaces'][$ifname]['ovpn'] == "server_{$tun}"))
471
						/* Already an interface defined - overwrite */
472
						break;
473 afb07cf1 Scott Ullrich
				} else {
474
475 3c2e5528 Scott Ullrich
					/* No existing entry, this is first unused */
476
					$config['interfaces'][$ifname] = array();
477 afb07cf1 Scott Ullrich
478
					/* add new filter rules */
479
					$filter_configure = true;
480 3c2e5528 Scott Ullrich
					break;
481
				}
482
				$i++;
483
			}
484 afb07cf1 Scott Ullrich
			$config['interfaces'][$ifname]['descr'] = strtoupper($server['tun_iface']);
485 3c2e5528 Scott Ullrich
			$config['interfaces'][$ifname]['if'] = $server['tun_iface'];
486 afb07cf1 Scott Ullrich
			if ($server['method'] == "ovpn")
487
				$config['interfaces'][$ifname]['ipaddr'] = long2ip( ip2long($server['ipblock']) + 1);
488
			else
489
				$config['interfaces'][$ifname]['ipaddr'] = $server['ipblock'];
490
			if (isset($server['bridge'])) {
491
				$config['interfaces'][$ifname]['bridge'] = $server['bridge'];
492
				$bridge_configure = true;
493
			} else if (isset($config['interfaces'][$ifname]['bridge'])) {
494
				/* bridge config removed */
495
				unset ($config['interfaces'][$ifname]['bridge']);
496
				$bridge_configure = true;
497
			}
498 3c2e5528 Scott Ullrich
			$config['interfaces'][$ifname]['subnet'] = $server['prefix'];
499
			$config['interfaces'][$ifname]['enable'] = isset($server['enable']) ? true : false;
500
			$config['interfaces'][$ifname]['ovpn'] = "server_{$tun}";
501
502
			write_config();
503 5b237745 Scott Ullrich
		}
504 3c2e5528 Scott Ullrich
	}
505 afb07cf1 Scott Ullrich
506
	/* do we have to reconfigure filter rules? */
507
	if (isset($bridge_configure))
508
		interfaces_optional_configure();
509
	else if (isset($filter_configure))
510
		filter_configure();
511
512 3c2e5528 Scott Ullrich
	return "OpenVPN server interface defined";
513
}
514
515
/* Delete a server interface definition */
516
function ovpn_server_iface_del($tun) {
517
	global $config;
518
519
	for ($i = 1; is_array($config['interfaces']['opt' . $i]); $i++) {
520
		$ifname = 'opt' . $i;
521
		if ((isset($config['interfaces'][$ifname]['ovpn']))
522
		     && ($config['interfaces'][$ifname]['if'] == "$tun")) {
523
			unset($config['interfaces'][$ifname]);
524 5b237745 Scott Ullrich
			break;
525
		}
526 3c2e5528 Scott Ullrich
	}
527
528
	/* shift down other OPTn interfaces to get rid of holes */
529
	$i++;
530
531
	/* look at the following OPTn ports */
532
	while (is_array($config['interfaces']['opt' . $i])) {
533
		$config['interfaces']['opt' . ($i - 1)] =
534
			$config['interfaces']['opt' . $i];
535
536
		unset($config['interfaces']['opt' . $i]);
537 5b237745 Scott Ullrich
		$i++;
538
	}
539 afb07cf1 Scott Ullrich
540
	/* reconfigure filter rules */
541
	interfaces_optional_configure();
542 5b237745 Scott Ullrich
}
543
544 afb07cf1 Scott Ullrich
/* Add client config file */
545
function ovpn_server_ccd_add() {
546
	global $config, $g;
547 3c2e5528 Scott Ullrich
548 afb07cf1 Scott Ullrich
	if (is_array($config['ovpn']['server']['ccd'])) {
549
		foreach ($config['ovpn']['server']['ccd'] as $id => $server) {
550
			/* define configuration options */
551
			ovpn_server_ccd_generate($id);
552
		}
553
	}
554
}
555 3c2e5528 Scott Ullrich
556 afb07cf1 Scott Ullrich
557
/* Construct client config file */
558
function ovpn_server_ccd_generate($id) {
559
	global $config, $g;
560
	$ovpnccd = $config['ovpn']['server']['ccd'][$id];
561
562
	$cn = $ovpnccd['cn'];
563
	$ccd_config = "";
564
        $push_options = "";
565
        
566
	/* Push reset */
567
	if (!isset($ovpnccd['disable']) && isset($ovpnccd['psh_reset']))  {
568
		$ccd_config .= "push-reset\n";
569
570
		/* Client push - redirect gateway */
571
		if (isset($ovpnccd['psh_options']['redir']))  {
572
			if (isset($ovpnccd['psh_options']['redir_loc']))
573
				$push_config .= "push \"redirect-gateway local\"\n";
574
			else
575
				$push_config .= "push \"redirect-gateway\"\n";
576
		}
577
578
		/* Client push - route delay */
579
		if (isset($ovpnccd['psh_options']['rte_delay']))
580
			$push_config .= "push \"route-delay {$ovpnccd['psh_options']['rte_delay_int']}\"\n";
581
582
		/* Client push - ping (note we set both server and client) */
583
		if (isset ($ovpnccd['psh_options']['ping'])){
584
			$ccd_config .= "ping {$server['psh_options']['ping_int']}\n ";
585
			$push_config .= "push \"ping {$ovpnccd['psh_options']['ping_int']}\"\n";
586
		}
587
588
		/* Client push - ping-restart (note server uses 2 x client interval) */
589
		if (isset ($ovpnccd['psh_options']['pingrst'])){
590
			$interval = $ovpnccd['psh_options']['pingrst_int'];
591
			$ccd_config .= "ping-restart " . ($interval * 2) . "\n";
592
			$push_config .= "push \"ping-restart $interval\"\n";
593
		}
594
595
		/* Client push - ping-exit (set on client) */
596
		if (isset ($ovpnccd['psh_options']['pingexit'])){
597
			$ccd_config .= "ping-exit {$ovpnccd['psh_options']['pingexit_int']}\n";
598
			$push_config .= "push \"ping-exit {$ovpnccd['psh_options']['pingexit_int']}\"\n";
599
		}
600
601
		/* Client push - inactive (set on client) */
602
		if (isset ($ovpnccd['psh_options']['inact'])){
603
			$ccd_config .= "inactive {$ovpnccd['psh_options']['inact_int']}\n";
604
			$push_config .= "push \"inactive {$ovpnccd['psh_options']['inact_int']}\"\n";
605
		}
606
607
		if (isset($push_config))
608
			$ccd_config .= $push_config;
609
	}
610
611
        if (!isset($ovpnccd['disable']) && is_array($ovpnccd['options'])) {
612
                foreach ($ovpnccd['options']['option'] as $option) {
613
                        $ccd_config .= "{$option}\n";
614
                }
615
        }
616
617
	/* Disable client from connecting */
618
	if (isset($ovpnccd['disable']))
619
		$ccd_config = "disable\n";
620
621
	unlink_if_exists("{$g['vardb_path']}/ccd/{$cn}");
622
623
	if (isset($ccd_config) && isset($ovpnccd['enable'])) {
624
		$fd = fopen("{$g['vardb_path']}/ccd/{$cn}", "w");
625
		if ($fd) {
626
			fwrite($fd, $ccd_config."\n");
627
			fclose($fd);    
628 3c2e5528 Scott Ullrich
		}
629
	}
630
}
631
632 afb07cf1 Scott Ullrich
/* Delete client config file */
633
function ovpn_server_ccd_del($cn) {
634
	global $g;
635
	
636
	unlink_if_exists("{$g['vardb_path']}/ccd/{$cn}");
637
	return 0;
638
}
639
640
/* Add CRL file */
641
function ovpn_server_crl_add() {
642
	global $config, $g, $d_ovpncrldirty_path;
643
644
	if (is_array($config['ovpn']['server']['crl'])) {
645
		foreach ($config['ovpn']['server']['crl'] as $id => $crlent) {
646
			/* get crl file name */
647
			$name = $crlent['crlname'];
648
649
			if (isset($crlent['enable'])) {
650
			
651
				/* add file */
652
				ovpn_server_crl_generate($id);
653
654
				if ($g['booting']) {
655
					/* next crl file */
656
					continue;
657
				}
658
				
659
				/* read dirtyfile */
660
				if (is_readable($d_ovpncrldirty_path))
661
					$lines = file($d_ovpncrldirty_path);
662
663
				/* reconfigure crl file */
664 bc5dc421 Scott Ullrich
				if (is_array($lines) && in_array($name . "\n", $lines)) {
665 afb07cf1 Scott Ullrich
666
					/* restart running openvpn daemon */
667
					foreach ($config['ovpn']['server']['tunnel'] as $id => $server) {
668
						$tun = $server['tun_iface'];
669
670
						if ($server['enable'] &&
671
						    isset($server['crlname']) && $server['crlname'] == $name)
672
							/* kill running server */
673
							ovpn_server_kill($tun);
674
675
							/* Start the openvpn daemon */
676
							mwexec("/usr/local/sbin/openvpn {$g['varetc_path']}/ovpn_srv_{$tun}.conf");
677
					}
678
679
				}
680
			
681
				/* next crl file */
682
				continue;
683 3c2e5528 Scott Ullrich
			}
684 afb07cf1 Scott Ullrich
			
685
			/* crl file disabled: remove file */
686
			ovpn_server_crl_del($name);
687 3c2e5528 Scott Ullrich
		}
688
	}
689 afb07cf1 Scott Ullrich
	return 0;
690 3c2e5528 Scott Ullrich
}
691
692 afb07cf1 Scott Ullrich
/* Write CRL to file */
693
function ovpn_server_crl_generate($id) {
694
	global $config, $g;
695
696
	$ovpncrl = $config['ovpn']['server']['crl'][$id];
697
698
	$fd = fopen("{$g['vardb_path']}/{$ovpncrl['crlname']}.crl.pem", "w");
699
	if ($fd) {
700
		fwrite($fd, base64_decode($ovpncrl['crl_list'])."\n");
701
		fclose($fd);
702
	}
703
}
704
705
/* Delete CRL file */
706
function ovpn_server_crl_del($name) {
707
	global $config, $g;
708
709
	/* have to wipe out the crl from the server config */
710
	foreach ($config['ovpn']['server']['tunnel'] as $id => $server) {
711
		if (isset($server['crlname']) && $server['crlname'] == $name) {
712
713
			/* get tunnel interface */
714
			$tun = $server['tun_iface'];
715
716
			/* remove crl file entry */
717
			unset($config['ovpn']['server']['tunnel'][$id]['crlname']);
718
			write_config();
719
			
720
			/* kill running server */
721
			ovpn_server_kill($tun);
722
723
			/* remove old certs & keys */
724
			ovpn_server_certs_del($tun);
725
			
726
			/* reconfigure daemon */
727
			ovpn_srv_config_generate($id);
728
729
			/* Start the openvpn daemon */
730
			mwexec("/usr/local/sbin/openvpn {$g['varetc_path']}/ovpn_srv_{$tun}.conf");
731
		}
732
	}
733
734
	unlink_if_exists("{$g['vardb_path']}/{$name}.crl.pem");
735
	return 0;
736
}
737
738
739
/* Get a list of crl files */
740
function ovpn_get_crl_list() {
741 3c2e5528 Scott Ullrich
	global $config;
742 afb07cf1 Scott Ullrich
743
	$crl_list = array();
744
745
	if (is_array($config['ovpn']['server']['crl'])) {
746
		foreach ($config['ovpn']['server']['crl'] as $crlent) {
747
			if (isset($crlent['enable']))
748
				$crl_list[] = $crlent['crlname'];
749 3c2e5528 Scott Ullrich
		}
750
	}
751 afb07cf1 Scott Ullrich
	return $crl_list;
752
}
753
754
/* append interface to $_ovpnsrvdirty_path */
755
function ovpn_srv_dirty($tun) {
756
	global $d_ovpnsrvdirty_path;
757
	
758
	$fd = fopen($d_ovpnsrvdirty_path, 'a');
759
	if ($fd) {
760 bc5dc421 Scott Ullrich
		fwrite($fd, $tun ."\n");
761 afb07cf1 Scott Ullrich
		fclose($fd);
762
	}
763 3c2e5528 Scott Ullrich
}
764
765 afb07cf1 Scott Ullrich
/* append file name to $_ovpncrldirty_path */
766
function ovpn_crl_dirty($name) {
767
	global $d_ovpncrldirty_path;
768
	
769
	$fd = fopen($d_ovpncrldirty_path, 'a');
770
	if ($fd) {
771 bc5dc421 Scott Ullrich
		fwrite($fd, $name ."\n");
772 afb07cf1 Scott Ullrich
		fclose($fd);
773
	}
774
}
775
776
777
/****************************/
778
/* Client related functions */
779
/****************************/
780
781 5b237745 Scott Ullrich
function ovpn_config_client() {
782
	/* Boot time configuration */
783 4f8e387d Scott Ullrich
	global $config, $g, $d_ovpnclidirty_path;
784 5b237745 Scott Ullrich
	
785
	foreach ($config['ovpn']['client']['tunnel'] as $id => $client) {
786 3c2e5528 Scott Ullrich
787
		/* get tunnel interface */
788
		$tun = $client['if'];
789
790 5b237745 Scott Ullrich
		if (isset($client['enable'])) {
791 afb07cf1 Scott Ullrich
792
			if ($g['booting']) {
793 5b237745 Scott Ullrich
				echo "Starting OpenVPN client $id... ";
794
		
795 afb07cf1 Scott Ullrich
				/* define configuration options */
796
				ovpn_cli_config_generate($id);
797
798
				/* Start openvpn for this client */
799
				mwexec("/usr/local/sbin/openvpn {$g['varetc_path']}/ovpn_cli_{$tun}.conf");
800 5b237745 Scott Ullrich
		
801
				/* Send the boot message */
802 3c2e5528 Scott Ullrich
				echo "done\n";
803 afb07cf1 Scott Ullrich
804
				/* next client */
805
				continue;
806
			}
807
808
			/* read dirtyfile */
809
			if (is_readable($d_ovpnclidirty_path))
810
				$lines = file($d_ovpnclidirty_path);
811
812
			/* reconfigure client */
813 bc5dc421 Scott Ullrich
			if (is_array($lines) && in_array($tun . "\n", $lines)) {
814 afb07cf1 Scott Ullrich
815
				/* kill running client */
816 3c2e5528 Scott Ullrich
				ovpn_client_kill($tun);
817
818 afb07cf1 Scott Ullrich
				/* remove old certs & keys */
819
				ovpn_client_certs_del($tun);
820
821
				/* define configuration options */
822
				ovpn_cli_config_generate($id);
823 5b237745 Scott Ullrich
			}
824 afb07cf1 Scott Ullrich
825
			/* Start the openvpn daemon */
826
			if (!is_readable("{$g['varrun_path']}/ovpn_cli_{$tun}.pid"))
827
				mwexec("/usr/local/sbin/openvpn {$g['varetc_path']}/ovpn_cli_{$tun}.conf");
828
829
			/* next client */
830
			continue;
831
		}
832
833
		/* client disabled */
834
		if (!$g['booting']) {
835
			/* kill running client */
836
			ovpn_client_kill($tun);
837
			
838
			/* remove old certs & keys */
839
			ovpn_client_certs_del($tun);
840
841
			/* stop any processes, unload the tap module */
842
			//if ($client['type'] == "tap")
843
			//	ovpn_unlink_tap();
844 5b237745 Scott Ullrich
		}
845
	}
846
	return 0;
847
}
848
849
/* Kill off a running client process */
850 afb07cf1 Scott Ullrich
function ovpn_client_certs_del($tun) {
851 5b237745 Scott Ullrich
	global $g;
852
	
853 3c2e5528 Scott Ullrich
	/* Remove old certs & keys */
854
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem");
855
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem");
856
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem");
857 707e9964 Scott Ullrich
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem");
858 afb07cf1 Scott Ullrich
	unlink_if_exists("{$g['varetc_path']}/ovpn_cli_up_{$tun}.pem");
859
	unlink_if_exists("{$g['varetc_path']}/ovpn_cli_{$tun}.conf");
860 3c2e5528 Scott Ullrich
861 5b237745 Scott Ullrich
	return 0;
862
}
863
864 afb07cf1 Scott Ullrich
/* Kill off a running client process */
865
function ovpn_client_kill($tun) {
866
	global $g;
867
868
	/* kill running client */
869
	killbypid("{$g['varrun_path']}/ovpn_cli_{$tun}.pid");
870
}
871
872 3c2e5528 Scott Ullrich
/* Generate the config for a OpenVPN client */
873 5b237745 Scott Ullrich
function ovpn_cli_config_generate($id) {
874
	/* configure the named client */
875
	global $config, $g;
876 3c2e5528 Scott Ullrich
	$client = $config['ovpn']['client']['tunnel'][$id];
877
878
	/* get tunnel interface */
879
	$tun = $client['if'];
880 afb07cf1 Scott Ullrich
881 707e9964 Scott Ullrich
	/* get optional interface name */
882
	$iface = ovpn_get_opt_interface($tun);
883
884 afb07cf1 Scott Ullrich
	/* Copy the TLS-Client certs & keys to disk */
885
	if ($client['authentication_method'] != "pre_shared_key" ) {
886
887
		$fd = fopen("{$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem", "w");
888
		if ($fd) {
889
			fwrite($fd, base64_decode($client['ca_cert'])."\n");
890
			fclose($fd);	
891
		}
892
893
		$fd = fopen("{$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem", "w");
894
		if ($fd) {
895
			fwrite($fd, base64_decode($client['cli_cert'])."\n");
896
			fclose($fd);	
897
		}
898
899
		touch ("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem");
900
		chmod ("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem", 0600);
901
		$fd = fopen("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem", "w");
902
		if ($fd) {
903
			fwrite($fd, base64_decode($client['cli_key'])."\n");
904
			fclose($fd);	
905
		}
906 3c2e5528 Scott Ullrich
	}
907 707e9964 Scott Ullrich
908 afb07cf1 Scott Ullrich
	if ($client['authentication_method'] == "pre_shared_key" || isset($client['tlsauth'])) {
909
		touch ("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem");
910
		chmod ("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem", 0600);
911
		$fd = fopen("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem", "w");
912 707e9964 Scott Ullrich
		if ($fd) {
913 afb07cf1 Scott Ullrich
			fwrite($fd, base64_decode($client['pre-shared-key'])."\n");
914
			fclose($fd);	
915 707e9964 Scott Ullrich
		}
916
	}
917
918 afb07cf1 Scott Ullrich
	$fd = fopen("{$g['varetc_path']}/ovpn_cli_{$tun}.conf", "w");
919
	if (!$fd) {
920
		printf("Error: cannot open ovpn_cli_{$tun}.conf in ovpn_cli_config_generate($id).\n");
921
		return 1;
922
	}
923
924
	/* Client support in 2.0 is very simple */
925
	$ovpn_config = "";
926
	$ovpn_config .= <<<EOD
927
daemon
928
verb 1
929
status /var/log/openvpn_{$tun}.log 60
930
writepid {$g['varrun_path']}/ovpn_cli_{$tun}.pid
931
dev {$client['if']}
932
lport {$client['cport']}
933
remote {$client['saddr']} {$client['sport']}
934
cipher {$client['crypto']}
935
936
EOD;
937
938
	/* Version 1.0 compatibility; http://openvpn.net/compat.html */
939
	if ($client['ver'] != "2") {
940
		$ovpn_config .= <<<EOD
941
key-method 1
942
tun-mtu 1500
943
tun-mtu-extra 32
944
mssfix 1450
945
946
EOD;
947
	}
948
949
	/* Set protocol being used (p = udp (default), tcp-client) */
950
	if ($client['proto'] == "tcp")
951
		$ovpn_config .= "proto tcp-client\n";
952
953 707e9964 Scott Ullrich
	/* TLS-Client params */
954 afb07cf1 Scott Ullrich
	if ($client['authentication_method'] != "pre_shared_key") {
955
		$ovpn_config .= <<<EOD
956
ca {$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem
957
cert {$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem
958
key {$g['vardb_path']}/ovpn_cli_key_{$tun}.pem
959 707e9964 Scott Ullrich
960 afb07cf1 Scott Ullrich
EOD;
961 707e9964 Scott Ullrich
962 afb07cf1 Scott Ullrich
		if (isset($client['pull']))
963
			$ovpn_config .= "client\n";
964
		else
965
			$ovpn_config .= "tls-client\n";
966
967
		/* TLS auth */
968
		if (isset($client['ns_cert_type']))
969
			$ovpn_config .= "ns-cert-type server\n";
970
971
		/* TLS auth */
972
		if (isset($client['tlsauth']))
973
			$ovpn_config .= "tls-auth {$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem 1\n";
974
975
		/* bridging enabled? */
976
		if ($client['bridge'] && $client['type'] == "tap") {
977
			$lastdigits = substr($tun, 3) + 2;
978
			$ovpn_cli_up = "/sbin/ifconfig " . $tun . " 127.0.0." . $lastdigits . "/32\n";
979
980
			$fdo = fopen("{$g['varetc_path']}/ovpn_cli_up_{$tun}.sh", "w");
981
			if ($fdo) {
982
				fwrite($fdo, $ovpn_cli_up);
983
				fclose($fdo);   
984
				chmod ("{$g['varetc_path']}/ovpn_cli_up_{$tun}.sh", 0755);
985
				$ovpn_config .= "up /var/etc/ovpn_cli_up_{$tun}.sh\n";
986
			}
987
		}
988
989
	} else {
990
		/* 'authentication_method' == "pre_shared_key" */
991
		$ovpn_config .= "secret {$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem 0\n";
992
993
		$network = gen_subnet($client['lipaddr'], $client['netmask']);
994
		$netmask = gen_subnet_mask($client['netmask']);
995
996
		if (strstr($client['type'], "tap"))
997
			$ovpn_config .= "ifconfig {$client['lipaddr']} {$netmask}\n";
998
		else
999
			$ovpn_config .= "ifconfig {$client['lipaddr']} {$client['ripaddr']}\n";
1000
1001
	} /* end authentication_method */
1002
1003 bc5dc421 Scott Ullrich
	/* LZO compression (off by default) */
1004
	if (isset($client['comp_method'])) {
1005
		switch ($client['comp_method']) {
1006
1007
			case 'lzo':
1008
				$ovpn_config .= "comp-lzo\n";
1009
				break;
1010
			case 'noadapt':
1011
				$ovpn_config .= "comp-lzo\n" . "comp-noadapt\n";
1012
				break;
1013
		}
1014
	}
1015
1016 afb07cf1 Scott Ullrich
	/* Expert mode paramters */
1017
	if (isset($client['expertmode_enabled']) && is_array($client['expertmode'])) {
1018
		$ovpn_config .= ";begin expertmode\n";
1019
		foreach ($client['expertmode']['option'] as $option) {
1020
			$ovpn_config .= "{$option}\n";
1021
		}
1022
		$ovpn_config .= ";end expertmode\n";
1023
	}
1024
1025
	fwrite($fd, $ovpn_config);
1026
	fclose($fd);
1027
1028
	/* trigger_error("OVPN: $ovpn_config", E_USER_NOTICE); */
1029 5b237745 Scott Ullrich
}
1030
1031
/* Define an OVPN tunnel interface in the interfaces array for each client */
1032
function ovpn_client_iface(){
1033 767a716e Scott Ullrich
	global $config, $filter_configure, $bridge_configure;
1034 5b237745 Scott Ullrich
		
1035 afb07cf1 Scott Ullrich
	unset($filter_configure);
1036
	unset($bridge_configure);
1037
1038 5b237745 Scott Ullrich
	foreach ($config['ovpn']['client']['tunnel'] as $id => $client) {
1039
		if (isset($client['enable'])) {
1040 3c2e5528 Scott Ullrich
1041
			/* get tunnel interface */
1042
			$tun = $client['if'];
1043
1044 5b237745 Scott Ullrich
			$i = 1;
1045
			while (true) {
1046
				$ifname = 'opt' . $i;
1047
				if (is_array($config['interfaces'][$ifname])) {
1048
					if ((isset($config['interfaces'][$ifname]['ovpn']))
1049 3c2e5528 Scott Ullrich
			     		     && ($config['interfaces'][$ifname]['ovpn'] == "client_{$tun}"))
1050 5b237745 Scott Ullrich
						/* Already an interface defined - overwrite */
1051
						break;
1052 afb07cf1 Scott Ullrich
				} else {
1053
1054 5b237745 Scott Ullrich
					/* No existing entry, this is first unused */
1055
					$config['interfaces'][$ifname] = array();
1056 afb07cf1 Scott Ullrich
1057
					/* add new filter rules */
1058
					$filter_configure = true;
1059 5b237745 Scott Ullrich
					break;
1060
				}
1061
				$i++;
1062
			}
1063 afb07cf1 Scott Ullrich
			$config['interfaces'][$ifname]['descr'] = strtoupper($client['if']);
1064 5b237745 Scott Ullrich
			$config['interfaces'][$ifname]['if'] = $client['if'];
1065
			$config['interfaces'][$ifname]['ipaddr'] = "0.0.0.0";
1066
			$config['interfaces'][$ifname]['subnet'] = "0";
1067 afb07cf1 Scott Ullrich
			if (isset($client['bridge'])) {
1068
				$config['interfaces'][$ifname]['bridge'] = $client['bridge'];
1069
				$bridge_configure = true;
1070
			} else if (isset($config['interfaces'][$ifname]['bridge'])) {
1071
				/* bridge config removed */
1072
				unset ($config['interfaces'][$ifname]['bridge']);
1073
				$bridge_configure = true;
1074
			}
1075 5b237745 Scott Ullrich
			$config['interfaces'][$ifname]['enable'] = isset($client['enable']) ? true : false;
1076 3c2e5528 Scott Ullrich
			$config['interfaces'][$ifname]['ovpn'] = "client_{$tun}";
1077 5b237745 Scott Ullrich
			write_config();
1078
		}
1079
	}
1080 afb07cf1 Scott Ullrich
1081
	/* do we have to reconfigure filter rules? */
1082
	if (isset($bridge_configure))
1083
		interfaces_optional_configure();
1084
	else if (isset($filter_configure))
1085
		filter_configure();
1086
1087 5b237745 Scott Ullrich
	return "OpenVPN client interfaces defined";
1088
}
1089
1090
/* Delete a client interface definition */
1091 3c2e5528 Scott Ullrich
function ovpn_client_iface_del($tun) {
1092 5b237745 Scott Ullrich
	global $config;
1093 3c2e5528 Scott Ullrich
1094
	for ($i = 1; is_array($config['interfaces']['opt' . $i]); $i++) {
1095 5b237745 Scott Ullrich
		$ifname = 'opt' . $i;
1096 3c2e5528 Scott Ullrich
		if ((isset($config['interfaces'][$ifname]['ovpn']))
1097
		     && ($config['interfaces'][$ifname]['if'] == "$tun")) {
1098
			unset($config['interfaces'][$ifname]);
1099
			break;
1100 5b237745 Scott Ullrich
		}
1101
	}
1102 3c2e5528 Scott Ullrich
1103
	/* shift down other OPTn interfaces to get rid of holes */
1104
	$i++;
1105
1106
	/* look at the following OPTn ports */
1107
	while (is_array($config['interfaces']['opt' . $i])) {
1108
		$config['interfaces']['opt' . ($i - 1)] =
1109
			$config['interfaces']['opt' . $i];
1110
1111
		unset($config['interfaces']['opt' . $i]);
1112
		$i++;
1113
	}
1114 afb07cf1 Scott Ullrich
1115
	/* reconfigure filter rules */
1116
	interfaces_optional_configure();
1117
}
1118
1119
/* append interface to ovpndirty_path */
1120
function ovpn_cli_dirty($tun) {
1121
	global $d_ovpnclidirty_path;
1122
	
1123
	$fd = fopen($d_ovpnclidirty_path, 'a');
1124
	if ($fd) {
1125 bc5dc421 Scott Ullrich
		fwrite($fd, $tun . "\n");
1126 afb07cf1 Scott Ullrich
		fclose($fd);
1127
	}
1128 5b237745 Scott Ullrich
}
1129
1130 3c2e5528 Scott Ullrich
1131 5b237745 Scott Ullrich
/******************/
1132
/* Misc functions */
1133 afb07cf1 Scott Ullrich
/******************/
1134
1135
/* find the first available device of type $type */
1136
function getnxt_if($type) {
1137
	global $config;
1138
1139
	/* initialize variables */
1140
	$iface_list	= array();
1141
	$max		= ($type == 'tun') ? 17 : 4;
1142
1143
	/* construct list of valid interfaces */
1144
	for ($i = 0; $i < $max ; $i++)
1145
		array_push($iface_list, $type . $i);
1146
	
1147
	/* delete interface in use from the list */
1148
	if ($a_server = $config['ovpn']['server']['tunnel']) {
1149
		foreach ($a_server as $server) {
1150
			$entry = array();
1151
			array_push($entry, $server['tun_iface']);
1152
			$iface_list = array_diff($iface_list, $entry);
1153
		}
1154
	}
1155
1156
	/* same for list of client tunnels  */
1157
	if ($a_client = $config['ovpn']['client']['tunnel']) {
1158
		foreach ($a_client as $client) {
1159
			$entry = array();
1160
			array_push($entry, $client['if']);
1161
			$iface_list = array_diff($iface_list, $entry);
1162
		}
1163
	}
1164
			
1165
	/* return first element of list, if list of interfaces isn't empty */
1166
	if (count($iface_list))
1167
		return array_shift($iface_list);
1168
	else
1169
		return false;
1170
}
1171
1172
/* find the next best available port */
1173
function getnxt_port() {
1174
1175
	/* construct list of valid ports */
1176
	$port_list = free_port_list();
1177
1178
        /* return first element of list, if list of ports isn't empty */
1179
        if (count($port_list))
1180
                return array_shift($port_list);
1181
        else
1182
                return false;
1183
}
1184
1185
/* construct list of free ports */
1186
function free_port_list() {
1187
	global $config;
1188
1189
	/* initialize variables */
1190
	$port_list	= array();
1191
	$first_port 	= 1194;
1192
	$max		= $first_port + 21;
1193
1194
	for ($i = $first_port; $i < $max; $i++)
1195
		array_push($port_list, $i);
1196
        
1197
        /* delete port in use from the list */
1198
        if ($a_server = $config['ovpn']['server']['tunnel']) {
1199
                foreach ($a_server as $server) {
1200
                        $entry = array();
1201
                        array_push($entry, $server['port']);
1202
                        $port_list = array_diff($port_list, $entry);
1203
                }
1204
        }
1205
1206
        /* same for list of client tunnels  */
1207
        if ($a_client = $config['ovpn']['client']['tunnel']) {
1208
                foreach ($a_client as $client) {
1209
                        $entry = array();
1210
                        array_push($entry, $client['cport']);
1211
                        $port_list = array_diff($port_list, $entry);
1212
                }
1213
        }
1214
1215
	return $port_list;
1216
}
1217
1218
/* construct list of used ports */
1219
function used_port_list() {
1220
	global $config;
1221
1222
	/* initialize variables */
1223
	$port_list	= array();
1224
1225
        /* add used ports to the list */
1226
        if ($a_server = $config['ovpn']['server']['tunnel']) {
1227
                foreach ($a_server as $server) {
1228
                        if (isset($server['enable']))
1229
				array_push($port_list, $server['port']);
1230
                }
1231
        }
1232
1233
        /* same for list of client tunnels  */
1234
        if ($a_client = $config['ovpn']['client']['tunnel']) {
1235
                foreach ($a_client as $client) {
1236
                        if (isset($client['enable']))
1237
                        	array_push($port_list, $client['cport']);
1238
                }
1239
        }
1240
1241
	return $port_list;
1242
}
1243
1244
/* construct list of bindings used for a specified port */
1245
function used_bind_list($port) {
1246
	global $config;
1247
1248
	/* initialize variables */
1249
	$bind_list	= array();
1250
1251
        /* add used bindings to the list */
1252
        if ($a_server = $config['ovpn']['server']['tunnel']) {
1253
                foreach ($a_server as $server) {
1254
                        if (isset($server['enable']) && $server['port'] == $port)
1255
				array_push($bind_list, $server['bind_iface']);
1256
                }
1257
        }
1258
1259
	/* client daemon always binds to 0.0.0.0 */
1260
	if ($a_client = $config['ovpn']['client']['tunnel']) {
1261
		foreach ($a_client as $client) {
1262
			if (isset($client['enable']) && $client['cport'] == $port)
1263
				array_push($bind_list, "all");
1264
		}
1265
	}
1266
1267
	/* return list of bindings */
1268
	return $bind_list;
1269
}
1270 5b237745 Scott Ullrich
1271
/* Calculate the last address in a range given the start and /prefix */
1272
function ovpn_calc_end($start, $prefix){
1273
	$first = ip2long($start);
1274
	$last = pow(2,(32 - $prefix)) - 1 + $first;
1275
	return long2ip($last);
1276
}
1277
1278
/* Calculate a mask given a /prefix */
1279
function ovpn_calc_mask($prefix){
1280
	return long2ip(ip2long("255.255.255.255") - (pow( 2, (32 - $prefix)) - 1));
1281
}
1282
1283 3c2e5528 Scott Ullrich
/* Port in use */
1284
function ovpn_port_inuse_server($port){
1285
	global $config;
1286 afb07cf1 Scott Ullrich
	if ($a_server = $config['ovpn']['server']['tunnel']) {
1287
		foreach ($a_server as $server) {
1288
			if ($server['port'] == $port) {
1289
				return true;
1290
			}
1291 3c2e5528 Scott Ullrich
		}
1292
	}
1293
	return false;
1294
}
1295
1296 5b237745 Scott Ullrich
/* Read in a file from the $_FILES array */
1297
function ovpn_get_file($file){
1298
	global $g;
1299
	
1300
	if (!is_uploaded_file($_FILES[$file]['tmp_name'])){
1301
		trigger_error("Bad file upload".$_FILES[$file]['error'], E_USER_NOTICE);
1302
		return NULL;
1303
	}
1304
	$contents = file_get_contents($_FILES[$file]['tmp_name']);
1305
	return $contents;
1306
}
1307
1308
1309
/* Get the IP address of a specified interface */
1310
function ovpn_get_ip($iface){
1311
	global $config;
1312
	
1313
	if ($iface == 'wan')
1314
		return get_current_wan_address();
1315
		
1316
	if ($config['interfaces'][$iface]['bridge'])
1317
		/* No bridging (yet) */
1318
		return false;
1319
	return $config['interfaces'][$iface]['ipaddr'];
1320
}
1321
	
1322 707e9964 Scott Ullrich
	
1323 5b237745 Scott Ullrich
/* Get a list of the cipher options supported by OpenVPN */
1324
function ovpn_get_cipher_list(){
1325
	
1326
/*	exec("/usr/local/sbin/openvpn --show-ciphers", $raw);
1327
	print_r ($raw);
1328
	
1329
	$ciphers = preg_grep('/ bit default key /', $raw);
1330
	
1331
	for($i = 0; $i <count($ciphers); $i++){
1332
		$tmp = explode(' ',$ciphers[$i]);
1333
		$cipher_list["$tmp[0]"] = "{$tmp[0]} ({$tmp[1]} {$tmp[2]})";
1334
	}
1335
*/
1336
	$cipher_list = array('DES-CBC' => 'DES-CBC (64 bit)',
1337
			     'RC2-CBC' => 'RC2-CBC (128 bit)',
1338
			     'DES-EDE-CBC' => 'DES-EDE-CBC (128 bit)',
1339
			     'DES-EDE3-CBC' => 'DES-EDE3-CBC (192 bit)',
1340
			     'DESX-CBC' => 'DESX-CBC (192 bit)',
1341
			     'BF-CBC' => 'BF-CBC (128 bit)',
1342
			     'RC2-40-CBC' => 'RC2-40-CBC (40 bit)',
1343
			     'CAST5-CBC' => 'CAST5-CBC (128 bit)',
1344
			     'RC5-CBC' => 'RC5-CBC (128 bit)',
1345
			     'RC2-64-CBC' => 'RC2-64-CBC (64 bit)',
1346
			     'AES-128-CBC' => 'AES-128-CBC (128 bit)',
1347
			     'AES-192-CBC' => 'AES-192-CBC (192 bit)',
1348
			     'AES-256-CBC' => 'AES-256-CBC (256 bit)');
1349
	return $cipher_list;
1350
}
1351
		
1352
	
1353 707e9964 Scott Ullrich
/* Get optional interface */
1354
/* needs tunneling interface (tun0, tun1, tap0, ...) */
1355
/* returns optional interface name (opt2, opt3, ...) */
1356
function ovpn_get_opt_interface($tun){
1357
	global $config;
1358
1359
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
1360
		$ifname = 'opt' . $i;
1361
1362
		if (isset($config['interfaces']['opt' . $i]['ovpn']))
1363
			if ($config['interfaces'][$ifname]['if'] == "$tun")
1364
				 return $ifname;
1365
	}
1366
	/* not found? */
1367
	return false;
1368
}
1369
1370 5b237745 Scott Ullrich
/* Build a list of the current real interfaces */
1371
function ovpn_real_interface_list(){
1372
	global $config;
1373
	
1374
	$interfaces = array('all' => 'ALL',
1375
			    'lan' => 'LAN',
1376
			    'wan' => 'WAN');
1377
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
1378
		if (isset($config['interfaces']['opt' . $i]['ovpn']))
1379
			/* Hide our own interface */
1380
			break;
1381
		if (isset($config['interfaces']['opt' . $i]['enable']))
1382
			$interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1383
	}
1384
	return $interfaces;
1385
}
1386
1387 afb07cf1 Scott Ullrich
/* called by interfaces_opt.php */
1388
function ovpn_ccd_sort() {
1389
	global $g, $config;
1390
1391
	function ccdcmp($a, $b) {
1392
		return strcmp($a['cn'][0], $b['cn'][0]);
1393
	}
1394
1395
	usort($config['ovpn']['server']['ccd'], "ccdcmp");
1396
1397
}
1398
1399
/* called by interfaces_opt.php */
1400
function ovpn_config_post() {
1401 767a716e Scott Ullrich
	global $_POST, $optcfg, $pconfig, $input_errors;
1402 afb07cf1 Scott Ullrich
	
1403
	unset($input_errors);
1404
1405
	/* bridge check */
1406
	if ($_POST['bridge'] && strstr($optcfg['if'], "tun"))
1407
		$input_errors[] = "Bridging a tun interface isn't possible.";
1408
1409
	if (($_POST['enable'] && !isset($optcfg['enable'])) || (!$_POST['enable'] && isset($optcfg['enable'])))
1410
		$input_errors[] = "Enabling or disabling a tunneling interface isn't supported on this page.";
1411
1412
	if ($_POST['ipaddr'] != $optcfg['ipaddr']) 
1413
		$input_errors[] = "Changing the IP address of a tunneling interfaces isn't supported on this page.";
1414
1415
	if ($_POST['subnet'] != $optcfg['subnet']) 
1416
		$input_errors[] = "Changing the subnet mask of a tunneling interfaces isn't supported on this page.";
1417
1418
	if ($input_errors) {
1419
		$pconfig['ipaddr'] = $optcfg['ipaddr'];
1420
		$pconfig['subnet'] = $optcfg['subnet'];
1421
		$pconfig['bridge'] = $optcfg['bridge'];
1422
		$pconfig['enable'] = isset($optcfg['enable']);
1423
	}
1424
1425
	return $input_errors;
1426
}
1427
1428
function check_bridging($bridge) {
1429 767a716e Scott Ullrich
	global $config, $input_errors, $index;
1430 afb07cf1 Scott Ullrich
	unset($input_errors);
1431
1432
	/* double bridging? */
1433
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) { 
1434
		if ($i != $index) {
1435
			if ($config['interfaces']['opt' . $i]['bridge'] == $bridge) {
1436
				$input_errors = "Optional interface {$i} " . 
1437
				  "({$config['interfaces']['opt' . $i]['descr']}) is already bridged to " .
1438
				  "the specified interface.";
1439
			} else if ($config['interfaces']['opt' . $i]['bridge'] == "opt{$index}") {
1440
				$input_errors = "Optional interface {$i} " . 
1441
				  "({$config['interfaces']['opt' . $i]['descr']}) is already bridged to " .
1442
				  "this interface.";
1443
			}
1444
		}
1445
	}
1446
1447
	if ($config['interfaces'][$bridge]['bridge'])
1448
		$input_errors = "The specified interface is already bridged to another interface.";
1449
1450
	return $input_errors;
1451
}
1452
1453
/*
1454
function is_specialnet($net) {
1455
	$specialsrcdst = explode(" ", "lan");
1456
	        
1457
	if (in_array($net, $specialsrcdst))
1458
		return true;
1459
	else
1460
		return false;
1461
}
1462
*/
1463
1464 5b237745 Scott Ullrich
	
1465
/* lock openvpn information, decide that the lock file is stale after
1466
   10 seconds */
1467
function ovpn_lock() {
1468
	
1469
	global $g;
1470
	
1471
	$lockfile = "{$g['varrun_path']}/ovpn.lock";
1472
	
1473
	$n = 0;
1474
	while ($n < 10) {
1475
		/* open the lock file in append mode to avoid race condition */
1476 3c2e5528 Scott Ullrich
		if ($fd = fopen($lockfile, "x")) {
1477 5b237745 Scott Ullrich
			/* succeeded */
1478
			fclose($fd);
1479
			return;
1480
		} else {
1481
			/* file locked, wait and try again */
1482
			sleep(1);
1483
			$n++;
1484
		}
1485
	}
1486
}
1487
1488
/* unlock configuration file */
1489
function ovpn_unlock() {
1490
	
1491
	global $g;
1492
	
1493
	$lockfile = "{$g['varrun_path']}/ovpn.lock";
1494
	
1495
	if (file_exists($lockfile))
1496
		unlink($lockfile);
1497
}
1498
1499 4f8e387d Scott Ullrich
?>