osquery-1/osquery/events/darwin/event_taps.cpp

121 lines
3.3 KiB
C++

/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include <osquery/flags.h>
#include <osquery/registry_factory.h>
#include "osquery/events/darwin/event_taps.h"
namespace osquery {
/// Flag that turns the keyboard events on
FLAG(bool,
enable_keyboard_events,
false,
"Enable listening for keyboard events");
/// Flag that turns the mouse events on
FLAG(bool, enable_mouse_events, false, "Enable listening for mouse events");
REGISTER(EventTappingEventPublisher,
"event_publisher",
"user_interaction_publisher");
CGEventRef EventTappingEventPublisher::eventCallback(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void* refcon) {
EventFactory::fire<EventTappingEventPublisher>(createEventContext());
// If you change from listenOnly, return event or you will drop all events
return nullptr;
}
EventTappingEventPublisher::~EventTappingEventPublisher() {
tearDown();
}
Status EventTappingEventPublisher::setUp() {
if (!FLAGS_enable_keyboard_events && !FLAGS_enable_mouse_events) {
return Status(1, "Publisher disabled via configuration");
}
return Status(0);
}
void EventTappingEventPublisher::tearDown() {
stop();
}
void EventTappingEventPublisher::stop() {
WriteLock lock(run_loop_mutex_);
if (run_loop_source_ != nullptr) {
CFRunLoopRemoveSource(run_loop_, run_loop_source_, kCFRunLoopCommonModes);
CFRelease(run_loop_source_);
run_loop_source_ = nullptr;
}
if (event_tap_ != nullptr) {
CGEventTapEnable(event_tap_, false);
CFRelease(event_tap_);
event_tap_ = nullptr;
}
if (run_loop_ != nullptr) {
CFRunLoopStop(run_loop_);
run_loop_ = nullptr;
}
}
Status EventTappingEventPublisher::restart() {
stop();
WriteLock lock(run_loop_mutex_);
run_loop_ = CFRunLoopGetCurrent();
CGEventMask mask = kCGEventNull;
if (FLAGS_enable_keyboard_events) {
mask |= 1 << kCGEventKeyDown;
}
if (FLAGS_enable_mouse_events) {
mask |= 1 << kCGEventLeftMouseDown;
}
event_tap_ = CGEventTapCreate(kCGSessionEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly,
mask,
eventCallback,
nullptr);
if (event_tap_ == nullptr) {
run_loop_ = nullptr;
return Status(1, "Could not create event tap");
}
run_loop_source_ =
CFMachPortCreateRunLoopSource(kCFAllocatorDefault, event_tap_, 0);
CFRunLoopAddSource(run_loop_, run_loop_source_, kCFRunLoopCommonModes);
CGEventTapEnable(event_tap_, true);
return Status(0);
}
Status EventTappingEventPublisher::run() {
Status s = restart();
if (s.ok()) {
CFRunLoopRun();
}
return s;
}
bool EventTappingEventPublisher::shouldFire(
const EventTappingSubscriptionContextRef& mc,
const EventTappingEventContextRef& ec) const {
return true;
}
}