Project

General

Profile

Download (22.5 KB) Statistics
| Branch: | Tag: | Revision:
1 a93e56c5 Matthew Grooms
<?php
2
/*
3 ac24dc24 Renato Botelho
 * ipsec.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6 c5d81585 Renato Botelho
 * Copyright (c) 2008 Shrew Soft Inc.
7 b8f91b7c Luiz Souza
 * Copyright (c) 2007-2018 Rubicon Communications, LLC (Netgate)
8 ac24dc24 Renato Botelho
 * All rights reserved.
9
 *
10 b12ea3fb Renato Botelho
 * 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 ac24dc24 Renato Botelho
 *
14 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
15 ac24dc24 Renato Botelho
 *
16 b12ea3fb Renato Botelho
 * 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 ac24dc24 Renato Botelho
 */
22 a93e56c5 Matthew Grooms
23 3462a529 Matthew Grooms
/* IPsec defines */
24 62657a7f jim-p
global $ipsec_loglevels;
25 e8c516a0 Phil Davis
$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 c6efc8fd Ermal
44 c53e411f Matt Smith
global $ipsec_log_sevs;
45
$ipsec_log_sevs = array(
46 e8c516a0 Phil Davis
	'-1' => gettext('Silent'),
47
	'0' => gettext('Audit'),
48
	'1' => gettext('Control'),
49
	'2' => gettext('Diag'),
50
	'3' => gettext('Raw'),
51
	'4' => gettext('Highest')
52 c53e411f Matt Smith
);
53
54
global $ipsec_log_cats;
55
$ipsec_log_cats = array(
56 e8c516a0 Phil Davis
	"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 c53e411f Matt Smith
);
73
74 8e461d38 Christian
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 62657a7f jim-p
global $my_identifier_list;
90 3462a529 Matthew Grooms
$my_identifier_list = array(
91 086cf944 Phil Davis
	'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 e8c516a0 Phil Davis
	'dyn_dns' => array('desc' => gettext('Dynamic DNS'), 'mobile' => true)
98
);
99 3462a529 Matthew Grooms
100 62657a7f jim-p
global $peer_identifier_list;
101 3462a529 Matthew Grooms
$peer_identifier_list = array(
102 b0994811 Chris Buechler
	'any' => array('desc' => gettext('Any'), 'mobile' => true),
103 086cf944 Phil Davis
	'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 e8c516a0 Phil Davis
	'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true)
109
);
110 3462a529 Matthew Grooms
111 62657a7f jim-p
global $ipsec_idhandling;
112 86e1846f Ermal LUÇI
$ipsec_idhandling = array(
113
	'yes' => 'YES', 'no' => 'NO', 'never' => 'NEVER', 'keep' => 'KEEP'
114 e8c516a0 Phil Davis
);
115 86e1846f Ermal LUÇI
116 62657a7f jim-p
global $p1_ealgos;
117 3462a529 Matthew Grooms
$p1_ealgos = array(
118 086cf944 Phil Davis
	'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
119 a46e0d74 Chris Buechler
	'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 086cf944 Phil Davis
	'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
123
	'3des' => array('name' => '3DES'),
124 e8c516a0 Phil Davis
	'cast128' => array('name' => 'CAST128')
125
);
126 3462a529 Matthew Grooms
127 62657a7f jim-p
global $p2_ealgos;
128 3462a529 Matthew Grooms
$p2_ealgos = array(
129 086cf944 Phil Davis
	'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 e8c516a0 Phil Davis
	'cast128' => array('name' => 'CAST128')
136
);
137 3462a529 Matthew Grooms
138 62657a7f jim-p
global $p1_halgos;
139 3462a529 Matthew Grooms
$p1_halgos = array(
140 665340db jim-p
	'md5' => 'MD5',
141 3462a529 Matthew Grooms
	'sha1' => 'SHA1',
142 665340db jim-p
	'sha256' => 'SHA256',
143
	'sha384' => 'SHA384',
144 b0cbebeb Ermal
	'sha512' => 'SHA512',
145
	'aesxcbc' => 'AES-XCBC'
146 665340db jim-p
);
147
148 62657a7f jim-p
global $p1_dhgroups;
149 665340db jim-p
$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 b0cbebeb Ermal
	18 => '18 (8192 bit)',
158 7a747654 Ermal LUÇI
	19 => '19 (nist ecp256)',
159
	20 => '20 (nist ecp384)',
160
	21 => '21 (nist ecp521)',
161 b0cbebeb Ermal
	22 => '22 (1024(sub 160) bit)',
162
	23 => '23 (2048(sub 224) bit)',
163 c55ec98a Bruno Thomsen
	24 => '24 (2048(sub 256) bit)',
164
	28 => '28 (brainpool ecp256)',
165
	29 => '29 (brainpool ecp384)',
166
	30 => '30 (brainpool ecp512)'
167 665340db jim-p
);
168 3462a529 Matthew Grooms
169 62657a7f jim-p
global $p2_halgos;
170 3462a529 Matthew Grooms
$p2_halgos = array(
171 665340db jim-p
	'hmac_md5' => 'MD5',
172 3462a529 Matthew Grooms
	'hmac_sha1' => 'SHA1',
173 665340db jim-p
	'hmac_sha256' => 'SHA256',
174
	'hmac_sha384' => 'SHA384',
175 b0cbebeb Ermal
	'hmac_sha512' => 'SHA512',
176
	'aesxcbc' => 'AES-XCBC'
177 665340db jim-p
);
178 3462a529 Matthew Grooms
179 62657a7f jim-p
global $p1_authentication_methods;
180 3462a529 Matthew Grooms
$p1_authentication_methods = array(
181 e8c516a0 Phil Davis
	'hybrid_rsa_server' => array('name' => gettext('Hybrid RSA + Xauth'), 'mobile' => true),
182
	'xauth_rsa_server' => array('name' => gettext('Mutual RSA + Xauth'), 'mobile' => true),
183
	'xauth_psk_server' => array('name' => gettext('Mutual PSK + Xauth'), 'mobile' => true),
184
	'eap-tls' => array('name' => gettext('EAP-TLS'), 'mobile' => true),
185
	'eap-radius' => array('name' => gettext('EAP-RADIUS'), 'mobile' => true),
186
	'eap-mschapv2' => array('name' => gettext('EAP-MSChapv2'), 'mobile' => true),
187
	'rsasig' => array('name' => gettext('Mutual RSA'), 'mobile' => false),
188
	'pre_shared_key' => array('name' => gettext('Mutual PSK'), 'mobile' => false)
189
);
190 3462a529 Matthew Grooms
191 62657a7f jim-p
global $ipsec_preshared_key_type;
192 10e2acb5 Ermal LUÇI
$ipsec_preshared_key_type = array(
193
	'PSK' => 'PSK',
194
	'EAP' => 'EAP'
195 e8c516a0 Phil Davis
);
196 10e2acb5 Ermal LUÇI
197 62657a7f jim-p
global $p2_modes;
198 4b96b367 mgrooms
$p2_modes = array(
199 e8c516a0 Phil Davis
	'tunnel' => gettext('Tunnel IPv4'),
200
	'tunnel6' => gettext('Tunnel IPv6'),
201 bd4c337c jim-p
	'transport' => gettext('Transport'),
202
	'vti' => gettext('Routed (VTI)')
203 e8c516a0 Phil Davis
);
204 4b96b367 mgrooms
205 62657a7f jim-p
global $p2_protos;
206 3462a529 Matthew Grooms
$p2_protos = array(
207
	'esp' => 'ESP',
208 e8c516a0 Phil Davis
	'ah' => 'AH'
209
);
210 3462a529 Matthew Grooms
211 62657a7f jim-p
global $p2_pfskeygroups;
212 3462a529 Matthew Grooms
$p2_pfskeygroups = array(
213 e8c516a0 Phil Davis
	0 => gettext('off'),
214
	1  => gettext('1 (768 bit)'),
215
	2  => gettext('2 (1024 bit)'),
216
	5  => gettext('5 (1536 bit)'),
217
	14 => gettext('14 (2048 bit)'),
218
	15 => gettext('15 (3072 bit)'),
219
	16 => gettext('16 (4096 bit)'),
220
	17 => gettext('17 (6144 bit)'),
221
	18 => gettext('18 (8192 bit)'),
222
	19 => gettext('19 (nist ecp256)'),
223
	20 => gettext('20 (nist ecp384)'),
224
	21 => gettext('21 (nist ecp521)'),
225 0be9d722 Steve Beaver
	22 => gettext('22 (1024(sub 160) bit)'),
226
	23 => gettext('23 (2048(sub 224) bit)'),
227
	24 => gettext('24 (2048(sub 256) bit)'),
228 e8c516a0 Phil Davis
	28 => gettext('28 (brainpool ecp256)'),
229
	29 => gettext('29 (brainpool ecp384)'),
230
	30 => gettext('30 (brainpool ecp512)')
231 665340db jim-p
);
232 3462a529 Matthew Grooms
233 4e96112a Luiz Otavio O Souza
function ipsec_enabled() {
234
	global $config;
235
236 4e322e2c Phil Davis
	if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
237 4e96112a Luiz Otavio O Souza
		return false;
238 4e322e2c Phil Davis
	}
239 4e96112a Luiz Otavio O Souza
240 fef38e5a Luiz Otavio O Souza
	/* Check if we have at least one phase 1 entry. */
241 4e96112a Luiz Otavio O Souza
	if (!isset($config['ipsec']['phase1']) ||
242
	    !is_array($config['ipsec']['phase1']) ||
243
	    empty($config['ipsec']['phase1'])) {
244
		return false;
245
	}
246 fef38e5a Luiz Otavio O Souza
	/* Check if at least one phase 1 entry is enabled. */
247
	foreach ($config['ipsec']['phase1'] as $phase1) {
248 4e322e2c Phil Davis
		if (!isset($phase1['disabled'])) {
249 fef38e5a Luiz Otavio O Souza
			return true;
250 4e322e2c Phil Davis
		}
251 fef38e5a Luiz Otavio O Souza
	}
252 4e96112a Luiz Otavio O Souza
253 fef38e5a Luiz Otavio O Souza
	return false;
254 4e96112a Luiz Otavio O Souza
}
255
256 d799787e Matthew Grooms
/*
257
 * ikeid management functions
258
 */
259
260
function ipsec_ikeid_used($ikeid) {
261
	global $config;
262
263 b37a2e8c Phil Davis
	foreach ($config['ipsec']['phase1'] as $ph1ent) {
264 086cf944 Phil Davis
		if ($ikeid == $ph1ent['ikeid']) {
265 d799787e Matthew Grooms
			return true;
266 b37a2e8c Phil Davis
		}
267
	}
268 d799787e Matthew Grooms
269
	return false;
270
}
271
272
function ipsec_ikeid_next() {
273
274
	$ikeid = 1;
275 b37a2e8c Phil Davis
	while (ipsec_ikeid_used($ikeid)) {
276 d799787e Matthew Grooms
		$ikeid++;
277 b37a2e8c Phil Davis
	}
278 d799787e Matthew Grooms
279
	return $ikeid;
280
}
281
282 a93e56c5 Matthew Grooms
/*
283
 * Return phase1 local address
284
 */
285
function ipsec_get_phase1_src(& $ph1ent) {
286
287 25f6730a Pierre POMES
	if ($ph1ent['interface']) {
288 d9901ff4 Chris Buechler
		if (substr($ph1ent['interface'], 0, 4) == "_vip") {
289 2a5960b0 Luiz Otavio O Souza
			$if = $ph1ent['interface'];
290 d9901ff4 Chris Buechler
		} else {
291 2a5960b0 Luiz Otavio O Souza
			$if = get_failover_interface($ph1ent['interface']);
292 d9901ff4 Chris Buechler
		}
293
	} else {
294 924876a8 Ermal Lu?i
		$if = "wan";
295 d9901ff4 Chris Buechler
	}
296 d1f69741 jim-p
	$ip6 = get_interface_ipv6($if);
297
	$ip4 = get_interface_ip($if);
298 d9901ff4 Chris Buechler
	if ($ph1ent['protocol'] == "inet6") {
299 d1f69741 jim-p
		$interfaceip = $ip6;
300
	} elseif ($ph1ent['protocol'] == "inet") {
301
		$interfaceip = $ip4;
302
	} elseif ($ph1ent['protocol'] == "both") {
303
		$ifips = array();
304
		if (!empty($ip4)) {
305
			$ifips[] = $ip4;
306
		}
307
		if (!empty($ip6)) {
308
			$ifips[] = $ip6;
309
		}
310
		$interfaceip = implode(',', $ifips);
311 d9901ff4 Chris Buechler
	}
312 a93e56c5 Matthew Grooms
313
	return $interfaceip;
314
}
315
316 3462a529 Matthew Grooms
/*
317
 * Return phase1 local address
318
 */
319
function ipsec_get_phase1_dst(& $ph1ent) {
320 df82fae1 smos
	global $g;
321 2ffafea3 Ermal
322 b37a2e8c Phil Davis
	if (empty($ph1ent['remote-gateway'])) {
323 2f3554bb jim-p
		return false;
324 b37a2e8c Phil Davis
	}
325 3462a529 Matthew Grooms
	$rg = $ph1ent['remote-gateway'];
326 33d5cb7a smos
	if (!is_ipaddr($rg)) {
327 086cf944 Phil Davis
		if (!platform_booting()) {
328 33d5cb7a smos
			return resolve_retry($rg);
329 b37a2e8c Phil Davis
		}
330 33d5cb7a smos
	}
331 b37a2e8c Phil Davis
	if (!is_ipaddr($rg)) {
332 0af7398a Matthew Grooms
		return false;
333 b37a2e8c Phil Davis
	}
334 0af7398a Matthew Grooms
335 3462a529 Matthew Grooms
	return $rg;
336
}
337
338 a93e56c5 Matthew Grooms
/*
339
 * Return phase2 idinfo in cidr format
340
 */
341 2ffafea3 Ermal
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
342 a93e56c5 Matthew Grooms
	global $config;
343
344 2ffafea3 Ermal
	switch ($idinfo['type']) {
345 a93e56c5 Matthew Grooms
		case "address":
346 98790f61 Seth Mos
			if ($addrbits) {
347 b37a2e8c Phil Davis
				if ($mode == "tunnel6") {
348 98790f61 Seth Mos
					return $idinfo['address']."/128";
349 b37a2e8c Phil Davis
				} else {
350 98790f61 Seth Mos
					return $idinfo['address']."/32";
351 b37a2e8c Phil Davis
				}
352 086cf944 Phil Davis
			} else {
353 a93e56c5 Matthew Grooms
				return $idinfo['address'];
354 086cf944 Phil Davis
			}
355 2ffafea3 Ermal
			break; /* NOTREACHED */
356 a93e56c5 Matthew Grooms
		case "network":
357 2ffafea3 Ermal
			return "{$idinfo['address']}/{$idinfo['netbits']}";
358
			break; /* NOTREACHED */
359 63017a73 Ermal Lu?i
		case "none":
360 3462a529 Matthew Grooms
		case "mobile":
361 00b56e04 Ermal LUÇI
			return '0.0.0.0/0';
362 2ffafea3 Ermal
			break; /* NOTREACHED */
363 a55e9c70 Ermal Lu?i
		default:
364 b37a2e8c Phil Davis
			if (empty($mode) && !empty($idinfo['mode'])) {
365 2ffafea3 Ermal
				$mode = $idinfo['mode'];
366 b37a2e8c Phil Davis
			}
367 2ffafea3 Ermal
368
			if ($mode == "tunnel6") {
369 98790f61 Seth Mos
				$address = get_interface_ipv6($idinfo['type']);
370
				$netbits = get_interface_subnetv6($idinfo['type']);
371 086cf944 Phil Davis
				$address = gen_subnetv6($address, $netbits);
372 2ffafea3 Ermal
				return "{$address}/{$netbits}";
373 98790f61 Seth Mos
			} else {
374
				$address = get_interface_ip($idinfo['type']);
375
				$netbits = get_interface_subnet($idinfo['type']);
376 086cf944 Phil Davis
				$address = gen_subnet($address, $netbits);
377 2ffafea3 Ermal
				return "{$address}/{$netbits}";
378 98790f61 Seth Mos
			}
379 2ffafea3 Ermal
			break; /* NOTREACHED */
380 98790f61 Seth Mos
	}
381 a93e56c5 Matthew Grooms
}
382
383
/*
384
 * Return phase2 idinfo in address/netmask format
385
 */
386 086cf944 Phil Davis
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
387 a93e56c5 Matthew Grooms
	global $config;
388
389 2ffafea3 Ermal
	switch ($idinfo['type']) {
390 a93e56c5 Matthew Grooms
		case "address":
391 98790f61 Seth Mos
			if ($addrbits) {
392 b37a2e8c Phil Davis
				if ($idinfo['mode'] == "tunnel6") {
393 98790f61 Seth Mos
					return $idinfo['address']."/128";
394 b37a2e8c Phil Davis
				} else {
395 98790f61 Seth Mos
					return $idinfo['address']."/255.255.255.255";
396 b37a2e8c Phil Davis
				}
397 086cf944 Phil Davis
			} else {
398 a93e56c5 Matthew Grooms
				return $idinfo['address'];
399 086cf944 Phil Davis
			}
400 2ffafea3 Ermal
			break; /* NOTREACHED */
401 63017a73 Ermal Lu?i
		case "none":
402 a93e56c5 Matthew Grooms
		case "network":
403
			return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
404 2ffafea3 Ermal
			break; /* NOTREACHED */
405 3462a529 Matthew Grooms
		case "mobile":
406
			return "0.0.0.0/0";
407 2ffafea3 Ermal
			break; /* NOTREACHED */
408 63017a73 Ermal Lu?i
		default:
409 2ffafea3 Ermal
			if ($idinfo['mode'] == "tunnel6") {
410 98790f61 Seth Mos
				$address = get_interface_ipv6($idinfo['type']);
411
				$netbits = get_interface_subnetv6($idinfo['type']);
412 086cf944 Phil Davis
				$address = gen_subnetv6($address, $netbits);
413 98790f61 Seth Mos
				return $address."/".$netbits;
414
			} else {
415
				$address = get_interface_ip($idinfo['type']);
416
				$netbits = get_interface_subnet($idinfo['type']);
417 086cf944 Phil Davis
				$address = gen_subnet($address, $netbits);
418 98790f61 Seth Mos
				return $address."/".$netbits;
419
			}
420 2ffafea3 Ermal
			break; /* NOTREACHED */
421 98790f61 Seth Mos
	}
422 a93e56c5 Matthew Grooms
}
423
424
/*
425
 *  Return phase2 idinfo in text format
426
 */
427
function ipsec_idinfo_to_text(& $idinfo) {
428 2ffafea3 Ermal
	global $config;
429 a93e56c5 Matthew Grooms
430 2ffafea3 Ermal
	switch ($idinfo['type']) {
431 b37a2e8c Phil Davis
		case "address":
432
			return $idinfo['address'];
433
			break; /* NOTREACHED */
434
		case "network":
435
			return $idinfo['address']."/".$idinfo['netbits'];
436
			break; /* NOTREACHED */
437
		case "mobile":
438
			return gettext("Mobile Client");
439
			break; /* NOTREACHED */
440
		case "none":
441
			return gettext("None");
442
			break; /* NOTREACHED */
443
		default:
444
			if (!empty($config['interfaces'][$idinfo['type']])) {
445
				return convert_friendly_interface_to_friendly_descr($idinfo['type']);
446
			} else {
447
				return strtoupper($idinfo['type']);
448
			}
449
			break; /* NOTREACHED */
450 2ffafea3 Ermal
	}
451 a93e56c5 Matthew Grooms
}
452
453
/*
454
 * Return phase1 association for phase2
455
 */
456 086cf944 Phil Davis
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
457 2ffafea3 Ermal
	global $config;
458
459 b37a2e8c Phil Davis
	if (!is_array($config['ipsec'])) {
460 fe12d7ea Ermal
		return false;
461 b37a2e8c Phil Davis
	}
462
	if (!is_array($config['ipsec']['phase1'])) {
463 fe12d7ea Ermal
		return false;
464 b37a2e8c Phil Davis
	}
465
	if (empty($config['ipsec']['phase1'])) {
466 fe12d7ea Ermal
		return false;
467 b37a2e8c Phil Davis
	}
468 2ffafea3 Ermal
469
	foreach ($config['ipsec']['phase1'] as $ph1tmp) {
470 b37a2e8c Phil Davis
		if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
471
			$ph1ent = $ph1tmp;
472
			return $ph1ent;
473
		}
474 2ffafea3 Ermal
	}
475
476
	return false;
477 a93e56c5 Matthew Grooms
}
478
479
/*
480
 * Check phase1 communications status
481
 */
482 ed6e93ea Chris Buechler
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
483 a93e56c5 Matthew Grooms
484 39f93e00 Ermal
	foreach ($ipsec_status as $ike) {
485 17318511 Ermal LUÇI
		if ($ike['id'] == $ikeid) {
486 b37a2e8c Phil Davis
			if ($ike['status'] == 'established') {
487 17318511 Ermal LUÇI
				return true;
488 b37a2e8c Phil Davis
			}
489 17318511 Ermal LUÇI
		}
490 fe12d7ea Ermal
	}
491 a93e56c5 Matthew Grooms
492
	return false;
493
}
494
495
/*
496
 * Check phase2 communications status
497
 */
498 ed6e93ea Chris Buechler
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
499 a93e56c5 Matthew Grooms
500 086cf944 Phil Davis
	if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
501 fe12d7ea Ermal
		return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
502 b37a2e8c Phil Davis
	}
503 a93e56c5 Matthew Grooms
504
	return false;
505
}
506
507 1dade399 Renato Botelho
/*
508
 * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
509
 */
510
function ipsec_list_sa() {
511
512 4e322e2c Phil Davis
	if (ipsec_enabled()) {
513 1dade399 Renato Botelho
		return pfSense_ipsec_list_sa();
514 4e322e2c Phil Davis
	}
515 1dade399 Renato Botelho
516
	return array();
517
}
518
519 e1c34c69 Renato Botelho
/*
520
 * Return dump of SPD table
521
 */
522
function ipsec_dump_spd() {
523
	$fd = @popen("/sbin/setkey -DP", "r");
524
	$spd = array();
525
	if ($fd) {
526
		while (!feof($fd)) {
527
			$line = chop(fgets($fd));
528
			if (!$line) {
529
				continue;
530
			}
531
			if ($line == "No SPD entries.") {
532
				break;
533
			}
534
			if ($line[0] != "\t") {
535
				if (is_array($cursp)) {
536
					$spd[] = $cursp;
537
				}
538
				$cursp = array();
539
				$linea = explode(" ", $line);
540
				$cursp['srcid'] = substr($linea[0], 0, strpos($linea[0], "["));
541
				$cursp['dstid'] = substr($linea[1], 0, strpos($linea[1], "["));
542
				$i = 0;
543
			} else if (is_array($cursp)) {
544
				$line = trim($line, "\t\r\n ");
545
				$linea = explode(" ", $line);
546
				switch ($i) {
547
					case 1:
548
						if ($linea[1] == "none")	/* don't show default anti-lockout rule */ {
549
							unset($cursp);
550
						} else {
551
							$cursp['dir'] = $linea[0];
552
						}
553
						break;
554
					case 2:
555
						$upperspec = explode("/", $linea[0]);
556
						$cursp['proto'] = $upperspec[0];
557
						list($cursp['src'], $cursp['dst']) = explode("-", $upperspec[2]);
558
						$cursp['reqid'] = substr($upperspec[3], strpos($upperspec[3], "#")+1);
559
						break;
560
				}
561
			}
562
			$i++;
563
		}
564
		if (is_array($cursp) && count($cursp)) {
565
			$spd[] = $cursp;
566
		}
567
		pclose($fd);
568
	}
569
570
	return $spd;
571
}
572
573 a93e56c5 Matthew Grooms
/*
574
 * Return dump of SAD table
575
 */
576 086cf944 Phil Davis
function ipsec_dump_sad() {
577 30c591d6 Ermal
	$fd = @popen("/sbin/setkey -D", "r");
578 a93e56c5 Matthew Grooms
	$sad = array();
579
	if ($fd) {
580
		while (!feof($fd)) {
581
			$line = chop(fgets($fd));
582 b37a2e8c Phil Davis
			if (!$line || $line[0] == " ") {
583 a93e56c5 Matthew Grooms
				continue;
584 b37a2e8c Phil Davis
			}
585
			if ($line == "No SAD entries.") {
586 a93e56c5 Matthew Grooms
				break;
587 b37a2e8c Phil Davis
			}
588
			if ($line[0] != "\t") {
589
				if (is_array($cursa)) {
590 a93e56c5 Matthew Grooms
					$sad[] = $cursa;
591 b37a2e8c Phil Davis
				}
592 a93e56c5 Matthew Grooms
				$cursa = array();
593 086cf944 Phil Davis
				list($cursa['src'], $cursa['dst']) = explode(" ", $line);
594 b37a2e8c Phil Davis
			} else {
595 648661c5 Ermal LUÇI
				$line = trim($line, "\t\n\r ");
596
				$linea = explode(" ", $line);
597
				foreach ($linea as $idx => $linee) {
598 b37a2e8c Phil Davis
					if ($linee == 'esp' || $linee == 'ah' || $linee[0] == '#') {
599 648661c5 Ermal LUÇI
						$cursa['proto'] = $linee;
600 b37a2e8c Phil Davis
					} else if (substr($linee, 0, 3) == 'spi') {
601 648661c5 Ermal LUÇI
						$cursa['spi'] = substr($linee, strpos($linee, 'x') + 1, -1);
602 b37a2e8c Phil Davis
					} else if (substr($linee, 0, 5) == 'reqid') {
603 648661c5 Ermal LUÇI
						$cursa['reqid'] = substr($linee, strpos($linee, 'x') + 1, -1);
604 b37a2e8c Phil Davis
					} else if (substr($linee, 0, 2) == 'E:') {
605 648661c5 Ermal LUÇI
						$cursa['ealgo'] = $linea[$idx + 1];
606 a93e56c5 Matthew Grooms
						break;
607 648661c5 Ermal LUÇI
					} else if (substr($linee, 0, 2) == 'A:') {
608
						$cursa['aalgo'] = $linea[$idx + 1];
609 a93e56c5 Matthew Grooms
						break;
610 648661c5 Ermal LUÇI
					} else if (substr($linee, 0, 8) == 'current:') {
611
						$cursa['data'] = substr($linea[$idx + 1], 0, strpos($linea[$idx + 1], 'bytes') - 1) . ' B';
612 f451ea09 jim-p
						break;
613 648661c5 Ermal LUÇI
					}
614 a93e56c5 Matthew Grooms
				}
615
			}
616
		}
617 b37a2e8c Phil Davis
		if (is_array($cursa) && count($cursa)) {
618 a93e56c5 Matthew Grooms
			$sad[] = $cursa;
619 b37a2e8c Phil Davis
		}
620 a93e56c5 Matthew Grooms
		pclose($fd);
621
	}
622
623
	return $sad;
624
}
625
626 6e0b68bf jim-p
/*
627
 * Return dump of mobile user list
628
 */
629
function ipsec_dump_mobile() {
630 33927941 PiBa-NL
	global $g, $config;
631 ed5fc757 Ermal
632 33927941 PiBa-NL
	if(!isset($config['ipsec']['client']['enable'])) {
633
		return array();
634
	}
635 0be9d722 Steve Beaver
636 796b7651 Renato Botelho
	$_gb = exec("/usr/local/sbin/ipsec leases 2>/dev/null", $output, $rc);
637 6e0b68bf jim-p
638 796b7651 Renato Botelho
	if ($rc != 0) {
639 276efd64 Chris Buechler
		log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
640 7ab6ad70 Ermal
		return array();
641 6e0b68bf jim-p
	}
642
643 796b7651 Renato Botelho
	$response = array();
644
	$id = -1;
645
646
	/* Leases in pool '10.7.200.0/24', usage: 1/254, 1 online */
647
	$lease_regex='/^Leases *in *pool *\'(?P<name>.+)\', *usage: *(?P<usage>\d+)\/(?P<size>\d+), *(?P<online>\d+) *online/';
648
	/* 10.7.200.1   online   'jimp' */
649
	$pool_regex='/\s*(?P<host>[\d\.]+)\s+(?P<status>online|offline)\s+\'(?P<id>.*)\'/';
650
	/* no matching leases found */
651
	$nopool_regex='/no *matching *leases *found/';
652
653
	$lease=false;
654
	foreach ($output as $line) {
655
		if (preg_match($lease_regex, $line, $matches)) {
656
			$id++;
657
			$response['pool'][$id] = array(
658
			    'name'   => $matches['name'],
659
			    'usage'  => $matches['usage'],
660
			    'size'   => $matches['size'],
661
			    'online' => $matches['online'],
662
			);
663
			$lease=true;
664
		} else if ($lease) {
665
			if (preg_match($nopool_regex, $line)) {
666
				$response['pool'][$id]['lease'][] = array();
667
				$lease=false;
668
			} else if (preg_match($pool_regex, $line, $matches)) {
669
				$response['pool'][$id]['lease'][] = array(
670
				    'host'   => $matches['host'],
671
				    'status' => $matches['status'],
672
				    'id'     => $matches['id']
673
				);
674
			}
675
		}
676 f3e15492 Renato Botelho
	}
677
678 796b7651 Renato Botelho
	unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex,
679
	    $nopool_regex);
680 7ab6ad70 Ermal
681
	return $response;
682 6e0b68bf jim-p
}
683
684 958420c5 jim-p
function ipsec_mobilekey_sort() {
685
	global $config;
686
687
	function mobilekeycmp($a, $b) {
688
		return strcmp($a['ident'][0], $b['ident'][0]);
689
	}
690
691
	usort($config['ipsec']['mobilekey'], "mobilekeycmp");
692
}
693
694 8f5c3d8d Pierre POMES
function ipsec_get_number_of_phase2($ikeid) {
695
	global $config;
696 b37a2e8c Phil Davis
	$a_phase2 = $config['ipsec']['phase2'];
697 8f5c3d8d Pierre POMES
698 6c07db48 Phil Davis
	$nbph2 = 0;
699 8f5c3d8d Pierre POMES
700 b37a2e8c Phil Davis
	if (is_array($a_phase2) && count($a_phase2)) {
701
		foreach ($a_phase2 as $ph2tmp) {
702
			if ($ph2tmp['ikeid'] == $ikeid) {
703 8f5c3d8d Pierre POMES
				$nbph2++;
704
			}
705
		}
706
	}
707
708
	return $nbph2;
709
}
710
711 859a5304 Renato Botelho
function ipsec_get_descr($ikeid) {
712
	global $config;
713
714
	if (!isset($config['ipsec']['phase1']) ||
715 b37a2e8c Phil Davis
	    !is_array($config['ipsec']['phase1'])) {
716 c607f306 Ermal LUÇI
		return '';
717 b37a2e8c Phil Davis
	}
718 859a5304 Renato Botelho
719 c607f306 Ermal LUÇI
	foreach ($config['ipsec']['phase1'] as $p1) {
720 859a5304 Renato Botelho
		if ($p1['ikeid'] == $ikeid) {
721 c607f306 Ermal LUÇI
			return $p1['descr'];
722 859a5304 Renato Botelho
		}
723
	}
724
725 c607f306 Ermal LUÇI
	return '';
726 859a5304 Renato Botelho
}
727
728 483c3b5b Ermal LUÇI
function ipsec_get_phase1($ikeid) {
729 b37a2e8c Phil Davis
		global $config;
730
731
		if (!isset($config['ipsec']['phase1']) ||
732
		    !is_array($config['ipsec']['phase1'])) {
733
			return '';
734
		}
735
736
		$a_phase1 = $config['ipsec']['phase1'];
737
		foreach ($a_phase1 as $p1) {
738
			if ($p1['ikeid'] == $ikeid) {
739
				return $p1;
740
			}
741
		}
742
		unset($a_phase1);
743 483c3b5b Ermal LUÇI
}
744
745 3ec026a4 jim-p
function ipsec_fixup_ip($ipaddr) {
746 b37a2e8c Phil Davis
	if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
747 587995fb Phil Davis
		return text_to_compressed_ip6($ipaddr);
748 b37a2e8c Phil Davis
	} else {
749 3ec026a4 jim-p
		return $ipaddr;
750 b37a2e8c Phil Davis
	}
751 3ec026a4 jim-p
}
752
753 95589abd jim-p
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
754
	if ($side == "local") {
755
		$id_type = $ph1ent['myid_type'];
756
		$id_data = $ph1ent['myid_data'];
757
758
		$addr = ipsec_get_phase1_src($ph1ent);
759 b37a2e8c Phil Davis
		if (!$addr) {
760 95589abd jim-p
			return array();
761 b37a2e8c Phil Davis
		}
762 d1f69741 jim-p
		/* When automatically guessing, use the first address. */
763
		$addr = explode(',', $addr);
764
		$addr = $addr[0];
765 664aef0b Chris Buechler
	} elseif ($side == "peer") {
766 95589abd jim-p
		$id_type = $ph1ent['peerid_type'];
767
		$id_data = $ph1ent['peerid_data'];
768
769 b37a2e8c Phil Davis
		if (isset($ph1ent['mobile'])) {
770 95589abd jim-p
			$addr = "%any";
771 b37a2e8c Phil Davis
		} else {
772 95589abd jim-p
			$addr = $ph1ent['remote-gateway'];
773 b37a2e8c Phil Davis
		}
774
	} else {
775 95589abd jim-p
		return array();
776 b37a2e8c Phil Davis
	}
777 95589abd jim-p
778
779
	$thisid_type = $id_type;
780
	switch ($thisid_type) {
781 b37a2e8c Phil Davis
		case 'myaddress':
782
			$thisid_type = 'address';
783
			$thisid_data = $addr;
784
			break;
785
		case 'dyn_dns':
786
			$thisid_type = 'dns';
787
			$thisid_data = $id_data;
788
			break;
789
		case 'peeraddress':
790
			$thisid_type = 'address';
791
			$thisid_data = $rgmap[$ph1ent['remote-gateway']];
792
			break;
793
		case 'address':
794
			$thisid_data = $id_data;
795
			break;
796
		case 'fqdn':
797
			$thisid_data = "{$id_data}";
798
			break;
799
		case 'keyid tag':
800
			$thisid_type = 'keyid';
801 10439116 Bruno Thomsen
			$thisid_data = "{$id_data}";
802 b37a2e8c Phil Davis
			break;
803
		case 'user_fqdn':
804
			$thisid_type = 'userfqdn';
805
			$thisid_data = "{$id_data}";
806
			break;
807
		case 'asn1dn':
808
			$thisid_data = $id_data;
809
			break;
810 95589abd jim-p
	}
811
	return array($thisid_type, $thisid_data);
812
}
813 060c3ac0 Renato Botelho
814
function ipsec_fixup_network($network) {
815 b37a2e8c Phil Davis
	if (substr($network, -3) == '|/0') {
816 060c3ac0 Renato Botelho
		$result = substr($network, 0, -3);
817 b37a2e8c Phil Davis
	} else {
818 060c3ac0 Renato Botelho
		$tmp = explode('|', $network);
819 b37a2e8c Phil Davis
		if (isset($tmp[1])) {
820 060c3ac0 Renato Botelho
			$result = $tmp[1];
821 b37a2e8c Phil Davis
		} else {
822 060c3ac0 Renato Botelho
			$result = $tmp[0];
823 b37a2e8c Phil Davis
		}
824 060c3ac0 Renato Botelho
		unset($tmp);
825
	}
826
827
	return $result;
828
}
829
830 1fe208ec Ermal LUÇI
function ipsec_new_reqid() {
831
	global $config;
832
833 b37a2e8c Phil Davis
	if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
834 1fe208ec Ermal LUÇI
		return;
835 b37a2e8c Phil Davis
	}
836 1fe208ec Ermal LUÇI
837
	$ipsecreqid = lock('ipsecreqids', LOCK_EX);
838
	$keyids = array();
839
	$keyid = 1;
840 b37a2e8c Phil Davis
	foreach ($config['ipsec']['phase2'] as $ph2) {
841 1fe208ec Ermal LUÇI
		$keyids[$ph2['reqid']] = $ph2['reqid'];
842 b37a2e8c Phil Davis
	}
843 1fe208ec Ermal LUÇI
844
	for ($i = 1; $i < 16000; $i++) {
845
		if (!isset($keyids[$i])) {
846
			$keyid = $i;
847
			break;
848
		}
849
	}
850
	unlock($ipsecreqid);
851
852
	return $keyid;
853
}
854
855 e470f721 jim-p
function ipsec_get_loglevels() {
856
	global $config, $ipsec_log_cats;
857
	$def_loglevel = '1';
858
859
	$levels = array();
860
861
	foreach (array_keys($ipsec_log_cats) as $cat) {
862
		if (isset($config['ipsec']['logging'][$cat])) {
863
			$levels[$cat] = $config['ipsec']['logging'][$cat];
864
		} elseif (in_array($cat, array('ike', 'chd', 'cfg'))) {
865
			$levels[$cat] = "2";
866
		} else {
867
			$levels[$cat] = $def_loglevel;
868
		}
869
	}
870
	return $levels;
871
}
872 bd4c337c jim-p
873
function ipsec_vti($ph1ent, $returnaddresses = false) {
874
	global $config;
875
	if (empty($ph1ent) || !is_array($ph1ent) || !is_array($config['ipsec']['phase2'])) {
876
		return false;
877
	}
878
879
	$is_vti = false;
880
	$vtisubnet_spec = array();
881
882
	foreach ($config['ipsec']['phase2'] as $ph2ent) {
883
		if ($ph1ent['ikeid'] != $ph2ent['ikeid']) {
884
			continue;
885
		}
886
		if ($ph2ent['mode'] == 'vti') {
887
			if ($returnaddresses) {
888
				$vtisubnet_spec[] = array(
889 65767828 jim-p
					'left' => ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']),
890 bd4c337c jim-p
					'right' => ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']),
891 235c051f jim-p
					'descr' => $ph2ent['descr'],
892 bd4c337c jim-p
				);
893
			}
894
			$is_vti = true;
895
		}
896
	}
897
	return ($returnaddresses) ? $vtisubnet_spec : $is_vti;
898
}
899
900 8f5c3d8d Pierre POMES
?>