QueryData genRpmPackages(QueryContext& context) { QueryData results; auto dropper = DropPrivileges::get(); if (!dropper->dropTo("nobody") && isUserAdmin()) { LOG(WARNING) << "Cannot drop privileges for rpm_packages"; return results; } // Isolate RPM/package inspection to the canonical: /usr/lib/rpm. RpmEnvironmentManager env_manager; // The following implementation uses http://rpm.org/api/4.11.1/ rpmInitCrypto(); if (rpmReadConfigFiles(nullptr, nullptr) != 0) { TLOG << "Cannot read RPM configuration files"; return results; } rpmts ts = rpmtsCreate(); rpmdbMatchIterator matches; if (context.constraints["name"].exists(EQUALS)) { auto name = (*context.constraints["name"].getAll(EQUALS).begin()); matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size()); } else { matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0); } Header header; while ((header = rpmdbNextIterator(matches)) != nullptr) { Row r; rpmtd td = rpmtdNew(); r["name"] = getRpmAttribute(header, RPMTAG_NAME, td); r["version"] = getRpmAttribute(header, RPMTAG_VERSION, td); r["release"] = getRpmAttribute(header, RPMTAG_RELEASE, td); r["source"] = getRpmAttribute(header, RPMTAG_SOURCERPM, td); r["size"] = getRpmAttribute(header, RPMTAG_SIZE, td); r["sha1"] = getRpmAttribute(header, RPMTAG_SHA1HEADER, td); r["arch"] = getRpmAttribute(header, RPMTAG_ARCH, td); rpmtdFree(td); results.push_back(r); } rpmdbFreeIterator(matches); rpmtsFree(ts); rpmFreeCrypto(); rpmFreeRpmrc(); return results; }
QueryData genOSXDefaultPreferences(QueryContext& context) { QueryData results; CFStringRef username = nullptr; if (context.constraints["username"].exists(EQUALS)) { auto users = context.constraints["username"].getAll(EQUALS); username = CFStringCreateWithCString( kCFAllocatorDefault, (*users.begin()).c_str(), kCFStringEncodingUTF8); } const auto* user = (username != nullptr) ? &username : (isUserAdmin()) ? &kCFPreferencesAnyUser : &kCFPreferencesCurrentUser; // Need lambda to iterate the map. auto preferencesIterator = ([&results, &username](CFMutableArrayRef& am, bool current_host) { for (CFIndex i = 0; i < CFArrayGetCount(am); ++i) { auto domain = static_cast<CFStringRef>(CFArrayGetValueAtIndex(am, i)); genOSXDomainPrefs(username, domain, current_host, results); } }); CFMutableArrayRef app_map = nullptr; if (context.constraints["domain"].exists(EQUALS)) { // If a specific domain is requested, speed up the set of type conversions. auto domains = context.constraints["domain"].getAll(EQUALS); app_map = CFArrayCreateMutable( kCFAllocatorDefault, domains.size(), &kCFTypeArrayCallBacks); for (const auto& domain : domains) { auto cf_domain = CFStringCreateWithCString( kCFAllocatorDefault, domain.c_str(), kCFStringEncodingASCII); CFArrayAppendValue(app_map, cf_domain); CFRelease(cf_domain); } // Iterate over each preference domain (applicationID). preferencesIterator(app_map, true); preferencesIterator(app_map, false); CFRelease(app_map); } else { // Listing ALL application preferences is deprecated. OSQUERY_USE_DEPRECATED( app_map = (CFMutableArrayRef)CFPreferencesCopyApplicationList( *user, kCFPreferencesCurrentHost)); if (app_map != nullptr) { // Iterate over each preference domain (applicationID). preferencesIterator(app_map, true); CFRelease(app_map); } // Again for 'any' host. OSQUERY_USE_DEPRECATED( app_map = (CFMutableArrayRef)CFPreferencesCopyApplicationList( *user, kCFPreferencesAnyHost)); if (app_map != nullptr) { // Iterate over each preference domain (applicationID). preferencesIterator(app_map, false); CFRelease(app_map); } } if (username != nullptr) { CFRelease(username); } return results; }
void genOSXDomainPrefs(const CFStringRef& username, const CFStringRef& domain, bool current_host, QueryData& results) { const auto* user = (username != nullptr) ? &username : (isUserAdmin()) ? &kCFPreferencesAnyUser : &kCFPreferencesCurrentUser; const auto* host = (current_host) ? &kCFPreferencesCurrentHost : &kCFPreferencesAnyHost; auto keys = CFPreferencesCopyKeyList(domain, *user, *host); if (keys == nullptr) { return; } auto values = CFPreferencesCopyMultiple(keys, domain, *user, *host); if (values == nullptr) { CFRelease(keys); return; } std::string username_string; if (username != nullptr) { username_string = stringFromCFString(username); } // Iterate over each preference domain's preference name. for (CFIndex j = 0; j < CFArrayGetCount(keys); ++j) { Row r; r["username"] = username_string; r["host"] = (current_host) ? "current" : "any"; r["domain"] = stringFromCFString(domain); auto key = static_cast<CFStringRef>(CFArrayGetValueAtIndex(keys, j)); if (CFStringGetTypeID() != CFGetTypeID(key)) { continue; } // Interesting results/behavior from Microsoft products. r["key"] = stringFromCFString(key); if (r.at("key").find('>') != std::string::npos || r.at("key").find('<') != std::string::npos || r.at("key").size() == 0) { continue; } // Check if the preference key is managed by a profile. auto forced = CFPreferencesAppValueIsForced(key, domain); r["forced"] = (forced) ? '1' : '0'; CFTypeRef value = nullptr; if (forced) { value = static_cast<CFTypeRef>(CFPreferencesCopyAppValue(key, domain)); } else { // Check the key and key type (which may be any CF type). value = static_cast<CFTypeRef>(CFDictionaryGetValue(values, key)); } genOSXPrefValues(value, r, results, 0); if (forced) { CFRelease(value); } } CFRelease(values); CFRelease(keys); }
void genRpmPackageFiles(RowYield& yield, QueryContext& context) { auto dropper = DropPrivileges::get(); if (!dropper->dropTo("nobody") && isUserAdmin()) { LOG(WARNING) << "Cannot drop privileges for rpm_package_files"; return; } // Isolate RPM/package inspection to the canonical: /usr/lib/rpm. RpmEnvironmentManager env_manager; if (rpmReadConfigFiles(nullptr, nullptr) != 0) { TLOG << "Cannot read RPM configuration files"; return; } rpmts ts = rpmtsCreate(); rpmdbMatchIterator matches; if (context.constraints["package"].exists(EQUALS)) { auto name = (*context.constraints["package"].getAll(EQUALS).begin()); matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size()); } else { matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0); } Header header; while ((header = rpmdbNextIterator(matches)) != nullptr) { rpmtd td = rpmtdNew(); rpmfi fi = rpmfiNew(ts, header, RPMTAG_BASENAMES, RPMFI_NOHEADER); std::string package_name = getRpmAttribute(header, RPMTAG_NAME, td); auto file_count = rpmfiFC(fi); if (file_count <= 0) { VLOG(1) << "RPM package " << package_name << " contains 0 files"; rpmfiFree(fi); continue; } else if (file_count > MAX_RPM_FILES) { VLOG(1) << "RPM package " << package_name << " contains over " << MAX_RPM_FILES << " files"; rpmfiFree(fi); continue; } // Iterate over every file in this package. for (size_t i = 0; rpmfiNext(fi) >= 0 && i < file_count; i++) { Row r; auto path = rpmfiFN(fi); r["package"] = package_name; r["path"] = (path != nullptr) ? path : ""; auto username = rpmfiFUser(fi); r["username"] = (username != nullptr) ? username : ""; auto groupname = rpmfiFGroup(fi); r["groupname"] = (groupname != nullptr) ? groupname : ""; r["mode"] = lsperms(rpmfiFMode(fi)); r["size"] = BIGINT(rpmfiFSize(fi)); int digest_algo; auto digest = rpmfiFDigestHex(fi, &digest_algo); if (digest_algo == PGPHASHALGO_SHA256) { r["sha256"] = (digest != nullptr) ? digest : ""; } yield(r); } rpmfiFree(fi); rpmtdFree(td); } rpmdbFreeIterator(matches); rpmtsFree(ts); rpmFreeRpmrc(); }