| Index: chrome/browser/password_manager/password_manager_util_win.cc
|
| diff --git a/chrome/browser/password_manager/password_manager_util_win.cc b/chrome/browser/password_manager/password_manager_util_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9da22940b4996eff5946ae51dfff39288302a2e6
|
| --- /dev/null
|
| +++ b/chrome/browser/password_manager/password_manager_util_win.cc
|
| @@ -0,0 +1,141 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +// windows.h must be first otherwise Win8 SDK breaks.
|
| +#include <windows.h>
|
| +#include <ntsecapi.h>
|
| +#include <wincred.h>
|
| +
|
| +// SECURITY_WIN32 must be defined in order to get
|
| +// EXTENDED_NAME_FORMAT enumeration.
|
| +#define SECURITY_WIN32 1
|
| +#include <security.h>
|
| +#undef SECURITY_WIN32
|
| +
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "grit/chromium_strings.h"
|
| +#include "grit/generated_resources.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +
|
| +#define PASSWORD_MANAGER_MAX_PASSWORD_TRIES 3
|
| +
|
| +namespace password_manager_util {
|
| +
|
| +bool AuthenticateUser() {
|
| + bool retval = false;
|
| + CREDUI_INFO cui = {};
|
| + WCHAR username[CREDUI_MAX_USERNAME_LENGTH+1] = {};
|
| + WCHAR displayname[CREDUI_MAX_USERNAME_LENGTH+1] = {};
|
| + WCHAR password[CREDUI_MAX_PASSWORD_LENGTH+1] = {};
|
| + DWORD username_length = CREDUI_MAX_USERNAME_LENGTH;
|
| + std::wstring product_name =
|
| + UTF16ToWide(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
|
| + std::wstring password_prompt =
|
| + UTF16ToWide(l10n_util::GetStringUTF16(
|
| + IDS_PASSWORDS_PAGE_AUTHENTICATION_PROMPT));
|
| + HANDLE handle = INVALID_HANDLE_VALUE;
|
| + int tries = 0;
|
| + bool use_displayname = false;
|
| + bool use_principalname = false;
|
| + DWORD logon_result = 0;
|
| +
|
| + // On a domain, we obtain the User Principal Name
|
| + // for domain authentication.
|
| + if (GetUserNameEx(NameUserPrincipal, username, &username_length)) {
|
| + use_principalname = true;
|
| + } else {
|
| + username_length = CREDUI_MAX_USERNAME_LENGTH;
|
| + // Otherwise, we're a workstation, use the plain local username.
|
| + if (!GetUserName(username, &username_length)) {
|
| + DLOG(ERROR) << "Unable to obtain username " << GetLastError();
|
| + return false;
|
| + } else {
|
| + // As we are on a workstation, it's possible the user
|
| + // has no password, so check here.
|
| + logon_result = LogonUser(username,
|
| + L".",
|
| + L"",
|
| + LOGON32_LOGON_NETWORK,
|
| + LOGON32_PROVIDER_DEFAULT,
|
| + &handle);
|
| + // Windows XP and above return ERROR_ACCOUNT_RESTRICTION for
|
| + // when the password is blank, so check for that here.
|
| + // See http://support.microsoft.com/kb/303846.
|
| + if (logon_result || GetLastError() == ERROR_ACCOUNT_RESTRICTION) {
|
| + SecureZeroMemory(username, sizeof(username));
|
| + if (logon_result)
|
| + CloseHandle(handle);
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Try and obtain a friendly display name.
|
| + username_length = CREDUI_MAX_USERNAME_LENGTH;
|
| + if (GetUserNameEx(NameDisplay, displayname, &username_length)) {
|
| + use_displayname = true;
|
| + }
|
| +
|
| + cui.cbSize = sizeof(CREDUI_INFO);
|
| + cui.hwndParent = NULL;
|
| + cui.pszMessageText = password_prompt.c_str();
|
| + cui.pszCaptionText = product_name.c_str();
|
| +
|
| + cui.hbmBanner = NULL;
|
| + BOOL save_password = FALSE;
|
| + DWORD credErr = NO_ERROR;
|
| + DWORD flags = CREDUI_FLAGS_GENERIC_CREDENTIALS |
|
| + CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
|
| + CREDUI_FLAGS_KEEP_USERNAME |
|
| + CREDUI_FLAGS_ALWAYS_SHOW_UI |
|
| + CREDUI_FLAGS_DO_NOT_PERSIST;
|
| +
|
| + do {
|
| + SecureZeroMemory(password, sizeof(password));
|
| + tries++;
|
| +
|
| + // TODO(wfh) Make sure we support smart cards here.
|
| + credErr = CredUIPromptForCredentials(
|
| + &cui,
|
| + product_name.c_str(),
|
| + NULL,
|
| + 0,
|
| + use_displayname ? displayname : username,
|
| + CREDUI_MAX_USERNAME_LENGTH+1,
|
| + password,
|
| + CREDUI_MAX_PASSWORD_LENGTH+1,
|
| + &save_password,
|
| + flags | (tries > 1 ? CREDUI_FLAGS_INCORRECT_PASSWORD : 0));
|
| +
|
| + if (credErr == NO_ERROR) {
|
| + logon_result = LogonUser(username,
|
| + use_principalname ? NULL : L".",
|
| + password,
|
| + LOGON32_LOGON_NETWORK,
|
| + LOGON32_PROVIDER_DEFAULT,
|
| + &handle);
|
| + if (logon_result) {
|
| + retval = true;
|
| + CloseHandle(handle);
|
| + } else {
|
| + if (GetLastError() == ERROR_ACCOUNT_RESTRICTION &&
|
| + wcslen(password) == 0) {
|
| + // Password is blank, so permit.
|
| + retval = true;
|
| + } else {
|
| + DLOG(WARNING) << "Unable to authenticate " << GetLastError();
|
| + }
|
| + }
|
| + }
|
| + } while (credErr == NO_ERROR &&
|
| + (retval == false && tries < PASSWORD_MANAGER_MAX_PASSWORD_TRIES));
|
| +
|
| + SecureZeroMemory(displayname, sizeof(displayname));
|
| + SecureZeroMemory(username, sizeof(username));
|
| + SecureZeroMemory(password, sizeof(password));
|
| +
|
| + return retval;
|
| +}
|
| +
|
| +} // namespace password_manager_util
|
|
|