blob: 9eeed18d3309a3a0031a20856f871efe009f7412 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/forensics/utils/redact/redactor.h"
#include <lib/inspect/cpp/hierarchy.h>
#include <lib/inspect/cpp/vmo/types.h>
#include <lib/syslog/cpp/macros.h>
#include <string_view>
namespace forensics {
namespace {
// Email stub alice@website.tld
constexpr std::string_view kEmailPattern = R"([a-zA-Z0-9]*@[a-zA-Z0-9]*\.[a-zA-Z]*)";
// uuid
constexpr std::string_view kUuidPattern =
R"([0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-\b[0-9a-fA-F]{12})";
// http(s) urls
constexpr std::string_view kUrlPattern = R"(https?://[^"',;!<> ]*)";
// The SSID identifier contains at most 32 pairs of hexadecimal characters, but match any number so
// SSID identifiers with the wrong number of hexadecimal characters are also redacted.
constexpr std::string_view kSsidPattern = R"((<ssid-[0-9a-fA-F]*>))";
// Long hex strings
constexpr std::string_view kHexPattern = R"((\b[0-9a-fA-F]{32}\b))";
// Obfuscated gaia ids
constexpr std::string_view kGaiaPattern = R"((\b1[0-9]{20}\b))";
constexpr std::string_view kUnredactedCanary =
R"(Email: alice@website.tld,
IPv4: 8.8.8.8,
IPv4_New: 8.9.10.42,
IPv4_Dup: 8.8.8.8,
IPv4_WithPort: 8.8.8.8:8080,
IPv461: ::ffff:12.34.56.78,
IPv462: ::ffff:ab12:cd34,
IPv6: 2001:503:eEa3:0:0:0:0:30,
IPv6_WithPort: [2001:503:eEa3:0:0:0:0:30]:8080,
IPv6C: fec8::7d84:c1dc:ab34:656a,
IPv6LL: fe80::7d84:c1dc:ab34:656a,
UUID: ddd0fA34-1016-11eb-adc1-0242ac120002,
MAC: de:ad:BE:EF:42:5a,
SSID: <ssid-666F6F>,
HTTP: http://fuchsia.dev/fuchsia/testing?q=Test,
HTTPS: https://fuchsia.dev/fuchsia/testing?q=Test,
HEX: 1234567890abcdefABCDEF0123456789,
v4Current: 0.1.2.3,
v4Loopback: 127.1.2.3,
v4LocalAddr: 169.254.12.34,
v4LocalMulti: 224.0.0.123,
v4Multi: 224.0.1.123,
broadcast: 255.255.255.255,
v6zeroes: :: ::1,
v6LeadingZeroes: ::abcd:dcba:bcde:f,
v6TrailingZeroes: f:e:d:c:abcd:dcba:bcde::,
v6LinkLocal: feB2:111:222:333:444:555:666:777,
v6LocalMulticast: ff72:111:222:333:444:555:666:777,
v6Multicast: ff77:111:222:333:444:555:666:777,
obfuscatedGaiaId: 106986199446298680449)";
constexpr std::string_view kRedactedCanary =
R"(Email: <REDACTED-EMAIL>,
IPv4: <REDACTED-IPV4: 1>,
IPv4_New: <REDACTED-IPV4: 2>,
IPv4_Dup: <REDACTED-IPV4: 1>,
IPv4_WithPort: <REDACTED-IPV4: 1>:8080,
IPv461: ::ffff:<REDACTED-IPV4: 3>,
IPv462: ::ffff:<REDACTED-IPV4: 5>,
IPv6: <REDACTED-IPV6: 6>,
IPv6_WithPort: [<REDACTED-IPV6: 6>]:8080,
IPv6C: <REDACTED-IPV6: 7>,
IPv6LL: fe80:<REDACTED-IPV6-LL: 8>,
UUID: <REDACTED-UUID>,
MAC: de:ad:BE:<REDACTED-MAC: 13>,
SSID: <REDACTED-SSID: 14>,
HTTP: <REDACTED-URL>,
HTTPS: <REDACTED-URL>,
HEX: <REDACTED-HEX: 15>,
v4Current: 0.1.2.3,
v4Loopback: 127.1.2.3,
v4LocalAddr: 169.254.12.34,
v4LocalMulti: 224.0.0.123,
v4Multi: <REDACTED-IPV4: 4>,
broadcast: 255.255.255.255,
v6zeroes: :: ::1,
v6LeadingZeroes: <REDACTED-IPV6: 9>,
v6TrailingZeroes: <REDACTED-IPV6: 10>,
v6LinkLocal: feB2:<REDACTED-IPV6-LL: 11>,
v6LocalMulticast: ff72:111:222:333:444:555:666:777,
v6Multicast: ff77:<REDACTED-IPV6-MULTI: 12>,
obfuscatedGaiaId: <REDACTED-OBFUSCATED-GAIA-ID: 16>)";
} // namespace
RedactorBase::RedactorBase(inspect::BoolProperty redaction_enabled)
: redaction_enabled_(std::move(redaction_enabled)) {}
Redactor::Redactor(const int starting_id, inspect::UintProperty cache_size,
inspect::BoolProperty redaction_enabled)
: RedactorBase(std::move(redaction_enabled)), cache_(std::move(cache_size), starting_id) {
Add(ReplaceIPv4())
.Add(ReplaceIPv6())
.Add(ReplaceMac())
.AddTextReplacer(kEmailPattern, "<REDACTED-EMAIL>")
.AddTextReplacer(kUuidPattern, "<REDACTED-UUID>")
.AddTextReplacer(kUrlPattern, "<REDACTED-URL>")
.AddIdReplacer(kSsidPattern, "<REDACTED-SSID: %d>")
.AddIdReplacer(kHexPattern, "<REDACTED-HEX: %d>")
.AddIdReplacer(kGaiaPattern, "<REDACTED-OBFUSCATED-GAIA-ID: %d>");
}
std::string& Redactor::Redact(std::string& text) {
for (const auto& replacer : replacers_) {
replacer(cache_, text);
}
return text;
}
Redactor& Redactor::Add(Replacer replacer) {
FX_CHECK(replacer != nullptr);
replacers_.push_back(std::move(replacer));
return *this;
}
Redactor& Redactor::AddTextReplacer(std::string_view pattern, std::string_view replacement) {
auto replacer = ReplaceWithText(pattern, replacement);
FX_CHECK(replacer != nullptr) << "Failed to build replacer for " << pattern << " " << replacement;
return Add(std::move(replacer));
}
Redactor& Redactor::AddIdReplacer(std::string_view pattern, std::string_view format) {
auto replacer = ReplaceWithIdFormatString(pattern, format);
FX_CHECK(replacer != nullptr) << "Failed to build replacer for " << pattern << " " << format;
return Add(std::move(replacer));
}
std::string Redactor::UnredactedCanary() const { return std::string(kUnredactedCanary); }
std::string Redactor::RedactedCanary() const { return std::string(kRedactedCanary); }
IdentityRedactor::IdentityRedactor(inspect::BoolProperty redaction_enabled)
: RedactorBase(std::move(redaction_enabled)) {}
std::string& IdentityRedactor::Redact(std::string& text) { return text; }
std::string IdentityRedactor::UnredactedCanary() const { return std::string(kUnredactedCanary); }
std::string IdentityRedactor::RedactedCanary() const { return std::string(kUnredactedCanary); }
} // namespace forensics