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 <encoding/payloads/ts_payload.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/id_payload.h>
30 #include <encoding/payloads/auth_payload.h>
31 #include <transforms/signers/signer.h>
32 #include <transforms/crypters/crypter.h>
33 #include <sa/states/ike_sa_established.h>
36 typedef struct private_ike_sa_init_responded_t private_ike_sa_init_responded_t
;
39 * Private data of a ike_sa_init_responded_t object.
42 struct private_ike_sa_init_responded_t
{
44 * methods of the state_t interface
46 ike_sa_init_responded_t
public;
51 protected_ike_sa_t
*ike_sa
;
56 sa_config_t
*sa_config
;
59 * Logger used to log data
61 * Is logger of ike_sa!
65 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
);
66 status_t (*build_sa_payload
) (private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
);
67 status_t (*build_auth_payload
) (private_ike_sa_init_responded_t
*this, auth_payload_t
*request
, message_t
*response
);
68 status_t (*build_ts_payload
) (private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
*response
);
72 * Implements state_t.get_state
74 static status_t
process_message(private_ike_sa_init_responded_t
*this, message_t
*request
)
80 exchange_type_t exchange_type
;
81 id_payload_t
*idi_request
, *idr_request
= NULL
;
82 auth_payload_t
*auth_request
;
83 sa_payload_t
*sa_request
;
84 ts_payload_t
*tsi_request
, *tsr_request
;
86 packet_t
*response_packet
;
88 exchange_type
= request
->get_exchange_type(request
);
89 if (exchange_type
!= IKE_AUTH
)
91 this->logger
->log(this->logger
, ERROR
| MORE
, "Message of type %s not supported in state ike_sa_init_responded",
92 mapping_find(exchange_type_m
,exchange_type
));
96 if (!request
->get_request(request
))
98 this->logger
->log(this->logger
, ERROR
| MORE
, "Only requests of type IKE_AUTH supported in state ike_sa_init_responded");
102 /* get signer for verification and crypter for decryption */
103 signer
= this->ike_sa
->get_signer_initiator(this->ike_sa
);
104 crypter
= this->ike_sa
->get_crypter_initiator(this->ike_sa
);
106 /* parse incoming message */
108 status
= request
->parse_body(request
, crypter
, signer
);
109 if (status
!= SUCCESS
)
111 this->logger
->log(this->logger
, ERROR
| MORE
, "Could not parse body of request message");
115 /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
116 payloads
= request
->get_payload_iterator(request
);
117 while (payloads
->has_next(payloads
))
120 payloads
->current(payloads
, (void**)&payload
);
122 switch (payload
->get_type(payload
))
126 idi_request
= (id_payload_t
*)payload
;
131 auth_request
= (auth_payload_t
*)payload
;
136 idr_request
= (id_payload_t
*)payload
;
139 case SECURITY_ASSOCIATION
:
141 sa_request
= (sa_payload_t
*)payload
;
146 /* TODO handle cert payloads */
149 case CERTIFICATE_REQUEST
:
151 /* TODO handle certrequest payloads */
154 case TRAFFIC_SELECTOR_INITIATOR
:
156 tsi_request
= (ts_payload_t
*)payload
;
159 case TRAFFIC_SELECTOR_RESPONDER
:
161 tsr_request
= (ts_payload_t
*)payload
;
166 /* can't happen, since message is verified, notify's? */
171 /* iterator can be destroyed */
172 payloads
->destroy(payloads
);
175 this->ike_sa
->build_message(this->ike_sa
, IKE_AUTH
, FALSE
, &response
);
177 /* add payloads to it */
179 status
= this->build_idr_payload(this, idi_request
, idr_request
, response
);
180 if (status
!= SUCCESS
)
182 this->logger
->log(this->logger
, ERROR
, "Building idr payload failed");
183 response
->destroy(response
);
186 status
= this->build_sa_payload(this, sa_request
, response
);
187 if (status
!= SUCCESS
)
189 this->logger
->log(this->logger
, ERROR
, "Building sa payload failed");
190 response
->destroy(response
);
193 status
= this->build_auth_payload(this, auth_request
, response
);
194 if (status
!= SUCCESS
)
196 this->logger
->log(this->logger
, ERROR
, "Building auth payload failed");
197 response
->destroy(response
);
200 status
= this->build_ts_payload(this, TRUE
, tsi_request
, response
);
201 if (status
!= SUCCESS
)
203 this->logger
->log(this->logger
, ERROR
, "Building tsi payload failed");
204 response
->destroy(response
);
207 status
= this->build_ts_payload(this, FALSE
, tsr_request
, response
);
208 if (status
!= SUCCESS
)
210 this->logger
->log(this->logger
, ERROR
, "Building tsr payload failed");
211 response
->destroy(response
);
215 /* generate response, get transfroms first */
216 signer
= this->ike_sa
->get_signer_responder(this->ike_sa
);
217 crypter
= this->ike_sa
->get_crypter_responder(this->ike_sa
);
218 status
= response
->generate(response
, crypter
, signer
, &response_packet
);
219 if (status
!= SUCCESS
)
221 this->logger
->log(this->logger
, ERROR
, "Error in message generation");
222 response
->destroy(response
);
228 this->logger
->log(this->logger
, CONTROL
| MORE
, "IKE_AUTH request successfully handled. Sending reply.");
229 charon
->send_queue
->add(charon
->send_queue
, response_packet
);
230 /* store for timeout reply */
231 this->ike_sa
->set_last_responded_message(this->ike_sa
, response
);
233 /* create new state */
234 this->ike_sa
->set_new_state(this->ike_sa
, (state_t
*)ike_sa_established_create(this->ike_sa
));
236 this->public.state_interface
.destroy(&(this->public.state_interface
));
242 * Implements private_ike_sa_init_responded_t.build_idr_payload
244 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
)
246 identification_t
*other_id
, *my_id
= NULL
;
247 init_config_t
*init_config
;
249 id_payload_t
*idr_response
;
251 other_id
= request_idi
->get_identification(request_idi
);
254 my_id
= request_idr
->get_identification(request_idr
);
257 /* build new sa config */
258 init_config
= this->ike_sa
->get_init_config(this->ike_sa
);
259 status
= charon
->configuration_manager
->get_sa_config_for_init_config_and_id(charon
->configuration_manager
,init_config
, other_id
,my_id
, &(this->sa_config
));
260 if (status
!= SUCCESS
)
262 this->logger
->log(this->logger
, ERROR
, "Could not find config for %s", other_id
->get_string(other_id
));
266 /* set sa_config in ike_sa for other states */
267 this->ike_sa
->set_sa_config(this->ike_sa
, this->sa_config
);
270 idr_response
= id_payload_create_from_identification(FALSE
, other_id
);
271 response
->add_payload(response
, (payload_t
*)idr_response
);
275 my_id
->destroy(my_id
);
277 other_id
->destroy(other_id
);
283 * Implements private_ike_sa_init_responded_t.build_sa_payload
285 static status_t
build_sa_payload(private_ike_sa_init_responded_t
*this, sa_payload_t
*request
, message_t
*response
)
287 child_proposal_t
*proposals
, *proposal_chosen
;
288 size_t proposal_count
;
290 sa_payload_t
*sa_response
;
292 /* dummy spis, until we have a child sa to request them */
293 u_int8_t ah_spi
[4] = {0x01, 0x02, 0x03, 0x04};
294 u_int8_t esp_spi
[4] = {0x05, 0x06, 0x07, 0x08};
296 status
= request
->get_child_proposals(request
, &proposals
, &proposal_count
);
297 if (status
== SUCCESS
)
299 proposal_chosen
= this->sa_config
->select_proposal(this->sa_config
, ah_spi
, esp_spi
, proposals
, proposal_count
);
300 if (proposal_chosen
!= NULL
)
302 sa_response
= sa_payload_create_from_child_proposals(proposal_chosen
, 1);
303 response
->add_payload(response
, (payload_t
*)sa_response
);
307 this->logger
->log(this->logger
, ERROR
, "no matching proposal found");
313 this->logger
->log(this->logger
, ERROR
, "requestor's sa payload contained no proposals");
318 allocator_free(proposal_chosen
);
319 allocator_free(proposals
);
326 * Implements private_ike_sa_init_responded_t.build_auth_payload
328 static status_t
build_auth_payload(private_ike_sa_init_responded_t
*this, auth_payload_t
*request
, message_t
*response
)
330 auth_payload_t
*dummy
;
331 u_int8_t data
[] = {0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03};
333 auth_data
.ptr
= data
;
334 auth_data
.len
= sizeof(data
);
336 /* TODO VERIFY auth here */
338 dummy
= auth_payload_create();
339 dummy
->set_data(dummy
, auth_data
);
340 dummy
->set_auth_method(dummy
, RSA_DIGITAL_SIGNATURE
);
342 /* TODO replace dummy */
344 response
->add_payload(response
, (payload_t
*)dummy
);
349 * Implements private_ike_sa_init_responded_t.build_ts_payload
351 static status_t
build_ts_payload(private_ike_sa_init_responded_t
*this, bool ts_initiator
, ts_payload_t
*request
, message_t
* response
)
353 traffic_selector_t
**ts_received
, **ts_selected
;
354 size_t ts_received_count
, ts_selected_count
;
355 status_t status
= SUCCESS
;
356 ts_payload_t
*ts_response
;
358 /* build a reply payload with selected traffic selectors */
359 ts_received_count
= request
->get_traffic_selectors(request
, &ts_received
);
360 /* select ts depending on payload type */
363 ts_selected_count
= this->sa_config
->select_traffic_selectors_initiator(this->sa_config
, ts_received
, ts_received_count
, &ts_selected
);
367 ts_selected_count
= this->sa_config
->select_traffic_selectors_responder(this->sa_config
, ts_received
, ts_received_count
, &ts_selected
);
369 if(ts_selected_count
== 0)
375 ts_response
= ts_payload_create_from_traffic_selectors(ts_initiator
, ts_selected
, ts_selected_count
);
376 response
->add_payload(response
, (payload_t
*)ts_response
);
380 while(ts_received_count
--)
382 traffic_selector_t
*ts
= *ts_received
+ ts_received_count
;
385 allocator_free(ts_received
);
386 while(ts_selected_count
--)
388 traffic_selector_t
*ts
= *ts_selected
+ ts_selected_count
;
391 allocator_free(ts_selected
);
396 * Implements state_t.get_state
398 static ike_sa_state_t
get_state(private_ike_sa_init_responded_t
*this)
400 return IKE_SA_INIT_RESPONDED
;
404 * Implements state_t.get_state
406 static void destroy(private_ike_sa_init_responded_t
*this)
408 this->logger
->log(this->logger
, CONTROL
| MORE
, "Going to destroy ike_sa_init_responded_t state object");
410 allocator_free(this);
414 * Described in header.
416 ike_sa_init_responded_t
*ike_sa_init_responded_create(protected_ike_sa_t
*ike_sa
)
418 private_ike_sa_init_responded_t
*this = allocator_alloc_thing(private_ike_sa_init_responded_t
);
420 /* interface functions */
421 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
422 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
423 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
425 /* private functions */
426 this->build_idr_payload
= build_idr_payload
;
427 this->build_sa_payload
= build_sa_payload
;
428 this->build_auth_payload
= build_auth_payload
;
429 this->build_ts_payload
= build_ts_payload
;
432 this->ike_sa
= ike_sa
;
433 this->logger
= this->ike_sa
->get_logger(this->ike_sa
);
435 return &(this->public);