Project

General

Profile

Download (19.1 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
	'blowfish' => array( 'name' => 'Blowfish', 'keysel' => array( 'lo' => 128, 'hi' => 256, 'step' => 64 ) ),
73
	'3des' => array( 'name' => '3DES' ),
74
	'cast128' => array( 'name' => 'CAST128' ),
75
	'des' => array( 'name' => 'DES' ));
76

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

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

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

    
116
global $p2_halgos;
117
$p2_halgos = array(
118
	'hmac_md5' => 'MD5',
119
	'hmac_sha1' => 'SHA1',
120
	'hmac_sha256' => 'SHA256',
121
	'hmac_sha384' => 'SHA384',
122
	'hmac_sha512' => 'SHA512',
123
	'aesxcbc' => 'AES-XCBC'
124
);
125

    
126
global $p1_authentication_methods;
127
$p1_authentication_methods = array(
128
	'hybrid_rsa_server' => array( 'name' => 'Hybrid RSA + Xauth', 'mobile' => true ),
129
	'xauth_rsa_server' => array( 'name' => 'Mutual RSA + Xauth', 'mobile' => true ),
130
	'xauth_psk_server' => array( 'name' => 'Mutual PSK + Xauth', 'mobile' => true ),
131
	'eap-tls' => array( 'name' => 'EAP-TLS', 'mobile' => true),
132
	'eap-radius' => array( 'name' => 'EAP-RADIUS', 'mobile' => true),
133
	'eap-mschapv2' => array( 'name' => 'EAP-MSChapv2', 'mobile' => true),
134
	'rsasig' => array( 'name' => 'Mutual RSA', 'mobile' => false ),
135
	'pre_shared_key' => array( 'name' => 'Mutual PSK', 'mobile' => false ) );
136

    
137
global $ipsec_preshared_key_type;
138
$ipsec_preshared_key_type = array(
139
	'PSK' => 'PSK',
140
	'EAP' => 'EAP'
141
	);
142

    
143
global $p2_modes;
144
$p2_modes = array(
145
	'tunnel' => 'Tunnel IPv4',
146
	'tunnel6' => 'Tunnel IPv6',
147
	'transport' => 'Transport');
148

    
149
global $p2_protos;
150
$p2_protos = array(
151
	'esp' => 'ESP',
152
	'ah' => 'AH');
153

    
154
global $p2_pfskeygroups;
155
$p2_pfskeygroups = array(
156
	0 => 'off',
157
	1  => '1 (768 bit)',
158
	2  => '2 (1024 bit)',
159
	5  => '5 (1536 bit)',
160
	14 => '14 (2048 bit)',
161
	15 => '15 (3072 bit)',
162
	16 => '16 (4096 bit)',
163
	17 => '17 (6144 bit)',
164
	18 => '18 (8192 bit)'
165
);
166

    
167
/*
168
 * ikeid management functions
169
 */
170

    
171
function ipsec_ikeid_used($ikeid) {
172
	global $config;
173

    
174
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
175
		if ( $ikeid == $ph1ent['ikeid'] ) {
176
			return true;
177
		}
178
	}
179

    
180
	return false;
181
}
182

    
183
function ipsec_ikeid_next() {
184

    
185
	$ikeid = 1;
186
	while (ipsec_ikeid_used($ikeid)) {
187
		$ikeid++;
188
	}
189

    
190
	return $ikeid;
191
}
192

    
193
/*
194
 * Return phase1 local address
195
 */
196
function ipsec_get_phase1_src(& $ph1ent) {
197

    
198
	if ($ph1ent['interface']) {
199
		if (!is_ipaddr($ph1ent['interface'])) {
200
			if (strpos($ph1ent['interface'], '_vip')) {
201
				$if = $ph1ent['interface'];
202
			} else {
203
				$if = get_failover_interface($ph1ent['interface']);
204
			}
205
			if ($ph1ent['protocol'] == "inet6") {
206
				$interfaceip = get_interface_ipv6($if);
207
			} else {
208
				$interfaceip = get_interface_ip($if);
209
			}
210
		} else {
211
			$interfaceip=$ph1ent['interface'];
212
		}
213
	} else {
214
		$if = "wan";
215
		if ($ph1ent['protocol'] == "inet6") {
216
			$interfaceip = get_interface_ipv6($if);
217
		} else {
218
			$interfaceip = get_interface_ip($if);
219
		}
220
	}
221

    
222
	return $interfaceip;
223
}
224

    
225
/*
226
 * Return phase1 local address
227
 */
228
function ipsec_get_phase1_dst(& $ph1ent) {
229
	global $g;
230

    
231
	if (empty($ph1ent['remote-gateway'])) {
232
		return false;
233
	}
234
	$rg = $ph1ent['remote-gateway'];
235
	if (!is_ipaddr($rg)) {
236
		if (! platform_booting()) {
237
			return resolve_retry($rg);
238
		}
239
	}
240
	if (!is_ipaddr($rg)) {
241
		return false;
242
	}
243

    
244
	return $rg;
245
}
246

    
247
/*
248
 * Return phase2 idinfo in cidr format
249
 */
250
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
251
	global $config;
252

    
253
	switch ($idinfo['type']) {
254
		case "address":
255
			if ($addrbits) {
256
				if ($mode == "tunnel6") {
257
					return $idinfo['address']."/128";
258
				} else {
259
					return $idinfo['address']."/32";
260
				}
261
			} else
262
				return $idinfo['address'];
263
			break; /* NOTREACHED */
264
		case "network":
265
			return "{$idinfo['address']}/{$idinfo['netbits']}";
266
			break; /* NOTREACHED */
267
		case "none":
268
		case "mobile":
269
			return '0.0.0.0/0';
270
			break; /* NOTREACHED */
271
		default:
272
			if (empty($mode) && !empty($idinfo['mode'])) {
273
				$mode = $idinfo['mode'];
274
			}
275

    
276
			if ($mode == "tunnel6") {
277
				$address = get_interface_ipv6($idinfo['type']);
278
				$netbits = get_interface_subnetv6($idinfo['type']);
279
				$address = gen_subnetv6($address,$netbits);
280
				return "{$address}/{$netbits}";
281
			} else {
282
				$address = get_interface_ip($idinfo['type']);
283
				$netbits = get_interface_subnet($idinfo['type']);
284
				$address = gen_subnet($address,$netbits);
285
				return "{$address}/{$netbits}";
286
			}
287
			break; /* NOTREACHED */
288
	}
289
}
290

    
291
/*
292
 * Return phase2 idinfo in address/netmask format
293
 */
294
function ipsec_idinfo_to_subnet(& $idinfo,$addrbits = false) {
295
	global $config;
296

    
297
	switch ($idinfo['type']) {
298
		case "address":
299
			if ($addrbits) {
300
				if ($idinfo['mode'] == "tunnel6") {
301
					return $idinfo['address']."/128";
302
				} else {
303
					return $idinfo['address']."/255.255.255.255";
304
				}
305
			} else
306
				return $idinfo['address'];
307
			break; /* NOTREACHED */
308
		case "none":
309
		case "network":
310
			return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
311
			break; /* NOTREACHED */
312
		case "mobile":
313
			return "0.0.0.0/0";
314
			break; /* NOTREACHED */
315
		default:
316
			if ($idinfo['mode'] == "tunnel6") {
317
				$address = get_interface_ipv6($idinfo['type']);
318
				$netbits = get_interface_subnetv6($idinfo['type']);
319
				$address = gen_subnetv6($address,$netbits);
320
				return $address."/".$netbits;
321
			} else {
322
				$address = get_interface_ip($idinfo['type']);
323
				$netbits = get_interface_subnet($idinfo['type']);
324
				$address = gen_subnet($address,$netbits);
325
				return $address."/".$netbits;
326
			}
327
			break; /* NOTREACHED */
328
	}
329
}
330

    
331
/*
332
 *  Return phase2 idinfo in text format
333
 */
334
function ipsec_idinfo_to_text(& $idinfo) {
335
	global $config;
336

    
337
	switch ($idinfo['type']) {
338
		case "address":
339
			return $idinfo['address'];
340
			break; /* NOTREACHED */
341
		case "network":
342
			return $idinfo['address']."/".$idinfo['netbits'];
343
			break; /* NOTREACHED */
344
		case "mobile":
345
			return gettext("Mobile Client");
346
			break; /* NOTREACHED */
347
		case "none":
348
			return gettext("None");
349
			break; /* NOTREACHED */
350
		default:
351
			if (!empty($config['interfaces'][$idinfo['type']])) {
352
				return convert_friendly_interface_to_friendly_descr($idinfo['type']);
353
			} else {
354
				return strtoupper($idinfo['type']);
355
			}
356
			break; /* NOTREACHED */
357
	}
358
}
359

    
360
/*
361
 * Return phase1 association for phase2
362
 */
363
function ipsec_lookup_phase1(& $ph2ent,& $ph1ent) {
364
	global $config;
365

    
366
	if (!is_array($config['ipsec'])) {
367
		return false;
368
	}
369
	if (!is_array($config['ipsec']['phase1'])) {
370
		return false;
371
	}
372
	if (empty($config['ipsec']['phase1'])) {
373
		return false;
374
	}
375

    
376
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
377
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
378
			$ph1ent = $ph1tmp;
379
			return $ph1ent;
380
		}
381
	}
382

    
383
	return false;
384
}
385

    
386
/*
387
 * Check phase1 communications status
388
 */
389
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
390

    
391
	foreach ($ipsec_status as $ike) {
392
		if ($ike['id'] == $ikeid) {
393
			if ($ike['status'] == 'established') {
394
				return true;
395
			}
396
		}
397
	}
398

    
399
	return false;
400
}
401

    
402
/*
403
 * Check phase2 communications status
404
 */
405
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
406

    
407
	if (ipsec_lookup_phase1($ph2ent,$ph1ent)) {
408
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
409
	}
410

    
411
	return false;
412
}
413

    
414
function ipsec_smp_dump_status() {
415
	global $config, $g, $custom_listtags;
416

    
417
        if (isset($config['ipsec']['enable'])) {
418
            if (!file_exists("{$g['varrun_path']}/charon.xml")) {
419
                log_error("IPsec daemon not running or has a problem!");
420
                return;
421
            }
422
        } else {
423
            return;
424
        }
425

    
426
	$fd = @fsockopen("unix://{$g['varrun_path']}/charon.xml");
427
	if (!$fd) {
428
		log_error("Could not read status from IPsec");
429
		return;
430
	}
431
	$query = '<?xml version="1.0"?><message xmlns="http://www.strongswan.org/smp/1.0" type="request" id="1">';
432
	$query .= '<query><ikesalist/></query></message>';
433

    
434
	@fwrite($fd, $query);
435
	$response = "";
436
	while (!strstr($sread, "</message>")) {
437
		$sread = fgets($fd);
438
		if ($sread === false) {
439
			break;
440
		}
441
		$response .= $sread;
442
	}
443
	fclose($fd);
444

    
445
	if ($sread === false) {
446
		log_error("Error during reading of status from IPsec");
447
		return;
448
	}
449

    
450
	@file_put_contents("{$g['tmp_path']}/smp_status.xml", $response);
451
	unset($response, $sread);
452

    
453
	$custom_listtags = array('ikesa', 'childsa', 'network', 'auth');
454
	$response = parse_xml_config("{$g['tmp_path']}/smp_status.xml", "message");
455
	@unlink("{$g['tmp_path']}/smp_status.xml");
456
	unset($custom_listtags);
457

    
458
	return $response;
459
}
460

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

    
513
	return $spd;
514
}
515

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

    
567
	return $sad;
568
}
569

    
570
/*
571
 * Return dump of mobile user list
572
 */
573
function ipsec_dump_mobile() {
574
	global $g, $custom_listtags;
575

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

    
578
	if (!file_exists("{$g['tmp_path']}/strongswan_leases.xml")) {
579
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
580
		return array();
581
	}
582

    
583
	/* This is needed for fixing #4130 */
584
	if (filesize("{$g['tmp_path']}/strongswan_leases.xml") < 200) {
585
		return array();
586
	}
587

    
588
	$custom_listtags = array('lease', 'pool');
589
	$response = parse_xml_config("{$g['tmp_path']}/strongswan_leases.xml", "leases");
590
	@unlink("{$g['tmp_path']}/strongswan_leases.xml");
591
	unset($custom_listtags, $_gb);
592

    
593
	return $response;
594
}
595

    
596
function ipsec_mobilekey_sort() {
597
	global $config;
598

    
599
	function mobilekeycmp($a, $b) {
600
		return strcmp($a['ident'][0], $b['ident'][0]);
601
	}
602

    
603
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
604
}
605

    
606
function ipsec_get_number_of_phase2($ikeid) {
607
	global $config;
608
	$a_phase2 = $config['ipsec']['phase2'];
609

    
610
	$nbph2=0;
611

    
612
	if (is_array($a_phase2) && count($a_phase2)) {
613
		foreach ($a_phase2 as $ph2tmp) {
614
			if ($ph2tmp['ikeid'] == $ikeid) {
615
				$nbph2++;
616
			}
617
		}
618
	}
619

    
620
	return $nbph2;
621
}
622

    
623
function ipsec_get_descr($ikeid) {
624
	global $config;
625

    
626
	if (!isset($config['ipsec']['phase1']) ||
627
	    !is_array($config['ipsec']['phase1'])) {
628
		return '';
629
	}
630

    
631
	foreach ($config['ipsec']['phase1'] as $p1) {
632
		if ($p1['ikeid'] == $ikeid) {
633
			return $p1['descr'];
634
		}
635
	}
636

    
637
	return '';
638
}
639

    
640
function ipsec_get_phase1($ikeid) {
641
		global $config;
642

    
643
		if (!isset($config['ipsec']['phase1']) ||
644
		    !is_array($config['ipsec']['phase1'])) {
645
			return '';
646
		}
647

    
648
		$a_phase1 = $config['ipsec']['phase1'];
649
		foreach ($a_phase1 as $p1) {
650
			if ($p1['ikeid'] == $ikeid) {
651
				return $p1;
652
			}
653
		}
654
		unset($a_phase1);
655
}
656

    
657
function ipsec_fixup_ip($ipaddr) {
658
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
659
		return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr));
660
	} else {
661
		return $ipaddr;
662
	}
663
}
664

    
665
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
666
	if ($side == "local") {
667
		$id_type = $ph1ent['myid_type'];
668
		$id_data = $ph1ent['myid_data'];
669

    
670
		$addr = ipsec_get_phase1_src($ph1ent);
671
		if (!$addr) {
672
			return array();
673
		}
674
	} elseif ($side == "peer") {
675
		$id_type = $ph1ent['peerid_type'];
676
		$id_data = $ph1ent['peerid_data'];
677

    
678
		if (isset($ph1ent['mobile'])) {
679
			$addr = "%any";
680
		} else {
681
			$addr = $ph1ent['remote-gateway'];
682
		}
683
	} else {
684
		return array();
685
	}
686

    
687

    
688
	$thisid_type = $id_type;
689
	switch ($thisid_type) {
690
		case 'myaddress':
691
			$thisid_type = 'address';
692
			$thisid_data = $addr;
693
			break;
694
		case 'dyn_dns':
695
			$thisid_type = 'dns';
696
			$thisid_data = $id_data;
697
			break;
698
		case 'peeraddress':
699
			$thisid_type = 'address';
700
			$thisid_data = $rgmap[$ph1ent['remote-gateway']];
701
			break;
702
		case 'address':
703
			$thisid_data = $id_data;
704
			break;
705
		case 'fqdn':
706
			$thisid_data = "{$id_data}";
707
			break;
708
		case 'keyid tag':
709
			$thisid_type = 'keyid';
710
			$thisid_data = "{$thisid_data}";
711
			break;
712
		case 'user_fqdn':
713
			$thisid_type = 'userfqdn';
714
			$thisid_data = "{$id_data}";
715
			break;
716
		case 'asn1dn':
717
			$thisid_data = $id_data;
718
			if ($thisid_data && $thisid_data[0] != '"') {
719
				$thisid_data = "\"{$id_data}\"";
720
			}
721
			break;
722
	}
723
	return array($thisid_type, $thisid_data);
724
}
725

    
726
function ipsec_fixup_network($network) {
727
	if (substr($network, -3) == '|/0') {
728
		$result = substr($network, 0, -3);
729
	} else {
730
		$tmp = explode('|', $network);
731
		if (isset($tmp[1])) {
732
			$result = $tmp[1];
733
		} else {
734
			$result = $tmp[0];
735
		}
736
		unset($tmp);
737
	}
738

    
739
	return $result;
740
}
741

    
742
function ipsec_new_reqid() {
743
	global $config;
744

    
745
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
746
		return;
747
	}
748

    
749
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
750
	$keyids = array();
751
	$keyid = 1;
752
	foreach ($config['ipsec']['phase2'] as $ph2) {
753
		$keyids[$ph2['reqid']] = $ph2['reqid'];
754
	}
755

    
756
	for ($i = 1; $i < 16000; $i++) {
757
		if (!isset($keyids[$i])) {
758
			$keyid = $i;
759
			break;
760
		}
761
	}
762
	unlock($ipsecreqid);
763

    
764
	return $keyid;
765
}
766

    
767
?>
(28-28/67)