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/reg_utils.h"
6
7 #include <atlbase.h>
8
9 #include "base/base64.h"
10 #include "base/stl_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/win/registry.h"
14 #include "base/win/win_util.h"
15 #include "build/branding_buildflags.h"
16 #include "chrome/credential_provider/common/gcp_strings.h"
17 #include "chrome/credential_provider/gaiacp/gaia_credential_provider_i.h"
18 #include "chrome/credential_provider/gaiacp/logging.h"
19
20 namespace credential_provider {
21
22 // Root registry key for GCPW configuration and state.
23 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
24 #define CREDENTIAL_PROVIDER_REGISTRY_KEY L"Software\\Google\\GCPW"
25 #else
26 #define CREDENTIAL_PROVIDER_REGISTRY_KEY L"Software\\Chromium\\GCPW"
27 #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
28
29 const wchar_t kGcpRootKeyName[] = CREDENTIAL_PROVIDER_REGISTRY_KEY;
30
31 const wchar_t kGcpUsersRootKeyName[] =
32 CREDENTIAL_PROVIDER_REGISTRY_KEY L"\\Users";
33
34 const wchar_t kWinlogonUserListRegKey[] =
35 L"SOFTWARE\\Microsoft\\Windows NT"
36 L"\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList";
37
38 const wchar_t kLogonUiUserTileRegKey[] =
39 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Authentication\\LogonUI"
40 L"\\UserTile";
41
42 const wchar_t kMicrosoftCryptographyRegKey[] =
43 L"SOFTWARE\\Microsoft\\Cryptography";
44 const wchar_t kMicrosoftCryptographyMachineGuidRegKey[] = L"MachineGuid";
45
46 constexpr wchar_t kRegUserDeviceResourceId[] = L"device_resource_id";
47 constexpr wchar_t kRegGlsPath[] = L"gls_path";
48 constexpr wchar_t kRegEnableVerboseLogging[] = L"enable_verbose_logging";
49 constexpr wchar_t kRegInitializeCrashReporting[] = L"enable_crash_reporting";
50 constexpr wchar_t kRegMdmUrl[] = L"mdm";
51 constexpr wchar_t kRegEnableDmEnrollment[] = L"enable_dm_enrollment";
52 constexpr wchar_t kRegDisablePasswordSync[] = L"disable_password_sync";
53 constexpr wchar_t kRegMdmSupportsMultiUser[] = L"enable_multi_user_login";
54 constexpr wchar_t kRegMdmAllowConsumerAccounts[] = L"enable_consumer_accounts ";
55 constexpr wchar_t kRegMdmEnableForcePasswordReset[] =
56 L"enable_force_reset_password_option";
57 constexpr wchar_t kRegDeviceDetailsUploadStatus[] =
58 L"device_details_upload_status";
59 constexpr wchar_t kRegDeviceDetailsUploadFailures[] =
60 L"device_details_upload_failures";
61 constexpr wchar_t kRegDeveloperMode[] = L"developer_mode";
62 constexpr wchar_t kRegUpdateCredentialsOnChange[] =
63 L"update_credentials_on_change";
64 constexpr wchar_t kRegUseShorterAccountName[] = L"use_shorter_account_name";
65 constexpr wchar_t kEmailDomainsKey[] = L"ed"; // deprecated.
66 constexpr wchar_t kEmailDomainsKeyNew[] = L"domains_allowed_to_login";
67
68 namespace {
69
70 constexpr wchar_t kAccountPicturesRootRegKey[] =
71 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AccountPicture\\Users";
72 constexpr wchar_t kImageRegKey[] = L"Image";
73
74 // Registry entry that controls whether GCPW is the default
75 // Credential Provider or not.
76 constexpr wchar_t kMakeGcpwDefaultCredProvider[] = L"set_gcpw_as_default_cp";
77 // Windows OS defined registry entry used to configure the
78 // default credential provider CLSID.
79 constexpr wchar_t kDefaultCredProviderPath[] =
80 L"Software\\Policies\\Microsoft\\Windows\\System";
81 constexpr wchar_t kDefaultCredProviderKey[] = L"DefaultCredentialProvider";
82
83 constexpr wchar_t kEnrollmentRegKey[] = L"SOFTWARE\\Google\\Enrollment";
84 constexpr wchar_t kDmTokenRegKey[] = L"dmtoken";
85
SetMachineRegDWORD(const base::string16 & key_name,const base::string16 & name,DWORD value)86 HRESULT SetMachineRegDWORD(const base::string16& key_name,
87 const base::string16& name,
88 DWORD value) {
89 base::win::RegKey key;
90 LONG sts = key.Create(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_WRITE);
91 if (sts != ERROR_SUCCESS)
92 return HRESULT_FROM_WIN32(sts);
93
94 sts = key.WriteValue(name.c_str(), value);
95 if (sts != ERROR_SUCCESS)
96 return HRESULT_FROM_WIN32(sts);
97
98 return S_OK;
99 }
100
SetMachineRegString(const base::string16 & key_name,const base::string16 & name,const base::string16 & value)101 HRESULT SetMachineRegString(const base::string16& key_name,
102 const base::string16& name,
103 const base::string16& value) {
104 base::win::RegKey key;
105 LONG sts = key.Create(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_WRITE);
106 if (sts != ERROR_SUCCESS)
107 return HRESULT_FROM_WIN32(sts);
108
109 if (value.empty()) {
110 sts = key.DeleteValue(name.c_str());
111 if (sts == ERROR_FILE_NOT_FOUND)
112 sts = ERROR_SUCCESS;
113 } else {
114 sts = key.WriteValue(name.c_str(), value.c_str());
115 }
116
117 if (sts != ERROR_SUCCESS)
118 return HRESULT_FROM_WIN32(sts);
119
120 return S_OK;
121 }
122
SetMachineRegBinaryInternal(const base::string16 & key_name,const base::string16 & name,const std::string & value,REGSAM sam_desired)123 HRESULT SetMachineRegBinaryInternal(const base::string16& key_name,
124 const base::string16& name,
125 const std::string& value,
126 REGSAM sam_desired) {
127 base::win::RegKey key;
128 LONG sts = key.Create(HKEY_LOCAL_MACHINE, key_name.c_str(), sam_desired);
129 if (sts != ERROR_SUCCESS)
130 return HRESULT_FROM_WIN32(sts);
131
132 if (value.empty()) {
133 sts = key.DeleteValue(name.c_str());
134 if (sts == ERROR_FILE_NOT_FOUND)
135 sts = ERROR_SUCCESS;
136 } else {
137 sts =
138 key.WriteValue(name.c_str(), value.c_str(), value.length(), REG_BINARY);
139 }
140
141 if (sts != ERROR_SUCCESS)
142 return HRESULT_FROM_WIN32(sts);
143
144 return S_OK;
145 }
146
GetImageRegKeyForSpecificSize(int image_size)147 base::string16 GetImageRegKeyForSpecificSize(int image_size) {
148 return base::StringPrintf(L"%ls%i", kImageRegKey, image_size);
149 }
150
GetAccountPictureRegPathForUSer(const base::string16 & user_sid)151 base::string16 GetAccountPictureRegPathForUSer(const base::string16& user_sid) {
152 return base::StringPrintf(L"%ls\\%ls", kAccountPicturesRootRegKey,
153 user_sid.c_str());
154 }
155
156 } // namespace
157
MakeGcpwDefaultCP()158 HRESULT MakeGcpwDefaultCP() {
159 if (GetGlobalFlagOrDefault(kMakeGcpwDefaultCredProvider, 1))
160 return SetMachineRegString(
161 kDefaultCredProviderPath, kDefaultCredProviderKey,
162 base::win::WStringFromGUID(CLSID_GaiaCredentialProvider));
163
164 return S_OK;
165 }
166
GetMachineRegDWORD(const base::string16 & key_name,const base::string16 & name,DWORD * value)167 HRESULT GetMachineRegDWORD(const base::string16& key_name,
168 const base::string16& name,
169 DWORD* value) {
170 base::win::RegKey key;
171 LONG sts = key.Open(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_READ);
172 if (sts != ERROR_SUCCESS)
173 return HRESULT_FROM_WIN32(sts);
174
175 sts = key.ReadValueDW(name.c_str(), value);
176 if (sts != ERROR_SUCCESS)
177 return HRESULT_FROM_WIN32(sts);
178
179 return S_OK;
180 }
181
GetMachineRegString(const base::string16 & key_name,const base::string16 & name,wchar_t * value,ULONG * length)182 HRESULT GetMachineRegString(const base::string16& key_name,
183 const base::string16& name,
184 wchar_t* value,
185 ULONG* length) {
186 DCHECK(value);
187 DCHECK(length);
188 DCHECK_GT(*length, 0u);
189
190 base::win::RegKey key;
191 LONG sts = key.Open(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_READ);
192 if (sts != ERROR_SUCCESS)
193 return HRESULT_FROM_WIN32(sts);
194
195 // read one less character that specified in |length| so that the returned
196 // string can always be null terminated. Note that string registry values
197 // are not guaranteed to be null terminated.
198 DWORD type;
199 ULONG local_length = (*length - 1) * sizeof(decltype(value[0]));
200 sts = key.ReadValue(name.c_str(), value, &local_length, &type);
201 if (type != REG_SZ)
202 return HRESULT_FROM_WIN32(ERROR_CANTREAD);
203
204 // When using this overload of the ReadValue() method, the returned length
205 // is in bytes. The caller expects the length in characters.
206 local_length /= sizeof(decltype(value[0]));
207
208 if (sts != ERROR_SUCCESS) {
209 if (sts == ERROR_MORE_DATA)
210 *length = local_length;
211 return HRESULT_FROM_WIN32(sts);
212 }
213
214 value[local_length] = 0;
215 *length = local_length;
216 return S_OK;
217 }
218
GetMachineRegBinaryInternal(const base::string16 & key_name,const base::string16 & name,std::string * val,REGSAM sam_desired)219 HRESULT GetMachineRegBinaryInternal(const base::string16& key_name,
220 const base::string16& name,
221 std::string* val,
222 REGSAM sam_desired) {
223 DCHECK(val);
224
225 base::win::RegKey key;
226 LONG sts = key.Open(HKEY_LOCAL_MACHINE, key_name.c_str(), sam_desired);
227 if (sts != ERROR_SUCCESS)
228 return HRESULT_FROM_WIN32(sts);
229
230 DWORD type;
231 DWORD size = 0;
232
233 sts = key.ReadValue(name.c_str(), nullptr, &size, &type);
234 if (sts != ERROR_SUCCESS)
235 return HRESULT_FROM_WIN32(sts);
236
237 if (type != REG_BINARY)
238 return HRESULT_FROM_WIN32(ERROR_CANTREAD);
239
240 std::vector<char> buffer(size);
241
242 sts = key.ReadValue(name.c_str(), const_cast<char*>(buffer.data()), &size,
243 &type);
244 if (sts != ERROR_SUCCESS) {
245 if (sts == ERROR_MORE_DATA)
246 return HRESULT_FROM_WIN32(sts);
247 }
248
249 val->assign(buffer.data(), buffer.size());
250
251 return S_OK;
252 }
253
GetAccountPictureRegString(const base::string16 & user_sid,int image_size,wchar_t * value,ULONG * length)254 HRESULT GetAccountPictureRegString(const base::string16& user_sid,
255 int image_size,
256 wchar_t* value,
257 ULONG* length) {
258 return GetMachineRegString(GetAccountPictureRegPathForUSer(user_sid),
259 GetImageRegKeyForSpecificSize(image_size), value,
260 length);
261 }
262
263 // Sets a specific account picture registry key in HKEY_LOCAL_MACHINE
SetAccountPictureRegString(const base::string16 & user_sid,int image_size,const base::string16 & value)264 HRESULT SetAccountPictureRegString(const base::string16& user_sid,
265 int image_size,
266 const base::string16& value) {
267 return SetMachineRegString(GetAccountPictureRegPathForUSer(user_sid),
268 GetImageRegKeyForSpecificSize(image_size), value);
269 }
270
GetGlobalFlag(const base::string16 & name,DWORD * value)271 HRESULT GetGlobalFlag(const base::string16& name, DWORD* value) {
272 return GetMachineRegDWORD(kGcpRootKeyName, name, value);
273 }
274
GetGlobalFlag(const base::string16 & name,wchar_t * value,ULONG * length)275 HRESULT GetGlobalFlag(const base::string16& name,
276 wchar_t* value,
277 ULONG* length) {
278 return GetMachineRegString(kGcpRootKeyName, name, value, length);
279 }
280
GetGlobalFlagOrDefault(const base::string16 & reg_key,const base::string16 & default_value)281 base::string16 GetGlobalFlagOrDefault(const base::string16& reg_key,
282 const base::string16& default_value) {
283 wchar_t reg_value_buffer[256];
284 ULONG length = base::size(reg_value_buffer);
285 HRESULT hr = GetGlobalFlag(reg_key, reg_value_buffer, &length);
286 if (FAILED(hr))
287 return default_value;
288
289 return reg_value_buffer;
290 }
291
GetGlobalFlagOrDefault(const base::string16 & reg_key,const DWORD & default_value)292 DWORD GetGlobalFlagOrDefault(const base::string16& reg_key,
293 const DWORD& default_value) {
294 DWORD value;
295 HRESULT hr = GetGlobalFlag(reg_key, &value);
296 return SUCCEEDED(hr) ? value : default_value;
297 }
298
SetGlobalFlag(const base::string16 & name,DWORD value)299 HRESULT SetGlobalFlag(const base::string16& name, DWORD value) {
300 return SetMachineRegDWORD(kGcpRootKeyName, name, value);
301 }
302
SetGlobalFlag(const base::string16 & name,const base::string16 & value)303 HRESULT SetGlobalFlag(const base::string16& name, const base::string16& value) {
304 return SetMachineRegString(kGcpRootKeyName, name, value);
305 }
306
SetGlobalFlagForTesting(const base::string16 & name,const base::string16 & value)307 HRESULT SetGlobalFlagForTesting(const base::string16& name,
308 const base::string16& value) {
309 return SetMachineRegString(kGcpRootKeyName, name, value);
310 }
311
SetGlobalFlagForTesting(const base::string16 & name,DWORD value)312 HRESULT SetGlobalFlagForTesting(const base::string16& name, DWORD value) {
313 return SetMachineRegDWORD(kGcpRootKeyName, name, value);
314 }
315
SetUpdaterClientsAppPathFlag(const base::string16 & name,DWORD value)316 HRESULT SetUpdaterClientsAppPathFlag(const base::string16& name, DWORD value) {
317 base::win::RegKey key;
318 LONG sts = key.Create(HKEY_LOCAL_MACHINE, kRegUpdaterClientsAppPath,
319 KEY_WRITE | KEY_WOW64_32KEY);
320 if (sts != ERROR_SUCCESS)
321 return HRESULT_FROM_WIN32(sts);
322
323 sts = key.WriteValue(name.c_str(), value);
324 if (sts != ERROR_SUCCESS)
325 return HRESULT_FROM_WIN32(sts);
326
327 return S_OK;
328 }
329
GetUpdaterClientsAppPathFlag(const base::string16 & name,DWORD * value)330 HRESULT GetUpdaterClientsAppPathFlag(const base::string16& name, DWORD* value) {
331 base::win::RegKey key;
332 LONG sts = key.Open(HKEY_LOCAL_MACHINE, kRegUpdaterClientsAppPath,
333 KEY_READ | KEY_WOW64_32KEY);
334 if (sts != ERROR_SUCCESS)
335 return HRESULT_FROM_WIN32(sts);
336
337 sts = key.ReadValueDW(name.c_str(), value);
338 if (sts != ERROR_SUCCESS)
339 return HRESULT_FROM_WIN32(sts);
340
341 return S_OK;
342 }
343
GetUpdaterClientsAppPathFlagOrDefault(const base::string16 & reg_key,const DWORD & default_value)344 DWORD GetUpdaterClientsAppPathFlagOrDefault(const base::string16& reg_key,
345 const DWORD& default_value) {
346 DWORD value;
347 HRESULT hr = GetUpdaterClientsAppPathFlag(reg_key, &value);
348 return SUCCEEDED(hr) ? value : default_value;
349 }
350
GetUserProperty(const base::string16 & sid,const base::string16 & name,DWORD * value)351 HRESULT GetUserProperty(const base::string16& sid,
352 const base::string16& name,
353 DWORD* value) {
354 wchar_t key_name[128];
355 swprintf_s(key_name, base::size(key_name), L"%s\\%s", kGcpUsersRootKeyName,
356 sid.c_str());
357 return GetMachineRegDWORD(key_name, name, value);
358 }
359
GetUserProperty(const base::string16 & sid,const base::string16 & name,wchar_t * value,ULONG * length)360 HRESULT GetUserProperty(const base::string16& sid,
361 const base::string16& name,
362 wchar_t* value,
363 ULONG* length) {
364 wchar_t key_name[128];
365 swprintf_s(key_name, base::size(key_name), L"%s\\%s", kGcpUsersRootKeyName,
366 sid.c_str());
367 return GetMachineRegString(key_name, name, value, length);
368 }
369
SetUserProperty(const base::string16 & sid,const base::string16 & name,DWORD value)370 HRESULT SetUserProperty(const base::string16& sid,
371 const base::string16& name,
372 DWORD value) {
373 wchar_t key_name[128];
374 swprintf_s(key_name, base::size(key_name), L"%s\\%s", kGcpUsersRootKeyName,
375 sid.c_str());
376 return SetMachineRegDWORD(key_name, name, value);
377 }
378
SetUserProperty(const base::string16 & sid,const base::string16 & name,const base::string16 & value)379 HRESULT SetUserProperty(const base::string16& sid,
380 const base::string16& name,
381 const base::string16& value) {
382 wchar_t key_name[128];
383 swprintf_s(key_name, base::size(key_name), L"%s\\%s", kGcpUsersRootKeyName,
384 sid.c_str());
385 return SetMachineRegString(key_name, name, value);
386 }
387
RemoveAllUserProperties(const base::string16 & sid)388 HRESULT RemoveAllUserProperties(const base::string16& sid) {
389 base::win::RegKey key;
390 LONG sts = key.Open(HKEY_LOCAL_MACHINE, kGcpUsersRootKeyName, KEY_WRITE);
391 if (sts != ERROR_SUCCESS)
392 return HRESULT_FROM_WIN32(sts);
393
394 sts = key.DeleteKey(sid.c_str());
395 return sts != ERROR_SUCCESS ? HRESULT_FROM_WIN32(sts) : S_OK;
396 }
397
GetUserTokenHandles(std::map<base::string16,UserTokenHandleInfo> * sid_to_handle_info)398 HRESULT GetUserTokenHandles(
399 std::map<base::string16, UserTokenHandleInfo>* sid_to_handle_info) {
400 DCHECK(sid_to_handle_info);
401 sid_to_handle_info->clear();
402
403 base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kGcpUsersRootKeyName);
404 for (; iter.Valid(); ++iter) {
405 const wchar_t* sid = iter.Name();
406 wchar_t gaia_id[256];
407 ULONG length = base::size(gaia_id);
408 HRESULT gaia_id_hr = GetUserProperty(sid, kUserId, gaia_id, &length);
409 wchar_t token_handle[256];
410 length = base::size(token_handle);
411 HRESULT token_handle_hr =
412 GetUserProperty(sid, kUserTokenHandle, token_handle, &length);
413 wchar_t email_address[256];
414 length = base::size(email_address);
415 HRESULT email_address_hr =
416 GetUserProperty(sid, kUserEmail, email_address, &length);
417 sid_to_handle_info->emplace(
418 sid,
419 UserTokenHandleInfo{SUCCEEDED(gaia_id_hr) ? gaia_id : L"",
420 SUCCEEDED(email_address_hr) ? email_address : L"",
421 SUCCEEDED(token_handle_hr) ? token_handle : L""});
422 }
423 return S_OK;
424 }
425
GetSidFromKey(const wchar_t * key,const base::string16 & value,wchar_t * sid,ULONG length)426 HRESULT GetSidFromKey(const wchar_t* key,
427 const base::string16& value,
428 wchar_t* sid,
429 ULONG length) {
430 DCHECK(sid);
431 bool result_found = false;
432 base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kGcpUsersRootKeyName);
433 for (; iter.Valid(); ++iter) {
434 const wchar_t* user_sid = iter.Name();
435 wchar_t result[256];
436 ULONG result_length = base::size(result);
437 HRESULT hr = GetUserProperty(user_sid, key, result, &result_length);
438 if (SUCCEEDED(hr) && value == result) {
439 // Make sure there are not 2 users with the same SID.
440 if (result_found)
441 return HRESULT_FROM_WIN32(ERROR_USER_EXISTS);
442
443 wcsncpy_s(sid, length, user_sid, wcslen(user_sid));
444 result_found = true;
445 }
446 }
447
448 return result_found ? S_OK : HRESULT_FROM_WIN32(ERROR_NONE_MAPPED);
449 }
450
GetSidFromEmail(const base::string16 & email,wchar_t * sid,ULONG length)451 HRESULT GetSidFromEmail(const base::string16& email,
452 wchar_t* sid,
453 ULONG length) {
454 return GetSidFromKey(kUserEmail, email, sid, length);
455 }
456
GetSidFromId(const base::string16 & id,wchar_t * sid,ULONG length)457 HRESULT GetSidFromId(const base::string16& id, wchar_t* sid, ULONG length) {
458 return GetSidFromKey(kUserId, id, sid, length);
459 }
460
GetIdFromSid(const wchar_t * sid,base::string16 * id)461 HRESULT GetIdFromSid(const wchar_t* sid, base::string16* id) {
462 DCHECK(id);
463
464 base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kGcpUsersRootKeyName);
465 for (; iter.Valid(); ++iter) {
466 const wchar_t* user_sid = iter.Name();
467
468 if (wcscmp(sid, user_sid) == 0) {
469 wchar_t user_id[256];
470 ULONG user_length = base::size(user_id);
471 HRESULT hr = GetUserProperty(user_sid, kUserId, user_id, &user_length);
472 if (SUCCEEDED(hr)) {
473 *id = user_id;
474 return S_OK;
475 }
476 }
477 }
478 return HRESULT_FROM_WIN32(ERROR_NONE_MAPPED);
479 }
480
GetUserEmailFromSid(const base::string16 & sid)481 std::string GetUserEmailFromSid(const base::string16& sid) {
482 wchar_t email_id[512];
483 ULONG email_id_size = base::size(email_id);
484 HRESULT hr = GetUserProperty(sid, kUserEmail, email_id, &email_id_size);
485
486 base::string16 email_id_str;
487 if (SUCCEEDED(hr) && email_id_size > 0)
488 email_id_str = base::string16(email_id, email_id_size - 1);
489
490 return base::UTF16ToUTF8(email_id_str);
491 }
492
SetUserWinlogonUserListEntry(const base::string16 & username,DWORD visible)493 HRESULT SetUserWinlogonUserListEntry(const base::string16& username,
494 DWORD visible) {
495 // Sets the value of the key that will hide the user from all credential
496 // providers.
497 base::win::RegKey key;
498 LONG sts = key.Create(HKEY_LOCAL_MACHINE, kWinlogonUserListRegKey, KEY_WRITE);
499 if (sts != ERROR_SUCCESS)
500 return HRESULT_FROM_WIN32(sts);
501
502 // The key is only set if we want to make a user invisible. The default
503 // behavior is for the user to be visible so delete the key in this case.
504 if (!visible) {
505 sts = key.WriteValue(username.c_str(), visible);
506 } else {
507 sts = key.DeleteValue(username.c_str());
508 if (sts == ERROR_FILE_NOT_FOUND)
509 sts = ERROR_SUCCESS;
510 }
511
512 if (sts != ERROR_SUCCESS)
513 return HRESULT_FROM_WIN32(sts);
514
515 return S_OK;
516 }
517
SetLogonUiUserTileEntry(const base::string16 & sid,CLSID cp_guid)518 HRESULT SetLogonUiUserTileEntry(const base::string16& sid, CLSID cp_guid) {
519 return SetMachineRegString(kLogonUiUserTileRegKey, sid,
520 base::win::WStringFromGUID(cp_guid));
521 }
522
GetMachineGuid(base::string16 * machine_guid)523 HRESULT GetMachineGuid(base::string16* machine_guid) {
524 // The machine guid is a unique identifier assigned to a computer on every
525 // install of Windows. This guid can be used to uniquely identify this device
526 // to various management services. The same guid is used to identify the
527 // device to Chrome Browser Cloud Management. It is fetched in this file:
528 // chrome/browser/policy/browser_dm_token_storage_win.cc:InitClientId.
529 DCHECK(machine_guid);
530 wchar_t machine_guid_buffer[64];
531 ULONG guid_length = base::size(machine_guid_buffer);
532 HRESULT hr = GetMachineRegString(kMicrosoftCryptographyRegKey,
533 kMicrosoftCryptographyMachineGuidRegKey,
534 machine_guid_buffer, &guid_length);
535
536 if (SUCCEEDED(hr))
537 *machine_guid = machine_guid_buffer;
538
539 return hr;
540 }
541
SetMachineGuidForTesting(const base::string16 & machine_guid)542 HRESULT SetMachineGuidForTesting(const base::string16& machine_guid) {
543 // Set a debug guid for the machine so that unit tests that override the
544 // registry can run properly.
545 return SetMachineRegString(kMicrosoftCryptographyRegKey,
546 kMicrosoftCryptographyMachineGuidRegKey,
547 machine_guid);
548 }
549
GetUserDeviceResourceId(const base::string16 & sid)550 base::string16 GetUserDeviceResourceId(const base::string16& sid) {
551 wchar_t known_resource_id[512];
552 ULONG known_resource_id_size = base::size(known_resource_id);
553 HRESULT hr = GetUserProperty(sid, kRegUserDeviceResourceId, known_resource_id,
554 &known_resource_id_size);
555
556 if (SUCCEEDED(hr) && known_resource_id_size > 0)
557 return base::string16(known_resource_id, known_resource_id_size - 1);
558
559 return base::string16();
560 }
561
GetDmToken(std::string * dm_token)562 HRESULT GetDmToken(std::string* dm_token) {
563 DCHECK(dm_token);
564
565 std::string binary_dm_token;
566 HRESULT hr =
567 GetMachineRegBinaryInternal(kEnrollmentRegKey, kDmTokenRegKey,
568 &binary_dm_token, KEY_READ | KEY_WOW64_32KEY);
569 if (SUCCEEDED(hr)) {
570 base::Base64Encode(binary_dm_token, dm_token);
571 }
572 return hr;
573 }
574
SetDmTokenForTesting(const std::string & dm_token)575 HRESULT SetDmTokenForTesting(const std::string& dm_token) {
576 // Set a debug dm token for the machine so that unit tests that override the
577 // registry can run properly.
578 return SetMachineRegBinaryInternal(kEnrollmentRegKey, kDmTokenRegKey,
579 dm_token, KEY_WRITE | KEY_WOW64_32KEY);
580 }
581
582 } // namespace credential_provider
583