Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: remoting/host/elevated_controller_win.cc

Issue 10191007: [Chromoting] Let the Windows daemon controller read the unprivileged part of the config without ele… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/elevated_controller_win.h" 5 #include "remoting/host/elevated_controller_win.h"
6 6
7 #include <sddl.h> 7 #include <sddl.h>
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/json/json_reader.h" 11 #include "base/json/json_reader.h"
12 #include "base/json/json_writer.h" 12 #include "base/json/json_writer.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/path_service.h" 14 #include "base/path_service.h"
15 #include "base/stringize_macros.h" 15 #include "base/stringize_macros.h"
16 #include "base/utf_string_conversions.h" 16 #include "base/utf_string_conversions.h"
17 #include "base/values.h" 17 #include "base/values.h"
18 #include "base/win/scoped_handle.h" 18 #include "base/win/scoped_handle.h"
19 #include "remoting/host/branding.h" 19 #include "remoting/host/branding.h"
20 #include "remoting/host/daemon_controller_common_win.h"
20 #include "remoting/host/elevated_controller_resource.h" 21 #include "remoting/host/elevated_controller_resource.h"
21 #include "remoting/host/verify_config_window_win.h" 22 #include "remoting/host/verify_config_window_win.h"
22 23
23 namespace { 24 namespace {
24 25
25 // The host configuration file name. 26 // The host configuration file name.
26 const FilePath::CharType kConfigFileName[] = FILE_PATH_LITERAL("host.json"); 27 const FilePath::CharType kConfigFileName[] = FILE_PATH_LITERAL("host.json");
27 28
28 // The extension for the temporary file. 29 // The extension for the temporary file.
29 const FilePath::CharType kTempFileExtension[] = FILE_PATH_LITERAL("json~"); 30 const FilePath::CharType kTempFileExtension[] = FILE_PATH_LITERAL("json~");
30 31
31 // The host configuration file security descriptor that enables full access to 32 // The host configuration file security descriptor that enables full access to
32 // Local System and built-in administrators only. 33 // Local System and built-in administrators only.
33 const char16 kConfigFileSecurityDescriptor[] = 34 const char16 kConfigFileSecurityDescriptor[] =
34 TO_L_STRING("O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)"); 35 TO_L_STRING("O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)");
35 36
36 // The maximum size of the configuration file. "1MB ought to be enough" for any 37 const char16 kUnprivilegedConfigFileSecurityDescriptor[] =
37 // reasonable configuration we will ever need. 1MB is low enough to make 38 TO_L_STRING("O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;AU)");
38 // the probability of out of memory situation fairly low. OOM is still possible
39 // and we will crash if it occurs.
40 const size_t kMaxConfigFileSize = 1024 * 1024;
41 39
42 // ReadConfig() filters the configuration file stripping all variables except of 40 // Configuration keys.
43 // the following two.
44 const char kHostId[] = "host_id"; 41 const char kHostId[] = "host_id";
45 const char kXmppLogin[] = "xmpp_login"; 42 const char kXmppLogin[] = "xmpp_login";
43 const char kHostSecretHash[] = "host_secret_hash";
46 44
47 // The configuration keys that cannot be specified in UpdateConfig(). 45 // The configuration keys that cannot be specified in UpdateConfig().
48 const char* const kReadonlyKeys[] = { kHostId, kXmppLogin }; 46 const char* const kReadonlyKeys[] = { kHostId, kXmppLogin };
49 47
48 // The configuration keys whose values may be read by GetConfig().
49 const char* const kUnprivilegedConfigKeys[] = { kHostId, kXmppLogin };
50
51 // TODO(simonmorris): Remove this routine: the plugin implements GetConfig(),
52 // so it's no longer used.
50 // Reads and parses the configuration file up to |kMaxConfigFileSize| in 53 // Reads and parses the configuration file up to |kMaxConfigFileSize| in
51 // size. 54 // size.
52 HRESULT ReadConfig(const FilePath& filename, 55 HRESULT ReadConfig(const FilePath& filename,
53 scoped_ptr<base::DictionaryValue>* config_out) { 56 scoped_ptr<base::DictionaryValue>* config_out) {
54 57
55 // Read raw data from the configuration file. 58 // Read raw data from the configuration file.
56 base::win::ScopedHandle file( 59 base::win::ScopedHandle file(
57 CreateFileW(filename.value().c_str(), 60 CreateFileW(filename.value().c_str(),
58 GENERIC_READ, 61 GENERIC_READ,
59 FILE_SHARE_READ | FILE_SHARE_WRITE, 62 FILE_SHARE_READ | FILE_SHARE_WRITE,
60 NULL, 63 NULL,
61 OPEN_EXISTING, 64 OPEN_EXISTING,
62 FILE_FLAG_SEQUENTIAL_SCAN, 65 FILE_FLAG_SEQUENTIAL_SCAN,
63 NULL)); 66 NULL));
64 67
65 if (!file.IsValid()) { 68 if (!file.IsValid()) {
66 DWORD error = GetLastError(); 69 DWORD error = GetLastError();
67 LOG_GETLASTERROR(ERROR) 70 LOG_GETLASTERROR(ERROR)
68 << "Failed to open '" << filename.value() << "'"; 71 << "Failed to open '" << filename.value() << "'";
69 return HRESULT_FROM_WIN32(error); 72 return HRESULT_FROM_WIN32(error);
70 } 73 }
71 74
72 scoped_array<char> buffer(new char[kMaxConfigFileSize]); 75 scoped_array<char> buffer(new char[remoting::kMaxConfigFileSize]);
73 DWORD size = kMaxConfigFileSize; 76 DWORD size = remoting::kMaxConfigFileSize;
74 if (!::ReadFile(file, &buffer[0], size, &size, NULL)) { 77 if (!::ReadFile(file, &buffer[0], size, &size, NULL)) {
75 DWORD error = GetLastError(); 78 DWORD error = GetLastError();
76 LOG_GETLASTERROR(ERROR) 79 LOG_GETLASTERROR(ERROR)
77 << "Failed to read '" << filename.value() << "'"; 80 << "Failed to read '" << filename.value() << "'";
78 return HRESULT_FROM_WIN32(error); 81 return HRESULT_FROM_WIN32(error);
79 } 82 }
80 83
81 // Parse the JSON configuration, expecting it to contain a dictionary. 84 // Parse the JSON configuration, expecting it to contain a dictionary.
82 std::string file_content(buffer.get(), size); 85 std::string file_content(buffer.get(), size);
83 scoped_ptr<base::Value> value( 86 scoped_ptr<base::Value> value(
84 base::JSONReader::Read(file_content, base::JSON_ALLOW_TRAILING_COMMAS)); 87 base::JSONReader::Read(file_content, base::JSON_ALLOW_TRAILING_COMMAS));
85 88
86 base::DictionaryValue* dictionary; 89 base::DictionaryValue* dictionary;
87 if (value.get() == NULL || !value->GetAsDictionary(&dictionary)) { 90 if (value.get() == NULL || !value->GetAsDictionary(&dictionary)) {
88 LOG(ERROR) << "Failed to read '" << filename.value() << "'."; 91 LOG(ERROR) << "Failed to read '" << filename.value() << "'.";
89 return E_FAIL; 92 return E_FAIL;
90 } 93 }
91 94
92 value.release(); 95 value.release();
93 config_out->reset(dictionary); 96 config_out->reset(dictionary);
94 return S_OK; 97 return S_OK;
95 } 98 }
96 99
97 // Writes the configuration file up to |kMaxConfigFileSize| in size. 100 HRESULT WriteConfigFile(const FilePath& filename,
98 HRESULT WriteConfig(const FilePath& filename, 101 const char16* security_descriptor,
99 const char* content, 102 const char* content,
100 size_t length) { 103 size_t length) {
101 if (length > kMaxConfigFileSize) {
102 return E_FAIL;
103 }
104
105 // Extract the configuration data that the user will verify.
106 scoped_ptr<base::Value> config_value(base::JSONReader::Read(content));
107 if (!config_value.get()) {
108 return E_FAIL;
109 }
110 base::DictionaryValue* config_dict = NULL;
111 if (!config_value->GetAsDictionary(&config_dict)) {
112 return E_FAIL;
113 }
114 std::string email, host_id, host_secret_hash;
115 if (!config_dict->GetString("xmpp_login", &email) ||
116 !config_dict->GetString("host_id", &host_id) ||
117 !config_dict->GetString("host_secret_hash", &host_secret_hash)) {
118 return E_FAIL;
119 }
120
121 // Ask the user to verify the configuration.
122 remoting::VerifyConfigWindowWin verify_win(email, host_id, host_secret_hash);
123 if (!verify_win.Run()) {
124 return E_FAIL;
125 }
126
127 // Create a security descriptor for the configuration file. 104 // Create a security descriptor for the configuration file.
128 SECURITY_ATTRIBUTES security_attributes; 105 SECURITY_ATTRIBUTES security_attributes;
129 security_attributes.nLength = sizeof(security_attributes); 106 security_attributes.nLength = sizeof(security_attributes);
130 security_attributes.bInheritHandle = FALSE; 107 security_attributes.bInheritHandle = FALSE;
131 108
132 ULONG security_descriptor_length = 0; 109 ULONG security_descriptor_length = 0;
133 if (!ConvertStringSecurityDescriptorToSecurityDescriptorW( 110 if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
134 kConfigFileSecurityDescriptor, 111 security_descriptor,
135 SDDL_REVISION_1, 112 SDDL_REVISION_1,
136 reinterpret_cast<PSECURITY_DESCRIPTOR*>( 113 reinterpret_cast<PSECURITY_DESCRIPTOR*>(
137 &security_attributes.lpSecurityDescriptor), 114 &security_attributes.lpSecurityDescriptor),
138 &security_descriptor_length)) { 115 &security_descriptor_length)) {
139 DWORD error = GetLastError(); 116 DWORD error = GetLastError();
140 LOG_GETLASTERROR(ERROR) << 117 LOG_GETLASTERROR(ERROR) <<
141 "Failed to create a security descriptor for the configuration file"; 118 "Failed to create a security descriptor for the configuration file";
142 return HRESULT_FROM_WIN32(error); 119 return HRESULT_FROM_WIN32(error);
143 } 120 }
144 121
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 DWORD error = GetLastError(); 155 DWORD error = GetLastError();
179 LOG_GETLASTERROR(ERROR) 156 LOG_GETLASTERROR(ERROR)
180 << "Failed to rename '" << tempname.value() << "' to '" 157 << "Failed to rename '" << tempname.value() << "' to '"
181 << filename.value() << "'"; 158 << filename.value() << "'";
182 return HRESULT_FROM_WIN32(error); 159 return HRESULT_FROM_WIN32(error);
183 } 160 }
184 161
185 return S_OK; 162 return S_OK;
186 } 163 }
187 164
165 // Writes the configuration file up to |kMaxConfigFileSize| in size.
166 HRESULT WriteConfig(const char* content, size_t length) {
167 if (length > remoting::kMaxConfigFileSize) {
168 return E_FAIL;
169 }
170
171 // Extract the configuration data that the user will verify.
172 scoped_ptr<base::Value> config_value(base::JSONReader::Read(content));
173 if (!config_value.get()) {
174 return E_FAIL;
175 }
176 base::DictionaryValue* config_dict = NULL;
177 if (!config_value->GetAsDictionary(&config_dict)) {
178 return E_FAIL;
179 }
180 std::string email, host_id, host_secret_hash;
181 if (!config_dict->GetString(kXmppLogin, &email) ||
182 !config_dict->GetString(kHostId, &host_id) ||
183 !config_dict->GetString(kHostSecretHash, &host_secret_hash)) {
184 return E_FAIL;
185 }
186
187 // Ask the user to verify the configuration.
188 remoting::VerifyConfigWindowWin verify_win(email, host_id, host_secret_hash);
189 if (!verify_win.Run()) {
190 return E_FAIL;
191 }
192
193 // Write the full configuration file.
194 HRESULT hr = WriteConfigFile(remoting::GetConfigDir().Append(kConfigFileName),
195 kConfigFileSecurityDescriptor,
196 content,
197 length);
198 if (FAILED(hr)) {
199 return hr;
200 }
201
202 // Extract the unprivileged fields from the configuration.
203 base::DictionaryValue unprivileged_config_dict;
204 for (int i = 0; i < arraysize(kUnprivilegedConfigKeys); ++i) {
205 const char* key = kUnprivilegedConfigKeys[i];
206 string16 value;
207 if (config_dict->GetString(key, &value)) {
208 unprivileged_config_dict.SetString(key, value);
209 }
210 }
211 std::string unprivileged_config_str;
212 base::JSONWriter::Write(&unprivileged_config_dict, &unprivileged_config_str);
213
214 // Write the unprivileged configuration file.
215 hr = WriteConfigFile(remoting::GetConfigDir().Append(
216 remoting::kUnprivilegedConfigFileName),
217 kUnprivilegedConfigFileSecurityDescriptor,
218 unprivileged_config_str.data(),
219 unprivileged_config_str.size());
220 if (FAILED(hr)) {
221 return hr;
222 }
223
224 return S_OK;
225 }
188 226
189 } // namespace 227 } // namespace
190 228
191 namespace remoting { 229 namespace remoting {
192 230
193 ElevatedControllerWin::ElevatedControllerWin() { 231 ElevatedControllerWin::ElevatedControllerWin() {
194 } 232 }
195 233
196 HRESULT ElevatedControllerWin::FinalConstruct() { 234 HRESULT ElevatedControllerWin::FinalConstruct() {
197 return S_OK; 235 return S_OK;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 STDMETHODIMP ElevatedControllerWin::SetConfig(BSTR config) { 275 STDMETHODIMP ElevatedControllerWin::SetConfig(BSTR config) {
238 // Determine the config directory path and create it if necessary. 276 // Determine the config directory path and create it if necessary.
239 FilePath config_dir = remoting::GetConfigDir(); 277 FilePath config_dir = remoting::GetConfigDir();
240 if (!file_util::CreateDirectory(config_dir)) { 278 if (!file_util::CreateDirectory(config_dir)) {
241 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); 279 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
242 } 280 }
243 281
244 std::string file_content = UTF16ToUTF8( 282 std::string file_content = UTF16ToUTF8(
245 string16(static_cast<char16*>(config), ::SysStringLen(config))); 283 string16(static_cast<char16*>(config), ::SysStringLen(config)));
246 284
247 return WriteConfig(config_dir.Append(kConfigFileName), 285 return WriteConfig(file_content.c_str(), file_content.size());
248 file_content.c_str(),
249 file_content.size());
250 } 286 }
251 287
252 STDMETHODIMP ElevatedControllerWin::StartDaemon() { 288 STDMETHODIMP ElevatedControllerWin::StartDaemon() {
253 ScopedScHandle service; 289 ScopedScHandle service;
254 HRESULT hr = OpenService(&service); 290 HRESULT hr = OpenService(&service);
255 if (FAILED(hr)) { 291 if (FAILED(hr)) {
256 return hr; 292 return hr;
257 } 293 }
258 294
259 // Change the service start type to 'auto'. 295 // Change the service start type to 'auto'.
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 scoped_ptr<base::DictionaryValue> config_old; 388 scoped_ptr<base::DictionaryValue> config_old;
353 HRESULT hr = ReadConfig(config_dir.Append(kConfigFileName), &config_old); 389 HRESULT hr = ReadConfig(config_dir.Append(kConfigFileName), &config_old);
354 if (FAILED(hr)) { 390 if (FAILED(hr)) {
355 return hr; 391 return hr;
356 } 392 }
357 // Merge items from the given config into the old config. 393 // Merge items from the given config into the old config.
358 config_old->MergeDictionary(config_dict); 394 config_old->MergeDictionary(config_dict);
359 // Write the updated config. 395 // Write the updated config.
360 std::string config_updated_str; 396 std::string config_updated_str;
361 base::JSONWriter::Write(config_old.get(), &config_updated_str); 397 base::JSONWriter::Write(config_old.get(), &config_updated_str);
362 return WriteConfig(config_dir.Append(kConfigFileName), 398 return WriteConfig(config_updated_str.c_str(), config_updated_str.size());
363 config_updated_str.c_str(),
364 config_updated_str.size());
365 } 399 }
366 400
367 HRESULT ElevatedControllerWin::OpenService(ScopedScHandle* service_out) { 401 HRESULT ElevatedControllerWin::OpenService(ScopedScHandle* service_out) {
368 DWORD error; 402 DWORD error;
369 403
370 ScopedScHandle scmanager( 404 ScopedScHandle scmanager(
371 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, 405 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
372 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); 406 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE));
373 if (!scmanager.IsValid()) { 407 if (!scmanager.IsValid()) {
374 error = GetLastError(); 408 error = GetLastError();
(...skipping 13 matching lines...) Expand all
388 << "Failed to open to the '" << kWindowsServiceName << "' service"; 422 << "Failed to open to the '" << kWindowsServiceName << "' service";
389 423
390 return HRESULT_FROM_WIN32(error); 424 return HRESULT_FROM_WIN32(error);
391 } 425 }
392 426
393 service_out->Set(service.Take()); 427 service_out->Set(service.Take());
394 return S_OK; 428 return S_OK;
395 } 429 }
396 430
397 } // namespace remoting 431 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698