Project

General

Profile

Download (21.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * ipsec.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2008 Shrew Soft Inc.
7
 * Copyright (c) 2007-2016 Rubicon Communications, LLC (Netgate)
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
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
137
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
138
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
139
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
140
	'3des' => array('name' => '3DES'),
141
	'cast128' => array('name' => 'CAST128')
142
);
143

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

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

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

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

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

    
208
global $ipsec_preshared_key_type;
209
$ipsec_preshared_key_type = array(
210
	'PSK' => 'PSK',
211
	'EAP' => 'EAP'
212
);
213

    
214
global $p2_modes;
215
$p2_modes = array(
216
	'tunnel' => gettext('Tunnel IPv4'),
217
	'tunnel6' => gettext('Tunnel IPv6'),
218
	'transport' => gettext('Transport')
219
);
220

    
221
global $p2_protos;
222
$p2_protos = array(
223
	'esp' => 'ESP',
224
	'ah' => 'AH'
225
);
226

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

    
246
function ipsec_enabled() {
247
	global $config;
248

    
249
	if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
250
		return false;
251
	}
252

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

    
266
	return false;
267
}
268

    
269
/*
270
 * ikeid management functions
271
 */
272

    
273
function ipsec_ikeid_used($ikeid) {
274
	global $config;
275

    
276
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
277
		if ($ikeid == $ph1ent['ikeid']) {
278
			return true;
279
		}
280
	}
281

    
282
	return false;
283
}
284

    
285
function ipsec_ikeid_next() {
286

    
287
	$ikeid = 1;
288
	while (ipsec_ikeid_used($ikeid)) {
289
		$ikeid++;
290
	}
291

    
292
	return $ikeid;
293
}
294

    
295
/*
296
 * Return phase1 local address
297
 */
298
function ipsec_get_phase1_src(& $ph1ent) {
299

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

    
315
	return $interfaceip;
316
}
317

    
318
/*
319
 * Return phase1 local address
320
 */
321
function ipsec_get_phase1_dst(& $ph1ent) {
322
	global $g;
323

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

    
337
	return $rg;
338
}
339

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

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

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

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

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

    
426
/*
427
 *  Return phase2 idinfo in text format
428
 */
429
function ipsec_idinfo_to_text(& $idinfo) {
430
	global $config;
431

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

    
455
/*
456
 * Return phase1 association for phase2
457
 */
458
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
459
	global $config;
460

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

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

    
478
	return false;
479
}
480

    
481
/*
482
 * Check phase1 communications status
483
 */
484
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
485

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

    
494
	return false;
495
}
496

    
497
/*
498
 * Check phase2 communications status
499
 */
500
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
501

    
502
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
503
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
504
	}
505

    
506
	return false;
507
}
508

    
509
/*
510
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
511
 */
512
function ipsec_list_sa() {
513

    
514
	if (ipsec_enabled()) {
515
		return pfSense_ipsec_list_sa();
516
	}
517

    
518
	return array();
519
}
520

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

    
572
	return $spd;
573
}
574

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

    
625
	return $sad;
626
}
627

    
628
/*
629
 * Return dump of mobile user list
630
 */
631
function ipsec_dump_mobile() {
632
	global $g, $config;
633

    
634
	if(!isset($config['ipsec']['client']['enable'])) {
635
		return array();
636
	}
637
	
638
	$_gb = exec("/usr/local/sbin/ipsec leases 2>/dev/null", $output, $rc);
639

    
640
	if ($rc != 0) {
641
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
642
		return array();
643
	}
644

    
645
	$response = array();
646
	$id = -1;
647

    
648
	/* Leases in pool '10.7.200.0/24', usage: 1/254, 1 online */
649
	$lease_regex='/^Leases *in *pool *\'(?P<name>.+)\', *usage: *(?P<usage>\d+)\/(?P<size>\d+), *(?P<online>\d+) *online/';
650
	/* 10.7.200.1   online   'jimp' */
651
	$pool_regex='/\s*(?P<host>[\d\.]+)\s+(?P<status>online|offline)\s+\'(?P<id>.*)\'/';
652
	/* no matching leases found */
653
	$nopool_regex='/no *matching *leases *found/';
654

    
655
	$lease=false;
656
	foreach ($output as $line) {
657
		if (preg_match($lease_regex, $line, $matches)) {
658
			$id++;
659
			$response['pool'][$id] = array(
660
			    'name'   => $matches['name'],
661
			    'usage'  => $matches['usage'],
662
			    'size'   => $matches['size'],
663
			    'online' => $matches['online'],
664
			);
665
			$lease=true;
666
		} else if ($lease) {
667
			if (preg_match($nopool_regex, $line)) {
668
				$response['pool'][$id]['lease'][] = array();
669
				$lease=false;
670
			} else if (preg_match($pool_regex, $line, $matches)) {
671
				$response['pool'][$id]['lease'][] = array(
672
				    'host'   => $matches['host'],
673
				    'status' => $matches['status'],
674
				    'id'     => $matches['id']
675
				);
676
			}
677
		}
678
	}
679

    
680
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
681
	    $nopool_regex);
682

    
683
	return $response;
684
}
685

    
686
function ipsec_mobilekey_sort() {
687
	global $config;
688

    
689
	function mobilekeycmp($a, $b) {
690
		return strcmp($a['ident'][0], $b['ident'][0]);
691
	}
692

    
693
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
694
}
695

    
696
function ipsec_get_number_of_phase2($ikeid) {
697
	global $config;
698
	$a_phase2 = $config['ipsec']['phase2'];
699

    
700
	$nbph2 = 0;
701

    
702
	if (is_array($a_phase2) && count($a_phase2)) {
703
		foreach ($a_phase2 as $ph2tmp) {
704
			if ($ph2tmp['ikeid'] == $ikeid) {
705
				$nbph2++;
706
			}
707
		}
708
	}
709

    
710
	return $nbph2;
711
}
712

    
713
function ipsec_get_descr($ikeid) {
714
	global $config;
715

    
716
	if (!isset($config['ipsec']['phase1']) ||
717
	    !is_array($config['ipsec']['phase1'])) {
718
		return '';
719
	}
720

    
721
	foreach ($config['ipsec']['phase1'] as $p1) {
722
		if ($p1['ikeid'] == $ikeid) {
723
			return $p1['descr'];
724
		}
725
	}
726

    
727
	return '';
728
}
729

    
730
function ipsec_get_phase1($ikeid) {
731
		global $config;
732

    
733
		if (!isset($config['ipsec']['phase1']) ||
734
		    !is_array($config['ipsec']['phase1'])) {
735
			return '';
736
		}
737

    
738
		$a_phase1 = $config['ipsec']['phase1'];
739
		foreach ($a_phase1 as $p1) {
740
			if ($p1['ikeid'] == $ikeid) {
741
				return $p1;
742
			}
743
		}
744
		unset($a_phase1);
745
}
746

    
747
function ipsec_fixup_ip($ipaddr) {
748
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
749
		return text_to_compressed_ip6($ipaddr);
750
	} else {
751
		return $ipaddr;
752
	}
753
}
754

    
755
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
756
	if ($side == "local") {
757
		$id_type = $ph1ent['myid_type'];
758
		$id_data = $ph1ent['myid_data'];
759

    
760
		$addr = ipsec_get_phase1_src($ph1ent);
761
		if (!$addr) {
762
			return array();
763
		}
764
	} elseif ($side == "peer") {
765
		$id_type = $ph1ent['peerid_type'];
766
		$id_data = $ph1ent['peerid_data'];
767

    
768
		if (isset($ph1ent['mobile'])) {
769
			$addr = "%any";
770
		} else {
771
			$addr = $ph1ent['remote-gateway'];
772
		}
773
	} else {
774
		return array();
775
	}
776

    
777

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

    
813
function ipsec_fixup_network($network) {
814
	if (substr($network, -3) == '|/0') {
815
		$result = substr($network, 0, -3);
816
	} else {
817
		$tmp = explode('|', $network);
818
		if (isset($tmp[1])) {
819
			$result = $tmp[1];
820
		} else {
821
			$result = $tmp[0];
822
		}
823
		unset($tmp);
824
	}
825

    
826
	return $result;
827
}
828

    
829
function ipsec_new_reqid() {
830
	global $config;
831

    
832
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
833
		return;
834
	}
835

    
836
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
837
	$keyids = array();
838
	$keyid = 1;
839
	foreach ($config['ipsec']['phase2'] as $ph2) {
840
		$keyids[$ph2['reqid']] = $ph2['reqid'];
841
	}
842

    
843
	for ($i = 1; $i < 16000; $i++) {
844
		if (!isset($keyids[$i])) {
845
			$keyid = $i;
846
			break;
847
		}
848
	}
849
	unlock($ipsecreqid);
850

    
851
	return $keyid;
852
}
853

    
854
?>
(30-30/67)