Commit b9a06b30 authored by alexeypa@chromium.org's avatar alexeypa@chromium.org

[Chromoting] Call SendSAS() directly from the host.

In order to call SendSAS() successfully the calling process's binary has to:
 - be signed.
 - be installed under %ProgramFiles% or %SystemRoot%\system32.
 - specify uiAccess='true' in the manifest.
 - run under SYSTEM or the currently logged-on user.

All of those requirements are met now, so SendSAS() can be called directly.

BUG=135217

Review URL: https://chromiumcodereview.appspot.com/10836224

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152191 0039d316-1c4b-4281-b951-d872f2087c98
parent 7eaa5920
......@@ -8,10 +8,3 @@
#include "ipc/ipc_message_macros.h"
#define IPC_MESSAGE_START ChromotingMsgStart
//-----------------------------------------------------------------------------
// The Chrmomoting session messages
// Asks the service to send the Secure Attention Sequence (SAS) to the current
// console session.
IPC_MESSAGE_CONTROL0(ChromotingHostMsg_SendSasToConsole)
......@@ -14,14 +14,15 @@
#include "base/utf_string_conversions.h"
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#include "remoting/host/win/desktop.h"
#include "remoting/host/win/scoped_thread_desktop.h"
namespace remoting {
namespace {
// Names of the API and library implementing software SAS generation.
const FilePath::CharType kSasDllFileName[] =
FILE_PATH_LITERAL("sas.dll");
const FilePath::CharType kSasDllFileName[] = FILE_PATH_LITERAL("sas.dll");
const char kSendSasName[] = "SendSAS";
// The prototype of SendSAS().
......@@ -33,10 +34,10 @@ const wchar_t kSystemPolicyKeyName[] =
L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
const wchar_t kSoftwareSasValueName[] = L"SoftwareSASGeneration";
const DWORD kEnableSoftwareSasByServices = 1;
const DWORD kEnableSoftwareSasByApps = 2;
// Toggles the default software SAS generation policy to enable SAS generation
// by services. Non-default policy is not changed.
// by applications. Non-default policy is not changed.
class ScopedSoftwareSasPolicy {
public:
ScopedSoftwareSasPolicy();
......@@ -88,7 +89,7 @@ bool ScopedSoftwareSasPolicy::Apply() {
// Override the default policy (i.e. there is no value in the registry) only.
if (!custom_policy) {
result = system_policy_.WriteValue(kSoftwareSasValueName,
kEnableSoftwareSasByServices);
kEnableSoftwareSasByApps);
if (result != ERROR_SUCCESS) {
SetLastError(result);
LOG_GETLASTERROR(ERROR)
......@@ -121,6 +122,18 @@ class SasInjectorWin : public SasInjector {
SendSasFunc send_sas_;
};
// Emulates Secure Attention Sequence (Ctrl+Alt+Del) by switching to
// the Winlogon desktop and injecting Ctrl+Alt+Del as a hot key.
// N.B. Windows XP/W2K3 only.
class SasInjectorXp : public SasInjector {
public:
SasInjectorXp();
virtual ~SasInjectorXp();
// SasInjector implementation.
virtual bool InjectSas() OVERRIDE;
};
SasInjectorWin::SasInjectorWin() : send_sas_(NULL) {
}
......@@ -157,7 +170,7 @@ bool SasInjectorWin::InjectSas() {
}
// Enable software SAS generation by services and send SAS. SAS can still fail
// if the policy does not allow services to generate software SAS.
// if the policy does not allow applications to generate software SAS.
ScopedSoftwareSasPolicy enable_sas;
if (!enable_sas.Apply())
return false;
......@@ -166,12 +179,43 @@ bool SasInjectorWin::InjectSas() {
return true;
}
SasInjectorXp::SasInjectorXp() {
}
SasInjectorXp::~SasInjectorXp() {
}
bool SasInjectorXp::InjectSas() {
const wchar_t kWinlogonDesktopName[] = L"Winlogon";
const wchar_t kSasWindowClassName[] = L"SAS window class";
const wchar_t kSasWindowTitle[] = L"SAS window";
scoped_ptr<remoting::Desktop> winlogon_desktop(
remoting::Desktop::GetDesktop(kWinlogonDesktopName));
if (!winlogon_desktop.get())
return false;
remoting::ScopedThreadDesktop desktop;
if (!desktop.SetThreadDesktop(winlogon_desktop.Pass()))
return false;
HWND window = FindWindow(kSasWindowClassName, kSasWindowTitle);
if (!window)
return false;
PostMessage(window,
WM_HOTKEY,
0,
MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));
return true;
}
scoped_ptr<SasInjector> SasInjector::Create() {
if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
if (base::win::GetVersion() < base::win::VERSION_VISTA) {
return scoped_ptr<SasInjector>(new SasInjectorXp());
} else {
return scoped_ptr<SasInjector>(new SasInjectorWin());
}
return scoped_ptr<SasInjector>();
}
} // namespace remoting
......@@ -14,15 +14,12 @@
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_proxy.h"
#include "remoting/host/chromoting_messages.h"
#include "remoting/host/sas_injector.h"
#include "remoting/host/win/desktop.h"
#include "remoting/host/win/scoped_thread_desktop.h"
#include "remoting/proto/event.pb.h"
namespace {
// The command line switch specifying the name of the Chromoting IPC channel.
const char kProcessChannelId[] = "chromoting-ipc";
const uint32 kUsbLeftControl = 0x0700e0;
const uint32 kUsbRightControl = 0x0700e4;
const uint32 kUsbLeftAlt = 0x0700e2;
......@@ -38,33 +35,6 @@ bool CheckCtrlAndAltArePressed(const std::set<uint32>& pressed_keys) {
(ctrl_keys + alt_keys == pressed_keys.size());
}
// Emulates Secure Attention Sequence (Ctrl+Alt+Del) by switching to
// the Winlogon desktop and injecting Ctrl+Alt+Del as a hot key.
// N.B. Windows XP/W2K3 only.
void EmulateSecureAttentionSequence() {
const wchar_t kWinlogonDesktopName[] = L"Winlogon";
const wchar_t kSasWindowClassName[] = L"SAS window class";
const wchar_t kSasWindowTitle[] = L"SAS window";
scoped_ptr<remoting::Desktop> winlogon_desktop(
remoting::Desktop::GetDesktop(kWinlogonDesktopName));
if (!winlogon_desktop.get())
return;
remoting::ScopedThreadDesktop desktop;
if (!desktop.SetThreadDesktop(winlogon_desktop.Pass()))
return;
HWND window = FindWindow(kSasWindowClassName, kSasWindowTitle);
if (!window)
return;
PostMessage(window,
WM_HOTKEY,
0,
MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));
}
} // namespace
namespace remoting {
......@@ -85,16 +55,6 @@ SessionEventExecutorWin::SessionEventExecutorWin(
// |weak_ptr_| and |weak_ptr_factory_| share a ThreadChecker, so the
// following line affects both of them.
weak_ptr_factory_.DetachFromThread();
std::string channel_name =
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kProcessChannelId);
// Connect to the Chromoting IPC channel if the name was passed in the command
// line.
if (!channel_name.empty()) {
chromoting_channel_.reset(new IPC::ChannelProxy(
channel_name, IPC::Channel::MODE_CLIENT, this, io_task_runner));
}
}
SessionEventExecutorWin::~SessionEventExecutorWin() {
......@@ -157,11 +117,9 @@ void SessionEventExecutorWin::InjectKeyEvent(const KeyEvent& event) {
CheckCtrlAndAltArePressed(pressed_keys_)) {
VLOG(3) << "Sending Secure Attention Sequence to console";
if (base::win::GetVersion() == base::win::VERSION_XP) {
EmulateSecureAttentionSequence();
} else if (chromoting_channel_.get()) {
chromoting_channel_->Send(new ChromotingHostMsg_SendSasToConsole());
}
if (sas_injector_.get() == NULL)
sas_injector_ = SasInjector::Create();
sas_injector_->InjectSas();
}
pressed_keys_.insert(event.usb_keycode());
......@@ -187,10 +145,6 @@ void SessionEventExecutorWin::InjectMouseEvent(const MouseEvent& event) {
nested_executor_->InjectMouseEvent(event);
}
bool SessionEventExecutorWin::OnMessageReceived(const IPC::Message& message) {
return false;
}
void SessionEventExecutorWin::SwitchToInputDesktop() {
// Switch to the desktop receiving user input if different from the current
// one.
......
......@@ -24,8 +24,9 @@ class ChannelProxy;
namespace remoting {
class SessionEventExecutorWin : public EventExecutor,
public IPC::Listener {
class SasInjector;
class SessionEventExecutorWin : public EventExecutor {
public:
SessionEventExecutorWin(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
......@@ -46,9 +47,6 @@ class SessionEventExecutorWin : public EventExecutor,
virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE;
virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE;
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
private:
// Switches to the desktop receiving a user input if different from
// the current one.
......@@ -61,8 +59,7 @@ class SessionEventExecutorWin : public EventExecutor,
ScopedThreadDesktop desktop_;
// The Chromoting IPC channel connecting the host with the service.
scoped_ptr<IPC::ChannelProxy> chromoting_channel_;
scoped_ptr<SasInjector> sas_injector_;
// Keys currently pressed by the client, used to detect Ctrl-Alt-Del.
std::set<uint32> pressed_keys_;
......
......@@ -30,7 +30,6 @@
#include "ipc/ipc_message_macros.h"
#include "remoting/host/constants.h"
#include "remoting/host/chromoting_messages.h"
#include "remoting/host/sas_injector.h"
#include "remoting/host/win/launch_process_with_token.h"
#include "remoting/host/win/wts_console_monitor.h"
......@@ -207,13 +206,7 @@ void WtsSessionProcessLauncher::OnChannelConnected() {
bool WtsSessionProcessLauncher::OnMessageReceived(const IPC::Message& message) {
DCHECK(main_message_loop_->BelongsToCurrentThread());
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;
return false;
}
void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) {
......@@ -441,18 +434,4 @@ void WtsSessionProcessLauncher::OnLauncherStopped() {
}
}
void WtsSessionProcessLauncher::OnSendSasToConsole() {
DCHECK(main_message_loop_->BelongsToCurrentThread());
if (attached_) {
if (sas_injector_.get() == NULL) {
sas_injector_ = SasInjector::Create();
}
if (sas_injector_.get() != NULL) {
sas_injector_->InjectSas();
}
}
}
} // namespace remoting
......@@ -32,7 +32,6 @@ class Message;
namespace remoting {
class SasInjector;
class WtsConsoleMonitor;
class WtsSessionProcessLauncher
......@@ -99,10 +98,6 @@ class WtsSessionProcessLauncher
// Called when the launcher reports the process to be stopped.
void OnLauncherStopped();
// Sends the Secure Attention Sequence to the session represented by
// |session_token_|.
void OnSendSasToConsole();
// |true| if this object is currently attached to the console session.
bool attached_;
......@@ -147,8 +142,6 @@ class WtsSessionProcessLauncher
// The token to be used to launch a process in a different session.
base::win::ScopedHandle session_token_;
scoped_ptr<SasInjector> sas_injector_;
DISALLOW_COPY_AND_ASSIGN(WtsSessionProcessLauncher);
};
......
......@@ -597,8 +597,6 @@
'host/daemon_process.cc',
'host/daemon_process.h',
'host/daemon_process_win.cc',
'host/sas_injector.h',
'host/sas_injector_win.cc',
'host/usage_stats_consent.h',
'host/usage_stats_consent_win.cc',
'host/win/host_service.cc',
......@@ -1274,6 +1272,8 @@
'host/register_support_host_request.h',
'host/remote_input_filter.cc',
'host/remote_input_filter.h',
'host/sas_injector.h',
'host/sas_injector_win.cc',
'host/screen_recorder.cc',
'host/screen_recorder.h',
'host/server_log_entry.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment