Chromium Code Reviews| 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; |
| } |