void genFileInfo(const fs::path& path, const fs::path& parent, const std::string& pattern, QueryData& results) { #ifndef WIN32 // Must provide the path, filename, directory separate from boost path->string // helpers to match any explicit (query-parsed) predicate constraints. struct stat file_stat, link_stat; if (lstat(path.string().c_str(), &link_stat) < 0 || stat(path.string().c_str(), &file_stat)) { // Path was not real, had too may links, or could not be accessed. return; } Row r; r["path"] = path.string(); r["filename"] = path.filename().string(); r["directory"] = parent.string(); r["inode"] = BIGINT(file_stat.st_ino); r["uid"] = BIGINT(file_stat.st_uid); r["gid"] = BIGINT(file_stat.st_gid); r["mode"] = lsperms(file_stat.st_mode); r["device"] = BIGINT(file_stat.st_rdev); r["size"] = BIGINT(file_stat.st_size); r["block_size"] = INTEGER(file_stat.st_blksize); r["hard_links"] = INTEGER(file_stat.st_nlink); // Times r["atime"] = BIGINT(file_stat.st_atime); r["mtime"] = BIGINT(file_stat.st_mtime); r["ctime"] = BIGINT(file_stat.st_ctime); #if defined(__linux__) // No 'birth' or create time in Linux. r["btime"] = "0"; #else r["btime"] = BIGINT(file_stat.st_birthtimespec.tv_sec); #endif // Type booleans boost::system::error_code ec; auto status = fs::status(path, ec); if (kTypeNames.count(status.type())) { r["type"] = kTypeNames.at(status.type()); } else { r["type"] = "unknown"; } r["is_file"] = (!S_ISDIR(file_stat.st_mode)) ? "1" : "0"; r["is_dir"] = (S_ISDIR(file_stat.st_mode)) ? "1" : "0"; r["is_link"] = (S_ISLNK(link_stat.st_mode)) ? "1" : "0"; r["is_char"] = (S_ISCHR(file_stat.st_mode)) ? "1" : "0"; r["is_block"] = (S_ISBLK(file_stat.st_mode)) ? "1" : "0"; results.push_back(r); #endif }
QueryData genSharedMemory(QueryContext &context) { QueryData results; // Use shared memory control (shmctl) to get the max SHMID. struct shm_info shm_info; int maxid = shmctl(0, SHM_INFO, (struct shmid_ds *)(void *)&shm_info); if (maxid < 0) { VLOG(1) << "Linux kernel not configured for shared memory"; return {}; } // Use a static pointer to access IPC permissions structure. struct shmid_ds shmseg; struct ipc_perm *ipcp = &shmseg.shm_perm; // Then iterate each shared memory ID up to the max. for (int id = 0; id <= maxid; id++) { int shmid = shmctl(id, SHM_STAT, &shmseg); if (shmid < 0) { continue; } Row r; r["shmid"] = INTEGER(shmid); struct passwd *pw = getpwuid(shmseg.shm_perm.uid); if (pw != nullptr) { r["owner_uid"] = BIGINT(pw->pw_uid); } pw = getpwuid(shmseg.shm_perm.cuid); if (pw != nullptr) { r["creator_uid"] = BIGINT(pw->pw_uid); } // Accessor, creator pids. r["pid"] = BIGINT(shmseg.shm_lpid); r["creator_pid"] = BIGINT(shmseg.shm_cpid); // Access, detached, creator times r["atime"] = BIGINT(shmseg.shm_atime); r["dtime"] = BIGINT(shmseg.shm_dtime); r["ctime"] = BIGINT(shmseg.shm_ctime); r["permissions"] = lsperms(ipcp->mode); r["size"] = BIGINT(shmseg.shm_segsz); r["attached"] = INTEGER(shmseg.shm_nattch); r["status"] = (ipcp->mode & SHM_DEST) ? "dest" : ""; r["locked"] = (ipcp->mode & SHM_LOCKED) ? "1" : "0"; results.push_back(r); } return results; }
void genFileInfo(const std::string& path, const std::string& filename, const std::string& dir, const std::string& pattern, QueryData& results) { // Must provide the path, filename, directory separate from boost path->string // helpers to match any explicit (query-parsed) predicate constraints. struct stat file_stat, link_stat; if (lstat(path.c_str(), &link_stat) < 0 || stat(path.c_str(), &file_stat)) { // Path was not real, had too may links, or could not be accessed. return; } Row r; r["path"] = path; r["filename"] = filename; r["directory"] = dir; r["inode"] = BIGINT(file_stat.st_ino); r["uid"] = BIGINT(file_stat.st_uid); r["gid"] = BIGINT(file_stat.st_gid); r["mode"] = lsperms(file_stat.st_mode); r["device"] = BIGINT(file_stat.st_rdev); r["size"] = BIGINT(file_stat.st_size); r["block_size"] = INTEGER(file_stat.st_blksize); r["hard_links"] = INTEGER(file_stat.st_nlink); // Times r["atime"] = BIGINT(file_stat.st_atime); r["mtime"] = BIGINT(file_stat.st_mtime); r["ctime"] = BIGINT(file_stat.st_ctime); // Type booleans r["is_file"] = (!S_ISDIR(file_stat.st_mode)) ? "1" : "0"; r["is_dir"] = (S_ISDIR(file_stat.st_mode)) ? "1" : "0"; r["is_link"] = (S_ISLNK(link_stat.st_mode)) ? "1" : "0"; r["is_char"] = (S_ISCHR(file_stat.st_mode)) ? "1" : "0"; r["is_block"] = (S_ISBLK(file_stat.st_mode)) ? "1" : "0"; // pattern r["pattern"] = pattern; results.push_back(r); }
QueryData genRpmPackageFiles(QueryContext& context) { QueryData results; if (rpmReadConfigFiles(nullptr, nullptr) != 0) { TLOG << "Cannot read RPM configuration files."; return results; } rpmts ts = rpmtsCreate(); rpmdbMatchIterator matches; if (context.constraints["package"].exists()) { 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); auto file_count = rpmfiFC(fi); if (file_count <= 0 || file_count > MAX_RPM_FILES) { // This package contains no or too many 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; r["package"] = getRpmAttribute(header, RPMTAG_NAME, td); auto path = rpmfiFN(fi); 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)); #ifdef CENTOS_CENTOS6 // Older versions of rpmlib/rpmip use a hash algorithm enum. pgpHashAlgo digest_algo; #else int digest_algo; #endif auto digest = rpmfiFDigestHex(fi, &digest_algo); if (digest_algo == PGPHASHALGO_SHA256) { r["sha256"] = (digest != nullptr) ? digest : ""; } results.push_back(r); } rpmfiFree(fi); rpmtdFree(td); } rpmdbFreeIterator(matches); rpmtsFree(ts); rpmFreeRpmrc(); return results; }
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(); }