Project

General

Profile

Download (19.6 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 $my_identifier_list;
46
$my_identifier_list = array(
47
	'myaddress' => array('desc' => gettext('My IP address'), 'mobile' => true),
48
	'address' => array('desc' => gettext('IP address'), 'mobile' => true),
49
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
50
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
51
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
52
	'keyid tag' => array('desc' => gettext('KeyID tag'), 'mobile' => true),
53
	'dyn_dns' => array('desc' => gettext('Dynamic DNS'), 'mobile' => true));
54

    
55
global $peer_identifier_list;
56
$peer_identifier_list = array(
57
	'any' => array('desc' => gettext('Any'), 'mobile' => true),
58
	'peeraddress' => array('desc' => gettext('Peer IP address'), 'mobile' => false),
59
	'address' => array('desc' => gettext('IP address'), 'mobile' => false),
60
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
61
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
62
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
63
	'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true));
64

    
65
global $ipsec_idhandling;
66
$ipsec_idhandling = array(
67
	'yes' => 'YES', 'no' => 'NO', 'never' => 'NEVER', 'keep' => 'KEEP'
68
	);
69

    
70
global $p1_ealgos;
71
$p1_ealgos = array(
72
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
73
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
74
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
75
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
76
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
77
	'3des' => array('name' => '3DES'),
78
	'cast128' => array('name' => 'CAST128'),
79
	'des' => array('name' => 'DES'));
80

    
81
global $p2_ealgos;
82
$p2_ealgos = array(
83
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
84
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
85
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
86
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
87
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
88
	'3des' => array('name' => '3DES'),
89
	'cast128' => array('name' => 'CAST128'),
90
	'des' => array('name' => 'DES'));
91

    
92
global $p1_halgos;
93
$p1_halgos = array(
94
	'md5' => 'MD5',
95
	'sha1' => 'SHA1',
96
	'sha256' => 'SHA256',
97
	'sha384' => 'SHA384',
98
	'sha512' => 'SHA512',
99
	'aesxcbc' => 'AES-XCBC'
100
);
101

    
102
global $p1_dhgroups;
103
$p1_dhgroups = array(
104
	1  => '1 (768 bit)',
105
	2  => '2 (1024 bit)',
106
	5  => '5 (1536 bit)',
107
	14 => '14 (2048 bit)',
108
	15 => '15 (3072 bit)',
109
	16 => '16 (4096 bit)',
110
	17 => '17 (6144 bit)',
111
	18 => '18 (8192 bit)',
112
	19 => '19 (nist ecp256)',
113
	20 => '20 (nist ecp384)',
114
	21 => '21 (nist ecp521)',
115
	22 => '22 (1024(sub 160) bit)',
116
	23 => '23 (2048(sub 224) bit)',
117
	24 => '24 (2048(sub 256) bit)',
118
	28 => '28 (brainpool ecp256)',
119
	29 => '29 (brainpool ecp384)',
120
	30 => '30 (brainpool ecp512)'
121
);
122

    
123
global $p2_halgos;
124
$p2_halgos = array(
125
	'hmac_md5' => 'MD5',
126
	'hmac_sha1' => 'SHA1',
127
	'hmac_sha256' => 'SHA256',
128
	'hmac_sha384' => 'SHA384',
129
	'hmac_sha512' => 'SHA512',
130
	'aesxcbc' => 'AES-XCBC'
131
);
132

    
133
global $p1_authentication_methods;
134
$p1_authentication_methods = array(
135
	'hybrid_rsa_server' => array('name' => 'Hybrid RSA + Xauth', 'mobile' => true),
136
	'xauth_rsa_server' => array('name' => 'Mutual RSA + Xauth', 'mobile' => true),
137
	'xauth_psk_server' => array('name' => 'Mutual PSK + Xauth', 'mobile' => true),
138
	'eap-tls' => array('name' => 'EAP-TLS', 'mobile' => true),
139
	'eap-radius' => array('name' => 'EAP-RADIUS', 'mobile' => true),
140
	'eap-mschapv2' => array('name' => 'EAP-MSChapv2', 'mobile' => true),
141
	'rsasig' => array('name' => 'Mutual RSA', 'mobile' => false),
142
	'pre_shared_key' => array('name' => 'Mutual PSK', 'mobile' => false));
143

    
144
global $ipsec_preshared_key_type;
145
$ipsec_preshared_key_type = array(
146
	'PSK' => 'PSK',
147
	'EAP' => 'EAP'
148
	);
149

    
150
global $p2_modes;
151
$p2_modes = array(
152
	'tunnel' => 'Tunnel IPv4',
153
	'tunnel6' => 'Tunnel IPv6',
154
	'transport' => 'Transport');
155

    
156
global $p2_protos;
157
$p2_protos = array(
158
	'esp' => 'ESP',
159
	'ah' => 'AH');
160

    
161
global $p2_pfskeygroups;
162
$p2_pfskeygroups = array(
163
	0 => 'off',
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
	28 => '28 (brainpool ecp256)',
176
	29 => '29 (brainpool ecp384)',
177
	30 => '30 (brainpool ecp512)'
178
);
179

    
180
/*
181
 * ikeid management functions
182
 */
183

    
184
function ipsec_ikeid_used($ikeid) {
185
	global $config;
186

    
187
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
188
		if ($ikeid == $ph1ent['ikeid']) {
189
			return true;
190
		}
191
	}
192

    
193
	return false;
194
}
195

    
196
function ipsec_ikeid_next() {
197

    
198
	$ikeid = 1;
199
	while (ipsec_ikeid_used($ikeid)) {
200
		$ikeid++;
201
	}
202

    
203
	return $ikeid;
204
}
205

    
206
/*
207
 * Return phase1 local address
208
 */
209
function ipsec_get_phase1_src(& $ph1ent) {
210

    
211
	if ($ph1ent['interface']) {
212
		if (!is_ipaddr($ph1ent['interface'])) {
213
			if (strpos($ph1ent['interface'], '_vip')) {
214
				$if = $ph1ent['interface'];
215
			} else {
216
				$if = get_failover_interface($ph1ent['interface']);
217
			}
218
			if ($ph1ent['protocol'] == "inet6") {
219
				$interfaceip = get_interface_ipv6($if);
220
			} else {
221
				$interfaceip = get_interface_ip($if);
222
			}
223
		} else {
224
			$interfaceip = $ph1ent['interface'];
225
		}
226
	} else {
227
		$if = "wan";
228
		if ($ph1ent['protocol'] == "inet6") {
229
			$interfaceip = get_interface_ipv6($if);
230
		} else {
231
			$interfaceip = get_interface_ip($if);
232
		}
233
	}
234

    
235
	return $interfaceip;
236
}
237

    
238
/*
239
 * Return phase1 local address
240
 */
241
function ipsec_get_phase1_dst(& $ph1ent) {
242
	global $g;
243

    
244
	if (empty($ph1ent['remote-gateway'])) {
245
		return false;
246
	}
247
	$rg = $ph1ent['remote-gateway'];
248
	if (!is_ipaddr($rg)) {
249
		if (!platform_booting()) {
250
			return resolve_retry($rg);
251
		}
252
	}
253
	if (!is_ipaddr($rg)) {
254
		return false;
255
	}
256

    
257
	return $rg;
258
}
259

    
260
/*
261
 * Return phase2 idinfo in cidr format
262
 */
263
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
264
	global $config;
265

    
266
	switch ($idinfo['type']) {
267
		case "address":
268
			if ($addrbits) {
269
				if ($mode == "tunnel6") {
270
					return $idinfo['address']."/128";
271
				} else {
272
					return $idinfo['address']."/32";
273
				}
274
			} else {
275
				return $idinfo['address'];
276
			}
277
			break; /* NOTREACHED */
278
		case "network":
279
			return "{$idinfo['address']}/{$idinfo['netbits']}";
280
			break; /* NOTREACHED */
281
		case "none":
282
		case "mobile":
283
			return '0.0.0.0/0';
284
			break; /* NOTREACHED */
285
		default:
286
			if (empty($mode) && !empty($idinfo['mode'])) {
287
				$mode = $idinfo['mode'];
288
			}
289

    
290
			if ($mode == "tunnel6") {
291
				$address = get_interface_ipv6($idinfo['type']);
292
				$netbits = get_interface_subnetv6($idinfo['type']);
293
				$address = gen_subnetv6($address, $netbits);
294
				return "{$address}/{$netbits}";
295
			} else {
296
				$address = get_interface_ip($idinfo['type']);
297
				$netbits = get_interface_subnet($idinfo['type']);
298
				$address = gen_subnet($address, $netbits);
299
				return "{$address}/{$netbits}";
300
			}
301
			break; /* NOTREACHED */
302
	}
303
}
304

    
305
/*
306
 * Return phase2 idinfo in address/netmask format
307
 */
308
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
309
	global $config;
310

    
311
	switch ($idinfo['type']) {
312
		case "address":
313
			if ($addrbits) {
314
				if ($idinfo['mode'] == "tunnel6") {
315
					return $idinfo['address']."/128";
316
				} else {
317
					return $idinfo['address']."/255.255.255.255";
318
				}
319
			} else {
320
				return $idinfo['address'];
321
			}
322
			break; /* NOTREACHED */
323
		case "none":
324
		case "network":
325
			return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
326
			break; /* NOTREACHED */
327
		case "mobile":
328
			return "0.0.0.0/0";
329
			break; /* NOTREACHED */
330
		default:
331
			if ($idinfo['mode'] == "tunnel6") {
332
				$address = get_interface_ipv6($idinfo['type']);
333
				$netbits = get_interface_subnetv6($idinfo['type']);
334
				$address = gen_subnetv6($address, $netbits);
335
				return $address."/".$netbits;
336
			} else {
337
				$address = get_interface_ip($idinfo['type']);
338
				$netbits = get_interface_subnet($idinfo['type']);
339
				$address = gen_subnet($address, $netbits);
340
				return $address."/".$netbits;
341
			}
342
			break; /* NOTREACHED */
343
	}
344
}
345

    
346
/*
347
 *  Return phase2 idinfo in text format
348
 */
349
function ipsec_idinfo_to_text(& $idinfo) {
350
	global $config;
351

    
352
	switch ($idinfo['type']) {
353
		case "address":
354
			return $idinfo['address'];
355
			break; /* NOTREACHED */
356
		case "network":
357
			return $idinfo['address']."/".$idinfo['netbits'];
358
			break; /* NOTREACHED */
359
		case "mobile":
360
			return gettext("Mobile Client");
361
			break; /* NOTREACHED */
362
		case "none":
363
			return gettext("None");
364
			break; /* NOTREACHED */
365
		default:
366
			if (!empty($config['interfaces'][$idinfo['type']])) {
367
				return convert_friendly_interface_to_friendly_descr($idinfo['type']);
368
			} else {
369
				return strtoupper($idinfo['type']);
370
			}
371
			break; /* NOTREACHED */
372
	}
373
}
374

    
375
/*
376
 * Return phase1 association for phase2
377
 */
378
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
379
	global $config;
380

    
381
	if (!is_array($config['ipsec'])) {
382
		return false;
383
	}
384
	if (!is_array($config['ipsec']['phase1'])) {
385
		return false;
386
	}
387
	if (empty($config['ipsec']['phase1'])) {
388
		return false;
389
	}
390

    
391
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
392
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
393
			$ph1ent = $ph1tmp;
394
			return $ph1ent;
395
		}
396
	}
397

    
398
	return false;
399
}
400

    
401
/*
402
 * Check phase1 communications status
403
 */
404
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
405

    
406
	foreach ($ipsec_status as $ike) {
407
		if ($ike['id'] == $ikeid) {
408
			if ($ike['status'] == 'established') {
409
				return true;
410
			}
411
		}
412
	}
413

    
414
	return false;
415
}
416

    
417
/*
418
 * Check phase2 communications status
419
 */
420
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
421

    
422
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
423
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
424
	}
425

    
426
	return false;
427
}
428

    
429
function ipsec_smp_dump_status() {
430
	global $config, $g, $custom_listtags;
431

    
432
        if (isset($config['ipsec']['enable'])) {
433
            if (!file_exists("{$g['varrun_path']}/charon.xml")) {
434
                log_error("IPsec daemon not running or has a problem!");
435
                return;
436
            }
437
        } else {
438
            return;
439
        }
440

    
441
	$fd = @fsockopen("unix://{$g['varrun_path']}/charon.xml");
442
	if (!$fd) {
443
		log_error("Could not read status from IPsec");
444
		return;
445
	}
446
	$query = '<?xml version="1.0"?><message xmlns="http://www.strongswan.org/smp/1.0" type="request" id="1">';
447
	$query .= '<query><ikesalist/></query></message>';
448

    
449
	@fwrite($fd, $query);
450
	$response = "";
451
	while (!strstr($sread, "</message>")) {
452
		$sread = fgets($fd);
453
		if ($sread === false) {
454
			break;
455
		}
456
		$response .= $sread;
457
	}
458
	fclose($fd);
459

    
460
	if ($sread === false) {
461
		log_error("Error during reading of status from IPsec");
462
		return;
463
	}
464

    
465
	@file_put_contents("{$g['tmp_path']}/smp_status.xml", $response);
466
	unset($response, $sread);
467

    
468
	$custom_listtags = array('ikesa', 'childsa', 'network', 'auth');
469
	$response = parse_xml_config("{$g['tmp_path']}/smp_status.xml", "message");
470
	@unlink("{$g['tmp_path']}/smp_status.xml");
471
	unset($custom_listtags);
472

    
473
	return $response;
474
}
475

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

    
527
	return $spd;
528
}
529

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

    
580
	return $sad;
581
}
582

    
583
/*
584
 * Return dump of mobile user list
585
 */
586
function ipsec_dump_mobile() {
587
	global $g, $custom_listtags;
588

    
589
	$_gb = exec("/usr/local/sbin/ipsec stroke leases > {$g['tmp_path']}/strongswan_leases.xml");
590

    
591
	if (!file_exists("{$g['tmp_path']}/strongswan_leases.xml")) {
592
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
593
		return array();
594
	}
595

    
596
	/* This is needed for fixing #4130 */
597
	if (filesize("{$g['tmp_path']}/strongswan_leases.xml") < 200) {
598
		return array();
599
	}
600

    
601
	$custom_listtags = array('lease', 'pool');
602
	$response = parse_xml_config("{$g['tmp_path']}/strongswan_leases.xml", "leases");
603
	@unlink("{$g['tmp_path']}/strongswan_leases.xml");
604
	unset($custom_listtags, $_gb);
605

    
606
	return $response;
607
}
608

    
609
function ipsec_mobilekey_sort() {
610
	global $config;
611

    
612
	function mobilekeycmp($a, $b) {
613
		return strcmp($a['ident'][0], $b['ident'][0]);
614
	}
615

    
616
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
617
}
618

    
619
function ipsec_get_number_of_phase2($ikeid) {
620
	global $config;
621
	$a_phase2 = $config['ipsec']['phase2'];
622

    
623
	$nbph2 = 0;
624

    
625
	if (is_array($a_phase2) && count($a_phase2)) {
626
		foreach ($a_phase2 as $ph2tmp) {
627
			if ($ph2tmp['ikeid'] == $ikeid) {
628
				$nbph2++;
629
			}
630
		}
631
	}
632

    
633
	return $nbph2;
634
}
635

    
636
function ipsec_get_descr($ikeid) {
637
	global $config;
638

    
639
	if (!isset($config['ipsec']['phase1']) ||
640
	    !is_array($config['ipsec']['phase1'])) {
641
		return '';
642
	}
643

    
644
	foreach ($config['ipsec']['phase1'] as $p1) {
645
		if ($p1['ikeid'] == $ikeid) {
646
			return $p1['descr'];
647
		}
648
	}
649

    
650
	return '';
651
}
652

    
653
function ipsec_get_phase1($ikeid) {
654
		global $config;
655

    
656
		if (!isset($config['ipsec']['phase1']) ||
657
		    !is_array($config['ipsec']['phase1'])) {
658
			return '';
659
		}
660

    
661
		$a_phase1 = $config['ipsec']['phase1'];
662
		foreach ($a_phase1 as $p1) {
663
			if ($p1['ikeid'] == $ikeid) {
664
				return $p1;
665
			}
666
		}
667
		unset($a_phase1);
668
}
669

    
670
function ipsec_fixup_ip($ipaddr) {
671
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
672
		return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr));
673
	} else {
674
		return $ipaddr;
675
	}
676
}
677

    
678
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
679
	if ($side == "local") {
680
		$id_type = $ph1ent['myid_type'];
681
		$id_data = $ph1ent['myid_data'];
682

    
683
		$addr = ipsec_get_phase1_src($ph1ent);
684
		if (!$addr) {
685
			return array();
686
		}
687
	} elseif ($side == "peer") {
688
		$id_type = $ph1ent['peerid_type'];
689
		$id_data = $ph1ent['peerid_data'];
690

    
691
		if (isset($ph1ent['mobile'])) {
692
			$addr = "%any";
693
		} else {
694
			$addr = $ph1ent['remote-gateway'];
695
		}
696
	} else {
697
		return array();
698
	}
699

    
700

    
701
	$thisid_type = $id_type;
702
	switch ($thisid_type) {
703
		case 'myaddress':
704
			$thisid_type = 'address';
705
			$thisid_data = $addr;
706
			break;
707
		case 'dyn_dns':
708
			$thisid_type = 'dns';
709
			$thisid_data = $id_data;
710
			break;
711
		case 'peeraddress':
712
			$thisid_type = 'address';
713
			$thisid_data = $rgmap[$ph1ent['remote-gateway']];
714
			break;
715
		case 'address':
716
			$thisid_data = $id_data;
717
			break;
718
		case 'fqdn':
719
			$thisid_data = "{$id_data}";
720
			break;
721
		case 'keyid tag':
722
			$thisid_type = 'keyid';
723
			$thisid_data = "{$id_data}";
724
			break;
725
		case 'user_fqdn':
726
			$thisid_type = 'userfqdn';
727
			$thisid_data = "{$id_data}";
728
			break;
729
		case 'asn1dn':
730
			$thisid_data = $id_data;
731
			break;
732
	}
733
	return array($thisid_type, $thisid_data);
734
}
735

    
736
function ipsec_fixup_network($network) {
737
	if (substr($network, -3) == '|/0') {
738
		$result = substr($network, 0, -3);
739
	} else {
740
		$tmp = explode('|', $network);
741
		if (isset($tmp[1])) {
742
			$result = $tmp[1];
743
		} else {
744
			$result = $tmp[0];
745
		}
746
		unset($tmp);
747
	}
748

    
749
	return $result;
750
}
751

    
752
function ipsec_new_reqid() {
753
	global $config;
754

    
755
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
756
		return;
757
	}
758

    
759
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
760
	$keyids = array();
761
	$keyid = 1;
762
	foreach ($config['ipsec']['phase2'] as $ph2) {
763
		$keyids[$ph2['reqid']] = $ph2['reqid'];
764
	}
765

    
766
	for ($i = 1; $i < 16000; $i++) {
767
		if (!isset($keyids[$i])) {
768
			$keyid = $i;
769
			break;
770
		}
771
	}
772
	unlock($ipsecreqid);
773

    
774
	return $keyid;
775
}
776

    
777
?>
(29-29/67)