2005-11-23 10:12:45 +00:00
/**
* @ file initiator_init . c
*
2005-12-02 08:05:20 +00:00
* @ brief Implementation of initiator_init_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 "initiator_init.h"
2005-11-29 10:25:07 +00:00
# include <daemon.h>
2005-11-23 10:12:45 +00:00
# include <sa/states/state.h>
# include <sa/states/ike_sa_init_requested.h>
# include <utils/allocator.h>
# include <transforms/diffie_hellman.h>
# include <encoding/payloads/sa_payload.h>
# include <encoding/payloads/ke_payload.h>
# include <encoding/payloads/nonce_payload.h>
2005-11-24 11:30:19 +00:00
typedef struct private_initiator_init_t private_initiator_init_t ;
2005-11-23 10:12:45 +00:00
/**
2005-12-02 08:05:20 +00:00
* Private data of a initiator_init_t object . .
2005-11-23 10:12:45 +00:00
*
*/
2005-11-24 11:30:19 +00:00
struct private_initiator_init_t {
2005-11-23 10:12:45 +00:00
/**
* Methods of the state_t interface .
*/
initiator_init_t public ;
/**
* Assigned IKE_SA .
*/
protected_ike_sa_t * ike_sa ;
/**
* Diffie hellman object used to generate public DH value .
* This objet is passed to the next state of type ike_sa_init_requested_t .
*/
diffie_hellman_t * diffie_hellman ;
/**
* DH group number .
*/
u_int16_t dh_group_number ;
/**
* DH group priority used to get dh_group_number from configuration manager .
* This priority is passed to the next state of type ike_sa_init_requested_t .
*/
u_int16_t dh_group_priority ;
/**
* Sent nonce .
* This nonce is passed to the next state of type ike_sa_init_requested_t .
*/
chunk_t sent_nonce ;
/**
* Logger used to log : - )
*
* Is logger of ike_sa !
*/
logger_t * logger ;
/**
* Builds the IKE_SA_INIT request message .
*
* @ param this calling object
* @ param message the created message will be stored at this location
*/
2005-11-28 20:29:47 +00:00
void ( * build_ike_sa_init_request ) ( private_initiator_init_t * this , message_t * * message ) ;
2005-11-23 10:12:45 +00:00
/**
* Builds the SA payload for this state .
*
* @ param this calling object
* @ param payload The generated SA payload object of type ke_payload_t is
* stored at this location .
*/
2005-11-28 20:29:47 +00:00
void ( * build_sa_payload ) ( private_initiator_init_t * this , payload_t * * payload ) ;
2005-11-23 10:12:45 +00:00
/**
* Builds the KE payload for this state .
*
* @ param this calling object
* @ param payload The generated KE payload object of type ke_payload_t is
* stored at this location .
*/
2005-11-28 20:29:47 +00:00
void ( * build_ke_payload ) ( private_initiator_init_t * this , payload_t * * payload ) ;
2005-11-23 10:12:45 +00:00
/**
* Builds the NONCE payload for this state .
*
* @ param this calling object
* @ param payload The generated NONCE payload object of type ke_payload_t is
* stored at this location .
*/
2005-11-28 20:29:47 +00:00
void ( * build_nonce_payload ) ( private_initiator_init_t * this , payload_t * * payload ) ;
2005-11-23 10:12:45 +00:00
/**
* Destroy function called internally of this class after state change succeeded .
*
* This destroy function does not destroy objects which were passed to the new state .
*
* @ param this calling object
*/
2005-11-28 20:29:47 +00:00
void ( * destroy_after_state_change ) ( private_initiator_init_t * this ) ;
2005-11-23 10:12:45 +00:00
} ;
/**
2005-12-02 08:52:01 +00:00
* Implementation of initiator_init_t . initiate_connection .
2005-11-23 10:12:45 +00:00
*/
2005-11-25 13:42:02 +00:00
static status_t initiate_connection ( private_initiator_init_t * this , char * name )
2005-11-23 10:12:45 +00:00
{
2005-12-02 08:05:20 +00:00
init_config_t * init_config ;
sa_config_t * sa_config ;
2005-11-28 20:29:47 +00:00
status_t status ;
2005-11-25 13:42:02 +00:00
2005-11-23 10:12:45 +00:00
this - > logger - > log ( this - > logger , CONTROL , " Initializing connection %s " , name ) ;
2005-12-01 17:16:10 +00:00
status = charon - > configuration_manager - > get_init_config_for_name ( charon - > configuration_manager , name , & init_config ) ;
2005-11-23 10:12:45 +00:00
if ( status ! = SUCCESS )
{
2005-12-01 17:16:10 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Could not retrieve INIT configuration informations for %s " , name ) ;
2005-11-23 10:12:45 +00:00
return INVALID_ARG ;
}
2005-12-01 17:16:10 +00:00
this - > ike_sa - > set_init_config ( this - > ike_sa , init_config ) ;
2005-12-01 19:53:48 +00:00
status = charon - > configuration_manager - > get_sa_config_for_name ( charon - > configuration_manager , name , & sa_config ) ;
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR | MORE , " Could not retrieve SA configuration informations for %s " , name ) ;
return INVALID_ARG ;
}
this - > ike_sa - > set_sa_config ( this - > ike_sa , sa_config ) ;
2005-12-02 08:52:01 +00:00
/* host informations are read from configuration */
2005-12-01 17:16:10 +00:00
this - > ike_sa - > set_other_host ( this - > ike_sa , init_config - > get_other_host_clone ( init_config ) ) ;
this - > ike_sa - > set_my_host ( this - > ike_sa , init_config - > get_my_host_clone ( init_config ) ) ;
this - > dh_group_number = init_config - > get_dh_group_number ( init_config , this - > dh_group_priority ) ;
if ( this - > dh_group_number = = MODP_UNDEFINED )
2005-11-28 20:29:47 +00:00
{
2005-12-01 17:16:10 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Diffie hellman group could not be retrieved with priority %d " , this - > dh_group_priority ) ;
2005-11-23 10:12:45 +00:00
return INVALID_ARG ;
}
2005-11-29 10:25:07 +00:00
2005-12-02 08:52:01 +00:00
/* next step is done in retry_initiate_connection */
return this - > public . retry_initiate_connection ( & ( this - > public ) , this - > dh_group_priority ) ;
}
/**
* Implementation of initiator_init_t . retry_initiate_connection .
*/
status_t retry_initiate_connection ( private_initiator_init_t * this , int dh_group_priority )
{
ike_sa_init_requested_t * next_state ;
init_config_t * init_config ;
randomizer_t * randomizer ;
message_t * message ;
packet_t * packet ;
status_t status ;
init_config = this - > ike_sa - > get_init_config ( this - > ike_sa ) ;
2005-11-23 10:12:45 +00:00
2005-12-02 08:52:01 +00:00
this - > dh_group_number = init_config - > get_dh_group_number ( init_config , dh_group_priority ) ;
if ( this - > dh_group_number = = MODP_UNDEFINED )
2005-11-23 10:12:45 +00:00
{
2005-12-02 08:52:01 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Diffie hellman group could not be retrieved with priority %d " , this - > dh_group_priority ) ;
return INVALID_ARG ;
2005-11-23 10:12:45 +00:00
}
2005-12-02 08:52:01 +00:00
this - > diffie_hellman = diffie_hellman_create ( this - > dh_group_number ) ;
2005-11-23 10:12:45 +00:00
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Get pseudo random bytes for nonce " ) ;
2005-11-25 13:42:02 +00:00
randomizer = this - > ike_sa - > get_randomizer ( this - > ike_sa ) ;
2005-11-28 20:29:47 +00:00
randomizer - > allocate_pseudo_random_bytes ( randomizer , NONCE_SIZE , & ( this - > sent_nonce ) ) ;
this - > logger - > log ( this - > logger , RAW | MOST , " Nonce " , & ( this - > sent_nonce ) ) ;
this - > build_ike_sa_init_request ( this , & message ) ;
2005-11-23 10:12:45 +00:00
/* generate packet */
2005-11-27 14:04:16 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " generate packet from message " ) ;
2005-11-28 15:43:05 +00:00
status = message - > generate ( message , NULL , NULL , & packet ) ;
2005-11-23 10:12:45 +00:00
if ( status ! = SUCCESS )
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , ERROR , " could not generate packet from message " ) ;
2005-11-23 10:12:45 +00:00
message - > destroy ( message ) ;
return status ;
}
2005-11-27 14:04:16 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Add packet to global send queue " ) ;
2005-11-29 10:25:07 +00:00
charon - > send_queue - > add ( charon - > send_queue , packet ) ;
2005-11-23 10:12:45 +00:00
/* state can now be changed */
2005-11-27 14:04:16 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Create next state object " ) ;
2005-11-23 10:12:45 +00:00
next_state = ike_sa_init_requested_create ( this - > ike_sa , this - > dh_group_number , this - > diffie_hellman , this - > sent_nonce ) ;
2005-11-25 13:42:02 +00:00
/* last message can now be set */
status = this - > ike_sa - > set_last_requested_message ( this - > ike_sa , message ) ;
if ( status ! = SUCCESS )
2005-11-23 10:12:45 +00:00
{
2005-11-25 13:42:02 +00:00
this - > logger - > log ( this - > logger , ERROR , " Could not set last requested message " ) ;
( next_state - > state_interface ) . destroy ( & ( next_state - > state_interface ) ) ;
message - > destroy ( message ) ;
return status ;
2005-11-23 10:12:45 +00:00
}
2005-11-25 13:42:02 +00:00
/* state can now be changed */
this - > ike_sa - > set_new_state ( this - > ike_sa , ( state_t * ) next_state ) ;
2005-11-23 10:12:45 +00:00
/* state has NOW changed :-) */
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Changed state of IKE_SA from %s to %s " , mapping_find ( ike_sa_state_m , INITIATOR_INIT ) , mapping_find ( ike_sa_state_m , IKE_SA_INIT_REQUESTED ) ) ;
2005-11-23 10:12:45 +00:00
2005-11-27 14:04:16 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy old sate object " ) ;
2005-11-23 10:12:45 +00:00
this - > destroy_after_state_change ( this ) ;
return SUCCESS ;
}
/**
* implements private_initiator_init_t . build_ike_sa_init_request
*/
2005-11-28 20:29:47 +00:00
static void build_ike_sa_init_request ( private_initiator_init_t * this , message_t * * request )
2005-11-23 10:12:45 +00:00
{
payload_t * payload ;
message_t * message ;
/* going to build message */
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Going to build message " ) ;
this - > ike_sa - > build_message ( this - > ike_sa , IKE_SA_INIT , TRUE , & message ) ;
2005-11-23 10:12:45 +00:00
2005-11-28 20:29:47 +00:00
/* build SA payload */
this - > build_sa_payload ( this , & payload ) ;
this - > logger - > log ( this - > logger , CONTROL | MOST , " add SA payload to message " ) ;
2005-11-28 16:55:46 +00:00
message - > add_payload ( message , payload ) ;
2005-11-28 20:29:47 +00:00
2005-11-23 10:12:45 +00:00
/* build KE payload */
2005-11-28 20:29:47 +00:00
this - > build_ke_payload ( this , & payload ) ;
this - > logger - > log ( this - > logger , CONTROL | MOST , " add KE payload to message " ) ;
2005-11-28 16:55:46 +00:00
message - > add_payload ( message , payload ) ;
2005-11-23 10:12:45 +00:00
/* build Nonce payload */
2005-11-28 20:29:47 +00:00
this - > build_nonce_payload ( this , & payload ) ;
this - > logger - > log ( this - > logger , CONTROL | MOST , " add nonce payload to message " ) ;
2005-11-28 16:55:46 +00:00
message - > add_payload ( message , payload ) ;
2005-11-23 10:12:45 +00:00
* request = message ;
}
/**
* implements private_initiator_init_t . build_sa_payload
*/
2005-11-28 20:29:47 +00:00
static void build_sa_payload ( private_initiator_init_t * this , payload_t * * payload )
2005-11-23 10:12:45 +00:00
{
sa_payload_t * sa_payload ;
2005-12-01 17:16:10 +00:00
size_t proposal_count ;
ike_proposal_t * proposals ;
init_config_t * init_config ;
2005-11-23 10:12:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " building sa payload " ) ;
2005-12-01 17:16:10 +00:00
init_config = this - > ike_sa - > get_init_config ( this - > ike_sa ) ;
2005-11-23 10:12:45 +00:00
2005-12-01 17:16:10 +00:00
proposal_count = init_config - > get_proposals ( init_config , & proposals ) ;
2005-11-23 10:12:45 +00:00
2005-12-01 17:16:10 +00:00
sa_payload = sa_payload_create_from_ike_proposals ( proposals , proposal_count ) ;
allocator_free ( proposals ) ;
2005-11-23 10:12:45 +00:00
* payload = ( payload_t * ) sa_payload ;
}
/**
* implements private_initiator_init_t . build_ke_payload
*/
2005-11-28 20:29:47 +00:00
static void build_ke_payload ( private_initiator_init_t * this , payload_t * * payload )
2005-11-23 10:12:45 +00:00
{
ke_payload_t * ke_payload ;
chunk_t key_data ;
2005-11-28 20:29:47 +00:00
2005-11-23 10:12:45 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " building ke payload " ) ;
2005-11-28 20:29:47 +00:00
this - > diffie_hellman - > get_my_public_value ( this - > diffie_hellman , & key_data ) ;
2005-11-23 10:12:45 +00:00
ke_payload = ke_payload_create ( ) ;
ke_payload - > set_dh_group_number ( ke_payload , this - > dh_group_number ) ;
2005-11-28 20:29:47 +00:00
ke_payload - > set_key_exchange_data ( ke_payload , key_data ) ;
2005-11-23 10:12:45 +00:00
2005-11-28 20:29:47 +00:00
allocator_free_chunk ( & key_data ) ;
2005-11-23 10:12:45 +00:00
* payload = ( payload_t * ) ke_payload ;
}
/**
* implements private_initiator_init_t . build_nonce_payload
*/
2005-11-28 20:29:47 +00:00
static void build_nonce_payload ( private_initiator_init_t * this , payload_t * * payload )
2005-11-23 10:12:45 +00:00
{
nonce_payload_t * nonce_payload ;
this - > logger - > log ( this - > logger , CONTROL | MORE , " building nonce payload " ) ;
2005-11-28 20:29:47 +00:00
nonce_payload = nonce_payload_create ( ) ;
2005-11-23 10:12:45 +00:00
2005-11-28 20:29:47 +00:00
nonce_payload - > set_nonce ( nonce_payload , this - > sent_nonce ) ;
2005-11-23 10:12:45 +00:00
2005-11-28 20:29:47 +00:00
* payload = ( payload_t * ) nonce_payload ;
2005-11-23 10:12:45 +00:00
}
/**
* Implements state_t . get_state
*/
static status_t process_message ( private_initiator_init_t * this , message_t * message , state_t * * new_state )
{
* new_state = ( state_t * ) this ;
this - > logger - > log ( this - > logger , ERROR | MORE , " In state INITIATOR_INIT no message is processed " ) ;
return FAILED ;
}
/**
* Implements state_t . get_state
*/
static ike_sa_state_t get_state ( private_initiator_init_t * this )
{
return INITIATOR_INIT ;
}
/**
* Implements state_t . get_state
*/
2005-11-28 20:29:47 +00:00
static void destroy ( private_initiator_init_t * this )
2005-11-23 10:12:45 +00:00
{
this - > logger - > log ( this - > logger , CONTROL | MORE , " Going to destroy initiator_init_t state object " ) ;
/* destroy stored proposal */
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy stored proposals " ) ;
2005-12-01 17:16:10 +00:00
2005-11-23 10:12:45 +00:00
/* destroy diffie hellman object */
if ( this - > diffie_hellman ! = NULL )
{
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy diffie_hellman_t object " ) ;
this - > diffie_hellman - > destroy ( this - > diffie_hellman ) ;
}
if ( this - > sent_nonce . ptr ! = NULL )
{
this - > logger - > log ( this - > logger , CONTROL | MOST , " Free memory of sent nonce " ) ;
allocator_free ( this - > sent_nonce . ptr ) ;
}
allocator_free ( this ) ;
}
/**
* Implements private_initiator_init_t . destroy_after_state_change
*/
2005-11-28 20:29:47 +00:00
static void destroy_after_state_change ( private_initiator_init_t * this )
2005-11-23 10:12:45 +00:00
{
this - > logger - > log ( this - > logger , CONTROL | MORE , " Going to destroy initiator_init_t state object " ) ;
/* destroy stored proposal */
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy stored proposals " ) ;
allocator_free ( this ) ;
}
/*
* Described in header .
*/
initiator_init_t * initiator_init_create ( protected_ike_sa_t * ike_sa )
{
private_initiator_init_t * this = allocator_alloc_thing ( private_initiator_init_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
/* public functions */
2005-11-25 13:42:02 +00:00
this - > public . initiate_connection = ( status_t ( * ) ( initiator_init_t * , char * ) ) initiate_connection ;
2005-12-02 08:52:01 +00:00
this - > public . retry_initiate_connection = ( status_t ( * ) ( initiator_init_t * , int ) ) retry_initiate_connection ;
2005-11-23 10:12:45 +00:00
/* private functions */
this - > destroy_after_state_change = destroy_after_state_change ;
this - > build_ike_sa_init_request = build_ike_sa_init_request ;
this - > build_nonce_payload = build_nonce_payload ;
this - > build_sa_payload = build_sa_payload ;
this - > build_ke_payload = build_ke_payload ;
/* private data */
this - > ike_sa = ike_sa ;
this - > dh_group_priority = 1 ;
2005-11-25 13:42:02 +00:00
this - > logger = this - > ike_sa - > get_logger ( this - > ike_sa ) ;
2005-11-23 10:12:45 +00:00
this - > sent_nonce = CHUNK_INITIALIZER ;
2005-11-28 20:29:47 +00:00
2005-11-23 10:12:45 +00:00
return & ( this - > public ) ;
}