osquery-1/osquery/events/darwin/tests/fsevents_tests.cpp

380 lines
11 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
2015-03-03 00:48:01 +00:00
* 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.
*
*/
2014-10-07 18:20:47 +00:00
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <gtest/gtest.h>
#include <osquery/events.h>
#include <osquery/filesystem.h>
#include <osquery/flags.h>
#include <osquery/tables.h>
#include "osquery/tests/test_util.h"
#include "osquery/events/darwin/fsevents.h"
2016-02-24 01:07:24 +00:00
namespace fs = boost::filesystem;
namespace osquery {
int kMaxEventLatency = 3000;
DECLARE_bool(verbose);
class FSEventsTests : public testing::Test {
protected:
void SetUp() override {
// FSEvents will use data from the config and config parsers.
Registry::registry("config_parser")->setUp();
FLAGS_verbose = true;
2016-02-24 01:07:24 +00:00
real_test_path = kTestWorkingDirectory + "fsevents-triggers" +
std::to_string(rand() % 10000 + 10000);
// Create a similar directory for embedded paths and directories.
real_test_dir = kTestWorkingDirectory + "fsevents-triggers" +
std::to_string(rand() % 10000 + 10000);
2015-05-07 03:02:23 +00:00
}
2016-02-24 01:07:24 +00:00
void TearDown() override {
remove(real_test_path);
fs::remove_all(real_test_dir);
}
void StartEventLoop() {
event_pub_ = std::make_shared<FSEventsEventPublisher>();
2015-12-16 19:47:47 +00:00
event_pub_->no_defer_ = true;
event_pub_->no_self_ = false;
EventFactory::registerEventPublisher(event_pub_);
2016-02-24 01:07:24 +00:00
FILE* fd = fopen(real_test_path.c_str(), "w");
fclose(fd);
temp_thread_ = std::thread(EventFactory::run, "fsevents");
2015-05-07 03:02:23 +00:00
// Wait for the publisher thread and FSEvent run loop to start.
}
void EndEventLoop() {
while (!event_pub_->hasStarted()) {
::usleep(20);
}
2015-05-07 03:02:23 +00:00
EventFactory::end(false);
temp_thread_.join();
}
void WaitForStream(int max) {
int delay = 0;
while (delay < max * 1000 * 2) {
if (event_pub_->isStreamRunning()) {
return;
}
::usleep(100);
delay += 100;
}
}
bool WaitForEvents(size_t max, size_t num_events = 0) {
size_t delay = 0;
while (delay <= max * 1000) {
if (num_events > 0 && event_pub_->numEvents() >= num_events) {
return true;
} else if (num_events == 0 && event_pub_->numEvents() > 0) {
return true;
}
delay += 100;
::usleep(100);
}
return false;
}
void CreateEvents(int num = 1) {
WaitForStream(kMaxEventLatency);
for (int i = 0; i < num; ++i) {
2016-02-24 01:07:24 +00:00
FILE* fd = fopen(real_test_path.c_str(), "a");
fputs("fsevents", fd);
fclose(fd);
}
event_pub_->flush();
}
size_t count{0};
std::shared_ptr<FSEventsEventPublisher> event_pub_{nullptr};
std::thread temp_thread_;
2015-05-07 03:02:23 +00:00
public:
/// Trigger path is the current test's eventing sink (accessed anywhere).
2016-02-24 01:07:24 +00:00
std::string real_test_path;
std::string real_test_dir;
};
TEST_F(FSEventsTests, test_register_event_pub) {
2015-01-30 18:44:25 +00:00
auto pub = std::make_shared<FSEventsEventPublisher>();
auto status = EventFactory::registerEventPublisher(pub);
EXPECT_TRUE(status.ok());
// Make sure only one event type exists
EXPECT_EQ(EventFactory::numEventPublishers(), 1U);
status = EventFactory::deregisterEventPublisher("fsevents");
EXPECT_TRUE(status.ok());
}
TEST_F(FSEventsTests, test_fsevents_add_subscription_missing_path) {
2015-01-30 18:44:25 +00:00
auto pub = std::make_shared<FSEventsEventPublisher>();
EventFactory::registerEventPublisher(pub);
// This subscription path is fake, and will succeed!
auto mc = std::make_shared<FSEventsSubscriptionContext>();
mc->path = "/this/path/is/fake";
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
auto subscription = Subscription::create("TestSubscriber", mc);
2015-01-30 18:44:25 +00:00
auto status = EventFactory::addSubscription("fsevents", subscription);
EXPECT_TRUE(status.ok());
EventFactory::deregisterEventPublisher("fsevents");
}
TEST_F(FSEventsTests, test_fsevents_add_subscription_success) {
auto event_pub = std::make_shared<FSEventsEventPublisher>();
EventFactory::registerEventPublisher(event_pub);
// This subscription path *should* be real.
auto mc = std::make_shared<FSEventsSubscriptionContext>();
mc->path = "/";
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
auto subscription = Subscription::create("TestSubscriber", mc);
2015-01-30 18:44:25 +00:00
auto status = EventFactory::addSubscription("fsevents", subscription);
EXPECT_TRUE(status.ok());
event_pub->configure();
// Make sure configure was called.
size_t num_paths = event_pub->numSubscriptionedPaths();
EXPECT_EQ(num_paths, 1U);
// A duplicate subscription will work.
auto mc_dup = std::make_shared<FSEventsSubscriptionContext>();
mc_dup->path = "/";
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
auto subscription_dup = Subscription::create("TestSubscriber", mc_dup);
2015-01-30 18:44:25 +00:00
status = EventFactory::addSubscription("fsevents", subscription_dup);
EXPECT_TRUE(status.ok());
event_pub->configure();
// But the paths with be deduped when the event type reconfigures.
num_paths = event_pub->numSubscriptionedPaths();
EXPECT_EQ(num_paths, 1U);
EventFactory::deregisterEventPublisher("fsevents");
}
2014-12-15 06:17:38 +00:00
class TestFSEventsEventSubscriber
: public EventSubscriber<FSEventsEventPublisher> {
public:
2015-04-29 19:36:24 +00:00
TestFSEventsEventSubscriber() : callback_count_(0) {
setName("TestFSEventsEventSubscriber");
}
Status init() override {
2015-04-27 09:12:58 +00:00
callback_count_ = 0;
return Status(0, "OK");
}
2016-02-24 01:07:24 +00:00
SCRef GetSubscription(const std::string& path, uint32_t mask = 0) {
2014-12-15 06:17:38 +00:00
auto sc = createSubscriptionContext();
2016-02-24 01:07:24 +00:00
sc->path = path;
2014-12-15 06:17:38 +00:00
sc->mask = mask;
return sc;
}
Status SimpleCallback(const ECRef& ec, const SCRef& sc) {
WriteLock lock(mutex_);
callback_count_ += 1;
return Status(0, "OK");
}
Status Callback(const ECRef& ec, const SCRef& sc) {
2014-12-15 18:17:56 +00:00
// The following comments are an example Callback routine.
// Row r;
// r["action"] = ec->action;
// r["path"] = ec->path;
// Normally would call Add here.
WriteLock lock(mutex_);
actions_.push_back(ec->action);
callback_count_ += 1;
return Status(0, "OK");
}
2015-05-07 03:02:23 +00:00
void WaitForEvents(int max, int initial = 0) {
int delay = 0;
while (delay < max * 1000) {
{
WriteLock lock(mutex_);
if (callback_count_ >= initial) {
return;
}
}
delay += 100;
::usleep(100);
}
}
public:
int callback_count_{0};
std::vector<std::string> actions_;
public:
mutable Mutex mutex_;
private:
FRIEND_TEST(FSEventsTests, test_fsevents_fire_event);
FRIEND_TEST(FSEventsTests, test_fsevents_event_action);
2016-02-24 01:07:24 +00:00
FRIEND_TEST(FSEventsTests, test_fsevents_embedded_wildcards);
};
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
TEST_F(FSEventsTests, test_fsevents_run) {
// Assume event type is registered.
event_pub_ = std::make_shared<FSEventsEventPublisher>();
EventFactory::registerEventPublisher(event_pub_);
// Create a subscriber.
auto sub = std::make_shared<TestFSEventsEventSubscriber>();
EventFactory::registerEventSubscriber(sub);
// Create a subscriptioning context
auto mc = std::make_shared<FSEventsSubscriptionContext>();
2016-02-24 01:07:24 +00:00
mc->path = real_test_path;
2015-04-27 09:12:58 +00:00
EventFactory::addSubscription(
"fsevents", Subscription::create("TestFSEventsEventSubscriber", mc));
event_pub_->configure();
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
// Create an event loop thread (similar to main)
temp_thread_ = std::thread(EventFactory::run, "fsevents");
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
EXPECT_TRUE(event_pub_->numEvents() == 0);
2015-05-07 03:02:23 +00:00
// Wait for the thread to start and the FSEvents stream to turn on.
WaitForStream(kMaxEventLatency);
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
// Cause an fsevents event(s) by writing to the watched path.
CreateEvents();
// Wait for the thread's run loop to select.
WaitForEvents(kMaxEventLatency);
EXPECT_TRUE(event_pub_->numEvents() > 0);
2015-05-07 03:02:23 +00:00
// We are managing the thread ourselves, so no join needed.
EventFactory::end(false);
temp_thread_.join();
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
}
TEST_F(FSEventsTests, test_fsevents_fire_event) {
// Assume event type is registered.
StartEventLoop();
2014-12-15 06:17:38 +00:00
// Simulate registering an event subscriber.
auto sub = std::make_shared<TestFSEventsEventSubscriber>();
EventFactory::registerEventSubscriber(sub);
// Create a subscriptioning context, note the added Event to the symbol
2016-02-24 01:07:24 +00:00
auto sc = sub->GetSubscription(real_test_path, 0);
sub->subscribe(&TestFSEventsEventSubscriber::SimpleCallback, sc);
event_pub_->configure();
CreateEvents();
// This time wait for the callback.
sub->WaitForEvents(kMaxEventLatency, count + 1);
count = event_pub_->numEvents();
// Make sure our expected event fired (aka subscription callback was called).
2014-12-15 06:17:38 +00:00
EXPECT_TRUE(sub->callback_count_ > 0);
EndEventLoop();
}
TEST_F(FSEventsTests, test_fsevents_event_action) {
// Assume event type is registered.
StartEventLoop();
2014-12-15 06:17:38 +00:00
// Simulate registering an event subscriber.
auto sub = std::make_shared<TestFSEventsEventSubscriber>();
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
auto status = sub->init();
2014-12-15 06:17:38 +00:00
2016-02-24 01:07:24 +00:00
auto sc = sub->GetSubscription(real_test_path, 0);
Implement YARA table. Currently only for OS X, will port to others soon. Also need to add tests. Remove old comment and add loading message. Implement YARA table for Linux. Use mask properly. Use the various masks to specify the kinds of events we are interested in. This removes the need to do the dirty "DELETED" check when the event fires. Make getYARAFiles return a const map. Switch to LOG(WARNING) and emit error number. Add vim .swp files to .gitignore. Add yara_utils.(c|h). Start to condense common code between the Linux and Darwin YARA tables into a yara_utils.h. Right now it includes a function to compile rules and store the results back in the map, indexed by category. It also has the callback used by YARA when a rule is processed. I can not move much more than that for the row creation code because the structures used in the event callback are slightly different. Include a better error message. The errors are still printed by the compiler callback, but this will allow my future work to return a Status from the event initialization to print a useful message in summary. Make Subscriber init() return Status. Each EventSubscriber::init() now returns a Status. If the init() fails for any reason the EventSubscriber is still stored but the failure is tracked. EventSubscribers now have a state member, which represents the current state of the subscriber. The current supported states are: uninitialized, running, paused, failed. Currently the only meaningful ones are running and failed, but I put paused in there as a forward-looking feature. Subscriptions now have a subscriber_name member. This is used in EventPublisherPlugin::fire() as a lookup to get the EventSubscriber and check the state. If the EventSubscriber is not running the event will not fire. Only the EventSubscribers on OS X are using this. I'll do the Linux implementation next. Chase the init() changes to Linux. This brings the Linux YARA table in line with the OS X one. Require a EventSubscriberID when creating a subscription. Now that Subscriptions are "tied" to EventSubscribers you must create a Subscription with the name of the Subscriber it is for. This is because when the event fires the list of Subscriptions is walked and the name is used to lookup the EventSubscriber and make sure it is in the running state. Fix various tests. Some tests would fire an event with only a Subscription, which is no longer a valid thing to do. For these tests an EventSubscription is created and registered in the EventFactory. When Subscriptions are created pass the name of the EventSubscriber to them. In some cases where no event is ever fired it is fine to pass a bogus name. Fix inotify tests. Move a test down so the class is defined and make sure to create an EventSubscriber and use it properly. Add support for yara to provision.sh. Right now this grabs yara 3.3.0 and applies the patch to fix min() and max(), which is commit fc4696c8b725be1ac099d340359c8d550d116041 in the yara repo. This has been tested under Ubuntu 14.04 only. Remove NOMINMAX. This is no longer necessary after the patch was backported to 3.3.0. Revert "Add support for yara to provision.sh." This reverts commit a8bd371498c0979f070adeff23d05571882ac3f1. Use vendored YARA code in third-party. This switches to using the YARA code contained in third-party, including the patch to fix min/max macros. Fix mismerge. Remove unused function after merge. Well, soon to be unused as soon as I fix up the Linux YARA table. ;) Chase config changes. Make the Linux YARA table use ConfigDataInstance along with files() and yaraFiles().
2015-03-10 13:22:16 +00:00
EventFactory::registerEventSubscriber(sub);
sub->subscribe(&TestFSEventsEventSubscriber::Callback, sc);
event_pub_->configure();
CreateEvents();
sub->WaitForEvents(kMaxEventLatency, count + 1);
count = event_pub_->numEvents();
// Make sure the fsevents action was expected.
2015-05-07 03:02:23 +00:00
ASSERT_TRUE(sub->actions_.size() > 0);
bool has_created = false;
bool has_unknown = false;
{
WriteLock lock(sub->mutex_);
for (const auto& action : sub->actions_) {
// Expect either a created event or attributes modified event.
if (action == "CREATED" || action == "ATTRIBUTES_MODIFIED") {
has_created = true;
} else if (action == "UNKNOWN" || action == "") {
// Allow an undetermined but existing FSevent on our target to pass.
has_unknown = true;
}
}
}
EXPECT_TRUE(has_created || has_unknown);
{
WriteLock lock(sub->mutex_);
sub->actions_.clear();
}
2015-05-07 03:02:23 +00:00
// Generate more events.
2015-06-06 00:36:29 +00:00
CreateEvents();
sub->WaitForEvents(kMaxEventLatency, count + 2);
count = event_pub_->numEvents();
2015-06-06 00:36:29 +00:00
bool has_updated = false;
{
WriteLock lock(sub->mutex_);
// We may have triggered several updated events.
for (const auto& action : sub->actions_) {
if (action == "UPDATED") {
has_updated = true;
}
2015-06-06 00:36:29 +00:00
}
}
EXPECT_TRUE(has_updated);
EndEventLoop();
}
2016-02-24 01:07:24 +00:00
TEST_F(FSEventsTests, test_fsevents_embedded_wildcards) {
// Assume event type is not registered.
event_pub_ = std::make_shared<FSEventsEventPublisher>();
EventFactory::registerEventPublisher(event_pub_);
auto sub = std::make_shared<TestFSEventsEventSubscriber>();
EventFactory::registerEventSubscriber(sub);
// Create ./fsevents/2/1/
fs::create_directories(real_test_dir + "/2/1");
auto sc = sub->createSubscriptionContext();
sc->path = real_test_dir + "/*/1";
sub->subscribe(&TestFSEventsEventSubscriber::SimpleCallback, sc);
// Now the publisher must be configured.
event_pub_->configure();
// The existing wild-card matched directory should be included.
// This is populated via filesystem wildcard globbing.
ASSERT_EQ(event_pub_->numSubscriptionedPaths(), 1U);
std::set<std::string> expected = {real_test_dir + "/2/1/"};
EXPECT_EQ(event_pub_->paths_, expected);
}
}