QueryData parseALFExceptionsTree(const pt::ptree& tree) { QueryData results; if (tree.count("exceptions") == 0) { return {}; } auto exceptions_tree = tree.get_child("exceptions"); for (const auto& it : exceptions_tree) { Row r; r["path"] = it.second.get("path", ""); r["state"] = INTEGER(it.second.get("state", -1)); results.push_back(r); } auto applications_tree = tree.get_child("applications"); for (const auto& it : applications_tree) { Row r; if (it.second.get("alias", "").length() > 0) { std::string path; auto alias_data = it.second.get<std::string>("alias", ""); if (pathFromPlistAliasData(alias_data, path).ok()) { r["path"] = path; r["state"] = INTEGER(it.second.get("state", -1)); results.push_back(r); } } } return results; }
QueryData genOsqueryExtensions(QueryContext& context) { QueryData results; ExtensionList extensions; if (getExtensions(extensions).ok()) { for (const auto& extension : extensions) { Row r; r["uuid"] = TEXT(extension.first); r["name"] = extension.second.name; r["version"] = extension.second.version; r["sdk_version"] = extension.second.sdk_version; r["path"] = getExtensionSocket(extension.first); r["type"] = (extension.first == 0) ? "core" : "extension"; results.push_back(r); } } const auto& modules = RegistryFactory::getModules(); for (const auto& module : modules) { Row r; r["uuid"] = TEXT(module.first); r["name"] = module.second.name; r["version"] = module.second.version; r["sdk_version"] = module.second.sdk_version; r["path"] = module.second.path; r["type"] = "module"; results.push_back(r); } return results; }
void genSocketDescriptor(int pid, int descriptor, QueryData& results) { struct socket_fdinfo si; if (proc_pidfdinfo(pid, descriptor, PROC_PIDFDSOCKETINFO, &si, PROC_PIDFDSOCKETINFO_SIZE) <= 0) { return; } if (si.psi.soi_family == AF_INET || si.psi.soi_family == AF_INET6) { Row r; r["pid"] = INTEGER(pid); r["fd"] = BIGINT(descriptor); r["socket"] = BIGINT(si.psi.soi_so); r["path"] = ""; // Darwin/OSX SOCKINFO_TCP is not IPPROTO_TCP if (si.psi.soi_kind == SOCKINFO_TCP) { r["protocol"] = INTEGER(6); } else { r["protocol"] = INTEGER(17); } // Darwin/OSX AF_INET6 == 30 if (si.psi.soi_family == AF_INET) { r["family"] = INTEGER(2); } else { r["family"] = INTEGER(10); } parseNetworkSocket(si, r); results.push_back(r); } else if (si.psi.soi_family == AF_UNIX) { Row r; r["pid"] = INTEGER(pid); r["socket"] = INTEGER(descriptor); r["family"] = "0"; r["protocol"] = "0"; r["local_address"] = ""; r["local_port"] = "0"; r["remote_address"] = ""; r["remote_port"] = "0"; if ((char*)si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path != nullptr) { r["path"] = si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path; } else { r["path"] = ""; } results.push_back(r); } else if (si.psi.soi_family == AF_APPLETALK) { // AF_APPLETALK = 17 } else if (si.psi.soi_family == AF_NATM) { // AF_NATM = 32 } else { // Unsupported socket type. } }
QueryData genSIPConfig(QueryContext& context) { auto os_version = SQL::selectAllFrom("os_version"); if (os_version.size() != 1) { VLOG(1) << "Could not determine OS version"; return {}; } // bail out if running on OS X < 10.11 if (os_version.front().at("major") == "10" && std::stoi(os_version.front().at("minor")) < 11) { VLOG(1) << "Not running on OS X 10.11 or higher"; return {}; } QueryData results; #if !defined(DARWIN_10_9) // check if weakly linked symbols exist if (csr_get_active_config == nullptr || csr_check == nullptr) { return {}; } csr_config_t config = 0; csr_get_active_config(&config); csr_config_t valid_allowed_flags = 0; for (const auto& kv : kRootlessConfigFlags) { valid_allowed_flags |= kv.second; } Row r; r["config_flag"] = "sip"; if (config == 0) { // SIP is enabled (default) r["enabled"] = INTEGER(1); r["enabled_nvram"] = INTEGER(1); } else if ((config | valid_allowed_flags) == valid_allowed_flags) { // mark SIP as NOT enabled (i.e. disabled) if // any of the valid_allowed_flags is set r["enabled"] = INTEGER(0); r["enabled_nvram"] = INTEGER(0); } results.push_back(r); uint32_t nvram_config = 0; auto nvram_status = genCsrConfigFromNvram(nvram_config); for (const auto& kv : kRootlessConfigFlags) { r["config_flag"] = kv.first; // csr_check returns zero if the config flag is allowed r["enabled"] = (csr_check(kv.second) == 0) ? INTEGER(1) : INTEGER(0); if (nvram_status.ok()) { r["enabled_nvram"] = (nvram_config & kv.second) ? INTEGER(1) : INTEGER(0); } results.push_back(r); } #endif return results; }
QueryData getTestDBExpectedResults() { QueryData d; Row row1; row1["username"] = "******"; row1["age"] = "23"; d.push_back(row1); Row row2; row2["username"] = "******"; row2["age"] = "24"; d.push_back(row2); return d; }
void genADConfig(const std::string& path, QueryData& results) { auto config = SQL::selectAllFrom("preferences", "path", EQUALS, path); if (config.size() == 0) { // Fail if the file could not be plist-parsed. return; } // Walk through module options quickly to find the trust domain. // The file name and domain will be included in every row. auto name = config[0].at("domain"); std::string domain; for (const auto& row : config) { if (row.at("subkey") == "ActiveDirectory/trust domain") { domain = row.at("value"); break; } } // Iterate again with the domain known, searching for options. for (const auto& row : config) { Row r; r["domain"] = domain; r["name"] = name; // Get references to common columns. const auto& key = row.at("key"); const auto& subkey = row.at("subkey"); if (key == "trustoptions" || key == "trustkerberosprincipal" || key == "trustaccount" || key == "trusttype") { r["option"] = key; r["value"] = row.at("value"); results.push_back(r); } else if (key == "options") { // The options key has a single subkey with the option name. r["option"] = subkey; r["value"] = row.at("value"); results.push_back(r); } else if (key == "module options") { // Module options may contain 'managed client template', skip those. if (subkey.find("managed client template") != std::string::npos) { continue; } // Skip the "ActiveDirectory/" preamble. r["option"] = subkey.substr(16); r["value"] = row.at("value"); results.push_back(r); } } }
QueryData genOsqueryEvents(QueryContext& context) { QueryData results; auto publishers = EventFactory::publisherTypes(); for (const auto& publisher : publishers) { Row r; r["name"] = publisher; r["publisher"] = publisher; r["type"] = "publisher"; auto pubref = EventFactory::getEventPublisher(publisher); if (pubref != nullptr) { r["subscriptions"] = INTEGER(pubref->numSubscriptions()); r["events"] = INTEGER(pubref->numEvents()); r["restarts"] = INTEGER(pubref->restartCount()); r["active"] = (pubref->hasStarted() && !pubref->isEnding()) ? "1" : "0"; } else { r["subscriptions"] = "0"; r["events"] = "0"; r["restarts"] = "0"; r["active"] = "-1"; } results.push_back(r); } auto subscribers = EventFactory::subscriberNames(); for (const auto& subscriber : subscribers) { Row r; r["name"] = subscriber; r["type"] = "subscriber"; // Subscribers will never 'restart'. r["restarts"] = "0"; auto subref = EventFactory::getEventSubscriber(subscriber); if (subref != nullptr) { r["publisher"] = subref->getType(); r["subscriptions"] = INTEGER(subref->numSubscriptions()); r["events"] = INTEGER(subref->numEvents()); // Subscribers are always active, even if their publisher is not. r["active"] = (subref->state() == SUBSCRIBER_RUNNING) ? "1" : "0"; } else { r["subscriptions"] = "0"; r["events"] = "0"; r["active"] = "-1"; } results.push_back(r); } return results; }
QueryData generate(tables::QueryContext& ctx) { QueryData results; if (ctx.constraints["test_int"].existsAndMatches("1")) { results.push_back({{"test_int", "1"}, {"test_text", "0"}}); } else { results.push_back({{"test_int", "0"}, {"test_text", "1"}}); } auto ints = ctx.constraints["test_int"].getAll<int>(tables::EQUALS); for (const auto& int_match : ints) { results.push_back({{"test_int", INTEGER(int_match)}}); } return results; }
QueryData genXProtectMeta(QueryContext& context) { QueryData results; pt::ptree tree; auto xprotect_meta = fs::path(kXProtectPath) / "XProtect.meta.plist"; if (!osquery::pathExists(xprotect_meta).ok()) { VLOG(1) << "XProtect.meta.plist is missing"; return results; } if (!osquery::parsePlist(xprotect_meta, tree).ok()) { VLOG(1) << "Could not parse the XProtect.meta.plist"; return results; } for (const auto& it : tree) { if (it.first == "JavaWebComponentVersionMinimum") { Row r; r["identifier"] = "java"; r["min_version"] = it.second.data(); r["type"] = "plugin"; results.push_back(std::move(r)); } else if (it.first == "ExtensionBlacklist") { for (const auto& ext : it.second.get_child("Extensions")) { Row r; r["identifier"] = ext.second.get("CFBundleIdentifier", ""); r["developer_id"] = ext.second.get("Developer Identifier", ""); r["type"] = "extension"; r["min_version"] = "any"; results.push_back(std::move(r)); } } else if (it.first == "PlugInBlacklist") { for (const auto& cat : it.second) { // Not sure why there's a category-like sub-dictionary, default="10". for (const auto& plug : cat.second) { Row r; r["identifier"] = plug.first; r["min_version"] = plug.second.get("MinimumPlugInBundleVersion", ""); r["type"] = "plugin"; r["developer_id"] = ""; results.push_back(std::move(r)); } } } } return std::move(results); }
QueryData generate(QueryContext& ctx) { QueryData results; for (int i = 0; i < 1000; i++) { results.push_back({{"test_int", "0"}, {"test_text", "hello"}}); } return results; }
void genAddressesFromAddr(const struct ifaddrs *addr, QueryData &results) { std::string dest_address; Row r; r["interface"] = std::string(addr->ifa_name); // Address and mask will appear every time. if (addr->ifa_addr != nullptr) { r["address"] = ipAsString(static_cast<struct sockaddr *>(addr->ifa_addr)); } if (addr->ifa_netmask != nullptr) { r["mask"] = ipAsString(static_cast<struct sockaddr *>(addr->ifa_netmask)); } // The destination address is used for either a broadcast or PtP address. if (addr->ifa_dstaddr != nullptr) { dest_address = ipAsString(static_cast<struct sockaddr *>(addr->ifa_dstaddr)); if ((addr->ifa_flags & IFF_BROADCAST) == IFF_BROADCAST) { r["broadcast"] = dest_address; } else { r["point_to_point"] = dest_address; } } results.push_back(r); }
QueryData genCurl(QueryContext& context) { QueryData results; auto requests = context.constraints["url"].getAll(EQUALS); auto user_agents = context.constraints["user_agent"].getAll(EQUALS); if (user_agents.size() > 1) { LOG(WARNING) << "Can only accept a single user_agent"; return results; } // Using the like clause for urls wouldn't make sense if (context.constraints["url"].getAll(LIKE).size()) { LOG(WARNING) << "Using LIKE clause for url is not supported"; } for (const auto& request : requests) { Row r; r["url"] = request; r["method"] = "GET"; r["user_agent"] = user_agents.empty() ? kOsqueryUserAgent : *(user_agents.begin()); auto status = processRequest(r); if (!status.ok()) { LOG(WARNING) << status.getMessage(); } results.push_back(r); } return results; }
void genSSHkeysForUser(const std::string& uid, const std::string& directory, QueryData& results) { for (const auto& kfile : kSSHAuthorizedkeys) { boost::filesystem::path keys_file = directory; keys_file /= kfile; std::string keys_content; if (!osquery::forensicReadFile(keys_file, keys_content).ok()) { // Cannot read a specific keys file. continue; } // Protocol 1 public key consist of: options, bits, exponent, modulus, // comment; Protocol 2 public key consist of: options, keytype, // base64-encoded key, comment. for (const auto& line : split(keys_content, "\n")) { if (!line.empty() && line[0] != '#') { Row r; r["uid"] = uid; r["key"] = line; r["key_file"] = keys_file.string(); results.push_back(r); } } } }
QueryData genMounts(QueryContext& context) { QueryData results; struct statfs *mnt; int mnts = 0; int i; char real_path[PATH_MAX]; mnts = getmntinfo(&mnt, MNT_WAIT); if (mnts == 0) { // Failed to get mount informaton. return results; } for (i = 0; i < mnts; i++) { Row r; r["path"] = TEXT(mnt[i].f_mntonname); r["device"] = TEXT(mnt[i].f_mntfromname); r["device_alias"] = std::string(realpath(mnt[i].f_mntfromname, real_path) ? real_path : mnt[i].f_mntfromname); r["type"] = TEXT(mnt[i].f_fstypename); r["flags"] = INTEGER(mnt[i].f_flags); r["blocks"] = BIGINT(mnt[i].f_blocks); r["blocks_free"] = BIGINT(mnt[i].f_bfree); r["blocks_available"] = BIGINT(mnt[i].f_bavail); r["blocks_size"] = BIGINT(mnt[i].f_bsize); r["inodes"] = BIGINT(mnt[i].f_files); r["inodes_free"] = BIGINT(mnt[i].f_ffree); r["owner"] = INTEGER(mnt[i].f_owner); results.push_back(r); } return results; }
void genACPITable(const std::string& table, QueryData& results) { fs::path table_path = table; // There may be "categories" of tables in the form of directories. Status status; if (!fs::is_regular_file(table_path)) { std::vector<std::string> child_tables; status = osquery::listFilesInDirectory(table_path, child_tables); if (status.ok()) { for (const auto& child_table : child_tables) { genACPITable(child_table, results); } } return; } Row r; r["name"] = table_path.filename().string(); std::string table_content; status = osquery::readFile(table_path, table_content); if (!status.ok()) { r["size"] = INTEGER(-1); } else { r["size"] = INTEGER(table_content.size()); r["md5"] = osquery::hashFromBuffer( HASH_TYPE_MD5, table_content.c_str(), table_content.length()); } results.push_back(r); }
QueryData parseEtcHostsContent(const std::string& content) { QueryData results; for (const auto& i : split(content, "\n")) { auto line = split(i); if (line.size() == 0 || boost::starts_with(line[0], "#")) { continue; } Row r; r["address"] = line[0]; if (line.size() > 1) { std::vector<std::string> hostnames; for (size_t i = 1; i < line.size(); ++i) { if (boost::starts_with(line[i], "#")) { break; } hostnames.push_back(line[i]); } r["hostnames"] = boost::algorithm::join(hostnames, " "); } results.push_back(r); } return results; }
void genOSXPlistPrefValue(const pt::ptree& tree, const Row& base, unsigned int level, QueryData& results) { if (tree.empty()) { Row r = base; r["value"] = tree.data(); results.push_back(std::move(r)); // No more levels to parse. return; } for (const auto& item : tree) { Row r = base; if (r["subkey"].size() > 0) { r["subkey"] += '/'; if (item.first.size() == 0) { r["subkey"] += std::to_string(level++); } } r["subkey"] += item.first; genOSXPlistPrefValue(item.second, r, level, results); } }
QueryData genMounts(QueryContext &context) { QueryData results; FILE *mounts; struct mntent *ent; char real_path[PATH_MAX]; struct statfs st; if ((mounts = setmntent("/proc/mounts", "r"))) { while ((ent = getmntent(mounts))) { Row r; r["device"] = std::string(ent->mnt_fsname); r["device_alias"] = std::string( realpath(ent->mnt_fsname, real_path) ? real_path : ent->mnt_fsname); r["path"] = std::string(ent->mnt_dir); r["type"] = std::string(ent->mnt_type); r["flags"] = std::string(ent->mnt_opts); if (!statfs(ent->mnt_dir, &st)) { r["blocks_size"] = BIGINT(st.f_bsize); r["blocks"] = BIGINT(st.f_blocks); r["blocks_free"] = BIGINT(st.f_bfree); r["blocks_available"] = BIGINT(st.f_bavail); r["inodes"] = BIGINT(st.f_files); r["inodes_free"] = BIGINT(st.f_ffree); } results.push_back(r); } endmntent(mounts); } return results; }
void extractDebPackageInfo(const struct pkginfo *pkg, QueryData &results) { Row r; struct varbuf vb; varbuf_init(&vb, 20); // Iterate over the desired fieldinfos, calling their fwritefunctions // to extract the package's information. const struct fieldinfo *fip = nullptr; for (fip = fieldinfos; fip->name; fip++) { fip->wcall(&vb, pkg, &pkg->installed, fw_printheader, fip); std::string line = vb.string(); if (!line.empty()) { size_t separator_position = line.find(':'); std::string key = line.substr(0, separator_position); std::string value = line.substr(separator_position + 1, line.length()); auto it = kFieldMappings.find(key); if (it != kFieldMappings.end()) { boost::algorithm::trim(value); r[it->second] = std::move(value); } } varbuf_reset(&vb); } varbuf_destroy(&vb); results.push_back(r); }
QueryData parseALFServicesTree(const pt::ptree& tree) { QueryData results; pt::ptree firewall_tree; try { firewall_tree = tree.get_child("firewall"); } catch (const pt::ptree_error& e) { LOG(ERROR) << "Error retrieving firewall key: " << e.what(); } for (const auto& it : kFirewallTreeKeys) { std::string proc; int state; pt::ptree subtree; try { subtree = firewall_tree.get_child(it.first); proc = subtree.get<std::string>("proc"); state = subtree.get<int>("state"); Row r; r["service"] = it.second; r["process"] = proc; r["state"] = INTEGER(state); results.push_back(r); } catch (const pt::ptree_error& e) { LOG(ERROR) << "Error retrieving " << it.first << " keys: " << e.what(); } catch (const boost::bad_lexical_cast& e) { LOG(ERROR) << "Error casting state (" << state << "): " << e.what(); } } return results; }
QueryData parseALFExceptionsTree(const pt::ptree& tree) { QueryData results; pt::ptree exceptions_tree; try { exceptions_tree = tree.get_child("exceptions"); } catch (const pt::ptree_error& e) { LOG(ERROR) << "Error retrieving exceptions key: " << e.what(); return {}; } for (const auto& it : exceptions_tree) { std::string path; int state; try { path = it.second.get<std::string>("path"); state = it.second.get<int>("state"); Row r; r["path"] = path; r["state"] = INTEGER(state); results.push_back(r); } catch (const pt::ptree_error& e) { LOG(ERROR) << "Error retrieving firewall exception keys: " << e.what(); } catch (const boost::bad_lexical_cast& e) { LOG(ERROR) << "Error casting state (" << state << "): " << e.what(); } } return results; }
QueryData genProcessEnvs(QueryContext &context) { QueryData results; auto pidlist = getProcList(context); int argmax = genMaxArgs(); for (auto &pid : pidlist) { if (!context.constraints["pid"].matches<int>(pid)) { // Optimize by not searching when a pid is a constraint. continue; } auto env = getProcEnv(pid, argmax); for (auto env_itr = env.begin(); env_itr != env.end(); ++env_itr) { Row r; r["pid"] = INTEGER(pid); r["key"] = env_itr->first; r["value"] = env_itr->second; results.push_back(r); } } return results; }
QueryData genMemoryMap(QueryContext& context) { QueryData results; // Linux memory map is exposed in /sys. std::vector<std::string> regions; auto status = listDirectoriesInDirectory(kMemoryMapLocation, regions); if (!status.ok()) { return {}; } for (const auto& index : regions) { fs::path index_path(index); Row r; r["region"] = index_path.filename().string(); // The type is a textual description std::string content; readFile(index_path / "type", content); boost::trim(content); r["type"] = content; // Keep these in 0xFFFF (hex) form. readFile(index_path / "start", content); boost::trim(content); r["start"] = content; readFile(index_path / "end", content); boost::trim(content); r["end"] = content; results.push_back(r); } return results; }
void genFirefoxAddonsFromExtensions(const std::string& uid, const std::string& path, QueryData& results) { pt::ptree tree; if (!osquery::parseJSON(path + kFirefoxExtensionsFile, tree).ok()) { TLOG << "Could not parse JSON from: " << path + kFirefoxExtensionsFile; return; } for (const auto& addon : tree.get_child("addons")) { Row r; r["uid"] = uid; // Most of the keys are in the top-level JSON dictionary. for (const auto& it : kFirefoxAddonKeys) { r[it.second] = addon.second.get(it.first, ""); // Convert bool-types to an integer. jsonBoolAsInt(r[it.second]); } // There are several ways to disabled the addon, check each. if (addon.second.get("softDisable", "false") == "true" || addon.second.get("appDisabled", "false") == "true" || addon.second.get("userDisabled", "false") == "true") { r["disabled"] = INTEGER(1); } else { r["disabled"] = INTEGER(0); } results.push_back(r); } }
void genSMBIOSMemoryDeviceMappedAddresses(size_t index, const SMBStructHeader* hdr, uint8_t* address, size_t size, QueryData& results) { if (hdr->type != kSMBIOSTypeMemoryDeviceMappedAddress || size < 0x12) { return; } Row r; r["handle"] = dmiWordToHexStr(address, 0x02); auto addr = dmiToDWord(address, 0x04); if (addr != 0xFFFFFFFF) { r["starting_address"] = toHexStr(addr, 8); r["ending_address"] = toHexStr(dmiToDWord(address, 0x08), 8); } else { r["starting_address"] = toHexStr(dmiToQWord(address, 0x13), 12); r["ending_address"] = toHexStr(dmiToQWord(address, 0x1B), 12); } r["memory_device_handle"] = dmiWordToHexStr(address, 0x0C); r["partition_row_position"] = INTEGER(static_cast<int>(address[0x10])); r["interleave_position"] = INTEGER(static_cast<int>(address[0x11])); r["interleave_data_depth"] = INTEGER(static_cast<int>(address[0x12])); results.push_back(std::move(r)); }
void extractAptSourceInfo(pkgCache::PkgFileIterator src, const pkgIndexFile* pkgIndex, QueryData& results) { Row r; r["name"] = pkgIndex->Describe(true); // If we don't pass it a path to construct, it will // just return the base URI of the repo r["base_uri"] = pkgIndex->ArchiveURI(""); if (isFieldOkay(src.FileName())) r["package_cache_file"] = src.FileName(); if (isFieldOkay(src.Archive())) r["release"] = src.Archive(); if (isFieldOkay(src.Component())) r["component"] = src.Component(); if (isFieldOkay(src.Version())) r["version"] = src.Version(); if (isFieldOkay(src.Origin())) r["maintainer"] = src.Origin(); if (isFieldOkay(src.Label())) r["label"] = src.Label(); if (isFieldOkay(src.Site())) r["site"] = src.Site(); results.push_back(r); }
void genXProtectReport(const std::string& path, QueryData& results) { pt::ptree report; if (!osquery::parsePlist(path, report).ok()) { // Failed to read the XProtect plist format. return; } if (report.count("root") == 0) { // Unsupported/unknown report format. return; } for (const auto& entry : report.get_child("root")) { Row r; r["name"] = entry.second.get("XProtectSignatureName", ""); if (r["name"].empty()) { continue; } r["user_action"] = entry.second.get("UserAction", ""); r["time"] = entry.second.get("LSQuarantineTimeStamp", ""); results.push_back(r); } }
QueryData genOsquerySchedule(QueryContext& context) { QueryData results; Config::getInstance().scheduledQueries( [&results](const std::string& name, const ScheduledQuery& query) { Row r; r["name"] = TEXT(name); r["query"] = TEXT(query.query); r["interval"] = INTEGER(query.interval); // Set default (0) values for each query if it has not yet executed. r["executions"] = "0"; r["output_size"] = "0"; r["wall_time"] = "0"; r["user_time"] = "0"; r["system_time"] = "0"; r["average_memory"] = "0"; r["last_executed"] = "0"; // Report optional performance information. Config::getInstance().getPerformanceStats( name, [&r](const QueryPerformance& perf) { r["executions"] = BIGINT(perf.executions); r["last_executed"] = BIGINT(perf.last_executed); r["output_size"] = BIGINT(perf.output_size); r["wall_time"] = BIGINT(perf.wall_time); r["user_time"] = BIGINT(perf.user_time); r["system_time"] = BIGINT(perf.system_time); r["average_memory"] = BIGINT(perf.average_memory); }); results.push_back(r); }); return results; }
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)); }
void genSSHkeyForHosts(const std::string& uid, const std::string& directory, QueryData& results) { // Get list of files in directory boost::filesystem::path keys_dir = directory; keys_dir /= kSSHUserKeysDir; std::vector<std::string> files_list; auto status = listFilesInDirectory(keys_dir, files_list, false); if (!status.ok()) { return; } // Go through each file for (const auto& kfile : files_list) { std::string keys_content; if (!forensicReadFile(kfile, keys_content).ok()) { // Cannot read a specific keys file. continue; } if (keys_content.find("PRIVATE KEY") != std::string::npos) { // File is private key, create record for it Row r; r["uid"] = uid; r["path"] = kfile; r["encrypted"] = INTEGER(0); // Check to see if the file is encrypted if (keys_content.find("ENCRYPTED") != std::string::npos) { r["encrypted"] = INTEGER(1); } results.push_back(r); } } }