From a83ddcc563632ab09ac43e0e1ce03791cfec131e Mon Sep 17 00:00:00 2001 From: Erik Karlsson Date: Tue, 16 May 2023 17:26:49 +0200 Subject: [PATCH] obuspa: Add controller MTP verification If CONFIG_OBUSPA_CONTROLLER_MTP_VERIFY=y is set, disabled by default, reject incoming USP records if from_id does not match a controller connected to the MTP instance on which the record was received. --- obuspa/Config.in | 2 +- .../0001-validate-controller-mtp.patch | 117 ++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 obuspa/patches/0001-validate-controller-mtp.patch diff --git a/obuspa/Config.in b/obuspa/Config.in index 639f4c319..9b1937998 100644 --- a/obuspa/Config.in +++ b/obuspa/Config.in @@ -23,7 +23,7 @@ config OBUSPA_MTP_ENABLE_COAP default y config OBUSPA_CONTROLLER_MTP_VERIFY - bool "Enable verification of MQTT response topic before processing the message" + bool "Enable verification of controller MTP before processing the message" default n endmenu endif diff --git a/obuspa/patches/0001-validate-controller-mtp.patch b/obuspa/patches/0001-validate-controller-mtp.patch new file mode 100644 index 000000000..6f5e703a7 --- /dev/null +++ b/obuspa/patches/0001-validate-controller-mtp.patch @@ -0,0 +1,117 @@ +diff --git a/src/core/device.h b/src/core/device.h +index 5ca0782..ee6d88c 100644 +--- a/src/core/device.h ++++ b/src/core/device.h +@@ -157,6 +157,9 @@ int DEVICE_CONTROLLER_Start(void); + void DEVICE_CONTROLLER_Stop(void); + int DEVICE_CONTROLLER_FindInstanceByEndpointId(char *endpoint_id); + int DEVICE_CONTROLLER_QueueBinaryMessage(mtp_send_item_t *msi, char *endpoint_id, char *usp_msg_id, mtp_reply_to_t *mtp_reply_to, time_t expiry_time); ++#ifdef OBUSPA_CONTROLLER_MTP_VERIFY ++bool DEVICE_CONTROLLER_IsMTPAllowed(char *endpoint_id, mtp_reply_to_t *mrt); ++#endif + bool DEVICE_CONTROLLER_IsMTPConfigured(char *endpoint_id, mtp_protocol_t protocol); + char *DEVICE_CONTROLLER_FindEndpointIdByInstance(int instance); + char *DEVICE_CONTROLLER_FindEndpointByMTP(mtp_reply_to_t *mrt); +diff --git a/src/core/device_controller.c b/src/core/device_controller.c +index ae609f5..a6335f5 100644 +--- a/src/core/device_controller.c ++++ b/src/core/device_controller.c +@@ -900,6 +900,78 @@ int DEVICE_CONTROLLER_QueueBinaryMessage(mtp_send_item_t *msi, char *endpoint_id + return USP_ERR_OK; + } + ++#ifdef OBUSPA_CONTROLLER_MTP_VERIFY ++/*********************************************************************//** ++** ++** DEVICE_CONTROLLER_IsMTPAllowed ++** ++** Determines whether an MTP is allowed to be used by the specified controller ++** This function is used by ValidateUspRecord() to determine whether to process a received USP message ++** ++** \param endpoint_id - Endpoint ID of controller that sent a USP message ++** \param mrt - pointer to structure specifying on which MTP the message was received ++** ++** \return true if the MTP is allowed, false otherwise ++** ++**************************************************************************/ ++bool DEVICE_CONTROLLER_IsMTPAllowed(char *endpoint_id, mtp_reply_to_t *mrt) ++{ ++ controller_t *cont = FindEnabledControllerByEndpointId(endpoint_id); ++ controller_mtp_t *mtp; ++ ++ // Disallow if no controller instance is found ++ if (cont == NULL) ++ { ++ return false; ++ } ++ ++ mtp = FindFirstEnabledMtp(cont, mrt->protocol); ++ ++#ifdef ENABLE_WEBSOCKETS ++ // Allow websocket server if no other MTP is configured ++ if ((mrt->protocol == kMtpProtocol_WebSockets) && (mrt->wsserv_conn_id != INVALID)) ++ { ++ return mtp == NULL; ++ } ++#endif ++ ++ // Disallow if there is no MTP configured with matching protocol ++ if ((mtp == NULL) || (mtp->protocol != mrt->protocol)) ++ { ++ return false; ++ } ++ ++ // Check that the configured MTP matches the MTP on which the message was received ++ switch(mtp->protocol) ++ { ++#ifndef DISABLE_STOMP ++ case kMtpProtocol_STOMP: ++ return mtp->stomp_connection_instance == mrt->stomp_instance; ++#endif ++ ++#ifdef ENABLE_COAP ++ case kMtpProtocol_CoAP: ++ return true; // More detailed checks are not implemented for CoAP ++#endif ++ ++#ifdef ENABLE_MQTT ++ case kMtpProtocol_MQTT: ++ return mtp->mqtt_connection_instance == mrt->mqtt_instance; ++#endif ++ ++#ifdef ENABLE_WEBSOCKETS ++ case kMtpProtocol_WebSockets: ++ return (mrt->wsclient_cont_instance == cont->instance) && (mrt->wsclient_mtp_instance == mtp->instance); ++#endif ++ default: ++ TERMINATE_BAD_CASE(mtp->protocol); ++ break; ++ } ++ ++ return false; ++} ++#endif ++ + /*********************************************************************//** + ** + ** DEVICE_CONTROLLER_IsMTPConfigured +diff --git a/src/core/msg_handler.c b/src/core/msg_handler.c +index 8313342..a953562 100644 +--- a/src/core/msg_handler.c ++++ b/src/core/msg_handler.c +@@ -759,6 +759,15 @@ int ValidateUspRecord(UspRecord__Record *rec, mtp_reply_to_t *mrt) + return USP_ERR_RECORD_FIELD_INVALID; + } + ++#ifdef OBUSPA_CONTROLLER_MTP_VERIFY ++ // Exit if the controller is not allowed to use the MTP on which the message was received ++ if (DEVICE_CONTROLLER_IsMTPAllowed(rec->from_id, mrt) == false) ++ { ++ USP_ERR_SetMessage("%s: Ignoring message from endpoint_id=%s (unauthorized MTP)", __FUNCTION__, rec->from_id); ++ return USP_ERR_PERMISSION_DENIED; ++ } ++#endif ++ + // Exit if the controller is unknown + cur_msg_controller_instance = DEVICE_CONTROLLER_FindInstanceByEndpointId(rec->from_id); + if (cur_msg_controller_instance == INVALID)