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

706 lines
26 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipike_payload.c,v $ $Revision: 1.38.10.9 $
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_payload.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
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipike_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipike_h.h"
#include "ipike_payload.h"
#include "ipike2_payload_authentication.h"
#include "ipike2_payload_configuration.h"
#include "ipike2_payload_delete.h"
#include "ipike2_payload_encrypted.h"
#include "ipike2_payload_identification.h"
#include "ipike2_payload_key_exchange.h"
#include "ipike2_payload_notify.h"
#include "ipike2_payload_sa.h"
#include "ipike2_payload_traffic_selector.h"
#include "ipike2_payload_eap.h"
#include "ipike_payload_sa.h"
#include "ipike_payload_key_exchange.h"
#include "ipike_payload_nonce.h"
#include "ipike_payload_delete.h"
#include "ipike_payload_identification.h"
#include "ipike_payload_notification.h"
#include "ipike_payload_hash.h"
#include "ipike_payload_certificate.h"
#include "ipike_payload_sign.h"
#include "ipike_payload_vendor_id.h"
#include "ipike_payload_nat.h"
#include <ipcom_clib.h>
#include <ipcom_syslog.h>
/*
****************************************************************************
* 4 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 5 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 6 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipike_check_payloads
*===========================================================================
*/
IP_GLOBAL Ipike_error
ipike_check_payloads(Ipike_isakmp_header *isakmp,Ip_bool phase1)
{
Ipike_error err = IPIKE_SUCCESS;
Ipike_payload_header *payload;
Ip_u8 this_payload;
Ip_u32 max_length;
Ip_s32 chain_length;
Ipike_payload_enum ctx;
if (isakmp->next_payload == IPIKE_PAYLOAD_NONE)
{
/* The message may have no payloads for IKEv2, so accept if v2 message */
IPCOM_LOG0(DEBUG, "ipike_check_payloads() :: no payloads exist"\
" according to the ISAKMP header");
if (isakmp->version >= 0x20)
return IPIKE_SUCCESS;
else
return IPIKE_ISAKMP_NO_PAYLOAD;
}
this_payload = isakmp->next_payload;
max_length = (Ip_u32)(ip_ntohl(isakmp->length) - sizeof(Ipike_isakmp_header));
if (max_length == 0)
{
IPCOM_LOG0(DEBUG, "ipike_check_payloads() :: next_payload is not none"\
" but no payload exist");
return IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
}
payload = (Ipike_payload_header*)((Ip_u8*)isakmp + sizeof(Ipike_isakmp_header));
chain_length = ipike_payload_chain_size(payload, max_length);
if (chain_length < 0 || chain_length > 0xffff)
{
IPCOM_LOG0(ERR, "ipike_check_payloads() :: the payloads extends"\
" beyond the end of the ISAKMP package");
return IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
}
payload = ipike_first_payload(isakmp, &ctx);
while (IPIKE_SUCCESS == err && IPIKE_PAYLOAD_NONE != this_payload)
{
/* Check reserved field, must be zero in IKEv1 */
#ifdef IPIKE_USE_VERSION1
if ( isakmp->version == 0x10 )
{
if ( payload->flags != 0 )
{
IPCOM_LOG1(ERR, "ipike_check_payloads() :: "\
"invalid reserved field (0x%.2x)",
payload->flags);
err = IPIKE_ISAKMP_INVALID_PAYLOAD;
break;
}
switch (this_payload)
{
case IPIKE_PAYLOAD_SECURITY_ASSOCIATION:
err = ipike_sa_check_payload((Ipike_sa_payload*) payload,phase1);
break;
case IPIKE_PAYLOAD_KEY_EXCHANGE:
err = ipike_key_exchange_check_payload((Ipike_ke_payload*) payload);
break;
case IPIKE_PAYLOAD_IDENTFICATION:
err = ipike_identification_check_payload((Ipike_id_payload*) payload);
break;
case IPIKE_PAYLOAD_HASH:
err = ipike_hash_check_payload((Ipike_hash_payload*) payload);
break;
case IPIKE_PAYLOAD_NONCE:
err = ipike_payload_nonce_check((Ipike_nonce_payload*) payload);
break;
case IPIKE_PAYLOAD_NOTIFICATION:
err = ipike_notification_check_payload((Ipike_notification_payload*) payload);
break;
case IPIKE_PAYLOAD_CERTIFICATE:
err = ipike_payload_certificate_check((Ipike_cert_payload*) payload);
break;
case IPIKE_PAYLOAD_SIGNATURE:
err = ipike_sign_check_payload((Ipike_sign_payload*) payload);
break;
case IPIKE_PAYLOAD_DELETE:
err = ipike_payload_delete_check((Ipike_delete_payload*) payload);
break;
case IPIKE_PAYLOAD_VENDOR_ID:
err = ipike_payload_vendor_id_check((Ipike_vendor_id_payload*) payload);
break;
case IPIKE_PAYLOAD_ATTRIBUTES:
err = ipike_payload_configuration_check((Ipike2_cp_payload*) payload);
break;
case IPIKE_PAYLOAD_NAT_DISCOVERY:
err = ipike_nat_discovery_check_payload((Ipike_nat_discovery_payload*) payload);
break;
case IPIKE_PAYLOAD_NAT_ORIGINAL_ADDRESS:
err = ipike_nat_original_address_check_payload((Ipike_nat_org_addr_payload*) payload);
break;
case IPIKE_PAYLOAD_CERTIFICATE_REQUEST:
err = ipike_payload_certificate_request_check((Ipike_cert_req_payload*) payload);
break;
default:
IPCOM_LOG1(ERR, "ipike_check_payloads() :: payload check failed "\
"since %d is an unsupported payload type",
this_payload);
err = IPIKE_ISAKMP_UNSUPPORTED_PAYLOAD;
break;
}
} /* if ( isakmp->version == 0x10 ) */
#endif
#ifdef IPIKE_USE_VERSION2
else if ( isakmp->version >= 0x20 )
{
switch (this_payload)
{
case IPIKE2_PAYLOAD_SECURITY_ASSOCIATION:
err = ipike_payload_sa_check((Ipike2_sa_payload*) payload);
break;
case IPIKE2_PAYLOAD_KEY_EXCHANGE:
err = ipike_payload_key_exchange_check((Ipike2_ke_payload*) payload);
break;
case IPIKE2_PAYLOAD_IDENTIFICATION_I:
case IPIKE2_PAYLOAD_IDENTIFICATION_R:
err = ipike_payload_identification_check((Ipike2_id_payload*) payload);
break;
case IPIKE2_PAYLOAD_CERTIFICATE:
err = ipike_payload_certificate_check((Ipike_cert_payload*) payload);
break;
case IPIKE2_PAYLOAD_CERTIFICATE_REQUEST:
err = ipike_payload_certificate_request_check((Ipike_cert_req_payload*) payload);
break;
case IPIKE2_PAYLOAD_AUTHENTICATION:
err = ipike_payload_authentication_check((Ipike2_auth_payload*) payload);
break;
case IPIKE2_PAYLOAD_NONCE:
err = ipike2_payload_nonce_check((Ipike_nonce_payload*) payload);
break;
case IPIKE2_PAYLOAD_NOTIFY:
err = ipike_payload_notify_check((Ipike2_notify_payload*) payload);
break;
case IPIKE2_PAYLOAD_DELETE:
err = ipike2_payload_delete_check((Ipike2_del_payload*) payload);
break;
case IPIKE2_PAYLOAD_VENDOR_ID:
err = ipike_payload_vendor_id_check((Ipike_vendor_id_payload*) payload);
break;
case IPIKE2_PAYLOAD_TRAFFIC_SELECTOR_I:
case IPIKE2_PAYLOAD_TRAFFIC_SELECTOR_R:
err = ipike_payload_traffic_selector_check((Ipike2_ts_payload*) payload);
break;
case IPIKE2_PAYLOAD_CONFIGURATION:
err = ipike_payload_configuration_check((Ipike2_cp_payload*) payload);
break;
case IPIKE2_PAYLOAD_EAP:
err = ipike_payload_eap_check((Ipike2_eap_payload*) payload);
break;
default:
/* IKE v2 is capable of handling unknown payload types */
IPCOM_LOG1(WARNING, "ipike_check_payloads() :: payload check failed "\
"since %d is an unsupported payload type",
this_payload);
break;
} /* switch */
} /* if ( isakmp->version >= 0x20 ) */
#endif /* IPIKE_USE_VERSION2 */
if (err != IPIKE_SUCCESS)
break;
this_payload = payload->next_payload;
payload = ipike_next_payload(&ctx);
if (payload == IP_NULL && this_payload != IPIKE_PAYLOAD_NONE)
err = IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
} /* while */
ipike_free_payload_enumerator(&ctx);
return err;
}
/*
*===========================================================================
* ipike_first_payload
*===========================================================================
*/
#ifdef IPCOM_USE_DMALLOC
IP_GLOBAL Ipike_payload_header *
ipike_first_payload_debug(Ipike_isakmp_header *isakmp, Ipike_payload_enum *ctx, const char *file, const char *function, Ip_u32 line)
#else
IP_GLOBAL Ipike_payload_header *
ipike_first_payload(Ipike_isakmp_header *isakmp, Ipike_payload_enum *ctx)
#endif
{
Ip_u32 len;
ctx->real_header = (Ipike_payload_header *) ((Ip_u8*) isakmp + sizeof(Ipike_isakmp_header));
ctx->allocated_header = IP_NULL;
len = ip_ntohl(isakmp->length);
if (len < sizeof(Ipike_isakmp_header))
{
IPCOM_LOG1(DEBUG2, "ipike_first_payload - isakmp header length too small %d", len);
return IP_NULL;
}
else if (len == sizeof(Ipike_isakmp_header))
{
return IP_NULL; /* No payloads */
}
len -= (Ip_u32)sizeof(Ipike_isakmp_header);
ctx->max_len = (Ip_u32)ipike_payload_chain_size(ctx->real_header, len);
if (ctx->max_len == 0xffffffff)
{
IPCOM_LOG0(DEBUG2, "ipike_first_payload - bad payload chain size");
(void)ipike_print_memory(IPCOM_LOG_DEBUG2, " ISAKMP data:\n", (Ip_u8*)isakmp, ip_ntohl(isakmp->length));
return IP_NULL;
}
#ifdef IPCOM_USE_DMALLOC
return ipike_next_payload_debug(ctx, file, function, line);
#else
return ipike_next_payload(ctx);
#endif
}
/*
*===========================================================================
* ipike_next_payload
*===========================================================================
*/
#ifdef IPCOM_USE_DMALLOC
IP_GLOBAL Ipike_payload_header*
ipike_next_payload_debug(Ipike_payload_enum *ctx, const char *file, const char *function, Ip_u32 line)
#else
IP_GLOBAL Ipike_payload_header *
ipike_next_payload(Ipike_payload_enum *ctx)
#endif
{
Ipike_payload_header payload_test;
Ip_u16 len;
/* We may get alignment problem, so always make a copy */
ipcom_free(ctx->allocated_header);
ctx->allocated_header = IP_NULL;
if (IP_NULL == ctx->real_header)
return IP_NULL;
ipcom_memcpy((void*)&payload_test, (void*)ctx->real_header, sizeof(payload_test));
len = ip_htons(payload_test.length);
if ((ctx->max_len > 0) && (len > ctx->max_len))
return IP_NULL;
#ifdef IPCOM_USE_DMALLOC
ctx->allocated_header = ipcom_dcalloc(sizeof(Ipike_payload_header), len/sizeof(Ipike_payload_header) + 1, file, function, line);
#else
ctx->allocated_header = ipcom_calloc(sizeof(Ipike_payload_header), len/sizeof(Ipike_payload_header) + 1);
#endif
if (IP_NULL == ctx->allocated_header)
return IP_NULL;
ipcom_memcpy((void*)ctx->allocated_header, (void*)ctx->real_header, len);
if (IPIKE_PAYLOAD_NONE == ctx->real_header->next_payload)
ctx->real_header = IP_NULL;
else
ctx->real_header = (Ipike_payload_header*)(((Ip_u8*)ctx->real_header) + len);
return ctx->allocated_header;
}
/*
*===========================================================================
* ipike_payload_sa_next_proposal
*===========================================================================
*/
IP_GLOBAL Ipike_payload_header*
ipike_next_payload_structure(Ipike_payload_header* p)
{
if (p->next_payload == IPIKE_PAYLOAD_NONE)
return IP_NULL;
p = (Ipike_payload_header*)((Ip_u8*)p + ip_htons(p->length));
return p;
}
/*
*===========================================================================
* ipike_free_payload_enumerator
*===========================================================================
*/
IP_GLOBAL void
ipike_free_payload_enumerator(Ipike_payload_enum* ctx)
{
ipcom_free(ctx->allocated_header);
}
/*
*===========================================================================
* ipike_payload_array_size
*===========================================================================
*/
IP_GLOBAL Ip_u32
ipike_payload_array_size(Ipike_payload_header** payloads)
{
int i;
Ip_u32 size = 0;
if (IP_NULL != payloads)
for (i = 0; payloads[i] != IP_NULL; i++)
size += ip_ntohs(payloads[i]->length);
return size;
}
/*
*===========================================================================
* ipike_payload_chain_size
*===========================================================================
*/
IP_GLOBAL Ip_s32
ipike_payload_chain_size(Ipike_payload_header* first_payload, Ip_u32 max_size)
{
Ip_u32 size = 0;
Ipike_payload_header payload = {0};
if (max_size != 0 && max_size < sizeof(payload))
return -1;
while (1)
{
if (max_size - size < sizeof(payload))
return -1;
ipcom_memcpy((void*)&payload, (void*)(((Ip_u8*)first_payload)+size), sizeof(payload));
size += ip_htons(payload.length);
if (size > max_size)
return -1;
if ( payload.next_payload == IPIKE_PAYLOAD_NONE ||
payload.length == 0 ||
size == 0)
break;
}
return (Ip_s32) size;
}
/*
*===========================================================================
* ipike_payload_type_to_string
*===========================================================================
*/
IP_GLOBAL const char *
ipike_payload_type_to_string(Ip_u8 payload_type)
{
const char *s;
if (ipike_map_string(ipike.payload_map, payload_type, &s) != IPIKE_SUCCESS)
return "invalid payload type";
return s;
}
/*
*===========================================================================
* ipike_payload_print
*===========================================================================
*/
IP_GLOBAL void
ipike_payload_print(Ipike_isakmp_header* isakmp, Ip_bool is_phase1, int version)
{
Ip_u8 this_payload;
Ipike_payload_header *payload;
Ipike_payload_enum ctx;
this_payload = isakmp->next_payload;
payload = ipike_first_payload(isakmp, &ctx);
/* The last payload is either a none payload or an encrypted payload */
while (IP_NULL != payload
&& IPIKE_PAYLOAD_NONE != this_payload
&& IPIKE2_PAYLOAD_ENCRYPTED != this_payload)
{
IPCOM_LOG1(DEBUG2, " < %s >",
ipike_payload_type_to_string(this_payload));
IPCOM_LOG2(DEBUG2, " Next Payload: %s (%d)",
ipike_payload_type_to_string(payload->next_payload),
(int) payload->next_payload);
IPCOM_LOG2(DEBUG2, " Payload Length: %d (%#x)",
ip_ntohs(payload->length),
ip_ntohs(payload->length));
if ( version == 0x10 )
{
switch (this_payload)
{
#ifdef IPIKE_USE_VERSION1
case IPIKE_PAYLOAD_SECURITY_ASSOCIATION:
if (is_phase1)
ipike_sa_ike_print_payload((Ipike_sa_payload*) payload);
else
ipike_sa_ipsec_print_payload((Ipike_sa_payload*) payload);
break;
case IPIKE_PAYLOAD_KEY_EXCHANGE:
ipike_key_exchange_print_payload((Ipike_ke_payload*) payload);
break;
case IPIKE_PAYLOAD_IDENTFICATION:
ipike_identification_print_payload((Ipike_id_payload*) payload);
break;
case IPIKE_PAYLOAD_HASH:
ipike_hash_print_payload((Ipike_hash_payload*) payload);
break;
case IPIKE_PAYLOAD_NONCE:
ipike_payload_nonce_print((Ipike_nonce_payload*) payload);
break;
case IPIKE_PAYLOAD_NOTIFICATION:
ipike_notification_print_payload((Ipike_notification_payload*) payload);
break;
case IPIKE_PAYLOAD_CERTIFICATE:
ipike_payload_certificate_print((Ipike_cert_payload*) payload);
break;
case IPIKE_PAYLOAD_CERTIFICATE_REQUEST:
ipike_payload_certificate_request_print((Ipike_cert_req_payload*) payload);
break;
case IPIKE_PAYLOAD_SIGNATURE:
ipike_sign_print_payload((Ipike_sign_payload*) payload);
break;
case IPIKE_PAYLOAD_DELETE:
ipike_payload_delete_print((Ipike_delete_payload*) payload);
break;
case IPIKE_PAYLOAD_VENDOR_ID:
ipike_payload_vendor_id_print((Ipike_vendor_id_payload*) payload);
break;
case IPIKE_PAYLOAD_ATTRIBUTES:
ipike_payload_configuration_print((Ipike2_cp_payload*) payload);
break;
case IPIKE_PAYLOAD_NAT_DISCOVERY:
ipike_nat_discovery_print_payload((Ipike_nat_discovery_payload*) payload);
break;
case IPIKE_PAYLOAD_NAT_ORIGINAL_ADDRESS:
ipike_nat_original_address_print_payload((Ipike_nat_org_addr_payload*) payload);
break;
#endif /* IPIKE_USE_VERSION1 */
default:
IPCOM_LOG1(WARNING,
"printing of payload failed since %d is a unknown payload type", this_payload);
break;
}
}
else if ( version >= 0x20 )
{
switch (this_payload)
{
#ifdef IPIKE_USE_VERSION2
case IPIKE2_PAYLOAD_SECURITY_ASSOCIATION:
ipike_payload_sa_print((Ipike2_sa_payload*) payload);
break;
case IPIKE2_PAYLOAD_KEY_EXCHANGE:
ipike_payload_key_exchange_print((Ipike2_ke_payload*) payload);
break;
case IPIKE2_PAYLOAD_IDENTIFICATION_I:
case IPIKE2_PAYLOAD_IDENTIFICATION_R:
ipike_payload_identification_print((Ipike2_id_payload*) payload);
break;
case IPIKE2_PAYLOAD_CERTIFICATE:
ipike_payload_certificate_print((Ipike_cert_payload*) payload);
break;
case IPIKE2_PAYLOAD_CERTIFICATE_REQUEST:
ipike_payload_certificate_request_print((Ipike_cert_req_payload*) payload);
break;
case IPIKE2_PAYLOAD_AUTHENTICATION:
ipike_payload_authentication_print((Ipike2_auth_payload*) payload);
break;
case IPIKE2_PAYLOAD_NONCE:
ipike_payload_nonce_print((Ipike_nonce_payload*) payload);
break;
case IPIKE2_PAYLOAD_NOTIFY:
Ipike_payload_notify_print((Ipike2_notify_payload*) payload);
break;
case IPIKE2_PAYLOAD_DELETE:
ipike2_payload_delete_print((Ipike2_del_payload*) payload);
break;
case IPIKE2_PAYLOAD_VENDOR_ID:
break;
case IPIKE2_PAYLOAD_TRAFFIC_SELECTOR_I:
case IPIKE2_PAYLOAD_TRAFFIC_SELECTOR_R:
ipike_payload_traffic_selector_print((Ipike2_ts_payload*) payload);
break;
case IPIKE2_PAYLOAD_CONFIGURATION:
ipike_payload_configuration_print((Ipike2_cp_payload*) payload);
break;
case IPIKE2_PAYLOAD_EAP:
ipike_payload_eap_print((Ipike2_eap_payload*) payload);
break;
#endif /* IPIKE_USE_VERSION2 */
default:
IPCOM_LOG1(WARNING,
"printing of payload failed since %d is a unknown payload type", this_payload);
break;
}
}
this_payload = payload->next_payload;
payload = ipike_next_payload(&ctx);
}
ipike_free_payload_enumerator(&ctx);
}
/*
*===========================================================================
* ipike_is_ike_rekeying
*===========================================================================
* Check if we are doing IKE-rekeying (missing traffic selectors)
*/
#ifdef IPIKE_USE_VERSION2
IP_PUBLIC Ip_bool
ipike_is_ike_rekeying(Ipike_isakmp_header *isakmp)
{
Ipike_payload_header *payload;
Ip_u8 this_payload;
Ipike_payload_enum ctx;
Ip_bool is_ike_rekeying = IP_TRUE;
if (isakmp->exchange_type != IPIKE2_ISAKMP_EXCH_CREATE_CHILD_SA)
return IP_FALSE;
this_payload = isakmp->next_payload;
payload = ipike_first_payload(isakmp, &ctx);
while (this_payload != IPIKE_PAYLOAD_NONE && payload != IP_NULL)
{
switch (this_payload)
{
case IPIKE2_PAYLOAD_TRAFFIC_SELECTOR_I:
case IPIKE2_PAYLOAD_TRAFFIC_SELECTOR_R:
is_ike_rekeying = IP_FALSE;
break;
case IPIKE2_PAYLOAD_SECURITY_ASSOCIATION:
case IPIKE2_PAYLOAD_NONCE:
case IPIKE2_PAYLOAD_KEY_EXCHANGE:
case IPIKE2_PAYLOAD_NOTIFY:
break;
default:
ipike_free_payload_enumerator(&ctx);
return IP_FALSE; /* unexpected payload, be safe and ignore whole message */
}
this_payload = payload->next_payload;
payload = ipike_next_payload(&ctx);
}
ipike_free_payload_enumerator(&ctx);
return is_ike_rekeying;
}
/*
*===========================================================================
* ipike_exchange_verify_critial_payload
*===========================================================================
*/
IP_PUBLIC Ipike_error
ipike_payload_handle_unsupported_payload(
Ipike_value *notify_data,
Ipike_payload_header *payload,
Ip_u8 this_payload)
{
if (IPIKE_PAYLOAD_CRITICAL & payload->flags)
{
/* Critial payloads that are unsupported should be reported back to sender */
(void)ipike_cpy_data(notify_data, &this_payload, 1);
IPCOM_LOG2(ERR,
"ipike_payload_handle_unsupported_payload() :: '%s' (%d) is an unsupported payload type",
ipike_payload_type_to_string(this_payload), this_payload);
return IPIKE_ISAKMP_UNSUPPORTED_CRITICAL_PAYLOAD;
}
/* It's safe to ignore all payloads that isn't critical */
IPCOM_LOG2(DEBUG2,
"ipike_payload_handle_unsupported_payload() :: '%s' (%d) is an unsupported payload type",
ipike_payload_type_to_string(this_payload), this_payload);
return IPIKE_SUCCESS;
}
#endif /* IPIKE_USE_VERSION2 */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/