Project

General

Profile

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