Project

General

Profile

Download (40.8 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	openvpn.inc
4
	
5
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
6
	Copyright (C) 2005 Peter Allgeyer (allgeyer@web.de).
7
	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
function ovpn_configure($reconfigure) {
37
	global $config;
38
	if (is_array($config['ovpn']['server']))
39
		ovpn_server_crl_add();
40
		ovpn_server_ccd_add();
41
		ovpn_config_server($reconfigure);
42
	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
	$link_count = fread($fd, filesize($g['vardb_path'] ."/ovpn_tap_link"));
68
	$link_count--;
69
	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
/*  Server related functions */
79
/*****************************/
80

    
81
/* Configure the server */
82
function ovpn_config_server($reconfigure) {
83
	global $config, $g, $d_ovpnsrvdirty_path;
84

    
85
	if($config['ovpn']['server']['tunnel'])
86
	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
			if ($g['booting']) {
93
				echo "Starting OpenVPN server $id... ";
94

    
95
				/* 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
			/* 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

    
114
			/* 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
			/* read dirtyfile */
121
			if (is_readable($d_ovpnsrvdirty_path))
122
				$lines = file($d_ovpnsrvdirty_path);
123

    
124
			/* reconfigure server */
125
			if (is_array($lines) && in_array($tun . "\n", $lines)) {
126

    
127
				/* kill running server */
128
				ovpn_server_kill($tun);
129

    
130
				/* remove old certs & keys */
131
				ovpn_server_certs_del($tun);
132

    
133
				/* define configuration options */
134
				ovpn_srv_config_generate($id);
135
			}
136

    
137
			/* Start the openvpn daemon */
138
			if (!is_readable("{$g['varrun_path']}/ovpn_srv_{$tun}.pid"))
139
				mwexec("/usr/local/sbin/openvpn {$g['varetc_path']}/ovpn_srv_{$tun}.conf");
140

    
141
			/* next server */
142
			continue;
143
		}
144

    
145
		/* 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
		}
157
	}
158
	return 0;
159
}
160

    
161
/* Kill off a running server process */
162
function ovpn_server_certs_del($tun) {
163
	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
	unlink_if_exists("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem");
171
	unlink_if_exists("{$g['varetc_path']}/ovpn_srv_up_{$tun}.sh");
172
	unlink_if_exists("{$g['varetc_path']}/ovpn_srv_{$tun}.conf");
173

    
174
	return 0;
175
}
176

    
177
/* 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
/* Generate the config for a OpenVPN server */
186
function ovpn_srv_config_generate($id) {
187
	global $config, $g;
188
	$server = $config['ovpn']['server']['tunnel'][$id];
189

    
190
	/* mount filesystem for read/write */
191
	conf_mount_rw();
192

    
193
	/* get tunnel interface */
194
	$tun = $server['tun_iface'];
195

    
196
	/* get optional interface name */
197
	$iface = ovpn_get_opt_interface($tun);
198

    
199
	/* 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
	/* First the generic stuff:
246
		- We are a server
247
		- We will run without privilege
248
	*/
249
	$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

    
265
	/* Set protocol being used (p = udp (default), tcp-server) */
266
	if ($server['proto'] == "tcp")
267
		$ovpn_config .= "proto tcp-server\n";
268

    
269
	/* Interface binding - 1 or all */
270
	if ($server['bind_iface'] != 'all')
271
		if ($ipaddr = ovpn_get_ip($server['bind_iface']))
272
			$ovpn_config .= "local {$ipaddr}\n";
273

    
274
	/* are we using dynamic ip addresses? */
275
	if (isset($server['dynip']))
276
		$ovpn_config .= "persist-remote-ip\n";
277

    
278
	/* 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
	/* Client to client routing (off by default) */
292
	if (isset($server['cli2cli']))
293
		$ovpn_config .= "client-to-client\n";
294

    
295
	/* Limit server to a maximum of n concurrent clients. */
296
	if (!empty($server['maxcli']))
297
		$ovpn_config .= "max-clients {$server['maxcli']}\n";
298

    
299
	/* Authentication method */
300
	if ($server['authentication_method'] != "pre_shared_key") {
301

    
302
		$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
		}
316

    
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
		$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
	} else {
416
		/* 'authentication_method' == "pre_shared_key" */
417
		$network = gen_subnet($server['lipaddr'], $server['netmask']);
418
		$netmask = gen_subnet_mask($server['netmask']);
419

    
420
		$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
	if (!isset($conflict))
432
		$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

    
446
	/* return from filesystem read/write mode and mount read-only */
447
	conf_mount_ro();
448

    
449
	//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
	global $config, $g, $bridge_configure, $filter_configure;
455

    
456
	unset($filter_configure);
457
	unset($bridge_configure);
458
	
459
	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
				} else {
474

    
475
					/* No existing entry, this is first unused */
476
					$config['interfaces'][$ifname] = array();
477

    
478
					/* add new filter rules */
479
					$filter_configure = true;
480
					break;
481
				}
482
				$i++;
483
			}
484
			$config['interfaces'][$ifname]['descr'] = strtoupper($server['tun_iface']);
485
			$config['interfaces'][$ifname]['if'] = $server['tun_iface'];
486
			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
			$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
		}
504
	}
505

    
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
	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
			break;
525
		}
526
	}
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
		$i++;
538
	}
539

    
540
	/* reconfigure filter rules */
541
	interfaces_optional_configure();
542
}
543

    
544
/* Add client config file */
545
function ovpn_server_ccd_add() {
546
	global $config, $g;
547

    
548
	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

    
556

    
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
		}
629
	}
630
}
631

    
632
/* 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
				if (is_array($lines) && in_array($name . "\n", $lines)) {
665

    
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
			}
684
			
685
			/* crl file disabled: remove file */
686
			ovpn_server_crl_del($name);
687
		}
688
	}
689
	return 0;
690
}
691

    
692
/* 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
	global $config;
742

    
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
		}
750
	}
751
	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
		fwrite($fd, $tun ."\n");
761
		fclose($fd);
762
	}
763
}
764

    
765
/* 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
		fwrite($fd, $name ."\n");
772
		fclose($fd);
773
	}
774
}
775

    
776

    
777
/****************************/
778
/* Client related functions */
779
/****************************/
780

    
781
function ovpn_config_client() {
782
	/* Boot time configuration */
783
	global $config, $g, $d_ovpnclidirty_path;
784
	
785
	foreach ($config['ovpn']['client']['tunnel'] as $id => $client) {
786

    
787
		/* get tunnel interface */
788
		$tun = $client['if'];
789

    
790
		if (isset($client['enable'])) {
791

    
792
			if ($g['booting']) {
793
				echo "Starting OpenVPN client $id... ";
794
		
795
				/* 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
		
801
				/* Send the boot message */
802
				echo "done\n";
803

    
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
			if (is_array($lines) && in_array($tun . "\n", $lines)) {
814

    
815
				/* kill running client */
816
				ovpn_client_kill($tun);
817

    
818
				/* remove old certs & keys */
819
				ovpn_client_certs_del($tun);
820

    
821
				/* define configuration options */
822
				ovpn_cli_config_generate($id);
823
			}
824

    
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
		}
845
	}
846
	return 0;
847
}
848

    
849
/* Kill off a running client process */
850
function ovpn_client_certs_del($tun) {
851
	global $g;
852
	
853
	/* 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
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem");
858
	unlink_if_exists("{$g['varetc_path']}/ovpn_cli_up_{$tun}.pem");
859
	unlink_if_exists("{$g['varetc_path']}/ovpn_cli_{$tun}.conf");
860

    
861
	return 0;
862
}
863

    
864
/* 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
/* Generate the config for a OpenVPN client */
873
function ovpn_cli_config_generate($id) {
874
	/* configure the named client */
875
	global $config, $g;
876
	$client = $config['ovpn']['client']['tunnel'][$id];
877

    
878
	/* get tunnel interface */
879
	$tun = $client['if'];
880

    
881
	/* get optional interface name */
882
	$iface = ovpn_get_opt_interface($tun);
883

    
884
	/* 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
	}
907

    
908
	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
		if ($fd) {
913
			fwrite($fd, base64_decode($client['pre-shared-key'])."\n");
914
			fclose($fd);	
915
		}
916
	}
917

    
918
	$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
	/* TLS-Client params */
954
	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

    
960
EOD;
961

    
962
		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
	/* 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
	/* 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
}
1030

    
1031
/* Define an OVPN tunnel interface in the interfaces array for each client */
1032
function ovpn_client_iface(){
1033
	global $config, $filter_configure, $bridge_configure;
1034
		
1035
	unset($filter_configure);
1036
	unset($bridge_configure);
1037

    
1038
	foreach ($config['ovpn']['client']['tunnel'] as $id => $client) {
1039
		if (isset($client['enable'])) {
1040

    
1041
			/* get tunnel interface */
1042
			$tun = $client['if'];
1043

    
1044
			$i = 1;
1045
			while (true) {
1046
				$ifname = 'opt' . $i;
1047
				if (is_array($config['interfaces'][$ifname])) {
1048
					if ((isset($config['interfaces'][$ifname]['ovpn']))
1049
			     		     && ($config['interfaces'][$ifname]['ovpn'] == "client_{$tun}"))
1050
						/* Already an interface defined - overwrite */
1051
						break;
1052
				} else {
1053

    
1054
					/* No existing entry, this is first unused */
1055
					$config['interfaces'][$ifname] = array();
1056

    
1057
					/* add new filter rules */
1058
					$filter_configure = true;
1059
					break;
1060
				}
1061
				$i++;
1062
			}
1063
			$config['interfaces'][$ifname]['descr'] = strtoupper($client['if']);
1064
			$config['interfaces'][$ifname]['if'] = $client['if'];
1065
			$config['interfaces'][$ifname]['ipaddr'] = "0.0.0.0";
1066
			$config['interfaces'][$ifname]['subnet'] = "0";
1067
			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
			$config['interfaces'][$ifname]['enable'] = isset($client['enable']) ? true : false;
1076
			$config['interfaces'][$ifname]['ovpn'] = "client_{$tun}";
1077
			write_config();
1078
		}
1079
	}
1080

    
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
	return "OpenVPN client interfaces defined";
1088
}
1089

    
1090
/* Delete a client interface definition */
1091
function ovpn_client_iface_del($tun) {
1092
	global $config;
1093

    
1094
	for ($i = 1; is_array($config['interfaces']['opt' . $i]); $i++) {
1095
		$ifname = 'opt' . $i;
1096
		if ((isset($config['interfaces'][$ifname]['ovpn']))
1097
		     && ($config['interfaces'][$ifname]['if'] == "$tun")) {
1098
			unset($config['interfaces'][$ifname]);
1099
			break;
1100
		}
1101
	}
1102

    
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

    
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
		fwrite($fd, $tun . "\n");
1126
		fclose($fd);
1127
	}
1128
}
1129

    
1130

    
1131
/******************/
1132
/* Misc functions */
1133
/******************/
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

    
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
/* Port in use */
1284
function ovpn_port_inuse_server($port){
1285
	global $config;
1286
	if ($a_server = $config['ovpn']['server']['tunnel']) {
1287
		foreach ($a_server as $server) {
1288
			if ($server['port'] == $port) {
1289
				return true;
1290
			}
1291
		}
1292
	}
1293
	return false;
1294
}
1295

    
1296
/* 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
	
1323
/* 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
/* 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
/* 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
/* 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
	global $_POST, $optcfg, $pconfig, $input_errors;
1402
	
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
	global $config, $input_errors, $index;
1430
	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
	
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
		if ($fd = fopen($lockfile, "x")) {
1477
			/* 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
?>
(13-13/27)