Implemented quick mode protocol handling, no CHILD_SA or HASH payloads yet
[strongswan.git] / src / libcharon / sa / task_manager_v1.c
1 /*
2 * Copyright (C) 2007 Tobias Brunner
3 * Copyright (C) 2007-2010 Martin Willi
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
17 #include "task_manager_v1.h"
18
19 #include <daemon.h>
20 #include <sa/tasks/main_mode.h>
21 #include <sa/tasks/quick_mode.h>
22
23 typedef struct exchange_t exchange_t;
24
25 /**
26 * An exchange in the air, used do detect and handle retransmission
27 */
28 struct exchange_t {
29
30 /**
31 * Message ID used for this transaction
32 */
33 u_int32_t mid;
34
35 /**
36 * generated packet for retransmission
37 */
38 packet_t *packet;
39 };
40
41 typedef struct private_task_manager_t private_task_manager_t;
42
43 /**
44 * private data of the task manager
45 */
46 struct private_task_manager_t {
47
48 /**
49 * public functions
50 */
51 task_manager_v1_t public;
52
53 /**
54 * associated IKE_SA we are serving
55 */
56 ike_sa_t *ike_sa;
57
58 /**
59 * RNG to create message IDs
60 */
61 rng_t *rng;
62
63 /**
64 * Exchange we are currently handling as responder
65 */
66 struct {
67 /**
68 * Message ID of the exchange
69 */
70 u_int32_t mid;
71
72 /**
73 * packet for retransmission
74 */
75 packet_t *packet;
76
77 } responding;
78
79 /**
80 * Exchange we are currently handling as initiator
81 */
82 struct {
83 /**
84 * Message ID of the exchange
85 */
86 u_int32_t mid;
87
88 /**
89 * how many times we have retransmitted so far
90 */
91 u_int retransmitted;
92
93 /**
94 * packet for retransmission
95 */
96 packet_t *packet;
97
98 /**
99 * type of the initated exchange
100 */
101 exchange_type_t type;
102
103 } initiating;
104
105 /**
106 * List of queued tasks not yet in action
107 */
108 linked_list_t *queued_tasks;
109
110 /**
111 * List of active tasks, initiated by ourselve
112 */
113 linked_list_t *active_tasks;
114
115 /**
116 * List of tasks initiated by peer
117 */
118 linked_list_t *passive_tasks;
119
120 /**
121 * Number of times we retransmit messages before giving up
122 */
123 u_int retransmit_tries;
124
125 /**
126 * Retransmission timeout
127 */
128 double retransmit_timeout;
129
130 /**
131 * Base to calculate retransmission timeout
132 */
133 double retransmit_base;
134 };
135
136 /**
137 * flush all tasks in the task manager
138 */
139 static void flush(private_task_manager_t *this)
140 {
141 this->queued_tasks->destroy_offset(this->queued_tasks,
142 offsetof(task_t, destroy));
143 this->queued_tasks = linked_list_create();
144 this->passive_tasks->destroy_offset(this->passive_tasks,
145 offsetof(task_t, destroy));
146 this->passive_tasks = linked_list_create();
147 this->active_tasks->destroy_offset(this->active_tasks,
148 offsetof(task_t, destroy));
149 this->active_tasks = linked_list_create();
150 }
151
152 METHOD(task_manager_t, retransmit, status_t,
153 private_task_manager_t *this, u_int32_t message_id)
154 {
155 return FAILED;
156 }
157
158 /**
159 * move a task of a specific type from the queue to the active list
160 */
161 static bool activate_task(private_task_manager_t *this, task_type_t type)
162 {
163 enumerator_t *enumerator;
164 task_t *task;
165 bool found = FALSE;
166
167 enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
168 while (enumerator->enumerate(enumerator, (void**)&task))
169 {
170 if (task->get_type(task) == type)
171 {
172 DBG2(DBG_IKE, " activating %N task", task_type_names, type);
173 this->queued_tasks->remove_at(this->queued_tasks, enumerator);
174 this->active_tasks->insert_last(this->active_tasks, task);
175 found = TRUE;
176 break;
177 }
178 }
179 enumerator->destroy(enumerator);
180 return found;
181 }
182
183 METHOD(task_manager_t, initiate, status_t,
184 private_task_manager_t *this)
185 {
186 enumerator_t *enumerator;
187 task_t *task;
188 message_t *message;
189 host_t *me, *other;
190 status_t status;
191 exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED;
192
193 if (!this->rng)
194 {
195 DBG1(DBG_IKE, "no RNG supported");
196 return FAILED;
197 }
198
199 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
200 {
201 DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
202 exchange_type_names, this->initiating.type);
203 /* do not initiate if we already have a message in the air */
204 return SUCCESS;
205 }
206
207 if (this->active_tasks->get_count(this->active_tasks) == 0)
208 {
209 DBG2(DBG_IKE, "activating new tasks");
210 switch (this->ike_sa->get_state(this->ike_sa))
211 {
212 case IKE_CREATED:
213 if (activate_task(this, TASK_MAIN_MODE))
214 {
215 exchange = ID_PROT;
216 }
217 break;
218 case IKE_ESTABLISHED:
219 if (activate_task(this, TASK_QUICK_MODE))
220 {
221 exchange = QUICK_MODE;
222 }
223 break;
224 default:
225 break;
226 }
227 }
228 else
229 {
230 DBG2(DBG_IKE, "reinitiating already active tasks");
231 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
232 while (enumerator->enumerate(enumerator, (void**)&task))
233 {
234 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
235 switch (task->get_type(task))
236 {
237 case TASK_MAIN_MODE:
238 exchange = ID_PROT;
239 break;
240 case TASK_QUICK_MODE:
241 exchange = QUICK_MODE;
242 break;
243 default:
244 continue;
245 }
246 break;
247 }
248 enumerator->destroy(enumerator);
249 }
250
251 if (exchange == EXCHANGE_TYPE_UNDEFINED)
252 {
253 DBG2(DBG_IKE, "nothing to initiate");
254 /* nothing to do yet... */
255 return SUCCESS;
256 }
257
258 me = this->ike_sa->get_my_host(this->ike_sa);
259 other = this->ike_sa->get_other_host(this->ike_sa);
260
261 message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
262 if (exchange != ID_PROT)
263 {
264 this->rng->get_bytes(this->rng, sizeof(this->initiating.mid),
265 (void*)&this->initiating.mid);
266 message->set_message_id(message, this->initiating.mid);
267 }
268 message->set_source(message, me->clone(me));
269 message->set_destination(message, other->clone(other));
270 message->set_exchange_type(message, exchange);
271 this->initiating.type = exchange;
272 this->initiating.retransmitted = 0;
273
274 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
275 while (enumerator->enumerate(enumerator, (void*)&task))
276 {
277 switch (task->build(task, message))
278 {
279 case SUCCESS:
280 /* task completed, remove it */
281 this->active_tasks->remove_at(this->active_tasks, enumerator);
282 task->destroy(task);
283 break;
284 case NEED_MORE:
285 /* processed, but task needs another exchange */
286 break;
287 case FAILED:
288 default:
289 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
290 {
291 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
292 }
293 /* FALL */
294 case DESTROY_ME:
295 /* critical failure, destroy IKE_SA */
296 enumerator->destroy(enumerator);
297 message->destroy(message);
298 flush(this);
299 return DESTROY_ME;
300 }
301 }
302 enumerator->destroy(enumerator);
303
304 /* update exchange type if a task changed it */
305 this->initiating.type = message->get_exchange_type(message);
306
307 status = this->ike_sa->generate_message(this->ike_sa, message,
308 &this->initiating.packet);
309 if (status != SUCCESS)
310 {
311 /* message generation failed. There is nothing more to do than to
312 * close the SA */
313 message->destroy(message);
314 flush(this);
315 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
316 return DESTROY_ME;
317 }
318 message->destroy(message);
319
320 charon->sender->send(charon->sender,
321 this->initiating.packet->clone(this->initiating.packet));
322
323 return SUCCESS;
324 }
325
326 /**
327 * handle exchange collisions
328 */
329 static bool handle_collisions(private_task_manager_t *this, task_t *task)
330 {
331 return FALSE;
332 }
333
334 /**
335 * build a response depending on the "passive" task list
336 */
337 static status_t build_response(private_task_manager_t *this, message_t *request)
338 {
339 enumerator_t *enumerator;
340 task_t *task;
341 message_t *message;
342 host_t *me, *other;
343 bool delete = FALSE;
344 status_t status;
345
346 me = request->get_destination(request);
347 other = request->get_source(request);
348
349 message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
350 message->set_exchange_type(message, request->get_exchange_type(request));
351 /* send response along the path the request came in */
352 message->set_source(message, me->clone(me));
353 message->set_destination(message, other->clone(other));
354 message->set_message_id(message, request->get_message_id(request));
355 message->set_request(message, FALSE);
356
357 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
358 while (enumerator->enumerate(enumerator, (void*)&task))
359 {
360 switch (task->build(task, message))
361 {
362 case SUCCESS:
363 /* task completed, remove it */
364 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
365 if (!handle_collisions(this, task))
366 {
367 task->destroy(task);
368 }
369 break;
370 case NEED_MORE:
371 /* processed, but task needs another exchange */
372 if (handle_collisions(this, task))
373 {
374 this->passive_tasks->remove_at(this->passive_tasks,
375 enumerator);
376 }
377 break;
378 case FAILED:
379 default:
380 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
381 /* FALL */
382 case DESTROY_ME:
383 /* destroy IKE_SA, but SEND response first */
384 delete = TRUE;
385 break;
386 }
387 if (delete)
388 {
389 break;
390 }
391 }
392 enumerator->destroy(enumerator);
393
394 /* message complete, send it */
395 DESTROY_IF(this->responding.packet);
396 this->responding.packet = NULL;
397 status = this->ike_sa->generate_message(this->ike_sa, message,
398 &this->responding.packet);
399 message->destroy(message);
400 if (status != SUCCESS)
401 {
402 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
403 return DESTROY_ME;
404 }
405
406 charon->sender->send(charon->sender,
407 this->responding.packet->clone(this->responding.packet));
408 if (delete)
409 {
410 return DESTROY_ME;
411 }
412 return SUCCESS;
413 }
414
415 /**
416 * handle an incoming request message
417 */
418 static status_t process_request(private_task_manager_t *this,
419 message_t *message)
420 {
421 enumerator_t *enumerator;
422 task_t *task = NULL;
423
424 if (this->passive_tasks->get_count(this->passive_tasks) == 0)
425 { /* create tasks depending on request type, if not already some queued */
426 switch (message->get_exchange_type(message))
427 {
428 case ID_PROT:
429 task = (task_t *)main_mode_create(this->ike_sa, FALSE);
430 this->passive_tasks->insert_last(this->passive_tasks, task);
431 break;
432 case AGGRESSIVE:
433 /* TODO-IKEv1: agressive mode */
434 return FAILED;
435 case QUICK_MODE:
436 task = (task_t *)quick_mode_create(this->ike_sa, NULL,
437 NULL, NULL);
438 this->passive_tasks->insert_last(this->passive_tasks, task);
439 break;
440 case INFORMATIONAL_V1:
441 /* TODO-IKEv1: informational */
442 return FAILED;
443 default:
444 return FAILED;
445 }
446 }
447 /* let the tasks process the message */
448 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
449 while (enumerator->enumerate(enumerator, (void*)&task))
450 {
451 switch (task->process(task, message))
452 {
453 case SUCCESS:
454 /* task completed, remove it */
455 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
456 task->destroy(task);
457 enumerator->destroy(enumerator);
458 return SUCCESS;
459 case NEED_MORE:
460 /* processed, but task needs at least another call to build() */
461 break;
462 case FAILED:
463 default:
464 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
465 /* FALL */
466 case DESTROY_ME:
467 /* critical failure, destroy IKE_SA */
468 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
469 enumerator->destroy(enumerator);
470 task->destroy(task);
471 return DESTROY_ME;
472 }
473 }
474 enumerator->destroy(enumerator);
475
476 return build_response(this, message);
477 }
478
479 /**
480 * handle an incoming response message
481 */
482 static status_t process_response(private_task_manager_t *this,
483 message_t *message)
484 {
485 enumerator_t *enumerator;
486 task_t *task;
487
488 if (message->get_exchange_type(message) != this->initiating.type)
489 {
490 DBG1(DBG_IKE, "received %N response, but expected %N",
491 exchange_type_names, message->get_exchange_type(message),
492 exchange_type_names, this->initiating.type);
493 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
494 return DESTROY_ME;
495 }
496
497 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
498 while (enumerator->enumerate(enumerator, (void*)&task))
499 {
500 switch (task->process(task, message))
501 {
502 case SUCCESS:
503 /* task completed, remove it */
504 this->active_tasks->remove_at(this->active_tasks, enumerator);
505 task->destroy(task);
506 break;
507 case NEED_MORE:
508 /* processed, but task needs another exchange */
509 break;
510 case FAILED:
511 default:
512 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
513 /* FALL */
514 case DESTROY_ME:
515 /* critical failure, destroy IKE_SA */
516 this->active_tasks->remove_at(this->active_tasks, enumerator);
517 enumerator->destroy(enumerator);
518 task->destroy(task);
519 return DESTROY_ME;
520 }
521 }
522 enumerator->destroy(enumerator);
523
524 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
525 this->initiating.packet->destroy(this->initiating.packet);
526 this->initiating.packet = NULL;
527
528 return initiate(this);
529 }
530
531 METHOD(task_manager_t, process_message, status_t,
532 private_task_manager_t *this, message_t *msg)
533 {
534 u_int32_t hash, mid;
535 host_t *me, *other;
536
537 mid = msg->get_message_id(msg);
538 hash = chunk_hash(msg->get_packet_data(msg));
539
540 /* TODO-IKEv1: update hosts more selectively */
541 me = msg->get_destination(msg);
542 other = msg->get_source(msg);
543
544 if ((mid && mid == this->initiating.mid) ||
545 (this->initiating.mid == 0 &&
546 this->active_tasks->get_count(this->active_tasks)))
547 {
548 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
549 charon->bus->message(charon->bus, msg, FALSE);
550 if (process_response(this, msg) != SUCCESS)
551 {
552 flush(this);
553 return DESTROY_ME;
554 }
555 }
556 else
557 {
558 if ((mid && mid == this->responding.mid) ||
559 hash == this->responding.mid)
560 {
561 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
562 "retransmitting response", mid);
563 charon->sender->send(charon->sender,
564 this->responding.packet->clone(this->responding.packet));
565 return SUCCESS;
566 }
567 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
568 charon->bus->message(charon->bus, msg, TRUE);
569 if (process_request(this, msg) != SUCCESS)
570 {
571 flush(this);
572 return DESTROY_ME;
573 }
574
575 if (!mid)
576 {
577 mid = hash;
578 }
579 this->responding.mid = mid;
580 }
581 return SUCCESS;
582 }
583
584 METHOD(task_manager_t, queue_task, void,
585 private_task_manager_t *this, task_t *task)
586 {
587 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
588 this->queued_tasks->insert_last(this->queued_tasks, task);
589 }
590
591 METHOD(task_manager_t, adopt_tasks, void,
592 private_task_manager_t *this, task_manager_t *other_public)
593 {
594 private_task_manager_t *other = (private_task_manager_t*)other_public;
595 task_t *task;
596
597 /* move queued tasks from other to this */
598 while (other->queued_tasks->remove_last(other->queued_tasks,
599 (void**)&task) == SUCCESS)
600 {
601 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
602 task->migrate(task, this->ike_sa);
603 this->queued_tasks->insert_first(this->queued_tasks, task);
604 }
605 }
606
607 METHOD(task_manager_t, busy, bool,
608 private_task_manager_t *this)
609 {
610 return (this->active_tasks->get_count(this->active_tasks) > 0);
611 }
612
613 METHOD(task_manager_t, incr_mid, void,
614 private_task_manager_t *this, bool initiate)
615 {
616 }
617
618 METHOD(task_manager_t, reset, void,
619 private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
620 {
621 }
622
623 METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
624 private_task_manager_t *this, task_queue_t queue)
625 {
626 switch (queue)
627 {
628 case TASK_QUEUE_ACTIVE:
629 return this->active_tasks->create_enumerator(this->active_tasks);
630 case TASK_QUEUE_PASSIVE:
631 return this->passive_tasks->create_enumerator(this->passive_tasks);
632 case TASK_QUEUE_QUEUED:
633 return this->queued_tasks->create_enumerator(this->queued_tasks);
634 default:
635 return enumerator_create_empty();
636 }
637 }
638
639 METHOD(task_manager_t, destroy, void,
640 private_task_manager_t *this)
641 {
642 flush(this);
643
644 this->active_tasks->destroy(this->active_tasks);
645 this->queued_tasks->destroy(this->queued_tasks);
646 this->passive_tasks->destroy(this->passive_tasks);
647
648 DESTROY_IF(this->responding.packet);
649 DESTROY_IF(this->initiating.packet);
650 DESTROY_IF(this->rng);
651 free(this);
652 }
653
654 /*
655 * see header file
656 */
657 task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
658 {
659 private_task_manager_t *this;
660
661 INIT(this,
662 .public = {
663 .task_manager = {
664 .process_message = _process_message,
665 .queue_task = _queue_task,
666 .initiate = _initiate,
667 .retransmit = _retransmit,
668 .incr_mid = _incr_mid,
669 .reset = _reset,
670 .adopt_tasks = _adopt_tasks,
671 .busy = _busy,
672 .create_task_enumerator = _create_task_enumerator,
673 .destroy = _destroy,
674 },
675 },
676 .ike_sa = ike_sa,
677 .initiating.type = EXCHANGE_TYPE_UNDEFINED,
678 .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
679 .queued_tasks = linked_list_create(),
680 .active_tasks = linked_list_create(),
681 .passive_tasks = linked_list_create(),
682 .retransmit_tries = lib->settings->get_int(lib->settings,
683 "charon.retransmit_tries", RETRANSMIT_TRIES),
684 .retransmit_timeout = lib->settings->get_double(lib->settings,
685 "charon.retransmit_timeout", RETRANSMIT_TIMEOUT),
686 .retransmit_base = lib->settings->get_double(lib->settings,
687 "charon.retransmit_base", RETRANSMIT_BASE),
688 );
689
690 return &this->public;
691 }