| // Copyright 2018 The Chromium OS 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 "policy_utils/policy_tool.h" |
| |
| #include <base/check_op.h> |
| #include <base/logging.h> |
| #include <base/strings/string_util.h> |
| #include <base/values.h> |
| |
| namespace { |
| using base::CommandLine; |
| using base::CompareCaseInsensitiveASCII; |
| using base::Value; |
| using policy_utils::PolicyWriter; |
| |
| // The command that is being executed. |
| enum class Command { CMD_CLEAR, CMD_SET, CMD_UNKNOWN }; |
| |
| // Individual policies that this tool can handle. |
| constexpr char kPolicyDeviceAllowBluetooth[] = "DeviceAllowBlueTooth"; |
| constexpr char kShowHomeButton[] = "ShowHomeButton"; |
| constexpr char kBookmarkBarEnabled[] = "BookmarkBarEnabled"; |
| |
| // The same policies, bundled up in a list. |
| const policy_utils::PolicyTool::PolicyList known_policies = { |
| kBookmarkBarEnabled, kPolicyDeviceAllowBluetooth, kShowHomeButton}; |
| |
| // Compare two strings for equality ignoring case. |
| bool IsEqualNoCase(const std::string& a, const std::string& b) { |
| return CompareCaseInsensitiveASCII(a, b) == 0; |
| } |
| |
| // Returns whether the policy, identified by its name, is supported. |
| bool VerifyPolicyName(const std::string& policy_name) { |
| for (const std::string& policy : known_policies) { |
| if (IsEqualNoCase(policy, policy_name)) |
| return true; |
| } |
| return false; |
| } |
| |
| // Parse and return the command from the cmd-line arguments. Returns |
| // Command::CMD_UNKNOWN if the command string is missing or not recognized. |
| Command GetCommandFromArgs(const CommandLine::StringVector& args) { |
| if (args.size() < 1) |
| return Command::CMD_UNKNOWN; |
| |
| const std::string& cmd = args[0]; |
| if (IsEqualNoCase(cmd, "set")) |
| return Command::CMD_SET; |
| else if (IsEqualNoCase(cmd, "clear")) |
| return Command::CMD_CLEAR; |
| |
| LOG(ERROR) << "Not a valid command: " << cmd; |
| return Command::CMD_UNKNOWN; |
| } |
| |
| // Parse and return a boolean value from the cmd-line arguments. Returns a null |
| // Value if the cmd-line value argument is missing or not a boolean. |
| Value GetBoolValueFromArgs(const CommandLine::StringVector& args) { |
| if (args.size() >= 3) { |
| const std::string& value = args[2]; |
| if (IsEqualNoCase(value, "true")) |
| return Value(true); |
| else if (IsEqualNoCase(value, "false")) |
| return Value(false); |
| |
| LOG(ERROR) << "Not a valid boolean value: " << value; |
| return Value(); |
| } |
| |
| return Value(); |
| } |
| |
| // Parse and return the value that is being set for the given policy. Returns |
| // a null Value if the set-value is missing or is not not the right type for |
| // the given policy. |
| Value GetValueForSetCommand(const std::string& policy, |
| const CommandLine::StringVector& args) { |
| if (IsEqualNoCase(policy, kPolicyDeviceAllowBluetooth) || |
| IsEqualNoCase(policy, kShowHomeButton) || |
| IsEqualNoCase(policy, kBookmarkBarEnabled)) { |
| return GetBoolValueFromArgs(args); |
| } |
| |
| return Value(); |
| } |
| |
| // Handle command |cmd| for the given policy, taking any required value from |
| // the args list. Returns 0 in case of success or an error code otherwise. |
| bool HandleCommandForPolicy(Command cmd, |
| const std::string& policy, |
| const CommandLine::StringVector& args, |
| const PolicyWriter& writer) { |
| DCHECK_NE(cmd, Command::CMD_UNKNOWN); |
| |
| if (!VerifyPolicyName(policy)) { |
| LOG(ERROR) << "Not a valid policy name: " << policy; |
| return false; |
| } |
| |
| // If this is a 'set' command, parse the value to set from the args. |
| Value set_value; |
| if (cmd == Command::CMD_SET) { |
| set_value = GetValueForSetCommand(policy, args); |
| if (set_value.type() == Value::Type::NONE) { |
| LOG(ERROR) << "No value or invalid value specified"; |
| return false; |
| } |
| } |
| |
| bool result = false; |
| if (IsEqualNoCase(policy, kPolicyDeviceAllowBluetooth)) { |
| if (cmd == Command::CMD_SET) |
| result = writer.SetDeviceAllowBluetooth(set_value.GetBool()); |
| else |
| result = writer.ClearDeviceAllowBluetooth(); |
| } else if (IsEqualNoCase(policy, kShowHomeButton)) { |
| if (cmd == Command::CMD_SET) |
| result = writer.SetShowHomeButton(set_value.GetBool()); |
| else |
| result = writer.ClearShowHomeButton(); |
| } else if (IsEqualNoCase(policy, kBookmarkBarEnabled)) { |
| if (cmd == Command::CMD_SET) |
| result = writer.SetBookmarkBarEnabled(set_value.GetBool()); |
| else |
| result = writer.ClearBookmarkBarEnabled(); |
| } |
| |
| if (!result) { |
| LOG(ERROR) << "Could not write policy to file.\n" |
| "You may need to run policy with sudo. " |
| "You may also need to make your rootfs writeable."; |
| } |
| |
| return result; |
| } |
| |
| } // namespace |
| |
| namespace policy_utils { |
| |
| using base::CommandLine; |
| |
| constexpr char PolicyTool::kChromePolicyDirPath[]; |
| constexpr char PolicyTool::kChromiumPolicyDirPath[]; |
| |
| // PolicyTool::PolicyTool() : writer_(kChromePolicyDirPath) {} |
| |
| PolicyTool::PolicyTool(const std::string& policy_dir_path) |
| : writer_(policy_dir_path) {} |
| |
| bool PolicyTool::DoCommand(const CommandLine::StringVector& args) const { |
| // Args must have at least one command and one policy name. |
| if (args.size() < 2) |
| return false; |
| |
| Command cmd = GetCommandFromArgs(args); |
| if (cmd == Command::CMD_UNKNOWN) |
| return false; |
| |
| const std::string& policy = args[1]; |
| return HandleCommandForPolicy(cmd, policy, args, writer_); |
| } |
| |
| const PolicyTool::PolicyList& PolicyTool::get_policies() { |
| return known_policies; |
| } |
| |
| } // namespace policy_utils |