added API for random number generators, served through credential factory
[strongswan.git] / src / charon / sa / ike_sa_manager.c
1 /*
2 * Copyright (C) 2005-2006 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include <pthread.h>
20 #include <string.h>
21
22 #include "ike_sa_manager.h"
23
24 #include <daemon.h>
25 #include <sa/ike_sa_id.h>
26 #include <bus/bus.h>
27 #include <utils/linked_list.h>
28 #include <crypto/hashers/hasher.h>
29
30 typedef struct entry_t entry_t;
31
32 /**
33 * An entry in the linked list, contains IKE_SA, locking and lookup data.
34 */
35 struct entry_t {
36
37 /**
38 * Number of threads waiting for this ike_sa_t object.
39 */
40 int waiting_threads;
41
42 /**
43 * Condvar where threads can wait until ike_sa_t object is free for use again.
44 */
45 pthread_cond_t condvar;
46
47 /**
48 * Is this ike_sa currently checked out?
49 */
50 bool checked_out;
51
52 /**
53 * Does this SA drives out new threads?
54 */
55 bool driveout_new_threads;
56
57 /**
58 * Does this SA drives out waiting threads?
59 */
60 bool driveout_waiting_threads;
61
62 /**
63 * Identifiaction of an IKE_SA (SPIs).
64 */
65 ike_sa_id_t *ike_sa_id;
66
67 /**
68 * The contained ike_sa_t object.
69 */
70 ike_sa_t *ike_sa;
71
72 /**
73 * hash of the IKE_SA_INIT message, used to detect retransmissions
74 */
75 chunk_t init_hash;
76
77 /**
78 * message ID currently processing, if any
79 */
80 u_int32_t message_id;
81 };
82
83 /**
84 * Implementation of entry_t.destroy.
85 */
86 static status_t entry_destroy(entry_t *this)
87 {
88 /* also destroy IKE SA */
89 this->ike_sa->destroy(this->ike_sa);
90 this->ike_sa_id->destroy(this->ike_sa_id);
91 chunk_free(&this->init_hash);
92 free(this);
93 return SUCCESS;
94 }
95
96 /**
97 * Creates a new entry for the ike_sa_t list.
98 */
99 static entry_t *entry_create(ike_sa_id_t *ike_sa_id)
100 {
101 entry_t *this = malloc_thing(entry_t);
102
103 this->waiting_threads = 0;
104 pthread_cond_init(&this->condvar, NULL);
105
106 /* we set checkout flag when we really give it out */
107 this->checked_out = FALSE;
108 this->driveout_new_threads = FALSE;
109 this->driveout_waiting_threads = FALSE;
110 this->message_id = -1;
111 this->init_hash = chunk_empty;
112
113 /* ike_sa_id is always cloned */
114 this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
115
116 /* create new ike_sa */
117 this->ike_sa = ike_sa_create(ike_sa_id);
118
119 return this;
120 }
121
122
123 typedef struct private_ike_sa_manager_t private_ike_sa_manager_t;
124
125 /**
126 * Additional private members of ike_sa_manager_t.
127 */
128 struct private_ike_sa_manager_t {
129 /**
130 * Public interface of ike_sa_manager_t.
131 */
132 ike_sa_manager_t public;
133
134 /**
135 * Lock for exclusivly accessing the manager.
136 */
137 pthread_mutex_t mutex;
138
139 /**
140 * Linked list with entries for the ike_sa_t objects.
141 */
142 linked_list_t *ike_sa_list;
143
144 /**
145 * RNG to get random SPIs for our side
146 */
147 rng_t *rng;
148
149 /**
150 * SHA1 hasher for IKE_SA_INIT retransmit detection
151 */
152 hasher_t *hasher;
153 };
154
155 /**
156 * Implementation of private_ike_sa_manager_t.get_entry_by_id.
157 */
158 static status_t get_entry_by_id(private_ike_sa_manager_t *this,
159 ike_sa_id_t *ike_sa_id, entry_t **entry)
160 {
161 enumerator_t *enumerator;
162 entry_t *current;
163 status_t status;
164
165 /* create enumerator over list of ike_sa's */
166 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
167
168 /* default status */
169 status = NOT_FOUND;
170
171 while (enumerator->enumerate(enumerator, &current))
172 {
173 if (current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id))
174 {
175 DBG2(DBG_MGR, "found entry by both SPIs");
176 *entry = current;
177 status = SUCCESS;
178 break;
179 }
180 if (ike_sa_id->get_responder_spi(ike_sa_id) == 0 ||
181 current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0)
182 {
183 /* seems to be a half ready ike_sa */
184 if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) ==
185 ike_sa_id->get_initiator_spi(ike_sa_id)) &&
186 (current->ike_sa_id->is_initiator(ike_sa_id) ==
187 ike_sa_id->is_initiator(current->ike_sa_id)))
188 {
189 DBG2(DBG_MGR, "found entry by initiator SPI");
190 *entry = current;
191 status = SUCCESS;
192 break;
193 }
194 }
195 }
196
197 enumerator->destroy(enumerator);
198 return status;
199 }
200
201 /**
202 * Implementation of private_ike_sa_manager_t.get_entry_by_sa.
203 */
204 static status_t get_entry_by_sa(private_ike_sa_manager_t *this,
205 ike_sa_t *ike_sa, entry_t **entry)
206 {
207 enumerator_t *enumerator;
208 entry_t *current;
209 status_t status;
210
211 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
212
213 /* default status */
214 status = NOT_FOUND;
215
216 while (enumerator->enumerate(enumerator, &current))
217 {
218 /* only pointers are compared */
219 if (current->ike_sa == ike_sa)
220 {
221 DBG2(DBG_MGR, "found entry by pointer");
222 *entry = current;
223 status = SUCCESS;
224 break;
225 }
226 }
227 enumerator->destroy(enumerator);
228
229 return status;
230 }
231
232 /**
233 * Implementation of private_ike_sa_manager_s.delete_entry.
234 */
235 static status_t delete_entry(private_ike_sa_manager_t *this, entry_t *entry)
236 {
237 enumerator_t *enumerator;
238 entry_t *current;
239 status_t status;
240
241 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
242
243 status = NOT_FOUND;
244
245 while (enumerator->enumerate(enumerator, &current))
246 {
247 if (current == entry)
248 {
249 /* mark it, so now new threads can get this entry */
250 entry->driveout_new_threads = TRUE;
251 /* wait until all workers have done their work */
252 while (entry->waiting_threads)
253 {
254 /* wake up all */
255 pthread_cond_broadcast(&(entry->condvar));
256 /* they will wake us again when their work is done */
257 pthread_cond_wait(&(entry->condvar), &(this->mutex));
258 }
259
260 DBG2(DBG_MGR, "found entry by pointer, deleting it");
261 this->ike_sa_list->remove_at(this->ike_sa_list, enumerator);
262 entry_destroy(entry);
263 status = SUCCESS;
264 break;
265 }
266 }
267 enumerator->destroy(enumerator);
268 return status;
269 }
270
271 /**
272 * Wait until no other thread is using an IKE_SA, return FALSE if entry not
273 * acquireable
274 */
275 static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry)
276 {
277 if (entry->driveout_new_threads)
278 {
279 /* we are not allowed to get this */
280 return FALSE;
281 }
282 while (entry->checked_out && !entry->driveout_waiting_threads)
283 {
284 /* so wait until we can get it for us.
285 * we register us as waiting. */
286 entry->waiting_threads++;
287 pthread_cond_wait(&(entry->condvar), &(this->mutex));
288 entry->waiting_threads--;
289 }
290 /* hm, a deletion request forbids us to get this SA, get next one */
291 if (entry->driveout_waiting_threads)
292 {
293 /* we must signal here, others may be waiting on it, too */
294 pthread_cond_signal(&(entry->condvar));
295 return FALSE;
296 }
297 return TRUE;
298 }
299
300 /**
301 * Implementation of private_ike_sa_manager_t.get_next_spi.
302 */
303 static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
304 {
305 u_int64_t spi;
306
307 this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi);
308 return spi;
309 }
310
311 /**
312 * Implementation of of ike_sa_manager.checkout.
313 */
314 static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
315 {
316 ike_sa_t *ike_sa = NULL;
317 entry_t *entry;
318
319 DBG2(DBG_MGR, "checkout IKE_SA, %d IKE_SAs in manager",
320 this->ike_sa_list->get_count(this->ike_sa_list));
321
322 pthread_mutex_lock(&(this->mutex));
323 if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
324 {
325 if (wait_for_entry(this, entry))
326 {
327 DBG2(DBG_MGR, "IKE_SA successfully checked out");
328 entry->checked_out = TRUE;
329 ike_sa = entry->ike_sa;
330 }
331 }
332 pthread_mutex_unlock(&this->mutex);
333 charon->bus->set_sa(charon->bus, ike_sa);
334 return ike_sa;
335 }
336
337 /**
338 * Implementation of of ike_sa_manager.checkout_new.
339 */
340 static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
341 {
342 entry_t *entry;
343 ike_sa_id_t *id;
344
345 if (initiator)
346 {
347 id = ike_sa_id_create(get_next_spi(this), 0, TRUE);
348 }
349 else
350 {
351 id = ike_sa_id_create(0, get_next_spi(this), FALSE);
352 }
353 entry = entry_create(id);
354 id->destroy(id);
355 pthread_mutex_lock(&this->mutex);
356 this->ike_sa_list->insert_last(this->ike_sa_list, entry);
357 entry->checked_out = TRUE;
358 pthread_mutex_unlock(&this->mutex);
359 DBG2(DBG_MGR, "created IKE_SA, %d IKE_SAs in manager",
360 this->ike_sa_list->get_count(this->ike_sa_list));
361 return entry->ike_sa;
362 }
363
364 /**
365 * Implementation of of ike_sa_manager.checkout_by_message.
366 */
367 static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
368 message_t *message)
369 {
370 entry_t *entry;
371 ike_sa_t *ike_sa = NULL;
372 ike_sa_id_t *id = message->get_ike_sa_id(message);
373 id = id->clone(id);
374 id->switch_initiator(id);
375
376 DBG2(DBG_MGR, "checkout IKE_SA by message, %d IKE_SAs in manager",
377 this->ike_sa_list->get_count(this->ike_sa_list));
378
379 if (message->get_request(message) &&
380 message->get_exchange_type(message) == IKE_SA_INIT)
381 {
382 /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */
383 enumerator_t *enumerator;
384 chunk_t data, hash;
385
386 data = message->get_packet_data(message);
387 this->hasher->allocate_hash(this->hasher, data, &hash);
388 chunk_free(&data);
389
390 pthread_mutex_lock(&this->mutex);
391 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
392 while (enumerator->enumerate(enumerator, &entry))
393 {
394 if (chunk_equals(hash, entry->init_hash))
395 {
396 if (entry->message_id == 0)
397 {
398 enumerator->destroy(enumerator);
399 pthread_mutex_unlock(&this->mutex);
400 chunk_free(&hash);
401 id->destroy(id);
402 DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing");
403 return NULL;
404 }
405 else if (wait_for_entry(this, entry))
406 {
407 DBG2(DBG_MGR, "IKE_SA checked out by hash");
408 entry->checked_out = TRUE;
409 entry->message_id = message->get_message_id(message);
410 ike_sa = entry->ike_sa;
411 }
412 break;
413 }
414 }
415 enumerator->destroy(enumerator);
416 pthread_mutex_unlock(&this->mutex);
417
418 if (ike_sa == NULL)
419 {
420 if (id->get_responder_spi(id) == 0 &&
421 message->get_exchange_type(message) == IKE_SA_INIT)
422 {
423 /* no IKE_SA found, create a new one */
424 id->set_responder_spi(id, get_next_spi(this));
425 entry = entry_create(id);
426
427 pthread_mutex_lock(&this->mutex);
428 this->ike_sa_list->insert_last(this->ike_sa_list, entry);
429 entry->checked_out = TRUE;
430 entry->message_id = message->get_message_id(message);
431 pthread_mutex_unlock(&this->mutex);
432 entry->init_hash = hash;
433 ike_sa = entry->ike_sa;
434 }
435 else
436 {
437 chunk_free(&hash);
438 DBG1(DBG_MGR, "ignoring message, no such IKE_SA");
439 }
440 }
441 else
442 {
443 chunk_free(&hash);
444 }
445 id->destroy(id);
446 charon->bus->set_sa(charon->bus, ike_sa);
447 return ike_sa;
448 }
449
450 pthread_mutex_lock(&(this->mutex));
451 if (get_entry_by_id(this, id, &entry) == SUCCESS)
452 {
453 /* only check out if we are not processing this request */
454 if (message->get_request(message) &&
455 message->get_message_id(message) == entry->message_id)
456 {
457 DBG1(DBG_MGR, "ignoring request with ID %d, already processing",
458 entry->message_id);
459 }
460 else if (wait_for_entry(this, entry))
461 {
462 ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa);
463 DBG2(DBG_MGR, "IKE_SA successfully checked out");
464 entry->checked_out = TRUE;
465 entry->message_id = message->get_message_id(message);
466 if (ike_id->get_responder_spi(ike_id) == 0)
467 {
468 ike_id->set_responder_spi(ike_id, id->get_responder_spi(id));
469 }
470 ike_sa = entry->ike_sa;
471 }
472 }
473 pthread_mutex_unlock(&this->mutex);
474 id->destroy(id);
475 charon->bus->set_sa(charon->bus, ike_sa);
476 return ike_sa;
477 }
478
479 /**
480 * Implementation of of ike_sa_manager.checkout_by_config.
481 */
482 static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
483 peer_cfg_t *peer_cfg)
484 {
485 enumerator_t *enumerator;
486 entry_t *entry;
487 ike_sa_t *ike_sa = NULL;
488 identification_t *my_id, *other_id;
489 host_t *my_host, *other_host;
490 ike_cfg_t *ike_cfg;
491
492 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
493 my_host = ike_cfg->get_my_host(ike_cfg);
494 other_host = ike_cfg->get_other_host(ike_cfg);
495 my_id = peer_cfg->get_my_id(peer_cfg);
496 other_id = peer_cfg->get_other_id(peer_cfg);
497
498 pthread_mutex_lock(&(this->mutex));
499
500 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
501 while (enumerator->enumerate(enumerator, &entry))
502 {
503 identification_t *found_my_id, *found_other_id;
504 host_t *found_my_host, *found_other_host;
505
506 if (!wait_for_entry(this, entry))
507 {
508 continue;
509 }
510
511 if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
512 {
513 /* skip IKE_SA which are not useable */
514 continue;
515 }
516
517 found_my_id = entry->ike_sa->get_my_id(entry->ike_sa);
518 found_other_id = entry->ike_sa->get_other_id(entry->ike_sa);
519 found_my_host = entry->ike_sa->get_my_host(entry->ike_sa);
520 found_other_host = entry->ike_sa->get_other_host(entry->ike_sa);
521
522 if (found_my_id->get_type(found_my_id) == ID_ANY &&
523 found_other_id->get_type(found_other_id) == ID_ANY)
524 {
525 /* IKE_SA has no IDs yet, so we can't use it */
526 continue;
527 }
528 DBG2(DBG_MGR, "candidate IKE_SA for \n\t%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]",
529 my_host, my_id, other_host, other_id,
530 found_my_host, found_my_id, found_other_host, found_other_id);
531 /* compare ID and hosts. Supplied ID may contain wildcards, and IP
532 * may be %any. */
533 if ((my_host->is_anyaddr(my_host) ||
534 my_host->ip_equals(my_host, found_my_host)) &&
535 (other_host->is_anyaddr(other_host) ||
536 other_host->ip_equals(other_host, found_other_host)) &&
537 found_my_id->matches(found_my_id, my_id) &&
538 found_other_id->matches(found_other_id, other_id) &&
539 streq(peer_cfg->get_name(peer_cfg),
540 entry->ike_sa->get_name(entry->ike_sa)))
541 {
542 /* looks good, we take this one */
543 DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]",
544 my_host, my_id, other_host, other_id);
545 entry->checked_out = TRUE;
546 ike_sa = entry->ike_sa;
547 break;
548 }
549 }
550 enumerator->destroy(enumerator);
551
552 if (!ike_sa)
553 {
554 u_int64_t initiator_spi;
555 entry_t *new_entry;
556 ike_sa_id_t *new_ike_sa_id;
557
558 initiator_spi = get_next_spi(this);
559 new_ike_sa_id = ike_sa_id_create(0, 0, TRUE);
560 new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi);
561
562 /* create entry */
563 new_entry = entry_create(new_ike_sa_id);
564 DBG2(DBG_MGR, "created IKE_SA");
565 new_ike_sa_id->destroy(new_ike_sa_id);
566
567 this->ike_sa_list->insert_last(this->ike_sa_list, new_entry);
568
569 /* check ike_sa out */
570 DBG2(DBG_MGR, "new IKE_SA created for IDs [%D]...[%D]", my_id, other_id);
571 new_entry->checked_out = TRUE;
572 ike_sa = new_entry->ike_sa;
573 }
574 pthread_mutex_unlock(&(this->mutex));
575 charon->bus->set_sa(charon->bus, ike_sa);
576 return ike_sa;
577 }
578
579 /**
580 * Implementation of of ike_sa_manager.checkout_by_id.
581 */
582 static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
583 bool child)
584 {
585 enumerator_t *enumerator;
586 iterator_t *children;
587 entry_t *entry;
588 ike_sa_t *ike_sa = NULL;
589 child_sa_t *child_sa;
590
591 pthread_mutex_lock(&(this->mutex));
592
593 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
594 while (enumerator->enumerate(enumerator, &entry))
595 {
596 if (wait_for_entry(this, entry))
597 {
598 /* look for a child with such a reqid ... */
599 if (child)
600 {
601 children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
602 while (children->iterate(children, (void**)&child_sa))
603 {
604 if (child_sa->get_reqid(child_sa) == id)
605 {
606 ike_sa = entry->ike_sa;
607 break;
608 }
609 }
610 children->destroy(children);
611 }
612 else /* ... or for a IKE_SA with such a unique id */
613 {
614 if (entry->ike_sa->get_unique_id(entry->ike_sa) == id)
615 {
616 ike_sa = entry->ike_sa;
617 }
618 }
619 /* got one, return */
620 if (ike_sa)
621 {
622 entry->checked_out = TRUE;
623 break;
624 }
625 }
626 }
627 enumerator->destroy(enumerator);
628 pthread_mutex_unlock(&(this->mutex));
629
630 charon->bus->set_sa(charon->bus, ike_sa);
631 return ike_sa;
632 }
633
634 /**
635 * Implementation of of ike_sa_manager.checkout_by_name.
636 */
637 static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
638 bool child)
639 {
640 enumerator_t *enumerator;
641 iterator_t *children;
642 entry_t *entry;
643 ike_sa_t *ike_sa = NULL;
644 child_sa_t *child_sa;
645
646 pthread_mutex_lock(&(this->mutex));
647
648 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
649 while (enumerator->enumerate(enumerator, &entry))
650 {
651 if (wait_for_entry(this, entry))
652 {
653 /* look for a child with such a policy name ... */
654 if (child)
655 {
656 children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
657 while (children->iterate(children, (void**)&child_sa))
658 {
659 if (streq(child_sa->get_name(child_sa), name))
660 {
661 ike_sa = entry->ike_sa;
662 break;
663 }
664 }
665 children->destroy(children);
666 }
667 else /* ... or for a IKE_SA with such a connection name */
668 {
669 if (streq(entry->ike_sa->get_name(entry->ike_sa), name))
670 {
671 ike_sa = entry->ike_sa;
672 }
673 }
674 /* got one, return */
675 if (ike_sa)
676 {
677 entry->checked_out = TRUE;
678 break;
679 }
680 }
681 }
682 enumerator->destroy(enumerator);
683 pthread_mutex_unlock(&(this->mutex));
684
685 charon->bus->set_sa(charon->bus, ike_sa);
686 return ike_sa;
687 }
688
689 /**
690 * Implementation of ike_sa_manager_t.checkout_duplicate.
691 */
692 static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
693 ike_sa_t *ike_sa)
694 {
695 enumerator_t *enumerator;
696 entry_t *entry;
697 ike_sa_t *duplicate = NULL;
698 identification_t *me, *other;
699
700 me = ike_sa->get_my_id(ike_sa);
701 other = ike_sa->get_other_id(ike_sa);
702
703 pthread_mutex_lock(&this->mutex);
704 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
705 while (enumerator->enumerate(enumerator, &entry))
706 {
707 if (entry->ike_sa == ike_sa)
708 { /* self is not a duplicate */
709 continue;
710 }
711 if (wait_for_entry(this, entry))
712 {
713 if (me->equals(me, entry->ike_sa->get_my_id(entry->ike_sa)) &&
714 other->equals(other, entry->ike_sa->get_other_id(entry->ike_sa)))
715 {
716 duplicate = entry->ike_sa;
717 entry->checked_out = TRUE;
718 break;
719 }
720 }
721 }
722 enumerator->destroy(enumerator);
723 pthread_mutex_unlock(&this->mutex);
724 return duplicate;
725 }
726
727 /**
728 * enumerator cleanup function
729 */
730 static void enumerator_unlock(private_ike_sa_manager_t *this)
731 {
732 pthread_mutex_unlock(&this->mutex);
733 }
734
735 /**
736 * enumerator filter function
737 */
738 static bool enumerator_filter(private_ike_sa_manager_t *this,
739 entry_t **in, ike_sa_t **out)
740 {
741 if (wait_for_entry(this, *in))
742 {
743 *out = (*in)->ike_sa;
744 return TRUE;
745 }
746 return FALSE;
747 }
748
749 /**
750 * Implementation of ike_sa_manager_t.create_iterator.
751 */
752 static enumerator_t *create_enumerator(private_ike_sa_manager_t* this)
753 {
754 pthread_mutex_lock(&this->mutex);
755 return enumerator_create_filter(
756 this->ike_sa_list->create_enumerator(this->ike_sa_list),
757 (void*)enumerator_filter, this, (void*)enumerator_unlock);
758 }
759
760 /**
761 * Implementation of ike_sa_manager_t.checkin.
762 */
763 static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
764 {
765 /* to check the SA back in, we look for the pointer of the ike_sa
766 * in all entries.
767 * We can't search by SPI's since the MAY have changed (e.g. on reception
768 * of a IKE_SA_INIT response). Updating of the SPI MAY be necessary...
769 */
770 status_t retval;
771 entry_t *entry;
772 ike_sa_id_t *ike_sa_id;
773
774 ike_sa_id = ike_sa->get_id(ike_sa);
775
776 DBG2(DBG_MGR, "checkin IKE_SA");
777
778 pthread_mutex_lock(&(this->mutex));
779
780 /* look for the entry */
781 if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
782 {
783 /* ike_sa_id must be updated */
784 entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
785 /* signal waiting threads */
786 entry->checked_out = FALSE;
787 entry->message_id = -1;
788 DBG2(DBG_MGR, "check-in of IKE_SA successful.");
789 pthread_cond_signal(&(entry->condvar));
790 retval = SUCCESS;
791 }
792 else
793 {
794 DBG2(DBG_MGR, "tried to check in nonexisting IKE_SA");
795 /* this SA is no more, this REALLY should not happen */
796 retval = NOT_FOUND;
797 }
798
799 DBG2(DBG_MGR, "%d IKE_SAs in manager now",
800 this->ike_sa_list->get_count(this->ike_sa_list));
801 pthread_mutex_unlock(&(this->mutex));
802
803 charon->bus->set_sa(charon->bus, NULL);
804 return retval;
805 }
806
807
808 /**
809 * Implementation of ike_sa_manager_t.checkin_and_destroy.
810 */
811 static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
812 {
813 /* deletion is a bit complex, we must garant that no thread is waiting for
814 * this SA.
815 * We take this SA from the list, and start signaling while threads
816 * are in the condvar.
817 */
818 entry_t *entry;
819 status_t retval;
820 ike_sa_id_t *ike_sa_id;
821
822 ike_sa_id = ike_sa->get_id(ike_sa);
823 DBG2(DBG_MGR, "checkin and destroy IKE_SA");
824 charon->bus->set_sa(charon->bus, NULL);
825
826 pthread_mutex_lock(&(this->mutex));
827
828 if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
829 {
830 /* drive out waiting threads, as we are in hurry */
831 entry->driveout_waiting_threads = TRUE;
832
833 delete_entry(this, entry);
834
835 DBG2(DBG_MGR, "check-in and destroy of IKE_SA successful");
836 retval = SUCCESS;
837 }
838 else
839 {
840 DBG2(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA");
841 retval = NOT_FOUND;
842 }
843
844 pthread_mutex_unlock(&(this->mutex));
845 return retval;
846 }
847
848 /**
849 * Implementation of ike_sa_manager_t.get_half_open_count.
850 */
851 static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
852 {
853 enumerator_t *enumerator;
854 entry_t *entry;
855 int count = 0;
856
857 pthread_mutex_lock(&(this->mutex));
858 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
859 while (enumerator->enumerate(enumerator, &entry))
860 {
861 /* we check if we have a responder CONNECTING IKE_SA without checkout */
862 if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
863 entry->ike_sa->get_state(entry->ike_sa) == IKE_CONNECTING)
864 {
865 /* if we have a host, we have wait until no other uses the IKE_SA */
866 if (ip)
867 {
868 if (wait_for_entry(this, entry) && ip->ip_equals(ip,
869 entry->ike_sa->get_other_host(entry->ike_sa)))
870 {
871 count++;
872 }
873 }
874 else
875 {
876 count++;
877 }
878 }
879 }
880 enumerator->destroy(enumerator);
881
882 pthread_mutex_unlock(&(this->mutex));
883 return count;
884 }
885
886 /**
887 * Implementation of ike_sa_manager_t.destroy.
888 */
889 static void destroy(private_ike_sa_manager_t *this)
890 {
891 /* destroy all list entries */
892 enumerator_t *enumerator;
893 entry_t *entry;
894
895 pthread_mutex_lock(&(this->mutex));
896 DBG2(DBG_MGR, "going to destroy IKE_SA manager and all managed IKE_SA's");
897 /* Step 1: drive out all waiting threads */
898 DBG2(DBG_MGR, "set driveout flags for all stored IKE_SA's");
899 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
900 while (enumerator->enumerate(enumerator, &entry))
901 {
902 /* do not accept new threads, drive out waiting threads */
903 entry->driveout_new_threads = TRUE;
904 entry->driveout_waiting_threads = TRUE;
905 }
906 enumerator->destroy(enumerator);
907 DBG2(DBG_MGR, "wait for all threads to leave IKE_SA's");
908 /* Step 2: wait until all are gone */
909 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
910 while (enumerator->enumerate(enumerator, &entry))
911 {
912 while (entry->waiting_threads)
913 {
914 /* wake up all */
915 pthread_cond_broadcast(&(entry->condvar));
916 /* go sleeping until they are gone */
917 pthread_cond_wait(&(entry->condvar), &(this->mutex));
918 }
919 }
920 enumerator->destroy(enumerator);
921 DBG2(DBG_MGR, "delete all IKE_SA's");
922 /* Step 3: initiate deletion of all IKE_SAs */
923 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
924 while (enumerator->enumerate(enumerator, &entry))
925 {
926 entry->ike_sa->delete(entry->ike_sa);
927 }
928 enumerator->destroy(enumerator);
929
930 DBG2(DBG_MGR, "destroy all entries");
931 /* Step 4: destroy all entries */
932 this->ike_sa_list->destroy_function(this->ike_sa_list, (void*)entry_destroy);
933 pthread_mutex_unlock(&(this->mutex));
934
935 this->rng->destroy(this->rng);
936 this->hasher->destroy(this->hasher);
937
938 free(this);
939 }
940
941 /*
942 * Described in header.
943 */
944 ike_sa_manager_t *ike_sa_manager_create()
945 {
946 private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t);
947
948 /* assign public functions */
949 this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
950 this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
951 this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new;
952 this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message;
953 this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config;
954 this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id;
955 this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name;
956 this->public.checkout_duplicate = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))checkout_duplicate;
957 this->public.create_enumerator = (enumerator_t*(*)(ike_sa_manager_t*))create_enumerator;
958 this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
959 this->public.checkin_and_destroy = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy;
960 this->public.get_half_open_count = (int(*)(ike_sa_manager_t*,host_t*))get_half_open_count;
961
962 /* initialize private variables */
963 this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
964 if (this->hasher == NULL)
965 {
966 DBG1(DBG_MGR, "manager initialization failed, no hasher supported");
967 free(this);
968 return NULL;
969 }
970 this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
971 if (this->rng == NULL)
972 {
973 DBG1(DBG_MGR, "manager initialization failed, no RNG supported");
974 this->hasher->destroy(this->hasher);
975 free(this);
976 return NULL;
977 }
978 this->ike_sa_list = linked_list_create();
979 pthread_mutex_init(&this->mutex, NULL);
980 return &this->public;
981 }
982