550 lines
20 KiB
C
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
|
|
****************************************************************************
|
|
*/
|