diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-12 19:23:07 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-12 19:23:07 +0000 |
commit | c2b374409956cdad6d90ae6913f02251b09d8280 (patch) | |
tree | 7b0d440a0685ff903a8bbe846ff57917b5731901 /remoting/host/sas_injector_win.cc | |
parent | 0ab8bf8880a7ede55591fefb0e1162dc1a6f33f0 (diff) | |
download | chromium_src-c2b374409956cdad6d90ae6913f02251b09d8280.zip chromium_src-c2b374409956cdad6d90ae6913f02251b09d8280.tar.gz chromium_src-c2b374409956cdad6d90ae6913f02251b09d8280.tar.bz2 |
Chromoting: Implemented security attention sequence (SAS) emulation on Windows.
The default SAS is Ctrl+Alt+Delete. It can neither be intercepted by the client (at least on Windows) nor it can be injected the same way other key strokes are injected. This CL makes the Windows host to interpret a double Scroll Lock as a SAS and invoke the Chromoting service to issue the actual SAS.
Review URL: http://codereview.chromium.org/9617027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126186 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host/sas_injector_win.cc')
-rw-r--r-- | remoting/host/sas_injector_win.cc | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/remoting/host/sas_injector_win.cc b/remoting/host/sas_injector_win.cc new file mode 100644 index 0000000..3dd55f1 --- /dev/null +++ b/remoting/host/sas_injector_win.cc @@ -0,0 +1,186 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/host/sas_injector.h" + +#include <windows.h> +#include <string> + +#include "base/logging.h" +#include "base/file_path.h" +#include "base/native_library.h" +#include "base/path_service.h" +#include "base/utf_string_conversions.h" +#include "base/win/registry.h" +#include "base/win/windows_version.h" + +namespace remoting { + +namespace { + +// Names of the API and library implementing software SAS generation. +const FilePath::CharType kSasDllFileName[] = + FILE_PATH_LITERAL("sas.dll"); +const char kSendSasName[] = "SendSAS"; + +// The prototype of SendSAS(). +typedef VOID (WINAPI *SendSasFunc)(BOOL); + +// The registry key and value holding the policy controlling software SAS +// generation. +const char kSystemPolicyKeyName[] = + "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; +const char kSoftwareSasValueName[] = "SoftwareSASGeneration"; + +const DWORD kEnableSoftwareSasByServices = 1; + +// Toggles the default software SAS generation policy to enable SAS generation +// by services. Non-default policy is not changed. +class ScopedSoftwareSasPolicy { + public: + ScopedSoftwareSasPolicy(); + ~ScopedSoftwareSasPolicy(); + + bool Apply(); + + private: + // The handle of the registry key were SoftwareSASGeneration policy is stored. + base::win::RegKey system_policy_; + + // Name of the registry value holding the policy. + string16 value_name_; + + // True if the policy needs to be restored. + bool restore_policy_; + + DISALLOW_COPY_AND_ASSIGN(ScopedSoftwareSasPolicy); +}; + +ScopedSoftwareSasPolicy::ScopedSoftwareSasPolicy() + : restore_policy_(false) { +} + +ScopedSoftwareSasPolicy::~ScopedSoftwareSasPolicy() { + // Restore the default policy by deleting the value that we have set. + if (restore_policy_) { + LONG result = system_policy_.DeleteValue(value_name_.c_str()); + if (result != ERROR_SUCCESS) { + SetLastError(result); + LOG_GETLASTERROR(ERROR) + << "Failed to restore the software SAS generation policy"; + } + } +} + +bool ScopedSoftwareSasPolicy::Apply() { + // Query the currently set SoftwareSASGeneration policy. + LONG result = system_policy_.Open(HKEY_LOCAL_MACHINE, + ASCIIToUTF16(kSystemPolicyKeyName).c_str(), + KEY_QUERY_VALUE | KEY_SET_VALUE | + KEY_WOW64_64KEY); + if (result != ERROR_SUCCESS) { + SetLastError(result); + LOG_GETLASTERROR(ERROR) << "Failed to open 'HKLM\\" + << kSystemPolicyKeyName << "'"; + return false; + } + + value_name_ = ASCIIToUTF16(kSoftwareSasValueName); + bool custom_policy = system_policy_.HasValue(value_name_.c_str()); + + // Override the default policy (i.e. there is no value in the registry) only. + if (!custom_policy) { + result = system_policy_.WriteValue(value_name_.c_str(), + kEnableSoftwareSasByServices); + if (result != ERROR_SUCCESS) { + SetLastError(result); + LOG_GETLASTERROR(ERROR) + << "Failed to enable software SAS generation by services"; + return false; + } else { + restore_policy_ = true; + } + } + + return true; +} + +} // namespace + +// Sends the Secure Attention Sequence using the SendSAS() function from +// sas.dll. This library is shipped starting from Win7/W2K8 R2 only. However +// Win7 SDK includes a redistributable verion of the same library that works on +// Vista/W2K8. We install the latter along with our binaries. +class SasInjectorWin : public SasInjector { + public: + SasInjectorWin(); + virtual ~SasInjectorWin(); + + // SasInjector implementation. + virtual bool InjectSas() OVERRIDE; + + private: + base::NativeLibrary sas_dll_; + SendSasFunc send_sas_; +}; + +SasInjectorWin::SasInjectorWin() : sas_dll_(NULL), send_sas_(NULL) { +} + +SasInjectorWin::~SasInjectorWin() { + if (sas_dll_ != NULL) { + base::UnloadNativeLibrary(sas_dll_); + } +} + +bool SasInjectorWin::InjectSas() { + // Load sas.dll. The library is expected to be in the same folder as this + // binary. + if (sas_dll_ == NULL) { + FilePath exe_path; + if (!PathService::Get(base::FILE_EXE, &exe_path)) { + LOG(ERROR) << "Failed to get the executable file name."; + return false; + } + + std::string error; + sas_dll_ = base::LoadNativeLibrary( + exe_path.DirName().Append(kSasDllFileName), + &error); + if (sas_dll_ == NULL) { + LOG(ERROR) << "Failed to load '" << kSasDllFileName << "'"; + return false; + } + } + + // Get the pointer to sas!SendSAS(). + if (send_sas_ == NULL) { + send_sas_ = reinterpret_cast<SendSasFunc>( + base::GetFunctionPointerFromNativeLibrary(sas_dll_, kSendSasName)); + if (send_sas_ == NULL) { + LOG(ERROR) << "Failed to retrieve the address of '" << kSendSasName + << "()'"; + return false; + } + } + + // Enable software SAS generation by services and send SAS. SAS can still fail + // if the policy does not allow services to generate software SAS. + ScopedSoftwareSasPolicy enable_sas; + if (!enable_sas.Apply()) + return false; + + (*send_sas_)(FALSE); + return true; +} + +scoped_ptr<SasInjector> SasInjector::Create() { + if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { + return scoped_ptr<SasInjector>(new SasInjectorWin()); + } + + return scoped_ptr<SasInjector>(); +} + +} // namespace remoting |