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 connection
= this->ike_sa
->get_connection(this->ike_sa
);
387 /* update adresses, as connection may contain wildcards, or wrong IDs */
388 other_id
= request_idi
->get_identification(request_idi
);
391 my_id
= request_idr
->get_identification(request_idr
);
392 connection
->update_my_id(connection
, my_id
);
396 my_id
= connection
->get_my_id(connection
);
398 connection
->update_other_id(connection
, other_id
);
400 /* build new sa config */
401 this->policy
= charon
->policies
->get_policy(charon
->policies
, my_id
, other_id
);
402 if (this->policy
== NULL
)
404 this->logger
->log(this->logger
, AUDIT
, "We don't have a policy for IDs %s - %s. Deleting IKE_SA",
405 my_id
->get_string(my_id
), other_id
->get_string(other_id
));
409 /* get my id from policy, which must contain a fully qualified valid id */
410 my_id
= this->policy
->get_my_id(this->policy
);
412 /* update others traffic selectors with actually used address */
413 this->policy
->update_other_ts(this->policy
, response
->get_destination(response
));
415 /* set policy in ike_sa for other states */
416 this->ike_sa
->set_policy(this->ike_sa
, this->policy
);
419 idr_response
= id_payload_create_from_identification(FALSE
, my_id
);
420 response
->add_payload(response
, (payload_t
*)idr_response
);
421 *response_idr
= idr_response
;
427 * Implementation of private_ike_sa_init_responded_t.build_sa_payload.
429 static status_t
build_sa_payload(private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
)
431 proposal_t
*proposal
, *proposal_tmp
;
432 linked_list_t
*proposal_list
;
433 sa_payload_t
*sa_response
;
435 prf_plus_t
*prf_plus
;
437 connection_t
*connection
;
439 /* get proposals from request */
440 proposal_list
= request
->get_proposals(request
);
441 if (proposal_list
->get_count(proposal_list
) == 0)
443 /* if the other side did not offer any proposals, we do not create child sa's */
444 this->logger
->log(this->logger
, AUDIT
, "IKE_AUH request did not contain any proposals. No CHILD_SA created");
445 sa_response
= sa_payload_create();
446 response
->add_payload(response
, (payload_t
*)sa_response
);
447 proposal_list
->destroy(proposal_list
);
451 /* now select a proposal */
452 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Selecting proposals:");
453 proposal
= this->policy
->select_proposal(this->policy
, proposal_list
);
454 /* list is not needed anymore */
455 while (proposal_list
->remove_last(proposal_list
, (void**)&proposal_tmp
) == SUCCESS
)
457 proposal_tmp
->destroy(proposal_tmp
);
459 proposal_list
->destroy(proposal_list
);
460 /* do we have a proposal */
461 if (proposal
== NULL
)
463 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA");
464 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, NO_PROPOSAL_CHOSEN
, CHUNK_INITIALIZER
);
468 /* set up child sa */
469 seed
= chunk_alloc(this->received_nonce
.len
+ this->sent_nonce
.len
);
470 memcpy(seed
.ptr
, this->received_nonce
.ptr
, this->received_nonce
.len
);
471 memcpy(seed
.ptr
+ this->received_nonce
.len
, this->sent_nonce
.ptr
, this->sent_nonce
.len
);
472 prf_plus
= prf_plus_create(this->ike_sa
->get_child_prf(this->ike_sa
), seed
);
475 connection
= this->ike_sa
->get_connection(this->ike_sa
);
476 this->child_sa
= child_sa_create(connection
->get_my_host(connection
),
477 connection
->get_other_host(connection
));
479 status
= this->child_sa
->add(this->child_sa
, proposal
, prf_plus
);
480 prf_plus
->destroy(prf_plus
);
481 if (status
!= SUCCESS
)
483 this->logger
->log(this->logger
, AUDIT
, "Could not install CHILD_SA! Deleting IKE_SA");
487 /* create payload with selected propsal */
488 sa_response
= sa_payload_create_from_proposal(proposal
);
489 response
->add_payload(response
, (payload_t
*)sa_response
);
490 proposal
->destroy(proposal
);
495 * Implementation of private_ike_sa_init_responded_t.build_auth_payload.
497 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
)
499 authenticator_t
*authenticator
;
500 auth_payload_t
*auth_reply
;
503 authenticator
= authenticator_create(this->ike_sa
);
504 status
= authenticator
->verify_auth_data(authenticator
,auth_request
, this->ike_sa_init_request_data
,this->sent_nonce
,other_id_payload
,TRUE
);
506 if (status
!= SUCCESS
)
508 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request verification failed. Deleting IKE_SA");
509 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, AUTHENTICATION_FAILED
, CHUNK_INITIALIZER
);
510 authenticator
->destroy(authenticator
);
514 status
= authenticator
->compute_auth_data(authenticator
,&auth_reply
, this->ike_sa_init_response_data
,this->received_nonce
,my_id_payload
,FALSE
);
515 authenticator
->destroy(authenticator
);
516 if (status
!= SUCCESS
)
518 this->logger
->log(this->logger
, AUDIT
, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA");
523 response
->add_payload(response
, (payload_t
*)auth_reply
);
528 * Implementation of private_ike_sa_init_responded_t.build_ts_payload.
530 static status_t
build_ts_payload(private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
* response
)
532 linked_list_t
*ts_received
, *ts_selected
;
533 traffic_selector_t
*ts
;
534 status_t status
= SUCCESS
;
535 ts_payload_t
*ts_response
;
537 /* build a reply payload with selected traffic selectors */
538 ts_received
= request
->get_traffic_selectors(request
);
539 /* select ts depending on payload type */
542 ts_selected
= this->policy
->select_other_traffic_selectors(this->policy
, ts_received
);
543 this->other_ts
= ts_selected
;
547 ts_selected
= this->policy
->select_my_traffic_selectors(this->policy
, ts_received
);
548 this->my_ts
= ts_selected
;
551 ts_response
= ts_payload_create_from_traffic_selectors(ts_initiator
, ts_selected
);
552 response
->add_payload(response
, (payload_t
*)ts_response
);
555 while (ts_received
->remove_last(ts_received
, (void**)&ts
) == SUCCESS
)
559 ts_received
->destroy(ts_received
);
564 static status_t
process_notify_payload(private_ike_sa_init_responded_t
*this, notify_payload_t
*notify_payload
)
566 notify_message_type_t notify_message_type
= notify_payload
->get_notify_message_type(notify_payload
);
568 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Process notify type %s",
569 mapping_find(notify_message_type_m
, notify_message_type
));
571 switch (notify_message_type
)
573 case SET_WINDOW_SIZE
:
575 * TODO Increase window size.
577 case INITIAL_CONTACT
:
579 * TODO Delete existing IKE_SA's with other Identity.
583 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request contained an unknown notify (%d), ignored.", notify_message_type
);
591 * Implementation of state_t.get_state.
593 static ike_sa_state_t
get_state(private_ike_sa_init_responded_t
*this)
595 return IKE_SA_INIT_RESPONDED
;
599 * Implementation of state_t.destroy.
601 static void destroy(private_ike_sa_init_responded_t
*this)
603 chunk_free(&(this->received_nonce
));
604 chunk_free(&(this->sent_nonce
));
605 chunk_free(&(this->ike_sa_init_response_data
));
606 chunk_free(&(this->ike_sa_init_request_data
));
609 traffic_selector_t
*ts
;
610 while (this->my_ts
->remove_last(this->my_ts
, (void**)&ts
) == SUCCESS
)
614 this->my_ts
->destroy(this->my_ts
);
618 traffic_selector_t
*ts
;
619 while (this->other_ts
->remove_last(this->other_ts
, (void**)&ts
) == SUCCESS
)
623 this->other_ts
->destroy(this->other_ts
);
627 this->child_sa
->destroy(this->child_sa
);
633 * Implementation of private_ike_sa_init_responded.destroy_after_state_change.
635 static void destroy_after_state_change(private_ike_sa_init_responded_t
*this)
637 chunk_free(&(this->received_nonce
));
638 chunk_free(&(this->sent_nonce
));
639 chunk_free(&(this->ike_sa_init_response_data
));
640 chunk_free(&(this->ike_sa_init_request_data
));
643 traffic_selector_t
*ts
;
644 while (this->my_ts
->remove_last(this->my_ts
, (void**)&ts
) == SUCCESS
)
648 this->my_ts
->destroy(this->my_ts
);
652 traffic_selector_t
*ts
;
653 while (this->other_ts
->remove_last(this->other_ts
, (void**)&ts
) == SUCCESS
)
657 this->other_ts
->destroy(this->other_ts
);
664 * Described in header.
666 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
)
668 private_ike_sa_init_responded_t
*this = malloc_thing(private_ike_sa_init_responded_t
);
670 /* interface functions */
671 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
672 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
673 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
675 /* private functions */
676 this->build_idr_payload
= build_idr_payload
;
677 this->build_sa_payload
= build_sa_payload
;
678 this->build_auth_payload
= build_auth_payload
;
679 this->build_ts_payload
= build_ts_payload
;
680 this->process_notify_payload
= process_notify_payload
;
681 this->destroy_after_state_change
= destroy_after_state_change
;
684 this->ike_sa
= ike_sa
;
685 this->received_nonce
= received_nonce
;
686 this->sent_nonce
= sent_nonce
;
687 this->ike_sa_init_response_data
= ike_sa_init_response_data
;
688 this->ike_sa_init_request_data
= ike_sa_init_request_data
;
690 this->other_ts
= NULL
;
691 this->child_sa
= NULL
;
692 this->logger
= logger_manager
->get_logger(logger_manager
, IKE_SA
);
694 return &(this->public);