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
);
99 if (status
== SUCCESS
)
101 this->current_state
= new_state
;
107 * @brief Implements function build_message of protected_ike_sa_t.
109 static status_t
build_message(protected_ike_sa_t
*this, exchange_type_t type
, bool request
, message_t
**message
)
112 message_t
*new_message
;
113 host_t
*source
, *destination
;
115 this ->logger
->log(this->logger
, CONTROL
|MORE
, "build empty message");
116 new_message
= message_create();
117 if (new_message
== NULL
)
119 this->logger
->log(this->logger
, ERROR
, "Fatal error: could not create empty message object");
123 status
= this->me
.host
->clone(this->me
.host
, &source
);
124 if (status
!= SUCCESS
)
126 this->logger
->log(this->logger
, ERROR
, "Fatal error: could not clone my host information");
127 new_message
->destroy(new_message
);
130 status
= this->other
.host
->clone(this->other
.host
, &destination
);
131 if (status
!= SUCCESS
)
133 this->logger
->log(this->logger
, ERROR
, "Fatal error: could not clone other host information");
134 source
->destroy(source
);
135 new_message
->destroy(new_message
);
139 new_message
->set_source(new_message
, source
);
140 new_message
->set_destination(new_message
, destination
);
142 new_message
->set_exchange_type(new_message
, type
);
143 new_message
->set_request(new_message
, request
);
145 new_message
->set_message_id(new_message
, (request
) ?
this->message_id_out
: this->message_id_in
);
147 status
= new_message
->set_ike_sa_id(new_message
, this->ike_sa_id
);
148 if (status
!= SUCCESS
)
150 this->logger
->log(this->logger
, ERROR
, "Fatal error: could not set ike_sa_id of message");
151 new_message
->destroy(new_message
);
155 *message
= new_message
;
161 * @brief implements function process_configuration of protected_ike_sa_t
163 static status_t
initialize_connection(protected_ike_sa_t
*this, char *name
)
165 /* work is done in state object of type INITIATOR_INIT */
166 initiator_init_t
*current_state
;
170 if (this->current_state
->get_state(this->current_state
) != INITIATOR_INIT
)
175 current_state
= (initiator_init_t
*) this->current_state
;
177 status
= current_state
->initiate_connection(current_state
,name
,&new_state
);
179 if (status
== SUCCESS
)
181 this->current_state
= new_state
;
185 this->create_delete_job(this);
191 * @brief implements function protected_ike_sa_t.get_id
193 static ike_sa_id_t
* get_id(protected_ike_sa_t
*this)
195 return this->ike_sa_id
;
199 * @brief implements function resend_last_reply of protected_ike_sa_t
201 status_t
resend_last_reply (protected_ike_sa_t
*this)
206 status
= this->last_responded_message
->generate(this->last_responded_message
, &packet
);
207 if (status
!= SUCCESS
)
209 this->logger
->log(this->logger
, ERROR
, "Could not generate message to resent");
213 status
= global_send_queue
->add(global_send_queue
, packet
);
214 if (status
!= SUCCESS
)
216 this->logger
->log(this->logger
, ERROR
, "Could not add packet to send queue");
217 packet
->destroy(packet
);
223 status_t
create_delete_job (protected_ike_sa_t
*this)
228 this->logger
->log(this->logger
, CONTROL
| MORE
, "Going to create job to delete this IKE_SA");
230 delete_job
= (job_t
*) delete_ike_sa_job_create(this->ike_sa_id
);
231 if (delete_job
== NULL
)
233 this->logger
->log(this->logger
, ERROR
, "Job to delete IKE SA could not be created");
237 status
= global_job_queue
->add(global_job_queue
,delete_job
);
238 if (status
!= SUCCESS
)
240 this->logger
->log(this->logger
, ERROR
, "%s Job to delete IKE SA could not be added to job queue",mapping_find(status_m
,status
));
241 delete_job
->destroy_all(delete_job
);
248 * @brief implements function destroy of protected_ike_sa_t
250 static status_t
destroy (protected_ike_sa_t
*this)
253 this->logger
->log(this->logger
, CONTROL
| MORE
, "Going to destroy IKE_SA");
255 /* destroy child sa's */
256 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy all child_sa's");
257 while (this->child_sas
->get_count(this->child_sas
) > 0)
260 if (this->child_sas
->remove_first(this->child_sas
,&child_sa
) != SUCCESS
)
264 /* destroy child sa */
266 this->child_sas
->destroy(this->child_sas
);
268 /* destroy ike_sa_id */
269 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy assigned ike_sa_id");
270 this->ike_sa_id
->destroy(this->ike_sa_id
);
272 /* destroy stored requested message */
273 if (this->last_requested_message
!= NULL
)
275 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy last requested message");
276 this->last_requested_message
->destroy(this->last_requested_message
);
279 /* destroy stored responded messages */
280 if (this->last_responded_message
!= NULL
)
282 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy last responded message");
283 this->last_responded_message
->destroy(this->last_responded_message
);
286 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy randomizer");
287 this->randomizer
->destroy(this->randomizer
);
289 if (this->me
.host
!= NULL
)
291 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy host informations of me");
292 this->me
.host
->destroy(this->me
.host
);
295 if (this->other
.host
!= NULL
)
297 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy host informations of other");
298 this->other
.host
->destroy(this->other
.host
);
301 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy current state object");
302 this->current_state
->destroy(this->current_state
);
304 this->logger
->log(this->logger
, CONTROL
| MOST
, "Destroy logger of IKE_SA");
306 global_logger_manager
->destroy_logger(global_logger_manager
, this->logger
);
308 allocator_free(this);
313 * Described in Header
315 ike_sa_t
* ike_sa_create(ike_sa_id_t
*ike_sa_id
)
317 protected_ike_sa_t
*this = allocator_alloc_thing(protected_ike_sa_t
);
323 /* Public functions */
324 this->public.process_message
= (status_t(*)(ike_sa_t
*, message_t
*)) process_message
;
325 this->public.initialize_connection
= (status_t(*)(ike_sa_t
*, char*)) initialize_connection
;
326 this->public.get_id
= (ike_sa_id_t
*(*)(ike_sa_t
*)) get_id
;
327 this->public.destroy
= (status_t(*)(ike_sa_t
*))destroy
;
329 /* private functions */
330 this->build_message
= build_message
;
331 this->resend_last_reply
= resend_last_reply
;
332 this->create_delete_job
= create_delete_job
;
334 /* initialize private fields */
335 this->logger
= global_logger_manager
->create_logger(global_logger_manager
, IKE_SA
, NULL
);
336 if (this->logger
== NULL
)
338 allocator_free(this);
341 if (ike_sa_id
->clone(ike_sa_id
,&(this->ike_sa_id
)) != SUCCESS
)
343 this->logger
->log(this->logger
, ERROR
, "Fatal error: Could not clone ike_sa_id");
344 global_logger_manager
->destroy_logger(global_logger_manager
,this->logger
);
345 allocator_free(this);
348 this->child_sas
= linked_list_create();
349 if (this->child_sas
== NULL
)
351 this->logger
->log(this->logger
, ERROR
, "Fatal error: Could not create list for child_sa's");
352 this->ike_sa_id
->destroy(this->ike_sa_id
);
353 global_logger_manager
->destroy_logger(global_logger_manager
,this->logger
);
354 allocator_free(this);
357 this->randomizer
= randomizer_create();
358 if (this->randomizer
== NULL
)
360 this->logger
->log(this->logger
, ERROR
, "Fatal error: Could not create list for child_sa's");
361 this->child_sas
->destroy(this->child_sas
);
362 this->ike_sa_id
->destroy(this->ike_sa_id
);
363 global_logger_manager
->destroy_logger(global_logger_manager
,this->logger
);
364 allocator_free(this);
367 this->me
.host
= NULL
;
368 this->other
.host
= NULL
;
369 this->last_requested_message
= NULL
;
370 this->last_responded_message
= NULL
;
371 this->message_id_out
= 0;
372 this->message_id_in
= 0;
375 /* at creation time, IKE_SA is in a initiator state */
376 if (ike_sa_id
->is_initiator(ike_sa_id
))
378 this->current_state
= (state_t
*) initiator_init_create(this);
382 this->current_state
= (state_t
*) responder_init_create(this);
385 if (this->current_state
== NULL
)
387 this->logger
->log(this->logger
, ERROR
, "Fatal error: Could not create state object");
388 this->child_sas
->destroy(this->child_sas
);
389 this->ike_sa_id
->destroy(this->ike_sa_id
);
390 global_logger_manager
->destroy_logger(global_logger_manager
,this->logger
);
391 this->randomizer
->destroy(this->randomizer
);
392 allocator_free(this);
396 return &(this->public);