Project

General

Profile

Download (24.7 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-2020 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
	31 => '31 (Elliptic Curve 25519, 256 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 $ipsec_closeactions;
202
$ipsec_closeactions = array(
203
	'' => gettext('Default'),
204
	'none' => gettext('No action'),
205
	'restart' => gettext('Restart/Reconnect'),
206
	'clear' => gettext('Close connection and clear SA'),
207
	'hold' => gettext('Close connection and reconnect on demand'),
208
);
209

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

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

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

    
250
function ipsec_enabled() {
251
	global $config;
252

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

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

    
270
	return false;
271
}
272

    
273
/*
274
 * ikeid management functions
275
 */
276

    
277
function ipsec_ikeid_used($ikeid) {
278
	global $config;
279

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

    
286
	return false;
287
}
288

    
289
function ipsec_ikeid_next() {
290

    
291
	$ikeid = 1;
292
	while (ipsec_ikeid_used($ikeid)) {
293
		$ikeid++;
294
	}
295

    
296
	return $ikeid;
297
}
298

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

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

    
330
	return $interfaceip;
331
}
332

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

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

    
352
	return $rg;
353
}
354

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

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

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

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

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

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

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

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

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

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

    
493
	return false;
494
}
495

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

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

    
509
	return false;
510
}
511

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

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

    
521
	return false;
522
}
523

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

    
529
	if (ipsec_enabled()) {
530
		return pfSense_ipsec_list_sa();
531
	}
532

    
533
	return array();
534
}
535

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

    
587
	return $spd;
588
}
589

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

    
640
	return $sad;
641
}
642

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

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

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

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

    
660
	$response = array();
661
	$id = -1;
662

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

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

    
695
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
696
	    $nopool_regex);
697

    
698
	return $response;
699
}
700

    
701
function ipsec_mobilekey_sort() {
702
	global $config;
703

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

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

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

    
715
	$nbph2 = 0;
716

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

    
725
	return $nbph2;
726
}
727

    
728
function ipsec_get_descr($ikeid) {
729
	global $config;
730

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

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

    
742
	return '';
743
}
744

    
745
function ipsec_get_phase1($ikeid) {
746
		global $config;
747

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

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

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

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

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

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

    
795

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

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

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

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

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

    
858
	return $idstring;
859
}
860

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

    
874
	return $result;
875
}
876

    
877
function ipsec_new_reqid() {
878
	global $config;
879

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

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

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

    
899
	return $keyid;
900
}
901

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

    
906
	$levels = array();
907

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

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

    
926
	$is_vti = false;
927
	$vtisubnet_spec = array();
928

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

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

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

    
973
?>
(27-27/60)