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 |
38809d47
|
Renato Botelho do Couto
|
* Copyright (c) 2007-2013 BSD Perimeter
|
8 |
|
|
* Copyright (c) 2013-2016 Electric Sheep Fencing
|
9 |
8f585441
|
Luiz Souza
|
* Copyright (c) 2014-2021 Rubicon Communications, LLC (Netgate)
|
10 |
ac24dc24
|
Renato Botelho
|
* All rights reserved.
|
11 |
|
|
*
|
12 |
b12ea3fb
|
Renato Botelho
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
13 |
|
|
* you may not use this file except in compliance with the License.
|
14 |
|
|
* You may obtain a copy of the License at
|
15 |
ac24dc24
|
Renato Botelho
|
*
|
16 |
b12ea3fb
|
Renato Botelho
|
* http://www.apache.org/licenses/LICENSE-2.0
|
17 |
ac24dc24
|
Renato Botelho
|
*
|
18 |
b12ea3fb
|
Renato Botelho
|
* Unless required by applicable law or agreed to in writing, software
|
19 |
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
20 |
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21 |
|
|
* See the License for the specific language governing permissions and
|
22 |
|
|
* limitations under the License.
|
23 |
ac24dc24
|
Renato Botelho
|
*/
|
24 |
a93e56c5
|
Matthew Grooms
|
|
25 |
c6220dcf
|
jim-p
|
require_once("filter.inc");
|
26 |
|
|
require_once("auth.inc");
|
27 |
|
|
require_once("certs.inc");
|
28 |
b08a1fa1
|
Viktor Gurov
|
require_once("interfaces.inc");
|
29 |
c6220dcf
|
jim-p
|
|
30 |
3462a529
|
Matthew Grooms
|
/* IPsec defines */
|
31 |
62657a7f
|
jim-p
|
global $ipsec_loglevels;
|
32 |
e8c516a0
|
Phil Davis
|
$ipsec_loglevels = array(
|
33 |
|
|
"dmn" => gettext("Daemon"),
|
34 |
|
|
"mgr" => gettext("SA Manager"),
|
35 |
|
|
"ike" => gettext("IKE SA"),
|
36 |
|
|
"chd" => gettext("IKE Child SA"),
|
37 |
|
|
"job" => gettext("Job Processing"),
|
38 |
|
|
"cfg" => gettext("Configuration backend"),
|
39 |
|
|
"knl" => gettext("Kernel Interface"),
|
40 |
|
|
"net" => gettext("Networking"),
|
41 |
|
|
"asn" => gettext("ASN encoding"),
|
42 |
|
|
"enc" => gettext("Message encoding"),
|
43 |
|
|
"imc" => gettext("Integrity checker"),
|
44 |
|
|
"imv" => gettext("Integrity Verifier"),
|
45 |
|
|
"pts" => gettext("Platform Trust Service"),
|
46 |
|
|
"tls" => gettext("TLS handler"),
|
47 |
|
|
"esp" => gettext("IPsec traffic"),
|
48 |
|
|
"lib" => gettext("StrongSwan Lib")
|
49 |
|
|
);
|
50 |
c6efc8fd
|
Ermal
|
|
51 |
c53e411f
|
Matt Smith
|
global $ipsec_log_sevs;
|
52 |
|
|
$ipsec_log_sevs = array(
|
53 |
e8c516a0
|
Phil Davis
|
'-1' => gettext('Silent'),
|
54 |
|
|
'0' => gettext('Audit'),
|
55 |
|
|
'1' => gettext('Control'),
|
56 |
|
|
'2' => gettext('Diag'),
|
57 |
|
|
'3' => gettext('Raw'),
|
58 |
|
|
'4' => gettext('Highest')
|
59 |
c53e411f
|
Matt Smith
|
);
|
60 |
|
|
|
61 |
|
|
global $ipsec_log_cats;
|
62 |
|
|
$ipsec_log_cats = array(
|
63 |
e8c516a0
|
Phil Davis
|
"dmn" => gettext("Daemon"),
|
64 |
|
|
"mgr" => gettext("SA Manager"),
|
65 |
|
|
"ike" => gettext("IKE SA"),
|
66 |
|
|
"chd" => gettext("IKE Child SA"),
|
67 |
|
|
"job" => gettext("Job Processing"),
|
68 |
|
|
"cfg" => gettext("Configuration backend"),
|
69 |
|
|
"knl" => gettext("Kernel Interface"),
|
70 |
|
|
"net" => gettext("Networking"),
|
71 |
|
|
"asn" => gettext("ASN encoding"),
|
72 |
|
|
"enc" => gettext("Message encoding"),
|
73 |
|
|
"imc" => gettext("Integrity checker"),
|
74 |
|
|
"imv" => gettext("Integrity Verifier"),
|
75 |
|
|
"pts" => gettext("Platform Trust Service"),
|
76 |
|
|
"tls" => gettext("TLS handler"),
|
77 |
|
|
"esp" => gettext("IPsec traffic"),
|
78 |
|
|
"lib" => gettext("StrongSwan Lib")
|
79 |
c53e411f
|
Matt Smith
|
);
|
80 |
|
|
|
81 |
8e461d38
|
Christian
|
global $ipsec_identifier_list;
|
82 |
|
|
$ipsec_identifier_list = array(
|
83 |
|
|
// 'ipv4' => array('desc' => gettext('IPv4 address'), 'mobile' => true),
|
84 |
|
|
// 'ipv6' => array('desc' => gettext('IPv6 address'), 'mobile' => true),
|
85 |
|
|
// 'rfc822' => array('desc' => gettext('RFC822'), 'mobile' => true),
|
86 |
|
|
'none' => array('desc' => '', 'mobile' => true),
|
87 |
|
|
'email' => array('desc' => gettext('E-mail address'), 'mobile' => true),
|
88 |
|
|
'userfqdn' => array('desc' => gettext('User Fully Qualified Domain Name'), 'mobile' => true)
|
89 |
|
|
// 'fqdn' => array('desc' => gettext('Fully Qualified Domain Name'), 'mobile' => true),
|
90 |
|
|
// 'dns' => array('desc' => gettext('DNS'), 'mobile' => true),
|
91 |
|
|
// 'asn1dn' => array('desc' => gettext('ASN.1 Distinguished Name'), 'mobile' => true),
|
92 |
|
|
// 'asn1gn' => array('desc' => gettext('ASN.1 GN'), 'mobile' => true),
|
93 |
|
|
// 'keyid' => array('desc' => gettext('KeyID'), 'mobile' => true)
|
94 |
|
|
);
|
95 |
|
|
|
96 |
62657a7f
|
jim-p
|
global $my_identifier_list;
|
97 |
3462a529
|
Matthew Grooms
|
$my_identifier_list = array(
|
98 |
086cf944
|
Phil Davis
|
'myaddress' => array('desc' => gettext('My IP address'), 'mobile' => true),
|
99 |
|
|
'address' => array('desc' => gettext('IP address'), 'mobile' => true),
|
100 |
|
|
'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
|
101 |
|
|
'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
|
102 |
|
|
'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
|
103 |
|
|
'keyid tag' => array('desc' => gettext('KeyID tag'), 'mobile' => true),
|
104 |
e8c516a0
|
Phil Davis
|
'dyn_dns' => array('desc' => gettext('Dynamic DNS'), 'mobile' => true)
|
105 |
|
|
);
|
106 |
3462a529
|
Matthew Grooms
|
|
107 |
62657a7f
|
jim-p
|
global $peer_identifier_list;
|
108 |
3462a529
|
Matthew Grooms
|
$peer_identifier_list = array(
|
109 |
b0994811
|
Chris Buechler
|
'any' => array('desc' => gettext('Any'), 'mobile' => true),
|
110 |
086cf944
|
Phil Davis
|
'peeraddress' => array('desc' => gettext('Peer IP address'), 'mobile' => false),
|
111 |
|
|
'address' => array('desc' => gettext('IP address'), 'mobile' => false),
|
112 |
|
|
'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true),
|
113 |
|
|
'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true),
|
114 |
|
|
'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true),
|
115 |
e8c516a0
|
Phil Davis
|
'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true)
|
116 |
|
|
);
|
117 |
3462a529
|
Matthew Grooms
|
|
118 |
62657a7f
|
jim-p
|
global $ipsec_idhandling;
|
119 |
86e1846f
|
Ermal LUÇI
|
$ipsec_idhandling = array(
|
120 |
c6220dcf
|
jim-p
|
'replace' => 'Yes (Replace)', 'no' => 'No', 'never' => 'Never', 'keep' => 'Keep'
|
121 |
e8c516a0
|
Phil Davis
|
);
|
122 |
86e1846f
|
Ermal LUÇI
|
|
123 |
62657a7f
|
jim-p
|
global $p1_ealgos;
|
124 |
3462a529
|
Matthew Grooms
|
$p1_ealgos = array(
|
125 |
086cf944
|
Phil Davis
|
'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
|
126 |
a46e0d74
|
Chris Buechler
|
'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
|
127 |
|
|
'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
|
128 |
|
|
'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
|
129 |
086cf944
|
Phil Davis
|
'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
|
130 |
|
|
'3des' => array('name' => '3DES'),
|
131 |
e8c516a0
|
Phil Davis
|
'cast128' => array('name' => 'CAST128')
|
132 |
|
|
);
|
133 |
3462a529
|
Matthew Grooms
|
|
134 |
62657a7f
|
jim-p
|
global $p2_ealgos;
|
135 |
3462a529
|
Matthew Grooms
|
$p2_ealgos = array(
|
136 |
086cf944
|
Phil Davis
|
'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
|
137 |
|
|
'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
|
138 |
|
|
'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
|
139 |
|
|
'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)),
|
140 |
|
|
'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)),
|
141 |
|
|
'3des' => array('name' => '3DES'),
|
142 |
e8c516a0
|
Phil Davis
|
'cast128' => array('name' => 'CAST128')
|
143 |
|
|
);
|
144 |
3462a529
|
Matthew Grooms
|
|
145 |
62657a7f
|
jim-p
|
global $p1_halgos;
|
146 |
3462a529
|
Matthew Grooms
|
$p1_halgos = array(
|
147 |
665340db
|
jim-p
|
'md5' => 'MD5',
|
148 |
3462a529
|
Matthew Grooms
|
'sha1' => 'SHA1',
|
149 |
665340db
|
jim-p
|
'sha256' => 'SHA256',
|
150 |
|
|
'sha384' => 'SHA384',
|
151 |
b0cbebeb
|
Ermal
|
'sha512' => 'SHA512',
|
152 |
|
|
'aesxcbc' => 'AES-XCBC'
|
153 |
665340db
|
jim-p
|
);
|
154 |
|
|
|
155 |
62657a7f
|
jim-p
|
global $p1_dhgroups;
|
156 |
665340db
|
jim-p
|
$p1_dhgroups = array(
|
157 |
|
|
1 => '1 (768 bit)',
|
158 |
|
|
2 => '2 (1024 bit)',
|
159 |
|
|
5 => '5 (1536 bit)',
|
160 |
|
|
14 => '14 (2048 bit)',
|
161 |
|
|
15 => '15 (3072 bit)',
|
162 |
|
|
16 => '16 (4096 bit)',
|
163 |
|
|
17 => '17 (6144 bit)',
|
164 |
b0cbebeb
|
Ermal
|
18 => '18 (8192 bit)',
|
165 |
7a747654
|
Ermal LUÇI
|
19 => '19 (nist ecp256)',
|
166 |
|
|
20 => '20 (nist ecp384)',
|
167 |
|
|
21 => '21 (nist ecp521)',
|
168 |
b0cbebeb
|
Ermal
|
22 => '22 (1024(sub 160) bit)',
|
169 |
|
|
23 => '23 (2048(sub 224) bit)',
|
170 |
c55ec98a
|
Bruno Thomsen
|
24 => '24 (2048(sub 256) bit)',
|
171 |
21bee028
|
jim-p
|
25 => '25 (nist ecp192)',
|
172 |
|
|
26 => '26 (nist ecp224)',
|
173 |
|
|
27 => '27 (brainpool ecp224)',
|
174 |
c55ec98a
|
Bruno Thomsen
|
28 => '28 (brainpool ecp256)',
|
175 |
|
|
29 => '29 (brainpool ecp384)',
|
176 |
4fc26748
|
jim-p
|
30 => '30 (brainpool ecp512)',
|
177 |
|
|
31 => '31 (Elliptic Curve 25519, 256 bit)',
|
178 |
3f45cc99
|
jim-p
|
32 => '32 (Elliptic Curve 25519, 448 bit)',
|
179 |
665340db
|
jim-p
|
);
|
180 |
3462a529
|
Matthew Grooms
|
|
181 |
62657a7f
|
jim-p
|
global $p2_halgos;
|
182 |
3462a529
|
Matthew Grooms
|
$p2_halgos = array(
|
183 |
665340db
|
jim-p
|
'hmac_md5' => 'MD5',
|
184 |
3462a529
|
Matthew Grooms
|
'hmac_sha1' => 'SHA1',
|
185 |
665340db
|
jim-p
|
'hmac_sha256' => 'SHA256',
|
186 |
|
|
'hmac_sha384' => 'SHA384',
|
187 |
b0cbebeb
|
Ermal
|
'hmac_sha512' => 'SHA512',
|
188 |
|
|
'aesxcbc' => 'AES-XCBC'
|
189 |
665340db
|
jim-p
|
);
|
190 |
3462a529
|
Matthew Grooms
|
|
191 |
62657a7f
|
jim-p
|
global $p1_authentication_methods;
|
192 |
3462a529
|
Matthew Grooms
|
$p1_authentication_methods = array(
|
193 |
d1f5587d
|
jim-p
|
'hybrid_cert_server' => array('name' => gettext('Hybrid Certificate + Xauth'), 'mobile' => true),
|
194 |
|
|
'xauth_cert_server' => array('name' => gettext('Mutual Certificate + Xauth'), 'mobile' => true),
|
195 |
e8c516a0
|
Phil Davis
|
'xauth_psk_server' => array('name' => gettext('Mutual PSK + Xauth'), 'mobile' => true),
|
196 |
|
|
'eap-tls' => array('name' => gettext('EAP-TLS'), 'mobile' => true),
|
197 |
|
|
'eap-radius' => array('name' => gettext('EAP-RADIUS'), 'mobile' => true),
|
198 |
|
|
'eap-mschapv2' => array('name' => gettext('EAP-MSChapv2'), 'mobile' => true),
|
199 |
0619c2b5
|
Viktor G
|
'cert' => array('name' => gettext('Mutual Certificate'), 'mobile' => false),
|
200 |
f645d52a
|
Viktor Gurov
|
'pkcs11' => array('name' => gettext('Mutual Certificate (PKCS#11)'), 'mobile' => false),
|
201 |
e8c516a0
|
Phil Davis
|
'pre_shared_key' => array('name' => gettext('Mutual PSK'), 'mobile' => false)
|
202 |
|
|
);
|
203 |
3462a529
|
Matthew Grooms
|
|
204 |
62657a7f
|
jim-p
|
global $ipsec_preshared_key_type;
|
205 |
10e2acb5
|
Ermal LUÇI
|
$ipsec_preshared_key_type = array(
|
206 |
|
|
'PSK' => 'PSK',
|
207 |
|
|
'EAP' => 'EAP'
|
208 |
e8c516a0
|
Phil Davis
|
);
|
209 |
10e2acb5
|
Ermal LUÇI
|
|
210 |
85c85e89
|
jim-p
|
global $ipsec_closeactions;
|
211 |
|
|
$ipsec_closeactions = array(
|
212 |
|
|
'' => gettext('Default'),
|
213 |
21568e75
|
jim-p
|
'none' => gettext('Close connection and clear SA'),
|
214 |
|
|
'start' => gettext('Restart/Reconnect'),
|
215 |
31a6bd5e
|
jim-p
|
'trap' => gettext('Close connection and reconnect on demand'),
|
216 |
85c85e89
|
jim-p
|
);
|
217 |
|
|
|
218 |
62657a7f
|
jim-p
|
global $p2_modes;
|
219 |
4b96b367
|
mgrooms
|
$p2_modes = array(
|
220 |
e8c516a0
|
Phil Davis
|
'tunnel' => gettext('Tunnel IPv4'),
|
221 |
|
|
'tunnel6' => gettext('Tunnel IPv6'),
|
222 |
bd4c337c
|
jim-p
|
'transport' => gettext('Transport'),
|
223 |
|
|
'vti' => gettext('Routed (VTI)')
|
224 |
e8c516a0
|
Phil Davis
|
);
|
225 |
4b96b367
|
mgrooms
|
|
226 |
62657a7f
|
jim-p
|
global $p2_protos;
|
227 |
3462a529
|
Matthew Grooms
|
$p2_protos = array(
|
228 |
|
|
'esp' => 'ESP',
|
229 |
e8c516a0
|
Phil Davis
|
'ah' => 'AH'
|
230 |
|
|
);
|
231 |
3462a529
|
Matthew Grooms
|
|
232 |
62657a7f
|
jim-p
|
global $p2_pfskeygroups;
|
233 |
3462a529
|
Matthew Grooms
|
$p2_pfskeygroups = array(
|
234 |
e8c516a0
|
Phil Davis
|
0 => gettext('off'),
|
235 |
|
|
1 => gettext('1 (768 bit)'),
|
236 |
|
|
2 => gettext('2 (1024 bit)'),
|
237 |
|
|
5 => gettext('5 (1536 bit)'),
|
238 |
|
|
14 => gettext('14 (2048 bit)'),
|
239 |
|
|
15 => gettext('15 (3072 bit)'),
|
240 |
|
|
16 => gettext('16 (4096 bit)'),
|
241 |
|
|
17 => gettext('17 (6144 bit)'),
|
242 |
|
|
18 => gettext('18 (8192 bit)'),
|
243 |
|
|
19 => gettext('19 (nist ecp256)'),
|
244 |
|
|
20 => gettext('20 (nist ecp384)'),
|
245 |
|
|
21 => gettext('21 (nist ecp521)'),
|
246 |
0be9d722
|
Steve Beaver
|
22 => gettext('22 (1024(sub 160) bit)'),
|
247 |
|
|
23 => gettext('23 (2048(sub 224) bit)'),
|
248 |
|
|
24 => gettext('24 (2048(sub 256) bit)'),
|
249 |
21bee028
|
jim-p
|
25 => gettext('25 (nist ecp192)'),
|
250 |
|
|
26 => gettext('26 (nist ecp224)'),
|
251 |
|
|
27 => gettext('27 (brainpool ecp224)'),
|
252 |
e8c516a0
|
Phil Davis
|
28 => gettext('28 (brainpool ecp256)'),
|
253 |
|
|
29 => gettext('29 (brainpool ecp384)'),
|
254 |
4fc26748
|
jim-p
|
30 => gettext('30 (brainpool ecp512)'),
|
255 |
|
|
31 => gettext('31 (Elliptic Curve 25519, 256 bit)'),
|
256 |
3f45cc99
|
jim-p
|
32 => gettext('32 (Elliptic Curve 25519, 448 bit)'),
|
257 |
665340db
|
jim-p
|
);
|
258 |
3462a529
|
Matthew Grooms
|
|
259 |
4e96112a
|
Luiz Otavio O Souza
|
function ipsec_enabled() {
|
260 |
|
|
global $config;
|
261 |
|
|
|
262 |
4e322e2c
|
Phil Davis
|
if (!isset($config['ipsec']) || !is_array($config['ipsec'])) {
|
263 |
4e96112a
|
Luiz Otavio O Souza
|
return false;
|
264 |
4e322e2c
|
Phil Davis
|
}
|
265 |
4e96112a
|
Luiz Otavio O Souza
|
|
266 |
fef38e5a
|
Luiz Otavio O Souza
|
/* Check if we have at least one phase 1 entry. */
|
267 |
4e96112a
|
Luiz Otavio O Souza
|
if (!isset($config['ipsec']['phase1']) ||
|
268 |
|
|
!is_array($config['ipsec']['phase1']) ||
|
269 |
|
|
empty($config['ipsec']['phase1'])) {
|
270 |
|
|
return false;
|
271 |
|
|
}
|
272 |
fef38e5a
|
Luiz Otavio O Souza
|
/* Check if at least one phase 1 entry is enabled. */
|
273 |
|
|
foreach ($config['ipsec']['phase1'] as $phase1) {
|
274 |
4e322e2c
|
Phil Davis
|
if (!isset($phase1['disabled'])) {
|
275 |
fef38e5a
|
Luiz Otavio O Souza
|
return true;
|
276 |
4e322e2c
|
Phil Davis
|
}
|
277 |
fef38e5a
|
Luiz Otavio O Souza
|
}
|
278 |
4e96112a
|
Luiz Otavio O Souza
|
|
279 |
fef38e5a
|
Luiz Otavio O Souza
|
return false;
|
280 |
4e96112a
|
Luiz Otavio O Souza
|
}
|
281 |
|
|
|
282 |
d799787e
|
Matthew Grooms
|
/*
|
283 |
|
|
* ikeid management functions
|
284 |
|
|
*/
|
285 |
|
|
|
286 |
|
|
function ipsec_ikeid_used($ikeid) {
|
287 |
|
|
global $config;
|
288 |
|
|
|
289 |
b37a2e8c
|
Phil Davis
|
foreach ($config['ipsec']['phase1'] as $ph1ent) {
|
290 |
086cf944
|
Phil Davis
|
if ($ikeid == $ph1ent['ikeid']) {
|
291 |
d799787e
|
Matthew Grooms
|
return true;
|
292 |
b37a2e8c
|
Phil Davis
|
}
|
293 |
|
|
}
|
294 |
d799787e
|
Matthew Grooms
|
|
295 |
|
|
return false;
|
296 |
|
|
}
|
297 |
|
|
|
298 |
|
|
function ipsec_ikeid_next() {
|
299 |
|
|
|
300 |
|
|
$ikeid = 1;
|
301 |
b37a2e8c
|
Phil Davis
|
while (ipsec_ikeid_used($ikeid)) {
|
302 |
d799787e
|
Matthew Grooms
|
$ikeid++;
|
303 |
b37a2e8c
|
Phil Davis
|
}
|
304 |
d799787e
|
Matthew Grooms
|
|
305 |
|
|
return $ikeid;
|
306 |
|
|
}
|
307 |
|
|
|
308 |
a93e56c5
|
Matthew Grooms
|
/*
|
309 |
|
|
* Return phase1 local address
|
310 |
|
|
*/
|
311 |
|
|
function ipsec_get_phase1_src(& $ph1ent) {
|
312 |
|
|
|
313 |
25f6730a
|
Pierre POMES
|
if ($ph1ent['interface']) {
|
314 |
d9901ff4
|
Chris Buechler
|
if (substr($ph1ent['interface'], 0, 4) == "_vip") {
|
315 |
2a5960b0
|
Luiz Otavio O Souza
|
$if = $ph1ent['interface'];
|
316 |
d9901ff4
|
Chris Buechler
|
} else {
|
317 |
2a5960b0
|
Luiz Otavio O Souza
|
$if = get_failover_interface($ph1ent['interface']);
|
318 |
d9901ff4
|
Chris Buechler
|
}
|
319 |
|
|
} else {
|
320 |
924876a8
|
Ermal Lu?i
|
$if = "wan";
|
321 |
d9901ff4
|
Chris Buechler
|
}
|
322 |
d1f69741
|
jim-p
|
$ip6 = get_interface_ipv6($if);
|
323 |
|
|
$ip4 = get_interface_ip($if);
|
324 |
d9901ff4
|
Chris Buechler
|
if ($ph1ent['protocol'] == "inet6") {
|
325 |
d1f69741
|
jim-p
|
$interfaceip = $ip6;
|
326 |
|
|
} elseif ($ph1ent['protocol'] == "inet") {
|
327 |
|
|
$interfaceip = $ip4;
|
328 |
|
|
} elseif ($ph1ent['protocol'] == "both") {
|
329 |
|
|
$ifips = array();
|
330 |
|
|
if (!empty($ip4)) {
|
331 |
|
|
$ifips[] = $ip4;
|
332 |
|
|
}
|
333 |
|
|
if (!empty($ip6)) {
|
334 |
|
|
$ifips[] = $ip6;
|
335 |
|
|
}
|
336 |
|
|
$interfaceip = implode(',', $ifips);
|
337 |
d9901ff4
|
Chris Buechler
|
}
|
338 |
a93e56c5
|
Matthew Grooms
|
|
339 |
|
|
return $interfaceip;
|
340 |
|
|
}
|
341 |
|
|
|
342 |
3462a529
|
Matthew Grooms
|
/*
|
343 |
|
|
* Return phase1 local address
|
344 |
|
|
*/
|
345 |
|
|
function ipsec_get_phase1_dst(& $ph1ent) {
|
346 |
df82fae1
|
smos
|
global $g;
|
347 |
2ffafea3
|
Ermal
|
|
348 |
b37a2e8c
|
Phil Davis
|
if (empty($ph1ent['remote-gateway'])) {
|
349 |
2f3554bb
|
jim-p
|
return false;
|
350 |
b37a2e8c
|
Phil Davis
|
}
|
351 |
3462a529
|
Matthew Grooms
|
$rg = $ph1ent['remote-gateway'];
|
352 |
33d5cb7a
|
smos
|
if (!is_ipaddr($rg)) {
|
353 |
086cf944
|
Phil Davis
|
if (!platform_booting()) {
|
354 |
d3ac1cea
|
Viktor G
|
return resolve_retry($rg, $ph1ent['protocol']);
|
355 |
b37a2e8c
|
Phil Davis
|
}
|
356 |
33d5cb7a
|
smos
|
}
|
357 |
b37a2e8c
|
Phil Davis
|
if (!is_ipaddr($rg)) {
|
358 |
0af7398a
|
Matthew Grooms
|
return false;
|
359 |
b37a2e8c
|
Phil Davis
|
}
|
360 |
0af7398a
|
Matthew Grooms
|
|
361 |
3462a529
|
Matthew Grooms
|
return $rg;
|
362 |
|
|
}
|
363 |
|
|
|
364 |
a93e56c5
|
Matthew Grooms
|
/*
|
365 |
|
|
* Return phase2 idinfo in cidr format
|
366 |
|
|
*/
|
367 |
2ffafea3
|
Ermal
|
function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") {
|
368 |
a93e56c5
|
Matthew Grooms
|
global $config;
|
369 |
|
|
|
370 |
2ffafea3
|
Ermal
|
switch ($idinfo['type']) {
|
371 |
a93e56c5
|
Matthew Grooms
|
case "address":
|
372 |
98790f61
|
Seth Mos
|
if ($addrbits) {
|
373 |
b37a2e8c
|
Phil Davis
|
if ($mode == "tunnel6") {
|
374 |
98790f61
|
Seth Mos
|
return $idinfo['address']."/128";
|
375 |
92ab21bb
|
Viktor Gurov
|
} elseif (($mode == "vti") && is_ipaddrv4($idinfo['address'])) {
|
376 |
|
|
return $idinfo['address']."/30";
|
377 |
c519b62f
|
jim-p
|
} elseif (($mode == "vti") && is_ipaddrv6($idinfo['address'])) {
|
378 |
|
|
return $idinfo['address']."/64";
|
379 |
b37a2e8c
|
Phil Davis
|
} else {
|
380 |
98790f61
|
Seth Mos
|
return $idinfo['address']."/32";
|
381 |
b37a2e8c
|
Phil Davis
|
}
|
382 |
086cf944
|
Phil Davis
|
} else {
|
383 |
a93e56c5
|
Matthew Grooms
|
return $idinfo['address'];
|
384 |
086cf944
|
Phil Davis
|
}
|
385 |
2ffafea3
|
Ermal
|
break; /* NOTREACHED */
|
386 |
a93e56c5
|
Matthew Grooms
|
case "network":
|
387 |
2ffafea3
|
Ermal
|
return "{$idinfo['address']}/{$idinfo['netbits']}";
|
388 |
|
|
break; /* NOTREACHED */
|
389 |
63017a73
|
Ermal Lu?i
|
case "none":
|
390 |
3462a529
|
Matthew Grooms
|
case "mobile":
|
391 |
00b56e04
|
Ermal LUÇI
|
return '0.0.0.0/0';
|
392 |
2ffafea3
|
Ermal
|
break; /* NOTREACHED */
|
393 |
a55e9c70
|
Ermal Lu?i
|
default:
|
394 |
b37a2e8c
|
Phil Davis
|
if (empty($mode) && !empty($idinfo['mode'])) {
|
395 |
2ffafea3
|
Ermal
|
$mode = $idinfo['mode'];
|
396 |
b37a2e8c
|
Phil Davis
|
}
|
397 |
2ffafea3
|
Ermal
|
|
398 |
|
|
if ($mode == "tunnel6") {
|
399 |
98790f61
|
Seth Mos
|
$address = get_interface_ipv6($idinfo['type']);
|
400 |
|
|
$netbits = get_interface_subnetv6($idinfo['type']);
|
401 |
086cf944
|
Phil Davis
|
$address = gen_subnetv6($address, $netbits);
|
402 |
2ffafea3
|
Ermal
|
return "{$address}/{$netbits}";
|
403 |
98790f61
|
Seth Mos
|
} else {
|
404 |
|
|
$address = get_interface_ip($idinfo['type']);
|
405 |
|
|
$netbits = get_interface_subnet($idinfo['type']);
|
406 |
086cf944
|
Phil Davis
|
$address = gen_subnet($address, $netbits);
|
407 |
2ffafea3
|
Ermal
|
return "{$address}/{$netbits}";
|
408 |
98790f61
|
Seth Mos
|
}
|
409 |
2ffafea3
|
Ermal
|
break; /* NOTREACHED */
|
410 |
98790f61
|
Seth Mos
|
}
|
411 |
a93e56c5
|
Matthew Grooms
|
}
|
412 |
|
|
|
413 |
|
|
/*
|
414 |
|
|
* Return phase2 idinfo in address/netmask format
|
415 |
|
|
*/
|
416 |
086cf944
|
Phil Davis
|
function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) {
|
417 |
a93e56c5
|
Matthew Grooms
|
global $config;
|
418 |
|
|
|
419 |
2ffafea3
|
Ermal
|
switch ($idinfo['type']) {
|
420 |
a93e56c5
|
Matthew Grooms
|
case "address":
|
421 |
98790f61
|
Seth Mos
|
if ($addrbits) {
|
422 |
b37a2e8c
|
Phil Davis
|
if ($idinfo['mode'] == "tunnel6") {
|
423 |
98790f61
|
Seth Mos
|
return $idinfo['address']."/128";
|
424 |
b37a2e8c
|
Phil Davis
|
} else {
|
425 |
98790f61
|
Seth Mos
|
return $idinfo['address']."/255.255.255.255";
|
426 |
b37a2e8c
|
Phil Davis
|
}
|
427 |
086cf944
|
Phil Davis
|
} else {
|
428 |
a93e56c5
|
Matthew Grooms
|
return $idinfo['address'];
|
429 |
086cf944
|
Phil Davis
|
}
|
430 |
2ffafea3
|
Ermal
|
break; /* NOTREACHED */
|
431 |
63017a73
|
Ermal Lu?i
|
case "none":
|
432 |
a93e56c5
|
Matthew Grooms
|
case "network":
|
433 |
|
|
return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
|
434 |
2ffafea3
|
Ermal
|
break; /* NOTREACHED */
|
435 |
3462a529
|
Matthew Grooms
|
case "mobile":
|
436 |
|
|
return "0.0.0.0/0";
|
437 |
2ffafea3
|
Ermal
|
break; /* NOTREACHED */
|
438 |
63017a73
|
Ermal Lu?i
|
default:
|
439 |
2ffafea3
|
Ermal
|
if ($idinfo['mode'] == "tunnel6") {
|
440 |
98790f61
|
Seth Mos
|
$address = get_interface_ipv6($idinfo['type']);
|
441 |
|
|
$netbits = get_interface_subnetv6($idinfo['type']);
|
442 |
086cf944
|
Phil Davis
|
$address = gen_subnetv6($address, $netbits);
|
443 |
98790f61
|
Seth Mos
|
return $address."/".$netbits;
|
444 |
|
|
} else {
|
445 |
|
|
$address = get_interface_ip($idinfo['type']);
|
446 |
|
|
$netbits = get_interface_subnet($idinfo['type']);
|
447 |
086cf944
|
Phil Davis
|
$address = gen_subnet($address, $netbits);
|
448 |
98790f61
|
Seth Mos
|
return $address."/".$netbits;
|
449 |
|
|
}
|
450 |
2ffafea3
|
Ermal
|
break; /* NOTREACHED */
|
451 |
98790f61
|
Seth Mos
|
}
|
452 |
a93e56c5
|
Matthew Grooms
|
}
|
453 |
|
|
|
454 |
|
|
/*
|
455 |
|
|
* Return phase2 idinfo in text format
|
456 |
|
|
*/
|
457 |
|
|
function ipsec_idinfo_to_text(& $idinfo) {
|
458 |
2ffafea3
|
Ermal
|
global $config;
|
459 |
a93e56c5
|
Matthew Grooms
|
|
460 |
2ffafea3
|
Ermal
|
switch ($idinfo['type']) {
|
461 |
b37a2e8c
|
Phil Davis
|
case "address":
|
462 |
|
|
return $idinfo['address'];
|
463 |
|
|
break; /* NOTREACHED */
|
464 |
|
|
case "network":
|
465 |
|
|
return $idinfo['address']."/".$idinfo['netbits'];
|
466 |
|
|
break; /* NOTREACHED */
|
467 |
|
|
case "mobile":
|
468 |
|
|
return gettext("Mobile Client");
|
469 |
|
|
break; /* NOTREACHED */
|
470 |
|
|
case "none":
|
471 |
|
|
return gettext("None");
|
472 |
|
|
break; /* NOTREACHED */
|
473 |
|
|
default:
|
474 |
|
|
if (!empty($config['interfaces'][$idinfo['type']])) {
|
475 |
|
|
return convert_friendly_interface_to_friendly_descr($idinfo['type']);
|
476 |
|
|
} else {
|
477 |
|
|
return strtoupper($idinfo['type']);
|
478 |
|
|
}
|
479 |
|
|
break; /* NOTREACHED */
|
480 |
2ffafea3
|
Ermal
|
}
|
481 |
a93e56c5
|
Matthew Grooms
|
}
|
482 |
|
|
|
483 |
|
|
/*
|
484 |
|
|
* Return phase1 association for phase2
|
485 |
|
|
*/
|
486 |
086cf944
|
Phil Davis
|
function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) {
|
487 |
2ffafea3
|
Ermal
|
global $config;
|
488 |
|
|
|
489 |
b37a2e8c
|
Phil Davis
|
if (!is_array($config['ipsec'])) {
|
490 |
fe12d7ea
|
Ermal
|
return false;
|
491 |
b37a2e8c
|
Phil Davis
|
}
|
492 |
|
|
if (!is_array($config['ipsec']['phase1'])) {
|
493 |
fe12d7ea
|
Ermal
|
return false;
|
494 |
b37a2e8c
|
Phil Davis
|
}
|
495 |
|
|
if (empty($config['ipsec']['phase1'])) {
|
496 |
fe12d7ea
|
Ermal
|
return false;
|
497 |
b37a2e8c
|
Phil Davis
|
}
|
498 |
2ffafea3
|
Ermal
|
|
499 |
|
|
foreach ($config['ipsec']['phase1'] as $ph1tmp) {
|
500 |
b37a2e8c
|
Phil Davis
|
if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
|
501 |
|
|
$ph1ent = $ph1tmp;
|
502 |
|
|
return $ph1ent;
|
503 |
|
|
}
|
504 |
2ffafea3
|
Ermal
|
}
|
505 |
|
|
|
506 |
|
|
return false;
|
507 |
a93e56c5
|
Matthew Grooms
|
}
|
508 |
|
|
|
509 |
|
|
/*
|
510 |
|
|
* Check phase1 communications status
|
511 |
|
|
*/
|
512 |
ed6e93ea
|
Chris Buechler
|
function ipsec_phase1_status(&$ipsec_status, $ikeid) {
|
513 |
a93e56c5
|
Matthew Grooms
|
|
514 |
39f93e00
|
Ermal
|
foreach ($ipsec_status as $ike) {
|
515 |
17318511
|
Ermal LUÇI
|
if ($ike['id'] == $ikeid) {
|
516 |
b37a2e8c
|
Phil Davis
|
if ($ike['status'] == 'established') {
|
517 |
17318511
|
Ermal LUÇI
|
return true;
|
518 |
b37a2e8c
|
Phil Davis
|
}
|
519 |
17318511
|
Ermal LUÇI
|
}
|
520 |
fe12d7ea
|
Ermal
|
}
|
521 |
a93e56c5
|
Matthew Grooms
|
|
522 |
|
|
return false;
|
523 |
|
|
}
|
524 |
|
|
|
525 |
|
|
/*
|
526 |
|
|
* Check phase2 communications status
|
527 |
|
|
*/
|
528 |
ed6e93ea
|
Chris Buechler
|
function ipsec_phase2_status(&$ipsec_status, &$phase2) {
|
529 |
a93e56c5
|
Matthew Grooms
|
|
530 |
086cf944
|
Phil Davis
|
if (ipsec_lookup_phase1($ph2ent, $ph1ent)) {
|
531 |
fe12d7ea
|
Ermal
|
return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']);
|
532 |
b37a2e8c
|
Phil Davis
|
}
|
533 |
a93e56c5
|
Matthew Grooms
|
|
534 |
|
|
return false;
|
535 |
|
|
}
|
536 |
|
|
|
537 |
1dade399
|
Renato Botelho
|
/*
|
538 |
|
|
* Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled
|
539 |
|
|
*/
|
540 |
|
|
function ipsec_list_sa() {
|
541 |
|
|
|
542 |
4e322e2c
|
Phil Davis
|
if (ipsec_enabled()) {
|
543 |
1dade399
|
Renato Botelho
|
return pfSense_ipsec_list_sa();
|
544 |
4e322e2c
|
Phil Davis
|
}
|
545 |
1dade399
|
Renato Botelho
|
|
546 |
|
|
return array();
|
547 |
|
|
}
|
548 |
|
|
|
549 |
e1c34c69
|
Renato Botelho
|
/*
|
550 |
|
|
* Return dump of SPD table
|
551 |
|
|
*/
|
552 |
|
|
function ipsec_dump_spd() {
|
553 |
|
|
$fd = @popen("/sbin/setkey -DP", "r");
|
554 |
|
|
$spd = array();
|
555 |
|
|
if ($fd) {
|
556 |
|
|
while (!feof($fd)) {
|
557 |
|
|
$line = chop(fgets($fd));
|
558 |
|
|
if (!$line) {
|
559 |
|
|
continue;
|
560 |
|
|
}
|
561 |
|
|
if ($line == "No SPD entries.") {
|
562 |
|
|
break;
|
563 |
|
|
}
|
564 |
|
|
if ($line[0] != "\t") {
|
565 |
|
|
if (is_array($cursp)) {
|
566 |
|
|
$spd[] = $cursp;
|
567 |
|
|
}
|
568 |
|
|
$cursp = array();
|
569 |
|
|
$linea = explode(" ", $line);
|
570 |
|
|
$cursp['srcid'] = substr($linea[0], 0, strpos($linea[0], "["));
|
571 |
|
|
$cursp['dstid'] = substr($linea[1], 0, strpos($linea[1], "["));
|
572 |
|
|
$i = 0;
|
573 |
|
|
} else if (is_array($cursp)) {
|
574 |
|
|
$line = trim($line, "\t\r\n ");
|
575 |
|
|
$linea = explode(" ", $line);
|
576 |
|
|
switch ($i) {
|
577 |
|
|
case 1:
|
578 |
|
|
if ($linea[1] == "none") /* don't show default anti-lockout rule */ {
|
579 |
|
|
unset($cursp);
|
580 |
|
|
} else {
|
581 |
|
|
$cursp['dir'] = $linea[0];
|
582 |
|
|
}
|
583 |
|
|
break;
|
584 |
|
|
case 2:
|
585 |
|
|
$upperspec = explode("/", $linea[0]);
|
586 |
|
|
$cursp['proto'] = $upperspec[0];
|
587 |
|
|
list($cursp['src'], $cursp['dst']) = explode("-", $upperspec[2]);
|
588 |
|
|
$cursp['reqid'] = substr($upperspec[3], strpos($upperspec[3], "#")+1);
|
589 |
|
|
break;
|
590 |
|
|
}
|
591 |
|
|
}
|
592 |
|
|
$i++;
|
593 |
|
|
}
|
594 |
|
|
if (is_array($cursp) && count($cursp)) {
|
595 |
|
|
$spd[] = $cursp;
|
596 |
|
|
}
|
597 |
|
|
pclose($fd);
|
598 |
|
|
}
|
599 |
|
|
|
600 |
|
|
return $spd;
|
601 |
|
|
}
|
602 |
|
|
|
603 |
a93e56c5
|
Matthew Grooms
|
/*
|
604 |
|
|
* Return dump of SAD table
|
605 |
|
|
*/
|
606 |
086cf944
|
Phil Davis
|
function ipsec_dump_sad() {
|
607 |
30c591d6
|
Ermal
|
$fd = @popen("/sbin/setkey -D", "r");
|
608 |
a93e56c5
|
Matthew Grooms
|
$sad = array();
|
609 |
|
|
if ($fd) {
|
610 |
|
|
while (!feof($fd)) {
|
611 |
|
|
$line = chop(fgets($fd));
|
612 |
b37a2e8c
|
Phil Davis
|
if (!$line || $line[0] == " ") {
|
613 |
a93e56c5
|
Matthew Grooms
|
continue;
|
614 |
b37a2e8c
|
Phil Davis
|
}
|
615 |
|
|
if ($line == "No SAD entries.") {
|
616 |
a93e56c5
|
Matthew Grooms
|
break;
|
617 |
b37a2e8c
|
Phil Davis
|
}
|
618 |
|
|
if ($line[0] != "\t") {
|
619 |
|
|
if (is_array($cursa)) {
|
620 |
a93e56c5
|
Matthew Grooms
|
$sad[] = $cursa;
|
621 |
b37a2e8c
|
Phil Davis
|
}
|
622 |
a93e56c5
|
Matthew Grooms
|
$cursa = array();
|
623 |
086cf944
|
Phil Davis
|
list($cursa['src'], $cursa['dst']) = explode(" ", $line);
|
624 |
b37a2e8c
|
Phil Davis
|
} else {
|
625 |
648661c5
|
Ermal LUÇI
|
$line = trim($line, "\t\n\r ");
|
626 |
|
|
$linea = explode(" ", $line);
|
627 |
|
|
foreach ($linea as $idx => $linee) {
|
628 |
b37a2e8c
|
Phil Davis
|
if ($linee == 'esp' || $linee == 'ah' || $linee[0] == '#') {
|
629 |
648661c5
|
Ermal LUÇI
|
$cursa['proto'] = $linee;
|
630 |
b37a2e8c
|
Phil Davis
|
} else if (substr($linee, 0, 3) == 'spi') {
|
631 |
648661c5
|
Ermal LUÇI
|
$cursa['spi'] = substr($linee, strpos($linee, 'x') + 1, -1);
|
632 |
b37a2e8c
|
Phil Davis
|
} else if (substr($linee, 0, 5) == 'reqid') {
|
633 |
648661c5
|
Ermal LUÇI
|
$cursa['reqid'] = substr($linee, strpos($linee, 'x') + 1, -1);
|
634 |
b37a2e8c
|
Phil Davis
|
} else if (substr($linee, 0, 2) == 'E:') {
|
635 |
648661c5
|
Ermal LUÇI
|
$cursa['ealgo'] = $linea[$idx + 1];
|
636 |
a93e56c5
|
Matthew Grooms
|
break;
|
637 |
648661c5
|
Ermal LUÇI
|
} else if (substr($linee, 0, 2) == 'A:') {
|
638 |
|
|
$cursa['aalgo'] = $linea[$idx + 1];
|
639 |
a93e56c5
|
Matthew Grooms
|
break;
|
640 |
648661c5
|
Ermal LUÇI
|
} else if (substr($linee, 0, 8) == 'current:') {
|
641 |
|
|
$cursa['data'] = substr($linea[$idx + 1], 0, strpos($linea[$idx + 1], 'bytes') - 1) . ' B';
|
642 |
f451ea09
|
jim-p
|
break;
|
643 |
648661c5
|
Ermal LUÇI
|
}
|
644 |
a93e56c5
|
Matthew Grooms
|
}
|
645 |
|
|
}
|
646 |
|
|
}
|
647 |
b37a2e8c
|
Phil Davis
|
if (is_array($cursa) && count($cursa)) {
|
648 |
a93e56c5
|
Matthew Grooms
|
$sad[] = $cursa;
|
649 |
b37a2e8c
|
Phil Davis
|
}
|
650 |
a93e56c5
|
Matthew Grooms
|
pclose($fd);
|
651 |
|
|
}
|
652 |
|
|
|
653 |
|
|
return $sad;
|
654 |
|
|
}
|
655 |
|
|
|
656 |
6e0b68bf
|
jim-p
|
/*
|
657 |
|
|
* Return dump of mobile user list
|
658 |
|
|
*/
|
659 |
|
|
function ipsec_dump_mobile() {
|
660 |
33927941
|
PiBa-NL
|
global $g, $config;
|
661 |
ed5fc757
|
Ermal
|
|
662 |
33927941
|
PiBa-NL
|
if(!isset($config['ipsec']['client']['enable'])) {
|
663 |
|
|
return array();
|
664 |
|
|
}
|
665 |
0be9d722
|
Steve Beaver
|
|
666 |
c6220dcf
|
jim-p
|
/* Fetch the pool contents and leases from swanctl. */
|
667 |
|
|
$_gb = exec("/usr/local/sbin/swanctl --list-pools --leases 2>/dev/null", $output, $rc);
|
668 |
6e0b68bf
|
jim-p
|
|
669 |
796b7651
|
Renato Botelho
|
if ($rc != 0) {
|
670 |
276efd64
|
Chris Buechler
|
log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!"));
|
671 |
7ab6ad70
|
Ermal
|
return array();
|
672 |
6e0b68bf
|
jim-p
|
}
|
673 |
|
|
|
674 |
c6220dcf
|
jim-p
|
$response = array(
|
675 |
|
|
'pool' => array(),
|
676 |
|
|
);
|
677 |
796b7651
|
Renato Botelho
|
|
678 |
c6220dcf
|
jim-p
|
/* swanctl --list-pools --leases example output, field names can be confirmed by
|
679 |
|
|
* looking at --raw or --pretty output. */
|
680 |
|
|
/* mobile-pool 10.7.200.0 0 / 1 / 254 */
|
681 |
|
|
$pool_regex='/^(?P<name>\S+)\s+(?P<base>\S+)\s+(?P<online>\d+) \/ (?P<offline>\d+) \/ (?P<size>\d+)/';
|
682 |
|
|
/* 10.7.200.1 online 'jimp' */
|
683 |
|
|
$lease_regex='/\s*(?P<host>[\d\.]+)\s+(?P<status>online|offline)\s+\'(?P<id>.*)\'/';
|
684 |
796b7651
|
Renato Botelho
|
foreach ($output as $line) {
|
685 |
c6220dcf
|
jim-p
|
if (preg_match($pool_regex, $line, $matches)) {
|
686 |
796b7651
|
Renato Botelho
|
$id++;
|
687 |
|
|
$response['pool'][$id] = array(
|
688 |
|
|
'name' => $matches['name'],
|
689 |
c6220dcf
|
jim-p
|
'base' => $matches['base'],
|
690 |
796b7651
|
Renato Botelho
|
'online' => $matches['online'],
|
691 |
c6220dcf
|
jim-p
|
'offline' => $matches['offline'],
|
692 |
|
|
'size' => $matches['size'],
|
693 |
|
|
);
|
694 |
|
|
} elseif (preg_match($lease_regex, $line, $matches)) {
|
695 |
|
|
$response['pool'][$id]['lease'][] = array(
|
696 |
|
|
'host' => $matches['host'],
|
697 |
|
|
'status' => $matches['status'],
|
698 |
|
|
'id' => $matches['id']
|
699 |
796b7651
|
Renato Botelho
|
);
|
700 |
|
|
}
|
701 |
f3e15492
|
Renato Botelho
|
}
|
702 |
|
|
|
703 |
c6220dcf
|
jim-p
|
unset($_gb, $output, $rc, $pool_regex);
|
704 |
7ab6ad70
|
Ermal
|
|
705 |
|
|
return $response;
|
706 |
6e0b68bf
|
jim-p
|
}
|
707 |
|
|
|
708 |
958420c5
|
jim-p
|
function ipsec_mobilekey_sort() {
|
709 |
|
|
global $config;
|
710 |
|
|
|
711 |
|
|
function mobilekeycmp($a, $b) {
|
712 |
|
|
return strcmp($a['ident'][0], $b['ident'][0]);
|
713 |
|
|
}
|
714 |
|
|
|
715 |
|
|
usort($config['ipsec']['mobilekey'], "mobilekeycmp");
|
716 |
|
|
}
|
717 |
|
|
|
718 |
8f5c3d8d
|
Pierre POMES
|
function ipsec_get_number_of_phase2($ikeid) {
|
719 |
|
|
global $config;
|
720 |
b37a2e8c
|
Phil Davis
|
$a_phase2 = $config['ipsec']['phase2'];
|
721 |
8f5c3d8d
|
Pierre POMES
|
|
722 |
6c07db48
|
Phil Davis
|
$nbph2 = 0;
|
723 |
8f5c3d8d
|
Pierre POMES
|
|
724 |
b37a2e8c
|
Phil Davis
|
if (is_array($a_phase2) && count($a_phase2)) {
|
725 |
|
|
foreach ($a_phase2 as $ph2tmp) {
|
726 |
|
|
if ($ph2tmp['ikeid'] == $ikeid) {
|
727 |
8f5c3d8d
|
Pierre POMES
|
$nbph2++;
|
728 |
|
|
}
|
729 |
|
|
}
|
730 |
|
|
}
|
731 |
|
|
|
732 |
|
|
return $nbph2;
|
733 |
|
|
}
|
734 |
|
|
|
735 |
859a5304
|
Renato Botelho
|
function ipsec_get_descr($ikeid) {
|
736 |
|
|
global $config;
|
737 |
|
|
|
738 |
|
|
if (!isset($config['ipsec']['phase1']) ||
|
739 |
b37a2e8c
|
Phil Davis
|
!is_array($config['ipsec']['phase1'])) {
|
740 |
c607f306
|
Ermal LUÇI
|
return '';
|
741 |
b37a2e8c
|
Phil Davis
|
}
|
742 |
859a5304
|
Renato Botelho
|
|
743 |
c607f306
|
Ermal LUÇI
|
foreach ($config['ipsec']['phase1'] as $p1) {
|
744 |
859a5304
|
Renato Botelho
|
if ($p1['ikeid'] == $ikeid) {
|
745 |
c607f306
|
Ermal LUÇI
|
return $p1['descr'];
|
746 |
859a5304
|
Renato Botelho
|
}
|
747 |
|
|
}
|
748 |
|
|
|
749 |
c607f306
|
Ermal LUÇI
|
return '';
|
750 |
859a5304
|
Renato Botelho
|
}
|
751 |
|
|
|
752 |
483c3b5b
|
Ermal LUÇI
|
function ipsec_get_phase1($ikeid) {
|
753 |
b37a2e8c
|
Phil Davis
|
global $config;
|
754 |
|
|
|
755 |
|
|
if (!isset($config['ipsec']['phase1']) ||
|
756 |
|
|
!is_array($config['ipsec']['phase1'])) {
|
757 |
|
|
return '';
|
758 |
|
|
}
|
759 |
|
|
|
760 |
|
|
$a_phase1 = $config['ipsec']['phase1'];
|
761 |
|
|
foreach ($a_phase1 as $p1) {
|
762 |
|
|
if ($p1['ikeid'] == $ikeid) {
|
763 |
|
|
return $p1;
|
764 |
|
|
}
|
765 |
|
|
}
|
766 |
|
|
unset($a_phase1);
|
767 |
483c3b5b
|
Ermal LUÇI
|
}
|
768 |
|
|
|
769 |
3ec026a4
|
jim-p
|
function ipsec_fixup_ip($ipaddr) {
|
770 |
b37a2e8c
|
Phil Davis
|
if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) {
|
771 |
587995fb
|
Phil Davis
|
return text_to_compressed_ip6($ipaddr);
|
772 |
b37a2e8c
|
Phil Davis
|
} else {
|
773 |
3ec026a4
|
jim-p
|
return $ipaddr;
|
774 |
b37a2e8c
|
Phil Davis
|
}
|
775 |
3ec026a4
|
jim-p
|
}
|
776 |
|
|
|
777 |
95589abd
|
jim-p
|
function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) {
|
778 |
|
|
if ($side == "local") {
|
779 |
|
|
$id_type = $ph1ent['myid_type'];
|
780 |
|
|
$id_data = $ph1ent['myid_data'];
|
781 |
|
|
|
782 |
|
|
$addr = ipsec_get_phase1_src($ph1ent);
|
783 |
b37a2e8c
|
Phil Davis
|
if (!$addr) {
|
784 |
95589abd
|
jim-p
|
return array();
|
785 |
b37a2e8c
|
Phil Davis
|
}
|
786 |
d1f69741
|
jim-p
|
/* When automatically guessing, use the first address. */
|
787 |
|
|
$addr = explode(',', $addr);
|
788 |
|
|
$addr = $addr[0];
|
789 |
664aef0b
|
Chris Buechler
|
} elseif ($side == "peer") {
|
790 |
95589abd
|
jim-p
|
$id_type = $ph1ent['peerid_type'];
|
791 |
|
|
$id_data = $ph1ent['peerid_data'];
|
792 |
|
|
|
793 |
b37a2e8c
|
Phil Davis
|
if (isset($ph1ent['mobile'])) {
|
794 |
95589abd
|
jim-p
|
$addr = "%any";
|
795 |
b37a2e8c
|
Phil Davis
|
} else {
|
796 |
95589abd
|
jim-p
|
$addr = $ph1ent['remote-gateway'];
|
797 |
b37a2e8c
|
Phil Davis
|
}
|
798 |
|
|
} else {
|
799 |
95589abd
|
jim-p
|
return array();
|
800 |
b37a2e8c
|
Phil Davis
|
}
|
801 |
95589abd
|
jim-p
|
|
802 |
|
|
|
803 |
|
|
$thisid_type = $id_type;
|
804 |
|
|
switch ($thisid_type) {
|
805 |
b37a2e8c
|
Phil Davis
|
case 'myaddress':
|
806 |
|
|
$thisid_type = 'address';
|
807 |
|
|
$thisid_data = $addr;
|
808 |
|
|
break;
|
809 |
|
|
case 'dyn_dns':
|
810 |
|
|
$thisid_type = 'dns';
|
811 |
|
|
$thisid_data = $id_data;
|
812 |
|
|
break;
|
813 |
|
|
case 'peeraddress':
|
814 |
|
|
$thisid_type = 'address';
|
815 |
|
|
$thisid_data = $rgmap[$ph1ent['remote-gateway']];
|
816 |
|
|
break;
|
817 |
|
|
case 'address':
|
818 |
|
|
$thisid_data = $id_data;
|
819 |
|
|
break;
|
820 |
|
|
case 'fqdn':
|
821 |
|
|
$thisid_data = "{$id_data}";
|
822 |
|
|
break;
|
823 |
|
|
case 'keyid tag':
|
824 |
|
|
$thisid_type = 'keyid';
|
825 |
10439116
|
Bruno Thomsen
|
$thisid_data = "{$id_data}";
|
826 |
b37a2e8c
|
Phil Davis
|
break;
|
827 |
|
|
case 'user_fqdn':
|
828 |
|
|
$thisid_type = 'userfqdn';
|
829 |
|
|
$thisid_data = "{$id_data}";
|
830 |
|
|
break;
|
831 |
|
|
case 'asn1dn':
|
832 |
|
|
$thisid_data = $id_data;
|
833 |
|
|
break;
|
834 |
95589abd
|
jim-p
|
}
|
835 |
|
|
return array($thisid_type, $thisid_data);
|
836 |
|
|
}
|
837 |
060c3ac0
|
Renato Botelho
|
|
838 |
3a73fc74
|
jim-p
|
/*
|
839 |
|
|
* Fixup ID type/data to include prefix when necessary, add quotes, etc.
|
840 |
|
|
*/
|
841 |
|
|
function ipsec_fixup_id($type, $data) {
|
842 |
|
|
/* List of types to pass through as-is without changes or adding prefix */
|
843 |
|
|
$auto_types = array('address');
|
844 |
|
|
/* List of types which need the resulting string double quoted. */
|
845 |
|
|
$quote_types = array('keyid', 'asn1dn');
|
846 |
|
|
|
847 |
|
|
/* If the first character of asn1dn type data is not #, then rely on
|
848 |
|
|
* automatic parsing https://redmine.pfsense.org/issues/4792 */
|
849 |
|
|
if (($type == 'asn1dn') && !empty($data) && ($data[0] != '#')) {
|
850 |
|
|
$auto_types[] = 'asn1dn';
|
851 |
|
|
}
|
852 |
|
|
|
853 |
|
|
if ($type == 'any') {
|
854 |
|
|
$idstring = "";
|
855 |
|
|
} elseif (!in_array($type, $auto_types)) {
|
856 |
|
|
$idstring = "{$type}:{$data}";
|
857 |
|
|
} else {
|
858 |
|
|
$idstring = $data;
|
859 |
|
|
}
|
860 |
|
|
|
861 |
|
|
if (in_array($type, $quote_types)) {
|
862 |
|
|
$idstring = "\"{$idstring}\"";
|
863 |
|
|
}
|
864 |
|
|
|
865 |
|
|
return $idstring;
|
866 |
|
|
}
|
867 |
|
|
|
868 |
060c3ac0
|
Renato Botelho
|
function ipsec_fixup_network($network) {
|
869 |
b37a2e8c
|
Phil Davis
|
if (substr($network, -3) == '|/0') {
|
870 |
060c3ac0
|
Renato Botelho
|
$result = substr($network, 0, -3);
|
871 |
b37a2e8c
|
Phil Davis
|
} else {
|
872 |
060c3ac0
|
Renato Botelho
|
$tmp = explode('|', $network);
|
873 |
b37a2e8c
|
Phil Davis
|
if (isset($tmp[1])) {
|
874 |
060c3ac0
|
Renato Botelho
|
$result = $tmp[1];
|
875 |
b37a2e8c
|
Phil Davis
|
} else {
|
876 |
060c3ac0
|
Renato Botelho
|
$result = $tmp[0];
|
877 |
b37a2e8c
|
Phil Davis
|
}
|
878 |
060c3ac0
|
Renato Botelho
|
unset($tmp);
|
879 |
|
|
}
|
880 |
|
|
|
881 |
|
|
return $result;
|
882 |
|
|
}
|
883 |
|
|
|
884 |
1fe208ec
|
Ermal LUÇI
|
function ipsec_new_reqid() {
|
885 |
|
|
global $config;
|
886 |
|
|
|
887 |
b37a2e8c
|
Phil Davis
|
if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) {
|
888 |
1fe208ec
|
Ermal LUÇI
|
return;
|
889 |
b37a2e8c
|
Phil Davis
|
}
|
890 |
1fe208ec
|
Ermal LUÇI
|
|
891 |
|
|
$ipsecreqid = lock('ipsecreqids', LOCK_EX);
|
892 |
|
|
$keyids = array();
|
893 |
|
|
$keyid = 1;
|
894 |
b37a2e8c
|
Phil Davis
|
foreach ($config['ipsec']['phase2'] as $ph2) {
|
895 |
1fe208ec
|
Ermal LUÇI
|
$keyids[$ph2['reqid']] = $ph2['reqid'];
|
896 |
b37a2e8c
|
Phil Davis
|
}
|
897 |
1fe208ec
|
Ermal LUÇI
|
|
898 |
|
|
for ($i = 1; $i < 16000; $i++) {
|
899 |
|
|
if (!isset($keyids[$i])) {
|
900 |
|
|
$keyid = $i;
|
901 |
|
|
break;
|
902 |
|
|
}
|
903 |
|
|
}
|
904 |
|
|
unlock($ipsecreqid);
|
905 |
|
|
|
906 |
|
|
return $keyid;
|
907 |
|
|
}
|
908 |
|
|
|
909 |
e470f721
|
jim-p
|
function ipsec_get_loglevels() {
|
910 |
|
|
global $config, $ipsec_log_cats;
|
911 |
|
|
$def_loglevel = '1';
|
912 |
|
|
|
913 |
|
|
$levels = array();
|
914 |
|
|
|
915 |
|
|
foreach (array_keys($ipsec_log_cats) as $cat) {
|
916 |
|
|
if (isset($config['ipsec']['logging'][$cat])) {
|
917 |
|
|
$levels[$cat] = $config['ipsec']['logging'][$cat];
|
918 |
|
|
} elseif (in_array($cat, array('ike', 'chd', 'cfg'))) {
|
919 |
|
|
$levels[$cat] = "2";
|
920 |
|
|
} else {
|
921 |
|
|
$levels[$cat] = $def_loglevel;
|
922 |
|
|
}
|
923 |
|
|
}
|
924 |
|
|
return $levels;
|
925 |
|
|
}
|
926 |
bd4c337c
|
jim-p
|
|
927 |
903826b5
|
Viktor Gurov
|
function ipsec_vti($ph1ent, $returnaddresses = false, $skipdisabled = true) {
|
928 |
bd4c337c
|
jim-p
|
global $config;
|
929 |
|
|
if (empty($ph1ent) || !is_array($ph1ent) || !is_array($config['ipsec']['phase2'])) {
|
930 |
|
|
return false;
|
931 |
|
|
}
|
932 |
|
|
|
933 |
|
|
$is_vti = false;
|
934 |
|
|
$vtisubnet_spec = array();
|
935 |
|
|
|
936 |
|
|
foreach ($config['ipsec']['phase2'] as $ph2ent) {
|
937 |
|
|
if ($ph1ent['ikeid'] != $ph2ent['ikeid']) {
|
938 |
|
|
continue;
|
939 |
|
|
}
|
940 |
|
|
if ($ph2ent['mode'] == 'vti') {
|
941 |
|
|
if ($returnaddresses) {
|
942 |
|
|
$vtisubnet_spec[] = array(
|
943 |
65767828
|
jim-p
|
'left' => ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']),
|
944 |
bd4c337c
|
jim-p
|
'right' => ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']),
|
945 |
235c051f
|
jim-p
|
'descr' => $ph2ent['descr'],
|
946 |
bd4c337c
|
jim-p
|
);
|
947 |
|
|
}
|
948 |
903826b5
|
Viktor Gurov
|
if (!$skipdisabled && isset($ph2ent['disabled'])) {
|
949 |
|
|
continue;
|
950 |
|
|
} else {
|
951 |
|
|
$is_vti = true;
|
952 |
|
|
}
|
953 |
bd4c337c
|
jim-p
|
}
|
954 |
|
|
}
|
955 |
|
|
return ($returnaddresses) ? $vtisubnet_spec : $is_vti;
|
956 |
|
|
}
|
957 |
|
|
|
958 |
a264f870
|
jim-p
|
/* Called when IPsec is reloaded through rc.newipsecdns and similar, gives
|
959 |
|
|
* packages an opportunity to execute custom code when IPsec reloads.
|
960 |
|
|
*/
|
961 |
|
|
function ipsec_reload_package_hook() {
|
962 |
|
|
global $g, $config;
|
963 |
81f19e11
|
jim-p
|
|
964 |
|
|
init_config_arr(array('installedpackages', 'package'));
|
965 |
a264f870
|
jim-p
|
foreach ($config['installedpackages']['package'] as $package) {
|
966 |
|
|
if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
|
967 |
|
|
continue;
|
968 |
|
|
}
|
969 |
|
|
|
970 |
|
|
$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
|
971 |
|
|
if (!empty($pkg_config['include_file']) &&
|
972 |
|
|
file_exists($pkg_config['include_file'])) {
|
973 |
|
|
require_once($pkg_config['include_file']);
|
974 |
|
|
}
|
975 |
|
|
if (empty($pkg_config['ipsec_reload_function'])) {
|
976 |
|
|
continue;
|
977 |
|
|
}
|
978 |
|
|
$pkg_ipsec_reload = $pkg_config['ipsec_reload_function'];
|
979 |
|
|
if (!function_exists($pkg_ipsec_reload)) {
|
980 |
|
|
continue;
|
981 |
|
|
}
|
982 |
|
|
$pkg_ipsec_reload();
|
983 |
|
|
}
|
984 |
|
|
}
|
985 |
|
|
|
986 |
c6220dcf
|
jim-p
|
/****f* certs/ipsec_convert_to_modp
|
987 |
|
|
* NAME
|
988 |
|
|
* ipsec_convert_to_modp - Take a DH Group number value and return the
|
989 |
|
|
* associated name
|
990 |
|
|
* INPUTS
|
991 |
|
|
* $index: DH group index number to look up
|
992 |
|
|
* RESULT
|
993 |
|
|
* Returns the Diffie Hellman Group keyword associated with the group number.
|
994 |
|
|
******/
|
995 |
|
|
function ipsec_convert_to_modp($index) {
|
996 |
|
|
$modpmap = array(
|
997 |
|
|
'1' => 'modp768',
|
998 |
|
|
'2' => 'modp1024',
|
999 |
|
|
'5' => 'modp1536',
|
1000 |
|
|
'14' => 'modp2048',
|
1001 |
|
|
'15' => 'modp3072',
|
1002 |
|
|
'16' => 'modp4096',
|
1003 |
|
|
'17' => 'modp6144',
|
1004 |
|
|
'18' => 'modp8192',
|
1005 |
|
|
'19' => 'ecp256',
|
1006 |
|
|
'20' => 'ecp384',
|
1007 |
|
|
'21' => 'ecp521',
|
1008 |
|
|
'22' => 'modp1024s160',
|
1009 |
|
|
'23' => 'modp2048s224',
|
1010 |
|
|
'24' => 'modp2048s256',
|
1011 |
|
|
'25' => 'ecp192',
|
1012 |
|
|
'26' => 'ecp224',
|
1013 |
|
|
'27' => 'ecp224bp',
|
1014 |
|
|
'28' => 'ecp256bp',
|
1015 |
|
|
'29' => 'ecp384bp',
|
1016 |
|
|
'30' => 'ecp512bp',
|
1017 |
|
|
'31' => 'curve25519',
|
1018 |
|
|
'32' => 'curve448',
|
1019 |
|
|
);
|
1020 |
|
|
|
1021 |
|
|
return $modpmap[$index];
|
1022 |
|
|
}
|
1023 |
|
|
|
1024 |
|
|
/*
|
1025 |
|
|
* Forcefully restart IPsec
|
1026 |
|
|
* This is required for when dynamic interfaces reload
|
1027 |
|
|
* For all other occasions the normal ipsec_configure()
|
1028 |
|
|
* will gracefully reload the settings without restarting
|
1029 |
|
|
*/
|
1030 |
|
|
function ipsec_force_reload($interface = "") {
|
1031 |
|
|
global $g, $config;
|
1032 |
|
|
|
1033 |
|
|
if (!ipsec_enabled()) {
|
1034 |
|
|
return;
|
1035 |
|
|
}
|
1036 |
|
|
|
1037 |
|
|
$ipseccfg = $config['ipsec'];
|
1038 |
|
|
|
1039 |
|
|
if (!empty($interface) && is_array($ipseccfg['phase1'])) {
|
1040 |
|
|
$found = false;
|
1041 |
|
|
foreach ($ipseccfg['phase1'] as $ipsec) {
|
1042 |
|
|
if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
|
1043 |
|
|
$found = true;
|
1044 |
|
|
break;
|
1045 |
|
|
}
|
1046 |
|
|
}
|
1047 |
|
|
if (!$found) {
|
1048 |
|
|
log_error(sprintf(gettext("Ignoring IPsec reload since there are no tunnels on interface %s"), $interface));
|
1049 |
|
|
return;
|
1050 |
|
|
}
|
1051 |
|
|
}
|
1052 |
|
|
|
1053 |
|
|
/* If we get this far then we need to take action. */
|
1054 |
|
|
log_error(gettext("Forcefully reloading IPsec"));
|
1055 |
|
|
ipsec_configure();
|
1056 |
|
|
}
|
1057 |
|
|
|
1058 |
|
|
/****f* ipsec/ipsec_strongswan_confgen
|
1059 |
|
|
* NAME
|
1060 |
|
|
* ipsec_strongswan_confgen - Generate strongswan.conf style formatted output
|
1061 |
|
|
* From a multi-dimensional array.
|
1062 |
|
|
* INPUTS
|
1063 |
|
|
* $confarr: An array of key=value pairs or key=array entries for subsections.
|
1064 |
|
|
* $indent : A string of tabs used when indenting lines.
|
1065 |
|
|
* RESULT
|
1066 |
|
|
* Returns a string of key=value pairs with proper indenting, and with named
|
1067 |
|
|
* subsections enclosed in braces.
|
1068 |
|
|
* NOTES
|
1069 |
|
|
* Values starting with a "#" (comments) or "include " will be printed
|
1070 |
|
|
* directly without their associated key name.
|
1071 |
|
|
******/
|
1072 |
|
|
function ipsec_strongswan_confgen($confarr, $indent = "") {
|
1073 |
|
|
$confstr = "";
|
1074 |
|
|
/* Only process the contents if it's an array. */
|
1075 |
|
|
if (is_array($confarr)) {
|
1076 |
|
|
foreach ($confarr as $key => $value) {
|
1077 |
|
|
if (is_array($value)) {
|
1078 |
|
|
/* If the array is empty, do not print anything */
|
1079 |
|
|
if (empty($value)) {
|
1080 |
|
|
continue;
|
1081 |
|
|
}
|
1082 |
|
|
/* If this is an array, setup the subsection name
|
1083 |
|
|
* and structure, then call this function
|
1084 |
|
|
* recursively to walk the lower array. */
|
1085 |
|
|
$confstr .= "{$indent}{$key} {\n";
|
1086 |
|
|
$confstr .= ipsec_strongswan_confgen($value, $indent . "\t");
|
1087 |
|
|
$confstr .= "{$indent}}\n";
|
1088 |
|
|
} else {
|
1089 |
|
|
$confstr .= "{$indent}";
|
1090 |
|
|
if ((substr($value, 0 , 1) != '#') &&
|
1091 |
|
|
(substr($value, 0 , 8) != 'include ')) {
|
1092 |
|
|
/* Not a comment or include, print the key */
|
1093 |
|
|
$confstr .= "{$key} = ";
|
1094 |
|
|
}
|
1095 |
|
|
$confstr .= "{$value}\n";
|
1096 |
|
|
}
|
1097 |
|
|
}
|
1098 |
|
|
}
|
1099 |
|
|
return $confstr;
|
1100 |
|
|
}
|
1101 |
|
|
|
1102 |
|
|
global $g, $ipsec_swanctl_basedir, $ipsec_swanctl_dirs;
|
1103 |
|
|
$ipsec_swanctl_basedir = "{$g['varetc_path']}/ipsec";
|
1104 |
|
|
$ipsec_swanctl_dirs = array(
|
1105 |
|
|
'conf' => "{$ipsec_swanctl_basedir}/conf.d",
|
1106 |
|
|
'certpath' => "{$ipsec_swanctl_basedir}/x509",
|
1107 |
|
|
'capath' => "{$ipsec_swanctl_basedir}/x509ca",
|
1108 |
|
|
'aapath' => "{$ipsec_swanctl_basedir}/x509aa",
|
1109 |
|
|
'ocsppath' => "{$ipsec_swanctl_basedir}/x509ocsp",
|
1110 |
|
|
'crlpath' => "{$ipsec_swanctl_basedir}/x509crl",
|
1111 |
|
|
'acpath' => "{$ipsec_swanctl_basedir}/x509ac",
|
1112 |
|
|
'rsakeys' => "{$ipsec_swanctl_basedir}/rsa",
|
1113 |
|
|
'eckeys' => "{$ipsec_swanctl_basedir}/ecdsa",
|
1114 |
|
|
'keypath' => "{$ipsec_swanctl_basedir}/private",
|
1115 |
|
|
'pubkpath' => "{$ipsec_swanctl_basedir}/pubkey",
|
1116 |
|
|
'blisspath' => "{$ipsec_swanctl_basedir}/bliss",
|
1117 |
|
|
'pkcs8path' => "{$ipsec_swanctl_basedir}/pkcs8",
|
1118 |
|
|
'pkcs12path' => "{$ipsec_swanctl_basedir}/pkcs12",
|
1119 |
|
|
);
|
1120 |
|
|
|
1121 |
|
|
/****f* ipsec/ipsec_create_dirs
|
1122 |
|
|
* NAME
|
1123 |
|
|
* ipsec_create_dirs - Create default set of strongSwan configuration directories.
|
1124 |
|
|
* INPUTS
|
1125 |
|
|
* None
|
1126 |
|
|
* RESULT
|
1127 |
|
|
* Cleans up and creates strongSwan configuration directories and links.
|
1128 |
|
|
******/
|
1129 |
|
|
function ipsec_create_dirs() {
|
1130 |
|
|
global $config, $g, $ipsec_swanctl_basedir, $ipsec_swanctl_dirs;
|
1131 |
|
|
|
1132 |
|
|
/* Cleanup base paths to ensure old files are not left behind (#5238) */
|
1133 |
|
|
if (!empty($ipsec_swanctl_basedir)) {
|
1134 |
|
|
@rmdir_recursive($ipsec_swanctl_basedir, false);
|
1135 |
|
|
}
|
1136 |
|
|
/* Create directory structure */
|
1137 |
|
|
array_map('safe_mkdir', array_values($ipsec_swanctl_dirs));
|
1138 |
|
|
|
1139 |
|
|
/* Create and link strongSwan config */
|
1140 |
|
|
$ssdpath = "{$g['varetc_path']}/ipsec/strongswan.d";
|
1141 |
|
|
if (!file_exists($ssdpath) || !is_link($ssdpath)) {
|
1142 |
|
|
if (is_dir($ssdpath) && !is_link($ssdpath)) {
|
1143 |
|
|
@rmdir_recursive($ssdpath, false);
|
1144 |
|
|
} else {
|
1145 |
|
|
@unlink($ssdpath);
|
1146 |
|
|
}
|
1147 |
|
|
@symlink("/usr/local/etc/strongswan.d",
|
1148 |
|
|
$ssdpath);
|
1149 |
|
|
}
|
1150 |
|
|
if (!file_exists("/usr/local/etc/strongswan.conf") ||
|
1151 |
|
|
!is_link("/usr/local/etc/strongswan.conf")) {
|
1152 |
|
|
@unlink("/usr/local/etc/strongswan.conf");
|
1153 |
|
|
@symlink("{$g['varetc_path']}/ipsec/strongswan.conf",
|
1154 |
|
|
"/usr/local/etc/strongswan.conf");
|
1155 |
|
|
}
|
1156 |
|
|
}
|
1157 |
|
|
|
1158 |
|
|
/****f* ipsec/ipsec_setup_gwifs
|
1159 |
|
|
* NAME
|
1160 |
|
|
* ipsec_setup_gwifs - Setup IPsec-related interfaces and gateways
|
1161 |
|
|
* INPUTS
|
1162 |
|
|
* None
|
1163 |
|
|
* RESULT
|
1164 |
|
|
* Sets up VTI interfaces and gateways, populates ipsecpinghosts
|
1165 |
|
|
******/
|
1166 |
|
|
function ipsec_setup_gwifs() {
|
1167 |
|
|
global $g, $a_phase1, $a_phase2, $rgmap, $filterdns_list,
|
1168 |
|
|
$aggressive_mode_psk, $mobile_ipsec_auth, $ifacesuse,
|
1169 |
|
|
$ipsecpinghostsactive;
|
1170 |
|
|
/* resolve all local, peer addresses and setup pings */
|
1171 |
|
|
unset($iflist);
|
1172 |
|
|
if (is_array($a_phase1) && count($a_phase1)) {
|
1173 |
|
|
$ipsecpinghosts = array();
|
1174 |
|
|
/* step through each phase1 entry */
|
1175 |
|
|
foreach ($a_phase1 as $ph1ent) {
|
1176 |
|
|
if (isset($ph1ent['disabled'])) {
|
1177 |
|
|
continue;
|
1178 |
|
|
}
|
1179 |
|
|
|
1180 |
|
|
if (substr($ph1ent['interface'], 0, 4) == "_vip") {
|
1181 |
|
|
$vpninterface = get_configured_vip_interface($ph1ent['interface']);
|
1182 |
|
|
$ifacesuse[] = get_real_interface($vpninterface);
|
1183 |
|
|
} else {
|
1184 |
|
|
$vpninterface = get_failover_interface($ph1ent['interface']);
|
1185 |
|
|
if (substr($vpninterface, 0, 4) == "_vip") {
|
1186 |
|
|
$vpninterface = get_configured_vip_interface($vpninterface);
|
1187 |
|
|
$ifacesuse[] = get_real_interface($vpninterface);
|
1188 |
|
|
} elseif (!empty($vpninterface)) {
|
1189 |
|
|
$ifacesuse[] = $vpninterface;
|
1190 |
|
|
}
|
1191 |
|
|
}
|
1192 |
|
|
|
1193 |
|
|
if ($ph1ent['mode'] == "aggressive" && ($ph1ent['authentication_method'] == "pre_shared_key" || $ph1ent['authentication_method'] == "xauth_psk_server")) {
|
1194 |
|
|
$aggressive_mode_psk = true;
|
1195 |
|
|
}
|
1196 |
|
|
|
1197 |
|
|
$ikeid = $ph1ent['ikeid'];
|
1198 |
|
|
|
1199 |
|
|
$local_spec = ipsec_get_phase1_src($ph1ent);
|
1200 |
|
|
/* When automatically guessing, use the first address. */
|
1201 |
|
|
$local_spec = explode(',', $local_spec);
|
1202 |
|
|
$local_spec = $local_spec[0];
|
1203 |
|
|
if (!is_ipaddr($local_spec)) {
|
1204 |
|
|
log_error(sprintf(gettext("IPsec ERROR: Could not find phase 1 source for connection %s. Omitting from configuration file."), $ph1ent['descr']));
|
1205 |
|
|
continue;
|
1206 |
|
|
}
|
1207 |
|
|
|
1208 |
|
|
if (isset($ph1ent['mobile'])) {
|
1209 |
|
|
$mobile_ipsec_auth = $ph1ent['authentication_method'];
|
1210 |
|
|
continue;
|
1211 |
|
|
}
|
1212 |
|
|
|
1213 |
|
|
/* see if this tunnel has a hostname for the remote-gateway. If so,
|
1214 |
|
|
try to resolve it now and add it to the list for filterdns */
|
1215 |
|
|
$rg = $ph1ent['remote-gateway'];
|
1216 |
|
|
if (!is_ipaddr($rg)) {
|
1217 |
|
|
$filterdns_list[] = "{$rg}";
|
1218 |
|
|
add_hostname_to_watch($rg);
|
1219 |
|
|
if (!platform_booting()) {
|
1220 |
d3ac1cea
|
Viktor G
|
$rg = resolve_retry($rg, $ph1ent['protocol']);
|
1221 |
c6220dcf
|
jim-p
|
}
|
1222 |
|
|
if (!is_ipaddr($rg)) {
|
1223 |
|
|
continue;
|
1224 |
|
|
}
|
1225 |
|
|
}
|
1226 |
d0cd4fc7
|
Frederic Bor
|
if (!isset($ph1ent['gw_duplicates']) && array_search($rg, $rgmap)) {
|
1227 |
c6220dcf
|
jim-p
|
log_error(sprintf(gettext("The remote gateway %s already exists on another phase 1 entry"), $rg));
|
1228 |
|
|
continue;
|
1229 |
|
|
}
|
1230 |
|
|
$rgmap[$ph1ent['remote-gateway']] = $rg;
|
1231 |
|
|
|
1232 |
|
|
$is_vti = false;
|
1233 |
|
|
if (is_array($a_phase2)) {
|
1234 |
|
|
/* step through each phase2 entry */
|
1235 |
|
|
foreach ($a_phase2 as $ph2ent) {
|
1236 |
|
|
if ($ph2ent['mode'] == 'vti') {
|
1237 |
|
|
$is_vti = true;
|
1238 |
|
|
}
|
1239 |
|
|
if (isset($ph2ent['disabled']) || ($ikeid != $ph2ent['ikeid'])) {
|
1240 |
|
|
continue;
|
1241 |
|
|
}
|
1242 |
|
|
|
1243 |
|
|
/* add an ipsec pinghosts entry */
|
1244 |
|
|
if ($ph2ent['pinghost']) {
|
1245 |
|
|
if (!is_array($iflist)) {
|
1246 |
|
|
$iflist = get_configured_interface_list();
|
1247 |
|
|
}
|
1248 |
|
|
$srcip = null;
|
1249 |
|
|
$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
|
1250 |
|
|
if (is_ipaddrv6($ph2ent['pinghost'])) {
|
1251 |
|
|
foreach ($iflist as $ifent => $ifname) {
|
1252 |
|
|
$interface_ip = get_interface_ipv6($ifent);
|
1253 |
|
|
if (!is_ipaddrv6($interface_ip)) {
|
1254 |
|
|
continue;
|
1255 |
|
|
}
|
1256 |
|
|
if (ip_in_subnet($interface_ip, $local_subnet)) {
|
1257 |
|
|
$srcip = $interface_ip;
|
1258 |
|
|
break;
|
1259 |
|
|
}
|
1260 |
|
|
}
|
1261 |
|
|
} else {
|
1262 |
|
|
foreach ($iflist as $ifent => $ifname) {
|
1263 |
|
|
$interface_ip = get_interface_ip($ifent);
|
1264 |
|
|
if (!is_ipaddrv4($interface_ip)) {
|
1265 |
|
|
continue;
|
1266 |
|
|
}
|
1267 |
|
|
if ($local_subnet == "0.0.0.0/0" || ip_in_subnet($interface_ip, $local_subnet)) {
|
1268 |
|
|
$srcip = $interface_ip;
|
1269 |
|
|
break;
|
1270 |
|
|
}
|
1271 |
|
|
}
|
1272 |
|
|
}
|
1273 |
|
|
/* if no valid src IP was found in configured interfaces, try the vips */
|
1274 |
|
|
if (is_null($srcip)) {
|
1275 |
|
|
$viplist = get_configured_vip_list();
|
1276 |
|
|
foreach ($viplist as $vip => $address) {
|
1277 |
|
|
if (ip_in_subnet($address, $local_subnet)) {
|
1278 |
|
|
$srcip = $address;
|
1279 |
|
|
break;
|
1280 |
|
|
}
|
1281 |
|
|
}
|
1282 |
|
|
}
|
1283 |
|
|
$dstip = $ph2ent['pinghost'];
|
1284 |
|
|
$family = "inet" . (is_ipaddrv6($dstip)) ? "6" : "";
|
1285 |
|
|
if (is_ipaddr($srcip)) {
|
1286 |
|
|
$ipsecpinghosts[] = "{$srcip}|{$dstip}|3|||||{$family}|\n";
|
1287 |
|
|
$ipsecpinghostsactive = true;
|
1288 |
|
|
}
|
1289 |
|
|
}
|
1290 |
|
|
}
|
1291 |
|
|
}
|
1292 |
|
|
if ($is_vti) {
|
1293 |
|
|
interface_ipsec_vti_configure($ph1ent);
|
1294 |
|
|
}
|
1295 |
|
|
}
|
1296 |
|
|
@file_put_contents("{$g['vardb_path']}/ipsecpinghosts", $ipsecpinghosts);
|
1297 |
|
|
unset($ipsecpinghosts);
|
1298 |
|
|
}
|
1299 |
|
|
unset($iflist);
|
1300 |
|
|
}
|
1301 |
|
|
|
1302 |
|
|
/****f* ipsec/ipsec_logging_config
|
1303 |
|
|
* NAME
|
1304 |
|
|
* ipsec_logging_config - Generate an array containing strongSwan logging
|
1305 |
|
|
* values.
|
1306 |
|
|
* INPUTS
|
1307 |
|
|
* None
|
1308 |
|
|
* RESULT
|
1309 |
|
|
* Returns an array which can be merged into the strongswan daemon logging
|
1310 |
|
|
* values so that each logging category is represented, even those not listed
|
1311 |
|
|
* in config.xml.
|
1312 |
|
|
******/
|
1313 |
|
|
function ipsec_logging_config() {
|
1314 |
|
|
global $config, $ipsec_log_cats, $ipsec_log_sevs;
|
1315 |
|
|
$logcfg = array();
|
1316 |
|
|
$log_levels = ipsec_get_loglevels();
|
1317 |
|
|
foreach (array_keys($ipsec_log_cats) as $cat) {
|
1318 |
|
|
if (is_numeric($log_levels[$cat]) &&
|
1319 |
|
|
in_array(intval($log_levels[$cat]), array_keys($ipsec_log_sevs), true)) {
|
1320 |
|
|
$logcfg[$cat] = $log_levels[$cat];
|
1321 |
|
|
}
|
1322 |
|
|
}
|
1323 |
|
|
return $logcfg;
|
1324 |
|
|
}
|
1325 |
|
|
|
1326 |
|
|
/****f* ipsec/ipsec_setup_strongswan
|
1327 |
|
|
* NAME
|
1328 |
|
|
* ipsec_setup_strongswan - Generate the strongswan.conf configuration file.
|
1329 |
|
|
* INPUTS
|
1330 |
|
|
* None
|
1331 |
|
|
* RESULT
|
1332 |
|
|
* Determines strongswan.conf values and crafts the configuration file in the
|
1333 |
|
|
* appropriate format.
|
1334 |
|
|
* NOTES
|
1335 |
|
|
* Called from ipsec_configure()
|
1336 |
|
|
******/
|
1337 |
|
|
function ipsec_setup_strongswan() {
|
1338 |
|
|
global $config, $g, $mobile_ipsec_auth, $a_client, $a_phase2, $aggressive_mode_psk, $ifacesuse;
|
1339 |
|
|
|
1340 |
|
|
/* strongswan.conf array */
|
1341 |
|
|
$ssconf = array();
|
1342 |
|
|
$ssconf[] = "# Automatically generated config file - DO NOT MODIFY. Changes will be overwritten.";
|
1343 |
|
|
$ssconf['starter'] = array();
|
1344 |
|
|
$ssconf['starter']['load_warning'] = "no";
|
1345 |
|
|
|
1346 |
|
|
$ssconf['charon'] = array();
|
1347 |
|
|
$ssconf['charon'][] = '# number of worker threads in charon';
|
1348 |
|
|
$ssconf['charon']['threads'] = '16';
|
1349 |
|
|
$ssconf['charon']['ikesa_table_size'] = '32';
|
1350 |
|
|
$ssconf['charon']['ikesa_table_segments'] = '4';
|
1351 |
|
|
$ssconf['charon']['init_limit_half_open'] = '1000';
|
1352 |
|
|
$ssconf['charon']['install_routes'] = 'no';
|
1353 |
|
|
$ssconf['charon']['load_modular'] = 'yes';
|
1354 |
|
|
$ssconf['charon']['ignore_acquire_ts'] = 'yes';
|
1355 |
|
|
|
1356 |
|
|
if ($aggressive_mode_psk) {
|
1357 |
|
|
$stronconf = '';
|
1358 |
|
|
if (file_exists("{$g['varetc_path']}/ipsec/strongswan.conf")) {
|
1359 |
|
|
$stronconf = file_get_contents("{$g['varetc_path']}/ipsec/strongswan.conf");
|
1360 |
|
|
}
|
1361 |
|
|
log_error("WARNING: Setting i_dont_care_about_security_and_use_aggressive_mode_psk option because a phase 1 is configured using aggressive mode with pre-shared keys. This is not a secure configuration.");
|
1362 |
|
|
$restart = (!empty($stronconf) && strpos($stronconf, 'i_dont_care_about_security_and_use_aggressive_mode_psk') === FALSE);
|
1363 |
|
|
unset($stronconf);
|
1364 |
|
|
$ssconf['charon']['i_dont_care_about_security_and_use_aggressive_mode_psk'] = "yes";
|
1365 |
|
|
}
|
1366 |
|
|
|
1367 |
|
|
if (isset($config['ipsec']['acceptunencryptedmainmode'])) {
|
1368 |
|
|
$ssconf['charon']['accept_unencrypted_mainmode_messages'] = "yes";
|
1369 |
|
|
}
|
1370 |
|
|
|
1371 |
4a879d79
|
Viktor G
|
if (isset($config['ipsec']['maxexchange'])) {
|
1372 |
|
|
$ssconf['charon']['max_ikev1_exchanges'] = $config['ipsec']['maxexchange'];
|
1373 |
|
|
}
|
1374 |
|
|
|
1375 |
c6220dcf
|
jim-p
|
$unity_enabled = isset($config['ipsec']['unityplugin']) ? 'yes' : 'no';
|
1376 |
|
|
$ssconf['charon']['cisco_unity'] = $unity_enabled;
|
1377 |
|
|
|
1378 |
|
|
if (isset($config['ipsec']['enableinterfacesuse']) && !empty($ifacesuse)) {
|
1379 |
|
|
$ssconf['charon']['interfaces_use'] = implode(',', array_unique($ifacesuse));
|
1380 |
|
|
}
|
1381 |
|
|
|
1382 |
|
|
if (isset($config['ipsec']['makebeforebreak'])) {
|
1383 |
|
|
$ssconf['charon']['make_before_break'] = "yes";
|
1384 |
|
|
}
|
1385 |
|
|
|
1386 |
92ed9792
|
Frederic Bor
|
if (isset($config['ipsec']['port'])) {
|
1387 |
|
|
$ssconf['charon']['port'] = $config['ipsec']['port'];
|
1388 |
|
|
}
|
1389 |
|
|
|
1390 |
|
|
if (isset($config['ipsec']['port_nat_t'])) {
|
1391 |
|
|
$ssconf['charon']['port_nat_t'] = $config['ipsec']['port_nat_t'];
|
1392 |
|
|
}
|
1393 |
|
|
|
1394 |
c6220dcf
|
jim-p
|
$ssconf['charon']['syslog'] = array();
|
1395 |
|
|
$ssconf['charon']['syslog']['identifier'] = 'charon';
|
1396 |
|
|
$ssconf['charon']['syslog'][] = "# log everything under daemon since it ends up in the same place regardless with our syslog.conf";
|
1397 |
|
|
$ssconf['charon']['syslog']['daemon'] = array();
|
1398 |
|
|
$ssconf['charon']['syslog']['daemon']['ike_name'] = 'yes';
|
1399 |
|
|
$ssconf['charon']['syslog']['daemon'] = array_merge($ssconf['charon']['syslog']['daemon'], ipsec_logging_config());
|
1400 |
|
|
$ssconf['charon']['syslog'][] = '# disable logging under auth so logs aren\'t duplicated';
|
1401 |
|
|
$ssconf['charon']['syslog']['auth'] = array();
|
1402 |
|
|
$ssconf['charon']['syslog']['auth']['default'] = -1;
|
1403 |
|
|
|
1404 |
|
|
$ssconf['charon']['plugins'] = array();
|
1405 |
|
|
$ssconf['charon']['plugins'][] = "# Load defaults";
|
1406 |
|
|
$ssconf['charon']['plugins'][] = "include {$g['varetc_path']}/ipsec/strongswan.d/charon/*.conf";
|
1407 |
|
|
$ssconf['charon']['plugins']['unity'] = array('load' => $unity_enabled);
|
1408 |
|
|
$ssconf['charon']['plugins']['curve25519'] = array('load' => "yes");
|
1409 |
|
|
|
1410 |
5f143b6e
|
Viktor Gurov
|
$ssconf['charon']['plugins']['pkcs11'] = array();
|
1411 |
|
|
$ssconf['charon']['plugins']['pkcs11']['load'] = "yes";
|
1412 |
|
|
$ssconf['charon']['plugins']['pkcs11']['modules'] = array();
|
1413 |
|
|
$ssconf['charon']['plugins']['pkcs11']['modules']['opensc'] = array();
|
1414 |
|
|
$ssconf['charon']['plugins']['pkcs11']['modules']['opensc']['load_certs'] = "yes";
|
1415 |
|
|
$ssconf['charon']['plugins']['pkcs11']['modules']['opensc']['path'] = "/usr/local/lib/opensc-pkcs11.so";
|
1416 |
|
|
|
1417 |
c6220dcf
|
jim-p
|
/* Find RADIUS servers designated for Mobile IPsec user auth */
|
1418 |
|
|
$radius_servers = array();
|
1419 |
|
|
foreach (explode(',', $config['ipsec']['client']['user_source']) as $user_source) {
|
1420 |
|
|
$auth_server = auth_get_authserver($user_source);
|
1421 |
|
|
$nice_user_source = strtolower(preg_replace('/[\s\.]+/', '_', $user_source));
|
1422 |
|
|
if ($auth_server && ($auth_server['type'] === 'radius')) {
|
1423 |
|
|
$radius_servers[$nice_user_source] = array();
|
1424 |
|
|
$radius_servers[$nice_user_source]['address'] = $auth_server['host'];
|
1425 |
|
|
$radius_servers[$nice_user_source]['secret'] = "\"{$auth_server['radius_secret']}\"";
|
1426 |
|
|
$radius_servers[$nice_user_source]['auth_port'] = empty($auth_server['radius_auth_port']) ? 1812 : $auth_server['radius_auth_port'];;
|
1427 |
|
|
$radius_servers[$nice_user_source]['acct_port'] = empty($auth_server['radius_acct_port']) ? 1813 : $auth_server['radius_acct_port'];
|
1428 |
|
|
}
|
1429 |
|
|
}
|
1430 |
|
|
|
1431 |
|
|
/* Generate an eap-radius config section if appropriate */
|
1432 |
|
|
if (count($radius_servers) && ($mobile_ipsec_auth === "eap-radius")) {
|
1433 |
|
|
$ssconf['charon']['plugins']['eap-radius'] = array();
|
1434 |
f9c9899b
|
Viktor Gurov
|
$ssconf['charon']['plugins']['eap-radius']['load'] = "2";
|
1435 |
c6220dcf
|
jim-p
|
$ssconf['charon']['plugins']['eap-radius']['class_group'] = "yes";
|
1436 |
|
|
$ssconf['charon']['plugins']['eap-radius']['eap_start'] = "no";
|
1437 |
|
|
/* Activate RADIUS accounting only if it was selected on the IPsec Mobile Clients tab */
|
1438 |
|
|
if ($auth_server && isset($auth_server['radius_acct_port']) &&
|
1439 |
|
|
(is_array($a_client) && ($a_client['radiusaccounting'] == "enabled"))){
|
1440 |
|
|
$ssconf['charon']['plugins']['eap-radius']['accounting'] = "yes";
|
1441 |
|
|
$ssconf['charon']['plugins']['eap-radius']['accounting_close_on_timeout'] = "no";
|
1442 |
|
|
}
|
1443 |
|
|
$ssconf['charon']['plugins']['eap-radius']['servers'] = $radius_servers;
|
1444 |
|
|
}
|
1445 |
|
|
|
1446 |
|
|
if (is_array($a_client) && isset($a_client['enable'])) {
|
1447 |
|
|
if ($a_client['user_source'] != "none") {
|
1448 |
|
|
$ssconf['charon']['plugins']['xauth-generic'] = array();
|
1449 |
|
|
$ssconf['charon']['plugins']['xauth-generic']['script'] = "/etc/inc/ipsec.auth-user.php";
|
1450 |
|
|
$authcfgs = array();
|
1451 |
|
|
foreach (explode(",", $a_client['user_source']) as $authcfg) {
|
1452 |
|
|
$authcfgs[] = ($authcfg == "system") ? "Local Database" : $authcfg;
|
1453 |
|
|
}
|
1454 |
|
|
$ssconf['charon']['plugins']['xauth-generic']['authcfg'] = implode(",", $authcfgs);
|
1455 |
|
|
}
|
1456 |
|
|
}
|
1457 |
|
|
|
1458 |
|
|
@file_put_contents("{$g['varetc_path']}/ipsec/strongswan.conf", ipsec_strongswan_confgen($ssconf));
|
1459 |
|
|
}
|
1460 |
|
|
|
1461 |
|
|
/****f* ipsec/ipsec_setup_pools
|
1462 |
|
|
* NAME
|
1463 |
|
|
* ipsec_setup_pools - Generate primary mobile pool configuration for swanctl
|
1464 |
|
|
* INPUTS
|
1465 |
|
|
* None
|
1466 |
|
|
* RESULT
|
1467 |
|
|
* Adds configured mobile pool settings to $scconf
|
1468 |
|
|
* NOTES
|
1469 |
|
|
* These values were formerly in strongswan.conf but may now be configured in
|
1470 |
|
|
* pools, making future expansion to support multiple pools possible.
|
1471 |
|
|
******/
|
1472 |
|
|
function ipsec_setup_pools() {
|
1473 |
|
|
global $config, $g, $mobile_ipsec_auth, $a_client, $a_phase2, $scconf;
|
1474 |
|
|
if (!is_array($a_client) || !isset($a_client['enable'])) {
|
1475 |
|
|
return;
|
1476 |
|
|
}
|
1477 |
f9c9899b
|
Viktor Gurov
|
if (($mobile_ipsec_auth == "eap-radius") && empty($a_client['pool_address']) &&
|
1478 |
|
|
empty($a_client['pool_address_v6'])) {
|
1479 |
|
|
return;
|
1480 |
|
|
}
|
1481 |
faf07413
|
jim-p
|
$scconf['mobile-pool'] = array();
|
1482 |
|
|
$scconf['pools'] = array();
|
1483 |
|
|
$pool_common =& $scconf['mobile-pool'];
|
1484 |
c6220dcf
|
jim-p
|
|
1485 |
|
|
$rightdnsservers = array();
|
1486 |
|
|
if (!empty($a_client['dns_server1'])) {
|
1487 |
|
|
$rightdnsservers[] = $a_client['dns_server1'];
|
1488 |
|
|
}
|
1489 |
|
|
if (!empty($a_client['dns_server2'])) {
|
1490 |
|
|
$rightdnsservers[] = $a_client['dns_server2'];
|
1491 |
|
|
}
|
1492 |
|
|
if (!empty($a_client['dns_server3'])) {
|
1493 |
|
|
$rightdnsservers[] = $a_client['dns_server3'];
|
1494 |
|
|
}
|
1495 |
|
|
if (!empty($a_client['dns_server4'])) {
|
1496 |
|
|
$rightdnsservers[] = $a_client['dns_server4'];
|
1497 |
|
|
}
|
1498 |
|
|
if (count($rightdnsservers)) {
|
1499 |
407a5c28
|
jim-p
|
$pool_common['dns'] = implode(',', $rightdnsservers);
|
1500 |
c6220dcf
|
jim-p
|
}
|
1501 |
|
|
|
1502 |
|
|
$cfgservers = array();
|
1503 |
|
|
if (!empty($a_client['wins_server1'])) {
|
1504 |
|
|
$cfgservers[] = $a_client['wins_server1'];
|
1505 |
|
|
}
|
1506 |
|
|
if (!empty($a_client['wins_server2'])) {
|
1507 |
|
|
$cfgservers[] = $a_client['wins_server2'];
|
1508 |
|
|
}
|
1509 |
|
|
if (!empty($cfgservers)) {
|
1510 |
407a5c28
|
jim-p
|
$pool_common['nbns'] = implode(",", $cfgservers);
|
1511 |
c6220dcf
|
jim-p
|
}
|
1512 |
|
|
unset($cfgservers);
|
1513 |
|
|
|
1514 |
407a5c28
|
jim-p
|
$net_list4 = array();
|
1515 |
|
|
$net_list6 = array();
|
1516 |
c6220dcf
|
jim-p
|
if (isset($a_client['net_list']) && is_array($a_phase2)) {
|
1517 |
|
|
foreach ($a_phase2 as $ph2ent) {
|
1518 |
|
|
if (isset($ph2ent['disabled']) ||
|
1519 |
|
|
!isset($ph2ent['mobile'])) {
|
1520 |
|
|
continue;
|
1521 |
|
|
}
|
1522 |
407a5c28
|
jim-p
|
$nlent = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
|
1523 |
|
|
if (is_subnetv4($nlent)) {
|
1524 |
|
|
$net_list4[] = $nlent;
|
1525 |
|
|
} elseif (is_subnetv6($nlent)) {
|
1526 |
|
|
$net_list6[] = $nlent;
|
1527 |
|
|
}
|
1528 |
|
|
unset($nlent);
|
1529 |
c6220dcf
|
jim-p
|
}
|
1530 |
|
|
}
|
1531 |
|
|
if (!empty($a_client['dns_domain'])) {
|
1532 |
407a5c28
|
jim-p
|
$pool_common[] = "# Search domain and default domain";
|
1533 |
|
|
$pool_common['28674'] = "\"{$a_client['dns_domain']}\"";
|
1534 |
c6220dcf
|
jim-p
|
if (empty($a_client['dns_split'])) {
|
1535 |
407a5c28
|
jim-p
|
$pool_common['28675'] = "\"{$a_client['dns_domain']}\"";
|
1536 |
c6220dcf
|
jim-p
|
}
|
1537 |
|
|
}
|
1538 |
|
|
|
1539 |
|
|
if (!empty($a_client['dns_split'])) {
|
1540 |
407a5c28
|
jim-p
|
$pool_common['28675'] = "\"{$a_client['dns_split']}\"";
|
1541 |
c6220dcf
|
jim-p
|
}
|
1542 |
|
|
|
1543 |
|
|
if (!empty($a_client['login_banner'])) {
|
1544 |
407a5c28
|
jim-p
|
$pool_common['28672'] = "\"{$a_client['login_banner']}\"";
|
1545 |
c6220dcf
|
jim-p
|
}
|
1546 |
|
|
|
1547 |
|
|
if (isset($a_client['save_passwd'])) {
|
1548 |
407a5c28
|
jim-p
|
$pool_common['28673'] = "1";
|
1549 |
c6220dcf
|
jim-p
|
}
|
1550 |
|
|
|
1551 |
|
|
if ($a_client['pfs_group']) {
|
1552 |
407a5c28
|
jim-p
|
$pool_common['28679'] = "\"{$a_client['pfs_group']}\"";
|
1553 |
|
|
}
|
1554 |
|
|
|
1555 |
|
|
if (!empty($a_client['pool_address'])) {
|
1556 |
|
|
$scconf['pools']['mobile-pool-v4 : mobile-pool'] = array();
|
1557 |
|
|
$v4pool =& $scconf['pools']['mobile-pool-v4 : mobile-pool'];
|
1558 |
|
|
$v4pool['addrs'] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
|
1559 |
|
|
if (!empty($net_list4)) {
|
1560 |
|
|
$v4pool['subnet'] = implode(",", $net_list4);
|
1561 |
|
|
$v4pool['split_include'] = implode(",", $net_list4);
|
1562 |
|
|
unset($net_list4);
|
1563 |
|
|
}
|
1564 |
|
|
}
|
1565 |
|
|
if (!empty($a_client['pool_address_v6'])) {
|
1566 |
|
|
$scconf['pools']['mobile-pool-v6 : mobile-pool'] = array();
|
1567 |
|
|
$v6pool =& $scconf['pools']['mobile-pool-v6 : mobile-pool'];
|
1568 |
|
|
$v6pool['addrs'] = "{$a_client['pool_address_v6']}/{$a_client['pool_netbits_v6']}";
|
1569 |
|
|
if (!empty($net_list6)) {
|
1570 |
|
|
$v6pool['subnet'] = implode(",", $net_list6);
|
1571 |
|
|
$v6pool['split_include'] = implode(",", $net_list6);
|
1572 |
|
|
unset($net_list6);
|
1573 |
|
|
}
|
1574 |
c6220dcf
|
jim-p
|
}
|
1575 |
|
|
|
1576 |
|
|
return;
|
1577 |
|
|
}
|
1578 |
|
|
|
1579 |
|
|
/****f* ipsec/ipsec_setup_userpools
|
1580 |
|
|
* NAME
|
1581 |
|
|
* ipsec_setup_userpools - Generate per-user custom pool settings for swanctl
|
1582 |
|
|
* INPUTS
|
1583 |
|
|
* None
|
1584 |
|
|
* RESULT
|
1585 |
|
|
* Adds configured per-user pool settings to $scconf using the primary mobile
|
1586 |
|
|
* pool as a base configuration.
|
1587 |
|
|
* NOTES
|
1588 |
|
|
* Given this new flexible format, it is now possible to override any valid
|
1589 |
|
|
* pool setting, so future expansion of per-user settings is possible.
|
1590 |
|
|
******/
|
1591 |
|
|
function ipsec_setup_userpools() {
|
1592 |
|
|
global $config, $scconf;
|
1593 |
|
|
$a_mobilekey = $config['ipsec']['mobilekey'];
|
1594 |
|
|
|
1595 |
|
|
/* Do not waste time if we do not have all the necessary information. */
|
1596 |
|
|
if (!is_array($a_mobilekey) ||
|
1597 |
|
|
empty($a_mobilekey) ||
|
1598 |
|
|
!is_array($scconf['connections']) ||
|
1599 |
faf07413
|
jim-p
|
!is_array($scconf['con-mobile-defaults']) ||
|
1600 |
c6220dcf
|
jim-p
|
!is_array($scconf['pools']) ||
|
1601 |
faf07413
|
jim-p
|
!is_array($scconf['mobile-pool'])) {
|
1602 |
c6220dcf
|
jim-p
|
return;
|
1603 |
|
|
}
|
1604 |
|
|
|
1605 |
|
|
$suffix = 1;
|
1606 |
|
|
foreach ($a_mobilekey as $mkent) {
|
1607 |
|
|
if (($mkent['type'] != "EAP") ||
|
1608 |
|
|
!isset($mkent['ident_type']) ||
|
1609 |
|
|
!isset($mkent['pool_address']) ||
|
1610 |
|
|
!isset($mkent['pool_netbits']) ||
|
1611 |
|
|
(strlen($mkent['pool_address']) < 1) ||
|
1612 |
|
|
!is_ipaddr($mkent['pool_address'])) {
|
1613 |
|
|
continue;
|
1614 |
|
|
}
|
1615 |
|
|
/* The name of just this pool */
|
1616 |
|
|
$upbase = "mobile-userpool-{$suffix}";
|
1617 |
|
|
/* The full connection name including a reference to the primary
|
1618 |
|
|
* mobile connection */
|
1619 |
faf07413
|
jim-p
|
$upconn = "con-{$upbase} : con-mobile-defaults";
|
1620 |
c6220dcf
|
jim-p
|
/* The full pool name including a reference to the primary
|
1621 |
|
|
* mobile pool */
|
1622 |
|
|
$upname = "{$upbase} : mobile-pool";
|
1623 |
|
|
|
1624 |
|
|
$scconf['connections'][$upconn] = array();
|
1625 |
|
|
$scconf['pools'][$upname] = array();
|
1626 |
|
|
|
1627 |
|
|
$clientid = ($mkent['ident_type'] == "none") ? "\"{$mkent['ident']}\"" : "{$mkent['ident_type']}:{$mkent['ident']}";
|
1628 |
|
|
$clienteapid = ($ph1ent['authentication_method'] == "eap-mschapv2") ? $clientid : '%any';
|
1629 |
|
|
|
1630 |
|
|
/* Craft a cloned connection with the ID information to match */
|
1631 |
|
|
$scconf['connections'][$upconn]['remote'] = array();
|
1632 |
|
|
$scconf['connections'][$upconn]['remote']['id'] = $clientid;
|
1633 |
|
|
$scconf['connections'][$upconn]['remote']['eap_id'] = $clienteapid;
|
1634 |
|
|
$scconf['connections'][$upconn]['pools'] = $upbase;
|
1635 |
|
|
|
1636 |
|
|
/* Craft a cloned pool with pool settings to override for this user */
|
1637 |
|
|
$scconf['pools'][$upname]['addrs'] = "{$mkent['pool_address']}/{$mkent['pool_netbits']}";
|
1638 |
|
|
if (isset($mkent['dns_address']) && strlen($mkent['dns_address']) > 0 && is_ipaddr($mkent['dns_address'])) {
|
1639 |
|
|
$scconf['pools'][$upname]['dns'] = $mkent['dns_address'];
|
1640 |
|
|
}
|
1641 |
|
|
$suffix++;
|
1642 |
|
|
}
|
1643 |
|
|
return;
|
1644 |
|
|
}
|
1645 |
|
|
|
1646 |
14b52494
|
Viktor Gurov
|
/****f* ipsec/ipsec_setup_bypass
|
1647 |
c6220dcf
|
jim-p
|
* NAME
|
1648 |
14b52494
|
Viktor Gurov
|
* ipsec_setup_bypass - Generate a bypass connection for LAN-LAN and custom rules traffic
|
1649 |
c6220dcf
|
jim-p
|
* INPUTS
|
1650 |
|
|
* None
|
1651 |
|
|
* RESULT
|
1652 |
|
|
* Sets up a bypass connection to prevent local traffic from being caught by
|
1653 |
|
|
* IPsec policies.
|
1654 |
|
|
******/
|
1655 |
14b52494
|
Viktor Gurov
|
function ipsec_setup_bypass() {
|
1656 |
c6220dcf
|
jim-p
|
global $config, $scconf;
|
1657 |
14b52494
|
Viktor Gurov
|
|
1658 |
|
|
$scconf['connections']['bypass'] = array();
|
1659 |
|
|
/* Prevents the connection from being considered for remote peers */
|
1660 |
|
|
$scconf['connections']['bypass']['remote_addrs'] = "127.0.0.1";
|
1661 |
|
|
$scconf['connections']['bypass']['children'] = array();
|
1662 |
|
|
|
1663 |
c6220dcf
|
jim-p
|
/* Locate the LAN IPv4 and IPv6 subnets */
|
1664 |
14b52494
|
Viktor Gurov
|
$bypassnets = array();
|
1665 |
c6220dcf
|
jim-p
|
if ($config['interfaces']['lan']) {
|
1666 |
|
|
$lanip = get_interface_ip("lan");
|
1667 |
|
|
if (!empty($lanip) && is_ipaddrv4($lanip)) {
|
1668 |
|
|
$lansn = get_interface_subnet("lan");
|
1669 |
|
|
$lansa = gen_subnetv4($lanip, $lansn);
|
1670 |
|
|
if (!empty($lansa) && !empty($lansn)) {
|
1671 |
|
|
$bypassnets[] = "{$lansa}/{$lansn}";
|
1672 |
|
|
}
|
1673 |
|
|
}
|
1674 |
|
|
$lanip6 = get_interface_ipv6("lan");
|
1675 |
|
|
if (!empty($lanip6) && is_ipaddrv6($lanip6)) {
|
1676 |
|
|
$lansn6 = get_interface_subnetv6("lan");
|
1677 |
|
|
$lansa6 = gen_subnetv6($lanip6, $lansn6);
|
1678 |
|
|
if (!empty($lansa6) && !empty($lansn6)) {
|
1679 |
|
|
$bypassnets[] = "{$lansa6}/{$lansn6}";
|
1680 |
|
|
}
|
1681 |
|
|
}
|
1682 |
|
|
}
|
1683 |
14b52494
|
Viktor Gurov
|
/* If we have viable targets, setup a bypass LAN connection */
|
1684 |
|
|
if (!empty($bypassnets) && !isset($config['ipsec']['noshuntlaninterfaces'])) {
|
1685 |
c6220dcf
|
jim-p
|
$bypass = implode(',', $bypassnets);
|
1686 |
14b52494
|
Viktor Gurov
|
$scconf['connections']['bypass']['children']['bypasslan'] = array();
|
1687 |
|
|
$scconf['connections']['bypass']['children']['bypasslan']['local_ts'] = $bypass;
|
1688 |
|
|
$scconf['connections']['bypass']['children']['bypasslan']['remote_ts'] = $bypass;
|
1689 |
|
|
$scconf['connections']['bypass']['children']['bypasslan']['mode'] = "pass";
|
1690 |
|
|
$scconf['connections']['bypass']['children']['bypasslan']['start_action'] = "trap";
|
1691 |
c6220dcf
|
jim-p
|
}
|
1692 |
14b52494
|
Viktor Gurov
|
|
1693 |
|
|
/* Setup custom bypass rules */
|
1694 |
|
|
if ((isset($config['ipsec']['ipsecbypass']) && $config['ipsec']['bypassrules']) &&
|
1695 |
|
|
is_array($config['ipsec']['bypassrules'])) {
|
1696 |
|
|
foreach ($config['ipsec']['bypassrules']['rule'] as $id => $rule) {
|
1697 |
|
|
$scconf['connections']['bypass']['children']["rule{$id}"] = array();
|
1698 |
|
|
$scconf['connections']['bypass']['children']["rule{$id}"]["local_ts"] = $rule['source'] .
|
1699 |
|
|
"/" . $rule['srcmask'];
|
1700 |
|
|
$scconf['connections']['bypass']['children']["rule{$id}"]["remote_ts"] = $rule['destination'] .
|
1701 |
|
|
"/" . $rule['dstmask'];
|
1702 |
|
|
$scconf['connections']['bypass']['children']["rule{$id}"]["mode"] = "pass";
|
1703 |
|
|
$scconf['connections']['bypass']['children']["rule{$id}"]["start_action"] = "trap";
|
1704 |
|
|
}
|
1705 |
|
|
}
|
1706 |
|
|
|
1707 |
c6220dcf
|
jim-p
|
return;
|
1708 |
|
|
}
|
1709 |
|
|
|
1710 |
|
|
/****f* ipsec/ipsec_setup_routes
|
1711 |
|
|
* NAME
|
1712 |
|
|
* ipsec_setup_routes - Setup OS routing table static routes for remote peers.
|
1713 |
|
|
* This ensures that IPsec connections are routed out of
|
1714 |
|
|
* the expected interface on egress.
|
1715 |
|
|
* INPUTS
|
1716 |
|
|
* $interface : The interface upon which routes will be configured.
|
1717 |
|
|
* $family : The address family ('inet' or 'inet6')
|
1718 |
|
|
* $sourcehost: The local source address used for initiating connections.
|
1719 |
d0cd4fc7
|
Frederic Bor
|
* $duplicates: If the ipsec tunnel allows duplicates remote peers
|
1720 |
c6220dcf
|
jim-p
|
* RESULT
|
1721 |
|
|
* Static routes in the OS routing table for IPsec peers
|
1722 |
|
|
******/
|
1723 |
ab380916
|
Frederic Bor
|
function ipsec_setup_routes($interface, $family, $sourcehost, $duplicates) {
|
1724 |
c6220dcf
|
jim-p
|
if (substr($interface, 0, 4) == "_vip") {
|
1725 |
|
|
$vpninterface = get_configured_vip_interface($interface);
|
1726 |
|
|
if (substr($vpninterface, 0, 4) == "_vip") {
|
1727 |
|
|
// vips are nested if its a ipalias with a carp parent
|
1728 |
|
|
$vpninterface = get_configured_vip_interface($vpninterface);
|
1729 |
|
|
}
|
1730 |
|
|
$ifacesuse = get_real_interface($vpninterface);
|
1731 |
|
|
} else {
|
1732 |
|
|
$ifacesuse = get_failover_interface($interface);
|
1733 |
|
|
if (substr($ifacesuse, 0, 4) == "_vip") {
|
1734 |
|
|
$vpninterface = get_configured_vip_interface($ifacesuse);
|
1735 |
|
|
$ifacesuse = get_real_interface($vpninterface);
|
1736 |
|
|
} else {
|
1737 |
|
|
$vpninterface = convert_real_interface_to_friendly_interface_name($ifacesuse);
|
1738 |
|
|
}
|
1739 |
|
|
}
|
1740 |
56d8a9b0
|
Renato Botelho do Couto
|
if ($family == 'inet' && !empty($ifacesuse) &&
|
1741 |
|
|
interface_has_gateway($vpninterface)) {
|
1742 |
|
|
$gatewayip = get_interface_gateway($vpninterface);
|
1743 |
|
|
$interfaceip = get_interface_ip($vpninterface);
|
1744 |
|
|
$subnet_bits = get_interface_subnet($vpninterface);
|
1745 |
|
|
$subnet_ip = gen_subnetv4($interfaceip, $subnet_bits);
|
1746 |
174cb4df
|
Renato Botelho do Couto
|
/*
|
1747 |
|
|
* if the remote gateway is in the local subnet, then don't add
|
1748 |
|
|
* a route
|
1749 |
|
|
*/
|
1750 |
56d8a9b0
|
Renato Botelho do Couto
|
if (is_ipaddrv4($sourcehost) &&
|
1751 |
|
|
!ip_in_subnet($sourcehost, "{$subnet_ip}/{$subnet_bits}") &&
|
1752 |
|
|
is_ipaddrv4($gatewayip) && !$duplicates) {
|
1753 |
c428cdf4
|
Renato Botelho do Couto
|
route_add_or_change($sourcehost, $gatewayip);
|
1754 |
c6220dcf
|
jim-p
|
}
|
1755 |
56d8a9b0
|
Renato Botelho do Couto
|
} else if ($family == 'inet6' && !empty($ifacesuse) &&
|
1756 |
|
|
interface_has_gatewayv6($vpninterface)) {
|
1757 |
|
|
$gatewayip = get_interface_gateway_v6($vpninterface);
|
1758 |
|
|
$interfaceip = get_interface_ipv6($vpninterface);
|
1759 |
|
|
$subnet_bits = get_interface_subnetv6($vpninterface);
|
1760 |
|
|
$subnet_ip = gen_subnetv6($interfaceip, $subnet_bits);
|
1761 |
174cb4df
|
Renato Botelho do Couto
|
/*
|
1762 |
|
|
* if the remote gateway is in the local subnet, then don't add
|
1763 |
|
|
* a route
|
1764 |
|
|
*/
|
1765 |
56d8a9b0
|
Renato Botelho do Couto
|
if (is_ipaddrv6($sourcehost) &&
|
1766 |
|
|
!ip_in_subnet($sourcehost, "{$subnet_ip}/{$subnet_bits}") &&
|
1767 |
|
|
is_ipaddrv6($gatewayip) && !$duplicates) {
|
1768 |
c428cdf4
|
Renato Botelho do Couto
|
route_add_or_change($sourcehost, $gatewayip);
|
1769 |
c6220dcf
|
jim-p
|
}
|
1770 |
|
|
}
|
1771 |
|
|
return $ifacesuse;
|
1772 |
|
|
}
|
1773 |
|
|
|
1774 |
|
|
/****f* ipsec/ipsec_setup_authentication
|
1775 |
|
|
* NAME
|
1776 |
|
|
* ipsec_setup_authentication - Generate an array with local/remote
|
1777 |
|
|
* authentication information for a given IPsec
|
1778 |
|
|
* Phase 1.
|
1779 |
|
|
* INPUTS
|
1780 |
|
|
* $ph1ent: An IPsec Phase 1 configuration
|
1781 |
|
|
* $conn : A swanctl connection array corresponding to the IPsec Phase 1.
|
1782 |
|
|
* RESULT
|
1783 |
|
|
* Populates $conn with local and remote arrays containing authentication
|
1784 |
|
|
* details.
|
1785 |
|
|
******/
|
1786 |
|
|
function ipsec_setup_authentication(& $ph1ent, & $conn) {
|
1787 |
5ed92e19
|
Viktor G
|
global $rgmap, $ipsec_swanctl_dirs, $config;
|
1788 |
c6220dcf
|
jim-p
|
$local = array();
|
1789 |
|
|
$remote = array();
|
1790 |
|
|
$remote2 = array();
|
1791 |
|
|
|
1792 |
|
|
list($myid_type, $myid_data) = ipsec_find_id($ph1ent, 'local');
|
1793 |
|
|
$localid = ipsec_fixup_id($myid_type, $myid_data);
|
1794 |
|
|
if (!empty($localid)) {
|
1795 |
|
|
$local['id'] = $localid;
|
1796 |
|
|
}
|
1797 |
|
|
|
1798 |
|
|
// Only specify peer ID if we are not dealing with mobile PSK
|
1799 |
|
|
if (!(isset($ph1ent['mobile']) &&
|
1800 |
|
|
in_array($ph1ent['authentication_method'], array("pre_shared_key", "xauth_psk_server")))) {
|
1801 |
|
|
list ($remoteid_type, $remoteid_data) = ipsec_find_id($ph1ent, 'peer', $rgmap);
|
1802 |
|
|
$remoteid = ipsec_fixup_id($remoteid_type, $remoteid_data);
|
1803 |
|
|
}
|
1804 |
|
|
if (!empty($remoteid)) {
|
1805 |
|
|
$remote['id'] = $remoteid;
|
1806 |
|
|
}
|
1807 |
|
|
|
1808 |
|
|
if (!empty($ph1ent['caref'])) {
|
1809 |
|
|
$ca = lookup_ca($ph1ent['caref']);
|
1810 |
|
|
if ($ca) {
|
1811 |
|
|
/* Get hash value to use for filename */
|
1812 |
|
|
$ca_details = openssl_x509_parse(base64_decode($ca['crt']));
|
1813 |
|
|
$cafn = "{$ipsec_swanctl_dirs['capath']}/{$ca_details['hash']}.0";
|
1814 |
|
|
}
|
1815 |
|
|
}
|
1816 |
|
|
|
1817 |
|
|
$authentication = "";
|
1818 |
|
|
switch ($ph1ent['authentication_method']) {
|
1819 |
|
|
case 'eap-mschapv2':
|
1820 |
|
|
if (isset($ph1ent['mobile'])) {
|
1821 |
|
|
$local['auth'] = "pubkey";
|
1822 |
|
|
$remote['eap_id'] = "%any";
|
1823 |
|
|
$remote['auth'] = "eap-mschapv2";
|
1824 |
|
|
}
|
1825 |
|
|
break;
|
1826 |
|
|
case 'eap-tls':
|
1827 |
|
|
if (isset($ph1ent['mobile'])) {
|
1828 |
|
|
$local['auth'] = "pubkey";
|
1829 |
|
|
$remote['eap_id'] = "%any";
|
1830 |
|
|
} else {
|
1831 |
|
|
$local['auth'] = "eap-tls";
|
1832 |
|
|
}
|
1833 |
|
|
$remote['auth'] = "eap-tls";
|
1834 |
|
|
break;
|
1835 |
|
|
case 'eap-radius':
|
1836 |
|
|
if (isset($ph1ent['mobile'])) {
|
1837 |
|
|
$local['auth'] = "pubkey";
|
1838 |
|
|
$remote['eap_id'] = "%any";
|
1839 |
|
|
} else {
|
1840 |
|
|
$local['auth'] = "eap-radius";
|
1841 |
|
|
}
|
1842 |
5ed92e19
|
Viktor G
|
if (($config['ipsec']['client']['group_source'] == 'enabled') &&
|
1843 |
|
|
!empty($config['ipsec']['client']['auth_groups'])) {
|
1844 |
|
|
$remote['groups'] = $config['ipsec']['client']['auth_groups'];
|
1845 |
|
|
}
|
1846 |
c6220dcf
|
jim-p
|
$remote['auth'] = "eap-radius";
|
1847 |
|
|
break;
|
1848 |
|
|
case 'xauth_cert_server':
|
1849 |
|
|
$local['auth'] = "pubkey";
|
1850 |
|
|
$remote['auth'] = "pubkey";
|
1851 |
|
|
$remote2['auth'] = "xauth-generic";
|
1852 |
|
|
break;
|
1853 |
|
|
case 'xauth_psk_server':
|
1854 |
|
|
$local['auth'] = "psk";
|
1855 |
|
|
$remote['auth'] = "psk";
|
1856 |
|
|
$remote2['auth'] = "xauth-generic";
|
1857 |
|
|
break;
|
1858 |
|
|
case 'pre_shared_key':
|
1859 |
|
|
$local['auth'] = "psk";
|
1860 |
|
|
$remote['auth'] = "psk";
|
1861 |
|
|
break;
|
1862 |
|
|
case 'cert':
|
1863 |
8c120b1f
|
Viktor G
|
case 'pkcs11':
|
1864 |
c6220dcf
|
jim-p
|
$local['auth'] = "pubkey";
|
1865 |
|
|
$remote['auth'] = "pubkey";
|
1866 |
|
|
break;
|
1867 |
|
|
case 'hybrid_cert_server':
|
1868 |
|
|
$local['auth'] = "pubkey";
|
1869 |
|
|
$remote['auth'] = "xauth-generic";
|
1870 |
|
|
break;
|
1871 |
|
|
}
|
1872 |
|
|
if (in_array($ph1ent['authentication_method'], array('eap-mschapv2', 'eap-tls', 'eap-radius', 'xauth_cert_server', 'cert', 'hybrid_cert_server')) &&
|
1873 |
|
|
!empty($ph1ent['certref'])) {
|
1874 |
5f143b6e
|
Viktor Gurov
|
$local['cert'] = array('file' => "{$ipsec_swanctl_dirs['certpath']}/cert-{$ph1ent['ikeid']}.crt");
|
1875 |
|
|
$conn['send_cert'] = "always";
|
1876 |
|
|
}
|
1877 |
|
|
if ($ph1ent['authentication_method'] == 'pkcs11') {
|
1878 |
|
|
$local['cert'] = array('handle' => "{$ph1ent['pkcs11certref']}");
|
1879 |
c6220dcf
|
jim-p
|
$conn['send_cert'] = "always";
|
1880 |
|
|
}
|
1881 |
5f143b6e
|
Viktor Gurov
|
if (in_array($ph1ent['authentication_method'], array('eap-tls', 'xauth_cert_server', 'cert', 'pkcs11')) &&
|
1882 |
c6220dcf
|
jim-p
|
isset($cafn)) {
|
1883 |
|
|
$remote['cacerts'] = $cafn;
|
1884 |
|
|
}
|
1885 |
|
|
|
1886 |
|
|
$conn['local'] = $local;
|
1887 |
|
|
/* If there is data for a second remote auth round, setup two remote
|
1888 |
|
|
* arrays with unique names, otherwise setup a single remote. */
|
1889 |
|
|
if (empty($remote2)) {
|
1890 |
|
|
$conn['remote'] = $remote;
|
1891 |
|
|
} else {
|
1892 |
|
|
$conn['remote-1'] = $remote;
|
1893 |
|
|
$conn['remote-2'] = $remote2;
|
1894 |
|
|
}
|
1895 |
|
|
}
|
1896 |
|
|
|
1897 |
|
|
/****f* ipsec/ipsec_setup_proposal_algo
|
1898 |
|
|
* NAME
|
1899 |
|
|
* ipsec_setup_proposal_algo - Form a single proposal algorithm string
|
1900 |
|
|
* INPUTS
|
1901 |
|
|
* $ealg_id: Encryption algorithm ID
|
1902 |
|
|
* $keylen : Key length for the encryption algorithm
|
1903 |
|
|
* $halgo : Hash algorithm
|
1904 |
|
|
* $modp : DH Group number
|
1905 |
|
|
* RESULT
|
1906 |
|
|
* Returns a string using the available information to form a single proposal
|
1907 |
|
|
* algorithm definition.
|
1908 |
|
|
* NOTES
|
1909 |
|
|
* Values left empty will not be added to the string. Some combinations may
|
1910 |
|
|
* require one or more parts to be omitted.
|
1911 |
|
|
******/
|
1912 |
f5ddbec1
|
Viktor G
|
function ipsec_setup_proposal_algo($ealg_id, $keylen, $halgo, $prfalgo, $modp) {
|
1913 |
c6220dcf
|
jim-p
|
$palgo = "";
|
1914 |
|
|
|
1915 |
|
|
/* Add the encryption algorithm (if present) */
|
1916 |
|
|
if (!empty($ealg_id)) {
|
1917 |
|
|
$palgo .= "{$ealg_id}";
|
1918 |
|
|
}
|
1919 |
|
|
|
1920 |
|
|
/* Add the key length (if present) */
|
1921 |
|
|
if (!empty($keylen)) {
|
1922 |
|
|
$palgo .= "{$keylen}";
|
1923 |
|
|
}
|
1924 |
|
|
|
1925 |
|
|
/* Add the hash algorithm (if present) */
|
1926 |
1cdd7dd2
|
jim-p
|
if (!empty($halgo)) {
|
1927 |
c6220dcf
|
jim-p
|
/* If there is some content in the propsal already, add a
|
1928 |
|
|
* separator */
|
1929 |
|
|
if (!empty($palgo)) {
|
1930 |
|
|
$palgo .= "-";
|
1931 |
|
|
}
|
1932 |
|
|
$halgo = str_replace('hmac_', '', $halgo);
|
1933 |
|
|
$palgo .= "{$halgo}";
|
1934 |
|
|
}
|
1935 |
|
|
|
1936 |
f5ddbec1
|
Viktor G
|
if (!empty($prfalgo)) {
|
1937 |
|
|
$palgo .= "-prf{$prfalgo}";
|
1938 |
|
|
}
|
1939 |
|
|
|
1940 |
c6220dcf
|
jim-p
|
/* Convert the DH group to its keyword and add (if present) */
|
1941 |
|
|
$modp = ipsec_convert_to_modp($modp);
|
1942 |
|
|
if (!empty($modp)) {
|
1943 |
|
|
$palgo .= "-{$modp}";
|
1944 |
|
|
}
|
1945 |
|
|
|
1946 |
|
|
return $palgo;
|
1947 |
|
|
}
|
1948 |
|
|
|
1949 |
|
|
/****f* ipsec/ipsec_setup_proposal_entry
|
1950 |
|
|
* NAME
|
1951 |
|
|
* ipsec_setup_proposal_entry - Generate a full proposal string for an IPsec
|
1952 |
|
|
* Phase 2 configuration.
|
1953 |
|
|
* INPUTS
|
1954 |
|
|
* $ph2ent : An IPsec Phase 2 configuration
|
1955 |
|
|
* $algo_arr: An array in which all proposal algorithms are collected
|
1956 |
|
|
* $ealg_id : Encryption algorithm ID
|
1957 |
|
|
* $keylen : Key length for the encryption algorithm
|
1958 |
|
|
* RESULT
|
1959 |
|
|
* Returns a string containing all proposal elements, and merges the entries
|
1960 |
|
|
* to $algo_arr as well.
|
1961 |
|
|
******/
|
1962 |
|
|
function ipsec_setup_proposal_entry(& $ph2ent, & $algo_arr, $ealg_id, $keylen) {
|
1963 |
|
|
global $config, $p2_ealgos;
|
1964 |
|
|
$proposal = array();
|
1965 |
|
|
|
1966 |
|
|
/* If multiple hash algorithms are present, loop through and add them all. */
|
1967 |
9d60be2a
|
Viktor G
|
if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])
|
1968 |
|
|
&& !strpos($ealg_id, "gcm")) {
|
1969 |
c6220dcf
|
jim-p
|
foreach ($ph2ent['hash-algorithm-option'] as $halgo) {
|
1970 |
f5ddbec1
|
Viktor G
|
$proposal[] = ipsec_setup_proposal_algo($ealg_id, $keylen, $halgo, false, $ph2ent['pfsgroup']);
|
1971 |
c6220dcf
|
jim-p
|
}
|
1972 |
|
|
} else {
|
1973 |
ffcfddc6
|
Viktor Gurov
|
$proposal[] = ipsec_setup_proposal_algo($ealg_id, $keylen, false, false, $ph2ent['pfsgroup']);
|
1974 |
c6220dcf
|
jim-p
|
}
|
1975 |
|
|
|
1976 |
|
|
/* Add to master list */
|
1977 |
|
|
$algo_arr = array_merge($algo_arr, $proposal);
|
1978 |
|
|
return implode(',', $proposal);
|
1979 |
|
|
}
|
1980 |
|
|
|
1981 |
|
|
/****f* ipsec/ipsec_setup_vtireq
|
1982 |
|
|
* NAME
|
1983 |
|
|
* ipsec_setup_vtireq - Setup a VTI type IPsec request
|
1984 |
|
|
* INPUTS
|
1985 |
|
|
* $child : A swanctl child array
|
1986 |
|
|
* $ipsec_vti_cleanup_ifs: An array of VTI interface names for later cleanup
|
1987 |
|
|
* $ikeid : The IKE ID of this child
|
1988 |
|
|
* $idx : The index of this child (for split connections/IKEv1)
|
1989 |
|
|
* RESULT
|
1990 |
|
|
* Sets up VTI-specific values for a request.
|
1991 |
|
|
******/
|
1992 |
|
|
function ipsec_setup_vtireq(& $child, & $ipsec_vti_cleanup_ifs, $ikeid, $idx = 0) {
|
1993 |
3b85b43b
|
Viktor G
|
$child['reqid'] = get_ipsecifnum($ikeid, $idx);
|
1994 |
c6220dcf
|
jim-p
|
/* This interface will be a valid IPsec interface, so remove it from the cleanup list. */
|
1995 |
|
|
$ipsec_vti_cleanup_ifs = array_diff($ipsec_vti_cleanup_ifs, array("ipsec{$child['reqid']}"));
|
1996 |
|
|
$child['local_ts'] .= ",0.0.0.0/0";
|
1997 |
|
|
$child['remote_ts'] .= ",0.0.0.0/0";
|
1998 |
|
|
}
|
1999 |
|
|
|
2000 |
|
|
/****f* ipsec/ipsec_setup_tunnels
|
2001 |
|
|
* NAME
|
2002 |
|
|
* ipsec_setup_tunnels - Configure all P1/P2 entries as swanctl connections
|
2003 |
|
|
* INPUTS
|
2004 |
|
|
* None
|
2005 |
|
|
* RESULT
|
2006 |
|
|
* Sets up a swanctl array for all connections in the configuration along with
|
2007 |
|
|
* their children, authentication, etc.
|
2008 |
|
|
******/
|
2009 |
|
|
function ipsec_setup_tunnels() {
|
2010 |
|
|
global $aggressive_mode_psk, $a_client, $config,
|
2011 |
|
|
$filterdns_list, $g, $ifacesuse, $ipsec_idhandling, $ipsec_log_cats,
|
2012 |
|
|
$ipsec_log_sevs, $ipsec_swanctl_basedir, $ipsec_swanctl_dirs,
|
2013 |
|
|
$ipseccfg, $mobile_ipsec_auth, $natfilterrules, $p1_ealgos,
|
2014 |
|
|
$p2_ealgos, $rgmap, $sa, $sn, $scconf, $conn, $tunnels,
|
2015 |
|
|
$ipsec_vti_cleanup_ifs, $conn_defaults;
|
2016 |
|
|
|
2017 |
|
|
foreach ($tunnels as $ph1ent) {
|
2018 |
|
|
/* Skip disabled entries */
|
2019 |
|
|
if (isset($ph1ent['disabled'])) {
|
2020 |
|
|
continue;
|
2021 |
|
|
}
|
2022 |
|
|
/* If the local source is invalid, skip this entry. */
|
2023 |
|
|
$local_spec = ipsec_get_phase1_src($ph1ent);
|
2024 |
|
|
if (!$local_spec) {
|
2025 |
|
|
continue;
|
2026 |
|
|
}
|
2027 |
|
|
|
2028 |
|
|
/* Determine the name of this connection, either con-mobile for
|
2029 |
|
|
* mobile clients, or a name based on the IKE ID otherwise. */
|
2030 |
faf07413
|
jim-p
|
if (isset($ph1ent['mobile'])) {
|
2031 |
|
|
$cname = "con-mobile";
|
2032 |
|
|
/* Start with common default values */
|
2033 |
|
|
$scconf["{$cname}-defaults"] = $conn_defaults;
|
2034 |
|
|
/* Array reference to make things easier */
|
2035 |
|
|
$conn =& $scconf["{$cname}-defaults"];
|
2036 |
|
|
$scconf['connections']["{$cname} : {$cname}-defaults"] = array("# Stub to load con-mobile-defaults");
|
2037 |
|
|
} else {
|
2038 |
1b4cb00f
|
Viktor G
|
if (get_ipsecifnum($ph1ent['ikeid'], 0)) {
|
2039 |
|
|
$cname = "con" . get_ipsecifnum($ph1ent['ikeid'], 0);
|
2040 |
|
|
} else {
|
2041 |
|
|
$cname = "con{$ph1ent['ikeid']}00000";
|
2042 |
|
|
}
|
2043 |
faf07413
|
jim-p
|
/* Start with common default values */
|
2044 |
|
|
$scconf['connections'][$cname] = $conn_defaults;
|
2045 |
|
|
/* Array reference to make things easier */
|
2046 |
|
|
$conn =& $scconf['connections'][$cname];
|
2047 |
|
|
}
|
2048 |
c6220dcf
|
jim-p
|
|
2049 |
|
|
/* Common parameters for all children */
|
2050 |
|
|
$child_params = array();
|
2051 |
|
|
if (!empty($ph1ent['closeaction'])) {
|
2052 |
|
|
$child_params['close_action'] = $ph1ent['closeaction'];
|
2053 |
|
|
}
|
2054 |
|
|
|
2055 |
|
|
$ikeid = $ph1ent['ikeid'];
|
2056 |
|
|
|
2057 |
|
|
/* "trap" adds policies to start a tunnel when interesting
|
2058 |
|
|
* traffic is observed by the host. */
|
2059 |
|
|
$start_action = "trap";
|
2060 |
|
|
|
2061 |
|
|
/* Set the IKE version appropriately (empty = IKEv1) */
|
2062 |
|
|
switch ($ph1ent['iketype']) {
|
2063 |
|
|
case 'auto':
|
2064 |
|
|
$ikeversion = 0;
|
2065 |
|
|
break;
|
2066 |
|
|
case 'ikev2':
|
2067 |
|
|
$ikeversion = 2;
|
2068 |
|
|
break;
|
2069 |
|
|
case 'ikev1':
|
2070 |
|
|
default:
|
2071 |
|
|
$ikeversion = 1;
|
2072 |
|
|
break;
|
2073 |
|
|
}
|
2074 |
|
|
$conn['version'] = $ikeversion;
|
2075 |
|
|
|
2076 |
|
|
/* For IKEv1 or auto, setup aggressive mode if configured */
|
2077 |
|
|
if ($ikeversion != 2){
|
2078 |
|
|
$conn['aggressive'] = ($ph1ent['mode'] == "aggressive") ? "yes" : "no";
|
2079 |
|
|
}
|
2080 |
|
|
|
2081 |
|
|
if (isset($ph1ent['mobile'])) {
|
2082 |
|
|
/* Mobile tunnels allow 'any' as a peer */
|
2083 |
|
|
$remote_spec = "0.0.0.0/0,::/0";
|
2084 |
|
|
/* Mobile tunnels cannot start automatically */
|
2085 |
|
|
$start_action = 'none';
|
2086 |
|
|
} else {
|
2087 |
|
|
$remote_spec = $ph1ent['remote-gateway'];
|
2088 |
|
|
$sourcehost = (is_ipaddr($remote_spec)) ? $remote_spec : $rgmap[$remote_spec];
|
2089 |
d0cd4fc7
|
Frederic Bor
|
$ifacesuse = ipsec_setup_routes($ph1ent['interface'], $ph1ent['protocol'], $sourcehost, isset($ph1ent['gw_duplicates']));
|
2090 |
c6220dcf
|
jim-p
|
}
|
2091 |
|
|
|
2092 |
|
|
/* Setup IKE proposals */
|
2093 |
|
|
if (is_array($ph1ent['encryption']['item'])) {
|
2094 |
|
|
$ciphers = array();
|
2095 |
|
|
foreach($ph1ent['encryption']['item'] as $p1enc) {
|
2096 |
|
|
if (!is_array($p1enc['encryption-algorithm']) ||
|
2097 |
|
|
empty($p1enc['encryption-algorithm']['name']) ||
|
2098 |
|
|
empty($p1enc['hash-algorithm'])) {
|
2099 |
|
|
continue;
|
2100 |
|
|
}
|
2101 |
f5ddbec1
|
Viktor G
|
if ($ph1ent['prfselect_enable'] != 'yes') {
|
2102 |
|
|
$p1enc['prf-algorithm'] = false;
|
2103 |
|
|
}
|
2104 |
c6220dcf
|
jim-p
|
$ciphers[] = ipsec_setup_proposal_algo($p1enc['encryption-algorithm']['name'],
|
2105 |
|
|
$p1enc['encryption-algorithm']['keylen'],
|
2106 |
|
|
$p1enc['hash-algorithm'],
|
2107 |
f5ddbec1
|
Viktor G
|
$p1enc['prf-algorithm'],
|
2108 |
c6220dcf
|
jim-p
|
$p1enc['dhgroup']);
|
2109 |
|
|
}
|
2110 |
|
|
$conn['proposals'] = implode(",", $ciphers);
|
2111 |
|
|
}
|
2112 |
|
|
|
2113 |
|
|
/* Configure DPD values. The DPD action is a per-child parameter,
|
2114 |
|
|
* not per-connection like the delay and timeout. */
|
2115 |
|
|
if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
|
2116 |
|
|
if ($start_action == "trap") {
|
2117 |
d4e1fdea
|
jim-p
|
$child_params['dpd_action'] = "trap";
|
2118 |
c6220dcf
|
jim-p
|
} else {
|
2119 |
|
|
$child_params['dpd_action'] = "clear";
|
2120 |
|
|
}
|
2121 |
|
|
$conn['dpd_delay'] = "{$ph1ent['dpd_delay']}s";
|
2122 |
|
|
$conn['dpd_timeout'] = $ph1ent['dpd_delay'] * ($ph1ent['dpd_maxfail'] + 1) . "s";
|
2123 |
d4e1fdea
|
jim-p
|
|
2124 |
|
|
/* Adjust dpd_action if the close_action is explicitly set */
|
2125 |
|
|
if (!empty($child_params['close_action'])) {
|
2126 |
|
|
switch ($ph1ent['closeaction']) {
|
2127 |
|
|
case 'trap':
|
2128 |
|
|
$child_params['dpd_action'] = 'trap';
|
2129 |
|
|
break;
|
2130 |
|
|
case 'start':
|
2131 |
|
|
$child_params['dpd_action'] = 'restart';
|
2132 |
|
|
break;
|
2133 |
|
|
case 'none':
|
2134 |
|
|
default:
|
2135 |
|
|
$child_params['dpd_action'] = 'clear';
|
2136 |
|
|
}
|
2137 |
|
|
}
|
2138 |
c6220dcf
|
jim-p
|
} else {
|
2139 |
d4e1fdea
|
jim-p
|
$child_params['dpd_action'] = "clear";
|
2140 |
c6220dcf
|
jim-p
|
}
|
2141 |
|
|
|
2142 |
9701089e
|
jim-p
|
/* Rekey (IKEv2 or Auto only, not supported by IKEv1) */
|
2143 |
c6220dcf
|
jim-p
|
if (($ikeversion == 0) || ($ikeversion == 2)) {
|
2144 |
391591ef
|
jim-p
|
$conn['rekey_time'] = ipsec_get_rekey_time($ph1ent) . "s";
|
2145 |
9701089e
|
jim-p
|
}
|
2146 |
|
|
|
2147 |
391591ef
|
jim-p
|
/* Reauth (Any) */
|
2148 |
|
|
$conn['reauth_time'] = ipsec_get_reauth_time($ph1ent) . "s";
|
2149 |
|
|
|
2150 |
9701089e
|
jim-p
|
/* Over Time */
|
2151 |
391591ef
|
jim-p
|
$conn['over_time'] = ipsec_get_over_time($ph1ent) . "s";
|
2152 |
|
|
|
2153 |
|
|
/* Rand Time */
|
2154 |
|
|
$conn['rand_time'] = ipsec_get_rand_time($ph1ent) . "s";
|
2155 |
c6220dcf
|
jim-p
|
|
2156 |
|
|
/* NAT Traversal */
|
2157 |
|
|
$conn['encap'] = ($ph1ent['nat_traversal'] == 'force') ? "yes" : "no";
|
2158 |
|
|
|
2159 |
|
|
/* MOBIKE support */
|
2160 |
|
|
$conn['mobike'] = ($ph1ent['mobike'] == 'on') ? "yes" : "no";
|
2161 |
|
|
|
2162 |
|
|
/* TFC Padding */
|
2163 |
|
|
if (isset($ph1ent['tfc_enable'])) {
|
2164 |
|
|
$conn['tfc_padding'] = (isset($ph1ent['tfc_bytes']) && is_numericint($ph1ent['tfc_bytes'])) ? $ph1ent['tfc_bytes'] : "mtu";
|
2165 |
|
|
}
|
2166 |
|
|
|
2167 |
92ed9792
|
Frederic Bor
|
/* Custom Ports */
|
2168 |
|
|
if (isset($ph1ent['ikeport'])) {
|
2169 |
|
|
/* For a connection without encapsulation, do not set local_port */
|
2170 |
|
|
$conn['remote_port'] = $ph1ent['ikeport'];
|
2171 |
|
|
} elseif (isset($ph1ent['nattport'])) {
|
2172 |
|
|
/* For an encapsulated connection,
|
2173 |
|
|
* set local_port to the server NAT-T port value or default (4500) */
|
2174 |
|
|
$conn['local_port'] = isset($config['ipsec']['port_nat_t']) ? $config['ipsec']['port_nat_t'] : 4500;
|
2175 |
|
|
$conn['remote_port'] = $ph1ent['nattport'];
|
2176 |
|
|
}
|
2177 |
|
|
|
2178 |
c6220dcf
|
jim-p
|
/* Arrays for P2s/children */
|
2179 |
|
|
$children = array();
|
2180 |
|
|
$remote_ts_spec = array();
|
2181 |
|
|
$local_ts_spec = array();
|
2182 |
|
|
$reqids = array();
|
2183 |
|
|
$has_vti = false;
|
2184 |
|
|
$ealgoAHsp2arr = array();
|
2185 |
|
|
$ealgoESPsp2arr = array();
|
2186 |
|
|
$suffix = 0;
|
2187 |
|
|
|
2188 |
|
|
foreach ($ph1ent['p2'] as $ph2ent) {
|
2189 |
|
|
/* If this entry is disabled, or cannot be configured, skip. */
|
2190 |
|
|
if (isset($ph2ent['disabled']) ||
|
2191 |
|
|
(isset($ph2ent['mobile']) && !isset($a_client['enable']))) {
|
2192 |
|
|
continue;
|
2193 |
|
|
}
|
2194 |
|
|
$child = array();
|
2195 |
|
|
$local_ts = "";
|
2196 |
|
|
$remote_ts = "";
|
2197 |
|
|
if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
|
2198 |
|
|
/* Normal tunnel child config */
|
2199 |
|
|
$child['mode'] = "tunnel";
|
2200 |
|
|
$child['policies'] = "yes";
|
2201 |
|
|
|
2202 |
|
|
$localid_type = $ph2ent['localid']['type'];
|
2203 |
|
|
$localsubnet_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']);
|
2204 |
|
|
|
2205 |
|
|
/* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */
|
2206 |
|
|
if (($localid_type == "none" || $localid_type == "mobile") &&
|
2207 |
|
|
isset($ph1ent['mobile']) && (ipsec_get_number_of_phase2($ikeid) == 1)) {
|
2208 |
|
|
$local_spec = '0.0.0.0/0,::/0';
|
2209 |
|
|
} else {
|
2210 |
|
|
if ($localid_type != "address") {
|
2211 |
|
|
$localid_type = "subnet";
|
2212 |
|
|
}
|
2213 |
|
|
// Don't let an empty subnet into config, it can cause parse errors. Ticket #2201.
|
2214 |
|
|
if (!is_ipaddr($localsubnet_data) && !is_subnet($localsubnet_data) && ($localsubnet_data != "0.0.0.0/0")) {
|
2215 |
|
|
log_error("Invalid IPsec Phase 2 \"{$ph2ent['descr']}\" - {$ph2ent['localid']['type']} has no subnet.");
|
2216 |
|
|
continue;
|
2217 |
|
|
}
|
2218 |
|
|
if (!empty($ph2ent['natlocalid'])) {
|
2219 |
|
|
$natlocalsubnet_data = ipsec_idinfo_to_cidr($ph2ent['natlocalid'], false, $ph2ent['mode']);
|
2220 |
|
|
if ($ph2ent['natlocalid']['type'] != "address") {
|
2221 |
|
|
if (is_subnet($natlocalsubnet_data)) {
|
2222 |
|
|
$localsubnet_data = "{$natlocalsubnet_data}|{$localsubnet_data}";
|
2223 |
|
|
}
|
2224 |
|
|
} else {
|
2225 |
|
|
if (is_ipaddr($natlocalsubnet_data)) {
|
2226 |
|
|
$localsubnet_data = "{$natlocalsubnet_data}|{$localsubnet_data}";
|
2227 |
|
|
}
|
2228 |
|
|
}
|
2229 |
|
|
$natfilterrules = true;
|
2230 |
|
|
}
|
2231 |
|
|
}
|
2232 |
|
|
|
2233 |
|
|
$local_ts = $localsubnet_data;
|
2234 |
|
|
|
2235 |
|
|
if (!isset($ph2ent['mobile'])) {
|
2236 |
|
|
$remote_ts = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
|
2237 |
|
|
} else if (!empty($a_client['pool_address'])) {
|
2238 |
|
|
$remote_ts = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
|
2239 |
|
|
}
|
2240 |
|
|
|
2241 |
|
|
} elseif ($ph2ent['mode'] == 'vti') {
|
2242 |
|
|
/* VTI-specific child config */
|
2243 |
|
|
$child['policies'] = "no";
|
2244 |
|
|
/* VTI cannot use trap policies, so start automatically instead */
|
2245 |
|
|
$start_action = 'start';
|
2246 |
d4e1fdea
|
jim-p
|
if ($child_params['dpd_action'] == "trap") {
|
2247 |
|
|
$child_params['dpd_action'] = "restart";
|
2248 |
|
|
}
|
2249 |
c6220dcf
|
jim-p
|
$localid_type = $ph2ent['localid']['type'];
|
2250 |
|
|
$localsubnet_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']);
|
2251 |
|
|
$local_ts = $localsubnet_data;
|
2252 |
|
|
$remote_ts = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
|
2253 |
|
|
$has_vti = true;
|
2254 |
|
|
} else {
|
2255 |
|
|
/* Transport mode child config */
|
2256 |
|
|
$child['mode'] = "transport";
|
2257 |
|
|
$child['policies'] = "yes";
|
2258 |
|
|
|
2259 |
|
|
if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
|
2260 |
|
|
($ph1ent['authentication_method'] == "pre_shared_key")) &&
|
2261 |
|
|
isset($ph1ent['mobile'])) {
|
2262 |
|
|
$local_spec = "0.0.0.0/0,::/0";
|
2263 |
|
|
} else {
|
2264 |
|
|
$local_ts = ipsec_get_phase1_src($ph1ent);
|
2265 |
|
|
}
|
2266 |
|
|
|
2267 |
|
|
if (!isset($ph2ent['mobile'])) {
|
2268 |
|
|
$remote_ts = $remote_spec;
|
2269 |
|
|
}
|
2270 |
|
|
}
|
2271 |
|
|
|
2272 |
|
|
if (!empty($local_ts)) {
|
2273 |
|
|
$local_ts_spec[] = $local_ts;
|
2274 |
|
|
}
|
2275 |
|
|
if (!empty($remote_ts)) {
|
2276 |
|
|
$remote_ts_spec[] = $remote_ts;
|
2277 |
|
|
}
|
2278 |
|
|
|
2279 |
|
|
/* If a PFS group is configured on the Mobile Clients tab,
|
2280 |
|
|
* and this is a mobile P2, use it here. */
|
2281 |
|
|
if (isset($a_client['pfs_group']) && isset($ph2ent['mobile'])) {
|
2282 |
|
|
$ph2ent['pfsgroup'] = $a_client['pfs_group'];
|
2283 |
|
|
}
|
2284 |
|
|
|
2285 |
|
|
$reqids[] = $ph2ent['reqid'];
|
2286 |
|
|
|
2287 |
|
|
if (!empty($ph2ent['lifetime'])) {
|
2288 |
391591ef
|
jim-p
|
$child['life_time'] = ipsec_get_life_time($ph2ent) . "s";
|
2289 |
170c0f08
|
jim-p
|
/* Rekey at 90% of lifetime */
|
2290 |
391591ef
|
jim-p
|
$child['rekey_time'] = ipsec_get_rekey_time($ph2ent) . "s";
|
2291 |
170c0f08
|
jim-p
|
/* Random rekey fuzz time */
|
2292 |
391591ef
|
jim-p
|
$child['rand_time'] = ipsec_get_rand_time($ph2ent) . "s";
|
2293 |
c6220dcf
|
jim-p
|
}
|
2294 |
|
|
|
2295 |
|
|
/* If we are to act only as a responder, disable the start action */
|
2296 |
|
|
$child['start_action'] = isset($ph1ent['responderonly']) ? 'none' : $start_action;
|
2297 |
|
|
|
2298 |
|
|
/* Setup child SA proposals */
|
2299 |
|
|
$proposal = array();
|
2300 |
6005c9f5
|
Viktor G
|
$ph2ent_ealgos = array();
|
2301 |
|
|
$ph2ent_ealgos_aead = array();
|
2302 |
c6220dcf
|
jim-p
|
if ($ph2ent['protocol'] == 'esp') {
|
2303 |
|
|
if (is_array($ph2ent['encryption-algorithm-option'])) {
|
2304 |
|
|
foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
|
2305 |
6005c9f5
|
Viktor G
|
if (strpos($ealg['name'], "gcm")) {
|
2306 |
|
|
/* put AEAD ciphers on top,
|
2307 |
|
|
* see https://redmine.pfsense.org/issues/11078 */
|
2308 |
|
|
$ph2ent_ealgos_aead[] = $ealg;
|
2309 |
|
|
} else {
|
2310 |
|
|
$ph2ent_ealgos[] = $ealg;
|
2311 |
|
|
}
|
2312 |
|
|
}
|
2313 |
|
|
$ph2ent_ealgos = array_merge(array_reverse($ph2ent_ealgos_aead), $ph2ent_ealgos);
|
2314 |
|
|
foreach ($ph2ent_ealgos as $ealg) {
|
2315 |
c6220dcf
|
jim-p
|
$ealg_id = $ealg['name'];
|
2316 |
|
|
$ealg_kl = $ealg['keylen'];
|
2317 |
|
|
|
2318 |
|
|
if (!empty($ealg_kl) && $ealg_kl == "auto") {
|
2319 |
|
|
if (empty($p2_ealgos) || !is_array($p2_ealgos)) {
|
2320 |
|
|
require_once("ipsec.inc");
|
2321 |
|
|
}
|
2322 |
|
|
$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
|
2323 |
|
|
$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
|
2324 |
|
|
$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
|
2325 |
|
|
/* XXX: in some cases where include ordering is suspect these variables
|
2326 |
|
|
* are somehow 0 and we enter this loop forever and timeout after 900
|
2327 |
|
|
* seconds wrecking bootup */
|
2328 |
|
|
if ($key_hi != 0 and $key_lo != 0 and $key_step != 0) {
|
2329 |
|
|
for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
|
2330 |
|
|
$proposal[] = ipsec_setup_proposal_entry($ph2ent, $ealgoESPsp2arr, $ealg_id, $keylen);
|
2331 |
|
|
}
|
2332 |
|
|
}
|
2333 |
|
|
} else {
|
2334 |
|
|
$proposal[] = ipsec_setup_proposal_entry($ph2ent, $ealgoESPsp2arr, $ealg_id, $ealg_kl);
|
2335 |
|
|
}
|
2336 |
|
|
}
|
2337 |
|
|
}
|
2338 |
|
|
} else if ($ph2ent['protocol'] == 'ah') {
|
2339 |
|
|
$proposal[] = ipsec_setup_proposal_entry($ph2ent, $ealgoAHsp2arr, '', '');
|
2340 |
|
|
}
|
2341 |
|
|
|
2342 |
|
|
/* Not mobile, and IKEv1 or Split Connections active */
|
2343 |
|
|
if (!isset($ph1ent['mobile']) && (($ikeversion == 1) || isset($ph1ent['splitconn']))) {
|
2344 |
|
|
if (!empty($remote_ts)) {
|
2345 |
|
|
/* Setup child sub-connections using unique names with a suffix */
|
2346 |
3b85b43b
|
Viktor G
|
$subconname = "con" . get_ipsecifnum($ph1ent['ikeid'], $idx) . $suffix;
|
2347 |
c6220dcf
|
jim-p
|
$children[$subconname] = $child;
|
2348 |
|
|
$children[$subconname]['local_ts'] = $local_ts;
|
2349 |
|
|
$children[$subconname]['remote_ts'] = $remote_ts;
|
2350 |
|
|
if ($has_vti) {
|
2351 |
|
|
ipsec_setup_vtireq($children[$subconname], $ipsec_vti_cleanup_ifs, $ph1ent['ikeid'], $suffix);
|
2352 |
|
|
}
|
2353 |
|
|
if (!empty($ph2ent['protocol']) && !empty($proposal)) {
|
2354 |
|
|
$children[$subconname][$ph2ent['protocol'] . '_proposals'] = implode(',', $proposal);
|
2355 |
|
|
}
|
2356 |
|
|
} else {
|
2357 |
|
|
log_error(sprintf(gettext("No phase2 specifications for tunnel with REQID = %s"), $ikeid));
|
2358 |
|
|
}
|
2359 |
|
|
} else {
|
2360 |
|
|
/* TODO: Fix this to nicely merge all P2 params for single child case */
|
2361 |
|
|
if (!is_array($children[$cname])) {
|
2362 |
|
|
$children[$cname] = array();
|
2363 |
|
|
}
|
2364 |
|
|
$children[$cname] = array_merge($children[$cname], $child);
|
2365 |
|
|
}
|
2366 |
|
|
$suffix++;
|
2367 |
|
|
}
|
2368 |
|
|
|
2369 |
|
|
$conn['local_addrs'] = $local_spec;
|
2370 |
|
|
$conn['remote_addrs'] = $remote_spec;
|
2371 |
|
|
|
2372 |
407a5c28
|
jim-p
|
$pools = array();
|
2373 |
c6220dcf
|
jim-p
|
if (isset($ph1ent['mobile'])) {
|
2374 |
f9c9899b
|
Viktor Gurov
|
if (($ph1ent['authentication_method'] == 'eap-radius') &&
|
2375 |
|
|
empty($a_client['pool_address']) && empty($a_client['pool_address_v6'])) {
|
2376 |
407a5c28
|
jim-p
|
$pools[] = "radius";
|
2377 |
f9c9899b
|
Viktor Gurov
|
} else {
|
2378 |
407a5c28
|
jim-p
|
if (!empty($a_client['pool_address'])) {
|
2379 |
|
|
$pools[] = "mobile-pool-v4";
|
2380 |
|
|
}
|
2381 |
|
|
if (!empty($a_client['pool_address_v6'])) {
|
2382 |
|
|
$pools[] = "mobile-pool-v6";
|
2383 |
|
|
}
|
2384 |
f9c9899b
|
Viktor Gurov
|
if (isset($a_client['radius_ip_priority_enable'])) {
|
2385 |
407a5c28
|
jim-p
|
$pools[] .= "radius";
|
2386 |
f9c9899b
|
Viktor Gurov
|
}
|
2387 |
|
|
}
|
2388 |
c6220dcf
|
jim-p
|
}
|
2389 |
407a5c28
|
jim-p
|
$conn['pools'] = implode(', ', $pools);
|
2390 |
c6220dcf
|
jim-p
|
|
2391 |
|
|
/* For IKEv2 without Split Connections, setup combined sets of
|
2392 |
|
|
* local/remote traffic selectors and propsals */
|
2393 |
|
|
if (!(!isset($ph1ent['mobile']) && (($ikeversion == 1) || isset($ph1ent['splitconn'])))) {
|
2394 |
|
|
if (!isset($ph1ent['mobile']) && !empty($remote_ts_spec)) {
|
2395 |
|
|
$children[$cname]['remote_ts'] = implode(",", $remote_ts_spec);
|
2396 |
|
|
}
|
2397 |
|
|
if (!empty($local_ts_spec)) {
|
2398 |
|
|
$children[$cname]['local_ts'] = implode(",", $local_ts_spec);
|
2399 |
|
|
}
|
2400 |
|
|
if ($has_vti) {
|
2401 |
|
|
ipsec_setup_vtireq($children[$cname], $ipsec_vti_cleanup_ifs, $ph1ent['ikeid']);
|
2402 |
|
|
}
|
2403 |
|
|
if (!empty($ealgoAHsp2arr)) {
|
2404 |
|
|
$children[$cname]['ah_proposals'] = implode(',', array_unique($ealgoAHsp2arr));
|
2405 |
|
|
}
|
2406 |
|
|
if (!empty($ealgoESPsp2arr)) {
|
2407 |
|
|
$children[$cname]['esp_proposals'] = implode(',', array_unique($ealgoESPsp2arr));
|
2408 |
|
|
}
|
2409 |
|
|
}
|
2410 |
|
|
|
2411 |
|
|
/* Setup connection authentication */
|
2412 |
|
|
ipsec_setup_authentication($ph1ent, $conn);
|
2413 |
|
|
|
2414 |
|
|
/* Add children to this connection, including default child parameters */
|
2415 |
|
|
if (count($children)) {
|
2416 |
|
|
foreach($children as $name => $child) {
|
2417 |
|
|
$conn['children'][$name] = array_merge($child_params, $child);
|
2418 |
|
|
}
|
2419 |
|
|
}
|
2420 |
|
|
|
2421 |
|
|
}
|
2422 |
|
|
|
2423 |
|
|
return;
|
2424 |
|
|
}
|
2425 |
|
|
|
2426 |
|
|
/****f* ipsec/ipsec_setup_secrets
|
2427 |
|
|
* NAME
|
2428 |
|
|
* ipsec_setup_secrets - Setup swanctl authentication secrets
|
2429 |
|
|
* INPUTS
|
2430 |
|
|
* None
|
2431 |
|
|
* RESULT
|
2432 |
|
|
* Returns a swanctl array containing secrets (PSKs, certs, etc) and writes out
|
2433 |
|
|
* necessary CA, CRL, and certificate data.
|
2434 |
|
|
******/
|
2435 |
|
|
function ipsec_setup_secrets() {
|
2436 |
|
|
global $config, $a_phase1, $ipsec_swanctl_dirs, $ipseccfg, $rgmap, $scconf;
|
2437 |
|
|
|
2438 |
|
|
$suffix = 0;
|
2439 |
|
|
|
2440 |
|
|
/* write out CRL files */
|
2441 |
|
|
if (is_array($config['crl']) && count($config['crl'])) {
|
2442 |
|
|
foreach ($config['crl'] as $crl) {
|
2443 |
|
|
if (!isset($crl['text'])) {
|
2444 |
|
|
log_error(sprintf(gettext("Warning: Missing CRL data for %s"), $crl['descr']));
|
2445 |
|
|
continue;
|
2446 |
|
|
}
|
2447 |
|
|
$fpath = "{$ipsec_swanctl_dirs['crlpath']}/{$crl['refid']}.crl";
|
2448 |
|
|
if (!@file_put_contents($fpath, base64_decode($crl['text']))) {
|
2449 |
|
|
log_error(sprintf(gettext("Error: Cannot write IPsec CRL file for %s"), $crl['descr']));
|
2450 |
|
|
continue;
|
2451 |
|
|
}
|
2452 |
|
|
}
|
2453 |
|
|
}
|
2454 |
|
|
|
2455 |
|
|
$vpncas = array();
|
2456 |
|
|
if (is_array($a_phase1) && count($a_phase1)) {
|
2457 |
|
|
foreach ($a_phase1 as $ph1ent) {
|
2458 |
|
|
if (isset($ph1ent['disabled'])) {
|
2459 |
|
|
continue;
|
2460 |
|
|
}
|
2461 |
|
|
|
2462 |
|
|
if (strstr($ph1ent['authentication_method'], 'cert') ||
|
2463 |
|
|
in_array($ph1ent['authentication_method'], array('eap-mschapv2', 'eap-tls', 'eap-radius'))) {
|
2464 |
|
|
/* Write certificate and private key, point to private key */
|
2465 |
|
|
$certline = '';
|
2466 |
|
|
|
2467 |
|
|
$ikeid = $ph1ent['ikeid'];
|
2468 |
|
|
$cert = lookup_cert($ph1ent['certref']);
|
2469 |
|
|
|
2470 |
|
|
if (!$cert) {
|
2471 |
|
|
log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
|
2472 |
|
|
continue;
|
2473 |
|
|
}
|
2474 |
|
|
|
2475 |
|
|
/* add signing CA cert chain of server cert
|
2476 |
|
|
* to the list of CAs to write
|
2477 |
|
|
*/
|
2478 |
|
|
$cachain = ca_chain_array($cert);
|
2479 |
|
|
if ($cachain && is_array($cachain)) {
|
2480 |
|
|
foreach ($cachain as $cacrt) {
|
2481 |
|
|
$vpncas[$cacrt['refid']] = $cacrt;
|
2482 |
|
|
}
|
2483 |
|
|
}
|
2484 |
|
|
|
2485 |
|
|
@chmod($ipsec_swanctl_dirs['certpath'], 0600);
|
2486 |
|
|
|
2487 |
|
|
$ph1keyfile = "{$ipsec_swanctl_dirs['keypath']}/cert-{$ikeid}.key";
|
2488 |
|
|
if (!file_put_contents($ph1keyfile, base64_decode($cert['prv']))) {
|
2489 |
|
|
log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
|
2490 |
|
|
continue;
|
2491 |
|
|
}
|
2492 |
|
|
@chmod($ph1keyfile, 0600);
|
2493 |
|
|
|
2494 |
|
|
$ph1certfile = "{$ipsec_swanctl_dirs['certpath']}/cert-{$ikeid}.crt";
|
2495 |
|
|
if (!file_put_contents($ph1certfile, base64_decode($cert['crt']))) {
|
2496 |
|
|
log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
|
2497 |
|
|
@unlink($ph1keyfile);
|
2498 |
|
|
continue;
|
2499 |
|
|
}
|
2500 |
|
|
@chmod($ph1certfile, 0600);
|
2501 |
|
|
|
2502 |
|
|
$scconf['secrets']['private-' . $suffix++] = array('file' => $ph1keyfile);
|
2503 |
5f143b6e
|
Viktor Gurov
|
} else if (strstr($ph1ent['authentication_method'], 'pkcs11')) {
|
2504 |
367d8609
|
Viktor Gurov
|
$p11_id = array();
|
2505 |
|
|
$output = shell_exec('/usr/local/bin/pkcs15-tool -c');
|
2506 |
|
|
preg_match_all('/ID\s+: (.*)/', $output, $p11_id);
|
2507 |
|
|
if (!empty($ph1ent['pkcs11certref']) && in_array($ph1ent['pkcs11certref'], $p11_id[1])) {
|
2508 |
5f143b6e
|
Viktor Gurov
|
$scconf['secrets']['token-' . $suffix++] = array(
|
2509 |
|
|
'handle' => $ph1ent['pkcs11certref'],
|
2510 |
|
|
'pin' => $ph1ent['pkcs11pin'],
|
2511 |
|
|
);
|
2512 |
|
|
} else {
|
2513 |
367d8609
|
Viktor Gurov
|
log_error(sprintf(gettext("Error: Invalid phase1 PKCS#11 certificate reference or PKCS#11 is not present for %s"), $ph1ent['name']));
|
2514 |
|
|
continue;
|
2515 |
5f143b6e
|
Viktor Gurov
|
}
|
2516 |
c6220dcf
|
jim-p
|
} else {
|
2517 |
|
|
/* Setup pre-shared keys */
|
2518 |
|
|
list($myid_type, $myid_data) = ipsec_find_id($ph1ent, 'local');
|
2519 |
|
|
list($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, 'peer', $rgmap);
|
2520 |
|
|
$myid = trim($myid_data);
|
2521 |
|
|
|
2522 |
|
|
if (empty($peerid_data)) {
|
2523 |
|
|
continue;
|
2524 |
|
|
}
|
2525 |
|
|
|
2526 |
|
|
if ($myid_type == 'fqdn' && !empty($myid)) {
|
2527 |
|
|
$myid = "@{$myid}";
|
2528 |
|
|
}
|
2529 |
|
|
|
2530 |
131b41fc
|
jim-p
|
$myid = isset($ph1ent['mobile']) ? ipsec_fixup_id($myid_type, trim($myid_data)) : "%any";
|
2531 |
|
|
$peerid = ($peerid_data != 'allusers') ? ipsec_fixup_id($peerid_type, trim($peerid_data)) : '';
|
2532 |
c6220dcf
|
jim-p
|
|
2533 |
|
|
if ($peerid_type == 'fqdn' && !empty($peerid)) {
|
2534 |
|
|
$peerid = "@{$peerid}";
|
2535 |
|
|
}
|
2536 |
|
|
|
2537 |
|
|
if (!empty($ph1ent['pre-shared-key'])) {
|
2538 |
|
|
$scconf['secrets']['ike-' . $suffix++] = array(
|
2539 |
|
|
'secret' => '0s' . base64_encode(trim($ph1ent['pre-shared-key'])),
|
2540 |
|
|
'id-0' => $myid,
|
2541 |
|
|
'id-1' => $peerid,
|
2542 |
|
|
);
|
2543 |
|
|
if (isset($ph1ent['mobile'])) {
|
2544 |
|
|
$scconf['secrets']['ike-' . $suffix++] = array(
|
2545 |
|
|
'secret' => '0s' . base64_encode(trim($ph1ent['pre-shared-key'])),
|
2546 |
|
|
'id-0' => $myid,
|
2547 |
|
|
'id-1' => '%any',
|
2548 |
|
|
);
|
2549 |
|
|
$scconf['secrets']['ike-' . $suffix++] = array(
|
2550 |
|
|
'secret' => '0s' . base64_encode(trim($ph1ent['pre-shared-key'])),
|
2551 |
|
|
);
|
2552 |
|
|
}
|
2553 |
|
|
}
|
2554 |
|
|
}
|
2555 |
|
|
|
2556 |
|
|
/* if the client authenticates with a cert add the
|
2557 |
|
|
* client cert CA chain to the list of CAs to write
|
2558 |
|
|
*/
|
2559 |
|
|
if (in_array($ph1ent['authentication_method'],
|
2560 |
8c120b1f
|
Viktor G
|
array('cert', 'eap-tls', 'xauth_cert_server', 'pkcs11'))) {
|
2561 |
c6220dcf
|
jim-p
|
if (!empty($ph1ent['caref']) && !array_key_exists($ph1ent['caref'], $vpncas)) {
|
2562 |
|
|
$thisca = lookup_ca($ph1ent['caref']);
|
2563 |
|
|
$vpncas[$ph1ent['caref']] = $thisca;
|
2564 |
|
|
/* follow chain up to root */
|
2565 |
|
|
$cachain = ca_chain_array($thisca);
|
2566 |
|
|
if ($cachain and is_array($cachain)) {
|
2567 |
|
|
foreach ($cachain as $cacrt) {
|
2568 |
|
|
$vpncas[$cacrt['refid']] = $cacrt;
|
2569 |
|
|
}
|
2570 |
|
|
}
|
2571 |
|
|
}
|
2572 |
|
|
}
|
2573 |
|
|
}
|
2574 |
|
|
}
|
2575 |
|
|
|
2576 |
|
|
/* Write the required CAs */
|
2577 |
|
|
foreach ($vpncas as $carefid => $cadata) {
|
2578 |
|
|
$cacrt = base64_decode($cadata['crt']);
|
2579 |
|
|
$cacrtattrs = openssl_x509_parse($cacrt);
|
2580 |
|
|
if (!is_array($cacrtattrs) || !isset($cacrtattrs['hash'])) {
|
2581 |
|
|
log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $cadata['descr']));
|
2582 |
|
|
continue;
|
2583 |
|
|
}
|
2584 |
|
|
$cafilename = "{$ipsec_swanctl_dirs['capath']}/{$cacrtattrs['hash']}.0";
|
2585 |
|
|
if (!@file_put_contents($cafilename, $cacrt)) {
|
2586 |
|
|
log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $cadata['descr']));
|
2587 |
|
|
continue;
|
2588 |
|
|
}
|
2589 |
|
|
}
|
2590 |
|
|
|
2591 |
|
|
/* Add user PSKs */
|
2592 |
|
|
if (is_array($config['system']) && is_array($config['system']['user'])) {
|
2593 |
|
|
foreach ($config['system']['user'] as $user) {
|
2594 |
|
|
if (!empty($user['ipsecpsk'])) {
|
2595 |
|
|
$scconf['secrets']['ike-' . $suffix++] = array(
|
2596 |
|
|
'secret' => '0s' . base64_encode(trim($user['ipsecpsk'])),
|
2597 |
|
|
'id-0' => $myid,
|
2598 |
|
|
'id-1' => $user['name'],
|
2599 |
|
|
);
|
2600 |
|
|
}
|
2601 |
|
|
}
|
2602 |
|
|
unset($user);
|
2603 |
|
|
}
|
2604 |
|
|
|
2605 |
|
|
/* add PSKs for mobile clients */
|
2606 |
|
|
if (is_array($ipseccfg['mobilekey'])) {
|
2607 |
|
|
foreach ($ipseccfg['mobilekey'] as $key) {
|
2608 |
|
|
if (($key['ident'] == 'allusers') ||
|
2609 |
|
|
($key['ident'] == 'any')) {
|
2610 |
|
|
$key['ident'] = '%any';
|
2611 |
|
|
}
|
2612 |
2c9c2891
|
jim-p
|
$userkeyprefix = (strtolower($key['type']) == 'eap') ? 'eap' : 'ike';
|
2613 |
|
|
$scconf['secrets'][$userkeyprefix . '-' . $suffix++] = array(
|
2614 |
c6220dcf
|
jim-p
|
'secret' => '0s' . base64_encode(trim($key['pre-shared-key'])),
|
2615 |
|
|
'id-0' => $key['ident'],
|
2616 |
|
|
);
|
2617 |
|
|
}
|
2618 |
|
|
unset($key);
|
2619 |
|
|
}
|
2620 |
|
|
return;
|
2621 |
|
|
}
|
2622 |
|
|
|
2623 |
|
|
/****f* ipsec/ipsec_configure
|
2624 |
|
|
* NAME
|
2625 |
|
|
* ipsec_configure - Configure IPsec
|
2626 |
|
|
* INPUTS
|
2627 |
|
|
* $restart: Boolean (default false), whether or not to restart the IPsec
|
2628 |
|
|
* daemons.
|
2629 |
|
|
* RESULT
|
2630 |
|
|
* IPsec-related configuration files are written, daemon is started or stopped
|
2631 |
|
|
* appropriately.
|
2632 |
|
|
******/
|
2633 |
|
|
function ipsec_configure($restart = false) {
|
2634 |
|
|
global $aggressive_mode_psk, $a_client, $a_phase1, $a_phase2, $config,
|
2635 |
|
|
$filterdns_list, $g, $ifacesuse, $ipsec_idhandling, $ipsec_log_cats,
|
2636 |
|
|
$ipsec_log_sevs, $ipsec_swanctl_basedir, $ipsec_swanctl_dirs,
|
2637 |
|
|
$ipseccfg, $mobile_ipsec_auth, $natfilterrules, $p1_ealgos,
|
2638 |
|
|
$p2_ealgos, $rgmap, $sa, $sn, $scconf, $tunnels, $mobile_configured,
|
2639 |
|
|
$ipsec_vti_cleanup_ifs, $conn_defaults, $pool_addrs;
|
2640 |
|
|
|
2641 |
|
|
/* service may have been enabled, disabled, or otherwise changed in a
|
2642 |
|
|
*way requiring rule updates */
|
2643 |
|
|
filter_configure();
|
2644 |
|
|
|
2645 |
|
|
if (!ipsec_enabled()) {
|
2646 |
|
|
/* IPsec is disabled */
|
2647 |
|
|
/* Stop charon */
|
2648 |
|
|
mwexec("/usr/local/sbin/strongswanrc stop");
|
2649 |
|
|
/* Stop dynamic monitoring */
|
2650 |
|
|
killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
|
2651 |
|
|
/* Wait for process to die */
|
2652 |
|
|
sleep(2);
|
2653 |
|
|
/* Shutdown enc0 interface*/
|
2654 |
|
|
mwexec("/sbin/ifconfig enc0 down");
|
2655 |
b08a1fa1
|
Viktor Gurov
|
ipsec_gre_default_mtu();
|
2656 |
c6220dcf
|
jim-p
|
return 0;
|
2657 |
|
|
} else {
|
2658 |
|
|
/* Startup enc0 interface */
|
2659 |
|
|
mwexec("/sbin/ifconfig enc0 up");
|
2660 |
|
|
}
|
2661 |
|
|
|
2662 |
|
|
if (platform_booting()) {
|
2663 |
|
|
echo gettext("Configuring IPsec VPN... ");
|
2664 |
|
|
}
|
2665 |
|
|
|
2666 |
|
|
$ipsecstartlock = lock('ipsec', LOCK_EX);
|
2667 |
|
|
|
2668 |
|
|
/* Prepare automatic ping_hosts.sh data */
|
2669 |
|
|
unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
|
2670 |
|
|
touch("{$g['vardb_path']}/ipsecpinghosts");
|
2671 |
|
|
$ipsecpinghostsactive = false;
|
2672 |
|
|
|
2673 |
|
|
/* Populate convenience variables */
|
2674 |
|
|
$syscfg = $config['system'];
|
2675 |
|
|
init_config_arr(array('ipsec', 'phase1'));
|
2676 |
|
|
$ipseccfg = $config['ipsec'];
|
2677 |
|
|
$a_phase1 = $config['ipsec']['phase1'];
|
2678 |
|
|
init_config_arr(array('ipsec', 'phase2'));
|
2679 |
|
|
$a_phase2 = $config['ipsec']['phase2'];
|
2680 |
|
|
init_config_arr(array('ipsec', 'client'));
|
2681 |
|
|
$a_client = $config['ipsec']['client'];
|
2682 |
|
|
|
2683 |
|
|
$mobile_configured = false;
|
2684 |
|
|
|
2685 |
|
|
/* Setup a single structured array to process, to avoid repeatedly
|
2686 |
|
|
* looping through the arrays to locate entries later. */
|
2687 |
|
|
$tunnels = array();
|
2688 |
|
|
foreach ($a_phase1 as $p1) {
|
2689 |
d2abe7c9
|
jim-p
|
if (empty($p1)) {
|
2690 |
|
|
continue;
|
2691 |
|
|
}
|
2692 |
c6220dcf
|
jim-p
|
if (isset($p1['mobile']) && !isset($p1['disabled'])) {
|
2693 |
|
|
$mobile_configured = true;
|
2694 |
|
|
}
|
2695 |
|
|
$tunnels[$p1['ikeid']] = $p1;
|
2696 |
|
|
$tunnels[$p1['ikeid']]['p2'] = array();
|
2697 |
|
|
}
|
2698 |
|
|
foreach ($a_phase2 as $p2) {
|
2699 |
|
|
$tunnels[$p2['ikeid']]['p2'][] = $p2;
|
2700 |
|
|
}
|
2701 |
|
|
|
2702 |
|
|
$ipsec_vti_cleanup_ifs = array();
|
2703 |
|
|
$rgmap = array();
|
2704 |
|
|
$filterdns_list = array();
|
2705 |
|
|
$aggressive_mode_psk = false;
|
2706 |
|
|
$mobile_ipsec_auth = "";
|
2707 |
|
|
$ifacesuse = array();
|
2708 |
|
|
$natfilterrules = false;
|
2709 |
|
|
|
2710 |
|
|
/* Configure asynchronous crypto. See https://redmine.pfsense.org/issues/8772 */
|
2711 |
|
|
set_sysctl(array('net.inet.ipsec.async_crypto' => (int) (isset($ipseccfg['async_crypto']) && ($ipseccfg['async_crypto'] == "enabled"))));
|
2712 |
|
|
|
2713 |
|
|
/* Build a list of all IPsec interfaces configured on the firewall at the OS level */
|
2714 |
|
|
foreach (get_interface_arr() as $thisif) {
|
2715 |
|
|
if (substr($thisif, 0, 5) == "ipsec") {
|
2716 |
|
|
$ipsec_vti_cleanup_ifs[] = $thisif;
|
2717 |
|
|
}
|
2718 |
|
|
}
|
2719 |
|
|
|
2720 |
|
|
/* Create directory structure for IPsec */
|
2721 |
|
|
ipsec_create_dirs();
|
2722 |
|
|
|
2723 |
|
|
/* Setup gateways and interfaces */
|
2724 |
|
|
ipsec_setup_gwifs();
|
2725 |
|
|
|
2726 |
|
|
/* Setup and write strongswan.conf */
|
2727 |
|
|
ipsec_setup_strongswan();
|
2728 |
|
|
|
2729 |
|
|
/* Start Global Connection default values */
|
2730 |
|
|
$conn_defaults = array();
|
2731 |
|
|
/* Fragmentation is on for everyone */
|
2732 |
|
|
$conn_defaults['fragmentation'] = "yes";
|
2733 |
|
|
/* Default to 'replace' for unique IDs (was 'yes' in ipsec.conf previously) */
|
2734 |
|
|
$conn_defaults['unique'] = 'replace';
|
2735 |
|
|
/* If the configuration has a valid alternate value for unique ID handling,
|
2736 |
|
|
* use it instead. */
|
2737 |
|
|
if (!empty($config['ipsec']['uniqueids']) &&
|
2738 |
|
|
array_key_exists($config['ipsec']['uniqueids'], $ipsec_idhandling)) {
|
2739 |
|
|
$conn_defaults['unique'] = $config['ipsec']['uniqueids'];
|
2740 |
|
|
}
|
2741 |
|
|
if (isset($config['ipsec']['strictcrlpolicy'])) {
|
2742 |
|
|
$conn_defaults['strictcrlpolicy'] = "yes";
|
2743 |
|
|
}
|
2744 |
|
|
/* Disable ipcomp for now. redmine #6167
|
2745 |
|
|
if (isset($config['ipsec']['compression'])) {
|
2746 |
|
|
$conn_defaults['compress'] = "yes";
|
2747 |
|
|
}
|
2748 |
|
|
set_single_sysctl('net.inet.ipcomp.ipcomp_enable', (isset($config['ipsec']['compression'])) ? 1 : 0);
|
2749 |
|
|
*/
|
2750 |
|
|
/* End Global Connection Defaults */
|
2751 |
|
|
|
2752 |
|
|
/* Start swanctl configuration (scconf) */
|
2753 |
|
|
$scconf = array();
|
2754 |
|
|
$scconf[] = "# This file is automatically generated. Do not edit";
|
2755 |
|
|
$scconf['connections'] = array();
|
2756 |
14b52494
|
Viktor Gurov
|
/* Setup IPsec bypass */
|
2757 |
|
|
ipsec_setup_bypass();
|
2758 |
c6220dcf
|
jim-p
|
/* Setup connections */
|
2759 |
|
|
ipsec_setup_tunnels();
|
2760 |
|
|
$scconf['pools'] = array();
|
2761 |
|
|
if ($mobile_configured) {
|
2762 |
|
|
/* Setup mobile address pools */
|
2763 |
|
|
ipsec_setup_pools();
|
2764 |
|
|
/* Setup per-user pools */
|
2765 |
|
|
ipsec_setup_userpools();
|
2766 |
|
|
}
|
2767 |
|
|
/* Setup secret data */
|
2768 |
|
|
$scconf['secrets'] = array();
|
2769 |
|
|
ipsec_setup_secrets();
|
2770 |
|
|
|
2771 |
|
|
@file_put_contents("{$g['varetc_path']}/ipsec/swanctl.conf", ipsec_strongswan_confgen($scconf));
|
2772 |
|
|
|
2773 |
|
|
/* Clean up unused VTI interfaces */
|
2774 |
|
|
foreach ($ipsec_vti_cleanup_ifs as $cleanif) {
|
2775 |
|
|
if (does_interface_exist($cleanif)) {
|
2776 |
|
|
mwexec("/sbin/ifconfig " . escapeshellarg($cleanif) . " destroy", false);
|
2777 |
|
|
}
|
2778 |
|
|
}
|
2779 |
|
|
|
2780 |
b08a1fa1
|
Viktor Gurov
|
/* set default MTU to 1400 for GRE over IPsec, othewise to 1476 */
|
2781 |
|
|
ipsec_gre_default_mtu();
|
2782 |
|
|
|
2783 |
c6220dcf
|
jim-p
|
/* Manage process */
|
2784 |
|
|
if ($restart === true) {
|
2785 |
|
|
mwexec_bg("/usr/local/sbin/strongswanrc restart", false);
|
2786 |
|
|
} else {
|
2787 |
|
|
if (isvalidpid("{$g['varrun_path']}/charon.pid")) {
|
2788 |
|
|
mwexec_bg("/usr/local/sbin/strongswanrc reload", false);
|
2789 |
|
|
} else {
|
2790 |
|
|
mwexec_bg("/usr/local/sbin/strongswanrc start", false);
|
2791 |
|
|
}
|
2792 |
|
|
}
|
2793 |
|
|
|
2794 |
|
|
// Run ping_hosts.sh once if it's enabled to avoid wait for minicron
|
2795 |
|
|
if ($ipsecpinghostsactive) {
|
2796 |
|
|
mwexec_bg("/usr/local/bin/ping_hosts.sh");
|
2797 |
|
|
}
|
2798 |
|
|
|
2799 |
|
|
if ($natfilterrules == true) {
|
2800 |
|
|
filter_configure();
|
2801 |
|
|
}
|
2802 |
|
|
/* start filterdns, if necessary */
|
2803 |
|
|
if (count($filterdns_list) > 0) {
|
2804 |
|
|
$interval = 60;
|
2805 |
|
|
if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval'])) {
|
2806 |
|
|
$interval = $ipseccfg['dns-interval'];
|
2807 |
|
|
}
|
2808 |
|
|
|
2809 |
|
|
$hostnames = "";
|
2810 |
|
|
array_unique($filterdns_list);
|
2811 |
|
|
foreach ($filterdns_list as $hostname) {
|
2812 |
|
|
$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
|
2813 |
|
|
}
|
2814 |
|
|
file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
|
2815 |
|
|
unset($hostnames);
|
2816 |
|
|
|
2817 |
|
|
if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid")) {
|
2818 |
|
|
sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
|
2819 |
|
|
} else {
|
2820 |
|
|
mwexec_bg("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
|
2821 |
|
|
}
|
2822 |
|
|
} else {
|
2823 |
|
|
killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
|
2824 |
|
|
@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
|
2825 |
|
|
}
|
2826 |
|
|
|
2827 |
|
|
if (platform_booting()) {
|
2828 |
|
|
echo "done\n";
|
2829 |
|
|
}
|
2830 |
|
|
|
2831 |
|
|
unlock($ipsecstartlock);
|
2832 |
|
|
return count($filterdns_list);
|
2833 |
|
|
}
|
2834 |
b08a1fa1
|
Viktor Gurov
|
|
2835 |
|
|
function ipsec_gre_default_mtu() {
|
2836 |
|
|
global $config;
|
2837 |
|
|
|
2838 |
|
|
foreach ($config['interfaces'] as $if => $ifdetail) {
|
2839 |
|
|
if (interface_is_type($ifdetail['if'], 'gre') && !isset($ifdetail['mtu'])) {
|
2840 |
|
|
if (is_greipsec($ifdetail['if'])) {
|
2841 |
|
|
set_interface_mtu($ifdetail['if'], 1400);
|
2842 |
|
|
} else {
|
2843 |
|
|
set_interface_mtu($ifdetail['if'], 1476);
|
2844 |
|
|
}
|
2845 |
|
|
}
|
2846 |
|
|
}
|
2847 |
|
|
}
|
2848 |
391591ef
|
jim-p
|
|
2849 |
|
|
/* Return the larger of derived SA rekey time and reauth time */
|
2850 |
|
|
function ipsec_get_renewmax($entry) {
|
2851 |
|
|
if (empty($entry) || !is_array($entry)) {
|
2852 |
|
|
return 0;
|
2853 |
|
|
}
|
2854 |
|
|
return max(ipsec_get_rekey_time($entry), ipsec_get_reauth_time($entry));
|
2855 |
|
|
}
|
2856 |
|
|
|
2857 |
|
|
/* Determine the life time of an SA entry (Hard upper total time limit for SA before it is removed) */
|
2858 |
|
|
function ipsec_get_life_time($entry) {
|
2859 |
|
|
if (empty($entry) || !is_array($entry)) {
|
2860 |
|
|
return 0;
|
2861 |
|
|
}
|
2862 |
|
|
/* Use a hardcoded value if present in the configuration */
|
2863 |
|
|
if ($entry['lifetime'] > 0) {
|
2864 |
|
|
return $entry['lifetime'];
|
2865 |
|
|
}
|
2866 |
|
|
/* If rekey or reauth are enabled, attempt to derive a lifetime from one of those */
|
2867 |
|
|
$renewmax = ipsec_get_renewmax($entry);
|
2868 |
|
|
if ($renewmax > 0) {
|
2869 |
|
|
return intval($renewmax / 0.9);
|
2870 |
|
|
}
|
2871 |
|
|
/* To reach here, rekey_time and lifetime are both 0 which is invalid
|
2872 |
|
|
* Default to 16000 for p1 and 4000 for p2 */
|
2873 |
|
|
if ($entry['iketype']) {
|
2874 |
|
|
return 16000;
|
2875 |
|
|
} else {
|
2876 |
|
|
return 4000;
|
2877 |
|
|
}
|
2878 |
|
|
}
|
2879 |
|
|
|
2880 |
|
|
/* Determine the rekey time of an SA entry (Time at which to rekey IKEv2 or Child SA entries) */
|
2881 |
|
|
function ipsec_get_rekey_time($entry) {
|
2882 |
|
|
if (empty($entry) || !is_array($entry)) {
|
2883 |
|
|
return 0;
|
2884 |
|
|
}
|
2885 |
|
|
/* Use a hardcoded value if present in the configuration */
|
2886 |
|
|
if (strlen($entry['rekey_time'])) {
|
2887 |
|
|
/* Check via strlen since 0 is a valid value */
|
2888 |
|
|
return $entry['rekey_time'];
|
2889 |
|
|
} elseif ($entry['lifetime'] > 0) {
|
2890 |
|
|
/* If rekey_time is empty and lifetime is non-zero, use 90% lifetime */
|
2891 |
|
|
return intval($entry['lifetime'] * 0.9);
|
2892 |
|
|
}
|
2893 |
|
|
/* To reach here, rekey_time and lifetime are empty
|
2894 |
|
|
* Default to 14400 for p1 and 3600 for p2 */
|
2895 |
|
|
if ($entry['iketype']) {
|
2896 |
|
|
return 14400;
|
2897 |
|
|
} else {
|
2898 |
|
|
return 3600;
|
2899 |
|
|
}
|
2900 |
|
|
}
|
2901 |
|
|
|
2902 |
|
|
/* Determine the reauth time of an SA entry (IKE SA tear-down/reauthenticate) */
|
2903 |
|
|
function ipsec_get_reauth_time($entry) {
|
2904 |
|
|
if (empty($entry) || !is_array($entry)) {
|
2905 |
|
|
return 0;
|
2906 |
|
|
}
|
2907 |
|
|
/* Use a hardcoded value if present in the configuration */
|
2908 |
|
|
if (strlen($entry['reauth_time'])) {
|
2909 |
|
|
/* Check via strlen since 0 is a valid value */
|
2910 |
|
|
return $entry['reauth_time'];
|
2911 |
|
|
} elseif ($entry['lifetime'] > 0) {
|
2912 |
|
|
/* If reauth_time is empty and lifetime is non-zero,
|
2913 |
|
|
* use 90% lifetime for IKEv1, disable for IKEv2/auto */
|
2914 |
|
|
if ($entry['iketype'] == 'ikev1') {
|
2915 |
|
|
return intval($entry['lifetime'] * 0.9);
|
2916 |
|
|
} else {
|
2917 |
|
|
return 0;
|
2918 |
|
|
}
|
2919 |
|
|
}
|
2920 |
|
|
/* To reach here, rekey_time and lifetime are empty
|
2921 |
|
|
* Default to disabled (0) */
|
2922 |
|
|
return 0;
|
2923 |
|
|
}
|
2924 |
|
|
|
2925 |
|
|
/* Determine the over time of an SA entry (Hard upper IKE SA time limit, relative to rekey/reauth time) */
|
2926 |
|
|
function ipsec_get_over_time($entry) {
|
2927 |
|
|
if (empty($entry) || !is_array($entry)) {
|
2928 |
|
|
return 0;
|
2929 |
|
|
}
|
2930 |
|
|
/* Automatically derive the value for rand_time */
|
2931 |
|
|
$lifetime = ipsec_get_life_time($entry);
|
2932 |
|
|
$renewmax = ipsec_get_renewmax($entry);
|
2933 |
|
|
if (($lifetime > 0) && ($renewmax > 0)) {
|
2934 |
|
|
/* If life time and rekey/reauth time both have values, subtract to get rand time */
|
2935 |
|
|
return $lifetime - $renewmax;
|
2936 |
|
|
} elseif ($lifetime > 0) {
|
2937 |
|
|
/* If only life time has a value, use 10% of that */
|
2938 |
|
|
return intval($lifetime * 0.1);
|
2939 |
|
|
} elseif ($renewmax > 0) {
|
2940 |
|
|
/* If only rekey/reauth time has a value, use 10% of that */
|
2941 |
|
|
return intval($renewmax * 0.1);
|
2942 |
|
|
}
|
2943 |
|
|
/* No value can be determined, default to 0 */
|
2944 |
|
|
return 0;
|
2945 |
|
|
}
|
2946 |
|
|
|
2947 |
|
|
/* Determine the rand time of an SA entry (random value subtracted from renewal time to prevent collisions) */
|
2948 |
|
|
function ipsec_get_rand_time($entry) {
|
2949 |
|
|
if (empty($entry) || !is_array($entry)) {
|
2950 |
|
|
return 0;
|
2951 |
|
|
}
|
2952 |
|
|
/* Use a hardcoded value if present in the configuration */
|
2953 |
|
|
if (strlen($entry['rand_time'])) {
|
2954 |
|
|
/* Check via strlen since 0 is a valid value */
|
2955 |
|
|
return $entry['rand_time'];
|
2956 |
|
|
}
|
2957 |
|
|
/* Logic to automatically determine rand time is identical to calculating over time */
|
2958 |
|
|
return ipsec_get_over_time($entry);
|
2959 |
|
|
}
|
2960 |
|
|
|
2961 |
8f5c3d8d
|
Pierre POMES
|
?>
|