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
25 #include "ike_sa_init_responded.h"
28 #include <sa/authenticator.h>
29 #include <sa/child_sa.h>
30 #include <encoding/payloads/ts_payload.h>
31 #include <encoding/payloads/sa_payload.h>
32 #include <encoding/payloads/id_payload.h>
33 #include <encoding/payloads/auth_payload.h>
34 #include <encoding/payloads/notify_payload.h>
35 #include <crypto/signers/signer.h>
36 #include <crypto/crypters/crypter.h>
37 #include <sa/states/ike_sa_established.h>
40 typedef struct private_ike_sa_init_responded_t private_ike_sa_init_responded_t
;
43 * Private data of a ike_sa_init_responded_t object.
46 struct private_ike_sa_init_responded_t
{
48 * Public interface of ike_sa_init_responded_t.
50 ike_sa_init_responded_t
public;
55 protected_ike_sa_t
*ike_sa
;
60 chunk_t received_nonce
;
68 * Binary representation of the IKE_SA_INIT response.
70 chunk_t ike_sa_init_response_data
;
73 * Binary representation of the IKE_SA_INIT request.
75 chunk_t ike_sa_init_request_data
;
88 * Traffic selectors applicable at our site
93 * Traffic selectors applicable at remote site
95 linked_list_t
*other_ts
;
100 * Is logger of ike_sa!
105 * Process received IDi and IDr payload and build IDr payload for IKE_AUTH response.
107 * @param this calling object
108 * @param request_idi ID payload representing initiator
109 * @param request_idr ID payload representing responder (May be zero)
110 * @param response The created IDr payload is added to this message_t object
111 * @param response_idr The created IDr payload is also written to this location
113 status_t (*build_idr_payload
) (private_ike_sa_init_responded_t
*this,
114 id_payload_t
*request_idi
,
115 id_payload_t
*request_idr
,
117 id_payload_t
**response_idr
);
120 * Process received SA payload and build SA payload for IKE_AUTH response.
122 * @param this calling object
123 * @param request SA payload received in IKE_AUTH request
124 * @param response The created SA payload is added to this message_t object
126 status_t (*build_sa_payload
) (private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
);
129 * Process received AUTH payload and build AUTH payload for IKE_AUTH response.
131 * @param this calling object
132 * @param request AUTH payload received in IKE_AUTH request
133 * @param other_id_payload other ID payload needed to verify AUTH data
134 * @param my_id_payload my ID payload needed to compute AUTH data
135 * @param response The created AUTH payload is added to this message_t object
137 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
);
140 * Process received TS payload and build TS payload for IKE_AUTH response.
142 * @param this calling object
143 * @param is_initiator type of TS payload. TRUE for TSi, FALSE for TSr
144 * @param request TS payload received in IKE_AUTH request
145 * @param response the created TS payload is added to this message_t object
147 status_t (*build_ts_payload
) (private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
*response
);
150 * Sends a IKE_AUTH reply containing a notify payload.
152 * @param this calling object
153 * @param notify_payload payload to process
155 * - DELETE_ME if IKE_SA should be deleted
156 * - SUCCSS if processed successfull
158 status_t (*process_notify_payload
) (private_ike_sa_init_responded_t
*this, notify_payload_t
* notify_payload
);
161 * Destroy function called internally of this class after state change to
162 * state IKE_SA_ESTABLISHED succeeded.
164 * This destroy function does not destroy objects which were passed to the new state.
166 * @param this calling object
168 void (*destroy_after_state_change
) (private_ike_sa_init_responded_t
*this);
172 * Implements state_t.get_state
174 static status_t
process_message(private_ike_sa_init_responded_t
*this, message_t
*request
)
176 id_payload_t
*idi_request
= NULL
, *idr_request
= NULL
,*idr_response
;
177 ts_payload_t
*tsi_request
= NULL
, *tsr_request
= NULL
;
178 auth_payload_t
*auth_request
= NULL
;
179 sa_payload_t
*sa_request
= NULL
;
180 iterator_t
*payloads
;
185 host_t
*my_host
, *other_host
;
186 connection_t
*connection
;
188 if (request
->get_exchange_type(request
) != IKE_AUTH
)
190 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "Message of type %s not supported in state ike_sa_init_responded",
191 mapping_find(exchange_type_m
,request
->get_exchange_type(request
)));
195 if (!request
->get_request(request
))
197 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "IKE_AUTH responses not allowed state ike_sa_init_responded");
201 /* get signer for verification and crypter for decryption */
202 signer
= this->ike_sa
->get_signer_initiator(this->ike_sa
);
203 crypter
= this->ike_sa
->get_crypter_initiator(this->ike_sa
);
205 status
= request
->parse_body(request
, crypter
, signer
);
206 if (status
!= SUCCESS
)
208 if (status
== NOT_SUPPORTED
)
210 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "IKE_AUTH request contains unsupported payload with critical flag set."
212 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, UNSUPPORTED_CRITICAL_PAYLOAD
, CHUNK_INITIALIZER
);
217 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request decryption faild. Ignoring message");
222 /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
223 payloads
= request
->get_payload_iterator(request
);
224 while (payloads
->has_next(payloads
))
227 payloads
->current(payloads
, (void**)&payload
);
229 switch (payload
->get_type(payload
))
233 idi_request
= (id_payload_t
*)payload
;
238 auth_request
= (auth_payload_t
*)payload
;
243 idr_request
= (id_payload_t
*)payload
;
246 case SECURITY_ASSOCIATION
:
248 sa_request
= (sa_payload_t
*)payload
;
251 case TRAFFIC_SELECTOR_INITIATOR
:
253 tsi_request
= (ts_payload_t
*)payload
;
256 case TRAFFIC_SELECTOR_RESPONDER
:
258 tsr_request
= (ts_payload_t
*)payload
;
263 notify_payload_t
*notify_payload
= (notify_payload_t
*) payload
;
264 status
= this->process_notify_payload(this, notify_payload
);
265 if (status
!= SUCCESS
)
267 payloads
->destroy(payloads
);
273 /* TODO handle cert payloads */
275 case CERTIFICATE_REQUEST
:
277 /* TODO handle certrequest payloads */
281 this->logger
->log(this->logger
, ERROR
|LEVEL1
, "Ignoring payload %s (%d)",
282 mapping_find(payload_type_m
, payload
->get_type(payload
)), payload
->get_type(payload
));
287 /* iterator can be destroyed */
288 payloads
->destroy(payloads
);
290 /* check if we have all payloads */
291 if (!(idi_request
&& sa_request
&& auth_request
&& tsi_request
&& tsr_request
))
293 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA");
298 this->ike_sa
->build_message(this->ike_sa
, IKE_AUTH
, FALSE
, &response
);
300 /* add payloads to it */
301 status
= this->build_idr_payload(this, idi_request
, idr_request
, response
,&idr_response
);
302 if (status
!= SUCCESS
)
304 response
->destroy(response
);
307 status
= this->build_auth_payload(this, auth_request
,idi_request
, idr_response
,response
);
308 if (status
!= SUCCESS
)
310 response
->destroy(response
);
313 status
= this->build_sa_payload(this, sa_request
, response
);
314 if (status
!= SUCCESS
)
316 response
->destroy(response
);
319 status
= this->build_ts_payload(this, TRUE
, tsi_request
, response
);
320 if (status
!= SUCCESS
)
322 response
->destroy(response
);
325 status
= this->build_ts_payload(this, FALSE
, tsr_request
, response
);
326 if (status
!= SUCCESS
)
328 response
->destroy(response
);
332 status
= this->ike_sa
->send_response(this->ike_sa
, response
);
333 /* message can now be sent (must not be destroyed) */
334 if (status
!= SUCCESS
)
336 this->logger
->log(this->logger
, AUDIT
, "Unable to send IKE_AUTH reply. Deleting IKE_SA");
337 response
->destroy(response
);
341 /* install child SA policies */
344 this->logger
->log(this->logger
, CONTROL
, "Proposal negotiation failed, no CHILD_SA built");
346 else if (this->my_ts
->get_count(this->my_ts
) == 0 || this->other_ts
->get_count(this->other_ts
) == 0)
348 this->logger
->log(this->logger
, CONTROL
, "Traffic selector negotiation failed, no CHILD_SA built");
349 this->child_sa
->destroy(this->child_sa
);
350 this->child_sa
= NULL
;
354 status
= this->child_sa
->add_policies(this->child_sa
, this->my_ts
, this->other_ts
);
355 if (status
!= SUCCESS
)
357 this->logger
->log(this->logger
, AUDIT
, "Could not install CHILD_SA policy! Deleting IKE_SA");
360 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
363 /* create new state */
364 this->ike_sa
->set_new_state(this->ike_sa
, (state_t
*)ike_sa_established_create(this->ike_sa
));
365 this->destroy_after_state_change(this);
367 connection
= this->ike_sa
->get_connection(this->ike_sa
);
368 my_host
= connection
->get_my_host(connection
);
369 other_host
= connection
->get_other_host(connection
);
370 this->logger
->log(this->logger
, AUDIT
, "IKE_SA established between %s - %s",
371 my_host
->get_address(my_host
), other_host
->get_address(other_host
));
377 * Implementation of private_ike_sa_init_responded_t.build_idr_payload.
379 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
)
381 identification_t
*other_id
, *my_id
= NULL
;
382 connection_t
*connection
;
383 id_payload_t
*idr_response
;
385 other_id
= request_idi
->get_identification(request_idi
);
388 my_id
= request_idr
->get_identification(request_idr
);
391 /* build new sa config */
392 connection
= this->ike_sa
->get_connection(this->ike_sa
);
393 this->policy
= charon
->policies
->get_policy(charon
->policies
, my_id
, other_id
);
394 if (this->policy
== NULL
)
398 this->logger
->log(this->logger
, AUDIT
, "We don't have a policy for IDs %s - %s. Deleting IKE_SA",
399 other_id
->get_string(other_id
),my_id
->get_string(my_id
));
400 my_id
->destroy(my_id
);
404 this->logger
->log(this->logger
, AUDIT
, "We don't have a policy for remote ID %s. Deleting IKE_SA",
405 other_id
->get_string(other_id
));
407 other_id
->destroy(other_id
);
413 my_id
->destroy(my_id
);
415 other_id
->destroy(other_id
);
417 /* get my id, if not requested */
418 my_id
= this->policy
->get_my_id(this->policy
);
420 /* update others traffic selectors with actually used address */
421 this->policy
->update_other_ts(this->policy
, response
->get_destination(response
));
423 /* set policy in ike_sa for other states */
424 this->ike_sa
->set_policy(this->ike_sa
, this->policy
);
427 idr_response
= id_payload_create_from_identification(FALSE
, my_id
);
428 response
->add_payload(response
, (payload_t
*)idr_response
);
429 *response_idr
= idr_response
;
435 * Implementation of private_ike_sa_init_responded_t.build_sa_payload.
437 static status_t
build_sa_payload(private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
)
439 proposal_t
*proposal
, *proposal_tmp
;
440 linked_list_t
*proposal_list
;
441 sa_payload_t
*sa_response
;
443 prf_plus_t
*prf_plus
;
445 connection_t
*connection
;
447 /* get proposals from request */
448 proposal_list
= request
->get_proposals(request
);
449 if (proposal_list
->get_count(proposal_list
) == 0)
451 /* if the other side did not offer any proposals, we do not create child sa's */
452 this->logger
->log(this->logger
, AUDIT
, "IKE_AUH request did not contain any proposals. No CHILD_SA created");
453 sa_response
= sa_payload_create();
454 response
->add_payload(response
, (payload_t
*)sa_response
);
455 proposal_list
->destroy(proposal_list
);
459 /* now select a proposal */
460 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Selecting proposals:");
461 proposal
= this->policy
->select_proposal(this->policy
, proposal_list
);
462 /* list is not needed anymore */
463 while (proposal_list
->remove_last(proposal_list
, (void**)&proposal_tmp
) == SUCCESS
)
465 proposal_tmp
->destroy(proposal_tmp
);
467 proposal_list
->destroy(proposal_list
);
468 /* do we have a proposal */
469 if (proposal
== NULL
)
471 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA");
472 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, NO_PROPOSAL_CHOSEN
, CHUNK_INITIALIZER
);
476 /* set up child sa */
477 seed
= chunk_alloc(this->received_nonce
.len
+ this->sent_nonce
.len
);
478 memcpy(seed
.ptr
, this->received_nonce
.ptr
, this->received_nonce
.len
);
479 memcpy(seed
.ptr
+ this->received_nonce
.len
, this->sent_nonce
.ptr
, this->sent_nonce
.len
);
480 prf_plus
= prf_plus_create(this->ike_sa
->get_child_prf(this->ike_sa
), seed
);
483 connection
= this->ike_sa
->get_connection(this->ike_sa
);
484 this->child_sa
= child_sa_create(connection
->get_my_host(connection
),
485 connection
->get_other_host(connection
));
487 status
= this->child_sa
->add(this->child_sa
, proposal
, prf_plus
);
488 prf_plus
->destroy(prf_plus
);
489 if (status
!= SUCCESS
)
491 this->logger
->log(this->logger
, AUDIT
, "Could not install CHILD_SA! Deleting IKE_SA");
495 /* create payload with selected propsal */
496 sa_response
= sa_payload_create_from_proposal(proposal
);
497 response
->add_payload(response
, (payload_t
*)sa_response
);
498 proposal
->destroy(proposal
);
503 * Implementation of private_ike_sa_init_responded_t.build_auth_payload.
505 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
)
507 authenticator_t
*authenticator
;
508 auth_payload_t
*auth_reply
;
511 authenticator
= authenticator_create(this->ike_sa
);
512 status
= authenticator
->verify_auth_data(authenticator
,auth_request
, this->ike_sa_init_request_data
,this->sent_nonce
,other_id_payload
,TRUE
);
514 if (status
!= SUCCESS
)
516 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request verification failed. Deleting IKE_SA");
517 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, AUTHENTICATION_FAILED
, CHUNK_INITIALIZER
);
518 authenticator
->destroy(authenticator
);
522 status
= authenticator
->compute_auth_data(authenticator
,&auth_reply
, this->ike_sa_init_response_data
,this->received_nonce
,my_id_payload
,FALSE
);
523 authenticator
->destroy(authenticator
);
524 if (status
!= SUCCESS
)
526 this->logger
->log(this->logger
, AUDIT
, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA");
531 response
->add_payload(response
, (payload_t
*)auth_reply
);
536 * Implementation of private_ike_sa_init_responded_t.build_ts_payload.
538 static status_t
build_ts_payload(private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
* response
)
540 linked_list_t
*ts_received
, *ts_selected
;
541 traffic_selector_t
*ts
;
542 status_t status
= SUCCESS
;
543 ts_payload_t
*ts_response
;
545 /* build a reply payload with selected traffic selectors */
546 ts_received
= request
->get_traffic_selectors(request
);
547 /* select ts depending on payload type */
550 ts_selected
= this->policy
->select_other_traffic_selectors(this->policy
, ts_received
);
551 this->other_ts
= ts_selected
;
555 ts_selected
= this->policy
->select_my_traffic_selectors(this->policy
, ts_received
);
556 this->my_ts
= ts_selected
;
559 ts_response
= ts_payload_create_from_traffic_selectors(ts_initiator
, ts_selected
);
560 response
->add_payload(response
, (payload_t
*)ts_response
);
563 while (ts_received
->remove_last(ts_received
, (void**)&ts
) == SUCCESS
)
567 ts_received
->destroy(ts_received
);
572 static status_t
process_notify_payload(private_ike_sa_init_responded_t
*this, notify_payload_t
*notify_payload
)
574 notify_message_type_t notify_message_type
= notify_payload
->get_notify_message_type(notify_payload
);
576 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Process notify type %s",
577 mapping_find(notify_message_type_m
, notify_message_type
));
579 switch (notify_message_type
)
581 case SET_WINDOW_SIZE
:
583 * TODO Increase window size.
585 case INITIAL_CONTACT
:
587 * TODO Delete existing IKE_SA's with other Identity.
591 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request contained an unknown notify (%d), ignored.", notify_message_type
);
599 * Implementation of state_t.get_state.
601 static ike_sa_state_t
get_state(private_ike_sa_init_responded_t
*this)
603 return IKE_SA_INIT_RESPONDED
;
607 * Implementation of state_t.destroy.
609 static void destroy(private_ike_sa_init_responded_t
*this)
611 chunk_free(&(this->received_nonce
));
612 chunk_free(&(this->sent_nonce
));
613 chunk_free(&(this->ike_sa_init_response_data
));
614 chunk_free(&(this->ike_sa_init_request_data
));
617 traffic_selector_t
*ts
;
618 while (this->my_ts
->remove_last(this->my_ts
, (void**)&ts
) == SUCCESS
)
622 this->my_ts
->destroy(this->my_ts
);
626 traffic_selector_t
*ts
;
627 while (this->other_ts
->remove_last(this->other_ts
, (void**)&ts
) == SUCCESS
)
631 this->other_ts
->destroy(this->other_ts
);
635 this->child_sa
->destroy(this->child_sa
);
641 * Implementation of private_ike_sa_init_responded.destroy_after_state_change.
643 static void destroy_after_state_change(private_ike_sa_init_responded_t
*this)
645 chunk_free(&(this->received_nonce
));
646 chunk_free(&(this->sent_nonce
));
647 chunk_free(&(this->ike_sa_init_response_data
));
648 chunk_free(&(this->ike_sa_init_request_data
));
651 traffic_selector_t
*ts
;
652 while (this->my_ts
->remove_last(this->my_ts
, (void**)&ts
) == SUCCESS
)
656 this->my_ts
->destroy(this->my_ts
);
660 traffic_selector_t
*ts
;
661 while (this->other_ts
->remove_last(this->other_ts
, (void**)&ts
) == SUCCESS
)
665 this->other_ts
->destroy(this->other_ts
);
672 * Described in header.
674 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
)
676 private_ike_sa_init_responded_t
*this = malloc_thing(private_ike_sa_init_responded_t
);
678 /* interface functions */
679 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
680 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
681 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
683 /* private functions */
684 this->build_idr_payload
= build_idr_payload
;
685 this->build_sa_payload
= build_sa_payload
;
686 this->build_auth_payload
= build_auth_payload
;
687 this->build_ts_payload
= build_ts_payload
;
688 this->process_notify_payload
= process_notify_payload
;
689 this->destroy_after_state_change
= destroy_after_state_change
;
692 this->ike_sa
= ike_sa
;
693 this->received_nonce
= received_nonce
;
694 this->sent_nonce
= sent_nonce
;
695 this->ike_sa_init_response_data
= ike_sa_init_response_data
;
696 this->ike_sa_init_request_data
= ike_sa_init_request_data
;
698 this->other_ts
= NULL
;
699 this->child_sa
= NULL
;
700 this->logger
= logger_manager
->get_logger(logger_manager
, IKE_SA
);
702 return &(this->public);