2c15ac765ebbf5aa208e02cdd9ed41f3a3c5d6db
[strongswan.git] / src / charon / sa / tasks / ike_auth.c
1 /*
2 * Copyright (C) 2005-2009 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
17 #include "ike_auth.h"
18
19 #include <string.h>
20
21 #include <daemon.h>
22 #include <encoding/payloads/id_payload.h>
23 #include <encoding/payloads/auth_payload.h>
24 #include <encoding/payloads/eap_payload.h>
25 #include <encoding/payloads/nonce_payload.h>
26 #include <sa/authenticators/eap_authenticator.h>
27
28 typedef struct private_ike_auth_t private_ike_auth_t;
29
30 /**
31 * Private members of a ike_auth_t task.
32 */
33 struct private_ike_auth_t {
34
35 /**
36 * Public methods and task_t interface.
37 */
38 ike_auth_t public;
39
40 /**
41 * Assigned IKE_SA.
42 */
43 ike_sa_t *ike_sa;
44
45 /**
46 * Are we the initiator?
47 */
48 bool initiator;
49
50 /**
51 * Nonce chosen by us in ike_init
52 */
53 chunk_t my_nonce;
54
55 /**
56 * Nonce chosen by peer in ike_init
57 */
58 chunk_t other_nonce;
59
60 /**
61 * IKE_SA_INIT message sent by us
62 */
63 packet_t *my_packet;
64
65 /**
66 * IKE_SA_INIT message sent by peer
67 */
68 packet_t *other_packet;
69
70 /**
71 * completed authentication configs initiated by us (auth_cfg_t)
72 */
73 linked_list_t *my_cfgs;
74
75 /**
76 * completed authentication configs initiated by other (auth_cfg_t)
77 */
78 linked_list_t *other_cfgs;;
79
80 /**
81 * currently active authenticator, to authenticate us
82 */
83 authenticator_t *my_auth;
84
85 /**
86 * currently active authenticator, to authenticate peer
87 */
88 authenticator_t *other_auth;
89
90 /**
91 * peer_cfg candidates, ordered by priority
92 */
93 linked_list_t *candidates;
94
95 /**
96 * selected peer config (might change when using multiple authentications)
97 */
98 peer_cfg_t *peer_cfg;
99
100 /**
101 * have we planned an(other) authentication exchange?
102 */
103 bool do_another_auth;
104
105 /**
106 * has the peer announced another authentication exchange?
107 */
108 bool expect_another_auth;
109
110 /**
111 * should we send a AUTHENTICATION_FAILED notify?
112 */
113 bool authentication_failed;
114 };
115
116 /**
117 * check if multiple authentication extension is enabled, configuration-wise
118 */
119 static bool multiple_auth_enabled()
120 {
121 return lib->settings->get_bool(lib->settings,
122 "charon.multiple_authentication", TRUE);
123 }
124
125 /**
126 * collect the needed information in the IKE_SA_INIT exchange from our message
127 */
128 static status_t collect_my_init_data(private_ike_auth_t *this,
129 message_t *message)
130 {
131 nonce_payload_t *nonce;
132
133 /* get the nonce that was generated in ike_init */
134 nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
135 if (nonce == NULL)
136 {
137 return FAILED;
138 }
139 this->my_nonce = nonce->get_nonce(nonce);
140
141 /* pre-generate the message, keep a copy */
142 if (this->ike_sa->generate_message(this->ike_sa, message,
143 &this->my_packet) != SUCCESS)
144 {
145 return FAILED;
146 }
147 return NEED_MORE;
148 }
149
150 /**
151 * collect the needed information in the IKE_SA_INIT exchange from others message
152 */
153 static status_t collect_other_init_data(private_ike_auth_t *this,
154 message_t *message)
155 {
156 /* we collect the needed information in the IKE_SA_INIT exchange */
157 nonce_payload_t *nonce;
158
159 /* get the nonce that was generated in ike_init */
160 nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
161 if (nonce == NULL)
162 {
163 return FAILED;
164 }
165 this->other_nonce = nonce->get_nonce(nonce);
166
167 /* keep a copy of the received packet */
168 this->other_packet = message->get_packet(message);
169 return NEED_MORE;
170 }
171
172 /**
173 * Get the next authentication configuration
174 */
175 static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local)
176 {
177 enumerator_t *e1, *e2;
178 auth_cfg_t *c1, *c2, *next = NULL;
179
180 /* find an available config not already done */
181 e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, local);
182 while (e1->enumerate(e1, &c1))
183 {
184 bool found = FALSE;
185
186 if (local)
187 {
188 e2 = this->my_cfgs->create_enumerator(this->my_cfgs);
189 }
190 else
191 {
192 e2 = this->other_cfgs->create_enumerator(this->other_cfgs);
193 }
194 while (e2->enumerate(e2, &c2))
195 {
196 if (c2->complies(c2, c1, FALSE))
197 {
198 found = TRUE;
199 break;
200 }
201 }
202 e2->destroy(e2);
203 if (!found)
204 {
205 next = c1;
206 break;
207 }
208 }
209 e1->destroy(e1);
210 return next;
211 }
212
213 /**
214 * Check if we have should initiate another authentication round
215 */
216 static bool do_another_auth(private_ike_auth_t *this)
217 {
218 bool do_another = FALSE;
219 enumerator_t *done, *todo;
220 auth_cfg_t *done_cfg, *todo_cfg;
221
222 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
223 {
224 return FALSE;
225 }
226
227 done = this->my_cfgs->create_enumerator(this->my_cfgs);
228 todo = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, TRUE);
229 while (todo->enumerate(todo, &todo_cfg))
230 {
231 if (!done->enumerate(done, &done_cfg))
232 {
233 done_cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
234 }
235 if (!done_cfg->complies(done_cfg, todo_cfg, FALSE))
236 {
237 do_another = TRUE;
238 break;
239 }
240 }
241 done->destroy(done);
242 todo->destroy(todo);
243 return do_another;
244 }
245
246 /**
247 * Get peer configuration candidates from backends
248 */
249 static bool load_cfg_candidates(private_ike_auth_t *this)
250 {
251 enumerator_t *enumerator;
252 peer_cfg_t *peer_cfg;
253 host_t *me, *other;
254 identification_t *my_id, *other_id;
255
256 me = this->ike_sa->get_my_host(this->ike_sa);
257 other = this->ike_sa->get_other_host(this->ike_sa);
258 my_id = this->ike_sa->get_my_id(this->ike_sa);
259 other_id = this->ike_sa->get_other_id(this->ike_sa);
260
261 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
262 me, other, my_id, other_id);
263 while (enumerator->enumerate(enumerator, &peer_cfg))
264 {
265 peer_cfg->get_ref(peer_cfg);
266 if (this->peer_cfg == NULL)
267 { /* best match */
268 this->peer_cfg = peer_cfg;
269 this->ike_sa->set_peer_cfg(this->ike_sa, peer_cfg);
270 }
271 else
272 {
273 this->candidates->insert_last(this->candidates, peer_cfg);
274 }
275 }
276 enumerator->destroy(enumerator);
277 if (this->peer_cfg)
278 {
279 DBG1(DBG_CFG, "selected peer config '%s'",
280 this->peer_cfg->get_name(this->peer_cfg));
281 return TRUE;
282 }
283 DBG1(DBG_CFG, "no matching peer config found");
284 return FALSE;
285 }
286
287 /**
288 * update the current peer candidate if necessary, using candidates
289 */
290 static bool update_cfg_candidates(private_ike_auth_t *this, bool strict)
291 {
292 do
293 {
294 if (this->peer_cfg)
295 {
296 bool complies = TRUE;
297 enumerator_t *e1, *e2, *tmp;
298 auth_cfg_t *c1, *c2;
299
300 e1 = this->other_cfgs->create_enumerator(this->other_cfgs);
301 e2 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
302
303 if (strict)
304 { /* swap lists in strict mode: all configured rounds must be
305 * fulfilled. If !strict, we check only the rounds done so far. */
306 tmp = e1;
307 e1 = e2;
308 e2 = tmp;
309 }
310 while (e1->enumerate(e1, &c1))
311 {
312 /* check if done authentications comply to configured ones */
313 if ((!e2->enumerate(e2, &c2)) ||
314 (!strict && !c1->complies(c1, c2, TRUE)) ||
315 (strict && !c2->complies(c2, c1, TRUE)))
316 {
317 complies = FALSE;
318 break;
319 }
320 }
321 e1->destroy(e1);
322 e2->destroy(e2);
323 if (complies)
324 {
325 break;
326 }
327 DBG1(DBG_CFG, "selected peer config '%s' inacceptable",
328 this->peer_cfg->get_name(this->peer_cfg));
329 this->peer_cfg->destroy(this->peer_cfg);
330 }
331 if (this->candidates->remove_first(this->candidates,
332 (void**)&this->peer_cfg) != SUCCESS)
333 {
334 DBG1(DBG_CFG, "no alternative config found");
335 this->peer_cfg = NULL;
336 }
337 else
338 {
339 DBG1(DBG_CFG, "switching to peer config '%s'",
340 this->peer_cfg->get_name(this->peer_cfg));
341 this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
342 }
343 }
344 while (this->peer_cfg);
345
346 return this->peer_cfg != NULL;
347 }
348
349 /**
350 * Implementation of task_t.build for initiator
351 */
352 static status_t build_i(private_ike_auth_t *this, message_t *message)
353 {
354 auth_cfg_t *cfg;
355
356 if (message->get_exchange_type(message) == IKE_SA_INIT)
357 {
358 return collect_my_init_data(this, message);
359 }
360
361 if (this->peer_cfg == NULL)
362 {
363 this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
364 this->peer_cfg->get_ref(this->peer_cfg);
365 }
366
367 if (message->get_message_id(message) == 1 &&
368 this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
369 { /* in the first IKE_AUTH, indicate support for multiple authentication */
370 message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED, chunk_empty);
371 }
372
373 if (!this->do_another_auth && !this->my_auth)
374 { /* we have done our rounds */
375 return NEED_MORE;
376 }
377
378 /* check if an authenticator is in progress */
379 if (this->my_auth == NULL)
380 {
381 identification_t *id;
382 id_payload_t *id_payload;
383
384 /* clean up authentication config from a previous round */
385 cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
386 cfg->purge(cfg, TRUE);
387
388 /* add (optional) IDr */
389 cfg = get_auth_cfg(this, FALSE);
390 if (cfg)
391 {
392 id = cfg->get(cfg, AUTH_RULE_IDENTITY);
393 if (id && !id->contains_wildcards(id))
394 {
395 this->ike_sa->set_other_id(this->ike_sa, id->clone(id));
396 id_payload = id_payload_create_from_identification(
397 ID_RESPONDER, id);
398 message->add_payload(message, (payload_t*)id_payload);
399 }
400 }
401 /* add IDi */
402 cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
403 cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
404 id = cfg->get(cfg, AUTH_RULE_IDENTITY);
405 if (!id)
406 {
407 DBG1(DBG_CFG, "configuration misses IDi");
408 return FAILED;
409 }
410 this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
411 id_payload = id_payload_create_from_identification(ID_INITIATOR, id);
412 message->add_payload(message, (payload_t*)id_payload);
413
414 /* build authentication data */
415 this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
416 this->other_nonce, this->my_nonce,
417 this->other_packet->get_data(this->other_packet),
418 this->my_packet->get_data(this->my_packet));
419 if (!this->my_auth)
420 {
421 return FAILED;
422 }
423 }
424 switch (this->my_auth->build(this->my_auth, message))
425 {
426 case SUCCESS:
427 /* authentication step complete, reset authenticator */
428 cfg = auth_cfg_create();
429 cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), TRUE);
430 this->my_cfgs->insert_last(this->my_cfgs, cfg);
431 this->my_auth->destroy(this->my_auth);
432 this->my_auth = NULL;
433 break;
434 case NEED_MORE:
435 break;
436 default:
437 return FAILED;
438 }
439
440 /* check for additional authentication rounds */
441 if (do_another_auth(this))
442 {
443 if (message->get_payload(message, AUTHENTICATION))
444 {
445 message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
446 }
447 }
448 else
449 {
450 this->do_another_auth = FALSE;
451 }
452 return NEED_MORE;
453 }
454
455 /**
456 * Implementation of task_t.process for responder
457 */
458 static status_t process_r(private_ike_auth_t *this, message_t *message)
459 {
460 auth_cfg_t *cfg, *cand;
461 id_payload_t *id_payload;
462 identification_t *id;
463
464 if (message->get_exchange_type(message) == IKE_SA_INIT)
465 {
466 return collect_other_init_data(this, message);
467 }
468
469 if (this->my_auth == NULL && this->do_another_auth)
470 {
471 /* handle (optional) IDr payload, apply proposed identity */
472 id_payload = (id_payload_t*)message->get_payload(message, ID_RESPONDER);
473 if (id_payload)
474 {
475 id = id_payload->get_identification(id_payload);
476 }
477 else
478 {
479 id = identification_create_from_encoding(ID_ANY, chunk_empty);
480 }
481 this->ike_sa->set_my_id(this->ike_sa, id);
482 }
483
484 if (!this->expect_another_auth)
485 {
486 return NEED_MORE;
487 }
488 if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED))
489 {
490 this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
491 }
492
493 if (this->other_auth == NULL)
494 {
495 /* handle IDi payload */
496 id_payload = (id_payload_t*)message->get_payload(message, ID_INITIATOR);
497 if (!id_payload)
498 {
499 DBG1(DBG_IKE, "IDi payload missing");
500 return FAILED;
501 }
502 id = id_payload->get_identification(id_payload);
503 this->ike_sa->set_other_id(this->ike_sa, id);
504 cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
505 cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
506
507 if (this->peer_cfg == NULL)
508 {
509 if (!load_cfg_candidates(this))
510 {
511 this->authentication_failed = TRUE;
512 return NEED_MORE;
513 }
514 }
515 if (message->get_payload(message, AUTHENTICATION) == NULL)
516 { /* before authenticating with EAP, we need a EAP config */
517 cand = get_auth_cfg(this, FALSE);
518 while (!cand || (
519 (uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK &&
520 (uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0))
521 { /* peer requested EAP, but current config does not match */
522 this->peer_cfg->destroy(this->peer_cfg);
523 this->peer_cfg = NULL;
524 if (!update_cfg_candidates(this, FALSE))
525 {
526 this->authentication_failed = TRUE;
527 return NEED_MORE;
528 }
529 cand = get_auth_cfg(this, FALSE);
530 }
531 cfg->merge(cfg, cand, TRUE);
532 }
533
534 /* verify authentication data */
535 this->other_auth = authenticator_create_verifier(this->ike_sa,
536 message, this->other_nonce, this->my_nonce,
537 this->other_packet->get_data(this->other_packet),
538 this->my_packet->get_data(this->my_packet));
539 if (!this->other_auth)
540 {
541 this->authentication_failed = TRUE;
542 return NEED_MORE;
543 }
544 }
545 switch (this->other_auth->process(this->other_auth, message))
546 {
547 case SUCCESS:
548 this->other_auth->destroy(this->other_auth);
549 this->other_auth = NULL;
550 break;
551 case NEED_MORE:
552 if (message->get_payload(message, AUTHENTICATION))
553 { /* AUTH verification successful, but another build() needed */
554 break;
555 }
556 return NEED_MORE;
557 default:
558 this->authentication_failed = TRUE;
559 return NEED_MORE;
560 }
561
562 /* store authentication information */
563 cfg = auth_cfg_create();
564 cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
565 this->other_cfgs->insert_last(this->other_cfgs, cfg);
566
567 /* another auth round done, invoke authorize hook */
568 if (!charon->bus->authorize(charon->bus, this->other_cfgs, FALSE))
569 {
570 DBG1(DBG_IKE, "round %d authorization hook forbids IKE_SA, cancelling",
571 this->other_cfgs->get_count(this->other_cfgs));
572 this->authentication_failed = TRUE;
573 return NEED_MORE;
574 }
575
576 if (!update_cfg_candidates(this, FALSE))
577 {
578 this->authentication_failed = TRUE;
579 return NEED_MORE;
580 }
581
582 if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
583 {
584 this->expect_another_auth = FALSE;
585 if (!update_cfg_candidates(this, TRUE))
586 {
587 this->authentication_failed = TRUE;
588 return NEED_MORE;
589 }
590 }
591 return NEED_MORE;
592 }
593
594 /**
595 * Implementation of task_t.build for responder
596 */
597 static status_t build_r(private_ike_auth_t *this, message_t *message)
598 {
599 auth_cfg_t *cfg;
600
601 if (message->get_exchange_type(message) == IKE_SA_INIT)
602 {
603 if (multiple_auth_enabled())
604 {
605 message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
606 chunk_empty);
607 }
608 return collect_my_init_data(this, message);
609 }
610
611 if (this->authentication_failed || this->peer_cfg == NULL)
612 {
613 message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
614 return FAILED;
615 }
616
617 if (this->my_auth == NULL && this->do_another_auth)
618 {
619 identification_t *id, *id_cfg;
620 id_payload_t *id_payload;
621
622 /* add IDr */
623 cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
624 cfg->purge(cfg, TRUE);
625 cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
626
627 id_cfg = cfg->get(cfg, AUTH_RULE_IDENTITY);
628 id = this->ike_sa->get_my_id(this->ike_sa);
629 if (id->get_type(id) == ID_ANY)
630 { /* no IDr received, apply configured ID */
631 if (!id_cfg || id_cfg->contains_wildcards(id_cfg))
632 {
633 DBG1(DBG_CFG, "IDr not configured and negotiation failed");
634 message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
635 chunk_empty);
636 return FAILED;
637 }
638 this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg));
639 id = id_cfg;
640 }
641 else
642 { /* IDr received, check if it matches configuration */
643 if (id_cfg && !id->matches(id, id_cfg))
644 {
645 DBG1(DBG_CFG, "received IDr %Y, but require %Y", id, id_cfg);
646 message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
647 chunk_empty);
648 return FAILED;
649 }
650 }
651
652 id_payload = id_payload_create_from_identification(ID_RESPONDER, id);
653 message->add_payload(message, (payload_t*)id_payload);
654
655 /* build authentication data */
656 this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
657 this->other_nonce, this->my_nonce,
658 this->other_packet->get_data(this->other_packet),
659 this->my_packet->get_data(this->my_packet));
660 if (!this->my_auth)
661 {
662 message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
663 return FAILED;
664 }
665 }
666
667 if (this->other_auth)
668 {
669 switch (this->other_auth->build(this->other_auth, message))
670 {
671 case SUCCESS:
672 this->other_auth->destroy(this->other_auth);
673 this->other_auth = NULL;
674 break;
675 case NEED_MORE:
676 break;
677 default:
678 if (!message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
679 { /* skip AUTHENTICATION_FAILED if we have EAP_FAILURE */
680 message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
681 chunk_empty);
682 }
683 return FAILED;
684 }
685 }
686 if (this->my_auth)
687 {
688 switch (this->my_auth->build(this->my_auth, message))
689 {
690 case SUCCESS:
691 cfg = auth_cfg_create();
692 cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
693 TRUE);
694 this->my_cfgs->insert_last(this->my_cfgs, cfg);
695 this->my_auth->destroy(this->my_auth);
696 this->my_auth = NULL;
697 break;
698 case NEED_MORE:
699 break;
700 default:
701 message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
702 chunk_empty);
703 return FAILED;
704 }
705 }
706
707 /* check for additional authentication rounds */
708 if (do_another_auth(this))
709 {
710 message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
711 }
712 else
713 {
714 this->do_another_auth = FALSE;
715 }
716 if (!this->do_another_auth && !this->expect_another_auth)
717 {
718 if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
719 this->ike_sa))
720 {
721 DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
722 message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
723 chunk_empty);
724 return FAILED;
725 }
726 if (!charon->bus->authorize(charon->bus, this->other_cfgs, TRUE))
727 {
728 DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
729 message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
730 chunk_empty);
731 return FAILED;
732 }
733 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
734 this->ike_sa->get_name(this->ike_sa),
735 this->ike_sa->get_unique_id(this->ike_sa),
736 this->ike_sa->get_my_host(this->ike_sa),
737 this->ike_sa->get_my_id(this->ike_sa),
738 this->ike_sa->get_other_host(this->ike_sa),
739 this->ike_sa->get_other_id(this->ike_sa));
740 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
741 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
742 return SUCCESS;
743 }
744 return NEED_MORE;
745 }
746
747 /**
748 * Implementation of task_t.process for initiator
749 */
750 static status_t process_i(private_ike_auth_t *this, message_t *message)
751 {
752 enumerator_t *enumerator;
753 payload_t *payload;
754 auth_cfg_t *cfg;
755
756 if (message->get_exchange_type(message) == IKE_SA_INIT)
757 {
758 if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) &&
759 multiple_auth_enabled())
760 {
761 this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
762 }
763 return collect_other_init_data(this, message);
764 }
765
766 enumerator = message->create_payload_enumerator(message);
767 while (enumerator->enumerate(enumerator, &payload))
768 {
769 if (payload->get_type(payload) == NOTIFY)
770 {
771 notify_payload_t *notify = (notify_payload_t*)payload;
772 notify_type_t type = notify->get_notify_type(notify);
773
774 switch (type)
775 {
776 case NO_PROPOSAL_CHOSEN:
777 case SINGLE_PAIR_REQUIRED:
778 case NO_ADDITIONAL_SAS:
779 case INTERNAL_ADDRESS_FAILURE:
780 case FAILED_CP_REQUIRED:
781 case TS_UNACCEPTABLE:
782 case INVALID_SELECTORS:
783 /* these are errors, but are not critical as only the
784 * CHILD_SA won't get build, but IKE_SA establishes anyway */
785 break;
786 case MOBIKE_SUPPORTED:
787 case ADDITIONAL_IP4_ADDRESS:
788 case ADDITIONAL_IP6_ADDRESS:
789 /* handled in ike_mobike task */
790 break;
791 case AUTH_LIFETIME:
792 /* handled in ike_auth_lifetime task */
793 break;
794 case ME_ENDPOINT:
795 /* handled in ike_me task */
796 break;
797 default:
798 {
799 if (type < 16383)
800 {
801 DBG1(DBG_IKE, "received %N notify error",
802 notify_type_names, type);
803 enumerator->destroy(enumerator);
804 return FAILED;
805 }
806 DBG2(DBG_IKE, "received %N notify",
807 notify_type_names, type);
808 break;
809 }
810 }
811 }
812 }
813 enumerator->destroy(enumerator);
814
815 if (this->my_auth)
816 {
817 switch (this->my_auth->process(this->my_auth, message))
818 {
819 case SUCCESS:
820 cfg = auth_cfg_create();
821 cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
822 TRUE);
823 this->my_cfgs->insert_last(this->my_cfgs, cfg);
824 this->my_auth->destroy(this->my_auth);
825 this->my_auth = NULL;
826 this->do_another_auth = do_another_auth(this);
827 break;
828 case NEED_MORE:
829 break;
830 default:
831 return FAILED;
832 }
833 }
834
835 if (this->expect_another_auth)
836 {
837 if (this->other_auth == NULL)
838 {
839 id_payload_t *id_payload;
840 identification_t *id;
841
842 /* responder is not allowed to do EAP */
843 if (!message->get_payload(message, AUTHENTICATION))
844 {
845 DBG1(DBG_IKE, "AUTH payload missing");
846 return FAILED;
847 }
848
849 /* handle IDr payload */
850 id_payload = (id_payload_t*)message->get_payload(message,
851 ID_RESPONDER);
852 if (!id_payload)
853 {
854 DBG1(DBG_IKE, "IDr payload missing");
855 return FAILED;
856 }
857 id = id_payload->get_identification(id_payload);
858 this->ike_sa->set_other_id(this->ike_sa, id);
859 cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
860 cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
861
862 /* verify authentication data */
863 this->other_auth = authenticator_create_verifier(this->ike_sa,
864 message, this->other_nonce, this->my_nonce,
865 this->other_packet->get_data(this->other_packet),
866 this->my_packet->get_data(this->my_packet));
867 if (!this->other_auth)
868 {
869 return FAILED;
870 }
871 }
872 switch (this->other_auth->process(this->other_auth, message))
873 {
874 case SUCCESS:
875 break;
876 case NEED_MORE:
877 return NEED_MORE;
878 default:
879 return FAILED;
880 }
881 /* store authentication information, reset authenticator */
882 cfg = auth_cfg_create();
883 cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
884 this->other_cfgs->insert_last(this->other_cfgs, cfg);
885 this->other_auth->destroy(this->other_auth);
886 this->other_auth = NULL;
887
888 /* another auth round done, invoke authorize hook */
889 if (!charon->bus->authorize(charon->bus, this->other_cfgs, FALSE))
890 {
891 DBG1(DBG_IKE, "round %d authorization forbids IKE_SA, cancelling",
892 this->other_cfgs->get_count(this->other_cfgs));
893 return FAILED;
894 }
895 }
896
897 if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
898 {
899 this->expect_another_auth = FALSE;
900 }
901 if (!this->expect_another_auth && !this->do_another_auth && !this->my_auth)
902 {
903 if (!update_cfg_candidates(this, TRUE))
904 {
905 return FAILED;
906 }
907 if (!charon->bus->authorize(charon->bus, this->other_cfgs, TRUE))
908 {
909 DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
910 return FAILED;
911 }
912 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
913 this->ike_sa->get_name(this->ike_sa),
914 this->ike_sa->get_unique_id(this->ike_sa),
915 this->ike_sa->get_my_host(this->ike_sa),
916 this->ike_sa->get_my_id(this->ike_sa),
917 this->ike_sa->get_other_host(this->ike_sa),
918 this->ike_sa->get_other_id(this->ike_sa));
919 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
920 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
921 return SUCCESS;
922 }
923 return NEED_MORE;
924 }
925
926 /**
927 * Implementation of task_t.get_type
928 */
929 static task_type_t get_type(private_ike_auth_t *this)
930 {
931 return IKE_AUTHENTICATE;
932 }
933
934 /**
935 * Implementation of task_t.migrate
936 */
937 static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
938 {
939 chunk_free(&this->my_nonce);
940 chunk_free(&this->other_nonce);
941 DESTROY_IF(this->my_packet);
942 DESTROY_IF(this->other_packet);
943 DESTROY_IF(this->peer_cfg);
944 DESTROY_IF(this->my_auth);
945 DESTROY_IF(this->other_auth);
946 this->my_cfgs->destroy_offset(this->my_cfgs, offsetof(auth_cfg_t, destroy));
947 this->other_cfgs->destroy_offset(this->other_cfgs, offsetof(auth_cfg_t, destroy));
948 this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
949
950 this->my_packet = NULL;
951 this->other_packet = NULL;
952 this->ike_sa = ike_sa;
953 this->peer_cfg = NULL;
954 this->my_auth = NULL;
955 this->other_auth = NULL;
956 this->do_another_auth = TRUE;
957 this->expect_another_auth = TRUE;
958 this->authentication_failed = FALSE;
959 this->my_cfgs = linked_list_create();
960 this->other_cfgs = linked_list_create();
961 this->candidates = linked_list_create();
962 }
963
964 /**
965 * Implementation of task_t.destroy
966 */
967 static void destroy(private_ike_auth_t *this)
968 {
969 chunk_free(&this->my_nonce);
970 chunk_free(&this->other_nonce);
971 DESTROY_IF(this->my_packet);
972 DESTROY_IF(this->other_packet);
973 DESTROY_IF(this->my_auth);
974 DESTROY_IF(this->other_auth);
975 DESTROY_IF(this->peer_cfg);
976 this->my_cfgs->destroy_offset(this->my_cfgs, offsetof(auth_cfg_t, destroy));
977 this->other_cfgs->destroy_offset(this->other_cfgs, offsetof(auth_cfg_t, destroy));
978 this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
979 free(this);
980 }
981
982 /*
983 * Described in header.
984 */
985 ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
986 {
987 private_ike_auth_t *this = malloc_thing(private_ike_auth_t);
988
989 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
990 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
991 this->public.task.destroy = (void(*)(task_t*))destroy;
992
993 if (initiator)
994 {
995 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
996 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
997 }
998 else
999 {
1000 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
1001 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
1002 }
1003
1004 this->ike_sa = ike_sa;
1005 this->initiator = initiator;
1006 this->my_nonce = chunk_empty;
1007 this->other_nonce = chunk_empty;
1008 this->my_packet = NULL;
1009 this->other_packet = NULL;
1010 this->peer_cfg = NULL;
1011 this->my_cfgs = linked_list_create();
1012 this->other_cfgs = linked_list_create();
1013 this->candidates = linked_list_create();
1014 this->my_auth = NULL;
1015 this->other_auth = NULL;
1016 this->do_another_auth = TRUE;
1017 this->expect_another_auth = TRUE;
1018 this->authentication_failed = FALSE;
1019
1020 return &this->public;
1021 }
1022