Files
m241Neelima/components/ip_net2-6.9/ipike/src/ipike_exchange_aggressive_mode.c
T
2026-07-30 11:19:44 +05:30

1239 lines
43 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_exchange_aggressive_mode.c,v $ $Revision: 1.21.10.11 $
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_exchange_aggressive_mode.c,v $
* $Author: zan $ $Date: 2013-08-01 02:00:39 $
* $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
****************************************************************************
*/
#ifdef IPIKE_USE_AGGRESSIVE_MODE
#include "ipike_h.h"
#include "ipike_exchange_aggressive_mode.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 <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
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipike_aggressive_mode_authentication_add
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_mode_authentication_add(Ipike_isakmp_exchange* ie)
{
Ipike_error err;
Ip_u16 auth_meth;
Ip_u16 hash_alg;
Ipike_value* hash;
Ipike_value* sign;
Ipike_transform_ike *transform_ike;
transform_ike=ipike_transform_ike_from_exch(ie);
if (transform_ike==IP_NULL)
return IPIKE_FAILED;
auth_meth = transform_ike->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;
if (ie->ike_sa->is_initiator)
{
hash = &ie->ike_sa->hash_i;
sign = &ie->ike_sa->sign_i;
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_hash_i(hash_alg, ie->ike_sa, hash)))
return err;
}
else
{
hash = &ie->ike_sa->hash_r;
sign = &ie->ike_sa->sign_r;
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_hash_r(hash_alg, ie->ike_sa, hash)))
return err;
}
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,
hash,
sign);
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,
hash,
sign);
if (IPIKE_SUCCESS == err)
return err;
return err;
}
/*
*===========================================================================
* ipike_aggressive_mode_authentication_check
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_mode_authentication_check(Ipike_isakmp_exchange* ie)
{
return ipike_main_mode_authentication_check(ie);
}
/*
*===========================================================================
* ipike_aggressive_mode_cert_update_responder_config
*===========================================================================
*/
IP_STATIC void
ipike_aggressive_mode_update_responder_config(Ipike_isakmp_exchange *ie)
{
ipike_main_mode_update_responder_config(ie);
}
/* This IKE daemon is responder */
/*
*===========================================================================
* ipike_aggressive_mode_update_after_msg_1
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_mode_update_after_msg_1(Ipike_isakmp_exchange* ie)
{
Ipike_error err;
Ipike_transform_ike* transform;
/* Check if there is a more suitable IKE SA config */
ipike_aggressive_mode_update_responder_config(ie);
err = ipike_policy_select_ike_sa_param(ie->ike_conf,
&ie->ike_sa->sa,
&ie->ike_sa->selected,
IP_FALSE);
if (IPIKE_SUCCESS != err)
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\
"select SA failed");
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, PROPOSAL_MISMATCH,
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
0, IP_NULL);
/* Log and return */
return err;
}
if (IPIKE_SUCCESS != (err = ipike_payload_nonce_generate(&ie->ike_sa->nr)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\
"nonce generation failed");
goto errout;
}
transform = ipike_transform_ike_from_exch(ie);
if (transform==IP_NULL)
{
err=IPIKE_FAILED;
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_generate_dh_key(
transform->dh_prime,
transform->dh_generator,
&ie->dh,
&ie->ike_sa->g_xr)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() ::"\
" DH key generation failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_dh_key(
ie->dh,
&ie->ike_sa->g_xi,
&ie->ike_sa->g_xy)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\
"compute DH key failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_skeyid(
ie->ike_conf,
ie->ike_sa)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\
" compute skeyid failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_phase1_secret_key(ie)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\
" compute phase1 failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_initial_phase1_iv(
ie->ike_sa,
&ie->iv)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\
"compute initial iv failed");
goto errout;
}
if ((IP_NULL == ie->ike_conf->local_id) ||
(IPIKE_SUCCESS != ipike_identification_generate(ie->ike_conf->local_id, &ie->ike_sa->idir)))
{
if (IPIKE_SUCCESS != (err = ipike_ipsec_set_idix(&ie->ike_sa->local_addr, &ie->ike_sa->idir)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\
"id initialize failed");
goto errout;
}
}
if (IPIKE_SUCCESS != (err = ipike_aggressive_mode_authentication_add(ie)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\
"add authentication failed");
goto errout;
}
return IPIKE_SUCCESS;
errout:
/* Log general IKE error */
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_aggressive_mode_update_after_msg_3
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_mode_update_after_msg_3(Ipike_isakmp_exchange* ie)
{
Ipike_error err;
if (IPIKE_SUCCESS != (err = ipike_aggressive_mode_authentication_check(ie)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_3() :: "\
"authentication check failed");
IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, AUTHENTICATION_ERROR,
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
0, IP_NULL);
return err;
}
/* Everything should be encrypted from now on */
ie->isakmp_flags = IPIKE_ISAKMP_ENCRYPTION;
return IPIKE_SUCCESS;
}
/* This IKE daemon is initiator */
/*
*===========================================================================
* ipike_aggressive_mode_update_before_msg_1
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_mode_update_before_msg_1(Ipike_isakmp_exchange* ie)
{
Ipike_error err;
Ipike_transform_ike* transform;
/* Try to use id from configuration, use ip-address if fails */
if ((IP_NULL == ie->ike_conf->local_id) ||
(IPIKE_SUCCESS != ipike_identification_generate(ie->ike_conf->local_id, &ie->ike_sa->idii)))
{
if (IPIKE_SUCCESS != (err = ipike_ipsec_set_idix(&ie->ike_sa->local_addr, &ie->ike_sa->idii)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() ::"\
"id initialize failed");
goto errout;
}
}
/* Initialize SA */
if (IPIKE_SUCCESS != (err = ipike_sa_ike_initialize(ie->ike_conf, &ie->ike_sa->sa)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\
"SA initialize failed");
goto errout;
}
/* Initialize KE */
transform = &ie->ike_sa->sa.proposals[0]->transforms[0]->ike;
if (IPIKE_SUCCESS != (err = ipike_crypto_generate_dh_key(
transform->dh_prime,
transform->dh_generator,
&ie->dh,
&ie->ike_sa->g_xi)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\
"DH key generation failed");
goto errout;
}
/* Initialize NONCE */
if (IPIKE_SUCCESS != (err = ipike_payload_nonce_generate(&ie->ike_sa->ni)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\
"nonce generation failed");
goto errout;
}
return IPIKE_SUCCESS;
errout:
/* Log general IKE error */
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_aggressive_mode_update_after_msg_2
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_mode_update_after_msg_2(Ipike_isakmp_exchange* ie)
{
Ipike_sadb_entry* ike_sa = ie->ike_sa;
Ipike_error err;
err = ipike_policy_select_ike_sa_param(ie->ike_conf,
&ike_sa->sa,
&ike_sa->selected,
IP_TRUE);
if (IPIKE_SUCCESS != err)
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\
"select SA failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_dh_key(
ie->dh,
&ike_sa->g_xr,
&ike_sa->g_xy)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\
"compute DH key failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_skeyid(
ie->ike_conf,
ike_sa)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\
"compute skeyid failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_phase1_secret_key(ie)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\
"compute phase1 failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_crypto_compute_initial_phase1_iv(
ike_sa,
&ie->iv)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\
"compute initial iv failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_aggressive_mode_authentication_check(ie)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\
"authentication check failed");
goto errout;
}
if (IPIKE_SUCCESS != (err = ipike_aggressive_mode_authentication_add(ie)))
{
IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\
"add authentication failed");
goto errout;
}
/* Everything should be encrypted from now on */
ie->isakmp_flags = IPIKE_ISAKMP_ENCRYPTION;
return IPIKE_SUCCESS;
errout:
/* Log general IKE error */
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_aggressive_mode_update_state
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_mode_update_state(Ipike_isakmp_exchange* ie)
{
switch (ie->message_number)
{
/* We are responder */
case 1: return ipike_aggressive_mode_update_after_msg_1(ie);
case 3: return ipike_aggressive_mode_update_after_msg_3(ie);
/* We are initiator */
case 0: return ipike_aggressive_mode_update_before_msg_1(ie);
case 2: return ipike_aggressive_mode_update_after_msg_2(ie);
}
IPCOM_LOG1(ERR,
"IKE aggressive mode has 3 messages, this was %d",
ie->message_number);
IPIKE_EVENT_LOG(IKE_PACKET_DISCARD, ISAKMP_PACKET_ERROR,
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
0, IP_NULL);
return IPIKE_INVALID_MESSAGE_NUMBER;
}
/*
*===========================================================================
* ipike_aggressive_mode_store_sai_b
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_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_aggressive_mode_cert_create
*===========================================================================
*/
IP_STATIC Ipike_error
ipike_aggressive_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;
}
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipike_aggressive_mode_on_new_exchange_initiator
*===========================================================================
*/
IP_PUBLIC Ipike_error
ipike_aggressive_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_aggressive_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_aggressive_mode_update_state(ie);
}
/*
*===========================================================================
* ipike_aggressive_mode_on_new_exchange_responder
*===========================================================================
*/
IP_PUBLIC Ipike_error
ipike_aggressive_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_aggressive_mode_on_new_exchange_responder: 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_aggressive_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_aggressive_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_aggressive_mode_on_delete_exchange
*===========================================================================
*/
IP_PUBLIC void
ipike_aggressive_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_aggressive_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_aggressive_mode_get_payload_order
*===========================================================================
*/
IP_PUBLIC const Ip_u16 *
ipike_aggressive_mode_get_payload_order(Ipike_isakmp_exchange* ie)
{
static Ip_u16 aggressive_mode_exchange[] =
{
/* message # 1 */
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
IPIKE_PAYLOAD_KEY_EXCHANGE,
IPIKE_PAYLOAD_NONCE,
IPIKE_PAYLOAD_IDENTFICATION,
IPIKE_PAYLOAD_CERTIFICATE_REQUEST | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_VENDOR_ID | IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD,
IPIKE_PAYLOAD_NONE,
/* message # 2 */
IPIKE_PAYLOAD_SECURITY_ASSOCIATION,
IPIKE_PAYLOAD_KEY_EXCHANGE,
IPIKE_PAYLOAD_NONCE,
IPIKE_PAYLOAD_IDENTFICATION,
IPIKE_PAYLOAD_HASH | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_CERTIFICATE_REQUEST | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_CERTIFICATE | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_SIGNATURE | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_VENDOR_ID | IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD,
IPIKE_PAYLOAD_NAT_DISCOVERY | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_NONE,
/* message # 3 */
IPIKE_PAYLOAD_HASH | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_CERTIFICATE_REQUEST | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_CERTIFICATE | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_SIGNATURE | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_NAT_DISCOVERY | IPIKE_PAYLOAD_OPT,
IPIKE_PAYLOAD_NONE,
};
int i = 1;
Ip_u16 n = 0;
Ip_u16* ret = aggressive_mode_exchange;
Ip_u16 auth_method = 0;
while (i != ie->message_number)
if (*ret++ == IPIKE_PAYLOAD_NONE)
i++;
/* Some optional must be added depending on authentication mechanism */
ipike_attribute_auth_method_from_string(ie->ike_conf->authentication.method,
&auth_method);
i = 0;
while (ret[i] != IPIKE_PAYLOAD_NONE)
{
n = (Ip_u16)(ret[i] & 0x3FFF);
if ( auth_method == IPIKE_ATTR_AUTH_PRE_SHARED_KEY )
{
switch (n)
{
case IPIKE_PAYLOAD_HASH:
ret[i] |= IPIKE_PAYLOAD_ADD;
break;
case IPIKE_PAYLOAD_CERTIFICATE:
case IPIKE_PAYLOAD_CERTIFICATE_REQUEST:
case IPIKE_PAYLOAD_SIGNATURE:
ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD);
break;
default:
break;
}
}
else
{
switch (n)
{
case IPIKE_PAYLOAD_HASH:
ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD);
break;
case 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);
break;
case 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);
break;
case IPIKE_PAYLOAD_SIGNATURE:
ret[i] |= IPIKE_PAYLOAD_ADD;
break;
default:
break;
}
}
i++;
}
/* Some optional must be added depending on 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);
}
i++;
}
return ret;
}
/*
*===========================================================================
* ipike_aggressive_mode_process_payloads
*===========================================================================
*/
IP_PUBLIC Ipike_error
ipike_aggressive_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
{
err = ipike_aggressive_mode_store_sai_b(
&ie->ike_sa->sai_b,
(Ipike_sa_payload*) payload);
/* Store the binary encoding of the SA from the initiator */
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_aggressive_mode_process_payloads() :: "\
"'%s' (%d) is an unsupported payload type",
ipike_payload_type_to_string(this_payload),
this_payload);
err = IPIKE_ISAKMP_UNSUPPORTED_PAYLOAD;
break;
}
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_PACKET_DISCARD, ISAKMP_PACKET_ERROR,
&ie->ike_sa->peer_addr, &ie->ike_sa->local_addr,
0, IP_NULL);
return err;
}
return ipike_aggressive_mode_update_state(ie);
}
/*
*===========================================================================
* ipike_aggressive_mode_add_reply_payloads
*===========================================================================
*/
IP_PUBLIC Ipike_error
ipike_aggressive_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;
payload_ids = ipike_aggressive_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_aggressive_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_aggressive_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;
break;
}
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);
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->peer_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;
return err;
}
/*
*===========================================================================
* ipike_aggressive_mode_cleartext_outgoing_message
*===========================================================================
*/
IP_PUBLIC Ipike_error
ipike_aggressive_mode_cleartext_outgoing_message(
Ipike_isakmp_exchange* ie,
Ipike_isakmp_header** outgoing_isakmp)
{
(void) ie;
(void) outgoing_isakmp;
return IPIKE_SUCCESS;
}
/*
*===========================================================================
* ipike_aggressive_mode_exchange_done
*===========================================================================
*/
IP_PUBLIC Ipike_error
ipike_aggressive_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, "Aggressive 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 (aggressive 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;
}
#endif /* IPIKE_USE_AGGRESSIVE_MODE */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/