File: | programs/pluto/ikev2.c |
Warning: | line 2905, column 8 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* demultiplex incoming IKE messages | |||
2 | * | |||
3 | * Copyright (C) 1997 Angelos D. Keromytis. | |||
4 | * Copyright (C) 1998-2010,2013-2017 D. Hugh Redelmeier <hugh@mimosa.com> | |||
5 | * Copyright (C) 2007-2008 Michael Richardson <mcr@xelerance.com> | |||
6 | * Copyright (C) 2009 David McCullough <david_mccullough@securecomputing.com> | |||
7 | * Copyright (C) 2008-2011 Paul Wouters <paul@xelerance.com> | |||
8 | * Copyright (C) 2010 Simon Deziel <simon@xelerance.com> | |||
9 | * Copyright (C) 2010 Tuomo Soini <tis@foobar.fi> | |||
10 | * Copyright (C) 2011-2012 Avesh Agarwal <avagarwa@redhat.com> | |||
11 | * Copyright (C) 2012 Paul Wouters <paul@libreswan.org> | |||
12 | * Copyright (C) 2012-2019 Paul Wouters <pwouters@redhat.com> | |||
13 | * Copyright (C) 2013 Matt Rogers <mrogers@redhat.com> | |||
14 | * Copyright (C) 2015-2019 Andrew Cagney | |||
15 | * Copyright (C) 2016-2018 Antony Antony <appu@phenome.org> | |||
16 | * Copyright (C) 2017 Sahana Prasad <sahana.prasad07@gmail.com> | |||
17 | * Copyright (C) 2020 Yulia Kuzovkova <ukuzovkova@gmail.com> | |||
18 | * Copyright (C) 2021 Paul Wouters <paul.wouters@aiven.io> | |||
19 | * | |||
20 | * This program is free software; you can redistribute it and/or modify it | |||
21 | * under the terms of the GNU General Public License as published by the | |||
22 | * Free Software Foundation; either version 2 of the License, or (at your | |||
23 | * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>. | |||
24 | * | |||
25 | * This program is distributed in the hope that it will be useful, but | |||
26 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |||
27 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
28 | * for more details. | |||
29 | * | |||
30 | */ | |||
31 | ||||
32 | #include <unistd.h> | |||
33 | #include <sys/types.h> | |||
34 | #include <sys/socket.h> | |||
35 | #include <netinet/in.h> | |||
36 | #include <arpa/inet.h> | |||
37 | ||||
38 | ||||
39 | #include "sysdep.h" | |||
40 | #include "constants.h" | |||
41 | ||||
42 | #include "defs.h" | |||
43 | #include "id.h" | |||
44 | #include "x509.h" | |||
45 | #include "pluto_x509.h" | |||
46 | #include "certs.h" | |||
47 | #include "connections.h" /* needs id.h */ | |||
48 | #include "state.h" | |||
49 | #include "packet.h" | |||
50 | #include "crypto.h" | |||
51 | #include "crypt_symkey.h" | |||
52 | #include "ike_alg.h" | |||
53 | #include "log.h" | |||
54 | #include "demux.h" /* needs packet.h */ | |||
55 | #include "ikev2.h" | |||
56 | #include "ipsec_doi.h" /* needs demux.h and state.h */ | |||
57 | #include "timer.h" | |||
58 | #include "whack.h" /* requires connections.h */ | |||
59 | #include "server.h" | |||
60 | #include "nat_traversal.h" | |||
61 | #include "vendor.h" | |||
62 | #include "ip_address.h" | |||
63 | #include "ikev2_send.h" | |||
64 | #include "state_db.h" | |||
65 | #include "ietf_constants.h" | |||
66 | #include "ikev2_cookie.h" | |||
67 | #include "plutoalg.h" /* for default_ike_groups */ | |||
68 | #include "ikev2_message.h" /* for ikev2_decrypt_msg() */ | |||
69 | #include "pluto_stats.h" | |||
70 | #include "keywords.h" | |||
71 | #include "ikev2_msgid.h" | |||
72 | #include "ikev2_redirect.h" | |||
73 | #include "ikev2_states.h" | |||
74 | #include "ip_endpoint.h" | |||
75 | #include "host_pair.h" /* for find_v2_host_connection() */ | |||
76 | #include "kernel.h" | |||
77 | #include "iface.h" | |||
78 | #include "ikev2_notify.h" | |||
79 | #include "unpack.h" | |||
80 | #include "pending.h" /* for release_pending_whacks() */ | |||
81 | #include "ikev2_host_pair.h" | |||
82 | #include "ikev2_ike_sa_init.h" | |||
83 | #include "ikev2_informational.h" | |||
84 | #include "ikev2_create_child_sa.h" | |||
85 | #include "ikev2_ike_intermediate.h" | |||
86 | #include "ikev2_ike_auth.h" | |||
87 | #include "ikev2_delete.h" /* for record_v2_delete() */ | |||
88 | #include "ikev2_child.h" /* for jam_v2_child_sa_details() */ | |||
89 | ||||
90 | /* | |||
91 | * IKEv2 has slightly different states than IKEv1. | |||
92 | * | |||
93 | * IKEv2 puts all the responsibility for retransmission on the end that | |||
94 | * wants to do something, usually, that the initiator. (But, not always | |||
95 | * the original initiator, of the responder decides it needs to rekey first) | |||
96 | * | |||
97 | * Each exchange has a bit that indicates if it is an Initiator message, | |||
98 | * or if it is a response. The Responder never retransmits its messages | |||
99 | * except in response to an Initiator retransmission. | |||
100 | * | |||
101 | * The message ID is *NOT* used in the cryptographic state at all, but instead | |||
102 | * serves the role of a sequence number. This makes the state machine far | |||
103 | * simpler, and there really are no exceptions. | |||
104 | * | |||
105 | * The upper level state machine is therefore much simpler. | |||
106 | * The lower level takes care of retransmissions, and the upper layer state | |||
107 | * machine just has to worry about whether it needs to go into cookie mode, | |||
108 | * etc. | |||
109 | * | |||
110 | * Like IKEv1, IKEv2 can have multiple child SAs. Like IKEv1, each one of | |||
111 | * the child SAs ("Phase 2") will get their own state. Unlike IKEv1, | |||
112 | * an implementation may negotiate multiple CHILD_SAs at the same time | |||
113 | * using different MessageIDs. This is enabled by an option (a notify) | |||
114 | * that the responder sends to the initiator. The initiator may only | |||
115 | * do concurrent negotiations if it sees the notify. | |||
116 | * | |||
117 | * XXX This implementation does not support concurrency, but it shouldn't be | |||
118 | * that hard to do. The most difficult part will be to map the message IDs | |||
119 | * to the right state. Some CHILD_SAs may take multiple round trips, | |||
120 | * and each one will have to be mapped to the same state. | |||
121 | * | |||
122 | * The IKEv2 state values are chosen from the same state space as IKEv1. | |||
123 | * | |||
124 | */ | |||
125 | ||||
126 | /* | |||
127 | * From RFC 5996 syntax: [optional] and {encrypted} | |||
128 | * | |||
129 | * Initiator Responder | |||
130 | * ------------------------------------------------------------------- | |||
131 | * | |||
132 | * IKE_SA_INIT exchange (initial exchange): | |||
133 | * | |||
134 | * HDR, SAi1, KEi, Ni --> | |||
135 | * <-- HDR, SAr1, KEr, Nr, [CERTREQ] | |||
136 | * | |||
137 | * IKE_AUTH exchange (after IKE_SA_INIT exchange): | |||
138 | * | |||
139 | * HDR, SK {IDi, [CERT,] [CERTREQ,] | |||
140 | * [IDr,] AUTH, SAi2, | |||
141 | * TSi, TSr} --> | |||
142 | * <-- HDR, SK {IDr, [CERT,] AUTH, | |||
143 | * SAr2, TSi, TSr} | |||
144 | * [Parent SA (SAx1) established. Child SA (SAx2) may have been established] | |||
145 | * | |||
146 | * | |||
147 | * Extended IKE_AUTH (see RFC 5996bis 2.6): | |||
148 | * | |||
149 | * HDR(A,0), SAi1, KEi, Ni --> | |||
150 | * <-- HDR(A,0), N(COOKIE) | |||
151 | * HDR(A,0), N(COOKIE), SAi1, | |||
152 | * KEi, Ni --> | |||
153 | * <-- HDR(A,B), SAr1, KEr, | |||
154 | * Nr, [CERTREQ] | |||
155 | * HDR(A,B), SK {IDi, [CERT,] | |||
156 | * [CERTREQ,] [IDr,] AUTH, | |||
157 | * SAi2, TSi, TSr} --> | |||
158 | * <-- HDR(A,B), SK {IDr, [CERT,] | |||
159 | * AUTH, SAr2, TSi, TSr} | |||
160 | * [Parent SA (SAx1) established. Child SA (SAx2) may have been established] | |||
161 | * | |||
162 | * | |||
163 | * CREATE_CHILD_SA Exchange (new child variant RFC 5996 1.3.1): | |||
164 | * | |||
165 | * HDR, SK {SA, Ni, [KEi], | |||
166 | * TSi, TSr} --> | |||
167 | * <-- HDR, SK {SA, Nr, [KEr], | |||
168 | * TSi, TSr} | |||
169 | * | |||
170 | * | |||
171 | * CREATE_CHILD_SA Exchange (rekey child variant RFC 5996 1.3.3): | |||
172 | * | |||
173 | * HDR, SK {N(REKEY_SA), SA, Ni, [KEi], | |||
174 | * TSi, TSr} --> | |||
175 | * <-- HDR, SK {SA, Nr, [KEr], | |||
176 | * TSi, TSr} | |||
177 | * | |||
178 | * | |||
179 | * CREATE_CHILD_SA Exchange (rekey parent SA variant RFC 5996 1.3.2): | |||
180 | * | |||
181 | * HDR, SK {SA, Ni, KEi} --> | |||
182 | * <-- HDR, SK {SA, Nr, KEr} | |||
183 | */ | |||
184 | ||||
185 | /* Short forms for building payload type sets */ | |||
186 | ||||
187 | #define P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)) LELEM(ISAKMP_NEXT_v2##N)((lset_t)1 << (ISAKMP_NEXT_v2##N)) | |||
188 | ||||
189 | /* | |||
190 | * IKEv2 State transitions (aka microcodes). | |||
191 | * | |||
192 | * This table contains all possible state transitions, some of which | |||
193 | * involve a message. | |||
194 | * | |||
195 | * During initialization this table parsed populating the | |||
196 | * corresponding IKEv2 finite states. While not the most efficient, | |||
197 | * it seems to work. | |||
198 | */ | |||
199 | ||||
200 | static /*const*/ struct v2_state_transition v2_state_transition_table[] = { | |||
201 | ||||
202 | #define req_clear_payloads message_payloads.required /* required unencrypted payloads (allows just one) for received packet */ | |||
203 | #define opt_clear_payloads message_payloads.optional /* optional unencrypted payloads (none or one) for received packet */ | |||
204 | #define req_enc_payloads encrypted_payloads.required /* required encrypted payloads (allows just one) for received packet */ | |||
205 | #define opt_enc_payloads encrypted_payloads.optional /* optional encrypted payloads (none or one) for received packet */ | |||
206 | ||||
207 | /* no state: --> I1 | |||
208 | * HDR, SAi1, KEi, Ni --> | |||
209 | */ | |||
210 | { .story = "initiate IKE_SA_INIT", | |||
211 | .state = STATE_V2_PARENT_I0, | |||
212 | .next_state = STATE_V2_PARENT_I1, | |||
213 | .send = MESSAGE_REQUEST, | |||
214 | .processor = NULL((void*)0), | |||
215 | .timeout_event = EVENT_RETRANSMIT, }, | |||
216 | ||||
217 | /* STATE_V2_PARENT_I1: R1B --> I1B | |||
218 | * <-- HDR, N | |||
219 | * HDR, N, SAi1, KEi, Ni --> | |||
220 | */ | |||
221 | ||||
222 | { .story = "received anti-DDOS COOKIE notify response; resending IKE_SA_INIT request with cookie payload added", | |||
223 | .state = STATE_V2_PARENT_I1, | |||
224 | .next_state = STATE_V2_PARENT_I0, | |||
225 | .flags = SMF2_SUPPRESS_SUCCESS_LOG, | |||
226 | .send = NO_MESSAGE, | |||
227 | .message_payloads = { .required = P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)), .notification = v2N_COOKIE, }, | |||
228 | .processor = ikev2_in_IKE_SA_INIT_R_v2N_COOKIE, | |||
229 | .recv_role = MESSAGE_RESPONSE, | |||
230 | .recv_type = ISAKMP_v2_IKE_SA_INIT, | |||
231 | .timeout_event = EVENT_SA_DISCARD, }, | |||
232 | ||||
233 | { .story = "received IKE_SA_INIT INVALID_KE_PAYLOAD notify response; resending IKE_SA_INIT with new KE payload", | |||
234 | .state = STATE_V2_PARENT_I1, | |||
235 | .next_state = STATE_V2_PARENT_I0, | |||
236 | .flags = SMF2_SUPPRESS_SUCCESS_LOG, | |||
237 | .send = NO_MESSAGE, | |||
238 | .message_payloads = { .required = P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)), .notification = v2N_INVALID_KE_PAYLOAD, }, | |||
239 | .processor = process_v2_IKE_SA_INIT_response_v2N_INVALID_KE_PAYLOAD, | |||
240 | .recv_role = MESSAGE_RESPONSE, | |||
241 | .recv_type = ISAKMP_v2_IKE_SA_INIT, | |||
242 | .timeout_event = EVENT_SA_DISCARD, }, | |||
243 | ||||
244 | { .story = "received REDIRECT notify response; resending IKE_SA_INIT request to new destination", | |||
245 | .state = STATE_V2_PARENT_I1, | |||
246 | .next_state = STATE_V2_IKE_SA_DELETE, | |||
247 | .flags = SMF2_SUPPRESS_SUCCESS_LOG, | |||
248 | .send = NO_MESSAGE, | |||
249 | .message_payloads = { .required = P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)), .notification = v2N_REDIRECT, }, | |||
250 | .processor = ikev2_in_IKE_SA_INIT_R_v2N_REDIRECT, | |||
251 | .recv_role = MESSAGE_RESPONSE, | |||
252 | .recv_type = ISAKMP_v2_IKE_SA_INIT, | |||
253 | /* XXX: this is an instant timeout */ | |||
254 | .timeout_event = EVENT_v2_REDIRECT, | |||
255 | }, | |||
256 | ||||
257 | /* STATE_V2_PARENT_I1: R1 --> I2 | |||
258 | * <-- HDR, SAr1, KEr, Nr, [CERTREQ] | |||
259 | * HDR, SK {IDi, [CERT,] [CERTREQ,] | |||
260 | * [IDr,] AUTH, SAi2, | |||
261 | * TSi, TSr} --> | |||
262 | */ | |||
263 | { .story = "Initiator: process IKE_SA_INIT reply, initiate IKE_AUTH or IKE_INTERMEDIATE", | |||
264 | .state = STATE_V2_PARENT_I1, | |||
265 | .next_state = STATE_V2_PARENT_I2, | |||
266 | .send = MESSAGE_REQUEST, | |||
267 | .req_clear_payloads = P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(KE)((lset_t)1 << (ISAKMP_NEXT_v2KE)) | P(Nr)((lset_t)1 << (ISAKMP_NEXT_v2Nr)), | |||
268 | .opt_clear_payloads = P(CERTREQ)((lset_t)1 << (ISAKMP_NEXT_v2CERTREQ)), | |||
269 | .processor = process_v2_IKE_SA_INIT_response, | |||
270 | .recv_role = MESSAGE_RESPONSE, | |||
271 | .recv_type = ISAKMP_v2_IKE_SA_INIT, | |||
272 | .timeout_event = EVENT_RETRANSMIT, }, | |||
273 | ||||
274 | { .story = "Initiator: process IKE_INTERMEDIATE reply, initiate IKE_AUTH or IKE_INTERMEDIATE", | |||
275 | .state = STATE_V2_PARENT_I2, | |||
276 | .next_state = STATE_V2_PARENT_I2, | |||
277 | .flags = MESSAGE_RESPONSE, | |||
278 | .send = MESSAGE_REQUEST, | |||
279 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
280 | .opt_clear_payloads = LEMPTY((lset_t)0), | |||
281 | .processor = process_v2_IKE_INTERMEDIATE_response, | |||
282 | .recv_role = MESSAGE_RESPONSE, | |||
283 | .recv_type = ISAKMP_v2_IKE_INTERMEDIATE, | |||
284 | .timeout_event = EVENT_RETRANSMIT, }, | |||
285 | ||||
286 | /* STATE_V2_PARENT_I2: R2 --> | |||
287 | * <-- HDR, SK {IDr, [CERT,] AUTH, | |||
288 | * SAr2, TSi, TSr} | |||
289 | * [Parent SA established] | |||
290 | */ | |||
291 | ||||
292 | /* | |||
293 | * This pair of state transitions should be merged? | |||
294 | */ | |||
295 | { .story = "Initiator: process IKE_AUTH response", | |||
296 | .state = STATE_V2_PARENT_I2, | |||
297 | .next_state = STATE_V2_ESTABLISHED_IKE_SA, | |||
298 | /* logged mid transition */ | |||
299 | .flags = SMF2_SUPPRESS_SUCCESS_LOG|SMF2_RELEASE_WHACK, | |||
300 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
301 | .req_enc_payloads = P(IDr)((lset_t)1 << (ISAKMP_NEXT_v2IDr)) | P(AUTH)((lset_t)1 << (ISAKMP_NEXT_v2AUTH)), | |||
302 | .opt_enc_payloads = P(CERT)((lset_t)1 << (ISAKMP_NEXT_v2CERT)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)) | P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(TSi)((lset_t)1 << (ISAKMP_NEXT_v2TSi)) | P(TSr)((lset_t)1 << (ISAKMP_NEXT_v2TSr)), | |||
303 | .processor = process_v2_IKE_AUTH_response, | |||
304 | .recv_role = MESSAGE_RESPONSE, | |||
305 | .recv_type = ISAKMP_v2_IKE_AUTH, | |||
306 | .timeout_event = EVENT_SA_REPLACE, | |||
307 | }, | |||
308 | ||||
309 | { .story = "Initiator: processing IKE_AUTH failure response", | |||
310 | .state = STATE_V2_PARENT_I2, | |||
311 | .next_state = STATE_V2_PARENT_I2, | |||
312 | .message_payloads = { .required = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), }, | |||
313 | /* .encrypted_payloads = { .required = P(N), }, */ | |||
314 | .processor = process_v2_IKE_AUTH_failure_response, | |||
315 | .recv_role = MESSAGE_RESPONSE, | |||
316 | .recv_type = ISAKMP_v2_IKE_AUTH, | |||
317 | }, | |||
318 | ||||
319 | /* no state: none I1 --> R1 | |||
320 | * <-- HDR, SAi1, KEi, Ni | |||
321 | * HDR, SAr1, KEr, Nr, [CERTREQ] --> | |||
322 | */ | |||
323 | { .story = "Respond to IKE_SA_INIT", | |||
324 | .state = STATE_V2_PARENT_R0, | |||
325 | .next_state = STATE_V2_PARENT_R1, | |||
326 | .send = MESSAGE_RESPONSE, | |||
327 | .req_clear_payloads = P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(KE)((lset_t)1 << (ISAKMP_NEXT_v2KE)) | P(Ni)((lset_t)1 << (ISAKMP_NEXT_v2Ni)), | |||
328 | .processor = process_v2_IKE_SA_INIT_request, | |||
329 | .recv_role = MESSAGE_REQUEST, | |||
330 | .recv_type = ISAKMP_v2_IKE_SA_INIT, | |||
331 | .timeout_event = EVENT_SA_DISCARD, }, | |||
332 | ||||
333 | /* STATE_V2_PARENT_R1: I2 --> R2 | |||
334 | * <-- HDR, SK {IDi, [CERT,] [CERTREQ,] | |||
335 | * [IDr,] AUTH, SAi2, | |||
336 | * TSi, TSr} | |||
337 | * HDR, SK {IDr, [CERT,] AUTH, | |||
338 | * SAr2, TSi, TSr} --> | |||
339 | * | |||
340 | * [Parent SA established] | |||
341 | */ | |||
342 | { .story = "Responder: process IKE_AUTH request (no SKEYSEED)", | |||
343 | .state = STATE_V2_PARENT_R1, | |||
344 | .next_state = STATE_V2_PARENT_R1, | |||
345 | .flags = SMF2_NO_SKEYSEED, | |||
346 | .send = MESSAGE_RESPONSE, | |||
347 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
348 | .req_enc_payloads = LEMPTY((lset_t)0), | |||
349 | .opt_enc_payloads = LEMPTY((lset_t)0), | |||
350 | .processor = process_v2_IKE_AUTH_request_no_skeyseed, | |||
351 | .recv_role = MESSAGE_REQUEST, | |||
352 | .recv_type = ISAKMP_v2_IKE_AUTH, | |||
353 | .timeout_event = EVENT_SA_DISCARD, }, | |||
354 | ||||
355 | { .story = "Responder: process IKE_INTERMEDIATE request (no SKEYSEED)", | |||
356 | .state = STATE_V2_PARENT_R1, | |||
357 | .next_state = STATE_V2_PARENT_R1, | |||
358 | .flags = MESSAGE_REQUEST | SMF2_NO_SKEYSEED, | |||
359 | .send = MESSAGE_RESPONSE, | |||
360 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
361 | .req_enc_payloads = LEMPTY((lset_t)0), | |||
362 | .opt_enc_payloads = LEMPTY((lset_t)0), | |||
363 | .processor = process_v2_IKE_INTERMEDIATE_request_no_skeyseed, | |||
364 | .recv_role = MESSAGE_REQUEST, | |||
365 | .recv_type = ISAKMP_v2_IKE_INTERMEDIATE, | |||
366 | .timeout_event = EVENT_SA_DISCARD, }, | |||
367 | ||||
368 | { .story = "Responder: process IKE_INTERMEDIATE request (with SKEYSEED)", | |||
369 | .state = STATE_V2_PARENT_R1, | |||
370 | .next_state = STATE_V2_PARENT_R1, | |||
371 | .flags = MESSAGE_REQUEST, | |||
372 | .send = MESSAGE_RESPONSE, | |||
373 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
374 | .req_enc_payloads = LEMPTY((lset_t)0), | |||
375 | .opt_enc_payloads = LEMPTY((lset_t)0), | |||
376 | .processor = process_v2_IKE_INTERMEDIATE_request, | |||
377 | .recv_role = MESSAGE_REQUEST, | |||
378 | .recv_type = ISAKMP_v2_IKE_INTERMEDIATE, | |||
379 | .timeout_event = EVENT_SA_DISCARD, }, | |||
380 | ||||
381 | /* | |||
382 | * These two transitions should be merged; the no-child | |||
383 | * variant is just so that the code can be hobbled. | |||
384 | */ | |||
385 | ||||
386 | { .story = "Responder: process IKE_AUTH request", | |||
387 | .state = STATE_V2_PARENT_R1, | |||
388 | .next_state = STATE_V2_ESTABLISHED_IKE_SA, | |||
389 | .flags = SMF2_SUPPRESS_SUCCESS_LOG|SMF2_RELEASE_WHACK, | |||
390 | .send = MESSAGE_RESPONSE, | |||
391 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
392 | .req_enc_payloads = P(IDi)((lset_t)1 << (ISAKMP_NEXT_v2IDi)) | P(AUTH)((lset_t)1 << (ISAKMP_NEXT_v2AUTH)), | |||
393 | .opt_enc_payloads = P(CERT)((lset_t)1 << (ISAKMP_NEXT_v2CERT)) | P(CERTREQ)((lset_t)1 << (ISAKMP_NEXT_v2CERTREQ)) | P(IDr)((lset_t)1 << (ISAKMP_NEXT_v2IDr)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)) | P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(TSi)((lset_t)1 << (ISAKMP_NEXT_v2TSi)) | P(TSr)((lset_t)1 << (ISAKMP_NEXT_v2TSr)), | |||
394 | .processor = process_v2_IKE_AUTH_request, | |||
395 | .recv_role = MESSAGE_REQUEST, | |||
396 | .recv_type = ISAKMP_v2_IKE_AUTH, | |||
397 | .timeout_event = EVENT_SA_REPLACE, }, | |||
398 | ||||
399 | /* | |||
400 | * There are three different CREATE_CHILD_SA's invocations, | |||
401 | * this is the combined write up (not in RFC). See above for | |||
402 | * individual cases from RFC. | |||
403 | * | |||
404 | * The order that they rekey here matters. | |||
405 | * | |||
406 | * HDR, SK {SA, Ni, [KEi], [N(REKEY_SA)], [TSi, TSr]} --> | |||
407 | * <-- HDR, SK {N} | |||
408 | * <-- HDR, SK {SA, Nr, [KEr], [TSi, TSr]} | |||
409 | */ | |||
410 | ||||
411 | /* | |||
412 | * CREATE_CHILD_SA exchange to rekey IKE SA. | |||
413 | * | |||
414 | * In the responder, note the lack of TS (traffic selectors) | |||
415 | * payload. Since rekey and create child exchanges contain TS | |||
416 | * they won't match. | |||
417 | */ | |||
418 | ||||
419 | /* no state: --> CREATE_CHILD IKE Rekey Request | |||
420 | * HDR, SAi, KEi, Ni --> | |||
421 | */ | |||
422 | ||||
423 | { .story = "initiate rekey IKE_SA (CREATE_CHILD_SA)", | |||
424 | .state = STATE_V2_REKEY_IKE_I0, | |||
425 | .next_state = STATE_V2_REKEY_IKE_I1, | |||
426 | .send = MESSAGE_REQUEST, | |||
427 | .processor = initiate_v2_CREATE_CHILD_SA_rekey_ike_request, | |||
428 | .timeout_event = EVENT_RETRANSMIT, }, | |||
429 | ||||
430 | { .story = "process rekey IKE SA request (CREATE_CHILD_SA)", | |||
431 | .state = STATE_V2_REKEY_IKE_R0, | |||
432 | .next_state = STATE_V2_ESTABLISHED_IKE_SA, | |||
433 | .send = MESSAGE_RESPONSE, | |||
434 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
435 | .req_enc_payloads = P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(Ni)((lset_t)1 << (ISAKMP_NEXT_v2Ni)) | P(KE)((lset_t)1 << (ISAKMP_NEXT_v2KE)), | |||
436 | .opt_enc_payloads = P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)), | |||
437 | .processor = process_v2_CREATE_CHILD_SA_rekey_ike_request, | |||
438 | .recv_role = MESSAGE_REQUEST, | |||
439 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
440 | .timeout_event = EVENT_SA_REPLACE }, | |||
441 | ||||
442 | { .story = "process rekey IKE SA response (CREATE_CHILD_SA)", | |||
443 | .state = STATE_V2_REKEY_IKE_I1, | |||
444 | .next_state = STATE_V2_ESTABLISHED_IKE_SA, | |||
445 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
446 | .req_enc_payloads = P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(Ni)((lset_t)1 << (ISAKMP_NEXT_v2Ni)) | P(KE)((lset_t)1 << (ISAKMP_NEXT_v2KE)), | |||
447 | .opt_enc_payloads = P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)), | |||
448 | .processor = process_v2_CREATE_CHILD_SA_rekey_ike_response, | |||
449 | .recv_role = MESSAGE_RESPONSE, | |||
450 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
451 | .timeout_event = EVENT_SA_REPLACE, }, | |||
452 | ||||
453 | { .story = "process rekey IKE SA failure response (CREATE_CHILD_SA)", | |||
454 | .state = STATE_V2_REKEY_IKE_I1, | |||
455 | .next_state = STATE_V2_CHILD_SA_DELETE, /* never reached */ | |||
456 | .flags = SMF2_RELEASE_WHACK, | |||
457 | .message_payloads = { .required = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), }, | |||
458 | .processor = process_v2_CREATE_CHILD_SA_failure_response, | |||
459 | .recv_role = MESSAGE_RESPONSE, | |||
460 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
461 | .timeout_event = EVENT_RETAIN, /* no timeout really */ | |||
462 | }, | |||
463 | ||||
464 | /* | |||
465 | * CREATE_CHILD_SA exchange to rekey existing child. | |||
466 | * | |||
467 | * In the responder, note the presence of both TS (traffic | |||
468 | * selectors) payload and REKEY_SA notification. Since a | |||
469 | * create child does not include the REKEY_SA notify it won't | |||
470 | * match. | |||
471 | */ | |||
472 | ||||
473 | { .story = "initiate rekey Child SA (CREATE_CHILD_SA)", | |||
474 | .state = STATE_V2_REKEY_CHILD_I0, | |||
475 | .next_state = STATE_V2_REKEY_CHILD_I1, | |||
476 | .send = MESSAGE_REQUEST, | |||
477 | .processor = initiate_v2_CREATE_CHILD_SA_rekey_child_request, | |||
478 | .timeout_event = EVENT_RETRANSMIT, }, | |||
479 | ||||
480 | { .story = "process rekey Child SA request (CREATE_CHILD_SA)", | |||
481 | .state = STATE_V2_REKEY_CHILD_R0, | |||
482 | .next_state = STATE_V2_ESTABLISHED_CHILD_SA, | |||
483 | .flags = SMF2_RELEASE_WHACK, | |||
484 | .send = MESSAGE_RESPONSE, | |||
485 | .message_payloads.required = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
486 | .encrypted_payloads.required = P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(Ni)((lset_t)1 << (ISAKMP_NEXT_v2Ni)) | P(TSi)((lset_t)1 << (ISAKMP_NEXT_v2TSi)) | P(TSr)((lset_t)1 << (ISAKMP_NEXT_v2TSr)), | |||
487 | .encrypted_payloads.optional = P(KE)((lset_t)1 << (ISAKMP_NEXT_v2KE)) | P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)), | |||
488 | .encrypted_payloads.notification = v2N_REKEY_SA, | |||
489 | .processor = process_v2_CREATE_CHILD_SA_rekey_child_request, | |||
490 | .recv_role = MESSAGE_REQUEST, | |||
491 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
492 | .timeout_event = EVENT_SA_REPLACE, }, | |||
493 | ||||
494 | { .story = "process rekey Child SA response (CREATE_CHILD_SA)", | |||
495 | .state = STATE_V2_REKEY_CHILD_I1, | |||
496 | .next_state = STATE_V2_ESTABLISHED_CHILD_SA, | |||
497 | .flags = SMF2_RELEASE_WHACK, | |||
498 | .message_payloads.required = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
499 | .encrypted_payloads.required = P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(Ni)((lset_t)1 << (ISAKMP_NEXT_v2Ni)) | P(TSi)((lset_t)1 << (ISAKMP_NEXT_v2TSi)) | P(TSr)((lset_t)1 << (ISAKMP_NEXT_v2TSr)), | |||
500 | .encrypted_payloads.optional = P(KE)((lset_t)1 << (ISAKMP_NEXT_v2KE)) | P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)), | |||
501 | .processor = process_v2_CREATE_CHILD_SA_rekey_child_response, | |||
502 | .recv_role = MESSAGE_RESPONSE, | |||
503 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
504 | .timeout_event = EVENT_SA_REPLACE, }, | |||
505 | ||||
506 | { .story = "process rekey Child SA failure response (CREATE_CHILD_SA)", | |||
507 | .state = STATE_V2_REKEY_CHILD_I1, | |||
508 | .next_state = STATE_V2_CHILD_SA_DELETE, /* never reached */ | |||
509 | .flags = SMF2_RELEASE_WHACK, | |||
510 | .message_payloads = { .required = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), }, | |||
511 | .processor = process_v2_CREATE_CHILD_SA_failure_response, | |||
512 | .recv_role = MESSAGE_RESPONSE, | |||
513 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
514 | .timeout_event = EVENT_RETAIN, /* no timeout really */ | |||
515 | }, | |||
516 | ||||
517 | /* | |||
518 | * CREATE_CHILD_SA exchange to create a new child. | |||
519 | * | |||
520 | * In the responder note the presence of just TS (traffic | |||
521 | * selectors) payloads. Earlier rules will have weeded out | |||
522 | * both rekey IKE (no TS payload) and rekey Child (has | |||
523 | * REKEY_SA notify) leaving just create new child. | |||
524 | */ | |||
525 | ||||
526 | { .story = "initiate create Child SA (CREATE_CHILD_SA)", | |||
527 | .state = STATE_V2_NEW_CHILD_I0, | |||
528 | .next_state = STATE_V2_NEW_CHILD_I1, | |||
529 | .send = MESSAGE_REQUEST, | |||
530 | .processor = initiate_v2_CREATE_CHILD_SA_new_child_request, | |||
531 | .timeout_event = EVENT_RETRANSMIT, }, | |||
532 | ||||
533 | { .story = "process create Child SA request (CREATE_CHILD_SA)", | |||
534 | .state = STATE_V2_NEW_CHILD_R0, | |||
535 | .next_state = STATE_V2_ESTABLISHED_CHILD_SA, | |||
536 | .flags = SMF2_RELEASE_WHACK, | |||
537 | .send = MESSAGE_RESPONSE, | |||
538 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
539 | .req_enc_payloads = P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(Ni)((lset_t)1 << (ISAKMP_NEXT_v2Ni)) | P(TSi)((lset_t)1 << (ISAKMP_NEXT_v2TSi)) | P(TSr)((lset_t)1 << (ISAKMP_NEXT_v2TSr)), | |||
540 | .opt_enc_payloads = P(KE)((lset_t)1 << (ISAKMP_NEXT_v2KE)) | P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)), | |||
541 | .processor = process_v2_CREATE_CHILD_SA_new_child_request, | |||
542 | .recv_role = MESSAGE_REQUEST, | |||
543 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
544 | .timeout_event = EVENT_SA_REPLACE, }, | |||
545 | ||||
546 | { .story = "process create Child SA response (CREATE_CHILD_SA)", | |||
547 | .state = STATE_V2_NEW_CHILD_I1, | |||
548 | .next_state = STATE_V2_ESTABLISHED_CHILD_SA, | |||
549 | .flags = SMF2_RELEASE_WHACK, | |||
550 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
551 | .req_enc_payloads = P(SA)((lset_t)1 << (ISAKMP_NEXT_v2SA)) | P(Ni)((lset_t)1 << (ISAKMP_NEXT_v2Ni)) | P(TSi)((lset_t)1 << (ISAKMP_NEXT_v2TSi)) | P(TSr)((lset_t)1 << (ISAKMP_NEXT_v2TSr)), | |||
552 | .opt_enc_payloads = P(KE)((lset_t)1 << (ISAKMP_NEXT_v2KE)) | P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)), | |||
553 | .processor = process_v2_CREATE_CHILD_SA_new_child_response, | |||
554 | .recv_role = MESSAGE_RESPONSE, | |||
555 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
556 | .timeout_event = EVENT_SA_REPLACE, }, | |||
557 | ||||
558 | { .story = "process create Child SA failure response (CREATE_CHILD_SA)", | |||
559 | .state = STATE_V2_NEW_CHILD_I1, | |||
560 | .next_state = STATE_V2_CHILD_SA_DELETE, /* never reached */ | |||
561 | .flags = SMF2_RELEASE_WHACK, | |||
562 | .message_payloads = { .required = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), }, | |||
563 | .processor = process_v2_CREATE_CHILD_SA_failure_response, | |||
564 | .recv_role = MESSAGE_RESPONSE, | |||
565 | .recv_type = ISAKMP_v2_CREATE_CHILD_SA, | |||
566 | .timeout_event = EVENT_RETAIN, /* no timeout really */ | |||
567 | }, | |||
568 | ||||
569 | /* Informational Exchange */ | |||
570 | ||||
571 | /* RFC 5996 1.4 "The INFORMATIONAL Exchange" | |||
572 | * | |||
573 | * HDR, SK {[N,] [D,] [CP,] ...} --> | |||
574 | * <-- HDR, SK {[N,] [D,] [CP], ...} | |||
575 | * | |||
576 | * A liveness exchange is a special empty message. | |||
577 | * | |||
578 | * XXX: since these just generate an empty response, they | |||
579 | * might as well have a dedicated liveness function. | |||
580 | * | |||
581 | * XXX: rather than all this transition duplication, the | |||
582 | * established states should share common transition stored | |||
583 | * outside of this table. | |||
584 | */ | |||
585 | ||||
586 | { .story = "Informational Request (liveness probe)", | |||
587 | .state = STATE_V2_ESTABLISHED_IKE_SA, | |||
588 | .next_state = STATE_V2_ESTABLISHED_IKE_SA, | |||
589 | .flags = SMF2_SUPPRESS_SUCCESS_LOG, | |||
590 | .send = MESSAGE_RESPONSE, | |||
591 | .message_payloads.required = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
592 | .processor = process_v2_INFORMATIONAL_request, | |||
593 | .recv_role = MESSAGE_REQUEST, | |||
594 | .recv_type = ISAKMP_v2_INFORMATIONAL, | |||
595 | .timeout_event = EVENT_RETAIN, }, | |||
596 | ||||
597 | { .story = "Informational Response (liveness probe)", | |||
598 | .state = STATE_V2_ESTABLISHED_IKE_SA, | |||
599 | .next_state = STATE_V2_ESTABLISHED_IKE_SA, | |||
600 | .flags = SMF2_SUPPRESS_SUCCESS_LOG|SMF2_RELEASE_WHACK, | |||
601 | .message_payloads.required = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
602 | .processor = process_v2_INFORMATIONAL_response, | |||
603 | .recv_role = MESSAGE_RESPONSE, | |||
604 | .recv_type = ISAKMP_v2_INFORMATIONAL, | |||
605 | .timeout_event = EVENT_RETAIN, }, | |||
606 | ||||
607 | { .story = "Informational Request", | |||
608 | .state = STATE_V2_ESTABLISHED_IKE_SA, | |||
609 | .next_state = STATE_V2_ESTABLISHED_IKE_SA, | |||
610 | .send = MESSAGE_RESPONSE, | |||
611 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
612 | .opt_enc_payloads = P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)) | P(D)((lset_t)1 << (ISAKMP_NEXT_v2D)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)), | |||
613 | .processor = process_v2_INFORMATIONAL_request, | |||
614 | .recv_role = MESSAGE_REQUEST, | |||
615 | .recv_type = ISAKMP_v2_INFORMATIONAL, | |||
616 | .timeout_event = EVENT_RETAIN, }, | |||
617 | ||||
618 | { .story = "Informational Response", | |||
619 | .state = STATE_V2_ESTABLISHED_IKE_SA, | |||
620 | .recv_type = ISAKMP_v2_INFORMATIONAL, | |||
621 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
622 | .opt_enc_payloads = P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)) | P(D)((lset_t)1 << (ISAKMP_NEXT_v2D)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)), | |||
623 | .processor = process_v2_INFORMATIONAL_response, | |||
624 | .next_state = STATE_V2_ESTABLISHED_IKE_SA, | |||
625 | .recv_role = MESSAGE_RESPONSE, | |||
626 | .timeout_event = EVENT_RETAIN, }, | |||
627 | ||||
628 | { .story = "IKE_SA_DEL: process INFORMATIONAL response", | |||
629 | .state = STATE_V2_IKE_SA_DELETE, | |||
630 | .next_state = STATE_V2_IKE_SA_DELETE, | |||
631 | .flags = 0, | |||
632 | .req_clear_payloads = P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)), | |||
633 | .opt_enc_payloads = P(N)((lset_t)1 << (ISAKMP_NEXT_v2N)) | P(D)((lset_t)1 << (ISAKMP_NEXT_v2D)) | P(CP)((lset_t)1 << (ISAKMP_NEXT_v2CP)), | |||
634 | .processor = IKE_SA_DEL_process_v2_INFORMATIONAL_response, | |||
635 | .recv_role = MESSAGE_RESPONSE, | |||
636 | .recv_type = ISAKMP_v2_INFORMATIONAL, | |||
637 | .timeout_event = EVENT_RETAIN, }, | |||
638 | ||||
639 | /* last entry */ | |||
640 | { .story = "roof", | |||
641 | .state = STATE_IKEv2_ROOF } | |||
642 | ||||
643 | #undef req_clear_payloads | |||
644 | #undef opt_clear_payloads | |||
645 | #undef req_enc_payloads | |||
646 | #undef opt_enc_payloads | |||
647 | ||||
648 | }; | |||
649 | ||||
650 | void init_ikev2(void) | |||
651 | { | |||
652 | dbg("checking IKEv2 state table"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("checking IKEv2 state table"); } }; | |||
653 | ||||
654 | /* | |||
655 | * Fill in FINITE_STATES[]. | |||
656 | * | |||
657 | * This is a hack until each finite-state is a separate object | |||
658 | * with corresponding edges (aka microcodes). | |||
659 | * | |||
660 | * XXX: Long term goal is to have a constant FINITE_STATES[] | |||
661 | * contain constant pointers and this static writeable array | |||
662 | * to just go away. | |||
663 | */ | |||
664 | for (enum state_kind kind = STATE_IKEv2_FLOOR; kind < STATE_IKEv2_ROOF; kind++) { | |||
665 | /* fill in using static struct */ | |||
666 | const struct finite_state *fs = &v2_states[kind - STATE_IKEv2_FLOOR]; | |||
667 | passert(fs->kind == kind)({ _Bool assertion__ = fs->kind == kind; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 667, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "fs->kind == kind"); } (void) 1; }); | |||
668 | passert(finite_states[kind] == NULL)({ _Bool assertion__ = finite_states[kind] == ((void*)0); if ( !assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 668, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_passert(logger_, here, "%s", "finite_states[kind] == ((void*)0)" ); } (void) 1; }); | |||
669 | finite_states[kind] = fs; | |||
670 | } | |||
671 | ||||
672 | /* | |||
673 | * Iterate over the state transitions filling in missing bits | |||
674 | * and checking for consistency. | |||
675 | */ | |||
676 | for (struct v2_state_transition *t = v2_state_transition_table; | |||
677 | t->state < STATE_IKEv2_ROOF; t++) { | |||
678 | ||||
679 | passert(t->state >= STATE_IKEv2_FLOOR)({ _Bool assertion__ = t->state >= STATE_IKEv2_FLOOR; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 679, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "t->state >= STATE_IKEv2_FLOOR" ); } (void) 1; }); | |||
680 | passert(t->state < STATE_IKEv2_ROOF)({ _Bool assertion__ = t->state < STATE_IKEv2_ROOF; if ( !assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 680, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_passert(logger_, here, "%s", "t->state < STATE_IKEv2_ROOF" ); } (void) 1; }); | |||
681 | struct finite_state *from = &v2_states[t->state - STATE_IKEv2_FLOOR]; | |||
682 | ||||
683 | passert(t->next_state >= STATE_IKEv2_FLOOR)({ _Bool assertion__ = t->next_state >= STATE_IKEv2_FLOOR ; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 683, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "t->next_state >= STATE_IKEv2_FLOOR" ); } (void) 1; }); | |||
684 | passert(t->next_state < STATE_IKEv2_ROOF)({ _Bool assertion__ = t->next_state < STATE_IKEv2_ROOF ; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 684, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "t->next_state < STATE_IKEv2_ROOF" ); } (void) 1; }); | |||
685 | const struct finite_state *to = finite_states[t->next_state]; | |||
686 | passert(to != NULL)({ _Bool assertion__ = to != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 686, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "to != ((void*)0)"); } (void) 1; }); | |||
687 | ||||
688 | if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { | |||
689 | if (from->nr_transitions == 0) { | |||
690 | LSWLOG_DEBUG(buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf ; buf != ((void*)0); buf = ((void*)0)) for (; buf != ((void*) 0); jambuf_to_logger(buf, &failsafe_logger, DEBUG_STREAM) , buf = ((void*)0)) { | |||
691 | jam(buf, " "); | |||
692 | lswlog_finite_state(buf, from); | |||
693 | jam(buf, ":"); | |||
694 | } | |||
695 | } | |||
696 | const char *send; | |||
697 | switch (t->send) { | |||
698 | case NO_MESSAGE: send = ""; break; | |||
699 | case MESSAGE_REQUEST: send = " send-request"; break; | |||
700 | case MESSAGE_RESPONSE: send = " send-response"; break; | |||
701 | default: bad_case(t->send)libreswan_bad_case("t->send", (t->send), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 701, }; &here; })); | |||
702 | } | |||
703 | DBG_log(" -> %s %s%s (%s)", to->short_name, | |||
704 | enum_name_short(&event_type_names, | |||
705 | t->timeout_event), | |||
706 | send, t->story); | |||
707 | } | |||
708 | ||||
709 | /* | |||
710 | * Check that the NOTIFY -> PBS -> MD.pbs[]!=NULL will work. | |||
711 | */ | |||
712 | if (t->message_payloads.notification != v2N_NOTHING_WRONG) { | |||
713 | pexpect(v2_pd_from_notification(t->message_payloads.notification) != PD_v2_INVALID)({ _Bool assertion__ = v2_pd_from_notification(t->message_payloads .notification) != PD_v2_INVALID; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 713, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect( logger_, here_, "%s", "v2_pd_from_notification(t->message_payloads.notification) != PD_v2_INVALID" ); } assertion__; }); | |||
714 | } | |||
715 | if (t->encrypted_payloads.notification != v2N_NOTHING_WRONG) { | |||
716 | pexpect(v2_pd_from_notification(t->encrypted_payloads.notification) != PD_v2_INVALID)({ _Bool assertion__ = v2_pd_from_notification(t->encrypted_payloads .notification) != PD_v2_INVALID; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 716, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect( logger_, here_, "%s", "v2_pd_from_notification(t->encrypted_payloads.notification) != PD_v2_INVALID" ); } assertion__; }); | |||
717 | } | |||
718 | ||||
719 | /* | |||
720 | * Check recv:MESSAGE_REQUEST->send:MESSAGE_RESPONSE. | |||
721 | */ | |||
722 | pexpect(t->recv_role == MESSAGE_REQUEST ? t->send = MESSAGE_RESPONSE : true)({ _Bool assertion__ = t->recv_role == MESSAGE_REQUEST ? t ->send = MESSAGE_RESPONSE : 1; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 722, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect (logger_, here_, "%s", "t->recv_role == MESSAGE_REQUEST ? t->send = MESSAGE_RESPONSE : 1" ); } assertion__; }); | |||
723 | ||||
724 | /* | |||
725 | * Check recv_type && recv_role | |||
726 | */ | |||
727 | pexpect(t->recv_role == NO_MESSAGE ? t->recv_type == 0 : t->recv_type != 0)({ _Bool assertion__ = t->recv_role == NO_MESSAGE ? t-> recv_type == 0 : t->recv_type != 0; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 727, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect (logger_, here_, "%s", "t->recv_role == NO_MESSAGE ? t->recv_type == 0 : t->recv_type != 0" ); } assertion__; }); | |||
728 | ||||
729 | /* | |||
730 | * Point .fs_v2_microcode at the first transition for | |||
731 | * the from state. All other transitions for the from | |||
732 | * state should follow immediately after (or to put it | |||
733 | * another way, previous should match). | |||
734 | */ | |||
735 | if (from->v2_transitions == NULL((void*)0)) { | |||
736 | /* start of the next state */ | |||
737 | passert(from->nr_transitions == 0)({ _Bool assertion__ = from->nr_transitions == 0; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 737, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "from->nr_transitions == 0" ); } (void) 1; }); | |||
738 | from->v2_transitions = t; | |||
739 | } else { | |||
740 | passert(t[-1].state == t->state)({ _Bool assertion__ = t[-1].state == t->state; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 740, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "t[-1].state == t->state" ); } (void) 1; }); | |||
741 | } | |||
742 | from->nr_transitions++; | |||
743 | } | |||
744 | } | |||
745 | ||||
746 | /* | |||
747 | * split an incoming message into payloads | |||
748 | */ | |||
749 | struct payload_summary ikev2_decode_payloads(struct logger *log, | |||
750 | struct msg_digest *md, | |||
751 | pb_stream *in_pbs, | |||
752 | enum next_payload_types_ikev2 np) | |||
753 | { | |||
754 | struct payload_summary summary = { | |||
755 | .parsed = true1, | |||
756 | .n = v2N_NOTHING_WRONG, | |||
757 | }; | |||
758 | ||||
759 | /* | |||
760 | * ??? zero out the digest descriptors -- might nuke | |||
761 | * ISAKMP_NEXT_v2SK digest! | |||
762 | * | |||
763 | * XXX: and v2SKF? Safer to leave them as is and just use new | |||
764 | * ones - always add to MD, never take away. | |||
765 | */ | |||
766 | ||||
767 | /* | |||
768 | * XXX: Currently, when a message containing an SK payload is | |||
769 | * decoded, the encrypted payloads get appended to the | |||
770 | * previously decoded non-encrypted payloads. For instance, | |||
771 | * given a message containing two notifications: | |||
772 | * | |||
773 | * N(1), SK{ N(2) } | |||
774 | * | |||
775 | * The notification digest would contain both the unencrypted | |||
776 | * N(1) and encrypted N(2). Since the unencrypted value is | |||
777 | * protected, while not very good, isn't really dangerous. | |||
778 | */ | |||
779 | ||||
780 | while (np != ISAKMP_NEXT_v2NONE) { | |||
781 | esb_buf b; | |||
782 | dbg("Now let's proceed with payload (%s)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("Now let's proceed with payload (%s)", enum_show (&ikev2_payload_names, np, &b)); } } | |||
783 | enum_show(&ikev2_payload_names, np, &b)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("Now let's proceed with payload (%s)", enum_show (&ikev2_payload_names, np, &b)); } }; | |||
784 | ||||
785 | if (md->digest_roof >= elemsof(md->digest)(sizeof(md->digest) / sizeof(*(md->digest)))) { | |||
786 | llog(RC_LOG_SERIOUS, log, | |||
787 | "more than %zu payloads in message; ignored", | |||
788 | elemsof(md->digest)(sizeof(md->digest) / sizeof(*(md->digest)))); | |||
789 | summary.n = v2N_INVALID_SYNTAX; | |||
790 | break; | |||
791 | } | |||
792 | ||||
793 | /* | |||
794 | * *pd is the payload digest for this payload. | |||
795 | * It has three fields: | |||
796 | * pbs is filled in by in_struct | |||
797 | * payload is filled in by in_struct | |||
798 | * next is filled in by list linking logic | |||
799 | */ | |||
800 | struct payload_digest *const pd = md->digest + md->digest_roof; | |||
801 | ||||
802 | /* | |||
803 | * map the payload onto its payload descriptor which | |||
804 | * describes how to decode it | |||
805 | */ | |||
806 | const struct_desc *sd = v2_payload_desc(np); | |||
807 | ||||
808 | if (sd == NULL((void*)0)) { | |||
809 | /* | |||
810 | * This payload is unknown to us. RFCs 4306 | |||
811 | * and 5996 2.5 say that if the payload has | |||
812 | * the Critical Bit, we should be upset but if | |||
813 | * it does not, we should just ignore it. | |||
814 | */ | |||
815 | diag_t d = pbs_in_struct(in_pbs, &ikev2_generic_desc, | |||
816 | &pd->payload, sizeof(pd->payload), &pd->pbs); | |||
817 | if (d != NULL((void*)0)) { | |||
818 | llog_diag(RC_LOG_SERIOUS, log, &d, | |||
819 | "malformed payload in packet"); | |||
820 | summary.n = v2N_INVALID_SYNTAX; | |||
821 | break; | |||
822 | } | |||
823 | if (pd->payload.v2gen.isag_critical & ISAKMP_PAYLOAD_CRITICAL(1<<ISAKMP_PAYLOAD_FLAG_CRITICAL_IX)) { | |||
824 | /* | |||
825 | * It was critical. See RFC 5996 1.5 | |||
826 | * "Version Numbers and Forward | |||
827 | * Compatibility" | |||
828 | */ | |||
829 | const char *role; | |||
830 | switch (v2_msg_role(md)) { | |||
831 | case MESSAGE_REQUEST: | |||
832 | role = "request"; | |||
833 | break; | |||
834 | case MESSAGE_RESPONSE: | |||
835 | role = "response"; | |||
836 | break; | |||
837 | default: | |||
838 | bad_case(v2_msg_role(md))libreswan_bad_case("v2_msg_role(md)", (v2_msg_role(md)), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 838, }; &here; })); | |||
839 | } | |||
840 | esb_buf b; | |||
841 | llog(RC_LOG_SERIOUS, log, | |||
842 | "message %s contained an unknown critical payload type (%s)", | |||
843 | role, enum_show(&ikev2_payload_names, np, &b)); | |||
844 | summary.n = v2N_UNSUPPORTED_CRITICAL_PAYLOAD; | |||
845 | summary.data[0] = np; | |||
846 | summary.data_size = 1; | |||
847 | break; | |||
848 | } | |||
849 | esb_buf eb; | |||
850 | llog(RC_COMMENT, log, | |||
851 | "non-critical payload ignored because it contains an unknown or unexpected payload type (%s) at the outermost level", | |||
852 | enum_show(&ikev2_payload_names, np, &eb)); | |||
853 | np = pd->payload.generic.isag_np; | |||
854 | continue; | |||
855 | } | |||
856 | ||||
857 | if (np >= LELEM_ROOF64) { | |||
858 | dbg("huge next-payload %u", np){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("huge next-payload %u", np); } }; | |||
859 | summary.n = v2N_INVALID_SYNTAX; | |||
860 | break; | |||
861 | } | |||
862 | summary.repeated |= (summary.present & LELEM(np)((lset_t)1 << (np))); | |||
863 | summary.present |= LELEM(np)((lset_t)1 << (np)); | |||
864 | ||||
865 | /* | |||
866 | * Read in the payload recording what type it should | |||
867 | * be. | |||
868 | */ | |||
869 | pd->payload_type = np; | |||
870 | diag_t d = pbs_in_struct(in_pbs, sd, | |||
871 | &pd->payload, sizeof(pd->payload), | |||
872 | &pd->pbs); | |||
873 | if (d != NULL((void*)0)) { | |||
874 | llog_diag(RC_LOG_SERIOUS, log, &d, | |||
875 | "malformed payload in packet"); | |||
876 | summary.n = v2N_INVALID_SYNTAX; | |||
877 | break; | |||
878 | } | |||
879 | ||||
880 | dbg("processing payload: %s (len=%zu)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("processing payload: %s (len=%zu)", enum_show( &ikev2_payload_names, np, &b), ((size_t)((&pd-> pbs)->roof - (&pd->pbs)->cur))); } } | |||
881 | enum_show(&ikev2_payload_names, np, &b),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("processing payload: %s (len=%zu)", enum_show( &ikev2_payload_names, np, &b), ((size_t)((&pd-> pbs)->roof - (&pd->pbs)->cur))); } } | |||
882 | pbs_left(&pd->pbs)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("processing payload: %s (len=%zu)", enum_show( &ikev2_payload_names, np, &b), ((size_t)((&pd-> pbs)->roof - (&pd->pbs)->cur))); } }; | |||
883 | ||||
884 | /* | |||
885 | * Place payload at the end of the chain for this | |||
886 | * type. | |||
887 | */ | |||
888 | if (md->last[np] == NULL((void*)0)) { | |||
889 | /* first */ | |||
890 | md->chain[np] = md->last[np] = pd; | |||
891 | pd->next = NULL((void*)0); | |||
892 | } else { | |||
893 | /* append */ | |||
894 | md->last[np]->next = pd; | |||
895 | md->last[np] = pd; | |||
896 | pd->next = NULL((void*)0); | |||
897 | } | |||
898 | ||||
899 | /* | |||
900 | * Go deeper: | |||
901 | * | |||
902 | * XXX: should this do 'deeper' analysis of packets. | |||
903 | * For instance checking the SPI of a notification | |||
904 | * payload? Probably not as the value may be ignored. | |||
905 | * | |||
906 | * The exception is seems to be v2N - both cookie and | |||
907 | * redirect code happen early and use the values. | |||
908 | */ | |||
909 | ||||
910 | switch (np) { | |||
911 | case ISAKMP_NEXT_v2N: | |||
912 | decode_v2N_payload(log, md, pd); | |||
913 | break; | |||
914 | default: | |||
915 | break; | |||
916 | } | |||
917 | ||||
918 | /* | |||
919 | * Determine the next payload. | |||
920 | * | |||
921 | * SK and SKF are special - their next-payload field | |||
922 | * is for the first embedded payload - so force it to | |||
923 | * NONE: | |||
924 | * | |||
925 | * RFC 5996 2.14 "Encrypted Payload": | |||
926 | * | |||
927 | * Next Payload - The payload type of the first | |||
928 | * embedded payload. Note that this is an exception | |||
929 | * in the standard header format, since the Encrypted | |||
930 | * payload is the last payload in the message and | |||
931 | * therefore the Next Payload field would normally be | |||
932 | * zero. But because the content of this payload is | |||
933 | * embedded payloads and there was no natural place to | |||
934 | * put the type of the first one, that type is placed | |||
935 | * here. | |||
936 | */ | |||
937 | switch (np) { | |||
938 | case ISAKMP_NEXT_v2SK: | |||
939 | case ISAKMP_NEXT_v2SKF: | |||
940 | /* special */ | |||
941 | np = ISAKMP_NEXT_v2NONE; | |||
942 | break; | |||
943 | default: | |||
944 | np = pd->payload.generic.isag_np; | |||
945 | break; | |||
946 | } | |||
947 | ||||
948 | md->digest_roof++; | |||
949 | } | |||
950 | ||||
951 | return summary; | |||
952 | } | |||
953 | ||||
954 | static struct child_sa *process_v2_child_ix(struct ike_sa *ike, | |||
955 | const struct v2_state_transition *svm) | |||
956 | { | |||
957 | /* | |||
958 | * XXX: Still a mess. Should call processor with the IKE SA. | |||
959 | * The processor can then create a nested state. | |||
960 | */ | |||
961 | enum sa_type sa_type; | |||
962 | switch (svm->state) { | |||
963 | case STATE_V2_NEW_CHILD_R0: | |||
964 | case STATE_V2_REKEY_CHILD_R0: | |||
965 | sa_type = IPSEC_SA; | |||
966 | break; | |||
967 | default: | |||
968 | pexpect(svm->state == STATE_V2_REKEY_IKE_R0)({ _Bool assertion__ = svm->state == STATE_V2_REKEY_IKE_R0 ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 968, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "svm->state == STATE_V2_REKEY_IKE_R0" ); } assertion__; }); | |||
969 | sa_type = IKE_SA; | |||
970 | } | |||
971 | ||||
972 | struct child_sa *child = new_v2_child_state(ike->sa.st_connection, | |||
973 | ike, sa_type, | |||
974 | SA_RESPONDER, | |||
975 | svm->state, | |||
976 | null_fd((struct fd *) ((void*)0))); | |||
977 | ||||
978 | connection_buf ibuf; | |||
979 | connection_buf cbuf; | |||
980 | dbg(PRI_CONNECTION" #%lu received %s CREATE_CHILD_SA Child "PRI_CONNECTION" #%lu in %s will process it further",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("\"%s\"%s"" #%lu received %s CREATE_CHILD_SA Child " "\"%s\"%s"" #%lu in %s will process it further", (ike->sa. st_connection)->name, str_connection_instance(ike->sa.st_connection , &ibuf), ike->sa.st_serialno, svm->story, (child-> sa.st_connection)->name, str_connection_instance(child-> sa.st_connection, &cbuf), child->sa.st_serialno, child ->sa.st_state->name); } } | |||
981 | pri_connection(ike->sa.st_connection, &ibuf),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("\"%s\"%s"" #%lu received %s CREATE_CHILD_SA Child " "\"%s\"%s"" #%lu in %s will process it further", (ike->sa. st_connection)->name, str_connection_instance(ike->sa.st_connection , &ibuf), ike->sa.st_serialno, svm->story, (child-> sa.st_connection)->name, str_connection_instance(child-> sa.st_connection, &cbuf), child->sa.st_serialno, child ->sa.st_state->name); } } | |||
982 | ike->sa.st_serialno, svm->story,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("\"%s\"%s"" #%lu received %s CREATE_CHILD_SA Child " "\"%s\"%s"" #%lu in %s will process it further", (ike->sa. st_connection)->name, str_connection_instance(ike->sa.st_connection , &ibuf), ike->sa.st_serialno, svm->story, (child-> sa.st_connection)->name, str_connection_instance(child-> sa.st_connection, &cbuf), child->sa.st_serialno, child ->sa.st_state->name); } } | |||
983 | pri_connection(child->sa.st_connection, &cbuf),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("\"%s\"%s"" #%lu received %s CREATE_CHILD_SA Child " "\"%s\"%s"" #%lu in %s will process it further", (ike->sa. st_connection)->name, str_connection_instance(ike->sa.st_connection , &ibuf), ike->sa.st_serialno, svm->story, (child-> sa.st_connection)->name, str_connection_instance(child-> sa.st_connection, &cbuf), child->sa.st_serialno, child ->sa.st_state->name); } } | |||
984 | child->sa.st_serialno, child->sa.st_state->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("\"%s\"%s"" #%lu received %s CREATE_CHILD_SA Child " "\"%s\"%s"" #%lu in %s will process it further", (ike->sa. st_connection)->name, str_connection_instance(ike->sa.st_connection , &ibuf), ike->sa.st_serialno, svm->story, (child-> sa.st_connection)->name, str_connection_instance(child-> sa.st_connection, &cbuf), child->sa.st_serialno, child ->sa.st_state->name); } }; | |||
985 | ||||
986 | return child; | |||
987 | } | |||
988 | ||||
989 | /* | |||
990 | * Find the SA (IKE or CHILD), within IKE's family, that is initiated | |||
991 | * or is responding to Message ID. | |||
992 | * | |||
993 | * XXX: There's overlap between this and the is_duplicate_*() code. | |||
994 | * For instance, there's little point in looking for a state when the | |||
995 | * IKE SA's window shows it too old (at least if we ignore | |||
996 | * record'n'send bugs). | |||
997 | */ | |||
998 | ||||
999 | static struct state *find_v2_sa_by_initiator_wip(struct ike_sa *ike, const msgid_t msgid) | |||
1000 | { | |||
1001 | /* | |||
1002 | * XXX: Would a linked list of CHILD SAs work better, would | |||
1003 | * mean reference counting? Should this also check that MSGID | |||
1004 | * is within the IKE SA's window? | |||
1005 | */ | |||
1006 | struct state *st; | |||
1007 | if (ike->sa.st_v2_msgid_wip.initiator == msgid) { | |||
1008 | /* short-cut */ | |||
1009 | st = &ike->sa; | |||
1010 | } else { | |||
1011 | struct state_query stq = { | |||
1012 | .where = HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1012, }; &here; }), | |||
1013 | .ike_version = IKEv2, | |||
1014 | .ike_spis = &ike->sa.st_ike_spis, | |||
1015 | }; | |||
1016 | st = NULL((void*)0); | |||
1017 | while (old2new_state(&stq)) { | |||
1018 | if (stq.st->st_v2_msgid_wip.initiator == msgid) { | |||
1019 | st = stq.st; | |||
1020 | break; | |||
1021 | } | |||
1022 | } | |||
1023 | } | |||
1024 | pexpect(st == NULL ||({ _Bool assertion__ = st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno; if ( !assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1026, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno" ); } assertion__; }) | |||
1025 | st->st_clonedfrom == SOS_NOBODY ||({ _Bool assertion__ = st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno; if ( !assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1026, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno" ); } assertion__; }) | |||
1026 | st->st_clonedfrom == ike->sa.st_serialno)({ _Bool assertion__ = st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno; if ( !assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1026, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno" ); } assertion__; }); | |||
1027 | return st; | |||
1028 | } | |||
1029 | ||||
1030 | static struct state *find_v2_sa_by_responder_wip(struct ike_sa *ike, const msgid_t msgid) | |||
1031 | { | |||
1032 | /* | |||
1033 | * XXX: Would a linked list of CHILD SAs work better, would | |||
1034 | * mean reference counting? Should this also check that MSGID | |||
1035 | * is within the IKE SA's window? | |||
1036 | */ | |||
1037 | struct state *st; | |||
1038 | if (ike->sa.st_v2_msgid_wip.responder == msgid) { | |||
1039 | /* short-cut */ | |||
1040 | st = &ike->sa; | |||
1041 | } else { | |||
1042 | struct state_query stq = { | |||
1043 | .where = HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1043, }; &here; }), | |||
1044 | .ike_version = IKEv2, | |||
1045 | .ike_spis = &ike->sa.st_ike_spis, | |||
1046 | }; | |||
1047 | st = NULL((void*)0); | |||
1048 | while (old2new_state(&stq)) { | |||
1049 | if (stq.st->st_v2_msgid_wip.responder == msgid) { | |||
1050 | st = stq.st; | |||
1051 | break; | |||
1052 | } | |||
1053 | } | |||
1054 | } | |||
1055 | pexpect(st == NULL ||({ _Bool assertion__ = st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno; if ( !assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1057, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno" ); } assertion__; }) | |||
1056 | st->st_clonedfrom == SOS_NOBODY ||({ _Bool assertion__ = st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno; if ( !assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1057, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno" ); } assertion__; }) | |||
1057 | st->st_clonedfrom == ike->sa.st_serialno)({ _Bool assertion__ = st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno; if ( !assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1057, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "st == ((void*)0) || st->st_clonedfrom == 0 || st->st_clonedfrom == ike->sa.st_serialno" ); } assertion__; }); | |||
1058 | return st; | |||
1059 | } | |||
1060 | ||||
1061 | /* | |||
1062 | * Is this a duplicate message? | |||
1063 | * | |||
1064 | * XXX: | |||
1065 | * | |||
1066 | * record'n'send bypassing the send queue can result in pluto having | |||
1067 | * more outstanding messages then the negotiated window size. | |||
1068 | * | |||
1069 | * This and the find_v2_sa_by_*_wip() have some overlap. For | |||
1070 | * instance, little point in searching for a state when the IKE SA's | |||
1071 | * window shows the Message ID is too old (only record'n'send breakage | |||
1072 | * means it might still have a message, argh!). | |||
1073 | */ | |||
1074 | ||||
1075 | /* | |||
1076 | * A duplicate request could be: | |||
1077 | * | |||
1078 | * - the request still being processed (for instance waiting on | |||
1079 | * crypto), which can be tossed | |||
1080 | * | |||
1081 | * - the request last processed, which should trigger a retransmit of | |||
1082 | * the response | |||
1083 | * | |||
1084 | * - an older request which can be tossed | |||
1085 | * | |||
1086 | * But if it is a fragment, much of this is skipped. | |||
1087 | */ | |||
1088 | static bool_Bool is_duplicate_request(struct ike_sa *ike, | |||
1089 | struct msg_digest *md) | |||
1090 | { | |||
1091 | passert(v2_msg_role(md) == MESSAGE_REQUEST)({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_REQUEST; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1091, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "v2_msg_role(md) == MESSAGE_REQUEST" ); } (void) 1; }); | |||
1092 | intmax_t msgid = md->hdr.isa_msgid; | |||
1093 | ||||
1094 | /* lie to keep test results happy */ | |||
1095 | dbg("#%lu st.st_msgid_lastrecv %jd md.hdr.isa_msgid %08jx",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu st.st_msgid_lastrecv %jd md.hdr.isa_msgid %08jx" , ike->sa.st_serialno, ike->sa.st_v2_msgid_windows.responder .recv, msgid); } } | |||
1096 | ike->sa.st_serialno, ike->sa.st_v2_msgid_windows.responder.recv, msgid){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu st.st_msgid_lastrecv %jd md.hdr.isa_msgid %08jx" , ike->sa.st_serialno, ike->sa.st_v2_msgid_windows.responder .recv, msgid); } }; | |||
1097 | ||||
1098 | /* the sliding window is really small?!? */ | |||
1099 | pexpect(ike->sa.st_v2_msgid_windows.responder.recv ==({ _Bool assertion__ = ike->sa.st_v2_msgid_windows.responder .recv == ike->sa.st_v2_msgid_windows.responder.sent; if (! assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1100, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike->sa.st_v2_msgid_windows.responder.recv == ike->sa.st_v2_msgid_windows.responder.sent" ); } assertion__; }) | |||
1100 | ike->sa.st_v2_msgid_windows.responder.sent)({ _Bool assertion__ = ike->sa.st_v2_msgid_windows.responder .recv == ike->sa.st_v2_msgid_windows.responder.sent; if (! assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1100, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike->sa.st_v2_msgid_windows.responder.recv == ike->sa.st_v2_msgid_windows.responder.sent" ); } assertion__; }); | |||
1101 | ||||
1102 | if (msgid < ike->sa.st_v2_msgid_windows.responder.sent) { | |||
1103 | /* | |||
1104 | * this is an OLD retransmit and out sliding window | |||
1105 | * holds only the most recent response. we can't do | |||
1106 | * anything | |||
1107 | */ | |||
1108 | log_state(RC_LOG, &ike->sa, | |||
1109 | "received too old retransmit: %jd < %jd", | |||
1110 | msgid, ike->sa.st_v2_msgid_windows.responder.sent); | |||
1111 | return true1; | |||
1112 | } else if (msgid == ike->sa.st_v2_msgid_windows.responder.sent) { | |||
1113 | /* | |||
1114 | * This was the last request processed and, | |||
1115 | * presumably, a response was sent. Retransmit the | |||
1116 | * saved response (the response was saved right?). | |||
1117 | */ | |||
1118 | if (ike->sa.st_v2_outgoing[MESSAGE_RESPONSE] == NULL((void*)0)) { | |||
1119 | FAIL_V2_MSGID(ike, &ike->sa,fail_v2_msgid(({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1122, }; &here ; }), ike, &ike->sa, "retransmission for message %jd exchange %s failed responder.sent %jd - there is no stored message or fragments to retransmit" , msgid, enum_name(&ikev2_exchange_names, md->hdr.isa_xchg ), ike->sa.st_v2_msgid_windows.responder.sent) | |||
1120 | "retransmission for message %jd exchange %s failed responder.sent %jd - there is no stored message or fragments to retransmit",fail_v2_msgid(({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1122, }; &here ; }), ike, &ike->sa, "retransmission for message %jd exchange %s failed responder.sent %jd - there is no stored message or fragments to retransmit" , msgid, enum_name(&ikev2_exchange_names, md->hdr.isa_xchg ), ike->sa.st_v2_msgid_windows.responder.sent) | |||
1121 | msgid, enum_name(&ikev2_exchange_names, md->hdr.isa_xchg),fail_v2_msgid(({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1122, }; &here ; }), ike, &ike->sa, "retransmission for message %jd exchange %s failed responder.sent %jd - there is no stored message or fragments to retransmit" , msgid, enum_name(&ikev2_exchange_names, md->hdr.isa_xchg ), ike->sa.st_v2_msgid_windows.responder.sent) | |||
1122 | ike->sa.st_v2_msgid_windows.responder.sent)fail_v2_msgid(({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1122, }; &here ; }), ike, &ike->sa, "retransmission for message %jd exchange %s failed responder.sent %jd - there is no stored message or fragments to retransmit" , msgid, enum_name(&ikev2_exchange_names, md->hdr.isa_xchg ), ike->sa.st_v2_msgid_windows.responder.sent); | |||
1123 | return true1; | |||
1124 | } | |||
1125 | /* | |||
1126 | * If things are fragmented, only respond to the first | |||
1127 | * fragment. | |||
1128 | */ | |||
1129 | unsigned fragment = 0; | |||
1130 | if (md->hdr.isa_np == ISAKMP_NEXT_v2SKF) { | |||
1131 | struct ikev2_skf skf; | |||
1132 | pb_stream in_pbs = md->message_pbs; /* copy */ | |||
1133 | pb_stream ignored; | |||
1134 | diag_t d = pbs_in_struct(&in_pbs, &ikev2_skf_desc, | |||
1135 | &skf, sizeof(skf), &ignored); | |||
1136 | if (d != NULL((void*)0)) { | |||
1137 | llog_diag(RC_LOG, ike->sa.st_logger, &d, "%s", ""); | |||
1138 | return true1; | |||
1139 | } | |||
1140 | fragment = skf.isaskf_number; | |||
1141 | } | |||
1142 | if (fragment == 0) { | |||
1143 | log_state(RC_LOG, &ike->sa, | |||
1144 | "received duplicate %s message request (Message ID %jd); retransmitting response", | |||
1145 | enum_name_short(&ikev2_exchange_names, md->hdr.isa_xchg), | |||
1146 | msgid); | |||
1147 | send_recorded_v2_message(ike, "ikev2-responder-retransmit", | |||
1148 | MESSAGE_RESPONSE); | |||
1149 | } else if (fragment == 1) { | |||
1150 | log_state(RC_LOG, &ike->sa, | |||
1151 | "received duplicate %s message request (Message ID %jd, fragment %u); retransmitting response", | |||
1152 | enum_name_short(&ikev2_exchange_names, md->hdr.isa_xchg), | |||
1153 | msgid, fragment); | |||
1154 | send_recorded_v2_message(ike, "ikev2-responder-retransmt (fragment 1)", | |||
1155 | MESSAGE_RESPONSE); | |||
1156 | } else { | |||
1157 | dbg_v2_msgid(ike, &ike->sa, | |||
1158 | "received duplicate %s message request (Message ID %jd, fragment %u); discarded as not fragment 1", | |||
1159 | enum_name_short(&ikev2_exchange_names, md->hdr.isa_xchg), | |||
1160 | msgid, fragment); | |||
1161 | } | |||
1162 | return true1; | |||
1163 | } else { | |||
1164 | /* all that is left */ | |||
1165 | pexpect(msgid > ike->sa.st_v2_msgid_windows.responder.sent)({ _Bool assertion__ = msgid > ike->sa.st_v2_msgid_windows .responder.sent; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 1165, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "msgid > ike->sa.st_v2_msgid_windows.responder.sent" ); } assertion__; }); | |||
1166 | } | |||
1167 | ||||
1168 | /* | |||
1169 | * Is something already processing this request? | |||
1170 | * | |||
1171 | * Processing only starts for real once a responder has | |||
1172 | * accumulated all fragments and obtained KEYMAT. | |||
1173 | */ | |||
1174 | { | |||
1175 | struct state *responder = find_v2_sa_by_responder_wip(ike, md->hdr.isa_msgid); | |||
1176 | /* only a true responder */ | |||
1177 | pexpect(responder == NULL ||({ _Bool assertion__ = responder == ((void*)0) || responder-> st_v2_msgid_wip.responder == msgid; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1178, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect (logger_, here_, "%s", "responder == ((void*)0) || responder->st_v2_msgid_wip.responder == msgid" ); } assertion__; }) | |||
1178 | responder->st_v2_msgid_wip.responder == msgid)({ _Bool assertion__ = responder == ((void*)0) || responder-> st_v2_msgid_wip.responder == msgid; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1178, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect (logger_, here_, "%s", "responder == ((void*)0) || responder->st_v2_msgid_wip.responder == msgid" ); } assertion__; }); | |||
1179 | if (responder != NULL((void*)0)) { | |||
1180 | /* this generates the log message */ | |||
1181 | pexpect(verbose_state_busy(responder))({ _Bool assertion__ = verbose_state_busy(responder); if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1181, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "verbose_state_busy(responder)" ); } assertion__; }); | |||
1182 | return true1; | |||
1183 | } | |||
1184 | } | |||
1185 | ||||
1186 | /* | |||
1187 | * The IKE SA responder, having accumulated all the fragments | |||
1188 | * for the IKE_AUTH request, is computing the SKEYSEED. When | |||
1189 | * SKEYSEED finishes .st_v2_rfrags is wiped and the Message | |||
1190 | * IDs updated to flag that the message as work-in-progress | |||
1191 | * (so above check will have succeeded). | |||
1192 | */ | |||
1193 | if (state_is_busy(&ike->sa)) { | |||
1194 | /* | |||
1195 | * To keep tests happy, try to output text matching | |||
1196 | * verbose_state_busy(); but with some extra detail. | |||
1197 | */ | |||
1198 | #if 0 | |||
1199 | /* | |||
1200 | * XXX: hang onto this code for now - it shows how to | |||
1201 | * lightly unpack fragments. Will be useful when | |||
1202 | * fragmentation code is moved out of the state lookup | |||
1203 | * code. | |||
1204 | */ | |||
1205 | unsigned fragment = 0; | |||
1206 | if (md->hdr.isa_np == ISAKMP_NEXT_v2SKF) { | |||
1207 | struct ikev2_skf skf; | |||
1208 | pb_stream in_pbs = md->message_pbs; /* copy */ | |||
1209 | pb_stream ignored; | |||
1210 | diag_t d = pbs_in_struct(&skf, &ikev2_skf_desc, &in_pbs, &ignored); | |||
1211 | if (d != NULL((void*)0)) { | |||
1212 | llog_diag(RC_LOG, st->st_logger, &d, "%s", ""); | |||
1213 | return true1; | |||
1214 | } | |||
1215 | fragment = skf.isaskf_number; | |||
1216 | } | |||
1217 | if (fragment == 0) { | |||
1218 | log_state(RC_LOG, &ike->sa, | |||
1219 | "discarding packet received during asynchronous work (DNS or crypto) in %s", | |||
1220 | ike->sa.st_state->name); | |||
1221 | } else if (fragment == 1) { | |||
1222 | log_state(RC_LOG, &ike->sa, | |||
1223 | "discarding fragments received during asynchronous work (DNS or crypto) in %s", | |||
1224 | ike->sa.st_state->name); | |||
1225 | } else { | |||
1226 | dbg_v2_msgid(ike, &ike->sa, | |||
1227 | "discarding fragment %u received during asynchronous work (DNS or crypto) in %s", | |||
1228 | fragment, ike->sa.st_state->name); | |||
1229 | } | |||
1230 | #else | |||
1231 | log_state(RC_LOG, &ike->sa, | |||
1232 | "discarding packet received during asynchronous work (DNS or crypto) in %s", | |||
1233 | ike->sa.st_state->name); | |||
1234 | #endif | |||
1235 | return true1; | |||
1236 | } | |||
1237 | ||||
1238 | struct v2_incoming_fragments *frags = ike->sa.st_v2_incoming[MESSAGE_REQUEST]; | |||
1239 | if (frags != NULL((void*)0)) { | |||
1240 | pexpect(frags->count < frags->total)({ _Bool assertion__ = frags->count < frags->total; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1240, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "frags->count < frags->total" ); } assertion__; }); | |||
1241 | dbg_v2_msgid(ike, &ike->sa, | |||
1242 | "not a duplicate - responder is accumulating fragments for message request %jd", | |||
1243 | msgid); | |||
1244 | } else { | |||
1245 | dbg_v2_msgid(ike, &ike->sa, | |||
1246 | "not a duplicate - message request %jd is new", | |||
1247 | msgid); | |||
1248 | } | |||
1249 | ||||
1250 | return false0; | |||
1251 | } | |||
1252 | ||||
1253 | /* | |||
1254 | * A duplicate response could be: | |||
1255 | * | |||
1256 | * - for an old request where there's no longer an initiator waiting, | |||
1257 | * and can be dropped | |||
1258 | * | |||
1259 | * - the initiator is busy, presumably because this response is a | |||
1260 | * duplicate and the initiator is waiting on crypto to complete so | |||
1261 | * it can decrypt the response | |||
1262 | */ | |||
1263 | static bool_Bool is_duplicate_response(struct ike_sa *ike, | |||
1264 | struct state *initiator, | |||
1265 | struct msg_digest *md) | |||
1266 | { | |||
1267 | passert(v2_msg_role(md) == MESSAGE_RESPONSE)({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_RESPONSE; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1267, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "v2_msg_role(md) == MESSAGE_RESPONSE" ); } (void) 1; }); | |||
1268 | intmax_t msgid = md->hdr.isa_msgid; | |||
1269 | ||||
1270 | /* only a true initiator */ | |||
1271 | pexpect(initiator == NULL ||({ _Bool assertion__ = initiator == ((void*)0) || initiator-> st_v2_msgid_wip.initiator == msgid; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1272, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect (logger_, here_, "%s", "initiator == ((void*)0) || initiator->st_v2_msgid_wip.initiator == msgid" ); } assertion__; }) | |||
1272 | initiator->st_v2_msgid_wip.initiator == msgid)({ _Bool assertion__ = initiator == ((void*)0) || initiator-> st_v2_msgid_wip.initiator == msgid; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1272, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect (logger_, here_, "%s", "initiator == ((void*)0) || initiator->st_v2_msgid_wip.initiator == msgid" ); } assertion__; }); | |||
1273 | ||||
1274 | /* the sliding window is really small?!? */ | |||
1275 | pexpect(ike->sa.st_v2_msgid_windows.responder.recv ==({ _Bool assertion__ = ike->sa.st_v2_msgid_windows.responder .recv == ike->sa.st_v2_msgid_windows.responder.sent; if (! assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1276, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike->sa.st_v2_msgid_windows.responder.recv == ike->sa.st_v2_msgid_windows.responder.sent" ); } assertion__; }) | |||
1276 | ike->sa.st_v2_msgid_windows.responder.sent)({ _Bool assertion__ = ike->sa.st_v2_msgid_windows.responder .recv == ike->sa.st_v2_msgid_windows.responder.sent; if (! assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1276, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike->sa.st_v2_msgid_windows.responder.recv == ike->sa.st_v2_msgid_windows.responder.sent" ); } assertion__; }); | |||
1277 | ||||
1278 | if (msgid <= ike->sa.st_v2_msgid_windows.initiator.recv) { | |||
1279 | /* | |||
1280 | * Processing of the response was completed so drop as | |||
1281 | * too old. | |||
1282 | * | |||
1283 | * XXX: Should be rate_log() but that shows up in the | |||
1284 | * whack output. While "correct" it messes with test | |||
1285 | * output. The old log line didn't show up because | |||
1286 | * current-state wasn't set. | |||
1287 | * | |||
1288 | * Here's roughly why INITIATOR can be non-NULL: | |||
1289 | * | |||
1290 | * - west.#8 needs a rekey, so west.#11 is created and | |||
1291 | * it sends a CREATE_CHILD_SA with Message ID 3. | |||
1292 | * | |||
1293 | * - west.#8 gives up on the re-key so it forces a | |||
1294 | * delete request (aka record'n'send), sending a | |||
1295 | * second message with ID 4 | |||
1296 | * | |||
1297 | * West has two outstanding messages yet its window | |||
1298 | * size of 1! | |||
1299 | * | |||
1300 | * - east receives the rekey with ID 3, creates | |||
1301 | * east.#11 and and sends it off for further | |||
1302 | * processing | |||
1303 | * | |||
1304 | * - east receives the delete with ID 4, forces a | |||
1305 | * message ID update and sends an ID 4 response | |||
1306 | * confirming the delete | |||
1307 | * | |||
1308 | * - east.#11 finishes its crypto so east sends back | |||
1309 | * its response with Message ID 3 for a re-keyed SA it | |||
1310 | * just deleted?!?! | |||
1311 | * | |||
1312 | * East has responded with two out-of-order messages | |||
1313 | * (if the window size was 2 this would be ok but it | |||
1314 | * isn't). | |||
1315 | * | |||
1316 | * - west receives the ID 4 response, tries to delete | |||
1317 | * the IKE SA but can't because west.#11 is lurking; | |||
1318 | * but regardless the ID window is forced 2->4 | |||
1319 | * | |||
1320 | * - west receives the ID 3 response, which is clearly | |||
1321 | * to-old so doesn't expect there to be a matching | |||
1322 | * initiator, arrg | |||
1323 | */ | |||
1324 | if (initiator != NULL((void*)0)) { | |||
1325 | dbg_v2_msgid(ike, initiator, "XXX: expecting initiator==NULL - suspect record'n'send with an out-of-order wrong packet response; discarding packet"); | |||
1326 | } else { | |||
1327 | dbg_v2_msgid(ike, initiator, "already processed response %jd (%s); discarding packet", | |||
1328 | msgid, enum_name_short(&ikev2_exchange_names, md->hdr.isa_xchg)); | |||
1329 | } | |||
1330 | return true1; | |||
1331 | } | |||
1332 | ||||
1333 | if (initiator == NULL((void*)0)) { | |||
1334 | /* | |||
1335 | * While there's an IKE SA matching the IKE SPIs, | |||
1336 | * there's no corresponding initiator for the message. | |||
1337 | * | |||
1338 | * XXX: rate_log() sends to whack which, while making | |||
1339 | * sense, but churns the test output. | |||
1340 | */ | |||
1341 | log_state(RC_LOG, &ike->sa, | |||
1342 | "%s message response with Message ID %jd has no matching SA", | |||
1343 | enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), msgid); | |||
1344 | return true1; | |||
1345 | } | |||
1346 | ||||
1347 | /* | |||
1348 | * Sanity check the MSGID and initiator against the IKE SA | |||
1349 | * Message ID window. | |||
1350 | */ | |||
1351 | ||||
1352 | if (msgid > ike->sa.st_v2_msgid_windows.initiator.sent) { | |||
1353 | /* | |||
1354 | * There was an initiator waiting for a message that, | |||
1355 | * according to the IKE SA, has yet to be sent?!? | |||
1356 | */ | |||
1357 | FAIL_V2_MSGID(ike, initiator,fail_v2_msgid(({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1359, }; &here ; }), ike, initiator, "dropping response with Message ID %jd which is from the future - last request sent was %jd" , msgid, ike->sa.st_v2_msgid_windows.initiator.sent) | |||
1358 | "dropping response with Message ID %jd which is from the future - last request sent was %jd",fail_v2_msgid(({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1359, }; &here ; }), ike, initiator, "dropping response with Message ID %jd which is from the future - last request sent was %jd" , msgid, ike->sa.st_v2_msgid_windows.initiator.sent) | |||
1359 | msgid, ike->sa.st_v2_msgid_windows.initiator.sent)fail_v2_msgid(({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1359, }; &here ; }), ike, initiator, "dropping response with Message ID %jd which is from the future - last request sent was %jd" , msgid, ike->sa.st_v2_msgid_windows.initiator.sent); | |||
1360 | return true1; | |||
1361 | } | |||
1362 | ||||
1363 | /* | |||
1364 | * If the state is busy, presumably doing something like | |||
1365 | * crypto, skip further processing. | |||
1366 | * | |||
1367 | * For fragments, things only go busy once all fragments have | |||
1368 | * been received (and re-transmitted fragments are ignored). | |||
1369 | * If this changes then a lot more than this code will need to | |||
1370 | * be moved. | |||
1371 | * | |||
1372 | * XXX: Is there a better way to handle this? | |||
1373 | */ | |||
1374 | if (verbose_state_busy(initiator)) { | |||
1375 | return true1; | |||
1376 | } | |||
1377 | ||||
1378 | return false0; | |||
1379 | } | |||
1380 | ||||
1381 | /* | |||
1382 | * process an input packet, possibly generating a reply. | |||
1383 | * | |||
1384 | * If all goes well, this routine eventually calls a state-specific | |||
1385 | * transition function. | |||
1386 | * | |||
1387 | * This routine will not release_any_md(mdp). It is expected that its | |||
1388 | * caller will do this. In fact, it will zap *mdp to NULL if it thinks | |||
1389 | * **mdp should not be freed. So the caller should be prepared for | |||
1390 | * *mdp being set to NULL. | |||
1391 | * | |||
1392 | * Start by looking for (or creating) the IKE SA responsible for the | |||
1393 | * IKE SPIs group ..... | |||
1394 | */ | |||
1395 | ||||
1396 | static void ike_process_packet(struct msg_digest *mdp, struct ike_sa *ike); | |||
1397 | ||||
1398 | void ikev2_process_packet(struct msg_digest *md) | |||
1399 | { | |||
1400 | /* Look for an state that matches the various things we know: | |||
1401 | * | |||
1402 | * 1) exchange type received? | |||
1403 | * 2) is it initiator or not? | |||
1404 | */ | |||
1405 | const enum isakmp_xchg_type ix = md->hdr.isa_xchg; | |||
1406 | ||||
1407 | /* | |||
1408 | * If the IKE SA initiator sent the message then this end is | |||
1409 | * looking for the IKE SA responder (and vice versa). | |||
1410 | */ | |||
1411 | enum sa_role expected_local_ike_role = (md->hdr.isa_flags & ISAKMP_FLAGS_v2_IKE_I(1<<ISAKMP_FLAGS_v2_IKE_I_IX)) ? SA_RESPONDER : SA_INITIATOR; | |||
1412 | ||||
1413 | /* | |||
1414 | * Dump what the message says, once a state has been found | |||
1415 | * this can be checked against what is. | |||
1416 | */ | |||
1417 | LSWDBGP(DBG_BASE, buf)for (_Bool lswlog_p = (cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))); lswlog_p; lswlog_p = 0) for (char lswbuf[( (size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) for (; buf != ((void*)0); jambuf_to_logger(buf , &failsafe_logger, DEBUG_STREAM), buf = ((void*)0)) { | |||
1418 | switch (expected_local_ike_role) { | |||
1419 | case SA_RESPONDER: | |||
1420 | jam(buf, "I am the IKE SA Original Responder"); | |||
1421 | break; | |||
1422 | case SA_INITIATOR: | |||
1423 | jam(buf, "I am the IKE SA Original Initiator"); | |||
1424 | break; | |||
1425 | default: | |||
1426 | bad_case(expected_local_ike_role)libreswan_bad_case("expected_local_ike_role", (expected_local_ike_role ), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1426, }; &here; })); | |||
1427 | } | |||
1428 | jam(buf, " receiving an IKEv2 "); | |||
1429 | jam_enum_short(buf, &ikev2_exchange_names, ix); | |||
1430 | switch (v2_msg_role(md)) { | |||
1431 | case MESSAGE_RESPONSE: | |||
1432 | jam(buf, " response "); | |||
1433 | break; | |||
1434 | case MESSAGE_REQUEST: | |||
1435 | jam(buf, " request "); | |||
1436 | break; | |||
1437 | default: | |||
1438 | bad_case(v2_msg_role(md))libreswan_bad_case("v2_msg_role(md)", (v2_msg_role(md)), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 1438, }; &here; })); | |||
1439 | } | |||
1440 | } | |||
1441 | ||||
1442 | /* | |||
1443 | * If the message is a new IKE_SA_INIT request (or previously | |||
1444 | * discarded request due to cookies) then there is no IKE SA, | |||
1445 | * and no point trying to use the state machinery. | |||
1446 | * | |||
1447 | * If the message is an IKE_SA_INIT response, then there might | |||
1448 | * be an IKE SA; but the number of checks required means that | |||
1449 | * it is also a good idea to just avoid the state machinery. | |||
1450 | */ | |||
1451 | ||||
1452 | if (ix == ISAKMP_v2_IKE_SA_INIT) { | |||
1453 | process_v2_IKE_SA_INIT(md); | |||
1454 | return; | |||
1455 | } | |||
1456 | ||||
1457 | passert(v2_msg_role(md) == MESSAGE_REQUEST ||({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_REQUEST || v2_msg_role (md) == MESSAGE_RESPONSE; if (!assertion__) { where_t here = ( { static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1458, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert( logger_, here, "%s", "v2_msg_role(md) == MESSAGE_REQUEST || v2_msg_role(md) == MESSAGE_RESPONSE" ); } (void) 1; }) | |||
1458 | v2_msg_role(md) == MESSAGE_RESPONSE)({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_REQUEST || v2_msg_role (md) == MESSAGE_RESPONSE; if (!assertion__) { where_t here = ( { static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1458, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert( logger_, here, "%s", "v2_msg_role(md) == MESSAGE_REQUEST || v2_msg_role(md) == MESSAGE_RESPONSE" ); } (void) 1; }); | |||
1459 | ||||
1460 | /* | |||
1461 | * Find the IKE SA with matching SPIs. | |||
1462 | * | |||
1463 | * The IKE SA's Message IDs can then be used to determine if | |||
1464 | * the message fits in the message window (new request, | |||
1465 | * expected response, or old message). | |||
1466 | */ | |||
1467 | struct ike_sa *ike = find_v2_ike_sa(&md->hdr.isa_ike_spis, | |||
1468 | expected_local_ike_role); | |||
1469 | if (ike == NULL((void*)0)) { | |||
1470 | esb_buf ixb; | |||
1471 | rate_log(md, "%s message %s has no corresponding IKE SA", | |||
1472 | enum_show_short(&ikev2_exchange_names, ix, &ixb), | |||
1473 | v2_msg_role(md) == MESSAGE_REQUEST ? "request" : "response"); | |||
1474 | return; | |||
1475 | } | |||
1476 | ||||
1477 | /* | |||
1478 | * There's at least an IKE SA, and possibly ST willing to | |||
1479 | * process the message. | |||
1480 | */ | |||
1481 | passert(ike != NULL)({ _Bool assertion__ = ike != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1481, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "ike != ((void*)0)"); } ( void) 1; }); | |||
1482 | ||||
1483 | /* | |||
1484 | * Re-check ST's IKE SA's role against the I(Initiator) flag | |||
1485 | * in the headers. Since above searches will only find an IKE | |||
1486 | * SA when the IKE SA's role is correct, this should always | |||
1487 | * work. | |||
1488 | */ | |||
1489 | if (!pexpect(ike->sa.st_sa_role == expected_local_ike_role)({ _Bool assertion__ = ike->sa.st_sa_role == expected_local_ike_role ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1489, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike->sa.st_sa_role == expected_local_ike_role" ); } assertion__; })) { | |||
1490 | return; | |||
1491 | } | |||
1492 | ||||
1493 | /* | |||
1494 | * Since there's an IKE SA start billing and logging against | |||
1495 | * it. | |||
1496 | */ | |||
1497 | statetime_t start = statetime_backdate(&ike->sa, &md->md_inception); | |||
1498 | ike_process_packet(md, ike); | |||
1499 | statetime_stop(&start, "%s()", __func__); | |||
1500 | } | |||
1501 | ||||
1502 | /* | |||
1503 | * The IKE SA for the message has been found (or created). Continue | |||
1504 | * verification, and identify the state (ST) that the message should | |||
1505 | * be sent to. | |||
1506 | */ | |||
1507 | ||||
1508 | static void ike_process_packet(struct msg_digest *md, struct ike_sa *ike) | |||
1509 | { | |||
1510 | /* | |||
1511 | * Deal with duplicate messages and busy states. | |||
1512 | */ | |||
1513 | struct state *st; | |||
1514 | switch (v2_msg_role(md)) { | |||
1515 | case MESSAGE_REQUEST: | |||
1516 | /* | |||
1517 | * The IKE SA always processes requests. | |||
1518 | * | |||
1519 | * XXX: except further down where the code creates a | |||
1520 | * new state when CREATE_CHILD_SA and switches to | |||
1521 | * that. | |||
1522 | * | |||
1523 | * The other quirk is with fragments; but the only | |||
1524 | * case that matters it when the IKE SA accumulating | |||
1525 | * them. | |||
1526 | */ | |||
1527 | if (md->fake_clone) { | |||
1528 | log_state(RC_LOG, &ike->sa, "IMPAIR: processing a fake (cloned) message"); | |||
1529 | } | |||
1530 | /* | |||
1531 | * Is this duplicate? | |||
1532 | * | |||
1533 | * If MD is a fragment then it isn't considered a | |||
1534 | * duplicate. | |||
1535 | */ | |||
1536 | if (is_duplicate_request(ike, md)) { | |||
1537 | return; | |||
1538 | } | |||
1539 | st = &ike->sa; | |||
1540 | break; | |||
1541 | case MESSAGE_RESPONSE: | |||
1542 | /* | |||
1543 | * This is the response to an earlier request; use the | |||
1544 | * IKE SA to find the state that initiated the | |||
1545 | * exchange (sent that request). | |||
1546 | * | |||
1547 | * If the response is a fragment then ST will be | |||
1548 | * non-NULL; is_duplicate_state() gets to figure out | |||
1549 | * if the fragments are complete or need to wait | |||
1550 | * longer. | |||
1551 | */ | |||
1552 | st = find_v2_sa_by_initiator_wip(ike, md->hdr.isa_msgid); | |||
1553 | if (md->fake_clone) { | |||
1554 | log_state(RC_LOG, &ike->sa, "IMPAIR: processing a fake (cloned) message"); | |||
1555 | } | |||
1556 | if (is_duplicate_response(ike, st, md)) { | |||
1557 | return; | |||
1558 | } | |||
1559 | pexpect(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1559, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect (logger_, here_, "%s", "st != ((void*)0)"); } assertion__; }); | |||
1560 | break; | |||
1561 | default: | |||
1562 | bad_case(v2_msg_role(md))libreswan_bad_case("v2_msg_role(md)", (v2_msg_role(md)), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 1562, }; &here; })); | |||
1563 | } | |||
1564 | ||||
1565 | /* | |||
1566 | * Now that the state that is to process the message has been | |||
1567 | * selected, switch logging to it. | |||
1568 | * | |||
1569 | * XXX: why the need to constantly pick a single winner and | |||
1570 | * switch to it? Because tests expect messages to be logged | |||
1571 | * against a specific state. It would be better of that code | |||
1572 | * specified that state as a parameter. | |||
1573 | */ | |||
1574 | passert(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1574, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "st != ((void*)0)"); } (void) 1; }); | |||
1575 | /* XXX: debug-logging this is redundant */ | |||
1576 | ||||
1577 | /* | |||
1578 | * Have a state an and IKE SA, time to decode the payloads. | |||
1579 | */ | |||
1580 | dbg("unpacking clear payload"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("unpacking clear payload"); } }; | |||
1581 | passert(!md->message_payloads.parsed)({ _Bool assertion__ = !md->message_payloads.parsed; if (! assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1581, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_passert(logger_, here, "%s", "!md->message_payloads.parsed" ); } (void) 1; }); | |||
1582 | pexpect(v2_msg_role(md) == MESSAGE_RESPONSE ||({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_RESPONSE || md->hdr.isa_xchg != ISAKMP_v2_IKE_SA_INIT; if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1583, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "v2_msg_role(md) == MESSAGE_RESPONSE || md->hdr.isa_xchg != ISAKMP_v2_IKE_SA_INIT" ); } assertion__; }) | |||
1583 | md->hdr.isa_xchg != ISAKMP_v2_IKE_SA_INIT)({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_RESPONSE || md->hdr.isa_xchg != ISAKMP_v2_IKE_SA_INIT; if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1583, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "v2_msg_role(md) == MESSAGE_RESPONSE || md->hdr.isa_xchg != ISAKMP_v2_IKE_SA_INIT" ); } assertion__; }); | |||
1584 | md->message_payloads = | |||
1585 | ikev2_decode_payloads(ike->sa.st_logger, md, | |||
1586 | &md->message_pbs, | |||
1587 | md->hdr.isa_np); | |||
1588 | if (md->message_payloads.n != v2N_NOTHING_WRONG) { | |||
1589 | /* | |||
1590 | * Should only respond when the message is an | |||
1591 | * IKE_SA_INIT request. But that was handled above | |||
1592 | * when dealing with cookies so here, there's zero | |||
1593 | * reason to respond. | |||
1594 | * | |||
1595 | * decode calls packet code and that logs errors on | |||
1596 | * the spot | |||
1597 | */ | |||
1598 | /* already logged */ | |||
1599 | return; | |||
1600 | } | |||
1601 | ||||
1602 | ikev2_process_state_packet(ike, st, md); | |||
1603 | } | |||
1604 | ||||
1605 | /* | |||
1606 | * XXX: Hack to find the transition that would have been run if the | |||
1607 | * packet was ok, so it can be 'failed'. | |||
1608 | * | |||
1609 | * This is largely astetic. It could use the first transition but | |||
1610 | * often a later transition reads better. Perhaps the last transition | |||
1611 | * since, presumably, that is the most generic? | |||
1612 | */ | |||
1613 | ||||
1614 | static void hack_error_transition(struct state *st, struct msg_digest *md) | |||
1615 | { | |||
1616 | passert(md != NULL)({ _Bool assertion__ = md != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1616, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "md != ((void*)0)"); } (void) 1; }); | |||
1617 | const struct v2_state_transition *transition; | |||
1618 | const struct finite_state *state = st->st_state; | |||
1619 | switch (state->kind) { | |||
1620 | case STATE_V2_PARENT_R1: | |||
1621 | /* | |||
1622 | * Responding to either an IKE_INTERMEDIATE or | |||
1623 | * IKE_AUTH request: look for the NOSKEYSEED | |||
1624 | * transitions (and prefer IKE_AUTH). | |||
1625 | * | |||
1626 | * Once SKEYSEED is off-loaded and STATE_V2_PARENT_I1 has | |||
1627 | * only one (ok, two) transition, this is no longer a | |||
1628 | * hack. | |||
1629 | */ | |||
1630 | pexpect(state->nr_transitions == 4)({ _Bool assertion__ = state->nr_transitions == 4; if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1630, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "state->nr_transitions == 4" ); } assertion__; }); | |||
1631 | if (md->hdr.isa_xchg == ISAKMP_v2_IKE_INTERMEDIATE) { | |||
1632 | transition = &state->v2_transitions[2]; | |||
1633 | pexpect(transition->recv_type == ISAKMP_v2_IKE_INTERMEDIATE)({ _Bool assertion__ = transition->recv_type == ISAKMP_v2_IKE_INTERMEDIATE ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1633, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->recv_type == ISAKMP_v2_IKE_INTERMEDIATE" ); } assertion__; }); | |||
1634 | pexpect(transition->next_state == STATE_V2_PARENT_R1)({ _Bool assertion__ = transition->next_state == STATE_V2_PARENT_R1 ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1634, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->next_state == STATE_V2_PARENT_R1" ); } assertion__; }); | |||
1635 | } else { | |||
1636 | transition = &state->v2_transitions[3]; | |||
1637 | pexpect(transition->recv_type == ISAKMP_v2_IKE_AUTH)({ _Bool assertion__ = transition->recv_type == ISAKMP_v2_IKE_AUTH ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1637, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->recv_type == ISAKMP_v2_IKE_AUTH" ); } assertion__; }); | |||
1638 | pexpect(transition->next_state == STATE_V2_ESTABLISHED_IKE_SA)({ _Bool assertion__ = transition->next_state == STATE_V2_ESTABLISHED_IKE_SA ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1638, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->next_state == STATE_V2_ESTABLISHED_IKE_SA" ); } assertion__; }); | |||
1639 | } | |||
1640 | pexpect((transition->flags & SMF2_NO_SKEYSEED) == 0)({ _Bool assertion__ = (transition->flags & SMF2_NO_SKEYSEED ) == 0; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 1640, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "(transition->flags & SMF2_NO_SKEYSEED) == 0" ); } assertion__; }); | |||
1641 | pexpect(transition->state == STATE_V2_PARENT_R1)({ _Bool assertion__ = transition->state == STATE_V2_PARENT_R1 ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1641, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->state == STATE_V2_PARENT_R1" ); } assertion__; }); | |||
1642 | break; | |||
1643 | case STATE_V2_PARENT_I2: | |||
1644 | { | |||
1645 | /* | |||
1646 | * Receiving IKE_AUTH response: it is buried deep | |||
1647 | * down; would adding an extra transition that always | |||
1648 | * matches be better? | |||
1649 | */ | |||
1650 | unsigned transition_nr = 1; | |||
1651 | pexpect(state->nr_transitions > transition_nr)({ _Bool assertion__ = state->nr_transitions > transition_nr ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1651, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "state->nr_transitions > transition_nr" ); } assertion__; }); | |||
1652 | transition = &state->v2_transitions[transition_nr]; | |||
1653 | pexpect(transition->state == STATE_V2_PARENT_I2)({ _Bool assertion__ = transition->state == STATE_V2_PARENT_I2 ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1653, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->state == STATE_V2_PARENT_I2" ); } assertion__; }); | |||
1654 | pexpect(transition->next_state == STATE_V2_ESTABLISHED_IKE_SA)({ _Bool assertion__ = transition->next_state == STATE_V2_ESTABLISHED_IKE_SA ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1654, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->next_state == STATE_V2_ESTABLISHED_IKE_SA" ); } assertion__; }); | |||
1655 | break; | |||
1656 | } | |||
1657 | default: | |||
1658 | if (/*pexpect*/(state->nr_transitions > 0)) { | |||
1659 | transition = &state->v2_transitions[state->nr_transitions - 1]; | |||
1660 | } else { | |||
1661 | static const struct v2_state_transition undefined_transition = { | |||
1662 | .story = "suspect message", | |||
1663 | .state = STATE_UNDEFINED, | |||
1664 | .next_state = STATE_UNDEFINED, | |||
1665 | }; | |||
1666 | transition = &undefined_transition; | |||
1667 | } | |||
1668 | break; | |||
1669 | } | |||
1670 | /*pexpect(st->st_v2_transition == NULL);*/ | |||
1671 | st->st_v2_transition = transition; | |||
1672 | } | |||
1673 | ||||
1674 | /* | |||
1675 | * The SA the message is intended for has also been identified. | |||
1676 | * Continue ... | |||
1677 | * | |||
1678 | * XXX: Well except for a CREATE_CHILD_SA request where, after further | |||
1679 | * processing the SA may get created. Should this message instead be | |||
1680 | * sent to the IKE SA, which can then create a WIP child? | |||
1681 | */ | |||
1682 | ||||
1683 | void ikev2_process_state_packet(struct ike_sa *ike, struct state *st, | |||
1684 | struct msg_digest *md) | |||
1685 | { | |||
1686 | passert(ike != NULL)({ _Bool assertion__ = ike != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1686, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "ike != ((void*)0)"); } ( void) 1; }); | |||
1687 | passert(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 1687, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "st != ((void*)0)"); } (void) 1; }); | |||
1688 | ||||
1689 | /* | |||
1690 | * There is no "struct state" object if-and-only-if we're | |||
1691 | * responding to a shiny new SA_INIT message. The start-state | |||
1692 | * transition will (probably) create the object. | |||
1693 | * | |||
1694 | * But what about when pluto, as the initial responder, is | |||
1695 | * fending of an attack attack by sending back and requiring | |||
1696 | * cookies - won't the cookie need a "struct state"? | |||
1697 | * According to the RFC: no. Instead a small table of | |||
1698 | * constants can be used to generate cookies on the fly. | |||
1699 | */ | |||
1700 | const struct finite_state *from_state = st->st_state; | |||
1701 | dbg("#%lu in state %s: %s", st->st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu in state %s: %s", st->st_serialno, from_state ->short_name, from_state->story); } } | |||
1702 | from_state->short_name, from_state->story){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu in state %s: %s", st->st_serialno, from_state ->short_name, from_state->story); } }; | |||
1703 | ||||
1704 | struct ikev2_payload_errors message_payload_status = { .bad = false0 }; | |||
1705 | struct ikev2_payload_errors encrypted_payload_status = { .bad = false0 }; | |||
1706 | ||||
1707 | const enum isakmp_xchg_type ix = md->hdr.isa_xchg; | |||
1708 | ||||
1709 | /* | |||
1710 | * XXX: Unlike find_v2_state_transition(), the below scans | |||
1711 | * every single state transition and then, in the case of a | |||
1712 | * CREATE_CHILD_SA, ignores the "from" state. | |||
1713 | * | |||
1714 | * XXX: Unlike find_v2_state_transition(), this code detects | |||
1715 | * and decrypts packets and fragments in the middle of the | |||
1716 | * lookup. Being more aggressive with decrypting fragments | |||
1717 | * will likely force that logic to be moved to before this | |||
1718 | * lookup. | |||
1719 | */ | |||
1720 | ||||
1721 | const struct v2_state_transition *svm; | |||
1722 | for (svm = v2_state_transition_table; svm->state != STATE_IKEv2_ROOF; | |||
1723 | svm++) { | |||
1724 | ||||
1725 | /* | |||
1726 | * Does the message match the state transition? | |||
1727 | */ | |||
1728 | if (svm->recv_type != ix) { | |||
1729 | continue; | |||
1730 | } | |||
1731 | if (svm->recv_role != v2_msg_role(md)) { | |||
1732 | continue; | |||
1733 | } | |||
1734 | ||||
1735 | /* | |||
1736 | * Does the from state match the SA's current state? | |||
1737 | * | |||
1738 | * XXX: Eventually this part won't be needed as each | |||
1739 | * state will have its own list of transitions. See | |||
1740 | * find_v2_state_transition() which is currently only | |||
1741 | * used by IKES_SA_INIT. | |||
1742 | * | |||
1743 | * Unfortunately ... | |||
1744 | * | |||
1745 | * For CREATE_CHILD_SA, the responder ignores the | |||
1746 | * .from_state and instead applies some other magic | |||
1747 | * (the .from_state ends up being used when creating | |||
1748 | * the Child SA). | |||
1749 | */ | |||
1750 | if (ix == ISAKMP_v2_CREATE_CHILD_SA && | |||
1751 | /* matched above */ svm->recv_role == MESSAGE_REQUEST) { | |||
1752 | dbg("potential CREATE_CHILD_SA responder stumbling through to process_v2_child_ix()"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("potential CREATE_CHILD_SA responder stumbling through to process_v2_child_ix()" ); } }; | |||
1753 | } else if (svm->state != from_state->kind) { | |||
1754 | continue; | |||
1755 | } | |||
1756 | ||||
1757 | /* | |||
1758 | * Check the message payloads are as expected. | |||
1759 | */ | |||
1760 | pexpect(md->message_payloads.parsed)({ _Bool assertion__ = md->message_payloads.parsed; if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1760, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "md->message_payloads.parsed" ); } assertion__; }); | |||
1761 | struct ikev2_payload_errors message_payload_errors | |||
1762 | = ikev2_verify_payloads(md, &md->message_payloads, | |||
1763 | &svm->message_payloads); | |||
1764 | if (message_payload_errors.bad) { | |||
1765 | /* Save this failure for later logging. */ | |||
1766 | message_payload_status = message_payload_errors; | |||
1767 | continue; | |||
1768 | } | |||
1769 | ||||
1770 | /* | |||
1771 | * If there is no SK (or SKF) payload then checking is | |||
1772 | * complete and things have matched. | |||
1773 | * | |||
1774 | * (.seen&(P(SK)|P(SKF))!=0 is equivalent. | |||
1775 | */ | |||
1776 | if (!(svm->message_payloads.required & P(SK)((lset_t)1 << (ISAKMP_NEXT_v2SK)))) { | |||
1777 | break; | |||
1778 | } | |||
1779 | ||||
1780 | /* | |||
1781 | * Since the encrypted payload appears plausible, deal | |||
1782 | * with fragmentation. | |||
1783 | */ | |||
1784 | if (!md->encrypted_payloads.parsed) { | |||
1785 | /* | |||
1786 | * Deal with fragmentation. The function | |||
1787 | * returns FALSE either when there are more | |||
1788 | * fragments, the fragment is corrupt, the | |||
1789 | * fragment is a duplicate, or the fragment | |||
1790 | * count changed (it also drops all | |||
1791 | * fragments). Either way stop processing. | |||
1792 | * | |||
1793 | * Only upon _first_ arrival of the last | |||
1794 | * fragment, does the function return TRUE. | |||
1795 | * The the processing flow below can then | |||
1796 | * continue to the SKEYSEED check. | |||
1797 | * | |||
1798 | * However, if SKEYSEED (g^{xy}) needed to be | |||
1799 | * computed then this code will be re-entered | |||
1800 | * with all fragments present (so "the" | |||
1801 | * function should not be called). | |||
1802 | */ | |||
1803 | struct v2_incoming_fragments *frags = | |||
1804 | ike->sa.st_v2_incoming[v2_msg_role(md)]; | |||
1805 | bool_Bool have_all_fragments = | |||
1806 | (frags != NULL((void*)0) && frags->count == frags->total); | |||
1807 | /* | |||
1808 | * XXX: Because fragments are only checked | |||
1809 | * all-at-once after they have all arrived, a | |||
1810 | * single corrupt fragment will cause all | |||
1811 | * fragments being thrown away, and the entire | |||
1812 | * process re-start (Is this tested?) | |||
1813 | * | |||
1814 | * XXX: This code should instead check | |||
1815 | * fragments as they arrive. That means | |||
1816 | * kicking off the g^{xy} calculation in the | |||
1817 | * background (if it were in the foreground, | |||
1818 | * the fragments would be dropped). Later. | |||
1819 | */ | |||
1820 | if (md->message_payloads.present & P(SKF)((lset_t)1 << (ISAKMP_NEXT_v2SKF))) { | |||
1821 | if (have_all_fragments) { | |||
1822 | dbg("already have all fragments, skipping fragment collection"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("already have all fragments, skipping fragment collection" ); } }; | |||
1823 | } else if (!ikev2_collect_fragment(md, ike)) { | |||
1824 | return; | |||
1825 | } | |||
1826 | } | |||
1827 | /* | |||
1828 | * For this state transition, does it only | |||
1829 | * apply when there's no SKEYSEED? If so, and | |||
1830 | * SKEYSEED is missing, then things match; else | |||
1831 | * things can't match. | |||
1832 | */ | |||
1833 | if (svm->flags & SMF2_NO_SKEYSEED) { | |||
1834 | if (ike->sa.hidden_variables.st_skeyid_calculated) { | |||
1835 | continue; | |||
1836 | } else { | |||
1837 | break; | |||
1838 | } | |||
1839 | } | |||
1840 | /* | |||
1841 | * XXX: Shouldn't reach this point without | |||
1842 | * SKEYSEED so bail if somehow that hasn't | |||
1843 | * happened. No point in even calling | |||
1844 | * ikev2_decrypt_msg() (it will also fail). | |||
1845 | * | |||
1846 | * Suspect it would be cleaner if the state | |||
1847 | * machine included an explicit SMF2_SKEYSEED | |||
1848 | * flag and all states requiring integrity | |||
1849 | * were marked with that. Currently P(SK) and | |||
1850 | * P(SKF) imply this. | |||
1851 | */ | |||
1852 | if (!pexpect(ike->sa.hidden_variables.st_skeyid_calculated)({ _Bool assertion__ = ike->sa.hidden_variables.st_skeyid_calculated ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 1852, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike->sa.hidden_variables.st_skeyid_calculated" ); } assertion__; })) { | |||
1853 | return; | |||
1854 | } | |||
1855 | /* | |||
1856 | * Decrypt the packet, checking it for | |||
1857 | * integrity. Anything lacking integrity is | |||
1858 | * dropped. | |||
1859 | */ | |||
1860 | if (!ikev2_decrypt_msg(ike, md)) { | |||
1861 | log_state(RC_LOG, &ike->sa, | |||
1862 | "encrypted payload seems to be corrupt; dropping packet"); | |||
1863 | return; | |||
1864 | } | |||
1865 | /* | |||
1866 | * The message is protected - the integrity | |||
1867 | * check passed - so it was definitely sent by | |||
1868 | * the other end of the secured IKE SA. | |||
1869 | * | |||
1870 | * However, for an AUTH packet, the other end | |||
1871 | * hasn't yet been authenticated (and an | |||
1872 | * INFORMATIONAL exchange immediately | |||
1873 | * following AUTH be due to failed | |||
1874 | * authentication). | |||
1875 | * | |||
1876 | * If there's something wrong with the message | |||
1877 | * contents, then the IKE SA gets abandoned, | |||
1878 | * but a new new one may be initiated. | |||
1879 | * | |||
1880 | * See "2.21.2. Error Handling in IKE_AUTH" | |||
1881 | * and "2.21.3. Error Handling after IKE SA | |||
1882 | * is Authenticated". | |||
1883 | * | |||
1884 | * For UNSUPPORTED_CRITICAL_PAYLOAD, while the | |||
1885 | * RFC clearly states that for the initial | |||
1886 | * exchanges and an INFORMATIONAL exchange | |||
1887 | * immediately following, the notification | |||
1888 | * causes a delete, it says nothing for | |||
1889 | * exchanges that follow. | |||
1890 | * | |||
1891 | * For moment treat it the same. Given the | |||
1892 | * PAYLOAD ID that should identify the problem | |||
1893 | * isn't being returned this is the least of | |||
1894 | * our problems. | |||
1895 | */ | |||
1896 | struct payload_digest *sk = md->chain[ISAKMP_NEXT_v2SK]; | |||
1897 | md->encrypted_payloads = ikev2_decode_payloads(ike->sa.st_logger, md, &sk->pbs, | |||
1898 | sk->payload.generic.isag_np); | |||
1899 | if (md->encrypted_payloads.n != v2N_NOTHING_WRONG) { | |||
1900 | /* | |||
1901 | * XXX: Hack to get the | |||
1902 | * transition that would have | |||
1903 | * been run so it can be | |||
1904 | * 'failed'. | |||
1905 | */ | |||
1906 | hack_error_transition(st, md); | |||
1907 | switch (v2_msg_role(md)) { | |||
1908 | case MESSAGE_REQUEST: | |||
1909 | /* | |||
1910 | * Send back a protected error | |||
1911 | * response. Need to first | |||
1912 | * put the IKE SA into | |||
1913 | * responder mode. | |||
1914 | */ | |||
1915 | v2_msgid_start_responder(ike, st, md); | |||
1916 | chunk_t data = chunk2(md->encrypted_payloads.data, | |||
1917 | md->encrypted_payloads.data_size); | |||
1918 | record_v2N_response(st->st_logger, ike, md, | |||
1919 | md->encrypted_payloads.n, &data, | |||
1920 | ENCRYPTED_PAYLOAD); | |||
1921 | break; | |||
1922 | case MESSAGE_RESPONSE: | |||
1923 | /* | |||
1924 | * Can't respond so kill the | |||
1925 | * IKE SA. The secured | |||
1926 | * message contained crap so | |||
1927 | * there's little that can be | |||
1928 | * done. | |||
1929 | */ | |||
1930 | break; | |||
1931 | default: | |||
1932 | bad_case(v2_msg_role(md))libreswan_bad_case("v2_msg_role(md)", (v2_msg_role(md)), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 1932, }; &here; })); | |||
1933 | } | |||
1934 | complete_v2_state_transition(st, md, STF_FATAL); | |||
1935 | return; | |||
1936 | } | |||
1937 | } /* else { go ahead } */ | |||
1938 | struct ikev2_payload_errors encrypted_payload_errors | |||
1939 | = ikev2_verify_payloads(md, &md->encrypted_payloads, | |||
1940 | &svm->encrypted_payloads); | |||
1941 | if (encrypted_payload_errors.bad) { | |||
1942 | /* Save this failure for later logging. */ | |||
1943 | encrypted_payload_status = encrypted_payload_errors; | |||
1944 | continue; | |||
1945 | } | |||
1946 | ||||
1947 | if (svm->state != from_state->kind && ix == ISAKMP_v2_CREATE_CHILD_SA) { | |||
1948 | /* | |||
1949 | * The IKE SA is receiving a CREATE_CHILD_SA | |||
1950 | * request. Unlike STATE_V2_PARENT_R0 (and the | |||
1951 | * initial responder) the R0 state isn't | |||
1952 | * obvious - rekey IKE SA, rekey CHILD SA, and | |||
1953 | * create CHILD SA are all slightly different. | |||
1954 | * | |||
1955 | * The code deals with this by ignoring the | |||
1956 | * from_state, and then later, forcing MD's | |||
1957 | * from state to values in the table. | |||
1958 | */ | |||
1959 | dbg("state #%lu forced to match CREATE_CHILD_SA from %s->%s by ignoring from state",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu forced to match CREATE_CHILD_SA from %s->%s by ignoring from state" , st->st_serialno, finite_states[svm->state]->name, finite_states [svm->next_state]->name); } } | |||
1960 | st->st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu forced to match CREATE_CHILD_SA from %s->%s by ignoring from state" , st->st_serialno, finite_states[svm->state]->name, finite_states [svm->next_state]->name); } } | |||
1961 | finite_states[svm->state]->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu forced to match CREATE_CHILD_SA from %s->%s by ignoring from state" , st->st_serialno, finite_states[svm->state]->name, finite_states [svm->next_state]->name); } } | |||
1962 | finite_states[svm->next_state]->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu forced to match CREATE_CHILD_SA from %s->%s by ignoring from state" , st->st_serialno, finite_states[svm->state]->name, finite_states [svm->next_state]->name); } }; | |||
1963 | } | |||
1964 | ||||
1965 | /* must be the right state machine entry */ | |||
1966 | break; | |||
1967 | } | |||
1968 | ||||
1969 | dbg("selected state microcode %s", svm->story){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("selected state microcode %s", svm->story); } }; | |||
1970 | ||||
1971 | /* no useful state microcode entry? */ | |||
1972 | if (svm->state == STATE_IKEv2_ROOF) { | |||
1973 | /* count all the error notifications */ | |||
1974 | for (struct payload_digest *ntfy = md->chain[ISAKMP_NEXT_v2N]; | |||
1975 | ntfy != NULL((void*)0); ntfy = ntfy->next) { | |||
1976 | pstat(ikev2_recv_notifies_e, ntfy->payload.v2n.isan_type){ const unsigned pstat_ = (ntfy->payload.v2n.isan_type); const struct pluto_stat *ps_ = &pstats_ikev2_recv_notifies_e; if (pstat_ < ps_->floor || pstat_ >= ps_->roof) { ps_ ->count[ps_->roof - ps_->floor]++; } else { ps_-> count[pstat_-ps_->floor]++; } }; | |||
1977 | } | |||
1978 | /* | |||
1979 | * All branches: log error, [complete transition] | |||
1980 | * (why), return so first error wins. | |||
1981 | */ | |||
1982 | if (message_payload_status.bad) { | |||
1983 | /* | |||
1984 | * A very messed up message - none of the | |||
1985 | * state transitions recognized it!. | |||
1986 | */ | |||
1987 | log_v2_payload_errors(st->st_logger, md, | |||
1988 | &message_payload_status); | |||
1989 | return; | |||
1990 | } | |||
1991 | if (encrypted_payload_status.bad) { | |||
1992 | /* | |||
1993 | * Payload decrypted and integrity was ok but | |||
1994 | * contents weren't valid. | |||
1995 | * | |||
1996 | * XXX: According to "2.21.2. Error Handling | |||
1997 | * in IKE_AUTH" and "2.21.3. Error Handling | |||
1998 | * after IKE SA is Authenticated" this should | |||
1999 | * be fatal, killing the IKE SA. Oops. | |||
2000 | * | |||
2001 | * XXX: how can one complete a state | |||
2002 | * transition on something that was never | |||
2003 | * started? Since this is fatal, the state | |||
2004 | * needs to be deleted. | |||
2005 | * | |||
2006 | * XXX: an alternative would be to treat this | |||
2007 | * like some new but as-of-yet not supported | |||
2008 | * message combination so just ignore it (but | |||
2009 | * update Message IDs). | |||
2010 | */ | |||
2011 | log_v2_payload_errors(st->st_logger, md, | |||
2012 | &encrypted_payload_status); | |||
2013 | /* | |||
2014 | * XXX: Hack to get the transition | |||
2015 | * that would have been run so it can | |||
2016 | * be 'failed'. | |||
2017 | */ | |||
2018 | hack_error_transition(st, md); | |||
2019 | switch (v2_msg_role(md)) { | |||
2020 | case MESSAGE_REQUEST: | |||
2021 | /* | |||
2022 | * Send back a protected error | |||
2023 | * response. Need to first put the | |||
2024 | * IKE SA into responder mode. | |||
2025 | */ | |||
2026 | v2_msgid_start_responder(ike, st, md); | |||
2027 | record_v2N_response(st->st_logger, ike, md, | |||
2028 | v2N_INVALID_SYNTAX, NULL((void*)0), | |||
2029 | ENCRYPTED_PAYLOAD); | |||
2030 | break; | |||
2031 | case MESSAGE_RESPONSE: | |||
2032 | /* | |||
2033 | * Can't respond so kill the IKE SA - | |||
2034 | * the secured message contained crap | |||
2035 | * so there's little that can be done. | |||
2036 | */ | |||
2037 | break; | |||
2038 | default: | |||
2039 | bad_case(v2_msg_role(md))libreswan_bad_case("v2_msg_role(md)", (v2_msg_role(md)), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 2039, }; &here; })); | |||
2040 | } | |||
2041 | /* XXX: calls delete_state() */ | |||
2042 | complete_v2_state_transition(st, md, STF_FATAL); | |||
2043 | return; | |||
2044 | } | |||
2045 | /* | |||
2046 | * Presumably things are pretty messed up. While | |||
2047 | * there might be a state there probably isn't an | |||
2048 | * established IKE SA (so don't even consider trying | |||
2049 | * to send an encrypted response), for instance: | |||
2050 | * | |||
2051 | * - instead of an IKE_AUTH request, the initiator | |||
2052 | * sends something totally unexpected (such as an | |||
2053 | * informational) and things end up here | |||
2054 | * | |||
2055 | * - when an IKE_AUTH request's IKE SA succeeeds but | |||
2056 | * CHILD SA fails (and pluto screws up the IKE SA by | |||
2057 | * updating its state but not its Message ID and not | |||
2058 | * responding), the re-transmitted IKE_AUTH ends up | |||
2059 | * here | |||
2060 | * | |||
2061 | * If a request, should it send an un-encrypted | |||
2062 | * v2N_INVALID_SYNTAX? | |||
2063 | */ | |||
2064 | log_state(RC_LOG, &ike->sa, "no useful state microcode entry found for incoming packet"); | |||
2065 | /* "dropping message with no matching microcode" */ | |||
2066 | return; | |||
2067 | } | |||
2068 | ||||
2069 | if (ix == ISAKMP_v2_CREATE_CHILD_SA) { | |||
2070 | /* | |||
2071 | * XXX: This code was embedded in the end of the FSM | |||
2072 | * search loop. Since it was always executed when the | |||
2073 | * state matches, move it out of the loop. Suspect | |||
2074 | * this, and the code below, really belong in the | |||
2075 | * state transition function proper. | |||
2076 | */ | |||
2077 | /* going to switch to child st. before that update parent */ | |||
2078 | if (!LHAS(ike->sa.hidden_variables.st_nat_traversal, NATED_HOST)(((ike->sa.hidden_variables.st_nat_traversal) & ((lset_t )1 << (NATED_HOST))) != ((lset_t)0))) | |||
2079 | update_ike_endpoints(ike, md); | |||
2080 | ||||
2081 | /* bit further processing of create CREATE_CHILD_SA exchange */ | |||
2082 | ||||
2083 | /* | |||
2084 | * let's get a child state either new or existing to | |||
2085 | * proceed | |||
2086 | */ | |||
2087 | struct child_sa *child; | |||
2088 | if (v2_msg_role(md) == MESSAGE_RESPONSE) { | |||
2089 | child = pexpect_child_sa(st); | |||
2090 | } else { | |||
2091 | pexpect(IS_IKE_SA(st))({ _Bool assertion__ = ((st)->st_clonedfrom == 0); if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2091, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "((st)->st_clonedfrom == 0)" ); } assertion__; }); | |||
2092 | child = process_v2_child_ix(ike, svm); | |||
2093 | } | |||
2094 | ||||
2095 | /* | |||
2096 | * Switch to child state (possibly from the same child | |||
2097 | * state, see above) | |||
2098 | */ | |||
2099 | dbg("forcing ST #%lu to CHILD #%lu.#%lu in FSM processor",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("forcing ST #%lu to CHILD #%lu.#%lu in FSM processor" , st->st_serialno, ike->sa.st_serialno, child->sa.st_serialno ); } } | |||
2100 | st->st_serialno, ike->sa.st_serialno, child->sa.st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("forcing ST #%lu to CHILD #%lu.#%lu in FSM processor" , st->st_serialno, ike->sa.st_serialno, child->sa.st_serialno ); } }; | |||
2101 | st = &child->sa; | |||
2102 | } | |||
2103 | ||||
2104 | v2_dispatch(ike, st, md, svm); | |||
2105 | } | |||
2106 | ||||
2107 | void v2_dispatch(struct ike_sa *ike, struct state *st, | |||
2108 | struct msg_digest *md, | |||
2109 | const struct v2_state_transition *svm) | |||
2110 | { | |||
2111 | md->svm = svm; | |||
2112 | ||||
2113 | /* | |||
2114 | * For the responder, update the work-in-progress Message ID | |||
2115 | * window (since work has commenced). | |||
2116 | * | |||
2117 | * Exclude the SKEYSEED calculation - the message has yet to | |||
2118 | * be decrypted so true work on the message is yet to comence. | |||
2119 | */ | |||
2120 | if (v2_msg_role(md) == MESSAGE_REQUEST && | |||
2121 | !(svm->flags & SMF2_NO_SKEYSEED)) { | |||
2122 | v2_msgid_start_responder(ike, st, md); | |||
2123 | } | |||
2124 | ||||
2125 | if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { | |||
2126 | if (pbs_left(&md->message_pbs)((size_t)((&md->message_pbs)->roof - (&md->message_pbs )->cur)) != 0) | |||
2127 | DBG_log("removing %d bytes of padding", | |||
2128 | (int) pbs_left(&md->message_pbs)((size_t)((&md->message_pbs)->roof - (&md->message_pbs )->cur))); | |||
2129 | } | |||
2130 | ||||
2131 | md->message_pbs.roof = md->message_pbs.cur; /* trim padding (not actually legit) */ | |||
2132 | ||||
2133 | dbg("calling processor %s", svm->story){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("calling processor %s", svm->story); } }; | |||
2134 | ||||
2135 | /* | |||
2136 | * XXX: for now pass in the possibly NULL child; suspect a | |||
2137 | * better model is to drop the child and instead have the IKE | |||
2138 | * SA run a nested state machine for the child. | |||
2139 | * | |||
2140 | * For instance, when a CREATE_CHILD_SA request arrives, pass | |||
2141 | * that to the IKE SA and then let it do all the create child | |||
2142 | * magic. | |||
2143 | */ | |||
2144 | so_serial_t old_st = st->st_serialno; | |||
2145 | ||||
2146 | statetime_t start = statetime_start(st); | |||
2147 | struct child_sa *child = IS_CHILD_SA(st)((st)->st_clonedfrom != 0) ? pexpect_child_sa(st) : NULL((void*)0); | |||
2148 | /* danger: st may not be valid */ | |||
2149 | stf_status e = svm->processor(ike, child, md); | |||
2150 | ||||
2151 | if (e == STF_SKIP_COMPLETE_STATE_TRANSITION) { | |||
2152 | /* | |||
2153 | * Danger! Processor did something dodgy like free ST! | |||
2154 | */ | |||
2155 | dbg("processor '%s' for #%lu suppresed complete st_v2_transition",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("processor '%s' for #%lu suppresed complete st_v2_transition" , svm->story, old_st); } } | |||
2156 | svm->story, old_st){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("processor '%s' for #%lu suppresed complete st_v2_transition" , svm->story, old_st); } }; | |||
2157 | } else { | |||
2158 | complete_v2_state_transition(st, md, e); | |||
2159 | } | |||
2160 | ||||
2161 | statetime_stop(&start, "processing: %s in %s()", svm->story, __func__); | |||
2162 | /* our caller with release_any_md(mdp) */ | |||
2163 | } | |||
2164 | ||||
2165 | /* | |||
2166 | * This logs to the main log the authentication and encryption keys | |||
2167 | * for an IKEv2 SA. This is done in a format that is compatible with | |||
2168 | * tcpdump 4.0's -E option. | |||
2169 | * | |||
2170 | * The log message will require that a cut command is used to remove | |||
2171 | * the initial text. | |||
2172 | * | |||
2173 | * DANGER: this intentionally leaks cryptographic secrets. | |||
2174 | */ | |||
2175 | void ikev2_log_parentSA(const struct state *st) | |||
2176 | { | |||
2177 | if (DBGP(DBG_PRIVATE)(cur_debugging & (((lset_t)1 << (DBG_PRIVATE_IX))))) { | |||
2178 | if (st->st_oakley.ta_integ == NULL((void*)0) || | |||
2179 | st->st_oakley.ta_encrypt == NULL((void*)0)) | |||
2180 | return; | |||
2181 | ||||
2182 | /* format initiator SPI */ | |||
2183 | char tispi[3 + 2*IKE_SA_SPI_SIZE8]; | |||
2184 | (void)datatot(st->st_ike_spis.initiator.bytes, sizeof(st->st_ike_spis.initiator.bytes), | |||
2185 | 'x', | |||
2186 | tispi, sizeof(tispi)); | |||
2187 | ||||
2188 | /* format responder SPI */ | |||
2189 | char trspi[3 + 2*IKE_SA_SPI_SIZE8]; | |||
2190 | (void)datatot(st->st_ike_spis.responder.bytes, sizeof(st->st_ike_spis.responder.bytes), | |||
2191 | 'x', | |||
2192 | trspi, sizeof(trspi)); | |||
2193 | ||||
2194 | const char *authalgo = st->st_oakley.ta_integ->integ_tcpdump_name; | |||
2195 | const char *encalgo = st->st_oakley.ta_encrypt->encrypt_tcpdump_name; | |||
2196 | ||||
2197 | /* | |||
2198 | * Text of encryption key length (suffix for encalgo). | |||
2199 | * No more than 3 digits, but compiler fears it might be 5. | |||
2200 | */ | |||
2201 | char tekl[6] = ""; | |||
2202 | if (st->st_oakley.enckeylen != 0) | |||
2203 | snprintf(tekl, sizeof(tekl), "%u", | |||
2204 | st->st_oakley.enckeylen); | |||
2205 | ||||
2206 | /* v2 IKE authentication key for initiator (256 bit bound) */ | |||
2207 | chunk_t ai = chunk_from_symkey("ai", st->st_skey_ai_nss, | |||
2208 | st->st_logger); | |||
2209 | char tai[3 + 2 * BYTES_FOR_BITS(256)(((256) + 8 - 1) / 8)] = ""; | |||
2210 | (void)datatot(ai.ptr, ai.len, 'x', tai, sizeof(tai)); | |||
2211 | free_chunk_content(&ai); | |||
2212 | ||||
2213 | /* v2 IKE encryption key for initiator (256 bit bound) */ | |||
2214 | chunk_t ei = chunk_from_symkey("ei", st->st_skey_ei_nss, | |||
2215 | st->st_logger); | |||
2216 | char tei[3 + 2 * BYTES_FOR_BITS(256)(((256) + 8 - 1) / 8)] = ""; | |||
2217 | (void)datatot(ei.ptr, ei.len, 'x', tei, sizeof(tei)); | |||
2218 | free_chunk_content(&ei); | |||
2219 | ||||
2220 | DBG_log("ikev2 I %s %s %s:%s %s%s:%s", | |||
2221 | tispi, trspi, | |||
2222 | authalgo, tai, | |||
2223 | encalgo, tekl, tei); | |||
2224 | ||||
2225 | /* v2 IKE authentication key for responder (256 bit bound) */ | |||
2226 | chunk_t ar = chunk_from_symkey("ar", st->st_skey_ar_nss, | |||
2227 | st->st_logger); | |||
2228 | char tar[3 + 2 * BYTES_FOR_BITS(256)(((256) + 8 - 1) / 8)] = ""; | |||
2229 | (void)datatot(ar.ptr, ar.len, 'x', tar, sizeof(tar)); | |||
2230 | free_chunk_content(&ar); | |||
2231 | ||||
2232 | /* v2 IKE encryption key for responder (256 bit bound) */ | |||
2233 | chunk_t er = chunk_from_symkey("er", st->st_skey_er_nss, | |||
2234 | st->st_logger); | |||
2235 | char ter[3 + 2 * BYTES_FOR_BITS(256)(((256) + 8 - 1) / 8)] = ""; | |||
2236 | (void)datatot(er.ptr, er.len, 'x', ter, sizeof(ter)); | |||
2237 | free_chunk_content(&er); | |||
2238 | ||||
2239 | DBG_log("ikev2 R %s %s %s:%s %s%s:%s", | |||
2240 | tispi, trspi, | |||
2241 | authalgo, tar, | |||
2242 | encalgo, tekl, ter); | |||
2243 | } | |||
2244 | } | |||
2245 | ||||
2246 | static void ikev2_child_emancipate(struct ike_sa *from, struct child_sa *to, | |||
2247 | const struct v2_state_transition *transition) | |||
2248 | { | |||
2249 | /* initialize the the new IKE SA. reset and message ID */ | |||
2250 | to->sa.st_clonedfrom = SOS_NOBODY0; | |||
2251 | v2_msgid_init_ike(pexpect_ike_sa(&to->sa)); | |||
2252 | ||||
2253 | /* Switch to the new IKE SPIs */ | |||
2254 | to->sa.st_ike_spis = to->sa.st_ike_rekey_spis; | |||
2255 | rehash_state_cookies_in_db(&to->sa); | |||
2256 | ||||
2257 | /* TO has correct IKE_SPI so can migrate */ | |||
2258 | v2_migrate_children(from, to); | |||
2259 | ||||
2260 | dbg("moving over any pending requests"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("moving over any pending requests"); } }; | |||
2261 | v2_msgid_migrate_queue(from, to); | |||
2262 | ||||
2263 | /* child is now a parent */ | |||
2264 | ikev2_ike_sa_established(pexpect_ike_sa(&to->sa), | |||
2265 | transition, transition->next_state); | |||
2266 | } | |||
2267 | ||||
2268 | static void jam_v2_ike_details(struct jambuf *buf, struct state *st) | |||
2269 | { | |||
2270 | jam_parent_sa_details(buf, st); | |||
2271 | } | |||
2272 | ||||
2273 | static void success_v2_state_transition(struct state *st, struct msg_digest *md, | |||
2274 | const struct v2_state_transition *transition) | |||
2275 | { | |||
2276 | /* | |||
2277 | * XXX: the transition's from state can lie - it may be | |||
2278 | * different to the ST's state! | |||
2279 | */ | |||
2280 | enum state_kind from_state = transition->state; | |||
2281 | struct connection *c = st->st_connection; | |||
2282 | struct ike_sa *ike = ike_sa(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2282, }; &here; })); | |||
2283 | ||||
2284 | if (from_state != transition->next_state) { | |||
2285 | dbg("transitioning from state %s to state %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("transitioning from state %s to state %s", finite_states [from_state]->name, finite_states[transition->next_state ]->name); } } | |||
2286 | finite_states[from_state]->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("transitioning from state %s to state %s", finite_states [from_state]->name, finite_states[transition->next_state ]->name); } } | |||
2287 | finite_states[transition->next_state]->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("transitioning from state %s to state %s", finite_states [from_state]->name, finite_states[transition->next_state ]->name); } }; | |||
2288 | } | |||
2289 | ||||
2290 | /* | |||
2291 | * Update counters, and if part of the transition, send the | |||
2292 | * new message. | |||
2293 | */ | |||
2294 | ||||
2295 | dbg("Message ID: updating counters for #%lu", st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("Message ID: updating counters for #%lu", st-> st_serialno); } }; | |||
2296 | v2_msgid_update_recv(ike, st, md); | |||
2297 | v2_msgid_update_sent(ike, st, md, transition->send); | |||
2298 | ||||
2299 | bool_Bool established_before = (IS_IKE_SA_ESTABLISHED(st)((st)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA) || | |||
2300 | IS_CHILD_SA_ESTABLISHED(st)((st)->st_state->kind == STATE_V2_ESTABLISHED_CHILD_SA)); | |||
2301 | ||||
2302 | if (from_state == STATE_V2_REKEY_IKE_R0 || | |||
2303 | from_state == STATE_V2_REKEY_IKE_I1) { | |||
2304 | ikev2_child_emancipate(ike, pexpect_child_sa(st), | |||
2305 | transition); | |||
2306 | /* Emancipated ST answers to no one - it's an IKE SA */ | |||
2307 | v2_msgid_schedule_next_initiator(pexpect_ike_sa(st)); | |||
2308 | } else { | |||
2309 | change_state(st, transition->next_state); | |||
2310 | v2_msgid_schedule_next_initiator(ike); | |||
2311 | } | |||
2312 | passert(st->st_state->kind >= STATE_IKEv2_FLOOR)({ _Bool assertion__ = st->st_state->kind >= STATE_IKEv2_FLOOR ; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2312, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "st->st_state->kind >= STATE_IKEv2_FLOOR" ); } (void) 1; }); | |||
2313 | passert(st->st_state->kind < STATE_IKEv2_ROOF)({ _Bool assertion__ = st->st_state->kind < STATE_IKEv2_ROOF ; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2313, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "st->st_state->kind < STATE_IKEv2_ROOF" ); } (void) 1; }); | |||
2314 | ||||
2315 | bool_Bool established_after = (IS_IKE_SA_ESTABLISHED(st)((st)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA) || | |||
2316 | IS_CHILD_SA_ESTABLISHED(st)((st)->st_state->kind == STATE_V2_ESTABLISHED_CHILD_SA)); | |||
2317 | ||||
2318 | bool_Bool just_established = (!established_before && established_after); | |||
2319 | if (just_established) { | |||
2320 | /* | |||
2321 | * Count successful transition into an established | |||
2322 | * state. | |||
2323 | */ | |||
2324 | pstat_sa_established(st); | |||
2325 | } | |||
2326 | ||||
2327 | /* | |||
2328 | * Tell whack and logs our progress. | |||
2329 | * | |||
2330 | * If it's OE or a state transition we're not telling anyone | |||
2331 | * about, then be quiet. | |||
2332 | */ | |||
2333 | ||||
2334 | dbg("announcing the state transition"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("announcing the state transition"); } }; | |||
2335 | enum rc_type w; | |||
2336 | void (*jam_details)(struct jambuf *buf, struct state *st); | |||
2337 | bool_Bool suppress_log = ((transition->flags & SMF2_SUPPRESS_SUCCESS_LOG) || | |||
2338 | (c != NULL((void*)0) && (c->policy & POLICY_OPPORTUNISTIC((lset_t)1 << (POLICY_OPPORTUNISTIC_IX))))); | |||
2339 | const char *sep = " "; | |||
2340 | if (transition->state == transition->next_state) { | |||
2341 | /* | |||
2342 | * HACK for seemingly going around in circles | |||
2343 | */ | |||
2344 | jam_details = NULL((void*)0); | |||
2345 | w = RC_NEW_V2_STATE + st->st_state->kind; | |||
2346 | } else if (IS_CHILD_SA(st)((st)->st_clonedfrom != 0) && just_established) { | |||
2347 | jam_details = jam_v2_child_details; | |||
2348 | suppress_log = false0; | |||
2349 | sep = "; "; | |||
2350 | w = RC_SUCCESS; /* also triggers detach */ | |||
2351 | } else if (IS_IKE_SA(st)((st)->st_clonedfrom == 0) && just_established) { | |||
2352 | /* ike_sa_established() called elsewhere */ | |||
2353 | jam_details = jam_v2_ike_details; | |||
2354 | w = RC_SUCCESS; /* also triggers detach */ | |||
2355 | } else if (transition->state == STATE_V2_PARENT_I1 && | |||
2356 | transition->next_state == STATE_V2_PARENT_I2) { | |||
2357 | jam_details = jam_v2_ike_details; | |||
2358 | w = RC_NEW_V2_STATE + st->st_state->kind; | |||
2359 | } else if (st->st_state->kind == STATE_V2_PARENT_R1) { | |||
2360 | jam_details = jam_v2_ike_details; | |||
2361 | w = RC_NEW_V2_STATE + st->st_state->kind; | |||
2362 | } else { | |||
2363 | jam_details = NULL((void*)0); | |||
2364 | w = RC_NEW_V2_STATE + st->st_state->kind; | |||
2365 | } | |||
2366 | ||||
2367 | if (suppress_log) { | |||
2368 | LSWDBGP(DBG_BASE, buf)for (_Bool lswlog_p = (cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))); lswlog_p; lswlog_p = 0) for (char lswbuf[( (size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) for (; buf != ((void*)0); jambuf_to_logger(buf , &failsafe_logger, DEBUG_STREAM), buf = ((void*)0)) { | |||
2369 | jam(buf, "%s", st->st_state->story); | |||
2370 | /* document SA details for admin's pleasure */ | |||
2371 | if (jam_details != NULL((void*)0)) { | |||
2372 | jam_string(buf, sep); | |||
2373 | jam_details(buf, st); | |||
2374 | } | |||
2375 | } | |||
2376 | } else { | |||
2377 | LLOG_JAMBUF(w, st->st_logger, buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf ; buf != ((void*)0); buf = ((void*)0)) for (({ if (((w) & NO_PREFIX) == ((lset_t)0) && (((w) & STREAM_MASK ) != DEBUG_STREAM || (cur_debugging & (((lset_t)1 << (DBG_ADD_PREFIX_IX)))))) { (st->st_logger)->object_vec ->jam_object_prefix(buf, (st->st_logger)->object); } }); buf != ((void*)0); jambuf_to_logger(buf, (st->st_logger ), w), buf = ((void*)0)) { | |||
2378 | jam(buf, "%s", st->st_state->story); | |||
2379 | /* document SA details for admin's pleasure */ | |||
2380 | if (jam_details != NULL((void*)0)) { | |||
2381 | jam_string(buf, sep); | |||
2382 | jam_details(buf, st); | |||
2383 | } | |||
2384 | } | |||
2385 | } | |||
2386 | ||||
2387 | /* | |||
2388 | * 2.23. NAT Traversal | |||
2389 | * | |||
2390 | * There are cases where a NAT box decides to remove mappings | |||
2391 | * that are still alive (for example, the keepalive interval | |||
2392 | * is too long, or the NAT box is rebooted). This will be | |||
2393 | * apparent to a host if it receives a packet whose integrity | |||
2394 | * protection validates, but has a different port, address, or | |||
2395 | * both from the one that was associated with the SA in the | |||
2396 | * validated packet. When such a validated packet is found, a | |||
2397 | * host that does not support other methods of recovery such | |||
2398 | * as IKEv2 Mobility and Multihoming (MOBIKE) [MOBIKE], and | |||
2399 | * that is not behind a NAT, SHOULD send all packets | |||
2400 | * (including retransmission packets) to the IP address and | |||
2401 | * port in the validated packet, and SHOULD store this as the | |||
2402 | * new address and port combination for the SA (that is, they | |||
2403 | * SHOULD dynamically update the address). A host behind a | |||
2404 | * NAT SHOULD NOT do this type of dynamic address update if a | |||
2405 | * validated packet has different port and/or address values | |||
2406 | * because it opens a possible DoS attack (such as allowing an | |||
2407 | * attacker to break the connection with a single packet). | |||
2408 | * Also, dynamic address update should only be done in | |||
2409 | * response to a new packet; otherwise, an attacker can revert | |||
2410 | * the addresses with old replayed packets. Because of this, | |||
2411 | * dynamic updates can only be done safely if replay | |||
2412 | * protection is enabled. When IKEv2 is used with MOBIKE, | |||
2413 | * dynamically updating the addresses described above | |||
2414 | * interferes with MOBIKE's way of recovering from the same | |||
2415 | * situation. See Section 3.8 of [MOBIKE] for more | |||
2416 | * information. | |||
2417 | * | |||
2418 | * XXX: so .... | |||
2419 | * | |||
2420 | * - replay protection? | |||
2421 | * | |||
2422 | * - IKE_AUTH exchange? Already handled? Exclude? | |||
2423 | */ | |||
2424 | if (nat_traversal_enabled && | |||
2425 | /* | |||
2426 | * Only when responding ... | |||
2427 | */ | |||
2428 | transition->send == MESSAGE_RESPONSE && | |||
2429 | pexpect(v2_msg_role(md) == MESSAGE_REQUEST)({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_REQUEST; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2429, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "v2_msg_role(md) == MESSAGE_REQUEST" ); } assertion__; }) && | |||
2430 | /* | |||
2431 | * Only when the request changes the remote's endpoint ... | |||
2432 | */ | |||
2433 | !endpoint_eq_endpoint(ike->sa.st_remote_endpoint, md->sender) && | |||
2434 | /* | |||
2435 | * Only when the request was protected and passes | |||
2436 | * integrity ... | |||
2437 | * | |||
2438 | * Once keymat is present, only encrypted messessages with | |||
2439 | * valid integrity can successfully complete a transaction | |||
2440 | * with STF_OK. True? True. | |||
2441 | * | |||
2442 | * IS_IKE_SA_ESTABLISHED() better? False. IKE_AUTH | |||
2443 | * messages meet the above requirements. | |||
2444 | */ | |||
2445 | ike->sa.hidden_variables.st_skeyid_calculated && | |||
2446 | md->encrypted_payloads.parsed && | |||
2447 | md->encrypted_payloads.n == v2N_NOTHING_WRONG && | |||
2448 | /* | |||
2449 | * Only when the local IKE SA isn't behind NAT but the | |||
2450 | * remote IKE SA is ... | |||
2451 | */ | |||
2452 | !LHAS(ike->sa.hidden_variables.st_nat_traversal, NATED_HOST)(((ike->sa.hidden_variables.st_nat_traversal) & ((lset_t )1 << (NATED_HOST))) != ((lset_t)0)) && | |||
2453 | LHAS(ike->sa.hidden_variables.st_nat_traversal, NATED_PEER)(((ike->sa.hidden_variables.st_nat_traversal) & ((lset_t )1 << (NATED_PEER))) != ((lset_t)0))) { | |||
2454 | /* | |||
2455 | * Things are looking plausible. | |||
2456 | */ | |||
2457 | if (ike->sa.st_ike_sent_v2n_mobike_supported && | |||
2458 | ike->sa.st_ike_seen_v2n_mobike_supported && | |||
2459 | md->hdr.isa_xchg == ISAKMP_v2_INFORMATIONAL) { | |||
2460 | /* | |||
2461 | * Only when MOBIKE has not been negotiated ... | |||
2462 | */ | |||
2463 | endpoint_buf sb, mb; | |||
2464 | dbg("NAT: MOBIKE: skipping remote sender from %s -> %s as MOBIKE delt with it in informational code(?)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT: MOBIKE: skipping remote sender from %s -> %s as MOBIKE delt with it in informational code(?)" , str_endpoint(&ike->sa.st_remote_endpoint, &sb), str_endpoint (&md->sender, &mb)); } } | |||
2465 | str_endpoint(&ike->sa.st_remote_endpoint, &sb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT: MOBIKE: skipping remote sender from %s -> %s as MOBIKE delt with it in informational code(?)" , str_endpoint(&ike->sa.st_remote_endpoint, &sb), str_endpoint (&md->sender, &mb)); } } | |||
2466 | str_endpoint(&md->sender, &mb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT: MOBIKE: skipping remote sender from %s -> %s as MOBIKE delt with it in informational code(?)" , str_endpoint(&ike->sa.st_remote_endpoint, &sb), str_endpoint (&md->sender, &mb)); } }; | |||
2467 | } else { | |||
2468 | endpoint_buf sb, mb; | |||
2469 | dbg("NAT: MOBKIE: updating remote sender from %s -> %s as non-MOBIKE or non-INFORMATIONAL",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT: MOBKIE: updating remote sender from %s -> %s as non-MOBIKE or non-INFORMATIONAL" , str_endpoint(&ike->sa.st_remote_endpoint, &sb), str_endpoint (&md->sender, &mb)); } } | |||
2470 | str_endpoint(&ike->sa.st_remote_endpoint, &sb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT: MOBKIE: updating remote sender from %s -> %s as non-MOBIKE or non-INFORMATIONAL" , str_endpoint(&ike->sa.st_remote_endpoint, &sb), str_endpoint (&md->sender, &mb)); } } | |||
2471 | str_endpoint(&md->sender, &mb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT: MOBKIE: updating remote sender from %s -> %s as non-MOBIKE or non-INFORMATIONAL" , str_endpoint(&ike->sa.st_remote_endpoint, &sb), str_endpoint (&md->sender, &mb)); } }; | |||
2472 | ike->sa.st_remote_endpoint = md->sender; | |||
2473 | } | |||
2474 | } | |||
2475 | ||||
2476 | /* if requested, send the new reply packet */ | |||
2477 | switch (transition->send) { | |||
2478 | case MESSAGE_REQUEST: | |||
2479 | case MESSAGE_RESPONSE: | |||
2480 | send_recorded_v2_message(ike, finite_states[from_state]->name, | |||
2481 | transition->send); | |||
2482 | break; | |||
2483 | case NO_MESSAGE: | |||
2484 | break; | |||
2485 | default: | |||
2486 | bad_case(transition->send)libreswan_bad_case("transition->send", (transition->send ), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2486, }; &here; }));; | |||
2487 | } | |||
2488 | ||||
2489 | if (just_established) { | |||
2490 | release_any_whack(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2490, }; &here; }), "IKEv2 transitions finished"); | |||
2491 | ||||
2492 | /* XXX should call unpend again on parent SA */ | |||
2493 | if (IS_CHILD_SA(st)((st)->st_clonedfrom != 0)) { | |||
2494 | /* with failed child sa, we end up here with an orphan?? */ | |||
2495 | dbg("unpending #%lu's IKE SA #%lu", st->st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("unpending #%lu's IKE SA #%lu", st->st_serialno , ike->sa.st_serialno); } } | |||
2496 | ike->sa.st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("unpending #%lu's IKE SA #%lu", st->st_serialno , ike->sa.st_serialno); } }; | |||
2497 | /* a better call unpend in ikev2_ike_sa_established? */ | |||
2498 | unpend(ike, c); | |||
2499 | ||||
2500 | /* | |||
2501 | * If this was an OE connection, check for removing a potential | |||
2502 | * matching bare shunt entry - bare shunts are always a %pass or | |||
2503 | * %hold SPI but are found regardless of whether we passed in | |||
2504 | * SPI_PASS or SPI_HOLD ? | |||
2505 | */ | |||
2506 | if (LIN(POLICY_OPPORTUNISTIC, c->policy)(((((lset_t)1 << (POLICY_OPPORTUNISTIC_IX))) & (c-> policy)) == (((lset_t)1 << (POLICY_OPPORTUNISTIC_IX))))) { | |||
2507 | struct spd_route *sr = &c->spd; | |||
2508 | struct bare_shunt **bs = bare_shunt_ptr(&sr->this.client, | |||
2509 | &sr->that.client, | |||
2510 | sr->this.protocol, | |||
2511 | "old bare shunt to delete"); | |||
2512 | ||||
2513 | if (bs != NULL((void*)0)) { | |||
2514 | dbg("deleting old bare shunt"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("deleting old bare shunt"); } }; | |||
2515 | if (!delete_bare_shunt(&c->spd.this.host_addr, | |||
2516 | &c->spd.that.host_addr, | |||
2517 | c->spd.this.protocol, | |||
2518 | SPI_PASS /* else its not bare */, | |||
2519 | /*skip_xfrm_policy_delete?*/true1, | |||
2520 | "installed IPsec SA replaced old bare shunt", | |||
2521 | st->st_logger)) { | |||
2522 | log_state(RC_LOG_SERIOUS, &ike->sa, | |||
2523 | "Failed to delete old bare shunt"); | |||
2524 | } | |||
2525 | } | |||
2526 | } | |||
2527 | release_any_whack(&ike->sa, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2527, }; &here; }), "IKEv2 transitions finished so releaseing IKE SA"); | |||
2528 | } | |||
2529 | } else if (transition->flags & SMF2_RELEASE_WHACK) { | |||
2530 | dbg("releasing whack"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("releasing whack"); } }; | |||
2531 | release_any_whack(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2531, }; &here; }), "ST per transition"); | |||
2532 | if (st != &ike->sa) { | |||
2533 | release_any_whack(&ike->sa, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2533, }; &here; }), "IKE per transition"); | |||
2534 | } | |||
2535 | } | |||
2536 | ||||
2537 | /* Schedule for whatever timeout is specified */ | |||
2538 | { | |||
2539 | enum event_type kind = transition->timeout_event; | |||
2540 | struct connection *c = st->st_connection; | |||
2541 | ||||
2542 | switch (kind) { | |||
2543 | ||||
2544 | case EVENT_RETRANSMIT: | |||
2545 | /* | |||
2546 | * Event retransmit is really a secret code to | |||
2547 | * indicate that a request is being sent and a | |||
2548 | * retransmit should already be scheduled. | |||
2549 | */ | |||
2550 | dbg("checking that a retransmit timeout_event was already"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("checking that a retransmit timeout_event was already" ); } }; | |||
2551 | delete_event(st); /* relying on retransmit */ | |||
2552 | pexpect(ike->sa.st_retransmit_event != NULL)({ _Bool assertion__ = ike->sa.st_retransmit_event != ((void *)0); if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c" , .line = 2552, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike->sa.st_retransmit_event != ((void*)0)" ); } assertion__; }); | |||
2553 | pexpect(transition->send == MESSAGE_REQUEST)({ _Bool assertion__ = transition->send == MESSAGE_REQUEST ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2553, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->send == MESSAGE_REQUEST" ); } assertion__; }); | |||
2554 | break; | |||
2555 | ||||
2556 | case EVENT_SA_REPLACE: /* IKE or Child SA replacement event */ | |||
2557 | schedule_v2_replace_event(st); | |||
2558 | break; | |||
2559 | ||||
2560 | case EVENT_SA_DISCARD: | |||
2561 | delete_event(st); | |||
2562 | event_schedule(kind, MAXIMUM_RESPONDER_WAIT_DELAYdeltatime(200), st); | |||
2563 | break; | |||
2564 | ||||
2565 | case EVENT_NULL: | |||
2566 | /* | |||
2567 | * Is there really no case where we want to | |||
2568 | * set no timer? more likely an accident? | |||
2569 | */ | |||
2570 | pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2570, }; &here; }), | |||
2571 | "V2 microcode entry (%s) has unspecified timeout_event", | |||
2572 | transition->story); | |||
2573 | break; | |||
2574 | ||||
2575 | case EVENT_v2_REDIRECT: | |||
2576 | event_delete(EVENT_v2_REDIRECT, st); | |||
2577 | event_schedule(EVENT_v2_REDIRECT, deltatime(0), st); | |||
2578 | break; | |||
2579 | ||||
2580 | case EVENT_RETAIN: | |||
2581 | /* the previous event is retained */ | |||
2582 | dbg("#%lu is retaining %s with is previously set timeout",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu is retaining %s with is previously set timeout" , st->st_serialno, (st->st_event == ((void*)0) ? "<no-event>" : enum_name(&event_type_names, st->st_event->ev_type ))); } } | |||
2583 | st->st_serialno, (st->st_event == NULL ? "<no-event>" :{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu is retaining %s with is previously set timeout" , st->st_serialno, (st->st_event == ((void*)0) ? "<no-event>" : enum_name(&event_type_names, st->st_event->ev_type ))); } } | |||
2584 | enum_name(&event_type_names, st->st_event->ev_type))){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu is retaining %s with is previously set timeout" , st->st_serialno, (st->st_event == ((void*)0) ? "<no-event>" : enum_name(&event_type_names, st->st_event->ev_type ))); } }; | |||
2585 | break; | |||
2586 | ||||
2587 | default: | |||
2588 | bad_case(kind)libreswan_bad_case("kind", (kind), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2588, }; &here; })); | |||
2589 | break; | |||
2590 | } | |||
2591 | /* | |||
2592 | * start liveness checks if set, making sure we only | |||
2593 | * schedule once when moving from I2->I3 or R1->R2 | |||
2594 | */ | |||
2595 | if (st->st_state->kind != from_state && | |||
2596 | st->st_state->kind != STATE_UNDEFINED && | |||
2597 | IS_CHILD_SA_ESTABLISHED(st)((st)->st_state->kind == STATE_V2_ESTABLISHED_CHILD_SA) && | |||
2598 | dpd_active_locally(st)) { | |||
2599 | dbg("dpd enabled, scheduling ikev2 liveness checks"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("dpd enabled, scheduling ikev2 liveness checks" ); } }; | |||
2600 | deltatime_t delay = deltatime_max(c->dpd_delay, deltatime(MIN_LIVENESS1)); | |||
2601 | event_schedule(EVENT_v2_LIVENESS, delay, st); | |||
2602 | } | |||
2603 | } | |||
2604 | } | |||
2605 | ||||
2606 | /* | |||
2607 | * Dependent on RESULT, either complete, suspend, abandon, or abort | |||
2608 | * (delete state) the state transition started by the state-specific | |||
2609 | * state transition function. | |||
2610 | * | |||
2611 | * Since this is function is meaningless without a state, ST really | |||
2612 | * should be non-NULL. | |||
2613 | * | |||
2614 | * XXX: A broken exception is when responding to an IKE_SA_INIT | |||
2615 | * request - the state machine calls the state transition function | |||
2616 | * with no state (trusting that the transition function will do the | |||
2617 | * job, but that isn't always true). The fix is to create the state | |||
2618 | * before calling the state transition function (like is done for the | |||
2619 | * CHILD_SA code). | |||
2620 | * | |||
2621 | * Since, when initiating an exchange there is no message, code can't | |||
2622 | * assume that (*MDP) is non-NULL. | |||
2623 | * | |||
2624 | * XXX: Some state transition functions switch state part way (see | |||
2625 | * AUTH child code) and then tunnel the new state to this code via | |||
2626 | * (*MDP)->st and some callers passing in (*MDP)->st). The fix is for | |||
2627 | * the AUTH code to handle the CHILD SA as a nested or separate | |||
2628 | * transition. | |||
2629 | * | |||
2630 | * XXX: The state transition structure (microcode) is stored in (*MDP) | |||
2631 | * forcing that structure to be created. The fix is to store the | |||
2632 | * state's transition in the state. As a bonus this makes determining | |||
2633 | * if a state is busy really really easy - if there's a | |||
2634 | * state-transition then it must be. | |||
2635 | * | |||
2636 | * This routine does not free (*MDP) (using release_any_md(mdp)). | |||
2637 | * However, when suspending a state transition, it will save it in ST | |||
2638 | * and zap (*MDP) so that the caller can't free it. Hence, the caller | |||
2639 | * must be prepared for (*MDP) being set to NULL. | |||
2640 | * | |||
2641 | * XXX: At some point (*MDP) was being used for: | |||
2642 | * | |||
2643 | * - find st | |||
2644 | * - success_v2_state_transition(st, md); | |||
2645 | * - for svm: | |||
2646 | * - svm->next_state, | |||
2647 | * - svm->flags & SMF2_SEND, | |||
2648 | * - svm->timeout_event, | |||
2649 | * -svm->flags, story | |||
2650 | * - find from_state (st might be gone) | |||
2651 | * - ikev2_update_msgid_counters(md); | |||
2652 | * - nat_traversal_change_port_lookup(md, st) | |||
2653 | * - !(md->hdr.isa_flags & ISAKMP_FLAGS_v2_MSG_R) to gate Notify payloads/exchanges [WRONG] | |||
2654 | * - find note for STF_INTERNAL_ERROR | |||
2655 | * - find note for STF_FAIL (might not be part of result (STF_FAIL+note)) | |||
2656 | * | |||
2657 | * We don't use these but complete_v1_state_transition does: | |||
2658 | * - record md->event_already_set | |||
2659 | * - remember_received_packet(st, md); | |||
2660 | * - fragvid, dpd, nortel | |||
2661 | */ | |||
2662 | void complete_v2_state_transition(struct state *st, | |||
2663 | struct msg_digest *md, | |||
2664 | stf_status result) | |||
2665 | { | |||
2666 | passert(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 2666, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "st != ((void*)0)"); } (void) 1; }); | |||
| ||||
2667 | struct ike_sa *ike = ike_sa(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2667, }; &here; })); | |||
2668 | /* struct child_sa *child = IS_CHILD_SA(st) ? pexpect_child_sa(st) : NULL; */ | |||
2669 | ||||
2670 | /* statistics */ | |||
2671 | /* this really depends on the type of error whether it is an IKE or IPsec fail */ | |||
2672 | if (result > STF_FAIL) { | |||
2673 | pstats(ike_stf, STF_FAIL){ const unsigned __pstat = (STF_FAIL); if (__pstat < (sizeof (pstats_ike_stf) / sizeof(*(pstats_ike_stf)))) { pstats_ike_stf [__pstat]++; } else if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { DBG_log("pstats %s %d", "ike_stf", __pstat ); } }; | |||
2674 | } else { | |||
2675 | pstats(ike_stf, result){ const unsigned __pstat = (result); if (__pstat < (sizeof (pstats_ike_stf) / sizeof(*(pstats_ike_stf)))) { pstats_ike_stf [__pstat]++; } else if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { DBG_log("pstats %s %d", "ike_stf", __pstat ); } }; | |||
2676 | } | |||
2677 | ||||
2678 | /* | |||
2679 | * Try to get the transition that is being completed ... | |||
2680 | * | |||
2681 | * For the moment this comes from the (presumably non-NULL) | |||
2682 | * MD.SVM. | |||
2683 | * | |||
2684 | * XXX: However, when a packet is bad and no transition is | |||
2685 | * selected, this code is still called: | |||
2686 | * | |||
2687 | * STF_IGNORE: to undo the v2_msgid_start_responder() call; | |||
2688 | * better would probably be to move that call to after a | |||
2689 | * transition has been found (but fragmentation makes this | |||
2690 | * messy). | |||
2691 | * | |||
2692 | * STF_FATAL: to discard a state in response to a bad exchange | |||
2693 | * (for instance a protected packet's contents are bogus). | |||
2694 | * | |||
2695 | * Long term, this value should be extracted from the state | |||
2696 | * and .st_v2_state_transition - it just isn't possible to | |||
2697 | * squeeze both the IKE and CHILD transitions into MD.ST. | |||
2698 | */ | |||
2699 | #if 0 | |||
2700 | const struct v2_state_transition *transition = st->st_v2_transition; | |||
2701 | if (!pexpect(transition != NULL)({ _Bool assertion__ = transition != ((void*)0); if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2701, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "transition != ((void*)0)" ); } assertion__; }) && md != NULL((void*)0)) { | |||
2702 | transition = md->svm; | |||
2703 | } | |||
2704 | #else | |||
2705 | const struct v2_state_transition *transition = (md != NULL((void*)0) && md->svm != NULL((void*)0) ? md->svm : | |||
2706 | st->st_v2_transition); | |||
2707 | #endif | |||
2708 | static const struct v2_state_transition undefined_transition = { | |||
2709 | .story = "suspect message", | |||
2710 | .state = STATE_UNDEFINED, | |||
2711 | .next_state = STATE_UNDEFINED, | |||
2712 | }; | |||
2713 | /* double negative */ | |||
2714 | if (!pexpect(transition != NULL)({ _Bool assertion__ = transition != ((void*)0); if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2714, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "transition != ((void*)0)" ); } assertion__; })) { | |||
2715 | transition = &undefined_transition; | |||
2716 | } | |||
2717 | ||||
2718 | LSWDBGP(DBG_BASE, buf)for (_Bool lswlog_p = (cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))); lswlog_p; lswlog_p = 0) for (char lswbuf[( (size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) for (; buf != ((void*)0); jambuf_to_logger(buf , &failsafe_logger, DEBUG_STREAM), buf = ((void*)0)) { | |||
2719 | const struct finite_state *transition_from = finite_states[transition->state]; | |||
2720 | ||||
2721 | jam(buf, "#%lu complete_v2_state_transition()", st->st_serialno); | |||
2722 | if (st->st_state != transition_from) { | |||
2723 | jam(buf, " in state %s", st->st_state->short_name); | |||
2724 | } | |||
2725 | jam(buf, " "); | |||
2726 | jam_v2_transition(buf, transition); | |||
2727 | jam(buf, " with status "); | |||
2728 | jam_v2_stf_status(buf, result); | |||
2729 | /* does MD.SVM diverge? */ | |||
2730 | if (md != NULL((void*)0) && transition != md->svm) { | |||
2731 | jam(buf, "; md.svm="); | |||
2732 | jam_v2_transition(buf, md->svm); | |||
2733 | } | |||
2734 | /* does ST.ST_V2_TRANSITION diverge? */ | |||
2735 | if (transition != st->st_v2_transition) { | |||
2736 | jam(buf, "; .st_v2_transition="); | |||
2737 | jam_v2_transition(buf, st->st_v2_transition); | |||
2738 | } | |||
2739 | } | |||
2740 | ||||
2741 | switch (result) { | |||
2742 | ||||
2743 | case STF_SUSPEND: | |||
2744 | /* | |||
2745 | * If this transition was triggered by an | |||
2746 | * incoming packet, save it. | |||
2747 | * | |||
2748 | * XXX: some initiator code creates a fake MD | |||
2749 | * (there isn't a real one); save that as | |||
2750 | * well. | |||
2751 | * | |||
2752 | * XXX: should the helper code be responsible for | |||
2753 | * saving an MD reference? | |||
2754 | */ | |||
2755 | suspend_any_md(st, md){ if (md != ((void*)0)) { { if ((cur_debugging & (((lset_t )1 << (DBG_BASE_IX))))) { DBG_log("suspending state #%lu and saving MD %p" , (st)->st_serialno, md); } }; ({ _Bool assertion__ = (st) ->st_suspended_md == ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2.c", .line = 2755, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "(st)->st_suspended_md == ((void*)0)" ); } (void) 1; }); (st)->st_suspended_md = md_addref(md, ( { static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2755, }; &here; })); ( st)->st_suspended_md_func = __func__; (st)->st_suspended_md_line = 2755; ({ _Bool assertion__ = state_is_busy(st); if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2755, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "state_is_busy(st)"); } ( void) 1; }); } else { { if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { DBG_log("no MD to suspend"); } }; } }; | |||
2756 | return; | |||
2757 | ||||
2758 | case STF_IGNORE: | |||
2759 | /* | |||
2760 | * logged above | |||
2761 | * | |||
2762 | * XXX: really? Suspect this means to say logged | |||
2763 | * where STF_IGNORE is returned. | |||
2764 | * | |||
2765 | * XXX: even when a packet is invalid and no | |||
2766 | * transition is selected (TRANSITION==NULL) this code | |||
2767 | * is executed - caller needs to cancel the responder | |||
2768 | * processing the message. | |||
2769 | */ | |||
2770 | if (v2_msg_role(md) == MESSAGE_REQUEST) { | |||
2771 | v2_msgid_cancel_responder(ike, st, md); | |||
2772 | } | |||
2773 | return; | |||
2774 | ||||
2775 | case STF_OK: | |||
2776 | /* advance the state */ | |||
2777 | success_v2_state_transition(st, md, transition); | |||
2778 | break; | |||
2779 | ||||
2780 | case STF_INTERNAL_ERROR: | |||
2781 | log_state(RC_INTERNALERR, st, "state transition function for %s had internal error", | |||
2782 | st->st_state->name); | |||
2783 | release_pending_whacks(st, "internal error"); | |||
2784 | break; | |||
2785 | ||||
2786 | case STF_V2_DELETE_IKE_AUTH_INITIATOR: | |||
2787 | /* | |||
2788 | * XXX: this is a hack so that IKE_AUTH initiator can | |||
2789 | * both delete the IKE SA and send an IKE SA delete | |||
2790 | * notification because the IKE_AUTH response was | |||
2791 | * rejected. | |||
2792 | */ | |||
2793 | /* | |||
2794 | * Initiator processing response, finish current | |||
2795 | * exchange ready for delete request. | |||
2796 | */ | |||
2797 | dbg("Message ID: forcing a response received update (deleting IKE_AUTH initiator)"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("Message ID: forcing a response received update (deleting IKE_AUTH initiator)" ); } }; | |||
2798 | pexpect(st->st_state->kind == STATE_V2_PARENT_I2)({ _Bool assertion__ = st->st_state->kind == STATE_V2_PARENT_I2 ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2798, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "st->st_state->kind == STATE_V2_PARENT_I2" ); } assertion__; }); | |||
2799 | pexpect(v2_msg_role(md) == MESSAGE_RESPONSE)({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_RESPONSE; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2799, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "v2_msg_role(md) == MESSAGE_RESPONSE" ); } assertion__; }); | |||
2800 | v2_msgid_update_recv(ike, &ike->sa, md); | |||
2801 | /* | |||
2802 | * All done, now delete the IKE family sending out a | |||
2803 | * last gasp delete. | |||
2804 | * | |||
2805 | * XXX: this call will fire and forget. It should | |||
2806 | * call v2_msgid_queue_initiator() with high priority | |||
2807 | * so this is performed as a separate transition? | |||
2808 | */ | |||
2809 | delete_ike_family(ike, DO_SEND_DELETE); | |||
2810 | /* get out of here -- everything is invalid */ | |||
2811 | ike = NULL((void*)0); | |||
2812 | st = NULL((void*)0); | |||
2813 | return; | |||
2814 | ||||
2815 | case STF_FATAL: | |||
2816 | /* | |||
2817 | * XXX: even when a packet is invalid and no | |||
2818 | * transition is selected (TRANSITION==NULL) this code | |||
2819 | * is executed - caller needs to kill the state. | |||
2820 | */ | |||
2821 | log_state(RC_FATAL, st, "encountered fatal error in state %s", | |||
2822 | st->st_state->name); | |||
2823 | switch (v2_msg_role(md)) { | |||
2824 | case MESSAGE_RESPONSE: | |||
2825 | dbg("Message ID: forcing a response received update"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("Message ID: forcing a response received update" ); } }; | |||
2826 | v2_msgid_update_recv(ike, NULL((void*)0), md); | |||
2827 | break; | |||
2828 | case MESSAGE_REQUEST: | |||
2829 | dbg("Message ID: responding with recorded fatal error"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("Message ID: responding with recorded fatal error" ); } }; | |||
2830 | pexpect(transition->send == MESSAGE_RESPONSE)({ _Bool assertion__ = transition->send == MESSAGE_RESPONSE ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2830, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->send == MESSAGE_RESPONSE" ); } assertion__; }); | |||
2831 | if (ike->sa.st_v2_outgoing[MESSAGE_RESPONSE] != NULL((void*)0)) { | |||
2832 | v2_msgid_update_recv(ike, st, md); | |||
2833 | v2_msgid_update_sent(ike, st, md, transition->send); | |||
2834 | send_recorded_v2_message(ike, "STF_FATAL", | |||
2835 | MESSAGE_RESPONSE); | |||
2836 | } else { | |||
2837 | dbg("Message ID: exchange zombie as no response?"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("Message ID: exchange zombie as no response?") ; } }; | |||
2838 | } | |||
2839 | break; | |||
2840 | case NO_MESSAGE: | |||
2841 | break; | |||
2842 | } | |||
2843 | ||||
2844 | /* if this was a child fail, don't destroy the IKE SA */ | |||
2845 | if (IS_IKE_SA(st)((st)->st_clonedfrom == 0)) { | |||
2846 | delete_ike_family(ike, DONT_SEND_DELETE); | |||
2847 | ike = NULL((void*)0); | |||
2848 | } | |||
2849 | ||||
2850 | /* kill all st pointers */ | |||
2851 | st = NULL((void*)0); | |||
2852 | break; | |||
2853 | ||||
2854 | case STF_FAIL: | |||
2855 | log_state(RC_NOTIFICATION, st, "state transition '%s' failed", | |||
2856 | transition->story); | |||
2857 | switch (v2_msg_role(md)) { | |||
2858 | case MESSAGE_RESPONSE: | |||
2859 | v2_msgid_update_recv(ike, st, md); | |||
2860 | v2_msgid_schedule_next_initiator(ike); | |||
2861 | break; | |||
2862 | case MESSAGE_REQUEST: | |||
2863 | dbg("Message ID: responding with recorded error"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("Message ID: responding with recorded error"); } }; | |||
2864 | pexpect(transition->send == MESSAGE_RESPONSE)({ _Bool assertion__ = transition->send == MESSAGE_RESPONSE ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2864, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "transition->send == MESSAGE_RESPONSE" ); } assertion__; }); | |||
2865 | v2_msgid_update_recv(ike, st, md); | |||
2866 | v2_msgid_update_sent(ike, st, md, transition->send); | |||
2867 | send_recorded_v2_message(ike, "STF_FAIL", MESSAGE_RESPONSE); | |||
2868 | break; | |||
2869 | case NO_MESSAGE: | |||
2870 | break; | |||
2871 | } | |||
2872 | release_pending_whacks(st, "fatal error"); /* fatal != STF_FATAL :) */ | |||
2873 | delete_state(st); | |||
2874 | ||||
2875 | /* kill all st pointers */ | |||
2876 | st = NULL((void*)0); | |||
2877 | ike = NULL((void*)0); | |||
2878 | break; | |||
2879 | ||||
2880 | default: /* STF_FAIL+notification */ | |||
2881 | passert(result > STF_FAIL)({ _Bool assertion__ = result > STF_FAIL; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2881, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "result > STF_FAIL"); } (void) 1; }); | |||
2882 | /* | |||
2883 | * XXX: For IKEv2, this code path isn't sufficient - a | |||
2884 | * message request can result in a response that | |||
2885 | * contains both a success and a fail. Better to | |||
2886 | * record the responses and and then return | |||
2887 | * STF_ZOMBIFY signaling both that the message should | |||
2888 | * be sent and the state deleted. | |||
2889 | */ | |||
2890 | v2_notification_t notification = result - STF_FAIL; | |||
2891 | /* Only the responder sends a notification */ | |||
2892 | if (v2_msg_role(md) == MESSAGE_REQUEST) { | |||
2893 | dbg("sending a notification reply"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("sending a notification reply"); } }; | |||
2894 | v2_msgid_update_recv(ike, st, md); | |||
2895 | record_v2N_response(st->st_logger, ike, md, | |||
2896 | notification, NULL((void*)0)/*no data*/, | |||
2897 | ENCRYPTED_PAYLOAD); | |||
2898 | v2_msgid_update_sent(ike, st, md, transition->send); | |||
2899 | send_recorded_v2_message(ike, "STF_FAIL", | |||
2900 | MESSAGE_RESPONSE); | |||
2901 | /* | |||
2902 | * XXX: is this always false; if true above | |||
2903 | * record would pexpect()? | |||
2904 | */ | |||
2905 | if (md->hdr.isa_xchg == ISAKMP_v2_IKE_SA_INIT) { | |||
| ||||
2906 | delete_state(st); | |||
2907 | /* kill all st pointers */ | |||
2908 | st = NULL((void*)0); ike = NULL((void*)0); | |||
2909 | } else { | |||
2910 | dbg("forcing #%lu to a discard event",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("forcing #%lu to a discard event", st->st_serialno ); } } | |||
2911 | st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("forcing #%lu to a discard event", st->st_serialno ); } }; | |||
2912 | delete_event(st); | |||
2913 | event_schedule(EVENT_SA_DISCARD, | |||
2914 | MAXIMUM_RESPONDER_WAIT_DELAYdeltatime(200), | |||
2915 | st); | |||
2916 | } | |||
2917 | } else { | |||
2918 | log_state(RC_NOTIFICATION+notification, st, | |||
2919 | "state transition '%s' failed with %s", | |||
2920 | transition->story, enum_name(&ikev2_notify_names, notification)); | |||
2921 | } | |||
2922 | break; | |||
2923 | } | |||
2924 | } | |||
2925 | ||||
2926 | void jam_v2_stf_status(struct jambuf *buf, unsigned status) | |||
2927 | { | |||
2928 | if (status <= STF_FAIL) { | |||
2929 | jam_enum(buf, &stf_status_names, status); | |||
2930 | } else { | |||
2931 | jam(buf, "STF_FAIL+"); | |||
2932 | jam_enum(buf, &ikev2_notify_names, status - STF_FAIL); | |||
2933 | } | |||
2934 | } | |||
2935 | ||||
2936 | static void reinitiate_ike_sa_init(struct state *st, void *arg) | |||
2937 | { | |||
2938 | if (st == NULL((void*)0)) { | |||
2939 | dbg("re-initiate lost state"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("re-initiate lost state"); } }; | |||
2940 | return; | |||
2941 | } | |||
2942 | struct ike_sa *ike = ike_sa(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2942, }; &here; })); | |||
2943 | if (ike == NULL((void*)0)) { | |||
2944 | /* already logged */ | |||
2945 | return; | |||
2946 | } | |||
2947 | stf_status (*resume)(struct ike_sa *ike) = arg; | |||
2948 | ||||
2949 | /* | |||
2950 | * Need to wind back the Message ID counters so that the send | |||
2951 | * code things it is creating Message 0. | |||
2952 | */ | |||
2953 | v2_msgid_init_ike(ike); | |||
2954 | ||||
2955 | /* | |||
2956 | * Pretend to be running the initiate state. | |||
2957 | */ | |||
2958 | set_v2_transition(&ike->sa, finite_states[STATE_V2_PARENT_I0]->v2_transitions, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2958, }; &here; })); /* first */ | |||
2959 | complete_v2_state_transition(&ike->sa, NULL((void*)0)/*no-MD*/, resume(ike)); | |||
2960 | } | |||
2961 | ||||
2962 | void schedule_reinitiate_v2_ike_sa_init(struct ike_sa *ike, | |||
2963 | stf_status (*resume)(struct ike_sa *ike)) | |||
2964 | { | |||
2965 | schedule_callback("reinitiating IKE_SA_INIT", ike->sa.st_serialno, | |||
2966 | reinitiate_ike_sa_init, resume); | |||
2967 | } | |||
2968 | ||||
2969 | bool_Bool v2_notification_fatal(v2_notification_t n) | |||
2970 | { | |||
2971 | return (n == v2N_INVALID_SYNTAX || | |||
2972 | n == v2N_AUTHENTICATION_FAILED || | |||
2973 | n == v2N_UNSUPPORTED_CRITICAL_PAYLOAD); | |||
2974 | } | |||
2975 | ||||
2976 | stf_status stf_status_from_v2_notification(v2_notification_t n) | |||
2977 | { | |||
2978 | return (n == v2N_NOTHING_WRONG ? STF_OK : | |||
2979 | v2_notification_fatal(n) ? STF_FATAL : | |||
2980 | STF_FAIL); | |||
2981 | } | |||
2982 | ||||
2983 | bool_Bool already_has_larval_v2_child(struct ike_sa *ike, const struct connection *c) | |||
2984 | { | |||
2985 | const lset_t pending_states = (LELEM(STATE_V2_NEW_CHILD_I1)((lset_t)1 << (STATE_V2_NEW_CHILD_I1)) | | |||
2986 | LELEM(STATE_V2_NEW_CHILD_I0)((lset_t)1 << (STATE_V2_NEW_CHILD_I0)) | | |||
2987 | LELEM(STATE_V2_NEW_CHILD_R0)((lset_t)1 << (STATE_V2_NEW_CHILD_R0))); | |||
2988 | ||||
2989 | struct state_query query = { | |||
2990 | .where = HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2.c", .line = 2990, }; &here; }), | |||
2991 | .ike_version = IKEv2, | |||
2992 | .ike_spis = &ike->sa.st_ike_spis, | |||
2993 | /* only children */ | |||
2994 | .ike = ike, | |||
2995 | }; | |||
2996 | ||||
2997 | while (old2new_state(&query)) { | |||
2998 | struct state *st = query.st; | |||
2999 | ||||
3000 | /* larval child state? */ | |||
3001 | if (!LHAS(pending_states, st->st_state->kind)(((pending_states) & ((lset_t)1 << (st->st_state ->kind))) != ((lset_t)0))) { | |||
3002 | continue; | |||
3003 | } | |||
3004 | /* not an instance, but a connection? */ | |||
3005 | if (!streq(st->st_connection->name, c->name)(strcmp((st->st_connection->name), (c->name)) == 0)) { | |||
3006 | continue; | |||
3007 | } | |||
3008 | llog(RC_LOG, c->logger, "connection already has the pending Child SA negotiation #%lu using IKE SA #%lu", | |||
3009 | st->st_serialno, ike->sa.st_serialno); | |||
3010 | return true1; | |||
3011 | } | |||
3012 | ||||
3013 | return false0; | |||
3014 | } |