2406 lines
74 KiB
C
2406 lines
74 KiB
C
/*
|
|
******************************************************************************
|
|
* SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipike2_payload_sa.c,v $ $Revision: 1.39.10.6 $
|
|
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike2_payload_sa.c,v $
|
|
* $Author: wdeng $ $Date: 2021-11-05 09:51:39 $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* IKE v2 Security Association Payload */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
#include "ipike_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPIKE_USE_VERSION2
|
|
|
|
#include "ipike_h.h"
|
|
#include "ipike_sadb.h"
|
|
#include "ipike_util.h"
|
|
#include "ipike_configuration.h"
|
|
|
|
#include "ipike_attributes.h"
|
|
#include "ipike_ipsec_attributes.h"
|
|
#include "ipike2_payload_sa.h"
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_syslog.h>
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_header_size
|
|
*===========================================================================
|
|
* Description: Returns the size of the SA payload header.
|
|
* Parameters: sa - a pointer to a SA payload.
|
|
* Returns: The size (in bytes) of the SA payload header.
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_header_size(void);
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_proposal_proto_id_to_string
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC const char *
|
|
ipike_sa_proposal_proto_id_to_string(Ip_u8 proto);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_transform_type_to_string
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC const char *
|
|
ipike_sa_transform_type_to_string(Ip_u8 type);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_transform_id_to_string
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC const char *
|
|
ipike_sa_transform_id_to_string(Ip_u8 type, Ip_u16 id);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_data
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike2_proposal_info*
|
|
ipike_payload_sa_proposal_data(Ipike2_sa_payload* sa);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_length
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_proposal_length(Ipike2_sa_payload* sa);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_data
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike2_transform_info*
|
|
ipike_payload_sa_transform_data(Ipike2_proposal_info* p);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_length
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_transform_length(Ipike2_proposal_info* p);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_attributes_data
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_attribute*
|
|
ipike_payload_sa_attributes_data(Ipike2_transform_info* t);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_attributes_length
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_attributes_length(Ipike2_transform_info* t);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_spi_data
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u8*
|
|
ipike_payload_sa_proposal_spi_data(Ipike2_proposal_info* p);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_size
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_size(Ipike2_sa* sa);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_next_proposal
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike2_proposal_info*
|
|
ipike_payload_sa_next_proposal(Ipike2_proposal_info* p);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_next_transform
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike2_transform_info*
|
|
ipike_payload_sa_next_transform(Ipike2_transform_info* t);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_next_attribute
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_attribute*
|
|
ipike_payload_sa_next_attribute(Ipike_attribute* a, Ip_size_t length);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_chain_length
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipike_payload_sa_proposal_chain_length(Ipike2_proposal_info* p, Ip_u32 size);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_chain_length
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipike_payload_sa_transform_chain_length(Ipike2_transform_info* t, Ip_u32 size);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_check
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_payload_sa_transform_check(Ipike2_transform_info* t);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_check
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_payload_sa_proposal_check(Ipike2_proposal_info* p);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_add_attribute
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_transform_add_attribute(
|
|
Ipike2_transform* transform,
|
|
Ip_u16 type,
|
|
const char* value);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_create
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_transform_create(
|
|
Ip_u8 type,
|
|
Ip_u16 id,
|
|
Ip_bool more,
|
|
Ipike2_transform** t);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_free_transform
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipike_free_transform(Ipike2_transform* t);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_add_transform
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_proposal_add_transform(
|
|
Ipike2_proposal* proposal,
|
|
Ip_u8 type,
|
|
Ip_u16 id);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_get_algorithms
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC const char*
|
|
ipike_proposal_get_algorithms(
|
|
Ipike_config_proposal* proposal_conf,
|
|
Ip_u8 type);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_is_transform_allowed
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipike_sa_is_transform_allowed(Ip_u8 protocol, Ip_u8 type, Ip_u16 id);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_add_transforms
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_proposal_add_transforms(
|
|
Ipike_config_proposal* proposal_conf,
|
|
Ip_u8 protocol,
|
|
Ip_u8 type,
|
|
Ipike2_proposal* proposal);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_create_proposal
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_create_proposal(
|
|
Ipike_config_proposal* proposal_conf,
|
|
Ip_u8 proposal_number,
|
|
Ip_u8 protocol,
|
|
Ipike2_proposal** proposal);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_create_proposals
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_create_proposals(
|
|
Ip_bool is_ike,
|
|
Ipike_config_proposal** proposals_conf,
|
|
Ipike2_proposal*** proposals);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_free_proposal
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipike_free_proposal(Ipike2_proposal* p);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_attribute_value
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_attribute_value(
|
|
Ipike_attribute * a,
|
|
Ip_u8 * data,
|
|
Ip_size_t size);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_transform_value
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_transform_value(
|
|
Ipike2_transform * t,
|
|
Ip_u8 * data,
|
|
Ip_size_t size);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_transform_content
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_transform_content(
|
|
Ip_bool more,
|
|
Ip_u8 type,
|
|
Ip_u16 id,
|
|
Ipike_attribute* attr,
|
|
Ip_u8* data,
|
|
Ip_size_t size);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_proposal_value
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_proposal_value(
|
|
Ipike2_proposal* p,
|
|
Ip_u8 * data,
|
|
Ip_size_t size);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_proposal_value
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_selected_proposal(
|
|
Ipike2_sa * sa,
|
|
Ip_u8 * data,
|
|
Ip_size_t size);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_extract
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_payload_sa_transform_extract(
|
|
Ipike2_transform_info* info,
|
|
Ipike2_transform* transform);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_extract
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_payload_sa_proposal_extract(
|
|
Ipike2_proposal_info* info,
|
|
Ipike2_proposal* proposal);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 LOCAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_header_size
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_header_size(void)
|
|
{
|
|
return (Ip_u16)(sizeof(Ipike_payload_header));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_proposal_proto_id_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC const char *
|
|
ipike_sa_proposal_proto_id_to_string(Ip_u8 proto)
|
|
{
|
|
const char* s;
|
|
if ((ipike_map_string(ipike.proposal_proto_map, proto, &s)))
|
|
return "invalid security protocol id";
|
|
return s;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_transform_type_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC const char *
|
|
ipike_sa_transform_type_to_string(Ip_u8 type)
|
|
{
|
|
const char* s;
|
|
if ((ipike_map_string(ipike.transform_type_map, type, &s)))
|
|
return "invalid transform type";
|
|
return s;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_transform_id_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC const char *
|
|
ipike_sa_transform_id_to_string(Ip_u8 type, Ip_u16 id)
|
|
{
|
|
const char *s;
|
|
static char buf[32];
|
|
|
|
ipcom_sprintf(buf, "unknown transform id %d", (int)id);
|
|
|
|
switch (type)
|
|
{
|
|
case IPIKE_TRANSFORM_TYPE_ENCR:
|
|
if ((ipike_map_string(ipike.transform_encr_id_map, id, &s)))
|
|
return buf;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_PRF:
|
|
if ((ipike_map_string(ipike.transform_prf_id_map, id, &s)))
|
|
return buf;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_INTEG:
|
|
if ((ipike_map_string(ipike.transform_integ_id_map, id, &s)))
|
|
return buf;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_DH:
|
|
if ((ipike_map_string(ipike.transform_dh_id_map, id, &s)))
|
|
return buf;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_ESN:
|
|
if (id == 0)
|
|
return "off";
|
|
else
|
|
return "on";
|
|
default:
|
|
ipcom_sprintf(buf, "unknown transform type %u", type);
|
|
return buf;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_data
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike2_proposal_info*
|
|
ipike_payload_sa_proposal_data(Ipike2_sa_payload* sa)
|
|
{
|
|
if (ip_htons(sa->header.length) <= ipike_payload_sa_header_size())
|
|
return IP_NULL;
|
|
return (Ipike2_proposal_info*)((Ip_u8*)sa + ipike_payload_sa_header_size());
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_length
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_proposal_length(Ipike2_sa_payload* sa)
|
|
{
|
|
if (ip_htons(sa->header.length) <= ipike_payload_sa_header_size())
|
|
return 0;
|
|
return (Ip_u16)(ip_htons(sa->header.length) - ipike_payload_sa_header_size());
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_data
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike2_transform_info*
|
|
ipike_payload_sa_transform_data(Ipike2_proposal_info* p)
|
|
{
|
|
if (ip_htons(p->length) < (sizeof(*p) + p->spi_size))
|
|
return IP_NULL;
|
|
return (Ipike2_transform_info*)((Ip_u8*)p + sizeof(*p) + p->spi_size);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_length
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_transform_length(Ipike2_proposal_info* p)
|
|
{
|
|
if (ip_htons(p->length) < (sizeof(*p) + p->spi_size))
|
|
return 0;
|
|
return (Ip_u16)(ip_htons(p->length) - sizeof(*p) - p->spi_size);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_attributes_data
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_attribute *
|
|
ipike_payload_sa_attributes_data(Ipike2_transform_info* t)
|
|
{
|
|
if (ip_htons(t->length) <= sizeof(*t))
|
|
return IP_NULL;
|
|
return (Ipike_attribute*)((Ip_u8*)t + sizeof(*t));
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_attributes_length
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_attributes_length(Ipike2_transform_info* t)
|
|
{
|
|
if (ip_htons(t->length) <= sizeof(*t))
|
|
return 0;
|
|
return (Ip_u16)(ip_htons(t->length) - sizeof(*t));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_spi_data
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_u8*
|
|
ipike_payload_sa_proposal_spi_data(Ipike2_proposal_info* p)
|
|
{
|
|
return ((Ip_u8*)p + sizeof(*p));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_size
|
|
*===========================================================================
|
|
* Description: Return propsal size(s) for this SA in host endian
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_payload_sa_size(Ipike2_sa *sa)
|
|
{
|
|
int size;
|
|
|
|
if (sa->proposals == IP_NULL)
|
|
/* No proposals */
|
|
return 0;
|
|
|
|
size = (int) ipike_payload_sa_header_size();
|
|
|
|
if (sa->selected_proposal == -1)
|
|
{
|
|
/* -1 -> Total size of all proposals */
|
|
int i;
|
|
for (i = 0; i < sa->proposal_count; i++)
|
|
size += ip_ntohs(sa->proposals[i]->info.length);
|
|
}
|
|
else
|
|
{
|
|
/* Size of selected proposal only */
|
|
if (sa->selected_proposal < sa->proposal_count)
|
|
size += ip_ntohs(sa->proposals[sa->selected_proposal]->info.length);
|
|
}
|
|
|
|
return (Ip_u16) size;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_next_proposal
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike2_proposal_info *
|
|
ipike_payload_sa_next_proposal(Ipike2_proposal_info *p)
|
|
{
|
|
if (p->more == 0)
|
|
return IP_NULL;
|
|
|
|
p = (Ipike2_proposal_info *)((Ip_u8 *)p + ip_htons(p->length));
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_next_transform
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike2_transform_info*
|
|
ipike_payload_sa_next_transform(Ipike2_transform_info* t)
|
|
{
|
|
if (t->more == 0)
|
|
return IP_NULL;
|
|
t = (Ipike2_transform_info*)((Ip_u8*)t + ip_htons(t->length));
|
|
|
|
return t;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_next_attribute
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_attribute*
|
|
ipike_payload_sa_next_attribute(Ipike_attribute* a, Ip_size_t length)
|
|
{
|
|
Ip_size_t n;
|
|
|
|
n = ipike_attribute_size(a);
|
|
if (length < n)
|
|
n = 0;
|
|
if (n == 0)
|
|
a = IP_NULL;
|
|
else
|
|
a = (Ipike_attribute*)((Ip_u8*)a + n);
|
|
|
|
return a;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_chain_length
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipike_payload_sa_proposal_chain_length(Ipike2_proposal_info* p, Ip_u32 size)
|
|
{
|
|
/* The proposals have same "header" format as payloads, so we can use
|
|
the next payload function */
|
|
return ipike_payload_chain_size((Ipike_payload_header*)p, size);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_chain_length
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipike_payload_sa_transform_chain_length(Ipike2_transform_info* t, Ip_u32 size)
|
|
{
|
|
/* The transforms have same "header" format as payloads, so we can use
|
|
the next payload function */
|
|
return ipike_payload_chain_size((Ipike_payload_header*)t, size);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_check
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_payload_sa_transform_check(Ipike2_transform_info* transform)
|
|
{
|
|
Ipike_attribute* attr;
|
|
Ip_size_t attr_len;
|
|
Ip_ssize_t attr_len_left;
|
|
Ip_size_t attr_total_size = 0; /* calculated total attribute size */
|
|
|
|
if (0 != IP_GET_NTOHS(&transform->reserved) ||
|
|
0 != IP_GET_NTOHS(&transform->reserved2))
|
|
{
|
|
IPCOM_LOG0(ERR, "the reserved field of the transform field is not zero");
|
|
return IPIKE_ISAKMP_INVALID_PAYLOAD;
|
|
}
|
|
|
|
if (transform->more != IPIKE_PAYLOAD_NONE &&
|
|
transform->more != IPIKE_PAYLOAD_TRANSFORM)
|
|
{
|
|
IPCOM_LOG3(ERR,
|
|
"invalid 'next payload' (%d) in field in the transform payload, only %d and %d are allowed",
|
|
(int) transform->more, IPIKE_PAYLOAD_NONE, IPIKE_PAYLOAD_TRANSFORM);
|
|
return IPIKE_WRONG_PAYLOAD;
|
|
}
|
|
|
|
attr = (Ipike_attribute*)((Ip_u8*)transform + sizeof(Ipike2_transform_info));
|
|
attr_len = attr_len_left = IP_GET_NTOHS(&transform->length) - sizeof(Ipike2_transform_info);
|
|
|
|
if (attr_len_left == 0)
|
|
{
|
|
/* No attributes in this transform */
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
if (attr_len_left < 0 || attr_len_left < (Ip_ssize_t)sizeof(Ipike_attribute))
|
|
return IPIKE_ISAKMP_INVALID_PAYLOAD;
|
|
|
|
while (attr)
|
|
{
|
|
attr_total_size += ipike_attribute_size(attr);
|
|
attr = ipike_next_attribute(attr, &attr_len_left);
|
|
}
|
|
|
|
if (attr_total_size > attr_len)
|
|
{
|
|
IPCOM_LOG2(ERR,
|
|
"the transform payload is too small to hold all attributes (%d > %d)",
|
|
attr_total_size,
|
|
attr_len);
|
|
return IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_check
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_payload_sa_proposal_check(Ipike2_proposal_info* p)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ipike2_transform_info* transform;
|
|
Ip_u32 total_length;
|
|
Ip_s32 chain_length;
|
|
Ip_u8 detected_transforms = 0;
|
|
|
|
/* Must have at least one transform */
|
|
if (p->transform_count == 0)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"ipike_check_proposal_payload: the propsal does not have any transforms");
|
|
err = IPIKE_ISAKMP_INVALID_PAYLOAD;
|
|
return err;
|
|
}
|
|
else
|
|
{
|
|
transform = ipike_payload_sa_transform_data(p);
|
|
if (transform==IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"The transforms extends beyond the end of the proposal");
|
|
err = IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
return err;
|
|
}
|
|
|
|
total_length = ipike_payload_sa_transform_length(p);
|
|
chain_length = ipike_payload_sa_transform_chain_length(transform, total_length);
|
|
if (chain_length < 0)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"The transforms extends beyond the end of the proposal");
|
|
err = IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
}
|
|
else if (chain_length != (Ip_s32) total_length)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"The transforms is not as long as indicated by the proposal");
|
|
err = IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
}
|
|
else
|
|
{
|
|
for (;IP_NULL != transform;
|
|
transform = ipike_payload_sa_next_transform(transform))
|
|
{
|
|
if (IPIKE_SUCCESS != (err = ipike_payload_sa_transform_check(transform)))
|
|
break;
|
|
detected_transforms++;
|
|
}
|
|
if ((IPIKE_SUCCESS != err) ||
|
|
(detected_transforms != p->transform_count))
|
|
{
|
|
IPCOM_LOG2(ERR,
|
|
"The propsal indicates %d transforms, %d was found",
|
|
(int)p->transform_count, (int)detected_transforms);
|
|
err = IPIKE_ISAKMP_INVALID_PAYLOAD;
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_add_attribute
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_transform_add_attribute(
|
|
Ipike2_transform* transform,
|
|
Ip_u16 type,
|
|
const char* value)
|
|
{
|
|
Ipike_error err;
|
|
Ipike_attribute* attr;
|
|
Ip_u16 n;
|
|
|
|
switch (type)
|
|
{
|
|
case IPIKE_ATTR_CLS_KEY_LENGTH:
|
|
err = ipike_attribute_key_length_from_enc_alg_string_v2(value, &n);
|
|
if (IPIKE_SUCCESS != err)
|
|
return err;
|
|
if (n == 0) /* default length, no need to specify length */
|
|
return IPIKE_SUCCESS;
|
|
attr = ipcom_malloc(sizeof(*attr));
|
|
if (IP_NULL == attr)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
attr->type = ip_htons(IPIKE_ATTR_BASIC | type);
|
|
attr->value = ip_htons(n*8);
|
|
if (IPIKE_SUCCESS != (err = ipike_array_add((void***)&transform->attributes, attr)))
|
|
{
|
|
ipcom_free(attr);
|
|
return err;
|
|
}
|
|
transform->info.length = ip_ntohs(transform->info.length);
|
|
transform->info.length = (Ip_u16)(transform->info.length + sizeof(Ipike_attribute));
|
|
transform->info.length = ip_htons(transform->info.length);
|
|
break;
|
|
default:
|
|
IP_PANIC(); /* Should never happen */
|
|
return IPIKE_FAILED;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_create
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_transform_create(
|
|
Ip_u8 type,
|
|
Ip_u16 id,
|
|
Ip_bool more,
|
|
Ipike2_transform** t)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ipike2_transform* transform;
|
|
|
|
if (IP_NULL == (transform = ipcom_calloc(1, sizeof(Ipike2_transform))))
|
|
{
|
|
IP_PANIC();
|
|
err = IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
transform->info.type = type;
|
|
transform->info.id = ip_htons(id);
|
|
transform->info.more = (Ip_u8)(more ? 0x03 : 0x00);
|
|
transform->info.length = ip_htons(sizeof(Ipike2_transform_info));
|
|
*t = transform;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_free_transform
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC void
|
|
ipike_free_transform(Ipike2_transform* t)
|
|
{
|
|
ipike_array_free((void**) t->attributes, ipcom_free);
|
|
ipcom_memset(t, 0, sizeof(Ipike2_transform));
|
|
|
|
ipcom_free(t);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_add_transform
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_proposal_add_transform(
|
|
Ipike2_proposal* proposal,
|
|
Ip_u8 type,
|
|
Ip_u16 id)
|
|
{
|
|
Ipike_error err;
|
|
Ipike2_transform* transform;
|
|
|
|
if (IPIKE_SUCCESS != (err = ipike_transform_create(type, id, IP_TRUE, &transform)))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_proposal_add_transform: Failed to add transform");
|
|
}
|
|
else if (IPIKE_SUCCESS != (err = ipike_array_add((void***) &proposal->transforms, transform)))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_proposal_add_transform: Failed to add transform");
|
|
ipcom_free(transform);
|
|
}
|
|
else
|
|
{
|
|
/* Update length of proposal (length host order) */
|
|
proposal->info.length = (Ip_u16)(proposal->info.length +
|
|
ip_ntohs(transform->info.length));
|
|
proposal->info.transform_count++;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_get_algorithms
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC const char*
|
|
ipike_proposal_get_algorithms(
|
|
Ipike_config_proposal* proposal_conf,
|
|
Ip_u8 type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case IPIKE_TRANSFORM_TYPE_DH:
|
|
return proposal_conf->dh_group;
|
|
case IPIKE_TRANSFORM_TYPE_ENCR:
|
|
return proposal_conf->encryption_alg;
|
|
case IPIKE_TRANSFORM_TYPE_PRF:
|
|
return proposal_conf->hash_alg;
|
|
case IPIKE_TRANSFORM_TYPE_INTEG:
|
|
return proposal_conf->integrity_alg;
|
|
default:
|
|
IP_PANIC();
|
|
break;
|
|
}
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_is_transform_allowed
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipike_sa_is_transform_allowed(
|
|
Ip_u8 protocol,
|
|
Ip_u8 type,
|
|
Ip_u16 id)
|
|
{
|
|
if ((protocol == IPIKE_PROTO_IPSEC_ESP || protocol == IPIKE_PROTO_IPSEC_AH) &&
|
|
type == IPIKE_TRANSFORM_TYPE_PRF)
|
|
return IP_FALSE;
|
|
|
|
if (protocol == IPIKE_PROTO_ISAKMP && type == IPIKE_TRANSFORM_TYPE_ENCR &&
|
|
(id == IPIKE_ENCR_NULL || id == IPIKE_ENCR_AES_CTR))
|
|
{
|
|
IPCOM_LOG1(DEBUG, "ipike_sa_is_transform_allowed() :: "\
|
|
"algorithm '%s' not allowed for ISKAMP",
|
|
ipike_attribute_encryption_alg_to_string_v2(id));
|
|
return IP_FALSE;
|
|
}
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_add_transforms
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_proposal_add_transforms(
|
|
Ipike_config_proposal *proposal_conf,
|
|
Ip_u8 protocol,
|
|
Ip_u8 type,
|
|
Ipike2_proposal *proposal)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
const char* str;
|
|
char** vec;
|
|
Ip_u32 i;
|
|
Ip_u16 id;
|
|
Ipike2_transform *transform;
|
|
|
|
str = ipike_proposal_get_algorithms(proposal_conf, type);
|
|
if (str == IP_NULL)
|
|
return IPIKE_SUCCESS; /* none available */
|
|
|
|
vec = ipike_strvec(str, ", ");
|
|
if (vec == IP_NULL)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
for (i = 0; vec[i] != IP_NULL && err == IPIKE_SUCCESS; i++)
|
|
{
|
|
id = ipike_sa_transform_id_from_string(type, vec[i]);
|
|
if ((id != 0) && ipike_sa_is_transform_allowed(protocol, type, id))
|
|
{
|
|
if (IPIKE_SUCCESS != (err = ipike_transform_create(type, id, IP_TRUE, &transform)))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_proposal_add_transforms: Failed to create transform");
|
|
}
|
|
|
|
/* Add optional key length */
|
|
else if (type == IPIKE_TRANSFORM_TYPE_ENCR
|
|
&& (IPIKE_SUCCESS != (err = ipike_transform_add_attribute(transform, IPIKE_ATTR_CLS_KEY_LENGTH, vec[i]))))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_proposal_add_transforms: Failed to add key length");
|
|
ipcom_free(transform);
|
|
}
|
|
else if (IPIKE_SUCCESS != (err = ipike_array_add((void***) &proposal->transforms, transform)))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_proposal_add_transforms: Failed to add transform");
|
|
ipcom_free(transform);
|
|
}
|
|
else
|
|
{
|
|
proposal->info.transform_count++;
|
|
proposal->info.length = (Ip_u16)(proposal->info.length +
|
|
ip_htons(transform->info.length));
|
|
}
|
|
}
|
|
}
|
|
|
|
ipike_array_free((void**)vec, ipcom_free);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_create_proposal
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_create_proposal(
|
|
Ipike_config_proposal* proposal_conf,
|
|
Ip_u8 proposal_number,
|
|
Ip_u8 protocol,
|
|
Ipike2_proposal **proposal)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ipike2_proposal *p;
|
|
|
|
p = ipcom_calloc(1, sizeof(Ipike2_proposal));
|
|
if (p == IP_NULL)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
p->info.proto_id = protocol;
|
|
|
|
err = ipike_proposal_add_transforms(proposal_conf, protocol, IPIKE_TRANSFORM_TYPE_DH, p);
|
|
if (err != IPIKE_SUCCESS)
|
|
goto errout;
|
|
|
|
if (protocol == IPIKE_PROTO_ISAKMP)
|
|
{
|
|
err = ipike_proposal_add_transforms(proposal_conf, protocol, IPIKE_TRANSFORM_TYPE_PRF, p);
|
|
if (err != IPIKE_SUCCESS)
|
|
goto errout;
|
|
}
|
|
|
|
if (protocol != IPIKE_PROTO_IPSEC_AH)
|
|
{
|
|
err = ipike_proposal_add_transforms(proposal_conf, protocol, IPIKE_TRANSFORM_TYPE_ENCR, p);
|
|
if (err != IPIKE_SUCCESS)
|
|
goto errout;
|
|
}
|
|
|
|
err = ipike_proposal_add_transforms(proposal_conf, protocol, IPIKE_TRANSFORM_TYPE_INTEG, p);
|
|
if (err != IPIKE_SUCCESS)
|
|
goto errout;
|
|
|
|
|
|
/* Add ESN for AH/ESP (default false=0) */
|
|
if ((p->info.proto_id == IPIKE_PROTO_IPSEC_ESP || p->info.proto_id == IPIKE_PROTO_IPSEC_AH)
|
|
&& !ipike_proposal_has_transform_type(p, IPIKE_TRANSFORM_TYPE_ESN))
|
|
{
|
|
/* If use_esn isn't specified or set to 'any' */
|
|
if ( proposal_conf->use_esn == IP_NULL ||
|
|
ipcom_strstr(proposal_conf->use_esn, "any") != IP_NULL)
|
|
|
|
{
|
|
/* Default is ESN both on (let responder choose) */
|
|
err = ipike_proposal_add_transform(p, IPIKE_TRANSFORM_TYPE_ESN, 1);
|
|
if (err != IPIKE_SUCCESS)
|
|
goto errout;
|
|
|
|
err = ipike_proposal_add_transform(p, IPIKE_TRANSFORM_TYPE_ESN, 0);
|
|
if (err != IPIKE_SUCCESS)
|
|
goto errout;
|
|
}
|
|
else
|
|
{
|
|
if (ipcom_strstr(proposal_conf->use_esn, "on") != IP_NULL)
|
|
{
|
|
err = ipike_proposal_add_transform(p, IPIKE_TRANSFORM_TYPE_ESN, 1);
|
|
if (err != IPIKE_SUCCESS)
|
|
goto errout;
|
|
}
|
|
if (ipcom_strstr(proposal_conf->use_esn, "off") != IP_NULL)
|
|
{
|
|
err = ipike_proposal_add_transform(p, IPIKE_TRANSFORM_TYPE_ESN, 0);
|
|
if (err != IPIKE_SUCCESS)
|
|
goto errout;
|
|
}
|
|
}
|
|
|
|
IPCOM_LOG1(DEBUG2,"use_esn from config: %s \n",
|
|
proposal_conf->use_esn ? proposal_conf->use_esn : "any");
|
|
}
|
|
|
|
|
|
if (p->info.transform_count == 0)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_create_proposal: at least 1 transform must be specified");
|
|
err = IPIKE_SA_NO_VALID_TRANSFORM_CONFIGURED;
|
|
goto errout;
|
|
}
|
|
|
|
/* Mark last transform as ending */
|
|
p->transforms[p->info.transform_count-1]->info.more = 0;
|
|
|
|
p->info.length = (Ip_u16)(p->info.length + sizeof(p->info));
|
|
p->info.number = proposal_number;
|
|
*proposal = p;
|
|
|
|
/* Store length in correct byte-order */
|
|
p->info.length = ip_htons(p->info.length);
|
|
|
|
/* Success */
|
|
return IPIKE_SUCCESS;
|
|
|
|
|
|
/* Failure */
|
|
errout:
|
|
ip_assert(err != IPIKE_SUCCESS);
|
|
ipcom_free(p);
|
|
return err;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_create_proposals
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_create_proposals(
|
|
Ip_bool is_ike,
|
|
Ipike_config_proposal** proposals_conf,
|
|
Ipike2_proposal*** proposals)
|
|
{
|
|
Ipike_error err = IPIKE_FAILED;
|
|
Ipike2_proposal* p;
|
|
Ip_u8 i;
|
|
Ip_u8 num;
|
|
|
|
if (proposals_conf != IP_NULL)
|
|
{
|
|
for (i = 0; i < 100 && IP_NULL != proposals_conf[i]; i++)
|
|
{
|
|
if ((proposals_conf[i]->number % 0xff) != 0)
|
|
num = (Ip_u8)(proposals_conf[i]->number);
|
|
else
|
|
num = (Ip_u8)(i + 1);
|
|
if (is_ike)
|
|
err = ipike_create_proposal(proposals_conf[i], num, IPIKE_PROTO_ISAKMP, &p);
|
|
else if (IP_NULL == proposals_conf[i]->encryption_alg)
|
|
err = ipike_create_proposal(proposals_conf[i], num, IPIKE_PROTO_IPSEC_AH, &p);
|
|
else
|
|
err = ipike_create_proposal(proposals_conf[i], num, IPIKE_PROTO_IPSEC_ESP, &p);
|
|
if (err != IPIKE_SUCCESS)
|
|
break;
|
|
if (IPIKE_SUCCESS != (err = ipike_array_add((void***) proposals, p)))
|
|
{
|
|
ipcom_free(p);
|
|
break;
|
|
}
|
|
if (proposals_conf[i+1] == IP_NULL)
|
|
p->info.more = 0; /* Last propsal */
|
|
else
|
|
p->info.more = 2; /* Always 2 for proposals */
|
|
}
|
|
}
|
|
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
ipike_array_free((void**)*proposals, ipcom_free);
|
|
*proposals = IP_NULL;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_free_proposal
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC void
|
|
ipike_free_proposal(Ipike2_proposal* p)
|
|
{
|
|
ipike_array_free((void**) p->transforms, (void(*)(void*)) ipike_free_transform);
|
|
ipcom_memset(p, 0, sizeof(Ipike2_proposal));
|
|
|
|
ipcom_free(p);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_attribute_value
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_attribute_value(
|
|
Ipike_attribute * a,
|
|
Ip_u8 * data,
|
|
Ip_size_t size)
|
|
{
|
|
Ip_size_t length;
|
|
|
|
if (IPIKE_ATTR_AF(ip_htons(a->type)))
|
|
length = sizeof(*a);
|
|
else
|
|
length = sizeof(*a) + ip_htons(a->value);
|
|
if (size >= length)
|
|
ipcom_memcpy((void*)data, (void*)a, length);
|
|
else
|
|
length = 0;
|
|
|
|
return length;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_transform_value
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_transform_value(
|
|
Ipike2_transform * t,
|
|
Ip_u8 * data,
|
|
Ip_size_t size)
|
|
{
|
|
Ip_size_t length = 0;
|
|
Ip_size_t length2 = 0;
|
|
Ip_u8 i;
|
|
|
|
/* Should always be enough area, so just ignore value if buffer too small */
|
|
if (size >= ip_htons(t->info.length))
|
|
{
|
|
length2 = sizeof(t->info);
|
|
ipcom_memcpy((void*)data, (void*)&t->info, length2);
|
|
/* Move buffer forward */
|
|
data += length2;
|
|
length += length2;
|
|
size -= length2;
|
|
/* Copy all eventual attributes */
|
|
if (t->attributes != IP_NULL)
|
|
{
|
|
for (i=0; t->attributes[i] != IP_NULL; i++)
|
|
{
|
|
length2 = ipike_copy_attribute_value(t->attributes[i], data, size);
|
|
/* Move buffer forward */
|
|
data += length2;
|
|
length += length2;
|
|
size -= length2;
|
|
}
|
|
}
|
|
ip_assert(length == ip_htons(t->info.length));
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_transform_content
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_transform_content(
|
|
Ip_bool more,
|
|
Ip_u8 type,
|
|
Ip_u16 id,
|
|
Ipike_attribute* attr,
|
|
Ip_u8* data,
|
|
Ip_size_t size)
|
|
{
|
|
Ip_size_t length;
|
|
Ipike2_transform transform;
|
|
|
|
ipcom_memset(&transform, 0, sizeof(transform));
|
|
transform.info.more = (Ip_u8)(more ? 0x03 : 0x00);
|
|
transform.info.length = sizeof(transform.info);
|
|
if (IP_NULL != attr)
|
|
transform.info.length = (Ip_u16)(transform.info.length +
|
|
ipike_attribute_size(attr));
|
|
transform.info.length = ip_htons(transform.info.length);
|
|
transform.info.type = type;
|
|
transform.info.id = ip_htons(id);
|
|
transform.attributes = IP_NULL;
|
|
if (IP_NULL != attr)
|
|
if (IPIKE_SUCCESS != ipike_array_add((void***)&transform.attributes, attr))
|
|
return 0;
|
|
length = ipike_copy_transform_value(&transform, data, size);
|
|
|
|
ipike_array_free((void**)transform.attributes, IP_NULL);
|
|
|
|
return length;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_proposal_value
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_proposal_value(
|
|
Ipike2_proposal * p,
|
|
Ip_u8 * data,
|
|
Ip_size_t size)
|
|
{
|
|
Ip_size_t length = 0;
|
|
Ip_size_t length2 = 0;
|
|
Ip_u8 i;
|
|
|
|
/* Size should be enough, so just ignore if too small */
|
|
ip_assert(size >= ip_htons(p->info.length));
|
|
if (size >= ip_htons(p->info.length))
|
|
{
|
|
/* Copy info part */
|
|
length2 = sizeof(p->info);
|
|
ipcom_memcpy((void*)data, (void*)&p->info, length2);
|
|
data += length2;
|
|
length += length2;
|
|
size -= length2;
|
|
|
|
/* Copy in optional SPI */
|
|
if (p->info.spi_size != 0)
|
|
{
|
|
length2 = p->info.spi_size;
|
|
ipcom_memcpy(data, p->spi, length2);
|
|
data += length2;
|
|
length += length2;
|
|
size -= length2;
|
|
}
|
|
|
|
/* Copy all transforms */
|
|
for (i = 0; p->transforms[i] != IP_NULL; i++)
|
|
{
|
|
length2 = ipike_copy_transform_value(p->transforms[i], data, size);
|
|
data += length2;
|
|
length += length2;
|
|
size -= length2;
|
|
}
|
|
ip_assert(i == p->info.transform_count);
|
|
ip_assert(length == ip_htons(p->info.length));
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_proposal_value
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_size_t
|
|
ipike_copy_selected_proposal(
|
|
Ipike2_sa * sa,
|
|
Ip_u8 * data,
|
|
Ip_size_t size)
|
|
{
|
|
Ip_size_t n;
|
|
Ipike2_proposal_info* info;
|
|
Ipike_attribute attr;
|
|
Ip_bool more;
|
|
|
|
/* Proposal header */
|
|
info = (Ipike2_proposal_info*)data;
|
|
ipcom_memset(info, 0, sizeof(*info));
|
|
info->proto_id = sa->proposals[sa->selected_proposal]->info.proto_id;
|
|
info->number = sa->proposals[sa->selected_proposal]->info.number;
|
|
|
|
n = sizeof(Ipike2_proposal_info);
|
|
data += n;
|
|
size -= n;
|
|
info->length = (Ip_u16) n;
|
|
/* Proposal spi */
|
|
n = sa->proposals[sa->selected_proposal]->info.spi_size;
|
|
ipcom_memcpy(data, sa->proposals[sa->selected_proposal]->spi, n);
|
|
data += n;
|
|
size -= n;
|
|
info->spi_size = (Ip_u8)n;
|
|
info->length = (Ip_u16)(info->length + n);
|
|
/* Add the selected transforms */
|
|
if (sa->selected_esn != IPIKE_TRANSFORM_UNKNOWN)
|
|
{
|
|
more = ((sa->selected_encr != IPIKE_TRANSFORM_UNKNOWN) ||
|
|
(sa->selected_integ != IPIKE_TRANSFORM_UNKNOWN) ||
|
|
(sa->selected_prf != IPIKE_TRANSFORM_UNKNOWN) ||
|
|
(sa->selected_dh != IPIKE_TRANSFORM_UNKNOWN));
|
|
n = ipike_copy_transform_content(more,
|
|
IPIKE_TRANSFORM_TYPE_ESN,
|
|
sa->selected_esn,
|
|
IP_NULL,
|
|
data,
|
|
size);
|
|
data += n;
|
|
size -= n;
|
|
info->transform_count++;
|
|
info->length = (Ip_u16)(info->length + n);
|
|
}
|
|
if (sa->selected_encr != IPIKE_TRANSFORM_UNKNOWN)
|
|
{
|
|
more = ((sa->selected_integ != IPIKE_TRANSFORM_UNKNOWN) ||
|
|
(sa->selected_prf != IPIKE_TRANSFORM_UNKNOWN) ||
|
|
(sa->selected_dh != IPIKE_TRANSFORM_UNKNOWN));
|
|
/* Only DES and 3DES have default key lengths */
|
|
if ((sa->selected_key_length != 0) &&
|
|
(sa->selected_encr != IPIKE_ENCR_DES) &&
|
|
(sa->selected_encr != IPIKE_ENCR_3DES))
|
|
{
|
|
attr.type = (Ip_u16)(IPIKE_ATTR_BASIC | IPIKE_ATTR_CLS_KEY_LENGTH);
|
|
attr.type = ip_htons(attr.type);
|
|
attr.value = (Ip_u16)(sa->selected_key_length*8);
|
|
attr.value = ip_htons(attr.value);
|
|
n = ipike_copy_transform_content(more,
|
|
IPIKE_TRANSFORM_TYPE_ENCR,
|
|
sa->selected_encr,
|
|
&attr,
|
|
data,
|
|
size);
|
|
}
|
|
else
|
|
{
|
|
n = ipike_copy_transform_content(more,
|
|
IPIKE_TRANSFORM_TYPE_ENCR,
|
|
sa->selected_encr,
|
|
IP_NULL,
|
|
data,
|
|
size);
|
|
}
|
|
data += n;
|
|
size -= n;
|
|
info->transform_count++;
|
|
info->length = (Ip_u16) (info->length + n);
|
|
}
|
|
if (sa->selected_integ != IPIKE_TRANSFORM_UNKNOWN)
|
|
{
|
|
more = ((sa->selected_prf != IPIKE_TRANSFORM_UNKNOWN) ||
|
|
(sa->selected_dh != IPIKE_TRANSFORM_UNKNOWN));
|
|
n = ipike_copy_transform_content(more,
|
|
IPIKE_TRANSFORM_TYPE_INTEG,
|
|
sa->selected_integ,
|
|
IP_NULL,
|
|
data,
|
|
size);
|
|
data += n;
|
|
size -= n;
|
|
info->transform_count++;
|
|
info->length = (Ip_u16)(info->length + n);
|
|
}
|
|
if (sa->selected_prf != IPIKE_TRANSFORM_UNKNOWN)
|
|
{
|
|
more = (sa->selected_dh != IPIKE_TRANSFORM_UNKNOWN);
|
|
n = ipike_copy_transform_content(more,
|
|
IPIKE_TRANSFORM_TYPE_PRF,
|
|
sa->selected_prf,
|
|
IP_NULL,
|
|
data,
|
|
size);
|
|
data += n;
|
|
size -= n;
|
|
info->transform_count++;
|
|
info->length = (Ip_u16)(info->length + n);
|
|
}
|
|
if (sa->selected_dh != IPIKE_TRANSFORM_UNKNOWN)
|
|
{
|
|
n = ipike_copy_transform_content(IP_FALSE,
|
|
IPIKE_TRANSFORM_TYPE_DH,
|
|
sa->selected_dh,
|
|
IP_NULL,
|
|
data,
|
|
size);
|
|
data += n;
|
|
size -= n;
|
|
info->transform_count++;
|
|
info->length = (Ip_u16)(info->length + n);
|
|
}
|
|
info->length = ip_htons(info->length);
|
|
|
|
return (ip_htons(info->length));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_transform_extract
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_payload_sa_transform_extract(
|
|
Ipike2_transform_info* info,
|
|
Ipike2_transform* transform)
|
|
{
|
|
Ipike_attribute* attr;
|
|
Ipike_attribute* attr2;
|
|
Ip_size_t length;
|
|
Ip_size_t size;
|
|
|
|
ipcom_memcpy((void*)&transform->info, (void*)info, sizeof(*info));
|
|
length = ipike_payload_sa_attributes_length(info);
|
|
if (length > 0)
|
|
{
|
|
attr = ipike_payload_sa_attributes_data(info);
|
|
while (attr != IP_NULL)
|
|
{
|
|
size = ipike_attribute_size(attr);
|
|
ip_assert(size <= length);
|
|
if (size > 0)
|
|
{
|
|
attr2 = ipcom_malloc(size);
|
|
if (IP_NULL == attr2)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
ipcom_memcpy((void*)attr2, (void*)attr, size);
|
|
if (IPIKE_SUCCESS != ipike_array_add((void***)&transform->attributes, attr2))
|
|
{
|
|
ipcom_free(attr2);
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
length -= size;
|
|
attr = ipike_payload_sa_next_attribute(attr, length);
|
|
}
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_proposal_extract
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_payload_sa_proposal_extract(
|
|
Ipike2_proposal_info* info,
|
|
Ipike2_proposal* proposal)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ipike2_transform_info* transform_info;
|
|
Ipike2_transform* transform;
|
|
|
|
ipcom_memcpy((void*)&proposal->info, (void*)info, sizeof(*info));
|
|
if (info->spi_size != 0)
|
|
{
|
|
if ( info->spi_size > sizeof(proposal->spi) )
|
|
return IPIKE_FAILED;
|
|
|
|
ipcom_memcpy(proposal->spi, ipike_payload_sa_proposal_spi_data(info), info->spi_size);
|
|
}
|
|
transform_info = ipike_payload_sa_transform_data(info);
|
|
while ((err == IPIKE_SUCCESS) && (transform_info != IP_NULL))
|
|
{
|
|
if (IP_NULL == (transform = ipcom_calloc(1, sizeof(Ipike2_transform))))
|
|
{
|
|
IP_PANIC();
|
|
err = IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
else if (IPIKE_SUCCESS != (err = ipike_payload_sa_transform_extract(transform_info, transform)))
|
|
{
|
|
ipike_free_transform(transform);
|
|
IPCOM_LOG0(DEBUG, "ipike_payload_sa_proposal_extract: failed to extract transform");
|
|
}
|
|
else if (IPIKE_SUCCESS != (err = ipike_array_add((void***)&proposal->transforms, transform)))
|
|
{
|
|
ipike_free_transform(transform);
|
|
IPCOM_LOG0(DEBUG, "ipike_payload_sa_proposal_extract: failed to add transform to array");
|
|
}
|
|
transform_info = ipike_payload_sa_next_transform(transform_info);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_transform_id_available
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_sa_transform_id_available(Ip_u8 type, Ip_u16 id)
|
|
{
|
|
const char* s;
|
|
|
|
id = ip_ntohs(id);
|
|
switch (type)
|
|
{
|
|
case IPIKE_TRANSFORM_TYPE_ENCR:
|
|
if ((ipike_map_string(ipike.transform_encr_id_map, id, &s)))
|
|
return IP_FALSE;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_PRF:
|
|
if ((ipike_map_string(ipike.transform_prf_id_map, id, &s)))
|
|
return IP_FALSE;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_INTEG:
|
|
if ((ipike_map_string(ipike.transform_integ_id_map, id, &s)))
|
|
return IP_FALSE;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_DH:
|
|
if ((ipike_map_string(ipike.transform_dh_id_map, id, &s)))
|
|
return IP_FALSE;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_ESN:
|
|
return IP_TRUE;
|
|
default:
|
|
return IP_FALSE;
|
|
}
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_transform_id_from_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_u16
|
|
ipike_sa_transform_id_from_string(Ip_u8 type, const char *s)
|
|
{
|
|
Ip_u16 id = IPIKE_ATTR_INVALID;
|
|
|
|
switch (type)
|
|
{
|
|
case IPIKE_TRANSFORM_TYPE_ENCR:
|
|
if ((ipike_attribute_map_Ip_u16(ipike.transform_encr_id_map, s, &id)))
|
|
return IPIKE_ATTR_INVALID;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_PRF:
|
|
if ((ipike_attribute_map_Ip_u16(ipike.transform_prf_id_map, s, &id)))
|
|
return IPIKE_ATTR_INVALID;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_INTEG:
|
|
if ((ipike_attribute_map_Ip_u16(ipike.transform_integ_id_map, s, &id)))
|
|
return IPIKE_ATTR_INVALID;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_DH:
|
|
if ((ipike_attribute_map_Ip_u16(ipike.transform_dh_id_map, s, &id)))
|
|
return IPIKE_ATTR_INVALID;
|
|
break;
|
|
case IPIKE_TRANSFORM_TYPE_ESN:
|
|
IP_PANIC();
|
|
break;
|
|
default:
|
|
return IPIKE_ATTR_INVALID;
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_encryption_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_transform_encryption_to_string(Ip_u16 id)
|
|
{
|
|
return ipike_sa_transform_id_to_string(IPIKE_TRANSFORM_TYPE_ENCR, id);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_integrity_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_transform_integrity_to_string(Ip_u16 id)
|
|
{
|
|
return ipike_sa_transform_id_to_string(IPIKE_TRANSFORM_TYPE_INTEG, id);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_hash_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_transform_hash_to_string(Ip_u16 id)
|
|
{
|
|
return ipike_sa_transform_id_to_string(IPIKE_TRANSFORM_TYPE_PRF, id);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_dh_group_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_transform_dh_group_to_string(Ip_u16 id)
|
|
{
|
|
return ipike_sa_transform_id_to_string(IPIKE_TRANSFORM_TYPE_DH, id);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_dh_group_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_transform_esn_to_string(Ip_u16 id)
|
|
{
|
|
return ipike_sa_transform_id_to_string(IPIKE_TRANSFORM_TYPE_ESN, id);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_create
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_payload_sa_create(Ipike2_sa* sa, Ipike2_sa_payload** payload)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ip_size_t sa_header_size;
|
|
Ip_size_t sa_size;
|
|
Ip_size_t n;
|
|
Ipike2_sa_payload* sa_payload;
|
|
Ip_u8* proposal_data;
|
|
int i;
|
|
|
|
sa_header_size = ipike_payload_sa_header_size();
|
|
sa_size = ipike_payload_sa_size(sa);
|
|
if (sa->proposal_count == 0)
|
|
{
|
|
IPCOM_LOG0(CRIT, "ipike_payload_sa_create: no proposals");
|
|
err = IPIKE_ISAKMP_NO_PROPOSAL_CHOSEN;
|
|
}
|
|
else if (IP_NULL == (sa_payload = ipcom_calloc(1, sa_size)))
|
|
{
|
|
IP_PANIC();
|
|
err = IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
/* Copy payload header */
|
|
sa_payload->header.next_payload = IPIKE2_PAYLOAD_SECURITY_ASSOCIATION;
|
|
sa_payload->header.length = ip_htons(sa_size);
|
|
|
|
proposal_data = ((Ip_u8*) sa_payload + sa_header_size);
|
|
sa_size -= sa_header_size;
|
|
|
|
/* Create either a specific SA payload or all */
|
|
if (sa->selected_proposal != -1)
|
|
{
|
|
n = ipike_copy_selected_proposal(sa, proposal_data, sa_size);
|
|
ip_assert(sa_size >= n);
|
|
sa_payload->header.length = ip_htons(n + sa_header_size);
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; sa->proposals[i] != IP_NULL; i++)
|
|
{
|
|
if (sa->selected_proposal == -1
|
|
|| sa->selected_proposal == sa->proposals[i]->info.number)
|
|
{
|
|
n = ipike_copy_proposal_value(sa->proposals[i], proposal_data, sa_size);
|
|
proposal_data += n;
|
|
sa_size -= n;
|
|
}
|
|
}
|
|
ip_assert(sa_size == 0);
|
|
}
|
|
*payload = sa_payload;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_free
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_payload_sa_free(Ipike2_sa *s, void(*free_func)(void*))
|
|
{
|
|
ip_assert(s != IP_NULL);
|
|
|
|
ipike_array_free((void**)s->proposals, (void(*)(void*))ipike_free_proposal);
|
|
|
|
/* Reset all negotiated SA values, keep the others unchanged */
|
|
s->selected_proposal = -1;
|
|
s->proposal_count = 0;
|
|
s->proposals = IP_NULL;
|
|
s->selected_encr = IPIKE_TRANSFORM_UNKNOWN;
|
|
s->selected_prf = IPIKE_TRANSFORM_UNKNOWN;
|
|
s->selected_integ = IPIKE_TRANSFORM_UNKNOWN;
|
|
s->selected_dh = IPIKE_TRANSFORM_UNKNOWN;
|
|
s->selected_esn = IPIKE_TRANSFORM_UNKNOWN;
|
|
s->selected_key_length = 0;
|
|
|
|
if (free_func)
|
|
free_func(s);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_initialize
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_payload_sa_initialize(Ip_bool is_ike, Ipike_config_proposal **proposals, Ipike2_sa *sa)
|
|
{
|
|
Ipike_error err;
|
|
int i;
|
|
|
|
ipcom_memset(sa, 0, sizeof(*sa));
|
|
|
|
err = ipike_create_proposals(is_ike, proposals, &sa->proposals);
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_payload_sa_initialize() :: failed to create proposals");
|
|
return err;
|
|
}
|
|
|
|
if (sa->proposals != IP_NULL)
|
|
for (i = 0; sa->proposals[i] != IP_NULL; i++)
|
|
sa->proposal_count++;
|
|
sa->selected_proposal = -1;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_check
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_payload_sa_check(Ipike2_sa_payload* sa)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ipike2_proposal_info* proposal;
|
|
Ip_u32 total_length;
|
|
Ip_s32 chain_length;
|
|
|
|
proposal = (Ipike2_proposal_info*)ipike_payload_sa_proposal_data(sa);
|
|
if (proposal==IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"The proposals extends beyond the end of the SA payload size");
|
|
err = IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
return err;
|
|
}
|
|
|
|
total_length = ipike_payload_sa_proposal_length(sa);
|
|
chain_length = ipike_payload_sa_proposal_chain_length(proposal, total_length);
|
|
if (chain_length < 0)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"The proposals extends beyond the end of the SA payload size");
|
|
err = IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
}
|
|
else if (chain_length != (Ip_s32) total_length)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"The proposals is not as long as indicated by the SA payload header");
|
|
err = IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
}
|
|
else
|
|
{
|
|
for (;IP_NULL != proposal; proposal = ipike_payload_sa_next_proposal(proposal))
|
|
{
|
|
if (IPIKE_SUCCESS != (err = ipike_payload_sa_proposal_check(proposal)))
|
|
break;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_print
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_payload_sa_print(Ipike2_sa_payload* sa)
|
|
{
|
|
Ipike2_proposal_info* proposal;
|
|
Ipike2_transform_info* transform;
|
|
const char* s = IP_NULL;
|
|
|
|
/* lint */
|
|
(void)s;
|
|
|
|
/* The payload must be correct, will assume check already run */
|
|
proposal = ipike_payload_sa_proposal_data(sa);
|
|
for (;IP_NULL != proposal; proposal = ipike_payload_sa_next_proposal(proposal))
|
|
{
|
|
s = ipike_sa_proposal_proto_id_to_string(proposal->proto_id);
|
|
IPCOM_LOG0(DEBUG2, " << proposal >>");
|
|
IPCOM_LOG1(DEBUG2, " Proposal #: %d", proposal->number);
|
|
IPCOM_LOG1(DEBUG2, " Protocol ID: %s", s);
|
|
IPCOM_LOG1(DEBUG2, " SPI Size: %d", (int)proposal->spi_size);
|
|
if (proposal->spi_size != 0)
|
|
{
|
|
(void)ipike_print_memory(IPCOM_LOG_DEBUG2, " spi data: ",
|
|
ipike_payload_sa_proposal_spi_data(proposal),
|
|
proposal->spi_size);
|
|
}
|
|
|
|
IPCOM_LOG1(DEBUG2, " # of Transforms: %d",
|
|
(int)proposal->transform_count);
|
|
transform = ipike_payload_sa_transform_data(proposal);
|
|
for (;IP_NULL != transform; transform = ipike_payload_sa_next_transform(transform))
|
|
{
|
|
IPCOM_LOG0(DEBUG2, " <<< transform >>>");
|
|
s = ipike_sa_transform_type_to_string(transform->type);
|
|
IPCOM_LOG1(DEBUG2, " Type: %s", s);
|
|
s = ipike_sa_transform_id_to_string(transform->type, ip_htons(transform->id));
|
|
IPCOM_LOG1(DEBUG2, " ID: %s", s);
|
|
|
|
if (ipike_payload_sa_attributes_length(transform) > 0)
|
|
{
|
|
(void)ipike_print_memory(IPCOM_LOG_DEBUG2,
|
|
" Attr: ",
|
|
(Ip_u8 *)ipike_payload_sa_attributes_data(transform),
|
|
ipike_payload_sa_attributes_length(transform));
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_extract
|
|
*===========================================================================
|
|
* Description: V1V2
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_payload_sa_extract(Ipike2_sa_payload *payload, Ipike2_sa *sa)
|
|
{
|
|
Ipike_error err = IPIKE_SA_NO_ACCEPTED_PROPOSAL;
|
|
Ipike2_proposal_info *proposal_info;
|
|
Ipike2_proposal *proposal;
|
|
|
|
ipike_payload_sa_free(sa, IP_NULL);
|
|
|
|
/* The payload must be correct, will assume check already run */
|
|
proposal_info = ipike_payload_sa_proposal_data(payload);
|
|
while (proposal_info != IP_NULL)
|
|
{
|
|
proposal = ipcom_calloc(1, sizeof(Ipike2_proposal));
|
|
if (proposal == IP_NULL)
|
|
{
|
|
IP_PANIC();
|
|
err = IPIKE_OUT_OF_MEMORY;
|
|
break;
|
|
}
|
|
|
|
err = ipike_payload_sa_proposal_extract(proposal_info, proposal);
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
ipike_free_proposal(proposal);
|
|
IPCOM_LOG0(DEBUG, "ipike_payload_sa_extract: failed to extract proposal");
|
|
break;
|
|
}
|
|
|
|
switch (proposal->info.proto_id)
|
|
{
|
|
case IPIKE_PROTO_ISAKMP:
|
|
break;
|
|
case IPIKE_PROTO_IPSEC_AH:
|
|
case IPIKE_PROTO_IPSEC_ESP:
|
|
break;
|
|
default:
|
|
/* wrong protocol proposal -> ignore */
|
|
ipike_free_proposal(proposal);
|
|
goto ignore;
|
|
}
|
|
|
|
err = ipike_array_add((void***)&sa->proposals, proposal);
|
|
if (err != IPIKE_SUCCESS)
|
|
{
|
|
ipike_free_proposal(proposal);
|
|
IPCOM_LOG0(DEBUG, "ipike_payload_sa_extract: failed to add proposal to array");
|
|
break;
|
|
}
|
|
|
|
sa->proposal_count++;
|
|
ignore:
|
|
proposal_info = ipike_payload_sa_next_proposal(proposal_info);
|
|
}
|
|
|
|
sa->selected_proposal = -1; /* No selected proposal */
|
|
if (err == IPIKE_SUCCESS && sa->proposal_count == 0)
|
|
err = IPIKE_SA_NO_ACCEPTED_PROPOSAL;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_payload_sa_set_spi
|
|
*===========================================================================
|
|
* Description: Set spi value for all SA proposals.
|
|
* Parameters: sa - Will be updated with the new spi value if the call was
|
|
* successful.
|
|
* spi - New spi value.
|
|
* Returns: IPIKE_SUCCESS
|
|
* IPIKE_OUT_OF_MEMORY
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_payload_sa_set_spi(Ipike2_sa *sa, Ip_u8 *spi_data, Ip_u16 spi_len)
|
|
{
|
|
Ip_u8 i;
|
|
|
|
for (i = 0; i < sa->proposal_count; i++)
|
|
{
|
|
if ( spi_len > sizeof(sa->proposals[0]->spi) )
|
|
return IPIKE_FAILED;
|
|
|
|
sa->proposals[i]->info.spi_size = (Ip_u8)spi_len;
|
|
ipcom_memcpy(sa->proposals[i]->spi, spi_data, spi_len);
|
|
|
|
sa->proposals[i]->info.length = (Ip_u16)(ip_ntohs(sa->proposals[i]->info.length)
|
|
+ spi_len);
|
|
sa->proposals[i]->info.length = ip_htons(sa->proposals[i]->info.length);
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_get_next_transform
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_u16
|
|
ipike_proposal_get_next_transform(Ipike2_sa* sa, Ip_u16 type, Ip_u16 old_id)
|
|
{
|
|
Ip_u8 i, j;
|
|
Ip_u16 id;
|
|
|
|
for (i=0; i<sa->proposal_count; i++)
|
|
{
|
|
for (j=0; (sa->proposals[i]->transforms[j] != 0); j++)
|
|
{
|
|
if (sa->proposals[i]->transforms[j]->info.type == type)
|
|
{
|
|
id = ip_htons(sa->proposals[i]->transforms[j]->info.id);
|
|
if (old_id == 0)
|
|
return id;
|
|
else if (old_id == id)
|
|
old_id = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return IPIKE_ATTR_INVALID;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_has_transform
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_proposal_has_transform(Ipike2_proposal* proposal, Ip_u16 type, Ip_u16 id)
|
|
{
|
|
Ip_u8 i;
|
|
|
|
for (i=0; (proposal->transforms[i] != 0); i++)
|
|
if (proposal->transforms[i]->info.type == type)
|
|
if (id == ip_htons(proposal->transforms[i]->info.id))
|
|
return IP_TRUE;
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_has_transform_type
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_proposal_has_transform_type(Ipike2_proposal* proposal, Ip_u16 type)
|
|
{
|
|
Ip_u8 i;
|
|
|
|
for (i=0; (proposal->transforms[i] != 0); i++)
|
|
{
|
|
if (proposal->transforms[i]->info.type == type)
|
|
{
|
|
return IP_TRUE;
|
|
}
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_proposal_remove_transform_type
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_proposal_remove_transform_type(Ipike2_sa* sa, Ip_u16 type)
|
|
{
|
|
Ip_u16 i, j;
|
|
Ip_u16 size;
|
|
|
|
for (i = 0; i<sa->proposal_count; i++)
|
|
{
|
|
for (j = 0; j<sa->proposals[i]->info.transform_count; j++)
|
|
{
|
|
if (sa->proposals[i]->transforms[j]->info.type == type)
|
|
{
|
|
size = (Ip_u16)(ip_ntohs(sa->proposals[i]->info.length) -
|
|
ip_ntohs(sa->proposals[i]->transforms[j]->info.length));
|
|
sa->proposals[i]->info.length = ip_htons(size);
|
|
|
|
ipike_array_remove((void***) &sa->proposals[i]->transforms,
|
|
sa->proposals[i]->transforms[j],
|
|
ipcom_free);
|
|
j--;
|
|
sa->proposals[i]->info.transform_count--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_transform_get_key_length
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_u16
|
|
ipike_transform_get_key_length(Ipike2_transform* transform)
|
|
{
|
|
Ip_u16 i;
|
|
Ipike_attribute* attr;
|
|
Ip_u16 type;
|
|
|
|
if (IP_NULL != transform->attributes)
|
|
{
|
|
for (i=0; ((attr = transform->attributes[i]) != IP_NULL); i++)
|
|
{
|
|
type = ip_htons(attr->type);
|
|
if (IPIKE_ATTR_AF(type) &&
|
|
(IPIKE_ATTR_TYPE(type) == IPIKE_ATTR_CLS_KEY_LENGTH))
|
|
{
|
|
return (Ip_u16)(ip_ntohs(attr->value)/8);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
|
|
int ipike_payload_sa_empty_file = 0;
|
|
|
|
#endif /* IPIKE_USE_VERSION2 */
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|