Project

General

Profile

Download (20.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	ipsec.inc
4

    
5
	part of pfSense (https://www.pfsense.org)
6
	Copyright (c) 2007-2016 Electric Sheep Fencing, LLC.
7
	Copyright (C) 2008 Shrew Soft Inc.
8
	All rights reserved.
9

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

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

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

    
21
	3. All advertising materials mentioning features or use of this software
22
	   must display the following acknowledgment:
23
	   "This product includes software developed by the pfSense Project
24
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
25

    
26
	4. The names "pfSense" and "pfSense Project" must not be used to
27
	   endorse or promote products derived from this software without
28
	   prior written permission. For written permission, please contact
29
	   coreteam@pfsense.org.
30

    
31
	5. Products derived from this software may not be called "pfSense"
32
	   nor may "pfSense" appear in their names without prior written
33
	   permission of the Electric Sheep Fencing, LLC.
34

    
35
	6. Redistributions of any form whatsoever must retain the following
36
	   acknowledgment:
37

    
38
	"This product includes software developed by the pfSense Project
39
	for use in the pfSense software distribution (http://www.pfsense.org/).
40

    
41
	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
42
	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
45
	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52
	OF THE POSSIBILITY OF SUCH DAMAGE.
53
*/
54

    
55
/* IPsec defines */
56
global $ipsec_loglevels;
57
$ipsec_loglevels = array("dmn" => "Daemon", "mgr" => "SA Manager", "ike" => "IKE SA", "chd" => "IKE Child SA",
58
	"job" => "Job Processing", "cfg" => "Configuration backend", "knl" => "Kernel Interface",
59
	"net" => "Networking", "asn" => "ASN encoding", "enc" => "Message encoding",
60
	"imc" => "Integrity checker", "imv" => "Integrity Verifier", "pts" => "Platform Trust Service",
61
	"tls" => "TLS handler", "esp" => "IPsec traffic", "lib" => "StrongSwan Lib");
62

    
63
global $ipsec_log_sevs;
64
$ipsec_log_sevs = array(
65
	'-1' => 'Silent',
66
	'0' => 'Audit',
67
	'1' => 'Control',
68
	'2' => 'Diag',
69
	'3' => 'Raw',
70
	'4' => 'Highest'
71
);
72

    
73
global $ipsec_log_cats;
74
$ipsec_log_cats = array(
75
	"dmn" => "Daemon",
76
	"mgr" => "SA Manager",
77
	"ike" => "IKE SA",
78
	"chd" => "IKE Child SA",
79
	"job" => "Job Processing",
80
	"cfg" => "Configuration backend",
81
	"knl" => "Kernel Interface",
82
	"net" => "Networking",
83
	"asn" => "ASN encoding",
84
	"enc" => "Message encoding",
85
	"imc" => "Integrity checker",
86
	"imv" => "Integrity Verifier",
87
	"pts" => "Platform Trust Service",
88
	"tls" => "TLS handler",
89
	"esp" => "IPsec traffic",
90
	"lib" => "StrongSwan Lib"
91
);
92

    
93
global $my_identifier_list;
94
$my_identifier_list = array(
95
	'myaddress' => array('desc' => gettext('My IP address'), 'mobile' => true),
96
	'address' => array('desc' => gettext('IP address'), 'mobile' => true),
97
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
98
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
99
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
100
	'keyid tag' => array('desc' => gettext('KeyID tag'), 'mobile' => true),
101
	'dyn_dns' => array('desc' => gettext('Dynamic DNS'), 'mobile' => true));
102

    
103
global $peer_identifier_list;
104
$peer_identifier_list = array(
105
	'any' => array('desc' => gettext('Any'), 'mobile' => true),
106
	'peeraddress' => array('desc' => gettext('Peer IP address'), 'mobile' => false),
107
	'address' => array('desc' => gettext('IP address'), 'mobile' => false),
108
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
109
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
110
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
111
	'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true));
112

    
113
global $ipsec_idhandling;
114
$ipsec_idhandling = array(
115
	'yes' => 'YES', 'no' => 'NO', 'never' => 'NEVER', 'keep' => 'KEEP'
116
	);
117

    
118
global $p1_ealgos;
119
$p1_ealgos = array(
120
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
121
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
122
	'3des' => array('name' => '3DES'),
123
	'cast128' => array('name' => 'CAST128'));
124

    
125
global $p2_ealgos;
126
$p2_ealgos = array(
127
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
128
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
129
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
130
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
131
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
132
	'3des' => array('name' => '3DES'),
133
	'cast128' => array('name' => 'CAST128'));
134

    
135
global $p1_halgos;
136
$p1_halgos = array(
137
	'md5' => 'MD5',
138
	'sha1' => 'SHA1',
139
	'sha256' => 'SHA256',
140
	'sha384' => 'SHA384',
141
	'sha512' => 'SHA512',
142
	'aesxcbc' => 'AES-XCBC'
143
);
144

    
145
global $p1_dhgroups;
146
$p1_dhgroups = array(
147
	1  => '1 (768 bit)',
148
	2  => '2 (1024 bit)',
149
	5  => '5 (1536 bit)',
150
	14 => '14 (2048 bit)',
151
	15 => '15 (3072 bit)',
152
	16 => '16 (4096 bit)',
153
	17 => '17 (6144 bit)',
154
	18 => '18 (8192 bit)',
155
	19 => '19 (nist ecp256)',
156
	20 => '20 (nist ecp384)',
157
	21 => '21 (nist ecp521)',
158
	22 => '22 (1024(sub 160) bit)',
159
	23 => '23 (2048(sub 224) bit)',
160
	24 => '24 (2048(sub 256) bit)',
161
	28 => '28 (brainpool ecp256)',
162
	29 => '29 (brainpool ecp384)',
163
	30 => '30 (brainpool ecp512)'
164
);
165

    
166
global $p2_halgos;
167
$p2_halgos = array(
168
	'hmac_md5' => 'MD5',
169
	'hmac_sha1' => 'SHA1',
170
	'hmac_sha256' => 'SHA256',
171
	'hmac_sha384' => 'SHA384',
172
	'hmac_sha512' => 'SHA512',
173
	'aesxcbc' => 'AES-XCBC'
174
);
175

    
176
global $p1_authentication_methods;
177
$p1_authentication_methods = array(
178
	'hybrid_rsa_server' => array('name' => 'Hybrid RSA + Xauth', 'mobile' => true),
179
	'xauth_rsa_server' => array('name' => 'Mutual RSA + Xauth', 'mobile' => true),
180
	'xauth_psk_server' => array('name' => 'Mutual PSK + Xauth', 'mobile' => true),
181
	'eap-tls' => array('name' => 'EAP-TLS', 'mobile' => true),
182
	'eap-radius' => array('name' => 'EAP-RADIUS', 'mobile' => true),
183
	'eap-mschapv2' => array('name' => 'EAP-MSChapv2', 'mobile' => true),
184
	'rsasig' => array('name' => 'Mutual RSA', 'mobile' => false),
185
	'pre_shared_key' => array('name' => 'Mutual PSK', 'mobile' => false));
186

    
187
global $ipsec_preshared_key_type;
188
$ipsec_preshared_key_type = array(
189
	'PSK' => 'PSK',
190
	'EAP' => 'EAP'
191
	);
192

    
193
global $p2_modes;
194
$p2_modes = array(
195
	'tunnel' => 'Tunnel IPv4',
196
	'tunnel6' => 'Tunnel IPv6',
197
	'transport' => 'Transport');
198

    
199
global $p2_protos;
200
$p2_protos = array(
201
	'esp' => 'ESP',
202
	'ah' => 'AH');
203

    
204
global $p2_pfskeygroups;
205
$p2_pfskeygroups = array(
206
	0 => 'off',
207
	1  => '1 (768 bit)',
208
	2  => '2 (1024 bit)',
209
	5  => '5 (1536 bit)',
210
	14 => '14 (2048 bit)',
211
	15 => '15 (3072 bit)',
212
	16 => '16 (4096 bit)',
213
	17 => '17 (6144 bit)',
214
	18 => '18 (8192 bit)',
215
	19 => '19 (nist ecp256)',
216
	20 => '20 (nist ecp384)',
217
	21 => '21 (nist ecp521)',
218
	28 => '28 (brainpool ecp256)',
219
	29 => '29 (brainpool ecp384)',
220
	30 => '30 (brainpool ecp512)'
221
);
222

    
223
function ipsec_enabled() {
224
	global $config;
225

    
226
	if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
227
		return false;
228
	}
229

    
230
	/* Check if we have at least one phase 1 entry. */
231
	if (!isset($config['ipsec']['phase1']) ||
232
	    !is_array($config['ipsec']['phase1']) ||
233
	    empty($config['ipsec']['phase1'])) {
234
		return false;
235
	}
236
	/* Check if at least one phase 1 entry is enabled. */
237
	foreach ($config['ipsec']['phase1'] as $phase1) {
238
		if (!isset($phase1['disabled'])) {
239
			return true;
240
		}
241
	}
242

    
243
	return false;
244
}
245

    
246
/*
247
 * ikeid management functions
248
 */
249

    
250
function ipsec_ikeid_used($ikeid) {
251
	global $config;
252

    
253
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
254
		if ($ikeid == $ph1ent['ikeid']) {
255
			return true;
256
		}
257
	}
258

    
259
	return false;
260
}
261

    
262
function ipsec_ikeid_next() {
263

    
264
	$ikeid = 1;
265
	while (ipsec_ikeid_used($ikeid)) {
266
		$ikeid++;
267
	}
268

    
269
	return $ikeid;
270
}
271

    
272
/*
273
 * Return phase1 local address
274
 */
275
function ipsec_get_phase1_src(& $ph1ent) {
276

    
277
	if ($ph1ent['interface']) {
278
		if (substr($ph1ent['interface'], 0, 4) == "_vip") {
279
			$if = $ph1ent['interface'];
280
		} else {
281
			$if = get_failover_interface($ph1ent['interface']);
282
		}
283
	} else {
284
		$if = "wan";
285
	}
286
	if ($ph1ent['protocol'] == "inet6") {
287
		$interfaceip = get_interface_ipv6($if);
288
	} else {
289
		$interfaceip = get_interface_ip($if);
290
	}
291

    
292
	return $interfaceip;
293
}
294

    
295
/*
296
 * Return phase1 local address
297
 */
298
function ipsec_get_phase1_dst(& $ph1ent) {
299
	global $g;
300

    
301
	if (empty($ph1ent['remote-gateway'])) {
302
		return false;
303
	}
304
	$rg = $ph1ent['remote-gateway'];
305
	if (!is_ipaddr($rg)) {
306
		if (!platform_booting()) {
307
			return resolve_retry($rg);
308
		}
309
	}
310
	if (!is_ipaddr($rg)) {
311
		return false;
312
	}
313

    
314
	return $rg;
315
}
316

    
317
/*
318
 * Return phase2 idinfo in cidr format
319
 */
320
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
321
	global $config;
322

    
323
	switch ($idinfo['type']) {
324
		case "address":
325
			if ($addrbits) {
326
				if ($mode == "tunnel6") {
327
					return $idinfo['address']."/128";
328
				} else {
329
					return $idinfo['address']."/32";
330
				}
331
			} else {
332
				return $idinfo['address'];
333
			}
334
			break; /* NOTREACHED */
335
		case "network":
336
			return "{$idinfo['address']}/{$idinfo['netbits']}";
337
			break; /* NOTREACHED */
338
		case "none":
339
		case "mobile":
340
			return '0.0.0.0/0';
341
			break; /* NOTREACHED */
342
		default:
343
			if (empty($mode) && !empty($idinfo['mode'])) {
344
				$mode = $idinfo['mode'];
345
			}
346

    
347
			if ($mode == "tunnel6") {
348
				$address = get_interface_ipv6($idinfo['type']);
349
				$netbits = get_interface_subnetv6($idinfo['type']);
350
				$address = gen_subnetv6($address, $netbits);
351
				return "{$address}/{$netbits}";
352
			} else {
353
				$address = get_interface_ip($idinfo['type']);
354
				$netbits = get_interface_subnet($idinfo['type']);
355
				$address = gen_subnet($address, $netbits);
356
				return "{$address}/{$netbits}";
357
			}
358
			break; /* NOTREACHED */
359
	}
360
}
361

    
362
/*
363
 * Return phase2 idinfo in address/netmask format
364
 */
365
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
366
	global $config;
367

    
368
	switch ($idinfo['type']) {
369
		case "address":
370
			if ($addrbits) {
371
				if ($idinfo['mode'] == "tunnel6") {
372
					return $idinfo['address']."/128";
373
				} else {
374
					return $idinfo['address']."/255.255.255.255";
375
				}
376
			} else {
377
				return $idinfo['address'];
378
			}
379
			break; /* NOTREACHED */
380
		case "none":
381
		case "network":
382
			return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
383
			break; /* NOTREACHED */
384
		case "mobile":
385
			return "0.0.0.0/0";
386
			break; /* NOTREACHED */
387
		default:
388
			if ($idinfo['mode'] == "tunnel6") {
389
				$address = get_interface_ipv6($idinfo['type']);
390
				$netbits = get_interface_subnetv6($idinfo['type']);
391
				$address = gen_subnetv6($address, $netbits);
392
				return $address."/".$netbits;
393
			} else {
394
				$address = get_interface_ip($idinfo['type']);
395
				$netbits = get_interface_subnet($idinfo['type']);
396
				$address = gen_subnet($address, $netbits);
397
				return $address."/".$netbits;
398
			}
399
			break; /* NOTREACHED */
400
	}
401
}
402

    
403
/*
404
 *  Return phase2 idinfo in text format
405
 */
406
function ipsec_idinfo_to_text(& $idinfo) {
407
	global $config;
408

    
409
	switch ($idinfo['type']) {
410
		case "address":
411
			return $idinfo['address'];
412
			break; /* NOTREACHED */
413
		case "network":
414
			return $idinfo['address']."/".$idinfo['netbits'];
415
			break; /* NOTREACHED */
416
		case "mobile":
417
			return gettext("Mobile Client");
418
			break; /* NOTREACHED */
419
		case "none":
420
			return gettext("None");
421
			break; /* NOTREACHED */
422
		default:
423
			if (!empty($config['interfaces'][$idinfo['type']])) {
424
				return convert_friendly_interface_to_friendly_descr($idinfo['type']);
425
			} else {
426
				return strtoupper($idinfo['type']);
427
			}
428
			break; /* NOTREACHED */
429
	}
430
}
431

    
432
/*
433
 * Return phase1 association for phase2
434
 */
435
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
436
	global $config;
437

    
438
	if (!is_array($config['ipsec'])) {
439
		return false;
440
	}
441
	if (!is_array($config['ipsec']['phase1'])) {
442
		return false;
443
	}
444
	if (empty($config['ipsec']['phase1'])) {
445
		return false;
446
	}
447

    
448
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
449
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
450
			$ph1ent = $ph1tmp;
451
			return $ph1ent;
452
		}
453
	}
454

    
455
	return false;
456
}
457

    
458
/*
459
 * Check phase1 communications status
460
 */
461
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
462

    
463
	foreach ($ipsec_status as $ike) {
464
		if ($ike['id'] == $ikeid) {
465
			if ($ike['status'] == 'established') {
466
				return true;
467
			}
468
		}
469
	}
470

    
471
	return false;
472
}
473

    
474
/*
475
 * Check phase2 communications status
476
 */
477
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
478

    
479
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
480
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
481
	}
482

    
483
	return false;
484
}
485

    
486
/*
487
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
488
 */
489
function ipsec_list_sa() {
490

    
491
	if (ipsec_enabled()) {
492
		return pfSense_ipsec_list_sa();
493
	}
494

    
495
	return array();
496
}
497

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

    
549
	return $spd;
550
}
551

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

    
602
	return $sad;
603
}
604

    
605
/*
606
 * Return dump of mobile user list
607
 */
608
function ipsec_dump_mobile() {
609
	global $g;
610

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

    
613
	if ($rc != 0) {
614
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
615
		return array();
616
	}
617

    
618
	$response = array();
619
	$id = -1;
620

    
621
	/* Leases in pool '10.7.200.0/24', usage: 1/254, 1 online */
622
	$lease_regex='/^Leases *in *pool *\'(?P<name>.+)\', *usage: *(?P<usage>\d+)\/(?P<size>\d+), *(?P<online>\d+) *online/';
623
	/* 10.7.200.1   online   'jimp' */
624
	$pool_regex='/\s*(?P<host>[\d\.]+)\s+(?P<status>online|offline)\s+\'(?P<id>.*)\'/';
625
	/* no matching leases found */
626
	$nopool_regex='/no *matching *leases *found/';
627

    
628
	$lease=false;
629
	foreach ($output as $line) {
630
		if (preg_match($lease_regex, $line, $matches)) {
631
			$id++;
632
			$response['pool'][$id] = array(
633
			    'name'   => $matches['name'],
634
			    'usage'  => $matches['usage'],
635
			    'size'   => $matches['size'],
636
			    'online' => $matches['online'],
637
			);
638
			$lease=true;
639
		} else if ($lease) {
640
			if (preg_match($nopool_regex, $line)) {
641
				$response['pool'][$id]['lease'][] = array();
642
				$lease=false;
643
			} else if (preg_match($pool_regex, $line, $matches)) {
644
				$response['pool'][$id]['lease'][] = array(
645
				    'host'   => $matches['host'],
646
				    'status' => $matches['status'],
647
				    'id'     => $matches['id']
648
				);
649
			}
650
		}
651
	}
652

    
653
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
654
	    $nopool_regex);
655

    
656
	return $response;
657
}
658

    
659
function ipsec_mobilekey_sort() {
660
	global $config;
661

    
662
	function mobilekeycmp($a, $b) {
663
		return strcmp($a['ident'][0], $b['ident'][0]);
664
	}
665

    
666
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
667
}
668

    
669
function ipsec_get_number_of_phase2($ikeid) {
670
	global $config;
671
	$a_phase2 = $config['ipsec']['phase2'];
672

    
673
	$nbph2 = 0;
674

    
675
	if (is_array($a_phase2) && count($a_phase2)) {
676
		foreach ($a_phase2 as $ph2tmp) {
677
			if ($ph2tmp['ikeid'] == $ikeid) {
678
				$nbph2++;
679
			}
680
		}
681
	}
682

    
683
	return $nbph2;
684
}
685

    
686
function ipsec_get_descr($ikeid) {
687
	global $config;
688

    
689
	if (!isset($config['ipsec']['phase1']) ||
690
	    !is_array($config['ipsec']['phase1'])) {
691
		return '';
692
	}
693

    
694
	foreach ($config['ipsec']['phase1'] as $p1) {
695
		if ($p1['ikeid'] == $ikeid) {
696
			return $p1['descr'];
697
		}
698
	}
699

    
700
	return '';
701
}
702

    
703
function ipsec_get_phase1($ikeid) {
704
		global $config;
705

    
706
		if (!isset($config['ipsec']['phase1']) ||
707
		    !is_array($config['ipsec']['phase1'])) {
708
			return '';
709
		}
710

    
711
		$a_phase1 = $config['ipsec']['phase1'];
712
		foreach ($a_phase1 as $p1) {
713
			if ($p1['ikeid'] == $ikeid) {
714
				return $p1;
715
			}
716
		}
717
		unset($a_phase1);
718
}
719

    
720
function ipsec_fixup_ip($ipaddr) {
721
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
722
		return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr));
723
	} else {
724
		return $ipaddr;
725
	}
726
}
727

    
728
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
729
	if ($side == "local") {
730
		$id_type = $ph1ent['myid_type'];
731
		$id_data = $ph1ent['myid_data'];
732

    
733
		$addr = ipsec_get_phase1_src($ph1ent);
734
		if (!$addr) {
735
			return array();
736
		}
737
	} elseif ($side == "peer") {
738
		$id_type = $ph1ent['peerid_type'];
739
		$id_data = $ph1ent['peerid_data'];
740

    
741
		if (isset($ph1ent['mobile'])) {
742
			$addr = "%any";
743
		} else {
744
			$addr = $ph1ent['remote-gateway'];
745
		}
746
	} else {
747
		return array();
748
	}
749

    
750

    
751
	$thisid_type = $id_type;
752
	switch ($thisid_type) {
753
		case 'myaddress':
754
			$thisid_type = 'address';
755
			$thisid_data = $addr;
756
			break;
757
		case 'dyn_dns':
758
			$thisid_type = 'dns';
759
			$thisid_data = $id_data;
760
			break;
761
		case 'peeraddress':
762
			$thisid_type = 'address';
763
			$thisid_data = $rgmap[$ph1ent['remote-gateway']];
764
			break;
765
		case 'address':
766
			$thisid_data = $id_data;
767
			break;
768
		case 'fqdn':
769
			$thisid_data = "{$id_data}";
770
			break;
771
		case 'keyid tag':
772
			$thisid_type = 'keyid';
773
			$thisid_data = "{$id_data}";
774
			break;
775
		case 'user_fqdn':
776
			$thisid_type = 'userfqdn';
777
			$thisid_data = "{$id_data}";
778
			break;
779
		case 'asn1dn':
780
			$thisid_data = $id_data;
781
			break;
782
	}
783
	return array($thisid_type, $thisid_data);
784
}
785

    
786
function ipsec_fixup_network($network) {
787
	if (substr($network, -3) == '|/0') {
788
		$result = substr($network, 0, -3);
789
	} else {
790
		$tmp = explode('|', $network);
791
		if (isset($tmp[1])) {
792
			$result = $tmp[1];
793
		} else {
794
			$result = $tmp[0];
795
		}
796
		unset($tmp);
797
	}
798

    
799
	return $result;
800
}
801

    
802
function ipsec_new_reqid() {
803
	global $config;
804

    
805
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
806
		return;
807
	}
808

    
809
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
810
	$keyids = array();
811
	$keyid = 1;
812
	foreach ($config['ipsec']['phase2'] as $ph2) {
813
		$keyids[$ph2['reqid']] = $ph2['reqid'];
814
	}
815

    
816
	for ($i = 1; $i < 16000; $i++) {
817
		if (!isset($keyids[$i])) {
818
			$keyid = $i;
819
			break;
820
		}
821
	}
822
	unlock($ipsecreqid);
823

    
824
	return $keyid;
825
}
826

    
827
?>
(28-28/65)