Project

General

Profile

Download (29.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2

    
3
/* $Id$ */
4
/*
5
	$RCSfile$
6
	
7
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
8
	All rights reserved.
9
	
10
	Copyright (C) 2006  Fernando Lemos
11
	All rights reserved.
12

    
13
	This file was rewritten from scratch by Fernando Lemos but
14
	*MIGHT* contain code previously written by:
15

    
16
	Copyright (C) 2005 Peter Allgeyer <allgeyer_AT_web.de>
17
	All rights reserved.
18

    
19
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
20
	All rights reserved.
21

    
22
	Redistribution and use in source and binary forms, with or without
23
	modification, are permitted provided that the following conditions are met:
24

    
25
	1. Redistributions of source code must retain the above copyright notices,
26
	   this list of conditions and the following disclaimer.
27

    
28
	2. Redistributions in binary form must reproduce the above copyright
29
	   notices, this list of conditions and the following disclaimer in the
30
	   documentation and/or other materials provided with the distribution.
31

    
32
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
34
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
35
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
36
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
	POSSIBILITY OF SUCH DAMAGE.
42
*/
43

    
44
require_once('config.inc');
45
require_once('pfsense-utils.inc');
46
require_once('util.inc');
47

    
48
// Return the list of ciphers OpenVPN supports
49
function openvpn_get_ciphers($pkg) {
50
	global $config;
51

    
52
	foreach ($pkg['fields']['field'] as $i => $field) {
53
		if ($field['fieldname'] == 'crypto') {
54
			$option_array = &$pkg['fields']['field'][$i]['options']['option'];
55
			$ciphers_out = shell_exec('openvpn --show-ciphers | grep "default key" | awk \'{print $1, "(" $2 "-" $3 ")";}\'');
56
			$ciphers = explode("\n", trim($ciphers_out));
57
			sort($ciphers);
58
			foreach ($ciphers as $cipher) {
59
				$value = explode(' ', $cipher);
60
				$value = $value[0];
61
				$option_array[] = array('value' => $value, 'name' => $cipher);
62
			}
63
		} 
64
		if ($field['fieldname'] == 'cipher') {
65
		        if (is_array($config['openvpn']['keys'])) {
66
                		if (count($config['openvpn']['keys']) > 0) {
67
					$option_array = &$pkg['fields']['field'][$i]['options']['option'];
68
                        		foreach ($config['openvpn']['keys'] as $cipher => $type) {
69
						if ($type['shared.key'])
70
							$option_array[] = array('value' => $cipher, 'name' => $cipher);
71
                       			}
72
                		}
73
        		}
74
		}
75
                if ($field['fieldname'] == 'cipherpki') {
76
                        if (is_array($config['openvpn']['keys'])) {
77
                                if (count($config['openvpn']['keys']) > 0) {
78
                                        $option_array = &$pkg['fields']['field'][$i]['options']['option'];
79
                                        foreach ($config['openvpn']['keys'] as $cipher => $type) {
80
                                                if ($type['auth_method'] == 'pki')
81
                                                        $option_array[] = array('value' => $cipher, 'name' => $type['descr']);
82
                                        }
83
                                }
84
                        }
85
                }
86

    
87
	}
88
}
89

    
90
function openvpn_validate_port($value, $name) {
91
	$value = trim($value);
92
	if (!empty($value) && !(is_numeric($value) && ($value > 0) && ($value < 65535)))
93
		return "The field '$name' must contain a valid port, ranging from 0 to 65535.";
94
	return false;
95
}
96

    
97

    
98
function openvpn_validate_cidr($value, $name) {
99
	$value = trim($value);
100
	if (!empty($value)) {
101
		list($ip, $mask) = explode('/', $value);
102
		if (!is_ipaddr($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
103
			return "The field '$name' must contain a valid CIDR range.";
104
	}
105
	return false;
106
}
107

    
108

    
109
// Do the input validation
110
function openvpn_validate_input($mode, $post, $input_errors) {
111
	$Mode = ucfirst($mode);
112

    
113
	if ($mode == 'server') {
114
		if ($result = openvpn_validate_port($post['local_port'], 'Local port'))
115
			$input_errors[] = $result;
116

    
117
		if ($result = openvpn_validate_cidr($post['addresspool'], 'Address pool'))
118
			$input_errors[] = $result;
119

    
120
		if ($result = openvpn_validate_cidr($post['local_network'], 'Local network'))
121
			$input_errors[] = $result;
122
			
123
/*  check for port in use - update of existing entries not possible because $_GET['act'] is not passed from pkg_edit.php :-( mfuchs		
124
    $portinuse = shell_exec('sockstat | grep '.$post['local_port'].' | grep '.strtolower($post['protocol']));
125
    if (!empty($portinuse))
126
    $input_errors[] = 'The port '.$post['local_port'].'/'.strtolower($post['protocol']).' is already in use.';
127
*/
128

    
129
	if (!empty($post['dhcp_dns'])) {
130
    $servers = explode(';', $post['dhcp_dns']);
131
      foreach ($servers as $server) if (!is_ipaddr($server))
132
        {$input_errors[] = 'The field \'DHCP Option: DNS Server\' must contain a valid IP address and no whitespaces.';
133
        break;}}
134
	if (!empty($post['dhcp_wins'])) {
135
    $servers = explode(';', $post['dhcp_wins']);
136
      foreach ($servers as $server) if (!is_ipaddr($server))
137
        {$input_errors[] = 'The field \'DHCP Option: WINS Server\' must contain a valid IP address and no whitespaces.';
138
        break;}}
139
	if (!empty($post['dhcp_nbdd'])) {
140
    $servers = explode(';', $post['dhcp_nbdd']);
141
      foreach ($servers as $server) if (!is_ipaddr($server))
142
        {$input_errors[] = 'The field \'DHCP Option: NBDD Server\' must contain a valid IP address and no whitespaces.';
143
        break;}}
144
	if (!empty($post['dhcp_ntp'])) {
145
    $servers = explode(';', $post['dhcp_ntp']);
146
      foreach ($servers as $server) if (!is_ipaddr($server))
147
        {$input_errors[] = 'The field \'DHCP Option: NTP Server\' must contain a valid IP address and no whitespaces.';
148
        break;}}
149
	if (isset($post['maxclients']) && $post['maxclients'] != "") {
150
		if (!is_numeric($post['maxclients']))
151
			$input_errors[] = 'The field \'Maximum clients\' must be numeric.';
152
		}
153

    
154
	}
155

    
156
	else { // Client mode
157
		if ($result = openvpn_validate_port($post['serverport'], 'Server port'))
158
			$input_errors[] = $result;
159

    
160
		$server_addr = trim($post['serveraddr']);
161
		if (!empty($value) && !(is_domain($server_addr) || is_ipaddr($server_addr)))
162
			$input_errors[] = 'The field \'Server address\' must contain a valid IP address or domain name.';
163

    
164
		if ($result = openvpn_validate_cidr($post['interface_ip'], 'Interface IP'))
165
			$input_errors[] = $result;
166

    
167
		if ($post['auth_method'] == 'shared_key') {
168
			if (empty($post['interface_ip']))
169
				$input_errors[] = 'The field \'Interface IP\' is required.';
170
		}
171
		if (isset($post['proxy_hostname']) && $post['proxy_hostname'] != "") {
172
			if (!is_domain($post['proxy_hostname']) || is_ipaddr($post['proxy_hostname']))
173
				$input_errors[] = 'The field \'Proxy Host\' must contain a valid IP address or domain name.';
174
			if (!is_port($post['proxy_port']))
175
				$input_errors[] = 'The field \'Proxy port\' must contain a valid port number.';
176
			if ($post['protocol'] != "TCP")
177
				$input_errors[] = 'The protocol must be TCP to use a HTTP proxy server.';
178
		}
179
		if (isset($post['use_shaper']) && $post['use_shaper'] != "") {
180
			if (!is_numeric($post['use_shaper']))
181
				$input_errors[] = 'The field \'Limit outgoing bandwidth\' must be numeric.';
182
		}
183

    
184
	}
185

    
186
	if ($result = openvpn_validate_cidr($post['remote_network'], 'Remote network'))
187
		$input_errors[] = $result;
188

    
189
/* This are no more needed comment them from now and remove later */
190
/*
191
	if ($_POST['auth_method'] == 'shared_key') {
192
		$reqfields[] = 'shared_key';
193
		$reqfieldsn[] = 'Shared key';
194
	}
195
	else {
196
		$req = explode(' ', "ca_cert {$mode}_cert {$mode}_key");
197
		$reqn = array(	'CA certificate',
198
				ucfirst($mode) . ' certificate',
199
				ucfirst($mode) . ' key');
200
		$reqfields = array_merge($reqfields, $req);
201
		$reqfieldsn = array_merge($reqfieldsn, $reqn);
202
		if ($mode == 'server') {
203
			$reqfields[] = 'dh_params';
204
			$reqfieldsn[] = 'DH parameters';
205
		}
206
	}
207
	do_input_validation($post, $reqfields, $reqfieldsn, &$input_errors);
208
*/
209
if ($mode != "server") {
210
	$value = trim($post['shared_key']);
211
	$items = array();
212

    
213
	if ($_POST['auth_method'] == 'shared_key') {
214
		$items[] = array(	'field' => 'shared.key',
215
					'string' => 'OpenVPN Static key V1',
216
					'name' => 'Shared key');
217
	}
218
	else {
219
		$items[] = array(	'field' => 'ca.crt',
220
					'string' => 'CERTIFICATE',
221
					'name' => 'CA certificate');
222
		$items[] = array(	'field' => "{$mode}.crt",
223
					'string' => 'CERTIFICATE',
224
					'name' => "$Mode certificate");
225
		$items[] = array(	'field' => "{$mode}.key",
226
					'string' => 'RSA PRIVATE KEY',
227
					'name' => "$Mode key");
228
	  $items[] = array(	'field' => 'tls',
229
		      'string' => 'OpenVPN Static key V1',
230
		      'name' => 'TLS');
231
		if ($mode == 'server') {
232
			$items[] = array(	'field' => 'dh_param.dhs',
233
						'string' => 'DH PARAMETERS',
234
						'name' => 'DH parameters');
235
			$items[] = array(	'field' => 'crl.crl',
236
						'string' => 'X509 CRL',
237
						'name' => 'CRL');
238
		}
239
	}
240
	foreach ($items as $item) {
241
		$value = trim($_POST[$item['field']]);
242
		$string = $item['string'];
243
		if ($value && (!strstr($value, "-----BEGIN {$string}-----") || !strstr($value, "-----END {$string}-----")))
244
			$input_errors[] = "The field '{$item['name']}' does not appear to be valid";
245
	}
246
}
247
}
248

    
249

    
250
function openvpn_validate_input_csc($post, $input_errors) {
251
	if ($result = openvpn_validate_cidr($post['ifconfig_push'], 'Interface IP'))
252
		$input_errors[] = $result;
253

    
254
	if ($post['push_reset'] != 'on') {
255
    if (!empty($post['dhcp_domainname']))
256
        $input_errors[] = 'It makes no sense to unselect push reset and configure DHCP options';
257
    elseif (!empty($post['dhcp_dns']))
258
        $input_errors[] = 'It makes no sense to unselect push reset and configure DHCP options';
259
    elseif (!empty($post['dhcp_wins']))
260
        $input_errors[] = 'It makes no sense to unselect push reset and configure DHCP options';
261
    elseif (!empty($post['dhcp_nbdd']))
262
        $input_errors[] = 'It makes no sense to unselect push reset and configure DHCP options';
263
    elseif (!empty($post['dhcp_ntp']))
264
        $input_errors[] = 'It makes no sense to unselect push reset and configure DHCP options';
265
    elseif ($post['dhcp_nbttype'])
266
        $input_errors[] = 'It makes no sense to unselect push reset and configure DHCP options';
267
    elseif (!empty($post['dhcp_nbtscope']))
268
        $input_errors[] = 'It makes no sense to unselect push reset and configure DHCP options';
269
    elseif ($post['dhcp_nbtdisable'])
270
        $input_errors[] = 'It makes no sense to unselect push reset and configure DHCP options';
271

    
272
  }
273
  else {
274

    
275
	if (!empty($post['dhcp_dns'])) {
276
    $servers = explode(';', $post['dhcp_dns']);
277
      foreach ($servers as $server) if (!is_ipaddr($server))
278
        {$input_errors[] = 'The field \'DHCP Option: DNS Server\' must contain a valid IP address and no whitespaces.';
279
        break;}}
280
	if (!empty($post['dhcp_wins'])) {
281
    $servers = explode(';', $post['dhcp_wins']);
282
      foreach ($servers as $server) if (!is_ipaddr($server))
283
        {$input_errors[] = 'The field \'DHCP Option: WINS Server\' must contain a valid IP address and no whitespaces.';
284
        break;}}
285
	if (!empty($post['dhcp_nbdd'])) {
286
    $servers = explode(';', $post['dhcp_nbdd']);
287
      foreach ($servers as $server) if (!is_ipaddr($server))
288
        {$input_errors[] = 'The field \'DHCP Option: NBDD Server\' must contain a valid IP address and no whitespaces.';
289
        break;}}
290
	if (!empty($post['dhcp_ntp'])) {
291
    $servers = explode(';', $post['dhcp_ntp']);
292
      foreach ($servers as $server) if (!is_ipaddr($server))
293
        {$input_errors[] = 'The field \'DHCP Option: NTP Server\' must contain a valid IP address and no whitespaces.';
294
        break;}}
295

    
296
}}
297

    
298
// Create server PKI certificate if it is not present on system 
299
function openvpn_server_create_cert($mode, $id) {
300
	if($mode == "client") 
301
		return;
302
	global $g, $config;
303
	$settings = $config['installedpackages']["openvpn$mode"]['config'][$id];
304
	log_error("Creating server certificate for {$settings['description']}.");
305
	$cakeysize = $settings['keysize'];
306
	$caname = $settings['cipherpki'];
307
	$ovpncapath = $g['varetc_path']."/openvpn/certificates";	
308
	$easyrsapath = $g['easyrsapath'];
309
	config_lock();
310
	$fd = fopen($ovpncapath . "/RUNME_2ND", "w");
311
	fwrite($fd, "cd $ovpncapath \n");
312
	fwrite($fd, "source $ovpncapath/$caname/vars \n");
313
	fwrite($fd, "$easyrsapath/pkitool --batch --server server \n");
314
	fwrite($fd, "openssl dhparam -out $ovpncapath/$caname/dh_params.dh  $cakeysize \n");
315
	fclose($fd);
316
	system("/bin/chmod a+rx $ovpncapath/RUNME_2ND");
317
	mwexec("/bin/tcsh $ovpncapath/RUNME_2ND");
318
	$config['installedpackages']["openvpn$mode"]['config'][$id]['server.key'] = file_get_contents("$ovpncapath/$caname/server.key");
319
	$config['installedpackages']["openvpn$mode"]['config'][$id]['server.crt'] = file_get_contents("$ovpncapath/$caname/server.crt");
320
	$config['installedpackages']["openvpn$mode"]['config'][$id]['dh_params.dh'] = file_get_contents("$ovpncapath/$caname/dh_params.dh");
321
	config_unlock();
322
	write_config();	
323
	log_error("Server certificate for {$settings['description']} created.");
324
}
325

    
326
// Rewrite the settings
327
function openvpn_reconfigure($mode, $id) {
328
	global $g, $config;
329

    
330
	$settings = $config['installedpackages']["openvpn$mode"]['config'][$id];
331
	
332
	if ($settings['disable']) 
333
		return;
334

    
335
	/* create cert if needed */
336
	if(!$settings['server.key'] and $mode == "server") 
337
		openvpn_server_create_cert($mode, $id);
338

    
339
	$lport = 1194 + $id;
340

    
341
	/*
342
	 * NOTE: if you change the name of the interfaces here than
343
	 * be sure to change it even on the openvpn command parameters at
344
	 * openvpn_restart() function.
345
	 */
346
	if (!$g['booting'])
347
		mwexec("/sbin/ifconfig ovpn{$id} destroy");
348
	mwexec("/sbin/ifconfig tun{$id} create");
349
	mwexec("/sbin/ifconfig tun{$id} name ovpn{$id}");
350
	mwexec("/sbin/ifconfig ovpn{$id} group openvpn");
351

    
352
        $pidfile = $g['varrun_path'] . "/openvpn_{$mode}{$id}.pid";
353
        $proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}");
354
        $cipher = $settings['crypto'];
355
	$openvpn_conf = "dev ovpn{$id}\n";
356
	$openvpn_conf .= "dev-type tun\n";
357
	$openvpn_conf .= "dev-node /dev/tun{$id}\n";
358
        $openvpn_conf .= <<<EOD
359
writepid $pidfile
360
#user nobody
361
#group nobody
362
daemon
363
keepalive 10 60
364
ping-timer-rem
365
persist-tun
366
persist-key
367
proto $proto
368
cipher $cipher
369
up /etc/rc.filter_configure
370
down /etc/rc.filter_configure
371

    
372
EOD;
373

    
374
	// Mode-specific stuff
375
	if ($mode == 'server') {
376
		list($ip, $mask) = explode('/', $settings['addresspool']);
377
		$mask = gen_subnet_mask($mask);
378

    
379
		// Using a shared key or not dynamically assigning IPs to the clients
380
		if (($settings['auth_method'] == 'shared_key') || ($settings['nopool'] == 'on')) {
381
			if ($settings['auth_method'] == 'pki') $openvpn_conf .= "tls-server\n";
382

    
383
			$baselong = ip2long($ip) & ip2long($mask);
384
			$ip1 = long2ip($baselong + 1);
385
			$ip2 = long2ip($baselong + 2);
386
			$openvpn_conf .= "ifconfig $ip1 $ip2\n";
387
		}
388
		// Using a PKI
389
		else if ($settings['auth_method'] == 'pki') {
390
			if ($settings['client2client']) $openvpn_conf .= "client-to-client\n";
391
			$openvpn_conf .= "server $ip $mask\n";
392
			$csc_dir = "{$g['varetc_path']}/openvpn_csc";
393
			$openvpn_conf .= "client-config-dir $csc_dir\n";
394
		}
395

    
396
		// We can push routes
397
		if (!empty($settings['local_network'])) {
398
			list($ip, $mask) = explode('/', $settings['local_network']);
399
			$mask = gen_subnet_mask($mask);
400
			$openvpn_conf .= "push \"route $ip $mask\"\n";
401
		}
402

    
403
        if ($settings['bind_to_iface'] == 'on') {
404
            $iface = $settings['interface'];
405
            $iface = convert_friendly_interface_to_real_interface_name($iface);
406
            $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6"));
407
            list($dummy, $ip, $dummy2, $dummy3) = explode(' ', $line);
408

    
409
            $openvpn_conf .= "local {$ip}\n";
410
        }
411

    
412
		// The port we'll listen at
413
		$openvpn_conf .= "lport {$settings['local_port']}\n";
414

    
415
		// DHCP-Options
416
	  if (!empty($settings['dhcp_domainname'])) $openvpn_conf .= "push \"dhcp-option DOMAIN {$settings['dhcp_domainname']}\"\n";
417

    
418
    if (!empty($settings['dhcp_dns'])) {
419
	   	$servers = explode(';', $settings['dhcp_dns']);
420
   	  if (is_array($servers)) {
421
			 foreach ($servers as $server) $openvpn_conf .= "push \"dhcp-option DNS {$server}\"\n";
422
  	  }
423
		  else {
424
			$openvpn_conf .= "push \"dhcp-option DNS {$settings['dhcp_dns']}\"\n";
425
		  }
426
    }
427

    
428
    if (!empty($settings['dhcp_wins'])) {
429
	   	$servers = explode(';', $settings['dhcp_wins']);
430
   	  if (is_array($servers)) {
431
			 foreach ($servers as $server) $openvpn_conf .= "push \"dhcp-option WINS {$server}\"\n";
432
  	  }
433
		  else {
434
			$openvpn_conf .= "push \"dhcp-option WINS {$settings['dhcp_wins']}\"\n";
435
		  }
436
    }
437

    
438
    if (!empty($settings['dhcp_nbdd'])) {
439
	   	$servers = explode(';', $settings['dhcp_nbdd']);
440
   	  if (is_array($servers)) {
441
			 foreach ($servers as $server) $openvpn_conf .= "push \"dhcp-option NBDD {$server}\"\n";
442
  	  }
443
		  else {
444
			$openvpn_conf .= "push \"dhcp-option NBDD {$settings['dhcp_nbdd']}\"\n";
445
		  }
446
    }
447

    
448
    if (!empty($settings['dhcp_ntp'])) {
449
	   	$servers = explode(';', $settings['dhcp_ntp']);
450
   	  if (is_array($servers)) {
451
			 foreach ($servers as $server) $openvpn_conf .= "push \"dhcp-option NTP {$server}\"\n";
452
  	  }
453
		  else {
454
			$openvpn_conf .= "push \"dhcp-option NTP {$settings['dhcp_ntp']}\"\n";
455
		  }
456
    }
457

    
458
  	if (!empty($settings['dhcp_nbttype']) && $settings['dhcp_nbttype'] !=0) $openvpn_conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
459
    if (!empty($settings['dhcp_nbtscope'])) $openvpn_conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
460
   	if ($settings['dhcp_nbtdisable']) $openvpn_conf .= "push \"dhcp-option DISABLE-NBT\"\n";
461

    
462
    if (!empty($settings['tls'])) $openvpn_conf .= "tls-auth {$g['varetc_path']}/openvpn_server{$id}.tls 0\n";
463
		if (!empty($settings['maxclients'])) $openvpn_conf .= "max-clients {$settings['maxclients']}\n";
464
		if ($settings['gwredir']) $openvpn_conf .= "push \"redirect-gateway def1\"\n";
465
			}
466

    
467
	else { // $mode == client
468
		// The remote server
469
		$openvpn_conf .= "remote {$settings['serveraddr']} {$settings['serverport']}\n";
470

    
471
		if ($settings['auth_method'] == 'pki') $openvpn_conf .= "client\n";
472
		if ($settings['use_dynamicport']) $openvpn_conf .= "nobind\n";
473
			else
474
			// The port we'll listen at
475
			$openvpn_conf .= "lport {$lport}\n";
476

    
477
		if (!empty($settings['use_shaper'])) $openvpn_conf .= "shaper {$settings['use_shaper']}\n";
478

    
479
		if (!empty($settings['interface_ip'])) {
480
			// Configure the IPs according to the address pool
481
			list($ip, $mask) = explode('/', $settings['interface_ip']);
482
			$mask = gen_subnet_mask($mask);
483
			$baselong = ip2long($ip) & ip2long($mask);
484
			$ip1 = long2ip($baselong + 1);
485
			$ip2 = long2ip($baselong + 2);
486
			$openvpn_conf .= "ifconfig $ip2 $ip1\n";
487
		}
488
		if (isset($settings['proxy_hostname']) && $settings['proxy_hostname'] != "") {
489
			/* ;http-proxy-retry # retry on connection failures */
490
			$openvpn_conf .= "http-proxy {$settings['proxy_hostname']} {$settings['proxy_port']}\n";
491
		}
492

    
493
    if (!empty($settings['tls'])) $openvpn_conf .= "tls-auth {$g['varetc_path']}/openvpn_client{$id}.tls 1\n";
494

    
495
	}
496

    
497
	// Add the routes if they're set
498
	if (!empty($settings['remote_network'])) {
499
		list($ip, $mask) = explode('/', $settings['remote_network']);
500
		$mask = gen_subnet_mask($mask);
501
		$openvpn_conf .= "route $ip $mask\n";
502
	}
503

    
504
		
505

    
506
        // Write the settings for the keys
507
        // Set the keys up
508
        $base_file = $g['varetc_path'] . "/openvpn/certificates/";
509
        $keys = array();
510
        if ($settings['auth_method'] == 'shared_key')
511
                $keys[] = array('field' => 'shared.key', 'ext'  => 'secret', 'directive' => 'secret');
512
        else {
513
                $keys[] = array('field' => 'ca.crt', 'directive' => 'ca');
514
                $keys[] = array('field' => "{$mode}.crt", 'directive' => 'cert');
515
                $keys[] = array('field' => "{$mode}.key", 'directive' => 'key');
516
                if ($mode == 'server')
517
                        $keys[] = array('field' => 'dh_params.dh', 'directive' => 'dh');
518
                if ($settings['crl'])
519
                        $keys[] = array('field' => 'crl.crl', 'directive' => 'crl-verify');
520
        }
521

    
522
        foreach ($keys as $key) {
523
                if ($mode == "server") {
524
			if ($settings['auth_method'] == 'pki' && isset($settings['cipherpki']) && 
525
				$settings['cipherpki'] != "none") 
526
                        	$openvpn_conf .= $key['directive'] . " " . $base_file . $settings['cipherpki'] . 
527
							"/".$key['field']."\n";
528
			else if ($settings['auth_method'] == 'pki' && isset($settings['cipherpki']) && 
529
				$settings['cipherpki'] != "none") 
530
                        	$openvpn_conf .= $key['directive'] . " " . $base_file . $settings['cipherpki'] . 
531
							"/".$key['field']."\n";
532
                } else {
533
                        $filename = $g['varetc_path']."/openvpn_{$mode}{$id}." . $key['field'];
534
                        file_put_contents($filename, base64_decode($settings[$key['field']]));
535
                        chown($filename, 'nobody');
536
                        chgrp($filename, 'nobody');
537
                        $openvpn_conf .= $key['directive'] . " $filename \n";
538
                }
539
        }
540

    
541
	if ($settings['use_lzo']) $openvpn_conf .= "comp-lzo\n";
542

    
543
	if ($settings['passtos']) $openvpn_conf .= "passtos\n";
544
	
545
	if ($settings['infiniteresolvretry']) $openvpn_conf .= "resolv-retry infinite\n";
546
	
547
	if ($settings['dynamic_ip']) {
548
		$openvpn_conf .= "persist-remote-ip\n";
549
		$openvpn_conf .= "float\n";
550
	}
551

    
552
	if (!empty($settings['custom_options'])) {
553
		$options = explode(';', $settings['custom_options']);
554
		if (is_array($options)) {
555
			foreach ($options as $option)
556
				$openvpn_conf .= "$option\n";
557
		}
558
		else {
559
			$openvpn_conf .= "{$settings['custom_options']}\n";
560
		}
561
	}
562

    
563
	file_put_contents($g['varetc_path'] . "/openvpn_{$mode}{$id}.conf", $openvpn_conf);
564
}
565

    
566

    
567
function openvpn_resync_csc($id) {
568
	global $g, $config;
569

    
570
	$settings = $config['installedpackages']['openvpncsc']['config'][$id];
571

    
572
	if ($settings['disable'] == 'on') {
573
		$filename = "{$g['varetc_path']}/openvpn_csc/{$settings['commonname']}";
574
		unlink_if_exists($filename);
575
		return;
576
	}
577
	
578
	$conf = '';
579
	if ($settings['block'] == 'on') $conf .= "disable\n";
580
	if ($settings['push_reset'] == 'on') $conf .= "push-reset\n";
581
	if (!empty($settings['ifconfig_push'])) {
582
		list($ip, $mask) = explode('/', $settings['ifconfig_push']);
583
		$baselong = ip2long($ip) & gen_subnet_mask_long($mask);
584
		$conf .= 'ifconfig-push ' . long2ip($baselong + 1) . ' ' . long2ip($baselong + 2) . "\n";
585
	}
586

    
587
// DHCP-Options
588
	  if (!empty($settings['dhcp_domainname'])) $conf .= "push \"dhcp-option DOMAIN {$settings['dhcp_domainname']}\"\n";
589

    
590
    if (!empty($settings['dhcp_dns'])) {
591
	   	$servers = explode(';', $settings['dhcp_dns']);
592
   	  if (is_array($servers)) {
593
			 foreach ($servers as $server) $conf .= "push \"dhcp-option DNS {$server}\"\n";
594
  	  }
595
		  else {
596
			$conf .= "push \"dhcp-option DNS {$settings['dhcp_dns']}\"\n";
597
		  }
598
    }
599

    
600
    if (!empty($settings['dhcp_wins'])) {
601
	   	$servers = explode(';', $settings['dhcp_wins']);
602
   	  if (is_array($servers)) {
603
			 foreach ($servers as $server) $conf .= "push \"dhcp-option WINS {$server}\"\n";
604
  	  }
605
		  else {
606
			$conf .= "push \"dhcp-option WINS {$settings['dhcp_wins']}\"\n";
607
		  }
608
    }
609

    
610
    if (!empty($settings['dhcp_nbdd'])) {
611
	   	$servers = explode(';', $settings['dhcp_nbdd']);
612
   	  if (is_array($servers)) {
613
			 foreach ($servers as $server) $conf .= "push \"dhcp-option NBDD {$server}\"\n";
614
  	  }
615
		  else {
616
			$conf .= "push \"dhcp-option NBDD {$settings['dhcp_nbdd']}\"\n";
617
		  }
618
    }
619

    
620
    if (!empty($settings['dhcp_ntp'])) {
621
	   	$servers = explode(';', $settings['dhcp_ntp']);
622
   	  if (is_array($servers)) {
623
			 foreach ($servers as $server) $conf .= "push \"dhcp-option NTP {$server}\"\n";
624
  	  }
625
		  else {
626
			$conf .= "push \"dhcp-option NTP {$settings['dhcp_ntp']}\"\n";
627
		  }
628
    }
629

    
630
  	if (!empty($settings['dhcp_nbttype']) && $settings['dhcp_nbttype'] !=0) $conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
631
    if (!empty($settings['dhcp_nbtscope'])) $conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
632
   	if ($settings['dhcp_nbtdisable']) $conf .= "push \"dhcp-option DISABLE-NBT\"\n";
633
    if ($settings['gwredir']) $conf .= "push \"redirect-gateway def1\"\n";
634

    
635
	if (!empty($settings['custom_options'])) {
636
		$options = explode(';', $settings['custom_options']);
637
		if (is_array($options)) {
638
			foreach ($options as $option)
639
				$conf .= "$option\n";
640
		}
641
		else {
642
			$conf .= "{$settings['custom_options']}\n";
643
		}
644
	}
645

    
646
	$filename = "{$g['varetc_path']}/openvpn_csc/{$settings['commonname']}";
647
	file_put_contents($filename, $conf);
648
	chown($filename, 'nobody');
649
	chgrp($filename, 'nogroup');
650

    
651
}
652

    
653

    
654
function openvpn_restart($mode, $id) {
655
	global $g, $config;
656

    
657
	$pidfile = $g['varrun_path'] . "/openvpn_{$mode}{$id}.pid";
658
	killbypid($pidfile);
659
	sleep(2);
660

    
661
	$settings = $config['installedpackages']["openvpn$mode"]['config'][$id];
662
	if ($settings['disable']) return;
663

    
664
	$configfile = $g['varetc_path'] . "/openvpn_{$mode}{$id}.conf";
665
	mwexec_bg("nohup openvpn --config $configfile");// --dev-type tun --dev-node /dev/tun{$id}");
666
	touch("{$g['tmp_path']}/filter_dirty");
667
}
668

    
669
//Make ciphers ready for openvpn
670
function openvpn_restore_all_ciphers() {
671
        global $config, $g;
672

    
673
        $ovpncapath = $g['varetc_path']."/openvpn/certificates";
674

    
675
        if (is_array($config['openvpn']['keys'])) {
676
                if (!is_dir($g['varetc_path']."/openvpn"))
677
                        safe_mkdir($g['varetc_path']."/openvpn");
678
                if (!is_dir($ovpncapath))
679
                        safe_mkdir($ovpncapath);
680

    
681
                /* XXX: hardcoded path; worth making it a global?! */
682
                mwexec("cp -r /usr/local/share/openvpn/certificates ".$g['varetc_path']."/openvpn/");
683
                if (!is_dir($ovpncapath)) {
684
                        log_error("Failed to create environment for creating certificates. ");
685
                } else {
686

    
687
                        foreach ($config['openvpn']['keys'] as $caname => $ciphers) {
688
                                if (!is_dir("$ovpncapath/$caname"))
689
                                        safe_mkdir("$ovpncapath/$caname");
690

    
691
                                $cfg = "";
692
                                /* NOTE: vars; Do we need them restored?! */
693
                                $cfg .= "setenv KEY_SIZE " .$ciphers['keysize'] ."\n";
694
                                $cfg .= "setenv KEY_EXPIRE ".$ciphers['keyexpire'] ."\n";
695
                                $cfg .= "setenv CA_EXPIRE " .$ciphers['caexpire'] . "\n";
696
                                $cfg .= "setenv KEY_COUNTRY " .$ciphers['keycountry'] ."\n";
697
                                $cfg .= "setenv KEY_RPOVINCE " .$ciphers['keyprovince'] . "\n";
698
                                $cfg .= "setenv KEY_CITY " .$ciphers['keycity'] . "\n";
699
                                $cfg .= "setenv KEY_ORG " .$ciphers['keyorg'] . "\n";
700
                                $cfg .= "setenv KEY_EMAIL " .$ciphers['keyemail'] . "\n";
701
                                file_put_contents("$ovpncapath/$caname/vars", $cfg);
702
                                /* put ciphers back in their files */
703
                                foreach ($ciphers as $filename => $value) {
704
                                        file_put_contents("$ovpncapath/$caname/$filename", $value);
705
                                }
706
                        }
707
                }
708
        }
709
}
710

    
711
// Resync the configuration and restart the VPN
712
function openvpn_resync($mode, $id) {
713
	openvpn_reconfigure($mode, $id);
714
	openvpn_restart($mode, $id);
715
}
716

    
717
function openvpn_create_cscdir() {
718
	global $g;
719

    
720
	$csc_dir = "{$g['varetc_path']}/openvpn_csc";
721
	if (is_dir($csc_dir))
722
		rmdir_recursive($csc_dir);
723
	make_dirs($csc_dir);
724
	chown($csc_dir, 'nobody');
725
	chgrp($csc_dir, 'nobody');
726
}
727

    
728
// Resync and restart all VPNs
729
function openvpn_resync_all() {
730
	global $config;
731
	$ovpncapath = $g['varetc_path']."/openvpn/certificates";
732

    
733
 	openvpn_restore_all_ciphers();
734

    
735
	foreach (array('server', 'client') as $mode) {
736
		if ($config['installedpackages']["openvpn$mode"]) {
737
			if (is_array($config['installedpackages']["openvpn$mode"]['config'])) {
738
				foreach ($config['installedpackages']["openvpn$mode"]['config'] as $id => $settings)
739
					openvpn_resync($mode, $id);
740
			}
741
		}
742
	}
743

    
744
	openvpn_create_cscdir();
745
	if ($config['installedpackages']['openvpncsc']) {
746
		if (is_array($config['installedpackages']['openvpncsc']['config'])) {
747
			foreach ($config['installedpackages']['openvpncsc']['config'] as $id => $csc)
748
				openvpn_resync_csc($id);
749
		}
750
	}
751
	
752
	/* give speedy machines time to settle */
753
	sleep(5);
754

    
755
	/* reload the filter policy */
756
	filter_configure();
757

    
758
}
759

    
760
function openvpn_print_javascript($mode) {
761
	$javascript = <<<EOD
762
<script language="JavaScript">
763
//<!--
764
function onAuthMethodChanged() {
765
	var method = document.iform.auth_method;
766
	var endis = (method.options[method.selectedIndex].value == 'shared_key');
767

    
768
	if ('$mode' == 'server') {
769
	document.iform.nopool.disabled = endis;
770
	document.iform.local_network.disabled = endis;
771
	document.iform.client2client.disabled = endis;
772
	document.iform.maxclients.disabled = endis;
773
	document.iform.cipher.disabled = !endis;
774
	document.iform.cipherpki.disabled = endis;
775
	}
776
	else { // Client mode
777
		document.iform.remote_network.disabled = !endis;;
778
 	        document.iform['shared.key'].disabled = !endis;
779
    	   	document.iform['ca.crt'].disabled = endis;
780
        	document.iform["{$mode}.crt"].disabled = endis;
781
        	document.iform["{$mode}.key"].disabled = endis;
782
        	document.iform.tls.disabled = endis;
783
	}
784
}
785
//-->
786
</script>
787

    
788
EOD;
789
	print($javascript);
790
}
791

    
792

    
793
function openvpn_print_javascript2() {
794
	$javascript = <<<EOD
795
<script language="JavaScript">
796
//<!--
797
	onAuthMethodChanged();
798
//-->
799
</script>
800

    
801
EOD;
802
	print($javascript);
803
}
804
?>
(14-14/29)