* chore: bump chromium in DEPS to 122.0.6239.2 * chore: update patches * refactor: extensions replaced StringPiece with string_view Ref: https://chromium-review.googlesource.com/c/chromium/src/+/5171926 * chore: bump chromium in DEPS to 122.0.6240.0 * chore: update patches * chore: bump chromium in DEPS to 122.0.6241.5 * chore: bump chromium in DEPS to 122.0.6245.0 * chore: bump chromium in DEPS to 122.0.6247.0 * chore: bump chromium in DEPS to 122.0.6249.0 * chore: bump chromium in DEPS to 122.0.6251.0 * 5192010: Rename {absl => std}::optional in //chrome/ https://chromium-review.googlesource.com/c/chromium/src/+/5192010 * 5109767: CodeHealth: Fix leaked raw_ptr in Linux ProcessSingleton https://chromium-review.googlesource.com/c/chromium/src/+/5109767 * 5105227: [media_preview] Show requested device in permission bubble https://chromium-review.googlesource.com/c/chromium/src/+/5105227 * chore: bump chromium in DEPS to 122.0.6253.0 * chore: update patches * 5180720: Polish tiled browser window UI on Linux | https://chromium-review.googlesource.com/c/chromium/src/+/5180720 * chore: update patches * chore: bump chromium in DEPS to 122.0.6255.0 * chore: update patches * 5186276: [autopip] Make "allow once" per navigation | https://chromium-review.googlesource.com/c/chromium/src/+/5186276 * chore: bump chromium in DEPS to 122.0.6257.0 * chore: bump chromium in DEPS to 122.0.6259.0 * chore: update patches * 5190661: Automated T* -> raw_ptr<T> rewrite "refresh" | https://chromium-review.googlesource.com/c/chromium/src/+/5190661 * 5206106: Make sure RenderFrameHosts are active when printing | https://chromium-review.googlesource.com/c/chromium/src/+/5206106 * 5202674: Reland "Automated T* -> raw_ptr<T> rewrite 'refresh'" https://chromium-review.googlesource.com/c/chromium/src/+/5202674 * fixup CodeHealth: Fix leaked raw_ptr in Linux ProcessSingleton https://chromium-review.googlesource.com/c/chromium/src/+/5109767 * fixup 5206106: Make sure RenderFrameHosts are active when printing * Make legacy ToV8() helpers private to ScriptPromiseResolver, their only user https://chromium-review.googlesource.com/c/chromium/src/+/5207474 * fixup CodeHealth: Fix leaked raw_ptr in Linux ProcessSingleton * fixup 5186276: [autopip] Make "allow once" per navigation https://chromium-review.googlesource.com/c/chromium/src/+/5186276 * chore: update patches after rebase * chore: bump chromium in DEPS to 122.0.6260.0 * 5191363: Mark LOG(FATAL) [[noreturn]] https://chromium-review.googlesource.com/c/chromium/src/+/5191363 * fixup 5186276: [autopip] Make "allow once" per navigation https://chromium-review.googlesource.com/c/chromium/src/+/5186276 * fixup Make legacy ToV8() helpers private to ScriptPromiseResolver https://chromium-review.googlesource.com/c/chromium/src/+/5207474 * chore: update patches * chore: bump chromium in DEPS to 122.0.6261.0 * chore: update patches * chore: restore patch that was mistakenly removed * 5181931: Improve LoginHandler (Part 9 / N) https://chromium-review.googlesource.com/c/chromium/src/+/5181931 * Dispatch SiteInstanceGotProcess() only when both process and site are set. https://chromium-review.googlesource.com/c/chromium/src/+/5142354 * 5171446: [AsyncSB] Pass navigation_id into CreateURLLoaderThrottles https://chromium-review.googlesource.com/c/chromium/src/+/5171446 * 5213708: Move DownloadTargetInfo into components/download https://chromium-review.googlesource.com/c/chromium/src/+/5213708 * extensions: Add a loader for Controlled Frame embedder scripts https://chromium-review.googlesource.com/c/chromium/src/+/5202765 * [CSC][Zoom] Add initial_zoom_level to DisplayMediaInformation https://chromium-review.googlesource.com/c/chromium/src/+/5168626 * chore: bump chromium in DEPS to 123.0.6262.0 * chore: bump chromium in DEPS to 122.0.6261.6 * fix: suppress clang -Wimplicit-const-int-float-conversion * fixup 5191363: Mark LOG(FATAL) [[noreturn]] for Windows https://chromium-review.googlesource.com/c/chromium/src/+/5191363 * 5167921: Remove Widget::IsTranslucentWindowOpacitySupported https://chromium-review.googlesource.com/c/chromium/src/+/5167921 Also 5148392: PinnedState: Support pinned state in PlatformWindowState | https://chromium-review.googlesource.com/c/chromium/src/+/5148392 * fixup: 5180720: Polish tiled browser window UI on Linux https://chromium-review.googlesource.com/c/chromium/src/+/5180720 * 5170669: clipboard: Migrate DOMException constructors to RejectWith- https://chromium-review.googlesource.com/c/chromium/src/+/5170669 * 5178824: [Fullscreen] Record UKM data https://chromium-review.googlesource.com/c/chromium/src/+/5178824 * chore: update patches after rebase --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com> Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: VerteDinde <vertedinde@electronjs.org> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
		
			
				
	
	
		
			158 lines
		
	
	
	
		
			4.9 KiB
			
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
	
		
			4.9 KiB
			
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright 2023 Slack Technologies, Inc.
 | 
						|
// Contributors: Weiyun Dai (https://github.com/WeiyunD/), Andrew Lay
 | 
						|
// (https://github.com/guohaolay) Use of this source code is governed by the MIT
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
#include "shell/common/asar/archive.h"
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
#include <sstream>
 | 
						|
 | 
						|
#include "base/base_paths.h"
 | 
						|
#include "base/json/json_reader.h"
 | 
						|
#include "base/logging.h"
 | 
						|
#include "base/no_destructor.h"
 | 
						|
#include "base/path_service.h"
 | 
						|
#include "base/strings/string_util.h"
 | 
						|
#include "base/strings/string_util_win.h"
 | 
						|
#include "base/strings/utf_string_conversions.h"
 | 
						|
#include "shell/common/asar/asar_util.h"
 | 
						|
 | 
						|
namespace asar {
 | 
						|
 | 
						|
const wchar_t kIntegrityCheckResourceType[] = L"Integrity";
 | 
						|
const wchar_t kIntegrityCheckResourceItem[] = L"ElectronAsar";
 | 
						|
 | 
						|
std::optional<base::FilePath> Archive::RelativePath() const {
 | 
						|
  base::FilePath exe_path;
 | 
						|
  if (!base::PathService::Get(base::FILE_EXE, &exe_path)) {
 | 
						|
    LOG(FATAL) << "Couldn't get exe file path";
 | 
						|
  }
 | 
						|
 | 
						|
  base::FilePath relative_path;
 | 
						|
  if (!exe_path.DirName().AppendRelativePath(path_, &relative_path)) {
 | 
						|
    return std::nullopt;
 | 
						|
  }
 | 
						|
 | 
						|
  return relative_path;
 | 
						|
}
 | 
						|
 | 
						|
std::optional<std::unordered_map<std::string, IntegrityPayload>>
 | 
						|
LoadIntegrityConfigCache() {
 | 
						|
  static base::NoDestructor<
 | 
						|
      std::optional<std::unordered_map<std::string, IntegrityPayload>>>
 | 
						|
      integrity_config_cache;
 | 
						|
 | 
						|
  // Skip loading if cache is already loaded
 | 
						|
  if (integrity_config_cache->has_value()) {
 | 
						|
    return *integrity_config_cache;
 | 
						|
  }
 | 
						|
 | 
						|
  // Init cache
 | 
						|
  *integrity_config_cache = std::unordered_map<std::string, IntegrityPayload>();
 | 
						|
 | 
						|
  // Load integrity config from exe resource
 | 
						|
  HMODULE module_handle = ::GetModuleHandle(NULL);
 | 
						|
 | 
						|
  HRSRC resource = ::FindResource(module_handle, kIntegrityCheckResourceItem,
 | 
						|
                                  kIntegrityCheckResourceType);
 | 
						|
  if (!resource) {
 | 
						|
    PLOG(FATAL) << "FindResource failed.";
 | 
						|
  }
 | 
						|
 | 
						|
  HGLOBAL rcData = ::LoadResource(module_handle, resource);
 | 
						|
  if (!rcData) {
 | 
						|
    PLOG(FATAL) << "LoadResource failed.";
 | 
						|
  }
 | 
						|
 | 
						|
  auto* res_data = static_cast<const char*>(::LockResource(rcData));
 | 
						|
  int res_size = SizeofResource(module_handle, resource);
 | 
						|
 | 
						|
  if (!res_data) {
 | 
						|
    PLOG(FATAL) << "Failed to integrity config from exe resource.";
 | 
						|
  }
 | 
						|
 | 
						|
  if (!res_size) {
 | 
						|
    PLOG(FATAL) << "Unexpected empty integrity config from exe resource.";
 | 
						|
  }
 | 
						|
 | 
						|
  // Parse integrity config payload
 | 
						|
  std::string integrity_config_payload = std::string(res_data, res_size);
 | 
						|
  std::optional<base::Value> root =
 | 
						|
      base::JSONReader::Read(integrity_config_payload);
 | 
						|
 | 
						|
  if (!root.has_value()) {
 | 
						|
    LOG(FATAL) << "Invalid integrity config: NOT a valid JSON.";
 | 
						|
  }
 | 
						|
 | 
						|
  const base::Value::List* file_configs = root.value().GetIfList();
 | 
						|
  if (!file_configs) {
 | 
						|
    LOG(FATAL) << "Invalid integrity config: NOT a list.";
 | 
						|
  }
 | 
						|
 | 
						|
  // Parse each individual file integrity config
 | 
						|
  for (size_t i = 0; i < file_configs->size(); i++) {
 | 
						|
    // Skip invalid file configs
 | 
						|
    const base::Value::Dict* ele_dict = (*file_configs)[i].GetIfDict();
 | 
						|
    if (!ele_dict) {
 | 
						|
      LOG(WARNING) << "Skip config " << i << ": NOT a valid dict";
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    const std::string* file = ele_dict->FindString("file");
 | 
						|
    if (!file || file->empty()) {
 | 
						|
      LOG(WARNING) << "Skip config " << i << ": Invalid file";
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    const std::string* alg = ele_dict->FindString("alg");
 | 
						|
    if (!alg || base::ToLowerASCII(*alg) != "sha256") {
 | 
						|
      LOG(WARNING) << "Skip config " << i << ": Invalid alg";
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    const std::string* value = ele_dict->FindString("value");
 | 
						|
    if (!value || value->empty()) {
 | 
						|
      LOG(WARNING) << "Skip config " << i << ": Invalid hash value";
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    // Add valid file config into cache
 | 
						|
    IntegrityPayload header_integrity;
 | 
						|
    header_integrity.algorithm = HashAlgorithm::kSHA256;
 | 
						|
    header_integrity.hash = base::ToLowerASCII(*value);
 | 
						|
 | 
						|
    integrity_config_cache->value()[base::ToLowerASCII(*file)] =
 | 
						|
        std::move(header_integrity);
 | 
						|
  }
 | 
						|
 | 
						|
  return *integrity_config_cache;
 | 
						|
}
 | 
						|
 | 
						|
std::optional<IntegrityPayload> Archive::HeaderIntegrity() const {
 | 
						|
  std::optional<base::FilePath> relative_path = RelativePath();
 | 
						|
  // Callers should have already asserted this
 | 
						|
  CHECK(relative_path.has_value());
 | 
						|
 | 
						|
  // Load integrity config from exe resource
 | 
						|
  std::optional<std::unordered_map<std::string, IntegrityPayload>>
 | 
						|
      integrity_config = LoadIntegrityConfigCache();
 | 
						|
  if (!integrity_config.has_value()) {
 | 
						|
    LOG(WARNING) << "Failed to integrity config from exe resource.";
 | 
						|
    return std::nullopt;
 | 
						|
  }
 | 
						|
 | 
						|
  // Convert Window rel path to UTF8 lower case
 | 
						|
  std::string rel_path_utf8 = base::WideToUTF8(relative_path.value().value());
 | 
						|
  rel_path_utf8 = base::ToLowerASCII(rel_path_utf8);
 | 
						|
 | 
						|
  // Find file integrity config
 | 
						|
  auto iter = integrity_config.value().find(rel_path_utf8);
 | 
						|
  if (iter == integrity_config.value().end()) {
 | 
						|
    LOG(FATAL) << "Failed to find file integrity info for " << rel_path_utf8;
 | 
						|
  }
 | 
						|
 | 
						|
  return iter->second;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace asar
 |