2005-11-08 13:33:28 +00:00
/**
* @ file ike_sa . c
2005-11-09 09:11:06 +00:00
*
2005-11-08 13:33:28 +00:00
* @ brief Class ike_sa_t . An object of this type is managed by an
2005-11-10 09:35:28 +00:00
* ike_sa_manager_t object and represents an IKE_SA
2005-11-09 09:11:06 +00:00
*
2005-11-08 13:33:28 +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 .
*/
2005-11-11 13:52:11 +00:00
# include "ike_sa.h"
2005-11-08 13:33:28 +00:00
# include "types.h"
2005-11-16 16:05:46 +00:00
# include "globals.h"
2005-11-18 10:31:56 +00:00
# include "definitions.h"
2005-11-11 13:52:11 +00:00
# include "utils/allocator.h"
2005-11-11 13:31:52 +00:00
# include "utils/linked_list.h"
2005-11-16 16:05:46 +00:00
# include "utils/logger_manager.h"
# include "utils/randomizer.h"
2005-11-18 10:31:56 +00:00
# include "transforms/diffie_hellman.h"
2005-11-16 16:05:46 +00:00
# include "payloads/sa_payload.h"
# include "payloads/nonce_payload.h"
# include "payloads/ke_payload.h"
# include "payloads/transform_substructure.h"
# include "payloads/transform_attribute.h"
2005-11-08 13:33:28 +00:00
2005-11-21 13:45:26 +00:00
/**
* Nonce size in bytes of all sent nonces
*/
# define NONCE_SIZE 16
2005-11-08 13:33:28 +00:00
/**
* States in which a IKE_SA can actually be
*/
typedef enum ike_sa_state_e ike_sa_state_t ;
2005-11-16 16:05:46 +00:00
enum ike_sa_state_e {
2005-11-08 13:33:28 +00:00
/**
* IKE_SA is is not in a state
*/
2005-11-17 11:23:51 +00:00
NO_STATE = 1 ,
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/**
* A IKE_SA_INIT - message was sent : role initiator
*/
2005-11-17 11:23:51 +00:00
IKE_SA_INIT_REQUESTED = 2 ,
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/**
* A IKE_SA_INIT - message was replied : role responder
*/
2005-11-17 11:23:51 +00:00
IKE_SA_INIT_RESPONDED = 3 ,
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/**
2005-11-09 09:11:06 +00:00
* An IKE_AUTH - message was sent after a successful
2005-11-08 13:33:28 +00:00
* IKE_SA_INIT - exchange : role initiator
*/
2005-11-17 11:23:51 +00:00
IKE_AUTH_REQUESTED = 4 ,
2005-11-08 13:33:28 +00:00
/**
* An IKE_AUTH - message was replied : role responder .
2005-11-09 09:11:06 +00:00
* In this state , all the informations for an IKE_SA
2005-11-08 13:33:28 +00:00
* and one CHILD_SA are known .
*/
2005-11-17 11:23:51 +00:00
IKE_SA_INITIALIZED = 5
2005-11-08 13:33:28 +00:00
} ;
2005-11-18 10:31:56 +00:00
/**
* string mappings for ike_sa_state
*/
mapping_t ike_sa_state_m [ ] = {
{ NO_STATE , " NO_STATE " } ,
{ IKE_SA_INIT_REQUESTED , " IKE_SA_INIT_REQUESTED " } ,
{ IKE_SA_INIT_RESPONDED , " IKE_SA_INIT_RESPONDED " } ,
{ IKE_AUTH_REQUESTED , " IKE_AUTH_REQUESTED " } ,
{ IKE_SA_INITIALIZED , " IKE_SA_INITIALIZED " } ,
{ MAPPING_END , NULL }
} ;
2005-11-08 13:33:28 +00:00
/**
* Private data of an message_t object
*/
typedef struct private_ike_sa_s private_ike_sa_t ;
2005-11-09 09:11:06 +00:00
struct private_ike_sa_s {
2005-11-08 13:33:28 +00:00
/**
* Public part of a ike_sa_t object
*/
ike_sa_t public ;
2005-11-16 16:05:46 +00:00
2005-11-21 10:59:45 +00:00
/**
* Builds an empty IKEv2 - Message
*
* Depending on the type of message ( request or response ) , the message id is
* either message_id_out or message_id_in .
*
*
* @ param this calling object
* @ param type exchange type of new message
* @ param request TRUE , if message has to be a request
* @ param message new message is stored at this location
* @ return
* - SUCCESS
* - OUT_OF_RES
*/
status_t ( * build_message ) ( private_ike_sa_t * this , exchange_type_t type , bool request , message_t * * message ) ;
2005-11-16 16:05:46 +00:00
status_t ( * build_sa_payload ) ( private_ike_sa_t * this , sa_payload_t * * payload ) ;
2005-11-18 13:59:21 +00:00
status_t ( * build_ke_payload ) ( private_ike_sa_t * this , ke_payload_t * * payload ) ;
2005-11-16 16:05:46 +00:00
status_t ( * build_nonce_payload ) ( private_ike_sa_t * this , nonce_payload_t * * payload ) ;
2005-11-18 10:31:56 +00:00
2005-11-21 10:59:45 +00:00
status_t ( * create_delete_job ) ( private_ike_sa_t * this ) ;
status_t ( * resend_last_reply ) ( private_ike_sa_t * this ) ;
2005-11-18 12:01:53 +00:00
2005-11-18 13:59:21 +00:00
status_t ( * transto_ike_sa_init_requested ) ( private_ike_sa_t * this , char * name ) ;
2005-11-18 10:31:56 +00:00
status_t ( * transto_ike_sa_init_responded ) ( private_ike_sa_t * this , message_t * message ) ;
status_t ( * transto_ike_auth_requested ) ( private_ike_sa_t * this , message_t * message ) ;
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/* Private values */
/**
* Identifier for the current IKE_SA
*/
ike_sa_id_t * ike_sa_id ;
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/**
* Linked List containing the child sa ' s of the current IKE_SA
*/
linked_list_t * child_sas ;
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/**
* Current state of the IKE_SA
*/
2005-11-18 10:31:56 +00:00
ike_sa_state_t state ;
2005-11-16 16:05:46 +00:00
/**
* this SA ' s source for random data
*/
randomizer_t * randomizer ;
2005-11-18 14:56:34 +00:00
/**
2005-11-21 09:21:34 +00:00
* contains the last responded message
2005-11-18 14:56:34 +00:00
*
*/
2005-11-21 09:21:34 +00:00
message_t * last_responded_message ;
2005-11-18 15:10:19 +00:00
/**
2005-11-21 09:21:34 +00:00
* contains the last requested message
2005-11-18 15:10:19 +00:00
*
*/
2005-11-21 09:21:34 +00:00
message_t * last_requested_message ;
2005-11-16 16:05:46 +00:00
2005-11-21 09:21:34 +00:00
/**
* Informations of this host
*/
2005-11-16 17:16:35 +00:00
struct {
host_t * host ;
} me ;
2005-11-21 09:21:34 +00:00
/**
* Informations of the other host
*/
2005-11-16 17:16:35 +00:00
struct {
host_t * host ;
} other ;
2005-11-18 10:31:56 +00:00
2005-11-18 12:24:12 +00:00
struct {
/**
* Diffie Hellman object used to compute shared secret
*/
diffie_hellman_t * diffie_hellman ;
2005-11-21 10:59:45 +00:00
2005-11-18 12:24:12 +00:00
/**
* Diffie Hellman group number
*/
u_int16_t dh_group_number ;
/**
* Priority used get matching dh_group number
*/
u_int16_t dh_group_priority ;
2005-11-18 16:29:14 +00:00
/**
* selected proposals
*/
linked_list_t * proposals ;
2005-11-21 10:59:45 +00:00
2005-11-18 14:56:34 +00:00
/**
2005-11-21 09:21:34 +00:00
* Sent nonce value
2005-11-18 14:56:34 +00:00
*/
chunk_t sent_nonce ;
2005-11-21 10:59:45 +00:00
2005-11-18 14:56:34 +00:00
/**
2005-11-21 09:21:34 +00:00
* received nonce value
2005-11-18 14:56:34 +00:00
*/
chunk_t received_nonce ;
2005-11-18 12:24:12 +00:00
} ike_sa_init_data ;
/**
* next message id to receive
*/
2005-11-18 12:01:53 +00:00
u_int32_t message_id_in ;
2005-11-18 12:24:12 +00:00
/**
* next message id to send
*/
2005-11-18 12:01:53 +00:00
u_int32_t message_id_out ;
2005-11-16 16:05:46 +00:00
/**
* a logger for this IKE_SA
*/
logger_t * logger ;
2005-11-08 13:33:28 +00:00
} ;
/**
* @ brief implements function process_message of private_ike_sa_t
*/
static status_t process_message ( private_ike_sa_t * this , message_t * message )
2005-11-18 10:31:56 +00:00
{
2005-11-18 14:56:34 +00:00
u_int32_t message_id ;
2005-11-18 15:10:19 +00:00
bool is_request ;
2005-11-21 10:59:45 +00:00
exchange_type_t exchange_type ;
/* we must process each request or response from remote host
* the check if a given message is possible for a given state is done in here
*/
/* find out type of message (request or response) */
2005-11-18 15:10:19 +00:00
is_request = message - > get_request ( message ) ;
2005-11-21 10:59:45 +00:00
exchange_type = message - > get_exchange_type ( message ) ;
2005-11-18 15:10:19 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Process %s message of exchange type %s " , ( is_request ) ? " REQUEST " : " RESPONSE " ,
2005-11-21 10:59:45 +00:00
mapping_find ( exchange_type_m , exchange_type ) ) ;
message_id = message - > get_message_id ( message ) ;
2005-11-18 15:10:19 +00:00
2005-11-21 10:59:45 +00:00
/*
* It has to be checked , if the message has to be resent cause of lost packets !
*/
if ( is_request & & ( message_id = = ( this - > message_id_in - 1 ) ) )
{
/* message can be resent ! */
this - > logger - > log ( this - > logger , CONTROL | MORE , " Resent message detected. Send stored reply " ) ;
return ( this - > resend_last_reply ( this ) ) ;
}
2005-11-18 14:56:34 +00:00
2005-11-21 10:59:45 +00:00
/* Now, the message id is checked for request AND reply */
if ( is_request )
{
/* In a request, the message has to be this->message_id_in (other case is already handled) */
if ( message_id ! = this - > message_id_in )
{
this - > logger - > log ( this - > logger , ERROR | MORE , " Message request with message id %d received, but %d expected " , message_id , this - > message_id_in ) ;
return FAILED ;
}
}
else
{
/* In a reply, the message has to be this->message_id_out -1 cause it is the reply to the last sent message*/
if ( message_id ! = ( this - > message_id_out - 1 ) )
{
this - > logger - > log ( this - > logger , ERROR | MORE , " Message reply with message id %d received, but %d expected " , message_id , this - > message_id_in ) ;
return FAILED ;
}
}
2005-11-18 14:56:34 +00:00
2005-11-21 10:59:45 +00:00
/* Now, the exchange type is checked and the appropriate transition handler is called*/
2005-11-18 10:31:56 +00:00
switch ( message - > get_exchange_type ( message ) )
{
case IKE_SA_INIT :
{
2005-11-21 10:59:45 +00:00
2005-11-18 10:31:56 +00:00
if ( message - > get_request ( message ) ) {
if ( this - > state = = NO_STATE )
{
/* state transission NO_STATE => IKE_SA_INIT_RESPONDED */
return this - > transto_ike_sa_init_responded ( this , message ) ;
}
}
else
{
if ( this - > state = = IKE_SA_INIT_REQUESTED )
{
/* state transission IKE_SA_INIT_REQUESTED => IKE_AUTH_REQUESTED*/
return this - > transto_ike_auth_requested ( this , message ) ;
}
}
2005-11-21 13:45:26 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Message in current state %s not supported " , mapping_find ( ike_sa_state_m , this - > state ) ) ;
2005-11-18 10:31:56 +00:00
break ;
}
case IKE_AUTH :
{
2005-11-21 10:59:45 +00:00
if ( this - > state < = IKE_SA_INIT_REQUESTED )
{
this - > logger - > log ( this - > logger , ERROR | MORE , " Current state %s of IKE_SA does not allow IKE_AUTH message " , mapping_find ( ike_sa_state_m , this - > state ) ) ;
return FAILED ;
}
break ;
2005-11-18 10:31:56 +00:00
}
case CREATE_CHILD_SA :
{
2005-11-21 10:59:45 +00:00
if ( this - > state < IKE_SA_INITIALIZED )
{
this - > logger - > log ( this - > logger , ERROR | MORE , " Current state %s of IKE_SA does not allow CREATE_CHILD_SA message " , mapping_find ( ike_sa_state_m , this - > state ) ) ;
return FAILED ;
}
break ;
2005-11-18 10:31:56 +00:00
}
case INFORMATIONAL :
{
2005-11-21 10:59:45 +00:00
break ;
2005-11-18 10:31:56 +00:00
}
default :
{
this - > logger - > log ( this - > logger , ERROR , " processing %s-message not supported. " ,
mapping_find ( exchange_type_m , message - > get_exchange_type ( message ) ) ) ;
return NOT_SUPPORTED ;
}
}
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL , " received %s-message in state %s, not handled. " ,
2005-11-18 10:31:56 +00:00
mapping_find ( exchange_type_m , message - > get_exchange_type ( message ) ) ,
mapping_find ( ike_sa_state_m , this - > state ) ) ;
return INVALID_STATE ;
}
2005-11-21 10:59:45 +00:00
/**
* @ brief Implements function build_message of private_ike_sa_t .
*/
2005-11-18 13:59:21 +00:00
static status_t build_message ( private_ike_sa_t * this , exchange_type_t type , bool request , message_t * * message )
2005-11-18 12:01:53 +00:00
{
status_t status ;
2005-11-18 13:59:21 +00:00
message_t * new_message ;
2005-11-18 12:01:53 +00:00
host_t * source , * destination ;
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " build empty message " ) ;
2005-11-18 13:59:21 +00:00
new_message = message_create ( ) ;
if ( new_message = = NULL )
2005-11-18 12:01:53 +00:00
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: could not create empty message object " ) ;
2005-11-18 12:01:53 +00:00
return OUT_OF_RES ;
}
status = this - > me . host - > clone ( this - > me . host , & source ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: could not clone my host information " ) ;
new_message - > destroy ( new_message ) ;
return status ;
}
status = this - > other . host - > clone ( this - > other . host , & destination ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Fatal error: could not clone other host information " ) ;
source - > destroy ( source ) ;
2005-11-18 13:59:21 +00:00
new_message - > destroy ( new_message ) ;
2005-11-18 12:01:53 +00:00
return status ;
}
2005-11-21 10:59:45 +00:00
2005-11-18 13:59:21 +00:00
new_message - > set_source ( new_message , source ) ;
new_message - > set_destination ( new_message , destination ) ;
new_message - > set_exchange_type ( new_message , type ) ;
new_message - > set_request ( new_message , request ) ;
2005-11-18 12:01:53 +00:00
2005-11-21 10:59:45 +00:00
new_message - > set_message_id ( new_message , ( request ) ? this - > message_id_out : this - > message_id_in ) ;
status = new_message - > set_ike_sa_id ( new_message , this - > ike_sa_id ) ;
if ( status ! = SUCCESS )
2005-11-18 15:10:19 +00:00
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: could not set ike_sa_id of message " ) ;
new_message - > destroy ( new_message ) ;
return status ;
2005-11-18 15:10:19 +00:00
}
2005-11-18 14:56:34 +00:00
2005-11-18 13:59:21 +00:00
* message = new_message ;
2005-11-18 12:01:53 +00:00
return SUCCESS ;
}
2005-11-21 10:59:45 +00:00
/**
* @ brief Implements function transto_ike_sa_init_requested of private_ike_sa_t .
*/
2005-11-18 13:59:21 +00:00
static status_t transto_ike_sa_init_requested ( private_ike_sa_t * this , char * name )
{
2005-11-18 14:56:34 +00:00
message_t * message ;
payload_t * payload ;
packet_t * packet ;
status_t status ;
2005-11-21 13:45:26 +00:00
linked_list_iterator_t * proposal_iterator ;
2005-11-18 14:56:34 +00:00
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL , " Initializing connection %s " , name ) ;
2005-11-18 14:56:34 +00:00
status = global_configuration_manager - > get_local_host ( global_configuration_manager , name , & ( this - > me . host ) ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Could not retrieve local host configuration information for %s " , name ) ;
2005-11-18 14:56:34 +00:00
return INVALID_ARG ;
}
status = global_configuration_manager - > get_remote_host ( global_configuration_manager , name , & ( this - > other . host ) ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Could not retrieve remote host configuration information for %s " , name ) ;
2005-11-18 14:56:34 +00:00
return INVALID_ARG ;
}
status = global_configuration_manager - > get_dh_group_number ( global_configuration_manager , name , & ( this - > ike_sa_init_data . dh_group_number ) , this - > ike_sa_init_data . dh_group_priority ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Could not retrieve DH group number for %s " , name ) ;
2005-11-18 14:56:34 +00:00
return INVALID_ARG ;
}
2005-11-21 13:45:26 +00:00
if ( this - > ike_sa_init_data . proposals - > get_count ( this - > ike_sa_init_data . proposals ) > 0 )
{
this - > logger - > log ( this - > logger , ERROR , " Proposals allready existing! " ) ;
return FAILED ;
}
status = this - > ike_sa_init_data . proposals - > create_iterator ( this - > ike_sa_init_data . proposals , & proposal_iterator , FALSE ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not create iterator on list for proposals " ) ;
return status ;
}
status = global_configuration_manager - > get_proposals_for_host ( global_configuration_manager , this - > other . host , proposal_iterator ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR | MORE , " Could not retrieve Proposals for %s " , name ) ;
return status ;
}
/* not needed anymore */
proposal_iterator - > destroy ( proposal_iterator ) ;
2005-11-18 14:56:34 +00:00
if ( this - > ike_sa_init_data . diffie_hellman ! = NULL )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Object of type diffie_hellman_t already existing! " ) ;
2005-11-18 14:56:34 +00:00
return FAILED ;
}
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " create diffie hellman object " ) ;
2005-11-18 14:56:34 +00:00
this - > ike_sa_init_data . diffie_hellman = diffie_hellman_create ( this - > ike_sa_init_data . dh_group_number ) ;
if ( this - > ike_sa_init_data . diffie_hellman = = NULL )
{
this - > logger - > log ( this - > logger , ERROR , " Object of type diffie_hellman_t could not be created! " ) ;
return FAILED ;
}
if ( this - > ike_sa_init_data . sent_nonce . ptr ! = NULL )
{
this - > logger - > log ( this - > logger , ERROR , " Nonce for IKE_SA_INIT phase already existing! " ) ;
return FAILED ;
}
2005-11-21 13:45:26 +00:00
if ( this - > randomizer - > allocate_pseudo_random_bytes ( this - > randomizer , NONCE_SIZE , & ( this - > ike_sa_init_data . sent_nonce ) ) ! = SUCCESS )
2005-11-18 14:56:34 +00:00
{
this - > logger - > log ( this - > logger , ERROR , " Could not create nonce! " ) ;
return OUT_OF_RES ;
}
/* going to build message */
status = this - > build_message ( this , IKE_SA_INIT , TRUE , & message ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not build message " ) ;
return status ;
}
/* build SA payload */
status = this - > build_sa_payload ( this , ( sa_payload_t * * ) & payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not build SA payload " ) ;
message - > destroy ( message ) ;
return status ;
}
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " add SA payload to message " ) ;
status = message - > add_payload ( message , payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add SA payload to message " ) ;
message - > destroy ( message ) ;
return status ;
}
2005-11-18 14:56:34 +00:00
/* build KE payload */
status = this - > build_ke_payload ( this , ( ke_payload_t * * ) & payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not build KE payload " ) ;
message - > destroy ( message ) ;
return status ;
}
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " add KE payload to message " ) ;
status = message - > add_payload ( message , payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add KE payload to message " ) ;
message - > destroy ( message ) ;
return status ;
}
2005-11-18 13:59:21 +00:00
2005-11-18 14:56:34 +00:00
/* build Nonce payload */
status = this - > build_nonce_payload ( this , ( nonce_payload_t * * ) & payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not build NONCE payload " ) ;
message - > destroy ( message ) ;
return status ;
}
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " add nonce payload to message " ) ;
status = message - > add_payload ( message , payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add nonce payload to message " ) ;
message - > destroy ( message ) ;
return status ;
}
2005-11-21 13:45:26 +00:00
/* generate packet */
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " generate packet from message " ) ;
2005-11-18 14:56:34 +00:00
status = message - > generate ( message , & packet ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: could not generate packet from message " ) ;
2005-11-18 14:56:34 +00:00
message - > destroy ( message ) ;
return status ;
}
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Add packet to global send queue " ) ;
2005-11-18 14:56:34 +00:00
status = global_send_queue - > add ( global_send_queue , packet ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add packet to send queue " ) ;
message - > destroy ( message ) ;
return status ;
}
2005-11-21 09:21:34 +00:00
if ( this - > last_requested_message ! = NULL )
2005-11-18 14:56:34 +00:00
{
/* destroy message */
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy stored last requested message " ) ;
2005-11-21 09:21:34 +00:00
this - > last_requested_message - > destroy ( this - > last_requested_message ) ;
2005-11-18 14:56:34 +00:00
}
2005-11-21 09:21:34 +00:00
this - > last_requested_message = message ;
2005-11-18 15:10:19 +00:00
/* message counter can now be increased */
this - > message_id_out + + ;
2005-11-18 14:56:34 +00:00
2005-11-21 13:45:26 +00:00
/* state has NOW changed :-) */
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Change state of IKE_SA from %s to %s " , mapping_find ( ike_sa_state_m , this - > state ) , mapping_find ( ike_sa_state_m , IKE_SA_INIT_REQUESTED ) ) ;
2005-11-18 14:56:34 +00:00
this - > state = IKE_SA_INIT_REQUESTED ;
return SUCCESS ;
2005-11-18 13:59:21 +00:00
}
2005-11-18 16:29:14 +00:00
static status_t transto_ike_sa_init_responded ( private_ike_sa_t * this , message_t * request )
2005-11-08 13:33:28 +00:00
{
2005-11-17 08:47:11 +00:00
status_t status ;
2005-11-18 10:31:56 +00:00
linked_list_iterator_t * payloads ;
2005-11-18 16:29:14 +00:00
message_t * response ;
host_t * source , * destination ;
2005-11-21 13:45:26 +00:00
payload_t * payload ;
packet_t * packet ;
2005-11-17 08:47:11 +00:00
2005-11-18 16:29:14 +00:00
/* this is the first message we process, so copy host infos */
request - > get_source ( request , & source ) ;
request - > get_destination ( request , & destination ) ;
/* we need to clone them, since we destroy the message later */
destination - > clone ( destination , & ( this - > me . host ) ) ;
source - > clone ( source , & ( this - > other . host ) ) ;
/* parse incoming message */
status = request - > parse_body ( request ) ;
2005-11-18 10:31:56 +00:00
if ( status ! = SUCCESS )
2005-11-17 11:20:39 +00:00
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Could not parse body of request message " ) ;
this - > create_delete_job ( this ) ;
2005-11-18 10:31:56 +00:00
return status ;
}
2005-11-21 10:59:45 +00:00
/* iterate over incoming payloads. We can be sure, the message contains only accepted payloads! */
2005-11-18 16:29:14 +00:00
status = request - > get_payload_iterator ( request , & payloads ) ;
2005-11-18 10:31:56 +00:00
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not get payload interator " ) ;
this - > create_delete_job ( this ) ;
return status ;
2005-11-17 11:20:39 +00:00
}
2005-11-21 10:59:45 +00:00
2005-11-18 10:31:56 +00:00
while ( payloads - > has_next ( payloads ) )
{
payload_t * payload ;
2005-11-21 10:59:45 +00:00
/* get current payload */
2005-11-18 16:29:14 +00:00
payloads - > current ( payloads , ( void * * ) & payload ) ;
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Processing payload of type %s " , mapping_find ( payload_type_m , payload - > get_type ( payload ) ) ) ;
2005-11-18 10:31:56 +00:00
switch ( payload - > get_type ( payload ) )
{
case SECURITY_ASSOCIATION :
{
2005-11-18 16:29:14 +00:00
sa_payload_t * sa_payload = ( sa_payload_t * ) payload ;
linked_list_iterator_t * suggested_proposals , * accepted_proposals ;
2005-11-21 10:59:45 +00:00
2005-11-18 16:29:14 +00:00
status = this - > ike_sa_init_data . proposals - > create_iterator ( this - > ike_sa_init_data . proposals , & accepted_proposals , FALSE ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not create iterator on list for proposals " ) ;
2005-11-18 16:29:14 +00:00
payloads - > destroy ( payloads ) ;
2005-11-21 10:59:45 +00:00
this - > create_delete_job ( this ) ;
2005-11-18 16:29:14 +00:00
return status ;
}
/* get the list of suggested proposals */
status = sa_payload - > create_proposal_substructure_iterator ( sa_payload , & suggested_proposals , TRUE ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not create iterator on suggested proposals " ) ;
2005-11-18 16:29:14 +00:00
accepted_proposals - > destroy ( accepted_proposals ) ;
payloads - > destroy ( payloads ) ;
2005-11-21 10:59:45 +00:00
this - > create_delete_job ( this ) ;
2005-11-18 16:29:14 +00:00
return status ;
}
2005-11-18 10:31:56 +00:00
2005-11-18 16:29:14 +00:00
/* 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 ) ;
2005-11-18 10:31:56 +00:00
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " No proposal of suggested proposals selected " ) ;
2005-11-18 16:29:14 +00:00
suggested_proposals - > destroy ( suggested_proposals ) ;
accepted_proposals - > destroy ( accepted_proposals ) ;
2005-11-18 10:31:56 +00:00
payloads - > destroy ( payloads ) ;
2005-11-21 10:59:45 +00:00
this - > create_delete_job ( this ) ;
2005-11-18 10:31:56 +00:00
return status ;
}
2005-11-21 10:59:45 +00:00
/* iterators are not needed anymore */
2005-11-18 16:29:14 +00:00
suggested_proposals - > destroy ( suggested_proposals ) ;
accepted_proposals - > destroy ( accepted_proposals ) ;
2005-11-18 10:31:56 +00:00
2005-11-21 13:45:26 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " SA Payload processed " ) ;
2005-11-21 10:59:45 +00:00
/* ok, we have what we need for sa_payload (proposals are stored in this->proposals)*/
2005-11-18 10:31:56 +00:00
break ;
}
case KEY_EXCHANGE :
{
2005-11-18 16:29:14 +00:00
ke_payload_t * ke_payload = ( ke_payload_t * ) payload ;
diffie_hellman_group_t group ;
2005-11-21 10:59:45 +00:00
diffie_hellman_t * dh ;
2005-11-18 16:29:14 +00:00
bool allowed_group ;
group = ke_payload - > get_dh_group_number ( ke_payload ) ;
status = global_configuration_manager - > is_dh_group_allowed_for_host ( global_configuration_manager ,
this - > other . host , group , & allowed_group ) ;
2005-11-21 10:59:45 +00:00
2005-11-18 16:29:14 +00:00
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Could not get informations about DH group " ) ;
2005-11-18 16:29:14 +00:00
payloads - > destroy ( payloads ) ;
2005-11-21 10:59:45 +00:00
this - > create_delete_job ( this ) ;
2005-11-18 16:29:14 +00:00
return status ;
}
if ( ! allowed_group )
{
2005-11-21 10:59:45 +00:00
/** @todo Send info reply */
2005-11-18 16:29:14 +00:00
}
2005-11-21 10:59:45 +00:00
/* create diffie hellman object to handle DH exchange */
2005-11-18 16:29:14 +00:00
dh = diffie_hellman_create ( group ) ;
if ( dh = = NULL )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Could not generate DH object " ) ;
2005-11-18 16:29:14 +00:00
payloads - > destroy ( payloads ) ;
2005-11-21 10:59:45 +00:00
this - > create_delete_job ( this ) ;
2005-11-18 16:29:14 +00:00
return OUT_OF_RES ;
}
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Set other DH public value " ) ;
2005-11-18 16:29:14 +00:00
status = dh - > set_other_public_value ( dh , ke_payload - > get_key_exchange_data ( ke_payload ) ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Could not set other DH public value " ) ;
2005-11-18 16:29:14 +00:00
dh - > destroy ( dh ) ;
payloads - > destroy ( payloads ) ;
2005-11-21 10:59:45 +00:00
this - > create_delete_job ( this ) ;
2005-11-18 16:29:14 +00:00
return OUT_OF_RES ;
}
2005-11-21 13:45:26 +00:00
if ( this - > ike_sa_init_data . diffie_hellman ! = NULL )
{
this - > logger - > log ( this - > logger , CONTROL | MORE , " Going to destroy allready existing diffie_hellman object " ) ;
this - > ike_sa_init_data . diffie_hellman - > destroy ( this - > ike_sa_init_data . diffie_hellman ) ;
}
2005-11-18 16:29:14 +00:00
this - > ike_sa_init_data . diffie_hellman = dh ;
2005-11-21 13:45:26 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " KE Payload processed " ) ;
2005-11-18 10:31:56 +00:00
break ;
}
case NONCE :
{
2005-11-18 16:29:14 +00:00
nonce_payload_t * nonce_payload = ( nonce_payload_t * ) payload ;
chunk_t nonce ;
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Get nonce value and store it " ) ;
2005-11-18 16:29:14 +00:00
nonce_payload - > get_nonce ( nonce_payload , & nonce ) ;
/** @todo free if there is already one */
this - > ike_sa_init_data . received_nonce . ptr = allocator_clone_bytes ( nonce . ptr , nonce . len ) ;
this - > ike_sa_init_data . received_nonce . len = nonce . len ;
if ( this - > ike_sa_init_data . received_nonce . ptr = = NULL )
{
payloads - > destroy ( payloads ) ;
2005-11-21 10:59:45 +00:00
this - > create_delete_job ( this ) ;
2005-11-18 16:29:14 +00:00
return OUT_OF_RES ;
}
2005-11-21 13:45:26 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Nonce Payload processed " ) ;
2005-11-18 10:31:56 +00:00
break ;
}
default :
{
2005-11-21 13:45:26 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Payload type not supported! " ) ;
payloads - > destroy ( payloads ) ;
this - > create_delete_job ( this ) ;
return OUT_OF_RES ;
2005-11-18 10:31:56 +00:00
}
}
}
2005-11-21 10:59:45 +00:00
/* iterator can be destroyed */
2005-11-18 16:29:14 +00:00
payloads - > destroy ( payloads ) ;
2005-11-18 10:31:56 +00:00
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Request successfully handled. Going to create reply. " ) ;
2005-11-18 16:29:14 +00:00
2005-11-21 13:45:26 +00:00
if ( this - > ike_sa_init_data . sent_nonce . ptr ! = NULL )
{
this - > logger - > log ( this - > logger , ERROR , " Nonce for IKE_SA_INIT phase already existing! " ) ;
return FAILED ;
}
this - > logger - > log ( this - > logger , CONTROL | MOST , " Going to create nonce. " ) ;
if ( this - > randomizer - > allocate_pseudo_random_bytes ( this - > randomizer , NONCE_SIZE , & ( this - > ike_sa_init_data . sent_nonce ) ) ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not create nonce! " ) ;
return OUT_OF_RES ;
}
2005-11-18 16:29:14 +00:00
/* set up the reply */
status = this - > build_message ( this , IKE_SA_INIT , FALSE , & response ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > logger - > log ( this - > logger , ERROR , " Could not create empty message " ) ;
this - > create_delete_job ( this ) ;
2005-11-18 16:29:14 +00:00
return status ;
}
2005-11-18 10:31:56 +00:00
2005-11-21 13:45:26 +00:00
/* build SA payload */
status = this - > build_sa_payload ( this , ( sa_payload_t * * ) & payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not build SA payload " ) ;
this - > create_delete_job ( this ) ;
response - > destroy ( response ) ;
return status ;
}
this - > logger - > log ( this - > logger , CONTROL | MOST , " add SA payload to message " ) ;
status = response - > add_payload ( response , payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add SA payload to message " ) ;
this - > create_delete_job ( this ) ;
response - > destroy ( response ) ;
return status ;
}
/* build KE payload */
status = this - > build_ke_payload ( this , ( ke_payload_t * * ) & payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not build KE payload " ) ;
this - > create_delete_job ( this ) ;
response - > destroy ( response ) ;
return status ;
}
this - > logger - > log ( this - > logger , CONTROL | MOST , " add KE payload to message " ) ;
status = response - > add_payload ( response , payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add KE payload to message " ) ;
this - > create_delete_job ( this ) ;
response - > destroy ( response ) ;
return status ;
}
/* build Nonce payload */
status = this - > build_nonce_payload ( this , ( nonce_payload_t * * ) & payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not build NONCE payload " ) ;
this - > create_delete_job ( this ) ;
response - > destroy ( response ) ;
return status ;
}
this - > logger - > log ( this - > logger , CONTROL | MOST , " add nonce payload to message " ) ;
status = response - > add_payload ( response , payload ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add nonce payload to message " ) ;
this - > create_delete_job ( this ) ;
response - > destroy ( response ) ;
return status ;
}
/* generate packet */
this - > logger - > log ( this - > logger , CONTROL | MOST , " generate packet from message " ) ;
status = response - > generate ( response , & packet ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Fatal error: could not generate packet from message " ) ;
this - > create_delete_job ( this ) ;
response - > destroy ( response ) ;
return status ;
}
this - > logger - > log ( this - > logger , CONTROL | MOST , " Add packet to global send queue " ) ;
status = global_send_queue - > add ( global_send_queue , packet ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add packet to send queue " ) ;
this - > create_delete_job ( this ) ;
response - > destroy ( response ) ;
return status ;
}
if ( this - > last_responded_message ! = NULL )
{
/* destroy message */
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy stored last responded message " ) ;
this - > last_responded_message - > destroy ( this - > last_responded_message ) ;
}
this - > last_responded_message = response ;
/* state has NOW changed :-) */
this - > logger - > log ( this - > logger , CONTROL | MORE , " Change state of IKE_SA from %s to %s " , mapping_find ( ike_sa_state_m , this - > state ) , mapping_find ( ike_sa_state_m , IKE_SA_INIT_REQUESTED ) ) ;
this - > state = IKE_SA_INIT_RESPONDED ;
2005-11-18 10:31:56 +00:00
return SUCCESS ;
}
2005-11-18 16:29:14 +00:00
static status_t transto_ike_auth_requested ( private_ike_sa_t * this , message_t * response )
{
status_t status ;
linked_list_iterator_t * payloads ;
/* parse incoming message */
status = response - > parse_body ( response ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not parse body " ) ;
return status ;
}
/* iterate over incoming payloads */
status = response - > get_payload_iterator ( response , & payloads ) ;
if ( status ! = SUCCESS )
{
response - > destroy ( response ) ;
return status ;
}
while ( payloads - > has_next ( payloads ) )
{
payload_t * payload ;
payloads - > current ( payloads , ( void * * ) & payload ) ;
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 :
{
ke_payload_t * ke_payload = ( ke_payload_t * ) payload ;
diffie_hellman_t * dh ;
chunk_t shared_secret ;
dh = this - > ike_sa_init_data . diffie_hellman ;
2005-11-21 13:45:26 +00:00
2005-11-18 16:29:14 +00:00
status = dh - > set_other_public_value ( dh , ke_payload - > get_key_exchange_data ( ke_payload ) ) ;
if ( status ! = SUCCESS )
{
dh - > destroy ( dh ) ;
payloads - > destroy ( payloads ) ;
return OUT_OF_RES ;
}
status = dh - > get_shared_secret ( dh , & shared_secret ) ;
this - > logger - > log_chunk ( this - > logger , RAW , " Shared secret " , & shared_secret ) ;
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 - > ike_sa_init_data . received_nonce . ptr = allocator_clone_bytes ( nonce . ptr , nonce . len ) ;
this - > ike_sa_init_data . received_nonce . len = nonce . len ;
if ( this - > ike_sa_init_data . received_nonce . ptr = = NULL )
{
payloads - > destroy ( payloads ) ;
return OUT_OF_RES ;
}
break ;
}
default :
{
/** @todo handle */
}
}
}
payloads - > destroy ( payloads ) ;
printf ( " done. \n " ) ;
/* set up the reply */
status = this - > build_message ( this , IKE_SA_INIT , FALSE , & response ) ;
if ( status ! = SUCCESS )
{
2005-11-21 10:59:45 +00:00
this - > create_delete_job ( this ) ;
2005-11-18 16:29:14 +00:00
return status ;
}
2005-11-21 10:59:45 +00:00
response - > destroy ( response ) ;
2005-11-18 16:29:14 +00:00
2005-11-21 10:59:45 +00:00
return SUCCESS ;
2005-11-18 16:29:14 +00:00
2005-11-08 13:33:28 +00:00
}
/**
* @ brief implements function process_configuration of private_ike_sa_t
*/
2005-11-16 17:16:35 +00:00
static status_t initialize_connection ( private_ike_sa_t * this , char * name )
2005-11-08 13:33:28 +00:00
{
2005-11-18 14:56:34 +00:00
/* work is done in transto_ike_sa_init_requested */
return ( this - > transto_ike_sa_init_requested ( this , name ) ) ;
2005-11-08 13:33:28 +00:00
}
2005-11-08 16:24:18 +00:00
/**
* @ brief implements function private_ike_sa_t . get_id
*/
static ike_sa_id_t * get_id ( private_ike_sa_t * this )
{
return this - > ike_sa_id ;
}
2005-11-08 13:33:28 +00:00
/**
2005-11-16 16:05:46 +00:00
* implements private_ike_sa_t . build_sa_payload
2005-11-08 13:33:28 +00:00
*/
2005-11-16 16:05:46 +00:00
static status_t build_sa_payload ( private_ike_sa_t * this , sa_payload_t * * payload )
2005-11-08 13:33:28 +00:00
{
2005-11-17 14:28:07 +00:00
sa_payload_t * sa_payload ;
2005-11-21 13:45:26 +00:00
linked_list_iterator_t * proposal_iterator ;
2005-11-17 14:28:07 +00:00
status_t status ;
2005-11-21 13:45:26 +00:00
/* SA payload takes proposals from this->ike_sa_init_data.proposals and writes them to the created sa_payload */
2005-11-17 14:28:07 +00:00
2005-11-18 07:07:32 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " building sa payload " ) ;
2005-11-16 16:05:46 +00:00
2005-11-21 13:45:26 +00:00
status = this - > ike_sa_init_data . proposals - > create_iterator ( this - > ike_sa_init_data . proposals , & proposal_iterator , FALSE ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not create iterator on list for proposals " ) ;
return status ;
}
2005-11-16 16:05:46 +00:00
sa_payload = sa_payload_create ( ) ;
if ( sa_payload = = NULL )
2005-11-08 13:33:28 +00:00
{
2005-11-21 13:45:26 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not create SA payload object " ) ;
2005-11-16 16:05:46 +00:00
return OUT_OF_RES ;
2005-11-08 13:33:28 +00:00
}
2005-11-21 13:45:26 +00:00
while ( proposal_iterator - > has_next ( proposal_iterator ) )
2005-11-17 14:28:07 +00:00
{
2005-11-21 13:45:26 +00:00
proposal_substructure_t * current_proposal ;
proposal_substructure_t * current_proposal_clone ;
status = proposal_iterator - > current ( proposal_iterator , ( void * * ) & current_proposal ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not get current proposal needed to copy " ) ;
sa_payload - > destroy ( sa_payload ) ;
return status ;
}
status = current_proposal - > clone ( current_proposal , & current_proposal_clone ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not clone current proposal " ) ;
sa_payload - > destroy ( sa_payload ) ;
return status ;
}
status = sa_payload - > add_proposal_substructure ( sa_payload , current_proposal_clone ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add cloned proposal to SA payload " ) ;
sa_payload - > destroy ( sa_payload ) ;
return status ;
}
2005-11-17 14:28:07 +00:00
}
2005-11-16 16:05:46 +00:00
2005-11-21 13:45:26 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " sa payload buildet " ) ;
2005-11-17 14:28:07 +00:00
* payload = sa_payload ;
2005-11-16 16:05:46 +00:00
2005-11-17 14:28:07 +00:00
return SUCCESS ;
2005-11-16 16:05:46 +00:00
}
2005-11-09 09:11:06 +00:00
2005-11-18 13:59:21 +00:00
static status_t build_ke_payload ( private_ike_sa_t * this , ke_payload_t * * payload )
{
2005-11-18 14:56:34 +00:00
ke_payload_t * ke_payload ;
chunk_t key_data ;
status_t status ;
this - > logger - > log ( this - > logger , CONTROL | MORE , " building ke payload " ) ;
2005-11-18 13:59:21 +00:00
2005-11-18 14:56:34 +00:00
if ( this - > state ! = NO_STATE )
{
this - > logger - > log ( this - > logger , ERROR , " KE payload in state %s not supported " , mapping_find ( ike_sa_state_m , this - > state ) ) ;
return FALSE ;
}
switch ( this - > ike_sa_id - > is_initiator ( this - > ike_sa_id ) )
{
case TRUE :
2005-11-21 13:45:26 +00:00
case FALSE :
2005-11-18 14:56:34 +00:00
{
this - > logger - > log ( this - > logger , CONTROL | MORE , " get public dh value to send in ke payload " ) ;
status = this - > ike_sa_init_data . diffie_hellman - > get_my_public_value ( this - > ike_sa_init_data . diffie_hellman , & key_data ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not get my DH public value " ) ;
return status ;
}
ke_payload = ke_payload_create ( ) ;
if ( ke_payload = = NULL )
{
this - > logger - > log ( this - > logger , ERROR , " Could not create KE payload " ) ;
allocator_free_chunk ( key_data ) ;
return OUT_OF_RES ;
}
ke_payload - > set_dh_group_number ( ke_payload , MODP_1024_BIT ) ;
if ( ke_payload - > set_key_exchange_data ( ke_payload , key_data ) ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not set key exchange data of KE payload " ) ;
ke_payload - > destroy ( ke_payload ) ;
allocator_free_chunk ( key_data ) ;
return OUT_OF_RES ;
}
allocator_free_chunk ( key_data ) ;
* payload = ke_payload ;
return SUCCESS ;
}
}
return FAILED ;
2005-11-18 13:59:21 +00:00
}
2005-11-16 16:05:46 +00:00
/**
* implements private_ike_sa_t . build_nonce_payload
*/
static status_t build_nonce_payload ( private_ike_sa_t * this , nonce_payload_t * * payload )
{
nonce_payload_t * nonce_payload ;
2005-11-21 13:45:26 +00:00
status_t status ;
2005-11-16 16:05:46 +00:00
2005-11-18 07:07:32 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " building nonce payload " ) ;
2005-11-21 13:45:26 +00:00
if ( this - > state ! = NO_STATE )
{
this - > logger - > log ( this - > logger , ERROR , " Nonce payload in state %s not supported " , mapping_find ( ike_sa_state_m , this - > state ) ) ;
return FALSE ;
}
2005-11-16 16:05:46 +00:00
nonce_payload = nonce_payload_create ( ) ;
if ( nonce_payload = = NULL )
2005-11-21 13:45:26 +00:00
{
this - > logger - > log ( this - > logger , ERROR , " Fatal error: could not create nonce payload object " ) ;
2005-11-16 16:05:46 +00:00
return OUT_OF_RES ;
}
2005-11-18 14:56:34 +00:00
2005-11-21 13:45:26 +00:00
status = nonce_payload - > set_nonce ( nonce_payload , this - > ike_sa_init_data . sent_nonce ) ;
2005-11-16 16:05:46 +00:00
2005-11-21 13:45:26 +00:00
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Fatal error: could not set nonce data of payload " ) ;
nonce_payload - > destroy ( nonce_payload ) ;
return status ;
}
2005-11-16 16:05:46 +00:00
* payload = nonce_payload ;
return SUCCESS ;
}
2005-11-21 10:59:45 +00:00
/**
* @ brief implements function resend_last_reply of private_ike_sa_t
*/
status_t resend_last_reply ( private_ike_sa_t * this )
{
packet_t * packet ;
status_t status ;
status = this - > last_responded_message - > generate ( this - > last_responded_message , & packet ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not generate message to resent " ) ;
return status ;
}
status = global_send_queue - > add ( global_send_queue , packet ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not add packet to send queue " ) ;
packet - > destroy ( packet ) ;
return status ;
}
return SUCCESS ;
}
status_t create_delete_job ( private_ike_sa_t * this )
{
job_t * delete_job ;
status_t status ;
this - > logger - > log ( this - > logger , CONTROL | MORE , " Going to create job to delete this IKE_SA " ) ;
delete_job = ( job_t * ) delete_ike_sa_job_create ( this - > ike_sa_id ) ;
if ( delete_job = = NULL )
{
this - > logger - > log ( this - > logger , ERROR , " Job to delete IKE SA could not be created " ) ;
return FAILED ;
}
status = global_job_queue - > add ( global_job_queue , delete_job ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " %s Job to delete IKE SA could not be added to job queue " , mapping_find ( status_m , status ) ) ;
delete_job - > destroy_all ( delete_job ) ;
return status ;
}
return SUCCESS ;
}
2005-11-16 16:05:46 +00:00
/**
* @ brief implements function destroy of private_ike_sa_t
*/
static status_t destroy ( private_ike_sa_t * this )
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Going to destroy IKE_SA " ) ;
2005-11-18 14:56:34 +00:00
/* destroy child sa's */
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy all child_sa's " ) ;
2005-11-18 14:56:34 +00:00
while ( this - > child_sas - > get_count ( this - > child_sas ) > 0 )
2005-11-16 16:05:46 +00:00
{
2005-11-18 14:56:34 +00:00
void * child_sa ;
if ( this - > child_sas - > remove_first ( this - > child_sas , & child_sa ) ! = SUCCESS )
{
break ;
}
/* destroy child sa */
2005-11-16 16:05:46 +00:00
}
2005-11-08 13:33:28 +00:00
this - > child_sas - > destroy ( this - > child_sas ) ;
2005-11-16 16:05:46 +00:00
2005-11-18 14:56:34 +00:00
/* destroy ike_sa_id */
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy assigned ike_sa_id " ) ;
2005-11-16 16:05:46 +00:00
this - > ike_sa_id - > destroy ( this - > ike_sa_id ) ;
2005-11-18 14:56:34 +00:00
2005-11-21 09:21:34 +00:00
/* destroy stored requested message */
if ( this - > last_requested_message ! = NULL )
2005-11-18 14:56:34 +00:00
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy last requested message " ) ;
this - > last_requested_message - > destroy ( this - > last_requested_message ) ;
2005-11-18 14:56:34 +00:00
}
2005-11-18 15:10:19 +00:00
/* destroy stored responded messages */
2005-11-21 09:21:34 +00:00
if ( this - > last_responded_message ! = NULL )
2005-11-18 15:10:19 +00:00
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy last responded message " ) ;
this - > last_responded_message - > destroy ( this - > last_responded_message ) ;
2005-11-18 15:10:19 +00:00
}
2005-11-21 09:21:34 +00:00
2005-11-21 10:59:45 +00:00
/* destroy stored proposal */
2005-11-21 13:45:26 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy stored proposals " ) ;
while ( this - > ike_sa_init_data . proposals - > get_count ( this - > ike_sa_init_data . proposals ) > 0 )
2005-11-21 10:59:45 +00:00
{
2005-11-21 13:45:26 +00:00
proposal_substructure_t * current_proposal ;
this - > ike_sa_init_data . proposals - > remove_first ( this - > ike_sa_init_data . proposals , ( void * * ) & current_proposal ) ;
current_proposal - > destroy ( current_proposal ) ;
2005-11-21 10:59:45 +00:00
}
2005-11-21 13:45:26 +00:00
this - > ike_sa_init_data . proposals - > destroy ( this - > ike_sa_init_data . proposals ) ;
2005-11-21 10:59:45 +00:00
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy randomizer " ) ;
2005-11-16 16:05:46 +00:00
this - > randomizer - > destroy ( this - > randomizer ) ;
2005-11-21 09:21:34 +00:00
2005-11-21 10:59:45 +00:00
/* destroy ike_sa_init data */
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Going to destroy ike_sa_init data " ) ;
2005-11-18 12:24:12 +00:00
if ( this - > ike_sa_init_data . diffie_hellman ! = NULL )
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy diffie hellman object " ) ;
2005-11-18 12:24:12 +00:00
this - > ike_sa_init_data . diffie_hellman - > destroy ( this - > ike_sa_init_data . diffie_hellman ) ;
}
2005-11-18 14:56:34 +00:00
if ( this - > ike_sa_init_data . sent_nonce . ptr ! = NULL )
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy sent nonce data " ) ;
2005-11-18 14:56:34 +00:00
allocator_free_chunk ( this - > ike_sa_init_data . sent_nonce ) ;
}
if ( this - > ike_sa_init_data . received_nonce . ptr ! = NULL )
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy received nonce data " ) ;
2005-11-18 14:56:34 +00:00
allocator_free_chunk ( this - > ike_sa_init_data . received_nonce ) ;
}
2005-11-16 16:05:46 +00:00
2005-11-21 10:59:45 +00:00
if ( this - > me . host ! = NULL )
{
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy host informations of me " ) ;
this - > me . host - > destroy ( this - > me . host ) ;
}
if ( this - > other . host ! = NULL )
{
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy host informations of other " ) ;
this - > other . host - > destroy ( this - > other . host ) ;
}
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy logger of IKE_SA " ) ;
2005-11-16 16:05:46 +00:00
global_logger_manager - > destroy_logger ( global_logger_manager , this - > logger ) ;
2005-11-08 13:33:28 +00:00
2005-11-09 09:11:06 +00:00
allocator_free ( this ) ;
2005-11-08 13:33:28 +00:00
return SUCCESS ;
}
/*
* Described in Header
*/
ike_sa_t * ike_sa_create ( ike_sa_id_t * ike_sa_id )
{
2005-11-09 09:35:06 +00:00
private_ike_sa_t * this = allocator_alloc_thing ( private_ike_sa_t ) ;
2005-11-08 13:33:28 +00:00
if ( this = = NULL )
{
return NULL ;
}
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/* Public functions */
this - > public . process_message = ( status_t ( * ) ( ike_sa_t * , message_t * ) ) process_message ;
2005-11-16 17:16:35 +00:00
this - > public . initialize_connection = ( status_t ( * ) ( ike_sa_t * , char * ) ) initialize_connection ;
2005-11-09 09:11:06 +00:00
this - > public . get_id = ( ike_sa_id_t * ( * ) ( ike_sa_t * ) ) get_id ;
2005-11-08 13:33:28 +00:00
this - > public . destroy = ( status_t ( * ) ( ike_sa_t * ) ) destroy ;
2005-11-16 16:05:46 +00:00
2005-11-18 14:56:34 +00:00
/* private functions */
2005-11-16 16:05:46 +00:00
this - > build_sa_payload = build_sa_payload ;
this - > build_nonce_payload = build_nonce_payload ;
2005-11-18 13:59:21 +00:00
this - > build_ke_payload = build_ke_payload ;
2005-11-18 12:01:53 +00:00
this - > build_message = build_message ;
2005-11-18 13:59:21 +00:00
this - > transto_ike_sa_init_requested = transto_ike_sa_init_requested ;
2005-11-18 10:31:56 +00:00
this - > transto_ike_sa_init_responded = transto_ike_sa_init_responded ;
this - > transto_ike_auth_requested = transto_ike_auth_requested ;
2005-11-21 10:59:45 +00:00
this - > resend_last_reply = resend_last_reply ;
this - > create_delete_job = create_delete_job ;
2005-11-16 16:05:46 +00:00
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/* initialize private fields */
2005-11-21 09:21:34 +00:00
this - > logger = global_logger_manager - > create_logger ( global_logger_manager , IKE_SA , NULL ) ;
if ( this - > logger = = NULL )
{
allocator_free ( this ) ;
}
2005-11-08 13:33:28 +00:00
if ( ike_sa_id - > clone ( ike_sa_id , & ( this - > ike_sa_id ) ) ! = SUCCESS )
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not clone ike_sa_id " ) ;
global_logger_manager - > destroy_logger ( global_logger_manager , this - > logger ) ;
2005-11-09 09:11:06 +00:00
allocator_free ( this ) ;
2005-11-08 13:33:28 +00:00
return NULL ;
}
this - > child_sas = linked_list_create ( ) ;
if ( this - > child_sas = = NULL )
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not create list for child_sa's " ) ;
2005-11-08 13:33:28 +00:00
this - > ike_sa_id - > destroy ( this - > ike_sa_id ) ;
2005-11-21 09:21:34 +00:00
global_logger_manager - > destroy_logger ( global_logger_manager , this - > logger ) ;
2005-11-09 09:11:06 +00:00
allocator_free ( this ) ;
2005-11-08 13:33:28 +00:00
return NULL ;
}
2005-11-16 16:05:46 +00:00
this - > randomizer = randomizer_create ( ) ;
if ( this - > randomizer = = NULL )
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not create list for child_sa's " ) ;
2005-11-16 16:05:46 +00:00
this - > child_sas - > destroy ( this - > child_sas ) ;
this - > ike_sa_id - > destroy ( this - > ike_sa_id ) ;
2005-11-21 09:21:34 +00:00
global_logger_manager - > destroy_logger ( global_logger_manager , this - > logger ) ;
2005-11-16 16:05:46 +00:00
allocator_free ( this ) ;
}
2005-11-16 17:16:35 +00:00
this - > me . host = NULL ;
this - > other . host = NULL ;
2005-11-18 12:24:12 +00:00
this - > ike_sa_init_data . diffie_hellman = NULL ;
this - > ike_sa_init_data . dh_group_number = 0 ;
/* 1 means highest priority */
this - > ike_sa_init_data . dh_group_priority = 1 ;
2005-11-18 14:56:34 +00:00
this - > ike_sa_init_data . sent_nonce . len = 0 ;
this - > ike_sa_init_data . sent_nonce . ptr = NULL ;
this - > ike_sa_init_data . received_nonce . len = 0 ;
this - > ike_sa_init_data . received_nonce . ptr = NULL ;
2005-11-21 13:45:26 +00:00
this - > ike_sa_init_data . proposals = linked_list_create ( ) ;
if ( this - > ike_sa_init_data . proposals = = NULL )
{
this - > logger - > log ( this - > logger , ERROR , " Fatal error: Could not create list for child_sa's " ) ;
this - > child_sas - > destroy ( this - > child_sas ) ;
this - > ike_sa_id - > destroy ( this - > ike_sa_id ) ;
this - > randomizer - > destroy ( this - > randomizer ) ;
global_logger_manager - > destroy_logger ( global_logger_manager , this - > logger ) ;
allocator_free ( this ) ;
}
2005-11-21 09:21:34 +00:00
this - > last_requested_message = NULL ;
this - > last_responded_message = NULL ;
2005-11-18 12:01:53 +00:00
this - > message_id_out = 0 ;
this - > message_id_in = 0 ;
2005-11-16 17:16:35 +00:00
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/* at creation time, IKE_SA isn't in a specific state */
2005-11-18 10:31:56 +00:00
this - > state = NO_STATE ;
2005-11-09 09:11:06 +00:00
return ( & this - > public ) ;
2005-11-08 13:33:28 +00:00
}