| // Copyright (c) 2012 The Chromium OS 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 "login_manager/session_manager_impl.h" |
| |
| #include <errno.h> |
| #include <glib.h> |
| #include <stdint.h> |
| #include <sys/socket.h> |
| |
| #include <algorithm> |
| #include <locale> |
| #include <string> |
| |
| #include <base/callback.h> |
| #include <base/command_line.h> |
| #include <base/files/file_util.h> |
| #include <base/memory/ref_counted.h> |
| #include <base/memory/scoped_ptr.h> |
| #include <base/message_loop/message_loop.h> |
| #include <base/message_loop/message_loop_proxy.h> |
| #include <base/stl_util.h> |
| #include <base/strings/string_util.h> |
| #include <chromeos/cryptohome.h> |
| #include <crypto/scoped_nss_types.h> |
| #include <dbus/message.h> |
| #include <vboot/crossystem.h> |
| |
| #include "bindings/chrome_device_policy.pb.h" |
| #include "bindings/device_management_backend.pb.h" |
| #include "login_manager/dbus_error_types.h" |
| #include "login_manager/dbus_signal_emitter.h" |
| #include "login_manager/device_local_account_policy_service.h" |
| #include "login_manager/device_policy_service.h" |
| #include "login_manager/key_generator.h" |
| #include "login_manager/login_metrics.h" |
| #include "login_manager/nss_util.h" |
| #include "login_manager/policy_key.h" |
| #include "login_manager/policy_service.h" |
| #include "login_manager/process_manager_service_interface.h" |
| #include "login_manager/regen_mitigator.h" |
| #include "login_manager/system_utils.h" |
| #include "login_manager/upstart_signal_emitter.h" |
| #include "login_manager/user_policy_service_factory.h" |
| |
| using base::FilePath; |
| using chromeos::cryptohome::home::GetUserPath; |
| using chromeos::cryptohome::home::SanitizeUserName; |
| using chromeos::cryptohome::home::kGuestUserName; |
| |
| namespace login_manager { // NOLINT |
| |
| const char SessionManagerImpl::kDemoUser[] = "demouser@"; |
| |
| const char SessionManagerImpl::kStarted[] = "started"; |
| const char SessionManagerImpl::kStopping[] = "stopping"; |
| const char SessionManagerImpl::kStopped[] = "stopped"; |
| |
| const char SessionManagerImpl::kLoggedInFlag[] = |
| "/var/run/session_manager/logged_in"; |
| const char SessionManagerImpl::kResetFile[] = |
| "/mnt/stateful_partition/factory_install_reset"; |
| |
| namespace { |
| |
| // Constants used in email validation. |
| const char kEmailSeparator = '@'; |
| const char kLegalCharacters[] = |
| "abcdefghijklmnopqrstuvwxyz" |
| "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| ".@1234567890!#$%&'*+-/=?^_`{|}~"; |
| |
| // The flag to pass to chrome to open a named socket for testing. |
| const char kTestingChannelFlag[] = "--testing-channel=NamedTestingInterface:"; |
| |
| // Device-local account state directory. |
| const base::FilePath::CharType kDeviceLocalAccountStateDir[] = |
| FILE_PATH_LITERAL("/var/lib/device_local_accounts"); |
| |
| // The name of the flag that indicates whether dev mode should be blocked. |
| const char kCrossystemBlockDevmode[] = "block_devmode"; |
| |
| // Crossystem property indicating firmware type. |
| const char kCrossystemMainfwType[] = "mainfw_type"; |
| |
| // Firmware type string returned when there is no Chrome OS firmware present. |
| const char kCrossystemMainfwTypeNonchrome[] = "nonchrome"; |
| |
| } // namespace |
| |
| SessionManagerImpl::Error::Error() : set_(false) { |
| } |
| |
| SessionManagerImpl::Error::Error(const std::string& name, |
| const std::string& message) |
| : name_(name), message_(message), set_(true) { |
| } |
| |
| SessionManagerImpl::Error::~Error() { |
| } |
| |
| void SessionManagerImpl::Error::Set(const std::string& name, |
| const std::string& message) { |
| name_ = name; |
| message_ = message; |
| set_ = true; |
| } |
| |
| struct SessionManagerImpl::UserSession { |
| public: |
| UserSession(const std::string& username, |
| const std::string& userhash, |
| bool is_incognito, |
| crypto::ScopedPK11Slot slot, |
| scoped_ptr<PolicyService> policy_service) |
| : username(username), |
| userhash(userhash), |
| is_incognito(is_incognito), |
| slot(slot.Pass()), |
| policy_service(policy_service.Pass()) {} |
| ~UserSession() {} |
| |
| const std::string username; |
| const std::string userhash; |
| const bool is_incognito; |
| crypto::ScopedPK11Slot slot; |
| scoped_ptr<PolicyService> policy_service; |
| }; |
| |
| SessionManagerImpl::SessionManagerImpl( |
| scoped_ptr<UpstartSignalEmitter> emitter, |
| DBusSignalEmitterInterface* dbus_emitter, |
| base::Closure lock_screen_closure, |
| base::Closure restart_device_closure, |
| KeyGenerator* key_gen, |
| ServerBackedStateKeyGenerator* state_key_generator, |
| ProcessManagerServiceInterface* manager, |
| LoginMetrics* metrics, |
| NssUtil* nss, |
| SystemUtils* utils) |
| : session_started_(false), |
| session_stopping_(false), |
| screen_locked_(false), |
| supervised_user_creation_ongoing_(false), |
| upstart_signal_emitter_(emitter.Pass()), |
| lock_screen_closure_(lock_screen_closure), |
| restart_device_closure_(restart_device_closure), |
| dbus_emitter_(dbus_emitter), |
| key_gen_(key_gen), |
| state_key_generator_(state_key_generator), |
| manager_(manager), |
| login_metrics_(metrics), |
| nss_(nss), |
| system_(utils), |
| owner_key_(nss->GetOwnerKeyFilePath(), nss), |
| mitigator_(key_gen) { |
| } |
| |
| SessionManagerImpl::~SessionManagerImpl() { |
| STLDeleteValues(&user_sessions_); |
| device_policy_->set_delegate(NULL); // Could use WeakPtr instead? |
| } |
| |
| void SessionManagerImpl::InjectPolicyServices( |
| scoped_ptr<DevicePolicyService> device_policy, |
| scoped_ptr<UserPolicyServiceFactory> user_policy_factory, |
| scoped_ptr<DeviceLocalAccountPolicyService> device_local_account_policy) { |
| device_policy_ = device_policy.Pass(); |
| user_policy_factory_ = user_policy_factory.Pass(); |
| device_local_account_policy_ = device_local_account_policy.Pass(); |
| } |
| |
| void SessionManagerImpl::AnnounceSessionStoppingIfNeeded() { |
| if (session_started_) { |
| session_stopping_ = true; |
| DLOG(INFO) << "emitting D-Bus signal SessionStateChanged:" << kStopping; |
| dbus_emitter_->EmitSignalWithString(kSessionStateChangedSignal, kStopping); |
| } |
| } |
| |
| void SessionManagerImpl::AnnounceSessionStopped() { |
| session_stopping_ = session_started_ = false; |
| DLOG(INFO) << "emitting D-Bus signal SessionStateChanged:" << kStopped; |
| dbus_emitter_->EmitSignalWithString(kSessionStateChangedSignal, kStopped); |
| } |
| |
| bool SessionManagerImpl::ShouldEndSession() { |
| return screen_locked_ || supervised_user_creation_ongoing_; |
| } |
| |
| |
| bool SessionManagerImpl::Initialize() { |
| scoped_refptr<base::MessageLoopProxy> loop_proxy = |
| base::MessageLoop::current()->message_loop_proxy(); |
| |
| key_gen_->set_delegate(this); |
| |
| device_policy_.reset(DevicePolicyService::Create( |
| login_metrics_, &owner_key_, &mitigator_, nss_, loop_proxy)); |
| device_policy_->set_delegate(this); |
| |
| user_policy_factory_.reset( |
| new UserPolicyServiceFactory(getuid(), loop_proxy, nss_, system_)); |
| device_local_account_policy_.reset(new DeviceLocalAccountPolicyService( |
| base::FilePath(kDeviceLocalAccountStateDir), &owner_key_, loop_proxy)); |
| |
| if (device_policy_->Initialize()) { |
| device_local_account_policy_->UpdateDeviceSettings( |
| device_policy_->GetSettings()); |
| UpdateSystemSettings(); |
| return true; |
| } |
| return false; |
| } |
| |
| void SessionManagerImpl::Finalize() { |
| device_policy_->PersistPolicySync(); |
| for (UserSessionMap::const_iterator it = user_sessions_.begin(); |
| it != user_sessions_.end(); |
| ++it) { |
| if (it->second) |
| it->second->policy_service->PersistPolicySync(); |
| } |
| } |
| |
| void SessionManagerImpl::EmitLoginPromptVisible(Error* error) { |
| login_metrics_->RecordStats("login-prompt-visible"); |
| dbus_emitter_->EmitSignal(kLoginPromptVisibleSignal); |
| scoped_ptr<dbus::Response> emit_response = |
| upstart_signal_emitter_->EmitSignal("login-prompt-visible", |
| std::vector<std::string>()); |
| if (!emit_response) { |
| const char msg[] = "Emitting login-prompt-visible upstart signal failed."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kEmitFailed, msg); |
| } |
| } |
| |
| std::string SessionManagerImpl::EnableChromeTesting( |
| bool relaunch, |
| std::vector<std::string> extra_args, |
| Error* error) { |
| // Check to see if we already have Chrome testing enabled. |
| bool already_enabled = !chrome_testing_path_.empty(); |
| |
| if (!already_enabled) { |
| base::FilePath temp_file_path; // So we don't clobber chrome_testing_path_; |
| if (!system_->GetUniqueFilenameInWriteOnlyTempDir(&temp_file_path)) { |
| error->Set(dbus_error::kTestingChannelError, |
| "Could not create testing channel filename."); |
| return std::string(); |
| } |
| chrome_testing_path_ = temp_file_path; |
| } |
| |
| if (!already_enabled || relaunch) { |
| // Delete testing channel file if it already exists. |
| system_->RemoveFile(chrome_testing_path_); |
| |
| // Add testing channel argument to extra arguments. |
| std::string testing_argument = kTestingChannelFlag; |
| testing_argument.append(chrome_testing_path_.value()); |
| extra_args.push_back(testing_argument); |
| |
| manager_->RestartBrowserWithArgs(extra_args, true); |
| } |
| return chrome_testing_path_.value(); |
| } |
| |
| bool SessionManagerImpl::StartSession(const std::string& email, |
| const std::string& unique_id, |
| Error* error) { |
| // Validate the |email|. |
| const std::string email_string(base::StringToLowerASCII(email)); |
| const bool is_incognito = |
| ((email_string == kGuestUserName) || (email_string == kDemoUser)); |
| if (!is_incognito && !ValidateEmail(email_string)) { |
| const char msg[] = "Provided email address is not valid. ASCII only."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kInvalidAccount, msg); |
| return false; |
| } |
| |
| // Check if this user already started a session. |
| if (user_sessions_.count(email_string) > 0) { |
| const char msg[] = "Provided email address already started a session."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kSessionExists, msg); |
| return false; |
| } |
| |
| // Create a UserSession object for this user. |
| std::string error_name; |
| scoped_ptr<UserSession> user_session( |
| CreateUserSession(email_string, is_incognito, &error_name)); |
| if (!user_session.get()) { |
| error->Set(error_name, "Can't create session."); |
| return false; |
| } |
| // Check whether the current user is the owner, and if so make sure she is |
| // whitelisted and has an owner key. |
| bool user_is_owner = false; |
| PolicyService::Error policy_error; |
| if (!device_policy_->CheckAndHandleOwnerLogin(user_session->username, |
| user_session->slot.get(), |
| &user_is_owner, |
| &policy_error)) { |
| error->Set(policy_error.code(), policy_error.message()); |
| return false; |
| } |
| |
| // If all previous sessions were incognito (or no previous sessions exist). |
| bool is_first_real_user = AllSessionsAreIncognito() && !is_incognito; |
| |
| // Send each user login event to UMA (right before we start session |
| // since the metrics library does not log events in guest mode). |
| int dev_mode = system_->IsDevMode(); |
| if (dev_mode > -1) |
| login_metrics_->SendLoginUserType(dev_mode, is_incognito, user_is_owner); |
| |
| scoped_ptr<dbus::Response> emit_response = |
| upstart_signal_emitter_->EmitSignal( |
| "start-user-session", |
| std::vector<std::string>(1, "CHROMEOS_USER=" + email_string)); |
| |
| if (!emit_response) { |
| const char msg[] = "Emitting start-user-session upstart signal failed."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kEmitFailed, msg); |
| return false; |
| } |
| LOG(INFO) << "Starting user session"; |
| manager_->SetBrowserSessionForUser(email_string, user_session->userhash); |
| session_started_ = true; |
| user_sessions_[email_string] = user_session.release(); |
| DLOG(INFO) << "emitting D-Bus signal SessionStateChanged:" << kStarted; |
| dbus_emitter_->EmitSignalWithString(kSessionStateChangedSignal, kStarted); |
| |
| if (device_policy_->KeyMissing() && !device_policy_->Mitigating() && |
| is_first_real_user) { |
| // This is the first sign-in on this unmanaged device. Take ownership. |
| key_gen_->Start(email_string); |
| } |
| |
| // Record that a login has successfully completed on this boot. |
| system_->AtomicFileWrite(base::FilePath(kLoggedInFlag), "1"); |
| return true; |
| } |
| |
| bool SessionManagerImpl::StopSession() { |
| LOG(INFO) << "Stopping all sessions"; |
| // Most calls to StopSession() will log the reason for the call. |
| // If you don't see a log message saying the reason for the call, it is |
| // likely a DBUS message. See dbus_glib_shim.cc for that call. |
| manager_->ScheduleShutdown(); |
| // TODO(cmasone): re-enable these when we try to enable logout without exiting |
| // the session manager |
| // browser_.job->StopSession(); |
| // user_policy_.reset(); |
| // session_started_ = false; |
| return true; |
| } |
| |
| void SessionManagerImpl::StorePolicy(const uint8_t* policy_blob, |
| size_t policy_blob_len, |
| PolicyService::Completion completion) { |
| int flags = PolicyService::KEY_ROTATE; |
| if (!session_started_) |
| flags |= PolicyService::KEY_INSTALL_NEW | PolicyService::KEY_CLOBBER; |
| device_policy_->Store(policy_blob, policy_blob_len, completion, flags); |
| } |
| |
| void SessionManagerImpl::RetrievePolicy(std::vector<uint8_t>* policy_data, |
| Error* error) { |
| if (!device_policy_->Retrieve(policy_data)) { |
| const char msg[] = "Failed to retrieve policy data."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kSigEncodeFail, msg); |
| return; |
| } |
| } |
| |
| void SessionManagerImpl::StorePolicyForUser( |
| const std::string& user_email, |
| const uint8_t* policy_blob, |
| size_t policy_blob_len, |
| PolicyService::Completion completion) { |
| PolicyService* policy_service = GetPolicyService(user_email); |
| if (!policy_service) { |
| PolicyService::Error error( |
| dbus_error::kSessionDoesNotExist, |
| "Cannot store user policy before session is started."); |
| LOG(ERROR) << error.message(); |
| completion.Run(error); |
| return; |
| } |
| |
| policy_service->Store( |
| policy_blob, |
| policy_blob_len, |
| completion, |
| PolicyService::KEY_INSTALL_NEW | PolicyService::KEY_ROTATE); |
| } |
| |
| void SessionManagerImpl::RetrievePolicyForUser( |
| const std::string& user_email, |
| std::vector<uint8_t>* policy_data, |
| Error* error) { |
| PolicyService* policy_service = GetPolicyService(user_email); |
| if (!policy_service) { |
| const char msg[] = "Cannot retrieve user policy before session is started."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kSessionDoesNotExist, msg); |
| return; |
| } |
| if (!policy_service->Retrieve(policy_data)) { |
| const char msg[] = "Failed to retrieve policy data."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kSigEncodeFail, msg); |
| } |
| } |
| |
| void SessionManagerImpl::StoreDeviceLocalAccountPolicy( |
| const std::string& account_id, |
| const uint8_t* policy_blob, |
| size_t policy_blob_len, |
| PolicyService::Completion completion) { |
| device_local_account_policy_->Store( |
| account_id, policy_blob, policy_blob_len, completion); |
| } |
| |
| void SessionManagerImpl::RetrieveDeviceLocalAccountPolicy( |
| const std::string& account_id, |
| std::vector<uint8_t>* policy_data, |
| Error* error) { |
| if (!device_local_account_policy_->Retrieve(account_id, policy_data)) { |
| const char msg[] = "Failed to retrieve policy data."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kSigEncodeFail, msg); |
| return; |
| } |
| } |
| |
| const char* SessionManagerImpl::RetrieveSessionState() { |
| if (!session_started_) |
| return kStopped; |
| else |
| return (session_stopping_ ? kStopping : kStarted); |
| } |
| |
| void SessionManagerImpl::RetrieveActiveSessions( |
| std::map<std::string, std::string>* active_sessions) { |
| for (UserSessionMap::const_iterator it = user_sessions_.begin(); |
| it != user_sessions_.end(); |
| ++it) { |
| if (it->second) { |
| (*active_sessions)[it->second->username] = it->second->userhash; |
| } |
| } |
| } |
| |
| void SessionManagerImpl::HandleSupervisedUserCreationStarting() { |
| supervised_user_creation_ongoing_ = true; |
| } |
| |
| void SessionManagerImpl::HandleSupervisedUserCreationFinished() { |
| supervised_user_creation_ongoing_ = false; |
| } |
| |
| void SessionManagerImpl::LockScreen(Error* error) { |
| if (!session_started_) { |
| const char msg[] = "Attempt to lock screen outside of user session."; |
| LOG(WARNING) << msg; |
| error->Set(dbus_error::kSessionDoesNotExist, msg); |
| return; |
| } |
| // If all sessions are incognito, then locking is not allowed. |
| if (AllSessionsAreIncognito()) { |
| const char msg[] = "Attempt to lock screen during Guest session."; |
| LOG(WARNING) << msg; |
| error->Set(dbus_error::kSessionExists, msg); |
| return; |
| } |
| if (!screen_locked_) { |
| screen_locked_ = true; |
| lock_screen_closure_.Run(); |
| } |
| LOG(INFO) << "LockScreen() method called."; |
| } |
| |
| void SessionManagerImpl::HandleLockScreenShown() { |
| LOG(INFO) << "HandleLockScreenShown() method called."; |
| dbus_emitter_->EmitSignal(kScreenIsLockedSignal); |
| } |
| |
| void SessionManagerImpl::HandleLockScreenDismissed() { |
| screen_locked_ = false; |
| LOG(INFO) << "HandleLockScreenDismissed() method called."; |
| dbus_emitter_->EmitSignal(kScreenIsUnlockedSignal); |
| } |
| |
| bool SessionManagerImpl::RestartJob(pid_t pid, |
| const std::string& arguments, |
| Error* error) { |
| if (!manager_->IsBrowser(pid)) { |
| const char msg[] = "Provided pid is unknown."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kUnknownPid, msg); |
| return false; |
| } |
| |
| gchar** argv = NULL; |
| gint argc = 0; |
| GError* parse_error = NULL; |
| if (!g_shell_parse_argv(arguments.c_str(), &argc, &argv, &parse_error)) { |
| LOG(ERROR) << "Could not parse command: " << parse_error->message; |
| g_strfreev(argv); |
| error->Set(DBUS_ERROR_INVALID_ARGS, parse_error->message); |
| return false; |
| } |
| base::CommandLine new_command_line(argc, argv); |
| g_strfreev(argv); |
| |
| // To set "logged-in" state for BWSI mode. |
| if (!StartSession(kGuestUserName, "", error)) |
| return false; |
| manager_->RestartBrowserWithArgs(new_command_line.argv(), false); |
| return true; |
| } |
| |
| bool SessionManagerImpl::RestartJobWithAuth(int fd, |
| const std::string& arguments, |
| Error* error) { |
| struct ucred ucred = {0}; |
| socklen_t len = sizeof(struct ucred); |
| if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { |
| PLOG(ERROR) << "Can't get peer creds"; |
| error->Set("GetPeerCredsFailed", strerror(errno)); |
| return false; |
| } |
| |
| return RestartJob(ucred.pid, arguments, error); |
| } |
| |
| void SessionManagerImpl::StartDeviceWipe(const std::string& reason, |
| Error* error) { |
| const base::FilePath session_path(kLoggedInFlag); |
| if (system_->Exists(session_path)) { |
| const char msg[] = "A user has already logged in this boot."; |
| LOG(ERROR) << msg; |
| error->Set(dbus_error::kSessionExists, msg); |
| return; |
| } |
| InitiateDeviceWipe(reason); |
| } |
| |
| void SessionManagerImpl::SetFlagsForUser( |
| const std::string& user_email, |
| const std::vector<std::string>& session_user_flags) { |
| manager_->SetFlagsForUser(user_email, session_user_flags); |
| } |
| |
| void SessionManagerImpl::RequestServerBackedStateKeys( |
| const ServerBackedStateKeyGenerator::StateKeyCallback& callback) { |
| state_key_generator_->RequestStateKeys(callback); |
| } |
| |
| void SessionManagerImpl::InitMachineInfo(const std::string& data, |
| Error* error) { |
| std::map<std::string, std::string> params; |
| if (!ServerBackedStateKeyGenerator::ParseMachineInfo(data, ¶ms)) |
| error->Set(dbus_error::kInitMachineInfoFail, "Parse failure."); |
| |
| if (!state_key_generator_->InitMachineInfo(params)) |
| error->Set(dbus_error::kInitMachineInfoFail, "Missing parameters."); |
| } |
| |
| void SessionManagerImpl::OnPolicyPersisted(bool success) { |
| device_local_account_policy_->UpdateDeviceSettings( |
| device_policy_->GetSettings()); |
| UpdateSystemSettings(); |
| dbus_emitter_->EmitSignalWithSuccessFailure(kPropertyChangeCompleteSignal, |
| success); |
| } |
| |
| void SessionManagerImpl::OnKeyPersisted(bool success) { |
| dbus_emitter_->EmitSignalWithSuccessFailure(kOwnerKeySetSignal, success); |
| } |
| |
| void SessionManagerImpl::OnKeyGenerated(const std::string& username, |
| const base::FilePath& temp_key_file) { |
| ImportValidateAndStoreGeneratedKey(username, temp_key_file); |
| } |
| |
| void SessionManagerImpl::ImportValidateAndStoreGeneratedKey( |
| const std::string& username, |
| const base::FilePath& temp_key_file) { |
| DLOG(INFO) << "Processing generated key at " << temp_key_file.value(); |
| std::string key; |
| base::ReadFileToString(temp_key_file, &key); |
| PLOG_IF(WARNING, !base::DeleteFile(temp_key_file, false)) |
| << "Can't delete " << temp_key_file.value(); |
| device_policy_->ValidateAndStoreOwnerKey( |
| username, key, user_sessions_[username]->slot.get()); |
| } |
| |
| void SessionManagerImpl::InitiateDeviceWipe(const std::string& reason) { |
| // The log string must not be confused with other clobbers-state parameters. |
| // Sanitize by replacing all non-alphanumeric characters with underscores and |
| // clamping size to 50 characters. |
| std::string sanitized_reason(reason.substr(0, 50)); |
| std::locale locale("C"); |
| std::replace_if(sanitized_reason.begin(), sanitized_reason.end(), |
| [&locale](const std::string::value_type character) { |
| return !std::isalnum(character, locale); |
| }, |
| '_'); |
| const base::FilePath reset_path(kResetFile); |
| system_->AtomicFileWrite(reset_path, |
| "fast safe keepimg reason=" + sanitized_reason); |
| restart_device_closure_.Run(); |
| } |
| |
| // static |
| bool SessionManagerImpl::ValidateEmail(const std::string& email_address) { |
| if (email_address.find_first_not_of(kLegalCharacters) != std::string::npos) |
| return false; |
| |
| size_t at = email_address.find(kEmailSeparator); |
| // it has NO @. |
| if (at == std::string::npos) |
| return false; |
| |
| // it has more than one @. |
| if (email_address.find(kEmailSeparator, at + 1) != std::string::npos) |
| return false; |
| |
| return true; |
| } |
| |
| bool SessionManagerImpl::AllSessionsAreIncognito() { |
| size_t incognito_count = 0; |
| for (UserSessionMap::const_iterator it = user_sessions_.begin(); |
| it != user_sessions_.end(); |
| ++it) { |
| if (it->second) |
| incognito_count += it->second->is_incognito; |
| } |
| return incognito_count == user_sessions_.size(); |
| } |
| |
| SessionManagerImpl::UserSession* SessionManagerImpl::CreateUserSession( |
| const std::string& username, |
| bool is_incognito, |
| std::string* error_message) { |
| scoped_ptr<PolicyService> user_policy(user_policy_factory_->Create(username)); |
| if (!user_policy) { |
| LOG(ERROR) << "User policy failed to initialize."; |
| if (error_message) |
| *error_message = dbus_error::kPolicyInitFail; |
| return NULL; |
| } |
| crypto::ScopedPK11Slot slot(nss_->OpenUserDB(GetUserPath(username))); |
| if (!slot) { |
| LOG(ERROR) << "Could not open the current user's NSS database."; |
| if (error_message) |
| *error_message = dbus_error::kNoUserNssDb; |
| return NULL; |
| } |
| return new SessionManagerImpl::UserSession(username, |
| SanitizeUserName(username), |
| is_incognito, |
| slot.Pass(), |
| user_policy.Pass()); |
| } |
| |
| PolicyService* SessionManagerImpl::GetPolicyService(const std::string& user) { |
| UserSessionMap::const_iterator it = user_sessions_.find(user); |
| return it == user_sessions_.end() ? NULL : it->second->policy_service.get(); |
| } |
| |
| void SessionManagerImpl::UpdateSystemSettings() { |
| // Only write settings when device ownership is established. |
| if (!owner_key_.IsPopulated()) |
| return; |
| |
| // Only write verified boot settings if running on Chrome OS firmware. |
| char buffer[VB_MAX_STRING_PROPERTY]; |
| if (VbGetSystemPropertyString(kCrossystemMainfwType, buffer, |
| sizeof(buffer)) && |
| strcmp(kCrossystemMainfwTypeNonchrome, buffer)) { |
| int block_devmode_setting = |
| device_policy_->GetSettings().system_settings().block_devmode() ? 1 : 0; |
| int block_devmode_value = VbGetSystemPropertyInt(kCrossystemBlockDevmode); |
| if (block_devmode_value == -1) |
| LOG(ERROR) << "Failed to read block_devmode flag!"; |
| |
| if (block_devmode_setting != block_devmode_value) { |
| if (VbSetSystemPropertyInt(kCrossystemBlockDevmode, |
| block_devmode_setting)) { |
| LOG(ERROR) << "Failed to write block_devmode flag!"; |
| } |
| } |
| } |
| } |
| |
| } // namespace login_manager |