void genBrowserPlugin(const std::string& uid,
                      const std::string& path,
                      QueryData& results,
                      bool is_disabled = false) {
  Row r;
  pt::ptree tree;

  r["uid"] = uid;
  auto info_path = path + "/Contents/Info.plist";
  // Ensure that what we're processing is actually a plug-in.
  if (!pathExists(info_path)) {
    return;
  }
  if (osquery::parsePlist(info_path, tree).ok()) {
    // Plugin did not include an Info.plist, or it was invalid
    for (const auto& it : kBrowserPluginKeys) {
      r[it.second] = tree.get(it.first, "");

      // Convert bool-types to an integer.
      jsonBoolAsInt(r[it.second]);
    }
  }

  if (r.count("native") == 0 || r.at("native").size() == 0) {
    // The default case for native execution is false.
    r["native"] = "0";
  }
  r["path"] = path;
  r["disabled"] = (is_disabled) ? "1" : "0";
  results.push_back(std::move(r));
}
Example #2
0
std::string generateRow(const Row& r,
                        const std::map<std::string, size_t>& lengths,
                        const std::vector<std::string>& order) {
  std::string out;
  for (const auto& column : order) {
    size_t size = 0;

    // Print a terminator for the previous value or lhs, followed by spaces.
    out += kToken + ' ';
    if (r.count(column) == 0 || lengths.count(column) == 0) {
      size = column.size() - utf8StringSize(FLAGS_nullvalue);
      out += FLAGS_nullvalue;
    } else {
      int buffer_size =
          static_cast<int>(lengths.at(column) - utf8StringSize(r.at(column)));
      if (buffer_size >= 0) {
        size = static_cast<size_t>(buffer_size);
        out += r.at(column);
      }
    }
    out += std::string(size + 1, ' ');
  }

  if (out.size() > 0) {
    // Only append if a row was added.
    out += kToken + "\n";
  }

  return out;
}
Example #3
0
void EventSubscriberPlugin::expireCheck(bool cleanup) {
  auto data_key = "data." + dbNamespace();
  auto eid_key = "eid." + dbNamespace();
  // Min key will be the last surviving key.
  size_t min_key = 0;

  {
    auto limit = getEventsMax();
    std::vector<std::string> keys;
    scanDatabaseKeys(kEvents, keys, data_key);
    if (keys.size() <= limit) {
      return;
    }

    // There is an overflow of events buffered for this subscriber.
    LOG(WARNING) << "Expiring events for subscriber: " << getName()
                 << " (limit " << limit << ")";
    VLOG(1) << "Subscriber events " << getName() << " exceeded limit " << limit
            << " by: " << keys.size() - limit;
    // Inspect the N-FLAGS_events_max -th event's value and expire before the
    // time within the content.
    std::string last_key;
    getDatabaseValue(kEvents, eid_key, last_key);
    // The EID is the next-index.
    // EID - events_max is the most last-recent event to keep.
    min_key = boost::lexical_cast<size_t>(last_key) - getEventsMax();

    if (cleanup) {
      // Scan each of the keys in keys, if their ID portion is < min_key.
      // Nix them, this requires lots of conversions, use with care.
      for (const auto& key : keys) {
        if (std::stoul(key.substr(key.rfind('.') + 1)) < min_key) {
          deleteDatabaseValue(kEvents, key);
        }
      }
    }
  }

  // Convert the key index into a time using the content.
  // The last-recent event is fetched and the corresponding time is used as
  // the expiration time for the subscriber.
  std::string content;
  getDatabaseValue(kEvents, data_key + "." + std::to_string(min_key), content);

  // Decode the value into a row structure to extract the time.
  Row r;
  if (!deserializeRowJSON(content, r) || r.count("time") == 0) {
    return;
  }

  // The last time will become the implicit expiration time.
  size_t last_time = boost::lexical_cast<size_t>(r.at("time"));
  if (last_time > 0) {
    expire_time_ = last_time;
  }

  // Finally, attempt an index query to trigger expirations.
  // In this case the result set is not used.
  getIndexes(expire_time_, 0);
}
Example #4
0
void genBrowserPlugin(const std::string& uid,
                      const std::string& path,
                      QueryData& results) {
  Row r;
  pt::ptree tree;

  r["uid"] = uid;
  if (osquery::parsePlist(path + "/Contents/Info.plist", tree).ok()) {
    // Plugin did not include an Info.plist, or it was invalid
    for (const auto& it : kBrowserPluginKeys) {
      r[it.second] = tree.get(it.first, "");

      // Convert bool-types to an integer.
      jsonBoolAsInt(r[it.second]);
    }
  }

  if (r.count("native") == 0 || r.at("native").size() == 0) {
    // The default case for native execution is false.
    r["native"] = "0";
  }

  r["path"] = path;
  results.push_back(std::move(r));
}
Example #5
0
TEST_F(AslTests, test_read_asl_row) {
  aslmsg row = asl_new(ASL_TYPE_MSG);
  ASSERT_EQ(0, asl_set(row, "Sender", "foo"));
  ASSERT_EQ(0, asl_set(row, "Level", "1"));
  ASSERT_EQ(0, asl_set(row, "Message", "bar"));
  ASSERT_EQ(0, asl_set(row, "Bang", "bang_val"));

  Row r;
  readAslRow(row, r);

  ASSERT_EQ((size_t)4, r.size());

  ASSERT_EQ("foo", r["sender"]);
  ASSERT_EQ("1", r["level"]);
  ASSERT_EQ("bar", r["message"]);
  ASSERT_EQ((size_t)0, r.count("bang"));
  ASSERT_EQ("{\"Bang\":\"bang_val\"}\n", r["extra"]);

  asl_release(row);
}
Example #6
0
void EventSubscriberPlugin::expireCheck() {
  auto db = DBHandle::getInstance();
  auto data_key = "data." + dbNamespace();
  auto eid_key = "eid." + dbNamespace();

  std::vector<std::string> keys;
  db->ScanPrefix(kEvents, keys, data_key);
  if (keys.size() <= FLAGS_events_max) {
    return;
  }

  // There is an overflow of events buffered for this subscriber.
  LOG(WARNING) << "Expiring events for subscriber: " << getName() << " limit ("
               << FLAGS_events_max << ") exceeded: " << keys.size();
  // Inspect the N-FLAGS_events_max -th event's value and expire before the
  // time within the content.
  std::string last_key;
  db->Get(kEvents, eid_key, last_key);
  // The EID is the next-index.
  size_t max_key = boost::lexical_cast<size_t>(last_key) - FLAGS_events_max - 1;

  // Convert the key index into a time using the content.
  std::string content;
  db->Get(kEvents, data_key + "." + std::to_string(max_key), content);

  // Decode the value into a row structure to extract the time.
  Row r;
  if (!deserializeRowJSON(content, r) || r.count("time") == 0) {
    return;
  }

  // The last time will become the implicit expiration time.
  size_t last_time = boost::lexical_cast<size_t>(r.at("time"));
  if (last_time > 0) {
    expire_time_ = last_time;
  }

  // Finally, attempt an index query to trigger expirations.
  // In this case the result set is not used.
  getIndexes(expire_time_ - 1, -1);
}
Example #7
0
int queryDataCallback(void* argument, int argc, char* argv[], char* column[]) {
  if (argument == nullptr) {
    VLOG(1) << "Query execution failed: received a bad callback argument";
    return SQLITE_MISUSE;
  }

  auto qData = static_cast<QueryData*>(argument);
  Row r;
  for (int i = 0; i < argc; i++) {
    if (column[i] != nullptr) {
      if (r.count(column[i])) {
        // Found a column name collision in the result.
        VLOG(1) << "Detected overloaded column name " << column[i]
                << " in query result consider using aliases";
      }
      r[column[i]] = (argv[i] != nullptr) ? argv[i] : FLAGS_nullvalue;
    }
  }
  (*qData).push_back(std::move(r));
  return 0;
}
Example #8
0
QueryData genDrivers(QueryContext& context) {
  QueryData results;

  auto devInfoset = setupDevInfoSet();
  if (devInfoset == nullptr) {
    win32LogWARNING("Error getting device handle");
    return results;
  }

  std::vector<SP_DEVINFO_DATA> devices;
  auto ret = getDeviceList(devInfoset, devices);
  if (!ret.ok()) {
    win32LogWARNING(ret.getMessage(), ret.getCode());
    return results;
  }

  for (auto& device : devices) {
    char devId[MAX_DEVICE_ID_LEN] = {0};
    if (CM_Get_Device_ID(device.DevInst, devId, MAX_DEVICE_ID_LEN, 0) !=
        CR_SUCCESS) {
      win32LogWARNING("Failed to get device ID");
      return QueryData();
    }

    SP_DRVINFO_DATA drvInfo = {0};
    SP_DRVINFO_DETAIL_DATA drvInfoDetail = {0};
    ret = getDeviceDriverInfo(devInfoset, device, drvInfo, drvInfoDetail);

    Row r;
    r["device_id"] = devId;
    r["inf"] = drvInfoDetail.InfFileName;
    r["provider"] = drvInfo.ProviderName;
    r["manufacturer"] = drvInfo.MfgName;
    r["date"] = std::to_string(osquery::filetimeToUnixtime(drvInfo.DriverDate));
    r["description"] = drvInfo.Description;
    ULARGE_INTEGER version;
    version.QuadPart = drvInfo.DriverVersion;
    r["version"] = std::to_string(HIWORD(version.HighPart)) + "." +
                   std::to_string(HIWORD(version.LowPart)) + "." +
                   std::to_string(LOWORD(version.HighPart)) + "." +
                   std::to_string(LOWORD(version.LowPart));

    for (const auto& elem : kAdditionalDeviceProps) {
      std::string val;
      ret = getDeviceProperty(devInfoset, device, elem.second, val);
      r[elem.first] = std::move(val);
    }

    if (r.count("driver_key") > 0) {
      if (!r.at("driver_key").empty()) {
        r["driver_key"].insert(0, kDriverKeyPath);
      }
    }
    if (r.count("service") > 0) {
      if (!r.at("service").empty()) {
        r["service_key"] = kServiceKeyPath + r["service"];
        r["image"] = getDriverImagePath(r["service_key"]);
      }
    }

    results.push_back(r);
  }

  return results;
}
Example #9
0
QueryData genKernelInfo(QueryContext& context) {
  QueryData results;

  mach_port_t master_port;
  auto kr = IOMasterPort(bootstrap_port, &master_port);
  if (kr != KERN_SUCCESS) {
    VLOG(1) << "Could not get the IOMaster port";
    return {};
  }

  // NVRAM registry entry is :/options.
  auto chosen = IORegistryEntryFromPath(master_port, kIODTChosenPath_);
  if (chosen == 0) {
    VLOG(1) << "Could not get IOKit boot device";
    return {};
  }

  // Parse the boot arguments, usually none.
  CFMutableDictionaryRef properties;
  kr = IORegistryEntryCreateCFProperties(
      chosen, &properties, kCFAllocatorDefault, 0);
  IOObjectRelease(chosen);

  if (kr != KERN_SUCCESS) {
    VLOG(1) << "Could not get IOKit boot device properties";
    return {};
  }

  Row r;
  CFTypeRef property;
  if (CFDictionaryGetValueIfPresent(
          properties, CFSTR("boot-args"), &property)) {
    r["arguments"] = stringFromCFData((CFDataRef)property);
  }

  if (CFDictionaryGetValueIfPresent(
          properties, CFSTR("boot-device-path"), &property)) {
    r["device"] = getCanonicalEfiDevicePath((CFDataRef)property);
  }

  if (CFDictionaryGetValueIfPresent(
          properties, CFSTR("boot-file"), &property)) {
    r["path"] = stringFromCFData((CFDataRef)property);
    boost::trim(r["path"]);
  }
  // No longer need chosen properties.
  CFRelease(properties);

  // The kernel version, signature, and build information is stored in Root.
  auto root = IORegistryGetRootEntry(master_port);
  if (root != 0) {
    property = (CFDataRef)IORegistryEntryCreateCFProperty(
        root, CFSTR(kIOKitBuildVersionKey), kCFAllocatorDefault, 0);
    if (property != nullptr) {
      // The version is in the form:
      // Darwin Kernel Version VERSION: DATE; root:BUILD/TAG
      auto signature = stringFromCFString((CFStringRef)property);
      CFRelease(property);

      r["version"] = signature.substr(22, signature.find(":") - 22);
    }
  }

  // With the path and device, try to locate the on-disk kernel
  if (r.count("path") > 0) {
    // This does not use the device path, potential invalidation.
    r["md5"] = hashFromFile(HASH_TYPE_MD5, "/" + r["path"]);
  }

  results.push_back(r);
  return results;
}