osquery-1/osquery/core/flags.cpp

226 lines
6.5 KiB
C++
Raw Normal View History

/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
2014-12-01 09:05:46 +00:00
#include <osquery/flags.h>
#include <osquery/registry.h>
2014-12-01 09:05:46 +00:00
#include "osquery/core/conversions.h"
#include "osquery/core/flagalias.h"
2015-02-17 08:36:20 +00:00
namespace boost {
template <>
bool lexical_cast<bool, std::string>(const std::string& arg) {
std::istringstream ss(arg);
bool b;
ss >> std::boolalpha >> b;
return b;
}
template <>
std::string lexical_cast<std::string, bool>(const bool& b) {
std::ostringstream ss;
ss << std::boolalpha << b;
return ss.str();
}
}
namespace flags = GFLAGS_NAMESPACE;
2014-12-01 09:05:46 +00:00
namespace osquery {
Flag& Flag::instance() {
static Flag f;
return f;
}
2015-02-17 08:36:20 +00:00
int Flag::create(const std::string& name, const FlagDetail& flag) {
2015-02-17 00:26:06 +00:00
instance().flags_.insert(std::make_pair(name, flag));
return 0;
2014-12-01 09:05:46 +00:00
}
2015-03-03 23:03:14 +00:00
int Flag::createAlias(const std::string& alias, const FlagDetail& flag) {
instance().aliases_.insert(std::make_pair(alias, flag));
2015-02-17 00:26:06 +00:00
return 0;
2014-12-01 09:05:46 +00:00
}
Status Flag::getDefaultValue(const std::string& name, std::string& value) {
flags::CommandLineFlagInfo info;
if (!flags::GetCommandLineFlagInfo(name.c_str(), &info)) {
2015-02-17 00:26:06 +00:00
return Status(1, "Flags name not found.");
2014-12-01 09:05:46 +00:00
}
2015-02-17 00:26:06 +00:00
value = info.default_value;
2014-12-01 09:05:46 +00:00
return Status(0, "OK");
}
bool Flag::isDefault(const std::string& name) {
flags::CommandLineFlagInfo info;
if (!flags::GetCommandLineFlagInfo(name.c_str(), &info)) {
2014-12-01 09:05:46 +00:00
return false;
}
2015-02-17 00:26:06 +00:00
return info.is_default;
2014-12-01 09:05:46 +00:00
}
2014-12-16 09:51:54 +00:00
std::string Flag::getValue(const std::string& name) {
const auto& custom = instance().custom_;
auto custom_flag = custom.find(name);
if (custom_flag != custom.end()) {
return custom_flag->second;
}
2014-12-16 09:51:54 +00:00
std::string current_value;
auto found = flags::GetCommandLineOption(name.c_str(), &current_value);
// If this is an extension and the flag was not found, forward the request.
if (Registry::get().external() && !found) {
PluginResponse resp;
Registry::call("config", {{"name", name}, {"action", "option"}}, resp);
if (resp.size() != 0) {
auto value = resp[0].find("value");
if (value != resp[0].end()) {
return value->second;
}
}
}
2014-12-16 09:51:54 +00:00
return current_value;
}
long int Flag::getInt32Value(const std::string& name) {
long int value = 0;
safeStrtol(Flag::getValue(name), 10, value);
return value;
}
2015-02-17 08:36:20 +00:00
std::string Flag::getType(const std::string& name) {
flags::CommandLineFlagInfo info;
if (!flags::GetCommandLineFlagInfo(name.c_str(), &info)) {
2015-02-17 08:36:20 +00:00
return "";
}
return info.type;
}
std::string Flag::getDescription(const std::string& name) {
if (instance().flags_.count(name)) {
return instance().flags_.at(name).description;
}
if (instance().aliases_.count(name)) {
2015-03-03 23:03:14 +00:00
return getDescription(instance().aliases_.at(name).description);
}
return "";
}
2014-12-01 09:05:46 +00:00
Status Flag::updateValue(const std::string& name, const std::string& value) {
2015-04-24 08:44:41 +00:00
if (instance().flags_.count(name) > 0) {
flags::SetCommandLineOption(name.c_str(), value.c_str());
2015-04-24 08:44:41 +00:00
return Status(0, "OK");
} else if (instance().aliases_.count(name) > 0) {
// Updating a flag by an alias name.
auto& real_name = instance().aliases_.at(name).description;
flags::SetCommandLineOption(real_name.c_str(), value.c_str());
return Status(0, "OK");
} else if (name.find("custom_") == 0) {
instance().custom_[name] = value;
2015-04-24 08:44:41 +00:00
}
return Status(1, "Flag not found");
2014-12-01 09:05:46 +00:00
}
2015-02-17 00:26:06 +00:00
std::map<std::string, FlagInfo> Flag::flags() {
std::vector<flags::CommandLineFlagInfo> info;
flags::GetAllFlags(&info);
2015-02-17 00:26:06 +00:00
std::map<std::string, FlagInfo> flags;
for (const auto& flag : info) {
if (instance().flags_.count(flag.name) == 0) {
// This flag info was not defined within osquery.
continue;
}
2015-02-17 08:36:20 +00:00
// Set the flag info from the internal info kept by Gflags, except for
// the stored description. Gflag keeps an "unknown" value if the flag
// was declared without a definition.
flags[flag.name] = {flag.type,
instance().flags_.at(flag.name).description,
flag.default_value,
flag.current_value,
2015-02-17 00:26:06 +00:00
instance().flags_.at(flag.name)};
}
for (const auto& flag : instance().custom_) {
flags[flag.first] = {"string", "", "", flag.second, {}};
}
2015-02-17 00:26:06 +00:00
return flags;
}
2015-03-03 23:03:14 +00:00
void Flag::printFlags(bool shell, bool external, bool cli) {
std::vector<flags::CommandLineFlagInfo> info;
flags::GetAllFlags(&info);
auto& details = instance().flags_;
2015-02-17 00:26:06 +00:00
std::map<std::string, const flags::CommandLineFlagInfo*> ordered_info;
for (const auto& flag : info) {
ordered_info[flag.name] = &flag;
}
// Determine max indent needed for all flag names.
2015-02-17 00:26:06 +00:00
size_t max = 0;
for (const auto& flag : details) {
max = (max > flag.first.size()) ? max : flag.first.size();
2015-02-17 00:26:06 +00:00
}
// Additional index for flag values.
max += 6;
2015-02-17 00:26:06 +00:00
// Show the Gflags-specific 'flagfile'.
if (!shell && cli) {
fprintf(stdout, " --flagfile PATH");
fprintf(stdout, "%s", std::string(max - 8 - 5, ' ').c_str());
fprintf(stdout, " Line-delimited file of additional flags\n");
}
auto& aliases = instance().aliases_;
for (const auto& flag : ordered_info) {
if (details.count(flag.second->name) > 0) {
const auto& detail = details.at(flag.second->name);
if ((shell && !detail.shell) || (!shell && detail.shell) ||
2015-03-03 23:03:14 +00:00
(external && !detail.external) || (!external && detail.external) ||
(cli && !detail.cli) || (!cli && detail.cli) || detail.hidden) {
continue;
}
} else if (aliases.count(flag.second->name) > 0) {
const auto& alias = aliases.at(flag.second->name);
// Aliases are only printed if this is an external tool and the alias
// is external.
if (!alias.external || !external) {
continue;
}
} else {
// This flag was not defined as an osquery flag or flag alias.
2015-02-17 00:26:06 +00:00
continue;
}
fprintf(stdout, " --%s", flag.second->name.c_str());
2015-02-17 00:26:06 +00:00
int pad = static_cast<int>(max);
if (flag.second->type != "bool") {
2015-02-17 00:26:06 +00:00
fprintf(stdout, " VALUE");
pad -= 6;
}
pad -= static_cast<int>(flag.second->name.size());
2015-02-17 00:26:06 +00:00
if (pad > 0 && pad < 80) {
// Never pad more than 80 characters.
fprintf(stdout, "%s", std::string(pad, ' ').c_str());
}
fprintf(stdout, " %s\n", getDescription(flag.second->name).c_str());
2014-12-01 09:05:46 +00:00
}
}
}