Index: remoting/host/wts_session_process_launcher_win.cc |
diff --git a/remoting/host/wts_session_process_launcher_win.cc b/remoting/host/wts_session_process_launcher_win.cc |
index c5e42dacceff16e9e07833a4bae75cb937b79d27..b86343e3b3bfb1915af01ea8a3b4471bd675e855 100644 |
--- a/remoting/host/wts_session_process_launcher_win.cc |
+++ b/remoting/host/wts_session_process_launcher_win.cc |
@@ -10,9 +10,15 @@ |
#include <windows.h> |
#include "base/logging.h" |
+#include "base/threading/thread.h" |
#include "base/utf_string_conversions.h" |
#include "base/win/scoped_handle.h" |
+#include "ipc/ipc_channel_proxy.h" |
+#include "ipc/ipc_message.h" |
+#include "ipc/ipc_message_macros.h" |
+#include "remoting/host/chromoting_service_messages.h" |
+#include "remoting/host/sas_sender_win.h" |
#include "remoting/host/wts_console_monitor_win.h" |
using base::win::ScopedHandle; |
@@ -28,6 +34,9 @@ const int kMinLaunchDelaySeconds = 1; |
// Name of the default session desktop. |
const char kDefaultDesktopName[] = "winsta0\\default"; |
+// Name of the chromoting service IPC channel. |
+const char kChromotingServiceChannelName[] = "chromoting_service"; |
+ |
// Takes the process token and makes a copy of it. The returned handle will have |
// |desired_access| rights. |
bool CopyProcessToken(DWORD desired_access, |
@@ -155,8 +164,10 @@ namespace remoting { |
WtsSessionProcessLauncher::WtsSessionProcessLauncher( |
WtsConsoleMonitor* monitor, |
- const FilePath& host_binary) |
+ const FilePath& host_binary, |
+ base::Thread* io_thread) |
: host_binary_(host_binary), |
+ io_thread_(io_thread), |
monitor_(monitor), |
state_(StateDetached) { |
monitor_->AddWtsConsoleObserver(this); |
@@ -167,6 +178,7 @@ WtsSessionProcessLauncher::~WtsSessionProcessLauncher() { |
DCHECK(!timer_.IsRunning()); |
DCHECK(process_.handle() == NULL); |
DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ DCHECK(chromoting_service_.get() == NULL); |
monitor_->RemoveWtsConsoleObserver(this); |
} |
@@ -176,10 +188,32 @@ void WtsSessionProcessLauncher::LaunchProcess() { |
DCHECK(!timer_.IsRunning()); |
DCHECK(process_.handle() == NULL); |
DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ DCHECK(chromoting_service_.get() == NULL); |
+ |
+ launch_time_ = base::Time::Now(); |
+ |
+ // Create the chromoting service IPC channel on the I/O thread. |
+ // N.B. IPC::Channel passes NULL security attributes pointer to |
+ // CreateNamedPipe() so the pipe gets a default security descriptor. |
+ // The ACLs in the default security descriptor for a named pipe grant |
+ // full control to the LocalSystem account, administrators, and |
+ // the creator owner. They also grant read access to members of the |
+ // Everyone group and the anonymous account. |
Wez
2012/03/07 01:56:13
nit: Clarify why read access is not an issue?
alexeypa (please no reviews)
2012/03/07 19:59:08
See PIPE_ACCESS_DUPLEX below
|
+ // |
+ // IPC::Channel also specifies the PIPE_ACCESS_DUPLEX mode for |
+ // the created pipe. A client has to specify the same duplex mode in |
+ // order to connect. |
Wez
2012/03/07 01:56:13
nit: How is this comment relevant to "the result",
alexeypa (please no reviews)
2012/03/07 19:59:08
Yes. I rephrased the comment to articulate it bett
|
+ // |
+ // In our case the result is that only processes running under |
+ // LocalSystem account will be able to connect to this channel. |
+ chromoting_service_.reset(new IPC::ChannelProxy( |
+ kChromotingServiceChannelName, |
+ IPC::Channel::MODE_SERVER, |
+ this, |
+ io_thread_->message_loop_proxy().get())); |
// Try to launch the process and attach an object watcher to the returned |
// handle so that we get notified when the process terminates. |
- launch_time_ = base::Time::Now(); |
if (LaunchProcessAsUser(host_binary_, session_token_, &process_)) { |
if (process_watcher_.StartWatching(process_.handle(), this)) { |
state_ = StateAttached; |
@@ -188,6 +222,7 @@ void WtsSessionProcessLauncher::LaunchProcess() { |
LOG(ERROR) << "Failed to arm the process watcher."; |
process_.Terminate(0); |
process_.Close(); |
+ chromoting_service_.reset(); |
} |
} |
@@ -206,10 +241,12 @@ void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) { |
DCHECK(!timer_.IsRunning()); |
DCHECK(process_.handle() != NULL); |
DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ DCHECK(chromoting_service_.get() != NULL); |
// The host process has been terminated for some reason. The handle can now be |
// closed. |
process_.Close(); |
+ chromoting_service_.reset(); |
// Expand the backoff interval if the process has died quickly or reset it if |
// it was up longer than the maximum backoff delay. |
@@ -230,11 +267,33 @@ void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) { |
this, &WtsSessionProcessLauncher::LaunchProcess); |
} |
+bool WtsSessionProcessLauncher::OnMessageReceived(const IPC::Message& message) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(WtsSessionProcessLauncher, message) |
+ IPC_MESSAGE_HANDLER(ChromotingServiceMsg_SendSas, OnSendSas) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+} |
+ |
+void WtsSessionProcessLauncher::OnSendSas() { |
+ if (state_ == StateAttached) { |
+ if (sas_sender_.get() == NULL) { |
+ sas_sender_ = SasSender::Create(); |
+ } |
+ |
+ if (sas_sender_.get() != NULL) { |
+ sas_sender_->Send(); |
+ } |
+ } |
+} |
+ |
void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) { |
DCHECK(state_ == StateDetached); |
DCHECK(!timer_.IsRunning()); |
DCHECK(process_.handle() == NULL); |
DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ DCHECK(chromoting_service_.get() == NULL); |
// Temporarily enable the SE_TCB_NAME privilege. The privileged token is |
// created as needed and kept for later reuse. |
@@ -250,7 +309,7 @@ void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) { |
return; |
} |
- // While the SE_TCB_NAME progolege is enabled, create a session token for |
+ // While the SE_TCB_NAME privilege is enabled, create a session token for |
// the launched process. |
bool result = CreateSessionToken(session_id, &session_token_); |
@@ -276,12 +335,14 @@ void WtsSessionProcessLauncher::OnSessionDetached() { |
DCHECK(!timer_.IsRunning()); |
DCHECK(process_.handle() == NULL); |
DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ DCHECK(chromoting_service_.get() == NULL); |
break; |
case StateStarting: |
DCHECK(timer_.IsRunning()); |
DCHECK(process_.handle() == NULL); |
DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ DCHECK(chromoting_service_.get() == NULL); |
timer_.Stop(); |
launch_backoff_ = base::TimeDelta(); |
@@ -292,10 +353,12 @@ void WtsSessionProcessLauncher::OnSessionDetached() { |
DCHECK(!timer_.IsRunning()); |
DCHECK(process_.handle() != NULL); |
DCHECK(process_watcher_.GetWatchedObject() != NULL); |
+ DCHECK(chromoting_service_.get() != NULL); |
process_watcher_.StopWatching(); |
process_.Terminate(0); |
process_.Close(); |
+ chromoting_service_.reset(); |
state_ = StateDetached; |
break; |
} |