2014-09-18 04:20:30 +00:00
|
|
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <functional>
|
|
|
|
#include <memory>
|
|
|
|
#include <map>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
#include <boost/make_shared.hpp>
|
2014-09-19 08:54:33 +00:00
|
|
|
#include <boost/thread/locks.hpp>
|
|
|
|
#include <boost/thread/mutex.hpp>
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
#include "osquery/status.h"
|
2014-09-19 08:54:33 +00:00
|
|
|
#include "osquery/database.h"
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
|
|
|
struct Monitor;
|
|
|
|
class EventType;
|
|
|
|
|
|
|
|
typedef const std::string EventTypeID;
|
2014-09-19 08:54:33 +00:00
|
|
|
typedef const std::string EventID;
|
|
|
|
typedef uint32_t EventContextID;
|
2014-09-18 04:20:30 +00:00
|
|
|
typedef uint32_t EventTime;
|
|
|
|
|
|
|
|
struct MonitorContext {};
|
|
|
|
struct EventContext {};
|
|
|
|
|
|
|
|
typedef boost::shared_ptr<Monitor> MonitorRef;
|
|
|
|
typedef boost::shared_ptr<EventType> EventTypeRef;
|
|
|
|
typedef boost::shared_ptr<MonitorContext> MonitorContextRef;
|
|
|
|
typedef boost::shared_ptr<EventContext> EventContextRef;
|
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
typedef std::function<Status(EventContextID, EventTime, EventContextRef)>
|
2014-09-21 21:29:28 +00:00
|
|
|
EventCallback;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
/// An EventType must track every monitor added.
|
|
|
|
typedef std::vector<MonitorRef> MonitorVector;
|
2014-09-22 21:35:07 +00:00
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
/// The EventFactory tracks every EventType and the name it specifies.
|
|
|
|
typedef std::map<EventTypeID, EventTypeRef> EventTypeMap;
|
2014-09-22 21:35:07 +00:00
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
/// The set of search-time binned lookup tables.
|
|
|
|
extern const std::vector<size_t> kEventTimeLists;
|
|
|
|
|
2014-09-18 04:20:30 +00:00
|
|
|
// Instead of attempting fancy RTTI limitations, each derived EventType may
|
|
|
|
// choose to macro-define a getter for a custom EventContext/MonitorContext.
|
|
|
|
// This assumes each event will implement custom fields for monitoring
|
|
|
|
// and custom fields holding event-related data.
|
2014-09-22 21:35:07 +00:00
|
|
|
#define DECLARE_EVENTTYPE(TYPE, MONITOR, EVENT) \
|
|
|
|
public: \
|
|
|
|
EventTypeID type() const { return TYPE; } \
|
|
|
|
static boost::shared_ptr<EVENT> getEventContext(EventContextRef context) { \
|
|
|
|
return boost::static_pointer_cast<EVENT>(context); \
|
|
|
|
} \
|
|
|
|
static boost::shared_ptr<MONITOR> getMonitorContext( \
|
|
|
|
MonitorContextRef context) { \
|
|
|
|
return boost::static_pointer_cast<MONITOR>(context); \
|
|
|
|
} \
|
|
|
|
static boost::shared_ptr<EVENT> createEventContext() { \
|
|
|
|
auto ec = boost::make_shared<EVENT>(); \
|
|
|
|
return ec; \
|
|
|
|
}
|
2014-09-19 08:54:33 +00:00
|
|
|
|
|
|
|
/// Helper define for binding EventModule to an EventType.
|
2014-09-22 21:35:07 +00:00
|
|
|
#define DECLARE_EVENTMODULE(NAME, TYPE) \
|
|
|
|
private: \
|
2014-09-19 08:54:33 +00:00
|
|
|
EventTypeID name() const { return NAME; } \
|
|
|
|
EventTypeID type() const { return TYPE; }
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief An implementation monitor context used to configure/create a monitor.
|
|
|
|
*
|
|
|
|
* The monitor stuct is a helper/boiler-plate constructor for a context and
|
|
|
|
* the caller's callback.
|
|
|
|
*/
|
|
|
|
struct Monitor {
|
2014-09-21 21:29:28 +00:00
|
|
|
public:
|
2014-09-18 04:20:30 +00:00
|
|
|
MonitorContextRef context;
|
|
|
|
EventCallback callback;
|
|
|
|
|
2014-09-21 21:29:28 +00:00
|
|
|
static MonitorRef create() { return boost::make_shared<Monitor>(); }
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
static MonitorRef create(const MonitorContextRef mc, EventCallback ec = 0) {
|
|
|
|
auto monitor = boost::make_shared<Monitor>();
|
|
|
|
monitor->context = mc;
|
|
|
|
monitor->callback = ec;
|
|
|
|
return monitor;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
/**
|
2014-09-18 04:20:30 +00:00
|
|
|
* @brief Generate OS events of a type (FS, Network, Syscall, ioctl).
|
|
|
|
*
|
2014-09-21 21:29:28 +00:00
|
|
|
* A class of OS Events is abstracted into a type-class responsible for
|
|
|
|
* remaining as agile as possible given a known-set of monitors using the
|
|
|
|
* events.
|
2014-09-18 04:20:30 +00:00
|
|
|
*
|
|
|
|
* There are four actions an event generator will take, start, configure, stop,
|
|
|
|
* and generate event. THe configure is a pseudo-start that may occur during
|
2014-09-21 21:29:28 +00:00
|
|
|
* runtime.
|
2014-09-18 04:20:30 +00:00
|
|
|
*/
|
|
|
|
class EventType {
|
2014-09-21 21:29:28 +00:00
|
|
|
public:
|
2014-09-18 04:20:30 +00:00
|
|
|
virtual void configure() {}
|
|
|
|
virtual void setUp() {}
|
|
|
|
virtual void tearDown() {}
|
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
virtual Status run();
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
Status addMonitor(const MonitorRef monitor) {
|
2014-09-19 08:54:33 +00:00
|
|
|
monitors_.push_back(monitor);
|
2014-09-18 04:20:30 +00:00
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
size_t numMonitors() { return monitors_.size(); }
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-21 21:29:28 +00:00
|
|
|
EventType(){};
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
virtual EventTypeID type() const = 0;
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
protected:
|
2014-09-19 08:54:33 +00:00
|
|
|
void fire(EventContextRef ec, EventTime event_time = 0);
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
protected:
|
2014-09-19 08:54:33 +00:00
|
|
|
/// The EventType will keep track of Monitors that contain associated callins.
|
|
|
|
MonitorVector monitors_;
|
2014-09-22 21:35:07 +00:00
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
/// An Event ID is assigned by the EventType within the EventContext.
|
|
|
|
/// This is not used to store EventData in the backing store.
|
|
|
|
EventContextID next_ec_id_;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-19 08:54:33 +00:00
|
|
|
boost::mutex ec_id_lock_;
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-19 08:54:33 +00:00
|
|
|
FRIEND_TEST(EventsTests, test_fire_event);
|
2014-09-18 04:20:30 +00:00
|
|
|
};
|
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
/**
|
|
|
|
* @brief An interface binding monitors, event response, and table generation.
|
|
|
|
*
|
|
|
|
* Use the EventModule interface when adding event monitors and defining callin
|
2014-09-22 21:35:07 +00:00
|
|
|
* functions. The EventCallback typedef is usually a member function for an
|
2014-09-19 08:54:33 +00:00
|
|
|
* EventModule. The EventModule interface includes a very important 'Add' method
|
2014-09-22 21:35:07 +00:00
|
|
|
* that abstracts the needed event to backing store interaction.
|
2014-09-19 08:54:33 +00:00
|
|
|
*
|
|
|
|
* Storing event data in the backing store must match a table spec for queries.
|
|
|
|
* Small overheads exist that help query-time indexing and lookups.
|
|
|
|
*/
|
|
|
|
class EventModule {
|
2014-09-22 21:35:07 +00:00
|
|
|
protected:
|
2014-09-19 08:54:33 +00:00
|
|
|
/// Store an event for Table-access into the underlying backing store.
|
|
|
|
Status Add(const osquery::Row& r, int event_time);
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-19 08:54:33 +00:00
|
|
|
/// Returns a new Event ID for this module, increments to the current EID.
|
|
|
|
EventID getEventID();
|
|
|
|
|
|
|
|
/// Records an added EventID/Event data.
|
|
|
|
Status recordEvent(EventID eid, int event_time);
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-19 08:54:33 +00:00
|
|
|
virtual EventTypeID type() const = 0;
|
|
|
|
virtual EventTypeID name() const = 0;
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-19 08:54:33 +00:00
|
|
|
boost::mutex event_id_lock_;
|
|
|
|
boost::mutex event_record_lock_;
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-19 08:54:33 +00:00
|
|
|
FRIEND_TEST(EventsDatabaseTests, test_event_module_id);
|
|
|
|
FRIEND_TEST(EventsDatabaseTests, test_unique_event_module_id);
|
|
|
|
};
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A factory for associating event generators to event type IDs.
|
|
|
|
*
|
|
|
|
* This factory both registers new event types and the monitors that use them.
|
|
|
|
* An event type is also a factor, the single event factory arbitates monitor
|
|
|
|
* creatating and management for each associated event type.
|
|
|
|
*
|
|
|
|
* Since event types may be plugins, they are created using the factory.
|
|
|
|
* Since monitors may be configured/disabled they are also factory-managed.
|
|
|
|
*/
|
|
|
|
class EventFactory {
|
2014-09-21 21:29:28 +00:00
|
|
|
public:
|
2014-09-18 04:20:30 +00:00
|
|
|
static boost::shared_ptr<EventFactory> get();
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
static Status registerEventType() {
|
|
|
|
auto event_type = boost::make_shared<T>();
|
|
|
|
return EventFactory::registerEventType(event_type);
|
|
|
|
}
|
|
|
|
static Status registerEventType(const EventTypeRef event_type);
|
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
// The dispatched event thread's entrypoint (if needed).
|
|
|
|
static Status run(EventTypeID type_id);
|
|
|
|
|
2014-09-18 04:20:30 +00:00
|
|
|
static Status addMonitor(EventTypeID type_id, const MonitorRef monitor);
|
2014-09-21 21:29:28 +00:00
|
|
|
static Status addMonitor(EventTypeID type_id,
|
|
|
|
const MonitorContextRef mc,
|
|
|
|
EventCallback callback = 0);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
static size_t numMonitors(EventTypeID type_id);
|
2014-09-18 04:20:30 +00:00
|
|
|
static size_t numEventTypes() {
|
|
|
|
return EventFactory::get()->event_types_.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
// A watching context MUST deregister events.
|
|
|
|
// EventType's assume they can hook/trampoline, which requires cleanup.
|
|
|
|
static Status deregisterEventType(const EventTypeRef event_type);
|
|
|
|
static Status deregisterEventType(EventTypeID type_id);
|
|
|
|
static Status deregisterEventTypes();
|
|
|
|
|
|
|
|
static EventTypeRef getEventType(EventTypeID);
|
|
|
|
|
2014-09-21 21:29:28 +00:00
|
|
|
private:
|
2014-09-18 04:20:30 +00:00
|
|
|
EventFactory() {}
|
|
|
|
|
2014-09-21 21:29:28 +00:00
|
|
|
private:
|
2014-09-18 04:20:30 +00:00
|
|
|
EventTypeMap event_types_;
|
|
|
|
};
|
|
|
|
}
|