summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-05 13:54:26 +0000
committermnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-05 13:54:26 +0000
commit3aa28927e31f361df119d575786a76e0de1e8d6d (patch)
treef9421a0d8391a6cfc9bd5c5285faaf0798d73b6f
parentfcbc06225ab8ec42ebec6c124e75021e2013deab (diff)
downloadchromium_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
-rw-r--r--chrome/browser/chromeos/login/enrollment/enrollment_screen.cc2
-rw-r--r--chrome/browser/chromeos/login/existing_user_controller.cc2
-rw-r--r--chrome/browser/chromeos/login/login_performer.cc32
-rw-r--r--chrome/browser/chromeos/login/login_performer.h13
-rw-r--r--chrome/browser/chromeos/login/login_utils.cc6
-rw-r--r--chrome/browser/chromeos/login/login_utils.h7
-rw-r--r--chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc2
-rw-r--r--chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc34
-rw-r--r--chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h11
-rw-r--r--chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc2
-rw-r--r--chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.cc10
-rw-r--r--chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc11
-rw-r--r--chrome/browser/chromeos/policy/wildcard_login_checker.cc88
-rw-r--r--chrome/browser/chromeos/policy/wildcard_login_checker.h67
-rw-r--r--chrome/browser/chromeos/settings/cros_settings.cc23
-rw-r--r--chrome/browser/chromeos/settings/cros_settings.h7
-rw-r--r--chrome/browser/chromeos/settings/cros_settings_unittest.cc42
-rw-r--r--chrome/browser/ui/webui/options/chromeos/accounts_options_handler.cc2
-rw-r--r--chrome/chrome_browser_chromeos.gypi2
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',