2 * @file ike_sa_init_responded.c
4 * @brief State of a IKE_SA after responding to an IKE_SA_INIT request
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
23 #include "ike_sa_init_responded.h"
26 #include <utils/allocator.h>
27 #include <sa/authenticator.h>
28 #include <sa/child_sa.h>
29 #include <encoding/payloads/ts_payload.h>
30 #include <encoding/payloads/sa_payload.h>
31 #include <encoding/payloads/id_payload.h>
32 #include <encoding/payloads/auth_payload.h>
33 #include <encoding/payloads/notify_payload.h>
34 #include <transforms/signers/signer.h>
35 #include <transforms/crypters/crypter.h>
36 #include <sa/states/ike_sa_established.h>
39 typedef struct private_ike_sa_init_responded_t private_ike_sa_init_responded_t
;
42 * Private data of a ike_sa_init_responded_t object.
45 struct private_ike_sa_init_responded_t
{
47 * Public interface of ike_sa_init_responded_t.
49 ike_sa_init_responded_t
public;
54 protected_ike_sa_t
*ike_sa
;
59 chunk_t received_nonce
;
67 * Binary representation of the IKE_SA_INIT response.
69 chunk_t ike_sa_init_response_data
;
72 * Binary representation of the IKE_SA_INIT request.
74 chunk_t ike_sa_init_request_data
;
79 sa_config_t
*sa_config
;
84 * Is logger of ike_sa!
89 * Process received IDi and IDr payload and build IDr payload for IKE_AUTH response.
91 * @param this calling object
92 * @param request_idi ID payload representing initiator
93 * @param request_idr ID payload representing responder (May be zero)
94 * @param response The created IDr payload is added to this message_t object
95 * @param response_idr The created IDr payload is also written to this location
97 status_t (*build_idr_payload
) (private_ike_sa_init_responded_t
*this,
98 id_payload_t
*request_idi
,
99 id_payload_t
*request_idr
,
101 id_payload_t
**response_idr
);
104 * Process received SA payload and build SA payload for IKE_AUTH response.
106 * @param this calling object
107 * @param request SA payload received in IKE_AUTH request
108 * @param response The created SA payload is added to this message_t object
110 status_t (*build_sa_payload
) (private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
);
113 * Process received AUTH payload and build AUTH payload for IKE_AUTH response.
115 * @param this calling object
116 * @param request AUTH payload received in IKE_AUTH request
117 * @param other_id_payload other ID payload needed to verify AUTH data
118 * @param my_id_payload my ID payload needed to compute AUTH data
119 * @param response The created AUTH payload is added to this message_t object
121 status_t (*build_auth_payload
) (private_ike_sa_init_responded_t
*this, auth_payload_t
*request
,id_payload_t
*other_id_payload
,id_payload_t
*my_id_payload
, message_t
* response
);
124 * Process received TS payload and build TS payload for IKE_AUTH response.
126 * @param this calling object
127 * @param is_initiator type of TS payload. TRUE for TSi, FALSE for TSr
128 * @param request TS payload received in IKE_AUTH request
129 * @param response the created TS payload is added to this message_t object
131 status_t (*build_ts_payload
) (private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
*response
);
134 * Sends a IKE_AUTH reply containing a notify payload.
136 * @param this calling object
137 * @param notify_payload payload to process
139 * - DELETE_ME if IKE_SA should be deleted
140 * - SUCCSS if processed successfull
142 status_t (*process_notify_payload
) (private_ike_sa_init_responded_t
*this, notify_payload_t
* notify_payload
);
146 * Implements state_t.get_state
148 static status_t
process_message(private_ike_sa_init_responded_t
*this, message_t
*request
)
150 id_payload_t
*idi_request
= NULL
, *idr_request
= NULL
,*idr_response
;
151 ts_payload_t
*tsi_request
= NULL
, *tsr_request
= NULL
;
152 auth_payload_t
*auth_request
= NULL
;
153 sa_payload_t
*sa_request
= NULL
;
154 iterator_t
*payloads
;
159 host_t
*my_host
, *other_host
;
162 if (request
->get_exchange_type(request
) != IKE_AUTH
)
164 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "Message of type %s not supported in state ike_sa_init_responded",
165 mapping_find(exchange_type_m
,request
->get_exchange_type(request
)));
169 if (!request
->get_request(request
))
171 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "IKE_AUTH responses not allowed state ike_sa_init_responded");
175 /* get signer for verification and crypter for decryption */
176 signer
= this->ike_sa
->get_signer_initiator(this->ike_sa
);
177 crypter
= this->ike_sa
->get_crypter_initiator(this->ike_sa
);
179 status
= request
->parse_body(request
, crypter
, signer
);
180 if (status
!= SUCCESS
)
182 if (status
== NOT_SUPPORTED
)
184 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "IKE_AUTH request contains unsupported payload with critical flag set."
186 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, UNSUPPORTED_CRITICAL_PAYLOAD
, CHUNK_INITIALIZER
);
191 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request decryption faild. Ignoring message");
196 /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
197 payloads
= request
->get_payload_iterator(request
);
198 while (payloads
->has_next(payloads
))
201 payloads
->current(payloads
, (void**)&payload
);
203 switch (payload
->get_type(payload
))
207 idi_request
= (id_payload_t
*)payload
;
212 auth_request
= (auth_payload_t
*)payload
;
217 idr_request
= (id_payload_t
*)payload
;
220 case SECURITY_ASSOCIATION
:
222 sa_request
= (sa_payload_t
*)payload
;
226 case TRAFFIC_SELECTOR_INITIATOR
:
228 tsi_request
= (ts_payload_t
*)payload
;
231 case TRAFFIC_SELECTOR_RESPONDER
:
233 tsr_request
= (ts_payload_t
*)payload
;
238 notify_payload_t
*notify_payload
= (notify_payload_t
*) payload
;
239 status
= this->process_notify_payload(this, notify_payload
);
240 if (status
!= SUCCESS
)
242 payloads
->destroy(payloads
);
248 /* TODO handle cert payloads */
250 case CERTIFICATE_REQUEST
:
252 /* TODO handle certrequest payloads */
256 this->logger
->log(this->logger
, ERROR
|LEVEL1
, "Ignoring payload %s (%d)",
257 mapping_find(payload_type_m
, payload
->get_type(payload
)), payload
->get_type(payload
));
262 /* iterator can be destroyed */
263 payloads
->destroy(payloads
);
265 /* check if we have all payloads */
266 if (!(idi_request
&& sa_request
&& auth_request
&& tsi_request
&& tsr_request
))
268 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA");
273 this->ike_sa
->build_message(this->ike_sa
, IKE_AUTH
, FALSE
, &response
);
275 /* add payloads to it */
276 status
= this->build_idr_payload(this, idi_request
, idr_request
, response
,&idr_response
);
277 if (status
!= SUCCESS
)
279 response
->destroy(response
);
282 status
= this->build_sa_payload(this, sa_request
, response
);
283 if (status
!= SUCCESS
)
285 response
->destroy(response
);
288 status
= this->build_auth_payload(this, auth_request
,idi_request
, idr_response
,response
);
289 if (status
!= SUCCESS
)
291 response
->destroy(response
);
294 status
= this->build_ts_payload(this, TRUE
, tsi_request
, response
);
295 if (status
!= SUCCESS
)
297 response
->destroy(response
);
300 status
= this->build_ts_payload(this, FALSE
, tsr_request
, response
);
301 if (status
!= SUCCESS
)
303 response
->destroy(response
);
307 status
= this->ike_sa
->send_response(this->ike_sa
, response
);
308 /* message can now be sent (must not be destroyed) */
309 if (status
!= SUCCESS
)
311 this->logger
->log(this->logger
, AUDIT
, "Unable to send IKE_AUTH reply. Deleting IKE_SA");
312 response
->destroy(response
);
316 /* create new state */my_host
= this->ike_sa
->get_my_host(this->ike_sa
);
317 other_host
= this->ike_sa
->get_other_host(this->ike_sa
);
318 this->logger
->log(this->logger
, AUDIT
, "IKE_SA established between %s - %s, authenticated peer with %s",
319 my_host
->get_address(my_host
), other_host
->get_address(other_host
),
320 mapping_find(auth_method_m
, auth_request
->get_auth_method(auth_request
)));
322 this->ike_sa
->create_delete_established_ike_sa_job(this->ike_sa
,this->sa_config
->get_ike_sa_lifetime(this->sa_config
));
323 this->ike_sa
->set_new_state(this->ike_sa
, (state_t
*)ike_sa_established_create(this->ike_sa
));
324 this->public.state_interface
.destroy(&(this->public.state_interface
));
330 * Implementation of private_ike_sa_init_responded_t.build_idr_payload.
332 static status_t
build_idr_payload(private_ike_sa_init_responded_t
*this, id_payload_t
*request_idi
, id_payload_t
*request_idr
, message_t
*response
,id_payload_t
**response_idr
)
334 identification_t
*other_id
, *my_id
= NULL
;
335 init_config_t
*init_config
;
337 id_payload_t
*idr_response
;
339 other_id
= request_idi
->get_identification(request_idi
);
342 my_id
= request_idr
->get_identification(request_idr
);
345 /* build new sa config */
346 init_config
= this->ike_sa
->get_init_config(this->ike_sa
);
347 status
= charon
->configuration_manager
->get_sa_config_for_init_config_and_id(charon
->configuration_manager
,init_config
, other_id
,my_id
, &(this->sa_config
));
348 if (status
!= SUCCESS
)
352 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request uses IDs %s to %s, which we have no config for",
353 other_id
->get_string(other_id
),my_id
->get_string(my_id
));
354 my_id
->destroy(my_id
);
358 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request uses ID %s, which we have no config for",
359 other_id
->get_string(other_id
));
361 other_id
->destroy(other_id
);
367 my_id
->destroy(my_id
);
369 other_id
->destroy(other_id
);
371 /* get my id, if not requested */
372 my_id
= this->sa_config
->get_my_id(this->sa_config
);
374 /* set sa_config in ike_sa for other states */
375 this->ike_sa
->set_sa_config(this->ike_sa
, this->sa_config
);
378 idr_response
= id_payload_create_from_identification(FALSE
, my_id
);
379 response
->add_payload(response
, (payload_t
*)idr_response
);
380 *response_idr
= idr_response
;
386 * Implementation of private_ike_sa_init_responded_t.build_sa_payload.
388 static status_t
build_sa_payload(private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
)
390 child_proposal_t
*proposal
, *proposal_tmp
;
391 linked_list_t
*proposal_list
;
392 sa_payload_t
*sa_response
;
393 child_sa_t
*child_sa
;
394 prf_plus_t
*prf_plus
;
397 /* TODO: child sa stuff */
399 /* get proposals from request */
400 proposal_list
= request
->get_child_proposals(request
);
401 if (proposal_list
->get_count(proposal_list
) == 0)
403 /* if the other side did not offer any proposals, we do not create child sa's */
404 this->logger
->log(this->logger
, AUDIT
, "IKE_AUH request did not contain any proposals. No CHILD_SA created");
405 sa_response
= sa_payload_create();
406 response
->add_payload(response
, (payload_t
*)sa_response
);
407 proposal_list
->destroy(proposal_list
);
411 /* now select a proposal */
412 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Selecting proposals:");
413 proposal
= this->sa_config
->select_proposal(this->sa_config
, proposal_list
);
414 /* list is not needed anymore */
415 while (proposal_list
->remove_last(proposal_list
, (void**)&proposal_tmp
) == SUCCESS
)
417 proposal_tmp
->destroy(proposal_tmp
);
419 proposal_list
->destroy(proposal_list
);
420 /* do we have a proposal */
421 if (proposal
== NULL
)
423 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA");
424 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, NO_PROPOSAL_CHOSEN
, CHUNK_INITIALIZER
);
428 /* create payload with selected propsal */
429 sa_response
= sa_payload_create_from_child_proposal(proposal
);
430 response
->add_payload(response
, (payload_t
*)sa_response
);
432 /* install child SAs for AH and esp */
433 seed
= allocator_alloc_as_chunk(this->received_nonce
.len
+ this->sent_nonce
.len
);
434 memcpy(seed
.ptr
, this->received_nonce
.ptr
, this->received_nonce
.len
);
435 memcpy(seed
.ptr
+ this->received_nonce
.len
, this->sent_nonce
.ptr
, this->sent_nonce
.len
);
436 prf_plus
= prf_plus_create(this->ike_sa
->get_child_prf(this->ike_sa
), seed
);
437 allocator_free_chunk(&seed
);
439 child_sa
= child_sa_create(proposal
, prf_plus
);
440 prf_plus
->destroy(prf_plus
);
441 child_sa
->destroy(child_sa
);
443 proposal
->destroy(proposal
);
448 * Implementation of private_ike_sa_init_responded_t.build_auth_payload.
450 static status_t
build_auth_payload(private_ike_sa_init_responded_t
*this, auth_payload_t
*auth_request
,id_payload_t
*other_id_payload
,id_payload_t
*my_id_payload
, message_t
* response
)
452 authenticator_t
*authenticator
;
453 auth_payload_t
*auth_reply
;
456 authenticator
= authenticator_create(this->ike_sa
);
459 status
= authenticator
->verify_auth_data(authenticator
,auth_request
, this->ike_sa_init_request_data
,this->sent_nonce
,other_id_payload
,TRUE
);
461 if (status
!= SUCCESS
)
463 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request verification failed. Deleting IKE_SA");
464 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, AUTHENTICATION_FAILED
, CHUNK_INITIALIZER
);
465 authenticator
->destroy(authenticator
);
470 status
= authenticator
->compute_auth_data(authenticator
,&auth_reply
, this->ike_sa_init_response_data
,this->received_nonce
,my_id_payload
,FALSE
);
471 authenticator
->destroy(authenticator
);
472 if (status
!= SUCCESS
)
474 this->logger
->log(this->logger
, AUDIT
, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA");
479 response
->add_payload(response
, (payload_t
*)auth_reply
);
484 * Implementation of private_ike_sa_init_responded_t.build_ts_payload.
486 static status_t
build_ts_payload(private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
* response
)
488 traffic_selector_t
**ts_received
, **ts_selected
;
489 size_t ts_received_count
, ts_selected_count
;
490 status_t status
= SUCCESS
;
491 ts_payload_t
*ts_response
;
493 /* build a reply payload with selected traffic selectors */
494 ts_received_count
= request
->get_traffic_selectors(request
, &ts_received
);
495 /* select ts depending on payload type */
498 ts_selected_count
= this->sa_config
->select_traffic_selectors_initiator(this->sa_config
, ts_received
, ts_received_count
, &ts_selected
);
502 ts_selected_count
= this->sa_config
->select_traffic_selectors_responder(this->sa_config
, ts_received
, ts_received_count
, &ts_selected
);
504 if(ts_selected_count
== 0)
506 this->logger
->log(this->logger
, AUDIT
, "IKE_AUH request did not contain any traffic selectors.");
507 ts_response
= ts_payload_create(ts_initiator
);
508 response
->add_payload(response
, (payload_t
*)ts_response
);
512 ts_response
= ts_payload_create_from_traffic_selectors(ts_initiator
, ts_selected
, ts_selected_count
);
513 response
->add_payload(response
, (payload_t
*)ts_response
);
517 while(ts_received_count
--)
519 traffic_selector_t
*ts
= *ts_received
+ ts_received_count
;
522 allocator_free(ts_received
);
523 while(ts_selected_count
--)
525 traffic_selector_t
*ts
= *ts_selected
+ ts_selected_count
;
528 allocator_free(ts_selected
);
532 static status_t
process_notify_payload(private_ike_sa_init_responded_t
*this, notify_payload_t
*notify_payload
)
534 notify_message_type_t notify_message_type
= notify_payload
->get_notify_message_type(notify_payload
);
536 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Process notify type %s for protocol %s",
537 mapping_find(notify_message_type_m
, notify_message_type
),
538 mapping_find(protocol_id_m
, notify_payload
->get_protocol_id(notify_payload
)));
540 switch (notify_message_type
)
542 case SET_WINDOW_SIZE
:
544 * TODO Increase window size.
546 case INITIAL_CONTACT
:
548 * TODO Delete existing IKE_SA's with other Identity.
552 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request contained an unknown notify (%d), ignored.", notify_message_type
);
560 * Implementation of state_t.get_state.
562 static ike_sa_state_t
get_state(private_ike_sa_init_responded_t
*this)
564 return IKE_SA_INIT_RESPONDED
;
568 * Implementation of state_t.get_state.
570 static void destroy(private_ike_sa_init_responded_t
*this)
572 this->logger
->log(this->logger
, CONTROL
| LEVEL3
, "Going to destroy ike_sa_init_responded_t state object");
574 this->logger
->log(this->logger
, CONTROL
| LEVEL3
, "Destroy received nonce");
575 allocator_free_chunk(&(this->received_nonce
));
576 this->logger
->log(this->logger
, CONTROL
| LEVEL3
, "Destroy sent nonce");
577 allocator_free_chunk(&(this->sent_nonce
));
578 this->logger
->log(this->logger
, CONTROL
| LEVEL3
, "Destroy IKE_SA_INIT response octets");
579 allocator_free_chunk(&(this->ike_sa_init_response_data
));
580 this->logger
->log(this->logger
, CONTROL
| LEVEL3
, "Destroy IKE_SA_INIT request octets");
581 allocator_free_chunk(&(this->ike_sa_init_request_data
));
583 allocator_free(this);
587 * Described in header.
589 ike_sa_init_responded_t
*ike_sa_init_responded_create(protected_ike_sa_t
*ike_sa
, chunk_t received_nonce
, chunk_t sent_nonce
,chunk_t ike_sa_init_request_data
, chunk_t ike_sa_init_response_data
)
591 private_ike_sa_init_responded_t
*this = allocator_alloc_thing(private_ike_sa_init_responded_t
);
593 /* interface functions */
594 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
595 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
596 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
598 /* private functions */
599 this->build_idr_payload
= build_idr_payload
;
600 this->build_sa_payload
= build_sa_payload
;
601 this->build_auth_payload
= build_auth_payload
;
602 this->build_ts_payload
= build_ts_payload
;
603 this->process_notify_payload
= process_notify_payload
;
606 this->ike_sa
= ike_sa
;
607 this->received_nonce
= received_nonce
;
608 this->sent_nonce
= sent_nonce
;
609 this->ike_sa_init_response_data
= ike_sa_init_response_data
;
610 this->ike_sa_init_request_data
= ike_sa_init_request_data
;
611 this->logger
= this->ike_sa
->get_logger(this->ike_sa
);
613 return &(this->public);