From 8faa04afdb15d0f6f8ce330c135badd2263207c1 Mon Sep 17 00:00:00 2001 From: Christian Crank Date: Thu, 12 Jun 2025 20:58:15 -0400 Subject: [PATCH] Validate short and long names so whitespace or empty names cannot be used (#6993) * Say issue #6867 about adding validation for long_name and short_name. Firmware should expect at least 1 non-whitespace character for both long_name and short_name. added the USERPREFS_CONFIG_DEVICE_ROLE example to userPrefs.jsonc * Validation for user long_name and short_name implemented. No longer can use whitespace characters. Return BAD_REQUEST error responses when validation fails and warning logs when validation rejects invalid names. * Improve whitespace validation for user names with ctype.h, ensure logging works * Add whitespace validation to ham mode to prevent validation bypass and to match python cli command * punctuation change --------- Co-authored-by: Ben Meadors --- src/modules/AdminModule.cpp | 44 +++++++++++++++++++++++++++++++++++++ userPrefs.jsonc | 1 + 2 files changed, 45 insertions(+) diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 4005222dc..ea4c46949 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -7,6 +7,7 @@ #include "SPILock.h" #include "meshUtils.h" #include +#include // for better whitespace handling #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH #include "BleOta.h" #endif @@ -155,6 +156,28 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta */ case meshtastic_AdminMessage_set_owner_tag: LOG_DEBUG("Client set owner"); + // Validate names + if (*r->set_owner.long_name) { + const char *start = r->set_owner.long_name; + // Skip all whitespace (space, tab, newline, etc) + while (*start && isspace((unsigned char)*start)) + start++; + if (*start == '\0') { + LOG_WARN("Rejected long_name: must contain at least 1 non-whitespace character"); + myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp); + break; + } + } + if (*r->set_owner.short_name) { + const char *start = r->set_owner.short_name; + while (*start && isspace((unsigned char)*start)) + start++; + if (*start == '\0') { + LOG_WARN("Rejected short_name: must contain at least 1 non-whitespace character"); + myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp); + break; + } + } handleSetOwner(r->set_owner); break; @@ -1153,6 +1176,27 @@ void AdminModule::handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uic void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p) { + // Validate ham parameters before setting since this would bypass validation in the owner struct + if (*p.call_sign) { + const char *start = p.call_sign; + // Skip all whitespace + while (*start && isspace((unsigned char)*start)) + start++; + if (*start == '\0') { + LOG_WARN("Rejected ham call_sign: must contain at least 1 non-whitespace character"); + return; + } + } + if (*p.short_name) { + const char *start = p.short_name; + while (*start && isspace((unsigned char)*start)) + start++; + if (*start == '\0') { + LOG_WARN("Rejected ham short_name: must contain at least 1 non-whitespace character"); + return; + } + } + // Set call sign and override lora limitations for licensed use strncpy(owner.long_name, p.call_sign, sizeof(owner.long_name)); strncpy(owner.short_name, p.short_name, sizeof(owner.short_name)); diff --git a/userPrefs.jsonc b/userPrefs.jsonc index a349a5700..497327478 100644 --- a/userPrefs.jsonc +++ b/userPrefs.jsonc @@ -21,6 +21,7 @@ // "USERPREFS_CONFIG_LORA_REGION": "meshtastic_Config_LoRaConfig_RegionCode_US", // "USERPREFS_CONFIG_OWNER_LONG_NAME": "My Long Name", // "USERPREFS_CONFIG_OWNER_SHORT_NAME": "MLN", + // "USERPREFS_CONFIG_DEVICE_ROLE": "meshtastic_Config_DeviceConfig_Role_CLIENT", // Defaults to CLIENT. ROUTER*, LOST AND FOUND, and REPEATER roles are restricted. // "USERPREFS_EVENT_MODE": "1", // "USERPREFS_FIXED_BLUETOOTH": "121212", // "USERPREFS_FIXED_GPS": "",