Project

General

Profile

Download (20 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	ipsec.inc
4
	Copyright (C) 2007 Scott Ullrich
5
	Copyright (C) 2008 Shrew Soft Inc
6
	All rights reserved.
7

    
8
	Parts of this code was originally based on vpn_ipsec_sad.php
9
	Copyright (C) 2003-2004 Manuel Kasper
10

    
11
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13

    
14
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16

    
17
	2. Redistributions in binary form must reproduce the above copyright
18
	   notice, this list of conditions and the following disclaimer in the
19
	   documentation and/or other materials provided with the distribution.
20

    
21
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32

    
33
/* IPsec defines */
34
global $ipsec_loglevels;
35
$ipsec_loglevels = array("dmn" => "Daemon", "mgr" => "SA Manager", "ike" => "IKE SA", "chd" => "IKE Child SA",
36
	"job" => "Job Processing", "cfg" => "Configuration backend", "knl" => "Kernel Interface",
37
	"net" => "Networking", "asn" => "ASN encoding", "enc" => "Message encoding",
38
	"imc" => "Integrity checker", "imv" => "Integrity Verifier", "pts" => "Platform Trust Service",
39
	"tls" => "TLS handler", "esp" => "IPsec traffic", "lib" => "StrongSwan Lib");
40

    
41
global $ipsec_log_sevs;
42
$ipsec_log_sevs = array(
43
	'-1' => 'Silent',
44
	'0' => 'Audit',
45
	'1' => 'Control',
46
	'2' => 'Diag',
47
	'3' => 'Raw',
48
	'4' => 'Highest'
49
);
50

    
51
global $ipsec_log_cats;
52
$ipsec_log_cats = array(
53
	"dmn" => "Daemon",
54
	"mgr" => "SA Manager",
55
	"ike" => "IKE SA",
56
	"chd" => "IKE Child SA",
57
	"job" => "Job Processing",
58
	"cfg" => "Configuration backend",
59
	"knl" => "Kernel Interface",
60
	"net" => "Networking",
61
	"asn" => "ASN encoding",
62
	"enc" => "Message encoding",
63
	"imc" => "Integrity checker",
64
	"imv" => "Integrity Verifier",
65
	"pts" => "Platform Trust Service",
66
	"tls" => "TLS handler",
67
	"esp" => "IPsec traffic",
68
	"lib" => "StrongSwan Lib"
69
);
70

    
71
global $my_identifier_list;
72
$my_identifier_list = array(
73
	'myaddress' => array('desc' => gettext('My IP address'), 'mobile' => true),
74
	'address' => array('desc' => gettext('IP address'), 'mobile' => true),
75
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
76
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
77
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
78
	'keyid tag' => array('desc' => gettext('KeyID tag'), 'mobile' => true),
79
	'dyn_dns' => array('desc' => gettext('Dynamic DNS'), 'mobile' => true));
80

    
81
global $peer_identifier_list;
82
$peer_identifier_list = array(
83
	'any' => array('desc' => gettext('Any'), 'mobile' => true),
84
	'peeraddress' => array('desc' => gettext('Peer IP address'), 'mobile' => false),
85
	'address' => array('desc' => gettext('IP address'), 'mobile' => false),
86
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
87
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
88
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
89
	'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true));
90

    
91
global $ipsec_idhandling;
92
$ipsec_idhandling = array(
93
	'yes' => 'YES', 'no' => 'NO', 'never' => 'NEVER', 'keep' => 'KEEP'
94
	);
95

    
96
global $p1_ealgos;
97
$p1_ealgos = array(
98
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
99
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
100
	'3des' => array('name' => '3DES'),
101
	'cast128' => array('name' => 'CAST128'));
102

    
103
global $p2_ealgos;
104
$p2_ealgos = array(
105
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
106
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
107
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
108
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
109
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
110
	'3des' => array('name' => '3DES'),
111
	'cast128' => array('name' => 'CAST128'));
112

    
113
global $p1_halgos;
114
$p1_halgos = array(
115
	'md5' => 'MD5',
116
	'sha1' => 'SHA1',
117
	'sha256' => 'SHA256',
118
	'sha384' => 'SHA384',
119
	'sha512' => 'SHA512',
120
	'aesxcbc' => 'AES-XCBC'
121
);
122

    
123
global $p1_dhgroups;
124
$p1_dhgroups = array(
125
	1  => '1 (768 bit)',
126
	2  => '2 (1024 bit)',
127
	5  => '5 (1536 bit)',
128
	14 => '14 (2048 bit)',
129
	15 => '15 (3072 bit)',
130
	16 => '16 (4096 bit)',
131
	17 => '17 (6144 bit)',
132
	18 => '18 (8192 bit)',
133
	19 => '19 (nist ecp256)',
134
	20 => '20 (nist ecp384)',
135
	21 => '21 (nist ecp521)',
136
	22 => '22 (1024(sub 160) bit)',
137
	23 => '23 (2048(sub 224) bit)',
138
	24 => '24 (2048(sub 256) bit)',
139
	28 => '28 (brainpool ecp256)',
140
	29 => '29 (brainpool ecp384)',
141
	30 => '30 (brainpool ecp512)'
142
);
143

    
144
global $p2_halgos;
145
$p2_halgos = array(
146
	'hmac_md5' => 'MD5',
147
	'hmac_sha1' => 'SHA1',
148
	'hmac_sha256' => 'SHA256',
149
	'hmac_sha384' => 'SHA384',
150
	'hmac_sha512' => 'SHA512',
151
	'aesxcbc' => 'AES-XCBC'
152
);
153

    
154
global $p1_authentication_methods;
155
$p1_authentication_methods = array(
156
	'hybrid_rsa_server' => array('name' => 'Hybrid RSA + Xauth', 'mobile' => true),
157
	'xauth_rsa_server' => array('name' => 'Mutual RSA + Xauth', 'mobile' => true),
158
	'xauth_psk_server' => array('name' => 'Mutual PSK + Xauth', 'mobile' => true),
159
	'eap-tls' => array('name' => 'EAP-TLS', 'mobile' => true),
160
	'eap-radius' => array('name' => 'EAP-RADIUS', 'mobile' => true),
161
	'eap-mschapv2' => array('name' => 'EAP-MSChapv2', 'mobile' => true),
162
	'rsasig' => array('name' => 'Mutual RSA', 'mobile' => false),
163
	'pre_shared_key' => array('name' => 'Mutual PSK', 'mobile' => false));
164

    
165
global $ipsec_preshared_key_type;
166
$ipsec_preshared_key_type = array(
167
	'PSK' => 'PSK',
168
	'EAP' => 'EAP'
169
	);
170

    
171
global $p2_modes;
172
$p2_modes = array(
173
	'tunnel' => 'Tunnel IPv4',
174
	'tunnel6' => 'Tunnel IPv6',
175
	'transport' => 'Transport');
176

    
177
global $p2_protos;
178
$p2_protos = array(
179
	'esp' => 'ESP',
180
	'ah' => 'AH');
181

    
182
global $p2_pfskeygroups;
183
$p2_pfskeygroups = array(
184
	0 => 'off',
185
	1  => '1 (768 bit)',
186
	2  => '2 (1024 bit)',
187
	5  => '5 (1536 bit)',
188
	14 => '14 (2048 bit)',
189
	15 => '15 (3072 bit)',
190
	16 => '16 (4096 bit)',
191
	17 => '17 (6144 bit)',
192
	18 => '18 (8192 bit)',
193
	19 => '19 (nist ecp256)',
194
	20 => '20 (nist ecp384)',
195
	21 => '21 (nist ecp521)',
196
	28 => '28 (brainpool ecp256)',
197
	29 => '29 (brainpool ecp384)',
198
	30 => '30 (brainpool ecp512)'
199
);
200

    
201
function ipsec_enabled() {
202
	global $config;
203

    
204
	if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
205
		return false;
206
	}
207

    
208
	/* Check if we have at least one phase 1 entry. */
209
	if (!isset($config['ipsec']['phase1']) ||
210
	    !is_array($config['ipsec']['phase1']) ||
211
	    empty($config['ipsec']['phase1'])) {
212
		return false;
213
	}
214
	/* Check if at least one phase 1 entry is enabled. */
215
	foreach ($config['ipsec']['phase1'] as $phase1) {
216
		if (!isset($phase1['disabled'])) {
217
			return true;
218
		}
219
	}
220

    
221
	return false;
222
}
223

    
224
/*
225
 * ikeid management functions
226
 */
227

    
228
function ipsec_ikeid_used($ikeid) {
229
	global $config;
230

    
231
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
232
		if ($ikeid == $ph1ent['ikeid']) {
233
			return true;
234
		}
235
	}
236

    
237
	return false;
238
}
239

    
240
function ipsec_ikeid_next() {
241

    
242
	$ikeid = 1;
243
	while (ipsec_ikeid_used($ikeid)) {
244
		$ikeid++;
245
	}
246

    
247
	return $ikeid;
248
}
249

    
250
/*
251
 * Return phase1 local address
252
 */
253
function ipsec_get_phase1_src(& $ph1ent) {
254

    
255
	if ($ph1ent['interface']) {
256
		if (!is_ipaddr($ph1ent['interface'])) {
257
			if (strpos($ph1ent['interface'], '_vip')) {
258
				$if = $ph1ent['interface'];
259
			} else {
260
				$if = get_failover_interface($ph1ent['interface']);
261
			}
262
			if ($ph1ent['protocol'] == "inet6") {
263
				$interfaceip = get_interface_ipv6($if);
264
			} else {
265
				$interfaceip = get_interface_ip($if);
266
			}
267
		} else {
268
			$interfaceip = $ph1ent['interface'];
269
		}
270
	} else {
271
		$if = "wan";
272
		if ($ph1ent['protocol'] == "inet6") {
273
			$interfaceip = get_interface_ipv6($if);
274
		} else {
275
			$interfaceip = get_interface_ip($if);
276
		}
277
	}
278

    
279
	return $interfaceip;
280
}
281

    
282
/*
283
 * Return phase1 local address
284
 */
285
function ipsec_get_phase1_dst(& $ph1ent) {
286
	global $g;
287

    
288
	if (empty($ph1ent['remote-gateway'])) {
289
		return false;
290
	}
291
	$rg = $ph1ent['remote-gateway'];
292
	if (!is_ipaddr($rg)) {
293
		if (!platform_booting()) {
294
			return resolve_retry($rg);
295
		}
296
	}
297
	if (!is_ipaddr($rg)) {
298
		return false;
299
	}
300

    
301
	return $rg;
302
}
303

    
304
/*
305
 * Return phase2 idinfo in cidr format
306
 */
307
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
308
	global $config;
309

    
310
	switch ($idinfo['type']) {
311
		case "address":
312
			if ($addrbits) {
313
				if ($mode == "tunnel6") {
314
					return $idinfo['address']."/128";
315
				} else {
316
					return $idinfo['address']."/32";
317
				}
318
			} else {
319
				return $idinfo['address'];
320
			}
321
			break; /* NOTREACHED */
322
		case "network":
323
			return "{$idinfo['address']}/{$idinfo['netbits']}";
324
			break; /* NOTREACHED */
325
		case "none":
326
		case "mobile":
327
			return '0.0.0.0/0';
328
			break; /* NOTREACHED */
329
		default:
330
			if (empty($mode) && !empty($idinfo['mode'])) {
331
				$mode = $idinfo['mode'];
332
			}
333

    
334
			if ($mode == "tunnel6") {
335
				$address = get_interface_ipv6($idinfo['type']);
336
				$netbits = get_interface_subnetv6($idinfo['type']);
337
				$address = gen_subnetv6($address, $netbits);
338
				return "{$address}/{$netbits}";
339
			} else {
340
				$address = get_interface_ip($idinfo['type']);
341
				$netbits = get_interface_subnet($idinfo['type']);
342
				$address = gen_subnet($address, $netbits);
343
				return "{$address}/{$netbits}";
344
			}
345
			break; /* NOTREACHED */
346
	}
347
}
348

    
349
/*
350
 * Return phase2 idinfo in address/netmask format
351
 */
352
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
353
	global $config;
354

    
355
	switch ($idinfo['type']) {
356
		case "address":
357
			if ($addrbits) {
358
				if ($idinfo['mode'] == "tunnel6") {
359
					return $idinfo['address']."/128";
360
				} else {
361
					return $idinfo['address']."/255.255.255.255";
362
				}
363
			} else {
364
				return $idinfo['address'];
365
			}
366
			break; /* NOTREACHED */
367
		case "none":
368
		case "network":
369
			return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
370
			break; /* NOTREACHED */
371
		case "mobile":
372
			return "0.0.0.0/0";
373
			break; /* NOTREACHED */
374
		default:
375
			if ($idinfo['mode'] == "tunnel6") {
376
				$address = get_interface_ipv6($idinfo['type']);
377
				$netbits = get_interface_subnetv6($idinfo['type']);
378
				$address = gen_subnetv6($address, $netbits);
379
				return $address."/".$netbits;
380
			} else {
381
				$address = get_interface_ip($idinfo['type']);
382
				$netbits = get_interface_subnet($idinfo['type']);
383
				$address = gen_subnet($address, $netbits);
384
				return $address."/".$netbits;
385
			}
386
			break; /* NOTREACHED */
387
	}
388
}
389

    
390
/*
391
 *  Return phase2 idinfo in text format
392
 */
393
function ipsec_idinfo_to_text(& $idinfo) {
394
	global $config;
395

    
396
	switch ($idinfo['type']) {
397
		case "address":
398
			return $idinfo['address'];
399
			break; /* NOTREACHED */
400
		case "network":
401
			return $idinfo['address']."/".$idinfo['netbits'];
402
			break; /* NOTREACHED */
403
		case "mobile":
404
			return gettext("Mobile Client");
405
			break; /* NOTREACHED */
406
		case "none":
407
			return gettext("None");
408
			break; /* NOTREACHED */
409
		default:
410
			if (!empty($config['interfaces'][$idinfo['type']])) {
411
				return convert_friendly_interface_to_friendly_descr($idinfo['type']);
412
			} else {
413
				return strtoupper($idinfo['type']);
414
			}
415
			break; /* NOTREACHED */
416
	}
417
}
418

    
419
/*
420
 * Return phase1 association for phase2
421
 */
422
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
423
	global $config;
424

    
425
	if (!is_array($config['ipsec'])) {
426
		return false;
427
	}
428
	if (!is_array($config['ipsec']['phase1'])) {
429
		return false;
430
	}
431
	if (empty($config['ipsec']['phase1'])) {
432
		return false;
433
	}
434

    
435
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
436
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
437
			$ph1ent = $ph1tmp;
438
			return $ph1ent;
439
		}
440
	}
441

    
442
	return false;
443
}
444

    
445
/*
446
 * Check phase1 communications status
447
 */
448
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
449

    
450
	foreach ($ipsec_status as $ike) {
451
		if ($ike['id'] == $ikeid) {
452
			if ($ike['status'] == 'established') {
453
				return true;
454
			}
455
		}
456
	}
457

    
458
	return false;
459
}
460

    
461
/*
462
 * Check phase2 communications status
463
 */
464
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
465

    
466
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
467
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
468
	}
469

    
470
	return false;
471
}
472

    
473
/*
474
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
475
 */
476
function ipsec_list_sa() {
477

    
478
	if (ipsec_enabled()) {
479
		return pfSense_ipsec_list_sa();
480
	}
481

    
482
	return array();
483
}
484

    
485
/*
486
 * Return dump of SPD table
487
 */
488
function ipsec_dump_spd() {
489
	$fd = @popen("/sbin/setkey -DP", "r");
490
	$spd = array();
491
	if ($fd) {
492
		while (!feof($fd)) {
493
			$line = chop(fgets($fd));
494
			if (!$line) {
495
				continue;
496
			}
497
			if ($line == "No SPD entries.") {
498
				break;
499
			}
500
			if ($line[0] != "\t") {
501
				if (is_array($cursp)) {
502
					$spd[] = $cursp;
503
				}
504
				$cursp = array();
505
				$linea = explode(" ", $line);
506
				$cursp['srcid'] = substr($linea[0], 0, strpos($linea[0], "["));
507
				$cursp['dstid'] = substr($linea[1], 0, strpos($linea[1], "["));
508
				$i = 0;
509
			} else if (is_array($cursp)) {
510
				$line = trim($line, "\t\r\n ");
511
				$linea = explode(" ", $line);
512
				switch ($i) {
513
					case 1:
514
						if ($linea[1] == "none")	/* don't show default anti-lockout rule */ {
515
							unset($cursp);
516
						} else {
517
							$cursp['dir'] = $linea[0];
518
						}
519
						break;
520
					case 2:
521
						$upperspec = explode("/", $linea[0]);
522
						$cursp['proto'] = $upperspec[0];
523
						list($cursp['src'], $cursp['dst']) = explode("-", $upperspec[2]);
524
						$cursp['reqid'] = substr($upperspec[3], strpos($upperspec[3], "#")+1);
525
						break;
526
				}
527
			}
528
			$i++;
529
		}
530
		if (is_array($cursp) && count($cursp)) {
531
			$spd[] = $cursp;
532
		}
533
		pclose($fd);
534
	}
535

    
536
	return $spd;
537
}
538

    
539
/*
540
 * Return dump of SAD table
541
 */
542
function ipsec_dump_sad() {
543
	$fd = @popen("/sbin/setkey -D", "r");
544
	$sad = array();
545
	if ($fd) {
546
		while (!feof($fd)) {
547
			$line = chop(fgets($fd));
548
			if (!$line || $line[0] == " ") {
549
				continue;
550
			}
551
			if ($line == "No SAD entries.") {
552
				break;
553
			}
554
			if ($line[0] != "\t") {
555
				if (is_array($cursa)) {
556
					$sad[] = $cursa;
557
				}
558
				$cursa = array();
559
				list($cursa['src'], $cursa['dst']) = explode(" ", $line);
560
			} else {
561
				$line = trim($line, "\t\n\r ");
562
				$linea = explode(" ", $line);
563
				foreach ($linea as $idx => $linee) {
564
					if ($linee == 'esp' || $linee == 'ah' || $linee[0] == '#') {
565
						$cursa['proto'] = $linee;
566
					} else if (substr($linee, 0, 3) == 'spi') {
567
						$cursa['spi'] = substr($linee, strpos($linee, 'x') + 1, -1);
568
					} else if (substr($linee, 0, 5) == 'reqid') {
569
						$cursa['reqid'] = substr($linee, strpos($linee, 'x') + 1, -1);
570
					} else if (substr($linee, 0, 2) == 'E:') {
571
						$cursa['ealgo'] = $linea[$idx + 1];
572
						break;
573
					} else if (substr($linee, 0, 2) == 'A:') {
574
						$cursa['aalgo'] = $linea[$idx + 1];
575
						break;
576
					} else if (substr($linee, 0, 8) == 'current:') {
577
						$cursa['data'] = substr($linea[$idx + 1], 0, strpos($linea[$idx + 1], 'bytes') - 1) . ' B';
578
						break;
579
					}
580
				}
581
			}
582
		}
583
		if (is_array($cursa) && count($cursa)) {
584
			$sad[] = $cursa;
585
		}
586
		pclose($fd);
587
	}
588

    
589
	return $sad;
590
}
591

    
592
/*
593
 * Return dump of mobile user list
594
 */
595
function ipsec_dump_mobile() {
596
	global $g;
597

    
598
	$_gb = exec("/usr/local/sbin/ipsec leases 2>/dev/null", $output, $rc);
599

    
600
	if ($rc != 0) {
601
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
602
		return array();
603
	}
604

    
605
	$response = array();
606
	$id = -1;
607

    
608
	/* Leases in pool '10.7.200.0/24', usage: 1/254, 1 online */
609
	$lease_regex='/^Leases *in *pool *\'(?P<name>.+)\', *usage: *(?P<usage>\d+)\/(?P<size>\d+), *(?P<online>\d+) *online/';
610
	/* 10.7.200.1   online   'jimp' */
611
	$pool_regex='/\s*(?P<host>[\d\.]+)\s+(?P<status>online|offline)\s+\'(?P<id>.*)\'/';
612
	/* no matching leases found */
613
	$nopool_regex='/no *matching *leases *found/';
614

    
615
	$lease=false;
616
	foreach ($output as $line) {
617
		if (preg_match($lease_regex, $line, $matches)) {
618
			$id++;
619
			$response['pool'][$id] = array(
620
			    'name'   => $matches['name'],
621
			    'usage'  => $matches['usage'],
622
			    'size'   => $matches['size'],
623
			    'online' => $matches['online'],
624
			);
625
			$lease=true;
626
		} else if ($lease) {
627
			if (preg_match($nopool_regex, $line)) {
628
				$response['pool'][$id]['lease'][] = array();
629
				$lease=false;
630
			} else if (preg_match($pool_regex, $line, $matches)) {
631
				$response['pool'][$id]['lease'][] = array(
632
				    'host'   => $matches['host'],
633
				    'status' => $matches['status'],
634
				    'id'     => $matches['id']
635
				);
636
			}
637
		}
638
	}
639

    
640
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
641
	    $nopool_regex);
642

    
643
	return $response;
644
}
645

    
646
function ipsec_mobilekey_sort() {
647
	global $config;
648

    
649
	function mobilekeycmp($a, $b) {
650
		return strcmp($a['ident'][0], $b['ident'][0]);
651
	}
652

    
653
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
654
}
655

    
656
function ipsec_get_number_of_phase2($ikeid) {
657
	global $config;
658
	$a_phase2 = $config['ipsec']['phase2'];
659

    
660
	$nbph2 = 0;
661

    
662
	if (is_array($a_phase2) && count($a_phase2)) {
663
		foreach ($a_phase2 as $ph2tmp) {
664
			if ($ph2tmp['ikeid'] == $ikeid) {
665
				$nbph2++;
666
			}
667
		}
668
	}
669

    
670
	return $nbph2;
671
}
672

    
673
function ipsec_get_descr($ikeid) {
674
	global $config;
675

    
676
	if (!isset($config['ipsec']['phase1']) ||
677
	    !is_array($config['ipsec']['phase1'])) {
678
		return '';
679
	}
680

    
681
	foreach ($config['ipsec']['phase1'] as $p1) {
682
		if ($p1['ikeid'] == $ikeid) {
683
			return $p1['descr'];
684
		}
685
	}
686

    
687
	return '';
688
}
689

    
690
function ipsec_get_phase1($ikeid) {
691
		global $config;
692

    
693
		if (!isset($config['ipsec']['phase1']) ||
694
		    !is_array($config['ipsec']['phase1'])) {
695
			return '';
696
		}
697

    
698
		$a_phase1 = $config['ipsec']['phase1'];
699
		foreach ($a_phase1 as $p1) {
700
			if ($p1['ikeid'] == $ikeid) {
701
				return $p1;
702
			}
703
		}
704
		unset($a_phase1);
705
}
706

    
707
function ipsec_fixup_ip($ipaddr) {
708
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
709
		return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr));
710
	} else {
711
		return $ipaddr;
712
	}
713
}
714

    
715
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
716
	if ($side == "local") {
717
		$id_type = $ph1ent['myid_type'];
718
		$id_data = $ph1ent['myid_data'];
719

    
720
		$addr = ipsec_get_phase1_src($ph1ent);
721
		if (!$addr) {
722
			return array();
723
		}
724
	} elseif ($side == "peer") {
725
		$id_type = $ph1ent['peerid_type'];
726
		$id_data = $ph1ent['peerid_data'];
727

    
728
		if (isset($ph1ent['mobile'])) {
729
			$addr = "%any";
730
		} else {
731
			$addr = $ph1ent['remote-gateway'];
732
		}
733
	} else {
734
		return array();
735
	}
736

    
737

    
738
	$thisid_type = $id_type;
739
	switch ($thisid_type) {
740
		case 'myaddress':
741
			$thisid_type = 'address';
742
			$thisid_data = $addr;
743
			break;
744
		case 'dyn_dns':
745
			$thisid_type = 'dns';
746
			$thisid_data = $id_data;
747
			break;
748
		case 'peeraddress':
749
			$thisid_type = 'address';
750
			$thisid_data = $rgmap[$ph1ent['remote-gateway']];
751
			break;
752
		case 'address':
753
			$thisid_data = $id_data;
754
			break;
755
		case 'fqdn':
756
			$thisid_data = "{$id_data}";
757
			break;
758
		case 'keyid tag':
759
			$thisid_type = 'keyid';
760
			$thisid_data = "{$id_data}";
761
			break;
762
		case 'user_fqdn':
763
			$thisid_type = 'userfqdn';
764
			$thisid_data = "{$id_data}";
765
			break;
766
		case 'asn1dn':
767
			$thisid_data = $id_data;
768
			break;
769
	}
770
	return array($thisid_type, $thisid_data);
771
}
772

    
773
function ipsec_fixup_network($network) {
774
	if (substr($network, -3) == '|/0') {
775
		$result = substr($network, 0, -3);
776
	} else {
777
		$tmp = explode('|', $network);
778
		if (isset($tmp[1])) {
779
			$result = $tmp[1];
780
		} else {
781
			$result = $tmp[0];
782
		}
783
		unset($tmp);
784
	}
785

    
786
	return $result;
787
}
788

    
789
function ipsec_new_reqid() {
790
	global $config;
791

    
792
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
793
		return;
794
	}
795

    
796
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
797
	$keyids = array();
798
	$keyid = 1;
799
	foreach ($config['ipsec']['phase2'] as $ph2) {
800
		$keyids[$ph2['reqid']] = $ph2['reqid'];
801
	}
802

    
803
	for ($i = 1; $i < 16000; $i++) {
804
		if (!isset($keyids[$i])) {
805
			$keyid = $i;
806
			break;
807
		}
808
	}
809
	unlock($ipsecreqid);
810

    
811
	return $keyid;
812
}
813

    
814
?>
(28-28/65)