Project

General

Profile

Download (18.8 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 (!file_exists("{$g['varrun_path']}/charon.xml")) {
414
		log_error("IPsec daemon not running or has a problem!");
415
		return;
416
	}
417

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

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

    
437
	if ($sread === false) {
438
		log_error("Error during reading of status from IPsec");
439
		return;
440
	}
441

    
442
	@file_put_contents("{$g['tmp_path']}/smp_status.xml", $response);
443
	unset($response, $sread);
444

    
445
	$custom_listtags = array('ikesa', 'childsa', 'network', 'auth');
446
	$response = parse_xml_config("{$g['tmp_path']}/smp_status.xml", "message");
447
	@unlink("{$g['tmp_path']}/smp_status.xml");
448
	unset($custom_listtags);
449

    
450
	return $response;
451
}
452

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

    
505
	return $spd;
506
}
507

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

    
559
	return $sad;
560
}
561

    
562
/*
563
 * Return dump of mobile user list
564
 */
565
function ipsec_dump_mobile() {
566
	global $g, $custom_listtags;
567

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

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

    
575
	/* This is needed for fixing #4130 */
576
	if (filesize("{$g['tmp_path']}/strongswan_leases.xml") < 200) {
577
		return array();
578
	}
579

    
580
	$custom_listtags = array('lease', 'pool');
581
	$response = parse_xml_config("{$g['tmp_path']}/strongswan_leases.xml", "leases");
582
	@unlink("{$g['tmp_path']}/strongswan_leases.xml");
583
	unset($custom_listtags, $_gb);
584

    
585
	return $response;
586
}
587

    
588
function ipsec_mobilekey_sort() {
589
	global $config;
590

    
591
	function mobilekeycmp($a, $b) {
592
		return strcmp($a['ident'][0], $b['ident'][0]);
593
	}
594

    
595
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
596
}
597

    
598
function ipsec_get_number_of_phase2($ikeid) {
599
	global $config;
600
	$a_phase2 = $config['ipsec']['phase2'];
601

    
602
	$nbph2=0;
603

    
604
	if (is_array($a_phase2) && count($a_phase2)) {
605
		foreach ($a_phase2 as $ph2tmp) {
606
			if ($ph2tmp['ikeid'] == $ikeid) {
607
				$nbph2++;
608
			}
609
		}
610
	}
611

    
612
	return $nbph2;
613
}
614

    
615
function ipsec_get_descr($ikeid) {
616
	global $config;
617

    
618
	if (!isset($config['ipsec']['phase1']) ||
619
	    !is_array($config['ipsec']['phase1'])) {
620
		return '';
621
	}
622

    
623
	foreach ($config['ipsec']['phase1'] as $p1) {
624
		if ($p1['ikeid'] == $ikeid) {
625
			return $p1['descr'];
626
		}
627
	}
628

    
629
	return '';
630
}
631

    
632
function ipsec_get_phase1($ikeid) {
633
		global $config;
634

    
635
		if (!isset($config['ipsec']['phase1']) ||
636
		    !is_array($config['ipsec']['phase1'])) {
637
			return '';
638
		}
639

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

    
649
function ipsec_fixup_ip($ipaddr) {
650
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
651
		return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr));
652
	} else {
653
		return $ipaddr;
654
	}
655
}
656

    
657
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
658
	if ($side == "local") {
659
		$id_type = $ph1ent['myid_type'];
660
		$id_data = $ph1ent['myid_data'];
661

    
662
		$addr = ipsec_get_phase1_src($ph1ent);
663
		if (!$addr) {
664
			return array();
665
		}
666
	} elseif ($side == "peer") {
667
		$id_type = $ph1ent['peerid_type'];
668
		$id_data = $ph1ent['peerid_data'];
669

    
670
		if (isset($ph1ent['mobile'])) {
671
			$addr = "%any";
672
		} else {
673
			$addr = $ph1ent['remote-gateway'];
674
		}
675
	} else {
676
		return array();
677
	}
678

    
679

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

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

    
731
	return $result;
732
}
733

    
734
function ipsec_new_reqid() {
735
	global $config;
736

    
737
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
738
		return;
739
	}
740

    
741
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
742
	$keyids = array();
743
	$keyid = 1;
744
	foreach ($config['ipsec']['phase2'] as $ph2) {
745
		$keyids[$ph2['reqid']] = $ph2['reqid'];
746
	}
747

    
748
	for ($i = 1; $i < 16000; $i++) {
749
		if (!isset($keyids[$i])) {
750
			$keyid = $i;
751
			break;
752
		}
753
	}
754
	unlock($ipsecreqid);
755

    
756
	return $keyid;
757
}
758

    
759
?>
(29-29/68)