Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1258)

Unified Diff: remoting/host/wts_session_process_launcher_win.cc

Issue 9617027: Chromoting: Implemented security attention sequence (SAS) emulation on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: - Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/wts_session_process_launcher_win.h ('k') | remoting/remoting.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..fa8b2b284a2528c2a87baf4c8758a23849c743b2 100644
--- a/remoting/host/wts_session_process_launcher_win.cc
+++ b/remoting/host/wts_session_process_launcher_win.cc
@@ -8,11 +8,23 @@
#include "remoting/host/wts_session_process_launcher_win.h"
#include <windows.h>
+#include <sddl.h>
+#include <limits>
#include "base/logging.h"
+#include "base/process_util.h"
+#include "base/rand_util.h"
+#include "base/string16.h"
+#include "base/stringprintf.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_messages.h"
+#include "remoting/host/sas_injector.h"
#include "remoting/host/wts_console_monitor_win.h"
using base::win::ScopedHandle;
@@ -28,6 +40,17 @@ const int kMinLaunchDelaySeconds = 1;
// Name of the default session desktop.
const char kDefaultDesktopName[] = "winsta0\\default";
+// Match the pipe name prefix used by Chrome IPC channels.
+const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome.";
+
+// Generates the command line of the host process.
+const char kHostProcessCommandLineFormat[] = "\"%ls\" --channel=%ls";
+
+// The security descriptor of the Chromoting IPC channel. It gives full access
+// to LocalSystem and denies access by anyone else.
+const char kChromotingChannelSecurityDescriptor[] =
+ "O:SY" "G:SY" "D:(A;;GA;;;SY)";
+
// Takes the process token and makes a copy of it. The returned handle will have
// |desired_access| rights.
bool CopyProcessToken(DWORD desired_access,
@@ -114,11 +137,74 @@ bool CreateSessionToken(uint32 session_id,
return true;
}
+// Generates random channel ID.
+// N.B. Stolen from src/content/common/child_process_host_impl.cc
+string16 GenerateRandomChannelId(void* instance) {
+ return base::StringPrintf(ASCIIToUTF16("%d.%p.%d").c_str(),
+ base::GetCurrentProcId(), instance,
+ base::RandInt(0, std::numeric_limits<int>::max()));
+}
+
+// Creates the server end of the Chromoting IPC channel.
+// N.B. This code is based on IPC::Channel's implementation.
+bool CreatePipeForIpcChannel(void* instance,
+ string16* channel_name_out,
+ ScopedHandle* pipe_out) {
+ // Create security descriptor for the channel.
+ SECURITY_ATTRIBUTES security_attributes;
+ security_attributes.nLength = sizeof(security_attributes);
+ security_attributes.bInheritHandle = FALSE;
+
+ ULONG security_descriptor_length = 0;
+ if (!ConvertStringSecurityDescriptorToSecurityDescriptorA(
+ kChromotingChannelSecurityDescriptor,
+ SDDL_REVISION_1,
+ reinterpret_cast<PSECURITY_DESCRIPTOR*>(
+ &security_attributes.lpSecurityDescriptor),
+ &security_descriptor_length)) {
+ LOG_GETLASTERROR(ERROR) <<
+ "Failed to create a security descriptor for the Chromoting IPC channel";
+ return false;
+ }
+
+ // Generate a random channel name.
+ string16 channel_name(GenerateRandomChannelId(instance));
+
+ // Convert it to the pipe name.
+ string16 pipe_name(ASCIIToUTF16(kChromePipeNamePrefix));
+ pipe_name.append(channel_name);
+
+ // Create the server end of the pipe. This code should match the code in
+ // IPC::Channel with exception of passing a non-default security descriptor.
+ HANDLE pipe = CreateNamedPipeW(pipe_name.c_str(),
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
+ FILE_FLAG_FIRST_PIPE_INSTANCE,
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
+ 1,
+ IPC::Channel::kReadBufferSize,
+ IPC::Channel::kReadBufferSize,
+ 5000,
+ &security_attributes);
+ if (pipe == INVALID_HANDLE_VALUE) {
+ LOG_GETLASTERROR(ERROR) <<
+ "Failed to create the server end of the Chromoting IPC channel";
+ LocalFree(security_attributes.lpSecurityDescriptor);
+ return false;
+ }
+
+ LocalFree(security_attributes.lpSecurityDescriptor);
+
+ *channel_name_out = channel_name;
+ pipe_out->Set(pipe);
+ return true;
+}
+
// Launches |binary| in the security context of the supplied |user_token|.
bool LaunchProcessAsUser(const FilePath& binary,
+ const string16& command_line,
HANDLE user_token,
base::Process* process_out) {
- string16 command_line = binary.value();
+ string16 application_name = binary.value();
string16 desktop = ASCIIToUTF16(kDefaultDesktopName);
PROCESS_INFORMATION process_info;
@@ -129,7 +215,7 @@ bool LaunchProcessAsUser(const FilePath& binary,
startup_info.lpDesktop = const_cast<LPWSTR>(desktop.c_str());
if (!CreateProcessAsUserW(user_token,
- command_line.c_str(),
+ application_name.c_str(),
const_cast<LPWSTR>(command_line.c_str()),
NULL,
NULL,
@@ -155,8 +241,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 +255,7 @@ WtsSessionProcessLauncher::~WtsSessionProcessLauncher() {
DCHECK(!timer_.IsRunning());
DCHECK(process_.handle() == NULL);
DCHECK(process_watcher_.GetWatchedObject() == NULL);
+ DCHECK(chromoting_channel_.get() == NULL);
monitor_->RemoveWtsConsoleObserver(this);
}
@@ -176,19 +265,40 @@ void WtsSessionProcessLauncher::LaunchProcess() {
DCHECK(!timer_.IsRunning());
DCHECK(process_.handle() == NULL);
DCHECK(process_watcher_.GetWatchedObject() == NULL);
+ DCHECK(chromoting_channel_.get() == NULL);
- // 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;
- return;
- } else {
- LOG(ERROR) << "Failed to arm the process watcher.";
- process_.Terminate(0);
- process_.Close();
+
+ string16 channel_name;
+ ScopedHandle pipe;
+ if (CreatePipeForIpcChannel(this, &channel_name, &pipe)) {
+ // Wrap the pipe into an IPC channel.
+ chromoting_channel_.reset(new IPC::ChannelProxy(
+ IPC::ChannelHandle(pipe.Get()),
+ IPC::Channel::MODE_SERVER,
+ this,
+ io_thread_->message_loop_proxy().get()));
+
+ string16 command_line =
+ base::StringPrintf(ASCIIToUTF16(kHostProcessCommandLineFormat).c_str(),
+ host_binary_.value().c_str(),
+ channel_name.c_str());
+
+ // Try to launch the process and attach an object watcher to the returned
+ // handle so that we get notified when the process terminates.
+ if (LaunchProcessAsUser(host_binary_, command_line, session_token_,
+ &process_)) {
+ if (process_watcher_.StartWatching(process_.handle(), this)) {
+ state_ = StateAttached;
+ return;
+ } else {
+ LOG(ERROR) << "Failed to arm the process watcher.";
+ process_.Terminate(0);
+ process_.Close();
+ }
}
+
+ chromoting_channel_.reset();
}
// Something went wrong. Try to launch the host again later. The attempts rate
@@ -206,10 +316,12 @@ void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) {
DCHECK(!timer_.IsRunning());
DCHECK(process_.handle() != NULL);
DCHECK(process_watcher_.GetWatchedObject() == NULL);
+ DCHECK(chromoting_channel_.get() != NULL);
// The host process has been terminated for some reason. The handle can now be
// closed.
process_.Close();
+ chromoting_channel_.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 +342,34 @@ 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(ChromotingHostMsg_SendSasToConsole,
+ OnSendSasToConsole)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void WtsSessionProcessLauncher::OnSendSasToConsole() {
+ if (state_ == StateAttached) {
+ if (sas_injector_.get() == NULL) {
+ sas_injector_ = SasInjector::Create();
+ }
+
+ if (sas_injector_.get() != NULL) {
+ sas_injector_->InjectSas();
+ }
+ }
+}
+
void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) {
DCHECK(state_ == StateDetached);
DCHECK(!timer_.IsRunning());
DCHECK(process_.handle() == NULL);
DCHECK(process_watcher_.GetWatchedObject() == NULL);
+ DCHECK(chromoting_channel_.get() == NULL);
// Temporarily enable the SE_TCB_NAME privilege. The privileged token is
// created as needed and kept for later reuse.
@@ -250,7 +385,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 +411,14 @@ void WtsSessionProcessLauncher::OnSessionDetached() {
DCHECK(!timer_.IsRunning());
DCHECK(process_.handle() == NULL);
DCHECK(process_watcher_.GetWatchedObject() == NULL);
+ DCHECK(chromoting_channel_.get() == NULL);
break;
case StateStarting:
DCHECK(timer_.IsRunning());
DCHECK(process_.handle() == NULL);
DCHECK(process_watcher_.GetWatchedObject() == NULL);
+ DCHECK(chromoting_channel_.get() == NULL);
timer_.Stop();
launch_backoff_ = base::TimeDelta();
@@ -292,10 +429,12 @@ void WtsSessionProcessLauncher::OnSessionDetached() {
DCHECK(!timer_.IsRunning());
DCHECK(process_.handle() != NULL);
DCHECK(process_watcher_.GetWatchedObject() != NULL);
+ DCHECK(chromoting_channel_.get() != NULL);
process_watcher_.StopWatching();
process_.Terminate(0);
process_.Close();
+ chromoting_channel_.reset();
state_ = StateDetached;
break;
}
« no previous file with comments | « remoting/host/wts_session_process_launcher_win.h ('k') | remoting/remoting.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698