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

550 lines
20 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_payload_notification.c,v $ $Revision: 1.32.10.8 $
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_payload_notification.c,v $
* $Author: hxu0 $ $Date: 2013-01-25 07:31:37 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/* Notification payload (RFC 2408, chapter 3.14) */
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipike_h.h"
#include "ipike_config.h"
#include "ipike_exchange_informational.h"
#include "ipike_payload_notification.h"
#include "ipike_payload_proposal.h"
#include "ipike_doi.h"
#include "ipike_sadb.h"
#include "ipike_util.h"
#include <ipcom_clib.h>
#include <ipcom_syslog.h>
/*
****************************************************************************
* 4 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 5 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 6 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
*===========================================================================
* ipike_notification_data
*===========================================================================
* Description: Returns a pointer to the SPI data in the payload.
* Parameters: notify - a notification payload.
* Returns: A pointer to the SPI data.
*
*/
IP_STATIC Ip_u8 *
ipike_notification_spi(Ipike_notification_payload *notify);
/*
*===========================================================================
* ipike_notification_data
*===========================================================================
* Description: Returns a pointer to the notification data in the payload.
* Parameters: notify - a notification payload.
* Returns: A pointer to the notification data.
*
*/
IP_STATIC Ip_u8 *
ipike_notification_data(Ipike_notification_payload* notify);
/*
*===========================================================================
* ipike_notification_data_length
*===========================================================================
* Description: Returns the length of the hash data.
* Parameters: notify - a notification payload.
* Returns: The length of the notification data (in bytes).
*
*
*/
IP_STATIC Ip_u16
ipike_notification_data_length(Ipike_notification_payload* notify);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipike_notification_spi
*===========================================================================
*/
IP_STATIC Ip_u8 *
ipike_notification_spi(Ipike_notification_payload* notify)
{
return (Ip_u8*) notify + IPIKE_NOTIFICATION_HEADER_LENGTH;
}
/*
*===========================================================================
* ipike_notification_data
*===========================================================================
*/
IP_STATIC Ip_u8 *
ipike_notification_data(Ipike_notification_payload* notify)
{
return (Ip_u8 *) notify + IPIKE_NOTIFICATION_HEADER_LENGTH + notify->spi_size;
}
/*
*===========================================================================
* ipike_notification_data_length
*===========================================================================
*/
IP_STATIC Ip_u16
ipike_notification_data_length(Ipike_notification_payload* notify)
{
return IPIKE_PAYLOAD_DATA_LENGTH(notify->header.length, (IPIKE_NOTIFICATION_HEADER_LENGTH + notify->spi_size));
}
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipike_notification_message_type_to_string
*===========================================================================
*/
IP_PUBLIC const char *
ipike_notification_message_type_to_string(Ip_u16 message_type)
{
static const char *message_type_str[] = {
"INVALID-PAYLOAD-TYPE",
"DOI-NOT-SUPPORTED",
"SITUATION-NOT-SUPPORTED",
"INVALID-COOKIE",
"INVALID-MAJOR-VERSION",
"INVALID-MINOR-VERSION",
"INVALID-EXCHANGE-TYPE",
"INVALID-FLAGS",
"INVALID-MESSAGE-ID",
"INVALID-PROTOCOL-ID",
"INVALID-SPI",
"INVALID-TRANSFORM-ID",
"ATTRIBUTES-NOT-SUPPORTED",
"NO-PROPOSAL-CHOSEN",
"BAD-PROPOSAL-SYNTAX",
"PAYLOAD-MALFORMED",
"INVALID-KEY-INFORMATION",
"INVALID-ID-INFORMATION",
"INVALID-CERT-ENCODING",
"INVALID-CERTIFICATE",
"CERT-TYPE-UNSUPPORTED",
"INVALID-CERT-AUTHORITY",
"INVALID-HASH-INFORMATION",
"AUTHENTICATION-FAILED",
"INVALID-SIGNATURE",
"ADDRESS-NOTIFICATION",
"NOTIFY-SA-LIFETIME",
"CERTIFICATE-UNAVAILABLE",
"UNSUPPORTED-EXCHANGE-TYPE",
"UNEQUAL-PAYLOAD-LENGTHS"
};
if (message_type >= IPIKE_NOTI_PRIVATE_USE_LOW
&& message_type <= IPIKE_NOTI_PRIVATE_USE_HIGH)
return "Private Use";
if (message_type == IPIKE_NOTI_RESPONDER_LIFETIME)
return "RESPONDER-LIFETIME";
if (message_type == IPIKE_NOTI_REPLAY_STATUS)
return "REPLAY-STATUS";
if (message_type == IPIKE_NOTI_INITIAL_CONTACT)
return "INITIAL-CONTACT";
if (message_type == IPIKE_NOTI_R_U_THERE)
return "R-U-THERE";
if (message_type == IPIKE_NOTI_R_U_THERE_ACK)
return "R-U-THERE-ACK";
if (message_type == IPIKE_NOTI_CONNECTED)
return "CONNECTED";
/* Only identify notify types we actually process */
if (message_type == 0 || message_type > IPIKE_NOTI_COUNT)
return "Invalid message type";
return message_type_str[message_type - 1];
}
/*
*===========================================================================
* ipike_notification_error_code_to_message_type
*===========================================================================
*/
IP_PUBLIC Ipike_error
ipike_notification_error_code_to_message_type(
Ipike_error err,
Ip_u16* message_type)
{
switch (err)
{
case IPIKE_ISAKMP_UNSUPPORTED_MAJOR_VERSION:
*message_type = IPIKE_NOTI_INVALID_MAJOR_VERSION;
break;
case IPIKE_ISAKMP_UNSUPPORTED_MINOR_VERSION:
*message_type = IPIKE_NOTI_INVALID_MINOR_VERSION;
break;
case IPIKE_ISAKMP_LENGTH_ERROR:
case IPIKE_ISAKMP_INVALID_MESSAGE_ID:
*message_type = IPIKE_NOTI_INVALID_MESSAGE_ID;
break;
case IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR:
*message_type = IPIKE_NOTI_UNEQUAL_PAYLOAD_LENGTHS;
break;
case IPIKE_ISAKMP_NO_PAYLOAD:
case IPIKE_ISAKMP_UNSUPPORTED_PAYLOAD:
case IPIKE_MISSING_PAYLOAD:
case IPIKE_WRONG_PAYLOAD:
case IPIKE_ISAKMP_INVALID_PAYLOAD_PROPOSAL:
*message_type = IPIKE_NOTI_INVALID_PAYLOAD_TYPE;
break;
case IPIKE_ISAKMP_INVALID_PAYLOAD:
case IPIKE_NONCE_INVALID_SIZE:
*message_type = IPIKE_NOTI_PAYLOAD_MALFORMED;
break;
case IPIKE_DOI_UNSUPPORTED:
*message_type = IPIKE_NOTI_DOI_NOT_SUPPORTED;
break;
case IPIKE_SITUATION_UNSUPPORTED:
*message_type = IPIKE_NOTI_SITUATION_NOT_SUPPORTED;
break;
case IPIKE_SA_NO_MATCHING_HASH_ALGORITHM:
case IPIKE_SA_NO_MATCHING_ENCRYPTION_ALGORITHM:
case IPIKE_SA_NO_ACCEPTED_TRANSFORM:
case IPIKE_SA_NO_ACCEPTED_PROPOSAL:
case IPIKE_SA_HASH_ALGORITHM_NOT_SUPPORTED:
case IPIKE_SA_ENCRYPTION_ALGORITHM_NOT_SUPPORTED:
case IPIKE_ISAKMP_NO_PROPOSAL_CHOSEN:
*message_type = IPIKE_NOTI_NO_PROPOSAL_CHOSEN;
break;
case IPIKE_SA_NO_PRE_SHARED_SECRET:
case IPIKE_SA_AUTHENTICATION_ALGORITHM_NOT_SUPPORTED:
case IPIKE_AUTHENTICATION_FAILED:
*message_type = IPIKE_NOTI_AUTHENTICATION_FAILED;
break;
case IPIKE_KE_DH_ERROR:
*message_type = IPIKE_NOTI_INVALID_KEY_INFORMATION;
break;
case IPIKE_PROPOSAL_INVALID_ID:
*message_type = IPIKE_NOTI_INVALID_PROTOCOL_ID;
break;
case IPIKE_ATTRIBUTE_MUST_BE_BASIC:
case IPIKE_ATTRIBUTE_INVALID_TYPE:
case IPIKE_ATTRIBUTE_INVALID_VALUE:
case IPIKE_ISAKMP_INVALID_PROPOSAL:
*message_type = IPIKE_NOTI_BAD_PROPOSAL_SYNTAX;
break;
case IPIKE_ATTRIBUTE_UNSUPPORTED_TYPE:
case IPIKE_ATTRIBUTE_UNSUPPORTED_VALUE:
*message_type = IPIKE_NOTI_ATTRIBUTES_NOT_SUPPORTED;
break;
case IPIKE_INVALID_EXCHANGE_TYPE:
*message_type = IPIKE_NOTI_INVALID_EXCHANGE_TYPE;
break;
case IPIKE_EXCHANGE_TYPE_NOT_SUPPORTED:
*message_type = IPIKE_NOTI_UNSUPPORTED_EXCHANGE_TYPE;
break;
case IPIKE_INVALID_HASH_VALUE:
*message_type = IPIKE_NOTI_INVALID_HASH_INFORMATION;
break;
case IPIKE_ISAKMP_INVALID_ID_TYPE:
*message_type = IPIKE_NOTI_INVALID_ID_INFORMATION;
break;
case IPIKE_INVALID_COOKIE:
*message_type = IPIKE_NOTI_INVALID_COOKIE;
break;
case IPIKE_ISAKMP_INVALID_FLAGS:
*message_type = IPIKE_NOTI_INVALID_FLAGS;
break;
case IPIKE_ISAKMP_INVALID_SPI:
*message_type = IPIKE_NOTI_INVALID_SPI;
break;
case IPIKE_ISAKMP_INVALID_TRANSFORM_ID:
*message_type = IPIKE_NOTI_INVALID_TRANSFORM_ID;
break;
case IPIKE_ISAKMP_INVALID_SIGNATURE:
*message_type = IPIKE_NOTI_INVALID_SIGNATURE;
break;
case IPIKE_ISAKMP_INVALID_CERT_ENCODING:
*message_type = IPIKE_NOTI_INVALID_CERT_ENCODING;
break;
case IPIKE_ISAKMP_CERT_TYPE_UNSUPPORTED:
*message_type = IPIKE_NOTI_CERT_TYPE_UNSUPPORTED;
break;
case IPIKE_ISAKMP_INVALID_CERT_AUTHORITY:
*message_type = IPIKE_NOTI_INVALID_CERT_AUTHORITY;
break;
case IPIKE_ISAKMP_INVALID_LIFETIME:
*message_type = IPIKE_NOTI_RESPONDER_LIFETIME;
break;
default:
/* Can not inform the other party about the error condition */
return IPIKE_INTERNAL_ERROR;
}
return IPIKE_SUCCESS;
}
/*
*===========================================================================
* ipike_notification_new
*===========================================================================
*/
IP_GLOBAL Ipike_notification_payload *
ipike_notification_new(
Ip_u32 doi,
Ip_u8 protocol_id,
Ip_u16 notify_message_type,
const Ip_u8 *spi,
Ip_u8 spi_length,
const Ip_u8 *data,
Ip_u16 data_length)
{
Ip_u16 payload_length;
Ipike_notification_payload* ret;
payload_length = (Ip_u16)(IPIKE_NOTIFICATION_HEADER_LENGTH + spi_length + data_length);
if (IP_NULL == (ret = ipcom_calloc(1, payload_length)))
{
IPCOM_LOG0(CRIT, "ipike_notification_new: out of memory");
return IP_NULL;
}
ret->header.length = ip_htons(payload_length);
ret->header.next_payload = IPIKE_PAYLOAD_NOTIFICATION;
ret->doi = ip_htonl(doi);
ret->protocol_id = protocol_id;
ret->spi_size = spi_length;
ret->message_type = ip_ntohs(notify_message_type);
ipcom_memcpy(ipike_notification_spi(ret), spi, spi_length);
if (data != IP_NULL && data_length > 0)
ipcom_memcpy(ipike_notification_data(ret), data, data_length);
return ret;
}
/*
*===========================================================================
* ipike_notification_check_payload
*===========================================================================
*/
IP_GLOBAL Ipike_error
ipike_notification_check_payload(Ipike_notification_payload* notify)
{
if (ip_ntohs(notify->header.length) < IPIKE_NOTIFICATION_HEADER_LENGTH + notify->spi_size)
{
IPCOM_LOG3(ERR,
"The indicated length of the notification payload (%d) is less than the header (%d) + SPI size (%d)",
ip_ntohs(notify->header.length),
IPIKE_NOTIFICATION_HEADER_LENGTH, notify->spi_size);
return IPIKE_ISAKMP_PAYLOAD_LENGTH_ERROR;
}
if (ip_ntohl(notify->doi) != IPIKE_DOI_IPSEC)
{
IPCOM_LOG1(ERR,
"during notification payload check: the DOI '%d' is not supported",
ip_ntohl(notify->doi));
return IPIKE_DOI_UNSUPPORTED;
}
return IPIKE_SUCCESS;
}
/*
*===========================================================================
* ipike_notification_process_message
*===========================================================================
*/
IP_GLOBAL Ipike_error
ipike_notification_process_message(
Ipike_isakmp_exchange* ie,
Ipike_notification_payload* payload)
{
Ip_u16 type = ip_ntohs(payload->message_type);
Ip_u32 counter = 0;
switch (type)
{
case IPIKE_NOTI_INITIAL_CONTACT:
/* Remove all IKE SA:s with same local/peer and not this responder
* and/or initiator cookie */
ipike_sadb_remove_all_except_this(ie->ike_sa);
break;
case IPIKE_NOTI_RESPONDER_LIFETIME:
case IPIKE_NOTI_REPLAY_STATUS:
IPCOM_LOG1(INFO,
"Notification '%s' not supported",
ipike_notification_message_type_to_string(type));
break;
case IPIKE_NOTI_R_U_THERE:
if (!(ie->isakmp_flags & IPIKE_ISAKMP_ENCRYPTION) ||
(sizeof(counter) != ipike_notification_data_length(payload)))
{
IPCOM_LOG0(ERR, "ipike_notification_process_message: bad R-U-THERE payload");
}
else
{
ipcom_memcpy(&counter, ipike_notification_data(payload), sizeof(counter));
counter = ip_ntohl(counter);
(void)ipike_informational_liveness(ie->ike_sa, counter);
}
break;
case IPIKE_NOTI_R_U_THERE_ACK:
if (!(ie->isakmp_flags & IPIKE_ISAKMP_ENCRYPTION) ||
(sizeof(counter) != ipike_notification_data_length(payload)))
{
IPCOM_LOG0(ERR, "Bad R-U-THERE-ACK payload");
}
else
{
ipcom_memcpy(&counter, ipike_notification_data(payload), sizeof(counter));
counter = ip_ntohl(counter);
if (counter != ie->ike_sa->liveness.local_counter)
{
IPCOM_LOG2(ERR, "Bad R-U-THERE-ACK payload (counter %d != %d)",
counter, ie->ike_sa->liveness.local_counter);
}
else
{
/* Peer is alive so reset livness sent counter */
ipike_sa_reset_liveness_resend_timeout(ie->ike_sa);
}
}
break;
case IPIKE_NOTI_AUTHENTICATION_FAILED:
/* Authentication failed, remove all ongoing negotiations */
IPCOM_LOG1(ERR, "ipike_notification_process_message() ::"\
" received '%s' notification from peer",
ipike_notification_message_type_to_string(type));
IPCOM_LOG0(NOTICE, "ipike_notification_process_message() ::"\
" aborting negotiations");
/* Abort the ongoing negotiation with the IKE SA */
ipike_isakmp_abort_exchanges(ie->ike_sa);
/* It should be save to remove the IKE SA but only if this
* informational message was protected. We can never let an
* unprotected message remove an established IKE SA */
if ( ie->ike_sa->state == IPIKE_SA_CONSTRUCTING )
{
ipike_sadb_set_state(ie, ie->ike_sa, IPIKE_SA_DYING);
}
break;
default:
if (type > IPIKE_NOTI_COUNT)
{
IPCOM_LOG1(INFO, "Unknown/Not processed notification 0x%.4x ignored", type);
}
}
return IPIKE_SUCCESS;
}
/*
*===========================================================================
* ipike_notification_print_payload
*===========================================================================
*/
IP_GLOBAL void
ipike_notification_print_payload(Ipike_notification_payload* notify)
{
char* not_hex;
IPCOM_LOG1(DEBUG2, " DOI: %s",
ipike_doi_to_string(ip_ntohl(notify->doi)));
IPCOM_LOG1(DEBUG2, " protocol-ID: %s",
ipike_proposal_proto_id_to_string(notify->protocol_id));
IPCOM_LOG2(DEBUG2, " notify message type: %s (%d)",
ipike_notification_message_type_to_string(ip_ntohs(notify->message_type)),
ip_ntohs(notify->message_type));
IPCOM_LOG1(DEBUG2, " SPI Size: %d", (int) notify->spi_size);
if (notify->spi_size != 0)
{
char* spi_hex;
spi_hex = ipike_memory_to_string(ipike_notification_spi(notify),
notify->spi_size, 4);
if (IP_NULL == spi_hex)
{
IPCOM_LOG0(CRIT, "ipike_print_notification_payload: out of memory");
return;
}
IPCOM_LOG1(DEBUG2, " SPI: %s", spi_hex);
ipcom_free(spi_hex);
}
not_hex = ipike_memory_to_string(ipike_notification_data(notify),
ipike_notification_data_length(notify),
1);
if (IP_NULL == not_hex)
{
IPCOM_LOG0(CRIT, "ipike_print_notification_payload: out of memory");
return;
}
IPCOM_LOG1(DEBUG2, " data: %s", not_hex);
ipcom_free(not_hex);
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/