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
;
82 * Proposal selected for CHILD_SA
87 * Traffic selectors applicable at our site
92 * Traffic selectors applicable at remote site
94 linked_list_t
*other_ts
;
99 * Is logger of ike_sa!
104 * Process received IDi and IDr payload and build IDr payload for IKE_AUTH response.
106 * @param this calling object
107 * @param request_idi ID payload representing initiator
108 * @param request_idr ID payload representing responder (May be zero)
109 * @param response The created IDr payload is added to this message_t object
110 * @param response_idr The created IDr payload is also written to this location
112 status_t (*build_idr_payload
) (private_ike_sa_init_responded_t
*this,
113 id_payload_t
*request_idi
,
114 id_payload_t
*request_idr
,
116 id_payload_t
**response_idr
);
119 * Process received SA payload and build SA payload for IKE_AUTH response.
121 * @param this calling object
122 * @param request SA payload received in IKE_AUTH request
123 * @param response The created SA payload is added to this message_t object
125 status_t (*build_sa_payload
) (private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
);
128 * Process received AUTH payload and build AUTH payload for IKE_AUTH response.
130 * @param this calling object
131 * @param request AUTH payload received in IKE_AUTH request
132 * @param other_id_payload other ID payload needed to verify AUTH data
133 * @param my_id_payload my ID payload needed to compute AUTH data
134 * @param response The created AUTH payload is added to this message_t object
136 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
);
139 * Process received TS payload and build TS payload for IKE_AUTH response.
141 * @param this calling object
142 * @param is_initiator type of TS payload. TRUE for TSi, FALSE for TSr
143 * @param request TS payload received in IKE_AUTH request
144 * @param response the created TS payload is added to this message_t object
146 status_t (*build_ts_payload
) (private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
*response
);
149 * Sends a IKE_AUTH reply containing a notify payload.
151 * @param this calling object
152 * @param notify_payload payload to process
154 * - DELETE_ME if IKE_SA should be deleted
155 * - SUCCSS if processed successfull
157 status_t (*process_notify_payload
) (private_ike_sa_init_responded_t
*this, notify_payload_t
* notify_payload
);
161 * Implements state_t.get_state
163 static status_t
process_message(private_ike_sa_init_responded_t
*this, message_t
*request
)
165 id_payload_t
*idi_request
= NULL
, *idr_request
= NULL
,*idr_response
;
166 ts_payload_t
*tsi_request
= NULL
, *tsr_request
= NULL
;
167 auth_payload_t
*auth_request
= NULL
;
168 sa_payload_t
*sa_request
= NULL
;
169 iterator_t
*payloads
;
174 host_t
*my_host
, *other_host
;
176 prf_plus_t
*prf_plus
;
177 child_sa_t
*child_sa
;
180 if (request
->get_exchange_type(request
) != IKE_AUTH
)
182 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "Message of type %s not supported in state ike_sa_init_responded",
183 mapping_find(exchange_type_m
,request
->get_exchange_type(request
)));
187 if (!request
->get_request(request
))
189 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "IKE_AUTH responses not allowed state ike_sa_init_responded");
193 /* get signer for verification and crypter for decryption */
194 signer
= this->ike_sa
->get_signer_initiator(this->ike_sa
);
195 crypter
= this->ike_sa
->get_crypter_initiator(this->ike_sa
);
197 status
= request
->parse_body(request
, crypter
, signer
);
198 if (status
!= SUCCESS
)
200 if (status
== NOT_SUPPORTED
)
202 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "IKE_AUTH request contains unsupported payload with critical flag set."
204 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, UNSUPPORTED_CRITICAL_PAYLOAD
, CHUNK_INITIALIZER
);
209 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request decryption faild. Ignoring message");
214 /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
215 payloads
= request
->get_payload_iterator(request
);
216 while (payloads
->has_next(payloads
))
219 payloads
->current(payloads
, (void**)&payload
);
221 switch (payload
->get_type(payload
))
225 idi_request
= (id_payload_t
*)payload
;
230 auth_request
= (auth_payload_t
*)payload
;
235 idr_request
= (id_payload_t
*)payload
;
238 case SECURITY_ASSOCIATION
:
240 sa_request
= (sa_payload_t
*)payload
;
244 case TRAFFIC_SELECTOR_INITIATOR
:
246 tsi_request
= (ts_payload_t
*)payload
;
249 case TRAFFIC_SELECTOR_RESPONDER
:
251 tsr_request
= (ts_payload_t
*)payload
;
256 notify_payload_t
*notify_payload
= (notify_payload_t
*) payload
;
257 status
= this->process_notify_payload(this, notify_payload
);
258 if (status
!= SUCCESS
)
260 payloads
->destroy(payloads
);
266 /* TODO handle cert payloads */
268 case CERTIFICATE_REQUEST
:
270 /* TODO handle certrequest payloads */
274 this->logger
->log(this->logger
, ERROR
|LEVEL1
, "Ignoring payload %s (%d)",
275 mapping_find(payload_type_m
, payload
->get_type(payload
)), payload
->get_type(payload
));
280 /* iterator can be destroyed */
281 payloads
->destroy(payloads
);
283 /* check if we have all payloads */
284 if (!(idi_request
&& sa_request
&& auth_request
&& tsi_request
&& tsr_request
))
286 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA");
291 this->ike_sa
->build_message(this->ike_sa
, IKE_AUTH
, FALSE
, &response
);
293 /* add payloads to it */
294 status
= this->build_idr_payload(this, idi_request
, idr_request
, response
,&idr_response
);
295 if (status
!= SUCCESS
)
297 response
->destroy(response
);
300 status
= this->build_sa_payload(this, sa_request
, response
);
301 if (status
!= SUCCESS
)
303 response
->destroy(response
);
306 status
= this->build_auth_payload(this, auth_request
,idi_request
, idr_response
,response
);
307 if (status
!= SUCCESS
)
309 response
->destroy(response
);
312 status
= this->build_ts_payload(this, TRUE
, tsi_request
, response
);
313 if (status
!= SUCCESS
)
315 response
->destroy(response
);
318 status
= this->build_ts_payload(this, FALSE
, tsr_request
, response
);
319 if (status
!= SUCCESS
)
321 response
->destroy(response
);
325 status
= this->ike_sa
->send_response(this->ike_sa
, response
);
326 /* message can now be sent (must not be destroyed) */
327 if (status
!= SUCCESS
)
329 this->logger
->log(this->logger
, AUDIT
, "Unable to send IKE_AUTH reply. Deleting IKE_SA");
330 response
->destroy(response
);
334 /* install child SAs for AH and esp */
337 this->logger
->log(this->logger
, CONTROL
, "Proposal negotiation failed, no CHILD_SA built");
339 else if (this->my_ts
->get_count(this->my_ts
) == 0 || this->other_ts
->get_count(this->other_ts
) == 0)
341 this->logger
->log(this->logger
, CONTROL
, "Traffic selector negotiation failed, no CHILD_SA built");
345 seed
= allocator_alloc_as_chunk(this->received_nonce
.len
+ this->sent_nonce
.len
);
346 memcpy(seed
.ptr
, this->received_nonce
.ptr
, this->received_nonce
.len
);
347 memcpy(seed
.ptr
+ this->received_nonce
.len
, this->sent_nonce
.ptr
, this->sent_nonce
.len
);
348 prf_plus
= prf_plus_create(this->ike_sa
->get_child_prf(this->ike_sa
), seed
);
349 allocator_free_chunk(&seed
);
351 child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
352 this->ike_sa
->get_other_host(this->ike_sa
));
354 status
= child_sa
->add(child_sa
, this->proposal
, prf_plus
);
355 prf_plus
->destroy(prf_plus
);
356 if (status
!= SUCCESS
)
358 this->logger
->log(this->logger
, AUDIT
, "Could not install CHILD_SA! Deleting IKE_SA");
361 status
= child_sa
->add_policy(child_sa
, this->my_ts
, this->other_ts
);
362 if (status
!= SUCCESS
)
364 this->logger
->log(this->logger
, AUDIT
, "Could not install CHILD_SA policy! Deleting IKE_SA");
367 this->ike_sa
->add_child_sa(this->ike_sa
, child_sa
);
370 /* create new state */
371 my_host
= this->ike_sa
->get_my_host(this->ike_sa
);
372 other_host
= this->ike_sa
->get_other_host(this->ike_sa
);
373 this->logger
->log(this->logger
, AUDIT
, "IKE_SA established between %s - %s, authenticated peer with %s",
374 my_host
->get_address(my_host
), other_host
->get_address(other_host
),
375 mapping_find(auth_method_m
, auth_request
->get_auth_method(auth_request
)));
377 this->ike_sa
->create_delete_established_ike_sa_job(this->ike_sa
,this->sa_config
->get_ike_sa_lifetime(this->sa_config
));
378 this->ike_sa
->set_new_state(this->ike_sa
, (state_t
*)ike_sa_established_create(this->ike_sa
));
379 this->public.state_interface
.destroy(&(this->public.state_interface
));
385 * Implementation of private_ike_sa_init_responded_t.build_idr_payload.
387 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
)
389 identification_t
*other_id
, *my_id
= NULL
;
390 init_config_t
*init_config
;
392 id_payload_t
*idr_response
;
394 other_id
= request_idi
->get_identification(request_idi
);
397 my_id
= request_idr
->get_identification(request_idr
);
400 /* build new sa config */
401 init_config
= this->ike_sa
->get_init_config(this->ike_sa
);
402 status
= charon
->configuration_manager
->get_sa_config_for_init_config_and_id(charon
->configuration_manager
,init_config
, other_id
,my_id
, &(this->sa_config
));
403 if (status
!= SUCCESS
)
407 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request uses IDs %s to %s, which we have no config for",
408 other_id
->get_string(other_id
),my_id
->get_string(my_id
));
409 my_id
->destroy(my_id
);
413 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request uses ID %s, which we have no config for",
414 other_id
->get_string(other_id
));
416 other_id
->destroy(other_id
);
422 my_id
->destroy(my_id
);
424 other_id
->destroy(other_id
);
426 /* get my id, if not requested */
427 my_id
= this->sa_config
->get_my_id(this->sa_config
);
429 /* set sa_config in ike_sa for other states */
430 this->ike_sa
->set_sa_config(this->ike_sa
, this->sa_config
);
433 idr_response
= id_payload_create_from_identification(FALSE
, my_id
);
434 response
->add_payload(response
, (payload_t
*)idr_response
);
435 *response_idr
= idr_response
;
441 * Implementation of private_ike_sa_init_responded_t.build_sa_payload.
443 static status_t
build_sa_payload(private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
)
445 proposal_t
*proposal
, *proposal_tmp
;
446 linked_list_t
*proposal_list
;
447 sa_payload_t
*sa_response
;
449 /* get proposals from request */
450 proposal_list
= request
->get_proposals(request
);
451 if (proposal_list
->get_count(proposal_list
) == 0)
453 /* if the other side did not offer any proposals, we do not create child sa's */
454 this->logger
->log(this->logger
, AUDIT
, "IKE_AUH request did not contain any proposals. No CHILD_SA created");
455 sa_response
= sa_payload_create();
456 response
->add_payload(response
, (payload_t
*)sa_response
);
457 proposal_list
->destroy(proposal_list
);
461 /* now select a proposal */
462 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Selecting proposals:");
463 proposal
= this->sa_config
->select_proposal(this->sa_config
, proposal_list
);
464 /* list is not needed anymore */
465 while (proposal_list
->remove_last(proposal_list
, (void**)&proposal_tmp
) == SUCCESS
)
467 proposal_tmp
->destroy(proposal_tmp
);
469 proposal_list
->destroy(proposal_list
);
470 /* do we have a proposal */
471 if (proposal
== NULL
)
473 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA");
474 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, NO_PROPOSAL_CHOSEN
, CHUNK_INITIALIZER
);
479 this->proposal
= proposal
;
481 /* create payload with selected propsal */
482 sa_response
= sa_payload_create_from_proposal(proposal
);
483 response
->add_payload(response
, (payload_t
*)sa_response
);
488 * Implementation of private_ike_sa_init_responded_t.build_auth_payload.
490 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
)
492 authenticator_t
*authenticator
;
493 auth_payload_t
*auth_reply
;
496 authenticator
= authenticator_create(this->ike_sa
);
497 status
= authenticator
->verify_auth_data(authenticator
,auth_request
, this->ike_sa_init_request_data
,this->sent_nonce
,other_id_payload
,TRUE
);
499 if (status
!= SUCCESS
)
501 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request verification failed. Deleting IKE_SA");
502 this->ike_sa
->send_notify(this->ike_sa
, IKE_AUTH
, AUTHENTICATION_FAILED
, CHUNK_INITIALIZER
);
503 authenticator
->destroy(authenticator
);
507 status
= authenticator
->compute_auth_data(authenticator
,&auth_reply
, this->ike_sa_init_response_data
,this->received_nonce
,my_id_payload
,FALSE
);
508 authenticator
->destroy(authenticator
);
509 if (status
!= SUCCESS
)
511 this->logger
->log(this->logger
, AUDIT
, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA");
516 response
->add_payload(response
, (payload_t
*)auth_reply
);
521 * Implementation of private_ike_sa_init_responded_t.build_ts_payload.
523 static status_t
build_ts_payload(private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
* response
)
525 linked_list_t
*ts_received
, *ts_selected
;
526 traffic_selector_t
*ts
;
527 status_t status
= SUCCESS
;
528 ts_payload_t
*ts_response
;
530 /* build a reply payload with selected traffic selectors */
531 ts_received
= request
->get_traffic_selectors(request
);
532 /* select ts depending on payload type */
535 ts_selected
= this->sa_config
->select_other_traffic_selectors(this->sa_config
, ts_received
);
536 this->other_ts
= ts_selected
;
540 ts_selected
= this->sa_config
->select_my_traffic_selectors(this->sa_config
, ts_received
);
541 this->my_ts
= ts_selected
;
544 ts_response
= ts_payload_create_from_traffic_selectors(ts_initiator
, ts_selected
);
545 response
->add_payload(response
, (payload_t
*)ts_response
);
548 while (ts_received
->remove_last(ts_received
, (void**)&ts
) == SUCCESS
)
552 ts_received
->destroy(ts_received
);
557 static status_t
process_notify_payload(private_ike_sa_init_responded_t
*this, notify_payload_t
*notify_payload
)
559 notify_message_type_t notify_message_type
= notify_payload
->get_notify_message_type(notify_payload
);
561 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Process notify type %s for protocol %s",
562 mapping_find(notify_message_type_m
, notify_message_type
),
563 mapping_find(protocol_id_m
, notify_payload
->get_protocol_id(notify_payload
)));
565 switch (notify_message_type
)
567 case SET_WINDOW_SIZE
:
569 * TODO Increase window size.
571 case INITIAL_CONTACT
:
573 * TODO Delete existing IKE_SA's with other Identity.
577 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH request contained an unknown notify (%d), ignored.", notify_message_type
);
585 * Implementation of state_t.get_state.
587 static ike_sa_state_t
get_state(private_ike_sa_init_responded_t
*this)
589 return IKE_SA_INIT_RESPONDED
;
593 * Implementation of state_t.get_state.
595 static void destroy(private_ike_sa_init_responded_t
*this)
597 allocator_free_chunk(&(this->received_nonce
));
598 allocator_free_chunk(&(this->sent_nonce
));
599 allocator_free_chunk(&(this->ike_sa_init_response_data
));
600 allocator_free_chunk(&(this->ike_sa_init_request_data
));
603 traffic_selector_t
*ts
;
604 while (this->my_ts
->remove_last(this->my_ts
, (void**)&ts
) == SUCCESS
)
608 this->my_ts
->destroy(this->my_ts
);
612 traffic_selector_t
*ts
;
613 while (this->other_ts
->remove_last(this->other_ts
, (void**)&ts
) == SUCCESS
)
617 this->other_ts
->destroy(this->other_ts
);
621 this->proposal
->destroy(this->proposal
);
624 allocator_free(this);
628 * Described in header.
630 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
)
632 private_ike_sa_init_responded_t
*this = allocator_alloc_thing(private_ike_sa_init_responded_t
);
634 /* interface functions */
635 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
636 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
637 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
639 /* private functions */
640 this->build_idr_payload
= build_idr_payload
;
641 this->build_sa_payload
= build_sa_payload
;
642 this->build_auth_payload
= build_auth_payload
;
643 this->build_ts_payload
= build_ts_payload
;
644 this->process_notify_payload
= process_notify_payload
;
647 this->ike_sa
= ike_sa
;
648 this->received_nonce
= received_nonce
;
649 this->sent_nonce
= sent_nonce
;
650 this->ike_sa_init_response_data
= ike_sa_init_response_data
;
651 this->ike_sa_init_request_data
= ike_sa_init_request_data
;
653 this->other_ts
= NULL
;
654 this->proposal
= NULL
;
655 this->logger
= this->ike_sa
->get_logger(this->ike_sa
);
657 return &(this->public);