示例#1
0
TEST_F(FilesystemTests, test_wildcard_single_file_list) {
  std::vector<std::string> files;
  std::vector<std::string> files_flag;
  auto status = resolveFilePattern(kFakeDirectory + "/%", files);
  auto status2 =
      resolveFilePattern(kFakeDirectory + "/%", files_flag, REC_LIST_FILES);
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(files.size(), 3);
  EXPECT_EQ(files.size(), files_flag.size());
  EXPECT_NE(std::find(files.begin(), files.end(), kFakeDirectory + "/roto.txt"),
            files.end());
}
示例#2
0
QueryData genSafariExtensions(QueryContext& context) {
  QueryData results;

  // Iterate over each user
  auto users = usersFromContext(context);
  for (const auto& row : users) {
    if (row.count("uid") > 0 && row.count("directory") > 0) {
      auto dir = fs::path(row.at("directory")) / kSafariExtensionsPath;
      // Check that an extensions directory exists.
      if (!pathExists(dir).ok()) {
        continue;
      }

      // Glob the extension files.
      std::vector<std::string> paths;
      if (!resolveFilePattern(dir / kSafariExtensionsPattern, paths).ok()) {
        continue;
      }

      for (const auto& extension_path : paths) {
        genSafariExtension(row.at("uid"), extension_path, results);
      }
    }
  }

  return results;
}
示例#3
0
std::set<std::string> FSEventsEventPublisher::transformSubscription(
    FSEventsSubscriptionContextRef& sc) const {
  std::set<std::string> paths;
  sc->discovered_ = sc->path;
  if (sc->path.find("**") != std::string::npos) {
    // Double star will indicate recursive matches, restricted to endings.
    sc->recursive = true;
    sc->discovered_ = sc->path.substr(0, sc->path.find("**"));
    // Remove '**' from the subscription path (used to match later).
    sc->path = sc->discovered_;
  }

  // If the path 'still' OR 'either' contains a single wildcard.
  if (sc->path.find('*') != std::string::npos) {
    // First check if the wildcard is applied to the end.
    auto fullpath = fs::path(sc->path);
    if (fullpath.filename().string().find('*') != std::string::npos) {
      sc->discovered_ = fullpath.parent_path().string();
    }

    // FSEvents needs a real path, if the wildcard is within the path then
    // a configure-time resolve is required.
    if (sc->discovered_.find('*') != std::string::npos) {
      std::vector<std::string> exploded_paths;
      resolveFilePattern(sc->discovered_, exploded_paths);
      for (const auto& path : exploded_paths) {
        paths.insert(path);
      }
      sc->recursive_match = sc->recursive;
      return paths;
    }
  }
  paths.insert(sc->discovered_);
  return paths;
}
示例#4
0
QueryData genChromeBasedExtensions(QueryContext& context, const fs::path sub_dir) {
  QueryData results;

  auto homes = osquery::getHomeDirectories();
  for (const auto& home : homes) {
    // For each user, enumerate all of their chrome profiles.
    std::vector<std::string> profiles;
    fs::path extension_path = home / sub_dir;
    if (!resolveFilePattern(extension_path, profiles, REC_LIST_FOLDERS).ok()) {
      continue;
    }

    // For each profile list each extension in the Extensions directory.
    std::vector<std::string> extensions;
    for (const auto& profile : profiles) {
      listDirectoriesInDirectory(profile, extensions);
    }

    // Generate an addons list from their extensions JSON.
    std::vector<std::string> versions;
    for (const auto& extension : extensions) {
      listDirectoriesInDirectory(extension, versions);
    }

    // Extensions use /<EXTENSION>/<VERSION>/manifest.json.
    for (const auto& version : versions) {
      genExtension(version, results);
    }
  }

  return results;
}
示例#5
0
int getBluetoothSharingStatus() {
  auto users = SQL::selectAllFrom("users");
  for (const auto& row : users) {
    if (row.count("uid") > 0 && row.count("directory") > 0) {
      auto dir = fs::path(row.at("directory")) / kRemoteBluetoothSharingPath;
      if (!pathExists(dir).ok()) {
        continue;
      }
      std::vector<std::string> paths;
      if (!resolveFilePattern(dir / kRemoteBluetoothSharingPattern, paths)
               .ok()) {
        continue;
      }

      for (const auto& bluetoothSharing_path : paths) {
        auto bluetoothSharingStatus =
            SQL::selectAllFrom("plist", "path", EQUALS, bluetoothSharing_path);
        if (bluetoothSharingStatus.empty()) {
          continue;
        }
        for (const auto& r : bluetoothSharingStatus) {
          if (r.find("key") == row.end() || row.find("value") == r.end()) {
            continue;
          }
          if (r.at("key") == "PrefKeyServicesEnabled" &&
              r.at("value") == INTEGER(1)) {
            return 1;
          }
        }
      }
    }
  }
  return 0;
}
示例#6
0
QueryData genChocolateyPackages(QueryContext& context) {
  QueryData results;

  auto chocoEnvInstall = getEnvVar("ChocolateyInstall");

  fs::path chocoInstallPath;
  if (chocoEnvInstall.is_initialized()) {
    chocoInstallPath = fs::path(*chocoEnvInstall);
  }

  if (chocoInstallPath.empty()) {
    LOG(WARNING) << "Did not find chocolatey path environment variable";
    return results;
  }

  auto nuspecPattern = chocoInstallPath / "lib/%/%.nuspec";
  std::vector<std::string> manifests;
  resolveFilePattern(nuspecPattern, manifests, GLOB_FILES);

  for (const auto& pkg : manifests) {
    Row r;
    auto s = genPackage(pkg, r);
    if (!s.ok()) {
      VLOG(1) << "Failed to parse " << pkg << " with " << s.getMessage();
    }
    results.push_back(r);
  }

  return results;
}
示例#7
0
QueryData genChromeBasedExtensions(QueryContext& context,
                                   const fs::path& sub_dir) {
  QueryData results;

  auto users = usersFromContext(context);
  for (const auto& row : users) {
    if (row.count("uid") > 0 && row.count("directory") > 0) {
      // For each user, enumerate all of their chrome profiles.
      std::vector<std::string> profiles;
      fs::path extension_path = row.at("directory") / sub_dir;
      if (!resolveFilePattern(extension_path, profiles, GLOB_FOLDERS).ok()) {
        continue;
      }

      // For each profile list each extension in the Extensions directory.
      std::vector<std::string> extensions;
      for (const auto& profile : profiles) {
        listDirectoriesInDirectory(profile, extensions);
      }

      // Generate an addons list from their extensions JSON.
      std::vector<std::string> versions;
      for (const auto& extension : extensions) {
        listDirectoriesInDirectory(extension, versions);
      }

      // Extensions use /<EXTENSION>/<VERSION>/manifest.json.
      for (const auto& version : versions) {
        genExtension(row.at("uid"), version, results);
      }
    }
  }

  return results;
}
示例#8
0
bool INotifyEventPublisher::monitorSubscription(
    INotifySubscriptionContextRef& sc, bool add_watch) {
    sc->discovered_ = sc->path;
    if (sc->path.find("**") != std::string::npos) {
        sc->recursive = true;
        sc->discovered_ = sc->path.substr(0, sc->path.find("**"));
        sc->path = sc->discovered_;
    }

    if (sc->path.find('*') != std::string::npos) {
        // If the wildcard exists within the file (leaf), remove and monitor the
        // directory instead. Apply a fnmatch on fired events to filter leafs.
        auto fullpath = fs::path(sc->path);
        if (fullpath.filename().string().find('*') != std::string::npos) {
            sc->discovered_ = fullpath.parent_path().string() + '/';
        }

        if (sc->discovered_.find('*') != std::string::npos) {
            // If a wildcard exists within the tree (stem), resolve at configure
            // time and monitor each path.
            std::vector<std::string> paths;
            resolveFilePattern(sc->discovered_, paths);
            for (const auto& _path : paths) {
                addMonitor(_path, sc->mask, sc->recursive, add_watch);
            }
            sc->recursive_match = sc->recursive;
            return true;
        }
    }
    if (isDirectory(sc->discovered_) && sc->discovered_.back() != '/') {
        sc->path += '/';
        sc->discovered_ += '/';
    }
    return addMonitor(sc->discovered_, sc->mask, sc->recursive, add_watch);
}
示例#9
0
inline void mergeAdditional(const tree_node& node, ConfigData& conf) {
  if (conf.all_data.count("additional_monitoring") > 0) {
    conf.all_data.get_child("additional_monitoring").erase(node.first);
  }
  conf.all_data.add_child("additional_monitoring." + node.first, node.second);

  // Support special merging of file paths.
  if (node.first == "file_paths") {
    for (const auto& category : node.second) {
      for (const auto& path : category.second) {
        resolveFilePattern(path.second.data(),
                           conf.files[category.first],
                           REC_LIST_FOLDERS | REC_EVENT_OPT);
      }
    }
  } else if (node.first == "yara") {
    for (const auto& category : node.second) {
      // Todo: the yara category key must come after "file_paths".
      if (conf.files.find(category.first) == conf.files.end()) {
        continue;
      }
      for (const auto& file : category.second) {
        conf.yara[category.first].push_back(
            file.second.get_value<std::string>());
      }
    }
  } else {
    // Unknown additional monitoring key.
  }
}
示例#10
0
inline void removeStalePaths(const std::string& manager) {
  std::vector<std::string> paths;
  // Attempt to remove all stale extension sockets.
  resolveFilePattern(manager + ".*", paths);
  for (const auto& path : paths) {
    remove(path);
  }
}
示例#11
0
TEST_F(FilesystemTests, test_double_wild_event_opt) {
  std::vector<std::string> all;
  auto status = resolveFilePattern(
      kFakeDirectory + "/%%", all, REC_LIST_FOLDERS | REC_EVENT_OPT);
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(all.size(), 1);
  EXPECT_NE(std::find(all.begin(), all.end(), kFakeDirectory), all.end());
}
示例#12
0
TEST_F(FilesystemTests, test_wildcard_full_recursion) {
  std::vector<std::string> files;
  auto status = resolveFilePattern(kFakeDirectory + "/%%", files);
  EXPECT_TRUE(status.ok());
  EXPECT_NE(std::find(files.begin(),
                      files.end(),
                      kFakeDirectory + "/deep1/deep2/level2.txt"),
            files.end());
}
示例#13
0
TEST_F(FilesystemTests, test_wildcard_end_last_component) {
  std::vector<std::string> files;
  auto status = resolveFilePattern(kFakeDirectory + "/%11/%sh", files);
  EXPECT_TRUE(status.ok());
  EXPECT_NE(std::find(files.begin(),
                      files.end(),
                      kFakeDirectory + "/deep11/not_bash"),
            files.end());
}
示例#14
0
TEST_F(FilesystemTests, test_wildcard_three_kinds) {
  std::vector<std::string> files;
  auto status = resolveFilePattern(kFakeDirectory + "/%p11/%/%%", files);
  EXPECT_TRUE(status.ok());
  EXPECT_NE(std::find(files.begin(),
                      files.end(),
                      kFakeDirectory + "/deep11/deep2/deep3/level3.txt"),
            files.end());
}
示例#15
0
TEST_F(FilesystemTests, test_no_wild) {
  std::vector<std::string> all;
  auto status =
      resolveFilePattern(kFakeDirectory + "/roto.txt", all, REC_LIST_FILES);
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(all.size(), 1);
  EXPECT_NE(std::find(all.begin(), all.end(), kFakeDirectory + "/roto.txt"),
            all.end());
}
示例#16
0
inline void mergeFilePath(const std::string& name,
                          const tree_node& node,
                          ConfigData& conf) {
  for (const auto& path : node.second) {
    resolveFilePattern(path.second.data(),
                       conf.files[node.first],
                       REC_LIST_FOLDERS | REC_EVENT_OPT);
  }
  conf.all_data.add_child(name + "." + node.first, node.second);
}
示例#17
0
TEST_F(FilesystemTests, test_wildcard_single_all_list) {
  std::vector<std::string> all;
  auto status = resolveFilePattern(kFakeDirectory + "/%", all, REC_LIST_ALL);
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(all.size(), 6);
  EXPECT_NE(std::find(all.begin(), all.end(), kFakeDirectory + "/roto.txt"),
            all.end());
  EXPECT_NE(std::find(all.begin(), all.end(), kFakeDirectory + "/deep11"),
            all.end());
}
示例#18
0
TEST_F(FilesystemTests, test_wildcard_single_folder_list) {
  std::vector<std::string> folders;
  auto status =
      resolveFilePattern(kFakeDirectory + "/%", folders, REC_LIST_FOLDERS);
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(folders.size(), 3);
  EXPECT_NE(
      std::find(folders.begin(), folders.end(), kFakeDirectory + "/deep11"),
      folders.end());
}
示例#19
0
TEST_F(FilesystemTests, test_dotdot) {
  std::vector<std::string> all;
  auto status = resolveFilePattern(
      kFakeDirectory + "/deep11/deep2/../../%", all, REC_LIST_FILES);
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(all.size(), 3);
  EXPECT_NE(std::find(all.begin(),
                      all.end(),
                      kFakeDirectory + "/deep11/deep2/../../door.txt"),
            all.end());
}
示例#20
0
TEST_F(FilesystemTests, test_letter_wild_opt) {
  std::vector<std::string> all;
  auto status = resolveFilePattern(
      kFakeDirectory + "/d%", all, REC_LIST_FOLDERS | REC_EVENT_OPT);
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(all.size(), 3);
  EXPECT_NE(std::find(all.begin(), all.end(), kFakeDirectory + "/deep1"),
            all.end());
  EXPECT_NE(std::find(all.begin(), all.end(), kFakeDirectory + "/door.txt"),
            all.end());
}
示例#21
0
TEST_F(FilesystemTests, test_wildcard_double_folders) {
  std::vector<std::string> all;
  auto status =
      resolveFilePattern(kFakeDirectory + "/%%", all, REC_LIST_FOLDERS);
  EXPECT_TRUE(status.ok());
  EXPECT_EQ(all.size(), 6);
  EXPECT_NE(std::find(all.begin(), all.end(), kFakeDirectory), all.end());
  EXPECT_NE(
      std::find(all.begin(), all.end(), kFakeDirectory + "/deep11/deep2/deep3"),
      all.end());
}
示例#22
0
TEST_F(FilesystemTests, test_dotdot_relative) {
  std::vector<std::string> all;
  auto status = resolveFilePattern(kTestDataPath + "%", all, REC_LIST_ALL);
  EXPECT_TRUE(status.ok());

  bool found = false;
  for (const auto& file : all) {
    if (file.find("test.config")) {
      found = true;
      break;
    }
  }
  EXPECT_TRUE(found);
}
示例#23
0
Status FilesystemConfigPlugin::genPack(const std::string& name,
                                       const std::string& value,
                                       std::string& pack) {
  if (name == "*") {
    // The config requested a multi-pack.
    std::vector<std::string> paths;
    resolveFilePattern(value, paths);

    pt::ptree multi_pack;
    for (const auto& path : paths) {
      std::string content;
      if (!readFile(path, content)) {
        LOG(WARNING) << "Cannot read multi-pack file: " << path;
        continue;
      }

      // Assemble an intermediate property tree for simplified parsing.
      pt::ptree single_pack;
      stripConfigComments(content);
      try {
        std::stringstream json_stream;
        json_stream << content;
        pt::read_json(json_stream, single_pack);
      } catch (const pt::json_parser::json_parser_error& /* e */) {
        LOG(WARNING) << "Cannot read multi-pack JSON: " << path;
        continue;
      }

      multi_pack.put_child(fs::path(path).stem().string(), single_pack);
    }

    // We should have a property tree of pack content mimicking embedded
    // configuration packs, ready to parse as a string.
    std::ostringstream output;
    pt::write_json(output, multi_pack, false);
    pack = output.str();
    if (pack.empty()) {
      return Status(1, "Multi-pack content empty");
    }

    return Status(0);
  }

  boost::system::error_code ec;
  if (!fs::is_regular_file(value, ec) || ec.value() != errc::success) {
    return Status(1, value + " is not a valid path");
  }

  return readFile(value, pack);
}
示例#24
0
QueryData genQuicklookCache(QueryContext& context) {
  QueryData results;

  // There may be several quick look caches.
  // Apply a GLOB search since the folder is randomized.
  std::vector<std::string> databases;
  if (!resolveFilePattern(kQuicklookPattern, databases)) {
    return results;
  }

  for (const auto& index : databases) {
    sqlite3* db = nullptr;
    auto rc = sqlite3_open_v2(
        index.c_str(), &db,
        (SQLITE_OPEN_READONLY | SQLITE_OPEN_PRIVATECACHE | SQLITE_OPEN_NOMUTEX),
        nullptr);
    if (rc != SQLITE_OK || db == nullptr) {
      VLOG(1) << "Cannot open " << index << " read only: "
              << rc << " " << getStringForSQLiteReturnCode(rc);
      if (db != nullptr) {
        sqlite3_close(db);
      }
      continue;
    }

    // QueryData file_results;
    std::string query =
        "SELECT f.*, last_hit_date, hit_count, icon_mode FROM (SELECT rowid, * "
        "FROM files) f, (SELECT *, max(last_hit_date) AS last_hit_date FROM "
        "thumbnails GROUP BY file_id) t WHERE t.file_id = rowid;";
    sqlite3_stmt* stmt = nullptr;
    rc = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr);
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
      Row r;
      genQuicklookRow(stmt, r);

      // For each row added to the results from this database, add the path to
      // the database, then move into the table's result set.
      r["cache_path"] = index;
      results.push_back(r);
    }

    // Clean up.
    sqlite3_finalize(stmt);
    sqlite3_close(db);
  }

  return results;
}
示例#25
0
QueryData ATCPlugin::generate(QueryContext& context) {
  QueryData qd;
  std::vector<std::string> paths;
  auto s = resolveFilePattern(path_, paths);
  if (!s.ok()) {
    LOG(WARNING) << "Could not glob: " << path_;
  }
  for (const auto& path : paths) {
    s = genQueryDataForSqliteTable(path, sqlite_query_, qd, false);
    if (!s.ok()) {
      LOG(WARNING) << "Error Code: " << s.getCode()
                   << " Could not generate data: " << s.getMessage();
    }
  }
  return qd;
}
示例#26
0
QueryData genOSXPlist(QueryContext& context) {
  QueryData results;

  // Resolve file paths for EQUALS and LIKE operations.
  auto paths = context.constraints["path"].getAll(EQUALS);
  context.expandConstraints(
      "path",
      LIKE,
      paths,
      ([&](const std::string& pattern, std::set<std::string>& out) {
        std::vector<std::string> patterns;
        auto status =
            resolveFilePattern(pattern, patterns, GLOB_ALL | GLOB_NO_CANON);
        if (status.ok()) {
          for (const auto& resolved : patterns) {
            out.insert(resolved);
          }
        }
        return status;
      }));

  for (const auto& path : paths) {
    if (!pathExists(path).ok() || !isReadable(path).ok()) {
      VLOG(1) << "Cannot find/read defaults plist from path: " + path;
      continue;
    }

    pt::ptree tree;
    if (!osquery::parsePlist(path, tree).ok()) {
      VLOG(1) << "Could not parse plist: " + path;
      continue;
    }

    for (const auto& item : tree) {
      Row r;

      r["path"] = path;
      r["key"] = item.first;
      r["subkey"] = "";
      genOSXPlistPrefValue(item.second, r, 0, results);
    }
  }

  return results;
}
示例#27
0
Status FilesystemConfigPlugin::genConfig(
    std::map<std::string, std::string>& config) {
  if (!fs::is_regular_file(FLAGS_config_path)) {
    return Status(1, "config file does not exist");
  }

  std::vector<std::string> conf_files;
  resolveFilePattern(FLAGS_config_path + ".d/%.conf", conf_files);
  std::sort(conf_files.begin(), conf_files.end());
  conf_files.push_back(FLAGS_config_path);

  for (const auto& path : conf_files) {
    std::string content;
    if (readFile(path, content).ok()) {
      config[path] = content;
    }
  }
  return Status(0, "OK");
}
示例#28
0
QueryData genSystemControls(QueryContext& context) {
    QueryData results;

    // Read the sysctl.conf values.
    std::map<std::string, std::string> config;
    for (const auto& path : kControlSettingsFiles) {
        genControlConfigFromPath(path, config);
    }

    for (const auto& dirs : kControlSettingsDirs) {
        std::vector<std::string> configs;
        if (resolveFilePattern(dirs, configs).ok()) {
            for (const auto& path : configs) {
                genControlConfigFromPath(path, config);
            }
        }
    }

    // Iterate through the sysctl-defined macro of control types.
    if (context.constraints["name"].exists(EQUALS)) {
        // Request MIB information by the description (name).
        auto names = context.constraints["name"].getAll(EQUALS);
        for (const auto& name : names) {
            genControlInfoFromName(name, results, config);
        }
    } else if (context.constraints["oid"].exists(EQUALS)) {
        // Request MIB by OID as a string, parse into set of INTs.
        auto oids = context.constraints["oid"].getAll(EQUALS);
        for (const auto& oid_string : oids) {
            genControlInfoFromOIDString(oid_string, results, config);
        }
    } else if (context.constraints["subsystem"].exists(EQUALS)) {
        // Limit the MIB search to a subsystem name (first find the INT).
        auto subsystems = context.constraints["subsystem"].getAll(EQUALS);
        for (const auto& subsystem : subsystems) {
            genAllControls(results, config, subsystem);
        }
    } else {
        genAllControls(results, config, "");
    }

    return results;
}
示例#29
0
文件: hash.cpp 项目: FritzX6/osquery
void expandFSPathConstraints(QueryContext& context,
                             const std::string& path_column_name,
                             std::set<std::string>& paths) {
  context.expandConstraints(
      path_column_name,
      LIKE,
      paths,
      ([&](const std::string& pattern, std::set<std::string>& out) {
        std::vector<std::string> patterns;
        auto status =
            resolveFilePattern(pattern, patterns, GLOB_ALL | GLOB_NO_CANON);
        if (status.ok()) {
          for (const auto& resolved : patterns) {
            out.insert(resolved);
          }
        }
        return status;
      }));
}
示例#30
0
void INotifyEventPublisher::configure() {
  for (auto& sub : subscriptions_) {
    // Anytime a configure is called, try to monitor all subscriptions.
    // Configure is called as a response to removing/adding subscriptions.
    // This means recalculating all monitored paths.
    auto sc = getSubscriptionContext(sub->context);
    if (sc->discovered_.size() > 0) {
      continue;
    }

    sc->discovered_ = sc->path;
    if (sc->path.find("**") != std::string::npos) {
      sc->recursive = true;
      sc->discovered_ = sc->path.substr(0, sc->path.find("**"));
      sc->path = sc->discovered_;
    }

    if (sc->path.find('*') != std::string::npos) {
      // If the wildcard exists within the file (leaf), remove and monitor the
      // directory instead. Apply a fnmatch on fired events to filter leafs.
      auto fullpath = fs::path(sc->path);
      if (fullpath.filename().string().find('*') != std::string::npos) {
        sc->discovered_ = fullpath.parent_path().string();
      }

      if (sc->discovered_.find('*') != std::string::npos) {
        // If a wildcard exists within the tree (stem), resolve at configure
        // time and monitor each path.
        std::vector<std::string> paths;
        resolveFilePattern(sc->discovered_, paths);
        for (const auto& _path : paths) {
          addMonitor(_path, sc->recursive);
        }
        sc->recursive_match = sc->recursive;
        continue;
      }
    }
    addMonitor(sc->discovered_, sc->recursive);
  }
}