Chromium Code Reviews| Index: remoting/host/sas_sender_win.cc |
| diff --git a/remoting/host/sas_sender_win.cc b/remoting/host/sas_sender_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..12ffa0b6cbc252503e65f8e3f53a642bdb48444c |
| --- /dev/null |
| +++ b/remoting/host/sas_sender_win.cc |
| @@ -0,0 +1,185 @@ |
| +// 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_sender_win.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 channged. |
| +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 security 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 SasSenderVista : public SasSender { |
|
Wez
2012/03/07 01:56:13
Why is this SasSanderVista rather than SasSenderWi
alexeypa (please no reviews)
2012/03/07 19:59:08
Because, potentially, we can have a different impl
Wez
2012/03/08 00:01:33
That's fine - this version is SasSenderWin, and on
alexeypa (please no reviews)
2012/03/08 01:52:54
Once we do that the naming will become odd: why is
|
| + public: |
| + SasSenderVista(); |
| + virtual ~SasSenderVista(); |
| + |
| + // SasSender implementation. |
| + virtual bool Send() OVERRIDE; |
| + |
| + private: |
| + base::NativeLibrary sas_dll_; |
| + SendSasFunc send_sas_; |
| +}; |
| + |
| +SasSenderVista::SasSenderVista() : sas_dll_(NULL), send_sas_(NULL) { |
| +} |
| + |
| +SasSenderVista::~SasSenderVista() { |
| + if (sas_dll_ != NULL) { |
| + base::UnloadNativeLibrary(sas_dll_); |
| + } |
| +} |
| + |
| +bool SasSenderVista::Send() { |
| + // Load sas.dll. The library is expected to be in |
| + // the same folder as this binary. |
|
Wez
2012/03/07 01:56:13
nit: Premature line-wrap.
alexeypa (please no reviews)
2012/03/07 19:59:08
Done.
|
| + 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 applow services to generate software SAS. |
|
Wez
2012/03/07 01:56:13
typo: allow
alexeypa (please no reviews)
2012/03/07 19:59:08
Done.
|
| + ScopedSoftwareSasPolicy enable_sas; |
| + if (enable_sas.Apply()) { |
| + (*send_sas_)(FALSE); |
|
Wez
2012/03/07 01:56:13
Is it a problem for us to call SendSAS if the poli
alexeypa (please no reviews)
2012/03/07 19:59:08
Yes. It does nothing if the policy is not enabled.
Wez
2012/03/08 00:01:33
So we shouldn't be testing the result of |enable_s
alexeypa (please no reviews)
2012/03/08 01:52:54
No, we should. False means 'something is badly wro
|
| + } |
| + |
| + return true; |
|
Wez
2012/03/07 01:56:13
Do you mean to return true whether or not the poli
alexeypa (please no reviews)
2012/03/07 19:59:08
Yes. False is returned only if any of the operatio
Wez
2012/03/08 00:01:33
Is it worth returning false, in that case, since t
alexeypa (please no reviews)
2012/03/08 01:52:54
We should (and do) behave differently. See above.
|
| +} |
| + |
| +scoped_ptr<SasSender> SasSender::Create() { |
| + if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { |
| + return scoped_ptr<SasSender>(new SasSenderVista()); |
| + } |
| + |
| + return scoped_ptr<SasSender>(); |
| +} |
| + |
| +} // namespace remoting |