| Index: chrome/browser/win/enumerate_modules_model.cc
|
| diff --git a/chrome/browser/win/enumerate_modules_model.cc b/chrome/browser/win/enumerate_modules_model.cc
|
| index 98aaffa7cb5706427dec229b7925b000e0cfe723..641644b3514d934184cfd296531ae45ebf1c6d04 100644
|
| --- a/chrome/browser/win/enumerate_modules_model.cc
|
| +++ b/chrome/browser/win/enumerate_modules_model.cc
|
| @@ -97,249 +97,8 @@ bool ConvertToLongPath(const base::string16& short_path,
|
| return false;
|
| }
|
|
|
| -// Helper for scoped tracking an HCERTSTORE.
|
| -struct ScopedHCERTSTORETraits {
|
| - static HCERTSTORE InvalidValue() { return nullptr; }
|
| - static void Free(HCERTSTORE store) {
|
| - ::CertCloseStore(store, 0);
|
| - }
|
| -};
|
| -using ScopedHCERTSTORE =
|
| - base::ScopedGeneric<HCERTSTORE, ScopedHCERTSTORETraits>;
|
| -
|
| -// Helper for scoped tracking an HCRYPTMSG.
|
| -struct ScopedHCRYPTMSGTraits {
|
| - static HCRYPTMSG InvalidValue() { return nullptr; }
|
| - static void Free(HCRYPTMSG message) {
|
| - ::CryptMsgClose(message);
|
| - }
|
| -};
|
| -using ScopedHCRYPTMSG =
|
| - base::ScopedGeneric<HCRYPTMSG, ScopedHCRYPTMSGTraits>;
|
| -
|
| -// Returns the "Subject" field from the digital signature in the provided
|
| -// binary, if any is present. Returns an empty string on failure.
|
| -base::string16 GetSubjectNameInFile(const base::FilePath& filename) {
|
| - ScopedHCERTSTORE store;
|
| - ScopedHCRYPTMSG message;
|
| -
|
| - // Find the crypto message for this filename.
|
| - {
|
| - HCERTSTORE temp_store = nullptr;
|
| - HCRYPTMSG temp_message = nullptr;
|
| - bool result = !!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
|
| - filename.value().c_str(),
|
| - CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
|
| - CERT_QUERY_FORMAT_FLAG_BINARY,
|
| - 0,
|
| - nullptr,
|
| - nullptr,
|
| - nullptr,
|
| - &temp_store,
|
| - &temp_message,
|
| - nullptr);
|
| - store.reset(temp_store);
|
| - message.reset(temp_message);
|
| - if (!result)
|
| - return base::string16();
|
| - }
|
| -
|
| - // Determine the size of the signer info data.
|
| - DWORD signer_info_size = 0;
|
| - bool result = !!CryptMsgGetParam(message.get(),
|
| - CMSG_SIGNER_INFO_PARAM,
|
| - 0,
|
| - nullptr,
|
| - &signer_info_size);
|
| - if (!result)
|
| - return base::string16();
|
| -
|
| - // Allocate enough space to hold the signer info.
|
| - std::unique_ptr<BYTE[]> signer_info_buffer(new BYTE[signer_info_size]);
|
| - CMSG_SIGNER_INFO* signer_info =
|
| - reinterpret_cast<CMSG_SIGNER_INFO*>(signer_info_buffer.get());
|
| -
|
| - // Obtain the signer info.
|
| - result = !!CryptMsgGetParam(message.get(),
|
| - CMSG_SIGNER_INFO_PARAM,
|
| - 0,
|
| - signer_info,
|
| - &signer_info_size);
|
| - if (!result)
|
| - return base::string16();
|
| -
|
| - // Search for the signer certificate.
|
| - CERT_INFO CertInfo = {0};
|
| - PCCERT_CONTEXT cert_context = nullptr;
|
| - CertInfo.Issuer = signer_info->Issuer;
|
| - CertInfo.SerialNumber = signer_info->SerialNumber;
|
| -
|
| - cert_context = CertFindCertificateInStore(
|
| - store.get(),
|
| - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
| - 0,
|
| - CERT_FIND_SUBJECT_CERT,
|
| - &CertInfo,
|
| - nullptr);
|
| - if (!cert_context)
|
| - return base::string16();
|
| -
|
| - // Determine the size of the Subject name.
|
| - DWORD subject_name_size = CertGetNameString(
|
| - cert_context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, nullptr, 0);
|
| - if (!subject_name_size)
|
| - return base::string16();
|
| -
|
| - base::string16 subject_name;
|
| - subject_name.resize(subject_name_size);
|
| -
|
| - // Get subject name.
|
| - if (!(CertGetNameString(cert_context,
|
| - CERT_NAME_SIMPLE_DISPLAY_TYPE,
|
| - 0,
|
| - nullptr,
|
| - const_cast<LPWSTR>(subject_name.c_str()),
|
| - subject_name_size))) {
|
| - return base::string16();
|
| - }
|
| -
|
| - return subject_name;
|
| -}
|
| -
|
| -// Helper for scoped tracking a catalog admin context.
|
| -struct CryptCATContextScopedTraits {
|
| - static PVOID InvalidValue() { return nullptr; }
|
| - static void Free(PVOID context) {
|
| - CryptCATAdminReleaseContext(context, 0);
|
| - }
|
| -};
|
| -using ScopedCryptCATContext =
|
| - base::ScopedGeneric<PVOID, CryptCATContextScopedTraits>;
|
| -
|
| -// Helper for scoped tracking of a catalog context. A catalog context is only
|
| -// valid with an associated admin context, so this is effectively a std::pair.
|
| -// A custom operator!= is required in order for a null |catalog_context| but
|
| -// non-null |context| to compare equal to the InvalidValue exposed by the
|
| -// traits class.
|
| -class CryptCATCatalogContext {
|
| - public:
|
| - CryptCATCatalogContext(PVOID context, PVOID catalog_context)
|
| - : context_(context), catalog_context_(catalog_context) {}
|
| -
|
| - bool operator!=(const CryptCATCatalogContext& rhs) const {
|
| - return catalog_context_ != rhs.catalog_context_;
|
| - }
|
| -
|
| - PVOID context() const { return context_; }
|
| - PVOID catalog_context() const { return catalog_context_; }
|
| -
|
| - private:
|
| - PVOID context_;
|
| - PVOID catalog_context_;
|
| -};
|
| -
|
| -struct CryptCATCatalogContextScopedTraits {
|
| - static CryptCATCatalogContext InvalidValue() {
|
| - return CryptCATCatalogContext(nullptr, nullptr);
|
| - }
|
| - static void Free(const CryptCATCatalogContext& c) {
|
| - CryptCATAdminReleaseCatalogContext(
|
| - c.context(), c.catalog_context(), 0);
|
| - }
|
| -};
|
| -using ScopedCryptCATCatalogContext = base::ScopedGeneric<
|
| - CryptCATCatalogContext, CryptCATCatalogContextScopedTraits>;
|
| -
|
| -// Extracts the subject name and catalog path if the provided file is present in
|
| -// a catalog file.
|
| -void GetCatalogCertificateInfo(const base::FilePath& filename,
|
| - ModuleEnumerator::CertificateInfo* cert_info) {
|
| - // Get a crypt context for signature verification.
|
| - ScopedCryptCATContext context;
|
| - {
|
| - PVOID raw_context = nullptr;
|
| - if (!CryptCATAdminAcquireContext(&raw_context, nullptr, 0))
|
| - return;
|
| - context.reset(raw_context);
|
| - }
|
| -
|
| - // Open the file of interest.
|
| - base::win::ScopedHandle file_handle(CreateFileW(
|
| - filename.value().c_str(), GENERIC_READ,
|
| - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
| - nullptr, OPEN_EXISTING, 0, nullptr));
|
| - if (!file_handle.IsValid())
|
| - return;
|
| -
|
| - // Get the size we need for our hash.
|
| - DWORD hash_size = 0;
|
| - CryptCATAdminCalcHashFromFileHandle(
|
| - file_handle.Get(), &hash_size, nullptr, 0);
|
| - if (hash_size == 0)
|
| - return;
|
| -
|
| - // Calculate the hash. If this fails then bail.
|
| - std::vector<BYTE> buffer(hash_size);
|
| - if (!CryptCATAdminCalcHashFromFileHandle(file_handle.Get(), &hash_size,
|
| - buffer.data(), 0)) {
|
| - return;
|
| - }
|
| -
|
| - // Get catalog for our context.
|
| - ScopedCryptCATCatalogContext catalog_context(CryptCATCatalogContext(
|
| - context.get(),
|
| - CryptCATAdminEnumCatalogFromHash(context.get(), buffer.data(), hash_size,
|
| - 0, nullptr)));
|
| - if (!catalog_context.is_valid())
|
| - return;
|
| -
|
| - // Get the catalog info. This includes the path to the catalog itself, which
|
| - // contains the signature of interest.
|
| - CATALOG_INFO catalog_info = {};
|
| - catalog_info.cbStruct = sizeof(catalog_info);
|
| - if (!CryptCATCatalogInfoFromContext(
|
| - catalog_context.get().catalog_context(), &catalog_info, 0)) {
|
| - return;
|
| - }
|
| -
|
| - // Attempt to get the "Subject" field from the signature of the catalog file
|
| - // itself.
|
| - base::FilePath catalog_path(catalog_info.wszCatalogFile);
|
| - base::string16 subject = GetSubjectNameInFile(catalog_path);
|
| -
|
| - if (subject.empty())
|
| - return;
|
| -
|
| - cert_info->type = ModuleEnumerator::CERTIFICATE_IN_CATALOG;
|
| - cert_info->path = catalog_path;
|
| - cert_info->subject = subject;
|
| -}
|
| -
|
| -// Extracts information about the certificate of the given file, if any is
|
| -// found.
|
| -void GetCertificateInfo(const base::FilePath& filename,
|
| - ModuleEnumerator::CertificateInfo* cert_info) {
|
| - DCHECK_EQ(ModuleEnumerator::NO_CERTIFICATE, cert_info->type);
|
| - DCHECK(cert_info->path.empty());
|
| - DCHECK(cert_info->subject.empty());
|
| -
|
| - GetCatalogCertificateInfo(filename, cert_info);
|
| - if (cert_info->type == ModuleEnumerator::CERTIFICATE_IN_CATALOG)
|
| - return;
|
| -
|
| - base::string16 subject = GetSubjectNameInFile(filename);
|
| - if (subject.empty())
|
| - return;
|
| -
|
| - cert_info->type = ModuleEnumerator::CERTIFICATE_IN_FILE;
|
| - cert_info->path = filename;
|
| - cert_info->subject = subject;
|
| -}
|
| -
|
| } // namespace
|
|
|
| -ModuleEnumerator::CertificateInfo::CertificateInfo() : type(NO_CERTIFICATE) {}
|
| -
|
| ModuleEnumerator::Module::Module() {
|
| }
|
|
|
| @@ -709,10 +468,10 @@ void ModuleEnumerator::ReportThirdPartyMetrics() {
|
| size_t third_party_loaded = 0;
|
| size_t third_party_not_loaded = 0;
|
| for (const auto& module : *enumerated_modules_) {
|
| - if (module.cert_info.type != ModuleEnumerator::NO_CERTIFICATE) {
|
| + if (module.cert_info.type != ModuleDatabase::NO_CERTIFICATE) {
|
| ++signed_modules;
|
|
|
| - if (module.cert_info.type == ModuleEnumerator::CERTIFICATE_IN_CATALOG)
|
| + if (module.cert_info.type == ModuleDatabase::CERTIFICATE_IN_CATALOG)
|
| ++catalog_modules;
|
|
|
| // The first time this certificate is encountered it will be inserted
|
|
|