2014-11-25 20:30:29 +00:00
|
|
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <map>
|
2014-12-03 04:36:46 +00:00
|
|
|
#include <memory>
|
2014-11-25 20:30:29 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
|
2014-12-03 04:36:46 +00:00
|
|
|
#include <sqlite3.h>
|
|
|
|
|
2014-12-03 23:31:09 +00:00
|
|
|
#include <osquery/database/results.h>
|
|
|
|
#include <osquery/status.h>
|
2014-11-25 20:30:29 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
namespace tables {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
|
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
|
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)
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
enum ConstraintOperator {
|
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
|
|
|
|
};
|
|
|
|
|
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.
|
2014-11-25 20:30:29 +00:00
|
|
|
Constraint(unsigned char _op) { op = _op; }
|
|
|
|
};
|
|
|
|
|
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 {
|
2014-11-26 00:28:10 +00:00
|
|
|
/// List of constraint operator/expressions.
|
2014-11-25 20:30:29 +00:00
|
|
|
std::vector<struct Constraint> constraints;
|
|
|
|
/// The SQLite affinity type.
|
|
|
|
std::string affinity;
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief Check if an expression matches the query constraints.
|
|
|
|
*
|
|
|
|
* @param expr a TEXT representation of the column literal type to check.
|
|
|
|
* @return If the expression matched all constraints.
|
|
|
|
*/
|
2014-11-29 00:22:02 +00:00
|
|
|
bool matches(const std::string& expr);
|
2014-11-25 20:30:29 +00:00
|
|
|
|
2014-11-27 09:45:35 +00:00
|
|
|
template <typename T>
|
|
|
|
bool matches(const T& expr) {
|
|
|
|
return literal_matches<T>(expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief If there is a constraint on this column.
|
|
|
|
*/
|
|
|
|
bool exists() { return (constraints.size() > 0); }
|
2014-11-29 01:40:23 +00:00
|
|
|
bool existsAndMatches(const std::string& expr) {
|
|
|
|
return (exists() && matches(expr));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool notExistsOrMatches(const std::string& expr) {
|
|
|
|
return (!exists() || matches(expr));
|
|
|
|
}
|
|
|
|
|
2014-11-30 05:55:14 +00:00
|
|
|
template <typename T>
|
2014-11-29 01:40:23 +00:00
|
|
|
bool existsAndMatches(const T& expr);
|
|
|
|
|
2014-11-30 05:55:14 +00:00
|
|
|
template <typename T>
|
2014-11-29 01:40:23 +00:00
|
|
|
bool notExistsOrMatches(const T& expr);
|
2014-11-27 09:45:35 +00:00
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
/**
|
|
|
|
* @brief Helper templated function for ConstraintList::matches
|
|
|
|
*/
|
2014-11-25 20:30:29 +00:00
|
|
|
template <typename T>
|
2014-11-29 00:22:02 +00:00
|
|
|
bool literal_matches(const T& base_expr);
|
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.
|
|
|
|
*/
|
2014-11-29 00:22:02 +00:00
|
|
|
std::vector<std::string> getAll(ConstraintOperator op);
|
2014-11-25 20:30:29 +00:00
|
|
|
|
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) {
|
|
|
|
constraints.push_back(constraint);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Pass a constraint map to the query request.
|
|
|
|
typedef std::map<std::string, struct ConstraintList> ConstraintMap;
|
|
|
|
/// Populate a containst list from a query's parsed predicate.
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2014-11-26 00:28:10 +00:00
|
|
|
typedef struct QueryContext QueryContext;
|
2014-11-25 20:30:29 +00:00
|
|
|
typedef struct Constraint Constraint;
|
|
|
|
}
|
2014-12-03 04:36:46 +00:00
|
|
|
}
|