Project

General

Profile

Download (21.2 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(
58
	"dmn" => gettext("Daemon"),
59
	"mgr" => gettext("SA Manager"),
60
	"ike" => gettext("IKE SA"),
61
	"chd" => gettext("IKE Child SA"),
62
	"job" => gettext("Job Processing"),
63
	"cfg" => gettext("Configuration backend"),
64
	"knl" => gettext("Kernel Interface"),
65
	"net" => gettext("Networking"),
66
	"asn" => gettext("ASN encoding"),
67
	"enc" => gettext("Message encoding"),
68
	"imc" => gettext("Integrity checker"),
69
	"imv" => gettext("Integrity Verifier"),
70
	"pts" => gettext("Platform Trust Service"),
71
	"tls" => gettext("TLS handler"),
72
	"esp" => gettext("IPsec traffic"),
73
	"lib" => gettext("StrongSwan Lib")
74
);
75

    
76
global $ipsec_log_sevs;
77
$ipsec_log_sevs = array(
78
	'-1' => gettext('Silent'),
79
	'0' => gettext('Audit'),
80
	'1' => gettext('Control'),
81
	'2' => gettext('Diag'),
82
	'3' => gettext('Raw'),
83
	'4' => gettext('Highest')
84
);
85

    
86
global $ipsec_log_cats;
87
$ipsec_log_cats = array(
88
	"dmn" => gettext("Daemon"),
89
	"mgr" => gettext("SA Manager"),
90
	"ike" => gettext("IKE SA"),
91
	"chd" => gettext("IKE Child SA"),
92
	"job" => gettext("Job Processing"),
93
	"cfg" => gettext("Configuration backend"),
94
	"knl" => gettext("Kernel Interface"),
95
	"net" => gettext("Networking"),
96
	"asn" => gettext("ASN encoding"),
97
	"enc" => gettext("Message encoding"),
98
	"imc" => gettext("Integrity checker"),
99
	"imv" => gettext("Integrity Verifier"),
100
	"pts" => gettext("Platform Trust Service"),
101
	"tls" => gettext("TLS handler"),
102
	"esp" => gettext("IPsec traffic"),
103
	"lib" => gettext("StrongSwan Lib")
104
);
105

    
106
global $my_identifier_list;
107
$my_identifier_list = array(
108
	'myaddress' => array('desc' => gettext('My IP address'), 'mobile' => true),
109
	'address' => array('desc' => gettext('IP address'), 'mobile' => true),
110
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
111
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
112
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
113
	'keyid tag' => array('desc' => gettext('KeyID tag'), 'mobile' => true),
114
	'dyn_dns' => array('desc' => gettext('Dynamic DNS'), 'mobile' => true)
115
);
116

    
117
global $peer_identifier_list;
118
$peer_identifier_list = array(
119
	'any' => array('desc' => gettext('Any'), 'mobile' => true),
120
	'peeraddress' => array('desc' => gettext('Peer IP address'), 'mobile' => false),
121
	'address' => array('desc' => gettext('IP address'), 'mobile' => false),
122
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
123
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
124
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
125
	'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true)
126
);
127

    
128
global $ipsec_idhandling;
129
$ipsec_idhandling = array(
130
	'yes' => 'YES', 'no' => 'NO', 'never' => 'NEVER', 'keep' => 'KEEP'
131
);
132

    
133
global $p1_ealgos;
134
$p1_ealgos = array(
135
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
136
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
137
	'3des' => array('name' => '3DES'),
138
	'cast128' => array('name' => 'CAST128')
139
);
140

    
141
global $p2_ealgos;
142
$p2_ealgos = array(
143
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
144
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
145
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
146
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
147
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
148
	'3des' => array('name' => '3DES'),
149
	'cast128' => array('name' => 'CAST128')
150
);
151

    
152
global $p1_halgos;
153
$p1_halgos = array(
154
	'md5' => 'MD5',
155
	'sha1' => 'SHA1',
156
	'sha256' => 'SHA256',
157
	'sha384' => 'SHA384',
158
	'sha512' => 'SHA512',
159
	'aesxcbc' => 'AES-XCBC'
160
);
161

    
162
global $p1_dhgroups;
163
$p1_dhgroups = array(
164
	1  => '1 (768 bit)',
165
	2  => '2 (1024 bit)',
166
	5  => '5 (1536 bit)',
167
	14 => '14 (2048 bit)',
168
	15 => '15 (3072 bit)',
169
	16 => '16 (4096 bit)',
170
	17 => '17 (6144 bit)',
171
	18 => '18 (8192 bit)',
172
	19 => '19 (nist ecp256)',
173
	20 => '20 (nist ecp384)',
174
	21 => '21 (nist ecp521)',
175
	22 => '22 (1024(sub 160) bit)',
176
	23 => '23 (2048(sub 224) bit)',
177
	24 => '24 (2048(sub 256) bit)',
178
	28 => '28 (brainpool ecp256)',
179
	29 => '29 (brainpool ecp384)',
180
	30 => '30 (brainpool ecp512)'
181
);
182

    
183
global $p2_halgos;
184
$p2_halgos = array(
185
	'hmac_md5' => 'MD5',
186
	'hmac_sha1' => 'SHA1',
187
	'hmac_sha256' => 'SHA256',
188
	'hmac_sha384' => 'SHA384',
189
	'hmac_sha512' => 'SHA512',
190
	'aesxcbc' => 'AES-XCBC'
191
);
192

    
193
global $p1_authentication_methods;
194
$p1_authentication_methods = array(
195
	'hybrid_rsa_server' => array('name' => gettext('Hybrid RSA + Xauth'), 'mobile' => true),
196
	'xauth_rsa_server' => array('name' => gettext('Mutual RSA + Xauth'), 'mobile' => true),
197
	'xauth_psk_server' => array('name' => gettext('Mutual PSK + Xauth'), 'mobile' => true),
198
	'eap-tls' => array('name' => gettext('EAP-TLS'), 'mobile' => true),
199
	'eap-radius' => array('name' => gettext('EAP-RADIUS'), 'mobile' => true),
200
	'eap-mschapv2' => array('name' => gettext('EAP-MSChapv2'), 'mobile' => true),
201
	'rsasig' => array('name' => gettext('Mutual RSA'), 'mobile' => false),
202
	'pre_shared_key' => array('name' => gettext('Mutual PSK'), 'mobile' => false)
203
);
204

    
205
global $ipsec_preshared_key_type;
206
$ipsec_preshared_key_type = array(
207
	'PSK' => 'PSK',
208
	'EAP' => 'EAP'
209
);
210

    
211
global $p2_modes;
212
$p2_modes = array(
213
	'tunnel' => gettext('Tunnel IPv4'),
214
	'tunnel6' => gettext('Tunnel IPv6'),
215
	'transport' => gettext('Transport')
216
);
217

    
218
global $p2_protos;
219
$p2_protos = array(
220
	'esp' => 'ESP',
221
	'ah' => 'AH'
222
);
223

    
224
global $p2_pfskeygroups;
225
$p2_pfskeygroups = array(
226
	0 => gettext('off'),
227
	1  => gettext('1 (768 bit)'),
228
	2  => gettext('2 (1024 bit)'),
229
	5  => gettext('5 (1536 bit)'),
230
	14 => gettext('14 (2048 bit)'),
231
	15 => gettext('15 (3072 bit)'),
232
	16 => gettext('16 (4096 bit)'),
233
	17 => gettext('17 (6144 bit)'),
234
	18 => gettext('18 (8192 bit)'),
235
	19 => gettext('19 (nist ecp256)'),
236
	20 => gettext('20 (nist ecp384)'),
237
	21 => gettext('21 (nist ecp521)'),
238
	28 => gettext('28 (brainpool ecp256)'),
239
	29 => gettext('29 (brainpool ecp384)'),
240
	30 => gettext('30 (brainpool ecp512)')
241
);
242

    
243
function ipsec_enabled() {
244
	global $config;
245

    
246
	if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
247
		return false;
248
	}
249

    
250
	/* Check if we have at least one phase 1 entry. */
251
	if (!isset($config['ipsec']['phase1']) ||
252
	    !is_array($config['ipsec']['phase1']) ||
253
	    empty($config['ipsec']['phase1'])) {
254
		return false;
255
	}
256
	/* Check if at least one phase 1 entry is enabled. */
257
	foreach ($config['ipsec']['phase1'] as $phase1) {
258
		if (!isset($phase1['disabled'])) {
259
			return true;
260
		}
261
	}
262

    
263
	return false;
264
}
265

    
266
/*
267
 * ikeid management functions
268
 */
269

    
270
function ipsec_ikeid_used($ikeid) {
271
	global $config;
272

    
273
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
274
		if ($ikeid == $ph1ent['ikeid']) {
275
			return true;
276
		}
277
	}
278

    
279
	return false;
280
}
281

    
282
function ipsec_ikeid_next() {
283

    
284
	$ikeid = 1;
285
	while (ipsec_ikeid_used($ikeid)) {
286
		$ikeid++;
287
	}
288

    
289
	return $ikeid;
290
}
291

    
292
/*
293
 * Return phase1 local address
294
 */
295
function ipsec_get_phase1_src(& $ph1ent) {
296

    
297
	if ($ph1ent['interface']) {
298
		if (substr($ph1ent['interface'], 0, 4) == "_vip") {
299
			$if = $ph1ent['interface'];
300
		} else {
301
			$if = get_failover_interface($ph1ent['interface']);
302
		}
303
	} else {
304
		$if = "wan";
305
	}
306
	if ($ph1ent['protocol'] == "inet6") {
307
		$interfaceip = get_interface_ipv6($if);
308
	} else {
309
		$interfaceip = get_interface_ip($if);
310
	}
311

    
312
	return $interfaceip;
313
}
314

    
315
/*
316
 * Return phase1 local address
317
 */
318
function ipsec_get_phase1_dst(& $ph1ent) {
319
	global $g;
320

    
321
	if (empty($ph1ent['remote-gateway'])) {
322
		return false;
323
	}
324
	$rg = $ph1ent['remote-gateway'];
325
	if (!is_ipaddr($rg)) {
326
		if (!platform_booting()) {
327
			return resolve_retry($rg);
328
		}
329
	}
330
	if (!is_ipaddr($rg)) {
331
		return false;
332
	}
333

    
334
	return $rg;
335
}
336

    
337
/*
338
 * Return phase2 idinfo in cidr format
339
 */
340
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
341
	global $config;
342

    
343
	switch ($idinfo['type']) {
344
		case "address":
345
			if ($addrbits) {
346
				if ($mode == "tunnel6") {
347
					return $idinfo['address']."/128";
348
				} else {
349
					return $idinfo['address']."/32";
350
				}
351
			} else {
352
				return $idinfo['address'];
353
			}
354
			break; /* NOTREACHED */
355
		case "network":
356
			return "{$idinfo['address']}/{$idinfo['netbits']}";
357
			break; /* NOTREACHED */
358
		case "none":
359
		case "mobile":
360
			return '0.0.0.0/0';
361
			break; /* NOTREACHED */
362
		default:
363
			if (empty($mode) && !empty($idinfo['mode'])) {
364
				$mode = $idinfo['mode'];
365
			}
366

    
367
			if ($mode == "tunnel6") {
368
				$address = get_interface_ipv6($idinfo['type']);
369
				$netbits = get_interface_subnetv6($idinfo['type']);
370
				$address = gen_subnetv6($address, $netbits);
371
				return "{$address}/{$netbits}";
372
			} else {
373
				$address = get_interface_ip($idinfo['type']);
374
				$netbits = get_interface_subnet($idinfo['type']);
375
				$address = gen_subnet($address, $netbits);
376
				return "{$address}/{$netbits}";
377
			}
378
			break; /* NOTREACHED */
379
	}
380
}
381

    
382
/*
383
 * Return phase2 idinfo in address/netmask format
384
 */
385
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
386
	global $config;
387

    
388
	switch ($idinfo['type']) {
389
		case "address":
390
			if ($addrbits) {
391
				if ($idinfo['mode'] == "tunnel6") {
392
					return $idinfo['address']."/128";
393
				} else {
394
					return $idinfo['address']."/255.255.255.255";
395
				}
396
			} else {
397
				return $idinfo['address'];
398
			}
399
			break; /* NOTREACHED */
400
		case "none":
401
		case "network":
402
			return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
403
			break; /* NOTREACHED */
404
		case "mobile":
405
			return "0.0.0.0/0";
406
			break; /* NOTREACHED */
407
		default:
408
			if ($idinfo['mode'] == "tunnel6") {
409
				$address = get_interface_ipv6($idinfo['type']);
410
				$netbits = get_interface_subnetv6($idinfo['type']);
411
				$address = gen_subnetv6($address, $netbits);
412
				return $address."/".$netbits;
413
			} else {
414
				$address = get_interface_ip($idinfo['type']);
415
				$netbits = get_interface_subnet($idinfo['type']);
416
				$address = gen_subnet($address, $netbits);
417
				return $address."/".$netbits;
418
			}
419
			break; /* NOTREACHED */
420
	}
421
}
422

    
423
/*
424
 *  Return phase2 idinfo in text format
425
 */
426
function ipsec_idinfo_to_text(& $idinfo) {
427
	global $config;
428

    
429
	switch ($idinfo['type']) {
430
		case "address":
431
			return $idinfo['address'];
432
			break; /* NOTREACHED */
433
		case "network":
434
			return $idinfo['address']."/".$idinfo['netbits'];
435
			break; /* NOTREACHED */
436
		case "mobile":
437
			return gettext("Mobile Client");
438
			break; /* NOTREACHED */
439
		case "none":
440
			return gettext("None");
441
			break; /* NOTREACHED */
442
		default:
443
			if (!empty($config['interfaces'][$idinfo['type']])) {
444
				return convert_friendly_interface_to_friendly_descr($idinfo['type']);
445
			} else {
446
				return strtoupper($idinfo['type']);
447
			}
448
			break; /* NOTREACHED */
449
	}
450
}
451

    
452
/*
453
 * Return phase1 association for phase2
454
 */
455
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
456
	global $config;
457

    
458
	if (!is_array($config['ipsec'])) {
459
		return false;
460
	}
461
	if (!is_array($config['ipsec']['phase1'])) {
462
		return false;
463
	}
464
	if (empty($config['ipsec']['phase1'])) {
465
		return false;
466
	}
467

    
468
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
469
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
470
			$ph1ent = $ph1tmp;
471
			return $ph1ent;
472
		}
473
	}
474

    
475
	return false;
476
}
477

    
478
/*
479
 * Check phase1 communications status
480
 */
481
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
482

    
483
	foreach ($ipsec_status as $ike) {
484
		if ($ike['id'] == $ikeid) {
485
			if ($ike['status'] == 'established') {
486
				return true;
487
			}
488
		}
489
	}
490

    
491
	return false;
492
}
493

    
494
/*
495
 * Check phase2 communications status
496
 */
497
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
498

    
499
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
500
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
501
	}
502

    
503
	return false;
504
}
505

    
506
/*
507
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
508
 */
509
function ipsec_list_sa() {
510

    
511
	if (ipsec_enabled()) {
512
		return pfSense_ipsec_list_sa();
513
	}
514

    
515
	return array();
516
}
517

    
518
/*
519
 * Return dump of SPD table
520
 */
521
function ipsec_dump_spd() {
522
	$fd = @popen("/sbin/setkey -DP", "r");
523
	$spd = array();
524
	if ($fd) {
525
		while (!feof($fd)) {
526
			$line = chop(fgets($fd));
527
			if (!$line) {
528
				continue;
529
			}
530
			if ($line == "No SPD entries.") {
531
				break;
532
			}
533
			if ($line[0] != "\t") {
534
				if (is_array($cursp)) {
535
					$spd[] = $cursp;
536
				}
537
				$cursp = array();
538
				$linea = explode(" ", $line);
539
				$cursp['srcid'] = substr($linea[0], 0, strpos($linea[0], "["));
540
				$cursp['dstid'] = substr($linea[1], 0, strpos($linea[1], "["));
541
				$i = 0;
542
			} else if (is_array($cursp)) {
543
				$line = trim($line, "\t\r\n ");
544
				$linea = explode(" ", $line);
545
				switch ($i) {
546
					case 1:
547
						if ($linea[1] == "none")	/* don't show default anti-lockout rule */ {
548
							unset($cursp);
549
						} else {
550
							$cursp['dir'] = $linea[0];
551
						}
552
						break;
553
					case 2:
554
						$upperspec = explode("/", $linea[0]);
555
						$cursp['proto'] = $upperspec[0];
556
						list($cursp['src'], $cursp['dst']) = explode("-", $upperspec[2]);
557
						$cursp['reqid'] = substr($upperspec[3], strpos($upperspec[3], "#")+1);
558
						break;
559
				}
560
			}
561
			$i++;
562
		}
563
		if (is_array($cursp) && count($cursp)) {
564
			$spd[] = $cursp;
565
		}
566
		pclose($fd);
567
	}
568

    
569
	return $spd;
570
}
571

    
572
/*
573
 * Return dump of SAD table
574
 */
575
function ipsec_dump_sad() {
576
	$fd = @popen("/sbin/setkey -D", "r");
577
	$sad = array();
578
	if ($fd) {
579
		while (!feof($fd)) {
580
			$line = chop(fgets($fd));
581
			if (!$line || $line[0] == " ") {
582
				continue;
583
			}
584
			if ($line == "No SAD entries.") {
585
				break;
586
			}
587
			if ($line[0] != "\t") {
588
				if (is_array($cursa)) {
589
					$sad[] = $cursa;
590
				}
591
				$cursa = array();
592
				list($cursa['src'], $cursa['dst']) = explode(" ", $line);
593
			} else {
594
				$line = trim($line, "\t\n\r ");
595
				$linea = explode(" ", $line);
596
				foreach ($linea as $idx => $linee) {
597
					if ($linee == 'esp' || $linee == 'ah' || $linee[0] == '#') {
598
						$cursa['proto'] = $linee;
599
					} else if (substr($linee, 0, 3) == 'spi') {
600
						$cursa['spi'] = substr($linee, strpos($linee, 'x') + 1, -1);
601
					} else if (substr($linee, 0, 5) == 'reqid') {
602
						$cursa['reqid'] = substr($linee, strpos($linee, 'x') + 1, -1);
603
					} else if (substr($linee, 0, 2) == 'E:') {
604
						$cursa['ealgo'] = $linea[$idx + 1];
605
						break;
606
					} else if (substr($linee, 0, 2) == 'A:') {
607
						$cursa['aalgo'] = $linea[$idx + 1];
608
						break;
609
					} else if (substr($linee, 0, 8) == 'current:') {
610
						$cursa['data'] = substr($linea[$idx + 1], 0, strpos($linea[$idx + 1], 'bytes') - 1) . ' B';
611
						break;
612
					}
613
				}
614
			}
615
		}
616
		if (is_array($cursa) && count($cursa)) {
617
			$sad[] = $cursa;
618
		}
619
		pclose($fd);
620
	}
621

    
622
	return $sad;
623
}
624

    
625
/*
626
 * Return dump of mobile user list
627
 */
628
function ipsec_dump_mobile() {
629
	global $g;
630

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

    
633
	if ($rc != 0) {
634
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
635
		return array();
636
	}
637

    
638
	$response = array();
639
	$id = -1;
640

    
641
	/* Leases in pool '10.7.200.0/24', usage: 1/254, 1 online */
642
	$lease_regex='/^Leases *in *pool *\'(?P<name>.+)\', *usage: *(?P<usage>\d+)\/(?P<size>\d+), *(?P<online>\d+) *online/';
643
	/* 10.7.200.1   online   'jimp' */
644
	$pool_regex='/\s*(?P<host>[\d\.]+)\s+(?P<status>online|offline)\s+\'(?P<id>.*)\'/';
645
	/* no matching leases found */
646
	$nopool_regex='/no *matching *leases *found/';
647

    
648
	$lease=false;
649
	foreach ($output as $line) {
650
		if (preg_match($lease_regex, $line, $matches)) {
651
			$id++;
652
			$response['pool'][$id] = array(
653
			    'name'   => $matches['name'],
654
			    'usage'  => $matches['usage'],
655
			    'size'   => $matches['size'],
656
			    'online' => $matches['online'],
657
			);
658
			$lease=true;
659
		} else if ($lease) {
660
			if (preg_match($nopool_regex, $line)) {
661
				$response['pool'][$id]['lease'][] = array();
662
				$lease=false;
663
			} else if (preg_match($pool_regex, $line, $matches)) {
664
				$response['pool'][$id]['lease'][] = array(
665
				    'host'   => $matches['host'],
666
				    'status' => $matches['status'],
667
				    'id'     => $matches['id']
668
				);
669
			}
670
		}
671
	}
672

    
673
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
674
	    $nopool_regex);
675

    
676
	return $response;
677
}
678

    
679
function ipsec_mobilekey_sort() {
680
	global $config;
681

    
682
	function mobilekeycmp($a, $b) {
683
		return strcmp($a['ident'][0], $b['ident'][0]);
684
	}
685

    
686
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
687
}
688

    
689
function ipsec_get_number_of_phase2($ikeid) {
690
	global $config;
691
	$a_phase2 = $config['ipsec']['phase2'];
692

    
693
	$nbph2 = 0;
694

    
695
	if (is_array($a_phase2) && count($a_phase2)) {
696
		foreach ($a_phase2 as $ph2tmp) {
697
			if ($ph2tmp['ikeid'] == $ikeid) {
698
				$nbph2++;
699
			}
700
		}
701
	}
702

    
703
	return $nbph2;
704
}
705

    
706
function ipsec_get_descr($ikeid) {
707
	global $config;
708

    
709
	if (!isset($config['ipsec']['phase1']) ||
710
	    !is_array($config['ipsec']['phase1'])) {
711
		return '';
712
	}
713

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

    
720
	return '';
721
}
722

    
723
function ipsec_get_phase1($ikeid) {
724
		global $config;
725

    
726
		if (!isset($config['ipsec']['phase1']) ||
727
		    !is_array($config['ipsec']['phase1'])) {
728
			return '';
729
		}
730

    
731
		$a_phase1 = $config['ipsec']['phase1'];
732
		foreach ($a_phase1 as $p1) {
733
			if ($p1['ikeid'] == $ikeid) {
734
				return $p1;
735
			}
736
		}
737
		unset($a_phase1);
738
}
739

    
740
function ipsec_fixup_ip($ipaddr) {
741
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
742
		return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr));
743
	} else {
744
		return $ipaddr;
745
	}
746
}
747

    
748
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
749
	if ($side == "local") {
750
		$id_type = $ph1ent['myid_type'];
751
		$id_data = $ph1ent['myid_data'];
752

    
753
		$addr = ipsec_get_phase1_src($ph1ent);
754
		if (!$addr) {
755
			return array();
756
		}
757
	} elseif ($side == "peer") {
758
		$id_type = $ph1ent['peerid_type'];
759
		$id_data = $ph1ent['peerid_data'];
760

    
761
		if (isset($ph1ent['mobile'])) {
762
			$addr = "%any";
763
		} else {
764
			$addr = $ph1ent['remote-gateway'];
765
		}
766
	} else {
767
		return array();
768
	}
769

    
770

    
771
	$thisid_type = $id_type;
772
	switch ($thisid_type) {
773
		case 'myaddress':
774
			$thisid_type = 'address';
775
			$thisid_data = $addr;
776
			break;
777
		case 'dyn_dns':
778
			$thisid_type = 'dns';
779
			$thisid_data = $id_data;
780
			break;
781
		case 'peeraddress':
782
			$thisid_type = 'address';
783
			$thisid_data = $rgmap[$ph1ent['remote-gateway']];
784
			break;
785
		case 'address':
786
			$thisid_data = $id_data;
787
			break;
788
		case 'fqdn':
789
			$thisid_data = "{$id_data}";
790
			break;
791
		case 'keyid tag':
792
			$thisid_type = 'keyid';
793
			$thisid_data = "{$id_data}";
794
			break;
795
		case 'user_fqdn':
796
			$thisid_type = 'userfqdn';
797
			$thisid_data = "{$id_data}";
798
			break;
799
		case 'asn1dn':
800
			$thisid_data = $id_data;
801
			break;
802
	}
803
	return array($thisid_type, $thisid_data);
804
}
805

    
806
function ipsec_fixup_network($network) {
807
	if (substr($network, -3) == '|/0') {
808
		$result = substr($network, 0, -3);
809
	} else {
810
		$tmp = explode('|', $network);
811
		if (isset($tmp[1])) {
812
			$result = $tmp[1];
813
		} else {
814
			$result = $tmp[0];
815
		}
816
		unset($tmp);
817
	}
818

    
819
	return $result;
820
}
821

    
822
function ipsec_new_reqid() {
823
	global $config;
824

    
825
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
826
		return;
827
	}
828

    
829
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
830
	$keyids = array();
831
	$keyid = 1;
832
	foreach ($config['ipsec']['phase2'] as $ph2) {
833
		$keyids[$ph2['reqid']] = $ph2['reqid'];
834
	}
835

    
836
	for ($i = 1; $i < 16000; $i++) {
837
		if (!isset($keyids[$i])) {
838
			$keyid = $i;
839
			break;
840
		}
841
	}
842
	unlock($ipsecreqid);
843

    
844
	return $keyid;
845
}
846

    
847
?>
(28-28/65)