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