TEST_F(VirtualTableTests, test_table_cache) {
  // Get a database connection.
  Registry::add<cacheTablePlugin>("table", "cache");
  auto dbc = SQLiteDBManager::getUnique();

  {
    auto cache = std::make_shared<cacheTablePlugin>();
    attachTableInternal("cache", cache->columnDefinition(), dbc);
  }

  QueryData results;
  // Run a query with a join within.
  std::string statement = "SELECT c2.data as data FROM cache c1, cache c2;";
  auto status = queryInternal(statement, results, dbc->db());
  dbc->clearAffectedTables();
  EXPECT_TRUE(status.ok());
  ASSERT_EQ(results.size(), 1U);
  EXPECT_EQ(results[0]["data"], "more_awesome_data");

  // Run the query again, the virtual table cache should have been expired.
  results.clear();
  statement = "SELECT data from cache c1";
  queryInternal(statement, results, dbc->db());
  ASSERT_EQ(results.size(), 1U);
  ASSERT_EQ(results[0]["data"], "awesome_data");
}
示例#2
0
TEST_F(ResultsTests, test_adding_duplicate_rows_to_query_data) {
  Row r1, r2, r3;
  r1["foo"] = "bar";
  r1["baz"] = "boo";

  r2["foo"] = "baz";
  r2["baz"] = "bop";

  r3["foo"] = "baz";
  r3["baz"] = "bop";

  QueryData q;
  bool s;

  s = addUniqueRowToQueryData(q, r1);
  EXPECT_TRUE(s);
  EXPECT_EQ(q.size(), 1);

  s = addUniqueRowToQueryData(q, r2);
  EXPECT_TRUE(s);
  EXPECT_EQ(q.size(), 2);

  s = addUniqueRowToQueryData(q, r3);
  EXPECT_FALSE(s);
  EXPECT_EQ(q.size(), 2);
}
示例#3
0
void jsonPrint(const QueryData& q) {
  printf("[\n");
  for (size_t i = 0; i < q.size(); ++i) {
    std::string row_string;

    if (serializeRowJSON(q[i], row_string).ok()) {
      row_string.pop_back();
      printf("  %s", row_string.c_str());
      if (i < q.size() - 1) {
        printf(",\n");
      }
    }
  }
  printf("\n]\n");
}
示例#4
0
TEST_F(LaunchdTests, test_parse_launchd_item) {
  QueryData results;
  genLaunchdItem(kTestDataPath + "test_launchd.plist", results);

  Row expected = {
      {"path", kTestDataPath + "test_launchd.plist"},
      {"name", "test_launchd.plist"},
      {"label", "com.apple.mDNSResponder"},
      {"run_at_load", ""},
      {"keep_alive", ""},
      {"on_demand", "false"},
      {"disabled", ""},
      {"username", "_mdnsresponder"},
      {"groupname", "_mdnsresponder"},
      {"stdout_path", ""},
      {"stderr_path", ""},
      {"start_interval", ""},
      {"program_arguments", "/usr/sbin/mDNSResponder"},
      {"program", ""},
      {"watch_paths", ""},
      {"queue_directories", ""},
      {"inetd_compatibility", ""},
      {"start_on_mount", ""},
      {"root_directory", ""},
      {"working_directory", ""},
      {"process_type", ""},
  };
  ASSERT_EQ(results.size(), 1);
  for (const auto& column : expected) {
    EXPECT_EQ(results[0][column.first], column.second);
  }
}
示例#5
0
TEST_F(AppsTests, test_sanity_check) {
  // Test beyond units, that there's at least 1 application on the built host.
  std::set<std::string> apps;
  genApplicationsFromPath("/Applications", apps);
  ASSERT_GT(apps.size(), 0);

  // Parse each application searching for a parsed Safari.
  bool found_safari = false;
  for (const auto& path : apps) {
    pt::ptree tree;
    if (osquery::parsePlist(path, tree).ok()) {
      QueryData results;
      genApplication(tree, path, results);

      // No asserts about individual Application parsing, expect edge cases.
      if (results.size() > 0 && results[0].count("bundle_identifier") > 0 &&
          results[0].at("bundle_identifier") == "com.apple.Safari") {
        // Assume Safari is installed on the build host.
        found_safari = true;
        break;
      }
    }
  }

  EXPECT_TRUE(found_safari);
}
示例#6
0
TEST_F(SQLTests, test_sql_sha256) {
  QueryData d;
  query("select sha256('test') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"],
            "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08");
}
示例#7
0
std::map<std::string, int> computeQueryDataLengths(const QueryData& q) {
  std::map<std::string, int> results;

  if (q.size() == 0) {
    return results;
  }

  for (const auto& it : q.front()) {
    results[it.first] = it.first.size();
  }

  for (const auto& row : q) {
    for (const auto& it : row) {
      try {
        if (it.second.size() > results[it.first]) {
          results[it.first] = it.second.size();
        }
      } catch (const std::out_of_range& e) {
        LOG(ERROR) << "Error retreiving the \"" << it.first
                   << "\" key in computeQueryDataLength:  " << e.what();
      }
    }
  }

  return results;
}
示例#8
0
TEST_F(AppsTests, test_parse_info_plist) {
  QueryData results;
  // Generate a set of results/single row using an example tree.
  auto tree = getInfoPlistTree();
  genApplication(tree, "/Applications/Foobar.app/Contents/Info.plist", results);
  ASSERT_EQ(results.size(), 1);
  ASSERT_EQ(results[0].count("name"), 1);

  Row expected = {
      {"name", "Foobar.app"},
      {"path", "/Applications/Foobar.app"},
      {"bundle_executable", "Photo Booth"},
      {"bundle_identifier", "com.apple.PhotoBooth"},
      {"bundle_name", ""},
      {"bundle_short_version", "6.0"},
      {"bundle_version", "517"},
      {"bundle_package_type", "APPL"},
      {"environment", ""},
      {"element", ""},
      {"compiler", "com.apple.compilers.llvm.clang.1_0"},
      {"development_region", "English"},
      {"display_name", ""},
      {"info_string", ""},
      {"minimum_system_version", "10.7.0"},
      {"category", "public.app-category.entertainment"},
      {"applescript_enabled", ""},
      {"copyright", ""},
  };

  // We could compare the entire map, but iterating the columns will produce
  // better error text as most likely parsing for a certain column/type changed.
  for (const auto& column : expected) {
    EXPECT_EQ(results[0][column.first], column.second);
  }
}
示例#9
0
TEST_F(SQLTests, test_sql_base64_conditional_encode) {
  QueryData d;
  query("select conditional_to_base64('test') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "test");

  QueryData d2;
  query("select conditional_to_base64('悪因悪果') as test;", d2);
  EXPECT_EQ(d2.size(), 1U);
  EXPECT_EQ(d2[0]["test"], "5oKq5Zug5oKq5p6c");
}
示例#10
0
TEST_F(VirtualTableTests, test_sqlite3_table_joins) {
  // Get a database connection.
  auto dbc = SQLiteDBManager::get();

  QueryData results;
  // Run a query with a join within.
  std::string statement =
      "SELECT p.pid FROM osquery_info oi, processes p WHERE oi.pid=p.pid";
  auto status = queryInternal(statement, results, dbc.db());
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(results.size(), 1U);
}
示例#11
0
文件: sqlite.cpp 项目: nemith/osquery
static void tryVacuum(sqlite3* db) {
    std::string q =
        "SELECT (sum(s1.pageno + 1 == s2.pageno) * 1.0 / count(*)) < 0.01 as v "
        " FROM "
        "(SELECT pageno FROM dbstat ORDER BY path) AS s1,"
        "(SELECT pageno FROM dbstat ORDER BY path) AS s2 WHERE "
        "s1.rowid + 1 = s2.rowid; ";

    QueryData results;
    sqlite3_exec(db, q.c_str(), getData, &results, nullptr);
    if (results.size() > 0 && results[0]["v"].back() == '1') {
        sqlite3_exec(db, "vacuum;", nullptr, nullptr, nullptr);
    }
}
示例#12
0
文件: sqlite.cpp 项目: nemith/osquery
Status SQLiteDatabasePlugin::get(const std::string& domain,
                                 const std::string& key,
                                 std::string& value) const {
    QueryData results;
    char* err = nullptr;
    std::string q = "select value from " + domain + " where key = '" + key + "';";
    sqlite3_exec(db_, q.c_str(), getData, &results, &err);
    if (err != nullptr) {
        sqlite3_free(err);
    }

    // Only assign value if the query found a result.
    if (results.size() > 0) {
        value = std::move(results[0]["value"]);
        return Status(0);
    }
    return Status(1);
}
示例#13
0
TEST_F(VirtualTableTests, test_json_extract) {
  // Get a database connection.
  Registry::add<jsonTablePlugin>("table", "json");
  auto dbc = SQLiteDBManager::get();

  {
    auto json = std::make_shared<jsonTablePlugin>();
    attachTableInternal("json", json->columnDefinition(), dbc->db());
  }

  QueryData results;
  // Run a query with a join within.
  std::string statement =
      "SELECT JSON_EXTRACT(data, '$.test') AS test FROM json;";
  auto status = queryInternal(statement, results, dbc->db());
  EXPECT_TRUE(status.ok());
  ASSERT_EQ(results.size(), 1U);
  EXPECT_EQ(results[0]["test"], "1");
}
示例#14
0
TEST_F(SQLiteUtilTests, test_reset) {
  auto internal_db = SQLiteDBManager::get()->db();
  ASSERT_NE(nullptr, internal_db);

  sqlite3_exec(internal_db,
               "create view test_view as select 'test';",
               nullptr,
               nullptr,
               nullptr);

  SQLiteDBManager::resetPrimary();
  auto instance = SQLiteDBManager::get();

  QueryData results;
  queryInternal("select * from test_view", results, instance);

  // Assume the internal (primary) database we reset and recreated.
  EXPECT_EQ(results.size(), 0U);
}
示例#15
0
TEST_F(LaunchdTests, test_parse_launchd_item) {
  // Read the contents of our testing launchd plist.
  pt::ptree tree;
  auto launchd_path = kTestDataPath + "test_launchd.plist";
  auto status = osquery::parsePlist(launchd_path, tree);
  ASSERT_TRUE(status.ok());

  // Parse the contents into a launchd table row.
  QueryData results;
  genLaunchdItem(tree, launchd_path, results);
  ASSERT_EQ(results.size(), 1U);

  Row expected = {
      {"path", kTestDataPath + "test_launchd.plist"},
      {"name", "test_launchd.plist"},
      {"label", "com.apple.mDNSResponder"},
      {"run_at_load", ""},
      {"keep_alive", ""},
      {"on_demand", "0"},
      {"disabled", ""},
      {"username", "_mdnsresponder"},
      {"groupname", "_mdnsresponder"},
      {"stdout_path", ""},
      {"stderr_path", ""},
      {"start_interval", ""},
      {"program_arguments", "/usr/sbin/mDNSResponder"},
      {"program", ""},
      {"watch_paths", ""},
      {"queue_directories", ""},
      {"inetd_compatibility", ""},
      {"start_on_mount", ""},
      {"root_directory", ""},
      {"working_directory", ""},
      {"process_type", ""},
  };

  // We could compare the entire map, but iterating the columns will produce
  // better error text as most likely parsing for a certain column/type changed.
  for (const auto& column : expected) {
    EXPECT_EQ(results[0][column.first], column.second);
  }
}
示例#16
0
void prettyPrint(const QueryData& results,
                 const std::vector<std::string>& columns,
                 std::map<std::string, size_t>& lengths) {
  if (results.size() == 0) {
    return;
  }

  // Call a final compute using the column names as minimum lengths.
  computeRowLengths(results.front(), lengths, true);

  // Output a nice header wrapping the column names.
  auto separator = generateToken(lengths, columns);
  auto header = separator + generateHeader(lengths, columns) + separator;
  printf("%s", header.c_str());

  // Iterate each row and pretty print.
  for (const auto& row : results) {
    printf("%s", generateRow(row, lengths, columns).c_str());
  }
  printf("%s", separator.c_str());
}
示例#17
0
std::string beautify(const QueryData& q,
                     const std::vector<std::string>& order) {
  auto lengths = computeQueryDataLengths(q);

  if (q.size() == 0) {
    return std::string();
  }

  auto separator = generateSeparator(lengths, order);
  std::ostringstream results;
  results << "\n";

  results << separator;
  results << generateHeader(lengths, order);
  results << separator;
  for (const auto& r : q) {
    results << generateRow(r, lengths, order);
  }
  results << separator;

  return results.str();
}
示例#18
0
文件: time.cpp 项目: FritzX6/osquery
TEST_F(Time, test_sanity) {
  QueryData data = execute_query("select * from time");

  ASSERT_EQ(data.size(), 1ul);

  ValidatatioMap row_map = {
      {"weekday", NonEmptyString},
      {"year", IntType},
      {"month", IntMinMaxCheck(1, 12)},
      {"day", IntMinMaxCheck(1, 31)},
      {"hour", IntMinMaxCheck(0, 24)},
      {"minutes", IntMinMaxCheck(0, 59)},
      {"seconds", IntMinMaxCheck(0, 59)},
      {"timezone", NonEmptyString},
      {"local_time", NonNegativeInt},
      {"local_timezone", NonEmptyString},
      {"unix_time", NonNegativeInt},
      {"timestamp", NonEmptyString},
      {"datetime", NonEmptyString},
      {"iso_8601", NonEmptyString},
  };
  validate_rows(data, row_map);
}
示例#19
0
TEST_F(RegistryTablesTest, test_registry_non_existing_key) {
  QueryData results;
  auto ret = queryKey(kInvalidTestKey, results);
  EXPECT_TRUE(ret.ok());
  EXPECT_TRUE(results.size() == 0);
}
示例#20
0
TEST_F(SQLTests, test_sql_base64_decode) {
  QueryData d;
  query("select from_base64('dGVzdA==') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "test");
}
示例#21
0
TEST_F(SQLTests, test_sql_md5) {
  QueryData d;
  query("select md5('test') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "098f6bcd4621d373cade4e832627b4f6");
}
示例#22
0
TEST_F(SQLTests, test_sql_sha1) {
  QueryData d;
  query("select sha1('test') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3");
}
示例#23
0
TEST_F(SQLTests, test_sql_base64_encode) {
  QueryData d;
  query("select to_base64('test') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "dGVzdA==");
}
示例#24
0
void getDrivesForArray(const std::string& arrayName,
                       MDInterface& md,
                       QueryData& data) {
  std::string path(md.getPathByDevName(arrayName));
  if (path.empty()) {
    LOG(ERROR) << "Could not get file path for " << arrayName;
    return;
  }

  mdu_array_info_t array;
  if (!md.getArrayInfo(path, array)) {
    return;
  }

  /* Create a vector of with all expected slot positions.  As we work through
   * the RAID disks, we remove discovered slots */
  std::vector<size_t> missingSlots(array.raid_disks);
  std::iota(missingSlots.begin(), missingSlots.end(), 0);

  /* Keep track of index in QueryData that have removed slots since we can't
   * make safe assumptions about it's original slot position if disk_number >=
   * total_disk and we're unable to deteremine total number of missing slots
   * until we walk thru all MD_SB_DISKS */
  std::vector<size_t> removedSlots;

  size_t qdPos = data.size();
  for (size_t i = 0; i < MD_SB_DISKS; i++) {
    mdu_disk_info_t disk;
    disk.number = i;
    if (!md.getDiskInfo(path, disk)) {
      continue;
    }

    if (disk.major > 0) {
      Row r;
      r["md_device_name"] = arrayName;
      r["drive_name"] = md.getDevName(disk.major, disk.minor);
      r["state"] = getDiskStateStr(disk.state);

      if (disk.raid_disk >= 0) {
        r["slot"] = INTEGER(disk.raid_disk);
        missingSlots.erase(
            std::remove(
                missingSlots.begin(), missingSlots.end(), disk.raid_disk),
            missingSlots.end());

        /* We assume that if the disk number is less than the total disk count
         * of the array, then it assumes its original slot position;  If the
         * number is greater than the disk count, then it's not safe to make
         * that assumption. We do this check here b/c if a recovery is targeted
         * for the same slot, we potentially miss identifying the original slot
         * position of the bad disk. */
      } else if (disk.raid_disk < 0 && disk.number < array.raid_disks) {
        r["slot"] = std::to_string(disk.number);
        missingSlots.erase(
            std::remove(missingSlots.begin(), missingSlots.end(), disk.number),
            missingSlots.end());

        /* Mark QueryData position as a removedSlot to handle later*/
      } else {
        removedSlots.push_back(qdPos);
      }

      qdPos++;
      data.push_back(r);
    }
  }

  /* Handle all missing slots.  See `scattered_faulty_and_removed` unit test in
   * `./tests/md_tables_tests.cpp`*/
  for (const auto& slot : missingSlots) {
    if (!removedSlots.empty()) {
      data[removedSlots[0]]["slot"] = INTEGER(slot);
      removedSlots.erase(removedSlots.begin());

    } else {
      Row r;
      r["md_device_name"] = arrayName;
      r["drive_name"] = "unknown";
      r["state"] = "removed";
      r["slot"] = std::to_string(slot);
      data.push_back(r);
    }
  }
}