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
5 #include "chrome/credential_provider/gaiacp/gaia_credential_provider_module.h"
6
7 #include <process.h>
8
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/strings/string_util.h"
14 #include "base/win/win_util.h"
15 #include "base/win/windows_version.h"
16 #include "chrome/common/chrome_version.h"
17 #include "chrome/credential_provider/eventlog/gcp_eventlog_messages.h"
18 #include "chrome/credential_provider/extension/extension_utils.h"
19 #include "chrome/credential_provider/extension/os_service_manager.h"
20 #include "chrome/credential_provider/gaiacp/associated_user_validator.h"
21 #include "chrome/credential_provider/gaiacp/gaia_credential_base.h"
22 #include "chrome/credential_provider/gaiacp/gaia_credential_provider_filter.h"
23 #include "chrome/credential_provider/gaiacp/gaia_credential_provider_i.h"
24 #include "chrome/credential_provider/gaiacp/gcp_crash_reporting.h"
25 #include "chrome/credential_provider/gaiacp/grit/gaia_static_resources.h"
26 #include "chrome/credential_provider/gaiacp/logging.h"
27 #include "chrome/credential_provider/gaiacp/mdm_utils.h"
28 #include "chrome/credential_provider/gaiacp/reg_utils.h"
29 #include "components/crash/core/app/crash_switches.h"
30 #include "content/public/common/content_switches.h"
31
32 namespace credential_provider {
33
34 namespace {
35
InvalidParameterHandler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t pReserved)36 void InvalidParameterHandler(const wchar_t* expression,
37 const wchar_t* function,
38 const wchar_t* file,
39 unsigned int line,
40 uintptr_t pReserved) {
41 LOGFN(ERROR) << "func=" << (function ? function : L"-")
42 << " expression=" << (expression ? expression : L"-")
43 << " file=" << (file ? file : L"-") << " line=" << line;
44 }
45
CheckGCPWExtensionStatus(void * param)46 unsigned __stdcall CheckGCPWExtensionStatus(void* param) {
47 LOGFN(VERBOSE);
48 if (!credential_provider::extension::IsGCPWExtensionRunning()) {
49 credential_provider::extension::OSServiceManager* service_manager =
50 credential_provider::extension::OSServiceManager::Get();
51
52 DWORD error_code = service_manager->StartGCPWService();
53 if (error_code != ERROR_SUCCESS) {
54 LOGFN(WARNING) << "Unable to start GCPW extension win32=" << error_code;
55 }
56 }
57 return 0;
58 }
59
60 } // namespace
61
CGaiaCredentialProviderModule()62 CGaiaCredentialProviderModule::CGaiaCredentialProviderModule()
63 : ATL::CAtlDllModuleT<CGaiaCredentialProviderModule>(),
64 exit_manager_(nullptr),
65 gcpw_extension_check_performed_(0),
66 crashpad_initialized_(0) {}
67
~CGaiaCredentialProviderModule()68 CGaiaCredentialProviderModule::~CGaiaCredentialProviderModule() {}
69
70 // static
71 HRESULT WINAPI
UpdateRegistryAppId(BOOL do_register)72 CGaiaCredentialProviderModule::UpdateRegistryAppId(BOOL do_register) throw() {
73 base::FilePath eventlog_path;
74 HRESULT hr = CGaiaCredentialBase::GetInstallDirectory(&eventlog_path);
75 if (FAILED(hr)) {
76 LOGFN(ERROR) << "CGaiaCredentialBase::GetInstallDirectory hr=" << putHR(hr);
77 return hr;
78 }
79 eventlog_path =
80 eventlog_path.Append(FILE_PATH_LITERAL("gcp_eventlog_provider.dll"));
81
82 auto provider_guid_string =
83 base::win::WStringFromGUID(CLSID_GaiaCredentialProvider);
84
85 auto filter_guid_string =
86 base::win::WStringFromGUID(CLSID_CGaiaCredentialProviderFilter);
87
88 ATL::_ATL_REGMAP_ENTRY regmap[] = {
89 {L"CP_CLASS_GUID", base::as_wcstr(provider_guid_string.c_str())},
90 {L"CP_FILTER_CLASS_GUID", base::as_wcstr(filter_guid_string.c_str())},
91 {L"VERSION", TEXT(CHROME_VERSION_STRING)},
92 {L"EVENTLOG_PATH", eventlog_path.value().c_str()},
93 {nullptr, nullptr},
94 };
95
96 return ATL::_pAtlModule->UpdateRegistryFromResource(
97 IDR_GAIACREDENTIALPROVIDER, do_register, regmap);
98 }
99
RefreshTokenHandleValidity()100 void CGaiaCredentialProviderModule::RefreshTokenHandleValidity() {
101 if (!token_handle_validity_refreshed_) {
102 credential_provider::AssociatedUserValidator::Get()
103 ->StartRefreshingTokenHandleValidity();
104 token_handle_validity_refreshed_ = true;
105 }
106 }
107
CheckGCPWExtension()108 void CGaiaCredentialProviderModule::CheckGCPWExtension() {
109 LOGFN(VERBOSE);
110 if (extension::IsGCPWExtensionEnabled() &&
111 ::InterlockedCompareExchange(&gcpw_extension_check_performed_, 1, 0) ==
112 0) {
113 gcpw_extension_checker_thread_handle_ =
114 reinterpret_cast<HANDLE>(_beginthreadex(
115 nullptr, 0, CheckGCPWExtensionStatus, nullptr, 0, nullptr));
116 }
117 }
118
InitializeCrashReporting()119 void CGaiaCredentialProviderModule::InitializeCrashReporting() {
120 // Perform a thread unsafe check to see whether crash reporting is
121 // initialized. Thread safe check is performed right before initializing crash
122 // reporting.
123 if (GetGlobalFlagOrDefault(kRegInitializeCrashReporting, 1) &&
124 !crashpad_initialized_) {
125 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
126
127 if (!base::EndsWith(cmd_line->GetProgram().value(), L"gcp_unittests.exe",
128 base::CompareCase::INSENSITIVE_ASCII) &&
129 cmd_line->GetSwitchValueASCII(switches::kProcessType) !=
130 crash_reporter::switches::kCrashpadHandler &&
131 ::InterlockedCompareExchange(&crashpad_initialized_, 1, 0) == 0) {
132 ConfigureGcpCrashReporting(*cmd_line);
133 LOGFN(VERBOSE) << "Crash reporting was initialized.";
134 }
135 }
136 }
137
LogProcessDetails()138 void CGaiaCredentialProviderModule::LogProcessDetails() {
139 wchar_t process_name[MAX_PATH] = {0};
140 GetModuleFileName(nullptr, process_name, MAX_PATH);
141
142 LOGFN(INFO) << "GCPW Initialized in " << process_name
143 << " GCPW Version: " << (CHROME_VERSION_STRING)
144 << " Windows Build: "
145 << base::win::OSInfo::GetInstance()->Kernel32BaseVersion()
146 << " Version:" << GetWindowsVersion();
147 }
148
DllMain(HINSTANCE,DWORD reason,LPVOID reserved)149 BOOL CGaiaCredentialProviderModule::DllMain(HINSTANCE /*hinstance*/,
150 DWORD reason,
151 LPVOID reserved) {
152 switch (reason) {
153 case DLL_PROCESS_ATTACH: {
154 exit_manager_ = std::make_unique<base::AtExitManager>();
155
156 _set_invalid_parameter_handler(InvalidParameterHandler);
157
158 // Initialize base. Command line will be set from GetCommandLineW().
159 base::CommandLine::Init(0, nullptr);
160
161 // Initialize logging.
162 logging::LoggingSettings settings;
163 settings.logging_dest = logging::LOG_NONE;
164 logging::InitLogging(settings);
165 logging::SetLogItems(true, // Enable process id.
166 true, // Enable thread id.
167 true, // Enable timestamp.
168 false); // Enable tickcount.
169 logging::SetEventSource("GCPW", GCPW_CATEGORY, MSG_LOG_MESSAGE);
170 if (GetGlobalFlagOrDefault(kRegEnableVerboseLogging, 0))
171 logging::SetMinLogLevel(logging::LOG_VERBOSE);
172 break;
173 }
174 case DLL_PROCESS_DETACH:
175 LOGFN(VERBOSE) << "DllMain(DLL_PROCESS_DETACH)";
176
177 // When this DLL is loaded for testing, don't reset the command line
178 // since it causes tests to crash.
179 if (!is_testing_)
180 base::CommandLine::Reset();
181
182 _set_invalid_parameter_handler(nullptr);
183 exit_manager_.reset();
184 break;
185
186 default:
187 break;
188 }
189
190 return ATL::CAtlDllModuleT<CGaiaCredentialProviderModule>::DllMain(reason,
191 reserved);
192 }
193
194 } // namespace credential_provider
195