1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// windows.h must be first otherwise Win8 SDK breaks. 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <windows.h> 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <LM.h> 803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <wincred.h> 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SECURITY_WIN32 must be defined in order to get 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// EXTENDED_NAME_FORMAT enumeration. 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#define SECURITY_WIN32 1 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <security.h> 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#undef SECURITY_WIN32 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/password_manager/password_manager_util.h" 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/prefs/pref_service.h" 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/time/time.h" 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/win/windows_version.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/browser_process.h" 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/chromium_strings.h" 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/password_manager/core/browser/password_manager.h" 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/password_manager/core/common/password_manager_pref_names.h" 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h" 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_AURA) 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/aura/window.h" 3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/window_tree_host.h" 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static 37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid password_manager::PasswordManager::RegisterLocalPrefs( 38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PrefRegistrySimple* registry) { 39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch registry->RegisterInt64Pref(password_manager::prefs::kOsPasswordLastChanged, 40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 0); 41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch registry->RegisterBooleanPref(password_manager::prefs::kOsPasswordBlank, 42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch false); 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace password_manager_util { 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const unsigned kMaxPasswordRetries = 3; 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const unsigned kCredUiDefaultFlags = 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CREDUI_FLAGS_GENERIC_CREDENTIALS | 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CREDUI_FLAGS_EXCLUDE_CERTIFICATES | 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CREDUI_FLAGS_KEEP_USERNAME | 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CREDUI_FLAGS_ALWAYS_SHOW_UI | 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CREDUI_FLAGS_DO_NOT_PERSIST; 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static int64 GetPasswordLastChanged(WCHAR* username) { 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LPUSER_INFO_1 user_info = NULL; 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DWORD age = 0; 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NET_API_STATUS ret = NetUserGetInfo(NULL, username, 1, (LPBYTE*) &user_info); 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (ret == NERR_Success) { 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Returns seconds since last password change. 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) age = user_info->usri1_password_age; 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NetApiBufferFree(user_info); 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return -1; 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Time changed = base::Time::Now() - base::TimeDelta::FromSeconds(age); 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return changed.ToInternalValue(); 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static bool CheckBlankPassword(WCHAR* username) { 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 last_changed = GetPasswordLastChanged(username); 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool need_recheck = true; 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool blank_password = false; 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If we cannot determine when the password was last changed 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // then assume the password is not blank 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (last_changed == -1) 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch blank_password = 87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch local_state->GetBoolean(password_manager::prefs::kOsPasswordBlank); 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 pref_last_changed = 89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch local_state->GetInt64(password_manager::prefs::kOsPasswordLastChanged); 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (pref_last_changed > 0 && last_changed <= pref_last_changed) { 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) need_recheck = false; 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (need_recheck) { 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HANDLE handle = INVALID_HANDLE_VALUE; 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Attempt to login using blank password. 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DWORD logon_result = LogonUser(username, 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) L".", 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) L"", 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOGON32_LOGON_NETWORK, 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOGON32_PROVIDER_DEFAULT, 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &handle); 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Win XP and later return ERROR_ACCOUNT_RESTRICTION for blank password. 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (logon_result) 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CloseHandle(handle); 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // In the case the password is blank, then LogonUser returns a failure, 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // handle is INVALID_HANDLE_VALUE, and GetLastError() is 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // ERROR_ACCOUNT_RESTRICTION. 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // http://msdn.microsoft.com/en-us/library/windows/desktop/ms681385 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) blank_password = (logon_result || 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetLastError() == ERROR_ACCOUNT_RESTRICTION); 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Account for clock skew between pulling the password age and 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // writing to the preferences by adding a small skew factor here. 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) last_changed += base::Time::kMicrosecondsPerSecond; 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Save the blank password status for later. 122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch local_state->SetBoolean(password_manager::prefs::kOsPasswordBlank, 123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch blank_password); 124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch local_state->SetInt64(password_manager::prefs::kOsPasswordLastChanged, 125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch last_changed); 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return blank_password; 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)OsPasswordStatus GetOsPasswordStatus() { 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD username_length = CREDUI_MAX_USERNAME_LENGTH; 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WCHAR username[CREDUI_MAX_USERNAME_LENGTH+1] = {}; 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OsPasswordStatus retVal = PASSWORD_STATUS_UNKNOWN; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (GetUserNameEx(NameUserPrincipal, username, &username_length)) { 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If we are on a domain, it is almost certain that the password is not 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // blank, but we do not actively check any further than this to avoid any 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // failed login attempts hitting the domain controller. 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) retVal = PASSWORD_STATUS_WIN_DOMAIN; 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) username_length = CREDUI_MAX_USERNAME_LENGTH; 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (GetUserName(username, &username_length)) { 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) retVal = CheckBlankPassword(username) ? PASSWORD_STATUS_BLANK : 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PASSWORD_STATUS_NONBLANK; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return retVal; 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool AuthenticateUser(gfx::NativeWindow window) { 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool retval = false; 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CREDUI_INFO cui = {}; 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WCHAR username[CREDUI_MAX_USERNAME_LENGTH+1] = {}; 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WCHAR displayname[CREDUI_MAX_USERNAME_LENGTH+1] = {}; 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WCHAR password[CREDUI_MAX_PASSWORD_LENGTH+1] = {}; 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DWORD username_length = CREDUI_MAX_USERNAME_LENGTH; 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::string16 password_prompt = 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_AUTHENTICATION_PROMPT); 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HANDLE handle = INVALID_HANDLE_VALUE; 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int tries = 0; 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool use_displayname = false; 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool use_principalname = false; 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DWORD logon_result = 0; 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Disable password manager reauthentication before Windows 7. 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // This is because of an interaction between LogonUser() and the sandbox. 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // http://crbug.com/345916 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_WIN7) 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // On a domain, we obtain the User Principal Name 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // for domain authentication. 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (GetUserNameEx(NameUserPrincipal, username, &username_length)) { 176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) use_principalname = true; 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) username_length = CREDUI_MAX_USERNAME_LENGTH; 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Otherwise, we're a workstation, use the plain local username. 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!GetUserName(username, &username_length)) { 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DLOG(ERROR) << "Unable to obtain username " << GetLastError(); 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // As we are on a workstation, it's possible the user 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // has no password, so check here. 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (CheckBlankPassword(username)) 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Try and obtain a friendly display name. 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) username_length = CREDUI_MAX_USERNAME_LENGTH; 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (GetUserNameEx(NameDisplay, displayname, &username_length)) 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) use_displayname = true; 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cui.cbSize = sizeof(CREDUI_INFO); 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cui.hwndParent = NULL; 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_AURA) 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) cui.hwndParent = window->GetHost()->GetAcceleratedWidget(); 200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#else 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cui.hwndParent = window; 202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cui.pszMessageText = password_prompt.c_str(); 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cui.pszCaptionText = product_name.c_str(); 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cui.hbmBanner = NULL; 208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BOOL save_password = FALSE; 209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DWORD credErr = NO_ERROR; 210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) do { 212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tries++; 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(wfh) Make sure we support smart cards here. 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) credErr = CredUIPromptForCredentials( 216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &cui, 217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) product_name.c_str(), 218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NULL, 219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 0, 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) use_displayname ? displayname : username, 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CREDUI_MAX_USERNAME_LENGTH+1, 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) password, 223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CREDUI_MAX_PASSWORD_LENGTH+1, 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &save_password, 225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kCredUiDefaultFlags | 226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (tries > 1 ? CREDUI_FLAGS_INCORRECT_PASSWORD : 0)); 227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (credErr == NO_ERROR) { 229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) logon_result = LogonUser(username, 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) use_principalname ? NULL : L".", 231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) password, 232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOGON32_LOGON_NETWORK, 233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOGON32_PROVIDER_DEFAULT, 234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &handle); 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (logon_result) { 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) retval = true; 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CloseHandle(handle); 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (GetLastError() == ERROR_ACCOUNT_RESTRICTION && 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) wcslen(password) == 0) { 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Password is blank, so permit. 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) retval = true; 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DLOG(WARNING) << "Unable to authenticate " << GetLastError(); 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SecureZeroMemory(password, sizeof(password)); 248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } while (credErr == NO_ERROR && 250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (retval == false && tries < kMaxPasswordRetries)); 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return retval; 252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace password_manager_util 255