#include "ike_sa_init_requested.h"
+#include "../globals.h"
#include "../utils/allocator.h"
#include "../transforms/diffie_hellman.h"
#include "../payloads/sa_payload.h"
* Diffie Hellman object used to compute shared secret
*/
diffie_hellman_t *diffie_hellman;
+
+ /**
+ * Shared secret of successful exchange
+ */
+ chunk_t shared_secret;
+
/**
* Sent nonce value
*/
*/
chunk_t received_nonce;
+ crypter_t *crypter;
+ signer_t *signer;
+ prf_t *prf;
+
/**
* DH group priority used to get dh_group_number from configuration manager.
- * Currently not used but usable if informational messages of unsupported dh group number are processed.
+ *
+ * Currently uused but usable if informational messages of unsupported dh group number are processed.
*/
u_int16_t dh_group_priority;
*/
static status_t process_message(private_ike_sa_init_requested_t *this, message_t *message, state_t **new_state)
{
- status_t status;
- linked_list_iterator_t *payloads;
- message_t *response;
+ status_t status;
+ linked_list_iterator_t *payloads;
+ exchange_type_t exchange_type;
+
+ exchange_type = message->get_exchange_type(message);
+ if (exchange_type != IKE_SA_INIT)
+ {
+ this->logger->log(this->logger, ERROR | MORE, "Message of type %s not supported in state ike_sa_init_requested",mapping_find(exchange_type_m,exchange_type));
+ return FAILED;
+ }
+
+ if (message->get_request(message))
+ {
+ this->logger->log(this->logger, ERROR | MORE, "Only responses of type IKE_SA_INIT supported in state ike_sa_init_requested");
+ return FAILED;
+ }
/* parse incoming message */
status = message->parse_body(message);
if (status != SUCCESS)
{
- this->logger->log(this->logger, ERROR, "Could not parse body");
+ this->logger->log(this->logger, ERROR | MORE, "Could not parse body");
return status;
}
+
/* iterate over incoming payloads */
status = message->get_payload_iterator(message, &payloads);
if (status != SUCCESS)
{
+ this->logger->log(this->logger, ERROR, "Could not create payload interator");
return status;
}
while (payloads->has_next(payloads))
this->logger->log(this->logger, CONTROL|MORE, "Processing payload %s", mapping_find(payload_type_m, payload->get_type(payload)));
switch (payload->get_type(payload))
{
-// case SECURITY_ASSOCIATION:
-// {
-// sa_payload_t *sa_payload = (sa_payload_t*)payload;
-// linked_list_iterator_t *suggested_proposals, *accepted_proposals;
-// /* create a list for accepted proposals */
-// if (this->ike_sa_init_data.proposals == NULL) {
-// this->ike_sa_init_data.proposals = linked_list_create();
-// }
-// else
-// {
-// /** @todo destroy list contents */
-// }
-// if (this->ike_sa_init_data.proposals == NULL)
-// {
-// payloads->destroy(payloads);
-// return OUT_OF_RES;
-// }
-// status = this->ike_sa_init_data.proposals->create_iterator(this->ike_sa_init_data.proposals, &accepted_proposals, FALSE);
-// if (status != SUCCESS)
-// {
-// payloads->destroy(payloads);
-// return status;
-// }
-//
-// /* get the list of suggested proposals */
-// status = sa_payload->create_proposal_substructure_iterator(sa_payload, &suggested_proposals, TRUE);
-// if (status != SUCCESS)
-// {
-// accepted_proposals->destroy(accepted_proposals);
-// payloads->destroy(payloads);
-// return status;
-// }
-//
-// /* now let the configuration-manager select a subset of the proposals */
-// status = global_configuration_manager->select_proposals_for_host(global_configuration_manager,
-// this->other.host, suggested_proposals, accepted_proposals);
-// if (status != SUCCESS)
-// {
-// suggested_proposals->destroy(suggested_proposals);
-// accepted_proposals->destroy(accepted_proposals);
-// payloads->destroy(payloads);
-// return status;
-// }
-//
-// suggested_proposals->destroy(suggested_proposals);
-// accepted_proposals->destroy(accepted_proposals);
-//
-// /* ok, we have what we need for sa_payload */
-// break;
-// }
- case KEY_EXCHANGE:
+ case SECURITY_ASSOCIATION:
{
- ke_payload_t *ke_payload = (ke_payload_t*)payload;
- diffie_hellman_t *dh;
- chunk_t shared_secret;
-
- dh = this->diffie_hellman;
+ sa_payload_t *sa_payload = (sa_payload_t*)payload;
+ linked_list_iterator_t *suggested_proposals;
+
+ /* get the list of suggested proposals */
+ status = sa_payload->create_proposal_substructure_iterator(sa_payload, &suggested_proposals, TRUE);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "Fatal errror: Could not create iterator on suggested proposals");
+ payloads->destroy(payloads);
+ return status;
+ }
+
+ if (this->crypter != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy existing crypter object");
+ this->crypter->destroy(this->crypter);
+ this->crypter = NULL;
+ }
- status = dh->set_other_public_value(dh, ke_payload->get_key_exchange_data(ke_payload));
+ if (this->signer != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy existing signer object");
+ this->signer->destroy(this->signer);
+ this->signer = NULL;
+ }
+
+ if (this->prf != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy existing prf object");
+ this->prf->destroy(this->prf);
+ this->prf = NULL;
+ }
+
+ /* now let the configuration-manager return the transforms for the given proposal*/
+ this->logger->log(this->logger, CONTROL | MOST, "Get transforms for suggested proposal");
+ status = global_configuration_manager->get_transforms_for_host_and_proposals(global_configuration_manager,
+ this->ike_sa->other.host, suggested_proposals, &(this->crypter),&(this->signer),&(this->prf));
if (status != SUCCESS)
{
- dh->destroy(dh);
+ this->logger->log(this->logger, ERROR | MORE, "Suggested proposals not supported!");
+ suggested_proposals->destroy(suggested_proposals);
payloads->destroy(payloads);
- return OUT_OF_RES;
+ return status;
}
- status = dh->get_shared_secret(dh, &shared_secret);
-
- this->logger->log_chunk(this->logger, RAW, "Shared secret", &shared_secret);
-
- allocator_free_chunk(shared_secret);
+ suggested_proposals->destroy(suggested_proposals);
+
+ /* ok, we have what we need for sa_payload */
+ break;
+ }
+ case KEY_EXCHANGE:
+ {
+ ke_payload_t *ke_payload = (ke_payload_t*)payload;
+
+ status = this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload));
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, ERROR, "Could not set other public value for DH exchange. Status %s",mapping_find(status_m,status));
+ payloads->destroy(payloads);
+ return OUT_OF_RES;
+ }
+ /* shared secret is computed AFTER processing of all payloads... */
break;
}
case NONCE:
{
- nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
- chunk_t nonce;
-
- nonce_payload->get_nonce(nonce_payload, &nonce);
- /** @todo free if there is already one */
- this->received_nonce.ptr = allocator_clone_bytes(nonce.ptr, nonce.len);
- this->received_nonce.len = nonce.len;
- if (this->received_nonce.ptr == NULL)
+ nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
+
+ if (this->received_nonce.ptr != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy existing received nonce");
+ allocator_free(this->received_nonce.ptr);
+ this->received_nonce.ptr = NULL;
+ this->received_nonce.len = 0;
+ }
+
+ status = nonce_payload->get_nonce(nonce_payload, &(this->received_nonce));
+ if (status != SUCCESS)
{
+ this->logger->log(this->logger, ERROR, "Fatal error: Could not get received nonce");
payloads->destroy(payloads);
return OUT_OF_RES;
}
+
break;
}
default:
{
- /** @todo handle */
+ this->logger->log(this->logger, ERROR, "Fatal errror: Payload type not supported!!!!");
+ payloads->destroy(payloads);
+ return FAILED;
}
}
}
payloads->destroy(payloads);
+ if (this->shared_secret.ptr != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy existing shared_secret");
+ allocator_free(this->shared_secret.ptr);
+ this->shared_secret.ptr = NULL;
+ this->shared_secret.len = 0;
+ }
+
+
+ /* store shared secret */
+ this->logger->log(this->logger, CONTROL | MOST, "Retrieve shared secret and store it");
+ status = this->diffie_hellman->get_shared_secret(this->diffie_hellman, &(this->shared_secret));
+ this->logger->log_chunk(this->logger, RAW, "Shared secret", &this->shared_secret);
+
+
+
+ /****************************
+ *
+ * TODO
+ *
+ * Create PRF+ object
+ *
+ * Create Keys for next process
+ *
+ * Send IKE_SA_AUTH request
+ *
+ ****************************/
+
/* set up the reply */
// status = this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response);
// response->destroy(response);
- *new_state = this;
+ *new_state = (state_t *) this;
return SUCCESS;
}
static status_t destroy(private_ike_sa_init_requested_t *this)
{
this->logger->log(this->logger, CONTROL | MORE, "Going to destroy state of type ike_sa_init_requested_t");
+
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie hellman object");
this->diffie_hellman->destroy(this->diffie_hellman);
if (this->sent_nonce.ptr != NULL)
{
this->logger->log(this->logger, CONTROL | MOST, "Destroy received nonce");
allocator_free(this->received_nonce.ptr);
}
+
+ if (this->shared_secret.ptr != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy shared secret");
+ allocator_free(this->shared_secret.ptr);
+ }
+
+ if (this->crypter != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy crypter object");
+ this->crypter->destroy(this->crypter);
+ }
+
+ if (this->signer != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy signer object");
+ this->signer->destroy(this->signer);
+ }
+
+ if (this->prf != NULL)
+ {
+ this->logger->log(this->logger, CONTROL | MOST, "Destroy prf object");
+ this->prf->destroy(this->prf);
+ }
allocator_free(this);
return SUCCESS;
this->ike_sa = ike_sa;
this->received_nonce.ptr = NULL;
this->received_nonce.len = 0;
+ this->shared_secret.ptr = NULL;
+ this->shared_secret.len = 0;
this->logger = this->ike_sa->logger;
this->diffie_hellman = diffie_hellman;
this->sent_nonce = sent_nonce;
this->dh_group_priority = dh_group_priority;
+ this->crypter = NULL;
+ this->signer = NULL;
+ this->prf = NULL;
+
return &(this->public);
}