- retransmitting of requests implemented
[strongswan.git] / Source / charon / config / configuration_manager.c
1 /**
2 * @file configuration.c
3 *
4 * @brief Configuration class used to store IKE_SA-configurations.
5 *
6 * Object of this type represents the configuration for all IKE_SA's and their child_sa's.
7 *
8 */
9
10 /*
11 * Copyright (C) 2005 Jan Hutter, Martin Willi
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #include <stdlib.h>
26
27 #include "configuration_manager.h"
28
29 #include <types.h>
30 #include <daemon.h>
31 #include <utils/allocator.h>
32
33 typedef struct configuration_entry_t configuration_entry_t;
34
35 /* A configuration entry combines a configuration name with a init and sa
36 * configuration represented as init_config_t and sa_config_t objects.
37 */
38 struct configuration_entry_t {
39
40 /**
41 * Configuration name.
42 *
43 */
44 char *name;
45
46 /**
47 * Configuration for IKE_SA_INIT exchange.
48 */
49 init_config_t *init_config;
50
51 /**
52 * Configuration for all phases after IKE_SA_INIT exchange.
53 */
54 sa_config_t *sa_config;
55
56 /**
57 * Destroys a configuration_entry_t
58 *
59 *
60 * @param this calling object
61 */
62 void (*destroy) (configuration_entry_t *this);
63 };
64
65 static void configuration_entry_destroy (configuration_entry_t *this)
66 {
67 allocator_free(this->name);
68 allocator_free(this);
69 }
70
71 /**
72 * Creates a configuration_entry_t object
73 *
74 * @param name name of the configuration entry (gets copied)
75 * @param init_config object of type init_config_t
76 * @param sa_config object of type sa_config_t
77 */
78 configuration_entry_t * configuration_entry_create(char * name, init_config_t * init_config, sa_config_t * sa_config)
79 {
80 configuration_entry_t *entry = allocator_alloc_thing(configuration_entry_t);
81
82 /* functions */
83 entry->destroy = configuration_entry_destroy;
84
85 /* private data */
86 entry->init_config = init_config;
87 entry->sa_config = sa_config;
88 entry->name = allocator_alloc(strlen(name) + 1);
89 strcpy(entry->name,name);
90 return entry;
91 }
92
93
94 typedef struct private_configuration_manager_t private_configuration_manager_t;
95
96 /**
97 * Private data of an configuration_t object
98 */
99 struct private_configuration_manager_t {
100
101 /**
102 * Public part of configuration manager.
103 */
104 configuration_manager_t public;
105
106 /**
107 * Holding all configurations.
108 */
109 linked_list_t *configurations;
110
111 /**
112 * Holding all init_configs.
113 */
114 linked_list_t *init_configs;
115
116 /**
117 * Holding all init_configs.
118 */
119 linked_list_t *sa_configs;
120
121
122 /**
123 * Assigned logger object.
124 */
125 logger_t *logger;
126
127
128 /**
129 * Max number of retransmitted requests.
130 */
131 u_int32_t max_retransmit_count;
132
133 /**
134 * First retransmit timeout in ms.
135 */
136 u_int32_t first_retransmit_timeout;
137
138 /**
139 * Load default configuration
140 *
141 *
142 * @param this calling object
143 * @param name name for the configuration
144 * @param init_config init_config_t object
145 * @param sa_config sa_config_t object
146 */
147 void (*add_new_configuration) (private_configuration_manager_t *this, char *name, init_config_t *init_config, sa_config_t *sa_config);
148
149 /**
150 * Load default configuration
151 *
152 *
153 * @param this calling object
154 */
155 void (*load_default_config) (private_configuration_manager_t *this);
156 };
157
158 /**
159 * Implementation of private_configuration_manager_t.load_default_config.
160 */
161 static void load_default_config (private_configuration_manager_t *this)
162 {
163 init_config_t *init_config1, *init_config2, *init_config3;
164 ike_proposal_t proposals[2];
165 child_proposal_t child_proposals[1];
166 sa_config_t *sa_config1, *sa_config2, *sa_config3;
167 traffic_selector_t *ts;
168
169 init_config1 = init_config_create("152.96.193.131","152.96.193.131",IKEV2_UDP_PORT,IKEV2_UDP_PORT);
170 init_config2 = init_config_create("152.96.193.131","152.96.193.130",IKEV2_UDP_PORT,IKEV2_UDP_PORT);
171 init_config3 = init_config_create("0.0.0.0","127.0.0.1",IKEV2_UDP_PORT,IKEV2_UDP_PORT);
172 ts = traffic_selector_create_from_string(1, TS_IPV4_ADDR_RANGE, "0.0.0.0", 0, "255.255.255.255", 65535);
173
174
175 proposals[0].encryption_algorithm = ENCR_AES_CBC;
176 proposals[0].encryption_algorithm_key_length = 16;
177 proposals[0].integrity_algorithm = AUTH_HMAC_MD5_96;
178 proposals[0].integrity_algorithm_key_length = 16;
179 proposals[0].pseudo_random_function = PRF_HMAC_MD5;
180 proposals[0].pseudo_random_function_key_length = 16;
181 proposals[0].diffie_hellman_group = MODP_1024_BIT;
182
183 proposals[1] = proposals[0];
184 proposals[1].integrity_algorithm = AUTH_HMAC_SHA1_96;
185 proposals[1].integrity_algorithm_key_length = 20;
186 proposals[1].pseudo_random_function = PRF_HMAC_SHA1;
187 proposals[1].pseudo_random_function_key_length = 20;
188
189 init_config1->add_proposal(init_config1,1,proposals[0]);
190 init_config1->add_proposal(init_config1,1,proposals[1]);
191 init_config2->add_proposal(init_config2,1,proposals[0]);
192 init_config2->add_proposal(init_config2,1,proposals[1]);
193 init_config3->add_proposal(init_config3,1,proposals[0]);
194 init_config3->add_proposal(init_config3,1,proposals[1]);
195
196 sa_config1 = sa_config_create(ID_IPV4_ADDR, "152.96.193.131",
197 ID_IPV4_ADDR, "152.96.193.130",
198 SHARED_KEY_MESSAGE_INTEGRITY_CODE);
199
200 sa_config1->add_traffic_selector_initiator(sa_config1,ts);
201 sa_config1->add_traffic_selector_responder(sa_config1,ts);
202
203 sa_config2 = sa_config_create(ID_IPV4_ADDR, "152.96.193.130",
204 ID_IPV4_ADDR, "152.96.193.131",
205 SHARED_KEY_MESSAGE_INTEGRITY_CODE);
206
207 sa_config2->add_traffic_selector_initiator(sa_config2,ts);
208 sa_config2->add_traffic_selector_responder(sa_config2,ts);
209
210 sa_config3 = sa_config_create(ID_IPV4_ADDR, "127.0.0.1",
211 ID_IPV4_ADDR, "127.0.0.1",
212 SHARED_KEY_MESSAGE_INTEGRITY_CODE);
213
214 sa_config3->add_traffic_selector_initiator(sa_config3,ts);
215 sa_config3->add_traffic_selector_responder(sa_config3,ts);
216
217 ts->destroy(ts);
218
219 /* ah and esp prop */
220 child_proposals[0].ah.is_set = TRUE;
221 child_proposals[0].ah.integrity_algorithm = AUTH_HMAC_MD5_96;
222 child_proposals[0].ah.integrity_algorithm_key_size = 16;
223 child_proposals[0].ah.diffie_hellman_group = MODP_1024_BIT;
224 child_proposals[0].ah.extended_sequence_numbers = NO_EXT_SEQ_NUMBERS;
225
226 child_proposals[0].esp.is_set = TRUE;
227 child_proposals[0].esp.diffie_hellman_group = MODP_1024_BIT;
228 child_proposals[0].esp.encryption_algorithm = ENCR_AES_CBC;
229 child_proposals[0].esp.encryption_algorithm_key_size = 16;
230 child_proposals[0].esp.integrity_algorithm = AUTH_UNDEFINED;
231 child_proposals[0].esp.extended_sequence_numbers = NO_EXT_SEQ_NUMBERS;
232 child_proposals[0].esp.spi[0] = 2;
233 child_proposals[0].esp.spi[1] = 2;
234 child_proposals[0].esp.spi[2] = 2;
235 child_proposals[0].esp.spi[3] = 2;
236
237 sa_config1->add_proposal(sa_config1, &child_proposals[0]);
238 sa_config2->add_proposal(sa_config2, &child_proposals[0]);
239 sa_config3->add_proposal(sa_config3, &child_proposals[0]);
240
241 this->add_new_configuration(this,"pinflb31",init_config1,sa_config2);
242 this->add_new_configuration(this,"pinflb30",init_config2,sa_config1);
243 this->add_new_configuration(this,"localhost",init_config3,sa_config3);
244
245 }
246
247 /**
248 * Implementation of configuration_manager_t.get_init_config_for_host.
249 */
250 static status_t get_init_config_for_host (private_configuration_manager_t *this, host_t *my_host, host_t *other_host,init_config_t **init_config)
251 {
252 iterator_t *iterator;
253 status_t status = NOT_FOUND;
254
255 iterator = this->configurations->create_iterator(this->configurations,TRUE);
256
257 while (iterator->has_next(iterator))
258 {
259 configuration_entry_t *entry;
260 host_t *config_my_host;
261 host_t *config_other_host;
262
263 iterator->current(iterator,(void **) &entry);
264
265 config_my_host = entry->init_config->get_my_host(entry->init_config);
266 config_other_host = entry->init_config->get_other_host(entry->init_config);
267
268 /* first check if ip is equal */
269 if(config_other_host->ip_is_equal(config_other_host,other_host))
270 {
271 /* could be right one, check my_host for default route*/
272 if (config_my_host->is_default_route(config_my_host))
273 {
274 *init_config = entry->init_config;
275 status = SUCCESS;
276 break;
277 }
278 /* check now if host informations are the same */
279 else if (config_my_host->ip_is_equal(config_my_host,my_host))
280 {
281 *init_config = entry->init_config;
282 status = SUCCESS;
283 break;
284 }
285
286 }
287 /* Then check for wildcard hosts!
288 * TODO
289 * actually its only checked if other host with default route can be found! */
290 else if (config_other_host->is_default_route(config_other_host))
291 {
292 /* could be right one, check my_host for default route*/
293 if (config_my_host->is_default_route(config_my_host))
294 {
295 *init_config = entry->init_config;
296 status = SUCCESS;
297 break;
298 }
299 /* check now if host informations are the same */
300 else if (config_my_host->ip_is_equal(config_my_host,my_host))
301 {
302 *init_config = entry->init_config;
303 status = SUCCESS;
304 break;
305 }
306 }
307 }
308
309 iterator->destroy(iterator);
310
311 return status;
312 }
313
314 /**
315 * Implementation of configuration_manager_t.get_init_config_for_name.
316 */
317 static status_t get_init_config_for_name (private_configuration_manager_t *this, char *name, init_config_t **init_config)
318 {
319 iterator_t *iterator;
320 status_t status = NOT_FOUND;
321
322 iterator = this->configurations->create_iterator(this->configurations,TRUE);
323
324 while (iterator->has_next(iterator))
325 {
326 configuration_entry_t *entry;
327 iterator->current(iterator,(void **) &entry);
328
329 if (strcmp(entry->name,name) == 0)
330 {
331
332 /* found configuration */
333 *init_config = entry->init_config;
334 status = SUCCESS;
335 break;
336 }
337 }
338
339 iterator->destroy(iterator);
340
341 return status;
342 }
343
344 /**
345 * Implementation of configuration_manager_t.get_sa_config_for_name.
346 */
347 static status_t get_sa_config_for_name (private_configuration_manager_t *this, char *name, sa_config_t **sa_config)
348 {
349 iterator_t *iterator;
350 status_t status = NOT_FOUND;
351
352 iterator = this->configurations->create_iterator(this->configurations,TRUE);
353
354 while (iterator->has_next(iterator))
355 {
356 configuration_entry_t *entry;
357 iterator->current(iterator,(void **) &entry);
358
359 if (strcmp(entry->name,name) == 0)
360 {
361 /* found configuration */
362 *sa_config = entry->sa_config;
363 status = SUCCESS;
364 break;
365 }
366 }
367
368 iterator->destroy(iterator);
369
370 return status;
371 }
372
373 /**
374 * Implementation of configuration_manager_t.get_sa_config_for_init_config_and_id.
375 */
376 static status_t get_sa_config_for_init_config_and_id (private_configuration_manager_t *this, init_config_t *init_config, identification_t *other_id, identification_t *my_id,sa_config_t **sa_config)
377 {
378 iterator_t *iterator;
379 status_t status = NOT_FOUND;
380
381 iterator = this->configurations->create_iterator(this->configurations,TRUE);
382
383 while (iterator->has_next(iterator))
384 {
385 configuration_entry_t *entry;
386 iterator->current(iterator,(void **) &entry);
387
388 if (entry->init_config == init_config)
389 {
390 identification_t *config_my_id = entry->sa_config->get_my_id(entry->sa_config);
391 identification_t *config_other_id = entry->sa_config->get_other_id(entry->sa_config);
392
393 /* host informations seem to be the same */
394 if (config_other_id->equals(config_other_id,other_id))
395 {
396 /* other ids seems to match */
397
398 if (my_id == NULL)
399 {
400 /* first matching one is selected */
401
402 /* TODO priorize found entries */
403 *sa_config = entry->sa_config;
404 status = SUCCESS;
405 break;
406 }
407
408 if (config_my_id->equals(config_my_id,my_id))
409 {
410 *sa_config = entry->sa_config;
411 status = SUCCESS;
412 break;
413 }
414
415 }
416 }
417 }
418
419 iterator->destroy(iterator);
420
421 return status;
422 }
423
424 /**
425 * Implementation of private_configuration_manager_t.add_new_configuration.
426 */
427 static void add_new_configuration (private_configuration_manager_t *this, char *name, init_config_t *init_config, sa_config_t *sa_config)
428 {
429 iterator_t *iterator;
430 bool found;
431
432 iterator = this->init_configs->create_iterator(this->init_configs,TRUE);
433 found = FALSE;
434 while (iterator->has_next(iterator))
435 {
436 init_config_t *found_init_config;
437 iterator->current(iterator,(void **) &found_init_config);
438 if (init_config == found_init_config)
439 {
440 found = TRUE;
441 break;
442 }
443 }
444 iterator->destroy(iterator);
445 if (!found)
446 {
447 this->init_configs->insert_first(this->init_configs,init_config);
448 }
449
450 iterator = this->sa_configs->create_iterator(this->sa_configs,TRUE);
451 found = FALSE;
452 while (iterator->has_next(iterator))
453 {
454 sa_config_t *found_sa_config;
455 iterator->current(iterator,(void **) &found_sa_config);
456 if (sa_config == found_sa_config)
457 {
458 found = TRUE;
459 break;
460 }
461 }
462 iterator->destroy(iterator);
463 if (!found)
464 {
465 this->sa_configs->insert_first(this->sa_configs,sa_config);
466 }
467
468 this->configurations->insert_first(this->configurations,configuration_entry_create(name,init_config,sa_config));
469 }
470
471 static status_t get_retransmit_timeout (private_configuration_manager_t *this, u_int32_t retransmit_count, u_int32_t *timeout)
472 {
473 if ((retransmit_count > this->max_retransmit_count) && (this->max_retransmit_count != 0))
474 {
475 return FAILED;
476 }
477
478 /**
479 * TODO implement a good retransmit policy
480 */
481 *timeout = this->first_retransmit_timeout * (retransmit_count + 1);
482
483 return SUCCESS;
484 }
485
486 /**
487 * Implementation of configuration_manager_t.destroy.
488 */
489 static void destroy(private_configuration_manager_t *this)
490 {
491 this->logger->log(this->logger,CONTROL | MORE, "Going to destroy configuration manager ");
492
493 while (this->configurations->get_count(this->configurations) > 0)
494 {
495 configuration_entry_t *entry;
496 this->configurations->remove_first(this->configurations,(void **) &entry);
497 entry->destroy(entry);
498 }
499 /* todo delete all config objects */
500
501 this->configurations->destroy(this->configurations);
502
503 while (this->sa_configs->get_count(this->sa_configs) > 0)
504 {
505 sa_config_t *sa_config;
506 this->sa_configs->remove_first(this->sa_configs,(void **) &sa_config);
507 sa_config->destroy(sa_config);
508 }
509
510 this->sa_configs->destroy(this->sa_configs);
511
512 while (this->init_configs->get_count(this->init_configs) > 0)
513 {
514 init_config_t *init_config;
515 this->init_configs->remove_first(this->init_configs,(void **) &init_config);
516 init_config->destroy(init_config);
517 }
518 this->init_configs->destroy(this->init_configs);
519
520 this->logger->log(this->logger,CONTROL | MOST, "Destroy assigned logger");
521 charon->logger_manager->destroy_logger(charon->logger_manager,this->logger);
522 allocator_free(this);
523 }
524
525 /*
526 * Described in header-file
527 */
528 configuration_manager_t *configuration_manager_create(u_int32_t first_retransmit_timeout,u_int32_t max_retransmit_count)
529 {
530 private_configuration_manager_t *this = allocator_alloc_thing(private_configuration_manager_t);
531
532 /* public functions */
533 this->public.destroy = (void(*)(configuration_manager_t*))destroy;
534 this->public.get_init_config_for_name = (status_t (*) (configuration_manager_t *, char *, init_config_t **)) get_init_config_for_name;
535 this->public.get_init_config_for_host = (status_t (*) (configuration_manager_t *, host_t *, host_t *,init_config_t **)) get_init_config_for_host;
536 this->public.get_sa_config_for_name =(status_t (*) (configuration_manager_t *, char *, sa_config_t **)) get_sa_config_for_name;
537 this->public.get_sa_config_for_init_config_and_id =(status_t (*) (configuration_manager_t *, init_config_t *, identification_t *, identification_t *,sa_config_t **)) get_sa_config_for_init_config_and_id;
538 this->public.get_retransmit_timeout = (status_t (*) (configuration_manager_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout;
539
540 /* private functions */
541 this->load_default_config = load_default_config;
542 this->add_new_configuration = add_new_configuration;
543
544 /* private variables */
545 this->logger = charon->logger_manager->create_logger(charon->logger_manager,CONFIGURATION_MANAGER,NULL);
546 this->configurations = linked_list_create();
547 this->sa_configs = linked_list_create();
548 this->init_configs = linked_list_create();
549 this->max_retransmit_count = max_retransmit_count;
550 this->first_retransmit_timeout = first_retransmit_timeout;
551
552 this->load_default_config(this);
553
554 return (&this->public);
555 }