2014-12-18 18:50:47 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
2015-01-21 20:56:25 +00:00
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
2014-12-18 18:50:47 +00:00
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*
|
|
|
|
*/
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2015-01-02 05:55:10 +00:00
|
|
|
#include <mutex>
|
2014-07-31 00:35:19 +00:00
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include <boost/property_tree/ptree.hpp>
|
|
|
|
#include <boost/property_tree/json_parser.hpp>
|
|
|
|
#include <boost/thread/shared_mutex.hpp>
|
|
|
|
|
2014-12-03 23:14:02 +00:00
|
|
|
#include <osquery/config.h>
|
|
|
|
#include <osquery/flags.h>
|
2015-01-16 01:40:42 +00:00
|
|
|
#include <osquery/hash.h>
|
2015-02-12 02:50:15 +00:00
|
|
|
#include <osquery/filesystem.h>
|
2015-01-21 21:36:55 +00:00
|
|
|
#include <osquery/logger.h>
|
2014-12-11 01:35:21 +00:00
|
|
|
|
2014-07-31 00:35:19 +00:00
|
|
|
namespace pt = boost::property_tree;
|
2015-02-12 02:50:15 +00:00
|
|
|
typedef std::map<std::string, std::vector<std::string> > EventFileMap_t;
|
|
|
|
|
2014-08-15 07:25:30 +00:00
|
|
|
namespace osquery {
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2015-03-03 23:03:14 +00:00
|
|
|
CLI_FLAG(string, config_plugin, "filesystem", "Config plugin name");
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2015-02-10 22:32:54 +00:00
|
|
|
// This lock is used to protect the entirety of the OSqueryConfig struct
|
|
|
|
// Is should be used when ever accessing the structs members, reading or
|
|
|
|
// writing.
|
2015-01-21 21:08:17 +00:00
|
|
|
static boost::shared_mutex rw_lock;
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2015-01-02 05:55:10 +00:00
|
|
|
Status Config::load() {
|
2015-03-08 21:52:13 +00:00
|
|
|
auto& config_plugin = Registry::getActive("config");
|
|
|
|
if (!Registry::exists("config", config_plugin)) {
|
|
|
|
return Status(1, "Missing config plugin " + config_plugin);
|
2015-03-04 02:40:24 +00:00
|
|
|
}
|
|
|
|
|
2014-07-31 00:35:19 +00:00
|
|
|
boost::unique_lock<boost::shared_mutex> lock(rw_lock);
|
2015-01-02 05:55:10 +00:00
|
|
|
|
2015-03-04 02:40:24 +00:00
|
|
|
OsqueryConfig conf;
|
|
|
|
if (!genConfig(conf).ok()) {
|
2015-01-02 05:55:10 +00:00
|
|
|
return Status(1, "Cannot generate config");
|
2014-12-01 09:05:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Override default arguments with flag options from config.
|
|
|
|
for (const auto& option : conf.options) {
|
|
|
|
if (Flag::isDefault(option.first)) {
|
|
|
|
// Only override if option was NOT given as an argument.
|
|
|
|
Flag::updateValue(option.first, option.second);
|
2015-03-03 23:03:14 +00:00
|
|
|
VLOG(1) << "Setting flag option: " << option.first << "="
|
|
|
|
<< option.second;
|
2014-11-17 22:19:09 +00:00
|
|
|
}
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
2015-03-04 02:40:24 +00:00
|
|
|
getInstance().cfg_ = conf;
|
2015-01-02 05:55:10 +00:00
|
|
|
return Status(0, "OK");
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
|
|
|
|
2014-12-11 01:35:21 +00:00
|
|
|
Status Config::genConfig(std::string& conf) {
|
2015-01-30 18:44:25 +00:00
|
|
|
PluginResponse response;
|
2015-03-08 21:52:13 +00:00
|
|
|
auto status = Registry::call("config", {{"action", "genConfig"}}, response);
|
2015-01-30 18:44:25 +00:00
|
|
|
if (!status.ok()) {
|
|
|
|
return status;
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
2015-01-04 07:12:28 +00:00
|
|
|
|
2015-01-30 18:44:25 +00:00
|
|
|
conf = response[0].at("data");
|
2014-12-11 01:35:21 +00:00
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
|
|
|
Status Config::genConfig(OsqueryConfig& conf) {
|
|
|
|
std::string config_string;
|
|
|
|
auto s = genConfig(config_string);
|
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
|
|
|
}
|
2015-01-04 07:12:28 +00:00
|
|
|
std::stringstream json;
|
|
|
|
pt::ptree tree;
|
2014-07-31 00:35:19 +00:00
|
|
|
try {
|
2015-01-04 07:12:28 +00:00
|
|
|
json << config_string;
|
|
|
|
pt::read_json(json, tree);
|
2014-12-01 09:05:46 +00:00
|
|
|
// Parse each scheduled query from the config.
|
2014-08-15 07:25:30 +00:00
|
|
|
for (const pt::ptree::value_type& v : tree.get_child("scheduledQueries")) {
|
2015-02-13 20:32:54 +00:00
|
|
|
osquery::OsqueryScheduledQuery q;
|
2014-07-31 00:35:19 +00:00
|
|
|
q.name = (v.second).get<std::string>("name");
|
|
|
|
q.query = (v.second).get<std::string>("query");
|
|
|
|
q.interval = (v.second).get<int>("interval");
|
|
|
|
conf.scheduledQueries.push_back(q);
|
|
|
|
}
|
2014-12-01 09:05:46 +00:00
|
|
|
|
|
|
|
// Flags may be set as 'options' within the config.
|
|
|
|
if (tree.count("options") > 0) {
|
|
|
|
for (const pt::ptree::value_type& v : tree.get_child("options")) {
|
|
|
|
conf.options[v.first.data()] = v.second.data();
|
|
|
|
}
|
|
|
|
}
|
2015-02-10 22:32:54 +00:00
|
|
|
|
2015-02-14 00:52:11 +00:00
|
|
|
if (tree.count("additional_monitoring") > 0) {
|
2015-02-28 01:28:51 +00:00
|
|
|
ReturnSetting settings = REC_LIST_FOLDERS | REC_EVENT_OPT;
|
2015-02-14 00:52:11 +00:00
|
|
|
for (const pt::ptree::value_type& v :
|
|
|
|
tree.get_child("additional_monitoring")) {
|
2015-02-13 20:32:54 +00:00
|
|
|
if (v.first == "file_paths") {
|
|
|
|
for (const pt::ptree::value_type& file_cat : v.second) {
|
|
|
|
for (const pt::ptree::value_type& file : file_cat.second) {
|
2015-02-14 00:52:11 +00:00
|
|
|
osquery::resolveFilePattern(file.second.get_value<std::string>(),
|
2015-02-28 01:28:51 +00:00
|
|
|
conf.eventFiles[file_cat.first],
|
|
|
|
settings);
|
2015-02-13 20:32:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-09-21 21:29:28 +00:00
|
|
|
} catch (const std::exception& e) {
|
2014-07-31 00:35:19 +00:00
|
|
|
LOG(ERROR) << "Error parsing config JSON: " << e.what();
|
|
|
|
return Status(1, e.what());
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
2014-09-15 18:17:48 +00:00
|
|
|
std::vector<OsqueryScheduledQuery> Config::getScheduledQueries() {
|
2014-07-31 00:35:19 +00:00
|
|
|
boost::shared_lock<boost::shared_mutex> lock(rw_lock);
|
2015-02-18 02:04:15 +00:00
|
|
|
return getInstance().cfg_.scheduledQueries;
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
2014-11-17 22:19:09 +00:00
|
|
|
|
2015-02-18 02:04:15 +00:00
|
|
|
std::map<std::string, std::vector<std::string> >& Config::getWatchedFiles() {
|
2015-02-10 22:32:54 +00:00
|
|
|
boost::shared_lock<boost::shared_mutex> lock(rw_lock);
|
2015-02-18 02:04:15 +00:00
|
|
|
return getInstance().cfg_.eventFiles;
|
2015-02-10 22:32:54 +00:00
|
|
|
}
|
|
|
|
|
2015-01-16 20:03:23 +00:00
|
|
|
Status Config::getMD5(std::string& hash_string) {
|
2014-12-11 01:35:21 +00:00
|
|
|
std::string config_string;
|
|
|
|
auto s = genConfig(config_string);
|
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2015-01-20 22:05:01 +00:00
|
|
|
hash_string = osquery::hashFromBuffer(
|
|
|
|
HASH_TYPE_MD5, (void*)config_string.c_str(), config_string.length());
|
2014-12-11 01:35:21 +00:00
|
|
|
|
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
2015-01-21 20:56:25 +00:00
|
|
|
|
|
|
|
Status Config::checkConfig() {
|
|
|
|
OsqueryConfig c;
|
|
|
|
return genConfig(c);
|
|
|
|
}
|
2015-01-30 18:44:25 +00:00
|
|
|
|
|
|
|
Status ConfigPlugin::call(const PluginRequest& request,
|
|
|
|
PluginResponse& response) {
|
|
|
|
if (request.count("action") == 0) {
|
|
|
|
return Status(1, "Config plugins require an action in PluginRequest");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request.at("action") == "genConfig") {
|
|
|
|
auto config_data = genConfig();
|
|
|
|
response.push_back({{"data", config_data.second}});
|
|
|
|
return config_data.first;
|
|
|
|
}
|
|
|
|
return Status(1, "Config plugin action unknown: " + request.at("action"));
|
|
|
|
}
|
2014-08-15 07:25:30 +00:00
|
|
|
}
|