Project

General

Profile

Download (19.4 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
);
118

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

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

    
140
global $ipsec_preshared_key_type;
141
$ipsec_preshared_key_type = array(
142
	'PSK' => 'PSK',
143
	'EAP' => 'EAP'
144
	);
145

    
146
global $p2_modes;
147
$p2_modes = array(
148
	'tunnel' => 'Tunnel IPv4',
149
	'tunnel6' => 'Tunnel IPv6',
150
	'transport' => 'Transport');
151

    
152
global $p2_protos;
153
$p2_protos = array(
154
	'esp' => 'ESP',
155
	'ah' => 'AH');
156

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

    
170
/*
171
 * ikeid management functions
172
 */
173

    
174
function ipsec_ikeid_used($ikeid) {
175
	global $config;
176

    
177
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
178
		if ( $ikeid == $ph1ent['ikeid'] ) {
179
			return true;
180
		}
181
	}
182

    
183
	return false;
184
}
185

    
186
function ipsec_ikeid_next() {
187

    
188
	$ikeid = 1;
189
	while (ipsec_ikeid_used($ikeid)) {
190
		$ikeid++;
191
	}
192

    
193
	return $ikeid;
194
}
195

    
196
/*
197
 * Return phase1 local address
198
 */
199
function ipsec_get_phase1_src(& $ph1ent) {
200

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

    
225
	return $interfaceip;
226
}
227

    
228
/*
229
 * Return phase1 local address
230
 */
231
function ipsec_get_phase1_dst(& $ph1ent) {
232
	global $g;
233

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

    
247
	return $rg;
248
}
249

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

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

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

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

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

    
334
/*
335
 *  Return phase2 idinfo in text format
336
 */
337
function ipsec_idinfo_to_text(& $idinfo) {
338
	global $config;
339

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

    
363
/*
364
 * Return phase1 association for phase2
365
 */
366
function ipsec_lookup_phase1(& $ph2ent,& $ph1ent) {
367
	global $config;
368

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

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

    
386
	return false;
387
}
388

    
389
/*
390
 * Check phase1 communications status
391
 */
392
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
393

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

    
402
	return false;
403
}
404

    
405
/*
406
 * Check phase2 communications status
407
 */
408
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
409

    
410
	if (ipsec_lookup_phase1($ph2ent,$ph1ent)) {
411
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
412
	}
413

    
414
	return false;
415
}
416

    
417
function ipsec_smp_dump_status() {
418
	global $config, $g, $custom_listtags;
419

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

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

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

    
448
	if ($sread === false) {
449
		log_error("Error during reading of status from IPsec");
450
		return;
451
	}
452

    
453
	@file_put_contents("{$g['tmp_path']}/smp_status.xml", $response);
454
	unset($response, $sread);
455

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

    
461
	return $response;
462
}
463

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

    
516
	return $spd;
517
}
518

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

    
570
	return $sad;
571
}
572

    
573
/*
574
 * Return dump of mobile user list
575
 */
576
function ipsec_dump_mobile() {
577
	global $g, $custom_listtags;
578

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

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

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

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

    
596
	return $response;
597
}
598

    
599
function ipsec_mobilekey_sort() {
600
	global $config;
601

    
602
	function mobilekeycmp($a, $b) {
603
		return strcmp($a['ident'][0], $b['ident'][0]);
604
	}
605

    
606
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
607
}
608

    
609
function ipsec_get_number_of_phase2($ikeid) {
610
	global $config;
611
	$a_phase2 = $config['ipsec']['phase2'];
612

    
613
	$nbph2=0;
614

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

    
623
	return $nbph2;
624
}
625

    
626
function ipsec_get_descr($ikeid) {
627
	global $config;
628

    
629
	if (!isset($config['ipsec']['phase1']) ||
630
	    !is_array($config['ipsec']['phase1'])) {
631
		return '';
632
	}
633

    
634
	foreach ($config['ipsec']['phase1'] as $p1) {
635
		if ($p1['ikeid'] == $ikeid) {
636
			return $p1['descr'];
637
		}
638
	}
639

    
640
	return '';
641
}
642

    
643
function ipsec_get_phase1($ikeid) {
644
		global $config;
645

    
646
		if (!isset($config['ipsec']['phase1']) ||
647
		    !is_array($config['ipsec']['phase1'])) {
648
			return '';
649
		}
650

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

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

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

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

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

    
690

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

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

    
742
	return $result;
743
}
744

    
745
function ipsec_new_reqid() {
746
	global $config;
747

    
748
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
749
		return;
750
	}
751

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

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

    
767
	return $keyid;
768
}
769

    
770
?>
(28-28/67)