2015-02-03 05:21:36 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include <osquery/core.h>
|
|
|
|
#include <osquery/logger.h>
|
|
|
|
#include <osquery/sql.h>
|
|
|
|
#include <osquery/tables.h>
|
|
|
|
#include <osquery/registry.h>
|
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
|
|
|
const std::map<tables::ConstraintOperator, std::string> kSQLOperatorRepr = {
|
|
|
|
{tables::EQUALS, "="},
|
|
|
|
{tables::GREATER_THAN, ">"},
|
|
|
|
{tables::LESS_THAN_OR_EQUALS, "<="},
|
|
|
|
{tables::LESS_THAN, "<"},
|
|
|
|
{tables::GREATER_THAN_OR_EQUALS, ">="},
|
|
|
|
};
|
|
|
|
|
|
|
|
SQL::SQL(const std::string& q) { status_ = query(q, results_); }
|
|
|
|
|
2015-01-23 22:52:07 +00:00
|
|
|
const QueryData& SQL::rows() { return results_; }
|
2015-02-03 05:21:36 +00:00
|
|
|
|
|
|
|
bool SQL::ok() { return status_.ok(); }
|
|
|
|
|
2015-01-23 22:52:07 +00:00
|
|
|
Status SQL::getStatus() { return status_; }
|
|
|
|
|
2015-02-03 05:21:36 +00:00
|
|
|
std::string SQL::getMessageString() { return status_.toString(); }
|
|
|
|
|
2015-01-23 22:52:07 +00:00
|
|
|
const std::string SQL::kHostColumnName = "_source_host";
|
|
|
|
void SQL::annotateHostInfo() {
|
|
|
|
std::string hostname = getHostname();
|
|
|
|
for (Row& row : results_) {
|
|
|
|
row[kHostColumnName] = hostname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-03 05:21:36 +00:00
|
|
|
std::vector<std::string> SQL::getTableNames() {
|
|
|
|
std::vector<std::string> results;
|
|
|
|
for (const auto& name : Registry::names("table")) {
|
|
|
|
results.push_back(name);
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
QueryData SQL::selectAllFrom(const std::string& table) {
|
2015-02-06 17:42:03 +00:00
|
|
|
PluginResponse response;
|
|
|
|
PluginRequest request;
|
|
|
|
request["action"] = "generate";
|
|
|
|
|
|
|
|
Registry::call("table", table, request, response);
|
|
|
|
return response;
|
2015-02-03 05:21:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QueryData SQL::selectAllFrom(const std::string& table,
|
|
|
|
const std::string& column,
|
|
|
|
tables::ConstraintOperator op,
|
|
|
|
const std::string& expr) {
|
2015-02-06 17:42:03 +00:00
|
|
|
PluginResponse response;
|
|
|
|
PluginRequest request = {{"action", "generate"}};
|
|
|
|
tables::QueryContext ctx;
|
|
|
|
ctx.constraints[column].add(tables::Constraint(op, expr));
|
2015-02-03 05:21:36 +00:00
|
|
|
|
2015-02-06 17:42:03 +00:00
|
|
|
tables::TablePlugin::setRequestFromContext(ctx, request);
|
|
|
|
Registry::call("table", table, request, response);
|
|
|
|
return response;
|
2015-02-03 05:21:36 +00:00
|
|
|
}
|
|
|
|
|
2015-02-19 23:19:00 +00:00
|
|
|
Status SQLPlugin::call(const PluginRequest& request, PluginResponse& response) {
|
|
|
|
response.clear();
|
|
|
|
if (request.count("action") == 0) {
|
|
|
|
return Status(1, "SQL plugin must include a request action");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request.at("action") == "query") {
|
|
|
|
return this->query(request.at("query"), response);
|
|
|
|
} else if (request.at("action") == "columns") {
|
|
|
|
tables::TableColumns columns;
|
|
|
|
auto status = this->getQueryColumns(request.at("query"), columns);
|
|
|
|
// Convert columns to response
|
|
|
|
for (const auto& column : columns) {
|
|
|
|
response.push_back({{"n", column.first}, {"t", column.second}});
|
|
|
|
}
|
|
|
|
return status;
|
2015-02-23 05:56:52 +00:00
|
|
|
} else if (request.at("action") == "attach") {
|
|
|
|
// Attach a virtual table name using an optional included definition.
|
|
|
|
return this->attach(request.at("table"));
|
|
|
|
} else if (request.at("action") == "detach") {
|
|
|
|
this->detach(request.at("table"));
|
|
|
|
return Status(0, "OK");
|
2015-02-19 23:19:00 +00:00
|
|
|
}
|
|
|
|
return Status(1, "Unknown action");
|
|
|
|
}
|
|
|
|
|
2015-02-03 05:21:36 +00:00
|
|
|
Status query(const std::string& q, QueryData& results) {
|
2015-02-19 23:19:00 +00:00
|
|
|
return Registry::call(
|
|
|
|
"sql", "sql", {{"action", "query"}, {"query", q}}, results);
|
2015-02-03 05:21:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Status getQueryColumns(const std::string& q, tables::TableColumns& columns) {
|
2015-02-19 23:19:00 +00:00
|
|
|
PluginResponse response;
|
|
|
|
auto status = Registry::call(
|
|
|
|
"sql", "sql", {{"action", "columns"}, {"query", q}}, response);
|
|
|
|
|
|
|
|
// Convert response to columns
|
|
|
|
for (const auto& item : response) {
|
|
|
|
columns.push_back(make_pair(item.at("n"), item.at("t")));
|
|
|
|
}
|
|
|
|
return status;
|
2015-02-03 05:21:36 +00:00
|
|
|
}
|
|
|
|
}
|