]>
Commit | Line | Data |
---|---|---|
c7dd2a7b MW |
1 | /** |
2 | * @file ike_sa_init_requested.c | |
3 | * | |
df3c59d0 | 4 | * @brief Implementation of ike_sa_init_requested_t. |
c7dd2a7b MW |
5 | * |
6 | */ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
22 | ||
23 | #include "ike_sa_init_requested.h" | |
24 | ||
0e96f7d8 | 25 | #include <daemon.h> |
c7dd2a7b MW |
26 | #include <utils/allocator.h> |
27 | #include <encoding/payloads/sa_payload.h> | |
28 | #include <encoding/payloads/ke_payload.h> | |
29 | #include <encoding/payloads/nonce_payload.h> | |
ae3012a0 | 30 | #include <encoding/payloads/notify_payload.h> |
f890d8fe | 31 | #include <encoding/payloads/id_payload.h> |
af30c6b9 | 32 | #include <encoding/payloads/auth_payload.h> |
1b3f92d2 | 33 | #include <encoding/payloads/ts_payload.h> |
c7dd2a7b | 34 | #include <transforms/diffie_hellman.h> |
af30c6b9 | 35 | #include <sa/states/ike_auth_requested.h> |
ae3012a0 | 36 | #include <sa/states/initiator_init.h> |
8d68033e | 37 | #include <sa/authenticator.h> |
c7dd2a7b | 38 | |
5796aa16 MW |
39 | |
40 | typedef struct private_ike_sa_init_requested_t private_ike_sa_init_requested_t; | |
41 | ||
c7dd2a7b MW |
42 | /** |
43 | * Private data of a ike_sa_init_requested_t object. | |
44 | * | |
45 | */ | |
5796aa16 | 46 | struct private_ike_sa_init_requested_t { |
c7dd2a7b | 47 | /** |
91194f45 | 48 | * Public interface of an ike_sa_init_requested_t object. |
c7dd2a7b MW |
49 | */ |
50 | ike_sa_init_requested_t public; | |
51 | ||
52 | /** | |
53 | * Assigned IKE_SA | |
54 | */ | |
55 | protected_ike_sa_t *ike_sa; | |
56 | ||
57 | /** | |
91194f45 | 58 | * Diffie Hellman object used to compute shared secret. |
c7dd2a7b MW |
59 | */ |
60 | diffie_hellman_t *diffie_hellman; | |
91194f45 | 61 | |
c7dd2a7b | 62 | /** |
91194f45 | 63 | * Sent nonce value. |
c7dd2a7b MW |
64 | */ |
65 | chunk_t sent_nonce; | |
66 | ||
67 | /** | |
68 | * Received nonce | |
69 | */ | |
70 | chunk_t received_nonce; | |
71 | ||
8d68033e | 72 | /** |
ce461bbd | 73 | * Selected proposal |
8d68033e | 74 | */ |
ce461bbd | 75 | proposal_t *proposal; |
8d68033e | 76 | |
c7dd2a7b | 77 | /** |
ce461bbd | 78 | * Packet data of ike_sa_init request |
c7dd2a7b | 79 | */ |
ce461bbd | 80 | chunk_t ike_sa_init_request_data; |
c7dd2a7b | 81 | |
30b5b412 MW |
82 | /** |
83 | * Created child sa, if any | |
84 | */ | |
85 | child_sa_t *child_sa; | |
86 | ||
c7dd2a7b | 87 | /** |
91194f45 | 88 | * Assigned logger |
c7dd2a7b MW |
89 | * |
90 | * Is logger of ike_sa! | |
91 | */ | |
92 | logger_t *logger; | |
f890d8fe | 93 | |
91194f45 | 94 | |
f890d8fe | 95 | /** |
91194f45 | 96 | * Process NONCE payload of IKE_SA_INIT response. |
f890d8fe | 97 | * |
91194f45 JH |
98 | * @param this calling object |
99 | * @param nonce_payload NONCE payload to process | |
100 | * @return SUCCESS in any case | |
f890d8fe | 101 | */ |
91194f45 JH |
102 | status_t (*process_nonce_payload) (private_ike_sa_init_requested_t *this, nonce_payload_t *nonce_payload); |
103 | ||
f890d8fe | 104 | /** |
91194f45 | 105 | * Process SA payload of IKE_SA_INIT response. |
f890d8fe | 106 | * |
91194f45 JH |
107 | * @param this calling object |
108 | * @param sa_payload SA payload to process | |
109 | * @return | |
110 | * - SUCCESS | |
111 | * - FAILED | |
f890d8fe | 112 | */ |
91194f45 | 113 | status_t (*process_sa_payload) (private_ike_sa_init_requested_t *this, sa_payload_t *sa_payload); |
f890d8fe | 114 | |
af30c6b9 | 115 | /** |
91194f45 | 116 | * Process KE payload of IKE_SA_INIT response. |
af30c6b9 | 117 | * |
91194f45 JH |
118 | * @param this calling object |
119 | * @param sa_payload KE payload to process | |
120 | * @return | |
121 | * - SUCCESS | |
122 | * - FAILED | |
123 | */ | |
124 | status_t (*process_ke_payload) (private_ike_sa_init_requested_t *this, ke_payload_t *ke_payload); | |
125 | ||
126 | /** | |
127 | * Build ID payload for IKE_AUTH request. | |
128 | * | |
129 | * @param this calling object | |
130 | * @param[out] id_payload buildet ID payload | |
131 | * @param response created payload will be added to this message_t object | |
8d68033e | 132 | * @return |
91194f45 JH |
133 | * - SUCCESS |
134 | * - FAILED | |
af30c6b9 | 135 | */ |
91194f45 | 136 | status_t (*build_id_payload) (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *response); |
af30c6b9 | 137 | |
1b3f92d2 | 138 | /** |
91194f45 | 139 | * Build AUTH payload for IKE_AUTH request. |
1b3f92d2 | 140 | * |
91194f45 JH |
141 | * @param this calling object |
142 | * @param my_id_payload buildet ID payload | |
143 | * @param response created payload will be added to this message_t object | |
144 | * @return | |
145 | * - SUCCESS | |
146 | * - FAILED | |
147 | */ | |
148 | status_t (*build_auth_payload) (private_ike_sa_init_requested_t *this,id_payload_t *my_id_payload, message_t *response); | |
149 | ||
150 | /** | |
151 | * Build SA payload for IKE_AUTH request. | |
152 | * | |
153 | * @param this calling object | |
154 | * @param response created payload will be added to this message_t object | |
155 | * @return | |
156 | * - SUCCESS | |
157 | * - FAILED | |
1b3f92d2 | 158 | */ |
91194f45 | 159 | status_t (*build_sa_payload) (private_ike_sa_init_requested_t *this, message_t *response); |
1b3f92d2 JH |
160 | |
161 | /** | |
91194f45 | 162 | * Build TSi payload for IKE_AUTH request. |
1b3f92d2 | 163 | * |
91194f45 JH |
164 | * @param this calling object |
165 | * @param response created payload will be added to this message_t object | |
166 | * @return | |
167 | * - SUCCESS | |
168 | * - FAILED | |
1b3f92d2 | 169 | */ |
91194f45 | 170 | status_t (*build_tsi_payload) (private_ike_sa_init_requested_t *this, message_t *response); |
1b3f92d2 JH |
171 | |
172 | /** | |
91194f45 | 173 | * Build TSr payload for IKE_AUTH request. |
1b3f92d2 | 174 | * |
91194f45 JH |
175 | * @param this calling object |
176 | * @param response created payload will be added to this message_t object | |
177 | * @return | |
178 | * - SUCCESS | |
179 | * - FAILED | |
1b3f92d2 | 180 | */ |
91194f45 | 181 | status_t (*build_tsr_payload) (private_ike_sa_init_requested_t *this, message_t *response); |
1b3f92d2 | 182 | |
5346c894 MW |
183 | /** |
184 | * Process a notify payload and react. | |
185 | * | |
186 | * @param this calling object | |
187 | * @param notify_payload notify_payload to handle | |
188 | */ | |
189 | status_t (*process_notify_payload) (private_ike_sa_init_requested_t *this, notify_payload_t *notify_payload); | |
190 | ||
af30c6b9 | 191 | /** |
91194f45 JH |
192 | * Destroy function called internally of this class after state change to |
193 | * state IKE_AUTH_REQUESTED succeeded. | |
194 | * | |
af30c6b9 JH |
195 | * This destroy function does not destroy objects which were passed to the new state. |
196 | * | |
197 | * @param this calling object | |
198 | */ | |
199 | void (*destroy_after_state_change) (private_ike_sa_init_requested_t *this); | |
c7dd2a7b MW |
200 | }; |
201 | ||
202 | /** | |
91194f45 | 203 | * Implementation of state_t.process_message. |
c7dd2a7b | 204 | */ |
1b3f92d2 | 205 | static status_t process_message(private_ike_sa_init_requested_t *this, message_t *ike_sa_init_reply) |
c7dd2a7b | 206 | { |
1b3f92d2 | 207 | ike_auth_requested_t *next_state; |
8d68033e | 208 | chunk_t ike_sa_init_reply_data; |
5346c894 MW |
209 | sa_payload_t *sa_payload = NULL; |
210 | ke_payload_t *ke_payload = NULL; | |
211 | id_payload_t *id_payload = NULL; | |
212 | nonce_payload_t *nonce_payload = NULL; | |
aad398a7 JH |
213 | u_int64_t responder_spi; |
214 | ike_sa_id_t *ike_sa_id; | |
1b3f92d2 | 215 | iterator_t *payloads; |
91194f45 | 216 | |
1b3f92d2 | 217 | message_t *request; |
1b3f92d2 | 218 | status_t status; |
aad398a7 | 219 | |
1b3f92d2 JH |
220 | /* |
221 | * In this state a reply message of type IKE_SA_INIT is expected: | |
222 | * | |
223 | * <-- HDR, SAr1, KEr, Nr, [CERTREQ] | |
224 | * or | |
225 | * <-- HDR, N | |
226 | */ | |
91194f45 JH |
227 | |
228 | if (ike_sa_init_reply->get_exchange_type(ike_sa_init_reply) != IKE_SA_INIT) | |
c7dd2a7b | 229 | { |
aee3eb52 | 230 | this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_init_requested", |
91194f45 | 231 | mapping_find(exchange_type_m,ike_sa_init_reply->get_exchange_type(ike_sa_init_reply))); |
c7dd2a7b MW |
232 | return FAILED; |
233 | } | |
234 | ||
1b3f92d2 | 235 | if (ike_sa_init_reply->get_request(ike_sa_init_reply)) |
c7dd2a7b | 236 | { |
5346c894 | 237 | this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT requests not allowed state ike_sa_init_responded"); |
c7dd2a7b MW |
238 | return FAILED; |
239 | } | |
240 | ||
241 | /* parse incoming message */ | |
1b3f92d2 | 242 | status = ike_sa_init_reply->parse_body(ike_sa_init_reply, NULL, NULL); |
c7dd2a7b MW |
243 | if (status != SUCCESS) |
244 | { | |
5346c894 | 245 | this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT reply parsing faild. Ignoring message"); |
c7dd2a7b MW |
246 | return status; |
247 | } | |
248 | ||
5346c894 | 249 | /* because we are original initiator we have to update the responder SPI to the new one */ |
79b8aa19 | 250 | responder_spi = ike_sa_init_reply->get_responder_spi(ike_sa_init_reply); |
1b3f92d2 JH |
251 | if (responder_spi == 0) |
252 | { | |
5346c894 | 253 | this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT reply contained a SPI of zero"); |
1b3f92d2 JH |
254 | return FAILED; |
255 | } | |
aad398a7 JH |
256 | ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public)); |
257 | ike_sa_id->set_responder_spi(ike_sa_id,responder_spi); | |
c7dd2a7b | 258 | |
1b3f92d2 JH |
259 | /* Iterate over all payloads. |
260 | * | |
261 | * The message is allready checked for the right payload types. | |
262 | */ | |
263 | payloads = ike_sa_init_reply->get_payload_iterator(ike_sa_init_reply); | |
c7dd2a7b | 264 | while (payloads->has_next(payloads)) |
56aeee49 | 265 | { |
c7dd2a7b MW |
266 | payload_t *payload; |
267 | payloads->current(payloads, (void**)&payload); | |
268 | ||
c7dd2a7b MW |
269 | switch (payload->get_type(payload)) |
270 | { | |
271 | case SECURITY_ASSOCIATION: | |
272 | { | |
91194f45 | 273 | sa_payload = (sa_payload_t*)payload; |
c7dd2a7b MW |
274 | break; |
275 | } | |
276 | case KEY_EXCHANGE: | |
277 | { | |
91194f45 | 278 | ke_payload = (ke_payload_t*)payload; |
c7dd2a7b MW |
279 | break; |
280 | } | |
281 | case NONCE: | |
282 | { | |
91194f45 | 283 | nonce_payload = (nonce_payload_t*)payload; |
c7dd2a7b MW |
284 | break; |
285 | } | |
5346c894 MW |
286 | case NOTIFY: |
287 | { | |
288 | notify_payload_t *notify_payload = (notify_payload_t *) payload; | |
289 | ||
290 | status = this->process_notify_payload(this, notify_payload); | |
291 | if (status != SUCCESS) | |
292 | { | |
293 | payloads->destroy(payloads); | |
294 | return status; | |
295 | } | |
296 | } | |
c7dd2a7b MW |
297 | default: |
298 | { | |
5346c894 MW |
299 | this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", |
300 | mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); | |
91194f45 | 301 | break; |
c7dd2a7b MW |
302 | } |
303 | ||
304 | } | |
305 | ||
306 | } | |
307 | payloads->destroy(payloads); | |
d048df5c | 308 | |
5346c894 MW |
309 | if (!(nonce_payload && sa_payload && ke_payload)) |
310 | { | |
311 | this->logger->log(this->logger, AUDIT, "IKE_SA_INIT reply did not contain all required payloads. Deleting IKE_SA"); | |
312 | return DELETE_ME; | |
313 | } | |
314 | ||
91194f45 JH |
315 | status = this->process_nonce_payload (this,nonce_payload); |
316 | if (status != SUCCESS) | |
317 | { | |
318 | return status; | |
319 | } | |
d048df5c | 320 | |
91194f45 JH |
321 | status = this->process_sa_payload (this,sa_payload); |
322 | if (status != SUCCESS) | |
323 | { | |
324 | return status; | |
325 | } | |
326 | ||
327 | status = this->process_ke_payload (this,ke_payload); | |
328 | if (status != SUCCESS) | |
329 | { | |
330 | return status; | |
331 | } | |
ce461bbd MW |
332 | |
333 | /* derive all the keys used in the IKE_SA */ | |
334 | status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->sent_nonce, this->received_nonce); | |
335 | if (status != SUCCESS) | |
336 | { | |
337 | this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA"); | |
338 | return DELETE_ME; | |
339 | } | |
340 | ||
5346c894 | 341 | /* build empty message */ |
91194f45 JH |
342 | this->ike_sa->build_message(this->ike_sa, IKE_AUTH, TRUE, &request); |
343 | ||
91194f45 JH |
344 | status = this->build_id_payload(this, &id_payload,request); |
345 | if (status != SUCCESS) | |
346 | { | |
347 | request->destroy(request); | |
348 | return status; | |
349 | } | |
91194f45 | 350 | status = this->build_auth_payload(this,(id_payload_t *) id_payload, request); |
8d68033e JH |
351 | if (status != SUCCESS) |
352 | { | |
91194f45 JH |
353 | request->destroy(request); |
354 | return status; | |
355 | } | |
91194f45 JH |
356 | status = this->build_sa_payload(this, request); |
357 | if (status != SUCCESS) | |
358 | { | |
359 | request->destroy(request); | |
360 | return status; | |
361 | } | |
91194f45 JH |
362 | status = this->build_tsi_payload(this, request); |
363 | if (status != SUCCESS) | |
364 | { | |
365 | request->destroy(request); | |
366 | return status; | |
8d68033e | 367 | } |
91194f45 JH |
368 | status = this->build_tsr_payload(this, request); |
369 | if (status != SUCCESS) | |
370 | { | |
371 | request->destroy(request); | |
372 | return status; | |
373 | } | |
8d68033e | 374 | |
5534ee84 JH |
375 | /* message can now be sent (must not be destroyed) */ |
376 | status = this->ike_sa->send_request(this->ike_sa, request); | |
f890d8fe JH |
377 | if (status != SUCCESS) |
378 | { | |
5346c894 | 379 | this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH request. Deleting IKE_SA"); |
1b3f92d2 | 380 | request->destroy(request); |
56aeee49 | 381 | return DELETE_ME; |
f890d8fe | 382 | } |
94b0f906 JH |
383 | |
384 | this->ike_sa->set_last_replied_message_id(this->ike_sa,ike_sa_init_reply->get_message_id(ike_sa_init_reply)); | |
5534ee84 | 385 | |
8d68033e JH |
386 | ike_sa_init_reply_data = ike_sa_init_reply->get_packet_data(ike_sa_init_reply); |
387 | ||
af30c6b9 | 388 | /* state can now be changed */ |
30b5b412 MW |
389 | next_state = ike_auth_requested_create(this->ike_sa, this->sent_nonce, this->received_nonce, |
390 | ike_sa_init_reply_data, this->child_sa); | |
af30c6b9 | 391 | this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state); |
f890d8fe | 392 | |
af30c6b9 | 393 | this->destroy_after_state_change(this); |
c7dd2a7b MW |
394 | return SUCCESS; |
395 | } | |
396 | ||
91194f45 JH |
397 | |
398 | /** | |
399 | * Implementation of private_ike_sa_init_requested_t.process_nonce_payload. | |
400 | */ | |
401 | status_t process_nonce_payload (private_ike_sa_init_requested_t *this, nonce_payload_t *nonce_payload) | |
402 | { | |
403 | allocator_free(this->received_nonce.ptr); | |
c3dc864e | 404 | this->received_nonce = nonce_payload->get_nonce(nonce_payload); |
91194f45 JH |
405 | return SUCCESS; |
406 | } | |
407 | ||
408 | ||
f890d8fe | 409 | /** |
91194f45 | 410 | * Implementation of private_ike_sa_init_requested_t.process_sa_payload. |
f890d8fe | 411 | */ |
91194f45 | 412 | status_t process_sa_payload (private_ike_sa_init_requested_t *this, sa_payload_t *sa_payload) |
f890d8fe | 413 | { |
ce461bbd MW |
414 | proposal_t *proposal; |
415 | linked_list_t *proposal_list; | |
91194f45 | 416 | init_config_t *init_config; |
f890d8fe | 417 | |
91194f45 | 418 | init_config = this->ike_sa->get_init_config(this->ike_sa); |
f890d8fe | 419 | |
ce461bbd MW |
420 | /* get the list of selected proposals, the peer has to select only one proposal */ |
421 | proposal_list = sa_payload->get_proposals (sa_payload); | |
422 | if (proposal_list->get_count(proposal_list) != 1) | |
8d68033e | 423 | { |
ce461bbd MW |
424 | this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response did not contain a single proposal. Deleting IKE_SA"); |
425 | while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) | |
426 | { | |
427 | proposal->destroy(proposal); | |
428 | } | |
429 | proposal_list->destroy(proposal_list); | |
430 | return DELETE_ME; | |
91194f45 | 431 | } |
ce461bbd MW |
432 | |
433 | /* we have to re-check if the others selection is valid */ | |
434 | this->proposal = init_config->select_proposal(init_config, proposal_list); | |
435 | while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) | |
91194f45 | 436 | { |
ce461bbd | 437 | proposal->destroy(proposal); |
8d68033e | 438 | } |
ce461bbd | 439 | proposal_list->destroy(proposal_list); |
8d68033e | 440 | |
ce461bbd | 441 | if (this->proposal == NULL) |
91194f45 | 442 | { |
5346c894 | 443 | this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained selected proposal we did not offer. Deleting IKE_SA"); |
91194f45 JH |
444 | return DELETE_ME; |
445 | } | |
ce461bbd | 446 | |
91194f45 JH |
447 | return SUCCESS; |
448 | } | |
449 | ||
450 | /** | |
451 | * Implementation of private_ike_sa_init_requested_t.process_ke_payload. | |
452 | */ | |
453 | status_t process_ke_payload (private_ike_sa_init_requested_t *this, ke_payload_t *ke_payload) | |
ce461bbd | 454 | { |
91194f45 | 455 | this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload)); |
1b3f92d2 | 456 | |
8d68033e | 457 | return SUCCESS; |
f890d8fe JH |
458 | } |
459 | ||
af30c6b9 JH |
460 | /** |
461 | * Implementation of private_ike_sa_init_requested_t.build_id_payload. | |
462 | */ | |
91194f45 | 463 | static status_t build_id_payload (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *request) |
f890d8fe | 464 | { |
1b3f92d2 | 465 | sa_config_t *sa_config; |
91194f45 | 466 | id_payload_t *new_id_payload; |
1b3f92d2 JH |
467 | identification_t *identification; |
468 | ||
469 | sa_config = this->ike_sa->get_sa_config(this->ike_sa); | |
8c7824fb | 470 | /* identification_t object gets NOT cloned here */ |
1b3f92d2 | 471 | identification = sa_config->get_my_id(sa_config); |
91194f45 JH |
472 | new_id_payload = id_payload_create_from_identification(TRUE,identification); |
473 | ||
aee3eb52 | 474 | this->logger->log(this->logger, CONTROL|LEVEL2, "Add ID payload to message"); |
91194f45 JH |
475 | request->add_payload(request,(payload_t *) new_id_payload); |
476 | ||
477 | *id_payload = new_id_payload; | |
f890d8fe | 478 | |
91194f45 | 479 | return SUCCESS; |
f890d8fe JH |
480 | } |
481 | ||
af30c6b9 JH |
482 | /** |
483 | * Implementation of private_ike_sa_init_requested_t.build_auth_payload. | |
484 | */ | |
91194f45 | 485 | static status_t build_auth_payload (private_ike_sa_init_requested_t *this, id_payload_t *my_id_payload, message_t *request) |
af30c6b9 | 486 | { |
8d68033e | 487 | authenticator_t *authenticator; |
af30c6b9 | 488 | auth_payload_t *auth_payload; |
8d68033e JH |
489 | status_t status; |
490 | ||
491 | authenticator = authenticator_create(this->ike_sa); | |
aebb38a0 | 492 | status = authenticator->compute_auth_data(authenticator,&auth_payload,this->ike_sa_init_request_data,this->received_nonce,my_id_payload,TRUE); |
8d68033e JH |
493 | authenticator->destroy(authenticator); |
494 | ||
495 | if (status != SUCCESS) | |
496 | { | |
5346c894 | 497 | this->logger->log(this->logger, AUDIT, "Could not generate AUTH data for IKE_AUTH request. Deleting IKE_SA"); |
91194f45 | 498 | return DELETE_ME; |
8d68033e JH |
499 | } |
500 | ||
aee3eb52 | 501 | this->logger->log(this->logger, CONTROL|LEVEL2, "Add AUTH payload to message"); |
91194f45 JH |
502 | request->add_payload(request,(payload_t *) auth_payload); |
503 | ||
8d68033e | 504 | return SUCCESS; |
af30c6b9 JH |
505 | } |
506 | ||
1b3f92d2 JH |
507 | /** |
508 | * Implementation of private_ike_sa_init_requested_t.build_sa_payload. | |
509 | */ | |
91194f45 | 510 | static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message_t *request) |
1b3f92d2 | 511 | { |
c06dbbab | 512 | linked_list_t *proposal_list; |
1b3f92d2 | 513 | sa_payload_t *sa_payload; |
93df94ac MW |
514 | sa_config_t *sa_config; |
515 | ||
dfa6e086 | 516 | /* get proposals form config, add to payload */ |
1b3f92d2 | 517 | sa_config = this->ike_sa->get_sa_config(this->ike_sa); |
c06dbbab | 518 | proposal_list = sa_config->get_proposals(sa_config); |
30b5b412 MW |
519 | /* build child sa */ |
520 | this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), | |
521 | this->ike_sa->get_other_host(this->ike_sa)); | |
522 | if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS) | |
523 | { | |
524 | this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); | |
525 | return DELETE_ME; | |
526 | } | |
527 | ||
528 | /* TODO: | |
529 | * Huston, we've got a problem here. Since SPIs are stored in | |
530 | * the proposal, and these proposals are shared across configs, | |
531 | * there may be some threading issues... fix it! | |
532 | */ | |
ce461bbd | 533 | sa_payload = sa_payload_create_from_proposal_list(proposal_list); |
dfa6e086 | 534 | |
aee3eb52 | 535 | this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message"); |
91194f45 JH |
536 | request->add_payload(request,(payload_t *) sa_payload); |
537 | ||
538 | return SUCCESS; | |
1b3f92d2 JH |
539 | } |
540 | ||
541 | /** | |
542 | * Implementation of private_ike_sa_init_requested_t.build_tsi_payload. | |
543 | */ | |
91194f45 | 544 | static status_t build_tsi_payload (private_ike_sa_init_requested_t *this, message_t *request) |
1b3f92d2 | 545 | { |
a527a426 | 546 | linked_list_t *ts_list; |
8c7824fb JH |
547 | ts_payload_t *ts_payload; |
548 | sa_config_t *sa_config; | |
1b3f92d2 JH |
549 | |
550 | sa_config = this->ike_sa->get_sa_config(this->ike_sa); | |
a527a426 MW |
551 | ts_list = sa_config->get_my_traffic_selectors(sa_config); |
552 | ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list); | |
91194f45 | 553 | |
aee3eb52 | 554 | this->logger->log(this->logger, CONTROL|LEVEL2, "Add TSi payload to message"); |
91194f45 JH |
555 | request->add_payload(request,(payload_t *) ts_payload); |
556 | ||
557 | return SUCCESS; | |
1b3f92d2 JH |
558 | } |
559 | ||
560 | /** | |
561 | * Implementation of private_ike_sa_init_requested_t.build_tsr_payload. | |
562 | */ | |
91194f45 | 563 | static status_t build_tsr_payload (private_ike_sa_init_requested_t *this, message_t *request) |
1b3f92d2 | 564 | { |
a527a426 | 565 | linked_list_t *ts_list; |
8c7824fb JH |
566 | ts_payload_t *ts_payload; |
567 | sa_config_t *sa_config; | |
1b3f92d2 JH |
568 | |
569 | sa_config = this->ike_sa->get_sa_config(this->ike_sa); | |
a527a426 MW |
570 | ts_list = sa_config->get_other_traffic_selectors(sa_config); |
571 | ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list); | |
8c7824fb | 572 | |
aee3eb52 | 573 | this->logger->log(this->logger, CONTROL|LEVEL2, "Add TSr payload to message"); |
91194f45 JH |
574 | request->add_payload(request,(payload_t *) ts_payload); |
575 | ||
576 | return SUCCESS; | |
1b3f92d2 JH |
577 | } |
578 | ||
5346c894 MW |
579 | /** |
580 | * Implementation of private_ike_sa_init_requested_t.process_notify_payload. | |
581 | */ | |
582 | static status_t process_notify_payload(private_ike_sa_init_requested_t *this, notify_payload_t *notify_payload) | |
583 | { | |
584 | notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); | |
585 | ||
586 | this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s for protocol %s", | |
587 | mapping_find(notify_message_type_m, notify_message_type), | |
588 | mapping_find(protocol_id_m, notify_payload->get_protocol_id(notify_payload))); | |
589 | ||
590 | if (notify_payload->get_protocol_id(notify_payload) != IKE) | |
591 | { | |
592 | this->logger->log(this->logger, ERROR | LEVEL1, "Notify reply not for IKE protocol."); | |
593 | return FAILED; | |
594 | } | |
595 | switch (notify_message_type) | |
596 | { | |
597 | case NO_PROPOSAL_CHOSEN: | |
598 | { | |
599 | this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained a NO_PROPOSAL_CHOSEN notify. Deleting IKE_SA"); | |
600 | return DELETE_ME; | |
601 | } | |
602 | case INVALID_MAJOR_VERSION: | |
603 | { | |
604 | this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained a INVALID_MAJOR_VERSION notify. Deleting IKE_SA"); | |
605 | return DELETE_ME; | |
606 | } | |
607 | case INVALID_KE_PAYLOAD: | |
608 | { | |
609 | initiator_init_t *initiator_init_state; | |
ce461bbd MW |
610 | chunk_t notify_data; |
611 | diffie_hellman_group_t dh_group; | |
612 | init_config_t *init_config; | |
613 | ||
614 | notify_data = notify_payload->get_notification_data(notify_payload); | |
615 | dh_group = ntohs(*((u_int16_t*)notify_data.ptr)); | |
616 | ||
617 | this->logger->log(this->logger, ERROR|LEVEL1, "Peer wouldn't accept DH group, it requested %s!", | |
618 | mapping_find(diffie_hellman_group_m, dh_group)); | |
619 | /* check if we can accept this dh group */ | |
620 | init_config = this->ike_sa->get_init_config(this->ike_sa); | |
621 | if (!init_config->check_dh_group(init_config, dh_group)) | |
622 | { | |
623 | this->logger->log(this->logger, AUDIT, | |
624 | "Peer does only accept DH group %s, which we do not accept! Aborting", | |
625 | mapping_find(diffie_hellman_group_m, dh_group)); | |
626 | return DELETE_ME; | |
627 | } | |
5346c894 | 628 | |
5346c894 MW |
629 | /* Going to change state back to initiator_init_t */ |
630 | this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object"); | |
631 | initiator_init_state = initiator_init_create(this->ike_sa); | |
632 | ||
633 | /* buffer of sent and received messages has to get reseted */ | |
634 | this->ike_sa->reset_message_buffers(this->ike_sa); | |
635 | ||
636 | /* state can now be changed */ | |
637 | this->ike_sa->set_new_state(this->ike_sa,(state_t *) initiator_init_state); | |
638 | ||
639 | /* state has NOW changed :-) */ | |
640 | this->logger->log(this->logger, CONTROL|LEVEL1, "Changed state of IKE_SA from %s to %s", | |
641 | mapping_find(ike_sa_state_m,INITIATOR_INIT), mapping_find(ike_sa_state_m,IKE_SA_INIT_REQUESTED)); | |
642 | ||
643 | this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy old sate object"); | |
644 | this->logger->log(this->logger, CONTROL|LEVEL2, "Going to retry initialization of connection"); | |
5346c894 MW |
645 | |
646 | this->public.state_interface.destroy(&(this->public.state_interface)); | |
ce461bbd | 647 | if (initiator_init_state->retry_initiate_connection (initiator_init_state, dh_group) != SUCCESS) |
6db4e80b MW |
648 | { |
649 | return DELETE_ME; | |
650 | } | |
651 | return FAILED; | |
5346c894 MW |
652 | } |
653 | default: | |
654 | { | |
655 | /* | |
656 | * - In case of unknown error: IKE_SA gets destroyed. | |
657 | * - In case of unknown status: logging | |
658 | */ | |
659 | if (notify_message_type < 16383) | |
660 | { | |
661 | this->logger->log(this->logger, AUDIT, "IKE_SA_INIT reply contained an unknown notify error (%d). Deleting IKE_SA", | |
662 | notify_message_type); | |
663 | return DELETE_ME; | |
664 | } | |
665 | else | |
666 | { | |
667 | this->logger->log(this->logger, CONTROL, "IKE_SA_INIT reply contained an unknown notify (%d), ignored.", | |
668 | notify_message_type); | |
669 | return SUCCESS; | |
670 | } | |
671 | } | |
672 | } | |
673 | } | |
674 | ||
c7dd2a7b | 675 | /** |
91194f45 | 676 | * Implementation of state_t.get_state. |
c7dd2a7b MW |
677 | */ |
678 | static ike_sa_state_t get_state(private_ike_sa_init_requested_t *this) | |
679 | { | |
680 | return IKE_SA_INIT_REQUESTED; | |
681 | } | |
682 | ||
af30c6b9 | 683 | /** |
91194f45 | 684 | * Implementation of private_ike_sa_init_requested_t.destroy_after_state_change. |
af30c6b9 JH |
685 | */ |
686 | static void destroy_after_state_change (private_ike_sa_init_requested_t *this) | |
687 | { | |
af30c6b9 | 688 | this->diffie_hellman->destroy(this->diffie_hellman); |
8d68033e | 689 | allocator_free_chunk(&(this->ike_sa_init_request_data)); |
ce461bbd MW |
690 | if (this->proposal) |
691 | { | |
692 | this->proposal->destroy(this->proposal); | |
693 | } | |
694 | allocator_free(this); | |
af30c6b9 JH |
695 | } |
696 | ||
c7dd2a7b | 697 | /** |
91194f45 | 698 | * Implementation state_t.destroy. |
c7dd2a7b | 699 | */ |
d048df5c | 700 | static void destroy(private_ike_sa_init_requested_t *this) |
c7dd2a7b | 701 | { |
c7dd2a7b | 702 | this->diffie_hellman->destroy(this->diffie_hellman); |
d048df5c MW |
703 | allocator_free(this->sent_nonce.ptr); |
704 | allocator_free(this->received_nonce.ptr); | |
8d68033e | 705 | allocator_free_chunk(&(this->ike_sa_init_request_data)); |
30b5b412 MW |
706 | if (this->child_sa) |
707 | { | |
708 | this->child_sa->destroy(this->child_sa); | |
709 | } | |
ce461bbd MW |
710 | if (this->proposal) |
711 | { | |
712 | this->proposal->destroy(this->proposal); | |
713 | } | |
c7dd2a7b | 714 | allocator_free(this); |
c7dd2a7b MW |
715 | } |
716 | ||
717 | /* | |
718 | * Described in header. | |
719 | */ | |
ce461bbd | 720 | ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa, diffie_hellman_t *diffie_hellman, chunk_t sent_nonce,chunk_t ike_sa_init_request_data) |
c7dd2a7b MW |
721 | { |
722 | private_ike_sa_init_requested_t *this = allocator_alloc_thing(private_ike_sa_init_requested_t); | |
723 | ||
c7dd2a7b | 724 | /* interface functions */ |
aad398a7 | 725 | this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; |
c7dd2a7b | 726 | this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; |
d048df5c | 727 | this->public.state_interface.destroy = (void (*) (state_t *)) destroy; |
c7dd2a7b | 728 | |
f890d8fe | 729 | /* private functions */ |
91194f45 JH |
730 | this->destroy_after_state_change = destroy_after_state_change; |
731 | this->process_nonce_payload = process_nonce_payload; | |
732 | this->process_sa_payload = process_sa_payload; | |
733 | this->process_ke_payload = process_ke_payload; | |
af30c6b9 | 734 | this->build_auth_payload = build_auth_payload; |
1b3f92d2 JH |
735 | this->build_tsi_payload = build_tsi_payload; |
736 | this->build_tsr_payload = build_tsr_payload; | |
91194f45 JH |
737 | this->build_id_payload = build_id_payload; |
738 | this->build_sa_payload = build_sa_payload; | |
5346c894 | 739 | this->process_notify_payload = process_notify_payload; |
f890d8fe | 740 | |
c7dd2a7b MW |
741 | /* private data */ |
742 | this->ike_sa = ike_sa; | |
d048df5c | 743 | this->received_nonce = CHUNK_INITIALIZER; |
aad398a7 | 744 | this->logger = this->ike_sa->get_logger(this->ike_sa); |
c7dd2a7b | 745 | this->diffie_hellman = diffie_hellman; |
ce461bbd | 746 | this->proposal = NULL; |
c7dd2a7b | 747 | this->sent_nonce = sent_nonce; |
30b5b412 | 748 | this->child_sa = NULL; |
8d68033e | 749 | this->ike_sa_init_request_data = ike_sa_init_request_data; |
c7dd2a7b MW |
750 | |
751 | return &(this->public); | |
752 | } |