Project

General

Profile

Download (24.6 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-2019 Rubicon Communications, LLC (Netgate)
8
 * All rights reserved.
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 * http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
200
global $ipsec_closeactions;
201
$ipsec_closeactions = array(
202
	'' => gettext('Default'),
203
	'none' => gettext('No action'),
204
	'restart' => gettext('Restart/Reconnect'),
205
	'clear' => gettext('Close connection and clear SA'),
206
	'hold' => gettext('Close connection and reconnect on demand'),
207
);
208

    
209
global $p2_modes;
210
$p2_modes = array(
211
	'tunnel' => gettext('Tunnel IPv4'),
212
	'tunnel6' => gettext('Tunnel IPv6'),
213
	'transport' => gettext('Transport'),
214
	'vti' => gettext('Routed (VTI)')
215
);
216

    
217
global $p2_protos;
218
$p2_protos = array(
219
	'esp' => 'ESP',
220
	'ah' => 'AH'
221
);
222

    
223
global $p2_pfskeygroups;
224
$p2_pfskeygroups = array(
225
	0 => gettext('off'),
226
	1  => gettext('1 (768 bit)'),
227
	2  => gettext('2 (1024 bit)'),
228
	5  => gettext('5 (1536 bit)'),
229
	14 => gettext('14 (2048 bit)'),
230
	15 => gettext('15 (3072 bit)'),
231
	16 => gettext('16 (4096 bit)'),
232
	17 => gettext('17 (6144 bit)'),
233
	18 => gettext('18 (8192 bit)'),
234
	19 => gettext('19 (nist ecp256)'),
235
	20 => gettext('20 (nist ecp384)'),
236
	21 => gettext('21 (nist ecp521)'),
237
	22 => gettext('22 (1024(sub 160) bit)'),
238
	23 => gettext('23 (2048(sub 224) bit)'),
239
	24 => gettext('24 (2048(sub 256) bit)'),
240
	25 => gettext('25 (nist ecp192)'),
241
	26 => gettext('26 (nist ecp224)'),
242
	27 => gettext('27 (brainpool ecp224)'),
243
	28 => gettext('28 (brainpool ecp256)'),
244
	29 => gettext('29 (brainpool ecp384)'),
245
	30 => gettext('30 (brainpool ecp512)')
246
);
247

    
248
function ipsec_enabled() {
249
	global $config;
250

    
251
	if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
252
		return false;
253
	}
254

    
255
	/* Check if we have at least one phase 1 entry. */
256
	if (!isset($config['ipsec']['phase1']) ||
257
	    !is_array($config['ipsec']['phase1']) ||
258
	    empty($config['ipsec']['phase1'])) {
259
		return false;
260
	}
261
	/* Check if at least one phase 1 entry is enabled. */
262
	foreach ($config['ipsec']['phase1'] as $phase1) {
263
		if (!isset($phase1['disabled'])) {
264
			return true;
265
		}
266
	}
267

    
268
	return false;
269
}
270

    
271
/*
272
 * ikeid management functions
273
 */
274

    
275
function ipsec_ikeid_used($ikeid) {
276
	global $config;
277

    
278
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
279
		if ($ikeid == $ph1ent['ikeid']) {
280
			return true;
281
		}
282
	}
283

    
284
	return false;
285
}
286

    
287
function ipsec_ikeid_next() {
288

    
289
	$ikeid = 1;
290
	while (ipsec_ikeid_used($ikeid)) {
291
		$ikeid++;
292
	}
293

    
294
	return $ikeid;
295
}
296

    
297
/*
298
 * Return phase1 local address
299
 */
300
function ipsec_get_phase1_src(& $ph1ent) {
301

    
302
	if ($ph1ent['interface']) {
303
		if (substr($ph1ent['interface'], 0, 4) == "_vip") {
304
			$if = $ph1ent['interface'];
305
		} else {
306
			$if = get_failover_interface($ph1ent['interface']);
307
		}
308
	} else {
309
		$if = "wan";
310
	}
311
	$ip6 = get_interface_ipv6($if);
312
	$ip4 = get_interface_ip($if);
313
	if ($ph1ent['protocol'] == "inet6") {
314
		$interfaceip = $ip6;
315
	} elseif ($ph1ent['protocol'] == "inet") {
316
		$interfaceip = $ip4;
317
	} elseif ($ph1ent['protocol'] == "both") {
318
		$ifips = array();
319
		if (!empty($ip4)) {
320
			$ifips[] = $ip4;
321
		}
322
		if (!empty($ip6)) {
323
			$ifips[] = $ip6;
324
		}
325
		$interfaceip = implode(',', $ifips);
326
	}
327

    
328
	return $interfaceip;
329
}
330

    
331
/*
332
 * Return phase1 local address
333
 */
334
function ipsec_get_phase1_dst(& $ph1ent) {
335
	global $g;
336

    
337
	if (empty($ph1ent['remote-gateway'])) {
338
		return false;
339
	}
340
	$rg = $ph1ent['remote-gateway'];
341
	if (!is_ipaddr($rg)) {
342
		if (!platform_booting()) {
343
			return resolve_retry($rg);
344
		}
345
	}
346
	if (!is_ipaddr($rg)) {
347
		return false;
348
	}
349

    
350
	return $rg;
351
}
352

    
353
/*
354
 * Return phase2 idinfo in cidr format
355
 */
356
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
357
	global $config;
358

    
359
	switch ($idinfo['type']) {
360
		case "address":
361
			if ($addrbits) {
362
				if ($mode == "tunnel6") {
363
					return $idinfo['address']."/128";
364
				} else {
365
					return $idinfo['address']."/32";
366
				}
367
			} else {
368
				return $idinfo['address'];
369
			}
370
			break; /* NOTREACHED */
371
		case "network":
372
			return "{$idinfo['address']}/{$idinfo['netbits']}";
373
			break; /* NOTREACHED */
374
		case "none":
375
		case "mobile":
376
			return '0.0.0.0/0';
377
			break; /* NOTREACHED */
378
		default:
379
			if (empty($mode) && !empty($idinfo['mode'])) {
380
				$mode = $idinfo['mode'];
381
			}
382

    
383
			if ($mode == "tunnel6") {
384
				$address = get_interface_ipv6($idinfo['type']);
385
				$netbits = get_interface_subnetv6($idinfo['type']);
386
				$address = gen_subnetv6($address, $netbits);
387
				return "{$address}/{$netbits}";
388
			} else {
389
				$address = get_interface_ip($idinfo['type']);
390
				$netbits = get_interface_subnet($idinfo['type']);
391
				$address = gen_subnet($address, $netbits);
392
				return "{$address}/{$netbits}";
393
			}
394
			break; /* NOTREACHED */
395
	}
396
}
397

    
398
/*
399
 * Return phase2 idinfo in address/netmask format
400
 */
401
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
402
	global $config;
403

    
404
	switch ($idinfo['type']) {
405
		case "address":
406
			if ($addrbits) {
407
				if ($idinfo['mode'] == "tunnel6") {
408
					return $idinfo['address']."/128";
409
				} else {
410
					return $idinfo['address']."/255.255.255.255";
411
				}
412
			} else {
413
				return $idinfo['address'];
414
			}
415
			break; /* NOTREACHED */
416
		case "none":
417
		case "network":
418
			return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
419
			break; /* NOTREACHED */
420
		case "mobile":
421
			return "0.0.0.0/0";
422
			break; /* NOTREACHED */
423
		default:
424
			if ($idinfo['mode'] == "tunnel6") {
425
				$address = get_interface_ipv6($idinfo['type']);
426
				$netbits = get_interface_subnetv6($idinfo['type']);
427
				$address = gen_subnetv6($address, $netbits);
428
				return $address."/".$netbits;
429
			} else {
430
				$address = get_interface_ip($idinfo['type']);
431
				$netbits = get_interface_subnet($idinfo['type']);
432
				$address = gen_subnet($address, $netbits);
433
				return $address."/".$netbits;
434
			}
435
			break; /* NOTREACHED */
436
	}
437
}
438

    
439
/*
440
 *  Return phase2 idinfo in text format
441
 */
442
function ipsec_idinfo_to_text(& $idinfo) {
443
	global $config;
444

    
445
	switch ($idinfo['type']) {
446
		case "address":
447
			return $idinfo['address'];
448
			break; /* NOTREACHED */
449
		case "network":
450
			return $idinfo['address']."/".$idinfo['netbits'];
451
			break; /* NOTREACHED */
452
		case "mobile":
453
			return gettext("Mobile Client");
454
			break; /* NOTREACHED */
455
		case "none":
456
			return gettext("None");
457
			break; /* NOTREACHED */
458
		default:
459
			if (!empty($config['interfaces'][$idinfo['type']])) {
460
				return convert_friendly_interface_to_friendly_descr($idinfo['type']);
461
			} else {
462
				return strtoupper($idinfo['type']);
463
			}
464
			break; /* NOTREACHED */
465
	}
466
}
467

    
468
/*
469
 * Return phase1 association for phase2
470
 */
471
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
472
	global $config;
473

    
474
	if (!is_array($config['ipsec'])) {
475
		return false;
476
	}
477
	if (!is_array($config['ipsec']['phase1'])) {
478
		return false;
479
	}
480
	if (empty($config['ipsec']['phase1'])) {
481
		return false;
482
	}
483

    
484
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
485
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
486
			$ph1ent = $ph1tmp;
487
			return $ph1ent;
488
		}
489
	}
490

    
491
	return false;
492
}
493

    
494
/*
495
 * Check phase1 communications status
496
 */
497
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
498

    
499
	foreach ($ipsec_status as $ike) {
500
		if ($ike['id'] == $ikeid) {
501
			if ($ike['status'] == 'established') {
502
				return true;
503
			}
504
		}
505
	}
506

    
507
	return false;
508
}
509

    
510
/*
511
 * Check phase2 communications status
512
 */
513
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
514

    
515
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
516
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
517
	}
518

    
519
	return false;
520
}
521

    
522
/*
523
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
524
 */
525
function ipsec_list_sa() {
526

    
527
	if (ipsec_enabled()) {
528
		return pfSense_ipsec_list_sa();
529
	}
530

    
531
	return array();
532
}
533

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

    
585
	return $spd;
586
}
587

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

    
638
	return $sad;
639
}
640

    
641
/*
642
 * Return dump of mobile user list
643
 */
644
function ipsec_dump_mobile() {
645
	global $g, $config;
646

    
647
	if(!isset($config['ipsec']['client']['enable'])) {
648
		return array();
649
	}
650

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

    
653
	if ($rc != 0) {
654
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
655
		return array();
656
	}
657

    
658
	$response = array();
659
	$id = -1;
660

    
661
	/* Leases in pool '10.7.200.0/24', usage: 1/254, 1 online */
662
	$lease_regex='/^Leases *in *pool *\'(?P<name>.+)\', *usage: *(?P<usage>\d+)\/(?P<size>\d+), *(?P<online>\d+) *online/';
663
	/* 10.7.200.1   online   'jimp' */
664
	$pool_regex='/\s*(?P<host>[\d\.]+)\s+(?P<status>online|offline)\s+\'(?P<id>.*)\'/';
665
	/* no matching leases found */
666
	$nopool_regex='/no *matching *leases *found/';
667

    
668
	$lease=false;
669
	foreach ($output as $line) {
670
		if (preg_match($lease_regex, $line, $matches)) {
671
			$id++;
672
			$response['pool'][$id] = array(
673
			    'name'   => $matches['name'],
674
			    'usage'  => $matches['usage'],
675
			    'size'   => $matches['size'],
676
			    'online' => $matches['online'],
677
			);
678
			$lease=true;
679
		} else if ($lease) {
680
			if (preg_match($nopool_regex, $line)) {
681
				$response['pool'][$id]['lease'][] = array();
682
				$lease=false;
683
			} else if (preg_match($pool_regex, $line, $matches)) {
684
				$response['pool'][$id]['lease'][] = array(
685
				    'host'   => $matches['host'],
686
				    'status' => $matches['status'],
687
				    'id'     => $matches['id']
688
				);
689
			}
690
		}
691
	}
692

    
693
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
694
	    $nopool_regex);
695

    
696
	return $response;
697
}
698

    
699
function ipsec_mobilekey_sort() {
700
	global $config;
701

    
702
	function mobilekeycmp($a, $b) {
703
		return strcmp($a['ident'][0], $b['ident'][0]);
704
	}
705

    
706
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
707
}
708

    
709
function ipsec_get_number_of_phase2($ikeid) {
710
	global $config;
711
	$a_phase2 = $config['ipsec']['phase2'];
712

    
713
	$nbph2 = 0;
714

    
715
	if (is_array($a_phase2) && count($a_phase2)) {
716
		foreach ($a_phase2 as $ph2tmp) {
717
			if ($ph2tmp['ikeid'] == $ikeid) {
718
				$nbph2++;
719
			}
720
		}
721
	}
722

    
723
	return $nbph2;
724
}
725

    
726
function ipsec_get_descr($ikeid) {
727
	global $config;
728

    
729
	if (!isset($config['ipsec']['phase1']) ||
730
	    !is_array($config['ipsec']['phase1'])) {
731
		return '';
732
	}
733

    
734
	foreach ($config['ipsec']['phase1'] as $p1) {
735
		if ($p1['ikeid'] == $ikeid) {
736
			return $p1['descr'];
737
		}
738
	}
739

    
740
	return '';
741
}
742

    
743
function ipsec_get_phase1($ikeid) {
744
		global $config;
745

    
746
		if (!isset($config['ipsec']['phase1']) ||
747
		    !is_array($config['ipsec']['phase1'])) {
748
			return '';
749
		}
750

    
751
		$a_phase1 = $config['ipsec']['phase1'];
752
		foreach ($a_phase1 as $p1) {
753
			if ($p1['ikeid'] == $ikeid) {
754
				return $p1;
755
			}
756
		}
757
		unset($a_phase1);
758
}
759

    
760
function ipsec_fixup_ip($ipaddr) {
761
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
762
		return text_to_compressed_ip6($ipaddr);
763
	} else {
764
		return $ipaddr;
765
	}
766
}
767

    
768
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
769
	if ($side == "local") {
770
		$id_type = $ph1ent['myid_type'];
771
		$id_data = $ph1ent['myid_data'];
772

    
773
		$addr = ipsec_get_phase1_src($ph1ent);
774
		if (!$addr) {
775
			return array();
776
		}
777
		/* When automatically guessing, use the first address. */
778
		$addr = explode(',', $addr);
779
		$addr = $addr[0];
780
	} elseif ($side == "peer") {
781
		$id_type = $ph1ent['peerid_type'];
782
		$id_data = $ph1ent['peerid_data'];
783

    
784
		if (isset($ph1ent['mobile'])) {
785
			$addr = "%any";
786
		} else {
787
			$addr = $ph1ent['remote-gateway'];
788
		}
789
	} else {
790
		return array();
791
	}
792

    
793

    
794
	$thisid_type = $id_type;
795
	switch ($thisid_type) {
796
		case 'myaddress':
797
			$thisid_type = 'address';
798
			$thisid_data = $addr;
799
			break;
800
		case 'dyn_dns':
801
			$thisid_type = 'dns';
802
			$thisid_data = $id_data;
803
			break;
804
		case 'peeraddress':
805
			$thisid_type = 'address';
806
			$thisid_data = $rgmap[$ph1ent['remote-gateway']];
807
			break;
808
		case 'address':
809
			$thisid_data = $id_data;
810
			break;
811
		case 'fqdn':
812
			$thisid_data = "{$id_data}";
813
			break;
814
		case 'keyid tag':
815
			$thisid_type = 'keyid';
816
			$thisid_data = "{$id_data}";
817
			break;
818
		case 'user_fqdn':
819
			$thisid_type = 'userfqdn';
820
			$thisid_data = "{$id_data}";
821
			break;
822
		case 'asn1dn':
823
			$thisid_data = $id_data;
824
			break;
825
	}
826
	return array($thisid_type, $thisid_data);
827
}
828

    
829
/*
830
 * Fixup ID type/data to include prefix when necessary, add quotes, etc.
831
 */
832
function ipsec_fixup_id($type, $data) {
833
	/* List of types to pass through as-is without changes or adding prefix */
834
	$auto_types = array('address');
835
	/* List of types which need the resulting string double quoted. */
836
	$quote_types = array('keyid', 'asn1dn');
837

    
838
	/* If the first character of asn1dn type data is not #, then rely on
839
	 * automatic parsing https://redmine.pfsense.org/issues/4792 */
840
	if (($type == 'asn1dn') && !empty($data) && ($data[0] != '#')) {
841
		$auto_types[] = 'asn1dn';
842
	}
843

    
844
	if ($type == 'any') {
845
		$idstring = "";
846
	} elseif (!in_array($type, $auto_types)) {
847
		$idstring = "{$type}:{$data}";
848
	} else {
849
		$idstring = $data;
850
	}
851

    
852
	if (in_array($type, $quote_types)) {
853
		$idstring = "\"{$idstring}\"";
854
	}
855

    
856
	return $idstring;
857
}
858

    
859
function ipsec_fixup_network($network) {
860
	if (substr($network, -3) == '|/0') {
861
		$result = substr($network, 0, -3);
862
	} else {
863
		$tmp = explode('|', $network);
864
		if (isset($tmp[1])) {
865
			$result = $tmp[1];
866
		} else {
867
			$result = $tmp[0];
868
		}
869
		unset($tmp);
870
	}
871

    
872
	return $result;
873
}
874

    
875
function ipsec_new_reqid() {
876
	global $config;
877

    
878
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
879
		return;
880
	}
881

    
882
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
883
	$keyids = array();
884
	$keyid = 1;
885
	foreach ($config['ipsec']['phase2'] as $ph2) {
886
		$keyids[$ph2['reqid']] = $ph2['reqid'];
887
	}
888

    
889
	for ($i = 1; $i < 16000; $i++) {
890
		if (!isset($keyids[$i])) {
891
			$keyid = $i;
892
			break;
893
		}
894
	}
895
	unlock($ipsecreqid);
896

    
897
	return $keyid;
898
}
899

    
900
function ipsec_get_loglevels() {
901
	global $config, $ipsec_log_cats;
902
	$def_loglevel = '1';
903

    
904
	$levels = array();
905

    
906
	foreach (array_keys($ipsec_log_cats) as $cat) {
907
		if (isset($config['ipsec']['logging'][$cat])) {
908
			$levels[$cat] = $config['ipsec']['logging'][$cat];
909
		} elseif (in_array($cat, array('ike', 'chd', 'cfg'))) {
910
			$levels[$cat] = "2";
911
		} else {
912
			$levels[$cat] = $def_loglevel;
913
		}
914
	}
915
	return $levels;
916
}
917

    
918
function ipsec_vti($ph1ent, $returnaddresses = false) {
919
	global $config;
920
	if (empty($ph1ent) || !is_array($ph1ent) || !is_array($config['ipsec']['phase2'])) {
921
		return false;
922
	}
923

    
924
	$is_vti = false;
925
	$vtisubnet_spec = array();
926

    
927
	foreach ($config['ipsec']['phase2'] as $ph2ent) {
928
		if ($ph1ent['ikeid'] != $ph2ent['ikeid']) {
929
			continue;
930
		}
931
		if ($ph2ent['mode'] == 'vti') {
932
			if ($returnaddresses) {
933
				$vtisubnet_spec[] = array(
934
					'left' => ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']),
935
					'right' => ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']),
936
					'descr' => $ph2ent['descr'],
937
				);
938
			}
939
			$is_vti = true;
940
		}
941
	}
942
	return ($returnaddresses) ? $vtisubnet_spec : $is_vti;
943
}
944

    
945
/* Called when IPsec is reloaded through rc.newipsecdns and similar, gives
946
 * packages an opportunity to execute custom code when IPsec reloads.
947
 */
948
function ipsec_reload_package_hook() {
949
	global $g, $config;
950
	foreach ($config['installedpackages']['package'] as $package) {
951
		if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
952
			continue;
953
		}
954

    
955
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
956
		if (!empty($pkg_config['include_file']) &&
957
		    file_exists($pkg_config['include_file'])) {
958
			require_once($pkg_config['include_file']);
959
		}
960
		if (empty($pkg_config['ipsec_reload_function'])) {
961
			continue;
962
		}
963
		$pkg_ipsec_reload = $pkg_config['ipsec_reload_function'];
964
		if (!function_exists($pkg_ipsec_reload)) {
965
			continue;
966
		}
967
		$pkg_ipsec_reload();
968
	}
969
}
970

    
971
?>
(27-27/60)