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-22 21:57:14 +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-11-25 20:30:29 +00:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2015-08-14 01:04:03 +00:00
|
|
|
#include <deque>
|
2014-11-25 20:30:29 +00:00
|
|
|
#include <map>
|
2014-12-03 04:36:46 +00:00
|
|
|
#include <memory>
|
2014-11-25 20:30:29 +00:00
|
|
|
#include <vector>
|
2015-02-06 17:42:03 +00:00
|
|
|
#include <set>
|
2014-11-25 20:30:29 +00:00
|
|
|
|
|
|
|
#include <boost/lexical_cast.hpp>
|
2015-01-30 18:44:25 +00:00
|
|
|
#include <boost/property_tree/ptree.hpp>
|
2014-11-25 20:30:29 +00:00
|
|
|
|
2015-01-30 18:44:25 +00:00
|
|
|
#include <osquery/registry.h>
|
2015-01-22 21:57:14 +00:00
|
|
|
#include <osquery/core.h>
|
2015-05-24 01:52:42 +00:00
|
|
|
#include <osquery/database.h>
|
2014-12-03 23:31:09 +00:00
|
|
|
#include <osquery/status.h>
|
2014-11-25 20:30:29 +00:00
|
|
|
|
2015-04-12 02:50:35 +00:00
|
|
|
/// Allow Tables to use "tracked" deprecated OS APIs.
|
2015-02-10 23:58:08 +00:00
|
|
|
#define OSQUERY_USE_DEPRECATED(expr) \
|
|
|
|
do { \
|
|
|
|
_Pragma("clang diagnostic push") \
|
|
|
|
_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \
|
|
|
|
expr; \
|
|
|
|
_Pragma("clang diagnostic pop") \
|
|
|
|
} while (0)
|
|
|
|
|
2014-11-25 20:30:29 +00:00
|
|
|
namespace osquery {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The SQLite type affinities are available as macros
|
|
|
|
*
|
|
|
|
* Type affinities: TEXT, INTEGER, BIGINT
|
|
|
|
*
|
|
|
|
* You can represent any data that can be lexically casted to a string.
|
|
|
|
* Using the type affinity names helps table developers understand the data
|
|
|
|
* types they are storing, and more importantly how they are treated at query
|
|
|
|
* time.
|
|
|
|
*/
|
|
|
|
#define TEXT(x) boost::lexical_cast<std::string>(x)
|
2014-11-26 00:28:10 +00:00
|
|
|
/// See the affinity type documentation for TEXT.
|
2014-11-25 20:30:29 +00:00
|
|
|
#define INTEGER(x) boost::lexical_cast<std::string>(x)
|
2014-11-26 00:28:10 +00:00
|
|
|
/// See the affinity type documentation for TEXT.
|
2014-11-25 20:30:29 +00:00
|
|
|
#define BIGINT(x) boost::lexical_cast<std::string>(x)
|
2014-11-26 00:28:10 +00:00
|
|
|
/// See the affinity type documentation for TEXT.
|
2014-11-25 20:30:29 +00:00
|
|
|
#define UNSIGNED_BIGINT(x) boost::lexical_cast<std::string>(x)
|
2015-06-22 07:55:17 +00:00
|
|
|
/// See the affinity type documentation for TEXT.
|
|
|
|
#define DOUBLE(x) boost::lexical_cast<std::string>(x)
|
2014-11-25 20:30:29 +00:00
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief The SQLite type affinities as represented as implementation literals.
|
|
|
|
*
|
|
|
|
* Type affinities: TEXT=std::string, INTEGER=int, BIGINT=long long int
|
|
|
|
*
|
|
|
|
* Just as the SQLite data is represented as lexically casted strings, as table
|
|
|
|
* may make use of the implementation language literals.
|
|
|
|
*/
|
2014-11-25 20:30:29 +00:00
|
|
|
#define TEXT_LITERAL std::string
|
2014-11-26 00:28:10 +00:00
|
|
|
/// See the literal type documentation for TEXT_LITERAL.
|
2014-11-25 20:30:29 +00:00
|
|
|
#define INTEGER_LITERAL int
|
2014-11-26 00:28:10 +00:00
|
|
|
/// See the literal type documentation for TEXT_LITERAL.
|
2014-11-25 20:30:29 +00:00
|
|
|
#define BIGINT_LITERAL long long int
|
2014-11-26 00:28:10 +00:00
|
|
|
/// See the literal type documentation for TEXT_LITERAL.
|
2014-11-25 20:30:29 +00:00
|
|
|
#define UNSIGNED_BIGINT_LITERAL unsigned long long int
|
2015-06-22 07:55:17 +00:00
|
|
|
/// See the literal type documentation for TEXT_LITERAL.
|
|
|
|
#define DOUBLE_LITERAL double
|
2014-11-26 00:28:10 +00:00
|
|
|
/// Cast an SQLite affinity type to the literal type.
|
2014-11-25 20:30:29 +00:00
|
|
|
#define AS_LITERAL(literal, value) boost::lexical_cast<literal>(value)
|
|
|
|
|
2015-01-12 18:02:44 +00:00
|
|
|
/// Helper alias for TablePlugin names.
|
2015-01-30 18:44:25 +00:00
|
|
|
typedef std::string TableName;
|
|
|
|
typedef std::vector<std::pair<std::string, std::string> > TableColumns;
|
2015-08-14 01:04:03 +00:00
|
|
|
typedef std::map<std::string, std::deque<std::string> > TableData;
|
2015-01-12 18:02:44 +00:00
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief A ConstraintOperator is applied in an query predicate.
|
|
|
|
*
|
|
|
|
* If the query contains a join or where clause with a constraint operator and
|
|
|
|
* expression the table generator may limit the data appropriately.
|
|
|
|
*/
|
2015-05-29 20:47:04 +00:00
|
|
|
enum ConstraintOperator : unsigned char {
|
2014-11-25 20:30:29 +00:00
|
|
|
EQUALS = 2,
|
|
|
|
GREATER_THAN = 4,
|
|
|
|
LESS_THAN_OR_EQUALS = 8,
|
|
|
|
LESS_THAN = 16,
|
|
|
|
GREATER_THAN_OR_EQUALS = 32
|
|
|
|
};
|
|
|
|
|
2015-06-22 07:55:17 +00:00
|
|
|
/// Type for flags for what constraint operators are admissible.
|
2015-05-29 20:47:04 +00:00
|
|
|
typedef unsigned char ConstraintOperatorFlag;
|
|
|
|
/// Flag for any operator type.
|
|
|
|
#define ANY_OP 0xFFU
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief A Constraint is an operator and expression.
|
|
|
|
*
|
|
|
|
* The constraint is applied to columns which have literal and affinity types.
|
|
|
|
*/
|
2014-11-25 20:30:29 +00:00
|
|
|
struct Constraint {
|
|
|
|
unsigned char op;
|
|
|
|
std::string expr;
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/// Construct a Constraint with the most-basic information, the operator.
|
2015-02-24 11:47:12 +00:00
|
|
|
explicit Constraint(unsigned char _op) { op = _op; }
|
2015-01-12 18:02:44 +00:00
|
|
|
|
|
|
|
// A constraint list in a context knows only the operator at creation.
|
2015-04-12 02:50:35 +00:00
|
|
|
explicit Constraint(unsigned char _op, const std::string& _expr)
|
|
|
|
: op(_op), expr(_expr) {}
|
2014-11-25 20:30:29 +00:00
|
|
|
};
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief A ConstraintList is a set of constraints for a column. This list
|
|
|
|
* should be mapped to a left-hand-side column name.
|
|
|
|
*
|
|
|
|
* The table generator does not need to check each constraint in its decision
|
|
|
|
* logic. The common constraint checking patterns (match) are abstracted using
|
|
|
|
* simple logic operators on the literal SQLite affinity types.
|
|
|
|
*
|
|
|
|
* A constraint list supports all AS_LITERAL types, and all ConstraintOperators.
|
|
|
|
*/
|
2014-11-25 20:30:29 +00:00
|
|
|
struct ConstraintList {
|
|
|
|
/// The SQLite affinity type.
|
|
|
|
std::string affinity;
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief Check if an expression matches the query constraints.
|
|
|
|
*
|
2015-01-12 18:02:44 +00:00
|
|
|
* Evaluate ALL constraints in this ConstraintList against the string
|
2015-04-12 02:50:35 +00:00
|
|
|
* expression. The affinity of the constraint will be used as the affinite
|
2015-01-12 18:02:44 +00:00
|
|
|
* and lexical type of the expression and set of constraint expressions.
|
2015-03-26 23:18:28 +00:00
|
|
|
* If there are no predicate constraints in this list, all expression will
|
|
|
|
* match. Constraints are limitations.
|
2015-01-12 18:02:44 +00:00
|
|
|
*
|
|
|
|
* @param expr a SQL type expression of the column literal type to check.
|
2014-11-26 00:28:10 +00:00
|
|
|
* @return If the expression matched all constraints.
|
|
|
|
*/
|
2015-02-11 03:18:56 +00:00
|
|
|
bool matches(const std::string& expr) const;
|
2014-11-25 20:30:29 +00:00
|
|
|
|
2015-01-12 18:02:44 +00:00
|
|
|
/**
|
|
|
|
* @brief Check if an expression matches the query constraints.
|
|
|
|
*
|
|
|
|
* `matches` also supports the set of SQL affinite types.
|
|
|
|
* The expression expr will be evaluated as a string and compared using
|
|
|
|
* the affinity of the constraint.
|
|
|
|
*
|
|
|
|
* @param expr a SQL type expression of the column literal type to check.
|
|
|
|
* @return If the expression matched all constraints.
|
|
|
|
*/
|
2014-11-27 09:45:35 +00:00
|
|
|
template <typename T>
|
2015-02-11 03:18:56 +00:00
|
|
|
bool matches(const T& expr) const {
|
2015-01-12 18:02:44 +00:00
|
|
|
return matches(TEXT(expr));
|
2014-11-27 09:45:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-05-29 20:47:04 +00:00
|
|
|
* @brief Check and return if there are constraints on this column.
|
2015-01-12 18:02:44 +00:00
|
|
|
*
|
2015-01-22 21:57:14 +00:00
|
|
|
* A ConstraintList is used in a ConstraintMap with a column name as the
|
2015-01-12 18:02:44 +00:00
|
|
|
* map index. Tables that act on optional constraints should check if any
|
2015-05-29 20:47:04 +00:00
|
|
|
* constraint was provided. The ops parameter serves to specify which
|
|
|
|
* operators we want to check existence for.
|
2015-01-12 18:02:44 +00:00
|
|
|
*
|
2015-05-29 20:47:04 +00:00
|
|
|
* @param ops (Optional: default ANY_OP) The operators types to look for.
|
2015-01-12 18:02:44 +00:00
|
|
|
* @return true if any constraint exists.
|
|
|
|
*/
|
2015-05-29 20:47:04 +00:00
|
|
|
bool exists(const ConstraintOperatorFlag ops = ANY_OP) const {
|
|
|
|
if (ops == ANY_OP) {
|
|
|
|
return (constraints_.size() > 0);
|
|
|
|
} else {
|
|
|
|
for (const struct Constraint &c : constraints_) {
|
|
|
|
if (c.op & ops) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2015-01-12 18:02:44 +00:00
|
|
|
|
|
|
|
/**
|
2015-04-12 02:50:35 +00:00
|
|
|
* @brief Check if a constraint exist AND matches the type expression.
|
2015-01-12 18:02:44 +00:00
|
|
|
*
|
|
|
|
* See ConstraintList::exists and ConstraintList::matches.
|
|
|
|
*
|
|
|
|
* @param expr The expression to match.
|
|
|
|
* @return true if any constraint exists AND matches the type expression.
|
2014-11-27 09:45:35 +00:00
|
|
|
*/
|
2015-01-12 18:02:44 +00:00
|
|
|
template <typename T>
|
2015-02-11 03:18:56 +00:00
|
|
|
bool existsAndMatches(const T& expr) const {
|
2014-11-29 01:40:23 +00:00
|
|
|
return (exists() && matches(expr));
|
|
|
|
}
|
|
|
|
|
2015-01-12 18:02:44 +00:00
|
|
|
/**
|
|
|
|
* @brief Check if a constraint is missing or matches a type expression.
|
|
|
|
*
|
2015-01-22 21:57:14 +00:00
|
|
|
* A ConstraintList is used in a ConstraintMap with a column name as the
|
2015-01-12 18:02:44 +00:00
|
|
|
* map index. Tables that act on required constraints can make decisions
|
|
|
|
* on missing constraints or a constraint match.
|
|
|
|
*
|
|
|
|
* @param expr The expression to match.
|
|
|
|
* @return true if constraint is missing or matches the type expression.
|
|
|
|
*/
|
|
|
|
template <typename T>
|
2015-02-11 03:18:56 +00:00
|
|
|
bool notExistsOrMatches(const T& expr) const {
|
2014-11-29 01:40:23 +00:00
|
|
|
return (!exists() || matches(expr));
|
|
|
|
}
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
2015-01-12 18:02:44 +00:00
|
|
|
* @brief Helper templated function for ConstraintList::matches.
|
2014-11-26 00:28:10 +00:00
|
|
|
*/
|
2014-11-25 20:30:29 +00:00
|
|
|
template <typename T>
|
2015-02-11 03:18:56 +00:00
|
|
|
bool literal_matches(const T& base_expr) const;
|
2014-11-25 20:30:29 +00:00
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief Get all expressions for a given ConstraintOperator.
|
|
|
|
*
|
|
|
|
* This is most useful if the table generation requires as column.
|
|
|
|
* The generator may `getAll(EQUALS)` then iterate.
|
|
|
|
*
|
|
|
|
* @param op the ConstraintOperator.
|
|
|
|
* @return A list of TEXT%-represented types matching the operator.
|
|
|
|
*/
|
2015-02-11 03:18:56 +00:00
|
|
|
std::set<std::string> getAll(ConstraintOperator op) const;
|
2015-02-06 17:42:03 +00:00
|
|
|
|
2015-07-06 07:04:37 +00:00
|
|
|
/// See ConstraintList::getAll, but as a selected literal type.
|
2015-02-06 17:42:03 +00:00
|
|
|
template<typename T>
|
2015-02-11 03:18:56 +00:00
|
|
|
std::set<T> getAll(ConstraintOperator op) const {
|
2015-02-06 17:42:03 +00:00
|
|
|
std::set<T> literal_matches;
|
|
|
|
auto matches = getAll(op);
|
|
|
|
for (const auto& match : matches) {
|
|
|
|
literal_matches.insert(AS_LITERAL(T, match));
|
|
|
|
}
|
|
|
|
return literal_matches;
|
|
|
|
}
|
2014-11-25 20:30:29 +00:00
|
|
|
|
2015-07-06 07:04:37 +00:00
|
|
|
/// Constraint list accessor, types and operator.
|
|
|
|
const std::vector<struct Constraint> getAll() const { return constraints_; }
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief Add a new Constraint to the list of constraints.
|
|
|
|
*
|
|
|
|
* @param constraint a new operator/expression to constrain.
|
|
|
|
*/
|
2014-11-25 20:30:29 +00:00
|
|
|
void add(const struct Constraint& constraint) {
|
2015-01-12 18:02:44 +00:00
|
|
|
constraints_.push_back(constraint);
|
2014-11-25 20:30:29 +00:00
|
|
|
}
|
2015-01-12 18:02:44 +00:00
|
|
|
|
2015-01-30 18:44:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Serialize a ConstraintList into a property tree.
|
|
|
|
*
|
|
|
|
* The property tree will use the format:
|
|
|
|
* {
|
|
|
|
* "affinity": affinity,
|
|
|
|
* "list": [
|
|
|
|
* {"op": op, "expr": expr}, ...
|
|
|
|
* ]
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
void serialize(boost::property_tree::ptree& tree) const;
|
2015-07-06 07:04:37 +00:00
|
|
|
|
|
|
|
/// See ConstraintList::unserialize.
|
2015-01-30 18:44:25 +00:00
|
|
|
void unserialize(const boost::property_tree::ptree& tree);
|
|
|
|
|
2015-04-12 02:50:35 +00:00
|
|
|
ConstraintList() : affinity("TEXT") {}
|
2015-01-12 18:02:44 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
/// List of constraint operator/expressions.
|
|
|
|
std::vector<struct Constraint> constraints_;
|
|
|
|
|
|
|
|
private:
|
|
|
|
FRIEND_TEST(TablesTests, test_constraint_list);
|
2014-11-25 20:30:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Pass a constraint map to the query request.
|
|
|
|
typedef std::map<std::string, struct ConstraintList> ConstraintMap;
|
2015-04-12 02:50:35 +00:00
|
|
|
/// Populate a constraint list from a query's parsed predicate.
|
2014-11-25 20:30:29 +00:00
|
|
|
typedef std::vector<std::pair<std::string, struct Constraint> > ConstraintSet;
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief A QueryContext is provided to every table generator for optimization
|
|
|
|
* on query components like predicate constraints and limits.
|
|
|
|
*/
|
|
|
|
struct QueryContext {
|
2014-11-25 20:30:29 +00:00
|
|
|
ConstraintMap constraints;
|
|
|
|
/// Support a limit to the number of results.
|
|
|
|
int limit;
|
2015-01-30 18:44:25 +00:00
|
|
|
|
|
|
|
QueryContext() : limit(0) {}
|
2014-11-25 20:30:29 +00:00
|
|
|
};
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
typedef struct QueryContext QueryContext;
|
2014-11-25 20:30:29 +00:00
|
|
|
typedef struct Constraint Constraint;
|
2015-01-12 18:02:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The TablePlugin defines the name, types, and column information.
|
|
|
|
*
|
|
|
|
* To attach a virtual table create a TablePlugin subclass and register the
|
|
|
|
* virtual table name as the plugin ID. osquery will enumerate all registered
|
2015-04-12 02:50:35 +00:00
|
|
|
* TablePlugins and attempt to attach them to SQLite at instantiation.
|
2015-01-22 21:57:14 +00:00
|
|
|
*
|
|
|
|
* Note: When updating this class, be sure to update the corresponding template
|
|
|
|
* in osquery/tables/templates/default.cpp.in
|
2015-01-12 18:02:44 +00:00
|
|
|
*/
|
2015-01-30 18:44:25 +00:00
|
|
|
class TablePlugin : public Plugin {
|
|
|
|
protected:
|
2015-11-09 02:31:50 +00:00
|
|
|
/// Return the table's column name and type pairs.
|
|
|
|
virtual TableColumns columns() const { return TableColumns(); }
|
2015-01-12 18:02:44 +00:00
|
|
|
|
2015-11-09 02:31:50 +00:00
|
|
|
/**
|
|
|
|
* @brief Generate a complete table representation.
|
|
|
|
*
|
|
|
|
* The TablePlugin::generate method is the most important part of the table.
|
|
|
|
* This should return a best-effort match of the expected results for a
|
|
|
|
* query. In common cases, this returns all rows for a virtual table.
|
|
|
|
* For EventSubscriber tables this will perform database lookups for events
|
|
|
|
* matching several conditions such as time within the SQL query or the last
|
|
|
|
* time the EventSubscriber was called.
|
|
|
|
*
|
|
|
|
* The context input is filled in "as best possible" by SQLite's
|
|
|
|
* virtual table APIs. In the best case this context include a limit or
|
|
|
|
* constraints organized by each possible column.
|
|
|
|
*
|
|
|
|
* @param request A query context filled in by SQLite's virtual table API.
|
|
|
|
* @return The result rows for this table, given the query context.
|
|
|
|
*/
|
|
|
|
virtual QueryData generate(QueryContext& request) { return QueryData(); }
|
2015-01-12 18:02:44 +00:00
|
|
|
|
2015-02-23 05:56:52 +00:00
|
|
|
protected:
|
2015-11-09 02:31:50 +00:00
|
|
|
/// An SQL table containing the table definition/syntax.
|
2015-02-23 05:56:52 +00:00
|
|
|
std::string columnDefinition() const;
|
2015-11-09 02:31:50 +00:00
|
|
|
|
|
|
|
/// Return the name and column pairs for attaching virtual tables.
|
2015-02-23 05:56:52 +00:00
|
|
|
PluginResponse routeInfo() const;
|
|
|
|
|
2015-11-09 02:31:50 +00:00
|
|
|
/**
|
|
|
|
* @brief Check if there are fresh cache results for this table.
|
|
|
|
*
|
|
|
|
* Table results are considered fresh when evaluated against a given interval.
|
|
|
|
* The interval is the expected rate for which this data should be generated.
|
|
|
|
* Caching and cache freshness only applies to queries acting on tables
|
|
|
|
* within a schedule. If two queries "one" and "two" both inspect the
|
|
|
|
* table "processes" at the interval 60. The first executed will cache results
|
|
|
|
* and the second will use the cached results.
|
|
|
|
*
|
|
|
|
* Table results are not cached if a QueryContext contains constraints or
|
|
|
|
* provides HOB (hand-off blocks) to additional tables within a query.
|
|
|
|
* Currently, the query scheduler cannot communicate to table implementations.
|
|
|
|
* An interval is set globally by the scheduler and passed to the table
|
|
|
|
* implementation as a future-proof API. There is no "shortcut" for caching
|
|
|
|
* when used in external tables. A cache lookup within an extension means
|
|
|
|
* a database call API and re-serialization to the virtual table APIs. In
|
|
|
|
* practice this does not perform well and is explicitly disabled.
|
|
|
|
*
|
|
|
|
* @param interval The interval this query expects the tables results.
|
|
|
|
* @return True if the cache contains fresh results, otherwise false.
|
|
|
|
*/
|
|
|
|
bool isCached(size_t interval);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Perform a database lookup of cached results and deserialize.
|
|
|
|
*
|
|
|
|
* If a query determined the table's cached results are fresh, it may ask the
|
|
|
|
* table to retrieve results from the database and deserialized them into
|
|
|
|
* table row data.
|
|
|
|
*
|
|
|
|
* @return The deserialized row data of cached results.
|
|
|
|
*/
|
|
|
|
QueryData getCache() const;
|
|
|
|
|
|
|
|
/// Similar to TablePlugin::getCache, if TablePlugin::generate is called.
|
|
|
|
void setCache(size_t step, size_t interval, const QueryData& results);
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// The last time in seconds the table data results were saved to cache.
|
|
|
|
size_t last_cached_{0};
|
|
|
|
/// The last interval in seconds when the table data was cached.
|
|
|
|
size_t last_interval_{0};
|
|
|
|
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* @brief The scheduled interval for the executing query.
|
|
|
|
*
|
|
|
|
* Scheduled queries execute within a pseudo-mutex, and each may communicate
|
|
|
|
* their scheduled interval to internal TablePlugin implementations. If the
|
|
|
|
* table is cachable then the interval can be used to calculate freshness.
|
|
|
|
*/
|
|
|
|
static size_t kCacheInterval;
|
|
|
|
/// The schedule step, this is the current position of the schedule.
|
|
|
|
static size_t kCacheStep;
|
|
|
|
|
2015-01-12 18:02:44 +00:00
|
|
|
public:
|
2015-11-09 02:31:50 +00:00
|
|
|
/**
|
|
|
|
* @brief The registry call "router".
|
|
|
|
*
|
|
|
|
* Like all of osquery's Plugin%s, the TablePlugin uses a "call" router to
|
|
|
|
* handle requests and responses from extensions. The TablePlugin uses an
|
|
|
|
* "action" key, which can be:
|
|
|
|
* - generate: call the plugin's row generate method (defined in spec).
|
|
|
|
* - columns: return a list of column name and SQLite types.
|
|
|
|
* - definition: return an SQL statement for table creation.
|
|
|
|
*
|
|
|
|
* @param request The plugin request, must include an action key.
|
|
|
|
* @param response A plugin response, for generation this contains the rows.
|
|
|
|
*/
|
2015-01-30 18:44:25 +00:00
|
|
|
Status call(const PluginRequest& request, PluginResponse& response);
|
2015-01-12 18:02:44 +00:00
|
|
|
|
2015-01-30 18:44:25 +00:00
|
|
|
public:
|
2015-11-09 02:31:50 +00:00
|
|
|
/// Helper data structure transformation methods.
|
2015-01-30 18:44:25 +00:00
|
|
|
static void setRequestFromContext(const QueryContext& context,
|
|
|
|
PluginRequest& request);
|
2015-11-09 02:31:50 +00:00
|
|
|
|
|
|
|
/// Helper data structure transformation methods.
|
2015-01-30 18:44:25 +00:00
|
|
|
static void setContextFromRequest(const PluginRequest& request,
|
|
|
|
QueryContext& context);
|
2015-01-31 01:52:14 +00:00
|
|
|
|
2015-02-23 05:56:52 +00:00
|
|
|
public:
|
2015-11-09 02:31:50 +00:00
|
|
|
/**
|
|
|
|
* @brief Add a virtual table that exists in an extension.
|
|
|
|
*
|
|
|
|
* When external table plugins are registered the core will attach them
|
|
|
|
* as virtual tables to the SQL internal implementation.
|
|
|
|
*
|
|
|
|
* @param name The table name.
|
|
|
|
* @param info The route info (column name and type pairs).
|
|
|
|
*/
|
2015-02-23 05:56:52 +00:00
|
|
|
static Status addExternal(const std::string& name,
|
|
|
|
const PluginResponse& info);
|
2015-11-09 02:31:50 +00:00
|
|
|
|
|
|
|
/// Remove an extension's table from the SQL virtual database.
|
2015-02-23 05:56:52 +00:00
|
|
|
static void removeExternal(const std::string& name);
|
|
|
|
|
2015-01-31 01:52:14 +00:00
|
|
|
private:
|
|
|
|
FRIEND_TEST(VirtualTableTests, test_tableplugin_columndefinition);
|
|
|
|
FRIEND_TEST(VirtualTableTests, test_tableplugin_statement);
|
2015-01-12 18:02:44 +00:00
|
|
|
};
|
|
|
|
|
2015-02-23 05:56:52 +00:00
|
|
|
/// Helper method to generate the virtual table CREATE statement.
|
|
|
|
std::string columnDefinition(const TableColumns& columns);
|
2015-11-09 02:31:50 +00:00
|
|
|
|
|
|
|
/// Helper method to generate the virtual table CREATE statement.
|
2015-02-23 05:56:52 +00:00
|
|
|
std::string columnDefinition(const PluginResponse& response);
|
|
|
|
|
2015-03-04 02:40:24 +00:00
|
|
|
CREATE_LAZY_REGISTRY(TablePlugin, "table");
|
2014-11-25 20:30:29 +00:00
|
|
|
}
|