# limitations under the License
ADD_OSQUERY_LIBRARY(osquery_core tables.cpp
- init.cpp
query.cpp
- system.cpp
database/database.cpp
database/in_memory_database.cpp
plugins/logger.cpp
plugins/plugin.cpp
plugins/sql.cpp
- posix/initializer.cpp
sql/column.cpp
sql/diff_results.cpp
sql/query_data.cpp
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <chrono>
-#include <iostream>
-#include <random>
-#include <thread>
-
-#include <stdio.h>
-#include <time.h>
-
-#include <osquery/system.h>
-
-#ifdef WIN32
-
-#include <osquery/utils/system/system.h>
-
-#include <WbemIdl.h>
-#include <signal.h>
-
-#else
-#include <unistd.h>
-#endif
-
-#ifndef WIN32
-#include <sys/resource.h>
-#endif
-
-#include <boost/filesystem.hpp>
-
-#include "osquery/utils/config/default_paths.h"
-#include "osquery/utils/info/platform_type.h"
-#include <osquery/core.h>
-#include <osquery/data_logger.h>
-#include <osquery/registry.h>
-#include <osquery/utils/info/version.h>
-#include <osquery/utils/system/time.h>
-
-#ifdef __linux__
-#include <sys/syscall.h>
-
-/*
- * These are the io priority groups as implemented by CFQ. RT is the realtime
- * class, it always gets premium service. BE is the best-effort scheduling
- * class, the default for any process. IDLE is the idle scheduling class, it
- * is only served when no one else is using the disk.
- */
-enum {
- IOPRIO_CLASS_NONE,
- IOPRIO_CLASS_RT,
- IOPRIO_CLASS_BE,
- IOPRIO_CLASS_IDLE,
-};
-
-/*
- * 8 best effort priority levels are supported
- */
-#define IOPRIO_BE_NR (8)
-
-enum {
- IOPRIO_WHO_PROCESS = 1,
- IOPRIO_WHO_PGRP,
- IOPRIO_WHO_USER,
-};
-#endif
-
-#define DESCRIPTION \
- "osquery %s, your OS as a high-performance relational database\n"
-#define EPILOG "\nosquery project page <https://osquery.io>.\n"
-#define OPTIONS \
- "\nosquery configuration options (set by config or CLI flags):\n\n"
-#define OPTIONS_SHELL "\nosquery shell-only CLI flags:\n\n"
-#define OPTIONS_CLI "osquery%s command line flags:\n\n"
-#define USAGE "Usage: %s [OPTION]... %s\n\n"
-
-namespace {
-extern "C" {
-volatile std::sig_atomic_t kHandledSignal{0};
-
-void signalHandler(int num) {
- // Inform exit status of main threads blocked by service joins.
- if (kHandledSignal == 0) {
- kHandledSignal = num;
- // If no part of osquery requested an interruption then the exit 'wanted'
- // code becomes the signal number.
- if (num != SIGUSR1 && osquery::kExitCode == 0) {
- // The only exception is SIGUSR1 which is used to signal the main thread
- // to interrupt dispatched services.
- osquery::kExitCode = 128 + num;
- }
-
- if (num == SIGTERM || num == SIGINT || num == SIGABRT ||
- num == SIGUSR1) {
- // Restore the default signal handler.
- std::signal(num, SIG_DFL);
- }
- }
-}
-}
-}
-
-using chrono_clock = std::chrono::high_resolution_clock;
-
-namespace fs = boost::filesystem;
-
-namespace osquery {
-
-ToolType kToolType{ToolType::UNKNOWN};
-
-/// The saved exit code from a thread's request to stop the process.
-volatile std::sig_atomic_t kExitCode{0};
-
-/// The saved thread ID for shutdown to short-circuit raising a signal.
-static std::thread::id kMainThreadId;
-
-/// Legacy thread ID to ensure that the windows service waits before exiting
-unsigned long kLegacyThreadId;
-
-std::function<void()> Initializer::shutdown_{nullptr};
-RecursiveMutex Initializer::shutdown_mutex_;
-
-static inline void printUsage(const std::string& binary, ToolType tool) {
- // Parse help options before gflags. Only display osquery-related options.
- fprintf(stdout, DESCRIPTION, kVersion.c_str());
- if (tool == ToolType::SHELL) {
- // The shell allows a caller to run a single SQL statement and exit.
- fprintf(stdout, USAGE, binary.c_str(), "[SQL STATEMENT]");
- } else {
- fprintf(stdout, USAGE, binary.c_str(), "");
- }
-
- fprintf(stdout, EPILOG);
-}
-
-Initializer::Initializer(int& argc,
- char**& argv,
- ToolType tool,
- bool const init_glog)
- : argc_(&argc), argv_(&argv) {
- // Initialize random number generated based on time.
- std::srand(static_cast<unsigned int>(
- chrono_clock::now().time_since_epoch().count()));
-
- // osquery can function as the daemon or shell depending on argv[0].
- if (tool == ToolType::SHELL_DAEMON) {
- if (fs::path(argv[0]).filename().string().find("osqueryd") !=
- std::string::npos) {
- kToolType = ToolType::DAEMON;
- binary_ = "osqueryd";
- } else {
- kToolType = ToolType::SHELL;
- binary_ = "osqueryi";
- }
- } else {
- // Set the tool type to allow runtime decisions based on daemon, shell, etc.
- kToolType = tool;
- }
-
- // The 'main' thread is that which executes the initializer.
- kMainThreadId = std::this_thread::get_id();
-
- // Initialize the COM libs
- platformSetup();
-}
-
-void Initializer::initDaemon() const {
-}
-
-void Initializer::initShell() const {
-}
-
-void Initializer::initWorker(const std::string& name) const {
- // Clear worker's arguments.
- auto original_name = std::string((*argv_)[0]);
- for (int i = 1; i < *argc_; i++) {
- if ((*argv_)[i] != nullptr) {
- memset((*argv_)[i], '\0', strlen((*argv_)[i]));
- }
- }
-}
-
-void Initializer::initActivePlugin(const std::string& type,
- const std::string& name) const {
- auto rs = RegistryFactory::get().setActive(type, name);
- if (!rs.ok()) {
- LOG(ERROR) << "Cannot activate " << name << " " << type
- << " plugin: " << rs.getMessage();
- requestShutdown(EXIT_CATASTROPHIC);
- }
-}
-
-void Initializer::installShutdown(std::function<void()>& handler) {
- RecursiveLock lock(shutdown_mutex_);
- shutdown_ = std::move(handler);
-}
-
-void Initializer::start() const {
- // Run the setup for all lazy registries (tables, SQL).
- Registry::setUp();
-}
-
-void Initializer::waitForShutdown() {
- {
- RecursiveLock lock(shutdown_mutex_);
- if (shutdown_ != nullptr) {
- // Copy the callable, then remove it, prevent callable recursion.
- auto shutdown = shutdown_;
- shutdown_ = nullptr;
-
- // Call the shutdown callable.
- shutdown();
- }
- }
-
- auto excode = (kExitCode != 0) ? kExitCode : EXIT_SUCCESS;
- exit(excode);
-}
-
-void Initializer::requestShutdown(int retcode) {
- if (kExitCode == 0) {
- kExitCode = retcode;
- }
-}
-
-void Initializer::requestShutdown(int retcode, const std::string& system_log) {
- requestShutdown(retcode);
-}
-
-void Initializer::shutdown(int retcode) {
- platformTeardown();
- ::exit(retcode);
-}
-}
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <osquery/system.h>
-
-namespace osquery {
-
-void Initializer::platformSetup() {
- /* No platform-specific logic is needed on POSIX. */
-}
-
-void Initializer::platformTeardown() {
- /* No platform-specific logic is needed on POSIX. */
-}
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#ifndef WIN32
-#include <grp.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#endif
-
-#include <signal.h>
-
-#if !defined(__FreeBSD__) && !defined(WIN32)
-#include <sys/syscall.h>
-#include <uuid/uuid.h>
-#endif
-
-#ifdef WIN32
-#include <WinSock2.h>
-#endif
-
-#if defined(__FreeBSD__)
-#include <pthread_np.h>
-#endif
-
-#if defined(__APPLE__)
-#include <sys/kauth.h>
-#endif
-
-#include <sstream>
-
-#include <boost/algorithm/string/case_conv.hpp>
-#include <boost/algorithm/string/trim.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/uuid/uuid.hpp>
-#include <boost/uuid/uuid_generators.hpp>
-#include <boost/uuid/uuid_io.hpp>
-
-#include <osquery/core.h>
-#include <osquery/logger.h>
-#include <osquery/sql.h>
-#include <osquery/system.h>
-
-#ifdef WIN32
-#include "osquery/core/windows/wmi.h"
-#endif
-#include "osquery/utils/info/tool_type.h"
-#include "osquery/utils/info/platform_type.h"
-#include "osquery/utils/conversions/tryto.h"
-#include "osquery/utils/config/default_paths.h"
-#ifdef WIN32
-#include <osquery/utils/conversions/windows/strings.h>
-#endif
-
-namespace fs = boost::filesystem;
-
-namespace osquery {
-
-const std::vector<std::string> kPlaceholderHardwareUUIDList{
- "00000000-0000-0000-0000-000000000000",
- "03000200-0400-0500-0006-000700080009",
- "03020100-0504-0706-0809-0a0b0c0d0e0f",
- "10000000-0000-8000-0040-000000000000",
-};
-
-#ifdef WIN32
-struct tm* gmtime_r(time_t* t, struct tm* result) {
- _gmtime64_s(result, t);
- return result;
-}
-
-struct tm* localtime_r(time_t* t, struct tm* result) {
- _localtime64_s(result, t);
- return result;
-}
-#endif
-
-std::string getHostname() {
- long max_path = 256;
- long size = 0;
-#ifndef WIN32
- static long max_hostname = sysconf(_SC_HOST_NAME_MAX);
- size = (max_hostname > max_path - 1) ? max_hostname + 1 : max_path;
-#endif
- if (isPlatform(PlatformType::TYPE_WINDOWS)) {
- size = max_path;
- }
-
- std::vector<char> hostname(size, 0x0);
- std::string hostname_string;
- gethostname(hostname.data(), size - 1);
- hostname_string = std::string(hostname.data());
- boost::algorithm::trim(hostname_string);
- return hostname_string;
-}
-
-std::string getFqdn() {
- if (!isPlatform(PlatformType::TYPE_WINDOWS)) {
- std::string fqdn_string = getHostname();
-
-#ifndef WIN32
- struct addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_flags = AI_CANONNAME;
-
- struct addrinfo* res = nullptr;
- if (getaddrinfo(fqdn_string.c_str(), nullptr, &hints, &res) == 0) {
- if (res->ai_canonname != nullptr) {
- fqdn_string = res->ai_canonname;
- }
- }
- if (res != nullptr) {
- freeaddrinfo(res);
- }
-#endif
- return fqdn_string;
- } else {
- unsigned long size = 256;
- std::vector<char> fqdn(size, 0x0);
-#ifdef WIN32
- GetComputerNameEx(ComputerNameDnsFullyQualified, fqdn.data(), &size);
-#endif
- return fqdn.data();
- }
-}
-
-std::string generateNewUUID() {
- boost::uuids::uuid uuid = boost::uuids::random_generator()();
- return boost::uuids::to_string(uuid);
-}
-
-bool isPlaceholderHardwareUUID(const std::string& uuid) {
- std::string lower_uuid = boost::to_lower_copy(uuid);
-
- return std::find(kPlaceholderHardwareUUIDList.begin(),
- kPlaceholderHardwareUUIDList.end(),
- lower_uuid) != kPlaceholderHardwareUUIDList.end();
-}
-
-std::string generateHostUUID() {
- return "Not supported";
-}
-
-Status getInstanceUUID(std::string& ident) {
- ident = osquery::generateNewUUID();
-
- return Status(-1, "Not supported");
-}
-
-Status getEphemeralUUID(std::string& ident) {
- if (ident.size() == 0) {
- ident = osquery::generateNewUUID();
- }
- return Status::success();
-}
-
-Status getHostUUID(std::string& ident) {
- return Status(-1, "Not supported");
-}
-
-Status getSpecifiedUUID(std::string& ident) {
- return Status::success();
-}
-
-std::string getHostIdentifier() {
- static std::string ident;
-
- Status result(2);
- if (ident.size() == 0) {
- // The identifier has not been set yet.
-
- if (!result.ok()) {
- // assuming the default of "hostname" as the machine identifier
- // intentionally not set to `ident` because the hostname may change
- // throughout the life of the process and we always want to be using the
- // most current hostname
- return osquery::getHostname();
- } else {
- VLOG(1) << "Using host identifier: " << ident;
- }
- }
- return ident;
-}
-
-Status checkStalePid(const std::string& content) {
- int pid;
- try {
- pid = boost::lexical_cast<int>(content);
- } catch (const boost::bad_lexical_cast& /* e */) {
- return Status::success();
- }
-
- // The pid is running, check if it is an osqueryd process by name.
- std::stringstream query_text;
-
- query_text << "SELECT name FROM processes WHERE pid = " << pid
- << " AND name LIKE 'osqueryd%';";
-
- SQL q(query_text.str());
- if (!q.ok()) {
- return Status(1, "Error querying processes: " + q.getMessageString());
- }
-
- if (q.rows().size() > 0) {
- // If the process really is osqueryd, return an "error" status.
-
- return Status(1, "osqueryd (" + content + ") is already running");
- } else {
- VLOG(1) << "Found stale process for osqueryd (" << content << ")";
- }
-
- return Status::success();
-}
-
-#ifndef WIN32
-
-static inline bool ownerFromResult(const Row& row, long& uid, long& gid) {
- auto const uid_exp = tryTo<long>(row.at("uid"), 10);
- auto const gid_exp = tryTo<long>(row.at("gid"), 10);
- if (uid_exp.isValue()) {
- uid = uid_exp.get();
- }
- if (gid_exp.isValue()) {
- gid = gid_exp.get();
- }
- return uid_exp.isValue() && gid_exp.isValue();
-}
-
-DropPrivilegesRef DropPrivileges::get() {
- DropPrivilegesRef handle = DropPrivilegesRef(new DropPrivileges());
- return handle;
-}
-
-bool DropPrivileges::dropToParent(const fs::path& path) {
- auto parent = path.parent_path().string();
- auto result = SQL::selectAllFrom("file", "path", EQUALS, parent);
- if (result.empty()) {
- return false;
- }
-
- if (result.front().at("symlink") == "1") {
- // The file is a symlink, inspect the owner of the link.
- struct stat link_stat;
- if (lstat(parent.c_str(), &link_stat) != 0) {
- return false;
- }
-
- return dropTo(link_stat.st_uid, link_stat.st_gid);
- }
-
- long uid = 0;
- long gid = 0;
- if (!ownerFromResult(result.front(), uid, gid)) {
- return false;
- }
-
- return dropTo(static_cast<uid_t>(uid), static_cast<gid_t>(gid));
-}
-
-bool DropPrivileges::dropTo(const std::string& user) {
- auto result = SQL::selectAllFrom("users", "username", EQUALS, user);
- if (result.empty()) {
- return false;
- }
-
- long uid = 0;
- long gid = 0;
- if (!ownerFromResult(result.front(), uid, gid)) {
- return false;
- }
-
- return dropTo(static_cast<uid_t>(uid), static_cast<gid_t>(gid));
-}
-
-bool setThreadEffective(uid_t uid, gid_t gid) {
-#if defined(__APPLE__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated"
- return (pthread_setugid_np(uid, gid) == 0);
-#pragma GCC diagnostic pop
-#elif defined(__linux__)
- return (syscall(SYS_setresgid, -1, gid, -1) == 0 &&
- syscall(SYS_setresuid, -1, uid, -1) == 0);
-#endif
- return 0;
-}
-
-bool DropPrivileges::dropTo(const std::string& uid, const std::string& gid) {
- auto const uid_exp = tryTo<uid_t>(uid, 10);
- auto const gid_exp = tryTo<gid_t>(gid, 10);
- if (uid_exp.isError() || gid_exp.isError() ||
- !dropTo(uid_exp.get(), gid_exp.get())) {
- return false;
- }
- return true;
-}
-
-bool DropPrivileges::dropTo(uid_t uid, gid_t gid) {
- if (uid == geteuid() && gid == getegid()) {
- // Privileges do not need to be dropped.
- return true;
- } else if (dropped() && uid == to_user_ && gid == to_group_) {
- // Privileges are already dropped to the requested user and group.
- return true;
- } else if (dropped()) {
- return false;
- }
-
- /// Drop process groups.
- if (original_groups_ != nullptr) {
- restoreGroups();
- }
-
- group_size_ = getgroups(0, nullptr);
- if (group_size_ > 0) {
- original_groups_ = (gid_t*)malloc(group_size_ * sizeof(gid_t));
- group_size_ = getgroups(group_size_, original_groups_);
- }
- setgroups(1, &gid);
-
- if (!setThreadEffective(uid, gid)) {
- (void)setegid(getgid());
- return false;
- }
-
- // Privileges are now dropped to the requested user/group.
- to_user_ = uid;
- to_group_ = gid;
- dropped_ = true;
- return true;
-}
-
-void DropPrivileges::restoreGroups() {
- if (group_size_ > 0) {
- setgroups(group_size_, original_groups_);
- group_size_ = 0;
- free(original_groups_);
- }
- original_groups_ = nullptr;
-}
-
-DropPrivileges::~DropPrivileges() {
- // We are elevating privileges, there is no security vulnerability if
- // either privilege change fails.
- if (dropped_) {
-#ifdef __APPLE__
- setThreadEffective(KAUTH_UID_NONE, KAUTH_GID_NONE);
-#else
- setThreadEffective(getuid(), getgid());
-#endif
- dropped_ = false;
- }
-
- if (original_groups_ != nullptr) {
- restoreGroups();
- }
-}
-#endif
-
-Status setThreadName(const std::string& name) {
-#if defined(__APPLE__)
- int return_code = pthread_setname_np(name.c_str());
- return return_code == 0
- ? Status::success()
- : Status::failure("pthread_setname_np failed with error " +
- std::to_string(return_code));
-#elif defined(__linux__)
- int return_code = pthread_setname_np(pthread_self(), name.c_str());
- return return_code == 0
- ? Status::success()
- : Status::failure("pthread_setname_np failed with error " +
- std::to_string(return_code));
-#elif defined(__FreeBSD__)
- // FreeBSD silently ignores errors and does not return an error code
- pthread_set_name_np(pthread_self(), name.c_str());
- return Status::success();
-#elif defined(WIN32)
- // SetThreadDescription is available in builds newer than 1607 of windows 10
- // and works even if there is no debugger.
- typedef HRESULT(WINAPI * PFNSetThreadDescription)(HANDLE hThread,
- PCWSTR lpThreadDescription);
- auto pfnSetThreadDescription = reinterpret_cast<PFNSetThreadDescription>(
- GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetThreadDescription"));
- if (pfnSetThreadDescription != nullptr) {
- std::wstring wideName{stringToWstring(name)};
- HRESULT hr = pfnSetThreadDescription(GetCurrentThread(), wideName.c_str());
- if (!FAILED(hr)) {
- return Status::success();
- }
- }
- return Status::failure(
- "setThreadName failed due to GetProcAddress returning null");
-#else
- return Status::failure("setThreadName not supported on this OS");
-#endif
-}
-
-bool checkPlatform(const std::string& platform) {
- if (platform.empty() || platform == "null") {
- return true;
- }
-
- if (platform.find("any") != std::string::npos ||
- platform.find("all") != std::string::npos) {
- return true;
- }
-
- // Technically "centos" and "ubuntu" are no longer supported. We have never
- // differentiated between Linux distributions, but rather execute all Linux
- // based queries on any Linux system.
- auto linux_type = (platform.find("linux") != std::string::npos ||
- platform.find("ubuntu") != std::string::npos ||
- platform.find("centos") != std::string::npos);
- if (linux_type && isPlatform(osquery::PlatformType::TYPE_LINUX)) {
- return true;
- }
-
- auto posix_type = (platform.find("posix") != std::string::npos);
- if (posix_type && isPlatform(osquery::PlatformType::TYPE_POSIX)) {
- return true;
- }
-
- return (platform.find(osquery::kSDKPlatform) != std::string::npos);
-}
-} // namespace osquery
#include <osquery/query.h>
#include <osquery/sql/tests/sql_test_utils.h>
-#include <osquery/system.h>
#include <osquery/tests/test_util.h>
namespace osquery {
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <gtest/gtest.h>
-
-#include "osquery/system.h"
-
-namespace osquery {
-
-class UUIDTests : public testing::Test {};
-
-TEST_F(UUIDTests, test_invalid_uuid) {
- std::string uuid = "10000000-0000-8000-0040-000000000000";
-
- EXPECT_TRUE(isPlaceholderHardwareUUID(uuid));
-}
-
-TEST_F(UUIDTests, test_valid_uuid) {
- std::string uuid = "226e380e-67d1-4214-9868-5383a79af0b8";
-
- EXPECT_FALSE(isPlaceholderHardwareUUID(uuid));
-}
-
-} // namespace osquery
#include <osquery/database.h>
#include <osquery/registry.h>
-#include <osquery/system.h>
#include <osquery/tables.h>
namespace osquery {
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#include <csignal>
-#include <mutex>
-#include <string>
-
-#include <boost/core/noncopyable.hpp>
-
-#include <osquery/core.h>
-#include <osquery/utils/mutex.h>
-#include <osquery/utils/system/system.h>
-#include <osquery/utils/info/tool_type.h>
-
-namespace osquery {
-
-class Status;
-
-/**
- * @brief The requested exit code.
- *
- * Use Initializer::shutdown to request shutdown in most cases.
- * This will raise a signal to the main thread requesting the dispatcher to
- * interrupt all services. There is a thread requesting a join of all services
- * that will continue the shutdown process.
- */
-extern volatile std::sig_atomic_t kExitCode;
-
-using ModuleHandle = void*;
-
-class Initializer : private boost::noncopyable {
- public:
- /**
- * @brief Sets up various aspects of osquery execution state.
- *
- * osquery needs a few things to happen as soon as the process begins
- * executing. Initializer takes care of setting up the relevant parameters.
- * Initializer should be called in an executable's `main()` function.
- *
- * @param argc the number of elements in argv
- * @param argv the command-line arguments passed to `main()`
- * @param tool the type of osquery main (daemon, shell, test, extension).
- * @param init_glog whether to start google logging module (it can be
- * initialized at most once)
- */
- Initializer(int& argc,
- char**& argv,
- ToolType tool = ToolType::TEST,
- bool init_glog = true);
-
- /**
- * @brief Sets up the process as an osquery daemon.
- *
- * A daemon has additional constraints, it can use a process mutex, check
- * for sane/non-default configurations, etc.
- */
- void initDaemon() const;
-
- /**
- * @brief Sets up the process as an osquery shell.
- *
- * The shell is lighter than a daemon and disables (by default) features.
- */
- void initShell() const;
-
- /**
- * @brief Daemon tools may want to continually spawn worker processes
- * and monitor their utilization.
- *
- * A daemon may call initWorkerWatcher to begin watching child daemon
- * processes until it-itself is unscheduled. The basic guarantee is that only
- * workers will return from the function.
- *
- * The worker-watcher will implement performance bounds on CPU utilization
- * and memory, as well as check for zombie/defunct workers and respawn them
- * if appropriate. The appropriateness is determined from heuristics around
- * how the worker exited. Various exit states and velocities may cause the
- * watcher to resign.
- *
- * @param name The name of the worker process.
- */
- void initWorkerWatcher(const std::string& name = "") const;
-
- /**
- * @brief Move a function callable into the initializer to be called.
- *
- * Install an optional platform method to call when waiting for shutdown.
- * This exists for Windows when the daemon must wait for the service to stop.
- */
- void installShutdown(std::function<void()>& handler);
-
- /// Assume initialization finished, start work.
- void start() const;
-
- public:
- /**
- * @brief Forcefully request the application to stop.
- *
- * Since all osquery tools may implement various 'dispatched' services in the
- * form of event handler threads or thrift service and client pools, a stop
- * request should behave nicely and request these services stop.
- *
- * Use shutdown whenever you would normally call stdlib exit.
- *
- * @param retcode the requested return code for the process.
- */
- static void requestShutdown(int retcode = EXIT_SUCCESS);
-
- /**
- * @brief Forcefully request the application to stop.
- *
- * See #requestShutdown, this overloaded alternative allows the caller to
- * also log a reason/message to the system log. This is intended for extreme
- * failure cases and thus requires an explicit error code.
- *
- * @param retcode the request return code for the process.
- * @param system_log A log line to write to the system's log.
- */
- static void requestShutdown(int retcode, const std::string& system_log);
-
- /// Exit immediately without requesting the dispatcher to stop.
- static void shutdown(int retcode = EXIT_SUCCESS);
-
- /**
- * @brief Cleanly wait for all services and components to shutdown.
- *
- * Enter a join of all services followed by a sync wait for event loops.
- * If the main thread is out of actions it can call #waitForShutdown.
- */
- static void waitForShutdown();
-
- /**
- * @brief Initialize any platform dependent libraries or objects
- *
- * On windows, we require the COM libraries be initialized just once
- */
- static void platformSetup();
-
- /**
- * @brief Before ending, tear down any platform specific setup
- *
- * On windows, we require the COM libraries be initialized just once
- */
- static void platformTeardown();
-
- /// Check the program is the osquery daemon.
- static bool isDaemon() {
- return kToolType == ToolType::DAEMON;
- }
-
- /// Check the program is the osquery shell.
- static bool isShell() {
- return kToolType == ToolType::SHELL;
- }
-
- /**
- * @brief Check if a process is an osquery worker.
- *
- * By default an osqueryd process will fork/exec then set an environment
- * variable: `OSQUERY_WORKER` while continually monitoring child I/O.
- * The environment variable causes subsequent child processes to skip several
- * initialization steps and jump into extension handling, registry setup,
- * config/logger discovery and then the event publisher and scheduler.
- */
- static bool isWorker();
-
- /**
- * @brief Check is a process is an osquery watcher.
- *
- * Is watcher is different from the opposite of isWorker. An osquery process
- * may have disabled the watchdog so the parent could be doing the work or
- * the worker child.
- */
- static bool isWatcher();
-
- public:
- /// Initialize this process as an osquery daemon worker.
- void initWorker(const std::string& name) const;
-
- /// Initialize the osquery watcher, optionally spawn a worker.
- void initWatcher() const;
-
- /// This pauses the watchdog process until the watcher thread stops.
- void waitForWatcher() const;
-
- private:
- /// Set and wait for an active plugin optionally broadcasted.
- void initActivePlugin(const std::string& type, const std::string& name) const;
-
- private:
- /// A saved, mutable, reference to the process's argc.
- int* argc_{nullptr};
-
- /// A saved, mutable, reference to the process's argv.
- char*** argv_{nullptr};
-
- /// The deduced program name determined by executing path.
- std::string binary_;
-
- /// A platform specific callback to wait for shutdown.
- static std::function<void()> shutdown_;
-
- /// Mutex to protect use of the shutdown callable.
- static RecursiveMutex shutdown_mutex_;
-};
-
-/**
- * @brief Getter for a host's current hostname
- *
- * @return a string representing the host's current hostname
- */
-std::string getHostname();
-
-/**
- * @brief Getter for a host's fully qualified domain name
- *
- * @return a string representation of the hosts fully qualified domain name
- * if the host is joined to a domain, otherwise it simply returns the hostname
- */
-std::string getFqdn();
-
-/**
- * @brief Generate a new generic UUID
- *
- * @return a string containing a random UUID
- */
-std::string generateNewUUID();
-
-/**
- * @brief Getter for an instance uuid
- *
- * @return ok on success and ident is set to the instance uuid, otherwise
- * failure.
- */
-Status getInstanceUUID(std::string& ident);
-
-/**
- * @brief Getter for an ephemeral uuid
- *
- * @return ok on success and ident is set to the ephemeral uuid, otherwise
- * failure.
- */
-Status getEphemeralUUID(std::string& ident);
-
-/**
- * @brief Getter for a host's uuid.
- *
- * @return ok on success and ident is set to the host's uuid, otherwise failure.
- */
-Status getHostUUID(std::string& ident);
-
-/**
- * @brief Determine whether the UUID is a placeholder.
- *
- * Some motherboards report placeholder UUIDs which, from point of view of being
- * unique, are useless. This method checks the provided UUID against a list of
- * known placeholders so that it can be treated as invalid. This method ignores
- * case.
- *
- * @param uuid UUID to test.
- * @return true if UUID is a placeholder and false otherwise.
- */
-bool isPlaceholderHardwareUUID(const std::string& uuid);
-
-/**
- * @brief generate a uuid to uniquely identify this machine
- *
- * @return uuid string to identify this machine
- */
-std::string generateHostUUID();
-
-/**
- * @brief Get a configured UUID/name that uniquely identify this machine
- *
- * @return string to identify this machine
- */
-std::string getHostIdentifier();
-
-/**
- * @brief Create a pid file
- *
- * @return A status object indicating the success or failure of the operation
- */
-Status createPidFile();
-
-/**
- * @brief Set the name of the thread
- *
- * @return If the name was set successfully
- */
-Status setThreadName(const std::string& name);
-
-bool checkPlatform(const std::string& platform);
-} // namespace osquery
#include <osquery/data_logger.h>
#include <osquery/plugins/logger.h>
#include <osquery/registry_factory.h>
-#include <osquery/system.h>
#include <osquery/utils/conversions/split.h>
#include <osquery/utils/info/platform_type.h>
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#ifdef WIN32
-#include <io.h>
-#endif
-
-#include <iostream>
-
-#include <boost/algorithm/string/predicate.hpp>
-#include <boost/filesystem.hpp>
-
-#include <osquery/core.h>
-#include <osquery/devtools/devtools.h>
-#include <osquery/logger.h>
-#include <osquery/main/main.h>
-#include <osquery/registry_factory.h>
-#include <osquery/sql/sqlite_util.h>
-#include <osquery/system.h>
-
-//#include <osquery/experimental/tracing/syscalls_tracing.h>
-
-namespace fs = boost::filesystem;
-
-namespace osquery {
-
-int startDaemon(Initializer& runner) {
- runner.start();
-
- // Finally wait for a signal / interrupt to shutdown.
- runner.waitForShutdown();
- return 0;
-}
-
-int startShell(osquery::Initializer& runner, int argc, char* argv[]) {
- int retcode = 0;
-
- // Finally shutdown.
- runner.requestShutdown();
- return retcode;
-}
-
-int startOsquery(int argc, char* argv[], std::function<void()> shutdown) {
- // Parse/apply flags, start registry, load logger/config plugins.
- osquery::Initializer runner(argc, argv, osquery::ToolType::SHELL);
-
- runner.installShutdown(shutdown);
- runner.initDaemon();
-
- if (runner.isDaemon()) {
- return startDaemon(runner);
- }
- return startShell(runner, argc, argv);
-}
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#include <string>
-#include <functional>
-
-#include <osquery/utils/status/status.h>
-
-namespace osquery {
-
-/**
- * @brief Install osqueryd as a service for the platform.
- *
- * Currently, this is only used by Windows. POSIX platforms use a companion
- * script called osquerycrl to move files and install launch daemons or init
- * scripts/systemd units.
- *
- * This disconnect of install flows is a limitation. The POSIX install flows
- * should be refactored into install/uninstall service methods.
- */
-Status installService(const std::string& path);
-
-/// See installService.
-Status uninstallService();
-
-/// Begin the platform-agnostic shell and daemon initialization.
-int startOsquery(int argc,
- char* argv[],
- std::function<void()> shutdown = nullptr);
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <osquery/core.h>
-#include <osquery/logger.h>
-#include <osquery/main/main.h>
-#include <osquery/system.h>
-
-namespace osquery {
-
-Status installService(const std::string& /*path*/) {
- LOG(INFO) << "The --install service flag only applies to Windows platforms";
- return Status(1);
-}
-
-Status uninstallService() {
- LOG(INFO) << "The --uninstall service flag only applies to Windows platforms";
- return Status(1);
-}
-} // namespace osquery
-
-int main(int argc, char* argv[]) {
- // On POSIX systems we can jump immediately into startOsquery.
- // A short abstraction exists to allow execute-as-service checks in Windows.
- return osquery::startOsquery(argc, argv);
-}
#include <osquery/plugins/sql.h>
#include <osquery/utils/conversions/split.h>
-#include <osquery/utils/info/tool_type.h>
namespace osquery {
}
Status getQueryTables(const std::string& q, std::vector<std::string>& tables) {
- if (kToolType == ToolType::TEST) {
- // We 'mock' this functionality for internal tests.
- return mockGetQueryTables(q, tables);
- }
-
PluginResponse response;
auto status = Registry::call(
"sql", "sql", {{"action", "tables"}, {"query", q}}, response);
#include <osquery/sql.h>
#include <osquery/sql/dynamic_table_row.h>
#include <osquery/sql/tests/sql_test_utils.h>
-#include <osquery/system.h>
#include <osquery/tables.h>
namespace osquery {
class SQLTests : public testing::Test {
public:
void SetUp() override {
- Initializer::platformSetup();
registryAndPluginInit();
}
};
#include <osquery/sql.h>
#include <osquery/sql/sqlite_util.h>
#include <osquery/sql/tests/sql_test_utils.h>
-#include <osquery/system.h>
#include <osquery/utils/info/platform_type.h>
#include <gtest/gtest.h>
class SQLiteUtilTests : public testing::Test {
public:
void SetUp() override {
- Initializer::platformSetup();
registryAndPluginInit();
}
};
#include <osquery/registry.h>
#include <osquery/sql.h>
#include <osquery/sql/dynamic_table_row.h>
-#include <osquery/system.h>
#include <osquery/sql/virtual_table.h>
class VirtualTableTests : public testing::Test {
public:
void SetUp() override {
- Initializer::platformSetup();
registryAndPluginInit();
}
};
#include <osquery/registry_factory.h>
#include <osquery/sql/dynamic_table_row.h>
#include <osquery/sql/virtual_table.h>
-#include <osquery/system.h>
#include <osquery/utils/conversions/tryto.h>
#include <osquery/logger.h>
<< " is event-based but events are disabled";
}
- // Provide a helpful reference to table documentation within the shell.
- if (Initializer::isShell() &&
- (!user_based_satisfied || !required_satisfied || !events_satisfied)) {
- LOG(WARNING) << "Please see the table documentation: "
- << table_doc(pVtab->content->name);
- }
-
// Reset the virtual table contents.
pCur->rows.clear();
options.clear();
#include <osquery/utils/system/time.h>
-#include <osquery/system.h>
#include <osquery/tables.h>
namespace osquery {
#include <osquery/logger.h>
#include <osquery/registry_factory.h>
#include <osquery/sql.h>
-#include <osquery/system.h>
#include <osquery/utils/system/time.h>
#include <osquery/utils/conversions/tryto.h>
using chrono_clock = std::chrono::high_resolution_clock;
void initTesting() {
- kToolType = ToolType::TEST;
if (osquery::isPlatform(PlatformType::TYPE_OSX)) {
kTestWorkingDirectory = "/private/tmp/osquery-tests";
} else {
fs::remove_all(kTestWorkingDirectory);
fs::create_directories(kTestWorkingDirectory);
-
- Initializer::platformSetup();
}
void shutdownTesting() {
- Initializer::platformTeardown();
}
ScheduledQuery getOsqueryScheduledQuery() {
chars.cpp
only_movable.cpp
status/status.cpp
- system/system.cpp
system/time.cpp
- system/uptime.cpp
system/posix/env.cpp
system/posix/errno.cpp
system/posix/filepath.cpp
- system/posix/system.cpp
system/posix/time.cpp
info/platform_type.cpp
- info/tool_type.cpp
- info/version.cpp
config/default_paths.cpp
conversions/tryto.cpp
conversions/split.cpp
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <osquery/utils/info/tool_type.h>
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-namespace osquery {
- /**
- * @brief A helpful tool type to report when logging, print help, or debugging.
- *
- * The Initializer class attempts to detect the ToolType using the tool name
- * and some compile time options.
- */
- enum class ToolType {
- UNKNOWN = 0,
- SHELL,
- DAEMON,
- TEST,
- EXTENSION,
- SHELL_DAEMON,
- };
-
- /// The osquery tool type for runtime decisions.
- extern ToolType kToolType;
-}
#include <osquery/utils/only_movable.h>
#include <osquery/utils/status/status.h>
-#include <osquery/utils/system/system.h>
#ifdef WIN32
#pragma warning(push, 3)
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include "system.h"
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#include <ctime>
-#include <memory>
-#include <string>
-
-#include <boost/filesystem/path.hpp>
-#include <boost/core/noncopyable.hpp>
-#include <gtest/gtest_prod.h>
-#include <osquery/utils/info/tool_type.h>
-
-namespace osquery {
-
-/// The osquery platform agnostic process identifier type.
-using PlatformPidType = pid_t;
-
-class DropPrivileges;
-using DropPrivilegesRef = std::shared_ptr<DropPrivileges>;
-
-class DropPrivileges : private boost::noncopyable {
- public:
- /// Make call sites use 'dropTo' booleans to improve the UI.
- static DropPrivilegesRef get();
-
- /**
- * @brief Attempt to drop privileges to that of the parent of a given path.
- *
- * This will return false if privileges could not be dropped or there was
- * an previous, and still active, request for dropped privileges.
- *
- * @return success if privileges were dropped, otherwise false.
- */
- bool dropToParent(const boost::filesystem::path& path);
-
- /// See DropPrivileges::dropToParent but explicitiy set the UID and GID.
- bool dropTo(const std::string& uid, const std::string& gid);
-
- /// See DropPrivileges::dropToParent but explicitly set the UID and GID.
- bool dropTo(uid_t uid, gid_t gid);
-
- /// See DropPrivileges::dropToParent but for a user's UID and GID.
- bool dropTo(const std::string& user);
-
- /// Check if effective privileges do not match real.
- bool dropped() {
- return (getuid() != geteuid() || getgid() != getegid());
- }
-
- /**
- * @brief The privilege/permissions dropper deconstructor will restore
- * effective permissions.
- *
- * There should only be a single drop of privilege/permission active.
- */
- virtual ~DropPrivileges();
-
- private:
- DropPrivileges() = default;
-
- /// Restore groups if dropping consecutively.
- void restoreGroups();
-
- private:
- /// Boolean to track if this instance needs to restore privileges.
- bool dropped_{false};
-
- /// The user this instance dropped privileges to.
- uid_t to_user_{0};
-
- /// The group this instance dropped privileges to.
- gid_t to_group_{0};
-
- /**
- * @brief If dropping explicitly to a user and group also drop groups.
- *
- * Original process groups before explicitly dropping privileges.
- * On restore, if there are any groups in this list, they will be added
- * to the processes group list.
- */
- gid_t* original_groups_{nullptr};
-
- /// The size of the original groups to backup when restoring privileges.
- size_t group_size_{0};
-
- private:
- FRIEND_TEST(PermissionsTests, test_explicit_drop);
- FRIEND_TEST(PermissionsTests, test_path_drop);
- FRIEND_TEST(PermissionsTests, test_nobody_drop);
-};
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include "system.h"
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#include <ctime>
-#include <memory>
-#include <string>
-
-#include <boost/filesystem/path.hpp>
-#include <boost/core/noncopyable.hpp>
-#include <gtest/gtest_prod.h>
-#include <osquery/utils/info/tool_type.h>
-
-namespace osquery {
-
-/// The osquery platform agnostic process identifier type.
-using PlatformPidType = pid_t;
-
-class DropPrivileges;
-using DropPrivilegesRef = std::shared_ptr<DropPrivileges>;
-
-class DropPrivileges : private boost::noncopyable {
- public:
- /// Make call sites use 'dropTo' booleans to improve the UI.
- static DropPrivilegesRef get();
-
- /**
- * @brief Attempt to drop privileges to that of the parent of a given path.
- *
- * This will return false if privileges could not be dropped or there was
- * an previous, and still active, request for dropped privileges.
- *
- * @return success if privileges were dropped, otherwise false.
- */
- bool dropToParent(const boost::filesystem::path& path);
-
- /// See DropPrivileges::dropToParent but explicitiy set the UID and GID.
- bool dropTo(const std::string& uid, const std::string& gid);
-
- /// See DropPrivileges::dropToParent but explicitly set the UID and GID.
- bool dropTo(uid_t uid, gid_t gid);
-
- /// See DropPrivileges::dropToParent but for a user's UID and GID.
- bool dropTo(const std::string& user);
-
- /// Check if effective privileges do not match real.
- bool dropped() {
- return (getuid() != geteuid() || getgid() != getegid());
- }
-
- /**
- * @brief The privilege/permissions dropper deconstructor will restore
- * effective permissions.
- *
- * There should only be a single drop of privilege/permission active.
- */
- virtual ~DropPrivileges();
-
- private:
- DropPrivileges() = default;
-
- /// Restore groups if dropping consecutively.
- void restoreGroups();
-
- private:
- /// Boolean to track if this instance needs to restore privileges.
- bool dropped_{false};
-
- /// The user this instance dropped privileges to.
- uid_t to_user_{0};
-
- /// The group this instance dropped privileges to.
- gid_t to_group_{0};
-
- /**
- * @brief If dropping explicitly to a user and group also drop groups.
- *
- * Original process groups before explicitly dropping privileges.
- * On restore, if there are any groups in this list, they will be added
- * to the processes group list.
- */
- gid_t* original_groups_{nullptr};
-
- /// The size of the original groups to backup when restoring privileges.
- size_t group_size_{0};
-
- private:
- FRIEND_TEST(PermissionsTests, test_explicit_drop);
- FRIEND_TEST(PermissionsTests, test_path_drop);
- FRIEND_TEST(PermissionsTests, test_nobody_drop);
-};
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <osquery/utils/system/uptime.h>
-
-#if defined(__APPLE__)
-#include <errno.h>
-#include <sys/sysctl.h>
-#include <time.h>
-#elif defined(__linux__)
-#include <sys/sysinfo.h>
-#elif defined(WIN32)
-#include <osquery/utils/system/system.h>
-#endif
-
-namespace osquery {
-
-long getUptime() {
-#if defined(DARWIN)
- struct timeval boot_time;
- size_t len = sizeof(boot_time);
- int mib[2] = {CTL_KERN, KERN_BOOTTIME};
-
- if (sysctl(mib, 2, &boot_time, &len, nullptr, 0) < 0) {
- return -1;
- }
-
- time_t seconds_since_boot = boot_time.tv_sec;
- time_t current_seconds = time(nullptr);
-
- return long(difftime(current_seconds, seconds_since_boot));
-#elif defined(__linux__)
- struct sysinfo sys_info;
-
- if (sysinfo(&sys_info) != 0) {
- return -1;
- }
-
- return sys_info.uptime;
-#elif defined(WIN32)
- return static_cast<long>(GetTickCount64() / 1000);
-#endif
-
- return -1;
-}
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-namespace osquery {
-
-long getUptime();
-
-} // namespace osquery