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