diff options
author | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-20 20:59:19 +0000 |
---|---|---|
committer | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-20 20:59:19 +0000 |
commit | 919af5861da3345c7a0758860eb4e0e9b3fbb4eb (patch) | |
tree | 2ca2e2a8fc6b0a62d3d7f92c9f35d7a8b08b5197 /remoting/host | |
parent | 8a6aaa7c2cf610f4b050b7558156598291120043 (diff) | |
download | chromium_src-919af5861da3345c7a0758860eb4e0e9b3fbb4eb.zip chromium_src-919af5861da3345c7a0758860eb4e0e9b3fbb4eb.tar.gz chromium_src-919af5861da3345c7a0758860eb4e0e9b3fbb4eb.tar.bz2 |
Write Mac Me2Me config as root
This makes the json file owned by root, and readable for the user who installed
the Me2e host components. Plugin elevates to root before writing the config
data.
BUG=None
TEST=Manual
Review URL: http://codereview.chromium.org/10084025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@133274 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host')
6 files changed, 67 insertions, 37 deletions
diff --git a/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh b/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh index eb7029c..a033362 100755 --- a/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh +++ b/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh @@ -8,6 +8,7 @@ NAME=org.chromium.chromoting CONFIG_DIR=/Library/PrivilegedHelperTools HOST_EXE=$CONFIG_DIR/$NAME.me2me_host ENABLED_FILE=$CONFIG_DIR/$NAME.me2me_enabled +CONFIG_FILE=$CONFIG_DIR/$NAME.json if [ "$1" = "--disable" ]; then # This script is executed from base::mac::ExecuteWithPrivilegesAndWait(), @@ -17,9 +18,13 @@ if [ "$1" = "--disable" ]; then rm -f "$ENABLED_FILE" elif [ "$1" = "--enable" ]; then echo $$ + cat > "$CONFIG_FILE" touch "$ENABLED_FILE" +elif [ "$1" = "--save-config" ]; then + echo $$ + cat > "$CONFIG_FILE" else exec "$HOST_EXE" \ - --auth-config="$CONFIG_DIR/$NAME.json" \ - --host-config="$CONFIG_DIR/$NAME.json" + --auth-config="$CONFIG_FILE" \ + --host-config="$CONFIG_FILE" fi diff --git a/remoting/host/installer/mac/Scripts/remoting_postflight.sh b/remoting/host/installer/mac/Scripts/remoting_postflight.sh index 2f72af4..ef9b7a8 100755 --- a/remoting/host/installer/mac/Scripts/remoting_postflight.sh +++ b/remoting/host/installer/mac/Scripts/remoting_postflight.sh @@ -6,7 +6,7 @@ HELPERTOOLS=/Library/PrivilegedHelperTools NAME=org.chromium.chromoting -AUTH_FILE="$HELPERTOOLS/$NAME.json" +CONFIG_FILE="$HELPERTOOLS/$NAME.json" PLIST=/Library/LaunchAgents/org.chromium.chromoting.plist ENABLED_FILE="$HELPERTOOLS/$NAME.me2me_enabled" ENABLED_FILE_BACKUP="$ENABLED_FILE.backup" @@ -26,10 +26,10 @@ function onexit { # Create auth file (with correct owner and permissions) if it doesn't already # exist. -if [[ ! -f "$AUTH_FILE" ]]; then - touch "$AUTH_FILE" - chown $USER "$AUTH_FILE" - chmod 600 "$AUTH_FILE" +if [[ ! -f "$CONFIG_FILE" ]]; then + touch "$CONFIG_FILE" + chmod 600 "$CONFIG_FILE" + chmod +a "$USER:allow:read" "$CONFIG_FILE" fi # Load the service. diff --git a/remoting/host/installer/mac/Scripts/remoting_preflight.sh b/remoting/host/installer/mac/Scripts/remoting_preflight.sh index 52bf3ea..6d13429 100755 --- a/remoting/host/installer/mac/Scripts/remoting_preflight.sh +++ b/remoting/host/installer/mac/Scripts/remoting_preflight.sh @@ -6,7 +6,7 @@ HELPERTOOLS=/Library/PrivilegedHelperTools NAME=org.chromium.chromoting -AUTH_FILE="$HELPERTOOLS/$NAME.json" +CONFIG_FILE="$HELPERTOOLS/$NAME.json" PLIST=/Library/LaunchAgents/org.chromium.chromoting.plist ENABLED_FILE="$HELPERTOOLS/$NAME.me2me_enabled" ENABLED_FILE_BACKUP="$ENABLED_FILE.backup" diff --git a/remoting/host/json_host_config.cc b/remoting/host/json_host_config.cc index 6c5c2e8..1f22adf 100644 --- a/remoting/host/json_host_config.cc +++ b/remoting/host/json_host_config.cc @@ -45,14 +45,17 @@ bool JsonHostConfig::Read() { bool JsonHostConfig::Save() { DCHECK(CalledOnValidThread()); - std::string file_content; - base::JSONWriter::WriteWithOptions(values_.get(), - base::JSONWriter::OPTIONS_PRETTY_PRINT, - &file_content); + std::string file_content = GetSerializedData(); // TODO(sergeyu): Move ImportantFileWriter to base and use it here. - int result = file_util::WriteFile(filename_, file_content.c_str(), + int result = file_util::WriteFile(filename_, file_content.data(), file_content.size()); return result == static_cast<int>(file_content.size()); } +std::string JsonHostConfig::GetSerializedData() { + std::string data; + base::JSONWriter::Write(values_.get(), &data); + return data; +} + } // namespace remoting diff --git a/remoting/host/json_host_config.h b/remoting/host/json_host_config.h index f4db06d..014e148 100644 --- a/remoting/host/json_host_config.h +++ b/remoting/host/json_host_config.h @@ -27,6 +27,8 @@ class JsonHostConfig : public InMemoryHostConfig { // MutableHostConfig interface. virtual bool Save() OVERRIDE; + std::string GetSerializedData(); + private: FilePath filename_; diff --git a/remoting/host/plugin/daemon_controller_mac.cc b/remoting/host/plugin/daemon_controller_mac.cc index b48d7ec..e6011fd 100644 --- a/remoting/host/plugin/daemon_controller_mac.cc +++ b/remoting/host/plugin/daemon_controller_mac.cc @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/bind.h" #include "base/compiler_specific.h" +#include "base/eintr_wrapper.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/json/json_writer.h" @@ -75,7 +76,7 @@ class DaemonControllerMac : public remoting::DaemonController { int tries_remaining, const base::TimeDelta& sleep); - bool RunToolScriptAsRoot(const char* command); + bool RunToolScriptAsRoot(const char* command, const std::string& input_data); bool StopService(); // The API for gaining root privileges is blocking (it prompts the user for @@ -165,24 +166,12 @@ void DaemonControllerMac::DoGetConfig(const GetConfigCallback& callback) { void DaemonControllerMac::DoSetConfigAndStart( scoped_ptr<base::DictionaryValue> config, const CompletionCallback& done_callback) { - // JsonHostConfig doesn't provide a way to save on the current thread, wait - // for completion, and know whether the save succeeded. Instead, use - // base::JSONWriter directly. - - // TODO(lambroslambrou): Improve the JsonHostConfig interface. std::string file_content; base::JSONWriter::Write(config.get(), &file_content); - if (file_util::WriteFile(FilePath(kHostConfigFile), file_content.c_str(), - file_content.size()) != - static_cast<int>(file_content.size())) { - LOG(ERROR) << "Failed to write config file: " << kHostConfigFile; - done_callback.Run(RESULT_FAILED); - return; - } // Creating the trigger file causes launchd to start the service, so the // extra step performed in DoStop() is not necessary here. - bool result = RunToolScriptAsRoot("--enable"); + bool result = RunToolScriptAsRoot("--enable", file_content); done_callback.Run(result ? RESULT_OK : RESULT_FAILED); } @@ -203,7 +192,10 @@ void DaemonControllerMac::DoUpdateConfig( } config_file.SetString(*key, value); } - bool success = config_file.Save(); + + std::string file_content = config_file.GetSerializedData(); + bool success = RunToolScriptAsRoot("--save-config", file_content); + done_callback.Run(success ? RESULT_OK : RESULT_FAILED); pid_t job_pid = base::mac::PIDForJob(kServiceName); if (job_pid > 0) { @@ -212,7 +204,7 @@ void DaemonControllerMac::DoUpdateConfig( } void DaemonControllerMac::DoStop(const CompletionCallback& done_callback) { - if (!RunToolScriptAsRoot("--disable")) { + if (!RunToolScriptAsRoot("--disable", "")) { done_callback.Run(RESULT_FAILED); return; } @@ -253,7 +245,8 @@ void DaemonControllerMac::NotifyWhenStopped( } } -bool DaemonControllerMac::RunToolScriptAsRoot(const char* command) { +bool DaemonControllerMac::RunToolScriptAsRoot(const char* command, + const std::string& input_data) { // TODO(lambroslambrou): Supply a localized prompt string here. base::mac::ScopedAuthorizationRef authorization( base::mac::AuthorizationCreateToRunAsRoot(CFSTR(""))); @@ -270,24 +263,51 @@ bool DaemonControllerMac::RunToolScriptAsRoot(const char* command) { // TODO(lambroslambrou): Use sandbox-exec to minimize exposure - // http://crbug.com/120903 const char* arguments[] = { command, NULL }; - int exit_status; - OSStatus status = base::mac::ExecuteWithPrivilegesAndWait( + FILE* pipe = NULL; + pid_t pid; + OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID( authorization.get(), kStartStopTool, kAuthorizationFlagDefaults, arguments, - NULL, - &exit_status); + &pipe, + &pid); if (status != errAuthorizationSuccess) { OSSTATUS_LOG(ERROR, status) << "AuthorizationExecuteWithPrivileges"; return false; } - if (exit_status != 0) { - LOG(ERROR) << kStartStopTool << " failed with exit status " << exit_status; + if (pid == -1) { + LOG(ERROR) << "Failed to get child PID"; return false; } - return true; + DCHECK(pipe); + if (!input_data.empty()) { + size_t bytes_written = fwrite(input_data.data(), sizeof(char), + input_data.size(), pipe); + // According to the fwrite manpage, a partial count is returned only if a + // write error has occurred. + if (bytes_written != input_data.size()) { + LOG(ERROR) << "Failed to write data to child process"; + } + // Need to close, since the child waits for EOF on its stdin. + if (fclose(pipe) != 0) { + PLOG(ERROR) << "fclose"; + } + } + + int exit_status; + pid_t wait_result = HANDLE_EINTR(waitpid(pid, &exit_status, 0)); + if (wait_result != pid) { + PLOG(ERROR) << "waitpid"; + return false; + } + if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) { + return true; + } else { + LOG(ERROR) << kStartStopTool << " failed with exit status " << exit_status; + return false; + } } bool DaemonControllerMac::StopService() { |