1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <wrl/client.h>
#include <string>
#include <utility>
#include "base/compiler_specific.h"
#include "base/containers/heap_array.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/test/mock_callback.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_com_initializer.h"
#include "chrome/elevation_service/elevation_service_delegate.h"
#include "chrome/elevation_service/elevation_service_idl.h"
#include "chrome/install_static/install_util.h"
#include "chrome/windows_services/service_program/process_wrl_module.h"
#include "chrome/windows_services/service_program/service.h"
#include "chrome/windows_services/service_program/test_support/scoped_mock_context.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const base::FilePath TestFile(const std::string& file) {
base::FilePath path;
base::PathService::Get(base::DIR_MODULE, &path);
return path.AppendASCII("elevated_recovery_unittest").AppendASCII(file);
}
} // namespace
class ServiceMainTest : public testing::Test {
protected:
ServiceMainTest() = default;
~ServiceMainTest() override { Service::UnregisterClassObjects(cookies_); }
void SetUp() override {
ASSERT_TRUE(com_initializer_.Succeeded());
ASSERT_HRESULT_SUCCEEDED(Service::RegisterClassObjects(
service_delegate_, module_released_callback_.Get(), cookies_));
}
base::MockCallback<base::OnceClosure>& mock_module_released_callback() {
return module_released_callback_;
}
private:
base::win::ScopedCOMInitializer com_initializer_;
::testing::NiceMock<base::MockCallback<base::OnceClosure>>
module_released_callback_;
elevation_service::Delegate service_delegate_;
base::HeapArray<DWORD> cookies_;
};
TEST_F(ServiceMainTest, ExitSignalTest) {
auto& module_released_callback = mock_module_released_callback();
ScopedMockContext mock_context;
ASSERT_TRUE(mock_context.Succeeded());
Microsoft::WRL::ComPtr<IUnknown> unknown;
ASSERT_HRESULT_SUCCEEDED(
::CoCreateInstance(install_static::GetElevatorClsid(), nullptr,
CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&unknown)));
Microsoft::WRL::ComPtr<IElevator> elevator;
ASSERT_HRESULT_SUCCEEDED(unknown.As(&elevator));
unknown.Reset();
ULONG_PTR proc_handle = 0;
EXPECT_EQ(CRYPT_E_NO_MATCH,
elevator->RunRecoveryCRXElevated(
TestFile("ChromeRecovery.crx3").value().c_str(),
L"{c49ab053-2387-4809-b188-1902648802e1}", L"57.8.0.1",
L"{c49ab053-2387-4809-b188-1902648802e1}",
::GetCurrentProcessId(), &proc_handle));
// An object instance has been created upon the request, and is held by the
// server module. Therefore, the callback has not yet run.
::testing::Mock::VerifyAndClearExpectations(&module_released_callback);
// Release the instance object. Now that the last (and the only) instance
// object of the module is released, the event becomes signaled.
EXPECT_CALL(module_released_callback, Run());
elevator.Reset();
}
TEST_F(ServiceMainTest, EncryptDecryptTest) {
ScopedMockContext mock_context;
ASSERT_TRUE(mock_context.Succeeded());
Microsoft::WRL::ComPtr<IUnknown> unknown;
ASSERT_HRESULT_SUCCEEDED(
::CoCreateInstance(install_static::GetElevatorClsid(), nullptr,
CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&unknown)));
Microsoft::WRL::ComPtr<IElevator> elevator;
ASSERT_HRESULT_SUCCEEDED(unknown.As(&elevator));
unknown.Reset();
std::string plaintext("hello world");
BSTR input = ::SysAllocStringByteLen(nullptr, plaintext.length());
ASSERT_TRUE(input);
UNSAFE_TODO(memcpy(input, plaintext.data(), plaintext.length()));
base::win::ScopedBstr output;
DWORD last_error;
HRESULT hr =
elevator->EncryptData(ProtectionLevel::PROTECTION_PATH_VALIDATION, input,
output.Receive(), &last_error);
::SysFreeString(input);
ASSERT_HRESULT_SUCCEEDED(hr);
std::string encrypted;
encrypted.assign(reinterpret_cast<const char*>(output.Get()),
output.ByteLength());
BSTR input2 = ::SysAllocStringByteLen(nullptr, encrypted.length());
UNSAFE_TODO(memcpy(input2, encrypted.data(), encrypted.length()));
base::win::ScopedBstr original;
hr = elevator->DecryptData(input2, original.Receive(), &last_error);
::SysFreeString(input);
ASSERT_HRESULT_SUCCEEDED(hr);
elevator.Reset();
std::string original_string;
original_string.assign(reinterpret_cast<const char*>(original.Get()),
original.ByteLength());
ASSERT_EQ(plaintext.length(), original_string.length());
ASSERT_EQ(plaintext, original_string);
}
|