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/nonce_payload.h>
35 typedef struct private_ike_auth_t private_ike_auth_t
;
38 * Private members of a ike_auth_t task.
40 struct private_ike_auth_t
{
43 * Public methods and task_t interface.
53 * Are we the initiator?
58 * Nonce chosen by us in ike_init
63 * Nonce chosen by peer in ike_init
68 * IKE_SA_INIT message sent by us
73 * IKE_SA_INIT message sent by peer
75 packet_t
*other_packet
;
78 * authenticator to authenticate us
80 authenticator_t
*my_auth
;
83 * authenticator to authenticate peer
85 authenticator_t
*other_auth
;
88 * has the peer been authenticated successfully?
90 bool peer_authenticated
;
94 * build the payloads for the message
96 static status_t
build_payloads(private_ike_auth_t
*this, message_t
*message
)
98 authenticator_t
*auth
;
99 auth_payload_t
*auth_payload
;
100 id_payload_t
*id_payload
;
102 identification_t
*me
, *other
;
104 auth_method_t method
= AUTH_RSA
;
107 /* add own ID payload */
108 me
= this->ike_sa
->get_my_id(this->ike_sa
);
109 other
= this->ike_sa
->get_other_id(this->ike_sa
);
112 /* create own authenticator and add auth payload */
113 policy
= this->ike_sa
->get_policy(this->ike_sa
);
116 SIG(IKE_UP_FAILED
, "no acceptable policy found");
120 method
= policy
->get_auth_method(policy
);
121 if (me
->contains_wildcards(me
))
123 me
= policy
->get_my_id(policy
);
124 if (me
->contains_wildcards(me
))
126 SIG(IKE_UP_FAILED
, "negotiation of own ID failed");
129 this->ike_sa
->set_my_id(this->ike_sa
, me
);
132 id_payload
= id_payload_create_from_identification(this->initiator
, me
);
133 message
->add_payload(message
, (payload_t
*)id_payload
);
135 /* as initiator, include other ID if it does not contain wildcards */
136 if (this->initiator
&& !other
->contains_wildcards(other
))
138 id_payload
= id_payload_create_from_identification(FALSE
, other
);
139 message
->add_payload(message
, (payload_t
*)id_payload
);
142 auth
= authenticator_create(this->ike_sa
, method
);
145 SIG(IKE_UP_FAILED
, "configured authentication method %N not supported",
146 auth_method_names
, method
);
150 ike_sa_init
= this->my_packet
->get_data(this->my_packet
);
151 status
= auth
->build(auth
, ike_sa_init
, this->other_nonce
, &auth_payload
);
153 if (status
!= SUCCESS
)
155 SIG(IKE_UP_FAILED
, "generating authentication data failed");
158 message
->add_payload(message
, (payload_t
*)auth_payload
);
164 * process payloads from message
166 static void process_payloads(private_ike_auth_t
*this, message_t
*message
)
168 iterator_t
*iterator
;
171 identification_t
*idi
= NULL
, *idr
= NULL
;
172 auth_payload_t
*auth_payload
= NULL
;
173 authenticator_t
*auth
;
174 auth_method_t auth_method
;
177 iterator
= message
->get_payload_iterator(message
);
178 while (iterator
->iterate(iterator
, (void**)&payload
))
180 type
= payload
->get_type(payload
);
185 id_payload_t
*id_payload
= (id_payload_t
*)payload
;
186 idi
= id_payload
->get_identification(id_payload
);
191 id_payload_t
*id_payload
= (id_payload_t
*)payload
;
192 idr
= id_payload
->get_identification(id_payload
);
197 auth_payload
= (auth_payload_t
*)payload
;
204 iterator
->destroy(iterator
);
207 if ((this->initiator
&& idr
== NULL
) || (!this->initiator
&& idi
== NULL
))
209 SIG(IKE_UP_FAILED
, "ID payload missing in message");
210 DESTROY_IF(idr
); DESTROY_IF(idi
);
216 this->ike_sa
->set_other_id(this->ike_sa
, idr
);
222 this->ike_sa
->set_my_id(this->ike_sa
, idr
);
224 this->ike_sa
->set_other_id(this->ike_sa
, idi
);
227 /* verify auth payload */
228 if (auth_payload
== NULL
)
230 SIG(IKE_UP_FAILED
, "AUTH payload missing in message");
234 auth_method
= auth_payload
->get_auth_method(auth_payload
);
235 auth
= authenticator_create(this->ike_sa
, auth_method
);
238 SIG(IKE_UP_FAILED
, "authentication method %N used by %D not "
239 "supported", auth_method_names
, auth_method
,
240 this->ike_sa
->get_other_id(this->ike_sa
));
243 status
= auth
->verify(auth
, this->other_packet
->get_data(this->other_packet
),
244 this->my_nonce
, auth_payload
);
246 if (status
!= SUCCESS
)
248 SIG(IKE_UP_FAILED
, "authentication of %D using %N failed",
249 this->ike_sa
->get_other_id(this->ike_sa
),
250 auth_method_names
, auth_method
);
253 this->peer_authenticated
= TRUE
;
257 * collect the needed information in the IKE_SA_INIT exchange from our message
259 static status_t
collect_my_init_data(private_ike_auth_t
*this, message_t
*message
)
261 nonce_payload_t
*nonce
;
263 /* get the nonce that was generated in ike_init */
264 nonce
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
269 this->my_nonce
= nonce
->get_nonce(nonce
);
271 /* pre-generate the message, so we can store it for us */
272 if (this->ike_sa
->generate_message(this->ike_sa
, message
,
273 &this->my_packet
) != SUCCESS
)
281 * collect the needed information in the IKE_SA_INIT exchange from others message
283 static status_t
collect_other_init_data(private_ike_auth_t
*this, message_t
*message
)
285 /* we collect the needed information in the IKE_SA_INIT exchange */
286 nonce_payload_t
*nonce
;
288 /* get the nonce that was generated in ike_init */
289 nonce
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
294 this->other_nonce
= nonce
->get_nonce(nonce
);
296 /* pre-generate the message, so we can store it for us */
297 this->other_packet
= message
->get_packet(message
);
302 * Implementation of task_t.build for initiator
304 static status_t
build_i(private_ike_auth_t
*this, message_t
*message
)
306 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
308 return collect_my_init_data(this, message
);
311 if (build_payloads(this, message
) == SUCCESS
)
319 * Implementation of task_t.process for initiator
321 static status_t
process_r(private_ike_auth_t
*this, message_t
*message
)
323 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
325 return collect_other_init_data(this, message
);
328 process_payloads(this, message
);
334 * Implementation of task_t.build for responder
336 static status_t
build_r(private_ike_auth_t
*this, message_t
*message
)
338 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
340 return collect_my_init_data(this, message
);
343 if (this->peer_authenticated
&& build_payloads(this, message
) == SUCCESS
)
345 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
346 SIG(IKE_UP_SUCCESS
, "IKE_SA established between %D[%H]...[%H]%D",
347 this->ike_sa
->get_my_id(this->ike_sa
),
348 this->ike_sa
->get_my_host(this->ike_sa
),
349 this->ike_sa
->get_other_host(this->ike_sa
),
350 this->ike_sa
->get_other_id(this->ike_sa
));
353 message
->add_notify(message
, TRUE
, AUTHENTICATION_FAILED
, chunk_empty
);
358 * Implementation of task_t.process for initiator
360 static status_t
process_i(private_ike_auth_t
*this, message_t
*message
)
362 iterator_t
*iterator
;
365 if (message
->get_exchange_type(message
) == IKE_SA_INIT
)
367 return collect_other_init_data(this, message
);
370 iterator
= message
->get_payload_iterator(message
);
371 while (iterator
->iterate(iterator
, (void**)&payload
))
373 if (payload
->get_type(payload
) == NOTIFY
)
375 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
376 notify_type_t type
= notify
->get_notify_type(notify
);
380 case NO_PROPOSAL_CHOSEN
:
381 case SINGLE_PAIR_REQUIRED
:
382 case NO_ADDITIONAL_SAS
:
383 case INTERNAL_ADDRESS_FAILURE
:
384 case FAILED_CP_REQUIRED
:
385 case TS_UNACCEPTABLE
:
386 case INVALID_SELECTORS
:
387 /* these are errors, but are not critical as only the
388 * CHILD_SA won't get build, but IKE_SA establishes anyway */
389 DBG1(DBG_IKE
, "received %N notify, no CHILD_SA built",
390 notify_type_names
, type
);
391 iterator
->destroy(iterator
);
397 DBG1(DBG_IKE
, "received %N notify error",
398 notify_type_names
, type
);
399 iterator
->destroy(iterator
);
406 iterator
->destroy(iterator
);
408 process_payloads(this, message
);
410 if (this->peer_authenticated
)
412 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
413 SIG(IKE_UP_SUCCESS
, "IKE_SA established between %D[%H]...[%H]%D",
414 this->ike_sa
->get_my_id(this->ike_sa
),
415 this->ike_sa
->get_my_host(this->ike_sa
),
416 this->ike_sa
->get_other_host(this->ike_sa
),
417 this->ike_sa
->get_other_id(this->ike_sa
));
424 * Implementation of task_t.get_type
426 static task_type_t
get_type(private_ike_auth_t
*this)
428 return IKE_AUTHENTICATE
;
432 * Implementation of task_t.migrate
434 static void migrate(private_ike_auth_t
*this, ike_sa_t
*ike_sa
)
436 chunk_free(&this->my_nonce
);
437 chunk_free(&this->other_nonce
);
438 DESTROY_IF(this->my_packet
);
439 DESTROY_IF(this->other_packet
);
440 DESTROY_IF(this->my_auth
);
441 DESTROY_IF(this->other_auth
);
442 this->my_packet
= NULL
;
443 this->other_packet
= NULL
;
444 this->my_auth
= NULL
;
445 this->other_auth
= NULL
;
446 this->peer_authenticated
= FALSE
;
447 this->ike_sa
= ike_sa
;
451 * Implementation of task_t.destroy
453 static void destroy(private_ike_auth_t
*this)
455 chunk_free(&this->my_nonce
);
456 chunk_free(&this->other_nonce
);
457 DESTROY_IF(this->my_packet
);
458 DESTROY_IF(this->other_packet
);
459 DESTROY_IF(this->my_auth
);
460 DESTROY_IF(this->other_auth
);
465 * Described in header.
467 ike_auth_t
*ike_auth_create(ike_sa_t
*ike_sa
, bool initiator
)
469 private_ike_auth_t
*this = malloc_thing(private_ike_auth_t
);
471 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
472 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
473 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
477 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
478 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
482 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
483 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
486 this->ike_sa
= ike_sa
;
487 this->initiator
= initiator
;
488 this->my_nonce
= chunk_empty
;
489 this->other_nonce
= chunk_empty
;
490 this->my_packet
= NULL
;
491 this->other_packet
= NULL
;
492 this->my_auth
= NULL
;
493 this->other_auth
= NULL
;
494 this->peer_authenticated
= FALSE
;
496 return &this->public;