Project

General

Profile

Download (20.2 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
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
104
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
105
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
106
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
107
	'3des' => array('name' => '3DES'),
108
	'cast128' => array('name' => 'CAST128'),
109
	'des' => array('name' => 'DES'));
110

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

    
122
global $p1_halgos;
123
$p1_halgos = array(
124
	'md5' => 'MD5',
125
	'sha1' => 'SHA1',
126
	'sha256' => 'SHA256',
127
	'sha384' => 'SHA384',
128
	'sha512' => 'SHA512',
129
	'aesxcbc' => 'AES-XCBC'
130
);
131

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

    
153
global $p2_halgos;
154
$p2_halgos = array(
155
	'hmac_md5' => 'MD5',
156
	'hmac_sha1' => 'SHA1',
157
	'hmac_sha256' => 'SHA256',
158
	'hmac_sha384' => 'SHA384',
159
	'hmac_sha512' => 'SHA512',
160
	'aesxcbc' => 'AES-XCBC'
161
);
162

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

    
174
global $ipsec_preshared_key_type;
175
$ipsec_preshared_key_type = array(
176
	'PSK' => 'PSK',
177
	'EAP' => 'EAP'
178
	);
179

    
180
global $p2_modes;
181
$p2_modes = array(
182
	'tunnel' => 'Tunnel IPv4',
183
	'tunnel6' => 'Tunnel IPv6',
184
	'transport' => 'Transport');
185

    
186
global $p2_protos;
187
$p2_protos = array(
188
	'esp' => 'ESP',
189
	'ah' => 'AH');
190

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

    
210
function ipsec_enabled() {
211
	global $config;
212

    
213
	if (!isset($config['ipsec']) || !is_array($config['ipsec']))
214
		return false;
215

    
216
	if (!isset($config['ipsec']['phase1']) ||
217
	    !is_array($config['ipsec']['phase1']) ||
218
	    empty($config['ipsec']['phase1'])) {
219
		return false;
220
	}
221

    
222
	return true;
223
}
224

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

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

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

    
238
	return false;
239
}
240

    
241
function ipsec_ikeid_next() {
242

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

    
248
	return $ikeid;
249
}
250

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

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

    
280
	return $interfaceip;
281
}
282

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

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

    
302
	return $rg;
303
}
304

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

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

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

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

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

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

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

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

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

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

    
443
	return false;
444
}
445

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

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

    
459
	return false;
460
}
461

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

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

    
471
	return false;
472
}
473

    
474
/*
475
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
476
 */
477
function ipsec_list_sa() {
478
	global $config;
479

    
480
	if (isset($config['ipsec']['enable'])) {
481
		return pfSense_ipsec_list_sa();
482
	}
483

    
484
	return array();
485
}
486

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

    
538
	return $spd;
539
}
540

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

    
591
	return $sad;
592
}
593

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

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

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

    
607
	$response = array();
608
	$id = -1;
609

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

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

    
642
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
643
	    $nopool_regex);
644

    
645
	return $response;
646
}
647

    
648
function ipsec_mobilekey_sort() {
649
	global $config;
650

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

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

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

    
662
	$nbph2 = 0;
663

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

    
672
	return $nbph2;
673
}
674

    
675
function ipsec_get_descr($ikeid) {
676
	global $config;
677

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

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

    
689
	return '';
690
}
691

    
692
function ipsec_get_phase1($ikeid) {
693
		global $config;
694

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

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

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

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

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

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

    
739

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

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

    
788
	return $result;
789
}
790

    
791
function ipsec_new_reqid() {
792
	global $config;
793

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

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

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

    
813
	return $keyid;
814
}
815

    
816
?>
(29-29/67)