From b821747851d29990a416a6b31e0ebeef3016659e Mon Sep 17 00:00:00 2001 From: rrandomsky Date: Tue, 14 Nov 2023 15:56:24 +0100 Subject: [PATCH] [MOS-1059] Erase only sensitive data from logs Erase only sensitive data from logs. --- .../Bluetooth/interface/profiles/HFP/HFP.cpp | 12 +- module-cellular/modem/ATCommon.cpp | 17 ++- module-cellular/modem/ATCommon.hpp | 2 +- .../service-cellular/ServiceCellular.cpp | 3 +- module-utils/utility/Anonymize.cpp | 141 ++++++++++++++++++ module-utils/utility/Anonymize.hpp | 25 ++++ module-utils/utility/CMakeLists.txt | 2 + pure_changelog.md | 1 + 8 files changed, 191 insertions(+), 12 deletions(-) create mode 100644 module-utils/utility/Anonymize.cpp create mode 100644 module-utils/utility/Anonymize.hpp diff --git a/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp b/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp index 941b30075dfc53242b8e88147133be64f088e970..3520349073193b2126471d52d1d2b3d5d5a2e694 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp @@ -16,6 +16,7 @@ #include #include "SCO/ScoUtils.hpp" +#include #define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) @@ -145,7 +146,7 @@ namespace bluetooth std::uint8_t HFP::HFPImpl::serviceBuffer[serviceBufferSize]; std::unique_ptr HFP::HFPImpl::sco; - SCOCodec HFP::HFPImpl::codec = SCOCodec::CVSD; + SCOCodec HFP::HFPImpl::codec = SCOCodec::CVSD; std::shared_ptr HFP::HFPImpl::audioDevice; std::unique_ptr HFP::HFPImpl::cellularInterface; @@ -202,8 +203,8 @@ namespace bluetooth void HFP::HFPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state) { - auto evt = std::make_shared(event, state); - auto msg = std::make_shared(std::move(evt)); + auto evt = std::make_shared(event, state); + auto msg = std::make_shared(std::move(evt)); ownerService->bus.sendUnicast(std::move(msg), service::name::evt_manager); } @@ -526,7 +527,10 @@ namespace bluetooth auto HFP::HFPImpl::setIncomingCallNumber(const std::string &num) const noexcept -> Result::Code { - LOG_SENSITIVE(LOGDEBUG, "Setting number: %s", num.c_str()); + LOG_SENSITIVE( + LOGDEBUG, + "Setting number: %s", + utils::anonymize::anonymizeNumbers(num, utils::anonymize::SIGNS_TO_LEAVE_FOR_PHONE_NUMBERS).c_str()); hfp_ag_set_clip(129, num.c_str()); return Result::Code::Success; } diff --git a/module-cellular/modem/ATCommon.cpp b/module-cellular/modem/ATCommon.cpp index dba41f9cc8ce89cd14985d34847c77d14e284c2c..7e2f75618c2e760b44cf7727b0c418c6a5ddab97 100644 --- a/module-cellular/modem/ATCommon.cpp +++ b/module-cellular/modem/ATCommon.cpp @@ -11,6 +11,7 @@ #include "ATStream.hpp" #include #include +#include using namespace at; using namespace std::chrono_literals; @@ -41,16 +42,20 @@ void Channel::cmdLog(std::string cmd, const Result &result, std::chrono::millise } break; case Result::Code::ERROR: { LOG_ERROR("AT response: error"); - LOG_SENSITIVE( - LOGERROR, "[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : ""); + LOG_SENSITIVE(LOGERROR, + "[AT]: >%s<, >%s<", + utils::anonymize::anonymizeCellularIfNecessary(cmd).c_str(), + result.response.size() ? result.response.back().c_str() : ""); } break; default: - LOG_SENSITIVE( - LOGDEBUG, "[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : ""); + LOG_SENSITIVE(LOGDEBUG, + "[AT]: >%s<, >%s<", + utils::anonymize::anonymizeCellularIfNecessary(cmd).c_str(), + result.response.size() ? result.response.back().c_str() : ""); break; } for ([[maybe_unused]] const auto &s : result.response) { - LOG_SENSITIVE(LOGINFO, "[AT] > %s", s.c_str()); + LOG_SENSITIVE(LOGINFO, "[AT] > %s", utils::anonymize::anonymizeCellularIfNecessary(s).c_str()); } } @@ -86,7 +91,7 @@ Result Channel::cmd(const std::string &cmd, std::chrono::milliseconds timeout, s cmdInit(); std::string cmdFixed = formatCommand(cmd); - LOG_DEBUG("Start of %s", cmdFixed.c_str()); + LOG_DEBUG("Start of %s", utils::anonymize::anonymizeCellularIfNecessary(cmdFixed).c_str()); cmdSend(cmdFixed); auto startTime = std::chrono::steady_clock::now(); diff --git a/module-cellular/modem/ATCommon.hpp b/module-cellular/modem/ATCommon.hpp index 87bb85b05b8a4c0ca0cc79ebd67870536d3486d0..33334e40b4c5c8bc74253fd07d9dc41a195202a2 100644 --- a/module-cellular/modem/ATCommon.hpp +++ b/module-cellular/modem/ATCommon.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once diff --git a/module-services/service-cellular/ServiceCellular.cpp b/module-services/service-cellular/ServiceCellular.cpp index 6855bcd6c9495cbc9cbdb7b32fbfff90dbef835a..b793bf2a86806fab17a0a04c2a3028c07216117b 100644 --- a/module-services/service-cellular/ServiceCellular.cpp +++ b/module-services/service-cellular/ServiceCellular.cpp @@ -98,6 +98,7 @@ #include #include "ServiceCellularPriv.hpp" +#include "Anonymize.hpp" #include #include @@ -973,7 +974,7 @@ std::optional> ServiceCellular::identifyNotificati const std::string str(data.begin(), data.end()); const std::string logStr = utils::removeNewLines(str); - LOG_SENSITIVE(LOGDEBUG, "Notification:: %s", logStr.c_str()); + LOG_SENSITIVE(LOGDEBUG, "Notification:: %s", utils::anonymize::anonymizeCellularIfNecessary(logStr).c_str()); auto urc = at::urc::UrcFactory::Create(str); urc->Handle(urcHandler); diff --git a/module-utils/utility/Anonymize.cpp b/module-utils/utility/Anonymize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99a0ffeff6d7949455dc697032a354bae78b7b3d --- /dev/null +++ b/module-utils/utility/Anonymize.cpp @@ -0,0 +1,141 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "Anonymize.hpp" + +namespace utils::anonymize +{ + // Anonymized text will replace by this character + constexpr auto anonymizationCharacter = '*'; + + // Amount of 'anonymizationCharacter' used during anonymization can be fixed, + // otherwise their amount depend on length of substring to anonymize + constexpr auto isAmountOfAnonymizationCharactersFixed = false; + constexpr auto fixedAmountOfAnonymizationCharacters = 4; + + // Substrings to find logs for anonymization from the cellular logs + constexpr auto cellularSubstringCPIN = "CPIN"; + constexpr auto cellularSubstringCLCC = "CLCC"; + constexpr auto cellularSubstringATD = "ATD"; + constexpr auto cellularSubstringCPBR = "CPBR"; + constexpr auto cellularSubstringCSPN = "CSPN"; + + std::string anonymizeInQuotationMarks(const std::string &textToAnonymize, std::size_t singsToLeaveAtEnd) + { + constexpr auto quotesMark = '\"'; + std::size_t startPosition = 0; + std::size_t endPosition = 0; + auto anonymizedText = textToAnonymize; + + // Find the position of the substring within the input string + while (startPosition < anonymizedText.length()) { + startPosition = anonymizedText.find(quotesMark, startPosition); + endPosition = anonymizedText.find(quotesMark, startPosition + 1); + + if (startPosition != std::string::npos && endPosition != std::string::npos) { + // Extract the substring between the quotes + const auto &extractedSubstring = + anonymizedText.substr(startPosition + 1, endPosition - startPosition - 1); + + // Determine the length of the extracted substring + const auto extractedLength = extractedSubstring.length(); + + // Amount of signs to left can't be higher than extracted substring + singsToLeaveAtEnd = std::min(extractedLength, singsToLeaveAtEnd); + + // Determine amount of anonymization characters + const auto amountOfAnonymizationCharacters = isAmountOfAnonymizationCharactersFixed + ? fixedAmountOfAnonymizationCharacters + : extractedLength - singsToLeaveAtEnd; + + // Replace the substring with the appropriate number of '*' characters + anonymizedText.replace(startPosition + 1, + extractedLength - singsToLeaveAtEnd, + amountOfAnonymizationCharacters, + anonymizationCharacter); + startPosition = endPosition + 1; + } + else { + break; + } + } + return anonymizedText; + } + + std::string anonymizeNumbers(const std::string &textToAnonymize, std::size_t singsToLeaveAtEnd) + { + std::size_t startPosition = 0; + std::size_t endPosition = 0; + auto isDigitFunction = [](char c) { return std::isdigit(c); }; + auto anonymizedText = textToAnonymize; + auto startSubstring = anonymizedText.begin(); + auto endSubstring = anonymizedText.begin(); + + while (startPosition < anonymizedText.length()) { + // Find first number in string + startSubstring = std::find_if(endSubstring, anonymizedText.end(), isDigitFunction); + + // If first number found then find last number and anonymize whole number in string + if (startSubstring != anonymizedText.end()) { + endSubstring = std::find_if_not(startSubstring, anonymizedText.end(), isDigitFunction); + + // Calculate positions + startPosition = std::distance(anonymizedText.begin(), startSubstring); + endPosition = std::distance(anonymizedText.begin(), endSubstring); + + if (startPosition != std::string::npos && endPosition != std::string::npos) { + // Extract the substring contained only numbers + const auto &extractedSubstring = + anonymizedText.substr(startPosition + 1, endPosition - startPosition); + + // Determine the length of the extracted substring + const auto extractedLength = extractedSubstring.length(); + + // Amount of signs to left can't be higher than extracted substring + singsToLeaveAtEnd = std::min(extractedLength, singsToLeaveAtEnd); + + // Determine amount of anonymization characters + const auto amountOfAnonymizationCharacters = isAmountOfAnonymizationCharactersFixed + ? fixedAmountOfAnonymizationCharacters + : extractedLength - singsToLeaveAtEnd; + + // Replace the substring with the appropriate number of '*' characters + anonymizedText.replace(startPosition, + extractedLength - singsToLeaveAtEnd, + amountOfAnonymizationCharacters, + anonymizationCharacter); + + startPosition = endPosition + 1; + } + else { + break; + } + } + else { + break; + } + } + return anonymizedText; + } + + std::string anonymizeCellularIfNecessary(const std::string &text) + { + std::map> anonymizeOption{ + {cellularSubstringCPIN, + [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_PIN_AND_PUK); }}, + {cellularSubstringCLCC, + [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_PHONE_NUMBERS); }}, + {cellularSubstringATD, [&text]() { return anonymizeNumbers(text, SIGNS_TO_LEAVE_FOR_PHONE_NUMBERS); }}, + {cellularSubstringCPBR, + [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_PHONE_NUMBERS); }}, + {cellularSubstringCSPN, + [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_NET_PROVIDER_NAME); }}}; + + for (const auto &[key, anonymizeFunction] : anonymizeOption) { + if (text.find(key) != std::string::npos) { + return anonymizeFunction(); + } + } + return text; + } +} // namespace utils::anonymize diff --git a/module-utils/utility/Anonymize.hpp b/module-utils/utility/Anonymize.hpp new file mode 100644 index 0000000000000000000000000000000000000000..eb75b1711dc3ee0b4e566d4083e44725bed12143 --- /dev/null +++ b/module-utils/utility/Anonymize.hpp @@ -0,0 +1,25 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include +#include +#include + +namespace utils::anonymize +{ + // Determine how many characters to leave at the end of anonymized substring + constexpr auto SIGNS_TO_LEAVE_FOR_PIN_AND_PUK = 0; + constexpr auto SIGNS_TO_LEAVE_FOR_PHONE_NUMBERS = 2; + constexpr auto SIGNS_TO_LEAVE_FOR_NET_PROVIDER_NAME = 1; + + // Basic function to anonymize provided string + std::string anonymizeInQuotationMarks(const std::string &textToAnonymize, std::size_t singsToLeaveAtEnd = 0); + std::string anonymizeNumbers(const std::string &textToAnonymize, std::size_t singsToLeaveAtEnd = 0); + + // To anonymize logs from cellular + std::string anonymizeCellularIfNecessary(const std::string &text); + +} // namespace utils::anonymize diff --git a/module-utils/utility/CMakeLists.txt b/module-utils/utility/CMakeLists.txt index 4a98b17879cf37512a6322af331bdb2d921ffcd6..e6e2aa2cd6102e48713f39de3027b49927bff2a0 100644 --- a/module-utils/utility/CMakeLists.txt +++ b/module-utils/utility/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(utility STATIC) target_sources(utility PRIVATE Utils.cpp + Anonymize.cpp PUBLIC integer.hpp @@ -12,6 +13,7 @@ target_sources(utility Utility.hpp Utils.hpp Units.hpp + Anonymize.hpp ) target_include_directories(utility diff --git a/pure_changelog.md b/pure_changelog.md index 9785672e72564bd70517251485be959e9a7a784b..b9940e906e99b291f0e714c0049cc393ef8be1d7 100644 --- a/pure_changelog.md +++ b/pure_changelog.md @@ -9,6 +9,7 @@ ### Changed / Improved * Hide the SOS label during onboarding when the modem is not ready for an emergency call. +* Anonymization sensitive data in logs added. ### Fixed