| Index: remoting/host/sas_injector_win.cc
|
| diff --git a/remoting/host/sas_injector_win.cc b/remoting/host/sas_injector_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3dd55f1cf32f6c09ef6ec298c7a8a21e2fba5bbe
|
| --- /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
|
|
|