improved IKE_SA uniqueness check
[strongswan.git] / src / charon / sa / tasks / ike_auth.c
1 /*
2 * Copyright (C) 2005-2007 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details
15 *
16 * $Id$
17 */
18
19 #include "ike_auth.h"
20
21 #include <string.h>
22
23 #include <daemon.h>
24 #include <crypto/diffie_hellman.h>
25 #include <encoding/payloads/id_payload.h>
26 #include <encoding/payloads/auth_payload.h>
27 #include <encoding/payloads/eap_payload.h>
28 #include <encoding/payloads/nonce_payload.h>
29 #include <sa/authenticators/eap_authenticator.h>
30
31
32 typedef struct private_ike_auth_t private_ike_auth_t;
33
34 /**
35 * Private members of a ike_auth_t task.
36 */
37 struct private_ike_auth_t {
38
39 /**
40 * Public methods and task_t interface.
41 */
42 ike_auth_t public;
43
44 /**
45 * Assigned IKE_SA.
46 */
47 ike_sa_t *ike_sa;
48
49 /**
50 * Are we the initiator?
51 */
52 bool initiator;
53
54 /**
55 * Nonce chosen by us in ike_init
56 */
57 chunk_t my_nonce;
58
59 /**
60 * Nonce chosen by peer in ike_init
61 */
62 chunk_t other_nonce;
63
64 /**
65 * IKE_SA_INIT message sent by us
66 */
67 packet_t *my_packet;
68
69 /**
70 * IKE_SA_INIT message sent by peer
71 */
72 packet_t *other_packet;
73
74 /**
75 * EAP authenticator when using EAP
76 */
77 eap_authenticator_t *eap_auth;
78
79 /**
80 * EAP payload received and ready to process
81 */
82 eap_payload_t *eap_payload;
83
84 /**
85 * has the peer been authenticated successfully?
86 */
87 bool peer_authenticated;
88 };
89
90 /**
91 * get the authentication class of a config
92 */
93 auth_class_t get_auth_class(peer_cfg_t *config)
94 {
95 auth_class_t *class;
96 auth_info_t *auth_info;
97
98 auth_info = config->get_auth(config);
99 if (auth_info->get_item(auth_info, AUTHN_AUTH_CLASS, (void**)&class))
100 {
101 return *class;
102 }
103 /* fallback to pubkey authentication */
104 return AUTH_CLASS_PUBKEY;
105 }
106
107 /**
108 * get the eap type/vendor
109 */
110 static eap_type_t get_eap_type(peer_cfg_t *config, u_int32_t *vendor)
111 {
112 auth_info_t *auth_info;
113 u_int *ptr;
114
115 *vendor = 0;
116 auth_info = config->get_auth(config);
117 if (auth_info->get_item(auth_info, AUTHN_EAP_VENDOR, (void**)&ptr))
118 {
119 *vendor = *ptr;
120 }
121 if (auth_info->get_item(auth_info, AUTHN_EAP_TYPE, (void**)&ptr))
122 {
123 return *ptr;
124 }
125 return EAP_NAK;
126 }
127
128 /**
129 * build the AUTH payload
130 */
131 static status_t build_auth(private_ike_auth_t *this, message_t *message)
132 {
133 authenticator_t *auth;
134 auth_payload_t *auth_payload;
135 peer_cfg_t *config;
136 status_t status;
137
138 /* create own authenticator and add auth payload */
139 config = this->ike_sa->get_peer_cfg(this->ike_sa);
140 if (!config)
141 {
142 DBG1(DBG_IKE, "unable to authenticate, no peer config found");
143 return FAILED;
144 }
145
146 auth = authenticator_create_from_class(this->ike_sa, get_auth_class(config));
147 if (auth == NULL)
148 {
149 DBG1(DBG_IKE, "configured authentication class %N not supported",
150 auth_class_names, get_auth_class(config));
151 return FAILED;
152 }
153
154 status = auth->build(auth, this->my_packet->get_data(this->my_packet),
155 this->other_nonce, &auth_payload);
156 auth->destroy(auth);
157 if (status != SUCCESS)
158 {
159 DBG1(DBG_IKE, "generating authentication data failed");
160 return FAILED;
161 }
162 message->add_payload(message, (payload_t*)auth_payload);
163 return SUCCESS;
164 }
165
166 /**
167 * build ID payload(s)
168 */
169 static status_t build_id(private_ike_auth_t *this, message_t *message)
170 {
171 identification_t *me, *other;
172 id_payload_t *id;
173 peer_cfg_t *config;
174
175 me = this->ike_sa->get_my_id(this->ike_sa);
176 other = this->ike_sa->get_other_id(this->ike_sa);
177 config = this->ike_sa->get_peer_cfg(this->ike_sa);
178
179 if (me->contains_wildcards(me))
180 {
181 me = config->get_my_id(config);
182 if (me->contains_wildcards(me))
183 {
184 DBG1(DBG_IKE, "negotiation of own ID failed");
185 return FAILED;
186 }
187 this->ike_sa->set_my_id(this->ike_sa, me->clone(me));
188 }
189
190 id = id_payload_create_from_identification(this->initiator ? ID_INITIATOR : ID_RESPONDER, me);
191 message->add_payload(message, (payload_t*)id);
192
193 /* as initiator, include other ID if it does not contain wildcards */
194 if (this->initiator && !other->contains_wildcards(other))
195 {
196 id = id_payload_create_from_identification(ID_RESPONDER, other);
197 message->add_payload(message, (payload_t*)id);
198 }
199 return SUCCESS;
200 }
201
202 /**
203 * process AUTH payload
204 */
205 static status_t process_auth(private_ike_auth_t *this, message_t *message)
206 {
207 auth_payload_t *auth_payload;
208 authenticator_t *auth;
209 auth_method_t auth_method;
210 status_t status;
211
212 auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
213
214 if (auth_payload == NULL)
215 {
216 /* AUTH payload is missing, client wants to use EAP authentication */
217 return NOT_FOUND;
218 }
219
220 auth_method = auth_payload->get_auth_method(auth_payload);
221 auth = authenticator_create_from_method(this->ike_sa,
222 auth_payload->get_auth_method(auth_payload));
223 if (auth == NULL)
224 {
225 DBG1(DBG_IKE, "authentication method %N used by '%D' not supported",
226 auth_method_names, auth_method,
227 this->ike_sa->get_other_id(this->ike_sa));
228 return NOT_SUPPORTED;
229 }
230 status = auth->verify(auth, this->other_packet->get_data(this->other_packet),
231 this->my_nonce, auth_payload);
232 auth->destroy(auth);
233 if (status != SUCCESS)
234 {
235 DBG0(DBG_IKE, "authentication of '%D' with %N failed",
236 this->ike_sa->get_other_id(this->ike_sa),
237 auth_method_names, auth_method);
238 return FAILED;
239 }
240 return SUCCESS;
241 }
242
243 /**
244 * process ID payload(s)
245 */
246 static status_t process_id(private_ike_auth_t *this, message_t *message)
247 {
248 identification_t *id, *req;
249 id_payload_t *idr, *idi;
250
251 idi = (id_payload_t*)message->get_payload(message, ID_INITIATOR);
252 idr = (id_payload_t*)message->get_payload(message, ID_RESPONDER);
253
254 if ((this->initiator && idr == NULL) || (!this->initiator && idi == NULL))
255 {
256 DBG1(DBG_IKE, "ID payload missing in message");
257 return FAILED;
258 }
259
260 if (this->initiator)
261 {
262 id = idr->get_identification(idr);
263 req = this->ike_sa->get_other_id(this->ike_sa);
264 if (!id->matches(id, req))
265 {
266 DBG0(DBG_IKE, "peer ID '%D' unacceptable, '%D' required", id, req);
267 id->destroy(id);
268 return FAILED;
269 }
270 this->ike_sa->set_other_id(this->ike_sa, id);
271 }
272 else
273 {
274 id = idi->get_identification(idi);
275 this->ike_sa->set_other_id(this->ike_sa, id);
276 if (idr)
277 {
278 id = idr->get_identification(idr);
279 this->ike_sa->set_my_id(this->ike_sa, id);
280 }
281 }
282 return SUCCESS;
283 }
284
285 /**
286 * collect the needed information in the IKE_SA_INIT exchange from our message
287 */
288 static status_t collect_my_init_data(private_ike_auth_t *this, message_t *message)
289 {
290 nonce_payload_t *nonce;
291
292 /* get the nonce that was generated in ike_init */
293 nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
294 if (nonce == NULL)
295 {
296 return FAILED;
297 }
298 this->my_nonce = nonce->get_nonce(nonce);
299
300 /* pre-generate the message, so we can store it for us */
301 if (this->ike_sa->generate_message(this->ike_sa, message,
302 &this->my_packet) != SUCCESS)
303 {
304 return FAILED;
305 }
306 return NEED_MORE;
307 }
308
309 /**
310 * collect the needed information in the IKE_SA_INIT exchange from others message
311 */
312 static status_t collect_other_init_data(private_ike_auth_t *this, message_t *message)
313 {
314 /* we collect the needed information in the IKE_SA_INIT exchange */
315 nonce_payload_t *nonce;
316
317 /* get the nonce that was generated in ike_init */
318 nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
319 if (nonce == NULL)
320 {
321 return FAILED;
322 }
323 this->other_nonce = nonce->get_nonce(nonce);
324
325 /* pre-generate the message, so we can store it for us */
326 this->other_packet = message->get_packet(message);
327 return NEED_MORE;
328 }
329
330
331 /**
332 * Implementation of task_t.build to create AUTH payload from EAP data
333 */
334 static status_t build_auth_eap(private_ike_auth_t *this, message_t *message)
335 {
336 authenticator_t *auth;
337 auth_payload_t *auth_payload;
338
339 auth = (authenticator_t*)this->eap_auth;
340 if (auth->build(auth, this->my_packet->get_data(this->my_packet),
341 this->other_nonce, &auth_payload) != SUCCESS)
342 {
343 DBG1(DBG_IKE, "generating authentication data failed");
344 if (!this->initiator)
345 {
346 message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
347 }
348 return FAILED;
349 }
350 message->add_payload(message, (payload_t*)auth_payload);
351 if (!this->initiator)
352 {
353 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
354 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
355 this->ike_sa->get_name(this->ike_sa),
356 this->ike_sa->get_unique_id(this->ike_sa),
357 this->ike_sa->get_my_host(this->ike_sa),
358 this->ike_sa->get_my_id(this->ike_sa),
359 this->ike_sa->get_other_host(this->ike_sa),
360 this->ike_sa->get_other_id(this->ike_sa));
361 return SUCCESS;
362 }
363 return NEED_MORE;
364 }
365
366 /**
367 * Implementation of task_t.process to verify AUTH payload after EAP
368 */
369 static status_t process_auth_eap(private_ike_auth_t *this, message_t *message)
370 {
371 auth_payload_t *auth_payload;
372 authenticator_t *auth;
373
374 auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
375 this->peer_authenticated = FALSE;
376
377 if (auth_payload)
378 {
379 auth = (authenticator_t*)this->eap_auth;
380 if (auth->verify(auth, this->other_packet->get_data(this->other_packet),
381 this->my_nonce, auth_payload) == SUCCESS)
382 {
383 this->peer_authenticated = TRUE;
384 }
385 }
386
387 if (!this->peer_authenticated)
388 {
389 DBG0(DBG_IKE, "authentication of '%D' with %N failed",
390 this->ike_sa->get_other_id(this->ike_sa),
391 auth_class_names, AUTH_CLASS_EAP);
392 if (this->initiator)
393 {
394 return FAILED;
395 }
396 return NEED_MORE;
397 }
398 if (this->initiator)
399 {
400 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
401 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
402 this->ike_sa->get_name(this->ike_sa),
403 this->ike_sa->get_unique_id(this->ike_sa),
404 this->ike_sa->get_my_host(this->ike_sa),
405 this->ike_sa->get_my_id(this->ike_sa),
406 this->ike_sa->get_other_host(this->ike_sa),
407 this->ike_sa->get_other_id(this->ike_sa));
408 return SUCCESS;
409 }
410 return NEED_MORE;
411 }
412
413 /**
414 * Implementation of task_t.process for EAP exchanges
415 */
416 static status_t process_eap_i(private_ike_auth_t *this, message_t *message)
417 {
418 eap_payload_t *eap;
419
420 eap = (eap_payload_t*)message->get_payload(message, EXTENSIBLE_AUTHENTICATION);
421 if (eap == NULL)
422 {
423 DBG1(DBG_IKE, "EAP payload missing");
424 return FAILED;
425 }
426 switch (this->eap_auth->process(this->eap_auth, eap, &eap))
427 {
428 case NEED_MORE:
429 this->eap_payload = eap;
430 return NEED_MORE;
431 case SUCCESS:
432 /* EAP exchange completed, now create and process AUTH */
433 this->eap_payload = NULL;
434 this->public.task.build = (status_t(*)(task_t*,message_t*))build_auth_eap;
435 this->public.task.process = (status_t(*)(task_t*,message_t*))process_auth_eap;
436 return NEED_MORE;
437 default:
438 this->eap_payload = NULL;
439 DBG0(DBG_IKE, "failed to authenticate against '%D' using EAP",
440 this->ike_sa->get_other_id(this->ike_sa));
441 return FAILED;
442 }
443 }
444
445 /**
446 * Implementation of task_t.process for EAP exchanges
447 */
448 static status_t process_eap_r(private_ike_auth_t *this, message_t *message)
449 {
450 this->eap_payload = (eap_payload_t*)message->get_payload(message,
451 EXTENSIBLE_AUTHENTICATION);
452 return NEED_MORE;
453 }
454
455 /**
456 * Implementation of task_t.build for EAP exchanges
457 */
458 static status_t build_eap_i(private_ike_auth_t *this, message_t *message)
459 {
460 message->add_payload(message, (payload_t*)this->eap_payload);
461 return NEED_MORE;
462 }
463
464 /**
465 * Implementation of task_t.build for EAP exchanges
466 */
467 static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
468 {
469 status_t status = NEED_MORE;
470 eap_payload_t *eap;
471
472 if (this->eap_payload == NULL)
473 {
474 DBG1(DBG_IKE, "EAP payload missing");
475 return FAILED;
476 }
477
478 switch (this->eap_auth->process(this->eap_auth, this->eap_payload, &eap))
479 {
480 case NEED_MORE:
481
482 break;
483 case SUCCESS:
484 /* EAP exchange completed, now create and process AUTH */
485 this->public.task.build = (status_t(*)(task_t*,message_t*))build_auth_eap;
486 this->public.task.process = (status_t(*)(task_t*,message_t*))process_auth_eap;
487 break;
488 default:
489 DBG0(DBG_IKE, "authentication of '%D' with %N failed",
490 this->ike_sa->get_other_id(this->ike_sa),
491 auth_class_names, AUTH_CLASS_EAP);
492 status = FAILED;
493 break;
494 }
495 message->add_payload(message, (payload_t*)eap);
496 return status;
497 }
498
499 /**
500 * Implementation of task_t.build for initiator
501 */
502 static status_t build_i(private_ike_auth_t *this, message_t *message)
503 {
504 peer_cfg_t *config;
505
506 if (message->get_exchange_type(message) == IKE_SA_INIT)
507 {
508 return collect_my_init_data(this, message);
509 }
510
511 if (build_id(this, message) != SUCCESS)
512 {
513 return FAILED;
514 }
515
516 config = this->ike_sa->get_peer_cfg(this->ike_sa);
517 if (get_auth_class(config) == AUTH_CLASS_EAP)
518 {
519 this->eap_auth = eap_authenticator_create(this->ike_sa);
520 }
521 else
522 {
523 if (build_auth(this, message) != SUCCESS)
524 {
525 return FAILED;
526 }
527 }
528
529 return NEED_MORE;
530 }
531
532 /**
533 * Implementation of task_t.process for responder
534 */
535 static status_t process_r(private_ike_auth_t *this, message_t *message)
536 {
537 peer_cfg_t *config;
538
539 if (message->get_exchange_type(message) == IKE_SA_INIT)
540 {
541 return collect_other_init_data(this, message);
542 }
543
544 if (process_id(this, message) != SUCCESS)
545 {
546 return NEED_MORE;
547 }
548
549 switch (process_auth(this, message))
550 {
551 case SUCCESS:
552 this->peer_authenticated = TRUE;
553 break;
554 case NOT_FOUND:
555 /* use EAP if no AUTH payload found */
556 this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED, TRUE);
557 break;
558 default:
559 return NEED_MORE;
560 }
561
562 config = charon->backends->get_peer_cfg(charon->backends,
563 this->ike_sa->get_my_host(this->ike_sa),
564 this->ike_sa->get_other_host(this->ike_sa),
565 this->ike_sa->get_my_id(this->ike_sa),
566 this->ike_sa->get_other_id(this->ike_sa),
567 this->ike_sa->get_other_auth(this->ike_sa));
568 if (config)
569 {
570 this->ike_sa->set_peer_cfg(this->ike_sa, config);
571 config->destroy(config);
572 }
573 if (!this->peer_authenticated)
574 {
575 this->eap_auth = eap_authenticator_create(this->ike_sa);
576 }
577 return NEED_MORE;
578 }
579
580 /**
581 * Implementation of task_t.build for responder
582 */
583 static status_t build_r(private_ike_auth_t *this, message_t *message)
584 {
585 peer_cfg_t *config;
586 eap_type_t eap_type;
587 u_int32_t eap_vendor;
588 eap_payload_t *eap_payload;
589 status_t status;
590
591 if (message->get_exchange_type(message) == IKE_SA_INIT)
592 {
593 return collect_my_init_data(this, message);
594 }
595
596 if (!this->peer_authenticated && this->eap_auth == NULL)
597 {
598 /* peer not authenticated, nor does it want to use EAP */
599 message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
600 return FAILED;
601 }
602
603 config = this->ike_sa->get_peer_cfg(this->ike_sa);
604 if (config == NULL)
605 {
606 DBG1(DBG_IKE, "no matching config found for '%D'...'%D'",
607 this->ike_sa->get_my_id(this->ike_sa),
608 this->ike_sa->get_other_id(this->ike_sa));
609 message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
610 return FAILED;
611 }
612
613 if (build_id(this, message) != SUCCESS ||
614 build_auth(this, message) != SUCCESS)
615 {
616 message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
617 return FAILED;
618 }
619
620 if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
621 this->ike_sa))
622 {
623 DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
624 message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
625 return FAILED;
626 }
627
628 /* use "traditional" authentication if we could authenticate peer */
629 if (this->peer_authenticated)
630 {
631 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
632 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
633 this->ike_sa->get_name(this->ike_sa),
634 this->ike_sa->get_unique_id(this->ike_sa),
635 this->ike_sa->get_my_host(this->ike_sa),
636 this->ike_sa->get_my_id(this->ike_sa),
637 this->ike_sa->get_other_host(this->ike_sa),
638 this->ike_sa->get_other_id(this->ike_sa));
639 return SUCCESS;
640 }
641
642 /* initiate EAP authenitcation */
643 eap_type = get_eap_type(config, &eap_vendor);
644 status = this->eap_auth->initiate(this->eap_auth, eap_type,
645 eap_vendor, &eap_payload);
646 message->add_payload(message, (payload_t*)eap_payload);
647 if (status != NEED_MORE)
648 {
649 DBG1(DBG_IKE, "unable to initiate EAP authentication");
650 return FAILED;
651 }
652
653 /* switch to EAP methods */
654 this->public.task.build = (status_t(*)(task_t*,message_t*))build_eap_r;
655 this->public.task.process = (status_t(*)(task_t*,message_t*))process_eap_r;
656 return NEED_MORE;
657 }
658
659 /**
660 * Implementation of task_t.process for initiator
661 */
662 static status_t process_i(private_ike_auth_t *this, message_t *message)
663 {
664 iterator_t *iterator;
665 payload_t *payload;
666 peer_cfg_t *config;
667 auth_info_t *auth;
668
669 if (message->get_exchange_type(message) == IKE_SA_INIT)
670 {
671 return collect_other_init_data(this, message);
672 }
673
674 iterator = message->get_payload_iterator(message);
675 while (iterator->iterate(iterator, (void**)&payload))
676 {
677 if (payload->get_type(payload) == NOTIFY)
678 {
679 notify_payload_t *notify = (notify_payload_t*)payload;
680 notify_type_t type = notify->get_notify_type(notify);
681
682 switch (type)
683 {
684 case NO_PROPOSAL_CHOSEN:
685 case SINGLE_PAIR_REQUIRED:
686 case NO_ADDITIONAL_SAS:
687 case INTERNAL_ADDRESS_FAILURE:
688 case FAILED_CP_REQUIRED:
689 case TS_UNACCEPTABLE:
690 case INVALID_SELECTORS:
691 /* these are errors, but are not critical as only the
692 * CHILD_SA won't get build, but IKE_SA establishes anyway */
693 break;
694 case MOBIKE_SUPPORTED:
695 case ADDITIONAL_IP4_ADDRESS:
696 case ADDITIONAL_IP6_ADDRESS:
697 /* handled in ike_mobike task */
698 break;
699 case AUTH_LIFETIME:
700 /* handled in ike_auth_lifetime task */
701 break;
702 case ME_ENDPOINT:
703 /* handled in ike_me task */
704 break;
705 default:
706 {
707 if (type < 16383)
708 {
709 DBG1(DBG_IKE, "received %N notify error",
710 notify_type_names, type);
711 iterator->destroy(iterator);
712 return FAILED;
713 }
714 DBG2(DBG_IKE, "received %N notify",
715 notify_type_names, type);
716 break;
717 }
718 }
719 }
720 }
721 iterator->destroy(iterator);
722
723 if (process_id(this, message) != SUCCESS ||
724 process_auth(this, message) != SUCCESS)
725 {
726 return FAILED;
727 }
728
729 if (this->eap_auth)
730 {
731 /* switch to EAP authentication methods */
732 this->public.task.build = (status_t(*)(task_t*,message_t*))build_eap_i;
733 this->public.task.process = (status_t(*)(task_t*,message_t*))process_eap_i;
734 return process_eap_i(this, message);
735 }
736
737 config = this->ike_sa->get_peer_cfg(this->ike_sa);
738 auth = this->ike_sa->get_other_auth(this->ike_sa);
739 if (!auth->complies(auth, config->get_auth(config)))
740 {
741 DBG0(DBG_IKE, "authorization of '%D' for config %s failed",
742 this->ike_sa->get_other_id(this->ike_sa), config->get_name(config));
743 return FAILED;
744 }
745 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
746 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
747 this->ike_sa->get_name(this->ike_sa),
748 this->ike_sa->get_unique_id(this->ike_sa),
749 this->ike_sa->get_my_host(this->ike_sa),
750 this->ike_sa->get_my_id(this->ike_sa),
751 this->ike_sa->get_other_host(this->ike_sa),
752 this->ike_sa->get_other_id(this->ike_sa));
753 return SUCCESS;
754 }
755
756 /**
757 * Implementation of task_t.get_type
758 */
759 static task_type_t get_type(private_ike_auth_t *this)
760 {
761 return IKE_AUTHENTICATE;
762 }
763
764 /**
765 * Implementation of task_t.migrate
766 */
767 static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
768 {
769 chunk_free(&this->my_nonce);
770 chunk_free(&this->other_nonce);
771 DESTROY_IF(this->my_packet);
772 DESTROY_IF(this->other_packet);
773 if (this->eap_auth)
774 {
775 this->eap_auth->authenticator_interface.destroy(
776 &this->eap_auth->authenticator_interface);
777 }
778
779 this->my_packet = NULL;
780 this->other_packet = NULL;
781 this->peer_authenticated = FALSE;
782 this->eap_auth = NULL;
783 this->eap_payload = NULL;
784 this->ike_sa = ike_sa;
785 if (this->initiator)
786 {
787 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
788 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
789 }
790 else
791 {
792 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
793 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
794 }
795 }
796
797 /**
798 * Implementation of task_t.destroy
799 */
800 static void destroy(private_ike_auth_t *this)
801 {
802 chunk_free(&this->my_nonce);
803 chunk_free(&this->other_nonce);
804 DESTROY_IF(this->my_packet);
805 DESTROY_IF(this->other_packet);
806 if (this->eap_auth)
807 {
808 this->eap_auth->authenticator_interface.destroy(
809 &this->eap_auth->authenticator_interface);
810 }
811 free(this);
812 }
813
814 /*
815 * Described in header.
816 */
817 ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
818 {
819 private_ike_auth_t *this = malloc_thing(private_ike_auth_t);
820
821 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
822 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
823 this->public.task.destroy = (void(*)(task_t*))destroy;
824
825 if (initiator)
826 {
827 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
828 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
829 }
830 else
831 {
832 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
833 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
834 }
835
836 this->ike_sa = ike_sa;
837 this->initiator = initiator;
838 this->my_nonce = chunk_empty;
839 this->other_nonce = chunk_empty;
840 this->my_packet = NULL;
841 this->other_packet = NULL;
842 this->peer_authenticated = FALSE;
843 this->eap_auth = NULL;
844 this->eap_payload = NULL;
845
846 return &this->public;
847 }