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 policy
= this->ike_sa
->get_policy(this->ike_sa
);
111 SIG(IKE_UP_FAILED
, "unable to authenticate, no policy found");
114 method
= policy
->get_auth_method(policy
);
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 policy
= this->ike_sa
->get_policy(this->ike_sa
);
149 if (me
->contains_wildcards(me
))
151 me
= policy
->get_my_id(policy
);
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
, 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(FALSE
, 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 using %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
;
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 this->ike_sa
->set_other_id(this->ike_sa
, id
);
237 id
= idi
->get_identification(idi
);
238 this->ike_sa
->set_other_id(this->ike_sa
, id
);
241 id
= idr
->get_identification(idr
);
242 this->ike_sa
->set_my_id(this->ike_sa
, id
);
249 * collect the needed information in the IKE_SA_INIT exchange from our message
251 static status_t
collect_my_init_data(private_ike_auth_t
*this, message_t
*message
)
253 nonce_payload_t
*nonce
;
255 /* get the nonce that was generated in ike_init */
256 nonce
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
261 this->my_nonce
= nonce
->get_nonce(nonce
);
263 /* pre-generate the message, so we can store it for us */
264 if (this->ike_sa
->generate_message(this->ike_sa
, message
,
265 &this->my_packet
) != SUCCESS
)
273 * collect the needed information in the IKE_SA_INIT exchange from others message
275 static status_t
collect_other_init_data(private_ike_auth_t
*this, message_t
*message
)
277 /* we collect the needed information in the IKE_SA_INIT exchange */
278 nonce_payload_t
*nonce
;
280 /* get the nonce that was generated in ike_init */
281 nonce
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
286 this->other_nonce
= nonce
->get_nonce(nonce
);
288 /* pre-generate the message, so we can store it for us */
289 this->other_packet
= message
->get_packet(message
);
294 * Implementation of task_t.build to create AUTH payload from EAP data
296 static status_t
build_auth_eap(private_ike_auth_t
*this, message_t
*message
)
298 authenticator_t
*auth
;
299 auth_payload_t
*auth_payload
;
301 auth
= (authenticator_t
*)this->eap_auth
;
302 if (auth
->build(auth
, this->my_packet
->get_data(this->my_packet
),
303 this->other_nonce
, &auth_payload
) != SUCCESS
)
305 SIG(IKE_UP_FAILED
, "generating authentication data failed");
306 if (!this->initiator
)
308 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
312 message
->add_payload(message
, (payload_t
*)auth_payload
);
313 if (!this->initiator
)
315 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
316 SIG(IKE_UP_SUCCESS
, "IKE_SA established between %D[%H]...[%H]%D",
317 this->ike_sa
->get_my_id(this->ike_sa
),
318 this->ike_sa
->get_my_host(this->ike_sa
),
319 this->ike_sa
->get_other_host(this->ike_sa
),
320 this->ike_sa
->get_other_id(this->ike_sa
));
327 * Implementation of task_t.process to verify AUTH payload after EAP
329 static status_t
process_auth_eap(private_ike_auth_t
*this, message_t
*message
)
331 auth_payload_t
*auth_payload
;
332 authenticator_t
*auth
;
334 auth_payload
= (auth_payload_t
*)message
->get_payload(message
, AUTHENTICATION
);
335 this->peer_authenticated
= FALSE
;
339 auth
= (authenticator_t
*)this->eap_auth
;
340 if (auth
->verify(auth
, this->other_packet
->get_data(this->other_packet
),
341 this->my_nonce
, auth_payload
) == SUCCESS
)
343 this->peer_authenticated
= TRUE
;
347 if (!this->peer_authenticated
)
349 SIG(IKE_UP_FAILED
, "authentication of %D using %N failed",
350 this->ike_sa
->get_other_id(this->ike_sa
),
351 auth_method_names
, AUTH_EAP
);
360 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
361 SIG(IKE_UP_SUCCESS
, "IKE_SA established between %D[%H]...[%H]%D",
362 this->ike_sa
->get_my_id(this->ike_sa
),
363 this->ike_sa
->get_my_host(this->ike_sa
),
364 this->ike_sa
->get_other_host(this->ike_sa
),
365 this->ike_sa
->get_other_id(this->ike_sa
));
372 * Implementation of task_t.process for EAP exchanges
374 static status_t
process_eap_i(private_ike_auth_t
*this, message_t
*message
)
378 eap
= (eap_payload_t
*)message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
);
381 SIG(IKE_UP_FAILED
, "EAP payload missing");
384 switch (this->eap_auth
->process(this->eap_auth
, eap
, &eap
))
387 this->eap_payload
= eap
;
390 /* EAP exchange completed, now create and process AUTH */
391 this->eap_payload
= NULL
;
392 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_auth_eap
;
393 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_auth_eap
;
396 this->eap_payload
= NULL
;
397 SIG(IKE_UP_FAILED
, "failed to authenticate against %D using EAP",
398 this->ike_sa
->get_other_id(this->ike_sa
));
404 * Implementation of task_t.process for EAP exchanges
406 static status_t
process_eap_r(private_ike_auth_t
*this, message_t
*message
)
408 this->eap_payload
= (eap_payload_t
*)message
->get_payload(message
,
409 EXTENSIBLE_AUTHENTICATION
);
414 * Implementation of task_t.build for EAP exchanges
416 static status_t
build_eap_i(private_ike_auth_t
*this, message_t
*message
)
418 message
->add_payload(message
, (payload_t
*)this->eap_payload
);
423 * Implementation of task_t.build for EAP exchanges
425 static status_t
build_eap_r(private_ike_auth_t
*this, message_t
*message
)
427 status_t status
= NEED_MORE
;
430 if (this->eap_payload
== NULL
)
432 SIG(IKE_UP_FAILED
, "EAP payload missing");
436 switch (this->eap_auth
->process(this->eap_auth
, this->eap_payload
, &eap
))
442 /* EAP exchange completed, now create and process AUTH */
443 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_auth_eap
;
444 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_auth_eap
;
447 SIG(IKE_UP_FAILED
, "authentication of %D using %N failed",
448 this->ike_sa
->get_other_id(this->ike_sa
),
449 auth_method_names
, AUTH_EAP
);
453 message
->add_payload(message
, (payload_t
*)eap
);
458 * Implementation of task_t.build for initiator
460 static status_t
build_i(private_ike_auth_t
*this, message_t
*message
)
464 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
466 return collect_my_init_data(this, message
);
469 if (build_id(this, message
) != SUCCESS
)
474 policy
= this->ike_sa
->get_policy(this->ike_sa
);
475 if (policy
->get_auth_method(policy
) == AUTH_EAP
)
477 this->eap_auth
= eap_authenticator_create(this->ike_sa
);
481 if (build_auth(this, message
) != SUCCESS
)
491 * Implementation of task_t.process for initiator
493 static status_t
process_r(private_ike_auth_t
*this, message_t
*message
)
495 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
497 return collect_other_init_data(this, message
);
500 if (process_id(this, message
) != SUCCESS
)
505 switch (process_auth(this, message
))
508 this->peer_authenticated
= TRUE
;
511 /* use EAP if no AUTH payload found */
512 this->eap_auth
= eap_authenticator_create(this->ike_sa
);
521 * Implementation of task_t.build for responder
523 static status_t
build_r(private_ike_auth_t
*this, message_t
*message
)
527 eap_payload_t
*eap_payload
;
530 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
532 return collect_my_init_data(this, message
);
535 policy
= this->ike_sa
->get_policy(this->ike_sa
);
538 SIG(IKE_UP_FAILED
, "no acceptable policy found");
539 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
543 if (build_id(this, message
) != SUCCESS
||
544 build_auth(this, message
) != SUCCESS
)
546 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
550 /* use "traditional" authentication if we could authenticate peer */
551 if (this->peer_authenticated
)
553 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
554 SIG(IKE_UP_SUCCESS
, "IKE_SA established between %D[%H]...[%H]%D",
555 this->ike_sa
->get_my_id(this->ike_sa
),
556 this->ike_sa
->get_my_host(this->ike_sa
),
557 this->ike_sa
->get_other_host(this->ike_sa
),
558 this->ike_sa
->get_other_id(this->ike_sa
));
562 if (this->eap_auth
== NULL
)
564 /* peer not authenticated, nor does it want to use EAP */
565 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
569 /* initiate EAP authenitcation */
570 eap_type
= policy
->get_eap_type(policy
);
571 status
= this->eap_auth
->initiate(this->eap_auth
, eap_type
, &eap_payload
);
572 message
->add_payload(message
, (payload_t
*)eap_payload
);
573 if (status
!= NEED_MORE
)
575 SIG(IKE_UP_FAILED
, "unable to initiate EAP authentication");
579 /* switch to EAP methods */
580 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_eap_r
;
581 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_eap_r
;
586 * Implementation of task_t.process for initiator
588 static status_t
process_i(private_ike_auth_t
*this, message_t
*message
)
590 iterator_t
*iterator
;
593 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
595 return collect_other_init_data(this, message
);
598 iterator
= message
->get_payload_iterator(message
);
599 while (iterator
->iterate(iterator
, (void**)&payload
))
601 if (payload
->get_type(payload
) == NOTIFY
)
603 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
604 notify_type_t type
= notify
->get_notify_type(notify
);
608 case NO_PROPOSAL_CHOSEN
:
609 case SINGLE_PAIR_REQUIRED
:
610 case NO_ADDITIONAL_SAS
:
611 case INTERNAL_ADDRESS_FAILURE
:
612 case FAILED_CP_REQUIRED
:
613 case TS_UNACCEPTABLE
:
614 case INVALID_SELECTORS
:
615 /* these are errors, but are not critical as only the
616 * CHILD_SA won't get build, but IKE_SA establishes anyway */
622 SIG(IKE_UP_FAILED
, "received %N notify error",
623 notify_type_names
, type
);
624 iterator
->destroy(iterator
);
627 DBG1(DBG_IKE
, "received %N notify",
628 notify_type_names
, type
);
634 iterator
->destroy(iterator
);
636 if (process_id(this, message
) != SUCCESS
||
637 process_auth(this, message
) != SUCCESS
)
644 /* switch to EAP authentication methods */
645 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_eap_i
;
646 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_eap_i
;
647 return process_eap_i(this, message
);
650 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
651 SIG(IKE_UP_SUCCESS
, "IKE_SA established between %D[%H]...[%H]%D",
652 this->ike_sa
->get_my_id(this->ike_sa
),
653 this->ike_sa
->get_my_host(this->ike_sa
),
654 this->ike_sa
->get_other_host(this->ike_sa
),
655 this->ike_sa
->get_other_id(this->ike_sa
));
660 * Implementation of task_t.get_type
662 static task_type_t
get_type(private_ike_auth_t
*this)
664 return IKE_AUTHENTICATE
;
668 * Implementation of task_t.migrate
670 static void migrate(private_ike_auth_t
*this, ike_sa_t
*ike_sa
)
672 chunk_free(&this->my_nonce
);
673 chunk_free(&this->other_nonce
);
674 DESTROY_IF(this->my_packet
);
675 DESTROY_IF(this->other_packet
);
678 this->eap_auth
->authenticator_interface
.destroy(
679 &this->eap_auth
->authenticator_interface
);
682 this->my_packet
= NULL
;
683 this->other_packet
= NULL
;
684 this->peer_authenticated
= FALSE
;
685 this->eap_auth
= NULL
;
686 this->eap_payload
= NULL
;
687 this->ike_sa
= ike_sa
;
690 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
691 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
695 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
696 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
701 * Implementation of task_t.destroy
703 static void destroy(private_ike_auth_t
*this)
705 chunk_free(&this->my_nonce
);
706 chunk_free(&this->other_nonce
);
707 DESTROY_IF(this->my_packet
);
708 DESTROY_IF(this->other_packet
);
711 this->eap_auth
->authenticator_interface
.destroy(
712 &this->eap_auth
->authenticator_interface
);
718 * Described in header.
720 ike_auth_t
*ike_auth_create(ike_sa_t
*ike_sa
, bool initiator
)
722 private_ike_auth_t
*this = malloc_thing(private_ike_auth_t
);
724 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
725 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
726 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
730 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
731 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
735 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
736 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
739 this->ike_sa
= ike_sa
;
740 this->initiator
= initiator
;
741 this->my_nonce
= chunk_empty
;
742 this->other_nonce
= chunk_empty
;
743 this->my_packet
= NULL
;
744 this->other_packet
= NULL
;
745 this->peer_authenticated
= FALSE
;
746 this->eap_auth
= NULL
;
747 this->eap_payload
= NULL
;
749 return &this->public;