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
	'peeraddress' => array('desc' => gettext('Peer IP address'), 'mobile' => false),
58
	'address' => array('desc' => gettext('IP address'), 'mobile' => false),
59
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
60
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
61
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
62
	'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true));
63

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

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

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

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

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

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

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

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

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

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

    
160
global $p2_pfskeygroups;
161
$p2_pfskeygroups = array(
162
	0 => 'off',
163
	1  => '1 (768 bit)',
164
	2  => '2 (1024 bit)',
165
	5  => '5 (1536 bit)',
166
	14 => '14 (2048 bit)',
167
	15 => '15 (3072 bit)',
168
	16 => '16 (4096 bit)',
169
	17 => '17 (6144 bit)',
170
	18 => '18 (8192 bit)',
171
	19 => '19 (nist ecp256)',
172
	20 => '20 (nist ecp384)',
173
	21 => '21 (nist ecp521)',
174
	28 => '28 (brainpool ecp256)',
175
	29 => '29 (brainpool ecp384)',
176
	30 => '30 (brainpool ecp512)'
177
);
178

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

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

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

    
192
	return false;
193
}
194

    
195
function ipsec_ikeid_next() {
196

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

    
202
	return $ikeid;
203
}
204

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

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

    
234
	return $interfaceip;
235
}
236

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

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

    
256
	return $rg;
257
}
258

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

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

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

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

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

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

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

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

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

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

    
397
	return false;
398
}
399

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

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

    
413
	return false;
414
}
415

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

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

    
425
	return false;
426
}
427

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

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

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

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

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

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

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

    
472
	return $response;
473
}
474

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

    
526
	return $spd;
527
}
528

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

    
579
	return $sad;
580
}
581

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

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

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

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

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

    
605
	return $response;
606
}
607

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

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

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

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

    
622
	$nbph2=0;
623

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

    
632
	return $nbph2;
633
}
634

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

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

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

    
649
	return '';
650
}
651

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

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

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

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

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

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

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

    
699

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

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

    
751
	return $result;
752
}
753

    
754
function ipsec_new_reqid() {
755
	global $config;
756

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

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

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

    
776
	return $keyid;
777
}
778

    
779
?>
(28-28/67)