2 * @file ike_auth_requested.c
4 * @brief Implementation of ike_auth_requested_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include "ike_auth_requested.h"
28 #include <encoding/payloads/ts_payload.h>
29 #include <encoding/payloads/sa_payload.h>
30 #include <encoding/payloads/id_payload.h>
31 #include <encoding/payloads/auth_payload.h>
32 #include <encoding/payloads/notify_payload.h>
33 #include <crypto/signers/signer.h>
34 #include <crypto/crypters/crypter.h>
35 #include <sa/states/ike_sa_established.h>
36 #include <sa/authenticator.h>
37 #include <sa/child_sa.h>
39 typedef struct private_ike_auth_requested_t private_ike_auth_requested_t
;
42 * Private data of a ike_auth_requested_t object.
45 struct private_ike_auth_requested_t
{
47 * Public interface of ike_auth_requested_t.
49 ike_auth_requested_t
public;
54 protected_ike_sa_t
*ike_sa
;
57 * SA config, just a copy of the one stored in the ike_sa.
62 * Received nonce from responder.
64 chunk_t received_nonce
;
67 * Sent nonce in IKE_SA_INIT request.
72 * IKE_SA_INIT-Request in binary form.
74 chunk_t ike_sa_init_reply_data
;
77 * Proposal to setup CHILD_SA
82 * Traffic selectors applicable at our site
87 * Traffic selectors applicable at remote site
89 linked_list_t
*other_ts
;
92 * Child sa created in ike_sa_init_requested
99 * Is logger of ike_sa!
104 * Process the IDr payload (check if other id is valid)
106 * @param this calling object
107 * @param idr_payload ID payload of responder
112 status_t (*process_idr_payload
) (private_ike_auth_requested_t
*this, id_payload_t
*idr_payload
);
115 * Process the SA payload (check if selected proposals are valid, setup child sa)
117 * @param this calling object
118 * @param sa_payload SA payload of responder
123 status_t (*process_sa_payload
) (private_ike_auth_requested_t
*this, sa_payload_t
*sa_payload
);
126 * Process the AUTH payload (check authenticity of message)
128 * @param this calling object
129 * @param auth_payload AUTH payload of responder
130 * @param other_id_payload ID payload of responder
135 status_t (*process_auth_payload
) (private_ike_auth_requested_t
*this, auth_payload_t
*auth_payload
, id_payload_t
*other_id_payload
);
138 * Process the TS payload (check if selected traffic selectors are valid)
140 * @param this calling object
141 * @param ts_initiator TRUE if TS payload is TSi, FALSE for TSr
142 * @param ts_payload TS payload of responder
147 status_t (*process_ts_payload
) (private_ike_auth_requested_t
*this, bool ts_initiator
, ts_payload_t
*ts_payload
);
150 * Process a notify payload
152 * @param this calling object
153 * @param notify_payload notify payload
159 status_t (*process_notify_payload
) (private_ike_auth_requested_t
*this, notify_payload_t
*notify_payload
);
162 * Destroy function called internally of this class after state change to
163 * state IKE_SA_ESTABLISHED succeeded.
165 * This destroy function does not destroy objects which were passed to the new state.
167 * @param this calling object
169 void (*destroy_after_state_change
) (private_ike_auth_requested_t
*this);
174 * Implements state_t.process_message
176 static status_t
process_message(private_ike_auth_requested_t
*this, message_t
*ike_auth_reply
)
178 ts_payload_t
*tsi_payload
= NULL
, *tsr_payload
= NULL
;
179 id_payload_t
*idr_payload
= NULL
;
180 auth_payload_t
*auth_payload
= NULL
;
181 sa_payload_t
*sa_payload
= NULL
;
182 iterator_t
*payloads
= NULL
;
183 crypter_t
*crypter
= NULL
;
184 signer_t
*signer
= NULL
;
186 host_t
*my_host
, *other_host
;
188 prf_plus_t
*prf_plus
;
189 connection_t
*connection
;
191 if (ike_auth_reply
->get_exchange_type(ike_auth_reply
) != IKE_AUTH
)
193 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "Message of type %s not supported in state ike_auth_requested",
194 mapping_find(exchange_type_m
,ike_auth_reply
->get_exchange_type(ike_auth_reply
)));
198 if (ike_auth_reply
->get_request(ike_auth_reply
))
200 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "IKE_AUTH requests not allowed state ike_sa_init_responded");
204 /* get signer for verification and crypter for decryption */
205 signer
= this->ike_sa
->get_signer_responder(this->ike_sa
);
206 crypter
= this->ike_sa
->get_crypter_responder(this->ike_sa
);
208 /* parse incoming message */
209 status
= ike_auth_reply
->parse_body(ike_auth_reply
, crypter
, signer
);
210 if (status
!= SUCCESS
)
212 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply decryption failed. Ignoring message");
216 this->policy
= this->ike_sa
->get_policy(this->ike_sa
);
218 /* we collect all payloads, which are processed later. Notify's are processed
219 * in place, since we don't know how may are there.
221 payloads
= ike_auth_reply
->get_payload_iterator(ike_auth_reply
);
222 while (payloads
->has_next(payloads
))
225 payloads
->current(payloads
, (void**)&payload
);
227 switch (payload
->get_type(payload
))
231 auth_payload
= (auth_payload_t
*)payload
;
236 idr_payload
= (id_payload_t
*)payload
;
239 case SECURITY_ASSOCIATION
:
241 sa_payload
= (sa_payload_t
*)payload
;
244 case TRAFFIC_SELECTOR_INITIATOR
:
246 tsi_payload
= (ts_payload_t
*)payload
;
249 case TRAFFIC_SELECTOR_RESPONDER
:
251 tsr_payload
= (ts_payload_t
*)payload
;
256 notify_payload_t
*notify_payload
= (notify_payload_t
*) payload
;
257 /* handle the notify directly, abort if no further processing required */
258 status
= this->process_notify_payload(this, notify_payload
);
259 if (status
!= SUCCESS
)
261 payloads
->destroy(payloads
);
267 /* TODO handle cert payloads */
271 this->logger
->log(this->logger
, ERROR
|LEVEL1
, "Ignoring Payload %s (%d)",
272 mapping_find(payload_type_m
, payload
->get_type(payload
)), payload
->get_type(payload
));
277 /* iterator can be destroyed */
278 payloads
->destroy(payloads
);
280 /* check if we have all payloads */
281 if (!(idr_payload
&& sa_payload
&& auth_payload
&& tsi_payload
&& tsr_payload
))
283 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA");
287 /* process all payloads */
288 status
= this->process_idr_payload(this, idr_payload
);
289 if (status
!= SUCCESS
)
293 status
= this->process_auth_payload(this, auth_payload
,idr_payload
);
294 if (status
!= SUCCESS
)
298 status
= this->process_sa_payload(this, sa_payload
);
299 if (status
!= SUCCESS
)
303 status
= this->process_ts_payload(this, TRUE
, tsi_payload
);
304 if (status
!= SUCCESS
)
308 status
= this->process_ts_payload(this, FALSE
, tsr_payload
);
309 if (status
!= SUCCESS
)
314 /* install child SAs for AH and esp */
317 this->logger
->log(this->logger
, CONTROL
, "No CHILD_SA requested, no CHILD_SA built");
321 this->logger
->log(this->logger
, CONTROL
, "Proposal negotiation failed, no CHILD_SA built");
322 this->child_sa
->destroy(this->child_sa
);
323 this->child_sa
= NULL
;
325 else if (this->my_ts
->get_count(this->my_ts
) == 0 || this->other_ts
->get_count(this->other_ts
) == 0)
327 this->logger
->log(this->logger
, CONTROL
, "Traffic selector negotiation failed, no CHILD_SA built");
328 this->child_sa
->destroy(this->child_sa
);
329 this->child_sa
= NULL
;
333 seed
= chunk_alloc(this->sent_nonce
.len
+ this->received_nonce
.len
);
334 memcpy(seed
.ptr
, this->sent_nonce
.ptr
, this->sent_nonce
.len
);
335 memcpy(seed
.ptr
+ this->sent_nonce
.len
, this->received_nonce
.ptr
, this->received_nonce
.len
);
336 prf_plus
= prf_plus_create(this->ike_sa
->get_child_prf(this->ike_sa
), seed
);
339 status
= this->child_sa
->update(this->child_sa
, this->proposal
, prf_plus
);
340 prf_plus
->destroy(prf_plus
);
341 if (status
!= SUCCESS
)
343 this->logger
->log(this->logger
, AUDIT
, "Could not install CHILD_SA! Deleting IKE_SA");
346 status
= this->child_sa
->add_policies(this->child_sa
, this->my_ts
, this->other_ts
);
347 if (status
!= SUCCESS
)
349 this->logger
->log(this->logger
, AUDIT
, "Could not install CHILD_SA policy! Deleting IKE_SA");
352 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
355 this->ike_sa
->set_last_replied_message_id(this->ike_sa
,ike_auth_reply
->get_message_id(ike_auth_reply
));
357 /* create new state */
358 this->ike_sa
->set_new_state(this->ike_sa
, (state_t
*)ike_sa_established_create(this->ike_sa
));
359 this->destroy_after_state_change(this);
361 connection
= this->ike_sa
->get_connection(this->ike_sa
);
362 my_host
= connection
->get_my_host(connection
);
363 other_host
= connection
->get_other_host(connection
);
364 this->logger
->log(this->logger
, AUDIT
, "IKE_SA established between %s - %s",
365 my_host
->get_address(my_host
), other_host
->get_address(other_host
));
371 * Implements private_ike_auth_requested_t.process_idr_payload
373 static status_t
process_idr_payload(private_ike_auth_requested_t
*this, id_payload_t
*idr_payload
)
375 identification_t
*other_id
, *configured_other_id
;
376 connection_t
*connection
;
378 other_id
= idr_payload
->get_identification(idr_payload
);
379 configured_other_id
= this->policy
->get_other_id(this->policy
);
381 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "configured ID: %s, ID of responder: %s",
382 configured_other_id
->get_string(configured_other_id
),
383 other_id
->get_string(other_id
));
385 if (!other_id
->belongs_to(other_id
, configured_other_id
))
387 other_id
->destroy(other_id
);
388 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply contained a not acceptable ID. Deleting IKE_SA");
392 connection
= this->ike_sa
->get_connection(this->ike_sa
);
393 connection
->update_other_id(connection
, other_id
->clone(other_id
));
395 this->policy
->update_other_id(this->policy
, other_id
);
400 * Implements private_ike_auth_requested_t.process_sa_payload
402 static status_t
process_sa_payload(private_ike_auth_requested_t
*this, sa_payload_t
*sa_payload
)
404 proposal_t
*proposal
, *proposal_tmp
;
405 linked_list_t
*proposal_list
;
407 /* get his selected proposal */
408 proposal_list
= sa_payload
->get_proposals(sa_payload
);
409 /* check count of proposals */
410 if (proposal_list
->get_count(proposal_list
) == 0)
412 /* no proposal? we accept this, but no child sa is built */
413 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply's SA_PAYLOAD didn't contain any proposals. No CHILD_SA created",
414 proposal_list
->get_count(proposal_list
));
415 proposal_list
->destroy(proposal_list
);
418 if (proposal_list
->get_count(proposal_list
) > 1)
420 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply's SA_PAYLOAD contained %d proposal. Deleting IKE_SA",
421 proposal_list
->get_count(proposal_list
));
422 while (proposal_list
->remove_last(proposal_list
, (void**)&proposal
) == SUCCESS
)
424 proposal
->destroy(proposal
);
426 proposal_list
->destroy(proposal_list
);
430 /* we have to re-check here if other's selection is valid */
431 proposal
= this->policy
->select_proposal(this->policy
, proposal_list
);
432 /* list not needed anymore */
433 while (proposal_list
->remove_last(proposal_list
, (void**)&proposal_tmp
) == SUCCESS
)
435 proposal_tmp
->destroy(proposal_tmp
);
437 proposal_list
->destroy(proposal_list
);
439 if (proposal
== NULL
)
441 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply contained a not offered proposal. Deleting IKE_SA");
446 this->proposal
= proposal
;
452 * Implements private_ike_auth_requested_t.process_auth_payload
454 static status_t
process_auth_payload(private_ike_auth_requested_t
*this, auth_payload_t
*auth_payload
, id_payload_t
*other_id_payload
)
456 authenticator_t
*authenticator
;
459 authenticator
= authenticator_create(this->ike_sa
);
460 status
= authenticator
->verify_auth_data(authenticator
,auth_payload
,this->ike_sa_init_reply_data
,this->sent_nonce
,other_id_payload
,FALSE
);
461 authenticator
->destroy(authenticator
);
462 if (status
!= SUCCESS
)
464 this->logger
->log(this->logger
, AUDIT
, "Verification of IKE_AUTH reply failed. Deleting IKE_SA");
468 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "AUTH data verified successfully");
473 * Implements private_ike_auth_requested_t.process_ts_payload
475 static status_t
process_ts_payload(private_ike_auth_requested_t
*this, bool ts_initiator
, ts_payload_t
*ts_payload
)
477 linked_list_t
*ts_received
, *ts_selected
;
478 traffic_selector_t
*ts
;
480 /* get ts form payload */
481 ts_received
= ts_payload
->get_traffic_selectors(ts_payload
);
482 /* select ts depending on payload type */
485 ts_selected
= this->policy
->select_my_traffic_selectors(this->policy
, ts_received
);
486 this->my_ts
= ts_selected
;
490 ts_selected
= this->policy
->select_other_traffic_selectors(this->policy
, ts_received
);
491 this->other_ts
= ts_selected
;
493 /* check if the responder selected valid proposals */
494 if (ts_selected
->get_count(ts_selected
) != ts_received
->get_count(ts_received
))
496 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply contained not offered traffic selectors.");
500 while (ts_received
->remove_last(ts_received
, (void**)&ts
) == SUCCESS
)
504 ts_received
->destroy(ts_received
);
510 * Implements private_ike_auth_requested_t.process_notify_payload
512 static status_t
process_notify_payload(private_ike_auth_requested_t
*this, notify_payload_t
*notify_payload
)
514 notify_message_type_t notify_message_type
= notify_payload
->get_notify_message_type(notify_payload
);
516 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Process notify type %s",
517 mapping_find(notify_message_type_m
, notify_message_type
));
519 switch (notify_message_type
)
523 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply contained an INVALID_SYNTAX notify. Deleting IKE_SA");
527 case AUTHENTICATION_FAILED
:
529 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply contained an AUTHENTICATION_FAILED notify. Deleting IKE_SA");
533 case SINGLE_PAIR_REQUIRED
:
535 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply contained a SINGLE_PAIR_REQUIRED notify. Deleting IKE_SA");
541 * - In case of unknown error: IKE_SA gets destroyed.
542 * - In case of unknown status: logging
545 if (notify_message_type
< 16383)
547 this->logger
->log(this->logger
, AUDIT
, "IKE_AUTH reply contained an unknown notify error (%d). Deleting IKE_SA",
548 notify_message_type
);
554 this->logger
->log(this->logger
, CONTROL
, "IKE_AUTH reply contained an unknown notify (%d), ignored.",
555 notify_message_type
);
563 * Implements state_t.get_state
565 static ike_sa_state_t
get_state(private_ike_auth_requested_t
*this)
567 return IKE_AUTH_REQUESTED
;
571 * Implements state_t.get_state
573 static void destroy(private_ike_auth_requested_t
*this)
575 chunk_free(&(this->received_nonce
));
576 chunk_free(&(this->sent_nonce
));
577 chunk_free(&(this->ike_sa_init_reply_data
));
580 this->child_sa
->destroy(this->child_sa
);
584 traffic_selector_t
*ts
;
585 while (this->my_ts
->remove_last(this->my_ts
, (void**)&ts
) == SUCCESS
)
589 this->my_ts
->destroy(this->my_ts
);
593 traffic_selector_t
*ts
;
594 while (this->other_ts
->remove_last(this->other_ts
, (void**)&ts
) == SUCCESS
)
598 this->other_ts
->destroy(this->other_ts
);
602 this->proposal
->destroy(this->proposal
);
607 * Implements protected_ike_sa_t.destroy_after_state_change
609 static void destroy_after_state_change(private_ike_auth_requested_t
*this)
611 chunk_free(&(this->received_nonce
));
612 chunk_free(&(this->sent_nonce
));
613 chunk_free(&(this->ike_sa_init_reply_data
));
616 traffic_selector_t
*ts
;
617 while (this->my_ts
->remove_last(this->my_ts
, (void**)&ts
) == SUCCESS
)
621 this->my_ts
->destroy(this->my_ts
);
625 traffic_selector_t
*ts
;
626 while (this->other_ts
->remove_last(this->other_ts
, (void**)&ts
) == SUCCESS
)
630 this->other_ts
->destroy(this->other_ts
);
634 this->proposal
->destroy(this->proposal
);
640 * Described in header.
642 ike_auth_requested_t
*ike_auth_requested_create(protected_ike_sa_t
*ike_sa
,chunk_t sent_nonce
,chunk_t received_nonce
,chunk_t ike_sa_init_reply_data
, child_sa_t
*child_sa
)
644 private_ike_auth_requested_t
*this = malloc_thing(private_ike_auth_requested_t
);
646 /* interface functions */
647 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
648 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
649 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
651 /* private functions */
652 this->process_idr_payload
= process_idr_payload
;
653 this->process_sa_payload
= process_sa_payload
;
654 this->process_auth_payload
= process_auth_payload
;
655 this->process_ts_payload
= process_ts_payload
;
656 this->process_notify_payload
= process_notify_payload
;
657 this->destroy_after_state_change
= destroy_after_state_change
;
660 this->ike_sa
= ike_sa
;
661 this->received_nonce
= received_nonce
;
662 this->sent_nonce
= sent_nonce
;
663 this->ike_sa_init_reply_data
= ike_sa_init_reply_data
;
664 this->logger
= logger_manager
->get_logger(logger_manager
, IKE_SA
);
666 this->other_ts
= NULL
;
667 this->proposal
= NULL
;
668 this->child_sa
= child_sa
;
670 return &(this->public);