Project

General

Profile

Download (19 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
	22 => '22 (1024(sub 160) bit)',
109
	23 => '23 (2048(sub 224) bit)',
110
	24 => '24 (2048(sub 256) bit)'
111
);
112

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

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

    
133
global $ipsec_preshared_key_type;
134
$ipsec_preshared_key_type = array(
135
	'PSK' => 'PSK',
136
	'EAP' => 'EAP'
137
	);
138

    
139
global $p2_modes;
140
$p2_modes = array(
141
	'tunnel' => 'Tunnel IPv4',
142
	'tunnel6' => 'Tunnel IPv6',
143
	'transport' => 'Transport');
144

    
145
global $p2_protos;
146
$p2_protos = array(
147
	'esp' => 'ESP',
148
	'ah' => 'AH');
149

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

    
163
/*
164
 * ikeid management functions
165
 */
166

    
167
function ipsec_ikeid_used($ikeid) {
168
	global $config;
169

    
170
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
171
		if ( $ikeid == $ph1ent['ikeid'] ) {
172
			return true;
173
		}
174
	}
175

    
176
	return false;
177
}
178

    
179
function ipsec_ikeid_next() {
180

    
181
	$ikeid = 1;
182
	while (ipsec_ikeid_used($ikeid)) {
183
		$ikeid++;
184
	}
185

    
186
	return $ikeid;
187
}
188

    
189
/*
190
 * Return phase1 local address
191
 */
192
function ipsec_get_phase1_src(& $ph1ent) {
193

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

    
218
	return $interfaceip;
219
}
220

    
221
/*
222
 * Return phase1 local address
223
 */
224
function ipsec_get_phase1_dst(& $ph1ent) {
225
	global $g;
226

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

    
240
	return $rg;
241
}
242

    
243
/*
244
 * Return phase2 idinfo in cidr format
245
 */
246
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
247
	global $config;
248

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

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

    
287
/*
288
 * Return phase2 idinfo in address/netmask format
289
 */
290
function ipsec_idinfo_to_subnet(& $idinfo,$addrbits = false) {
291
	global $config;
292

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

    
327
/*
328
 *  Return phase2 idinfo in text format
329
 */
330
function ipsec_idinfo_to_text(& $idinfo) {
331
	global $config;
332

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

    
356
/*
357
 * Return phase1 association for phase2
358
 */
359
function ipsec_lookup_phase1(& $ph2ent,& $ph1ent) {
360
	global $config;
361

    
362
	if (!is_array($config['ipsec'])) {
363
		return false;
364
	}
365
	if (!is_array($config['ipsec']['phase1'])) {
366
		return false;
367
	}
368
	if (empty($config['ipsec']['phase1'])) {
369
		return false;
370
	}
371

    
372
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
373
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
374
			$ph1ent = $ph1tmp;
375
			return $ph1ent;
376
		}
377
	}
378

    
379
	return false;
380
}
381

    
382
/*
383
 * Check phase1 communications status
384
 */
385
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
386

    
387
	foreach ($ipsec_status as $ike) {
388
		if ($ike['id'] == $ikeid) {
389
			if ($ike['status'] == 'established') {
390
				return true;
391
			}
392
		}
393
	}
394

    
395
	return false;
396
}
397

    
398
/*
399
 * Check phase2 communications status
400
 */
401
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
402

    
403
	if (ipsec_lookup_phase1($ph2ent,$ph1ent)) {
404
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
405
	}
406

    
407
	return false;
408
}
409

    
410
function ipsec_smp_dump_status() {
411
	global $config, $g, $custom_listtags;
412

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

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

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

    
441
	if ($sread === false) {
442
		log_error("Error during reading of status from IPsec");
443
		return;
444
	}
445

    
446
	@file_put_contents("{$g['tmp_path']}/smp_status.xml", $response);
447
	unset($response, $sread);
448

    
449
	$custom_listtags = array('ikesa', 'childsa', 'network', 'auth');
450
	$response = parse_xml_config("{$g['tmp_path']}/smp_status.xml", "message");
451
	@unlink("{$g['tmp_path']}/smp_status.xml");
452
	unset($custom_listtags);
453

    
454
	return $response;
455
}
456

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

    
509
	return $spd;
510
}
511

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

    
563
	return $sad;
564
}
565

    
566
/*
567
 * Return dump of mobile user list
568
 */
569
function ipsec_dump_mobile() {
570
	global $g, $custom_listtags;
571

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

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

    
579
	/* This is needed for fixing #4130 */
580
	if (filesize("{$g['tmp_path']}/strongswan_leases.xml") < 200) {
581
		return array();
582
	}
583

    
584
	$custom_listtags = array('lease', 'pool');
585
	$response = parse_xml_config("{$g['tmp_path']}/strongswan_leases.xml", "leases");
586
	@unlink("{$g['tmp_path']}/strongswan_leases.xml");
587
	unset($custom_listtags, $_gb);
588

    
589
	return $response;
590
}
591

    
592
function ipsec_mobilekey_sort() {
593
	global $config;
594

    
595
	function mobilekeycmp($a, $b) {
596
		return strcmp($a['ident'][0], $b['ident'][0]);
597
	}
598

    
599
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
600
}
601

    
602
function ipsec_get_number_of_phase2($ikeid) {
603
	global $config;
604
	$a_phase2 = $config['ipsec']['phase2'];
605

    
606
	$nbph2=0;
607

    
608
	if (is_array($a_phase2) && count($a_phase2)) {
609
		foreach ($a_phase2 as $ph2tmp) {
610
			if ($ph2tmp['ikeid'] == $ikeid) {
611
				$nbph2++;
612
			}
613
		}
614
	}
615

    
616
	return $nbph2;
617
}
618

    
619
function ipsec_get_descr($ikeid) {
620
	global $config;
621

    
622
	if (!isset($config['ipsec']['phase1']) ||
623
	    !is_array($config['ipsec']['phase1'])) {
624
		return '';
625
	}
626

    
627
	foreach ($config['ipsec']['phase1'] as $p1) {
628
		if ($p1['ikeid'] == $ikeid) {
629
			return $p1['descr'];
630
		}
631
	}
632

    
633
	return '';
634
}
635

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

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

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

    
653
function ipsec_fixup_ip($ipaddr) {
654
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
655
		return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr));
656
	} else {
657
		return $ipaddr;
658
	}
659
}
660

    
661
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
662
	if ($side == "local") {
663
		$id_type = $ph1ent['myid_type'];
664
		$id_data = $ph1ent['myid_data'];
665

    
666
		$addr = ipsec_get_phase1_src($ph1ent);
667
		if (!$addr) {
668
			return array();
669
		}
670
	} elseif ($side == "peer") {
671
		$id_type = $ph1ent['peerid_type'];
672
		$id_data = $ph1ent['peerid_data'];
673

    
674
		if (isset($ph1ent['mobile'])) {
675
			$addr = "%any";
676
		} else {
677
			$addr = $ph1ent['remote-gateway'];
678
		}
679
	} else {
680
		return array();
681
	}
682

    
683

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

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

    
735
	return $result;
736
}
737

    
738
function ipsec_new_reqid() {
739
	global $config;
740

    
741
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
742
		return;
743
	}
744

    
745
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
746
	$keyids = array();
747
	$keyid = 1;
748
	foreach ($config['ipsec']['phase2'] as $ph2) {
749
		$keyids[$ph2['reqid']] = $ph2['reqid'];
750
	}
751

    
752
	for ($i = 1; $i < 16000; $i++) {
753
		if (!isset($keyids[$i])) {
754
			$keyid = $i;
755
			break;
756
		}
757
	}
758
	unlock($ipsecreqid);
759

    
760
	return $keyid;
761
}
762

    
763
?>
(28-28/67)