blob: d6547785c845b57c9e496b57a2113fcc77d5e313 [file] [log] [blame]
// Copyright 2017 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 <string>
#include "ash/public/cpp/ash_switches.h"
#include "base/base_paths.h"
#include "base/environment.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/authpolicy/kerberos_files_handler.h"
#include "chrome/browser/chromeos/login/test/active_directory_login_mixin.h"
#include "chrome/browser/chromeos/login/test/device_state_mixin.h"
#include "chrome/browser/chromeos/login/test/oobe_base_test.h"
#include "chrome/browser/chromeos/login/test/session_manager_state_waiter.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h"
#include "components/user_manager/user_names.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/network_service_util.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
namespace chromeos {
namespace {
constexpr char kTestActiveDirectoryUser[] = "test-user";
constexpr char kTestUserRealm[] = "user.realm";
constexpr char kPassword[] = "password";
constexpr char kNewPassword[] = "new_password";
constexpr char kDifferentNewPassword[] = "different_new_password";
void AssertNetworkServiceEnvEquals(const std::string& name,
const std::string& expected_value) {
std::string value;
if (content::IsOutOfProcessNetworkService()) {
mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
content::GetNetworkService()->BindTestInterface(
network_service_test.BindNewPipeAndPassReceiver());
mojo::ScopedAllowSyncCallForTesting allow_sync_call;
network_service_test->GetEnvironmentVariableValue(name, &value);
} else {
// If the network service is running in-process, we can read the
// environment variable directly.
base::Environment::Create()->GetVar(name, &value);
}
EXPECT_EQ(value, expected_value);
}
class ActiveDirectoryLoginTest : public OobeBaseTest {
public:
ActiveDirectoryLoginTest()
: OobeBaseTest(),
// Using the same realm as supervised user domain. Should be treated
// as normal realm.
test_realm_(user_manager::kSupervisedUserDomain),
test_user_(kTestActiveDirectoryUser + ("@" + test_realm_)) {}
~ActiveDirectoryLoginTest() override = default;
protected:
FakeAuthPolicyClient* fake_auth_policy_client() {
return FakeAuthPolicyClient::Get();
}
const std::string test_realm_;
const std::string test_user_;
DeviceStateMixin device_state_{
&mixin_host_,
DeviceStateMixin::State::OOBE_COMPLETED_ACTIVE_DIRECTORY_ENROLLED};
ActiveDirectoryLoginMixin ad_login_{&mixin_host_};
private:
DISALLOW_COPY_AND_ASSIGN(ActiveDirectoryLoginTest);
};
class ActiveDirectoryLoginAutocompleteTest : public ActiveDirectoryLoginTest {
public:
ActiveDirectoryLoginAutocompleteTest() = default;
void SetUpInProcessBrowserTestFixture() override {
ActiveDirectoryLoginTest::SetUpInProcessBrowserTestFixture();
enterprise_management::ChromeDeviceSettingsProto device_settings;
device_settings.mutable_login_screen_domain_auto_complete()
->set_login_screen_domain_auto_complete(kTestUserRealm);
fake_auth_policy_client()->set_device_policy(device_settings);
autocomplete_realm_ = "@" + std::string(kTestUserRealm);
ad_login_.set_autocomplete_realm(autocomplete_realm_);
}
std::string autocomplete_realm_;
private:
DISALLOW_COPY_AND_ASSIGN(ActiveDirectoryLoginAutocompleteTest);
};
} // namespace
// Test successful Active Directory login.
IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, LoginSuccess) {
OobeBaseTest::WaitForSigninScreen();
ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
ad_login_.TestNoError();
ad_login_.TestDomainHidden();
ad_login_.SubmitActiveDirectoryCredentials(test_user_, kPassword);
test::WaitForPrimaryUserSessionStart();
}
// Tests that the Kerberos SSO environment variables are set correctly after
// an Active Directory log in.
IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, KerberosVarsCopied) {
OobeBaseTest::WaitForSigninScreen();
ad_login_.TestNoError();
ad_login_.TestDomainHidden();
ad_login_.SubmitActiveDirectoryCredentials(test_user_, kPassword);
test::WaitForPrimaryUserSessionStart();
base::FilePath dir;
base::PathService::Get(base::DIR_HOME, &dir);
dir = dir.Append(kKrb5Directory);
std::string expected_krb5cc_value =
kKrb5CCFilePrefix + dir.Append(kKrb5CCFile).value();
AssertNetworkServiceEnvEquals(kKrb5CCEnvName, expected_krb5cc_value);
std::string expected_krb5_config_value = dir.Append(kKrb5ConfFile).value();
AssertNetworkServiceEnvEquals(kKrb5ConfEnvName, expected_krb5_config_value);
}
// Test different UI errors for Active Directory login.
IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, LoginErrors) {
OobeBaseTest::WaitForSigninScreen();
ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
ad_login_.TestNoError();
ad_login_.TestDomainHidden();
ad_login_.SubmitActiveDirectoryCredentials("", "");
ad_login_.TestUserError();
ad_login_.TestDomainHidden();
ad_login_.SubmitActiveDirectoryCredentials(test_user_, "");
ad_login_.TestPasswordError();
ad_login_.TestDomainHidden();
ad_login_.SubmitActiveDirectoryCredentials(
std::string(kTestActiveDirectoryUser) + "@", kPassword);
ad_login_.WaitForAuthError();
ad_login_.TestUserError();
ad_login_.TestDomainHidden();
fake_auth_policy_client()->set_auth_error(authpolicy::ERROR_BAD_USER_NAME);
ad_login_.SubmitActiveDirectoryCredentials(test_user_, kPassword);
ad_login_.WaitForAuthError();
ad_login_.TestUserError();
ad_login_.TestDomainHidden();
fake_auth_policy_client()->set_auth_error(authpolicy::ERROR_BAD_PASSWORD);
ad_login_.SubmitActiveDirectoryCredentials(test_user_, kPassword);
ad_login_.WaitForAuthError();
ad_login_.TestPasswordError();
ad_login_.TestDomainHidden();
fake_auth_policy_client()->set_auth_error(authpolicy::ERROR_UNKNOWN);
ad_login_.SubmitActiveDirectoryCredentials(test_user_, kPassword);
ad_login_.WaitForAuthError();
// Inputs are not invalidated for the unknown error.
ad_login_.TestNoError();
ad_login_.TestDomainHidden();
}
// Test successful Active Directory login from the password change screen.
IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, PasswordChange_LoginSuccess) {
OobeBaseTest::WaitForSigninScreen();
ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
ad_login_.TestLoginVisible();
ad_login_.TestDomainHidden();
ad_login_.TriggerPasswordChangeScreen();
// Password accepted by AuthPolicyClient.
fake_auth_policy_client()->set_auth_error(authpolicy::ERROR_NONE);
ad_login_.SubmitActiveDirectoryPasswordChangeCredentials(
kPassword, kNewPassword, kNewPassword);
test::WaitForPrimaryUserSessionStart();
}
// Test different UI errors for Active Directory password change screen.
IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, PasswordChange_UIErrors) {
OobeBaseTest::WaitForSigninScreen();
ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
ad_login_.TestLoginVisible();
ad_login_.TestDomainHidden();
ad_login_.TriggerPasswordChangeScreen();
// Password rejected by UX.
// Empty passwords.
ad_login_.SubmitActiveDirectoryPasswordChangeCredentials("", "", "");
ad_login_.TestPasswordChangeOldPasswordError();
// Empty new password.
ad_login_.SubmitActiveDirectoryPasswordChangeCredentials(kPassword, "", "");
ad_login_.TestPasswordChangeNewPasswordError();
// Empty confirmation of the new password.
ad_login_.SubmitActiveDirectoryPasswordChangeCredentials(kPassword,
kNewPassword, "");
ad_login_.TestPasswordChangeConfirmNewPasswordError();
// Confirmation of password is different from new password.
ad_login_.SubmitActiveDirectoryPasswordChangeCredentials(
kPassword, kNewPassword, kDifferentNewPassword);
ad_login_.TestPasswordChangeConfirmNewPasswordError();
// Password rejected by AuthPolicyClient.
fake_auth_policy_client()->set_auth_error(authpolicy::ERROR_BAD_PASSWORD);
ad_login_.SubmitActiveDirectoryPasswordChangeCredentials(
kPassword, kNewPassword, kNewPassword);
ad_login_.TestPasswordChangeOldPasswordError();
}
class ActiveDirectoryWebUILoginTest : public ActiveDirectoryLoginTest {
public:
ActiveDirectoryWebUILoginTest() = default;
~ActiveDirectoryWebUILoginTest() override = default;
// chromeos::ActiveDirectoryLoginTest:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(ash::switches::kShowWebUiLogin);
chromeos::ActiveDirectoryLoginTest::SetUpCommandLine(command_line);
}
private:
DISALLOW_COPY_AND_ASSIGN(ActiveDirectoryWebUILoginTest);
};
// Test reopening Active Directory password change screen clears errors.
IN_PROC_BROWSER_TEST_F(ActiveDirectoryWebUILoginTest,
PasswordChange_ReopenClearErrors) {
OobeBaseTest::WaitForSigninScreen();
ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
ad_login_.TestLoginVisible();
ad_login_.TestDomainHidden();
ad_login_.TriggerPasswordChangeScreen();
// Empty new password.
ad_login_.SubmitActiveDirectoryPasswordChangeCredentials("", "", "");
ad_login_.TestPasswordChangeOldPasswordError();
ad_login_.ClosePasswordChangeScreen();
ad_login_.TestLoginVisible();
ad_login_.TriggerPasswordChangeScreen();
ad_login_.TestPasswordChangeNoErrors();
}
// Tests that autocomplete works. Submits username without domain.
IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginAutocompleteTest, LoginSuccess) {
OobeBaseTest::WaitForSigninScreen();
ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
ad_login_.TestNoError();
ad_login_.TestDomainVisible();
ad_login_.SubmitActiveDirectoryCredentials(kTestActiveDirectoryUser,
kPassword);
test::WaitForPrimaryUserSessionStart();
}
// Tests that user could override autocomplete domain.
IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginAutocompleteTest, TestAutocomplete) {
OobeBaseTest::WaitForSigninScreen();
ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
ad_login_.TestLoginVisible();
ad_login_.TestDomainVisible();
fake_auth_policy_client()->set_auth_error(authpolicy::ERROR_BAD_PASSWORD);
// Submit with a different domain.
ad_login_.SetUserInput(test_user_);
ad_login_.TestDomainHidden();
ad_login_.TestUserInput(test_user_);
ad_login_.SubmitActiveDirectoryCredentials(test_user_, "password");
ad_login_.WaitForAuthError();
ad_login_.TestLoginVisible();
ad_login_.TestDomainHidden();
ad_login_.TestUserInput(test_user_);
// Set userinput with the autocomplete domain. JS will remove the autocomplete
// domain.
ad_login_.SetUserInput(kTestActiveDirectoryUser + autocomplete_realm_);
ad_login_.TestDomainVisible();
ad_login_.TestUserInput(kTestActiveDirectoryUser);
ad_login_.SubmitActiveDirectoryCredentials(
kTestActiveDirectoryUser + autocomplete_realm_, "password");
ad_login_.WaitForAuthError();
ad_login_.TestLoginVisible();
ad_login_.TestDomainVisible();
ad_login_.TestUserInput(kTestActiveDirectoryUser);
}
} // namespace chromeos