Fixed EAP authentication regression
[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 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
734 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
735 this->ike_sa->get_name(this->ike_sa),
736 this->ike_sa->get_unique_id(this->ike_sa),
737 this->ike_sa->get_my_host(this->ike_sa),
738 this->ike_sa->get_my_id(this->ike_sa),
739 this->ike_sa->get_other_host(this->ike_sa),
740 this->ike_sa->get_other_id(this->ike_sa));
741 return SUCCESS;
742 }
743 return NEED_MORE;
744 }
745
746 /**
747 * Implementation of task_t.process for initiator
748 */
749 static status_t process_i(private_ike_auth_t *this, message_t *message)
750 {
751 enumerator_t *enumerator;
752 payload_t *payload;
753 auth_cfg_t *cfg;
754
755 if (message->get_exchange_type(message) == IKE_SA_INIT)
756 {
757 if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) &&
758 multiple_auth_enabled())
759 {
760 this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
761 }
762 return collect_other_init_data(this, message);
763 }
764
765 enumerator = message->create_payload_enumerator(message);
766 while (enumerator->enumerate(enumerator, &payload))
767 {
768 if (payload->get_type(payload) == NOTIFY)
769 {
770 notify_payload_t *notify = (notify_payload_t*)payload;
771 notify_type_t type = notify->get_notify_type(notify);
772
773 switch (type)
774 {
775 case NO_PROPOSAL_CHOSEN:
776 case SINGLE_PAIR_REQUIRED:
777 case NO_ADDITIONAL_SAS:
778 case INTERNAL_ADDRESS_FAILURE:
779 case FAILED_CP_REQUIRED:
780 case TS_UNACCEPTABLE:
781 case INVALID_SELECTORS:
782 /* these are errors, but are not critical as only the
783 * CHILD_SA won't get build, but IKE_SA establishes anyway */
784 break;
785 case MOBIKE_SUPPORTED:
786 case ADDITIONAL_IP4_ADDRESS:
787 case ADDITIONAL_IP6_ADDRESS:
788 /* handled in ike_mobike task */
789 break;
790 case AUTH_LIFETIME:
791 /* handled in ike_auth_lifetime task */
792 break;
793 case ME_ENDPOINT:
794 /* handled in ike_me task */
795 break;
796 default:
797 {
798 if (type < 16383)
799 {
800 DBG1(DBG_IKE, "received %N notify error",
801 notify_type_names, type);
802 enumerator->destroy(enumerator);
803 return FAILED;
804 }
805 DBG2(DBG_IKE, "received %N notify",
806 notify_type_names, type);
807 break;
808 }
809 }
810 }
811 }
812 enumerator->destroy(enumerator);
813
814 if (this->my_auth)
815 {
816 switch (this->my_auth->process(this->my_auth, message))
817 {
818 case SUCCESS:
819 cfg = auth_cfg_create();
820 cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
821 TRUE);
822 this->my_cfgs->insert_last(this->my_cfgs, cfg);
823 this->my_auth->destroy(this->my_auth);
824 this->my_auth = NULL;
825 this->do_another_auth = do_another_auth(this);
826 break;
827 case NEED_MORE:
828 break;
829 default:
830 return FAILED;
831 }
832 }
833
834 if (this->expect_another_auth)
835 {
836 if (this->other_auth == NULL)
837 {
838 id_payload_t *id_payload;
839 identification_t *id;
840
841 /* responder is not allowed to do EAP */
842 if (!message->get_payload(message, AUTHENTICATION))
843 {
844 DBG1(DBG_IKE, "AUTH payload missing");
845 return FAILED;
846 }
847
848 /* handle IDr payload */
849 id_payload = (id_payload_t*)message->get_payload(message,
850 ID_RESPONDER);
851 if (!id_payload)
852 {
853 DBG1(DBG_IKE, "IDr payload missing");
854 return FAILED;
855 }
856 id = id_payload->get_identification(id_payload);
857 this->ike_sa->set_other_id(this->ike_sa, id);
858 cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
859 cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
860
861 /* verify authentication data */
862 this->other_auth = authenticator_create_verifier(this->ike_sa,
863 message, this->other_nonce, this->my_nonce,
864 this->other_packet->get_data(this->other_packet),
865 this->my_packet->get_data(this->my_packet));
866 if (!this->other_auth)
867 {
868 return FAILED;
869 }
870 }
871 switch (this->other_auth->process(this->other_auth, message))
872 {
873 case SUCCESS:
874 break;
875 case NEED_MORE:
876 return NEED_MORE;
877 default:
878 return FAILED;
879 }
880 /* store authentication information, reset authenticator */
881 cfg = auth_cfg_create();
882 cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
883 this->other_cfgs->insert_last(this->other_cfgs, cfg);
884 this->other_auth->destroy(this->other_auth);
885 this->other_auth = NULL;
886
887 /* another auth round done, invoke authorize hook */
888 if (!charon->bus->authorize(charon->bus, this->other_cfgs, FALSE))
889 {
890 DBG1(DBG_IKE, "round %d authorization forbids IKE_SA, cancelling",
891 this->other_cfgs->get_count(this->other_cfgs));
892 return FAILED;
893 }
894 }
895
896 if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
897 {
898 this->expect_another_auth = FALSE;
899 }
900 if (!this->expect_another_auth && !this->do_another_auth && !this->my_auth)
901 {
902 if (!update_cfg_candidates(this, TRUE))
903 {
904 return FAILED;
905 }
906 if (!charon->bus->authorize(charon->bus, this->other_cfgs, TRUE))
907 {
908 DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
909 return FAILED;
910 }
911 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
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 return SUCCESS;
920 }
921 return NEED_MORE;
922 }
923
924 /**
925 * Implementation of task_t.get_type
926 */
927 static task_type_t get_type(private_ike_auth_t *this)
928 {
929 return IKE_AUTHENTICATE;
930 }
931
932 /**
933 * Implementation of task_t.migrate
934 */
935 static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
936 {
937 chunk_free(&this->my_nonce);
938 chunk_free(&this->other_nonce);
939 DESTROY_IF(this->my_packet);
940 DESTROY_IF(this->other_packet);
941 DESTROY_IF(this->peer_cfg);
942 DESTROY_IF(this->my_auth);
943 DESTROY_IF(this->other_auth);
944 this->my_cfgs->destroy_offset(this->my_cfgs, offsetof(auth_cfg_t, destroy));
945 this->other_cfgs->destroy_offset(this->other_cfgs, offsetof(auth_cfg_t, destroy));
946 this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
947
948 this->my_packet = NULL;
949 this->other_packet = NULL;
950 this->ike_sa = ike_sa;
951 this->peer_cfg = NULL;
952 this->my_auth = NULL;
953 this->other_auth = NULL;
954 this->do_another_auth = TRUE;
955 this->expect_another_auth = TRUE;
956 this->authentication_failed = FALSE;
957 this->my_cfgs = linked_list_create();
958 this->other_cfgs = linked_list_create();
959 this->candidates = linked_list_create();
960 }
961
962 /**
963 * Implementation of task_t.destroy
964 */
965 static void destroy(private_ike_auth_t *this)
966 {
967 chunk_free(&this->my_nonce);
968 chunk_free(&this->other_nonce);
969 DESTROY_IF(this->my_packet);
970 DESTROY_IF(this->other_packet);
971 DESTROY_IF(this->my_auth);
972 DESTROY_IF(this->other_auth);
973 DESTROY_IF(this->peer_cfg);
974 this->my_cfgs->destroy_offset(this->my_cfgs, offsetof(auth_cfg_t, destroy));
975 this->other_cfgs->destroy_offset(this->other_cfgs, offsetof(auth_cfg_t, destroy));
976 this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
977 free(this);
978 }
979
980 /*
981 * Described in header.
982 */
983 ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
984 {
985 private_ike_auth_t *this = malloc_thing(private_ike_auth_t);
986
987 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
988 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
989 this->public.task.destroy = (void(*)(task_t*))destroy;
990
991 if (initiator)
992 {
993 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
994 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
995 }
996 else
997 {
998 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
999 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
1000 }
1001
1002 this->ike_sa = ike_sa;
1003 this->initiator = initiator;
1004 this->my_nonce = chunk_empty;
1005 this->other_nonce = chunk_empty;
1006 this->my_packet = NULL;
1007 this->other_packet = NULL;
1008 this->peer_cfg = NULL;
1009 this->my_cfgs = linked_list_create();
1010 this->other_cfgs = linked_list_create();
1011 this->candidates = linked_list_create();
1012 this->my_auth = NULL;
1013 this->other_auth = NULL;
1014 this->do_another_auth = TRUE;
1015 this->expect_another_auth = TRUE;
1016 this->authentication_failed = FALSE;
1017
1018 return &this->public;
1019 }
1020