diff options
author | jamiewalch@google.com <jamiewalch@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-15 18:11:12 +0000 |
---|---|---|
committer | jamiewalch@google.com <jamiewalch@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-15 18:11:12 +0000 |
commit | e59e30dcffffb67e476b63b7737e4eec79756cc2 (patch) | |
tree | dfaef3e1b0daa993e1f9199d27d74688209e32d6 /remoting | |
parent | f0417774888b46efa3a354a6ae8f7402d2cac7d6 (diff) | |
download | chromium_src-e59e30dcffffb67e476b63b7737e4eec79756cc2.zip chromium_src-e59e30dcffffb67e476b63b7737e4eec79756cc2.tar.gz chromium_src-e59e30dcffffb67e476b63b7737e4eec79756cc2.tar.bz2 |
Make curtain-mode controllable by policy.
BUG=110111
Review URL: https://chromiumcodereview.appspot.com/10829306
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@151714 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/host/constants.h | 3 | ||||
-rw-r--r-- | remoting/host/curtain_mode_mac.cc | 85 | ||||
-rw-r--r-- | remoting/host/curtain_mode_mac.h | 35 | ||||
-rwxr-xr-x | remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh | 2 | ||||
-rw-r--r-- | remoting/host/policy_hack/policy_watcher.cc | 3 | ||||
-rw-r--r-- | remoting/host/remoting_me2me_host.cc | 68 | ||||
-rwxr-xr-x | remoting/tools/me2me_virtual_host.py | 1 |
7 files changed, 153 insertions, 44 deletions
diff --git a/remoting/host/constants.h b/remoting/host/constants.h index 63a2769..54aa228 100644 --- a/remoting/host/constants.h +++ b/remoting/host/constants.h @@ -29,11 +29,12 @@ enum HostExitCodes { kInvalidHostIdExitCode = 3, kInvalidOauthCredentialsExitCode = 4, kInvalidHostDomainExitCode = 5, + kLoginScreenNotSupportedExitCode = 6, // The range of the exit codes that should be interpreted as a permanent error // condition. kMinPermanentErrorExitCode = kInvalidHostConfigurationExitCode, - kMaxPermanentErrorExitCode = kInvalidHostDomainExitCode + kMaxPermanentErrorExitCode = kLoginScreenNotSupportedExitCode }; #if defined(OS_WIN) diff --git a/remoting/host/curtain_mode_mac.cc b/remoting/host/curtain_mode_mac.cc index 07e186d..a7dedff 100644 --- a/remoting/host/curtain_mode_mac.cc +++ b/remoting/host/curtain_mode_mac.cc @@ -18,30 +18,37 @@ const char* kCGSessionPath = namespace remoting { -CurtainMode::CurtainMode() : event_handler_(NULL) { +CurtainMode::CurtainMode(const base::Closure& on_session_activate, + const base::Closure& on_error) + : on_session_activate_(on_session_activate), + on_error_(on_error), + connection_active_(false), + event_handler_(NULL) { } CurtainMode::~CurtainMode() { - if (event_handler_) { - RemoveEventHandler(event_handler_); - } + SetEnabled(false); } -bool CurtainMode::Init(const base::Closure& on_session_activate) { - DCHECK(on_session_activate_.is_null()); - on_session_activate_ = on_session_activate; - EventTypeSpec event; - event.eventClass = kEventClassSystem; - event.eventKind = kEventSystemUserSessionActivated; - OSStatus result = InstallApplicationEventHandler( - NewEventHandlerUPP(SessionActivateHandler), 1, &event, this, - &event_handler_); - return result == noErr; +void CurtainMode::SetEnabled(bool enabled) { + if (enabled) { + if (connection_active_) { + if (!ActivateCurtain()) { + on_error_.Run(); + } + } + } else { + RemoveEventHandler(); + } } -void CurtainMode::OnClientAuthenticated(const std::string& jid) { - // If the current session is attached to the console and is not showing - // the logon screen then switch it out to ensure privacy. +bool CurtainMode::ActivateCurtain() { + // Try to install the switch-in handler. Do this before switching out the + // current session so that the console session is not affected if it fails. + if (!InstallEventHandler()) { + return false; + } + base::mac::ScopedCFTypeRef<CFDictionaryRef> session( CGSessionCopyCurrentDictionary()); const void* on_console = CFDictionaryGetValue(session, @@ -55,8 +62,29 @@ void CurtainMode::OnClientAuthenticated(const std::string& jid) { } else if (child > 0) { int status = 0; waitpid(child, &status, 0); + if (status != 0) { + LOG(ERROR) << kCGSessionPath << " failed."; + return false; + } + } else { + LOG(ERROR) << "fork() failed."; + return false; } } + return true; +} + +// TODO(jamiewalch): This code assumes at most one client connection at a time. +// Add OnFirstClientConnected and OnLastClientDisconnected optional callbacks +// to the HostStatusObserver interface to address this. +void CurtainMode::OnClientAuthenticated(const std::string& jid) { + connection_active_ = true; + SetEnabled(true); +} + +void CurtainMode::OnClientDisconnected(const std::string& jid) { + SetEnabled(false); + connection_active_ = false; } OSStatus CurtainMode::SessionActivateHandler(EventHandlerCallRef handler, @@ -68,9 +96,28 @@ OSStatus CurtainMode::SessionActivateHandler(EventHandlerCallRef handler, } void CurtainMode::OnSessionActivate() { - if (!on_session_activate_.is_null()) { - on_session_activate_.Run(); + on_session_activate_.Run(); +} + +bool CurtainMode::InstallEventHandler() { + OSStatus result = noErr; + if (!event_handler_) { + EventTypeSpec event; + event.eventClass = kEventClassSystem; + event.eventKind = kEventSystemUserSessionActivated; + result = ::InstallApplicationEventHandler( + NewEventHandlerUPP(SessionActivateHandler), 1, &event, this, + &event_handler_); + } + return result == noErr; +} + +bool CurtainMode::RemoveEventHandler() { + OSStatus result = noErr; + if (event_handler_) { + result = ::RemoveEventHandler(event_handler_); } + return result == noErr; } } // namespace remoting diff --git a/remoting/host/curtain_mode_mac.h b/remoting/host/curtain_mode_mac.h index 3d21805..b439b11 100644 --- a/remoting/host/curtain_mode_mac.h +++ b/remoting/host/curtain_mode_mac.h @@ -17,27 +17,46 @@ namespace remoting { class CurtainMode : public HostStatusObserver { public: - CurtainMode(); + // Set callbacks to be invoked when the switched-out session is switched back + // to the console, or in case of errors activating curtain-mode. Typically, + // remote clients should be disconnected in both cases: for errors, because + // the privacy guarantee of curtain-mode cannot be honoured; for switch-in, + // to ensure that only one connection (console or remote) exists to a session. + // Note that only the session's owner (or someone who knows the password) can + // attach it to the console, so this is safe. + CurtainMode(const base::Closure& on_session_activate, + const base::Closure& on_error); virtual ~CurtainMode(); - // Set the callback to be invoked when the switched-out remote session is - // switched back to the console. Typically, remote connections should be - // closed in this event to make sure that only one connection (console or - // remote) exists to a session at any time to ensure privacy. Note that - // only the session's owner (or someone who knows the owner's password) - // can attach it to the console, so this is safe. - bool Init(const base::Closure& on_session_activate); + // Enable or disable curtain-mode. Note that disabling curtain-mode does not + // deactivate the curtain, but it does remove the switch-in handler, meaning + // that on_session_activate will not be invoked if curtain-mode is disabled. + // Conversely, enabling curtain-mode *does* activate the curtain if there is + // a connected client at the time. + void SetEnabled(bool enabled); // Overridden from HostStatusObserver virtual void OnClientAuthenticated(const std::string& jid) OVERRIDE; + virtual void OnClientDisconnected(const std::string& jid) OVERRIDE; private: + // If the current session is attached to the console and is not showing + // the logon screen then switch it out to ensure privacy. + bool ActivateCurtain(); + + // Add or remove the switch-in event handler. + bool InstallEventHandler(); + bool RemoveEventHandler(); + + // Handlers for the switch-in event. static OSStatus SessionActivateHandler(EventHandlerCallRef handler, EventRef event, void* user_data); void OnSessionActivate(); base::Closure on_session_activate_; + base::Closure on_error_; + bool connection_active_; EventHandlerRef event_handler_; }; diff --git a/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh b/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh index 59d20e0..ea0383b 100755 --- a/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh +++ b/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh @@ -21,7 +21,7 @@ SIGTERM_EXIT_CODE=143 # has occurred and that the host should not be restarted. Please, keep these # constants in sync with remoting/host/constants.h. MIN_PERMANENT_ERROR_EXIT_CODE=2 -MAX_PERMANENT_ERROR_EXIT_CODE=5 +MAX_PERMANENT_ERROR_EXIT_CODE=6 HOST_PID=0 SIGNAL_WAS_TRAPPED=0 diff --git a/remoting/host/policy_hack/policy_watcher.cc b/remoting/host/policy_hack/policy_watcher.cc index 4217076..270bccb 100644 --- a/remoting/host/policy_hack/policy_watcher.cc +++ b/remoting/host/policy_hack/policy_watcher.cc @@ -123,7 +123,8 @@ const char PolicyWatcher::kHostRequireCurtainPolicyName[] = const char* const PolicyWatcher::kBooleanPolicyNames[] = { PolicyWatcher::kNatPolicyName, - PolicyWatcher::kHostRequireTwoFactorPolicyName + PolicyWatcher::kHostRequireTwoFactorPolicyName, + PolicyWatcher::kHostRequireCurtainPolicyName }; const int PolicyWatcher::kBooleanPolicyNamesNum = diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index e9e4732..701ce32 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc @@ -50,6 +50,7 @@ #include "remoting/protocol/me2me_host_authenticator_factory.h" #if defined(OS_MACOSX) +#include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsautorelease_pool.h" #include "remoting/host/curtain_mode_mac.h" #include "remoting/host/sighup_listener_mac.h" @@ -103,7 +104,14 @@ class HostProcess allow_nat_traversal_(true), restarting_(false), shutting_down_(false), - exit_code_(kSuccessExitCode) { + exit_code_(kSuccessExitCode) +#if defined(OS_MACOSX) + , curtain_(base::Bind(&HostProcess::OnDisconnectRequested, + base::Unretained(this)), + base::Bind(&HostProcess::OnDisconnectRequested, + base::Unretained(this))) +#endif + { context_.reset( new ChromotingHostContext(message_loop_.message_loop_proxy())); context_->Start(); @@ -319,6 +327,10 @@ class HostProcess return; } + if (!host_) { + StartHost(); + } + bool bool_value; std::string string_value; if (policies->GetString(policy_hack::PolicyWatcher::kHostDomainPolicyName, @@ -329,6 +341,11 @@ class HostProcess &bool_value)) { OnNatPolicyUpdate(bool_value); } + if (policies->GetBoolean( + policy_hack::PolicyWatcher::kHostRequireCurtainPolicyName, + &bool_value)) { + OnCurtainPolicyUpdate(bool_value); + } } void OnHostDomainPolicyUpdate(const std::string& host_domain) { @@ -356,15 +373,44 @@ class HostProcess bool policy_changed = allow_nat_traversal_ != nat_traversal_enabled; allow_nat_traversal_ = nat_traversal_enabled; - if (host_) { - // Restart the host if the policy has changed while the host was - // online. - if (policy_changed) - RestartHost(); + if (policy_changed) { + RestartHost(); + } + } + + void OnCurtainPolicyUpdate(bool curtain_required) { +#if defined(OS_MACOSX) + if (!context_->network_task_runner()->BelongsToCurrentThread()) { + context_->network_task_runner()->PostTask(FROM_HERE, base::Bind( + &HostProcess::OnCurtainPolicyUpdate, base::Unretained(this), + curtain_required)); + return; + } + + if (curtain_required) { + // If curtain mode is required, then we can't currently support remoting + // the login screen. This is because we don't curtain the login screen + // and the current daemon architecture means that the connction is closed + // immediately after login, leaving the host system uncurtained. + // + // TODO(jamiewalch): Fix this once we have implemented the multi-process + // daemon architecture (crbug.com/134894) + base::mac::ScopedCFTypeRef<CFDictionaryRef> session( + CGSessionCopyCurrentDictionary()); + const void* logged_in = CFDictionaryGetValue(session, + kCGSessionLoginDoneKey); + if (logged_in != kCFBooleanTrue) { + Shutdown(kLoginScreenNotSupportedExitCode); + return; + } + + host_->AddStatusObserver(&curtain_); + curtain_.SetEnabled(true); } else { - // Just start the host otherwise. - StartHost(); + curtain_.SetEnabled(false); + host_->RemoveStatusObserver(&curtain_); } +#endif } void StartHost() { @@ -447,12 +493,6 @@ class HostProcess base::Unretained(this))); #endif -#if defined(OS_MACOSX) - curtain_.Init(base::Bind(&HostProcess::OnDisconnectRequested, - base::Unretained(this))); - host_->AddStatusObserver(&curtain_); -#endif - host_->Start(); CreateAuthenticatorFactory(); diff --git a/remoting/tools/me2me_virtual_host.py b/remoting/tools/me2me_virtual_host.py index 2b1b85c6..cc39536 100755 --- a/remoting/tools/me2me_virtual_host.py +++ b/remoting/tools/me2me_virtual_host.py @@ -916,6 +916,7 @@ def main(): logging.info("Host domain is blocked by policy - exiting.") os.remove(host.config_file) return 0 + # Nothing to do for Mac-only status 6 (login screen unsupported) if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) |