예제 #1
0
Status SyslogEventPublisher::run() {
  // This run function will be called by the event factory with ~100ms pause
  // (see InterruptableRunnable::pause()) between runs. In case something goes
  // weird and there is a huge amount of input, we limit how many logs we
  // take in per run to avoid pegging the CPU.
  for (size_t i = 0; i < kMaxLogsPerRun; ++i) {
    if (readStream_.rdbuf()->in_avail() == 0) {
      // If there is no pending data, we have flushed everything and can wait
      // until the next time EventFactory calls run(). This also allows the
      // thread to join when it is stopped by EventFactory.
      return Status(0, "OK");
    }
    std::string line;
    std::getline(readStream_, line);
    auto ec = createEventContext();
    Status status = populateEventContext(line, ec);
    if (status.ok()) {
      fire(ec);
      if (errorCount_ > 0) {
        --errorCount_;
      }
    } else {
      LOG(ERROR) << status.getMessage() << " in line: " << line;
      ++errorCount_;
      if (errorCount_ >= kErrorThreshold) {
        return Status(1, "Too many errors in syslog parsing.");
      }
    }
  }
  return Status(0, "OK");
}
예제 #2
0
void IOKitHIDEventPublisher::fire(const IOHIDDeviceRef &device,
                                  const std::string &action) {
  auto ec = createEventContext();
  ec->device = device;
  ec->action = action;

  // Fill in more-useful fields.
  ec->vendor_id = getProperty(device, CFSTR(kIOHIDVendorIDKey));
  ec->model_id = getProperty(device, CFSTR(kIOHIDProductIDKey));
  ec->vendor = getProperty(device, CFSTR(kIOHIDManufacturerKey));
  ec->model = getProperty(device, CFSTR(kIOHIDProductKey));
  ec->transport = getProperty(device, CFSTR(kIOHIDTransportKey));
  ec->primary_usage = getProperty(device, CFSTR(kIOHIDPrimaryUsageKey));
  ec->device_usage = getProperty(device, CFSTR(kIOHIDDeviceUsageKey));

  // Fill in more esoteric properties.
  ec->version = getProperty(device, CFSTR(kIOHIDVersionNumberKey));
  ec->location = getProperty(device, CFSTR(kIOHIDLocationIDKey));
  ec->serial = getProperty(device, CFSTR(kIOHIDSerialNumberKey));
  ec->country_code = getProperty(device, CFSTR(kIOHIDCountryCodeKey));

  if (ec->location.size() > 0 || ec->model_id.size() > 0) {
    // Only emit results that contain an location or model_id.
    EventFactory::fire<IOKitHIDEventPublisher>(ec);
  }
}
예제 #3
0
void SCNetworkEventPublisher::Callback(const SCNetworkReachabilityRef target,
                                       SCNetworkReachabilityFlags flags,
                                       void* info) {
  auto ec = createEventContext();
  ec->subscription = *(SCNetworkSubscriptionContextRef*)info;
  ec->flags = flags;
}
예제 #4
0
void IOKitEventPublisher::newEvent(const io_service_t& device,
                                   IOKitEventContext::Action action) {
  auto ec = createEventContext();
  ec->action = action;

  {
    // The IORegistry name is not needed.
    io_name_t class_name = {0};
    if (IOObjectGetClass(device, class_name) != kIOReturnSuccess) {
      return;
    }
    ec->type = std::string(class_name);
  }

  // Get the device details
  CFMutableDictionaryRef details;
  IORegistryEntryCreateCFProperties(
      device, &details, kCFAllocatorDefault, kNilOptions);
  if (ec->type == kIOUSBDeviceClassName_) {
    ec->path = getIOKitProperty(details, "USB Address") + ":";
    ec->path += getIOKitProperty(details, "PortNum");
    ec->model = getIOKitProperty(details, "USB Product Name");
    ec->model_id = getIOKitProperty(details, "idProduct");
    ec->vendor = getIOKitProperty(details, "USB Vendor Name");
    ec->vendor_id = getIOKitProperty(details, "idVendor");
    idToHex(ec->vendor_id);
    idToHex(ec->model_id);
    ec->serial = getIOKitProperty(details, "USB Serial Number");
    if (ec->serial.size() == 0) {
      ec->serial = getIOKitProperty(details, "iSerialNumber");
    }
    ec->version = "";
    ec->driver = getIOKitProperty(details, "IOUserClientClass");
  } else if (ec->type == kIOPCIDeviceClassName_) {
    auto compatible = getIOKitProperty(details, "compatible");
    auto properties = IOKitPCIProperties(compatible);
    ec->model_id = properties.model_id;
    ec->vendor_id = properties.vendor_id;
    ec->driver = properties.driver;
    if (ec->driver.empty()) {
      ec->driver = getIOKitProperty(details, "IOName");
    }

    ec->path = getIOKitProperty(details, "pcidebug");
    ec->version = getIOKitProperty(details, "revision-id");
    ec->model = getIOKitProperty(details, "model");
  } else {
    // Get the name as the model.
    io_name_t name = {0};
    IORegistryEntryGetName(device, name);
    if (name[0] != 0) {
      ec->model = std::string(name);
    }
  }

  CFRelease(details);
  fire(ec);
}
예제 #5
0
void DiskArbitrationEventPublisher::DiskAppearedCallback(DADiskRef disk,
                                                         void* context) {
  auto ec = createEventContext();

  CFDictionaryRef disk_properties = DADiskCopyDescription(disk);
  CFTypeRef devicePathKey;
  if (!CFDictionaryGetValueIfPresent(
          disk_properties, kDADiskDescriptionDevicePathKey, &devicePathKey)) {
    CFRelease(disk_properties);
    return;
  }

  auto device_path = stringFromCFString((CFStringRef)devicePathKey);
  ec->device_path = device_path;

  auto entry =
      IORegistryEntryFromPath(kIOMasterPortDefault, device_path.c_str());
  if (entry == MACH_PORT_NULL) {
    CFRelease(disk_properties);
    return;
  }

  auto protocol_properties = (CFDictionaryRef)IORegistryEntryCreateCFProperty(
      entry,
      CFSTR(kIOPropertyProtocolCharacteristicsKey_),
      kCFAllocatorDefault,
      kNilOptions);

  if (protocol_properties != nullptr) {
    CFDataRef path = (CFDataRef)CFDictionaryGetValue(
        protocol_properties, CFSTR(kVirtualInterfaceLocation_));
    if (path != nullptr) {
      ec->path = stringFromCFData(path);
      // extract checksum once on the whole disk and not for every partition
      if (CFBooleanGetValue((CFBooleanRef)CFDictionaryGetValue(
              disk_properties, kDADiskDescriptionMediaWholeKey))) {
        ec->checksum = extractUdifChecksum(ec->path);
      }
    } else {
      // There was no interface location.
      ec->path = getProperty(kDADiskDescriptionDevicePathKey, disk_properties);
    }
    CFRelease(protocol_properties);
  } else {
    ec->path = "";
  }

  if (ec->path.find("/SSD0@0") == std::string::npos) {
    // This is not an internal SSD.
    fire("add", ec, disk_properties);
  }

  CFRelease(disk_properties);
  IOObjectRelease(entry);
}
예제 #6
0
void FSEventsEventPublisher::Callback(
    ConstFSEventStreamRef stream,
    void* callback_info,
    size_t num_events,
    void* event_paths,
    const FSEventStreamEventFlags fsevent_flags[],
    const FSEventStreamEventId fsevent_ids[]) {
  for (size_t i = 0; i < num_events; ++i) {
    auto ec = createEventContext();
    ec->fsevent_stream = stream;
    ec->fsevent_flags = fsevent_flags[i];
    ec->transaction_id = fsevent_ids[i];
    ec->path = std::string(((char**)event_paths)[i]);

    if (ec->fsevent_flags & kFSEventStreamEventFlagMustScanSubDirs) {
      // The FSEvents thread coalesced events within and will report a root.
      TLOG << "FSEvents collision, root: " << ec->path;
    }

    if (ec->fsevent_flags & kFSEventStreamEventFlagRootChanged) {
      // Must rescan for the changed root.
    }

    if (ec->fsevent_flags & kFSEventStreamEventFlagUnmount) {
      // Should remove the watch on this path.
    }

    if (ec->fsevent_flags & kFSEventStreamEventFlagMount) {
      auto mc = std::make_shared<FSEventsSubscriptionContext>();
      mc->path = ec->path + "/*";
      auto subscription = Subscription::create("file_events", mc);
      auto status = EventFactory::addSubscription("fsevents", subscription);
      auto pub = EventFactory::getEventPublisher("fsevents");
      pub->configure();
    }

    // Record the string-version of the first matched mask bit.
    bool has_action = false;
    for (const auto& action : kMaskActions) {
      if (ec->fsevent_flags & action.first) {
        // Actions may be multiplexed. Fire and event for each.
        ec->action = action.second;
        EventFactory::fire<FSEventsEventPublisher>(ec);
        has_action = true;
      }
    }

    if (!has_action) {
      // If no action was matched for this path event, fire and unknown.
      ec->action = "UNKNOWN";
      EventFactory::fire<FSEventsEventPublisher>(ec);
    }
  }
}
예제 #7
0
파일: inotify.cpp 프로젝트: nyimbi/osquery
INotifyEventContextRef INotifyEventPublisher::createEventContextFrom(
    struct inotify_event* event) {
  auto shared_event = std::make_shared<struct inotify_event>(*event);
  auto ec = createEventContext();
  ec->event = shared_event;

  // Get the pathname the watch fired on.
  ec->path = descriptor_paths_[event->wd];
  if (event->len > 1) {
    ec->path += event->name;
  }

  for (const auto& action : kMaskActions) {
    if (event->mask & action.first) {
      ec->action = action.second;
      break;
    }
  }
  return ec;
}
예제 #8
0
파일: udev.cpp 프로젝트: theopolis/osquery
UdevEventContextRef UdevEventPublisher::createEventContextFrom(
    struct udev_device* device) {
  auto ec = createEventContext();
  ec->device = device;
  // Map the action string to the eventing enum.
  ec->action = UDEV_EVENT_ACTION_UNKNOWN;
  ec->action_string = std::string(udev_device_get_action(device));
  if (ec->action_string == "add") {
    ec->action = UDEV_EVENT_ACTION_ADD;
  } else if (ec->action_string == "remove") {
    ec->action = UDEV_EVENT_ACTION_REMOVE;
  } else if (ec->action_string == "change") {
    ec->action = UDEV_EVENT_ACTION_CHANGE;
  }

  // Set the subscription-aware variables for the event.
  auto value = udev_device_get_subsystem(device);
  if (value != nullptr) {
    ec->subsystem = std::string(value);
  }

  value = udev_device_get_devnode(device);
  if (value != nullptr) {
    ec->devnode = std::string(value);
  }

  value = udev_device_get_devtype(device);
  if (value != nullptr) {
    ec->devtype = std::string(value);
  }

  value = udev_device_get_driver(device);
  if (value != nullptr) {
    ec->driver = std::string(value);
  }

  return ec;
}
예제 #9
0
Status AuditEventPublisher::run() {
  if (!FLAGS_disable_audit && (count_ == 0 || count_++ % 10 == 0)) {
    // Request an update to the audit status.
    // This will also fill in the status on first run.
    audit_request_status(handle_);
  }

  // Reset the reply data.
  int result = 0;
  bool handle_reply = false;
  while (true) {
    handle_reply = false;

    // Request a reply in a non-blocking mode.
    // This allows the publisher's run loop to periodically request an audit
    // status update. These updates can check for other processes attempting to
    // gain control over the audit sink.
    // This non-blocking also allows faster receipt of multi-message events.
    result = audit_get_reply(handle_, &reply_, GET_REPLY_NONBLOCKING, 0);
    if (result > 0) {
      switch (reply_.type) {
      case NLMSG_NOOP:
      case NLMSG_DONE:
      case NLMSG_ERROR:
        // Not handled, request another reply.
        break;
      case AUDIT_LIST_RULES:
        // Build rules cache.
        handleListRules();
        break;
      case AUDIT_GET:
        // Make a copy of the status reply and store as the most-recent.
        if (reply_.status != nullptr) {
          memcpy(&status_, reply_.status, sizeof(struct audit_status));
        }
        break;
      case (AUDIT_GET + 1)...(AUDIT_LIST_RULES - 1):
      case (AUDIT_LIST_RULES + 1)... AUDIT_LAST_USER_MSG:
        // Not interested in handling meta-commands and actions.
        break;
      case AUDIT_DAEMON_START... AUDIT_DAEMON_CONFIG: // 1200 - 1203
      case AUDIT_CONFIG_CHANGE:
        handleAuditConfigChange(reply_);
        break;
      case AUDIT_SYSCALL: // 1300
        // A monitored syscall was issued, most likely part of a multi-record.
        handle_reply = true;
        break;
      case AUDIT_CWD: // 1307
      case AUDIT_PATH: // 1302
      case AUDIT_EXECVE: // // 1309 (execve arguments).
        handle_reply = true;
      case AUDIT_EOE: // 1320 (multi-record event).
        break;
      default:
        // All other cases, pass to reply.
        handle_reply = true;
      }
    } else {
      // Fall through to the run loop cool down.
      break;
    }

    // Replies are 'handled' as potential events for several audit types.
    if (handle_reply) {
      auto ec = createEventContext();
      // Build the event context from the reply type and parse the message.
      if (handleAuditReply(reply_, ec)) {
        fire(ec);
      }
    }
  }
예제 #10
0
void DiskArbitrationEventPublisher::DiskDisappearedCallback(DADiskRef disk,
                                                            void* context) {
  CFDictionaryRef disk_properties = DADiskCopyDescription(disk);
  fire("remove", createEventContext(), disk_properties);
  CFRelease(disk_properties);
}