elevated_recovery_unittest.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "chrome/elevation_service/elevated_recovery_impl.h"
  5. #include <windows.h>
  6. #include <wrl/implements.h>
  7. #include <memory>
  8. #include <vector>
  9. #include "base/command_line.h"
  10. #include "base/files/file_path.h"
  11. #include "base/files/file_util.h"
  12. #include "base/files/scoped_temp_dir.h"
  13. #include "base/path_service.h"
  14. #include "base/win/scoped_com_initializer.h"
  15. #include "chrome/elevation_service/scoped_mock_context.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. namespace elevation_service {
  18. namespace {
  19. // There is no exe in "valid_publisher.crx3", so we point to the manifest
  20. // instead for these tests.
  21. constexpr base::FilePath::CharType kManifestJSONFileName[] =
  22. FILE_PATH_LITERAL("manifest.json");
  23. // The SHA256 of the SubjectPublicKeyInfo used to sign "valid_publisher.crx3",
  24. // which houses extension id ojjgnpkioondelmggbekfhllhdaimnho.
  25. std::vector<uint8_t> GetValidPublisherCrx3Hash() {
  26. return std::vector<uint8_t>{0xe9, 0x96, 0xdf, 0xa8, 0xee, 0xd3, 0x4b, 0xc6,
  27. 0x61, 0x4a, 0x57, 0xbb, 0x73, 0x08, 0xcd, 0x7e,
  28. 0x51, 0x9b, 0xcc, 0x69, 0x08, 0x41, 0xe1, 0x96,
  29. 0x9f, 0x7c, 0xb1, 0x73, 0xef, 0x16, 0x80, 0x0a};
  30. }
  31. // The test exe within components/test/data/update_client/ChromeRecovery.crx3.
  32. constexpr base::FilePath::CharType kRecoveryExeName[] =
  33. FILE_PATH_LITERAL("ChromeRecovery.exe");
  34. // The SHA256 of the SubjectPublicKeyInfo used to sign
  35. // components/test/data/update_client/ChromeRecovery.crx3.
  36. std::vector<uint8_t> GetRunactionTestWinCrx3Hash() {
  37. return std::vector<uint8_t>{0x69, 0xfc, 0x41, 0xf6, 0x17, 0x20, 0xc6, 0x36,
  38. 0x92, 0xcd, 0x95, 0x76, 0x69, 0xf6, 0x28, 0xcc,
  39. 0xbe, 0x98, 0x4b, 0x93, 0x17, 0xd6, 0x9c, 0xb3,
  40. 0x64, 0x0c, 0x0d, 0x25, 0x61, 0xc5, 0x80, 0x1d};
  41. }
  42. const base::FilePath GetUnpackDir() {
  43. base::FilePath path;
  44. base::PathService::Get(base::DIR_TEMP, &path);
  45. return path;
  46. }
  47. const base::FilePath TestFile(const std::string& file) {
  48. base::FilePath path;
  49. base::PathService::Get(base::DIR_MODULE, &path);
  50. return path.AppendASCII("elevated_recovery_unittest")
  51. .AppendASCII(file);
  52. }
  53. } // namespace
  54. class ElevatedRecoveryTest : public testing::Test {
  55. protected:
  56. ElevatedRecoveryTest() = default;
  57. void SetUp() override {
  58. ASSERT_TRUE(com_initializer_.Succeeded());
  59. ASSERT_TRUE(mock_context_.Succeeded());
  60. }
  61. private:
  62. base::win::ScopedCOMInitializer com_initializer_;
  63. ScopedMockContext mock_context_;
  64. };
  65. TEST_F(ElevatedRecoveryTest, Do_RunChromeRecoveryCRX_InvalidArgs) {
  66. base::win::ScopedHandle proc_handle;
  67. // Empty browser_appid/browser_version/session_id.
  68. EXPECT_EQ(E_INVALIDARG, elevation_service::RunChromeRecoveryCRX(
  69. TestFile("valid_publisher.crx3"), std::wstring(),
  70. std::wstring(), std::wstring(),
  71. ::GetCurrentProcessId(), &proc_handle));
  72. // Invalid browser_appid, valid browser_version/session_id.
  73. EXPECT_EQ(E_INVALIDARG,
  74. elevation_service::RunChromeRecoveryCRX(
  75. TestFile("valid_publisher.crx3"), L"invalidappid", L"1.2.3.4",
  76. L"{c49ab053-2387-4809-b188-1902648802e1}",
  77. ::GetCurrentProcessId(), &proc_handle));
  78. // Empty browser_appid, invalid browser_version, valid session_id.
  79. EXPECT_EQ(E_INVALIDARG, elevation_service::RunChromeRecoveryCRX(
  80. TestFile("valid_publisher.crx3"), std::wstring(),
  81. L"invalidbrowserversion",
  82. L"{c49ab053-2387-4809-b188-1902648802e1}",
  83. ::GetCurrentProcessId(), &proc_handle));
  84. // Valid browser_appid, invalid browser_version, valid session_id.
  85. EXPECT_EQ(E_INVALIDARG, elevation_service::RunChromeRecoveryCRX(
  86. TestFile("valid_publisher.crx3"),
  87. L"{c49ab053-2387-4809-b188-1902648802e1}",
  88. L"invalidbrowserversion",
  89. L"{c49ab053-2387-4809-b188-1902648802e1}",
  90. ::GetCurrentProcessId(), &proc_handle));
  91. // Valid browser_appid, valid browser_version, invalid session_id.
  92. EXPECT_EQ(E_INVALIDARG,
  93. elevation_service::RunChromeRecoveryCRX(
  94. TestFile("valid_publisher.crx3"),
  95. L"{c49ab053-2387-4809-b188-1902648802e1}", L"57.8.0.1",
  96. L"invalidsessionid", ::GetCurrentProcessId(), &proc_handle));
  97. }
  98. TEST_F(ElevatedRecoveryTest, Do_RunCRX_InvalidArgs) {
  99. base::win::ScopedHandle proc_handle;
  100. // Non-matching CRX/CRX-hash.
  101. EXPECT_EQ(CRYPT_E_NO_MATCH,
  102. elevation_service::RunCRX(
  103. TestFile("valid_no_publisher.crx3"),
  104. base::CommandLine(base::CommandLine::NO_PROGRAM),
  105. crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF,
  106. GetValidPublisherCrx3Hash(), GetUnpackDir(),
  107. base::FilePath(kManifestJSONFileName), ::GetCurrentProcessId(),
  108. &proc_handle));
  109. // Non-existent CRX file.
  110. EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
  111. elevation_service::RunCRX(
  112. TestFile("nonexistent.crx3"),
  113. base::CommandLine(base::CommandLine::NO_PROGRAM),
  114. crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF,
  115. GetValidPublisherCrx3Hash(), GetUnpackDir(),
  116. base::FilePath(kManifestJSONFileName), ::GetCurrentProcessId(),
  117. &proc_handle));
  118. // manifest.json is not a Windows executable, ::CreateProcess therefore
  119. // returns ERROR_BAD_EXE_FORMAT.
  120. EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_BAD_EXE_FORMAT),
  121. elevation_service::RunCRX(
  122. TestFile("valid_publisher.crx3"),
  123. base::CommandLine(base::CommandLine::NO_PROGRAM),
  124. crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF,
  125. GetValidPublisherCrx3Hash(), GetUnpackDir(),
  126. base::FilePath(kManifestJSONFileName), ::GetCurrentProcessId(),
  127. &proc_handle));
  128. }
  129. TEST_F(ElevatedRecoveryTest, Do_RunCRX_ValidArgs) {
  130. base::win::ScopedHandle proc_handle;
  131. // ChromeRecovery.crx3 contains ChromeRecovery.exe which returns a hardcoded
  132. // value of 1877345072.
  133. EXPECT_EQ(S_OK,
  134. elevation_service::RunCRX(
  135. TestFile("ChromeRecovery.crx3"),
  136. base::CommandLine(base::CommandLine::NO_PROGRAM),
  137. crx_file::VerifierFormat::CRX3, GetRunactionTestWinCrx3Hash(),
  138. GetUnpackDir(), base::FilePath(kRecoveryExeName),
  139. ::GetCurrentProcessId(), &proc_handle));
  140. EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(proc_handle.Get(), 500));
  141. DWORD exit_code = 0;
  142. EXPECT_TRUE(::GetExitCodeProcess(proc_handle.Get(), &exit_code));
  143. EXPECT_EQ(1877345072UL, exit_code);
  144. }
  145. TEST(ElevatedRecoveryCleanupTest, Do_CleanupChromeRecoveryDirectory) {
  146. base::FilePath recovery_dir;
  147. ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &recovery_dir));
  148. recovery_dir = recovery_dir.DirName().DirName().Append(
  149. FILE_PATH_LITERAL("ChromeRecovery"));
  150. ASSERT_TRUE(base::CreateDirectory(recovery_dir));
  151. base::FilePath temp_file;
  152. ASSERT_TRUE(base::CreateTemporaryFileInDir(recovery_dir, &temp_file));
  153. ASSERT_TRUE(base::CreateTemporaryFileInDir(recovery_dir, &temp_file));
  154. ASSERT_TRUE(base::CreateTemporaryFileInDir(recovery_dir, &temp_file));
  155. base::ScopedTempDir scoped_dir;
  156. ASSERT_TRUE(scoped_dir.CreateUniqueTempDirUnderPath(recovery_dir));
  157. ASSERT_TRUE(base::CreateTemporaryFileInDir(scoped_dir.GetPath(), &temp_file));
  158. ASSERT_TRUE(base::CreateTemporaryFileInDir(scoped_dir.GetPath(), &temp_file));
  159. EXPECT_EQ(S_OK, elevation_service::CleanupChromeRecoveryDirectory());
  160. EXPECT_TRUE(base::PathExists(recovery_dir));
  161. EXPECT_TRUE(base::IsDirectoryEmpty(recovery_dir));
  162. }
  163. } // namespace elevation_service