GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: ikev2_pld.c,v 1.62 2017/04/13 07:04:09 patrick Exp $ */ |
||
2 |
|||
3 |
/* |
||
4 |
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> |
||
5 |
* Copyright (c) 2014 Hans-Joerg Hoexer |
||
6 |
* |
||
7 |
* Permission to use, copy, modify, and distribute this software for any |
||
8 |
* purpose with or without fee is hereby granted, provided that the above |
||
9 |
* copyright notice and this permission notice appear in all copies. |
||
10 |
* |
||
11 |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||
12 |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||
13 |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||
14 |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||
15 |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||
16 |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||
17 |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||
18 |
*/ |
||
19 |
|||
20 |
#include <sys/queue.h> |
||
21 |
#include <sys/socket.h> |
||
22 |
#include <sys/wait.h> |
||
23 |
#include <sys/uio.h> |
||
24 |
|||
25 |
#include <netinet/in.h> |
||
26 |
#include <arpa/inet.h> |
||
27 |
|||
28 |
#include <stdlib.h> |
||
29 |
#include <stdio.h> |
||
30 |
#include <unistd.h> |
||
31 |
#include <string.h> |
||
32 |
#include <signal.h> |
||
33 |
#include <errno.h> |
||
34 |
#include <err.h> |
||
35 |
#include <pwd.h> |
||
36 |
#include <event.h> |
||
37 |
|||
38 |
#include <openssl/sha.h> |
||
39 |
#include <openssl/evp.h> |
||
40 |
|||
41 |
#include "iked.h" |
||
42 |
#include "ikev2.h" |
||
43 |
#include "eap.h" |
||
44 |
#include "dh.h" |
||
45 |
|||
46 |
int ikev2_validate_pld(struct iked_message *, size_t, size_t, |
||
47 |
struct ikev2_payload *); |
||
48 |
int ikev2_pld_payloads(struct iked *, struct iked_message *, |
||
49 |
size_t, size_t, unsigned int); |
||
50 |
int ikev2_validate_sa(struct iked_message *, size_t, size_t, |
||
51 |
struct ikev2_payload *, struct ikev2_sa_proposal *); |
||
52 |
int ikev2_pld_sa(struct iked *, struct ikev2_payload *, |
||
53 |
struct iked_message *, size_t, size_t); |
||
54 |
int ikev2_validate_xform(struct iked_message *, size_t, size_t, |
||
55 |
struct ikev2_transform *); |
||
56 |
int ikev2_pld_xform(struct iked *, struct ikev2_sa_proposal *, |
||
57 |
struct iked_message *, size_t, size_t); |
||
58 |
int ikev2_validate_attr(struct iked_message *, size_t, size_t, |
||
59 |
struct ikev2_attribute *); |
||
60 |
int ikev2_pld_attr(struct iked *, struct ikev2_transform *, |
||
61 |
struct iked_message *, size_t, size_t); |
||
62 |
int ikev2_validate_ke(struct iked_message *, size_t, size_t, |
||
63 |
struct ikev2_payload *, struct ikev2_keyexchange *); |
||
64 |
int ikev2_pld_ke(struct iked *, struct ikev2_payload *, |
||
65 |
struct iked_message *, size_t, size_t); |
||
66 |
int ikev2_validate_id(struct iked_message *, size_t, size_t, |
||
67 |
struct ikev2_payload *, struct ikev2_id *); |
||
68 |
int ikev2_pld_id(struct iked *, struct ikev2_payload *, |
||
69 |
struct iked_message *, size_t, size_t, unsigned int); |
||
70 |
int ikev2_validate_cert(struct iked_message *, size_t, size_t, |
||
71 |
struct ikev2_payload *, struct ikev2_cert *); |
||
72 |
int ikev2_pld_cert(struct iked *, struct ikev2_payload *, |
||
73 |
struct iked_message *, size_t, size_t); |
||
74 |
int ikev2_validate_certreq(struct iked_message *, size_t, size_t, |
||
75 |
struct ikev2_payload *, struct ikev2_cert *); |
||
76 |
int ikev2_pld_certreq(struct iked *, struct ikev2_payload *, |
||
77 |
struct iked_message *, size_t, size_t); |
||
78 |
int ikev2_validate_nonce(struct iked_message *, size_t, size_t, |
||
79 |
struct ikev2_payload *); |
||
80 |
int ikev2_pld_nonce(struct iked *, struct ikev2_payload *, |
||
81 |
struct iked_message *, size_t, size_t); |
||
82 |
int ikev2_validate_notify(struct iked_message *, size_t, size_t, |
||
83 |
struct ikev2_payload *, struct ikev2_notify *); |
||
84 |
int ikev2_pld_notify(struct iked *, struct ikev2_payload *, |
||
85 |
struct iked_message *, size_t, size_t); |
||
86 |
int ikev2_validate_delete(struct iked_message *, size_t, size_t, |
||
87 |
struct ikev2_payload *, struct ikev2_delete *); |
||
88 |
int ikev2_pld_delete(struct iked *, struct ikev2_payload *, |
||
89 |
struct iked_message *, size_t, size_t); |
||
90 |
int ikev2_validate_ts(struct iked_message *, size_t, size_t, |
||
91 |
struct ikev2_payload *, struct ikev2_tsp *); |
||
92 |
int ikev2_pld_ts(struct iked *, struct ikev2_payload *, |
||
93 |
struct iked_message *, size_t, size_t, unsigned int); |
||
94 |
int ikev2_validate_auth(struct iked_message *, size_t, size_t, |
||
95 |
struct ikev2_payload *, struct ikev2_auth *); |
||
96 |
int ikev2_pld_auth(struct iked *, struct ikev2_payload *, |
||
97 |
struct iked_message *, size_t, size_t); |
||
98 |
int ikev2_pld_e(struct iked *, struct ikev2_payload *, |
||
99 |
struct iked_message *, size_t); |
||
100 |
int ikev2_validate_cp(struct iked_message *, size_t, size_t, |
||
101 |
struct ikev2_payload *, struct ikev2_cp *); |
||
102 |
int ikev2_pld_cp(struct iked *, struct ikev2_payload *, |
||
103 |
struct iked_message *, size_t, size_t); |
||
104 |
int ikev2_validate_eap(struct iked_message *, size_t, size_t, |
||
105 |
struct ikev2_payload *, struct eap_header *); |
||
106 |
int ikev2_pld_eap(struct iked *, struct ikev2_payload *, |
||
107 |
struct iked_message *, size_t, size_t); |
||
108 |
|||
109 |
int |
||
110 |
ikev2_pld_parse(struct iked *env, struct ike_header *hdr, |
||
111 |
struct iked_message *msg, size_t offset) |
||
112 |
{ |
||
113 |
333357680 |
log_debug("%s: header ispi %s rspi %s" |
|
114 |
" nextpayload %s version 0x%02x exchange %s flags 0x%02x" |
||
115 |
" msgid %d length %u response %d", __func__, |
||
116 |
666715360 |
print_spi(betoh64(hdr->ike_ispi), 8), |
|
117 |
333357680 |
print_spi(betoh64(hdr->ike_rspi), 8), |
|
118 |
333357680 |
print_map(hdr->ike_nextpayload, ikev2_payload_map), |
|
119 |
333357680 |
hdr->ike_version, |
|
120 |
333357680 |
print_map(hdr->ike_exchange, ikev2_exchange_map), |
|
121 |
333357680 |
hdr->ike_flags, |
|
122 |
333357680 |
betoh32(hdr->ike_msgid), |
|
123 |
333357680 |
betoh32(hdr->ike_length), |
|
124 |
333357680 |
msg->msg_response); |
|
125 |
|||
126 |
✓✓ | 333357680 |
if (ibuf_size(msg->msg_data) < betoh32(hdr->ike_length)) { |
127 |
9618560 |
log_debug("%s: short message", __func__); |
|
128 |
9618560 |
return (-1); |
|
129 |
} |
||
130 |
|||
131 |
323739120 |
offset += sizeof(*hdr); |
|
132 |
|||
133 |
323739120 |
return (ikev2_pld_payloads(env, msg, offset, |
|
134 |
323739120 |
betoh32(hdr->ike_length), hdr->ike_nextpayload)); |
|
135 |
333357680 |
} |
|
136 |
|||
137 |
int |
||
138 |
ikev2_validate_pld(struct iked_message *msg, size_t offset, size_t left, |
||
139 |
struct ikev2_payload *pld) |
||
140 |
{ |
||
141 |
1690421140 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
142 |
size_t pld_length; |
||
143 |
|||
144 |
/* We need at least the generic header. */ |
||
145 |
✓✓ | 845210570 |
if (left < sizeof(*pld)) { |
146 |
690 |
log_debug("%s: malformed payload: too short for generic " |
|
147 |
"header (%zu < %zu)", __func__, left, sizeof(*pld)); |
||
148 |
690 |
return (-1); |
|
149 |
} |
||
150 |
845209880 |
memcpy(pld, msgbuf + offset, sizeof(*pld)); |
|
151 |
|||
152 |
/* |
||
153 |
* We need at least the specified number of bytes. |
||
154 |
* pld_length is the full size of the payload including |
||
155 |
* the generic payload header. |
||
156 |
*/ |
||
157 |
845209880 |
pld_length = betoh16(pld->pld_length); |
|
158 |
✓✓ | 845209880 |
if (left < pld_length) { |
159 |
10508620 |
log_debug("%s: malformed payload: shorter than specified " |
|
160 |
"(%zu < %zu)", __func__, left, pld_length); |
||
161 |
10508620 |
return (-1); |
|
162 |
} |
||
163 |
/* |
||
164 |
* Sanity check the specified payload size, it must |
||
165 |
* be at last the size of the generic payload header. |
||
166 |
*/ |
||
167 |
✓✓ | 834701260 |
if (pld_length < sizeof(*pld)) { |
168 |
437070 |
log_debug("%s: malformed payload: shorter than minimum " |
|
169 |
"header size (%zu < %zu)", __func__, pld_length, |
||
170 |
sizeof(*pld)); |
||
171 |
437070 |
return (-1); |
|
172 |
} |
||
173 |
|||
174 |
834264190 |
return (0); |
|
175 |
845210570 |
} |
|
176 |
|||
177 |
int |
||
178 |
ikev2_pld_payloads(struct iked *env, struct iked_message *msg, |
||
179 |
size_t offset, size_t length, unsigned int payload) |
||
180 |
{ |
||
181 |
647478240 |
struct ikev2_payload pld; |
|
182 |
unsigned int e; |
||
183 |
int ret; |
||
184 |
323739120 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
185 |
size_t left; |
||
186 |
|||
187 |
/* Check if message was decrypted in an E payload */ |
||
188 |
323739120 |
e = msg->msg_e ? IKED_E : 0; |
|
189 |
|||
190 |
✓✓✓✓ |
3163255900 |
while (payload != 0 && offset < length) { |
191 |
/* Bytes left in datagram. */ |
||
192 |
845210570 |
left = length - offset; |
|
193 |
|||
194 |
✓✓ | 845210570 |
if (ikev2_validate_pld(msg, offset, left, &pld)) |
195 |
10946380 |
return (-1); |
|
196 |
|||
197 |
834264190 |
log_debug("%s: %spayload %s" |
|
198 |
" nextpayload %s critical 0x%02x length %d", |
||
199 |
834264190 |
__func__, e ? "decrypted " : "", |
|
200 |
834264190 |
print_map(payload, ikev2_payload_map), |
|
201 |
834264190 |
print_map(pld.pld_nextpayload, ikev2_payload_map), |
|
202 |
834264190 |
pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD, |
|
203 |
834264190 |
betoh16(pld.pld_length)); |
|
204 |
|||
205 |
/* Skip over generic payload header. */ |
||
206 |
834264190 |
offset += sizeof(pld); |
|
207 |
834264190 |
left -= sizeof(pld); |
|
208 |
ret = 0; |
||
209 |
|||
210 |
✗✓✗✓ ✗✗✗✗ ✓✗✗✓ ✗✓✗✗ ✗✓✗✗ ✓ |
834264190 |
switch (payload | e) { |
211 |
case IKEV2_PAYLOAD_SA: |
||
212 |
case IKEV2_PAYLOAD_SA | IKED_E: |
||
213 |
133239710 |
ret = ikev2_pld_sa(env, &pld, msg, offset, left); |
|
214 |
133239710 |
break; |
|
215 |
case IKEV2_PAYLOAD_KE: |
||
216 |
case IKEV2_PAYLOAD_KE | IKED_E: |
||
217 |
179417390 |
ret = ikev2_pld_ke(env, &pld, msg, offset, left); |
|
218 |
179417390 |
break; |
|
219 |
case IKEV2_PAYLOAD_IDi | IKED_E: |
||
220 |
case IKEV2_PAYLOAD_IDr | IKED_E: |
||
221 |
ret = ikev2_pld_id(env, &pld, msg, offset, left, |
||
222 |
payload); |
||
223 |
break; |
||
224 |
case IKEV2_PAYLOAD_CERT | IKED_E: |
||
225 |
ret = ikev2_pld_cert(env, &pld, msg, offset, left); |
||
226 |
break; |
||
227 |
case IKEV2_PAYLOAD_CERTREQ: |
||
228 |
case IKEV2_PAYLOAD_CERTREQ | IKED_E: |
||
229 |
625130 |
ret = ikev2_pld_certreq(env, &pld, msg, offset, left); |
|
230 |
625130 |
break; |
|
231 |
case IKEV2_PAYLOAD_AUTH | IKED_E: |
||
232 |
ret = ikev2_pld_auth(env, &pld, msg, offset, left); |
||
233 |
break; |
||
234 |
case IKEV2_PAYLOAD_NONCE: |
||
235 |
case IKEV2_PAYLOAD_NONCE | IKED_E: |
||
236 |
127288420 |
ret = ikev2_pld_nonce(env, &pld, msg, offset, left); |
|
237 |
127288420 |
break; |
|
238 |
case IKEV2_PAYLOAD_NOTIFY: |
||
239 |
case IKEV2_PAYLOAD_NOTIFY | IKED_E: |
||
240 |
250235690 |
ret = ikev2_pld_notify(env, &pld, msg, offset, left); |
|
241 |
250235690 |
break; |
|
242 |
case IKEV2_PAYLOAD_DELETE | IKED_E: |
||
243 |
ret = ikev2_pld_delete(env, &pld, msg, offset, left); |
||
244 |
break; |
||
245 |
case IKEV2_PAYLOAD_TSi | IKED_E: |
||
246 |
case IKEV2_PAYLOAD_TSr | IKED_E: |
||
247 |
ret = ikev2_pld_ts(env, &pld, msg, offset, left, |
||
248 |
payload); |
||
249 |
break; |
||
250 |
case IKEV2_PAYLOAD_SK: |
||
251 |
68340 |
ret = ikev2_pld_e(env, &pld, msg, offset); |
|
252 |
68340 |
break; |
|
253 |
case IKEV2_PAYLOAD_CP | IKED_E: |
||
254 |
ret = ikev2_pld_cp(env, &pld, msg, offset, left); |
||
255 |
break; |
||
256 |
case IKEV2_PAYLOAD_EAP | IKED_E: |
||
257 |
ret = ikev2_pld_eap(env, &pld, msg, offset, left); |
||
258 |
break; |
||
259 |
default: |
||
260 |
143389510 |
print_hex(msgbuf, offset, |
|
261 |
143389510 |
betoh16(pld.pld_length) - sizeof(pld)); |
|
262 |
143389510 |
break; |
|
263 |
} |
||
264 |
|||
265 |
✓✓✗✓ |
849204790 |
if (ret != 0 && ikev2_msg_frompeer(msg)) { |
266 |
(void)ikev2_send_informational(env, msg); |
||
267 |
return (-1); |
||
268 |
} |
||
269 |
|||
270 |
/* Encrypted payload must appear last */ |
||
271 |
✓✓ | 834264190 |
if (payload == IKEV2_PAYLOAD_SK) |
272 |
68340 |
return (0); |
|
273 |
|||
274 |
834195850 |
payload = pld.pld_nextpayload; |
|
275 |
834195850 |
offset += betoh16(pld.pld_length) - sizeof(pld); |
|
276 |
} |
||
277 |
|||
278 |
312724400 |
return (0); |
|
279 |
323739120 |
} |
|
280 |
|||
281 |
int |
||
282 |
ikev2_validate_sa(struct iked_message *msg, size_t offset, size_t left, |
||
283 |
struct ikev2_payload *pld, struct ikev2_sa_proposal *sap) |
||
284 |
{ |
||
285 |
266479420 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
286 |
size_t pld_length, sap_length; |
||
287 |
|||
288 |
133239710 |
pld_length = betoh16(pld->pld_length); |
|
289 |
✓✓ | 133239710 |
if (pld_length < sizeof(*pld) + sizeof(*sap)) { |
290 |
10880 |
log_debug("%s: malformed payload: specified length smaller " |
|
291 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
292 |
sizeof(*pld) + sizeof(*sap)); |
||
293 |
10880 |
return (-1); |
|
294 |
} |
||
295 |
|||
296 |
/* This will actually be caught by earlier checks. */ |
||
297 |
✗✓ | 133228830 |
if (left < sizeof(*sap)) { |
298 |
log_debug("%s: malformed payload: too short for header " |
||
299 |
"(%zu < %zu)", __func__, left, sizeof(*sap)); |
||
300 |
return (-1); |
||
301 |
} |
||
302 |
133228830 |
memcpy(sap, msgbuf + offset, sizeof(*sap)); |
|
303 |
|||
304 |
133228830 |
sap_length = betoh16(sap->sap_length); |
|
305 |
✓✓ | 133228830 |
if (sap_length < sizeof(*sap)) { |
306 |
58270 |
log_debug("%s: malformed payload: shorter than minimum header " |
|
307 |
"size (%zu < %zu)", __func__, sap_length, sizeof(*sap)); |
||
308 |
58270 |
return (-1); |
|
309 |
} |
||
310 |
✓✓ | 133170560 |
if (left < sap_length) { |
311 |
902020 |
log_debug("%s: malformed payload: too long for actual payload " |
|
312 |
"size (%zu < %zu)", __func__, left, sap_length); |
||
313 |
902020 |
return (-1); |
|
314 |
} |
||
315 |
/* |
||
316 |
* NB: There might be more proposals, we parse only the first one. |
||
317 |
* This condition must never be true. |
||
318 |
*/ |
||
319 |
✓✓ | 132268540 |
if (pld_length - sizeof(*pld) < sap_length) { |
320 |
361980 |
log_debug("%s: payload malformed: SA payload length mismatches " |
|
321 |
"proposal substructure length (%lu < %zu)", __func__, |
||
322 |
pld_length - sizeof(*pld), sap_length); |
||
323 |
361980 |
return (-1); |
|
324 |
} |
||
325 |
/* |
||
326 |
* If there is only one proposal, sap_length must be the |
||
327 |
* total payload size. |
||
328 |
*/ |
||
329 |
✓✓✓✓ |
263091030 |
if (!sap->sap_more && ((pld_length - sizeof(*pld)) != sap_length)) { |
330 |
905910 |
log_debug("%s: payload malformed: SA payload length mismatches " |
|
331 |
"single proposal substructure length (%lu != %zu)", |
||
332 |
__func__, pld_length - sizeof(*pld), sap_length); |
||
333 |
905910 |
return (-1); |
|
334 |
} |
||
335 |
/* |
||
336 |
* If there are more than one proposal, there must be bytes |
||
337 |
* left in the payload. |
||
338 |
*/ |
||
339 |
✓✓✓✓ |
131722740 |
if (sap->sap_more && ((pld_length - sizeof(*pld)) <= sap_length)) { |
340 |
719390 |
log_debug("%s: payload malformed: SA payload too small for " |
|
341 |
"further proposals (%zu <= %zu)", __func__, |
||
342 |
pld_length - sizeof(*pld), sap_length); |
||
343 |
719390 |
return (-1); |
|
344 |
} |
||
345 |
130281260 |
return (0); |
|
346 |
133239710 |
} |
|
347 |
|||
348 |
/* |
||
349 |
* NB: This function parses both the SA header and the first proposal. |
||
350 |
* Additional proposals are ignored. |
||
351 |
*/ |
||
352 |
int |
||
353 |
ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, |
||
354 |
struct iked_message *msg, size_t offset, size_t left) |
||
355 |
{ |
||
356 |
266479420 |
struct ikev2_sa_proposal sap; |
|
357 |
struct iked_proposal *prop = NULL; |
||
358 |
uint32_t spi32; |
||
359 |
uint64_t spi = 0, spi64; |
||
360 |
133239710 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
361 |
struct iked_proposals *props; |
||
362 |
size_t total; |
||
363 |
|||
364 |
✓✓ | 133239710 |
if (ikev2_validate_sa(msg, offset, left, pld, &sap)) |
365 |
2958450 |
return (-1); |
|
366 |
|||
367 |
✓✓ | 130281260 |
if (sap.sap_more) |
368 |
2700 |
log_debug("%s: more than one proposal specified", __func__); |
|
369 |
|||
370 |
/* Assumed size of the first proposals, including SPI if present. */ |
||
371 |
130281260 |
total = (betoh16(sap.sap_length) - sizeof(sap)); |
|
372 |
|||
373 |
130281260 |
props = &msg->msg_parent->msg_proposals; |
|
374 |
|||
375 |
130281260 |
offset += sizeof(sap); |
|
376 |
130281260 |
left -= sizeof(sap); |
|
377 |
|||
378 |
✓✓ | 130281260 |
if (sap.sap_spisize) { |
379 |
✓✓ | 715590 |
if (left < sap.sap_spisize) { |
380 |
67390 |
log_debug("%s: malformed payload: SPI larger than " |
|
381 |
"actual payload (%zu < %d)", __func__, left, |
||
382 |
67390 |
sap.sap_spisize); |
|
383 |
67390 |
return (-1); |
|
384 |
} |
||
385 |
✓✓ | 648200 |
if (total < sap.sap_spisize) { |
386 |
149600 |
log_debug("%s: malformed payload: SPI larger than " |
|
387 |
"proposal (%zu < %d)", __func__, total, |
||
388 |
149600 |
sap.sap_spisize); |
|
389 |
149600 |
return (-1); |
|
390 |
} |
||
391 |
✗✓ | 498600 |
if (total < sap.sap_spisize) { |
392 |
log_debug("%s: malformed payload: SPI too large " |
||
393 |
"(%zu < %d)", __func__, total, sap.sap_spisize); |
||
394 |
return (-1); |
||
395 |
} |
||
396 |
✓✓✓ | 498600 |
switch (sap.sap_spisize) { |
397 |
case 4: |
||
398 |
82960 |
memcpy(&spi32, msgbuf + offset, 4); |
|
399 |
82960 |
spi = betoh32(spi32); |
|
400 |
82960 |
break; |
|
401 |
case 8: |
||
402 |
82960 |
memcpy(&spi64, msgbuf + offset, 8); |
|
403 |
82960 |
spi = betoh64(spi64); |
|
404 |
82960 |
break; |
|
405 |
default: |
||
406 |
332680 |
log_debug("%s: unsupported SPI size %d", |
|
407 |
__func__, sap.sap_spisize); |
||
408 |
332680 |
return (-1); |
|
409 |
} |
||
410 |
|||
411 |
165920 |
offset += sap.sap_spisize; |
|
412 |
165920 |
left -= sap.sap_spisize; |
|
413 |
|||
414 |
/* Assumed size of the proposal, now without SPI. */ |
||
415 |
165920 |
total -= sap.sap_spisize; |
|
416 |
165920 |
} |
|
417 |
|||
418 |
/* |
||
419 |
* As we verified sanity of packet headers, this check will |
||
420 |
* be always false, but just to be sure we keep it. |
||
421 |
*/ |
||
422 |
✗✓ | 129731590 |
if (left < total) { |
423 |
log_debug("%s: payload malformed: too long for payload " |
||
424 |
"(%zu < %zu)", __func__, left, total); |
||
425 |
return (-1); |
||
426 |
} |
||
427 |
|||
428 |
129731590 |
log_debug("%s: more %d reserved %d length %d" |
|
429 |
" proposal #%d protoid %s spisize %d xforms %d spi %s", |
||
430 |
129731590 |
__func__, sap.sap_more, sap.sap_reserved, |
|
431 |
129731590 |
betoh16(sap.sap_length), sap.sap_proposalnr, |
|
432 |
129731590 |
print_map(sap.sap_protoid, ikev2_saproto_map), sap.sap_spisize, |
|
433 |
129731590 |
sap.sap_transforms, print_spi(spi, sap.sap_spisize)); |
|
434 |
|||
435 |
✗✓ | 129731590 |
if (ikev2_msg_frompeer(msg)) { |
436 |
if ((msg->msg_parent->msg_prop = config_add_proposal(props, |
||
437 |
sap.sap_proposalnr, sap.sap_protoid)) == NULL) { |
||
438 |
log_debug("%s: invalid proposal", __func__); |
||
439 |
return (-1); |
||
440 |
} |
||
441 |
prop = msg->msg_parent->msg_prop; |
||
442 |
prop->prop_peerspi.spi = spi; |
||
443 |
prop->prop_peerspi.spi_protoid = sap.sap_protoid; |
||
444 |
prop->prop_peerspi.spi_size = sap.sap_spisize; |
||
445 |
|||
446 |
prop->prop_localspi.spi_protoid = sap.sap_protoid; |
||
447 |
prop->prop_localspi.spi_size = sap.sap_spisize; |
||
448 |
} |
||
449 |
|||
450 |
/* |
||
451 |
* Parse the attached transforms |
||
452 |
*/ |
||
453 |
✓✓✓✓ |
258932010 |
if (sap.sap_transforms && |
454 |
129200420 |
ikev2_pld_xform(env, &sap, msg, offset, total) != 0) { |
|
455 |
11160320 |
log_debug("%s: invalid proposal transforms", __func__); |
|
456 |
11160320 |
return (-1); |
|
457 |
} |
||
458 |
|||
459 |
118571270 |
return (0); |
|
460 |
133239710 |
} |
|
461 |
|||
462 |
int |
||
463 |
ikev2_validate_xform(struct iked_message *msg, size_t offset, size_t total, |
||
464 |
struct ikev2_transform *xfrm) |
||
465 |
{ |
||
466 |
1489756120 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
467 |
size_t xfrm_length; |
||
468 |
|||
469 |
✓✓ | 744878060 |
if (total < sizeof(*xfrm)) { |
470 |
195300 |
log_debug("%s: payload malformed: too short for header " |
|
471 |
"(%zu < %zu)", __func__, total, sizeof(*xfrm)); |
||
472 |
195300 |
return (-1); |
|
473 |
} |
||
474 |
744682760 |
memcpy(xfrm, msgbuf + offset, sizeof(*xfrm)); |
|
475 |
|||
476 |
744682760 |
xfrm_length = betoh16(xfrm->xfrm_length); |
|
477 |
✓✓ | 744682760 |
if (xfrm_length < sizeof(*xfrm)) { |
478 |
480600 |
log_debug("%s: payload malformed: shorter than minimal header " |
|
479 |
"(%zu < %zu)", __func__, xfrm_length, sizeof(*xfrm)); |
||
480 |
480600 |
return (-1); |
|
481 |
} |
||
482 |
✓✓ | 744202160 |
if (total < xfrm_length) { |
483 |
5745240 |
log_debug("%s: malformed payload: too long for payload size " |
|
484 |
"(%zu < %zu)", __func__, total, xfrm_length); |
||
485 |
5745240 |
return (-1); |
|
486 |
} |
||
487 |
|||
488 |
738456920 |
return (0); |
|
489 |
744878060 |
} |
|
490 |
|||
491 |
int |
||
492 |
ikev2_pld_xform(struct iked *env, struct ikev2_sa_proposal *sap, |
||
493 |
struct iked_message *msg, size_t offset, size_t total) |
||
494 |
{ |
||
495 |
1489756120 |
struct ikev2_transform xfrm; |
|
496 |
744878060 |
char id[BUFSIZ]; |
|
497 |
int ret = 0; |
||
498 |
size_t xfrm_length; |
||
499 |
|||
500 |
✓✓ | 744878060 |
if (ikev2_validate_xform(msg, offset, total, &xfrm)) |
501 |
6421140 |
return (-1); |
|
502 |
|||
503 |
738456920 |
xfrm_length = betoh16(xfrm.xfrm_length); |
|
504 |
|||
505 |
✓✓✓✓ ✓✓ |
738456920 |
switch (xfrm.xfrm_type) { |
506 |
case IKEV2_XFORMTYPE_ENCR: |
||
507 |
125562720 |
strlcpy(id, print_map(betoh16(xfrm.xfrm_id), |
|
508 |
ikev2_xformencr_map), sizeof(id)); |
||
509 |
125562720 |
break; |
|
510 |
case IKEV2_XFORMTYPE_PRF: |
||
511 |
358344180 |
strlcpy(id, print_map(betoh16(xfrm.xfrm_id), |
|
512 |
ikev2_xformprf_map), sizeof(id)); |
||
513 |
358344180 |
break; |
|
514 |
case IKEV2_XFORMTYPE_INTEGR: |
||
515 |
127792040 |
strlcpy(id, print_map(betoh16(xfrm.xfrm_id), |
|
516 |
ikev2_xformauth_map), sizeof(id)); |
||
517 |
127792040 |
break; |
|
518 |
case IKEV2_XFORMTYPE_DH: |
||
519 |
123335660 |
strlcpy(id, print_map(betoh16(xfrm.xfrm_id), |
|
520 |
ikev2_xformdh_map), sizeof(id)); |
||
521 |
123335660 |
break; |
|
522 |
case IKEV2_XFORMTYPE_ESN: |
||
523 |
161560 |
strlcpy(id, print_map(betoh16(xfrm.xfrm_id), |
|
524 |
ikev2_xformesn_map), sizeof(id)); |
||
525 |
161560 |
break; |
|
526 |
default: |
||
527 |
3260760 |
snprintf(id, sizeof(id), "<%d>", betoh16(xfrm.xfrm_id)); |
|
528 |
3260760 |
break; |
|
529 |
} |
||
530 |
|||
531 |
738456920 |
log_debug("%s: more %d reserved %d length %zu" |
|
532 |
" type %s id %s", |
||
533 |
738456920 |
__func__, xfrm.xfrm_more, xfrm.xfrm_reserved, xfrm_length, |
|
534 |
738456920 |
print_map(xfrm.xfrm_type, ikev2_xformtype_map), id); |
|
535 |
|||
536 |
/* |
||
537 |
* Parse transform attributes, if available |
||
538 |
*/ |
||
539 |
738456920 |
msg->msg_attrlength = 0; |
|
540 |
✓✓ | 738456920 |
if (xfrm_length > sizeof(xfrm)) { |
541 |
✓✓ | 382296540 |
if (ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm), |
542 |
254864360 |
xfrm_length - sizeof(xfrm)) != 0) { |
|
543 |
1472580 |
return (-1); |
|
544 |
} |
||
545 |
} |
||
546 |
|||
547 |
✗✓ | 736984340 |
if (ikev2_msg_frompeer(msg)) { |
548 |
if (config_add_transform(msg->msg_parent->msg_prop, |
||
549 |
xfrm.xfrm_type, betoh16(xfrm.xfrm_id), |
||
550 |
msg->msg_attrlength, msg->msg_attrlength) == NULL) { |
||
551 |
log_debug("%s: failed to add transform", __func__); |
||
552 |
return (-1); |
||
553 |
} |
||
554 |
} |
||
555 |
|||
556 |
/* Next transform */ |
||
557 |
736984340 |
offset += xfrm_length; |
|
558 |
736984340 |
total -= xfrm_length; |
|
559 |
✓✓ | 736984340 |
if (xfrm.xfrm_more == IKEV2_XFORM_MORE) |
560 |
615677640 |
ret = ikev2_pld_xform(env, sap, msg, offset, total); |
|
561 |
✓✓ | 121306700 |
else if (total != 0) { |
562 |
/* No more transforms but still some data left. */ |
||
563 |
3266600 |
log_debug("%s: less data than specified, %zu bytes left", |
|
564 |
__func__, total); |
||
565 |
ret = -1; |
||
566 |
3266600 |
} |
|
567 |
|||
568 |
736984340 |
return (ret); |
|
569 |
744878060 |
} |
|
570 |
|||
571 |
int |
||
572 |
ikev2_validate_attr(struct iked_message *msg, size_t offset, size_t total, |
||
573 |
struct ikev2_attribute *attr) |
||
574 |
{ |
||
575 |
257132400 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
576 |
|||
577 |
✓✓ | 128566200 |
if (total < sizeof(*attr)) { |
578 |
805020 |
log_debug("%s: payload malformed: too short for header " |
|
579 |
"(%zu < %zu)", __func__, total, sizeof(*attr)); |
||
580 |
805020 |
return (-1); |
|
581 |
} |
||
582 |
127761180 |
memcpy(attr, msgbuf + offset, sizeof(*attr)); |
|
583 |
|||
584 |
127761180 |
return (0); |
|
585 |
128566200 |
} |
|
586 |
|||
587 |
int |
||
588 |
ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm, |
||
589 |
struct iked_message *msg, size_t offset, size_t total) |
||
590 |
{ |
||
591 |
257132400 |
struct ikev2_attribute attr; |
|
592 |
unsigned int type; |
||
593 |
128566200 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
594 |
int ret = 0; |
||
595 |
size_t attr_length; |
||
596 |
|||
597 |
✓✓ | 128566200 |
if (ikev2_validate_attr(msg, offset, total, &attr)) |
598 |
805020 |
return (-1); |
|
599 |
|||
600 |
127761180 |
type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV; |
|
601 |
|||
602 |
127761180 |
log_debug("%s: attribute type %s length %d total %zu", |
|
603 |
127761180 |
__func__, print_map(type, ikev2_attrtype_map), |
|
604 |
127761180 |
betoh16(attr.attr_length), total); |
|
605 |
|||
606 |
✓✓ | 127761180 |
if (betoh16(attr.attr_type) & IKEV2_ATTRAF_TV) { |
607 |
/* Type-Value attribute */ |
||
608 |
125969600 |
offset += sizeof(attr); |
|
609 |
125969600 |
total -= sizeof(attr); |
|
610 |
|||
611 |
✓✓ | 125969600 |
if (type == IKEV2_ATTRTYPE_KEY_LENGTH) |
612 |
124739360 |
msg->msg_attrlength = betoh16(attr.attr_length); |
|
613 |
} else { |
||
614 |
/* Type-Length-Value attribute */ |
||
615 |
1791580 |
attr_length = betoh16(attr.attr_length); |
|
616 |
✓✓ | 1791580 |
if (attr_length < sizeof(attr)) { |
617 |
1040 |
log_debug("%s: payload malformed: shorter than " |
|
618 |
"minimal header (%zu < %zu)", __func__, |
||
619 |
attr_length, sizeof(attr)); |
||
620 |
1040 |
return (-1); |
|
621 |
} |
||
622 |
✓✓ | 1790540 |
if (total < attr_length) { |
623 |
666520 |
log_debug("%s: payload malformed: attribute larger " |
|
624 |
"than actual payload (%zu < %zu)", __func__, |
||
625 |
total, attr_length); |
||
626 |
666520 |
return (-1); |
|
627 |
} |
||
628 |
2248040 |
print_hex(msgbuf, offset + sizeof(attr), |
|
629 |
1124020 |
attr_length - sizeof(attr)); |
|
630 |
1124020 |
offset += attr_length; |
|
631 |
1124020 |
total -= attr_length; |
|
632 |
} |
||
633 |
|||
634 |
✓✓ | 127093620 |
if (total > 0) { |
635 |
/* Next attribute */ |
||
636 |
1134020 |
ret = ikev2_pld_attr(env, xfrm, msg, offset, total); |
|
637 |
1134020 |
} |
|
638 |
|||
639 |
127093620 |
return (ret); |
|
640 |
128566200 |
} |
|
641 |
|||
642 |
int |
||
643 |
ikev2_validate_ke(struct iked_message *msg, size_t offset, size_t left, |
||
644 |
struct ikev2_payload *pld, struct ikev2_keyexchange *kex) |
||
645 |
{ |
||
646 |
358834780 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
647 |
size_t pld_length; |
||
648 |
|||
649 |
179417390 |
pld_length = betoh16(pld->pld_length); |
|
650 |
✓✓ | 179417390 |
if (pld_length < sizeof(*pld) + sizeof(*kex)) { |
651 |
4270 |
log_debug("%s: malformed payload: specified length smaller " |
|
652 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
653 |
sizeof(*pld) + sizeof(*kex)); |
||
654 |
4270 |
return (-1); |
|
655 |
} |
||
656 |
|||
657 |
/* This will actually be caught by earlier checks. */ |
||
658 |
✗✓ | 179413120 |
if (left < sizeof(*kex)) { |
659 |
log_debug("%s: malformed payload: too short for header " |
||
660 |
"(%zu < %zu)", __func__, left, sizeof(*kex)); |
||
661 |
return (-1); |
||
662 |
} |
||
663 |
179413120 |
memcpy(kex, msgbuf + offset, sizeof(*kex)); |
|
664 |
|||
665 |
179413120 |
return (0); |
|
666 |
179417390 |
} |
|
667 |
|||
668 |
int |
||
669 |
ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld, |
||
670 |
struct iked_message *msg, size_t offset, size_t left) |
||
671 |
{ |
||
672 |
358834780 |
struct ikev2_keyexchange kex; |
|
673 |
uint8_t *buf; |
||
674 |
size_t len; |
||
675 |
179417390 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
676 |
|||
677 |
✓✓ | 179417390 |
if (ikev2_validate_ke(msg, offset, left, pld, &kex)) |
678 |
4270 |
return (-1); |
|
679 |
|||
680 |
179413120 |
log_debug("%s: dh group %s reserved %d", __func__, |
|
681 |
179413120 |
print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map), |
|
682 |
179413120 |
betoh16(kex.kex_reserved)); |
|
683 |
|||
684 |
179413120 |
buf = msgbuf + offset + sizeof(kex); |
|
685 |
179413120 |
len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(kex); |
|
686 |
|||
687 |
✓✓ | 179413120 |
if (len == 0) { |
688 |
116120 |
log_debug("%s: malformed payload: no KE data given", __func__); |
|
689 |
116120 |
return (-1); |
|
690 |
} |
||
691 |
/* This will actually be caught by earlier checks. */ |
||
692 |
✗✓ | 179297000 |
if (left < len) { |
693 |
log_debug("%s: malformed payload: smaller than specified " |
||
694 |
"(%zu < %zu)", __func__, left, len); |
||
695 |
return (-1); |
||
696 |
} |
||
697 |
|||
698 |
179297000 |
print_hex(buf, 0, len); |
|
699 |
|||
700 |
✗✓ | 179297000 |
if (ikev2_msg_frompeer(msg)) { |
701 |
ibuf_release(msg->msg_parent->msg_ke); |
||
702 |
if ((msg->msg_parent->msg_ke = ibuf_new(buf, len)) == NULL) { |
||
703 |
log_debug("%s: failed to get exchange", __func__); |
||
704 |
return (-1); |
||
705 |
} |
||
706 |
} |
||
707 |
|||
708 |
179297000 |
return (0); |
|
709 |
179417390 |
} |
|
710 |
|||
711 |
int |
||
712 |
ikev2_validate_id(struct iked_message *msg, size_t offset, size_t left, |
||
713 |
struct ikev2_payload *pld, struct ikev2_id *id) |
||
714 |
{ |
||
715 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
716 |
size_t pld_length; |
||
717 |
|||
718 |
pld_length = betoh16(pld->pld_length); |
||
719 |
if (pld_length < sizeof(*pld) + sizeof(*id)) { |
||
720 |
log_debug("%s: malformed payload: specified length smaller " |
||
721 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
722 |
sizeof(*pld) + sizeof(*id)); |
||
723 |
return (-1); |
||
724 |
} |
||
725 |
|||
726 |
/* This will actually be caught by earlier checks. */ |
||
727 |
if (left < sizeof(*id)) { |
||
728 |
log_debug("%s: malformed payload: too short for header " |
||
729 |
"(%zu < %zu)", __func__, left, sizeof(*id)); |
||
730 |
return (-1); |
||
731 |
} |
||
732 |
memcpy(id, msgbuf + offset, sizeof(*id)); |
||
733 |
|||
734 |
return (0); |
||
735 |
} |
||
736 |
|||
737 |
int |
||
738 |
ikev2_pld_id(struct iked *env, struct ikev2_payload *pld, |
||
739 |
struct iked_message *msg, size_t offset, size_t left, unsigned int payload) |
||
740 |
{ |
||
741 |
uint8_t *ptr; |
||
742 |
struct ikev2_id id; |
||
743 |
size_t len; |
||
744 |
struct iked_id *idp, idb; |
||
745 |
struct iked_sa *sa = msg->msg_sa; |
||
746 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
747 |
char idstr[IKED_ID_SIZE]; |
||
748 |
|||
749 |
if (ikev2_validate_id(msg, offset, left, pld, &id)) |
||
750 |
return (-1); |
||
751 |
|||
752 |
bzero(&idb, sizeof(idb)); |
||
753 |
|||
754 |
/* Don't strip the Id payload header */ |
||
755 |
ptr = msgbuf + offset; |
||
756 |
len = betoh16(pld->pld_length) - sizeof(*pld); |
||
757 |
|||
758 |
idb.id_type = id.id_type; |
||
759 |
idb.id_offset = sizeof(id); |
||
760 |
if ((idb.id_buf = ibuf_new(ptr, len)) == NULL) |
||
761 |
return (-1); |
||
762 |
|||
763 |
if (ikev2_print_id(&idb, idstr, sizeof(idstr)) == -1) { |
||
764 |
log_debug("%s: malformed id", __func__); |
||
765 |
return (-1); |
||
766 |
} |
||
767 |
|||
768 |
log_debug("%s: id %s length %zu", __func__, idstr, len); |
||
769 |
|||
770 |
if (!ikev2_msg_frompeer(msg)) { |
||
771 |
ibuf_release(idb.id_buf); |
||
772 |
return (0); |
||
773 |
} |
||
774 |
|||
775 |
if (!((sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr) || |
||
776 |
(!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDi))) { |
||
777 |
log_debug("%s: unexpected id payload", __func__); |
||
778 |
return (0); |
||
779 |
} |
||
780 |
|||
781 |
idp = &msg->msg_parent->msg_id; |
||
782 |
if (idp->id_type) { |
||
783 |
log_debug("%s: duplicate id payload", __func__); |
||
784 |
return (-1); |
||
785 |
} |
||
786 |
|||
787 |
idp->id_buf = idb.id_buf; |
||
788 |
idp->id_offset = idb.id_offset; |
||
789 |
idp->id_type = idb.id_type; |
||
790 |
|||
791 |
return (0); |
||
792 |
} |
||
793 |
|||
794 |
int |
||
795 |
ikev2_validate_cert(struct iked_message *msg, size_t offset, size_t left, |
||
796 |
struct ikev2_payload *pld, struct ikev2_cert *cert) |
||
797 |
{ |
||
798 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
799 |
size_t pld_length; |
||
800 |
|||
801 |
pld_length = betoh16(pld->pld_length); |
||
802 |
if (pld_length < sizeof(*pld) + sizeof(*cert)) { |
||
803 |
log_debug("%s: malformed payload: specified length smaller " |
||
804 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
805 |
sizeof(*pld) + sizeof(*cert)); |
||
806 |
return (-1); |
||
807 |
} |
||
808 |
|||
809 |
/* This will actually be caught by earlier checks. */ |
||
810 |
if (left < sizeof(*cert)) { |
||
811 |
log_debug("%s: malformed payload: too short for header " |
||
812 |
"(%zu < %zu)", __func__, left, sizeof(*cert)); |
||
813 |
return (-1); |
||
814 |
} |
||
815 |
memcpy(cert, msgbuf + offset, sizeof(*cert)); |
||
816 |
|||
817 |
return (0); |
||
818 |
} |
||
819 |
|||
820 |
int |
||
821 |
ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld, |
||
822 |
struct iked_message *msg, size_t offset, size_t left) |
||
823 |
{ |
||
824 |
struct ikev2_cert cert; |
||
825 |
uint8_t *buf; |
||
826 |
size_t len; |
||
827 |
struct iked_id *certid; |
||
828 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
829 |
|||
830 |
if (ikev2_validate_cert(msg, offset, left, pld, &cert)) |
||
831 |
return (-1); |
||
832 |
offset += sizeof(cert); |
||
833 |
|||
834 |
buf = msgbuf + offset; |
||
835 |
len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert); |
||
836 |
|||
837 |
log_debug("%s: type %s length %zu", |
||
838 |
__func__, print_map(cert.cert_type, ikev2_cert_map), len); |
||
839 |
|||
840 |
print_hex(buf, 0, len); |
||
841 |
|||
842 |
if (!ikev2_msg_frompeer(msg)) |
||
843 |
return (0); |
||
844 |
|||
845 |
certid = &msg->msg_parent->msg_cert; |
||
846 |
if (certid->id_type) { |
||
847 |
log_debug("%s: duplicate cert payload", __func__); |
||
848 |
return (-1); |
||
849 |
} |
||
850 |
|||
851 |
if ((certid->id_buf = ibuf_new(buf, len)) == NULL) { |
||
852 |
log_debug("%s: failed to save cert", __func__); |
||
853 |
return (-1); |
||
854 |
} |
||
855 |
certid->id_type = cert.cert_type; |
||
856 |
certid->id_offset = 0; |
||
857 |
|||
858 |
return (0); |
||
859 |
} |
||
860 |
|||
861 |
int |
||
862 |
ikev2_validate_certreq(struct iked_message *msg, size_t offset, size_t left, |
||
863 |
struct ikev2_payload *pld, struct ikev2_cert *cert) |
||
864 |
{ |
||
865 |
1250260 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
866 |
size_t pld_length; |
||
867 |
|||
868 |
625130 |
pld_length = betoh16(pld->pld_length); |
|
869 |
✓✓ | 625130 |
if (pld_length < sizeof(*pld) + sizeof(*cert)) { |
870 |
4190 |
log_debug("%s: malformed payload: specified length smaller " |
|
871 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
872 |
sizeof(*pld) + sizeof(*cert)); |
||
873 |
4190 |
return (-1); |
|
874 |
} |
||
875 |
|||
876 |
/* This will actually be caught by earlier checks. */ |
||
877 |
✗✓ | 620940 |
if (left < sizeof(*cert)) { |
878 |
log_debug("%s: malformed payload: too short for header " |
||
879 |
"(%zu < %zu)", __func__, left, sizeof(*cert)); |
||
880 |
return (-1); |
||
881 |
} |
||
882 |
620940 |
memcpy(cert, msgbuf + offset, sizeof(*cert)); |
|
883 |
|||
884 |
620940 |
return (0); |
|
885 |
625130 |
} |
|
886 |
|||
887 |
int |
||
888 |
ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld, |
||
889 |
struct iked_message *msg, size_t offset, size_t left) |
||
890 |
{ |
||
891 |
1250260 |
struct iked_sa *sa = msg->msg_sa; |
|
892 |
625130 |
struct ikev2_cert cert; |
|
893 |
uint8_t *buf; |
||
894 |
ssize_t len; |
||
895 |
625130 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
896 |
|||
897 |
✓✓ | 625130 |
if (ikev2_validate_certreq(msg, offset, left, pld, &cert)) |
898 |
4190 |
return (-1); |
|
899 |
620940 |
offset += sizeof(cert); |
|
900 |
|||
901 |
620940 |
buf = msgbuf + offset; |
|
902 |
620940 |
len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert); |
|
903 |
|||
904 |
620940 |
log_debug("%s: type %s length %zd", |
|
905 |
620940 |
__func__, print_map(cert.cert_type, ikev2_cert_map), len); |
|
906 |
|||
907 |
/* This will actually be caught by earlier checks. */ |
||
908 |
✗✓ | 620940 |
if (len < 0) { |
909 |
log_debug("%s: invalid certificate request length", __func__); |
||
910 |
return (-1); |
||
911 |
} |
||
912 |
|||
913 |
620940 |
print_hex(buf, 0, len); |
|
914 |
|||
915 |
✓✗ | 620940 |
if (!ikev2_msg_frompeer(msg)) |
916 |
620940 |
return (0); |
|
917 |
|||
918 |
if (cert.cert_type == IKEV2_CERT_X509_CERT) { |
||
919 |
if (!len) |
||
920 |
return (0); |
||
921 |
if ((len % SHA_DIGEST_LENGTH) != 0) { |
||
922 |
log_debug("%s: invalid certificate request", __func__); |
||
923 |
return (-1); |
||
924 |
} |
||
925 |
} |
||
926 |
|||
927 |
if (msg->msg_sa == NULL) |
||
928 |
return (-1); |
||
929 |
|||
930 |
/* Optional certreq for PSK */ |
||
931 |
if (sa->sa_hdr.sh_initiator) |
||
932 |
sa->sa_stateinit |= IKED_REQ_CERT; |
||
933 |
else |
||
934 |
sa->sa_statevalid |= IKED_REQ_CERT; |
||
935 |
|||
936 |
ca_setreq(env, sa, &sa->sa_policy->pol_localid, |
||
937 |
cert.cert_type, buf, len, PROC_CERT); |
||
938 |
|||
939 |
return (0); |
||
940 |
625130 |
} |
|
941 |
|||
942 |
int |
||
943 |
ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left, |
||
944 |
struct ikev2_payload *pld, struct ikev2_auth *auth) |
||
945 |
{ |
||
946 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
947 |
size_t pld_length; |
||
948 |
|||
949 |
pld_length = betoh16(pld->pld_length); |
||
950 |
if (pld_length < sizeof(*pld) + sizeof(*auth)) { |
||
951 |
log_debug("%s: malformed payload: specified length smaller " |
||
952 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
953 |
sizeof(*pld) + sizeof(*auth)); |
||
954 |
return (-1); |
||
955 |
} |
||
956 |
|||
957 |
/* This will actually be caught by earlier checks. */ |
||
958 |
if (left < sizeof(*auth)) { |
||
959 |
log_debug("%s: malformed payload: too short for header " |
||
960 |
"(%zu < %zu)", __func__, left, sizeof(*auth)); |
||
961 |
return (-1); |
||
962 |
} |
||
963 |
memcpy(auth, msgbuf + offset, sizeof(*auth)); |
||
964 |
|||
965 |
return (0); |
||
966 |
} |
||
967 |
|||
968 |
int |
||
969 |
ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld, |
||
970 |
struct iked_message *msg, size_t offset, size_t left) |
||
971 |
{ |
||
972 |
struct ikev2_auth auth; |
||
973 |
struct iked_id *idp; |
||
974 |
uint8_t *buf; |
||
975 |
size_t len; |
||
976 |
struct iked_sa *sa = msg->msg_sa; |
||
977 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
978 |
|||
979 |
if (ikev2_validate_auth(msg, offset, left, pld, &auth)) |
||
980 |
return (-1); |
||
981 |
offset += sizeof(auth); |
||
982 |
|||
983 |
buf = msgbuf + offset; |
||
984 |
len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(auth); |
||
985 |
|||
986 |
log_debug("%s: method %s length %zu", |
||
987 |
__func__, print_map(auth.auth_method, ikev2_auth_map), len); |
||
988 |
|||
989 |
print_hex(buf, 0, len); |
||
990 |
|||
991 |
if (!ikev2_msg_frompeer(msg)) |
||
992 |
return (0); |
||
993 |
|||
994 |
/* The AUTH payload indicates if the responder wants EAP or not */ |
||
995 |
if (!sa_stateok(sa, IKEV2_STATE_EAP)) |
||
996 |
sa_state(env, sa, IKEV2_STATE_AUTH_REQUEST); |
||
997 |
|||
998 |
idp = &msg->msg_parent->msg_auth; |
||
999 |
if (idp->id_type) { |
||
1000 |
log_debug("%s: duplicate auth payload", __func__); |
||
1001 |
return (-1); |
||
1002 |
} |
||
1003 |
|||
1004 |
ibuf_release(idp->id_buf); |
||
1005 |
idp->id_type = auth.auth_method; |
||
1006 |
idp->id_offset = 0; |
||
1007 |
if ((idp->id_buf = ibuf_new(buf, len)) == NULL) |
||
1008 |
return (-1); |
||
1009 |
|||
1010 |
return (0); |
||
1011 |
} |
||
1012 |
|||
1013 |
int |
||
1014 |
ikev2_validate_nonce(struct iked_message *msg, size_t offset, size_t left, |
||
1015 |
struct ikev2_payload *pld) |
||
1016 |
{ |
||
1017 |
size_t pld_length; |
||
1018 |
|||
1019 |
/* This will actually be caught by earlier checks. */ |
||
1020 |
254576840 |
pld_length = betoh16(pld->pld_length); |
|
1021 |
✗✓ | 127288420 |
if (pld_length < sizeof(*pld)) { |
1022 |
log_debug("%s: malformed payload: specified length smaller " |
||
1023 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
1024 |
sizeof(*pld)); |
||
1025 |
return (-1); |
||
1026 |
} |
||
1027 |
|||
1028 |
127288420 |
return (0); |
|
1029 |
127288420 |
} |
|
1030 |
|||
1031 |
int |
||
1032 |
ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld, |
||
1033 |
struct iked_message *msg, size_t offset, size_t left) |
||
1034 |
{ |
||
1035 |
size_t len; |
||
1036 |
uint8_t *buf; |
||
1037 |
254576840 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
1038 |
|||
1039 |
✗✓ | 127288420 |
if (ikev2_validate_nonce(msg, offset, left, pld)) |
1040 |
return (-1); |
||
1041 |
|||
1042 |
127288420 |
buf = msgbuf + offset; |
|
1043 |
127288420 |
len = betoh16(pld->pld_length) - sizeof(*pld); |
|
1044 |
|||
1045 |
✓✓ | 127288420 |
if (len == 0) { |
1046 |
79080 |
log_debug("%s: malformed payload: no NONCE given", __func__); |
|
1047 |
79080 |
return (-1); |
|
1048 |
} |
||
1049 |
/* This will actually be caught by earlier checks. */ |
||
1050 |
✗✓ | 127209340 |
if (left < len) { |
1051 |
log_debug("%s: malformed payload: smaller than specified " |
||
1052 |
"(%zu < %zu)", __func__, left, len); |
||
1053 |
return (-1); |
||
1054 |
} |
||
1055 |
|||
1056 |
127209340 |
print_hex(buf, 0, len); |
|
1057 |
|||
1058 |
✗✓ | 127209340 |
if (ikev2_msg_frompeer(msg)) { |
1059 |
ibuf_release(msg->msg_nonce); |
||
1060 |
if ((msg->msg_nonce = ibuf_new(buf, len)) == NULL) { |
||
1061 |
log_debug("%s: failed to get peer nonce", __func__); |
||
1062 |
return (-1); |
||
1063 |
} |
||
1064 |
msg->msg_parent->msg_nonce = msg->msg_nonce; |
||
1065 |
} |
||
1066 |
|||
1067 |
127209340 |
return (0); |
|
1068 |
127288420 |
} |
|
1069 |
|||
1070 |
int |
||
1071 |
ikev2_validate_notify(struct iked_message *msg, size_t offset, size_t left, |
||
1072 |
struct ikev2_payload *pld, struct ikev2_notify *n) |
||
1073 |
{ |
||
1074 |
500471380 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
1075 |
size_t pld_length; |
||
1076 |
|||
1077 |
250235690 |
pld_length = betoh16(pld->pld_length); |
|
1078 |
✓✓ | 250235690 |
if (pld_length < sizeof(*pld) + sizeof(*n)) { |
1079 |
160 |
log_debug("%s: malformed payload: specified length smaller " |
|
1080 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
1081 |
sizeof(*pld) + sizeof(*n)); |
||
1082 |
160 |
return (-1); |
|
1083 |
} |
||
1084 |
|||
1085 |
/* This will actually be caught by earlier checks. */ |
||
1086 |
✗✓ | 250235530 |
if (left < sizeof(*n)) { |
1087 |
log_debug("%s: malformed payload: too short for header " |
||
1088 |
"(%zu < %zu)", __func__, left, sizeof(*n)); |
||
1089 |
return (-1); |
||
1090 |
} |
||
1091 |
250235530 |
memcpy(n, msgbuf + offset, sizeof(*n)); |
|
1092 |
|||
1093 |
250235530 |
return (0); |
|
1094 |
250235690 |
} |
|
1095 |
|||
1096 |
int |
||
1097 |
ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, |
||
1098 |
struct iked_message *msg, size_t offset, size_t left) |
||
1099 |
{ |
||
1100 |
500471380 |
struct ikev2_notify n; |
|
1101 |
250235690 |
uint8_t *buf, md[SHA_DIGEST_LENGTH]; |
|
1102 |
size_t len; |
||
1103 |
250235690 |
uint32_t spi32; |
|
1104 |
250235690 |
uint64_t spi64; |
|
1105 |
struct iked_spi *rekey; |
||
1106 |
uint16_t type; |
||
1107 |
250235690 |
uint16_t group; |
|
1108 |
uint16_t cpi; |
||
1109 |
uint16_t signature_hash; |
||
1110 |
uint8_t transform; |
||
1111 |
|||
1112 |
✓✓ | 250235690 |
if (ikev2_validate_notify(msg, offset, left, pld, &n)) |
1113 |
160 |
return (-1); |
|
1114 |
250235530 |
type = betoh16(n.n_type); |
|
1115 |
|||
1116 |
250235530 |
log_debug("%s: protoid %s spisize %d type %s", |
|
1117 |
__func__, |
||
1118 |
250235530 |
print_map(n.n_protoid, ikev2_saproto_map), n.n_spisize, |
|
1119 |
250235530 |
print_map(type, ikev2_n_map)); |
|
1120 |
|||
1121 |
250235530 |
len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(n); |
|
1122 |
✗✓ | 250235530 |
if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(n), len)) == NULL) |
1123 |
return (-1); |
||
1124 |
|||
1125 |
250235530 |
print_hex(buf, 0, len); |
|
1126 |
|||
1127 |
✓✗ | 250235530 |
if (!ikev2_msg_frompeer(msg)) |
1128 |
250235530 |
return (0); |
|
1129 |
|||
1130 |
switch (type) { |
||
1131 |
case IKEV2_N_NAT_DETECTION_SOURCE_IP: |
||
1132 |
case IKEV2_N_NAT_DETECTION_DESTINATION_IP: |
||
1133 |
if (len != sizeof(md)) { |
||
1134 |
log_debug("%s: malformed payload: hash size mismatch" |
||
1135 |
" (%zu != %zu)", __func__, len, sizeof(md)); |
||
1136 |
return (-1); |
||
1137 |
} |
||
1138 |
if (ikev2_nat_detection(env, msg, md, sizeof(md), type) == -1) |
||
1139 |
return (-1); |
||
1140 |
if (memcmp(buf, md, len) != 0) { |
||
1141 |
log_debug("%s: %s detected NAT, enabling " |
||
1142 |
"UDP encapsulation", __func__, |
||
1143 |
print_map(type, ikev2_n_map)); |
||
1144 |
|||
1145 |
/* |
||
1146 |
* Enable UDP encapsulation of ESP packages if |
||
1147 |
* the check detected NAT. |
||
1148 |
*/ |
||
1149 |
if (msg->msg_sa != NULL) |
||
1150 |
msg->msg_sa->sa_udpencap = 1; |
||
1151 |
/* Send keepalive, since we are behind a NAT-gw */ |
||
1152 |
if (type == IKEV2_N_NAT_DETECTION_DESTINATION_IP) |
||
1153 |
msg->msg_sa->sa_usekeepalive = 1; |
||
1154 |
} |
||
1155 |
print_hex(md, 0, sizeof(md)); |
||
1156 |
break; |
||
1157 |
case IKEV2_N_AUTHENTICATION_FAILED: |
||
1158 |
if (!msg->msg_e) { |
||
1159 |
log_debug("%s: AUTHENTICATION_FAILED not encrypted", |
||
1160 |
__func__); |
||
1161 |
return (-1); |
||
1162 |
} |
||
1163 |
/* |
||
1164 |
* If we are the responder, then we only accept |
||
1165 |
* AUTHENTICATION_FAILED from authenticated peers. |
||
1166 |
* If we are the initiator, the peer cannot be authenticated. |
||
1167 |
*/ |
||
1168 |
if (!msg->msg_sa->sa_hdr.sh_initiator) { |
||
1169 |
if (!sa_stateok(msg->msg_sa, IKEV2_STATE_VALID)) { |
||
1170 |
log_debug("%s: ignoring AUTHENTICATION_FAILED" |
||
1171 |
" from unauthenticated initiator", |
||
1172 |
__func__); |
||
1173 |
return (-1); |
||
1174 |
} |
||
1175 |
} else { |
||
1176 |
if (sa_stateok(msg->msg_sa, IKEV2_STATE_VALID)) { |
||
1177 |
log_debug("%s: ignoring AUTHENTICATION_FAILED" |
||
1178 |
" from authenticated responder", |
||
1179 |
__func__); |
||
1180 |
return (-1); |
||
1181 |
} |
||
1182 |
} |
||
1183 |
log_debug("%s: AUTHENTICATION_FAILED, closing SA", __func__); |
||
1184 |
sa_state(env, msg->msg_sa, IKEV2_STATE_CLOSED); |
||
1185 |
msg->msg_sa = NULL; |
||
1186 |
break; |
||
1187 |
case IKEV2_N_INVALID_KE_PAYLOAD: |
||
1188 |
if (sa_stateok(msg->msg_sa, IKEV2_STATE_VALID) && |
||
1189 |
!msg->msg_e) { |
||
1190 |
log_debug("%s: INVALID_KE_PAYLOAD not encrypted", |
||
1191 |
__func__); |
||
1192 |
return (-1); |
||
1193 |
} |
||
1194 |
if (len != sizeof(group)) { |
||
1195 |
log_debug("%s: malformed payload: group size mismatch" |
||
1196 |
" (%zu != %zu)", __func__, len, sizeof(group)); |
||
1197 |
return (-1); |
||
1198 |
} |
||
1199 |
/* XXX chould also happen for PFS */ |
||
1200 |
if (!msg->msg_sa->sa_hdr.sh_initiator) { |
||
1201 |
log_debug("%s: not an initiator", __func__); |
||
1202 |
sa_state(env, msg->msg_sa, IKEV2_STATE_CLOSED); |
||
1203 |
msg->msg_sa = NULL; |
||
1204 |
return (-1); |
||
1205 |
} |
||
1206 |
memcpy(&group, buf, len); |
||
1207 |
group = betoh16(group); |
||
1208 |
if (group_getid(group) == NULL) { |
||
1209 |
log_debug("%s: unable to select DH group %u", __func__, |
||
1210 |
group); |
||
1211 |
return (-1); |
||
1212 |
} |
||
1213 |
msg->msg_policy->pol_peerdh = group; |
||
1214 |
log_debug("%s: responder selected DH group %u", __func__, |
||
1215 |
group); |
||
1216 |
sa_state(env, msg->msg_sa, IKEV2_STATE_CLOSED); |
||
1217 |
msg->msg_sa = NULL; |
||
1218 |
|||
1219 |
/* |
||
1220 |
* XXX should also happen for PFS so we have to check state. |
||
1221 |
*/ |
||
1222 |
timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, NULL); |
||
1223 |
timer_add(env, &env->sc_inittmr, IKED_INITIATOR_INITIAL); |
||
1224 |
break; |
||
1225 |
case IKEV2_N_NO_ADDITIONAL_SAS: |
||
1226 |
if (!msg->msg_e) { |
||
1227 |
log_debug("%s: NO_ADDITIONAL_SAS not encrypted", |
||
1228 |
__func__); |
||
1229 |
return (-1); |
||
1230 |
} |
||
1231 |
/* This makes sense for Child SAs only atm */ |
||
1232 |
if (msg->msg_sa->sa_stateflags & IKED_REQ_CHILDSA) { |
||
1233 |
ikev2_disable_rekeying(env, msg->msg_sa); |
||
1234 |
msg->msg_sa->sa_stateflags &= ~IKED_REQ_CHILDSA; |
||
1235 |
} |
||
1236 |
break; |
||
1237 |
case IKEV2_N_REKEY_SA: |
||
1238 |
if (!msg->msg_e) { |
||
1239 |
log_debug("%s: N_REKEY_SA not encrypted", __func__); |
||
1240 |
return (-1); |
||
1241 |
} |
||
1242 |
if (len != n.n_spisize) { |
||
1243 |
log_debug("%s: malformed notification", __func__); |
||
1244 |
return (-1); |
||
1245 |
} |
||
1246 |
rekey = &msg->msg_parent->msg_rekey; |
||
1247 |
if (rekey->spi != 0) { |
||
1248 |
log_debug("%s: rekeying of multiple SAs not supported", |
||
1249 |
__func__); |
||
1250 |
return (-1); |
||
1251 |
} |
||
1252 |
switch (n.n_spisize) { |
||
1253 |
case 4: |
||
1254 |
memcpy(&spi32, buf, len); |
||
1255 |
rekey->spi = betoh32(spi32); |
||
1256 |
break; |
||
1257 |
case 8: |
||
1258 |
memcpy(&spi64, buf, len); |
||
1259 |
rekey->spi = betoh64(spi64); |
||
1260 |
break; |
||
1261 |
default: |
||
1262 |
log_debug("%s: invalid spi size %d", __func__, |
||
1263 |
n.n_spisize); |
||
1264 |
return (-1); |
||
1265 |
} |
||
1266 |
rekey->spi_size = n.n_spisize; |
||
1267 |
rekey->spi_protoid = n.n_protoid; |
||
1268 |
|||
1269 |
log_debug("%s: rekey %s spi %s", __func__, |
||
1270 |
print_map(n.n_protoid, ikev2_saproto_map), |
||
1271 |
print_spi(rekey->spi, n.n_spisize)); |
||
1272 |
break; |
||
1273 |
case IKEV2_N_IPCOMP_SUPPORTED: |
||
1274 |
if (!msg->msg_e) { |
||
1275 |
log_debug("%s: N_IPCOMP_SUPPORTED not encrypted", |
||
1276 |
__func__); |
||
1277 |
return (-1); |
||
1278 |
} |
||
1279 |
if (len < sizeof(cpi) + sizeof(transform)) { |
||
1280 |
log_debug("%s: ignoring malformed ipcomp notification", |
||
1281 |
__func__); |
||
1282 |
return (0); |
||
1283 |
} |
||
1284 |
memcpy(&cpi, buf, sizeof(cpi)); |
||
1285 |
memcpy(&transform, buf + sizeof(cpi), sizeof(transform)); |
||
1286 |
log_debug("%s: cpi 0x%x, transform %s, len %zu", __func__, |
||
1287 |
betoh16(cpi), print_map(transform, ikev2_ipcomp_map), len); |
||
1288 |
/* we only support deflate */ |
||
1289 |
if ((msg->msg_policy->pol_flags & IKED_POLICY_IPCOMP) && |
||
1290 |
(transform == IKEV2_IPCOMP_DEFLATE)) { |
||
1291 |
msg->msg_sa->sa_ipcomp = transform; |
||
1292 |
msg->msg_sa->sa_cpi_out = betoh16(cpi); |
||
1293 |
} |
||
1294 |
break; |
||
1295 |
case IKEV2_N_COOKIE: |
||
1296 |
if (msg->msg_e) { |
||
1297 |
log_debug("%s: N_COOKIE encrypted", |
||
1298 |
__func__); |
||
1299 |
return (-1); |
||
1300 |
} |
||
1301 |
if (len < IKED_COOKIE_MIN || len > IKED_COOKIE_MAX) { |
||
1302 |
log_debug("%s: ignoring malformed cookie" |
||
1303 |
" notification: %zu", __func__, len); |
||
1304 |
return (0); |
||
1305 |
} |
||
1306 |
log_debug("%s: received cookie, len %zu", __func__, len); |
||
1307 |
print_hex(buf, 0, len); |
||
1308 |
|||
1309 |
ibuf_release(msg->msg_cookie); |
||
1310 |
if ((msg->msg_cookie = ibuf_new(buf, len)) == NULL) { |
||
1311 |
log_debug("%s: failed to get peer cookie", __func__); |
||
1312 |
return (-1); |
||
1313 |
} |
||
1314 |
msg->msg_parent->msg_cookie = msg->msg_cookie; |
||
1315 |
break; |
||
1316 |
case IKEV2_N_SIGNATURE_HASH_ALGORITHMS: |
||
1317 |
if (msg->msg_e) { |
||
1318 |
log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted", |
||
1319 |
__func__); |
||
1320 |
return (-1); |
||
1321 |
} |
||
1322 |
if (msg->msg_sa == NULL || |
||
1323 |
msg->msg_sa->sa_sigsha2) { |
||
1324 |
log_debug("%s: SIGNATURE_HASH_ALGORITHMS: no SA or " |
||
1325 |
"duplicate notify", __func__); |
||
1326 |
return (-1); |
||
1327 |
} |
||
1328 |
if (len < sizeof(signature_hash) || |
||
1329 |
len % sizeof(signature_hash)) { |
||
1330 |
log_debug("%s: malformed signature hash notification" |
||
1331 |
"(%zu bytes)", __func__, len); |
||
1332 |
return (0); |
||
1333 |
} |
||
1334 |
while (len >= sizeof(signature_hash)) { |
||
1335 |
memcpy(&signature_hash, buf, sizeof(signature_hash)); |
||
1336 |
signature_hash = betoh16(signature_hash); |
||
1337 |
log_debug("%s: signature hash %s (%x)", __func__, |
||
1338 |
print_map(signature_hash, ikev2_sighash_map), |
||
1339 |
signature_hash); |
||
1340 |
len -= sizeof(signature_hash); |
||
1341 |
buf += sizeof(signature_hash); |
||
1342 |
if (signature_hash == IKEV2_SIGHASH_SHA2_256) |
||
1343 |
msg->msg_sa->sa_sigsha2 = 1; |
||
1344 |
} |
||
1345 |
break; |
||
1346 |
} |
||
1347 |
|||
1348 |
return (0); |
||
1349 |
250235690 |
} |
|
1350 |
|||
1351 |
int |
||
1352 |
ikev2_validate_delete(struct iked_message *msg, size_t offset, size_t left, |
||
1353 |
struct ikev2_payload *pld, struct ikev2_delete *del) |
||
1354 |
{ |
||
1355 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
1356 |
size_t pld_length; |
||
1357 |
|||
1358 |
pld_length = betoh16(pld->pld_length); |
||
1359 |
if (pld_length < sizeof(*pld) + sizeof(*del)) { |
||
1360 |
log_debug("%s: malformed payload: specified length smaller " |
||
1361 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
1362 |
sizeof(*pld) + sizeof(*del)); |
||
1363 |
return (-1); |
||
1364 |
} |
||
1365 |
|||
1366 |
/* This will actually be caught by earlier checks. */ |
||
1367 |
if (left < sizeof(*del)) { |
||
1368 |
log_debug("%s: malformed payload: too short for header " |
||
1369 |
"(%zu < %zu)", __func__, left, sizeof(*del)); |
||
1370 |
return (-1); |
||
1371 |
} |
||
1372 |
memcpy(del, msgbuf + offset, sizeof(*del)); |
||
1373 |
|||
1374 |
return (0); |
||
1375 |
} |
||
1376 |
|||
1377 |
int |
||
1378 |
ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, |
||
1379 |
struct iked_message *msg, size_t offset, size_t left) |
||
1380 |
{ |
||
1381 |
struct iked_childsa **peersas = NULL; |
||
1382 |
struct iked_sa *sa = msg->msg_sa; |
||
1383 |
struct ikev2_delete del, *localdel; |
||
1384 |
struct ibuf *resp = NULL; |
||
1385 |
uint64_t *localspi = NULL; |
||
1386 |
uint64_t spi64, spi = 0; |
||
1387 |
uint32_t spi32; |
||
1388 |
uint8_t *buf, *msgbuf = ibuf_data(msg->msg_data); |
||
1389 |
size_t found = 0, failed = 0; |
||
1390 |
int cnt, i, len, sz, ret = -1; |
||
1391 |
|||
1392 |
/* Skip if it's a response, then we don't have to deal with it */ |
||
1393 |
if (ikev2_msg_frompeer(msg) && |
||
1394 |
msg->msg_parent->msg_response) |
||
1395 |
return (0); |
||
1396 |
|||
1397 |
if (ikev2_validate_delete(msg, offset, left, pld, &del)) |
||
1398 |
return (-1); |
||
1399 |
cnt = betoh16(del.del_nspi); |
||
1400 |
sz = del.del_spisize; |
||
1401 |
|||
1402 |
log_debug("%s: proto %s spisize %d nspi %d", |
||
1403 |
__func__, print_map(del.del_protoid, ikev2_saproto_map), |
||
1404 |
sz, cnt); |
||
1405 |
|||
1406 |
buf = msgbuf + offset + sizeof(del); |
||
1407 |
len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(del); |
||
1408 |
|||
1409 |
print_hex(buf, 0, len); |
||
1410 |
|||
1411 |
switch (sz) { |
||
1412 |
case 4: |
||
1413 |
case 8: |
||
1414 |
break; |
||
1415 |
default: |
||
1416 |
if (del.del_protoid != IKEV2_SAPROTO_IKE) { |
||
1417 |
log_debug("%s: invalid SPI size", __func__); |
||
1418 |
return (-1); |
||
1419 |
} |
||
1420 |
if (ikev2_msg_frompeer(msg)) { |
||
1421 |
/* Send an empty informational response */ |
||
1422 |
if ((resp = ibuf_static()) == NULL) |
||
1423 |
goto done; |
||
1424 |
ret = ikev2_send_ike_e(env, sa, resp, |
||
1425 |
IKEV2_PAYLOAD_NONE, |
||
1426 |
IKEV2_EXCHANGE_INFORMATIONAL, 1); |
||
1427 |
msg->msg_parent->msg_responded = 1; |
||
1428 |
ibuf_release(resp); |
||
1429 |
ikev2_ikesa_recv_delete(env, sa); |
||
1430 |
} else { |
||
1431 |
/* |
||
1432 |
* We're sending a delete message. Upper layer |
||
1433 |
* must deal with deletion of the IKE SA. |
||
1434 |
*/ |
||
1435 |
ret = 0; |
||
1436 |
} |
||
1437 |
return (ret); |
||
1438 |
} |
||
1439 |
|||
1440 |
if ((len / sz) != cnt) { |
||
1441 |
log_debug("%s: invalid payload length %d/%d != %d", |
||
1442 |
__func__, len, sz, cnt); |
||
1443 |
return (-1); |
||
1444 |
} |
||
1445 |
|||
1446 |
if (ikev2_msg_frompeer(msg) && |
||
1447 |
((peersas = calloc(cnt, sizeof(struct iked_childsa *))) == NULL || |
||
1448 |
(localspi = calloc(cnt, sizeof(uint64_t))) == NULL)) { |
||
1449 |
log_warn("%s", __func__); |
||
1450 |
goto done; |
||
1451 |
} |
||
1452 |
|||
1453 |
for (i = 0; i < cnt; i++) { |
||
1454 |
switch (sz) { |
||
1455 |
case 4: |
||
1456 |
memcpy(&spi32, buf + (i * sz), sizeof(spi32)); |
||
1457 |
spi = betoh32(spi32); |
||
1458 |
break; |
||
1459 |
case 8: |
||
1460 |
memcpy(&spi64, buf + (i * sz), sizeof(spi64)); |
||
1461 |
spi = betoh64(spi64); |
||
1462 |
break; |
||
1463 |
} |
||
1464 |
|||
1465 |
log_debug("%s: spi %s", __func__, print_spi(spi, sz)); |
||
1466 |
|||
1467 |
if (peersas == NULL || sa == NULL) |
||
1468 |
continue; |
||
1469 |
|||
1470 |
if ((peersas[i] = childsa_lookup(sa, spi, |
||
1471 |
del.del_protoid)) == NULL) { |
||
1472 |
log_warnx("%s: CHILD SA doesn't exist for spi %s", |
||
1473 |
__func__, print_spi(spi, del.del_spisize)); |
||
1474 |
continue; |
||
1475 |
} |
||
1476 |
|||
1477 |
if (ikev2_childsa_delete(env, sa, del.del_protoid, spi, |
||
1478 |
&localspi[i], 0) == -1) |
||
1479 |
failed++; |
||
1480 |
else |
||
1481 |
found++; |
||
1482 |
|||
1483 |
/* |
||
1484 |
* Flows are left in the require mode so that it would be |
||
1485 |
* possible to quickly negotiate a new Child SA |
||
1486 |
*/ |
||
1487 |
} |
||
1488 |
|||
1489 |
/* Parsed outgoing message? */ |
||
1490 |
if (!ikev2_msg_frompeer(msg)) |
||
1491 |
goto done; |
||
1492 |
|||
1493 |
if (msg->msg_parent->msg_response) { |
||
1494 |
ret = 0; |
||
1495 |
goto done; |
||
1496 |
} |
||
1497 |
|||
1498 |
/* Response to the INFORMATIONAL with Delete payload */ |
||
1499 |
|||
1500 |
if ((resp = ibuf_static()) == NULL) |
||
1501 |
goto done; |
||
1502 |
|||
1503 |
if (found) { |
||
1504 |
if ((localdel = ibuf_advance(resp, sizeof(*localdel))) == NULL) |
||
1505 |
goto done; |
||
1506 |
|||
1507 |
localdel->del_protoid = del.del_protoid; |
||
1508 |
localdel->del_spisize = del.del_spisize; |
||
1509 |
localdel->del_nspi = htobe16(found); |
||
1510 |
|||
1511 |
for (i = 0; i < cnt; i++) { |
||
1512 |
if (localspi[i] == 0) /* happens if found < cnt */ |
||
1513 |
continue; |
||
1514 |
switch (sz) { |
||
1515 |
case 4: |
||
1516 |
spi32 = htobe32(localspi[i]); |
||
1517 |
if (ibuf_add(resp, &spi32, sizeof(spi32)) != 0) |
||
1518 |
goto done; |
||
1519 |
break; |
||
1520 |
case 8: |
||
1521 |
spi64 = htobe64(localspi[i]); |
||
1522 |
if (ibuf_add(resp, &spi64, sizeof(spi64)) != 0) |
||
1523 |
goto done; |
||
1524 |
break; |
||
1525 |
} |
||
1526 |
} |
||
1527 |
|||
1528 |
log_warnx("%s: deleted %zu spis", __func__, found); |
||
1529 |
} |
||
1530 |
|||
1531 |
if (found) { |
||
1532 |
ret = ikev2_send_ike_e(env, sa, resp, IKEV2_PAYLOAD_DELETE, |
||
1533 |
IKEV2_EXCHANGE_INFORMATIONAL, 1); |
||
1534 |
msg->msg_parent->msg_responded = 1; |
||
1535 |
} else { |
||
1536 |
/* XXX should we send an INVALID_SPI notification? */ |
||
1537 |
ret = 0; |
||
1538 |
} |
||
1539 |
|||
1540 |
done: |
||
1541 |
free(localspi); |
||
1542 |
free(peersas); |
||
1543 |
ibuf_release(resp); |
||
1544 |
return (ret); |
||
1545 |
} |
||
1546 |
|||
1547 |
int |
||
1548 |
ikev2_validate_ts(struct iked_message *msg, size_t offset, size_t left, |
||
1549 |
struct ikev2_payload *pld, struct ikev2_tsp *tsp) |
||
1550 |
{ |
||
1551 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
1552 |
size_t pld_length; |
||
1553 |
|||
1554 |
pld_length = betoh16(pld->pld_length); |
||
1555 |
if (pld_length < sizeof(*pld) + sizeof(*tsp)) { |
||
1556 |
log_debug("%s: malformed payload: specified length smaller " |
||
1557 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
1558 |
sizeof(*pld) + sizeof(*tsp)); |
||
1559 |
return (-1); |
||
1560 |
} |
||
1561 |
|||
1562 |
/* This will actually be caught by earlier checks. */ |
||
1563 |
if (left < sizeof(*tsp)) { |
||
1564 |
log_debug("%s: malformed payload: too short for header " |
||
1565 |
"(%zu < %zu)", __func__, left, sizeof(*tsp)); |
||
1566 |
return (-1); |
||
1567 |
} |
||
1568 |
memcpy(tsp, msgbuf + offset, sizeof(*tsp)); |
||
1569 |
|||
1570 |
return (0); |
||
1571 |
} |
||
1572 |
|||
1573 |
int |
||
1574 |
ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld, |
||
1575 |
struct iked_message *msg, size_t offset, size_t left, unsigned int payload) |
||
1576 |
{ |
||
1577 |
struct ikev2_tsp tsp; |
||
1578 |
struct ikev2_ts ts; |
||
1579 |
size_t len, i; |
||
1580 |
struct sockaddr_in s4; |
||
1581 |
struct sockaddr_in6 s6; |
||
1582 |
uint8_t buf[2][128]; |
||
1583 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
1584 |
|||
1585 |
if (ikev2_validate_ts(msg, offset, left, pld, &tsp)) |
||
1586 |
return (-1); |
||
1587 |
offset += sizeof(tsp); |
||
1588 |
|||
1589 |
len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(tsp); |
||
1590 |
|||
1591 |
log_debug("%s: count %d length %zu", __func__, |
||
1592 |
tsp.tsp_count, len); |
||
1593 |
|||
1594 |
for (i = 0; i < tsp.tsp_count; i++) { |
||
1595 |
memcpy(&ts, msgbuf + offset, sizeof(ts)); |
||
1596 |
|||
1597 |
log_debug("%s: type %s protoid %u length %d " |
||
1598 |
"startport %u endport %u", __func__, |
||
1599 |
print_map(ts.ts_type, ikev2_ts_map), |
||
1600 |
ts.ts_protoid, betoh16(ts.ts_length), |
||
1601 |
betoh16(ts.ts_startport), |
||
1602 |
betoh16(ts.ts_endport)); |
||
1603 |
|||
1604 |
switch (ts.ts_type) { |
||
1605 |
case IKEV2_TS_IPV4_ADDR_RANGE: |
||
1606 |
bzero(&s4, sizeof(s4)); |
||
1607 |
s4.sin_family = AF_INET; |
||
1608 |
s4.sin_len = sizeof(s4); |
||
1609 |
memcpy(&s4.sin_addr.s_addr, |
||
1610 |
msgbuf + offset + sizeof(ts), 4); |
||
1611 |
print_host((struct sockaddr *)&s4, |
||
1612 |
(char *)buf[0], sizeof(buf[0])); |
||
1613 |
memcpy(&s4.sin_addr.s_addr, |
||
1614 |
msgbuf + offset + sizeof(ts) + 4, 4); |
||
1615 |
print_host((struct sockaddr *)&s4, |
||
1616 |
(char *)buf[1], sizeof(buf[1])); |
||
1617 |
log_debug("%s: start %s end %s", __func__, |
||
1618 |
buf[0], buf[1]); |
||
1619 |
break; |
||
1620 |
case IKEV2_TS_IPV6_ADDR_RANGE: |
||
1621 |
bzero(&s6, sizeof(s6)); |
||
1622 |
s6.sin6_family = AF_INET6; |
||
1623 |
s6.sin6_len = sizeof(s6); |
||
1624 |
memcpy(&s6.sin6_addr, |
||
1625 |
msgbuf + offset + sizeof(ts), 16); |
||
1626 |
print_host((struct sockaddr *)&s6, |
||
1627 |
(char *)buf[0], sizeof(buf[0])); |
||
1628 |
memcpy(&s6.sin6_addr, |
||
1629 |
msgbuf + offset + sizeof(ts) + 16, 16); |
||
1630 |
print_host((struct sockaddr *)&s6, |
||
1631 |
(char *)buf[1], sizeof(buf[1])); |
||
1632 |
log_debug("%s: start %s end %s", __func__, |
||
1633 |
buf[0], buf[1]); |
||
1634 |
break; |
||
1635 |
default: |
||
1636 |
break; |
||
1637 |
} |
||
1638 |
|||
1639 |
offset += betoh16(ts.ts_length); |
||
1640 |
} |
||
1641 |
|||
1642 |
return (0); |
||
1643 |
} |
||
1644 |
|||
1645 |
int |
||
1646 |
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld, |
||
1647 |
struct iked_message *msg, size_t offset) |
||
1648 |
{ |
||
1649 |
136680 |
struct iked_sa *sa = msg->msg_sa; |
|
1650 |
struct ibuf *e = NULL; |
||
1651 |
68340 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
|
1652 |
68340 |
struct iked_message emsg; |
|
1653 |
uint8_t *buf; |
||
1654 |
size_t len; |
||
1655 |
int ret = -1; |
||
1656 |
|||
1657 |
68340 |
buf = msgbuf + offset; |
|
1658 |
68340 |
len = betoh16(pld->pld_length) - sizeof(*pld); |
|
1659 |
|||
1660 |
✓✗ | 68340 |
if ((e = ibuf_new(buf, len)) == NULL) |
1661 |
goto done; |
||
1662 |
|||
1663 |
✗✓ | 68340 |
if (ikev2_msg_frompeer(msg)) { |
1664 |
e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e); |
||
1665 |
} else { |
||
1666 |
68340 |
sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1; |
|
1667 |
68340 |
e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e); |
|
1668 |
68340 |
sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1; |
|
1669 |
} |
||
1670 |
|||
1671 |
✗✓ | 68340 |
if (e == NULL) |
1672 |
goto done; |
||
1673 |
|||
1674 |
/* |
||
1675 |
* Parse decrypted payload |
||
1676 |
*/ |
||
1677 |
bzero(&emsg, sizeof(emsg)); |
||
1678 |
memcpy(&emsg, msg, sizeof(*msg)); |
||
1679 |
emsg.msg_data = e; |
||
1680 |
emsg.msg_e = 1; |
||
1681 |
emsg.msg_parent = msg; |
||
1682 |
TAILQ_INIT(&emsg.msg_proposals); |
||
1683 |
|||
1684 |
ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e), |
||
1685 |
pld->pld_nextpayload); |
||
1686 |
|||
1687 |
done: |
||
1688 |
68340 |
ibuf_release(e); |
|
1689 |
|||
1690 |
68340 |
return (ret); |
|
1691 |
68340 |
} |
|
1692 |
|||
1693 |
int |
||
1694 |
ikev2_validate_cp(struct iked_message *msg, size_t offset, size_t left, |
||
1695 |
struct ikev2_payload *pld, struct ikev2_cp *cp) |
||
1696 |
{ |
||
1697 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
1698 |
size_t pld_length; |
||
1699 |
|||
1700 |
pld_length = betoh16(pld->pld_length); |
||
1701 |
if (pld_length < sizeof(*pld) + sizeof(*cp)) { |
||
1702 |
log_debug("%s: malformed payload: specified length smaller " |
||
1703 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
1704 |
sizeof(*pld) + sizeof(*cp)); |
||
1705 |
return (-1); |
||
1706 |
} |
||
1707 |
|||
1708 |
/* This will actually be caught by earlier checks. */ |
||
1709 |
if (left < sizeof(*cp)) { |
||
1710 |
log_debug("%s: malformed payload: too short for header " |
||
1711 |
"(%zu < %zu)", __func__, left, sizeof(*cp)); |
||
1712 |
return (-1); |
||
1713 |
} |
||
1714 |
memcpy(cp, msgbuf + offset, sizeof(*cp)); |
||
1715 |
|||
1716 |
return (0); |
||
1717 |
} |
||
1718 |
|||
1719 |
int |
||
1720 |
ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld, |
||
1721 |
struct iked_message *msg, size_t offset, size_t left) |
||
1722 |
{ |
||
1723 |
struct ikev2_cp cp; |
||
1724 |
struct ikev2_cfg *cfg; |
||
1725 |
uint8_t *buf; |
||
1726 |
size_t len, i; |
||
1727 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
1728 |
struct iked_sa *sa = msg->msg_sa; |
||
1729 |
|||
1730 |
if (ikev2_validate_cp(msg, offset, left, pld, &cp)) |
||
1731 |
return (-1); |
||
1732 |
offset += sizeof(cp); |
||
1733 |
|||
1734 |
buf = msgbuf + offset; |
||
1735 |
len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cp); |
||
1736 |
|||
1737 |
log_debug("%s: type %s length %zu", |
||
1738 |
__func__, print_map(cp.cp_type, ikev2_cp_map), len); |
||
1739 |
print_hex(buf, 0, len); |
||
1740 |
|||
1741 |
for (i = 0; i < len;) { |
||
1742 |
cfg = (struct ikev2_cfg *)(buf + i); |
||
1743 |
|||
1744 |
log_debug("%s: %s 0x%04x length %d", __func__, |
||
1745 |
print_map(betoh16(cfg->cfg_type), ikev2_cfg_map), |
||
1746 |
betoh16(cfg->cfg_type), |
||
1747 |
betoh16(cfg->cfg_length)); |
||
1748 |
|||
1749 |
i += betoh16(cfg->cfg_length) + sizeof(*cfg); |
||
1750 |
} |
||
1751 |
|||
1752 |
if (!ikev2_msg_frompeer(msg)) |
||
1753 |
return (0); |
||
1754 |
|||
1755 |
if (sa) |
||
1756 |
sa->sa_cp = cp.cp_type; |
||
1757 |
|||
1758 |
return (0); |
||
1759 |
} |
||
1760 |
|||
1761 |
int |
||
1762 |
ikev2_validate_eap(struct iked_message *msg, size_t offset, size_t left, |
||
1763 |
struct ikev2_payload *pld, struct eap_header *hdr) |
||
1764 |
{ |
||
1765 |
uint8_t *msgbuf = ibuf_data(msg->msg_data); |
||
1766 |
size_t pld_length; |
||
1767 |
|||
1768 |
pld_length = betoh16(pld->pld_length); |
||
1769 |
if (pld_length < sizeof(*pld) + sizeof(*hdr)) { |
||
1770 |
log_debug("%s: malformed payload: specified length smaller " |
||
1771 |
"than minimum size (%zu < %zu)", __func__, pld_length, |
||
1772 |
sizeof(*pld) + sizeof(*hdr)); |
||
1773 |
return (-1); |
||
1774 |
} |
||
1775 |
|||
1776 |
/* This will actually be caught by earlier checks. */ |
||
1777 |
if (left < sizeof(*hdr)) { |
||
1778 |
log_debug("%s: malformed payload: too short for header " |
||
1779 |
"(%zu < %zu)", __func__, left, sizeof(*hdr)); |
||
1780 |
return (-1); |
||
1781 |
} |
||
1782 |
memcpy(hdr, msgbuf + offset, sizeof(*hdr)); |
||
1783 |
|||
1784 |
return (0); |
||
1785 |
} |
||
1786 |
|||
1787 |
int |
||
1788 |
ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld, |
||
1789 |
struct iked_message *msg, size_t offset, size_t left) |
||
1790 |
{ |
||
1791 |
struct eap_header hdr; |
||
1792 |
struct eap_message *eap = NULL; |
||
1793 |
struct iked_sa *sa = msg->msg_sa; |
||
1794 |
size_t len; |
||
1795 |
|||
1796 |
if (ikev2_validate_eap(msg, offset, left, pld, &hdr)) |
||
1797 |
return (-1); |
||
1798 |
len = betoh16(hdr.eap_length); |
||
1799 |
|||
1800 |
if (len < sizeof(*eap)) { |
||
1801 |
log_info("%s: %s id %d length %d", __func__, |
||
1802 |
print_map(hdr.eap_code, eap_code_map), |
||
1803 |
hdr.eap_id, betoh16(hdr.eap_length)); |
||
1804 |
} else { |
||
1805 |
/* Now try to get the indicated length */ |
||
1806 |
if ((eap = ibuf_seek(msg->msg_data, offset, len)) == NULL) { |
||
1807 |
log_debug("%s: invalid EAP length", __func__); |
||
1808 |
return (-1); |
||
1809 |
} |
||
1810 |
|||
1811 |
log_info("%s: %s id %d length %d EAP-%s", __func__, |
||
1812 |
print_map(eap->eap_code, eap_code_map), |
||
1813 |
eap->eap_id, betoh16(eap->eap_length), |
||
1814 |
print_map(eap->eap_type, eap_type_map)); |
||
1815 |
|||
1816 |
if (eap_parse(env, sa, eap, msg->msg_response) == -1) |
||
1817 |
return (-1); |
||
1818 |
} |
||
1819 |
|||
1820 |
return (0); |
||
1821 |
} |
Generated by: GCOVR (Version 3.3) |