TEST_F(ConfigTests, test_config_update) {
  std::string digest;
  // Get a snapshot of the digest before making config updates.
  auto status = Config::getMD5(digest);
  EXPECT_TRUE(status);

  // Request an update of the 'new_source1'. Set new1 = value.
  status =
      Config::update({{"new_source1", "{\"options\": {\"new1\": \"value\"}}"}});
  EXPECT_TRUE(status);

  // At least, the amalgamated config digest should have changed.
  std::string new_digest;
  Config::getMD5(new_digest);
  EXPECT_NE(digest, new_digest);

  // Access the option that was added in the update to source 'new_source1'.
  {
    ConfigDataInstance config;
    auto option = config.data().get<std::string>("options.new1", "");
    EXPECT_EQ(option, "value");
  }

  // Add a lexically larger source that emits the same option 'new1'.
  Config::update({{"new_source2", "{\"options\": {\"new1\": \"changed\"}}"}});

  {
    ConfigDataInstance config;
    auto option = config.data().get<std::string>("options.new1", "");
    // Expect the amalgamation to have overwritten 'new_source1'.
    EXPECT_EQ(option, "changed");
  }

  // Again add a source but emit a different option, both 'new1' and 'new2'
  // should be in the amalgamated/merged config.
  Config::update({{"new_source3", "{\"options\": {\"new2\": \"different\"}}"}});

  {
    ConfigDataInstance config;
    auto option = config.data().get<std::string>("options.new1", "");
    EXPECT_EQ(option, "changed");
    option = config.data().get<std::string>("options.new2", "");
    EXPECT_EQ(option, "different");
  }
}
Beispiel #2
0
Status Config::getMD5(std::string& hash_string) {
  // Request an accessor to our own config, outside of an update.
  ConfigDataInstance config;

  std::stringstream out;
  pt::write_json(out, config.data());

  hash_string = osquery::hashFromBuffer(
      HASH_TYPE_MD5, (void*)out.str().c_str(), out.str().length());

  return Status(0, "OK");
}
Beispiel #3
0
Status Config::getMD5(std::string& hash_string) {
  // Request an accessor to our own config, outside of an update.
  ConfigDataInstance config;

  std::stringstream out;
  try {
    pt::write_json(out, config.data(), false);
  } catch (const pt::json_parser::json_parser_error& e) {
    return Status(1, e.what());
  }

  hash_string = osquery::hashFromBuffer(
      HASH_TYPE_MD5, (void*)out.str().c_str(), out.str().length());

  return Status(0, "OK");
}
Beispiel #4
0
Status ProcessEventSubscriber::Callback(
    const TypedKernelEventContextRef<osquery_process_event_t> &ec,
    const void *user_data) {
  Row r;
  r["overflows"] = "";
  r["cmdline_count"] = BIGINT(ec->event.actual_argc);
  r["cmdline_size"] = BIGINT(ec->event.arg_length);
  if (ec->event.argc != ec->event.actual_argc) {
    r["overflows"] = "cmdline";
  }

  r["envc"] = BIGINT(ec->event.envc);
  r["environment_count"] = BIGINT(ec->event.actual_envc);
  r["environment_size"] = BIGINT(ec->event.env_length);
  if (ec->event.envc != ec->event.actual_envc) {
    r["overflows"] +=
        std::string(((r["overflows"].size() > 0) ? ", " : "")) + "environment";
  }

  char *argv = &(ec->flexible_data.data()[ec->event.argv_offset]);
  std::string argv_accumulator("");
  while (ec->event.argc-- > 0) {
    argv_accumulator += argv;
    argv_accumulator += " ";
    argv += strlen(argv) + 1;
  }
  r["cmdline"] = std::move(argv_accumulator);

  {
    // A configuration can optionally restrict environment variable logging to
    // a whitelist. This is helpful for limiting logged data as well as
    // protecting against logging unsafe/private variables.
    bool use_whitelist = false;
    pt::ptree whitelist;

    // Check if an events whitelist exists.
    ConfigDataInstance config;
    if (config.data().count("events")) {
      // Only apply a whitelist search if the events and environment_variables
      // keys are included. Otherwise, optimize by adding all.
      if (config.data().get_child("events").count("environment_variables")) {
        use_whitelist = true;
        whitelist = config.data().get_child("events.environment_variables");
      }
    }

    char *envv = &(ec->flexible_data.data()[ec->event.envv_offset]);
    std::string envv_accumulator("");
    while (ec->event.envc-- > 0) {
      auto envv_string = std::string(envv);
      if (use_whitelist) {
        for (const auto &item : whitelist) {
          if (envv_string.find(item.second.data()) == 0) {
            envv_accumulator += std::move(envv_string) + ' ';
            break;
          }
        }
      } else {
        envv_accumulator += std::move(envv_string) + ' ';
      }
      envv += strlen(envv) + 1;
    }
    r["environment"] = std::move(envv_accumulator);
  }

  r["pid"] = BIGINT(ec->event.pid);
  r["parent"] = BIGINT(ec->event.ppid);
  r["uid"] = BIGINT(ec->event.uid);
  r["euid"] = BIGINT(ec->event.euid);
  r["gid"] = BIGINT(ec->event.gid);
  r["egid"] = BIGINT(ec->event.egid);
  r["owner_uid"] = BIGINT(ec->event.owner_uid);
  r["owner_gid"] = BIGINT(ec->event.owner_gid);
  r["create_time"] = BIGINT(ec->event.create_time);
  r["access_time"] = BIGINT(ec->event.access_time);
  r["modify_time"] = BIGINT(ec->event.modify_time);
  r["change_time"] = BIGINT(ec->event.change_time);
  r["mode"] = BIGINT(ec->event.mode);
  r["path"] = ec->event.path;
  r["uptime"] = BIGINT(ec->uptime);

  add(r, ec->time);

  return Status(0, "OK");
}