[Chromoting] Let the Windows daemon controller read the unprivileged part of...

[Chromoting] Let the Windows daemon controller read the unprivileged part of the config without elevating permissions.

The elevated controller writes the unprivileged part of the config to a file
with an ACL that lets the daemon controller read it.

BUG=121518


Review URL: http://codereview.chromium.org/10191007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@133964 0039d316-1c4b-4281-b951-d872f2087c98
parent c11498c4
// 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/daemon_controller_common_win.h"
// Code common to the Windows daemon controller and the Windows elevated
// controller.
namespace remoting {
const FilePath::CharType* kUnprivilegedConfigFileName =
FILE_PATH_LITERAL("host_unprivileged.json");
const size_t kMaxConfigFileSize = 1024 * 1024;
} // namespace remoting
// 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.
#ifndef REMOTING_HOST_DAEMON_CONTROLLER_COMMON_WIN_H_
#define REMOTING_HOST_DAEMON_CONTROLLER_COMMON_WIN_H_
#include "base/file_path.h"
// Code common to the Windows daemon controller and the Windows elevated
// controller.
namespace remoting {
// The unprivileged configuration file name. The directory for the file is
// returned by remoting::GetConfigDir().
extern const FilePath::CharType* kUnprivilegedConfigFileName;
// The maximum size of the configuration file. "1MB ought to be enough" for any
// reasonable configuration we will ever need. 1MB is low enough to make
// the probability of out of memory situation fairly low. OOM is still possible
// and we will crash if it occurs.
extern const size_t kMaxConfigFileSize;
} // namespace remoting
#endif // REMOTING_HOST_DAEMON_CONTROLLER_COMMON_WIN_H_
This diff is collapsed.
......@@ -24,6 +24,7 @@
#include "base/win/scoped_comptr.h"
#include "remoting/base/scoped_sc_handle_win.h"
#include "remoting/host/branding.h"
#include "remoting/host/daemon_controller_common_win.h"
#include "remoting/host/plugin/daemon_installer_win.h"
// MIDL-generated declarations and definitions.
......@@ -310,35 +311,53 @@ DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) {
void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) {
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
IDaemonControl* control = NULL;
HRESULT hr = worker_thread_.ActivateElevatedController(&control);
if (FAILED(hr)) {
callback.Run(scoped_ptr<base::DictionaryValue>());
scoped_ptr<base::DictionaryValue> dictionary_null(NULL);
// Get the name of the configuration file.
FilePath dir = remoting::GetConfigDir();
FilePath filename = dir.Append(kUnprivilegedConfigFileName);
// Read raw data from the configuration file.
base::win::ScopedHandle file(
CreateFileW(filename.value().c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL));
if (!file.IsValid()) {
DWORD error = GetLastError();
LOG_GETLASTERROR(ERROR)
<< "Failed to open '" << filename.value() << "'";
callback.Run(dictionary_null.Pass());
return;
}
// Get the host configuration.
ScopedBstr host_config;
hr = control->GetConfig(host_config.Receive());
if (FAILED(hr)) {
callback.Run(scoped_ptr<base::DictionaryValue>());
scoped_array<char> buffer(new char[kMaxConfigFileSize]);
DWORD size = kMaxConfigFileSize;
if (!::ReadFile(file, &buffer[0], size, &size, NULL)) {
DWORD error = GetLastError();
LOG_GETLASTERROR(ERROR)
<< "Failed to read '" << filename.value() << "'";
callback.Run(dictionary_null.Pass());
return;
}
string16 file_content(static_cast<BSTR>(host_config), host_config.Length());
// Parse the string into a dictionary.
scoped_ptr<base::Value> config(
base::JSONReader::Read(UTF16ToUTF8(file_content),
base::JSON_ALLOW_TRAILING_COMMAS));
// Parse the JSON configuration, expecting it to contain a dictionary.
std::string file_content(buffer.get(), size);
scoped_ptr<base::Value> value(
base::JSONReader::Read(file_content, base::JSON_ALLOW_TRAILING_COMMAS));
base::DictionaryValue* dictionary;
if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) {
callback.Run(scoped_ptr<base::DictionaryValue>());
base::DictionaryValue* dictionary = NULL;
if (value.get() == NULL || !value->GetAsDictionary(&dictionary)) {
LOG(ERROR) << "Failed to read '" << filename.value() << "'";
callback.Run(dictionary_null.Pass());
return;
}
// Release value, because dictionary points to the same object.
value.release();
config.release();
callback.Run(scoped_ptr<base::DictionaryValue>(dictionary));
}
......@@ -356,7 +375,7 @@ void DaemonControllerWin::DoInstallAsNeededAndStart(
return;
}
// Otherwise, install it if it's COM registration entry is missing.
// Otherwise, install it if its COM registration entry is missing.
if (hr == CO_E_CLASSSTRING) {
scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create(
base::Bind(&DaemonControllerWin::OnInstallationComplete,
......
......@@ -320,6 +320,8 @@
'sources': [
'host/branding.cc',
'host/branding.h',
'host/daemon_controller_common_win.cc',
'host/daemon_controller_common_win.h',
'host/elevated_controller.rc',
'host/elevated_controller_module_win.cc',
'host/elevated_controller_win.cc',
......@@ -616,6 +618,8 @@
'host/it2me_host_user_interface.cc',
'host/it2me_host_user_interface.h',
'host/plugin/daemon_controller.h',
'host/daemon_controller_common_win.cc',
'host/daemon_controller_common_win.h',
'host/plugin/daemon_controller_linux.cc',
'host/plugin/daemon_controller_mac.cc',
'host/plugin/daemon_controller_win.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment