[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 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 | |||||
Joe Downing | dbffadb | 2018-10-08 19:46:24 | [diff] [blame] | 7 | #include <memory> |
8 | #include <utility> | ||||
9 | |||||
Joe Downing | 7c84a3cc | 2021-08-26 00:28:43 | [diff] [blame] | 10 | #include "base/files/file_path.h" |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 11 | #include "base/logging.h" |
Joe Downing | 7c84a3cc | 2021-08-26 00:28:43 | [diff] [blame] | 12 | #include "base/scoped_native_library.h" |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 13 | #include "base/win/registry.h" |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 14 | |
15 | namespace remoting { | ||||
16 | |||||
17 | namespace { | ||||
18 | |||||
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 19 | // The registry key and value holding the policy controlling software SAS |
20 | // generation. | ||||
[email protected] | 8cdb83f | 2012-06-20 17:24:43 | [diff] [blame] | 21 | const wchar_t kSystemPolicyKeyName[] = |
22 | L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; | ||||
23 | const wchar_t kSoftwareSasValueName[] = L"SoftwareSASGeneration"; | ||||
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 24 | |
[email protected] | e8f8dcee | 2012-11-02 00:16:05 | [diff] [blame] | 25 | const DWORD kEnableSoftwareSasByServices = 1; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 26 | |
Joe Downing | 7c84a3cc | 2021-08-26 00:28:43 | [diff] [blame] | 27 | // https://docs.microsoft.com/en-us/windows/win32/api/sas/nf-sas-sendsas |
28 | typedef void(NTAPI* SendSASFunction)(BOOL); | ||||
29 | |||||
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 30 | // Toggles the default software SAS generation policy to enable SAS generation |
[email protected] | e8f8dcee | 2012-11-02 00:16:05 | [diff] [blame] | 31 | // by services. Non-default policy is not changed. |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 32 | class ScopedSoftwareSasPolicy { |
33 | public: | ||||
34 | ScopedSoftwareSasPolicy(); | ||||
Peter Boström | e9178e4 | 2021-09-22 18:11:49 | [diff] [blame] | 35 | |
36 | ScopedSoftwareSasPolicy(const ScopedSoftwareSasPolicy&) = delete; | ||||
37 | ScopedSoftwareSasPolicy& operator=(const ScopedSoftwareSasPolicy&) = delete; | ||||
38 | |||||
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 39 | ~ScopedSoftwareSasPolicy(); |
40 | |||||
41 | bool Apply(); | ||||
42 | |||||
43 | private: | ||||
44 | // The handle of the registry key were SoftwareSASGeneration policy is stored. | ||||
45 | base::win::RegKey system_policy_; | ||||
46 | |||||
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 47 | // True if the policy needs to be restored. |
Joe Downing | dbffadb | 2018-10-08 19:46:24 | [diff] [blame] | 48 | bool restore_policy_ = false; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 49 | }; |
50 | |||||
Joe Downing | dbffadb | 2018-10-08 19:46:24 | [diff] [blame] | 51 | ScopedSoftwareSasPolicy::ScopedSoftwareSasPolicy() = default; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 52 | |
53 | ScopedSoftwareSasPolicy::~ScopedSoftwareSasPolicy() { | ||||
54 | // Restore the default policy by deleting the value that we have set. | ||||
55 | if (restore_policy_) { | ||||
[email protected] | 96e2c55 | 2012-04-14 05:21:54 | [diff] [blame] | 56 | LONG result = system_policy_.DeleteValue(kSoftwareSasValueName); |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 57 | if (result != ERROR_SUCCESS) { |
58 | SetLastError(result); | ||||
[email protected] | ad8cfa9 | 2014-05-21 20:06:23 | [diff] [blame] | 59 | PLOG(ERROR) << "Failed to restore the software SAS generation policy"; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 60 | } |
61 | } | ||||
62 | } | ||||
63 | |||||
64 | bool ScopedSoftwareSasPolicy::Apply() { | ||||
65 | // Query the currently set SoftwareSASGeneration policy. | ||||
66 | LONG result = system_policy_.Open(HKEY_LOCAL_MACHINE, | ||||
[email protected] | 96e2c55 | 2012-04-14 05:21:54 | [diff] [blame] | 67 | kSystemPolicyKeyName, |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 68 | KEY_QUERY_VALUE | KEY_SET_VALUE | |
69 | KEY_WOW64_64KEY); | ||||
70 | if (result != ERROR_SUCCESS) { | ||||
71 | SetLastError(result); | ||||
[email protected] | ad8cfa9 | 2014-05-21 20:06:23 | [diff] [blame] | 72 | PLOG(ERROR) << "Failed to open 'HKLM\\" << kSystemPolicyKeyName << "'"; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 73 | return false; |
74 | } | ||||
75 | |||||
[email protected] | 96e2c55 | 2012-04-14 05:21:54 | [diff] [blame] | 76 | bool custom_policy = system_policy_.HasValue(kSoftwareSasValueName); |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 77 | |
78 | // Override the default policy (i.e. there is no value in the registry) only. | ||||
79 | if (!custom_policy) { | ||||
[email protected] | 96e2c55 | 2012-04-14 05:21:54 | [diff] [blame] | 80 | result = system_policy_.WriteValue(kSoftwareSasValueName, |
[email protected] | e8f8dcee | 2012-11-02 00:16:05 | [diff] [blame] | 81 | kEnableSoftwareSasByServices); |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 82 | if (result != ERROR_SUCCESS) { |
83 | SetLastError(result); | ||||
[email protected] | ad8cfa9 | 2014-05-21 20:06:23 | [diff] [blame] | 84 | PLOG(ERROR) << "Failed to enable software SAS generation by services"; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 85 | return false; |
86 | } else { | ||||
87 | restore_policy_ = true; | ||||
88 | } | ||||
89 | } | ||||
90 | |||||
91 | return true; | ||||
92 | } | ||||
93 | |||||
94 | } // namespace | ||||
95 | |||||
joedow | 19d55d3 | 2016-06-03 20:55:15 | [diff] [blame] | 96 | // Sends Secure Attention Sequence. Checks the current policy before sending. |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 97 | class SasInjectorWin : public SasInjector { |
98 | public: | ||||
99 | SasInjectorWin(); | ||||
Joe Downing | 7c84a3cc | 2021-08-26 00:28:43 | [diff] [blame] | 100 | SasInjectorWin(const SasInjectorWin&) = delete; |
101 | SasInjectorWin& operator=(const SasInjectorWin&) = delete; | ||||
nick | 697f429 | 2015-04-23 18:22:31 | [diff] [blame] | 102 | ~SasInjectorWin() override; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 103 | |
104 | // SasInjector implementation. | ||||
nick | 697f429 | 2015-04-23 18:22:31 | [diff] [blame] | 105 | bool InjectSas() override; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 106 | }; |
107 | |||||
Joe Downing | dbffadb | 2018-10-08 19:46:24 | [diff] [blame] | 108 | SasInjectorWin::SasInjectorWin() = default; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 109 | |
Joe Downing | dbffadb | 2018-10-08 19:46:24 | [diff] [blame] | 110 | SasInjectorWin::~SasInjectorWin() = default; |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 111 | |
112 | bool SasInjectorWin::InjectSas() { | ||||
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 113 | // Enable software SAS generation by services and send SAS. SAS can still fail |
[email protected] | e8f8dcee | 2012-11-02 00:16:05 | [diff] [blame] | 114 | // if the policy does not allow services to generate software SAS. |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 115 | ScopedSoftwareSasPolicy enable_sas; |
joedow | 19d55d3 | 2016-06-03 20:55:15 | [diff] [blame] | 116 | if (!enable_sas.Apply()) { |
Joe Downing | 7c84a3cc | 2021-08-26 00:28:43 | [diff] [blame] | 117 | LOG(ERROR) << "SAS policy could not be applied, skipping SAS injection."; |
[email protected] | b9a06b3 | 2012-08-17 23:52:13 | [diff] [blame] | 118 | return false; |
[email protected] | 6672f38 | 2012-11-15 17:37:01 | [diff] [blame] | 119 | } |
[email protected] | b9a06b3 | 2012-08-17 23:52:13 | [diff] [blame] | 120 | |
Joe Downing | 7c84a3cc | 2021-08-26 00:28:43 | [diff] [blame] | 121 | // Use LoadLibrary here as sas.dll is not consistently shipped on all Windows |
122 | // SKUs (notably server releases) and linking against it prevents the host | ||||
123 | // from starting correctly. | ||||
124 | bool sas_injected = false; | ||||
125 | base::ScopedNativeLibrary library(base::FilePath(L"sas.dll")); | ||||
126 | if (library.is_valid()) { | ||||
127 | SendSASFunction send_sas_func = reinterpret_cast<SendSASFunction>( | ||||
128 | library.GetFunctionPointer("SendSAS")); | ||||
129 | if (send_sas_func) { | ||||
130 | sas_injected = true; | ||||
131 | send_sas_func(/*AsUser=*/FALSE); | ||||
132 | } else { | ||||
133 | LOG(ERROR) << "SendSAS() not found in sas.dll, skipping SAS injection."; | ||||
134 | } | ||||
135 | } else { | ||||
136 | LOG(ERROR) << "sas.dll could not be loaded, skipping SAS injection."; | ||||
137 | } | ||||
138 | return sas_injected; | ||||
[email protected] | b9a06b3 | 2012-08-17 23:52:13 | [diff] [blame] | 139 | } |
140 | |||||
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 141 | std::unique_ptr<SasInjector> SasInjector::Create() { |
Joe Downing | dbffadb | 2018-10-08 19:46:24 | [diff] [blame] | 142 | return std::make_unique<SasInjectorWin>(); |
[email protected] | c2b37440 | 2012-03-12 19:23:07 | [diff] [blame] | 143 | } |
144 | |||||
145 | } // namespace remoting |