diff options
author | mnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-05 13:54:26 +0000 |
---|---|---|
committer | mnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-05 13:54:26 +0000 |
commit | 3aa28927e31f361df119d575786a76e0de1e8d6d (patch) | |
tree | f9421a0d8391a6cfc9bd5c5285faaf0798d73b6f | |
parent | fcbc06225ab8ec42ebec6c124e75021e2013deab (diff) | |
download | chromium_src-3aa28927e31f361df119d575786a76e0de1e8d6d.zip chromium_src-3aa28927e31f361df119d575786a76e0de1e8d6d.tar.gz chromium_src-3aa28927e31f361df119d575786a76e0de1e8d6d.tar.bz2 |
Merge r247829 - Make an online wildcard login check for enterprise devices.
This checks with GAIA to reconfirm whether a given user is permitted
to log in to a device. The check complements the existing login
whitelist check based on device policy.
BUG=chromium:336284
TEST=Manual
TBR=mnissler@chromium.org
Review URL: https://codereview.chromium.org/155833002
git-svn-id: svn://svn.chromium.org/chrome/branches/1750/src@248985 0039d316-1c4b-4281-b951-d872f2087c98
19 files changed, 316 insertions, 47 deletions
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc index 78c373ad..7a32e68 100644 --- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc +++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc @@ -176,7 +176,7 @@ void EnrollmentScreen::OnConfirmationClosed() { if (is_auto_enrollment_ && !enrollment_failed_once_ && !user_.empty() && - LoginUtils::IsWhitelisted(user_)) { + LoginUtils::IsWhitelisted(user_, NULL)) { actor_->ShowLoginSpinnerScreen(); get_screen_observer()->OnExit( ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED); diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index 80c26f1..9e115fa 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -196,7 +196,7 @@ void ExistingUserController::UpdateLoginDisplay(const UserList& users) { (*it)->GetType() != User::USER_TYPE_LOCALLY_MANAGED || UserManager::Get()->AreLocallyManagedUsersAllowed(); bool meets_whitelist_requirements = - LoginUtils::IsWhitelisted((*it)->email()) || + LoginUtils::IsWhitelisted((*it)->email(), NULL) || (*it)->GetType() != User::USER_TYPE_REGULAR; if (meets_locally_managed_requirements && meets_whitelist_requirements) { filtered_users.push_back(*it); diff --git a/chrome/browser/chromeos/login/login_performer.cc b/chrome/browser/chromeos/login/login_performer.cc index 365704f..29579a7 100644 --- a/chrome/browser/chromeos/login/login_performer.cc +++ b/chrome/browser/chromeos/login/login_performer.cc @@ -20,6 +20,7 @@ #include "chrome/browser/chromeos/login/managed/locally_managed_user_login_flow.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" +#include "chrome/browser/chromeos/policy/wildcard_login_checker.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/policy/browser_policy_connector.h" @@ -160,13 +161,27 @@ void LoginPerformer::PerformLogin(const UserContext& user_context, return; } - bool is_whitelisted = LoginUtils::IsWhitelisted( - gaia::CanonicalizeEmail(user_context.username)); + bool wildcard_match = false; + std::string email = gaia::CanonicalizeEmail(user_context.username); + bool is_whitelisted = LoginUtils::IsWhitelisted(email, &wildcard_match); if (is_whitelisted) { switch (auth_mode_) { - case AUTH_MODE_EXTENSION: - StartLoginCompletion(); + case AUTH_MODE_EXTENSION: { + // On enterprise devices, reconfirm login permission with the server. + policy::BrowserPolicyConnector* connector = + g_browser_process->browser_policy_connector(); + if (connector->IsEnterpriseManaged() && wildcard_match && + !connector->IsNonEnterpriseUser(email)) { + wildcard_login_checker_.reset(new policy::WildcardLoginChecker()); + wildcard_login_checker_->Start( + ProfileHelper::GetSigninProfile()->GetRequestContext(), + base::Bind(&LoginPerformer::OnlineWildcardLoginCheckCompleted, + weak_factory_.GetWeakPtr())); + } else { + StartLoginCompletion(); + } break; + } case AUTH_MODE_INTERNAL: StartAuthentication(); break; @@ -316,4 +331,13 @@ void LoginPerformer::StartAuthentication() { user_context_.auth_code.clear(); } +void LoginPerformer::OnlineWildcardLoginCheckCompleted(bool result) { + if (result) { + StartLoginCompletion(); + } else { + if (delegate_) + delegate_->WhiteListCheckFailed(user_context_.username); + } +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/login/login_performer.h b/chrome/browser/chromeos/login/login_performer.h index 379a458..d4ec7d8 100644 --- a/chrome/browser/chromeos/login/login_performer.h +++ b/chrome/browser/chromeos/login/login_performer.h @@ -8,6 +8,7 @@ #include <string> #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/chromeos/login/authenticator.h" #include "chrome/browser/chromeos/login/login_status_consumer.h" @@ -18,6 +19,10 @@ #include "content/public/browser/notification_registrar.h" #include "google_apis/gaia/google_service_auth_error.h" +namespace policy { +class WildcardLoginChecker; +} + namespace chromeos { // This class encapsulates sign in operations. @@ -117,6 +122,11 @@ class LoginPerformer : public LoginStatusConsumer, // Starts authentication. void StartAuthentication(); + // Completion callback for the online wildcard login check for enterprise + // devices. Continues the login process or signals whitelist check failure + // depending on the value of |result|. + void OnlineWildcardLoginCheckCompleted(bool result); + // Used for logging in. scoped_refptr<Authenticator> authenticator_; @@ -141,6 +151,9 @@ class LoginPerformer : public LoginStatusConsumer, // Authorization mode type. AuthorizationMode auth_mode_; + // Used to verify logins that matched wildcard on the login whitelist. + scoped_ptr<policy::WildcardLoginChecker> wildcard_login_checker_; + base::WeakPtrFactory<LoginPerformer> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LoginPerformer); diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc index 3a6bb91..2b6ed3dd 100644 --- a/chrome/browser/chromeos/login/login_utils.cc +++ b/chrome/browser/chromeos/login/login_utils.cc @@ -855,7 +855,8 @@ void LoginUtils::Set(LoginUtils* mock) { } // static -bool LoginUtils::IsWhitelisted(const std::string& username) { +bool LoginUtils::IsWhitelisted(const std::string& username, + bool* wildcard_match) { // Skip whitelist check for tests. if (CommandLine::ForCurrentProcess()->HasSwitch( chromeos::switches::kOobeSkipPostLogin)) { @@ -867,7 +868,8 @@ bool LoginUtils::IsWhitelisted(const std::string& username) { cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user); if (allow_new_user) return true; - return cros_settings->FindEmailInList(kAccountsPrefUsers, username); + return cros_settings->FindEmailInList( + kAccountsPrefUsers, username, wildcard_match); } } // namespace chromeos diff --git a/chrome/browser/chromeos/login/login_utils.h b/chrome/browser/chromeos/login/login_utils.h index 0e64383..75d87ab 100644 --- a/chrome/browser/chromeos/login/login_utils.h +++ b/chrome/browser/chromeos/login/login_utils.h @@ -11,9 +11,9 @@ class CommandLine; class GURL; -class Profile; class PrefRegistrySimple; class PrefService; +class Profile; namespace chromeos { @@ -48,8 +48,9 @@ class LoginUtils { static void Set(LoginUtils* ptr); // Checks if the given username is whitelisted and allowed to sign-in to - // this device. - static bool IsWhitelisted(const std::string& username); + // this device. |wildcard_match| may be NULL. If it's present, it'll be set to + // true if the whitelist check was satisfied via a wildcard. + static bool IsWhitelisted(const std::string& username, bool* wildcard_match); virtual ~LoginUtils() {} diff --git a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc index 37d9532..e6bda14 100644 --- a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc +++ b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc @@ -57,6 +57,8 @@ void PolicyOAuth2TokenFetcher::StartFetchingRefreshToken() { void PolicyOAuth2TokenFetcher::StartFetchingAccessToken() { std::vector<std::string> scopes; scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth); + scopes.push_back( + GaiaUrls::GetInstance()->oauth_wrap_bridge_user_info_scope()); access_token_fetcher_.reset( new OAuth2AccessTokenFetcher(this, system_context_getter_.get())); access_token_fetcher_->Start( diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc index 385d998..29b4391 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc @@ -13,7 +13,9 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h" #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" +#include "chrome/browser/chromeos/policy/wildcard_login_checker.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/lifetime/application_lifetime.h" #include "components/policy/core/common/cloud/cloud_external_data_manager.h" #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" #include "components/policy/core/common/cloud/device_management_service.h" @@ -47,6 +49,20 @@ const char kUMAInitialFetchOAuth2Error[] = const char kUMAInitialFetchOAuth2NetworkError[] = "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError"; +void OnWildcardCheckCompleted(const std::string& username, bool result) { + if (!result) { + LOG(ERROR) << "Online wildcard login check failed, terminating session."; + + // TODO(mnissler): This only removes the user pod from the login screen, but + // the cryptohome remains. This is because deleting the cryptohome for a + // logged-in session is not possible. Fix this either by delaying the + // cryptohome deletion operation or by getting rid of the in-session + // wildcard check. + chromeos::UserManager::Get()->RemoveUserFromList(username); + chrome::AttemptUserExit(); + } +} + } // namespace UserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS( @@ -125,6 +141,14 @@ void UserCloudPolicyManagerChromeOS::Connect( void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable( const std::string& access_token) { access_token_ = access_token; + + if (!wildcard_username_.empty()) { + wildcard_login_checker_.reset(new WildcardLoginChecker()); + wildcard_login_checker_->StartWithAccessToken( + access_token, + base::Bind(&OnWildcardCheckCompleted, wildcard_username_)); + } + if (service() && service()->IsInitializationComplete() && client() && !client()->is_registered()) { OnOAuth2PolicyTokenFetched( @@ -136,6 +160,12 @@ bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const { return client() && client()->is_registered(); } +void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck( + const std::string& username) { + DCHECK(access_token_.empty()); + wildcard_username_ = username; +} + void UserCloudPolicyManagerChromeOS::Shutdown() { if (client()) client()->RemoveObserver(this); @@ -181,8 +211,7 @@ void UserCloudPolicyManagerChromeOS::OnInitializationCompleted( if (wait_for_policy_fetch_) { FetchPolicyOAuthTokenUsingSigninProfile(); } else if (!access_token_.empty()) { - OnOAuth2PolicyTokenFetched( - access_token_, GoogleServiceAuthError(GoogleServiceAuthError::NONE)); + OnAccessTokenAvailable(access_token_); } } @@ -266,7 +295,6 @@ void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched( const std::string& policy_token, const GoogleServiceAuthError& error) { DCHECK(!client()->is_registered()); - time_token_available_ = base::Time::Now(); if (wait_for_policy_fetch_) { UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayOAuth2Token, diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h index d180a74..d2841ee 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h @@ -36,6 +36,7 @@ namespace policy { class CloudExternalDataManager; class DeviceManagementService; class PolicyOAuth2TokenFetcher; +class WildcardLoginChecker; // UserCloudPolicyManagerChromeOS implements logic for initializing user policy // on Chrome OS. @@ -85,6 +86,10 @@ class UserCloudPolicyManagerChromeOS // Returns true if the underlying CloudPolicyClient is already registered. bool IsClientRegistered() const; + // Indicates a wildcard login check should be performed once an access token + // is available. + void EnableWildcardLoginCheck(const std::string& username); + // ConfigurationPolicyProvider: virtual void Shutdown() OVERRIDE; virtual bool IsInitializationComplete(PolicyDomain domain) const OVERRIDE; @@ -128,6 +133,9 @@ class UserCloudPolicyManagerChromeOS // Manages external data referenced by policies. scoped_ptr<CloudExternalDataManager> external_data_manager_; + // Username for the wildcard login check if applicable, empty otherwise. + std::string wildcard_username_; + // Path where policy for components will be cached. base::FilePath component_policy_cache_path_; @@ -146,6 +154,9 @@ class UserCloudPolicyManagerChromeOS // a callback with an unretained reference to the manager, when it exists. scoped_ptr<PolicyOAuth2TokenFetcher> token_fetcher_; + // Keeps alive the wildcard checker while its running. + scoped_ptr<WildcardLoginChecker> wildcard_login_checker_; + // The access token passed to OnAccessTokenAvailable. It is stored here so // that it can be used if OnInitializationCompleted is called later. std::string access_token_; diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc index 393a05c..106a8ad 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc @@ -250,6 +250,8 @@ class UserCloudPolicyManagerChromeOSTest : public testing::Test { EXPECT_TRUE(token_service); OAuth2TokenService::ScopeSet scopes; scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); + scopes.insert( + GaiaUrls::GetInstance()->oauth_wrap_bridge_user_info_scope()); token_service->IssueTokenForScope( scopes, "5678", base::Time::Now() + base::TimeDelta::FromSeconds(3600)); diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.cc index 3e3f531..fa68af9 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.cc @@ -15,6 +15,7 @@ #include "base/threading/sequenced_worker_pool.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/chromeos/login/user.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/policy/user_cloud_external_data_manager.h" @@ -199,6 +200,15 @@ scoped_ptr<UserCloudPolicyManagerChromeOS> base::MessageLoopProxy::current(), file_task_runner, io_task_runner)); + + bool wildcard_match = false; + if (connector->IsEnterpriseManaged() && + chromeos::LoginUtils::IsWhitelisted(username, &wildcard_match) && + wildcard_match && + !connector->IsNonEnterpriseUser(username)) { + manager->EnableWildcardLoginCheck(username); + } + manager->Init(SchemaRegistryServiceFactory::GetForContext(profile)); manager->Connect(g_browser_process->local_state(), device_management_service, diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc index 455cdaf..963b4eb 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc @@ -10,6 +10,7 @@ #include "components/policy/core/common/cloud/cloud_policy_core.h" #include "content/public/browser/notification_source.h" #include "google_apis/gaia/gaia_constants.h" +#include "google_apis/gaia/gaia_urls.h" namespace policy { @@ -72,12 +73,9 @@ void UserCloudPolicyTokenForwarder::OnInitializationCompleted( } void UserCloudPolicyTokenForwarder::Initialize() { - if (manager_->IsClientRegistered()) { - // We already have a DMToken, so no need to ask for an access token. - // All done here. - Shutdown(); - return; - } + // TODO(mnissler): Once a better way to reconfirm whether a user is on the + // login whitelist is available, there is no reason to fetch the OAuth2 token + // here if the client is already registered, so check and bail out here. if (token_service_->RefreshTokenIsAvailable( token_service_->GetPrimaryAccountId())) @@ -89,6 +87,7 @@ void UserCloudPolicyTokenForwarder::Initialize() { void UserCloudPolicyTokenForwarder::RequestAccessToken() { OAuth2TokenService::ScopeSet scopes; scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); + scopes.insert(GaiaUrls::GetInstance()->oauth_wrap_bridge_user_info_scope()); request_ = token_service_->StartRequest( token_service_->GetPrimaryAccountId(), scopes, this); } diff --git a/chrome/browser/chromeos/policy/wildcard_login_checker.cc b/chrome/browser/chromeos/policy/wildcard_login_checker.cc new file mode 100644 index 0000000..6f127da --- /dev/null +++ b/chrome/browser/chromeos/policy/wildcard_login_checker.cc @@ -0,0 +1,88 @@ +// Copyright (c) 2014 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. + +#include "chrome/browser/chromeos/policy/wildcard_login_checker.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h" +#include "chrome/browser/policy/browser_policy_connector.h" +#include "net/url_request/url_request_context_getter.h" + +namespace policy { + +namespace { + +// Presence of this key in the userinfo response indicates whether the user is +// on a hosted domain. +const char kHostedDomainKey[] = "hd"; + +} // namespace + +WildcardLoginChecker::WildcardLoginChecker() {} + +WildcardLoginChecker::~WildcardLoginChecker() {} + +void WildcardLoginChecker::Start( + scoped_refptr<net::URLRequestContextGetter> signin_context, + const StatusCallback& callback) { + CHECK(!token_fetcher_); + CHECK(!user_info_fetcher_); + callback_ = callback; + token_fetcher_.reset(new PolicyOAuth2TokenFetcher( + signin_context, + g_browser_process->system_request_context(), + base::Bind(&WildcardLoginChecker::OnPolicyTokenFetched, + base::Unretained(this)))); + token_fetcher_->Start(); +} + +void WildcardLoginChecker::StartWithAccessToken( + const std::string& access_token, + const StatusCallback& callback) { + CHECK(!token_fetcher_); + CHECK(!user_info_fetcher_); + callback_ = callback; + + StartUserInfoFetcher(access_token); +} + +void WildcardLoginChecker::OnGetUserInfoSuccess( + const base::DictionaryValue* response) { + OnCheckCompleted(response->HasKey(kHostedDomainKey)); +} + +void WildcardLoginChecker::OnGetUserInfoFailure( + const GoogleServiceAuthError& error) { + LOG(ERROR) << "Failed to fetch user info " << error.ToString(); + OnCheckCompleted(false); +} + +void WildcardLoginChecker::OnPolicyTokenFetched( + const std::string& access_token, + const GoogleServiceAuthError& error) { + if (error.state() != GoogleServiceAuthError::NONE) { + LOG(ERROR) << "Failed to fetch policy token " << error.ToString(); + OnCheckCompleted(false); + return; + } + + token_fetcher_.reset(); + StartUserInfoFetcher(access_token); +} + +void WildcardLoginChecker::StartUserInfoFetcher( + const std::string& access_token) { + user_info_fetcher_.reset( + new UserInfoFetcher(this, g_browser_process->system_request_context())); + user_info_fetcher_->Start(access_token); +} + +void WildcardLoginChecker::OnCheckCompleted(bool result) { + if (!callback_.is_null()) + callback_.Run(result); +} + +} // namespace policy diff --git a/chrome/browser/chromeos/policy/wildcard_login_checker.h b/chrome/browser/chromeos/policy/wildcard_login_checker.h new file mode 100644 index 0000000..496fadb --- /dev/null +++ b/chrome/browser/chromeos/policy/wildcard_login_checker.h @@ -0,0 +1,67 @@ +// Copyright (c) 2014 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. + +#ifndef CHROME_BROWSER_CHROMEOS_POLICY_WILDCARD_LOGIN_CHECKER_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_WILDCARD_LOGIN_CHECKER_H_ + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "components/policy/core/common/cloud/user_info_fetcher.h" +#include "google_apis/gaia/google_service_auth_error.h" + +namespace net { +class URLRequestContextGetter; +} + +namespace policy { + +class PolicyOAuth2TokenFetcher; + +// Performs online verification whether wildcard login is allowed, i.e. whether +// the user is a hosted user. This class performs an asynchronous check and +// reports the result via a callback. +class WildcardLoginChecker : public UserInfoFetcher::Delegate { + public: + typedef base::Callback<void(bool)> StatusCallback; + + WildcardLoginChecker(); + virtual ~WildcardLoginChecker(); + + // Starts checking. The result will be reported via |callback_|. + void Start(scoped_refptr<net::URLRequestContextGetter> signin_context, + const StatusCallback& callback); + + // Starts checking with a provided access token. + void StartWithAccessToken(const std::string& access_token, + const StatusCallback& callback); + + // UserInfoFetcher::Delegate: + virtual void OnGetUserInfoSuccess(const base::DictionaryValue* response) + OVERRIDE; + virtual void OnGetUserInfoFailure(const GoogleServiceAuthError& error) + OVERRIDE; + + private: + // Starts the check after successful token minting. + void OnPolicyTokenFetched(const std::string& access_token, + const GoogleServiceAuthError& error); + + // Starts the user info fetcher. + void StartUserInfoFetcher(const std::string& access_token); + + // Handles the response of the check and calls ReportResult(). + void OnCheckCompleted(bool result); + + StatusCallback callback_; + + scoped_ptr<PolicyOAuth2TokenFetcher> token_fetcher_; + scoped_ptr<UserInfoFetcher> user_info_fetcher_; + + DISALLOW_COPY_AND_ASSIGN(WildcardLoginChecker); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_WILDCARD_LOGIN_CHECKER_H_ diff --git a/chrome/browser/chromeos/settings/cros_settings.cc b/chrome/browser/chromeos/settings/cros_settings.cc index 382add7..61ab700 100644 --- a/chrome/browser/chromeos/settings/cros_settings.cc +++ b/chrome/browser/chromeos/settings/cros_settings.cc @@ -200,7 +200,8 @@ bool CrosSettings::GetDictionary( } bool CrosSettings::FindEmailInList(const std::string& path, - const std::string& email) const { + const std::string& email, + bool* wildcard_match) const { DCHECK(CalledOnValidThread()); std::string canonicalized_email( gaia::CanonicalizeEmail(gaia::SanitizeEmail(email))); @@ -211,9 +212,14 @@ bool CrosSettings::FindEmailInList(const std::string& path, std::string("*").append(canonicalized_email.substr(at_pos)); } + if (wildcard_match) + *wildcard_match = false; + const base::ListValue* list; if (!GetList(path, &list)) return false; + + bool found_wildcard_match = false; for (base::ListValue::const_iterator entry(list->begin()); entry != list->end(); ++entry) { @@ -225,12 +231,19 @@ bool CrosSettings::FindEmailInList(const std::string& path, std::string canonicalized_entry( gaia::CanonicalizeEmail(gaia::SanitizeEmail(entry_string))); - if (canonicalized_entry == canonicalized_email || - canonicalized_entry == wildcard_email) { + if (canonicalized_entry == canonicalized_email) return true; - } + + // If there is a wildcard match, don't exit early. There might be an exact + // match further down the list that should take precedence if present. + if (canonicalized_entry == wildcard_email) + found_wildcard_match = true; } - return false; + + if (wildcard_match) + *wildcard_match = found_wildcard_match; + + return found_wildcard_match; } bool CrosSettings::AddSettingsProvider(CrosSettingsProvider* provider) { diff --git a/chrome/browser/chromeos/settings/cros_settings.h b/chrome/browser/chromeos/settings/cros_settings.h index 2fa5e50..05db94f 100644 --- a/chrome/browser/chromeos/settings/cros_settings.h +++ b/chrome/browser/chromeos/settings/cros_settings.h @@ -86,8 +86,11 @@ class CrosSettings : public base::NonThreadSafe { // Helper function for the whitelist op. Implemented here because we will need // this in a few places. The functions searches for |email| in the pref |path| - // It respects whitelists so foo@bar.baz will match *@bar.baz too. - bool FindEmailInList(const std::string& path, const std::string& email) const; + // It respects whitelists so foo@bar.baz will match *@bar.baz too. If the + // match was via a wildcard, |wildcard_match| is set to true. + bool FindEmailInList(const std::string& path, + const std::string& email, + bool* wildcard_match) const; // Adding/removing of providers. bool AddSettingsProvider(CrosSettingsProvider* provider); diff --git a/chrome/browser/chromeos/settings/cros_settings_unittest.cc b/chrome/browser/chromeos/settings/cros_settings_unittest.cc index fd24ce8..eed35a6 100644 --- a/chrome/browser/chromeos/settings/cros_settings_unittest.cc +++ b/chrome/browser/chromeos/settings/cros_settings_unittest.cc @@ -89,6 +89,10 @@ class CrosSettingsTest : public testing::Test { response.set_policy_data_signature("false"); } + static bool IsWhitelisted(CrosSettings* cs, const std::string& username) { + return cs->FindEmailInList(kAccountsPrefUsers, username, NULL); + } + base::MessageLoop message_loop_; content::TestBrowserThread ui_thread_; @@ -231,25 +235,25 @@ TEST_F(CrosSettingsTest, FindEmailInList) { CrosSettings* cs = &settings_; cs->Set(kAccountsPrefUsers, list); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "user@example.com")); - EXPECT_FALSE(cs->FindEmailInList(kAccountsPrefUsers, "us.er@example.com")); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "USER@example.com")); - EXPECT_FALSE(cs->FindEmailInList(kAccountsPrefUsers, "user")); - - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "nodomain")); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "nodomain@gmail.com")); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "no.domain@gmail.com")); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "NO.DOMAIN")); - - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "with.dots@gmail.com")); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "withdots@gmail.com")); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "WITH.DOTS@gmail.com")); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "WITHDOTS")); - - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "Upper@example.com")); - EXPECT_FALSE(cs->FindEmailInList(kAccountsPrefUsers, "U.pper@example.com")); - EXPECT_FALSE(cs->FindEmailInList(kAccountsPrefUsers, "Upper")); - EXPECT_TRUE(cs->FindEmailInList(kAccountsPrefUsers, "upper@example.com")); + EXPECT_TRUE(IsWhitelisted(cs, "user@example.com")); + EXPECT_FALSE(IsWhitelisted(cs, "us.er@example.com")); + EXPECT_TRUE(IsWhitelisted(cs, "USER@example.com")); + EXPECT_FALSE(IsWhitelisted(cs, "user")); + + EXPECT_TRUE(IsWhitelisted(cs, "nodomain")); + EXPECT_TRUE(IsWhitelisted(cs, "nodomain@gmail.com")); + EXPECT_TRUE(IsWhitelisted(cs, "no.domain@gmail.com")); + EXPECT_TRUE(IsWhitelisted(cs, "NO.DOMAIN")); + + EXPECT_TRUE(IsWhitelisted(cs, "with.dots@gmail.com")); + EXPECT_TRUE(IsWhitelisted(cs, "withdots@gmail.com")); + EXPECT_TRUE(IsWhitelisted(cs, "WITH.DOTS@gmail.com")); + EXPECT_TRUE(IsWhitelisted(cs, "WITHDOTS")); + + EXPECT_TRUE(IsWhitelisted(cs, "Upper@example.com")); + EXPECT_FALSE(IsWhitelisted(cs, "U.pper@example.com")); + EXPECT_FALSE(IsWhitelisted(cs, "Upper")); + EXPECT_TRUE(IsWhitelisted(cs, "upper@example.com")); } } // namespace chromeos diff --git a/chrome/browser/ui/webui/options/chromeos/accounts_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/accounts_options_handler.cc index b4d4784..e65263f 100644 --- a/chrome/browser/ui/webui/options/chromeos/accounts_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/accounts_options_handler.cc @@ -32,7 +32,7 @@ namespace { // in the whitelist. bool WhitelistUser(const std::string& username) { CrosSettings* cros_settings = CrosSettings::Get(); - if (cros_settings->FindEmailInList(kAccountsPrefUsers, username)) + if (cros_settings->FindEmailInList(kAccountsPrefUsers, username, NULL)) return false; base::StringValue username_value(username); cros_settings->AppendToList(kAccountsPrefUsers, &username_value); diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index e9e6270..fab7f80 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -759,6 +759,8 @@ 'browser/chromeos/policy/user_policy_disk_cache.h', 'browser/chromeos/policy/user_policy_token_loader.cc', 'browser/chromeos/policy/user_policy_token_loader.h', + 'browser/chromeos/policy/wildcard_login_checker.cc', + 'browser/chromeos/policy/wildcard_login_checker.h', 'browser/chromeos/power/idle_action_warning_dialog_view.cc', 'browser/chromeos/power/idle_action_warning_dialog_view.h', 'browser/chromeos/power/idle_action_warning_observer.cc', |