blob: 0f38dee61bde5dabba15fa793e4b05d8b5f6032d [file] [log] [blame]
// Copyright (c) 2015 The Chromium 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 "components/safe_browsing_db/util.h"
#include <stddef.h>
#include "base/macros.h"
#include "base/trace_event/trace_event.h"
#include "crypto/sha2.h"
#include "net/base/escape.h"
#include "url/gurl.h"
namespace safe_browsing {
// Utility functions -----------------------------------------------------------
namespace {
bool IsKnownList(const std::string& name) {
for (size_t i = 0; i < arraysize(kAllLists); ++i) {
if (!strcmp(kAllLists[i], name.c_str())) {
return true;
}
}
return false;
}
} // namespace
// ThreatMetadata ------------------------------------------------------------
ThreatMetadata::ThreatMetadata()
: threat_pattern_type(ThreatPatternType::NONE) {}
ThreatMetadata::ThreatMetadata(const ThreatMetadata& other) = default;
ThreatMetadata::~ThreatMetadata() {}
bool ThreatMetadata::operator==(const ThreatMetadata& other) const {
return threat_pattern_type == other.threat_pattern_type &&
api_permissions == other.api_permissions &&
population_id == other.population_id;
}
bool ThreatMetadata::operator!=(const ThreatMetadata& other) const {
return !operator==(other);
}
// SBCachedFullHashResult ------------------------------------------------------
SBCachedFullHashResult::SBCachedFullHashResult() {}
SBCachedFullHashResult::SBCachedFullHashResult(
const base::Time& in_expire_after)
: expire_after(in_expire_after) {}
SBCachedFullHashResult::SBCachedFullHashResult(
const SBCachedFullHashResult& other) = default;
SBCachedFullHashResult::~SBCachedFullHashResult() {}
// Listnames that browser can process.
const char kMalwareList[] = "goog-malware-shavar";
const char kPhishingList[] = "goog-phish-shavar";
const char kBinUrlList[] = "goog-badbinurl-shavar";
const char kCsdWhiteList[] = "goog-csdwhite-sha256";
const char kDownloadWhiteList[] = "goog-downloadwhite-digest256";
const char kExtensionBlacklist[] = "goog-badcrxids-digestvar";
const char kIPBlacklist[] = "goog-badip-digest256";
const char kUnwantedUrlList[] = "goog-unwanted-shavar";
const char kModuleWhitelist[] = "goog-whitemodule-digest256";
const char kResourceBlacklist[] = "goog-badresource-shavar";
const char* kAllLists[10] = {
kMalwareList, kPhishingList, kBinUrlList, kCsdWhiteList,
kDownloadWhiteList, kExtensionBlacklist, kIPBlacklist, kUnwantedUrlList,
kModuleWhitelist, kResourceBlacklist,
};
ListType GetListId(const base::StringPiece& name) {
ListType id;
if (name == kMalwareList) {
id = MALWARE;
} else if (name == kPhishingList) {
id = PHISH;
} else if (name == kBinUrlList) {
id = BINURL;
} else if (name == kCsdWhiteList) {
id = CSDWHITELIST;
} else if (name == kDownloadWhiteList) {
id = DOWNLOADWHITELIST;
} else if (name == kExtensionBlacklist) {
id = EXTENSIONBLACKLIST;
} else if (name == kIPBlacklist) {
id = IPBLACKLIST;
} else if (name == kUnwantedUrlList) {
id = UNWANTEDURL;
} else if (name == kModuleWhitelist) {
id = MODULEWHITELIST;
} else if (name == kResourceBlacklist) {
id = RESOURCEBLACKLIST;
} else {
id = INVALID;
}
return id;
}
bool GetListName(ListType list_id, std::string* list) {
switch (list_id) {
case MALWARE:
*list = kMalwareList;
break;
case PHISH:
*list = kPhishingList;
break;
case BINURL:
*list = kBinUrlList;
break;
case CSDWHITELIST:
*list = kCsdWhiteList;
break;
case DOWNLOADWHITELIST:
*list = kDownloadWhiteList;
break;
case EXTENSIONBLACKLIST:
*list = kExtensionBlacklist;
break;
case IPBLACKLIST:
*list = kIPBlacklist;
break;
case UNWANTEDURL:
*list = kUnwantedUrlList;
break;
case MODULEWHITELIST:
*list = kModuleWhitelist;
break;
case RESOURCEBLACKLIST:
*list = kResourceBlacklist;
break;
default:
return false;
}
DCHECK(IsKnownList(*list));
return true;
}
SBFullHash SBFullHashForString(const base::StringPiece& str) {
SBFullHash h;
crypto::SHA256HashString(str, &h.full_hash, sizeof(h.full_hash));
return h;
}
SBFullHash StringToSBFullHash(const std::string& hash_in) {
DCHECK_EQ(crypto::kSHA256Length, hash_in.size());
SBFullHash hash_out;
memcpy(hash_out.full_hash, hash_in.data(), crypto::kSHA256Length);
return hash_out;
}
std::string SBFullHashToString(const SBFullHash& hash) {
DCHECK_EQ(crypto::kSHA256Length, sizeof(hash.full_hash));
return std::string(hash.full_hash, sizeof(hash.full_hash));
}
void UrlToFullHashes(const GURL& url,
bool include_whitelist_hashes,
std::vector<SBFullHash>* full_hashes) {
// Include this function in traces because it's not cheap so it should be
// called sparingly.
TRACE_EVENT2("loader", "safe_browsing::UrlToFullHashes", "url", url.spec(),
"include_whitelist_hashes", include_whitelist_hashes);
std::string canon_host;
std::string canon_path;
std::string canon_query;
V4ProtocolManagerUtil::CanonicalizeUrl(url, &canon_host, &canon_path,
&canon_query);
std::vector<std::string> hosts;
if (url.HostIsIPAddress()) {
hosts.push_back(url.host());
} else {
V4ProtocolManagerUtil::GenerateHostVariantsToCheck(canon_host, &hosts);
}
std::vector<std::string> paths;
V4ProtocolManagerUtil::GeneratePathVariantsToCheck(canon_path, canon_query,
&paths);
for (const std::string& host : hosts) {
for (const std::string& path : paths) {
full_hashes->push_back(
SBFullHashForString(host + path));
// We may have /foo as path-prefix in the whitelist which should
// also match with /foo/bar and /foo?bar. Hence, for every path
// that ends in '/' we also add the path without the slash.
if (include_whitelist_hashes && path.size() > 1 && path.back() == '/') {
full_hashes->push_back(SBFullHashForString(
host + path.substr(0, path.size() - 1)));
}
}
}
}
} // namespace safe_browsing