summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base_paths_win.cc6
-rw-r--r--base/base_paths_win.h12
-rw-r--r--remoting/VERSION2
-rw-r--r--remoting/host/branding.cc2
-rw-r--r--remoting/host/elevated_controller.idl13
-rw-r--r--remoting/host/elevated_controller_win.cc155
-rw-r--r--remoting/host/elevated_controller_win.h1
-rw-r--r--remoting/host/installer/chromoting.wxs41
-rw-r--r--remoting/host/wts_session_process_launcher_win.cc24
-rw-r--r--remoting/remoting.gyp8
10 files changed, 179 insertions, 85 deletions
diff --git a/base/base_paths_win.cc b/base/base_paths_win.cc
index eab412a..0b24833 100644
--- a/base/base_paths_win.cc
+++ b/base/base_paths_win.cc
@@ -89,6 +89,12 @@ bool PathProviderWin(int key, FilePath* result) {
return false;
cur = FilePath(system_buffer);
break;
+ case base::DIR_COMMON_APP_DATA:
+ if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, system_buffer)))
+ return false;
+ cur = FilePath(system_buffer);
+ break;
case base::DIR_PROFILE:
if (FAILED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT,
system_buffer)))
diff --git a/base/base_paths_win.h b/base/base_paths_win.h
index 02b1f49..c005bb2 100644
--- a/base/base_paths_win.h
+++ b/base/base_paths_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -27,9 +27,13 @@ enum {
// Start Menu\Programs"
DIR_APP_DATA, // Application Data directory under the user profile.
DIR_PROFILE, // Usually "C:\Documents and settings\<user>.
- DIR_LOCAL_APP_DATA_LOW, // Local AppData directory for low integrity level.
- DIR_LOCAL_APP_DATA, // "Local Settings\Application Data" directory under the
- // user profile.
+ DIR_LOCAL_APP_DATA_LOW, // Local AppData directory for low integrity level.
+ DIR_LOCAL_APP_DATA, // "Local Settings\Application Data" directory under
+ // the user profile.
+ DIR_COMMON_APP_DATA, // W2K, XP, W2K3: "C:\Documents and Settings\
+ // All Users\Application Data".
+ // Vista, W2K8 and above: "C:\ProgramData".
+
PATH_WIN_END
};
diff --git a/remoting/VERSION b/remoting/VERSION
index b0ecd30..1807650 100644
--- a/remoting/VERSION
+++ b/remoting/VERSION
@@ -1,4 +1,4 @@
MAJOR=1
MINOR=4
-BUILD=2
+BUILD=4
PATCH=0
diff --git a/remoting/host/branding.cc b/remoting/host/branding.cc
index 2e55190..1316139a 100644
--- a/remoting/host/branding.cc
+++ b/remoting/host/branding.cc
@@ -42,7 +42,7 @@ FilePath GetConfigDir() {
FilePath app_data_dir;
#if defined(OS_WIN)
- PathService::Get(base::DIR_LOCAL_APP_DATA, &app_data_dir);
+ PathService::Get(base::DIR_COMMON_APP_DATA, &app_data_dir);
#elif defined(OS_MACOSX)
PathService::Get(base::DIR_APP_DATA, &app_data_dir);
#else
diff --git a/remoting/host/elevated_controller.idl b/remoting/host/elevated_controller.idl
index 06ba0b5..3d3c82c 100644
--- a/remoting/host/elevated_controller.idl
+++ b/remoting/host/elevated_controller.idl
@@ -14,10 +14,12 @@ import "ocidl.idl";
pointer_default(unique)
]
interface IDaemonControl: IDispatch {
- [ id(1), helpstring("Reads the daemon configuration.") ]
+ [ id(1), helpstring("Returns a filtered copy of the daemon's configuration "
+ "stripped of all security-sensitive information.") ]
HRESULT GetConfig([out, retval] BSTR* config_out);
- [ id(2), helpstring("Writes the daemon configuration.") ]
+ [ id(2), helpstring("Replaces the existing daemon's configuration with "
+ "the specified settings.") ]
HRESULT SetConfig([in] BSTR config);
[ id(3), helpstring("Starts the daemon.") ]
@@ -25,6 +27,13 @@ interface IDaemonControl: IDispatch {
[ id(4), helpstring("Stops the daemon.") ]
HRESULT StopDaemon();
+
+ [ id(5), helpstring("Modifies the existing daemon's configuration by "
+ "merging it with the specified settings. A subset of "
+ "items is allowed to be modified using this method. "
+ "Any read-only settings such as 'host_id' (and some "
+ "others) are not modified.") ]
+ HRESULT UpdateConfig([in] BSTR config);
};
[
diff --git a/remoting/host/elevated_controller_win.cc b/remoting/host/elevated_controller_win.cc
index fbeeea9..f1163e75 100644
--- a/remoting/host/elevated_controller_win.cc
+++ b/remoting/host/elevated_controller_win.cc
@@ -4,6 +4,8 @@
#include "remoting/host/elevated_controller_win.h"
+#include <sddl.h>
+
#include "base/file_util.h"
#include "base/logging.h"
#include "base/json/json_reader.h"
@@ -20,30 +22,32 @@
namespace {
+// The host configuration file name.
+const FilePath::CharType kConfigFileName[] = FILE_PATH_LITERAL("host.json");
+
+// The extension for the temporary file.
+const FilePath::CharType kTempFileExtension[] = FILE_PATH_LITERAL("json~");
+
+// The host configuration file security descriptor that enables full access to
+// Local System and built-in administrators only.
+const char kConfigFileSecurityDescriptor[] =
+ "O:BA" "G:BA" "D:(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;
+
// ReadConfig() filters the configuration file stripping all variables except of
// the following two.
const char kHostId[] = "host_id";
const char kXmppLogin[] = "xmpp_login";
-// Names of the configuration files.
-const FilePath::CharType kAuthConfigFilename[] = FILE_PATH_LITERAL("auth.json");
-const FilePath::CharType kHostConfigFilename[] = FILE_PATH_LITERAL("host.json");
-
-// TODO(alexeypa): Remove the hardcoded undocumented paths and store
-// the configuration in the registry.
-#ifdef OFFICIAL_BUILD
-const FilePath::CharType kConfigDir[] = FILE_PATH_LITERAL(
- "config\\systemprofile\\AppData\\Local\\Google\\Chrome Remote Desktop");
-#else
-const FilePath::CharType kConfigDir[] =
- FILE_PATH_LITERAL("config\\systemprofile\\AppData\\Local\\Chromoting");
-#endif
-
-// Reads and parses a JSON configuration file.
+// Reads and parses the configuration file up to |kMaxConfigFileSize| in
+// size.
HRESULT ReadConfig(const FilePath& filename,
scoped_ptr<base::DictionaryValue>* config_out) {
- // TODO(alexeypa): Remove 64KB limitation.
- const size_t kMaxConfigFileSize = 64 * 1024;
// Read raw data from the configuration file.
base::win::ScopedHandle file(
@@ -58,12 +62,12 @@ HRESULT ReadConfig(const FilePath& filename,
if (!file.IsValid()) {
DWORD error = GetLastError();
LOG_GETLASTERROR(ERROR)
- << "Failed to read '" << filename.value() << "'";
+ << "Failed to open '" << filename.value() << "'";
return HRESULT_FROM_WIN32(error);
}
- std::vector<char> buffer(kMaxConfigFileSize);
- DWORD size = static_cast<DWORD>(buffer.size());
+ scoped_array<char> buffer(new char[kMaxConfigFileSize]);
+ DWORD size = kMaxConfigFileSize;
if (!::ReadFile(file, &buffer[0], size, &size, NULL)) {
DWORD error = GetLastError();
LOG_GETLASTERROR(ERROR)
@@ -72,7 +76,7 @@ HRESULT ReadConfig(const FilePath& filename,
}
// Parse the JSON configuration, expecting it to contain a dictionary.
- std::string file_content(&buffer[0], size);
+ std::string file_content(buffer.get(), size);
scoped_ptr<base::Value> value(base::JSONReader::Read(file_content, true));
base::DictionaryValue* dictionary;
@@ -86,6 +90,76 @@ 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;
+ }
+
+ // Create a security descriptor for the configuration file.
+ SECURITY_ATTRIBUTES security_attributes;
+ security_attributes.nLength = sizeof(security_attributes);
+ security_attributes.bInheritHandle = FALSE;
+
+ ULONG security_descriptor_length = 0;
+ if (!ConvertStringSecurityDescriptorToSecurityDescriptorA(
+ kConfigFileSecurityDescriptor,
+ SDDL_REVISION_1,
+ reinterpret_cast<PSECURITY_DESCRIPTOR*>(
+ &security_attributes.lpSecurityDescriptor),
+ &security_descriptor_length)) {
+ DWORD error = GetLastError();
+ LOG_GETLASTERROR(ERROR) <<
+ "Failed to create a security descriptor for the configuration file";
+ return HRESULT_FROM_WIN32(error);
+ }
+
+ // 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);
+ }
+
+ 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);
+ }
+ }
+
+ // Now that the configuration is stored successfully replace the actual
+ // configuration file.
+ if (!MoveFileExW(tempname.value().c_str(),
+ filename.value().c_str(),
+ MOVEFILE_REPLACE_EXISTING)) {
+ DWORD error = GetLastError();
+ LOG_GETLASTERROR(ERROR)
+ << "Failed to rename '" << tempname.value() << "' to '"
+ << filename.value() << "'";
+ return HRESULT_FROM_WIN32(error);
+ }
+
+ return S_OK;
+}
+
+
} // namespace
namespace remoting {
@@ -101,14 +175,11 @@ void ElevatedControllerWin::FinalRelease() {
}
STDMETHODIMP ElevatedControllerWin::GetConfig(BSTR* config_out) {
- FilePath system_profile;
- PathService::Get(base::DIR_SYSTEM, &system_profile);
+ FilePath config_dir = remoting::GetConfigDir();
// Read the host configuration.
scoped_ptr<base::DictionaryValue> config;
- HRESULT hr = ReadConfig(
- system_profile.Append(kConfigDir).Append(kHostConfigFilename),
- &config);
+ HRESULT hr = ReadConfig(config_dir.Append(kConfigFileName), &config);
if (FAILED(hr)) {
return hr;
}
@@ -139,11 +210,7 @@ STDMETHODIMP ElevatedControllerWin::GetConfig(BSTR* config_out) {
STDMETHODIMP ElevatedControllerWin::SetConfig(BSTR config) {
// Determine the config directory path and create it if necessary.
- // N.B. The configuration files are stored in LocalSystems's profile which is
- // not readable by non administrators.
- FilePath system_profile;
- PathService::Get(base::DIR_SYSTEM, &system_profile);
- FilePath config_dir = system_profile.Append(kConfigDir);
+ FilePath config_dir = remoting::GetConfigDir();
if (!file_util::CreateDirectory(config_dir)) {
return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
}
@@ -151,25 +218,9 @@ STDMETHODIMP ElevatedControllerWin::SetConfig(BSTR config) {
std::string file_content = UTF16ToUTF8(
string16(static_cast<char16*>(config), ::SysStringLen(config)));
- int written = file_util::WriteFile(
- config_dir.Append(kAuthConfigFilename),
- file_content.c_str(),
- file_content.size());
- if (written != static_cast<int>(file_content.size())) {
- return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
- }
-
- // TODO(alexeypa): Store the authentication and host configurations in a
- // single file.
- written = file_util::WriteFile(
- config_dir.Append(kHostConfigFilename),
- file_content.c_str(),
- file_content.size());
- if (written != static_cast<int>(file_content.size())) {
- return E_FAIL;
- }
-
- return S_OK;
+ return WriteConfig(config_dir.Append(kConfigFileName),
+ file_content.c_str(),
+ file_content.size());
}
STDMETHODIMP ElevatedControllerWin::StartDaemon() {
@@ -212,6 +263,10 @@ STDMETHODIMP ElevatedControllerWin::StopDaemon() {
return S_OK;
}
+STDMETHODIMP ElevatedControllerWin::UpdateConfig(BSTR config) {
+ return E_NOTIMPL;
+}
+
HRESULT ElevatedControllerWin::OpenService(ScopedScHandle* service_out) {
DWORD error;
diff --git a/remoting/host/elevated_controller_win.h b/remoting/host/elevated_controller_win.h
index 6f73162..af855d4 100644
--- a/remoting/host/elevated_controller_win.h
+++ b/remoting/host/elevated_controller_win.h
@@ -32,6 +32,7 @@ class ATL_NO_VTABLE ElevatedControllerWin
STDMETHOD(SetConfig)(BSTR config);
STDMETHOD(StartDaemon)();
STDMETHOD(StopDaemon)();
+ STDMETHOD(UpdateConfig)(BSTR config);
DECLARE_NO_REGISTRY()
diff --git a/remoting/host/installer/chromoting.wxs b/remoting/host/installer/chromoting.wxs
index e90fabc..d546a44 100644
--- a/remoting/host/installer/chromoting.wxs
+++ b/remoting/host/installer/chromoting.wxs
@@ -63,18 +63,27 @@
<Media Id="1" Cabinet="chromoting.cab" EmbedCab="yes"/>
<Directory Id="TARGETDIR" Name="SourceDir">
- <Directory Id="ProgramFilesFolder" Name="PFiles">
+ <Directory Id="ProgramFilesFolder">
<?ifdef OfficialBuild ?>
- <Directory Id="google" Name="Google">
- <Directory Id="chromoting" Name="Chrome Remote Desktop"/>
+ <Directory Id="program_files_google" Name="Google">
+ <Directory Id="binaries" Name="Chrome Remote Desktop"/>
</Directory>
<?else?>
- <Directory Id="chromoting" Name="Chromoting"/>
+ <Directory Id="binaries" Name="Chromoting"/>
+ <?endif?>
+ </Directory>
+ <Directory Id="CommonAppDataFolder">
+ <?ifdef OfficialBuild ?>
+ <Directory Id="common_app_data_google" Name="Google">
+ <Directory Id="config_files" Name="Chrome Remote Desktop"/>
+ </Directory>
+ <?else?>
+ <Directory Id="config_files" Name="Chromoting"/>
<?endif?>
</Directory>
</Directory>
- <DirectoryRef Id="chromoting" FileSource="$(var.FileSource)">
+ <DirectoryRef Id="binaries" FileSource="$(var.FileSource)">
<Component Id="sas.dll"
Guid="3c33dd97-3750-467f-8ec6-730611d346d4">
<File Id="sas.dll"
@@ -84,8 +93,8 @@
Vital="yes"/>
</Component>
- <Component Id="remoting_service.exe"
- Guid="23103839-bb02-4007-b149-998ddd8d7cba">
+ <Component Id="remoting_host"
+ Guid="8b5f7392-dfa9-4fa3-83ac-87bd6676da50">
<File Id="remoting_service.exe"
DiskId="1"
KeyPath="yes"
@@ -96,9 +105,9 @@
Type="ownProcess"
Vital="yes"
Name="$(var.ServiceName)"
- DisplayName="@[chromoting]remoting_service.exe,-101"
- Description="@[chromoting]remoting_service.exe,-102"
- Arguments="--host-binary=&quot;[chromoting]remoting_me2me_host.exe&quot;"
+ DisplayName="@[#remoting_service.exe],-101"
+ Description="@[#remoting_service.exe],-102"
+ Arguments="--host-binary=&quot;[#remoting_me2me_host.exe]&quot; --auth-config=&quot;[config_files]host.json&quot; --host-config=&quot;[config_files]host.json&quot;"
Start="auto"
Account="LocalSystem"
ErrorControl="ignore"
@@ -109,10 +118,7 @@
Remove="uninstall"
Name="$(var.ServiceName)"
Wait="yes" />
- </Component>
- <Component Id="remoting_me2me_host.exe"
- Guid="0e1889af-f3f8-45a2-b2d0-c719d53c4474">
<File Id="remoting_me2me_host.exe"
DiskId="1"
Name="remoting_me2me_host.exe"
@@ -121,8 +127,8 @@
Name="$(var.EventSourceName)"
Log="Application"
CategoryCount="1"
- CategoryMessageFile="[chromoting]remoting_me2me_host.exe"
- EventMessageFile="[chromoting]remoting_me2me_host.exe"
+ CategoryMessageFile="[#remoting_me2me_host.exe]"
+ EventMessageFile="[#remoting_me2me_host.exe]"
SupportsErrors="yes"
SupportsInformationals="yes"/>
@@ -271,7 +277,7 @@
<RegistryKey Key="HELPDIR" Action="create">
<RegistryValue Type="string"
- Value="[chromoting]"/>
+ Value="[binaries]"/>
</RegistryKey>
</RegistryKey>
</RegistryKey>
@@ -285,8 +291,7 @@
<Feature Id="chromoting_host" Level="1" Title="$(var.ChromotingHost)">
<ComponentRef Id="omaha_registration"/>
- <ComponentRef Id="remoting_service.exe"/>
- <ComponentRef Id="remoting_me2me_host.exe"/>
+ <ComponentRef Id="remoting_host"/>
<ComponentRef Id="sas.dll"/>
<ComponentRef Id="service_controller"/>
</Feature>
diff --git a/remoting/host/wts_session_process_launcher_win.cc b/remoting/host/wts_session_process_launcher_win.cc
index 45d81cf..769d9a9 100644
--- a/remoting/host/wts_session_process_launcher_win.cc
+++ b/remoting/host/wts_session_process_launcher_win.cc
@@ -11,6 +11,7 @@
#include <sddl.h>
#include <limits>
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/process_util.h"
#include "base/rand_util.h"
@@ -43,8 +44,12 @@ const char kDefaultDesktopName[] = "winsta0\\default";
// Match the pipe name prefix used by Chrome IPC channels.
const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome.";
-// Generates the command line of the host process.
-const char kHostProcessCommandLineFormat[] = "\"%ls\" --chromoting-ipc=%ls";
+// The IPC channel name is passed to the host in the command line.
+const char kChromotingIpcSwitchName[] = "chromoting-ipc";
+
+// The command line parameters that should be copied from the service's command
+// line to the host process.
+const char* kCopiedSwitchNames[] = { "auth-config", "host-config" };
// The security descriptor of the Chromoting IPC channel. It gives full access
// to LocalSystem and denies access by anyone else.
@@ -279,15 +284,18 @@ void WtsSessionProcessLauncher::LaunchProcess() {
this,
io_thread_->message_loop_proxy().get()));
- string16 command_line =
- base::StringPrintf(ASCIIToUTF16(kHostProcessCommandLineFormat).c_str(),
- host_binary_.value().c_str(),
- channel_name.c_str());
+ // Create the host process command line passing the name of the IPC channel
+ // to use and copying known switches from the service's command line.
+ CommandLine command_line(host_binary_);
+ command_line.AppendSwitchNative(kChromotingIpcSwitchName, channel_name);
+ command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
+ kCopiedSwitchNames,
+ _countof(kCopiedSwitchNames));
// Try to launch the process and attach an object watcher to the returned
// handle so that we get notified when the process terminates.
- if (LaunchProcessAsUser(host_binary_, command_line, session_token_,
- &process_)) {
+ if (LaunchProcessAsUser(host_binary_, command_line.GetCommandLineString(),
+ session_token_, &process_)) {
if (process_watcher_.StartWatching(process_.handle(), this)) {
state_ = StateAttached;
return;
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index da3492b..db396ff 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -412,7 +412,12 @@
{
'rule_name': 'candle',
'extension': 'wxs',
- 'inputs': [ ],
+ 'inputs': [
+ '<(PRODUCT_DIR)/remoting_host_controller.exe',
+ '<(PRODUCT_DIR)/remoting_me2me_host.exe',
+ '<(PRODUCT_DIR)/remoting_service.exe',
+ '<(sas_dll_path)'
+ ],
'outputs': [
'<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).wixobj',
],
@@ -437,6 +442,7 @@
'rule_name': 'light',
'extension': 'wixobj',
'inputs': [
+ '<(PRODUCT_DIR)/remoting_host_controller.exe',
'<(PRODUCT_DIR)/remoting_me2me_host.exe',
'<(PRODUCT_DIR)/remoting_service.exe',
'<(sas_dll_path)'