1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "remoting/host/sas_injector.h" 6 7 #include <windows.h> 8 #include <sas.h> 9 10 #include <memory> 11 #include <utility> 12 13 #include "base/logging.h" 14 #include "base/macros.h" 15 #include "base/win/registry.h" 16 17 namespace remoting { 18 19 namespace { 20 21 // The registry key and value holding the policy controlling software SAS 22 // generation. 23 const wchar_t kSystemPolicyKeyName[] = 24 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; 25 const wchar_t kSoftwareSasValueName[] = L"SoftwareSASGeneration"; 26 27 const DWORD kEnableSoftwareSasByServices = 1; 28 29 // Toggles the default software SAS generation policy to enable SAS generation 30 // by services. Non-default policy is not changed. 31 class ScopedSoftwareSasPolicy { 32 public: 33 ScopedSoftwareSasPolicy(); 34 ~ScopedSoftwareSasPolicy(); 35 36 bool Apply(); 37 38 private: 39 // The handle of the registry key were SoftwareSASGeneration policy is stored. 40 base::win::RegKey system_policy_; 41 42 // True if the policy needs to be restored. 43 bool restore_policy_ = false; 44 45 DISALLOW_COPY_AND_ASSIGN(ScopedSoftwareSasPolicy); 46 }; 47 48 ScopedSoftwareSasPolicy::ScopedSoftwareSasPolicy() = default; 49 ~ScopedSoftwareSasPolicy()50ScopedSoftwareSasPolicy::~ScopedSoftwareSasPolicy() { 51 // Restore the default policy by deleting the value that we have set. 52 if (restore_policy_) { 53 LONG result = system_policy_.DeleteValue(kSoftwareSasValueName); 54 if (result != ERROR_SUCCESS) { 55 SetLastError(result); 56 PLOG(ERROR) << "Failed to restore the software SAS generation policy"; 57 } 58 } 59 } 60 Apply()61bool ScopedSoftwareSasPolicy::Apply() { 62 // Query the currently set SoftwareSASGeneration policy. 63 LONG result = system_policy_.Open(HKEY_LOCAL_MACHINE, 64 kSystemPolicyKeyName, 65 KEY_QUERY_VALUE | KEY_SET_VALUE | 66 KEY_WOW64_64KEY); 67 if (result != ERROR_SUCCESS) { 68 SetLastError(result); 69 PLOG(ERROR) << "Failed to open 'HKLM\\" << kSystemPolicyKeyName << "'"; 70 return false; 71 } 72 73 bool custom_policy = system_policy_.HasValue(kSoftwareSasValueName); 74 75 // Override the default policy (i.e. there is no value in the registry) only. 76 if (!custom_policy) { 77 result = system_policy_.WriteValue(kSoftwareSasValueName, 78 kEnableSoftwareSasByServices); 79 if (result != ERROR_SUCCESS) { 80 SetLastError(result); 81 PLOG(ERROR) << "Failed to enable software SAS generation by services"; 82 return false; 83 } else { 84 restore_policy_ = true; 85 } 86 } 87 88 return true; 89 } 90 91 } // namespace 92 93 // Sends Secure Attention Sequence. Checks the current policy before sending. 94 class SasInjectorWin : public SasInjector { 95 public: 96 SasInjectorWin(); 97 ~SasInjectorWin() override; 98 99 // SasInjector implementation. 100 bool InjectSas() override; 101 102 private: 103 DISALLOW_COPY_AND_ASSIGN(SasInjectorWin); 104 }; 105 106 SasInjectorWin::SasInjectorWin() = default; 107 108 SasInjectorWin::~SasInjectorWin() = default; 109 InjectSas()110bool SasInjectorWin::InjectSas() { 111 // Enable software SAS generation by services and send SAS. SAS can still fail 112 // if the policy does not allow services to generate software SAS. 113 ScopedSoftwareSasPolicy enable_sas; 114 if (!enable_sas.Apply()) { 115 return false; 116 } 117 118 SendSAS(/*AsUser=*/FALSE); 119 return true; 120 } 121 Create()122std::unique_ptr<SasInjector> SasInjector::Create() { 123 return std::make_unique<SasInjectorWin>(); 124 } 125 126 } // namespace remoting 127