- still one memory leak and segmentation fault
[strongswan.git] / Source / charon / ike_sa.c
1 /**
2 * @file ike_sa.c
3 *
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
6 *
7 */
8
9 /*
10 * Copyright (C) 2005 Jan Hutter, Martin Willi
11 * Hochschule fuer Technik Rapperswil
12 *
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>.
17 *
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
21 * for more details.
22 */
23
24 #include "ike_sa.h"
25
26 #include "types.h"
27 #include "globals.h"
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"
41
42
43
44
45 /**
46 * @brief implements function process_message of protected_ike_sa_t
47 */
48 static status_t process_message (protected_ike_sa_t *this, message_t *message)
49 {
50 u_int32_t message_id;
51 exchange_type_t exchange_type;
52 bool is_request;
53 status_t status;
54 state_t *new_state;
55
56 /* we must process each request or response from remote host */
57
58 /* find out type of message (request or response) */
59 is_request = message->get_request(message);
60 exchange_type = message->get_exchange_type(message);
61
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));
63
64 message_id = message->get_message_id(message);
65
66 /*
67 * It has to be checked, if the message has to be resent cause of lost packets!
68 */
69 if (is_request && ( message_id == (this->message_id_in - 1)))
70 {
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));
74 }
75
76 /* Now, the message id is checked for request AND reply */
77 if (is_request)
78 {
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)
81 {
82 this->logger->log(this->logger, ERROR | MORE, "Message request with message id %d received, but %d expected",message_id,this->message_id_in);
83 return FAILED;
84 }
85 }
86 else
87 {
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))
90 {
91 this->logger->log(this->logger, ERROR | MORE, "Message reply with message id %d received, but %d expected",message_id,this->message_id_in);
92 return FAILED;
93 }
94 }
95
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
99 if (status == SUCCESS)
100 {
101 this->current_state = new_state;
102 }
103 return status;
104 }
105
106 /**
107 * @brief Implements function build_message of protected_ike_sa_t.
108 */
109 static status_t build_message(protected_ike_sa_t *this, exchange_type_t type, bool request, message_t **message)
110 {
111 status_t status;
112 message_t *new_message;
113 host_t *source, *destination;
114
115 this ->logger->log(this->logger, CONTROL|MORE, "build empty message");
116 new_message = message_create();
117 if (new_message == NULL)
118 {
119 this->logger->log(this->logger, ERROR, "Fatal error: could not create empty message object");
120 return OUT_OF_RES;
121 }
122
123 status = this->me.host->clone(this->me.host, &source);
124 if (status != SUCCESS)
125 {
126 this->logger->log(this->logger, ERROR, "Fatal error: could not clone my host information");
127 new_message->destroy(new_message);
128 return status;
129 }
130 status = this->other.host->clone(this->other.host, &destination);
131 if (status != SUCCESS)
132 {
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);
136 return status;
137 }
138
139 new_message->set_source(new_message, source);
140 new_message->set_destination(new_message, destination);
141
142 new_message->set_exchange_type(new_message, type);
143 new_message->set_request(new_message, request);
144
145 new_message->set_message_id(new_message, (request) ? this->message_id_out : this->message_id_in);
146
147 status = new_message->set_ike_sa_id(new_message, this->ike_sa_id);
148 if (status != SUCCESS)
149 {
150 this->logger->log(this->logger, ERROR, "Fatal error: could not set ike_sa_id of message");
151 new_message->destroy(new_message);
152 return status;
153 }
154
155 *message = new_message;
156
157 return SUCCESS;
158 }
159
160 /**
161 * @brief implements function process_configuration of protected_ike_sa_t
162 */
163 static status_t initialize_connection(protected_ike_sa_t *this, char *name)
164 {
165 /* work is done in state object of type INITIATOR_INIT */
166 initiator_init_t *current_state;
167 status_t status;
168 state_t *new_state;
169
170 if (this->current_state->get_state(this->current_state) != INITIATOR_INIT)
171 {
172 return FAILED;
173 }
174
175 current_state = (initiator_init_t *) this->current_state;
176
177 status = current_state->initiate_connection(current_state,name,&new_state);
178
179 if (status == SUCCESS)
180 {
181 this->current_state = new_state;
182 }
183 else
184 {
185 this->create_delete_job(this);
186 }
187 return status;
188 }
189
190 /**
191 * @brief implements function protected_ike_sa_t.get_id
192 */
193 static ike_sa_id_t* get_id(protected_ike_sa_t *this)
194 {
195 return this->ike_sa_id;
196 }
197
198 /**
199 * @brief implements function resend_last_reply of protected_ike_sa_t
200 */
201 status_t resend_last_reply (protected_ike_sa_t *this)
202 {
203 packet_t *packet;
204 status_t status;
205
206 status = this->last_responded_message->generate(this->last_responded_message, &packet);
207 if (status != SUCCESS)
208 {
209 this->logger->log(this->logger, ERROR, "Could not generate message to resent");
210 return status;
211 }
212
213 status = global_send_queue->add(global_send_queue, packet);
214 if (status != SUCCESS)
215 {
216 this->logger->log(this->logger, ERROR, "Could not add packet to send queue");
217 packet->destroy(packet);
218 return status;
219 }
220 return SUCCESS;
221 }
222
223 status_t create_delete_job (protected_ike_sa_t *this)
224 {
225 job_t *delete_job;
226 status_t status;
227
228 this->logger->log(this->logger, CONTROL | MORE, "Going to create job to delete this IKE_SA");
229
230 delete_job = (job_t *) delete_ike_sa_job_create(this->ike_sa_id);
231 if (delete_job == NULL)
232 {
233 this->logger->log(this->logger, ERROR, "Job to delete IKE SA could not be created");
234 return FAILED;
235 }
236
237 status = global_job_queue->add(global_job_queue,delete_job);
238 if (status != SUCCESS)
239 {
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);
242 return status;
243 }
244 return SUCCESS;
245 }
246
247 /**
248 * @brief implements function destroy of protected_ike_sa_t
249 */
250 static status_t destroy (protected_ike_sa_t *this)
251 {
252
253 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy IKE_SA");
254
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)
258 {
259 void *child_sa;
260 if (this->child_sas->remove_first(this->child_sas,&child_sa) != SUCCESS)
261 {
262 break;
263 }
264 /* destroy child sa */
265 }
266 this->child_sas->destroy(this->child_sas);
267
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);
271
272 /* destroy stored requested message */
273 if (this->last_requested_message != NULL)
274 {
275 this->logger->log(this->logger, CONTROL | MOST, "Destroy last requested message");
276 this->last_requested_message->destroy(this->last_requested_message);
277 }
278
279 /* destroy stored responded messages */
280 if (this->last_responded_message != NULL)
281 {
282 this->logger->log(this->logger, CONTROL | MOST, "Destroy last responded message");
283 this->last_responded_message->destroy(this->last_responded_message);
284 }
285
286 this->logger->log(this->logger, CONTROL | MOST, "Destroy randomizer");
287 this->randomizer->destroy(this->randomizer);
288
289 if (this->me.host != NULL)
290 {
291 this->logger->log(this->logger, CONTROL | MOST, "Destroy host informations of me");
292 this->me.host->destroy(this->me.host);
293 }
294
295 if (this->other.host != NULL)
296 {
297 this->logger->log(this->logger, CONTROL | MOST, "Destroy host informations of other");
298 this->other.host->destroy(this->other.host);
299 }
300
301 this->logger->log(this->logger, CONTROL | MOST, "Destroy current state object");
302 this->current_state->destroy(this->current_state);
303
304 this->logger->log(this->logger, CONTROL | MOST, "Destroy logger of IKE_SA");
305
306 global_logger_manager->destroy_logger(global_logger_manager, this->logger);
307
308 allocator_free(this);
309 return SUCCESS;
310 }
311
312 /*
313 * Described in Header
314 */
315 ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
316 {
317 protected_ike_sa_t *this = allocator_alloc_thing(protected_ike_sa_t);
318 if (this == NULL)
319 {
320 return NULL;
321 }
322
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;
328
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;
333
334 /* initialize private fields */
335 this->logger = global_logger_manager->create_logger(global_logger_manager, IKE_SA, NULL);
336 if (this->logger == NULL)
337 {
338 allocator_free(this);
339 }
340
341 if (ike_sa_id->clone(ike_sa_id,&(this->ike_sa_id)) != SUCCESS)
342 {
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);
346 return NULL;
347 }
348 this->child_sas = linked_list_create();
349 if (this->child_sas == NULL)
350 {
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);
355 return NULL;
356 }
357 this->randomizer = randomizer_create();
358 if (this->randomizer == NULL)
359 {
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);
365 }
366
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;
373
374
375 /* at creation time, IKE_SA is in a initiator state */
376 if (ike_sa_id->is_initiator(ike_sa_id))
377 {
378 this->current_state = (state_t *) initiator_init_create(this);
379 }
380 else
381 {
382 this->current_state = (state_t *) responder_init_create(this);
383 }
384
385 if (this->current_state == NULL)
386 {
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);
393 }
394
395
396 return &(this->public);
397 }