4 * @brief Implementation of the ike_auth task.
9 * Copyright (C) 2005-2007 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 #include <crypto/diffie_hellman.h>
30 #include <encoding/payloads/id_payload.h>
31 #include <encoding/payloads/auth_payload.h>
32 #include <encoding/payloads/eap_payload.h>
33 #include <encoding/payloads/nonce_payload.h>
34 #include <sa/authenticators/eap_authenticator.h>
38 typedef struct private_ike_auth_t private_ike_auth_t
;
41 * Private members of a ike_auth_t task.
43 struct private_ike_auth_t
{
46 * Public methods and task_t interface.
56 * Are we the initiator?
61 * Nonce chosen by us in ike_init
66 * Nonce chosen by peer in ike_init
71 * IKE_SA_INIT message sent by us
76 * IKE_SA_INIT message sent by peer
78 packet_t
*other_packet
;
81 * EAP authenticator when using EAP
83 eap_authenticator_t
*eap_auth
;
86 * EAP payload received and ready to process
88 eap_payload_t
*eap_payload
;
91 * has the peer been authenticated successfully?
93 bool peer_authenticated
;
97 * build the AUTH payload
99 static status_t
build_auth(private_ike_auth_t
*this, message_t
*message
)
101 authenticator_t
*auth
;
102 auth_payload_t
*auth_payload
;
104 auth_method_t method
;
107 /* create own authenticator and add auth payload */
108 config
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
111 SIG(IKE_UP_FAILED
, "unable to authenticate, no peer config found");
114 method
= config
->get_auth_method(config
);
116 auth
= authenticator_create(this->ike_sa
, method
);
119 SIG(IKE_UP_FAILED
, "configured authentication method %N not supported",
120 auth_method_names
, method
);
124 status
= auth
->build(auth
, this->my_packet
->get_data(this->my_packet
),
125 this->other_nonce
, &auth_payload
);
127 if (status
!= SUCCESS
)
129 SIG(IKE_UP_FAILED
, "generating authentication data failed");
132 message
->add_payload(message
, (payload_t
*)auth_payload
);
137 * build ID payload(s)
139 static status_t
build_id(private_ike_auth_t
*this, message_t
*message
)
141 identification_t
*me
, *other
;
145 me
= this->ike_sa
->get_my_id(this->ike_sa
);
146 other
= this->ike_sa
->get_other_id(this->ike_sa
);
147 config
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
149 if (me
->contains_wildcards(me
))
151 me
= config
->get_my_id(config
);
152 if (me
->contains_wildcards(me
))
154 SIG(IKE_UP_FAILED
, "negotiation of own ID failed");
157 this->ike_sa
->set_my_id(this->ike_sa
, me
->clone(me
));
160 id
= id_payload_create_from_identification(this->initiator
? ID_INITIATOR
: ID_RESPONDER
, me
);
161 message
->add_payload(message
, (payload_t
*)id
);
163 /* as initiator, include other ID if it does not contain wildcards */
164 if (this->initiator
&& !other
->contains_wildcards(other
))
166 id
= id_payload_create_from_identification(ID_RESPONDER
, other
);
167 message
->add_payload(message
, (payload_t
*)id
);
173 * process AUTH payload
175 static status_t
process_auth(private_ike_auth_t
*this, message_t
*message
)
177 auth_payload_t
*auth_payload
;
178 authenticator_t
*auth
;
179 auth_method_t auth_method
;
182 auth_payload
= (auth_payload_t
*)message
->get_payload(message
, AUTHENTICATION
);
184 if (auth_payload
== NULL
)
186 /* AUTH payload is missing, client wants to use EAP authentication */
190 auth_method
= auth_payload
->get_auth_method(auth_payload
);
191 auth
= authenticator_create(this->ike_sa
, auth_method
);
195 SIG(IKE_UP_FAILED
, "authentication method %N used by %D not "
196 "supported", auth_method_names
, auth_method
,
197 this->ike_sa
->get_other_id(this->ike_sa
));
198 return NOT_SUPPORTED
;
200 status
= auth
->verify(auth
, this->other_packet
->get_data(this->other_packet
),
201 this->my_nonce
, auth_payload
);
203 if (status
!= SUCCESS
)
205 SIG(IKE_UP_FAILED
, "authentication of '%D' with %N failed",
206 this->ike_sa
->get_other_id(this->ike_sa
),
207 auth_method_names
, auth_method
);
214 * process ID payload(s)
216 static status_t
process_id(private_ike_auth_t
*this, message_t
*message
)
218 identification_t
*id
, *req
;
219 id_payload_t
*idr
, *idi
;
221 idi
= (id_payload_t
*)message
->get_payload(message
, ID_INITIATOR
);
222 idr
= (id_payload_t
*)message
->get_payload(message
, ID_RESPONDER
);
224 if ((this->initiator
&& idr
== NULL
) || (!this->initiator
&& idi
== NULL
))
226 SIG(IKE_UP_FAILED
, "ID payload missing in message");
232 id
= idr
->get_identification(idr
);
233 req
= this->ike_sa
->get_other_id(this->ike_sa
);
234 if (!id
->matches(id
, req
, NULL
))
236 SIG(IKE_UP_FAILED
, "peer ID %D unacceptable, %D required", id
, req
);
240 this->ike_sa
->set_other_id(this->ike_sa
, id
);
244 id
= idi
->get_identification(idi
);
245 this->ike_sa
->set_other_id(this->ike_sa
, id
);
248 id
= idr
->get_identification(idr
);
249 this->ike_sa
->set_my_id(this->ike_sa
, id
);
256 * collect the needed information in the IKE_SA_INIT exchange from our message
258 static status_t
collect_my_init_data(private_ike_auth_t
*this, message_t
*message
)
260 nonce_payload_t
*nonce
;
262 /* get the nonce that was generated in ike_init */
263 nonce
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
268 this->my_nonce
= nonce
->get_nonce(nonce
);
270 /* pre-generate the message, so we can store it for us */
271 if (this->ike_sa
->generate_message(this->ike_sa
, message
,
272 &this->my_packet
) != SUCCESS
)
280 * collect the needed information in the IKE_SA_INIT exchange from others message
282 static status_t
collect_other_init_data(private_ike_auth_t
*this, message_t
*message
)
284 /* we collect the needed information in the IKE_SA_INIT exchange */
285 nonce_payload_t
*nonce
;
287 /* get the nonce that was generated in ike_init */
288 nonce
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
293 this->other_nonce
= nonce
->get_nonce(nonce
);
295 /* pre-generate the message, so we can store it for us */
296 this->other_packet
= message
->get_packet(message
);
302 * Implementation of task_t.build to create AUTH payload from EAP data
304 static status_t
build_auth_eap(private_ike_auth_t
*this, message_t
*message
)
306 authenticator_t
*auth
;
307 auth_payload_t
*auth_payload
;
309 auth
= (authenticator_t
*)this->eap_auth
;
310 if (auth
->build(auth
, this->my_packet
->get_data(this->my_packet
),
311 this->other_nonce
, &auth_payload
) != SUCCESS
)
313 SIG(IKE_UP_FAILED
, "generating authentication data failed");
314 if (!this->initiator
)
316 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
320 message
->add_payload(message
, (payload_t
*)auth_payload
);
321 if (!this->initiator
)
323 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
324 SIG(IKE_UP_SUCCESS
, "IKE_SA '%s' established between %D[%H]...[%H]%D",
325 this->ike_sa
->get_name(this->ike_sa
),
326 this->ike_sa
->get_my_id(this->ike_sa
),
327 this->ike_sa
->get_my_host(this->ike_sa
),
328 this->ike_sa
->get_other_host(this->ike_sa
),
329 this->ike_sa
->get_other_id(this->ike_sa
));
336 * Implementation of task_t.process to verify AUTH payload after EAP
338 static status_t
process_auth_eap(private_ike_auth_t
*this, message_t
*message
)
340 auth_payload_t
*auth_payload
;
341 authenticator_t
*auth
;
343 auth_payload
= (auth_payload_t
*)message
->get_payload(message
, AUTHENTICATION
);
344 this->peer_authenticated
= FALSE
;
348 auth
= (authenticator_t
*)this->eap_auth
;
349 if (auth
->verify(auth
, this->other_packet
->get_data(this->other_packet
),
350 this->my_nonce
, auth_payload
) == SUCCESS
)
352 this->peer_authenticated
= TRUE
;
356 if (!this->peer_authenticated
)
358 SIG(IKE_UP_FAILED
, "authentication of '%D' with %N failed",
359 this->ike_sa
->get_other_id(this->ike_sa
),
360 auth_method_names
, AUTH_EAP
);
369 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
370 SIG(IKE_UP_SUCCESS
, "IKE_SA '%s' established between %D[%H]...[%H]%D",
371 this->ike_sa
->get_name(this->ike_sa
),
372 this->ike_sa
->get_my_id(this->ike_sa
),
373 this->ike_sa
->get_my_host(this->ike_sa
),
374 this->ike_sa
->get_other_host(this->ike_sa
),
375 this->ike_sa
->get_other_id(this->ike_sa
));
382 * Implementation of task_t.process for EAP exchanges
384 static status_t
process_eap_i(private_ike_auth_t
*this, message_t
*message
)
388 eap
= (eap_payload_t
*)message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
);
391 SIG(IKE_UP_FAILED
, "EAP payload missing");
394 switch (this->eap_auth
->process(this->eap_auth
, eap
, &eap
))
397 this->eap_payload
= eap
;
400 /* EAP exchange completed, now create and process AUTH */
401 this->eap_payload
= NULL
;
402 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_auth_eap
;
403 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_auth_eap
;
406 this->eap_payload
= NULL
;
407 SIG(IKE_UP_FAILED
, "failed to authenticate against %D using EAP",
408 this->ike_sa
->get_other_id(this->ike_sa
));
414 * Implementation of task_t.process for EAP exchanges
416 static status_t
process_eap_r(private_ike_auth_t
*this, message_t
*message
)
418 this->eap_payload
= (eap_payload_t
*)message
->get_payload(message
,
419 EXTENSIBLE_AUTHENTICATION
);
424 * Implementation of task_t.build for EAP exchanges
426 static status_t
build_eap_i(private_ike_auth_t
*this, message_t
*message
)
428 message
->add_payload(message
, (payload_t
*)this->eap_payload
);
433 * Implementation of task_t.build for EAP exchanges
435 static status_t
build_eap_r(private_ike_auth_t
*this, message_t
*message
)
437 status_t status
= NEED_MORE
;
440 if (this->eap_payload
== NULL
)
442 SIG(IKE_UP_FAILED
, "EAP payload missing");
446 switch (this->eap_auth
->process(this->eap_auth
, this->eap_payload
, &eap
))
452 /* EAP exchange completed, now create and process AUTH */
453 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_auth_eap
;
454 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_auth_eap
;
457 SIG(IKE_UP_FAILED
, "authentication of '%D' with %N failed",
458 this->ike_sa
->get_other_id(this->ike_sa
),
459 auth_method_names
, AUTH_EAP
);
463 message
->add_payload(message
, (payload_t
*)eap
);
468 * Implementation of task_t.build for initiator
470 static status_t
build_i(private_ike_auth_t
*this, message_t
*message
)
474 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
476 return collect_my_init_data(this, message
);
479 if (build_id(this, message
) != SUCCESS
)
484 config
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
485 if (config
->get_auth_method(config
) == AUTH_EAP
)
487 this->eap_auth
= eap_authenticator_create(this->ike_sa
);
491 if (build_auth(this, message
) != SUCCESS
)
501 * Implementation of task_t.process for responder
503 static status_t
process_r(private_ike_auth_t
*this, message_t
*message
)
507 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
509 return collect_other_init_data(this, message
);
512 if (process_id(this, message
) != SUCCESS
)
517 switch (process_auth(this, message
))
520 this->peer_authenticated
= TRUE
;
523 /* use EAP if no AUTH payload found */
524 this->ike_sa
->set_condition(this->ike_sa
, COND_EAP_AUTHENTICATED
, TRUE
);
525 this->eap_auth
= eap_authenticator_create(this->ike_sa
);
531 config
= charon
->backends
->get_peer_cfg(charon
->backends
,
532 this->ike_sa
->get_my_id(this->ike_sa
),
533 this->ike_sa
->get_other_id(this->ike_sa
),
534 this->ike_sa
->get_other_ca(this->ike_sa
));
537 this->ike_sa
->set_peer_cfg(this->ike_sa
, config
);
538 config
->destroy(config
);
545 * Implementation of task_t.build for responder
547 static status_t
build_r(private_ike_auth_t
*this, message_t
*message
)
551 eap_payload_t
*eap_payload
;
554 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
556 return collect_my_init_data(this, message
);
559 config
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
562 SIG(IKE_UP_FAILED
, "no matching config found for %D...%D",
563 this->ike_sa
->get_my_id(this->ike_sa
),
564 this->ike_sa
->get_other_id(this->ike_sa
));
565 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
569 if (build_id(this, message
) != SUCCESS
||
570 build_auth(this, message
) != SUCCESS
)
572 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
576 /* use "traditional" authentication if we could authenticate peer */
577 if (this->peer_authenticated
)
579 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
580 SIG(IKE_UP_SUCCESS
, "IKE_SA '%s' established between %D[%H]...[%H]%D",
581 this->ike_sa
->get_name(this->ike_sa
),
582 this->ike_sa
->get_my_id(this->ike_sa
),
583 this->ike_sa
->get_my_host(this->ike_sa
),
584 this->ike_sa
->get_other_host(this->ike_sa
),
585 this->ike_sa
->get_other_id(this->ike_sa
));
589 if (this->eap_auth
== NULL
)
591 /* peer not authenticated, nor does it want to use EAP */
592 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
596 /* initiate EAP authenitcation */
597 eap_type
= config
->get_eap_type(config
);
598 status
= this->eap_auth
->initiate(this->eap_auth
, eap_type
, &eap_payload
);
599 message
->add_payload(message
, (payload_t
*)eap_payload
);
600 if (status
!= NEED_MORE
)
602 SIG(IKE_UP_FAILED
, "unable to initiate EAP authentication");
606 /* switch to EAP methods */
607 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_eap_r
;
608 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_eap_r
;
613 * Implementation of task_t.process for initiator
615 static status_t
process_i(private_ike_auth_t
*this, message_t
*message
)
617 iterator_t
*iterator
;
620 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
622 return collect_other_init_data(this, message
);
625 iterator
= message
->get_payload_iterator(message
);
626 while (iterator
->iterate(iterator
, (void**)&payload
))
628 if (payload
->get_type(payload
) == NOTIFY
)
630 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
631 notify_type_t type
= notify
->get_notify_type(notify
);
635 case NO_PROPOSAL_CHOSEN
:
636 case SINGLE_PAIR_REQUIRED
:
637 case NO_ADDITIONAL_SAS
:
638 case INTERNAL_ADDRESS_FAILURE
:
639 case FAILED_CP_REQUIRED
:
640 case TS_UNACCEPTABLE
:
641 case INVALID_SELECTORS
:
642 /* these are errors, but are not critical as only the
643 * CHILD_SA won't get build, but IKE_SA establishes anyway */
645 case MOBIKE_SUPPORTED
:
646 case ADDITIONAL_IP4_ADDRESS
:
647 case ADDITIONAL_IP6_ADDRESS
:
648 /* handled in ike_mobike task */
651 /* handled in ike_auth_lifetime task */
654 /* handled in ike_p2p task */
660 SIG(IKE_UP_FAILED
, "received %N notify error",
661 notify_type_names
, type
);
662 iterator
->destroy(iterator
);
665 DBG1(DBG_IKE
, "received %N notify",
666 notify_type_names
, type
);
672 iterator
->destroy(iterator
);
674 if (process_id(this, message
) != SUCCESS
||
675 process_auth(this, message
) != SUCCESS
)
682 /* switch to EAP authentication methods */
683 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_eap_i
;
684 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_eap_i
;
685 return process_eap_i(this, message
);
688 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
689 SIG(IKE_UP_SUCCESS
, "IKE_SA '%s' established between %D[%H]...[%H]%D",
690 this->ike_sa
->get_name(this->ike_sa
),
691 this->ike_sa
->get_my_id(this->ike_sa
),
692 this->ike_sa
->get_my_host(this->ike_sa
),
693 this->ike_sa
->get_other_host(this->ike_sa
),
694 this->ike_sa
->get_other_id(this->ike_sa
));
699 * Implementation of task_t.get_type
701 static task_type_t
get_type(private_ike_auth_t
*this)
703 return IKE_AUTHENTICATE
;
707 * Implementation of task_t.migrate
709 static void migrate(private_ike_auth_t
*this, ike_sa_t
*ike_sa
)
711 chunk_free(&this->my_nonce
);
712 chunk_free(&this->other_nonce
);
713 DESTROY_IF(this->my_packet
);
714 DESTROY_IF(this->other_packet
);
717 this->eap_auth
->authenticator_interface
.destroy(
718 &this->eap_auth
->authenticator_interface
);
721 this->my_packet
= NULL
;
722 this->other_packet
= NULL
;
723 this->peer_authenticated
= FALSE
;
724 this->eap_auth
= NULL
;
725 this->eap_payload
= NULL
;
726 this->ike_sa
= ike_sa
;
729 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
730 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
734 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
735 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
740 * Implementation of task_t.destroy
742 static void destroy(private_ike_auth_t
*this)
744 chunk_free(&this->my_nonce
);
745 chunk_free(&this->other_nonce
);
746 DESTROY_IF(this->my_packet
);
747 DESTROY_IF(this->other_packet
);
750 this->eap_auth
->authenticator_interface
.destroy(
751 &this->eap_auth
->authenticator_interface
);
757 * Described in header.
759 ike_auth_t
*ike_auth_create(ike_sa_t
*ike_sa
, bool initiator
)
761 private_ike_auth_t
*this = malloc_thing(private_ike_auth_t
);
763 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
764 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
765 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
769 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
770 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
774 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
775 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
778 this->ike_sa
= ike_sa
;
779 this->initiator
= initiator
;
780 this->my_nonce
= chunk_empty
;
781 this->other_nonce
= chunk_empty
;
782 this->my_packet
= NULL
;
783 this->other_packet
= NULL
;
784 this->peer_authenticated
= FALSE
;
785 this->eap_auth
= NULL
;
786 this->eap_payload
= NULL
;
788 return &this->public;