1888 lines
64 KiB
C
1888 lines
64 KiB
C
/*
|
|
******************************************************************************
|
|
* SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_exchange_main_mode.c,v $ $Revision: 1.33.10.13 $
|
|
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_exchange_main_mode.c,v $
|
|
* $Author: hxu0 $ $Date: 2015-07-13 08:20:47 $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
#include "ipike_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipike_h.h"
|
|
#include "ipike_exchange_main_mode.h"
|
|
#include "ipike_exchange_informational.h"
|
|
#include "ipike_crypto.h"
|
|
#include "ipike_payload.h"
|
|
#include "ipike_attributes.h"
|
|
#include "ipike_payload_sa.h"
|
|
#include "ipike_payload_certificate.h"
|
|
#include "ipike_payload_key_exchange.h"
|
|
#include "ipike_payload_nonce.h"
|
|
#include "ipike_payload_identification.h"
|
|
#include "ipike_payload_notification.h"
|
|
#include "ipike_payload_hash.h"
|
|
#include "ipike_payload_sign.h"
|
|
#include "ipike_payload_transform.h"
|
|
#include "ipike_payload_vendor_id.h"
|
|
#include "ipike_payload_nat.h"
|
|
#include "ipike_util.h"
|
|
#include "ipike_sadb.h"
|
|
#include "ipike_ipsec.h"
|
|
#include "ipike_configuration.h"
|
|
#include "ipike_policy.h"
|
|
#include "ipike_http_fetcher.h"
|
|
|
|
#include <openssl/x509.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_sock2.h>
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_state
|
|
*===========================================================================
|
|
* Description: Updates the exchange state after the data from
|
|
* message #1, 2, 3, 4, 5 or 6
|
|
* has been stored.
|
|
* Parameters: ie - holds all the states associated with the exchange.
|
|
* Returns: IPIKE_SUCCESS
|
|
* IPIKE_OUT_OF_MEMORY
|
|
* IPIKE_KE_DH_ERROR
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_1(Ipike_isakmp_exchange* ie);
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_2(Ipike_isakmp_exchange* ie);
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_3(Ipike_isakmp_exchange* ie);
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_4(Ipike_isakmp_exchange* ie);
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_5(Ipike_isakmp_exchange* ie);
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_6(Ipike_isakmp_exchange* ie);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_state
|
|
*===========================================================================
|
|
* Description: Calls functions that updates necessary state paramters during
|
|
* phase 1 main mode exchange.
|
|
* Parameters: ie - holds all the states associated with the exchange.
|
|
* Returns: IPIKE_SUCCESS
|
|
* IPIKE_OUT_OF_MEMORY
|
|
* IPIKE_KE_DH_ERROR
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_state(Ipike_isakmp_exchange* ie);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 LOCAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_initialize_id
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_initialize_id(
|
|
Ipike_isakmp_exchange* ie,
|
|
Ipike_id* id)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
const char* str = ie->ike_conf->local_id;
|
|
|
|
/* Try to use id from configuration, use IP-address if fails */
|
|
if (IP_NULL == str ||
|
|
IPIKE_SUCCESS != ipike_identification_generate(str, id))
|
|
{
|
|
err = ipike_ipsec_set_idix(&ie->ike_sa->local_addr, id);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* This IKE daemon is responder */
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_after_msg_1
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_1(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
|
|
err = ipike_policy_select_ike_sa_param(ie->ike_conf,
|
|
&ie->ike_sa->sa,
|
|
&ie->ike_sa->selected,
|
|
IP_FALSE);
|
|
|
|
if ( err != IPIKE_SUCCESS )
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, PROPOSAL_MISMATCH,
|
|
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
return err;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_after_msg_3
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_3(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
Ipike_sadb_entry *ike_sa = ie->ike_sa;
|
|
Ipike_transform_ike *transform = ipike_transform_ike_from_exch(ie);
|
|
|
|
if (transform==IP_NULL)
|
|
return IPIKE_FAILED;
|
|
|
|
if (IPIKE_SUCCESS != (err = ipike_payload_nonce_generate(&ike_sa->nr)))
|
|
goto errout;
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_generate_dh_key(transform->dh_prime,
|
|
transform->dh_generator, &ie->dh, &ike_sa->g_xr)))
|
|
goto errout;
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_dh_key(ie->dh,
|
|
&ike_sa->g_xi, &ike_sa->g_xy)))
|
|
goto errout;
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_skeyid(ie->ike_conf, ike_sa)))
|
|
goto errout;
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_phase1_secret_key(ie)))
|
|
goto errout;
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_initial_phase1_iv(ike_sa, &ie->iv)))
|
|
goto errout;
|
|
|
|
return IPIKE_SUCCESS;
|
|
|
|
errout:
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR,
|
|
&ike_sa->peer_addr, &ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_after_msg_5
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_5(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
Ipike_sadb_entry* ike_sa = ie->ike_sa;
|
|
Ip_u16 auth_meth;
|
|
Ip_u16 hash_alg;
|
|
Ipike_transform_ike *transform_ike;
|
|
|
|
/* Check if there is a more suitable IKE SA config */
|
|
ipike_main_mode_update_responder_config(ie);
|
|
|
|
if (IPIKE_SUCCESS != (err = ipike_main_mode_authentication_check(ie)))
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, AUTHENTICATION_ERROR,
|
|
&ike_sa->peer_addr, &ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
return err;
|
|
}
|
|
|
|
switch (ike_sa->sa.doi)
|
|
{
|
|
case IPIKE_DOI_IPSEC:
|
|
if (IPIKE_SUCCESS != (err = ipike_main_mode_initialize_id(ie, &ike_sa->idir)))
|
|
goto errout;
|
|
break;
|
|
default:
|
|
IPCOM_LOG1(ERR, "ipike_main_mode_update_after_msg_5() :: "\
|
|
"the DOI %d is not supported", ike_sa->sa.doi);
|
|
err = IPIKE_DOI_UNSUPPORTED;
|
|
goto errout;
|
|
}
|
|
|
|
transform_ike = ipike_transform_ike_from_exch(ie);
|
|
if (transform_ike==IP_NULL)
|
|
{
|
|
err = IPIKE_FAILED;
|
|
goto errout;
|
|
}
|
|
auth_meth = transform_ike->authentication_method;
|
|
|
|
if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES)
|
|
hash_alg = IPIKE_ATTR_HASH_SHA1;
|
|
else
|
|
hash_alg = transform_ike->hash_algorithm;
|
|
|
|
err = ipike_crypto_compute_hash_r(hash_alg, ike_sa, &ike_sa->hash_r);
|
|
|
|
if ( err != IPIKE_SUCCESS )
|
|
goto errout;
|
|
|
|
if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES)
|
|
err = ipike_crypto_compute_dsa_sign(ie->ike_conf->authentication.key_id,
|
|
ie->ike_conf->authentication.private_key,
|
|
&ike_sa->hash_r,
|
|
&ike_sa->sign_r);
|
|
else if (auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES)
|
|
err = ipike_crypto_compute_rsa_sign(ie->ike_conf->authentication.key_id,
|
|
ie->ike_conf->authentication.private_key,
|
|
&ike_sa->hash_r,
|
|
&ike_sa->sign_r);
|
|
|
|
/* Everything should be encrypted from now on */
|
|
ie->isakmp_flags = IPIKE_ISAKMP_ENCRYPTION;
|
|
|
|
errout:
|
|
|
|
if ( err != IPIKE_SUCCESS )
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR,
|
|
&ike_sa->peer_addr, &ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
return err;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/* This IKE daemon is initiator */
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_before_msg_1
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_before_msg_1(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
err = ipike_sa_ike_initialize(ie->ike_conf, &ie->ike_sa->sa);
|
|
|
|
if ( err != IPIKE_SUCCESS )
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR,
|
|
&ie->ike_sa->local_addr, &ie->ike_sa->peer_addr,
|
|
0, IP_NULL);
|
|
return err;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_after_msg_2
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_2(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
Ipike_sadb_entry* ike_sa = ie->ike_sa;
|
|
Ipike_transform_ike* transform;
|
|
|
|
err = ipike_policy_select_ike_sa_param(ie->ike_conf,
|
|
&ike_sa->sa,
|
|
&ie->ike_sa->selected,
|
|
IP_TRUE);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, PROPOSAL_MISMATCH,
|
|
&ike_sa->peer_addr, &ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
return err;
|
|
}
|
|
|
|
transform = ipike_transform_ike_from_exch(ie);
|
|
|
|
/* We should have a selected transform here otherwise would
|
|
* ipike_policy_select_ike_sa_param failed */
|
|
ip_assert(transform != IP_NULL);
|
|
|
|
err = ipike_crypto_generate_dh_key(transform->dh_prime,
|
|
transform->dh_generator,
|
|
&ie->dh, &ike_sa->g_xi);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
goto errout;
|
|
|
|
err = ipike_payload_nonce_generate(&ike_sa->ni);
|
|
|
|
errout:
|
|
if (IPIKE_SUCCESS != err)
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR,
|
|
&ike_sa->peer_addr, &ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_after_msg_4
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_4(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
Ipike_sadb_entry* ike_sa = ie->ike_sa;
|
|
Ip_u16 auth_meth;
|
|
Ip_u16 hash_alg;
|
|
Ipike_transform_ike *transform_ike;
|
|
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_dh_key(ie->dh,
|
|
&ike_sa->g_xr, &ike_sa->g_xy)))
|
|
goto errout;
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_skeyid(ie->ike_conf, ike_sa)))
|
|
goto errout;
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_phase1_secret_key(ie)))
|
|
goto errout;
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_initial_phase1_iv(ike_sa, &ie->iv)))
|
|
goto errout;
|
|
|
|
switch (ike_sa->sa.doi)
|
|
{
|
|
case IPIKE_DOI_IPSEC:
|
|
if (IPIKE_SUCCESS != (err = ipike_main_mode_initialize_id(ie, &ike_sa->idii)))
|
|
goto errout;
|
|
break;
|
|
default:
|
|
IPCOM_LOG1(ERR, "ipike_main_mode_update_after_msg_4() ::"\
|
|
" the DOI %d is not supported",
|
|
ike_sa->sa.doi);
|
|
err = IPIKE_DOI_UNSUPPORTED;
|
|
goto errout;
|
|
}
|
|
|
|
transform_ike = ipike_transform_ike_from_exch(ie);
|
|
if (transform_ike==IP_NULL)
|
|
{
|
|
err= IPIKE_FAILED;
|
|
goto errout;
|
|
}
|
|
auth_meth = transform_ike->authentication_method;
|
|
if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES)
|
|
hash_alg = IPIKE_ATTR_HASH_SHA1;
|
|
else
|
|
hash_alg = transform_ike->hash_algorithm;
|
|
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_hash_i(hash_alg, ike_sa, &ike_sa->hash_i)))
|
|
goto errout;
|
|
|
|
if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES)
|
|
err = ipike_crypto_compute_dsa_sign(ie->ike_conf->authentication.key_id,
|
|
ie->ike_conf->authentication.private_key,
|
|
&ike_sa->hash_i,
|
|
&ike_sa->sign_i);
|
|
else if (auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES)
|
|
err = ipike_crypto_compute_rsa_sign(ie->ike_conf->authentication.key_id,
|
|
ie->ike_conf->authentication.private_key,
|
|
&ike_sa->hash_i,
|
|
&ike_sa->sign_i);
|
|
|
|
/* Everything should be encrypted from now on */
|
|
ie->isakmp_flags = IPIKE_ISAKMP_ENCRYPTION;
|
|
|
|
errout:
|
|
|
|
if ( err != IPIKE_SUCCESS )
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR,
|
|
&ike_sa->peer_addr, &ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
return err;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_after_msg_6
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_after_msg_6(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
err = ipike_main_mode_authentication_check(ie);
|
|
|
|
if ( err != IPIKE_SUCCESS )
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, AUTHENTICATION_ERROR,
|
|
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
return err;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_state
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_update_state(Ipike_isakmp_exchange* ie)
|
|
{
|
|
switch (ie->message_number)
|
|
{
|
|
/* We are responder */
|
|
case 1: return ipike_main_mode_update_after_msg_1(ie);
|
|
case 3: return ipike_main_mode_update_after_msg_3(ie);
|
|
case 5: return ipike_main_mode_update_after_msg_5(ie);
|
|
|
|
/* We are initiator */
|
|
case 0: return ipike_main_mode_update_before_msg_1(ie);
|
|
case 2: return ipike_main_mode_update_after_msg_2(ie);
|
|
case 4: return ipike_main_mode_update_after_msg_4(ie);
|
|
case 6: return ipike_main_mode_update_after_msg_6(ie);
|
|
|
|
}
|
|
IPCOM_LOG1(ERR,
|
|
"IKE main mode has 6 messages, this was %d",
|
|
ie->message_number);
|
|
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, ISAKMP_PACKET_ERROR,
|
|
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
|
|
return IPIKE_INVALID_MESSAGE_NUMBER;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_store_sai_b
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_store_sai_b(Ipike_value* sai_b, Ipike_sa_payload* payload)
|
|
{
|
|
sai_b->len = ip_ntohs(payload->header.length) - IPIKE_PAYLOAD_HEADER_LENGTH;
|
|
if (IP_NULL == (sai_b->value = ipcom_malloc(sai_b->len)))
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
ipcom_memcpy(sai_b->value, (Ip_u8 *) payload + IPIKE_PAYLOAD_HEADER_LENGTH,
|
|
sai_b->len);
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_cert_create
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_cert_create(
|
|
Ipike_config_ike_sa* conf,
|
|
Ipike_cert_payload** payload)
|
|
{
|
|
Ipike_error err;
|
|
Ipike_cert cert;
|
|
|
|
cert.peer = ipike_crypto_read_cert(conf->authentication.certificate);
|
|
err = ipike_payload_certificate_create(cert.peer, IP_NULL, payload);
|
|
X509_free(cert.peer);
|
|
return err;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_verify_auth
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_verify_auth(Ipike_isakmp_exchange *ie)
|
|
{
|
|
Ipike_sadb_entry *ike_sa = ie->ike_sa;
|
|
Ipike_transform_ike *transform = IP_NULL;
|
|
Ipike_error err = IPIKE_AUTHENTICATION_FAILED;
|
|
Ip_u16 auth_meth = 0;
|
|
Ip_u16 hash_alg = 0;
|
|
|
|
ip_assert(ike_sa);
|
|
|
|
transform = ipike_transform_ike_from_exch(ie);
|
|
|
|
if (transform == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_main_mode_verify_auth :: null transform");
|
|
goto error;
|
|
}
|
|
|
|
auth_meth = transform->authentication_method;
|
|
|
|
if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES)
|
|
hash_alg = IPIKE_ATTR_HASH_SHA1;
|
|
else
|
|
hash_alg = ipike_transform_ike_from_exch(ie)->hash_algorithm;
|
|
|
|
/* Compute hash for RSA and DSS */
|
|
if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES ||
|
|
auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES )
|
|
{
|
|
if (ike_sa->is_initiator)
|
|
err = ipike_crypto_compute_hash_r(hash_alg, ike_sa, &ike_sa->hash_r);
|
|
else
|
|
err = ipike_crypto_compute_hash_i(hash_alg, ike_sa, &ike_sa->hash_i);
|
|
|
|
if (err != IPIKE_SUCCESS)
|
|
goto error;
|
|
}
|
|
|
|
/* Verify signature */
|
|
if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES)
|
|
{
|
|
err = ipike_crypto_verify_dsa_sign(ike_sa->cert.peer,
|
|
ike_sa->is_initiator ? &ike_sa->hash_r : &ike_sa->hash_i,
|
|
ike_sa->is_initiator ? &ike_sa->sign_r : &ike_sa->sign_i);
|
|
}
|
|
else if ( auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES )
|
|
{
|
|
err = ipike_crypto_verify_rsa_sign(ike_sa->cert.peer,
|
|
ike_sa->is_initiator ? &ike_sa->hash_r : &ike_sa->hash_i,
|
|
ike_sa->is_initiator ? &ike_sa->sign_r : &ike_sa->sign_i);
|
|
}
|
|
else
|
|
{
|
|
if (ike_sa->is_initiator)
|
|
err = ipike_crypto_verify_hash_r(ie->ike_sa);
|
|
else
|
|
err = ipike_crypto_verify_hash_i(ie->ike_sa);
|
|
}
|
|
|
|
error:
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_http_get_crl_cb
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC void
|
|
ipike_main_mode_http_get_crl_cb(
|
|
Ipike_error status,
|
|
const char *data,
|
|
Ip_size_t data_len,
|
|
void *id)
|
|
{
|
|
Ipike_isakmp_exchange *ie = IP_NULL;
|
|
X509_CRL *crl = IP_NULL;
|
|
X509_CRL** crls = IP_NULL;
|
|
X509** trusted = IP_NULL;
|
|
X509** ca = IP_NULL;
|
|
Ipike_sadb_entry* ike_sa = IP_NULL;
|
|
Ipike_error err = IPIKE_AUTHENTICATION_FAILED;
|
|
|
|
ip_assert(id);
|
|
|
|
/* Get exchange state using the unique id */
|
|
ie = ipike_isakmp_get_exchange_from_unique_id(id, ipike_isakmp_get_unique_id_size());
|
|
|
|
if ( !ie )
|
|
{
|
|
/* No exchange found => abort */
|
|
IPCOM_LOG0(ERR, "ipike_main_mode_http_get_crl_cb()"\
|
|
" :: no IKE exchange state found");
|
|
|
|
/* Free allocated id */
|
|
ipcom_free( id );
|
|
|
|
/* No exchange found, stop proccessing */
|
|
return;
|
|
}
|
|
|
|
/* We should always have a valid ike_sa here */
|
|
ip_assert(ie->ike_sa);
|
|
|
|
ike_sa = ie->ike_sa;
|
|
|
|
/* Was the HTTP request successful */
|
|
if ( IPIKE_SUCCESS != status )
|
|
{
|
|
IPCOM_LOG1(ERR,
|
|
"ipike_main_mode_http_get_crl_cb() ::"\
|
|
" bad http response received (%d)", status);
|
|
goto done_continue;
|
|
}
|
|
|
|
/* Decode CRL */
|
|
crl = ipike_crypto_decode_crl((Ip_u8 *)data, data_len);
|
|
|
|
if ( !crl )
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"ipike_main_mode_http_get_crl_cb() :: failed to decode crl");
|
|
goto done_continue;
|
|
}
|
|
|
|
/* Add CRL to CRL list */
|
|
if ( IPIKE_SUCCESS != ipike_array_add((void***) &crls, crl) )
|
|
goto done_continue;
|
|
|
|
/* Get intermediate CA certs from local storage */
|
|
ca = ipike_crypto_get_intermediate_ca_certs(
|
|
&ike_sa->cert,
|
|
ie->ike_conf->authentication.intermediate_ca_store);
|
|
|
|
/* Get trusted CA certs from local storage */
|
|
trusted = ipike_crypto_get_trusted_certs(
|
|
ie->ike_conf->authentication.trusted_ca_store);
|
|
|
|
/* Must at least have one trusted CA */
|
|
if ( !trusted )
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"ipike_main_mode_http_get_crl_cb() ::"\
|
|
" failed to read trusted certificate");
|
|
goto done_continue;
|
|
}
|
|
|
|
#ifdef IPIKE_USE_OCSP
|
|
/* IKEv1 doesnt support OCSP define necessary for avoiding code duplication */
|
|
err = ipike_crypto_verify_certificate_ocsp(trusted, ca, ike_sa->cert.peer, crls, IP_NULL);
|
|
#else
|
|
err = ipike_crypto_verify_certificate(trusted, ca, ike_sa->cert.peer, crls);
|
|
#endif
|
|
|
|
|
|
done_continue:
|
|
/* Free allocated id */
|
|
ipcom_free( id );
|
|
|
|
ipike_array_free((void**) trusted, (void(*)(void*)) X509_free);
|
|
ipike_array_free((void**) ca, (void(*)(void*)) X509_free);
|
|
ipike_array_free((void**) crls, (void(*)(void*)) X509_CRL_free);
|
|
|
|
/* Update error state of IKE SA */
|
|
ie->ike_sa->error = err;
|
|
|
|
/* On failure */
|
|
if ( err != IPIKE_SUCCESS )
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"ipike_main_mode_http_get_crl_cb() ::"\
|
|
" certificate verification failed");
|
|
(void)ipike_informational_report_error(ie->ike_sa, IP_NULL, err);
|
|
|
|
/* Set IKE SA to dying */
|
|
ipike_sadb_set_state(ie, ie->ike_sa, IPIKE_SA_DYING);
|
|
|
|
/* Destroy this exchange */
|
|
ipike_isakmp_free_exchange(ie, IP_TRUE);
|
|
}
|
|
else
|
|
{
|
|
/* Continue the exchange and send the response */
|
|
ipike_isakmp_process_message_continue(ie);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_http_get
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_main_mode_http_get(
|
|
Ipike_isakmp_exchange *ie,
|
|
const char *uri,
|
|
Ipike_http_fetcher_callback callback)
|
|
{
|
|
Ip_u8 *id;
|
|
Ip_u32 id_len;
|
|
|
|
if ( !uri )
|
|
return IPIKE_FAILED;
|
|
|
|
id_len = ipike_isakmp_get_unique_id_size();
|
|
id = ipcom_malloc( id_len );
|
|
|
|
if ( !id )
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
memset( id, 0, id_len);
|
|
|
|
/* Create an unique id for this exchange that is used for obtaining
|
|
correct exchange state in the callback */
|
|
if ( !ipike_isakmp_get_unique_id_for_exchange(ie, id, &id_len))
|
|
goto error_out;
|
|
|
|
/* Get data that is pointed out by the URI */
|
|
if ( IPIKE_SUCCESS != ipike_http_fetcher_get(uri, callback, id) )
|
|
{
|
|
IPCOM_LOG1(ERR, "ipike_main_mode_http_get :: failed to fetch \"%s\"", uri);
|
|
goto error_out;
|
|
}
|
|
|
|
/* Mark that this exchange is waiting for an external response */
|
|
ie->wait_response = IP_TRUE;
|
|
|
|
return IPIKE_SUCCESS;
|
|
|
|
error_out:
|
|
|
|
ipcom_free(id);
|
|
|
|
return IPIKE_FAILED;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_cert_req_create
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ipike_error
|
|
ipike_main_mode_add_cert_request(
|
|
Ipike_config_ike_sa* conf,
|
|
Ipike_payload_header*** reply_payloads)
|
|
{
|
|
Ipike_cert_req_payload* payload = IP_NULL;
|
|
X509** trusted = IP_NULL;
|
|
X509** iter = IP_NULL;
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
|
|
/* Get trusted CA certs from local storage */
|
|
trusted = ipike_crypto_get_trusted_certs(conf->authentication.trusted_ca_store);
|
|
|
|
/* Create a certificate request payload for each trusted CA */
|
|
for (iter = trusted; iter && *iter; iter++)
|
|
{
|
|
payload = IP_NULL;
|
|
err = ipike_payload_certificate_req_create_v1(&payload, *iter);
|
|
|
|
if ( err != IPIKE_SUCCESS )
|
|
goto errout;
|
|
|
|
/* Add the payload if we have constructed on*/
|
|
if ( payload )
|
|
{
|
|
err = ipike_array_add((void***) reply_payloads, payload);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
{
|
|
ipcom_free(payload);
|
|
goto errout;
|
|
}
|
|
}
|
|
}
|
|
|
|
errout:
|
|
|
|
ipike_array_free((void**) trusted, (void(*)(void*)) X509_free);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_update_responder_config
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC void
|
|
ipike_main_mode_update_responder_config(Ipike_isakmp_exchange *ie)
|
|
{
|
|
Ipike_sadb_entry* ike_sa;
|
|
Ipike_config_ike_sa *ike_conf;
|
|
Ipike_id* id;
|
|
|
|
ike_sa = ie->ike_sa;
|
|
id = &ike_sa->idii;
|
|
|
|
ike_conf = ipike_config_get_ike_sa_from_address_and_remote_id(ie,
|
|
&ie->msg.local_addr,
|
|
&ie->msg.peer_addr,
|
|
id->id_type,
|
|
&id->id_data,
|
|
ike_sa->cert.peer);
|
|
|
|
if ( IP_NULL != ike_conf && ike_conf != ie->ike_conf )
|
|
{
|
|
/* We found a differnet configuration that can be used */
|
|
ie->ike_conf = ike_conf;
|
|
|
|
/* Update IKE SA parameters */
|
|
if ( IP_NULL != ike_sa->id )
|
|
ipcom_free(ike_sa->id);
|
|
|
|
ike_sa->id = ipcom_strdup( ike_conf->ike_id );
|
|
|
|
IPCOM_LOG0(NOTICE, "ipike_main_mode_update_responder_config :: Updated IKE SA config selection based on 'remote_identifier'");
|
|
}
|
|
|
|
/* Fall through even if no matching configuration was found since and
|
|
* let the negotiation fail in the authentication check */
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_authentication_check
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_main_mode_authentication_check(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
Ip_u16 auth_meth;
|
|
Ipike_transform_ike *transform;
|
|
Ipike_sadb_entry* ike_sa = ie->ike_sa;
|
|
X509** trusted = IP_NULL;
|
|
X509** ca = IP_NULL;
|
|
X509_CRL** crls = IP_NULL;
|
|
Ipike_id* id;
|
|
|
|
if (ike_sa->is_initiator)
|
|
id = &ike_sa->idir;
|
|
else
|
|
id = &ike_sa->idii;
|
|
|
|
/* Do we allow the remote peer access */
|
|
err = ipike_policy_accept_id(ie->ike_conf->remote_id,
|
|
id->id_type,
|
|
&id->id_data,
|
|
ike_sa->cert.peer);
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipike_main_mode_authentication_check() ::"\
|
|
" bad 'remote_identifier', err = %d", err);
|
|
goto error;
|
|
}
|
|
|
|
/* Authenticate */
|
|
err = ipike_main_mode_verify_auth(ie);
|
|
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipike_main_mode_authentication_check() ::"\
|
|
" failed to verify authentication data, err = %d",
|
|
err);
|
|
goto error;
|
|
}
|
|
|
|
transform = ipike_transform_ike_from_exch(ie);
|
|
if (transform == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_main_mode_authentication_check() ::"\
|
|
" null transform");
|
|
goto error;
|
|
}
|
|
|
|
auth_meth = transform->authentication_method;
|
|
|
|
if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES ||
|
|
auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES)
|
|
{
|
|
/* Check if a remote (HTTP) location of CRL is configured */
|
|
if ( ie->ike_conf->authentication.crl_store &&
|
|
ipcom_strncmp(ie->ike_conf->authentication.crl_store, "http://", 7) == 0 )
|
|
{
|
|
/* Fetching CRLs using CRL using http */
|
|
IPCOM_LOG1(DEBUG2, "ipike_main_mode_authentication_check() ::"\
|
|
" fetching crl via http \"%s\"",
|
|
ie->ike_conf->authentication.crl_store );
|
|
|
|
/* Verify certificate when we have received the CRL in the callback */
|
|
err = ipike_main_mode_http_get(ie,
|
|
ie->ike_conf->authentication.crl_store,
|
|
ipike_main_mode_http_get_crl_cb);
|
|
|
|
/* Failed to fetch CRL */
|
|
if ( IPIKE_SUCCESS != err )
|
|
{
|
|
err = IPIKE_AUTHENTICATION_FAILED;
|
|
IPCOM_LOG0(ERR, "ipike_main_mode_authentication_check() ::"\
|
|
" failed to fetch crl via http");
|
|
goto error;
|
|
}
|
|
|
|
/* Fetching CRLs via HTTP, break processing for now and continue
|
|
* when we have received the certificate */
|
|
return err;
|
|
}
|
|
else
|
|
{
|
|
ca = ipike_crypto_get_intermediate_ca_certs(
|
|
&ike_sa->cert,
|
|
ie->ike_conf->authentication.intermediate_ca_store);
|
|
trusted = ipike_crypto_get_trusted_certs(
|
|
ie->ike_conf->authentication.trusted_ca_store);
|
|
|
|
crls = ipike_crypto_read_crls(ie->ike_conf->authentication.crl_store);
|
|
|
|
if (trusted == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"ipike_main_mode_authentication_check() ::"\
|
|
" failed to read trusted certificate");
|
|
err = IPIKE_INVALID_VALUE;
|
|
goto error;
|
|
}
|
|
|
|
#ifdef IPIKE_USE_OCSP
|
|
/* IKEv1 doesnt support OCSP define necessary for avoiding code
|
|
* duplication */
|
|
err = ipike_crypto_verify_certificate_ocsp(trusted, ca, ike_sa->cert.peer, crls, IP_NULL);
|
|
#else
|
|
err = ipike_crypto_verify_certificate(trusted, ca, ike_sa->cert.peer, crls);
|
|
#endif
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"ipike_main_mode_update_after_msg_6: certificate verification failed");
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
|
|
error:
|
|
ipike_array_free((void**) trusted, (void(*)(void*)) X509_free);
|
|
ipike_array_free((void**) ca, (void(*)(void*)) X509_free);
|
|
ipike_array_free((void**) crls, (void(*)(void*)) X509_CRL_free);
|
|
|
|
if (err)
|
|
{
|
|
/* Send a response and then destroy this exchange */
|
|
ie->send_and_destroy = IP_TRUE;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_on_new_exchange_initiator
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ipike_error
|
|
ipike_main_mode_on_new_exchange_initiator(
|
|
Ipike_isakmp_exchange* ie,
|
|
Ipike_sadb_entry* ike_sa,
|
|
const void* option1,
|
|
const void* trigger_flow)
|
|
{
|
|
Ipike_error err;
|
|
Ip_u8 initiator_cookie[IPIKE_ISAKMP_COOKIE_SIZE];
|
|
Ip_u8 responder_cookie[IPIKE_ISAKMP_COOKIE_SIZE];
|
|
union Ip_sockaddr_union peer_addr;
|
|
union Ip_sockaddr_union local_addr;
|
|
Ipike_config_flow *flow = IP_NULL;
|
|
|
|
/* IKE v1 */
|
|
ie->version = 1 << 4;
|
|
/* Store option1, only establish IKE SA if set */
|
|
ie->option1 = option1;
|
|
|
|
if (trigger_flow != IP_NULL)
|
|
{
|
|
/* Make a copy of the flow information, we will need to pass this
|
|
* further to the IPsec SA establishment */
|
|
flow = ipike_config_flow_duplicate(trigger_flow);
|
|
|
|
if (flow == IP_NULL)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
/* Store the flow in the place holder for option2*/
|
|
ie->option2 = flow;
|
|
}
|
|
|
|
ipcom_microtime(&ie->start);
|
|
ipcom_memset(responder_cookie, 0, IPIKE_ISAKMP_COOKIE_SIZE);
|
|
|
|
err = ipike_crypto_generate_cookie(initiator_cookie);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
return err;
|
|
|
|
/* Do we have an IKE SA, i.e. this is a reauthentication */
|
|
if (ike_sa != IP_NULL)
|
|
{
|
|
/* Use the same addresses and ports as the old IKE SA */
|
|
err = ipike_addr_copy(&local_addr, &ike_sa->local_addr);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
return err;
|
|
|
|
err = ipike_addr_copy(&peer_addr, &ike_sa->peer_addr);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
return err;
|
|
}
|
|
else
|
|
{
|
|
/* Use local address from configuration */
|
|
err = ipike_addr_copy(&local_addr, &ie->ike_conf->local_address);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
return err;
|
|
|
|
/* Check if we have a valid host address in the configuration */
|
|
if ( ipike_config_netobj_is_host(&ie->ike_conf->remote_address) )
|
|
{
|
|
/* Use remote address from configuration */
|
|
err = ipike_addr_copy(&peer_addr,
|
|
&ie->ike_conf->remote_address.addr);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
return err;
|
|
}
|
|
/* Was this negotiation triggered by a flow */
|
|
else if (flow != IP_NULL)
|
|
{
|
|
/* Use remote address from the trigger flow */
|
|
err = ipike_addr_copy(&peer_addr, &flow->dst[0]->addr);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
return err;
|
|
}
|
|
else
|
|
{
|
|
/* No idea of the remote address */
|
|
return IPIKE_CONF_INVALID_VALUE;
|
|
}
|
|
|
|
/* Reset destination port to default IKE port (500) */
|
|
ipike_addr_set_port(&peer_addr, ipike.port);
|
|
}
|
|
|
|
if (ipike_addr_is_any(&local_addr))
|
|
{
|
|
/* Try to figure out our local address based on the peer address */
|
|
err = ipike_dispatcher_socket_local_addr_get(&local_addr,
|
|
&peer_addr);
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(NOTICE,
|
|
"ipike_main_mode_on_new_exchange_initiator() ::"\
|
|
" failed to get local address");
|
|
/* Ignore error, the stack will find out the address
|
|
* eventually, however NAT-T will fail because of
|
|
* mismatching hashes */
|
|
}
|
|
}
|
|
|
|
err = ipike_sadb_add(initiator_cookie,
|
|
responder_cookie,
|
|
&local_addr,
|
|
&peer_addr,
|
|
&ie->ike_sa);
|
|
|
|
if (err != IPIKE_SUCCESS)
|
|
return err;
|
|
|
|
ie->is_phase1 = IP_TRUE;
|
|
ie->exchange_initiator = IP_TRUE;
|
|
|
|
ie->ike_sa->is_initiator = IP_TRUE;
|
|
ie->ike_sa->id = ipcom_strdup(ie->ike_conf->ike_id);
|
|
ie->ike_sa->version = ie->version;
|
|
ie->ike_sa->has_got_natt_capability = IP_FALSE;
|
|
|
|
return ipike_main_mode_update_state(ie);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_on_new_exchange_responder
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ipike_error
|
|
ipike_main_mode_on_new_exchange_responder(
|
|
Ipike_isakmp_exchange* ie,
|
|
Ipike_isakmp_header* first_isakmp,
|
|
union Ip_sockaddr_union* local_addr,
|
|
union Ip_sockaddr_union* peer_addr)
|
|
{
|
|
Ipike_error err;
|
|
Ip_u8 responder_cookie[IPIKE_ISAKMP_COOKIE_SIZE];
|
|
Ip_u8 retry;
|
|
|
|
ipcom_microtime(&ie->start);
|
|
|
|
/* IKE version 1 */
|
|
ie->version = 1 << 4;
|
|
|
|
if (first_isakmp->message_id != 0)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_main_mode_on_new_exchange: message id must be zero in this exchange");
|
|
err = IPIKE_ISAKMP_INVALID_MESSAGE_ID;
|
|
}
|
|
else
|
|
{
|
|
retry = 0;
|
|
do {
|
|
if (retry++ > 100)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_main_mode_on_new_exchange_responder: too many retries");
|
|
return IPIKE_FAILED;
|
|
}
|
|
/* Generate responder cookie until the initiator/responder
|
|
* cookie pair is unique */
|
|
if (IPIKE_SUCCESS != (err = ipike_crypto_generate_cookie(responder_cookie)))
|
|
return err;
|
|
} while (ipike_sadb_exist(first_isakmp->initiator_cookie, responder_cookie));
|
|
|
|
if (IPIKE_SUCCESS != (err = ipike_sadb_add(first_isakmp->initiator_cookie,
|
|
responder_cookie,
|
|
local_addr,
|
|
peer_addr,
|
|
&ie->ike_sa)))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_main_mode_on_new_exchange_responder: failed to add sa");
|
|
}
|
|
else
|
|
{
|
|
ie->is_phase1 = IP_TRUE;
|
|
ie->ike_sa->is_initiator = IP_FALSE;
|
|
ie->ike_sa->id = ipcom_strdup(ie->ike_conf->ike_id);
|
|
ie->ike_sa->version = ie->version;
|
|
ie->ike_sa->has_got_natt_capability = IP_FALSE;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_on_delete_exchange
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC void
|
|
ipike_main_mode_on_delete_exchange(Ipike_isakmp_exchange* ie)
|
|
{
|
|
if (ie->ike_sa == IP_NULL)
|
|
return;
|
|
|
|
if (ie->message_number < ipike_isakmp_exchange_message_count(ie))
|
|
{
|
|
IPCOM_LOG0(WARNING,
|
|
"ipike_main_mode_on_delete_exchange: the exchange was not finished,"
|
|
" removing (incomplete) IKE SA");
|
|
(void) ipike_sadb_set_state(ie, ie->ike_sa, IPIKE_SA_DYING);
|
|
}
|
|
|
|
if (ie->option2)
|
|
ipike_config_flow_destroy((Ipike_config_flow *)ie->option2);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_get_payload_order
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC const Ip_u16 *
|
|
ipike_main_mode_get_payload_order(Ipike_isakmp_exchange* ie)
|
|
{
|
|
/* All authentication methods has #1 and #2 equal
|
|
and the authentication method can not be known
|
|
by the responder before processing #1 */
|
|
static Ip_u16 before_first_sa_processed[] = {
|
|
/* message # 1 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 2 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 3 */
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 4 */
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 5 */
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 6 */
|
|
IPIKE_PAYLOAD_NONE,
|
|
};
|
|
|
|
static Ip_u16 pre_shared_keys_payloads[] = {
|
|
/* message # 1 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 2 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 3 */
|
|
IPIKE_PAYLOAD_KEY_EXCHANGE,
|
|
IPIKE_PAYLOAD_NONCE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 4 */
|
|
IPIKE_PAYLOAD_KEY_EXCHANGE,
|
|
IPIKE_PAYLOAD_NONCE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 5 */
|
|
IPIKE_PAYLOAD_IDENTFICATION,
|
|
IPIKE_PAYLOAD_HASH,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NOTIFICATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 6 */
|
|
IPIKE_PAYLOAD_IDENTFICATION,
|
|
IPIKE_PAYLOAD_HASH,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NOTIFICATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
};
|
|
|
|
static Ip_u16 public_keys_sign_payloads[] = {
|
|
/* message # 1 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE_REQUEST,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 2 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE_REQUEST,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 3 */
|
|
IPIKE_PAYLOAD_KEY_EXCHANGE,
|
|
IPIKE_PAYLOAD_NONCE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE_REQUEST,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 4 */
|
|
IPIKE_PAYLOAD_KEY_EXCHANGE,
|
|
IPIKE_PAYLOAD_NONCE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_CERTIFICATE_REQUEST,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 5 */
|
|
IPIKE_PAYLOAD_IDENTFICATION,
|
|
IPIKE_PAYLOAD_CERTIFICATE | IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD,
|
|
IPIKE_PAYLOAD_SIGNATURE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NOTIFICATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_CERTIFICATE_REQUEST,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 6 */
|
|
IPIKE_PAYLOAD_IDENTFICATION,
|
|
IPIKE_PAYLOAD_CERTIFICATE | IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD,
|
|
IPIKE_PAYLOAD_SIGNATURE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NOTIFICATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE_REQUEST,
|
|
IPIKE_PAYLOAD_NONE,
|
|
};
|
|
|
|
static Ip_u16 public_keys_encrypt_payloads[] = {
|
|
/* message # 1 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 2 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 3 */
|
|
IPIKE_PAYLOAD_KEY_EXCHANGE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_HASH,
|
|
IPIKE_PAYLOAD_IDENTFICATION,
|
|
IPIKE_PAYLOAD_NONCE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 4 */
|
|
IPIKE_PAYLOAD_KEY_EXCHANGE,
|
|
IPIKE_PAYLOAD_IDENTFICATION,
|
|
IPIKE_PAYLOAD_NONCE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 5 */
|
|
IPIKE_PAYLOAD_HASH,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 6 */
|
|
IPIKE_PAYLOAD_HASH,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
};
|
|
|
|
static Ip_u16 rev_public_keys_encrypt_payloads[] = {
|
|
/* message # 1 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 2 */
|
|
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 3 */
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_HASH,
|
|
IPIKE_PAYLOAD_NONCE,
|
|
IPIKE_PAYLOAD_KEY_EXCHANGE,
|
|
IPIKE_PAYLOAD_IDENTFICATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 4 */
|
|
IPIKE_PAYLOAD_NONCE,
|
|
IPIKE_PAYLOAD_KEY_EXCHANGE,
|
|
IPIKE_PAYLOAD_IDENTFICATION,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 5 */
|
|
IPIKE_PAYLOAD_HASH,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
|
|
/* message # 6 */
|
|
IPIKE_PAYLOAD_HASH,
|
|
IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID,
|
|
IPIKE_PAYLOAD_NONE,
|
|
};
|
|
|
|
static Ip_u16 *id_prot_payloads[] = {
|
|
before_first_sa_processed,
|
|
pre_shared_keys_payloads,
|
|
public_keys_sign_payloads,
|
|
public_keys_sign_payloads,
|
|
public_keys_encrypt_payloads,
|
|
rev_public_keys_encrypt_payloads
|
|
};
|
|
|
|
int i = 1;
|
|
int message_nr = ie->message_number;
|
|
Ip_u16 * ret;
|
|
Ip_u16 n = 0;
|
|
Ip_u16 auth_method = 0;
|
|
|
|
|
|
if (ipike_transform_ike_from_exch(ie) != IP_NULL)
|
|
auth_method = ipike_transform_ike_from_exch(ie)->authentication_method;
|
|
if (auth_method > IPIKE_ATTR_AUTH_COUNT)
|
|
return IP_NULL;
|
|
|
|
ret = id_prot_payloads[auth_method];
|
|
|
|
i = 1;
|
|
while (i != message_nr)
|
|
if (*ret++ == IPIKE_PAYLOAD_NONE)
|
|
i++;
|
|
|
|
/* Some optional must be added if we are using NAT traversal */
|
|
i = 0;
|
|
while (ret[i] != IPIKE_PAYLOAD_NONE)
|
|
{
|
|
n = (Ip_u16)(ret[i] & 0x3FFF);
|
|
if (n == IPIKE_PAYLOAD_NAT_DISCOVERY)
|
|
{
|
|
if (ipike.port_nat != 0 && ie->ike_sa->has_got_natt_capability)
|
|
ret[i] |= IPIKE_PAYLOAD_ADD;
|
|
else
|
|
ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD);
|
|
}
|
|
|
|
/* Check policy for sending certificate and certificate request */
|
|
if ( auth_method != IPIKE_ATTR_AUTH_PRE_SHARED_KEY )
|
|
{
|
|
if ( n == IPIKE_PAYLOAD_CERTIFICATE )
|
|
{
|
|
if ( ipike_isakmp_should_send_certificate(ie) )
|
|
ret[i] |= IPIKE_PAYLOAD_ADD;
|
|
else
|
|
ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD);
|
|
}
|
|
else if ( n == IPIKE_PAYLOAD_CERTIFICATE_REQUEST )
|
|
{
|
|
if ( ipike_isakmp_should_send_certificate_req(ie) )
|
|
ret[i] |= IPIKE_PAYLOAD_ADD;
|
|
else
|
|
ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD);
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_process_payloads
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ipike_error
|
|
ipike_main_mode_process_payloads(
|
|
Ipike_isakmp_exchange *ie,
|
|
Ipike_isakmp_header *isakmp)
|
|
{
|
|
Ipike_payload_header *payload;
|
|
Ip_u8 this_payload;
|
|
Ipike_error err;
|
|
Ipike_payload_enum ctx;
|
|
|
|
/* Process payloads */
|
|
this_payload = isakmp->next_payload;
|
|
payload = ipike_first_payload(isakmp, &ctx);
|
|
err = IPIKE_SUCCESS;
|
|
|
|
while (payload != IP_NULL)
|
|
{
|
|
switch (this_payload)
|
|
{
|
|
case IPIKE_PAYLOAD_SECURITY_ASSOCIATION:
|
|
/* RFC2409 Section 5,
|
|
* The SA payload MUST precede all other payloads in a
|
|
* phase 1 exchange. */
|
|
if (IPIKE_PAYLOAD_SECURITY_ASSOCIATION != isakmp->next_payload)
|
|
return IPIKE_WRONG_PAYLOAD;
|
|
|
|
if (ie->ike_sa->is_initiator)
|
|
/* Free the SA that was sent to the responder */
|
|
ipike_sa_free(&ie->ike_sa->sa, IP_NULL);
|
|
else
|
|
{
|
|
/* Store the binary encoding of the SA from the initiator */
|
|
err = ipike_main_mode_store_sai_b(&ie->ike_sa->sai_b,
|
|
(Ipike_sa_payload*) payload);
|
|
if (IPIKE_SUCCESS != err)
|
|
break;
|
|
}
|
|
|
|
err = ipike_sa_extract(ie,
|
|
(Ipike_sa_payload*) payload,
|
|
&ie->ike_sa->sa);
|
|
break;
|
|
case IPIKE_PAYLOAD_KEY_EXCHANGE:
|
|
err = ipike_key_exchange_extract((Ipike_ke_payload*) payload,
|
|
ie->ike_sa->is_initiator ?
|
|
&ie->ike_sa->g_xr :
|
|
&ie->ike_sa->g_xi);
|
|
break;
|
|
case IPIKE_PAYLOAD_NONCE:
|
|
err = ipike_payload_nonce_extract((Ipike_nonce_payload*) payload,
|
|
ie->ike_sa->is_initiator ?
|
|
&ie->ike_sa->nr :
|
|
&ie->ike_sa->ni);
|
|
break;
|
|
case IPIKE_PAYLOAD_IDENTFICATION:
|
|
err = ipike_identification_ike_extract((Ipike_id_payload*) payload,
|
|
ie->ike_sa->sa.doi,
|
|
ie->ike_sa->is_initiator ?
|
|
&ie->ike_sa->idir :
|
|
&ie->ike_sa->idii);
|
|
break;
|
|
case IPIKE_PAYLOAD_HASH:
|
|
err = ipike_hash_extract((Ipike_hash_payload*) payload,
|
|
ie->ike_sa->is_initiator ?
|
|
&ie->ike_sa->hash_r :
|
|
&ie->ike_sa->hash_i);
|
|
break;
|
|
case IPIKE_PAYLOAD_NOTIFICATION:
|
|
err = ipike_notification_process_message(ie,
|
|
(Ipike_notification_payload*) payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_CERTIFICATE:
|
|
err = ipike_payload_certificate_extract(
|
|
(Ipike_cert_payload*) payload,
|
|
&ie->ike_sa->cert);
|
|
break;
|
|
case IPIKE_PAYLOAD_CERTIFICATE_REQUEST:
|
|
ie->certificate_requested = IP_TRUE;
|
|
err = ipike_payload_certificate_req_extract_v1(
|
|
(Ipike_cert_req_payload*) payload,
|
|
&ie->ike_sa->cert);
|
|
break;
|
|
case IPIKE_PAYLOAD_SIGNATURE:
|
|
err = ipike_sign_extract((Ipike_sign_payload*) payload,
|
|
ie->ike_sa->is_initiator ?
|
|
&ie->ike_sa->sign_r :
|
|
&ie->ike_sa->sign_i);
|
|
break;
|
|
case IPIKE_PAYLOAD_VENDOR_ID:
|
|
err = ipike_payload_vendor_id_process(ie->ike_sa,
|
|
(Ipike_vendor_id_payload*) payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_NAT_DISCOVERY:
|
|
err = ipike_nat_discovery_process(
|
|
ie->ike_sa,
|
|
(Ipike_nat_discovery_payload*) payload);
|
|
break;
|
|
default:
|
|
IPCOM_LOG2(ERR,
|
|
"ipike_main_mode_process_payloads() ::"\
|
|
" '%s' (%d) is an unsupported payload type",
|
|
ipike_payload_type_to_string(this_payload),
|
|
this_payload);
|
|
|
|
err = IPIKE_ISAKMP_UNSUPPORTED_PAYLOAD;
|
|
}
|
|
|
|
if (err != IPIKE_SUCCESS)
|
|
break;
|
|
|
|
this_payload = payload->next_payload;
|
|
payload = ipike_next_payload(&ctx);
|
|
}
|
|
|
|
ipike_free_payload_enumerator(&ctx);
|
|
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, ISAKMP_PACKET_ERROR,
|
|
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
return err;
|
|
}
|
|
|
|
return ipike_main_mode_update_state(ie);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_add_reply_payloads
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ipike_error
|
|
ipike_main_mode_add_reply_payloads(
|
|
Ipike_isakmp_exchange* ie,
|
|
Ipike_payload_header*** reply_payloads)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
const Ip_u16* payload_ids = IP_NULL;
|
|
int i = 0;
|
|
Ipike_transform_ike *transform_ike;
|
|
|
|
if ( ie->ike_sa->error != IPIKE_SUCCESS )
|
|
return ie->ike_sa->error;
|
|
|
|
payload_ids = ipike_main_mode_get_payload_order(ie);
|
|
|
|
ip_assert(payload_ids != IP_NULL);
|
|
|
|
for (i = 0; payload_ids[i] != IPIKE_PAYLOAD_NONE; i++)
|
|
{
|
|
Ipike_payload_header* reply_payload = IP_NULL;
|
|
Ip_u8 payload_type;
|
|
|
|
if (IP_BIT_ISSET(payload_ids[i], IPIKE_PAYLOAD_OPT) &&
|
|
IP_BIT_ISSET(payload_ids[i], IPIKE_PAYLOAD_ADD) == IP_FALSE)
|
|
/* Only add the optional payload that had the IPIKE_PAYLOAD_ADD bit set */
|
|
continue;
|
|
|
|
payload_type = (Ip_u8) payload_ids[i];
|
|
|
|
switch (payload_type)
|
|
{
|
|
case IPIKE_PAYLOAD_SECURITY_ASSOCIATION:
|
|
err = ipike_sa_create(&ie->ike_sa->sa,
|
|
(Ipike_sa_payload**) &reply_payload);
|
|
if (err == IPIKE_SUCCESS && ie->ike_sa->is_initiator)
|
|
{
|
|
err = ipike_main_mode_store_sai_b(&ie->ike_sa->sai_b,
|
|
(Ipike_sa_payload*) reply_payload);
|
|
if (err != IPIKE_SUCCESS)
|
|
ipcom_free(reply_payload);
|
|
}
|
|
break;
|
|
case IPIKE_PAYLOAD_KEY_EXCHANGE:
|
|
err = ipike_key_exchange_create(ie->ike_sa->is_initiator ? &ie->ike_sa->g_xi : &ie->ike_sa->g_xr,
|
|
(Ipike_ke_payload**) &reply_payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_IDENTFICATION:
|
|
err = ipike_identification_create(ie->ike_sa->is_initiator ? &ie->ike_sa->idii : &ie->ike_sa->idir,
|
|
(Ipike_id_payload**) &reply_payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_HASH:
|
|
err = ipike_hash_create(ie->ike_sa->is_initiator ? &ie->ike_sa->hash_i : &ie->ike_sa->hash_r,
|
|
(Ipike_hash_payload**) &reply_payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_NONCE:
|
|
err = ipike_payload_nonce_create(ie->ike_sa->is_initiator ? &ie->ike_sa->ni : &ie->ike_sa->nr,
|
|
(Ipike_nonce_payload**) &reply_payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_CERTIFICATE:
|
|
err = ipike_main_mode_cert_create(ie->ike_conf,
|
|
(Ipike_cert_payload**) &reply_payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_SIGNATURE:
|
|
err = ipike_sign_create(ie->ike_sa->is_initiator ? &ie->ike_sa->sign_i : &ie->ike_sa->sign_r,
|
|
(Ipike_sign_payload**) &reply_payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_VENDOR_ID:
|
|
if ((IPIKE_SUCCESS == err) && (ipike.port_nat != 0))
|
|
{
|
|
err = ipike_payload_vendor_id_create(IPIKE_VENDOR_ID_NAT_T,
|
|
(Ipike_vendor_id_payload**) &reply_payload);
|
|
if (IPIKE_SUCCESS == err)
|
|
{
|
|
err = ipike_array_add((void***) reply_payloads, reply_payload);
|
|
if (IPIKE_SUCCESS != err)
|
|
ipcom_free(reply_payload);
|
|
}
|
|
}
|
|
if (IPIKE_SUCCESS == err)
|
|
{
|
|
err = ipike_payload_vendor_id_create(IPIKE_VENDOR_ID_DPD,
|
|
(Ipike_vendor_id_payload**) &reply_payload);
|
|
if (IPIKE_SUCCESS == err)
|
|
{
|
|
err = ipike_array_add((void***) reply_payloads, reply_payload);
|
|
if (IPIKE_SUCCESS != err)
|
|
ipcom_free(reply_payload);
|
|
}
|
|
}
|
|
reply_payload = IP_NULL;
|
|
break;
|
|
case IPIKE_PAYLOAD_NAT_DISCOVERY:
|
|
/* Always two payloads (local and peer) */
|
|
transform_ike = ipike_transform_ike_from_exch(ie);
|
|
if (transform_ike==IP_NULL)
|
|
{
|
|
err=IPIKE_FAILED;
|
|
goto error;
|
|
}
|
|
err = ipike_nat_discovery_create(&ie->ike_sa->peer_addr,
|
|
ie->ike_sa->initiator_cookie,
|
|
ie->ike_sa->responder_cookie,
|
|
transform_ike->hash_algorithm,
|
|
(Ipike_nat_discovery_payload**) &reply_payload);
|
|
if (IPIKE_SUCCESS == err)
|
|
err = ipike_array_add((void***) reply_payloads, reply_payload);
|
|
if (IPIKE_SUCCESS == err)
|
|
err = ipike_nat_discovery_create(&ie->ike_sa->local_addr,
|
|
ie->ike_sa->initiator_cookie,
|
|
ie->ike_sa->responder_cookie,
|
|
transform_ike->hash_algorithm,
|
|
(Ipike_nat_discovery_payload**) &reply_payload);
|
|
break;
|
|
case IPIKE_PAYLOAD_CERTIFICATE_REQUEST:
|
|
/* Request certificate if do not already have the peers certificate */
|
|
if ( !ie->ike_sa->cert.peer )
|
|
err = ipike_main_mode_add_cert_request(ie->ike_conf, reply_payloads);
|
|
break;
|
|
case IPIKE_PAYLOAD_NOTIFICATION:
|
|
case IPIKE_PAYLOAD_DELETE:
|
|
IPCOM_LOG1(ERR,
|
|
"Payload creation for '%s' is not implemented",
|
|
ipike_payload_type_to_string(payload_type));
|
|
err = IPIKE_NOT_IMPLEMENTED;
|
|
goto error;
|
|
default:
|
|
IPCOM_LOG1(ERR,
|
|
"Payload creation failed since %d is a unknown payload type",
|
|
payload_type);
|
|
err = IPIKE_ISAKMP_UNSUPPORTED_PAYLOAD;
|
|
goto error;
|
|
}
|
|
|
|
if (err != IPIKE_SUCCESS)
|
|
goto error;
|
|
|
|
if (reply_payload != IP_NULL)
|
|
{
|
|
if (IPIKE_SUCCESS != (err = ipike_array_add((void***) reply_payloads, reply_payload)))
|
|
{
|
|
ipcom_free(reply_payload);
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
error:
|
|
ipike_array_free((void**) *reply_payloads, ipcom_free); /*lint !e123 */
|
|
*reply_payloads = IP_NULL;
|
|
|
|
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR,
|
|
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
|
|
0, IP_NULL);
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_cleartext_outgoing_message
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ipike_error
|
|
ipike_main_mode_cleartext_outgoing_message(
|
|
Ipike_isakmp_exchange* ie,
|
|
Ipike_isakmp_header** outgoing_isakmp)
|
|
{
|
|
(void) ie;
|
|
(void) outgoing_isakmp;
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_main_mode_exchange_done
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ipike_error
|
|
ipike_main_mode_exchange_done(Ipike_isakmp_exchange* ie)
|
|
{
|
|
Ipike_error err;
|
|
|
|
ipike_sadb_free_intermediate(ie->ike_sa);
|
|
if (IPIKE_SUCCESS != (err = ipike_cpy_value(&ie->ike_sa->base_iv, &ie->iv)))
|
|
return err;
|
|
if (IPIKE_SUCCESS != (err = ipike_sadb_set_state(ie, ie->ike_sa, IPIKE_SA_ACTIVE)))
|
|
return err;
|
|
|
|
/* Set liveness */
|
|
ie->ike_sa->liveness.timeout = (Ip_u32) ie->ike_conf->liveness;
|
|
|
|
ipcom_microtime(&ie->stop);
|
|
IPCOM_LOG3(INFO, "Main mode exchange done in %d ms (peer: %s, Message ID: %d)",
|
|
(ie->stop.tv_sec - ie->start.tv_sec) * 1000 + (ie->stop.tv_usec - ie->start.tv_usec) / 1000,
|
|
ipike_addr_to_str(&ie->ike_sa->peer_addr),
|
|
ie->message_id);
|
|
|
|
(void)ipike_print_memory(IPCOM_LOG_DEBUG, "Final phase 1 (main mode) IV: ",
|
|
ie->iv.value, ie->iv.len);
|
|
|
|
if (ie->ike_conf->initial_contact && (ie->rekey_spi.len == 0))
|
|
ipike_informational_report_initial_contact(ie->ike_sa);
|
|
|
|
/* Initiate a quick mode exchange if we are the initiator and
|
|
* if option1 (only IKE) is not set */
|
|
if (ie->ike_sa->is_initiator && !ie->option1)
|
|
(void)ipike_isakmp_initiate_ipsec_exchanges(ie->ike_sa,
|
|
IP_NULL,
|
|
ie->option2);
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|