Project

General

Profile

Download (22.8 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * ipsec.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2008 Shrew Soft Inc.
7
 * Copyright (c) 2007-2013 BSD Perimeter
8
 * Copyright (c) 2013-2016 Electric Sheep Fencing
9
 * Copyright (c) 2014-2019 Rubicon Communications, LLC (Netgate)
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24

    
25
/* IPsec defines */
26
global $ipsec_loglevels;
27
$ipsec_loglevels = array(
28
	"dmn" => gettext("Daemon"),
29
	"mgr" => gettext("SA Manager"),
30
	"ike" => gettext("IKE SA"),
31
	"chd" => gettext("IKE Child SA"),
32
	"job" => gettext("Job Processing"),
33
	"cfg" => gettext("Configuration backend"),
34
	"knl" => gettext("Kernel Interface"),
35
	"net" => gettext("Networking"),
36
	"asn" => gettext("ASN encoding"),
37
	"enc" => gettext("Message encoding"),
38
	"imc" => gettext("Integrity checker"),
39
	"imv" => gettext("Integrity Verifier"),
40
	"pts" => gettext("Platform Trust Service"),
41
	"tls" => gettext("TLS handler"),
42
	"esp" => gettext("IPsec traffic"),
43
	"lib" => gettext("StrongSwan Lib")
44
);
45

    
46
global $ipsec_log_sevs;
47
$ipsec_log_sevs = array(
48
	'-1' => gettext('Silent'),
49
	'0' => gettext('Audit'),
50
	'1' => gettext('Control'),
51
	'2' => gettext('Diag'),
52
	'3' => gettext('Raw'),
53
	'4' => gettext('Highest')
54
);
55

    
56
global $ipsec_log_cats;
57
$ipsec_log_cats = array(
58
	"dmn" => gettext("Daemon"),
59
	"mgr" => gettext("SA Manager"),
60
	"ike" => gettext("IKE SA"),
61
	"chd" => gettext("IKE Child SA"),
62
	"job" => gettext("Job Processing"),
63
	"cfg" => gettext("Configuration backend"),
64
	"knl" => gettext("Kernel Interface"),
65
	"net" => gettext("Networking"),
66
	"asn" => gettext("ASN encoding"),
67
	"enc" => gettext("Message encoding"),
68
	"imc" => gettext("Integrity checker"),
69
	"imv" => gettext("Integrity Verifier"),
70
	"pts" => gettext("Platform Trust Service"),
71
	"tls" => gettext("TLS handler"),
72
	"esp" => gettext("IPsec traffic"),
73
	"lib" => gettext("StrongSwan Lib")
74
);
75

    
76
global $ipsec_identifier_list;
77
$ipsec_identifier_list = array(
78
	// 'ipv4' => array('desc' => gettext('IPv4 address'), 'mobile' => true),
79
	// 'ipv6' => array('desc' => gettext('IPv6 address'), 'mobile' => true),
80
	// 'rfc822' => array('desc' => gettext('RFC822'), 'mobile' => true),
81
	'none' => array('desc' => '', 'mobile' => true),
82
	'email' => array('desc' => gettext('E-mail address'), 'mobile' => true),
83
	'userfqdn' => array('desc' => gettext('User Fully Qualified Domain Name'), 'mobile' => true)
84
	// 'fqdn' => array('desc' => gettext('Fully Qualified Domain Name'), 'mobile' => true),
85
	// 'dns' => array('desc' => gettext('DNS'), 'mobile' => true),
86
	// 'asn1dn' => array('desc' => gettext('ASN.1 Distinguished Name'), 'mobile' => true),
87
	// 'asn1gn' => array('desc' => gettext('ASN.1 GN'), 'mobile' => true),
88
	// 'keyid' => array('desc' => gettext('KeyID'), 'mobile' => true)
89
);
90

    
91
global $my_identifier_list;
92
$my_identifier_list = array(
93
	'myaddress' => array('desc' => gettext('My IP address'), 'mobile' => true),
94
	'address' => array('desc' => gettext('IP address'), 'mobile' => true),
95
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
96
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
97
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
98
	'keyid tag' => array('desc' => gettext('KeyID tag'), 'mobile' => true),
99
	'dyn_dns' => array('desc' => gettext('Dynamic DNS'), 'mobile' => true)
100
);
101

    
102
global $peer_identifier_list;
103
$peer_identifier_list = array(
104
	'any' => array('desc' => gettext('Any'), 'mobile' => true),
105
	'peeraddress' => array('desc' => gettext('Peer IP address'), 'mobile' => false),
106
	'address' => array('desc' => gettext('IP address'), 'mobile' => false),
107
	'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
108
	'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
109
	'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
110
	'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true)
111
);
112

    
113
global $ipsec_idhandling;
114
$ipsec_idhandling = array(
115
	'yes' => 'YES', 'no' => 'NO', 'never' => 'NEVER', 'keep' => 'KEEP'
116
);
117

    
118
global $p1_ealgos;
119
$p1_ealgos = array(
120
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
121
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
122
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
123
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
124
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
125
	'3des' => array('name' => '3DES'),
126
	'cast128' => array('name' => 'CAST128')
127
);
128

    
129
global $p2_ealgos;
130
$p2_ealgos = array(
131
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
132
	'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
133
	'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
134
	'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
135
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
136
	'3des' => array('name' => '3DES'),
137
	'cast128' => array('name' => 'CAST128')
138
);
139

    
140
global $p1_halgos;
141
$p1_halgos = array(
142
	'md5' => 'MD5',
143
	'sha1' => 'SHA1',
144
	'sha256' => 'SHA256',
145
	'sha384' => 'SHA384',
146
	'sha512' => 'SHA512',
147
	'aesxcbc' => 'AES-XCBC'
148
);
149

    
150
global $p1_dhgroups;
151
$p1_dhgroups = array(
152
	1  => '1 (768 bit)',
153
	2  => '2 (1024 bit)',
154
	5  => '5 (1536 bit)',
155
	14 => '14 (2048 bit)',
156
	15 => '15 (3072 bit)',
157
	16 => '16 (4096 bit)',
158
	17 => '17 (6144 bit)',
159
	18 => '18 (8192 bit)',
160
	19 => '19 (nist ecp256)',
161
	20 => '20 (nist ecp384)',
162
	21 => '21 (nist ecp521)',
163
	22 => '22 (1024(sub 160) bit)',
164
	23 => '23 (2048(sub 224) bit)',
165
	24 => '24 (2048(sub 256) bit)',
166
	28 => '28 (brainpool ecp256)',
167
	29 => '29 (brainpool ecp384)',
168
	30 => '30 (brainpool ecp512)',
169
	31 => '31 (Elliptic Curve 25519, 256 bit)',
170
	32 => '32 (Elliptic Curve 25519, 448 bit)',
171
);
172

    
173
global $p2_halgos;
174
$p2_halgos = array(
175
	'hmac_md5' => 'MD5',
176
	'hmac_sha1' => 'SHA1',
177
	'hmac_sha256' => 'SHA256',
178
	'hmac_sha384' => 'SHA384',
179
	'hmac_sha512' => 'SHA512',
180
	'aesxcbc' => 'AES-XCBC'
181
);
182

    
183
global $p1_authentication_methods;
184
$p1_authentication_methods = array(
185
	'hybrid_rsa_server' => array('name' => gettext('Hybrid RSA + Xauth'), 'mobile' => true),
186
	'xauth_rsa_server' => array('name' => gettext('Mutual RSA + Xauth'), 'mobile' => true),
187
	'xauth_psk_server' => array('name' => gettext('Mutual PSK + Xauth'), 'mobile' => true),
188
	'eap-tls' => array('name' => gettext('EAP-TLS'), 'mobile' => true),
189
	'eap-radius' => array('name' => gettext('EAP-RADIUS'), 'mobile' => true),
190
	'eap-mschapv2' => array('name' => gettext('EAP-MSChapv2'), 'mobile' => true),
191
	'rsasig' => array('name' => gettext('Mutual RSA'), 'mobile' => false),
192
	'pre_shared_key' => array('name' => gettext('Mutual PSK'), 'mobile' => false)
193
);
194

    
195
global $ipsec_preshared_key_type;
196
$ipsec_preshared_key_type = array(
197
	'PSK' => 'PSK',
198
	'EAP' => 'EAP'
199
);
200

    
201
global $p2_modes;
202
$p2_modes = array(
203
	'tunnel' => gettext('Tunnel IPv4'),
204
	'tunnel6' => gettext('Tunnel IPv6'),
205
	'transport' => gettext('Transport'),
206
	'vti' => gettext('Routed (VTI)')
207
);
208

    
209
global $p2_protos;
210
$p2_protos = array(
211
	'esp' => 'ESP',
212
	'ah' => 'AH'
213
);
214

    
215
global $p2_pfskeygroups;
216
$p2_pfskeygroups = array(
217
	0 => gettext('off'),
218
	1  => gettext('1 (768 bit)'),
219
	2  => gettext('2 (1024 bit)'),
220
	5  => gettext('5 (1536 bit)'),
221
	14 => gettext('14 (2048 bit)'),
222
	15 => gettext('15 (3072 bit)'),
223
	16 => gettext('16 (4096 bit)'),
224
	17 => gettext('17 (6144 bit)'),
225
	18 => gettext('18 (8192 bit)'),
226
	19 => gettext('19 (nist ecp256)'),
227
	20 => gettext('20 (nist ecp384)'),
228
	21 => gettext('21 (nist ecp521)'),
229
	22 => gettext('22 (1024(sub 160) bit)'),
230
	23 => gettext('23 (2048(sub 224) bit)'),
231
	24 => gettext('24 (2048(sub 256) bit)'),
232
	28 => gettext('28 (brainpool ecp256)'),
233
	29 => gettext('29 (brainpool ecp384)'),
234
	30 => gettext('30 (brainpool ecp512)'),
235
	31 => gettext('31 (Elliptic Curve 25519, 256 bit)'),
236
	32 => gettext('32 (Elliptic Curve 25519, 448 bit)'),
237
);
238

    
239
function ipsec_enabled() {
240
	global $config;
241

    
242
	if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
243
		return false;
244
	}
245

    
246
	/* Check if we have at least one phase 1 entry. */
247
	if (!isset($config['ipsec']['phase1']) ||
248
	    !is_array($config['ipsec']['phase1']) ||
249
	    empty($config['ipsec']['phase1'])) {
250
		return false;
251
	}
252
	/* Check if at least one phase 1 entry is enabled. */
253
	foreach ($config['ipsec']['phase1'] as $phase1) {
254
		if (!isset($phase1['disabled'])) {
255
			return true;
256
		}
257
	}
258

    
259
	return false;
260
}
261

    
262
/*
263
 * ikeid management functions
264
 */
265

    
266
function ipsec_ikeid_used($ikeid) {
267
	global $config;
268

    
269
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
270
		if ($ikeid == $ph1ent['ikeid']) {
271
			return true;
272
		}
273
	}
274

    
275
	return false;
276
}
277

    
278
function ipsec_ikeid_next() {
279

    
280
	$ikeid = 1;
281
	while (ipsec_ikeid_used($ikeid)) {
282
		$ikeid++;
283
	}
284

    
285
	return $ikeid;
286
}
287

    
288
/*
289
 * Return phase1 local address
290
 */
291
function ipsec_get_phase1_src(& $ph1ent) {
292

    
293
	if ($ph1ent['interface']) {
294
		if (substr($ph1ent['interface'], 0, 4) == "_vip") {
295
			$if = $ph1ent['interface'];
296
		} else {
297
			$if = get_failover_interface($ph1ent['interface']);
298
		}
299
	} else {
300
		$if = "wan";
301
	}
302
	$ip6 = get_interface_ipv6($if);
303
	$ip4 = get_interface_ip($if);
304
	if ($ph1ent['protocol'] == "inet6") {
305
		$interfaceip = $ip6;
306
	} elseif ($ph1ent['protocol'] == "inet") {
307
		$interfaceip = $ip4;
308
	} elseif ($ph1ent['protocol'] == "both") {
309
		$ifips = array();
310
		if (!empty($ip4)) {
311
			$ifips[] = $ip4;
312
		}
313
		if (!empty($ip6)) {
314
			$ifips[] = $ip6;
315
		}
316
		$interfaceip = implode(',', $ifips);
317
	}
318

    
319
	return $interfaceip;
320
}
321

    
322
/*
323
 * Return phase1 local address
324
 */
325
function ipsec_get_phase1_dst(& $ph1ent) {
326
	global $g;
327

    
328
	if (empty($ph1ent['remote-gateway'])) {
329
		return false;
330
	}
331
	$rg = $ph1ent['remote-gateway'];
332
	if (!is_ipaddr($rg)) {
333
		if (!platform_booting()) {
334
			return resolve_retry($rg);
335
		}
336
	}
337
	if (!is_ipaddr($rg)) {
338
		return false;
339
	}
340

    
341
	return $rg;
342
}
343

    
344
/*
345
 * Return phase2 idinfo in cidr format
346
 */
347
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
348
	global $config;
349

    
350
	switch ($idinfo['type']) {
351
		case "address":
352
			if ($addrbits) {
353
				if ($mode == "tunnel6") {
354
					return $idinfo['address']."/128";
355
				} else {
356
					return $idinfo['address']."/32";
357
				}
358
			} else {
359
				return $idinfo['address'];
360
			}
361
			break; /* NOTREACHED */
362
		case "network":
363
			return "{$idinfo['address']}/{$idinfo['netbits']}";
364
			break; /* NOTREACHED */
365
		case "none":
366
		case "mobile":
367
			return '0.0.0.0/0';
368
			break; /* NOTREACHED */
369
		default:
370
			if (empty($mode) && !empty($idinfo['mode'])) {
371
				$mode = $idinfo['mode'];
372
			}
373

    
374
			if ($mode == "tunnel6") {
375
				$address = get_interface_ipv6($idinfo['type']);
376
				$netbits = get_interface_subnetv6($idinfo['type']);
377
				$address = gen_subnetv6($address, $netbits);
378
				return "{$address}/{$netbits}";
379
			} else {
380
				$address = get_interface_ip($idinfo['type']);
381
				$netbits = get_interface_subnet($idinfo['type']);
382
				$address = gen_subnet($address, $netbits);
383
				return "{$address}/{$netbits}";
384
			}
385
			break; /* NOTREACHED */
386
	}
387
}
388

    
389
/*
390
 * Return phase2 idinfo in address/netmask format
391
 */
392
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
393
	global $config;
394

    
395
	switch ($idinfo['type']) {
396
		case "address":
397
			if ($addrbits) {
398
				if ($idinfo['mode'] == "tunnel6") {
399
					return $idinfo['address']."/128";
400
				} else {
401
					return $idinfo['address']."/255.255.255.255";
402
				}
403
			} else {
404
				return $idinfo['address'];
405
			}
406
			break; /* NOTREACHED */
407
		case "none":
408
		case "network":
409
			return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
410
			break; /* NOTREACHED */
411
		case "mobile":
412
			return "0.0.0.0/0";
413
			break; /* NOTREACHED */
414
		default:
415
			if ($idinfo['mode'] == "tunnel6") {
416
				$address = get_interface_ipv6($idinfo['type']);
417
				$netbits = get_interface_subnetv6($idinfo['type']);
418
				$address = gen_subnetv6($address, $netbits);
419
				return $address."/".$netbits;
420
			} else {
421
				$address = get_interface_ip($idinfo['type']);
422
				$netbits = get_interface_subnet($idinfo['type']);
423
				$address = gen_subnet($address, $netbits);
424
				return $address."/".$netbits;
425
			}
426
			break; /* NOTREACHED */
427
	}
428
}
429

    
430
/*
431
 *  Return phase2 idinfo in text format
432
 */
433
function ipsec_idinfo_to_text(& $idinfo) {
434
	global $config;
435

    
436
	switch ($idinfo['type']) {
437
		case "address":
438
			return $idinfo['address'];
439
			break; /* NOTREACHED */
440
		case "network":
441
			return $idinfo['address']."/".$idinfo['netbits'];
442
			break; /* NOTREACHED */
443
		case "mobile":
444
			return gettext("Mobile Client");
445
			break; /* NOTREACHED */
446
		case "none":
447
			return gettext("None");
448
			break; /* NOTREACHED */
449
		default:
450
			if (!empty($config['interfaces'][$idinfo['type']])) {
451
				return convert_friendly_interface_to_friendly_descr($idinfo['type']);
452
			} else {
453
				return strtoupper($idinfo['type']);
454
			}
455
			break; /* NOTREACHED */
456
	}
457
}
458

    
459
/*
460
 * Return phase1 association for phase2
461
 */
462
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
463
	global $config;
464

    
465
	if (!is_array($config['ipsec'])) {
466
		return false;
467
	}
468
	if (!is_array($config['ipsec']['phase1'])) {
469
		return false;
470
	}
471
	if (empty($config['ipsec']['phase1'])) {
472
		return false;
473
	}
474

    
475
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
476
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
477
			$ph1ent = $ph1tmp;
478
			return $ph1ent;
479
		}
480
	}
481

    
482
	return false;
483
}
484

    
485
/*
486
 * Check phase1 communications status
487
 */
488
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
489

    
490
	foreach ($ipsec_status as $ike) {
491
		if ($ike['id'] == $ikeid) {
492
			if ($ike['status'] == 'established') {
493
				return true;
494
			}
495
		}
496
	}
497

    
498
	return false;
499
}
500

    
501
/*
502
 * Check phase2 communications status
503
 */
504
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
505

    
506
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
507
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
508
	}
509

    
510
	return false;
511
}
512

    
513
/*
514
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
515
 */
516
function ipsec_list_sa() {
517

    
518
	if (ipsec_enabled()) {
519
		return pfSense_ipsec_list_sa();
520
	}
521

    
522
	return array();
523
}
524

    
525
/*
526
 * Return dump of SPD table
527
 */
528
function ipsec_dump_spd() {
529
	$fd = @popen("/sbin/setkey -DP", "r");
530
	$spd = array();
531
	if ($fd) {
532
		while (!feof($fd)) {
533
			$line = chop(fgets($fd));
534
			if (!$line) {
535
				continue;
536
			}
537
			if ($line == "No SPD entries.") {
538
				break;
539
			}
540
			if ($line[0] != "\t") {
541
				if (is_array($cursp)) {
542
					$spd[] = $cursp;
543
				}
544
				$cursp = array();
545
				$linea = explode(" ", $line);
546
				$cursp['srcid'] = substr($linea[0], 0, strpos($linea[0], "["));
547
				$cursp['dstid'] = substr($linea[1], 0, strpos($linea[1], "["));
548
				$i = 0;
549
			} else if (is_array($cursp)) {
550
				$line = trim($line, "\t\r\n ");
551
				$linea = explode(" ", $line);
552
				switch ($i) {
553
					case 1:
554
						if ($linea[1] == "none")	/* don't show default anti-lockout rule */ {
555
							unset($cursp);
556
						} else {
557
							$cursp['dir'] = $linea[0];
558
						}
559
						break;
560
					case 2:
561
						$upperspec = explode("/", $linea[0]);
562
						$cursp['proto'] = $upperspec[0];
563
						list($cursp['src'], $cursp['dst']) = explode("-", $upperspec[2]);
564
						$cursp['reqid'] = substr($upperspec[3], strpos($upperspec[3], "#")+1);
565
						break;
566
				}
567
			}
568
			$i++;
569
		}
570
		if (is_array($cursp) && count($cursp)) {
571
			$spd[] = $cursp;
572
		}
573
		pclose($fd);
574
	}
575

    
576
	return $spd;
577
}
578

    
579
/*
580
 * Return dump of SAD table
581
 */
582
function ipsec_dump_sad() {
583
	$fd = @popen("/sbin/setkey -D", "r");
584
	$sad = array();
585
	if ($fd) {
586
		while (!feof($fd)) {
587
			$line = chop(fgets($fd));
588
			if (!$line || $line[0] == " ") {
589
				continue;
590
			}
591
			if ($line == "No SAD entries.") {
592
				break;
593
			}
594
			if ($line[0] != "\t") {
595
				if (is_array($cursa)) {
596
					$sad[] = $cursa;
597
				}
598
				$cursa = array();
599
				list($cursa['src'], $cursa['dst']) = explode(" ", $line);
600
			} else {
601
				$line = trim($line, "\t\n\r ");
602
				$linea = explode(" ", $line);
603
				foreach ($linea as $idx => $linee) {
604
					if ($linee == 'esp' || $linee == 'ah' || $linee[0] == '#') {
605
						$cursa['proto'] = $linee;
606
					} else if (substr($linee, 0, 3) == 'spi') {
607
						$cursa['spi'] = substr($linee, strpos($linee, 'x') + 1, -1);
608
					} else if (substr($linee, 0, 5) == 'reqid') {
609
						$cursa['reqid'] = substr($linee, strpos($linee, 'x') + 1, -1);
610
					} else if (substr($linee, 0, 2) == 'E:') {
611
						$cursa['ealgo'] = $linea[$idx + 1];
612
						break;
613
					} else if (substr($linee, 0, 2) == 'A:') {
614
						$cursa['aalgo'] = $linea[$idx + 1];
615
						break;
616
					} else if (substr($linee, 0, 8) == 'current:') {
617
						$cursa['data'] = substr($linea[$idx + 1], 0, strpos($linea[$idx + 1], 'bytes') - 1) . ' B';
618
						break;
619
					}
620
				}
621
			}
622
		}
623
		if (is_array($cursa) && count($cursa)) {
624
			$sad[] = $cursa;
625
		}
626
		pclose($fd);
627
	}
628

    
629
	return $sad;
630
}
631

    
632
/*
633
 * Return dump of mobile user list
634
 */
635
function ipsec_dump_mobile() {
636
	global $g, $config;
637

    
638
	if(!isset($config['ipsec']['client']['enable'])) {
639
		return array();
640
	}
641

    
642
	$_gb = exec("/usr/local/sbin/ipsec leases 2>/dev/null", $output, $rc);
643

    
644
	if ($rc != 0) {
645
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
646
		return array();
647
	}
648

    
649
	$response = array();
650
	$id = -1;
651

    
652
	/* Leases in pool '10.7.200.0/24', usage: 1/254, 1 online */
653
	$lease_regex='/^Leases *in *pool *\'(?P<name>.+)\', *usage: *(?P<usage>\d+)\/(?P<size>\d+), *(?P<online>\d+) *online/';
654
	/* 10.7.200.1   online   'jimp' */
655
	$pool_regex='/\s*(?P<host>[\d\.]+)\s+(?P<status>online|offline)\s+\'(?P<id>.*)\'/';
656
	/* no matching leases found */
657
	$nopool_regex='/no *matching *leases *found/';
658

    
659
	$lease=false;
660
	foreach ($output as $line) {
661
		if (preg_match($lease_regex, $line, $matches)) {
662
			$id++;
663
			$response['pool'][$id] = array(
664
			    'name'   => $matches['name'],
665
			    'usage'  => $matches['usage'],
666
			    'size'   => $matches['size'],
667
			    'online' => $matches['online'],
668
			);
669
			$lease=true;
670
		} else if ($lease) {
671
			if (preg_match($nopool_regex, $line)) {
672
				$response['pool'][$id]['lease'][] = array();
673
				$lease=false;
674
			} else if (preg_match($pool_regex, $line, $matches)) {
675
				$response['pool'][$id]['lease'][] = array(
676
				    'host'   => $matches['host'],
677
				    'status' => $matches['status'],
678
				    'id'     => $matches['id']
679
				);
680
			}
681
		}
682
	}
683

    
684
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
685
	    $nopool_regex);
686

    
687
	return $response;
688
}
689

    
690
function ipsec_mobilekey_sort() {
691
	global $config;
692

    
693
	function mobilekeycmp($a, $b) {
694
		return strcmp($a['ident'][0], $b['ident'][0]);
695
	}
696

    
697
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
698
}
699

    
700
function ipsec_get_number_of_phase2($ikeid) {
701
	global $config;
702
	$a_phase2 = $config['ipsec']['phase2'];
703

    
704
	$nbph2 = 0;
705

    
706
	if (is_array($a_phase2) && count($a_phase2)) {
707
		foreach ($a_phase2 as $ph2tmp) {
708
			if ($ph2tmp['ikeid'] == $ikeid) {
709
				$nbph2++;
710
			}
711
		}
712
	}
713

    
714
	return $nbph2;
715
}
716

    
717
function ipsec_get_descr($ikeid) {
718
	global $config;
719

    
720
	if (!isset($config['ipsec']['phase1']) ||
721
	    !is_array($config['ipsec']['phase1'])) {
722
		return '';
723
	}
724

    
725
	foreach ($config['ipsec']['phase1'] as $p1) {
726
		if ($p1['ikeid'] == $ikeid) {
727
			return $p1['descr'];
728
		}
729
	}
730

    
731
	return '';
732
}
733

    
734
function ipsec_get_phase1($ikeid) {
735
		global $config;
736

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

    
742
		$a_phase1 = $config['ipsec']['phase1'];
743
		foreach ($a_phase1 as $p1) {
744
			if ($p1['ikeid'] == $ikeid) {
745
				return $p1;
746
			}
747
		}
748
		unset($a_phase1);
749
}
750

    
751
function ipsec_fixup_ip($ipaddr) {
752
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
753
		return text_to_compressed_ip6($ipaddr);
754
	} else {
755
		return $ipaddr;
756
	}
757
}
758

    
759
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
760
	if ($side == "local") {
761
		$id_type = $ph1ent['myid_type'];
762
		$id_data = $ph1ent['myid_data'];
763

    
764
		$addr = ipsec_get_phase1_src($ph1ent);
765
		if (!$addr) {
766
			return array();
767
		}
768
		/* When automatically guessing, use the first address. */
769
		$addr = explode(',', $addr);
770
		$addr = $addr[0];
771
	} elseif ($side == "peer") {
772
		$id_type = $ph1ent['peerid_type'];
773
		$id_data = $ph1ent['peerid_data'];
774

    
775
		if (isset($ph1ent['mobile'])) {
776
			$addr = "%any";
777
		} else {
778
			$addr = $ph1ent['remote-gateway'];
779
		}
780
	} else {
781
		return array();
782
	}
783

    
784

    
785
	$thisid_type = $id_type;
786
	switch ($thisid_type) {
787
		case 'myaddress':
788
			$thisid_type = 'address';
789
			$thisid_data = $addr;
790
			break;
791
		case 'dyn_dns':
792
			$thisid_type = 'dns';
793
			$thisid_data = $id_data;
794
			break;
795
		case 'peeraddress':
796
			$thisid_type = 'address';
797
			$thisid_data = $rgmap[$ph1ent['remote-gateway']];
798
			break;
799
		case 'address':
800
			$thisid_data = $id_data;
801
			break;
802
		case 'fqdn':
803
			$thisid_data = "{$id_data}";
804
			break;
805
		case 'keyid tag':
806
			$thisid_type = 'keyid';
807
			$thisid_data = "{$id_data}";
808
			break;
809
		case 'user_fqdn':
810
			$thisid_type = 'userfqdn';
811
			$thisid_data = "{$id_data}";
812
			break;
813
		case 'asn1dn':
814
			$thisid_data = $id_data;
815
			break;
816
	}
817
	return array($thisid_type, $thisid_data);
818
}
819

    
820
function ipsec_fixup_network($network) {
821
	if (substr($network, -3) == '|/0') {
822
		$result = substr($network, 0, -3);
823
	} else {
824
		$tmp = explode('|', $network);
825
		if (isset($tmp[1])) {
826
			$result = $tmp[1];
827
		} else {
828
			$result = $tmp[0];
829
		}
830
		unset($tmp);
831
	}
832

    
833
	return $result;
834
}
835

    
836
function ipsec_new_reqid() {
837
	global $config;
838

    
839
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
840
		return;
841
	}
842

    
843
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
844
	$keyids = array();
845
	$keyid = 1;
846
	foreach ($config['ipsec']['phase2'] as $ph2) {
847
		$keyids[$ph2['reqid']] = $ph2['reqid'];
848
	}
849

    
850
	for ($i = 1; $i < 16000; $i++) {
851
		if (!isset($keyids[$i])) {
852
			$keyid = $i;
853
			break;
854
		}
855
	}
856
	unlock($ipsecreqid);
857

    
858
	return $keyid;
859
}
860

    
861
function ipsec_get_loglevels() {
862
	global $config, $ipsec_log_cats;
863
	$def_loglevel = '1';
864

    
865
	$levels = array();
866

    
867
	foreach (array_keys($ipsec_log_cats) as $cat) {
868
		if (isset($config['ipsec']['logging'][$cat])) {
869
			$levels[$cat] = $config['ipsec']['logging'][$cat];
870
		} elseif (in_array($cat, array('ike', 'chd', 'cfg'))) {
871
			$levels[$cat] = "2";
872
		} else {
873
			$levels[$cat] = $def_loglevel;
874
		}
875
	}
876
	return $levels;
877
}
878

    
879
function ipsec_vti($ph1ent, $returnaddresses = false) {
880
	global $config;
881
	if (empty($ph1ent) || !is_array($ph1ent) || !is_array($config['ipsec']['phase2'])) {
882
		return false;
883
	}
884

    
885
	$is_vti = false;
886
	$vtisubnet_spec = array();
887

    
888
	foreach ($config['ipsec']['phase2'] as $ph2ent) {
889
		if ($ph1ent['ikeid'] != $ph2ent['ikeid']) {
890
			continue;
891
		}
892
		if ($ph2ent['mode'] == 'vti') {
893
			if ($returnaddresses) {
894
				$vtisubnet_spec[] = array(
895
					'left' => ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']),
896
					'right' => ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']),
897
					'descr' => $ph2ent['descr'],
898
				);
899
			}
900
			$is_vti = true;
901
		}
902
	}
903
	return ($returnaddresses) ? $vtisubnet_spec : $is_vti;
904
}
905

    
906
?>
(27-27/59)