/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 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 #include /* **************************************************************************** * 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 **************************************************************************** */