blob: fc6bc378e8be70fb6bbb30eb38a82af0e95822b9 [file] [log] [blame]
// Copyright 2018 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 "chrome/chrome_cleaner/os/digest_verifier.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/chrome_cleaner/os/disk_util.h"
#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
#include "chrome/chrome_cleaner/os/resource_util.h"
#include "chrome/chrome_cleaner/proto/file_digest.pb.h"
namespace chrome_cleaner {
// static
scoped_refptr<DigestVerifier> DigestVerifier::CreateFromResource(
int resource_id) {
// MakeRefCounted does not work with private constructor
auto instance = base::WrapRefCounted(new DigestVerifier());
if (!instance->InitializeFromResource(resource_id)) {
LOG(ERROR) << "Failed to initialize DigestVerifier from resource "
<< resource_id;
return nullptr;
}
return instance;
}
scoped_refptr<DigestVerifier> DigestVerifier::CreateFromFile(
const base::FilePath& file) {
// MakeRefCounted does not work with private constructor
auto instance = base::WrapRefCounted(new DigestVerifier());
if (!instance->InitializeFromFile(file))
return nullptr;
return instance;
}
bool DigestVerifier::IsKnownFile(const base::FilePath& file) const {
const auto digest_entry =
digests_.find(base::ToLowerASCII(file.BaseName().value()));
if (digest_entry == digests_.end())
return false;
std::string actual_digest;
if (!chrome_cleaner::ComputeSHA256DigestOfPath(file, &actual_digest)) {
LOG(ERROR) << "Failed to compute digest for " << SanitizePath(file);
return false;
}
return (base::ToLowerASCII(actual_digest) == digest_entry->second);
}
std::vector<base::FilePath::StringType> DigestVerifier::GetKnownFileNames()
const {
std::vector<base::FilePath::StringType> result;
result.reserve(digests_.size());
for (auto iter = digests_.begin(); iter != digests_.end(); ++iter) {
result.push_back(iter->first);
}
return result;
}
DigestVerifier::DigestVerifier() = default;
DigestVerifier::~DigestVerifier() = default;
bool DigestVerifier::InitializeFromResource(int resource_id) {
base::StringPiece serialized_digest_pb;
if (!chrome_cleaner::LoadResourceOfKind(resource_id, L"TEXT",
&serialized_digest_pb)) {
LOG(DFATAL) << "Failed to load expected digests from resources";
return false;
}
chrome_cleaner::FileDigests digests_pb;
if (!digests_pb.ParseFromString(serialized_digest_pb.as_string())) {
LOG(ERROR) << "Failed to parse digests protobuf";
return false;
}
for (const chrome_cleaner::FileDigest& digest : digests_pb.file_digests()) {
const std::wstring filename = base::UTF8ToWide(digest.filename());
digests_[base::ToLowerASCII(filename)] =
base::ToLowerASCII(digest.digest());
}
return true;
}
bool DigestVerifier::InitializeFromFile(const base::FilePath& file) {
std::string digest;
if (!chrome_cleaner::ComputeSHA256DigestOfPath(file, &digest)) {
LOG(ERROR) << "Failed to compute digest for " << SanitizePath(file);
return false;
}
digests_[base::ToLowerASCII(file.BaseName().value())] =
base::ToLowerASCII(digest);
return true;
}
} // namespace chrome_cleaner