| Index: remoting/host/elevated_controller_win.cc
|
| diff --git a/remoting/host/elevated_controller_win.cc b/remoting/host/elevated_controller_win.cc
|
| index ac47f84af6f59cbb5b57379bf46c0b457dafed1c..4e7c9f58ee5956cf0de8668610bb9136dee5b478 100644
|
| --- a/remoting/host/elevated_controller_win.cc
|
| +++ b/remoting/host/elevated_controller_win.cc
|
| @@ -17,6 +17,7 @@
|
| #include "base/values.h"
|
| #include "base/win/scoped_handle.h"
|
| #include "remoting/host/branding.h"
|
| +#include "remoting/host/daemon_controller_common_win.h"
|
| #include "remoting/host/elevated_controller_resource.h"
|
| #include "remoting/host/verify_config_window_win.h"
|
|
|
| @@ -33,20 +34,22 @@ const FilePath::CharType kTempFileExtension[] = FILE_PATH_LITERAL("json~");
|
| const char16 kConfigFileSecurityDescriptor[] =
|
| TO_L_STRING("O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)");
|
|
|
| -// 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.
|
| -const size_t kMaxConfigFileSize = 1024 * 1024;
|
| +const char16 kUnprivilegedConfigFileSecurityDescriptor[] =
|
| + TO_L_STRING("O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;AU)");
|
|
|
| -// ReadConfig() filters the configuration file stripping all variables except of
|
| -// the following two.
|
| +// Configuration keys.
|
| const char kHostId[] = "host_id";
|
| const char kXmppLogin[] = "xmpp_login";
|
| +const char kHostSecretHash[] = "host_secret_hash";
|
|
|
| // The configuration keys that cannot be specified in UpdateConfig().
|
| const char* const kReadonlyKeys[] = { kHostId, kXmppLogin };
|
|
|
| +// The configuration keys whose values may be read by GetConfig().
|
| +const char* const kUnprivilegedConfigKeys[] = { kHostId, kXmppLogin };
|
| +
|
| +// TODO(simonmorris): Remove this routine: the plugin implements GetConfig(),
|
| +// so it's no longer used.
|
| // Reads and parses the configuration file up to |kMaxConfigFileSize| in
|
| // size.
|
| HRESULT ReadConfig(const FilePath& filename,
|
| @@ -69,8 +72,8 @@ HRESULT ReadConfig(const FilePath& filename,
|
| return HRESULT_FROM_WIN32(error);
|
| }
|
|
|
| - scoped_array<char> buffer(new char[kMaxConfigFileSize]);
|
| - DWORD size = kMaxConfigFileSize;
|
| + scoped_array<char> buffer(new char[remoting::kMaxConfigFileSize]);
|
| + DWORD size = remoting::kMaxConfigFileSize;
|
| if (!::ReadFile(file, &buffer[0], size, &size, NULL)) {
|
| DWORD error = GetLastError();
|
| LOG_GETLASTERROR(ERROR)
|
| @@ -94,36 +97,15 @@ HRESULT ReadConfig(const FilePath& filename,
|
| return S_OK;
|
| }
|
|
|
| -// Writes the configuration file up to |kMaxConfigFileSize| in size.
|
| -HRESULT WriteConfig(const FilePath& filename,
|
| - const char* content,
|
| - size_t length) {
|
| - if (length > kMaxConfigFileSize) {
|
| - return E_FAIL;
|
| - }
|
| -
|
| - // Extract the configuration data that the user will verify.
|
| - scoped_ptr<base::Value> config_value(base::JSONReader::Read(content));
|
| - if (!config_value.get()) {
|
| - return E_FAIL;
|
| - }
|
| - base::DictionaryValue* config_dict = NULL;
|
| - if (!config_value->GetAsDictionary(&config_dict)) {
|
| - return E_FAIL;
|
| - }
|
| - std::string email, host_id, host_secret_hash;
|
| - if (!config_dict->GetString("xmpp_login", &email) ||
|
| - !config_dict->GetString("host_id", &host_id) ||
|
| - !config_dict->GetString("host_secret_hash", &host_secret_hash)) {
|
| - return E_FAIL;
|
| - }
|
| -
|
| - // Ask the user to verify the configuration.
|
| - remoting::VerifyConfigWindowWin verify_win(email, host_id, host_secret_hash);
|
| - if (!verify_win.Run()) {
|
| - return E_FAIL;
|
| - }
|
| +FilePath GetTempLocationFor(const FilePath& filename) {
|
| + return filename.ReplaceExtension(kTempFileExtension);
|
| +}
|
|
|
| +// Writes a config file to a temporary location.
|
| +HRESULT WriteConfigFileToTemp(const FilePath& filename,
|
| + const char16* security_descriptor,
|
| + const char* content,
|
| + size_t length) {
|
| // Create a security descriptor for the configuration file.
|
| SECURITY_ATTRIBUTES security_attributes;
|
| security_attributes.nLength = sizeof(security_attributes);
|
| @@ -131,7 +113,7 @@ HRESULT WriteConfig(const FilePath& filename,
|
|
|
| ULONG security_descriptor_length = 0;
|
| if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
| - kConfigFileSecurityDescriptor,
|
| + security_descriptor,
|
| SDDL_REVISION_1,
|
| reinterpret_cast<PSECURITY_DESCRIPTOR*>(
|
| &security_attributes.lpSecurityDescriptor),
|
| @@ -143,35 +125,39 @@ HRESULT WriteConfig(const FilePath& filename,
|
| }
|
|
|
| // Create a temporary file and write configuration to it.
|
| - FilePath tempname = filename.ReplaceExtension(kTempFileExtension);
|
| - {
|
| - base::win::ScopedHandle file(
|
| - CreateFileW(tempname.value().c_str(),
|
| - GENERIC_WRITE,
|
| - 0,
|
| - &security_attributes,
|
| - CREATE_ALWAYS,
|
| - FILE_FLAG_SEQUENTIAL_SCAN,
|
| - NULL));
|
| -
|
| - if (!file.IsValid()) {
|
| - DWORD error = GetLastError();
|
| - LOG_GETLASTERROR(ERROR)
|
| - << "Failed to create '" << filename.value() << "'";
|
| - return HRESULT_FROM_WIN32(error);
|
| - }
|
| + FilePath tempname = GetTempLocationFor(filename);
|
| + base::win::ScopedHandle file(
|
| + CreateFileW(tempname.value().c_str(),
|
| + GENERIC_WRITE,
|
| + 0,
|
| + &security_attributes,
|
| + CREATE_ALWAYS,
|
| + FILE_FLAG_SEQUENTIAL_SCAN,
|
| + NULL));
|
|
|
| - DWORD written;
|
| - if (!WriteFile(file, content, static_cast<DWORD>(length), &written, NULL)) {
|
| - DWORD error = GetLastError();
|
| - LOG_GETLASTERROR(ERROR)
|
| - << "Failed to write to '" << filename.value() << "'";
|
| - return HRESULT_FROM_WIN32(error);
|
| - }
|
| + if (!file.IsValid()) {
|
| + DWORD error = GetLastError();
|
| + LOG_GETLASTERROR(ERROR)
|
| + << "Failed to create '" << filename.value() << "'";
|
| + return HRESULT_FROM_WIN32(error);
|
| }
|
|
|
| + DWORD written;
|
| + if (!WriteFile(file, content, static_cast<DWORD>(length), &written, NULL)) {
|
| + DWORD error = GetLastError();
|
| + LOG_GETLASTERROR(ERROR)
|
| + << "Failed to write to '" << filename.value() << "'";
|
| + return HRESULT_FROM_WIN32(error);
|
| + }
|
| +
|
| + return S_OK;
|
| +}
|
| +
|
| +// Moves a config file from its temporary location to its permanent location.
|
| +HRESULT MoveConfigFileFromTemp(const FilePath& filename) {
|
| // Now that the configuration is stored successfully replace the actual
|
| // configuration file.
|
| + FilePath tempname = GetTempLocationFor(filename);
|
| if (!MoveFileExW(tempname.value().c_str(),
|
| filename.value().c_str(),
|
| MOVEFILE_REPLACE_EXISTING)) {
|
| @@ -185,6 +171,82 @@ HRESULT WriteConfig(const FilePath& filename,
|
| return S_OK;
|
| }
|
|
|
| +// Writes the configuration file up to |kMaxConfigFileSize| in size.
|
| +HRESULT WriteConfig(const char* content, size_t length) {
|
| + if (length > remoting::kMaxConfigFileSize) {
|
| + return E_FAIL;
|
| + }
|
| +
|
| + // Extract the configuration data that the user will verify.
|
| + scoped_ptr<base::Value> config_value(base::JSONReader::Read(content));
|
| + if (!config_value.get()) {
|
| + return E_FAIL;
|
| + }
|
| + base::DictionaryValue* config_dict = NULL;
|
| + if (!config_value->GetAsDictionary(&config_dict)) {
|
| + return E_FAIL;
|
| + }
|
| + std::string email, host_id, host_secret_hash;
|
| + if (!config_dict->GetString(kXmppLogin, &email) ||
|
| + !config_dict->GetString(kHostId, &host_id) ||
|
| + !config_dict->GetString(kHostSecretHash, &host_secret_hash)) {
|
| + return E_FAIL;
|
| + }
|
| +
|
| + // Ask the user to verify the configuration.
|
| + remoting::VerifyConfigWindowWin verify_win(email, host_id, host_secret_hash);
|
| + if (!verify_win.Run()) {
|
| + return E_FAIL;
|
| + }
|
| +
|
| + // Extract the unprivileged fields from the configuration.
|
| + base::DictionaryValue unprivileged_config_dict;
|
| + for (int i = 0; i < arraysize(kUnprivilegedConfigKeys); ++i) {
|
| + const char* key = kUnprivilegedConfigKeys[i];
|
| + string16 value;
|
| + if (config_dict->GetString(key, &value)) {
|
| + unprivileged_config_dict.SetString(key, value);
|
| + }
|
| + }
|
| + std::string unprivileged_config_str;
|
| + base::JSONWriter::Write(&unprivileged_config_dict, &unprivileged_config_str);
|
| +
|
| + // Write the full configuration file to a temporary location.
|
| + FilePath full_config_file_path =
|
| + remoting::GetConfigDir().Append(kConfigFileName);
|
| + HRESULT hr = WriteConfigFileToTemp(full_config_file_path,
|
| + kConfigFileSecurityDescriptor,
|
| + content,
|
| + length);
|
| + if (FAILED(hr)) {
|
| + return hr;
|
| + }
|
| +
|
| + // Write the unprivileged configuration file to a temporary location.
|
| + FilePath unprivileged_config_file_path =
|
| + remoting::GetConfigDir().Append(remoting::kUnprivilegedConfigFileName);
|
| + hr = WriteConfigFileToTemp(unprivileged_config_file_path,
|
| + kUnprivilegedConfigFileSecurityDescriptor,
|
| + unprivileged_config_str.data(),
|
| + unprivileged_config_str.size());
|
| + if (FAILED(hr)) {
|
| + return hr;
|
| + }
|
| +
|
| + // Move the full configuration file to its permanent location.
|
| + hr = MoveConfigFileFromTemp(full_config_file_path);
|
| + if (FAILED(hr)) {
|
| + return hr;
|
| + }
|
| +
|
| + // Move the unprivileged configuration file to its permanent location.
|
| + hr = MoveConfigFileFromTemp(unprivileged_config_file_path);
|
| + if (FAILED(hr)) {
|
| + return hr;
|
| + }
|
| +
|
| + return S_OK;
|
| +}
|
|
|
| } // namespace
|
|
|
| @@ -244,9 +306,7 @@ STDMETHODIMP ElevatedControllerWin::SetConfig(BSTR config) {
|
| std::string file_content = UTF16ToUTF8(
|
| string16(static_cast<char16*>(config), ::SysStringLen(config)));
|
|
|
| - return WriteConfig(config_dir.Append(kConfigFileName),
|
| - file_content.c_str(),
|
| - file_content.size());
|
| + return WriteConfig(file_content.c_str(), file_content.size());
|
| }
|
|
|
| STDMETHODIMP ElevatedControllerWin::StartDaemon() {
|
| @@ -359,9 +419,7 @@ STDMETHODIMP ElevatedControllerWin::UpdateConfig(BSTR config) {
|
| // Write the updated config.
|
| std::string config_updated_str;
|
| base::JSONWriter::Write(config_old.get(), &config_updated_str);
|
| - return WriteConfig(config_dir.Append(kConfigFileName),
|
| - config_updated_str.c_str(),
|
| - config_updated_str.size());
|
| + return WriteConfig(config_updated_str.c_str(), config_updated_str.size());
|
| }
|
|
|
| HRESULT ElevatedControllerWin::OpenService(ScopedScHandle* service_out) {
|
|
|