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
	$fd = fopen($ovpncapath . "/RUNME_2ND", "w");
310
	fwrite($fd, "cd $ovpncapath \n");
311
	fwrite($fd, "source $ovpncapath/$caname/vars \n");
312
	fwrite($fd, "$easyrsapath/pkitool --batch --server server \n");
313
	fwrite($fd, "openssl dhparam -out $ovpncapath/$caname/dh_params.dh  $cakeysize \n");
314
	fclose($fd);
315
	system("/bin/chmod a+rx $ovpncapath/RUNME_2ND");
316
	mwexec("/bin/tcsh $ovpncapath/RUNME_2ND");
317
	$config['installedpackages']["openvpn$mode"]['config'][$id]['server.key'] = file_get_contents("$ovpncapath/$caname/server.key");
318
	$config['installedpackages']["openvpn$mode"]['config'][$id]['server.crt'] = file_get_contents("$ovpncapath/$caname/server.crt");
319
	$config['installedpackages']["openvpn$mode"]['config'][$id]['dh_params.dh'] = file_get_contents("$ovpncapath/$caname/dh_params.dh");
320
	write_config();	
321
	log_error("Server certificate for {$settings['description']} created.");
322
}
323

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

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

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

    
337
	$lport = 1194 + $id;
338

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

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

    
370
EOD;
371

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

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

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

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

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

    
407
            $openvpn_conf .= "local {$ip}\n";
408
        }
409

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

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

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

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

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

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

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

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

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

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

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

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

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

    
493
	}
494

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

    
502
		
503

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

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

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

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

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

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

    
564

    
565
function openvpn_resync_csc($id) {
566
	global $g, $config;
567

    
568
	$settings = $config['installedpackages']['openvpncsc']['config'][$id];
569

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

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

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

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

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

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

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

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

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

    
649
}
650

    
651

    
652
function openvpn_restart($mode, $id) {
653
	global $g, $config;
654

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

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

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

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

    
671
        $ovpncapath = $g['varetc_path']."/openvpn/certificates";
672

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

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

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

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

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

    
715
function openvpn_create_cscdir() {
716
	global $g;
717

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

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

    
731
 	openvpn_restore_all_ciphers();
732

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

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

    
753
	/* reload the filter policy */
754
	filter_configure();
755

    
756
}
757

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

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

    
786
EOD;
787
	print($javascript);
788
}
789

    
790

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

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