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>
2005-12-02 13:20:20 +00:00
# include <queues/jobs/retransmit_request_job.h>
2005-11-23 10:12:45 +00:00
# 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 .
2005-12-06 08:27:20 +00:00
* This objet is passed to the next state of type IKE_SA_INIT_REQUESTED .
2005-11-23 10:12:45 +00:00
*/
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 .
2005-12-06 08:27:20 +00:00
* This priority is passed to the next state of type IKE_SA_INIT_REQUESTED .
2005-11-23 10:12:45 +00:00
*/
u_int16_t dh_group_priority ;
/**
* Sent nonce .
2005-12-06 08:27:20 +00:00
* This nonce is passed to the next state of type IKE_SA_INIT_REQUESTED .
2005-11-23 10:12:45 +00:00
*/
chunk_t sent_nonce ;
/**
2005-12-06 08:27:20 +00:00
* Assigned logger .
2005-11-23 10:12:45 +00:00
*
* Is logger of ike_sa !
*/
logger_t * logger ;
/**
* Builds the SA payload for this state .
*
* @ param this calling object
2005-12-06 08:27:20 +00:00
* @ param request message_t object to add the SA payload
2005-11-23 10:12:45 +00:00
*/
2005-12-06 08:27:20 +00:00
void ( * build_sa_payload ) ( private_initiator_init_t * this , message_t * request ) ;
2005-11-23 10:12:45 +00:00
/**
* Builds the KE payload for this state .
*
* @ param this calling object
2005-12-06 08:27:20 +00:00
* @ param request message_t object to add the KE payload
2005-11-23 10:12:45 +00:00
*/
2005-12-06 08:27:20 +00:00
void ( * build_ke_payload ) ( private_initiator_init_t * this , message_t * request ) ;
2005-11-28 20:29:47 +00:00
2005-11-23 10:12:45 +00:00
/**
* Builds the NONCE payload for this state .
*
* @ param this calling object
2005-12-06 08:27:20 +00:00
* @ param request message_t object to add the NONCE payload
2005-11-23 10:12:45 +00:00
*/
2005-12-06 08:27:20 +00:00
void ( * build_nonce_payload ) ( private_initiator_init_t * this , message_t * request ) ;
2005-11-23 10:12:45 +00:00
/**
2005-12-05 12:21:38 +00:00
* Destroy function called internally of this class after state change to state
* IKE_SA_INIT_REQUESTED succeeded .
2005-11-23 10:12:45 +00:00
*
* 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-12-03 14:47:58 +00:00
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-12-02 11:38:56 +00:00
return DELETE_ME ;
2005-11-23 10:12:45 +00:00
}
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 ) ;
2005-12-02 11:38:56 +00:00
return DELETE_ME ;
2005-12-01 19:53:48 +00:00
}
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-05 12:21:38 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Diffie hellman group could not be retrieved with priority %d " , this - > dh_group_priority ) ;
2005-12-02 11:38:56 +00:00
return DELETE_ME ;
2005-11-23 10:12:45 +00:00
}
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 ;
2005-12-03 14:47:58 +00:00
chunk_t ike_sa_init_request_data ;
2005-12-02 08:52:01 +00:00
init_config_t * init_config ;
2005-12-03 14:47:58 +00:00
ike_sa_id_t * ike_sa_id ;
2005-12-02 08:52:01 +00:00
message_t * message ;
status_t status ;
2005-12-03 14:47:58 +00:00
2005-12-02 11:38:56 +00:00
this - > dh_group_priority = dh_group_priority ;
2005-12-02 08:52:01 +00:00
init_config = this - > ike_sa - > get_init_config ( this - > ike_sa ) ;
2005-11-23 10:12:45 +00:00
2005-12-02 11:38:56 +00:00
ike_sa_id = this - > ike_sa - > public . get_id ( & ( this - > ike_sa - > public ) ) ;
ike_sa_id - > set_responder_spi ( ike_sa_id , 0 ) ;
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 11:38:56 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " Diffie hellman group could not be retrieved with priority %d " , dh_group_priority ) ;
return DELETE_ME ;
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-12-06 08:27:20 +00:00
/* going to build message */
this - > logger - > log ( this - > logger , CONTROL | MOST , " Going to build message " ) ;
this - > ike_sa - > build_message ( this - > ike_sa , IKE_SA_INIT , TRUE , & message ) ;
/* build SA payload */
this - > build_sa_payload ( this , message ) ;
2005-12-02 13:20:20 +00:00
2005-12-06 08:27:20 +00:00
/* build KE payload */
this - > build_ke_payload ( this , message ) ;
2005-12-02 13:20:20 +00:00
2005-12-06 08:27:20 +00:00
/* build Nonce payload */
this - > build_nonce_payload ( this , message ) ;
2005-11-28 20:29:47 +00:00
2005-11-23 10:12:45 +00:00
2005-12-02 13:20:20 +00:00
/* message can now be sent (must not be destroyed) */
status = this - > ike_sa - > send_request ( this - > ike_sa , message ) ;
2005-11-23 10:12:45 +00:00
if ( status ! = SUCCESS )
{
2005-12-02 13:20:20 +00:00
this - > logger - > log ( this - > logger , ERROR , " Could not send request message " ) ;
2005-11-23 10:12:45 +00:00
message - > destroy ( message ) ;
2005-12-02 11:38:56 +00:00
return DELETE_ME ;
2005-11-23 10:12:45 +00:00
}
2005-12-03 14:47:58 +00:00
message = this - > ike_sa - > get_last_requested_message ( this - > ike_sa ) ;
ike_sa_init_request_data = message - > get_packet_data ( message ) ;
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-12-03 14:47:58 +00:00
next_state = ike_sa_init_requested_create ( this - > ike_sa , this - > dh_group_priority , this - > diffie_hellman , this - > sent_nonce , ike_sa_init_request_data ) ;
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-12-02 13:20:20 +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 ;
}
/**
2005-12-06 08:27:20 +00:00
* Implementation of private_initiator_init_t . build_sa_payload .
2005-11-23 10:12:45 +00:00
*/
2005-12-06 08:27:20 +00:00
static void build_sa_payload ( private_initiator_init_t * this , message_t * request )
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
2005-12-06 08:27:20 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Building SA payload " ) ;
2005-11-23 10:12:45 +00:00
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-12-06 08:27:20 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Add SA payload to message " ) ;
request - > add_payload ( request , ( payload_t * ) sa_payload ) ;
2005-11-23 10:12:45 +00:00
}
/**
2005-12-06 08:27:20 +00:00
* Implementation of private_initiator_init_t . build_ke_payload .
2005-11-23 10:12:45 +00:00
*/
2005-12-06 08:27:20 +00:00
static void build_ke_payload ( private_initiator_init_t * this , message_t * request )
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-12-06 08:27:20 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Building KE payload " ) ;
2005-11-23 10:12:45 +00:00
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-12-06 08:27:20 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Add KE payload to message " ) ;
request - > add_payload ( request , ( payload_t * ) ke_payload ) ;
2005-11-23 10:12:45 +00:00
}
/**
2005-12-06 08:27:20 +00:00
* Implementation of private_initiator_init_t . build_nonce_payload .
2005-11-23 10:12:45 +00:00
*/
2005-12-06 08:27:20 +00:00
static void build_nonce_payload ( private_initiator_init_t * this , message_t * request )
2005-11-23 10:12:45 +00:00
{
nonce_payload_t * nonce_payload ;
2005-12-06 08:27:20 +00:00
randomizer_t * randomizer ;
this - > logger - > log ( this - > logger , CONTROL | MORE , " Building NONCE payload " ) ;
this - > logger - > log ( this - > logger , CONTROL | MOST , " Get pseudo random bytes for NONCE " ) ;
randomizer = this - > ike_sa - > get_randomizer ( this - > ike_sa ) ;
2005-11-23 10:12:45 +00:00
2005-12-06 08:27:20 +00:00
randomizer - > allocate_pseudo_random_bytes ( randomizer , NONCE_SIZE , & ( this - > sent_nonce ) ) ;
this - > logger - > log ( this - > logger , RAW | MOST , " Initiator NONCE " , & ( this - > sent_nonce ) ) ;
2005-11-23 10:12:45 +00:00
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-12-06 08:27:20 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Add NONCE payload to message " ) ;
request - > add_payload ( request , ( payload_t * ) nonce_payload ) ;
2005-11-23 10:12:45 +00:00
}
/**
2005-12-06 08:27:20 +00:00
* Implementation of state_t . process_message .
2005-11-23 10:12:45 +00:00
*/
2005-12-02 11:38:56 +00:00
static status_t process_message ( private_initiator_init_t * this , message_t * message )
2005-11-23 10:12:45 +00:00
{
this - > logger - > log ( this - > logger , ERROR | MORE , " In state INITIATOR_INIT no message is processed " ) ;
return FAILED ;
}
/**
2005-12-06 08:27:20 +00:00
* Implementation of state_t . get_state .
2005-11-23 10:12:45 +00:00
*/
static ike_sa_state_t get_state ( private_initiator_init_t * this )
{
return INITIATOR_INIT ;
}
/**
2005-12-06 08:27:20 +00:00
* Implementation of state_t . destroy .
2005-11-23 10:12:45 +00:00
*/
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 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 ) ;
}
/**
2005-12-06 08:27:20 +00:00
* Implementation of private_initiator_init_t . destroy_after_state_change
2005-11-23 10:12:45 +00:00
*/
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 " ) ;
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_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-12-06 08:27:20 +00:00
this - > diffie_hellman = NULL ;
2005-11-28 20:29:47 +00:00
2005-11-23 10:12:45 +00:00
return & ( this - > public ) ;
}