2005-11-23 10:12:45 +00:00
|
|
|
/**
|
|
|
|
* @file ike_sa_established.c
|
|
|
|
*
|
2005-11-29 08:08:03 +00:00
|
|
|
* @brief Implementation of ike_sa_established_t.
|
2005-11-23 10:12:45 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2005 Jan Hutter, Martin Willi
|
|
|
|
* Hochschule fuer Technik Rapperswil
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
|
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ike_sa_established.h"
|
|
|
|
|
|
|
|
#include <utils/allocator.h>
|
2005-12-12 14:14:52 +00:00
|
|
|
#include <encoding/payloads/delete_payload.h>
|
2005-11-23 10:12:45 +00:00
|
|
|
|
2005-11-24 11:30:19 +00:00
|
|
|
|
|
|
|
typedef struct private_ike_sa_established_t private_ike_sa_established_t;
|
|
|
|
|
2005-11-23 10:12:45 +00:00
|
|
|
/**
|
|
|
|
* Private data of a ike_sa_established_t object.
|
|
|
|
*/
|
2005-11-24 11:30:19 +00:00
|
|
|
struct private_ike_sa_established_t {
|
2005-11-23 10:12:45 +00:00
|
|
|
/**
|
|
|
|
* methods of the state_t interface
|
|
|
|
*/
|
|
|
|
ike_sa_established_t public;
|
|
|
|
|
|
|
|
/**
|
2005-12-12 14:14:52 +00:00
|
|
|
* Assigned IKE_SA.
|
2005-11-23 10:12:45 +00:00
|
|
|
*/
|
|
|
|
protected_ike_sa_t *ike_sa;
|
|
|
|
|
2005-12-12 14:14:52 +00:00
|
|
|
/**
|
|
|
|
* Assigned logger. Use logger of IKE_SA.
|
|
|
|
*/
|
|
|
|
logger_t *logger;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process a notify payload
|
|
|
|
*
|
|
|
|
* @param this calling object
|
|
|
|
* @param notify_payload notify payload
|
|
|
|
* @param response response message of type INFORMATIONAL
|
|
|
|
*
|
|
|
|
* - SUCCESS
|
|
|
|
* - FAILED
|
|
|
|
* - DELETE_ME
|
|
|
|
*/
|
|
|
|
status_t (*process_notify_payload) (private_ike_sa_established_t *this, notify_payload_t *notify_payload,message_t *response);
|
2005-11-23 10:12:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements state_t.get_state
|
|
|
|
*/
|
2005-11-25 13:42:02 +00:00
|
|
|
static status_t process_message(private_ike_sa_established_t *this, message_t *message)
|
2005-11-23 10:12:45 +00:00
|
|
|
{
|
2005-12-12 14:14:52 +00:00
|
|
|
delete_payload_t *delete_request = NULL;
|
2005-12-12 14:29:54 +00:00
|
|
|
ike_sa_id_t *ike_sa_id;
|
2005-12-12 14:14:52 +00:00
|
|
|
iterator_t *payloads;
|
|
|
|
message_t *response;
|
|
|
|
crypter_t *crypter;
|
|
|
|
signer_t *signer;
|
|
|
|
status_t status;
|
|
|
|
|
|
|
|
if (message->get_exchange_type(message) != INFORMATIONAL)
|
|
|
|
{
|
|
|
|
this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_established",
|
|
|
|
mapping_find(exchange_type_m,message->get_exchange_type(message)));
|
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!message->get_request(message))
|
|
|
|
{
|
|
|
|
this->logger->log(this->logger, ERROR | LEVEL1, "INFORMATIONAL responses not handled in state ike_sa_established");
|
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
|
2005-12-12 14:29:54 +00:00
|
|
|
ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public));
|
|
|
|
|
2005-12-12 14:14:52 +00:00
|
|
|
/* get signer for verification and crypter for decryption */
|
2005-12-12 14:29:54 +00:00
|
|
|
if (!ike_sa_id->is_initiator(ike_sa_id))
|
|
|
|
{
|
|
|
|
crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
|
|
|
|
signer = this->ike_sa->get_signer_initiator(this->ike_sa);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
|
|
|
|
signer = this->ike_sa->get_signer_responder(this->ike_sa);
|
|
|
|
}
|
2005-12-12 14:14:52 +00:00
|
|
|
|
|
|
|
/* parse incoming message */
|
|
|
|
status = message->parse_body(message, crypter, signer);
|
|
|
|
if (status != SUCCESS)
|
|
|
|
{
|
|
|
|
this->logger->log(this->logger, AUDIT, "INFORMATIONAL request decryption failed. Ignoring message");
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* build empty INFORMATIONAL message */
|
|
|
|
this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &response);
|
|
|
|
|
|
|
|
payloads = message->get_payload_iterator(message);
|
|
|
|
|
|
|
|
while (payloads->has_next(payloads))
|
|
|
|
{
|
|
|
|
payload_t *payload;
|
|
|
|
payloads->current(payloads, (void**)&payload);
|
|
|
|
|
|
|
|
switch (payload->get_type(payload))
|
|
|
|
{
|
|
|
|
case NOTIFY:
|
|
|
|
{
|
|
|
|
notify_payload_t *notify_payload = (notify_payload_t *) payload;
|
|
|
|
/* handle the notify directly, abort if no further processing required */
|
|
|
|
status = this->process_notify_payload(this, notify_payload,response);
|
|
|
|
if (status != SUCCESS)
|
|
|
|
{
|
|
|
|
payloads->destroy(payloads);
|
|
|
|
response->destroy(response);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case DELETE:
|
|
|
|
{
|
|
|
|
delete_request = (delete_payload_t *) payload;
|
2006-03-14 13:22:48 +00:00
|
|
|
break;
|
2005-12-12 14:14:52 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)",
|
|
|
|
mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* iterator can be destroyed */
|
|
|
|
payloads->destroy(payloads);
|
|
|
|
|
|
|
|
if (delete_request)
|
2006-03-14 13:22:48 +00:00
|
|
|
{
|
|
|
|
if (delete_request->get_protocol_id(delete_request) == IKE)
|
2005-12-12 14:14:52 +00:00
|
|
|
{
|
2006-03-14 13:22:48 +00:00
|
|
|
this->logger->log(this->logger, AUDIT, "DELETE request for IKE_SA received");
|
2005-12-12 14:14:52 +00:00
|
|
|
response->destroy(response);
|
2006-03-14 13:22:48 +00:00
|
|
|
return DELETE_ME;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->logger->log(this->logger, AUDIT, "DELETE request for CHILD_SA received. Ignored");
|
|
|
|
response->destroy(response);
|
|
|
|
return SUCCESS;
|
2005-12-12 14:14:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
status = this->ike_sa->send_response(this->ike_sa, response);
|
|
|
|
/* message can now be sent (must not be destroyed) */
|
|
|
|
if (status != SUCCESS)
|
|
|
|
{
|
|
|
|
this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL reply");
|
|
|
|
response->destroy(response);
|
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-11-23 10:12:45 +00:00
|
|
|
/**
|
2005-12-12 14:14:52 +00:00
|
|
|
* Implementation of private_ike_sa_established_t.process_notify_payload;
|
|
|
|
*/
|
|
|
|
static status_t process_notify_payload (private_ike_sa_established_t *this, notify_payload_t *notify_payload, message_t *response)
|
|
|
|
{
|
|
|
|
notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload);
|
|
|
|
|
|
|
|
this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s for protocol %s",
|
|
|
|
mapping_find(notify_message_type_m, notify_message_type),
|
|
|
|
mapping_find(protocol_id_m, notify_payload->get_protocol_id(notify_payload)));
|
|
|
|
|
|
|
|
switch (notify_message_type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
this->logger->log(this->logger, AUDIT, "INFORMATIONAL request contained an unknown notify (%d), ignored.", notify_message_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implementation of state_t.get_state.
|
2005-11-23 10:12:45 +00:00
|
|
|
*/
|
|
|
|
static ike_sa_state_t get_state(private_ike_sa_established_t *this)
|
|
|
|
{
|
|
|
|
return IKE_SA_ESTABLISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2005-12-12 14:14:52 +00:00
|
|
|
* Implementation of state_t.get_state
|
2005-11-23 10:12:45 +00:00
|
|
|
*/
|
2005-11-28 20:29:47 +00:00
|
|
|
static void destroy(private_ike_sa_established_t *this)
|
2005-11-23 10:12:45 +00:00
|
|
|
{
|
|
|
|
allocator_free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Described in header.
|
|
|
|
*/
|
|
|
|
ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa)
|
|
|
|
{
|
|
|
|
private_ike_sa_established_t *this = allocator_alloc_thing(private_ike_sa_established_t);
|
|
|
|
|
|
|
|
/* interface functions */
|
2005-11-25 13:42:02 +00:00
|
|
|
this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
|
2005-11-23 10:12:45 +00:00
|
|
|
this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
|
2005-11-28 20:29:47 +00:00
|
|
|
this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
|
2005-11-23 10:12:45 +00:00
|
|
|
|
2005-12-12 14:14:52 +00:00
|
|
|
/* private functions */
|
|
|
|
this->process_notify_payload = process_notify_payload;
|
|
|
|
|
2005-11-23 10:12:45 +00:00
|
|
|
/* private data */
|
|
|
|
this->ike_sa = ike_sa;
|
2005-12-12 14:14:52 +00:00
|
|
|
this->logger = ike_sa->get_logger(ike_sa);
|
2005-11-23 10:12:45 +00:00
|
|
|
|
|
|
|
return &(this->public);
|
|
|
|
}
|