summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorjamiewalch@google.com <jamiewalch@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-15 18:11:12 +0000
committerjamiewalch@google.com <jamiewalch@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-15 18:11:12 +0000
commite59e30dcffffb67e476b63b7737e4eec79756cc2 (patch)
treedfaef3e1b0daa993e1f9199d27d74688209e32d6 /remoting
parentf0417774888b46efa3a354a6ae8f7402d2cac7d6 (diff)
downloadchromium_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.h3
-rw-r--r--remoting/host/curtain_mode_mac.cc85
-rw-r--r--remoting/host/curtain_mode_mac.h35
-rwxr-xr-xremoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh2
-rw-r--r--remoting/host/policy_hack/policy_watcher.cc3
-rw-r--r--remoting/host/remoting_me2me_host.cc68
-rwxr-xr-xremoting/tools/me2me_virtual_host.py1
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)