OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/win/elevated_controller.h" | 5 #include "remoting/host/win/elevated_controller.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/file_version_info.h" | 8 #include "base/file_version_info.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 // The maximum size of the configuration file. "1MB ought to be enough" for any | 28 // The maximum size of the configuration file. "1MB ought to be enough" for any |
29 // reasonable configuration we will ever need. 1MB is low enough to make | 29 // reasonable configuration we will ever need. 1MB is low enough to make |
30 // the probability of out of memory situation fairly low. OOM is still possible | 30 // the probability of out of memory situation fairly low. OOM is still possible |
31 // and we will crash if it occurs. | 31 // and we will crash if it occurs. |
32 const size_t kMaxConfigFileSize = 1024 * 1024; | 32 const size_t kMaxConfigFileSize = 1024 * 1024; |
33 | 33 |
34 // The host configuration file name. | 34 // The host configuration file name. |
35 const FilePath::CharType kConfigFileName[] = FILE_PATH_LITERAL("host.json"); | 35 const base::FilePath::CharType kConfigFileName[] = FILE_PATH_LITERAL("host.json"
); |
36 | 36 |
37 // The unprivileged configuration file name. | 37 // The unprivileged configuration file name. |
38 const FilePath::CharType kUnprivilegedConfigFileName[] = | 38 const base::FilePath::CharType kUnprivilegedConfigFileName[] = |
39 FILE_PATH_LITERAL("host_unprivileged.json"); | 39 FILE_PATH_LITERAL("host_unprivileged.json"); |
40 | 40 |
41 // The extension for the temporary file. | 41 // The extension for the temporary file. |
42 const FilePath::CharType kTempFileExtension[] = FILE_PATH_LITERAL("json~"); | 42 const base::FilePath::CharType kTempFileExtension[] = FILE_PATH_LITERAL("json~")
; |
43 | 43 |
44 // The host configuration file security descriptor that enables full access to | 44 // The host configuration file security descriptor that enables full access to |
45 // Local System and built-in administrators only. | 45 // Local System and built-in administrators only. |
46 const char kConfigFileSecurityDescriptor[] = | 46 const char kConfigFileSecurityDescriptor[] = |
47 "O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)"; | 47 "O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)"; |
48 | 48 |
49 const char kUnprivilegedConfigFileSecurityDescriptor[] = | 49 const char kUnprivilegedConfigFileSecurityDescriptor[] = |
50 "O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;AU)"; | 50 "O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;AU)"; |
51 | 51 |
52 // Configuration keys. | 52 // Configuration keys. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 } | 85 } |
86 | 86 |
87 hr = CoRevertToSelf(); | 87 hr = CoRevertToSelf(); |
88 CHECK(SUCCEEDED(hr)); | 88 CHECK(SUCCEEDED(hr)); |
89 | 89 |
90 return !!result; | 90 return !!result; |
91 } | 91 } |
92 | 92 |
93 // Reads and parses the configuration file up to |kMaxConfigFileSize| in | 93 // Reads and parses the configuration file up to |kMaxConfigFileSize| in |
94 // size. | 94 // size. |
95 HRESULT ReadConfig(const FilePath& filename, | 95 HRESULT ReadConfig(const base::FilePath& filename, |
96 scoped_ptr<base::DictionaryValue>* config_out) { | 96 scoped_ptr<base::DictionaryValue>* config_out) { |
97 | 97 |
98 // Read raw data from the configuration file. | 98 // Read raw data from the configuration file. |
99 base::win::ScopedHandle file( | 99 base::win::ScopedHandle file( |
100 CreateFileW(filename.value().c_str(), | 100 CreateFileW(filename.value().c_str(), |
101 GENERIC_READ, | 101 GENERIC_READ, |
102 FILE_SHARE_READ | FILE_SHARE_WRITE, | 102 FILE_SHARE_READ | FILE_SHARE_WRITE, |
103 NULL, | 103 NULL, |
104 OPEN_EXISTING, | 104 OPEN_EXISTING, |
105 FILE_FLAG_SEQUENTIAL_SCAN, | 105 FILE_FLAG_SEQUENTIAL_SCAN, |
(...skipping 24 matching lines...) Expand all Loading... |
130 if (value.get() == NULL || !value->GetAsDictionary(&dictionary)) { | 130 if (value.get() == NULL || !value->GetAsDictionary(&dictionary)) { |
131 LOG(ERROR) << "Failed to read '" << filename.value() << "'."; | 131 LOG(ERROR) << "Failed to read '" << filename.value() << "'."; |
132 return E_FAIL; | 132 return E_FAIL; |
133 } | 133 } |
134 | 134 |
135 value.release(); | 135 value.release(); |
136 config_out->reset(dictionary); | 136 config_out->reset(dictionary); |
137 return S_OK; | 137 return S_OK; |
138 } | 138 } |
139 | 139 |
140 FilePath GetTempLocationFor(const FilePath& filename) { | 140 base::FilePath GetTempLocationFor(const base::FilePath& filename) { |
141 return filename.ReplaceExtension(kTempFileExtension); | 141 return filename.ReplaceExtension(kTempFileExtension); |
142 } | 142 } |
143 | 143 |
144 // Writes a config file to a temporary location. | 144 // Writes a config file to a temporary location. |
145 HRESULT WriteConfigFileToTemp(const FilePath& filename, | 145 HRESULT WriteConfigFileToTemp(const base::FilePath& filename, |
146 const char* security_descriptor, | 146 const char* security_descriptor, |
147 const char* content, | 147 const char* content, |
148 size_t length) { | 148 size_t length) { |
149 // Create the security descriptor for the configuration file. | 149 // Create the security descriptor for the configuration file. |
150 ScopedSd sd = ConvertSddlToSd(security_descriptor); | 150 ScopedSd sd = ConvertSddlToSd(security_descriptor); |
151 if (!sd) { | 151 if (!sd) { |
152 DWORD error = GetLastError(); | 152 DWORD error = GetLastError(); |
153 LOG_GETLASTERROR(ERROR) << | 153 LOG_GETLASTERROR(ERROR) << |
154 "Failed to create a security descriptor for the configuration file"; | 154 "Failed to create a security descriptor for the configuration file"; |
155 return HRESULT_FROM_WIN32(error); | 155 return HRESULT_FROM_WIN32(error); |
156 } | 156 } |
157 | 157 |
158 SECURITY_ATTRIBUTES security_attributes = {0}; | 158 SECURITY_ATTRIBUTES security_attributes = {0}; |
159 security_attributes.nLength = sizeof(security_attributes); | 159 security_attributes.nLength = sizeof(security_attributes); |
160 security_attributes.lpSecurityDescriptor = sd.get(); | 160 security_attributes.lpSecurityDescriptor = sd.get(); |
161 security_attributes.bInheritHandle = FALSE; | 161 security_attributes.bInheritHandle = FALSE; |
162 | 162 |
163 // Create a temporary file and write configuration to it. | 163 // Create a temporary file and write configuration to it. |
164 FilePath tempname = GetTempLocationFor(filename); | 164 base::FilePath tempname = GetTempLocationFor(filename); |
165 base::win::ScopedHandle file( | 165 base::win::ScopedHandle file( |
166 CreateFileW(tempname.value().c_str(), | 166 CreateFileW(tempname.value().c_str(), |
167 GENERIC_WRITE, | 167 GENERIC_WRITE, |
168 0, | 168 0, |
169 &security_attributes, | 169 &security_attributes, |
170 CREATE_ALWAYS, | 170 CREATE_ALWAYS, |
171 FILE_FLAG_SEQUENTIAL_SCAN, | 171 FILE_FLAG_SEQUENTIAL_SCAN, |
172 NULL)); | 172 NULL)); |
173 | 173 |
174 if (!file.IsValid()) { | 174 if (!file.IsValid()) { |
175 DWORD error = GetLastError(); | 175 DWORD error = GetLastError(); |
176 LOG_GETLASTERROR(ERROR) | 176 LOG_GETLASTERROR(ERROR) |
177 << "Failed to create '" << filename.value() << "'"; | 177 << "Failed to create '" << filename.value() << "'"; |
178 return HRESULT_FROM_WIN32(error); | 178 return HRESULT_FROM_WIN32(error); |
179 } | 179 } |
180 | 180 |
181 DWORD written; | 181 DWORD written; |
182 if (!WriteFile(file, content, static_cast<DWORD>(length), &written, NULL)) { | 182 if (!WriteFile(file, content, static_cast<DWORD>(length), &written, NULL)) { |
183 DWORD error = GetLastError(); | 183 DWORD error = GetLastError(); |
184 LOG_GETLASTERROR(ERROR) | 184 LOG_GETLASTERROR(ERROR) |
185 << "Failed to write to '" << filename.value() << "'"; | 185 << "Failed to write to '" << filename.value() << "'"; |
186 return HRESULT_FROM_WIN32(error); | 186 return HRESULT_FROM_WIN32(error); |
187 } | 187 } |
188 | 188 |
189 return S_OK; | 189 return S_OK; |
190 } | 190 } |
191 | 191 |
192 // Moves a config file from its temporary location to its permanent location. | 192 // Moves a config file from its temporary location to its permanent location. |
193 HRESULT MoveConfigFileFromTemp(const FilePath& filename) { | 193 HRESULT MoveConfigFileFromTemp(const base::FilePath& filename) { |
194 // Now that the configuration is stored successfully replace the actual | 194 // Now that the configuration is stored successfully replace the actual |
195 // configuration file. | 195 // configuration file. |
196 FilePath tempname = GetTempLocationFor(filename); | 196 base::FilePath tempname = GetTempLocationFor(filename); |
197 if (!MoveFileExW(tempname.value().c_str(), | 197 if (!MoveFileExW(tempname.value().c_str(), |
198 filename.value().c_str(), | 198 filename.value().c_str(), |
199 MOVEFILE_REPLACE_EXISTING)) { | 199 MOVEFILE_REPLACE_EXISTING)) { |
200 DWORD error = GetLastError(); | 200 DWORD error = GetLastError(); |
201 LOG_GETLASTERROR(ERROR) | 201 LOG_GETLASTERROR(ERROR) |
202 << "Failed to rename '" << tempname.value() << "' to '" | 202 << "Failed to rename '" << tempname.value() << "' to '" |
203 << filename.value() << "'"; | 203 << filename.value() << "'"; |
204 return HRESULT_FROM_WIN32(error); | 204 return HRESULT_FROM_WIN32(error); |
205 } | 205 } |
206 | 206 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 const char* key = kUnprivilegedConfigKeys[i]; | 246 const char* key = kUnprivilegedConfigKeys[i]; |
247 string16 value; | 247 string16 value; |
248 if (config_dict->GetString(key, &value)) { | 248 if (config_dict->GetString(key, &value)) { |
249 unprivileged_config_dict.SetString(key, value); | 249 unprivileged_config_dict.SetString(key, value); |
250 } | 250 } |
251 } | 251 } |
252 std::string unprivileged_config_str; | 252 std::string unprivileged_config_str; |
253 base::JSONWriter::Write(&unprivileged_config_dict, &unprivileged_config_str); | 253 base::JSONWriter::Write(&unprivileged_config_dict, &unprivileged_config_str); |
254 | 254 |
255 // Write the full configuration file to a temporary location. | 255 // Write the full configuration file to a temporary location. |
256 FilePath full_config_file_path = | 256 base::FilePath full_config_file_path = |
257 remoting::GetConfigDir().Append(kConfigFileName); | 257 remoting::GetConfigDir().Append(kConfigFileName); |
258 HRESULT hr = WriteConfigFileToTemp(full_config_file_path, | 258 HRESULT hr = WriteConfigFileToTemp(full_config_file_path, |
259 kConfigFileSecurityDescriptor, | 259 kConfigFileSecurityDescriptor, |
260 content, | 260 content, |
261 length); | 261 length); |
262 if (FAILED(hr)) { | 262 if (FAILED(hr)) { |
263 return hr; | 263 return hr; |
264 } | 264 } |
265 | 265 |
266 // Write the unprivileged configuration file to a temporary location. | 266 // Write the unprivileged configuration file to a temporary location. |
267 FilePath unprivileged_config_file_path = | 267 base::FilePath unprivileged_config_file_path = |
268 remoting::GetConfigDir().Append(kUnprivilegedConfigFileName); | 268 remoting::GetConfigDir().Append(kUnprivilegedConfigFileName); |
269 hr = WriteConfigFileToTemp(unprivileged_config_file_path, | 269 hr = WriteConfigFileToTemp(unprivileged_config_file_path, |
270 kUnprivilegedConfigFileSecurityDescriptor, | 270 kUnprivilegedConfigFileSecurityDescriptor, |
271 unprivileged_config_str.data(), | 271 unprivileged_config_str.data(), |
272 unprivileged_config_str.size()); | 272 unprivileged_config_str.size()); |
273 if (FAILED(hr)) { | 273 if (FAILED(hr)) { |
274 return hr; | 274 return hr; |
275 } | 275 } |
276 | 276 |
277 // Move the full configuration file to its permanent location. | 277 // Move the full configuration file to its permanent location. |
(...skipping 17 matching lines...) Expand all Loading... |
295 } | 295 } |
296 | 296 |
297 HRESULT ElevatedController::FinalConstruct() { | 297 HRESULT ElevatedController::FinalConstruct() { |
298 return S_OK; | 298 return S_OK; |
299 } | 299 } |
300 | 300 |
301 void ElevatedController::FinalRelease() { | 301 void ElevatedController::FinalRelease() { |
302 } | 302 } |
303 | 303 |
304 STDMETHODIMP ElevatedController::GetConfig(BSTR* config_out) { | 304 STDMETHODIMP ElevatedController::GetConfig(BSTR* config_out) { |
305 FilePath config_dir = remoting::GetConfigDir(); | 305 base::FilePath config_dir = remoting::GetConfigDir(); |
306 | 306 |
307 // Read the unprivileged part of host configuration. | 307 // Read the unprivileged part of host configuration. |
308 scoped_ptr<base::DictionaryValue> config; | 308 scoped_ptr<base::DictionaryValue> config; |
309 HRESULT hr = ReadConfig(config_dir.Append(kUnprivilegedConfigFileName), | 309 HRESULT hr = ReadConfig(config_dir.Append(kUnprivilegedConfigFileName), |
310 &config); | 310 &config); |
311 if (FAILED(hr)) { | 311 if (FAILED(hr)) { |
312 return hr; | 312 return hr; |
313 } | 313 } |
314 | 314 |
315 // Convert the config back to a string and return it to the caller. | 315 // Convert the config back to a string and return it to the caller. |
(...skipping 24 matching lines...) Expand all Loading... |
340 *version_out = ::SysAllocString(version.c_str()); | 340 *version_out = ::SysAllocString(version.c_str()); |
341 if (version_out == NULL) { | 341 if (version_out == NULL) { |
342 return E_OUTOFMEMORY; | 342 return E_OUTOFMEMORY; |
343 } | 343 } |
344 | 344 |
345 return S_OK; | 345 return S_OK; |
346 } | 346 } |
347 | 347 |
348 STDMETHODIMP ElevatedController::SetConfig(BSTR config) { | 348 STDMETHODIMP ElevatedController::SetConfig(BSTR config) { |
349 // Determine the config directory path and create it if necessary. | 349 // Determine the config directory path and create it if necessary. |
350 FilePath config_dir = remoting::GetConfigDir(); | 350 base::FilePath config_dir = remoting::GetConfigDir(); |
351 if (!file_util::CreateDirectory(config_dir)) { | 351 if (!file_util::CreateDirectory(config_dir)) { |
352 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); | 352 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); |
353 } | 353 } |
354 | 354 |
355 std::string file_content = UTF16ToUTF8( | 355 std::string file_content = UTF16ToUTF8( |
356 string16(static_cast<char16*>(config), ::SysStringLen(config))); | 356 string16(static_cast<char16*>(config), ::SysStringLen(config))); |
357 | 357 |
358 return WriteConfig(file_content.c_str(), file_content.size(), owner_window_); | 358 return WriteConfig(file_content.c_str(), file_content.size(), owner_window_); |
359 } | 359 } |
360 | 360 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 if (!config_value->GetAsDictionary(&config_dict)) { | 455 if (!config_value->GetAsDictionary(&config_dict)) { |
456 return E_FAIL; | 456 return E_FAIL; |
457 } | 457 } |
458 // Check for bad keys. | 458 // Check for bad keys. |
459 for (int i = 0; i < arraysize(kReadonlyKeys); ++i) { | 459 for (int i = 0; i < arraysize(kReadonlyKeys); ++i) { |
460 if (config_dict->HasKey(kReadonlyKeys[i])) { | 460 if (config_dict->HasKey(kReadonlyKeys[i])) { |
461 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); | 461 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); |
462 } | 462 } |
463 } | 463 } |
464 // Get the old config. | 464 // Get the old config. |
465 FilePath config_dir = remoting::GetConfigDir(); | 465 base::FilePath config_dir = remoting::GetConfigDir(); |
466 scoped_ptr<base::DictionaryValue> config_old; | 466 scoped_ptr<base::DictionaryValue> config_old; |
467 HRESULT hr = ReadConfig(config_dir.Append(kConfigFileName), &config_old); | 467 HRESULT hr = ReadConfig(config_dir.Append(kConfigFileName), &config_old); |
468 if (FAILED(hr)) { | 468 if (FAILED(hr)) { |
469 return hr; | 469 return hr; |
470 } | 470 } |
471 // Merge items from the given config into the old config. | 471 // Merge items from the given config into the old config. |
472 config_old->MergeDictionary(config_dict); | 472 config_old->MergeDictionary(config_dict); |
473 // Write the updated config. | 473 // Write the updated config. |
474 std::string config_updated_str; | 474 std::string config_updated_str; |
475 base::JSONWriter::Write(config_old.get(), &config_updated_str); | 475 base::JSONWriter::Write(config_old.get(), &config_updated_str); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 << "Failed to open to the '" << kWindowsServiceName << "' service"; | 522 << "Failed to open to the '" << kWindowsServiceName << "' service"; |
523 | 523 |
524 return HRESULT_FROM_WIN32(error); | 524 return HRESULT_FROM_WIN32(error); |
525 } | 525 } |
526 | 526 |
527 service_out->Set(service.Take()); | 527 service_out->Set(service.Take()); |
528 return S_OK; | 528 return S_OK; |
529 } | 529 } |
530 | 530 |
531 } // namespace remoting | 531 } // namespace remoting |
OLD | NEW |