842 lines
27 KiB
C
842 lines
27 KiB
C
/*
|
|
******************************************************************************
|
|
* SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_payload_sa.c,v $ $Revision: 1.32.10.15 $
|
|
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_payload_sa.c,v $
|
|
* $Author: yli12 $ $Date: 2016-03-25 09:56:29 $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* IKE Security Association Payload
|
|
NOTE! The current implementation does only support the IPSec DOI */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipike_h.h"
|
|
#include "ipike_config.h"
|
|
#include "ipike_payload_sa.h"
|
|
#include "ipike_payload_proposal.h"
|
|
#include "ipike_sadb.h"
|
|
#include "ipike_util.h"
|
|
#include "ipike_configuration.h"
|
|
#include "ipike_ipsec_attributes.h"
|
|
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_syslog.h>
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_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_sa_header_size(Ipike_sa_payload* sa);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_proposal_data
|
|
*===========================================================================
|
|
* Description: Returns a pointer to the first proposal payload.
|
|
* Parameters: sa - a pointer to a SA payload.
|
|
* Returns: A pointer to the first proposal payload.
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_proposal_payload*
|
|
ipike_sa_proposal_data(Ipike_sa_payload* sa);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_proposal_length
|
|
*===========================================================================
|
|
* Description: Returns the length of the proposal payload(s).
|
|
* Parameters: sa - a pointer to a SA payload.
|
|
* Returns: The length (in bytes) of the proposal payload(s).
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_sa_proposal_length(Ipike_sa_payload* sa);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_process_message_ipsec
|
|
*===========================================================================
|
|
* Description: Updates the security association and exchange paramters
|
|
* with the selected encryption and hash alghorithm using
|
|
* IPSec domain of interpretation.
|
|
* Parameters: ie - paramters for the ongoing exchange.
|
|
* payload - a SA payload.
|
|
* sa - will be updated with the paramters from the SA payload
|
|
* if the call was successful.
|
|
* Returns: IPIKE_SUCCESS
|
|
* IPIKE_OUT_OF_MEMORY
|
|
* IPIKE_SA_NO_ACCEPTED_TRANSFORM,
|
|
* IPIKE_SA_DOI_SITUATION_UNSUPPORTED,
|
|
*
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_sa_process_message_ipsec(Ipike_isakmp_exchange* ie, Ipike_sa_payload* payload, Ipike_sa* sa);
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_print_payload
|
|
*===========================================================================
|
|
* Description: Prints the content of a security association payload to
|
|
* the system log.
|
|
* Parameters: sa - a SA payload.
|
|
* print_proposal_payload - a function that knowns how to print
|
|
* the proposal payload in the current phase and DOI.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipike_sa_print_payload(
|
|
Ipike_sa_payload* sa,
|
|
void (*print_proposal_payload)(Ipike_proposal_payload*),
|
|
Ip_bool phase1);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 LOCAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_header_size
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_sa_header_size(Ipike_sa_payload *sa)
|
|
{
|
|
switch (ip_ntohl(sa->doi))
|
|
{
|
|
/* case IPIKE_DOI_ISAKMP:
|
|
return IPIKE_SA_HEADER_SIZE_ISAKMP;*/
|
|
case IPIKE_DOI_IPSEC:
|
|
return IPIKE_SA_HEADER_SIZE_IPSEC;
|
|
}
|
|
IPCOM_LOG1(ERR, "unsupported DOI (%d)", ip_ntohl(sa->doi));
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_proposal_data
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_proposal_payload *
|
|
ipike_sa_proposal_data(Ipike_sa_payload *sa)
|
|
{
|
|
return (Ipike_proposal_payload *) ((Ip_u8 *) sa + ipike_sa_header_size(sa));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_proposal_length
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_u16
|
|
ipike_sa_proposal_length(Ipike_sa_payload *sa)
|
|
{
|
|
return (Ip_u16) (ip_ntohs(sa->header.length) - ipike_sa_header_size(sa));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_next_payload
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_proposal_payload*
|
|
ipike_sa_next_payload(Ipike_proposal_payload* payload)
|
|
{
|
|
return (Ipike_proposal_payload*)ipike_next_payload_structure(&payload->header);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_process_message_ipsec
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_sa_process_message_ipsec(
|
|
Ipike_isakmp_exchange* ie,
|
|
Ipike_sa_payload* payload,
|
|
Ipike_sa* sa)
|
|
{
|
|
Ipike_proposal_payload* proposal_payload = ipike_sa_proposal_data(payload);
|
|
int proposal_count = 0;
|
|
Ipike_error err;
|
|
|
|
if (payload->situation.ip_sec == 0)
|
|
{
|
|
IPCOM_LOG0(WARNING, "No situation specified");
|
|
return IPIKE_SITUATION_UNSUPPORTED;
|
|
}
|
|
|
|
if ((payload->situation.ip_sec & IPIKE_SIT_SECRECY)
|
|
|| (payload->situation.ip_sec & IPIKE_SIT_INTEGRITY))
|
|
{
|
|
IPCOM_LOG2(WARNING, "Situation: [%s%s ] not supported",
|
|
payload->situation.ip_sec & IPIKE_SIT_SECRECY ? " SECRECY" : "",
|
|
payload->situation.ip_sec & IPIKE_SIT_INTEGRITY ? " INTEGRITY" : "");
|
|
return IPIKE_SITUATION_UNSUPPORTED;
|
|
}
|
|
|
|
while (proposal_payload != IP_NULL)
|
|
{
|
|
Ipike_proposal* proposal;
|
|
|
|
if (IP_NULL == (proposal = ipcom_calloc(1, sizeof(Ipike_proposal))))
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
err = ipike_proposal_extract(ie, proposal_payload, proposal);
|
|
|
|
if (err == IPIKE_SUCCESS)
|
|
{
|
|
proposal_count++;
|
|
|
|
err = ipike_array_add((void***) &sa->proposals, proposal);
|
|
|
|
if (IPIKE_SUCCESS != err)
|
|
return err;
|
|
}
|
|
else
|
|
ipike_proposal_free(proposal);
|
|
|
|
if (err != IPIKE_SUCCESS && err != IPIKE_SA_NO_ACCEPTED_TRANSFORM)
|
|
return err;
|
|
|
|
proposal_payload = ipike_sa_next_payload(proposal_payload);
|
|
}
|
|
sa->proposal_count = proposal_count;
|
|
|
|
/* In phase1, multi proposal in one sa is not allowed */
|
|
if ((ie->is_phase1) && (sa->proposal_count > 1))
|
|
{
|
|
return IPIKE_FAILED;
|
|
}
|
|
return proposal_count == 0 ? IPIKE_SA_NO_ACCEPTED_PROPOSAL : IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_print_payload
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC void
|
|
ipike_sa_print_payload(
|
|
Ipike_sa_payload* sa,
|
|
void (*print_proposal_payload)(Ipike_proposal_payload*),
|
|
Ip_bool phase1)
|
|
{
|
|
Ipike_proposal_payload *proposal;
|
|
|
|
if ( ipike_sa_check_payload(sa, phase1) != IPIKE_SUCCESS )
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"ipike_sa_print_payload() :: unable to print invalid sa payload");
|
|
return;
|
|
}
|
|
|
|
IPCOM_LOG1(DEBUG2, " DOI: %s",
|
|
ipike_doi_to_string(ip_ntohl(sa->doi)));
|
|
|
|
/* The only supported DOI is IPSec */
|
|
IPCOM_LOG3(DEBUG2, " situation: [%s%s%s ]",
|
|
sa->situation.ip_sec & IPIKE_SIT_IDENTITY_ONLY ? " IDENTITY" : "",
|
|
sa->situation.ip_sec & IPIKE_SIT_SECRECY ? " SECRECY" : "",
|
|
sa->situation.ip_sec & IPIKE_SIT_INTEGRITY ? " INTEGRITY" : "");
|
|
|
|
for (proposal = ipike_sa_proposal_data(sa);
|
|
IP_NULL != proposal;
|
|
proposal = ipike_sa_next_payload(proposal))
|
|
{
|
|
IPCOM_LOG1(DEBUG2, " << %s >>",
|
|
ipike_payload_type_to_string(IPIKE_PAYLOAD_PROPOSAL));
|
|
IPCOM_LOG2(DEBUG2, " Next Payload: %s (%d)",
|
|
ipike_payload_type_to_string(proposal->header.next_payload),
|
|
(int) proposal->header.next_payload);
|
|
IPCOM_LOG1(DEBUG2, " Payload Length: %d",
|
|
ip_ntohs(proposal->header.length));
|
|
|
|
print_proposal_payload(proposal);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_new
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_sa_payload*
|
|
ipike_sa_new(
|
|
Ip_u32 doi,
|
|
Ipike_sa_situation situation,
|
|
Ipike_proposal_payload** proposals)
|
|
{
|
|
Ip_u16 sa_header_size;
|
|
Ip_u16 sa_size;
|
|
Ipike_sa_payload* sa_payload;
|
|
Ip_u8* proposal_data;
|
|
int i;
|
|
|
|
switch (doi)
|
|
{
|
|
case IPIKE_DOI_ISAKMP:
|
|
sa_header_size = (Ip_u16) IPIKE_SA_HEADER_SIZE_ISAKMP;
|
|
break;
|
|
case IPIKE_DOI_IPSEC:
|
|
sa_header_size = (Ip_u16) IPIKE_SA_HEADER_SIZE_IPSEC;
|
|
break;
|
|
default:
|
|
IPCOM_LOG1(ERR, "DOI %d is not supported", doi);
|
|
return IP_NULL;
|
|
}
|
|
sa_size = (Ip_u16)(ipike_payload_array_size((Ipike_payload_header**) proposals) + sa_header_size);
|
|
|
|
if (IP_NULL == (sa_payload = ipcom_calloc(1, sa_size)))
|
|
{
|
|
IPCOM_LOG0(CRIT, "ipike_sa_create: out of memory");
|
|
return IP_NULL;
|
|
}
|
|
|
|
sa_payload->header.length = ip_htons(sa_size);
|
|
sa_payload->header.next_payload = IPIKE_PAYLOAD_SECURITY_ASSOCIATION;
|
|
sa_payload->doi = ip_htonl(doi);
|
|
switch (doi)
|
|
{
|
|
case IPIKE_DOI_ISAKMP:
|
|
sa_payload->situation.isakmp = situation.isakmp;
|
|
break;
|
|
case IPIKE_DOI_IPSEC:
|
|
sa_payload->situation.ip_sec = situation.ip_sec;
|
|
break;
|
|
}
|
|
|
|
proposal_data = ((Ip_u8*) sa_payload + sa_header_size);
|
|
|
|
for (i = 0; proposals[i] != IP_NULL; i++)
|
|
{
|
|
if (proposals[i+1] != IP_NULL)
|
|
proposals[i]->header.next_payload = IPIKE_PAYLOAD_PROPOSAL;
|
|
else
|
|
proposals[i]->header.next_payload = IPIKE_PAYLOAD_NONE;
|
|
ipcom_memcpy(proposal_data, (void*)proposals[i], ip_ntohs(proposals[i]->header.length));
|
|
proposal_data += ip_ntohs(proposals[i]->header.length);
|
|
}
|
|
|
|
return sa_payload;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_free
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_sa_free(Ipike_sa *s, void(*free_func)(void*))
|
|
{
|
|
ipike_array_free((void**) s->proposals, (void(*)(void*)) ipike_proposal_free);
|
|
ipcom_memset(s, 0, sizeof(Ipike_sa));
|
|
if (free_func)
|
|
free_func(s);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_create
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_sa_create(Ipike_sa* sa, Ipike_sa_payload** payload)
|
|
{
|
|
Ipike_proposal_payload** proposals = IP_NULL;
|
|
Ipike_proposal_payload* proposal;
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
int i = 0;
|
|
Ipike_proposal* end_prop = IP_NULL;
|
|
|
|
ip_assert(sa->proposals != IP_NULL);
|
|
|
|
if (sa->selected_proposal >= 0)
|
|
{
|
|
/* TODO is this logic valid ? it assumes proposals with same
|
|
number are consecutive */
|
|
i = sa->selected_proposal;
|
|
end_prop = sa->proposals[i + ipike_sa_selected_proposal_count(sa)];
|
|
}
|
|
|
|
for (; sa->proposals[i] != end_prop; i++)
|
|
{
|
|
if (IPIKE_SUCCESS != (err = ipike_proposal_create(sa->proposals[i], &proposal)))
|
|
goto cleanup;
|
|
if (IPIKE_SUCCESS != (err = ipike_array_add((void***) &proposals, proposal)))
|
|
{
|
|
ipcom_free(proposal);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
if (IP_NULL == (*payload = ipike_sa_new(sa->doi, sa->situation, proposals)))
|
|
{
|
|
IP_PANIC();
|
|
err = IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
cleanup:
|
|
ipike_array_free((void**) proposals, ipcom_free); /*lint !e123 */
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_ike_initialize
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_sa_ike_initialize(
|
|
Ipike_config_ike_sa* conf,
|
|
Ipike_sa* sa)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ipike_proposal* p = IP_NULL;
|
|
|
|
if ((IP_NULL == conf->proposals) ||
|
|
(IP_NULL == conf->proposals[0]))
|
|
{
|
|
err = IPIKE_SA_NO_VALID_TRANSFORM_CONFIGURED;
|
|
}
|
|
else
|
|
{
|
|
/* We only support a single proposal with IKE v1, each configuration
|
|
* proposal is converted to an IKE v1 transform and added to one
|
|
* single IKE v1 proposal. */
|
|
if (IP_NULL == (p = ipcom_calloc(1, sizeof(*p))))
|
|
{
|
|
IP_PANIC();
|
|
err = IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
if (IPIKE_SUCCESS == err)
|
|
err = ipike_proposal_ike_initialize(conf,
|
|
conf->proposals,
|
|
(Ip_u8)(1),
|
|
p);
|
|
if (IPIKE_SUCCESS == err)
|
|
err = ipike_array_add((void***) &sa->proposals, p);
|
|
if (IPIKE_SUCCESS != err)
|
|
ipike_proposal_free(p);
|
|
}
|
|
if (IPIKE_SUCCESS == err)
|
|
{
|
|
sa->doi = IPIKE_DOI_IPSEC;
|
|
sa->situation.isakmp = IPIKE_SIT_IDENTITY_ONLY;
|
|
sa->selected_proposal = -1;
|
|
sa->selected_proposal2 = -1;
|
|
sa->proposal_count = 0;
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_sa_ike_initialize: failed to intialize IKE SA");
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_ipsec_initialize
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_sa_ipsec_initialize(
|
|
Ipike_config_ipsec_sa* conf,
|
|
Ipike_sa* sa)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ipike_proposal* p = IP_NULL;
|
|
Ip_u8 i = 0;
|
|
Ip_u8 num = 0;
|
|
|
|
if ((IP_NULL == conf->proposals) ||
|
|
(IP_NULL == conf->proposals[0]))
|
|
{
|
|
err = IPIKE_SA_NO_VALID_TRANSFORM_CONFIGURED;
|
|
}
|
|
else
|
|
{
|
|
for (i=0; (IP_NULL != conf->proposals[i]); i++)
|
|
{
|
|
if (IP_NULL == (p = ipcom_calloc(1, sizeof(*p))))
|
|
{
|
|
IP_PANIC();
|
|
err = IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
if (IPIKE_SUCCESS == err)
|
|
{
|
|
if (conf->proposals[i]->number != 0)
|
|
num = (Ip_u8)conf->proposals[i]->number;
|
|
else
|
|
num = (Ip_u8)(i+1);
|
|
err = ipike_proposal_ipsec_initialize(conf,
|
|
conf->proposals[i],
|
|
num,
|
|
p);
|
|
}
|
|
if (IPIKE_SUCCESS == err)
|
|
err = ipike_array_add((void***) &sa->proposals, p);
|
|
if (IPIKE_SUCCESS != err)
|
|
{
|
|
ipike_proposal_free(p);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (IPIKE_SUCCESS == err)
|
|
{
|
|
sa->doi = IPIKE_DOI_IPSEC;
|
|
sa->situation.isakmp = IPIKE_SIT_IDENTITY_ONLY;
|
|
sa->selected_proposal = -1;
|
|
sa->selected_proposal2 = -1;
|
|
sa->proposal_count = i;
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_sa_ipsec_initialize: failed to intialize IPSec SA");
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_ipsec_set_behind_nat
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_sa_ipsec_set_behind_nat(Ipike_sa* sa)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
/* Change encapsulation mode:
|
|
* tunnel > udp_tunnel
|
|
* transport > udp_transport */
|
|
for (i=0; i < sa->proposal_count; i++)
|
|
for (j=0; sa->proposals[i]->transforms[j] != IP_NULL; j++)
|
|
if (sa->proposals[i]->transforms[j]->ipsec.encapsulation_mode == IPIKE_IPSEC_ENCAPSULATION_MODE_TUNNEL)
|
|
sa->proposals[i]->transforms[j]->ipsec.encapsulation_mode = IPIKE_IPSEC_ENCAPSULATION_MODE_UDP_TUNNEL;
|
|
else if (sa->proposals[i]->transforms[j]->ipsec.encapsulation_mode == IPIKE_IPSEC_ENCAPSULATION_MODE_TRANSPORT)
|
|
{
|
|
sa->proposals[i]->transforms[j]->ipsec.encapsulation_mode = IPIKE_IPSEC_ENCAPSULATION_MODE_UDP_TRANSPORT;
|
|
sa->send_original_address = IP_TRUE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_check_payload
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_sa_check_payload(Ipike_sa_payload* sa, Ip_bool phase1)
|
|
{
|
|
Ipike_proposal_payload* proposal;
|
|
Ip_u32 proposal_payload_max_len;
|
|
Ip_s32 chain_length;
|
|
unsigned int next_payload;
|
|
int i = 0;
|
|
|
|
if ((sa->header.next_payload == IPIKE_PAYLOAD_PROPOSAL) ||
|
|
(sa->header.next_payload == IPIKE_PAYLOAD_TRANSFORM))
|
|
{
|
|
return IPIKE_WRONG_PAYLOAD;
|
|
}
|
|
|
|
/* Check DOI field */
|
|
if ( ip_ntohl(sa->doi) != IPIKE_DOI_ISAKMP &&
|
|
ip_ntohl(sa->doi) != IPIKE_DOI_IPSEC )
|
|
{
|
|
IPCOM_LOG1(ERR, "ipike_sa_check_payload() :: DOI not supported (%d)",
|
|
sa->doi);
|
|
return IPIKE_DOI_UNSUPPORTED;
|
|
}
|
|
|
|
/* Check situation field */
|
|
if ( sa->situation.ip_sec != IPIKE_SIT_IDENTITY_ONLY )
|
|
{
|
|
IPCOM_LOG1(ERR, "ipike_sa_check_payload() :: "\
|
|
"DOI situation not supported (0x%.2x)",
|
|
sa->situation.ip_sec);
|
|
return IPIKE_SITUATION_UNSUPPORTED;
|
|
}
|
|
|
|
proposal_payload_max_len = ipike_sa_proposal_length(sa);
|
|
proposal = ipike_sa_proposal_data(sa);
|
|
|
|
/* Check the length of the proposal payload chain */
|
|
chain_length = ipike_payload_chain_size(
|
|
&proposal->header, proposal_payload_max_len);
|
|
if (chain_length <= 0)
|
|
{
|
|
IPCOM_LOG0(ERR,
|
|
"the proposal payloads extends beyond the end of the SA payload size");
|
|
return IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
}
|
|
if (chain_length != (Ip_s32) proposal_payload_max_len)
|
|
{
|
|
IPCOM_LOG0(ERR, "the propsal payload is not as long as indicated by the SA payload header");
|
|
return IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
|
|
}
|
|
|
|
/* Save "next payload" so we can determine if the payload is supported */
|
|
next_payload = proposal->header.next_payload;
|
|
|
|
for (;IP_NULL != proposal; proposal = ipike_sa_next_payload(proposal))
|
|
{
|
|
Ipike_error err;
|
|
|
|
if(proposal->header.flags)
|
|
{
|
|
return IPIKE_ISAKMP_INVALID_PAYLOAD;
|
|
}
|
|
|
|
if((phase1 == IP_TRUE) && (i != 0))/* WIND00397389 */
|
|
{
|
|
return IPIKE_ISAKMP_INVALID_PAYLOAD;
|
|
}
|
|
|
|
/* Ignore unsupported payload */
|
|
if ( IPIKE_PAYLOAD_NONE != next_payload &&
|
|
IPIKE_PAYLOAD_PROPOSAL != next_payload )
|
|
{
|
|
IPCOM_LOG3(WARNING,
|
|
"ipike_check_proposal_payload: ignoring unsupported payload (%u) in field in "
|
|
"the proposal payload, only %d and %d are supported",
|
|
next_payload, IPIKE_PAYLOAD_NONE, IPIKE_PAYLOAD_PROPOSAL);
|
|
return IPIKE_ISAKMP_INVALID_PAYLOAD_PROPOSAL;
|
|
}
|
|
|
|
if (IPIKE_SUCCESS != (err = ipike_proposal_check_payload(proposal,phase1)))
|
|
return err;
|
|
|
|
|
|
next_payload = proposal->header.next_payload;
|
|
i++;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_extract
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_sa_extract(
|
|
Ipike_isakmp_exchange* ie,
|
|
Ipike_sa_payload* payload,
|
|
Ipike_sa* sa)
|
|
{
|
|
Ipike_error err;
|
|
sa->selected_proposal = -1; /* No selected proposal */
|
|
sa->selected_proposal2 = -1; /* For ESP + AH */
|
|
sa->doi = ip_ntohl(payload->doi);
|
|
sa->situation.ip_sec = payload->situation.ip_sec;
|
|
|
|
switch ( sa->doi )
|
|
{
|
|
case IPIKE_DOI_IPSEC:
|
|
err = ipike_sa_process_message_ipsec(ie, payload, sa);
|
|
break;
|
|
default:
|
|
return IPIKE_DOI_UNSUPPORTED;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_selected_proposal_count
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL int
|
|
ipike_sa_selected_proposal_count(Ipike_sa* sa)
|
|
{
|
|
int count = 0;
|
|
Ip_u8 p_number;
|
|
|
|
if (sa->proposals == IP_NULL)
|
|
return 0;
|
|
if (sa->selected_proposal < 0)
|
|
return -1;
|
|
p_number = sa->proposals[sa->selected_proposal]->number;
|
|
while (sa->proposals[sa->selected_proposal + count] != IP_NULL
|
|
&& p_number == sa->proposals[sa->selected_proposal + count]->number)
|
|
count++;
|
|
return count;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_selected_proposal_get
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_proposal *
|
|
ipike_sa_selected_proposal_get(Ipike_sa* sa)
|
|
{
|
|
if (sa->proposals == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
if (sa->selected_proposal < 0)
|
|
return IP_NULL;
|
|
|
|
return sa->proposals[sa->selected_proposal];
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_selected_transform_get
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_transform *
|
|
ipike_sa_selected_transform_get(Ipike_sa* sa)
|
|
{
|
|
Ipike_proposal * proposal;
|
|
|
|
proposal = ipike_sa_selected_proposal_get(sa);
|
|
|
|
if (proposal == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
if (proposal->transforms == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
if (proposal->selected_transform < 0)
|
|
return IP_NULL;
|
|
|
|
return proposal->transforms[proposal->selected_transform];
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_contains_transform_transport_nat
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_sa_contains_transform_transport_nat(Ipike_sa * sa)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
for (i=0; i < sa->proposal_count; i++)
|
|
{
|
|
for (j=0; sa->proposals[i]->transforms[j] != IP_NULL; j++)
|
|
{
|
|
if (sa->proposals[i]->transforms[j]->ipsec.encapsulation_mode ==
|
|
IPIKE_IPSEC_ENCAPSULATION_MODE_UDP_TRANSPORT)
|
|
{
|
|
return IP_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_ike_print_payload
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_sa_ike_print_payload(Ipike_sa_payload* sa)
|
|
{
|
|
ipike_sa_print_payload(sa, ipike_proposal_ike_print_payload, IP_TRUE);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_sa_ipsec_print_payload
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_sa_ipsec_print_payload(Ipike_sa_payload* sa)
|
|
{
|
|
ipike_sa_print_payload(sa, ipike_proposal_ipsec_print_payload, IP_FALSE);
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|