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
	pfSense_BUILDER_BINARIES:	/sbin/setkey	/sbin/route
33
	pfSense_MODULE:	ipsec
34

    
35
*/
36

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

    
45
global $ipsec_log_sevs;
46
$ipsec_log_sevs = array(
47
	'-1' => 'Silent',
48
	'0' => 'Audit',
49
	'1' => 'Control',
50
	'2' => 'Diag',
51
	'3' => 'Raw',
52
	'4' => 'Highest'
53
);
54

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

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

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

    
95
global $ipsec_idhandling;
96
$ipsec_idhandling = array(
97
	'yes' => 'YES', 'no' => 'NO', 'never' => 'NEVER', 'keep' => 'KEEP'
98
	);
99

    
100
global $p1_ealgos;
101
$p1_ealgos = array(
102
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
103
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
104
	'3des' => array('name' => '3DES'),
105
	'cast128' => array('name' => 'CAST128'));
106

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

    
117
global $p1_halgos;
118
$p1_halgos = array(
119
	'md5' => 'MD5',
120
	'sha1' => 'SHA1',
121
	'sha256' => 'SHA256',
122
	'sha384' => 'SHA384',
123
	'sha512' => 'SHA512',
124
	'aesxcbc' => 'AES-XCBC'
125
);
126

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

    
148
global $p2_halgos;
149
$p2_halgos = array(
150
	'hmac_md5' => 'MD5',
151
	'hmac_sha1' => 'SHA1',
152
	'hmac_sha256' => 'SHA256',
153
	'hmac_sha384' => 'SHA384',
154
	'hmac_sha512' => 'SHA512',
155
	'aesxcbc' => 'AES-XCBC'
156
);
157

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

    
169
global $ipsec_preshared_key_type;
170
$ipsec_preshared_key_type = array(
171
	'PSK' => 'PSK',
172
	'EAP' => 'EAP'
173
	);
174

    
175
global $p2_modes;
176
$p2_modes = array(
177
	'tunnel' => 'Tunnel IPv4',
178
	'tunnel6' => 'Tunnel IPv6',
179
	'transport' => 'Transport');
180

    
181
global $p2_protos;
182
$p2_protos = array(
183
	'esp' => 'ESP',
184
	'ah' => 'AH');
185

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

    
205
function ipsec_enabled() {
206
	global $config;
207

    
208
	if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
209
		return false;
210
	}
211

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

    
225
	return false;
226
}
227

    
228
/*
229
 * ikeid management functions
230
 */
231

    
232
function ipsec_ikeid_used($ikeid) {
233
	global $config;
234

    
235
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
236
		if ($ikeid == $ph1ent['ikeid']) {
237
			return true;
238
		}
239
	}
240

    
241
	return false;
242
}
243

    
244
function ipsec_ikeid_next() {
245

    
246
	$ikeid = 1;
247
	while (ipsec_ikeid_used($ikeid)) {
248
		$ikeid++;
249
	}
250

    
251
	return $ikeid;
252
}
253

    
254
/*
255
 * Return phase1 local address
256
 */
257
function ipsec_get_phase1_src(& $ph1ent) {
258

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

    
283
	return $interfaceip;
284
}
285

    
286
/*
287
 * Return phase1 local address
288
 */
289
function ipsec_get_phase1_dst(& $ph1ent) {
290
	global $g;
291

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

    
305
	return $rg;
306
}
307

    
308
/*
309
 * Return phase2 idinfo in cidr format
310
 */
311
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
312
	global $config;
313

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

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

    
353
/*
354
 * Return phase2 idinfo in address/netmask format
355
 */
356
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
357
	global $config;
358

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

    
394
/*
395
 *  Return phase2 idinfo in text format
396
 */
397
function ipsec_idinfo_to_text(& $idinfo) {
398
	global $config;
399

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

    
423
/*
424
 * Return phase1 association for phase2
425
 */
426
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
427
	global $config;
428

    
429
	if (!is_array($config['ipsec'])) {
430
		return false;
431
	}
432
	if (!is_array($config['ipsec']['phase1'])) {
433
		return false;
434
	}
435
	if (empty($config['ipsec']['phase1'])) {
436
		return false;
437
	}
438

    
439
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
440
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
441
			$ph1ent = $ph1tmp;
442
			return $ph1ent;
443
		}
444
	}
445

    
446
	return false;
447
}
448

    
449
/*
450
 * Check phase1 communications status
451
 */
452
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
453

    
454
	foreach ($ipsec_status as $ike) {
455
		if ($ike['id'] == $ikeid) {
456
			if ($ike['status'] == 'established') {
457
				return true;
458
			}
459
		}
460
	}
461

    
462
	return false;
463
}
464

    
465
/*
466
 * Check phase2 communications status
467
 */
468
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
469

    
470
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
471
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
472
	}
473

    
474
	return false;
475
}
476

    
477
/*
478
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
479
 */
480
function ipsec_list_sa() {
481

    
482
	if (ipsec_enabled()) {
483
		return pfSense_ipsec_list_sa();
484
	}
485

    
486
	return array();
487
}
488

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

    
540
	return $spd;
541
}
542

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

    
593
	return $sad;
594
}
595

    
596
/*
597
 * Return dump of mobile user list
598
 */
599
function ipsec_dump_mobile() {
600
	global $g;
601

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

    
604
	if ($rc != 0) {
605
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
606
		return array();
607
	}
608

    
609
	$response = array();
610
	$id = -1;
611

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

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

    
644
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
645
	    $nopool_regex);
646

    
647
	return $response;
648
}
649

    
650
function ipsec_mobilekey_sort() {
651
	global $config;
652

    
653
	function mobilekeycmp($a, $b) {
654
		return strcmp($a['ident'][0], $b['ident'][0]);
655
	}
656

    
657
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
658
}
659

    
660
function ipsec_get_number_of_phase2($ikeid) {
661
	global $config;
662
	$a_phase2 = $config['ipsec']['phase2'];
663

    
664
	$nbph2 = 0;
665

    
666
	if (is_array($a_phase2) && count($a_phase2)) {
667
		foreach ($a_phase2 as $ph2tmp) {
668
			if ($ph2tmp['ikeid'] == $ikeid) {
669
				$nbph2++;
670
			}
671
		}
672
	}
673

    
674
	return $nbph2;
675
}
676

    
677
function ipsec_get_descr($ikeid) {
678
	global $config;
679

    
680
	if (!isset($config['ipsec']['phase1']) ||
681
	    !is_array($config['ipsec']['phase1'])) {
682
		return '';
683
	}
684

    
685
	foreach ($config['ipsec']['phase1'] as $p1) {
686
		if ($p1['ikeid'] == $ikeid) {
687
			return $p1['descr'];
688
		}
689
	}
690

    
691
	return '';
692
}
693

    
694
function ipsec_get_phase1($ikeid) {
695
		global $config;
696

    
697
		if (!isset($config['ipsec']['phase1']) ||
698
		    !is_array($config['ipsec']['phase1'])) {
699
			return '';
700
		}
701

    
702
		$a_phase1 = $config['ipsec']['phase1'];
703
		foreach ($a_phase1 as $p1) {
704
			if ($p1['ikeid'] == $ikeid) {
705
				return $p1;
706
			}
707
		}
708
		unset($a_phase1);
709
}
710

    
711
function ipsec_fixup_ip($ipaddr) {
712
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
713
		return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr));
714
	} else {
715
		return $ipaddr;
716
	}
717
}
718

    
719
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
720
	if ($side == "local") {
721
		$id_type = $ph1ent['myid_type'];
722
		$id_data = $ph1ent['myid_data'];
723

    
724
		$addr = ipsec_get_phase1_src($ph1ent);
725
		if (!$addr) {
726
			return array();
727
		}
728
	} elseif ($side == "peer") {
729
		$id_type = $ph1ent['peerid_type'];
730
		$id_data = $ph1ent['peerid_data'];
731

    
732
		if (isset($ph1ent['mobile'])) {
733
			$addr = "%any";
734
		} else {
735
			$addr = $ph1ent['remote-gateway'];
736
		}
737
	} else {
738
		return array();
739
	}
740

    
741

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

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

    
790
	return $result;
791
}
792

    
793
function ipsec_new_reqid() {
794
	global $config;
795

    
796
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
797
		return;
798
	}
799

    
800
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
801
	$keyids = array();
802
	$keyid = 1;
803
	foreach ($config['ipsec']['phase2'] as $ph2) {
804
		$keyids[$ph2['reqid']] = $ph2['reqid'];
805
	}
806

    
807
	for ($i = 1; $i < 16000; $i++) {
808
		if (!isset($keyids[$i])) {
809
			$keyid = $i;
810
			break;
811
		}
812
	}
813
	unlock($ipsecreqid);
814

    
815
	return $keyid;
816
}
817

    
818
?>
(28-28/65)