4 * @brief Class ike_sa_t. An object of this type is managed by an
5 * ike_sa_manager_t object and represents an IKE_SA
10 * Copyright (C) 2005 Jan Hutter, Martin Willi
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28 #include "definitions.h"
29 #include "utils/allocator.h"
30 #include "utils/linked_list.h"
31 #include "utils/logger_manager.h"
32 #include "utils/randomizer.h"
33 #include "transforms/diffie_hellman.h"
34 #include "payloads/sa_payload.h"
35 #include "payloads/nonce_payload.h"
36 #include "payloads/ke_payload.h"
37 #include "payloads/transform_substructure.h"
38 #include "payloads/transform_attribute.h"
39 #include "states/initiator_init.h"
40 #include "states/responder_init.h"
46 * @brief implements function process_message of protected_ike_sa_t
48 static status_t
process_message (protected_ike_sa_t
*this, message_t
*message
)
51 exchange_type_t exchange_type
;
56 /* we must process each request or response from remote host */
58 /* find out type of message (request or response) */
59 is_request
= message
->get_request(message
);
60 exchange_type
= message
->get_exchange_type(message
);
62 this->logger
->log(this->logger
, CONTROL
|MORE
, "Process %s message of exchange type %s",(is_request
) ?
"REQUEST" : "RESPONSE",mapping_find(exchange_type_m
,exchange_type
));
64 message_id
= message
->get_message_id(message
);
67 * It has to be checked, if the message has to be resent cause of lost packets!
69 if (is_request
&& ( message_id
== (this->message_id_in
- 1)))
71 /* message can be resent ! */
72 this->logger
->log(this->logger
, CONTROL
|MORE
, "Resent message detected. Send stored reply");
73 return (this->resend_last_reply(this));
76 /* Now, the message id is checked for request AND reply */
79 /* In a request, the message has to be this->message_id_in (other case is already handled) */
80 if (message_id
!= this->message_id_in
)
82 this->logger
->log(this->logger
, ERROR
| MORE
, "Message request with message id %d received, but %d expected",message_id
,this->message_id_in
);
88 /* In a reply, the message has to be this->message_id_out -1 cause it is the reply to the last sent message*/
89 if (message_id
!= (this->message_id_out
- 1))
91 this->logger
->log(this->logger
, ERROR
| MORE
, "Message reply with message id %d received, but %d expected",message_id
,this->message_id_in
);
96 /* now the message is processed by the current state object */
97 status
= this->current_state
->process_message(this->current_state
,message
,&new_state
);
98 if (status
== SUCCESS
)
100 this->current_state
= new_state
;
106 * @brief Implements function build_message of protected_ike_sa_t.
108 static status_t
build_message(protected_ike_sa_t
*this, exchange_type_t type
, bool request
, message_t
**message
)
111 message_t
*new_message
;
112 host_t
*source
, *destination
;
114 this ->logger
->log(this->logger
, CONTROL
|MORE
, "build empty message");
115 new_message
= message_create();
116 if (new_message
== NULL
)
118 this->logger
->log(this->logger
, ERROR
, "Fatal error: could not create empty message object");
122 status
= this->me
.host
->clone(this->me
.host
, &source
);
123 if (status
!= SUCCESS
)
125 this->logger
->log(this->logger
, ERROR
, "Fatal error: could not clone my host information");
126 new_message
->destroy(new_message
);
129 status
= this->other
.host
->clone(this->other
.host
, &destination
);
130 if (status
!= SUCCESS
)
132 this->logger
->log(this->logger
, ERROR
, "Fatal error: could not clone other host information");
133 source
->destroy(source
);
134 new_message
->destroy(new_message
);
138 new_message
->set_source(new_message
, source
);
139 new_message
->set_destination(new_message
, destination
);
141 new_message
->set_exchange_type(new_message
, type
);
142 new_message
->set_request(new_message
, request
);
144 new_message
->set_message_id(new_message
, (request
) ?
this->message_id_out
: this->message_id_in
);
146 status
= new_message
->set_ike_sa_id(new_message
, this->ike_sa_id
);
147 if (status
!= SUCCESS
)
149 this->logger
->log(this->logger
, ERROR
, "Fatal error: could not set ike_sa_id of message");
150 new_message
->destroy(new_message
);
154 *message
= new_message
;
160 * @brief implements function process_configuration of protected_ike_sa_t
162 static status_t
initialize_connection(protected_ike_sa_t
*this, char *name
)
164 /* work is done in state object of type INITIATOR_INIT */
165 initiator_init_t
*current_state
;
169 if (this->current_state
->get_state(this->current_state
) != INITIATOR_INIT
)
174 current_state
= (initiator_init_t
*) this->current_state
;
176 status
= current_state
->initiate_connection(current_state
,name
,&new_state
);
178 if (status
== SUCCESS
)
180 this->current_state
= new_state
;
184 this->create_delete_job(this);
190 * @brief implements function protected_ike_sa_t.get_id
192 static ike_sa_id_t
* get_id(protected_ike_sa_t
*this)
194 return this->ike_sa_id
;
198 * @brief implements function resend_last_reply of protected_ike_sa_t
200 status_t
resend_last_reply (protected_ike_sa_t
*this)
205 status
= this->last_responded_message
->generate(this->last_responded_message
, &packet
);
206 if (status
!= SUCCESS
)
208 this->logger
->log(this->logger
, ERROR
, "Could not generate message to resent");
212 status
= global_send_queue
->add(global_send_queue
, packet
);
213 if (status
!= SUCCESS
)
215 this->logger
->log(this->logger
, ERROR
, "Could not add packet to send queue");
216 packet
->destroy(packet
);
222 status_t
create_delete_job (protected_ike_sa_t
*this)
227 this->logger
->log(this->logger
, CONTROL
| MORE
, "Going to create job to delete this IKE_SA");
229 delete_job
= (job_t
*) delete_ike_sa_job_create(this->ike_sa_id
);
230 if (delete_job
== NULL
)
232 this->logger
->log(this->logger
, ERROR
, "Job to delete IKE SA could not be created");
236 status
= global_job_queue
->add(global_job_queue
,delete_job
);
237 if (status
!= SUCCESS
)
239 this->logger
->log(this->logger
, ERROR
, "%s Job to delete IKE SA could not be added to job queue",mapping_find(status_m
,status
));
240 delete_job
->destroy_all(delete_job
);
247 * @brief implements function destroy of protected_ike_sa_t
249 static status_t
destroy (protected_ike_sa_t
*this)
252 this->logger
->log(this->logger
, CONTROL
| MORE
, "Going to destroy IKE_SA");
254 /* destroy child sa's */
255 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy all child_sa's");
256 while (this->child_sas
->get_count(this->child_sas
) > 0)
259 if (this->child_sas
->remove_first(this->child_sas
,&child_sa
) != SUCCESS
)
263 /* destroy child sa */
265 this->child_sas
->destroy(this->child_sas
);
267 /* destroy ike_sa_id */
268 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy assigned ike_sa_id");
269 this->ike_sa_id
->destroy(this->ike_sa_id
);
271 /* destroy stored requested message */
272 if (this->last_requested_message
!= NULL
)
274 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy last requested message");
275 this->last_requested_message
->destroy(this->last_requested_message
);
278 /* destroy stored responded messages */
279 if (this->last_responded_message
!= NULL
)
281 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy last responded message");
282 this->last_responded_message
->destroy(this->last_responded_message
);
285 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy randomizer");
286 this->randomizer
->destroy(this->randomizer
);
288 // if (this->me.host != NULL)
290 // this->logger->log(this->logger, CONTROL | MOST, "Destroy host informations of me");
291 // this->me.host->destroy(this->me.host);
294 // if (this->other.host != NULL)
296 // this->logger->log(this->logger, CONTROL | MOST, "Destroy host informations of other");
297 // this->other.host->destroy(this->other.host);
300 // this->logger->log(this->logger, CONTROL | MOST, "Destroy current state object");
301 // this->current_state->destroy(this->current_state);
303 // this->logger->log(this->logger, CONTROL | MOST, "Destroy logger of IKE_SA");
304 // global_logger_manager->destroy_logger(global_logger_manager, this->logger);
306 // allocator_free(this);
311 * Described in Header
313 ike_sa_t
* ike_sa_create(ike_sa_id_t
*ike_sa_id
)
315 protected_ike_sa_t
*this = allocator_alloc_thing(protected_ike_sa_t
);
321 /* Public functions */
322 this->public.process_message
= (status_t(*)(ike_sa_t
*, message_t
*)) process_message
;
323 this->public.initialize_connection
= (status_t(*)(ike_sa_t
*, char*)) initialize_connection
;
324 this->public.get_id
= (ike_sa_id_t
*(*)(ike_sa_t
*)) get_id
;
325 this->public.destroy
= (status_t(*)(ike_sa_t
*))destroy
;
327 /* private functions */
328 this->build_message
= build_message
;
329 this->resend_last_reply
= resend_last_reply
;
330 this->create_delete_job
= create_delete_job
;
332 /* initialize private fields */
333 this->logger
= global_logger_manager
->create_logger(global_logger_manager
, IKE_SA
, NULL
);
334 if (this->logger
== NULL
)
336 allocator_free(this);
339 if (ike_sa_id
->clone(ike_sa_id
,&(this->ike_sa_id
)) != SUCCESS
)
341 this->logger
->log(this->logger
, ERROR
, "Fatal error: Could not clone ike_sa_id");
342 global_logger_manager
->destroy_logger(global_logger_manager
,this->logger
);
343 allocator_free(this);
346 this->child_sas
= linked_list_create();
347 if (this->child_sas
== NULL
)
349 this->logger
->log(this->logger
, ERROR
, "Fatal error: Could not create list for child_sa's");
350 this->ike_sa_id
->destroy(this->ike_sa_id
);
351 global_logger_manager
->destroy_logger(global_logger_manager
,this->logger
);
352 allocator_free(this);
355 this->randomizer
= randomizer_create();
356 if (this->randomizer
== NULL
)
358 this->logger
->log(this->logger
, ERROR
, "Fatal error: Could not create list for child_sa's");
359 this->child_sas
->destroy(this->child_sas
);
360 this->ike_sa_id
->destroy(this->ike_sa_id
);
361 global_logger_manager
->destroy_logger(global_logger_manager
,this->logger
);
362 allocator_free(this);
365 this->me
.host
= NULL
;
366 this->other
.host
= NULL
;
367 this->last_requested_message
= NULL
;
368 this->last_responded_message
= NULL
;
369 this->message_id_out
= 0;
370 this->message_id_in
= 0;
373 /* at creation time, IKE_SA is in a initiator state */
374 if (ike_sa_id
->is_initiator(ike_sa_id
))
376 this->current_state
= (state_t
*) initiator_init_create(this);
380 this->current_state
= (state_t
*) responder_init_create(this);
384 return (&this->public);