Project

General

Profile

Download (24.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	openvpn.inc
4
	
5
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
6
	All rights reserved.
7
	
8
	Redistribution and use in source and binary forms, with or without
9
	modification, are permitted provided that the following conditions are met:
10
	
11
	1. Redistributions of source code must retain the above copyright notice,
12
	   this list of conditions and the following disclaimer.
13
	
14
	2. Redistributions in binary form must reproduce the above copyright
15
	   notice, this list of conditions and the following disclaimer in the
16
	   documentation and/or other materials provided with the distribution.
17
	
18
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
	POSSIBILITY OF SUCH DAMAGE.
28
*/
29
	
30
/* include all configuration functions */
31
require_once("globals.inc");
32
require_once("config.inc");
33
require_once("functions.inc");
34

    
35
function ovpn_configure($reconfigure) {
36
	global $config;
37
	if (is_array($config['ovpn']['server']))
38
		ovpn_config_server($reconfigure);
39
	if (is_array($config['ovpn']['client']))
40
		ovpn_config_client();
41
	return;
42
}
43

    
44
function ovpn_link_tap() {
45
	/* Add a reference to the tap KLM.  If ref count = 1, load it */
46
	global $g;
47
	
48
	if (!is_file($g['vardb_path'] ."/ovpn_tap_link")){
49
		$link_count = 1;
50
		mwexec("/sbin/kldload if_tap");
51
		$fd = fopen($g['vardb_path'] ."/ovpn_tap_link", 'w');
52
	}
53
	else {
54
		$fd = fopen($g['vardb_path'] ."/ovpn_tap_link", 'r+');
55
		$link_count = fread($fd);
56
		$link_count ++;
57
	}
58
	fwrite($fd, $link_count);
59
	fclose($fd);
60
	return true;
61
}
62

    
63
function ovpn_unlink_tap() {
64
	/* Remove a reference to the tap KLM.  If ref count = 0, unload it */
65
	global $g;
66
	
67
	if (!is_file($g['vardb_path'] ."/ovpn_tap_link"))
68
		return false;  //no file, no links so why are we called?
69
		
70
	$fd = fopen($g['vardb_path'] ."/ovpn_tap_link", 'r+');
71
	$link_count = fread($fd);
72
	$link_count --;
73
	fwrite($fd, $link_count);
74
	fclose($fd);
75
		
76
	if ($link_count == 0)
77
		mwexec("/sbin/kldunload if_tap");
78
	return true;
79
}
80

    
81
/*****************************/	
82
/*  Server related functions */
83
/*****************************/
84

    
85
function getnxt_server_if($type) {
86
	/* find the first available device of type $type */
87
	global $config;
88
	$a_server = $config['ovpn']['server']['tunnel'];
89
	$max = ($type == 'tun') ? 17 : 4;
90
	for ($i = 0; $i < $max ; $i++) {
91
		$hit = false;
92
		foreach ($a_server as $server) {
93
			if ($server['tun_iface'] == $type . $i) {
94
				$hit = true;
95
				break;
96
			}
97
		}
98
		if (!$hit)
99
			return $type . $i;
100
	}
101
	return false;
102
}
103

    
104
function getnxt_server_port() {
105
	/* Get first unused port */
106
	global $config;
107
	$a_server = $config['ovpn']['server']['tunnel'];
108
	$port = 1194;
109
	while (true) {
110
		$hit = false;
111
		foreach ($a_server as $server) {
112
			if ($server['port'] == $port) {
113
				$hit = true;
114
				break;
115
			}
116
		}
117
		if (!$hit)
118
			if (!ovpn_port_inuse_client($port))
119
				return $port;
120
		$port++;
121
	}
122
	return false; /* should never get here */
123
}
124

    
125
/* Configure the server */
126
function ovpn_config_server($reconfigure) {
127
	global $config, $g;
128

    
129
	foreach ($config['ovpn']['server']['tunnel'] as $id => $server) {
130
		/* get tunnel interface */
131
		$tun = $server['tun_iface'];
132
			
133
		/* kill any running openvpn daemon */
134
		killbypid($g['varrun_path']."/ovpn_srv_{$tun}.pid");
135

    
136
		if (isset($server['enable'])) {
137

    
138
			if ($g['booting'])
139
				echo "Starting OpenVPN server $id... ";
140

    
141
			/* send SIGUSR1 to running openvpn daemon */
142
			if ( $reconfigure == "true" && isset($server['dynip'])) {
143
				sigkillbypid($g['varrun_path']."/ovpn_srv_{$tun}.pid", "SIGUSR1");
144
				continue;
145
			}
146

    
147
			/* Remove old certs & keys */
148
			unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem");
149
			unlink_if_exists("{$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem");
150
			unlink_if_exists("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem");
151
			unlink_if_exists("{$g['vardb_path']}/ovpn_dh_{$tun}.pem");
152
			unlink_if_exists("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem");
153
			unlink_if_exists("{$g['varetc_path']}/ovpn_srv_up_{$tun}.pem");
154
			unlink_if_exists("{$g['varetc_path']}/ovpn_cli_up_{$tun}.pem");
155

    
156
			/* Copy the TLS-Server certs & keys to disk */
157
			$fd = fopen("{$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem", "w");
158
			if ($fd) {
159
				fwrite($fd, base64_decode($server['ca_cert'])."\n");
160
				fclose($fd);	
161
			}
162
			$fd = fopen("{$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem", "w");
163
			if ($fd) {
164
				fwrite($fd, base64_decode($server['srv_cert'])."\n");
165
				fclose($fd);	
166
			}
167
			touch ("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem");
168
			chmod ("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem", 0600);
169
			$fd = fopen("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem", "w");
170
			if ($fd) {
171
				fwrite($fd, base64_decode($server['srv_key'])."\n");
172
				fclose($fd);	
173
			}
174
			$fd = fopen("{$g['vardb_path']}/ovpn_dh_{$tun}.pem", "w");
175
			if ($fd) {
176
				fwrite($fd, base64_decode($server['dh_param'])."\n");
177
				fclose($fd);	
178
			}
179

    
180
			touch ("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem");
181
			chmod ("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem", 0600);
182
			$fd = fopen("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem", "w");
183
			if ($fd) {
184
				fwrite($fd, base64_decode($server['pre-shared-key'])."\n");
185
				fclose($fd);	
186
			}
187

    
188
			/* Start the openvpn daemon */
189
			mwexec("/usr/local/sbin/openvpn " . ovpn_srv_config_generate($id));
190

    
191
			if ($g['booting'])
192
				/* Send the boot message */
193
				echo "done\n";
194
		}
195
		else {
196
			if (!$g['booting']){
197
				/* stop any processes, unload the tap module */
198
				/* Remove old certs & keys */
199
				ovpn_server_kill($tun);
200

    
201
				if ($server['type'] == "tap")
202
					ovpn_unlink_tap();
203
			}
204
		}
205
	}
206
	return 0;
207
}
208

    
209
/* Kill off a running server process */
210
function ovpn_server_kill($tun) {
211
	global $g;
212
	
213
	killbypid("{$g['varrun_path']}/ovpn_srv_{$tun}.pid");
214

    
215
	/* Remove old certs & keys */
216
	unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem");
217
	unlink_if_exists("{$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem");
218
	unlink_if_exists("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem");
219
	unlink_if_exists("{$g['vardb_path']}/ovpn_dh_{$tun}.pem");
220
	unlink_if_exists("{$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem");
221

    
222
	return 0;
223
}
224

    
225
/* Generate the config for a OpenVPN server */
226
function ovpn_srv_config_generate($id) {
227
	global $config, $g;
228
	$server = $config['ovpn']['server']['tunnel'][$id];
229

    
230
	/* get tunnel interface */
231
	$tun = $server['tun_iface'];
232

    
233
	/* get optional interface name */
234
	$iface = ovpn_get_opt_interface($tun);
235

    
236
	/* First the generic stuff:
237
		- We are a server
238
		- We are a TLS Server (for authentication)
239
		- We will run without privilege
240
	*/
241
	$ovpn_config = "--daemon --user nobody --group nobody --verb {$server['verb']} --persist-tun --persist-key --status /var/log/openvpn_{$tun}.log 60 ";
242

    
243
	/* pid file */
244
	$ovpn_config .= "--writepid {$g['varrun_path']}/ovpn_srv_{$tun}.pid ";
245
	
246
	/* interface */
247
	$ovpn_config .= "--dev {$server['tun_iface']} ";
248
	
249
	/* port */
250
	$ovpn_config .= "--port {$server['port']} ";
251

    
252
	/* Set protocol being used (p = udp (default), tcp-server)
253
	if ($server['proto'] == 'tcp') {
254
		$ovpn_config .= "--proto tcp-server ";
255
	}
256
	
257
	/* Interface binding - 1 or all */
258
	if ($server['bind_iface'] != 'all') {
259
		if ($ipaddr = ovpn_get_ip($server['bind_iface']))
260
			$ovpn_config .= "--local $ipaddr ";
261
		else
262
			return "Interface bridged";
263
	}
264

    
265
	/* are we using dynamic ip addresses? */
266
	if (isset($server['dynip']))
267
		$ovpn_config .= "--persist-remote-ip ";
268
	
269
	/* Client to client routing (off by default) */
270
	if (isset($server['cli2cli']))
271
		$ovpn_config .= "--client-to-client ";
272
	
273
	/* Set maximum simultaneous clients */
274
	$ovpn_config .= "--max-clients {$server['maxcli']} ";
275
	 
276
	/* bridging enabled? */
277
	if (($ifname = $config['interfaces'][$iface]['bridge']) && $server['type'] == "tap") {
278
		$gateway = $config['interfaces'][$ifname]['ipaddr'];
279
		$netmask = gen_subnet_mask($config['interfaces'][$ifname]['subnet']);
280
		$poolstart = $server['ipblock'];
281
		$poolend = gen_subnet_max($server['ipblock'], $server['prefix']);
282

    
283
		$ovpn_config .= "--server-bridge $gateway $netmask $poolstart $poolend ";
284

    
285
		$lastdigits = substr($tun, 3) + 2;
286
		$ovpn_srv_up = "/sbin/ifconfig " . $tun . " 127.0.0." . $lastdigits . "/32\n";
287

    
288
		$fd = fopen("{$g['varetc_path']}/ovpn_srv_up_{$tun}.sh", "w");
289
		if ($fd) {
290
			fwrite($fd, $ovpn_srv_up);
291
			fclose($fd);	
292
			chmod ("{$g['varetc_path']}/ovpn_srv_up_{$tun}.sh", 0755);
293
			$ovpn_config .= "--up /var/etc/ovpn_srv_up_{$tun}.sh ";
294
		}
295
	} else {
296
		/* New --server macro simplifies config */
297
		$netmask = gen_subnet_mask($server['prefix']);
298

    
299
		$ovpn_config .= "--server {$server['ipblock']} {$netmask} ";
300
	}
301
	
302
	/* TLS-Server params */
303
	$ovpn_config .= "--ca {$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem ";
304
	$ovpn_config .= "--cert {$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem ";
305
	$ovpn_config .= "--key {$g['vardb_path']}/ovpn_srv_key_{$tun}.pem ";
306
	$ovpn_config .= "--dh {$g['vardb_path']}/ovpn_dh_{$tun}.pem ";
307
	
308
	/* TLS auth */
309
	if (isset($server['tlsauth']))
310
		$ovpn_config .= "--tls-auth {$g['vardb_path']}/ovpn_srv_psk_{$tun}.pem 0 ";
311
	
312
	/* Data channel encryption cipher*/
313
	$ovpn_config .= "--cipher {$server['crypto']} ";
314
	
315
	/* Duplicate CNs */
316
	if (isset($server['dupcn']))
317
		$ovpn_config .= "--duplicate-cn ";
318
		
319
	/* Client push - redirect gateway */
320
	if (isset($server['psh_options']['redir'])){
321
		if (isset($server['psh_options']['redir_loc']))
322
			$ovpn_config .= "--push \"redirect-gateway local\" ";
323
		else
324
			$ovpn_config .= "--push \"redirect-gateway\" ";
325
	}
326
			
327
	/* Client push - route delay */
328
	if (isset($server['psh_options']['rte_delay']))
329
		$ovpn_config .= "--push \"route-delay {$server['psh_options']['rte_delay_int']}\" ";
330
		
331
	/* Client push - ping (note we set both server and client) */
332
	if (isset ($server['psh_options']['ping'])){
333
		$conflict = true;
334
		$interval = $server['psh_options']['ping_int'];
335
		$ovpn_config .= "--ping {$server['psh_options']['ping_int']} ";
336
		$ovpn_config .= "--push \"ping {$server['psh_options']['ping_int']}\" ";
337
	}
338
	
339
	/* Client push - ping-restart (note server uses 2 x client interval) */
340
	if (isset ($server['psh_options']['pingrst'])){
341
		$conflict = true;
342
		$interval = $server['psh_options']['pingrst_int'];
343
		$ovpn_config .= "--ping-restart " . ($interval * 2) . " ";
344
		$ovpn_config .= "--push \"ping-restart $interval\" ";
345
	}
346
	
347
	/* Client push - ping-exit (set on client) */
348
	if (isset ($server['psh_options']['pingexit'])){
349
		$conflict = true;
350
		$ovpn_config .= "--ping-exit {$server['psh_options']['pingexit_int']} ";
351
		$ovpn_config .= "--push \"ping-exit {$server['psh_options']['pingexit_int']}\" ";
352
	}
353
	
354
	/* Client push - inactive (set on client) */
355
	if (isset ($server['psh_options']['inact'])){
356
		$ovpn_config .= "--inactive {$server['psh_options']['inact_int']} ";
357
		$ovpn_config .= "--push \"inactive {$server['psh_options']['inact_int']}\" ";
358
	}
359
	
360
	if (!isset($conflict))
361
		$ovpn_config .= "--keepalive 10 60 ";
362

    
363
	//trigger_error("OVPN: $ovpn_config", E_USER_NOTICE);
364
	return $ovpn_config;
365
}
366

    
367
/* Define an OVPN Server tunnel interface in the interfaces array and assign a name */
368
function ovpn_server_iface(){
369
	global $config, $g;
370
	
371
	foreach ($config['ovpn']['server']['tunnel'] as $id => $server) {
372
		if (isset($server['enable'])) {
373

    
374
			/* get tunnel interface */
375
			$tun = $server['tun_iface'];
376
			
377
			$i = 1;
378
			while (true) {
379
				$ifname = 'opt' . $i;
380
				if (is_array($config['interfaces'][$ifname])) {
381
					if ((isset($config['interfaces'][$ifname]['ovpn']))
382
					     && ($config['interfaces'][$ifname]['ovpn'] == "server_{$tun}"))
383
						/* Already an interface defined - overwrite */
384
						break;
385
				}
386
				else {
387
					/* No existing entry, this is first unused */
388
					$config['interfaces'][$ifname] = array();
389
					break;
390
				}
391
				$i++;
392
			}
393
			$config['interfaces'][$ifname]['descr'] = strtoupper($ifname);
394
			$config['interfaces'][$ifname]['if'] = $server['tun_iface'];
395
			$config['interfaces'][$ifname]['ipaddr'] = long2ip( ip2long($server['ipblock']) + 1);
396
			$config['interfaces'][$ifname]['subnet'] = $server['prefix'];
397
			$config['interfaces'][$ifname]['enable'] = isset($server['enable']) ? true : false;
398
			$config['interfaces'][$ifname]['ovpn'] = "server_{$tun}";
399

    
400
			write_config();
401
		}
402
	}
403
	return "OpenVPN server interface defined";
404
}
405

    
406
/* Delete a server interface definition */
407
function ovpn_server_iface_del($tun) {
408
	global $config;
409

    
410
	for ($i = 1; is_array($config['interfaces']['opt' . $i]); $i++) {
411
		$ifname = 'opt' . $i;
412
		if ((isset($config['interfaces'][$ifname]['ovpn']))
413
		     && ($config['interfaces'][$ifname]['if'] == "$tun")) {
414
			unset($config['interfaces'][$ifname]);
415
			break;
416
		}
417
	}
418

    
419

    
420
	/* shift down other OPTn interfaces to get rid of holes */
421
	$i++;
422

    
423
	/* look at the following OPTn ports */
424
	while (is_array($config['interfaces']['opt' . $i])) {
425
		$config['interfaces']['opt' . ($i - 1)] =
426
			$config['interfaces']['opt' . $i];
427

    
428
		unset($config['interfaces']['opt' . $i]);
429
		$i++;
430
	}
431
}
432

    
433

    
434
/****************************/
435
/* Client related functions */
436
/****************************/
437

    
438
function getnxt_client_if($type) {
439
	/* find the first available device of type $type */
440
	global $config;
441
	$max = ($type == 'tun') ? 17 : 4;
442
	for ($i = 0; $i < $max; $i++) {
443
		$hit = false;
444
		foreach ($a_client as $client) {
445
			if ($client['if'] == $type . $i) {
446
				$hit = true;
447
				break;
448
			}
449
		}
450
		if (!$hit)
451
			return $type . $i;
452
	}
453
        return false;
454
}
455

    
456
function getnxt_client_port() {
457
        /* Get first unused port */
458
	global $config;
459
	$a_client = $config['ovpn']['client']['tunnel'];
460
	$port = 1194;
461
	while (true) {
462
		$hit = false;
463
		foreach ($a_client as $client) {
464
			if ($client['port'] == $port) {
465
				$hit = true;
466
				break;
467
			}
468
		}
469
		if (!$hit)
470
			if (!ovpn_port_inuse_server($port))
471
				return $port;
472
		$port++;
473
	}
474
	return false; /* should never get here */
475
}
476

    
477
/* Port in use */
478
function ovpn_port_inuse_client($port){
479
	global $config;
480
	$a_client = $config['ovpn']['client']['tunnel'];
481
	foreach ($a_client as $client) {
482
		if ($client['port'] == $port) {
483
			return true;
484
		}
485
	}
486
	return false;
487
}
488

    
489
function ovpn_config_client() {
490
	/* Boot time configuration */
491
	global $config, $g;
492
	
493
	foreach ($config['ovpn']['client']['tunnel'] as $id => $client) {
494

    
495
		/* get tunnel interface */
496
		$tun = $client['if'];
497

    
498
		/* kill any running openvpn daemon */
499
		killbypid($g['varrun_path']."/ovpn_cli_{$tun}.pid");
500

    
501
		if (isset($client['enable'])) {
502
	
503
			if ($g['booting'])
504
				echo "Starting OpenVPN client $id... ";
505
		
506
			/* Remove old certs & keys */
507
			unlink_if_exists("{$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem");
508
			unlink_if_exists("{$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem");
509
			unlink_if_exists("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem");
510
			unlink_if_exists("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem");
511
			unlink_if_exists("{$g['varetc_path']}/ovpn_cli_up_{$tun}.pem");
512
		
513
			/* Copy the TLS-Client certs & keys to disk */
514
			$fd = fopen("{$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem", "w");
515
			if ($fd) {
516
				fwrite($fd, base64_decode($client['ca_cert'])."\n");
517
				fclose($fd);	
518
			}
519
			else
520
				trigger_error("OVPN: No open for CA", E_USER_NOTICE);
521
			$fd = fopen("{$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem", "w");
522
			if ($fd) {
523
				fwrite($fd, base64_decode($client['cli_cert'])."\n");
524
				fclose($fd);	
525
			}
526
			touch ("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem");
527
			chmod ("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem", 0600);
528
			$fd = fopen("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem", "w");
529
			if ($fd) {
530
				fwrite($fd, base64_decode($client['cli_key'])."\n");
531
				fclose($fd);	
532
			}
533
			touch ("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem");
534
			chmod ("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem", 0600);
535
			$fd = fopen("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem", "w");
536
			if ($fd) {
537
				fwrite($fd, base64_decode($client['pre-shared-key'])."\n");
538
				fclose($fd);	
539
			}
540
				
541
			/* Start openvpn for this client */
542
			mwexec("/usr/local/sbin/openvpn " . ovpn_cli_config_generate($id));
543
		
544
			if ($g['booting'])
545
				/* Send the boot message */
546
				echo "done\n";
547
		}
548
		else {
549
			if (!$g['booting']){
550
				/* stop any processes, unload the tap module */
551
				/* Remove old certs & keys */
552
				ovpn_client_kill($tun);
553

    
554
				if ($client['type'] == "tap")
555
					ovpn_unlink_tap();
556
			}
557
		}
558
	}
559
	return 0;
560
	
561
}
562

    
563
/* Kill off a running client process */
564
function ovpn_client_kill($tun) {
565
	global $g;
566
	
567
	killbypid("{$g['varrun_path']}/ovpn_cli_{$tun}.pid");
568
	
569
	/* Remove old certs & keys */
570
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem");
571
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem");
572
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem");
573
	unlink_if_exists("{$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem");
574

    
575
	return 0;
576
}
577

    
578
/* Generate the config for a OpenVPN client */
579
function ovpn_cli_config_generate($id) {
580
	/* configure the named client */
581
	global $config, $g;
582
	$client = $config['ovpn']['client']['tunnel'][$id];
583

    
584
	/* get tunnel interface */
585
	$tun = $client['if'];
586
	
587
	/* get optional interface name */
588
	$iface = ovpn_get_opt_interface($tun);
589

    
590
	/* Client support in 2.0 is very simple */
591
	$ovpn_config = "--client --daemon --verb 1 --status /var/log/openvpn_{$tun}.log 60 ";
592
	
593
	/* pid file */
594
	$ovpn_config .= "--writepid {$g['varrun_path']}/ovpn_cli_{$tun}.pid ";
595
	
596
	/* interface */
597
	$ovpn_config .= "--dev {$client['if']} ";
598
	
599
	/* protocol */
600
	/* Set protocol being used (p = udp (default), tcp-client)
601
	if ($client['proto'] == 'tcp') {
602
		$ovpn_config .= "--proto tcp-client ";
603
	}
604
	
605
	/* port */
606
	$ovpn_config .= "--lport {$client['port']} ";
607
	
608
	/* server location */
609
	$ovpn_config .= "--remote {$client['saddr']} {$client['sport']} ";
610
	
611
	/* bridging enabled? */
612
	if (($ifname = $config['interfaces'][$iface]['bridge']) && $client['type'] == "tap") {
613
		$lastdigits = substr($tun, 3) + 2;
614
		$ovpn_srv_up = "/sbin/ifconfig " . $tun . " 127.0.0." . $lastdigits . "/32\n";
615

    
616
		$fd = fopen("{$g['varetc_path']}/ovpn_cli_up_{$tun}.sh", "w");
617
		if ($fd) {
618
			fwrite($fd, $ovpn_cli_up);
619
			fclose($fd);    
620
			chmod ("{$g['varetc_path']}/ovpn_cli_up_{$tun}.sh", 0755);
621
			$ovpn_config .= "--up /var/etc/ovpn_cli_up_{$tun}.sh ";
622
		}
623
	}
624

    
625
	/* TLS-Client params */
626
	$ovpn_config .= "--ca {$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem ";
627
	$ovpn_config .= "--cert {$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem ";
628
	$ovpn_config .= "--key {$g['vardb_path']}/ovpn_cli_key_{$tun}.pem ";
629

    
630
	/* TLS auth */
631
	if (isset($client['tlsauth']))
632
		$ovpn_config .= "--tls-auth {$g['vardb_path']}/ovpn_cli_psk_{$tun}.pem 1 ";
633

    
634
	/* Data channel encryption cipher*/
635
	$ovpn_config .= "--cipher {$client['crypto']} ";
636
	
637
	//trigger_error("OVPN: $ovpn_config", E_USER_NOTICE);
638
	return $ovpn_config;
639
}
640

    
641
/* Define an OVPN tunnel interface in the interfaces array for each client */
642
function ovpn_client_iface(){
643
	global $config;
644
		
645
	foreach ($config['ovpn']['client']['tunnel'] as $id => $client) {
646
		if (isset($client['enable'])) {
647

    
648
			/* get tunnel interface */
649
			$tun = $client['if'];
650

    
651
			$i = 1;
652
			while (true) {
653
				$ifname = 'opt' . $i;
654
				if (is_array($config['interfaces'][$ifname])) {
655
					if ((isset($config['interfaces'][$ifname]['ovpn']))
656
			     		     && ($config['interfaces'][$ifname]['ovpn'] == "client_{$tun}"))
657
						/* Already an interface defined - overwrite */
658
						break;
659
				}
660
				else {
661
					/* No existing entry, this is first unused */
662
					$config['interfaces'][$ifname] = array();
663
					break;
664
				}
665
				$i++;
666
			}
667
			$config['interfaces'][$ifname]['descr'] = strtoupper($ifname);
668
			$config['interfaces'][$ifname]['if'] = $client['if'];
669
			$config['interfaces'][$ifname]['ipaddr'] = "0.0.0.0";
670
			$config['interfaces'][$ifname]['subnet'] = "0";
671
			$config['interfaces'][$ifname]['enable'] = isset($client['enable']) ? true : false;
672
			$config['interfaces'][$ifname]['ovpn'] = "client_{$tun}";
673
			write_config();
674
		}
675
	}
676
	return "OpenVPN client interfaces defined";
677
}
678

    
679
/* Delete a client interface definition */
680
function ovpn_client_iface_del($tun) {
681
	global $config;
682

    
683
	for ($i = 1; is_array($config['interfaces']['opt' . $i]); $i++) {
684
		$ifname = 'opt' . $i;
685
		if ((isset($config['interfaces'][$ifname]['ovpn']))
686
		     && ($config['interfaces'][$ifname]['if'] == "$tun")) {
687
			unset($config['interfaces'][$ifname]);
688
			break;
689
		}
690
	}
691

    
692

    
693
	/* shift down other OPTn interfaces to get rid of holes */
694
	$i++;
695

    
696
	/* look at the following OPTn ports */
697
	while (is_array($config['interfaces']['opt' . $i])) {
698
		$config['interfaces']['opt' . ($i - 1)] =
699
			$config['interfaces']['opt' . $i];
700

    
701
		unset($config['interfaces']['opt' . $i]);
702
		$i++;
703
	}
704
}
705

    
706

    
707
/******************/
708
/* Misc functions */
709

    
710
/* Calculate the last address in a range given the start and /prefix */
711
function ovpn_calc_end($start, $prefix){
712

    
713
	$first = ip2long($start);
714
	$last = pow(2,(32 - $prefix)) - 1 + $first;
715
	return long2ip($last);
716
}
717

    
718
/* Calculate a mask given a /prefix */
719
function ovpn_calc_mask($prefix){
720

    
721
	return long2ip(ip2long("255.255.255.255") - (pow( 2, (32 - $prefix)) - 1));
722
}
723

    
724
/* Port in use */
725
function ovpn_port_inuse_server($port){
726
	global $config;
727
	$a_server = $config['ovpn']['server']['tunnel'];
728
	foreach ($a_server as $server) {
729
		if ($server['port'] == $port) {
730
			return true;
731
		}
732
	}
733
	return false;
734
}
735

    
736
/* Read in a file from the $_FILES array */
737
function ovpn_get_file($file){
738
	global $g;
739
	
740
	if (!is_uploaded_file($_FILES[$file]['tmp_name'])){
741
		trigger_error("Bad file upload".$_FILES[$file]['error'], E_USER_NOTICE);
742
		return NULL;
743
	}
744
	$contents = file_get_contents($_FILES[$file]['tmp_name']);
745
	return $contents;
746
}
747

    
748

    
749
/* Get the IP address of a specified interface */
750
function ovpn_get_ip($iface){
751
	global $config;
752
	
753
	if ($iface == 'wan')
754
		return get_current_wan_address();
755
		
756
	if ($config['interfaces'][$iface]['bridge'])
757
		/* No bridging (yet) */
758
		return false;
759
	return $config['interfaces'][$iface]['ipaddr'];
760
}
761
	
762
	
763
/* Get a list of the cipher options supported by OpenVPN */
764
function ovpn_get_cipher_list(){
765
	
766
/*	exec("/usr/local/sbin/openvpn --show-ciphers", $raw);
767
	print_r ($raw);
768
	
769
	$ciphers = preg_grep('/ bit default key /', $raw);
770
	
771
	for($i = 0; $i <count($ciphers); $i++){
772
		$tmp = explode(' ',$ciphers[$i]);
773
		$cipher_list["$tmp[0]"] = "{$tmp[0]} ({$tmp[1]} {$tmp[2]})";
774
	}
775
*/
776
	$cipher_list = array('DES-CBC' => 'DES-CBC (64 bit)',
777
			     'RC2-CBC' => 'RC2-CBC (128 bit)',
778
			     'DES-EDE-CBC' => 'DES-EDE-CBC (128 bit)',
779
			     'DES-EDE3-CBC' => 'DES-EDE3-CBC (192 bit)',
780
			     'DESX-CBC' => 'DESX-CBC (192 bit)',
781
			     'BF-CBC' => 'BF-CBC (128 bit)',
782
			     'RC2-40-CBC' => 'RC2-40-CBC (40 bit)',
783
			     'CAST5-CBC' => 'CAST5-CBC (128 bit)',
784
			     'RC5-CBC' => 'RC5-CBC (128 bit)',
785
			     'RC2-64-CBC' => 'RC2-64-CBC (64 bit)',
786
			     'AES-128-CBC' => 'AES-128-CBC (128 bit)',
787
			     'AES-192-CBC' => 'AES-192-CBC (192 bit)',
788
			     'AES-256-CBC' => 'AES-256-CBC (256 bit)');
789
	return $cipher_list;
790
}
791
		
792
	
793
/* Get optional interface */
794
/* needs tunneling interface (tun0, tun1, tap0, ...) */
795
/* returns optional interface name (opt2, opt3, ...) */
796
function ovpn_get_opt_interface($tun){
797
	global $config;
798

    
799
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
800
		$ifname = 'opt' . $i;
801

    
802
		if (isset($config['interfaces']['opt' . $i]['ovpn']))
803
			if ($config['interfaces'][$ifname]['if'] == "$tun")
804
				 return $ifname;
805
	}
806
	/* not found? */
807
	return false;
808
}
809

    
810
/* Build a list of the current real interfaces */
811
function ovpn_real_interface_list(){
812
	global $config;
813
	
814
	$interfaces = array('all' => 'ALL',
815
			    'lan' => 'LAN',
816
			    'wan' => 'WAN');
817
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
818
		if (isset($config['interfaces']['opt' . $i]['ovpn']))
819
			/* Hide our own interface */
820
			break;
821
		if (isset($config['interfaces']['opt' . $i]['enable']))
822
			$interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
823
	}
824
	return $interfaces;
825
}
826

    
827
	
828
/* lock openvpn information, decide that the lock file is stale after
829
   10 seconds */
830
function ovpn_lock() {
831
	
832
	global $g;
833
	
834
	$lockfile = "{$g['varrun_path']}/ovpn.lock";
835
	
836
	$n = 0;
837
	while ($n < 10) {
838
		/* open the lock file in append mode to avoid race condition */
839
		if ($fd = fopen($lockfile, "x")) {
840
			/* succeeded */
841
			fclose($fd);
842
			return;
843
		} else {
844
			/* file locked, wait and try again */
845
			sleep(1);
846
			$n++;
847
		}
848
	}
849
}
850

    
851
/* unlock configuration file */
852
function ovpn_unlock() {
853
	
854
	global $g;
855
	
856
	$lockfile = "{$g['varrun_path']}/ovpn.lock";
857
	
858
	if (file_exists($lockfile))
859
		unlink($lockfile);
860
}
861

    
862
?>
(11-11/23)