ADD_OSQUERY_LIBRARY(osquery_core tables.cpp
query.cpp
- database/database.cpp
- database/in_memory_database.cpp
plugins/logger.cpp
plugins/plugin.cpp
plugins/sql.cpp
+++ /dev/null
-/**
- * Copyright (c) 2018-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/database/database.h>
-#include <osquery/utils/conversions/tryto.h>
-
-namespace osquery {
-
-Expected<int32_t, DatabaseError> Database::getInt32(const std::string& domain,
- const std::string& key) {
- Expected<std::string, DatabaseError> string_value = getString(domain, key);
- if (string_value) {
- auto value = tryTo<int32_t>(*string_value);
- if (value) {
- return *value;
- } else {
- return createError(DatabaseError::FailToReadData, value.takeError())
- << "Failed to convert string to int";
- }
- } else {
- return string_value.takeError();
- }
-}
-
-ExpectedSuccess<DatabaseError> Database::putInt32(const std::string& domain,
- const std::string& key,
- const int32_t value) {
- std::string buffer = std::to_string(value);
- return putString(domain, key, buffer);
-}
-
-Expected<int32_t, DatabaseError> Database::getInt32Or(
- const std::string& domain,
- const std::string& key,
- const int32_t default_value) {
- auto result = getInt32(domain, key);
- if (!result && result.getError() == DatabaseError::KeyNotFound) {
- return default_value;
- }
- return result;
-}
-
-Expected<std::string, DatabaseError> Database::getStringOr(
- const std::string& domain,
- const std::string& key,
- const std::string& default_value) {
- auto result = getString(domain, key);
- if (!result && result.getError() == DatabaseError::KeyNotFound) {
- return default_value;
- }
- return result;
-}
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2018-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 <cstdint>
-
-#include <osquery/debug/debug_only.h>
-#include <osquery/logger.h>
-#include <osquery/utils/error/error.h>
-#include <osquery/utils/expected/expected.h>
-
-namespace osquery {
-
-enum class DatabaseError {
- // Unknown error, currently unused
- Unknown = 1,
- DbIsNotOpen = 2,
- InvalidPath = 3,
- FailToDestroyDB = 4,
- FailToOpenDatabase = 5,
- FailToReadData = 6,
- FailToWriteData = 7,
- KeyNotFound = 8,
- DomainNotFound = 9,
- // Corruption or other unrecoverable error after DB can't be longer used
- // Database should be closed, destroyed and opened again
- // If this error was received during data access, then application
- // is likely to die soon
- // See message and/or underlying error for details
- Panic = 10,
-};
-
-class Database {
- public:
- explicit Database(std::string name) : name_(std::move(name)) {}
- virtual ~Database() = default;
-
- const std::string& getName() const {
- return name_;
- }
-
- virtual ExpectedSuccess<DatabaseError> open() = 0;
- virtual void close() = 0;
-
- // This funcion should completely destroy db, so after next open
- // db should be fresh new
- // Implementation can expect that db is closed before
- // calling destroyDB and should crash/fail in case when db is still open
- virtual ExpectedSuccess<DatabaseError> destroyDB() = 0;
-
- // Return default value in case of NotFound error
- Expected<int32_t, DatabaseError> getInt32Or(const std::string& domain,
- const std::string& key,
- const int32_t default_value = 0);
- Expected<std::string, DatabaseError> getStringOr(
- const std::string& domain,
- const std::string& key,
- const std::string& default_value = "");
-
- virtual Expected<int32_t, DatabaseError> getInt32(const std::string& domain,
- const std::string& key);
- virtual Expected<std::string, DatabaseError> getString(
- const std::string& domain, const std::string& key) = 0;
-
- virtual ExpectedSuccess<DatabaseError> putInt32(const std::string& domain,
- const std::string& key,
- const int32_t value);
- virtual ExpectedSuccess<DatabaseError> putString(
- const std::string& domain,
- const std::string& key,
- const std::string& value) = 0;
-
- virtual Expected<std::vector<std::string>, DatabaseError> getKeys(
- const std::string& domain, const std::string& prefix = "") = 0;
-
- // This function designed to write batch of data as one operation and get
- // as much performance as possbile. Because of this, db may not guarantee
- // data consistency or atomic nature of operation
- // Please see actual function implementation for details and limitations
- virtual ExpectedSuccess<DatabaseError> putStringsUnsafe(
- const std::string& domain,
- const std::vector<std::pair<std::string, std::string>>& data) = 0;
-
- void panic(const Error<DatabaseError>& error) {
- LOG(ERROR) << "Database did panic: " << error.getMessage();
- debug_only::fail("Database did panic");
- }
-
- private:
- const std::string name_;
-};
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2018-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/database/in_memory_database.h>
-#include <osquery/logger.h>
-
-#include <boost/algorithm/string.hpp>
-#include <boost/core/demangle.hpp>
-
-namespace osquery {
-
-template <typename StorageType>
-std::vector<std::string> InMemoryStorage<StorageType>::getKeys(
- const std::string& prefix) const {
- std::vector<std::string> result;
- for (const auto& iter : storage_) {
- if (boost::starts_with(iter.first, prefix)) {
- result.push_back(iter.first);
- }
- }
- return result;
-}
-
-template <typename StorageType>
-void InMemoryStorage<StorageType>::put(const std::string& key,
- const StorageType value) {
- storage_[key] = value;
-}
-
-template <typename StorageType>
-Expected<StorageType, DatabaseError> InMemoryStorage<StorageType>::get(
- const std::string& key) const {
- auto iter = storage_.find(key);
- if (iter != storage_.end()) {
- return iter->second;
- }
- return createError(DatabaseError::KeyNotFound)
- << "Can't find value for key " << key;
-}
-
-void InMemoryDatabase::close() {
- VLOG(1) << "Closing db... ";
- debug_only::verifyTrue(is_open_, "database is not open");
- is_open_ = false;
- auto status = destroyDB();
- debug_only::verifyTrue(status.isValue(),
- "InMemoryDatabase::destroyDB couldn't fail");
-}
-
-ExpectedSuccess<DatabaseError> InMemoryDatabase::destroyDB() {
- VLOG(1) << "Destroying in memory db";
- storage_.clear();
- return Success();
-}
-
-ExpectedSuccess<DatabaseError> InMemoryDatabase::open() {
- debug_only::verifyTrue(!is_open_, "database is already open");
- is_open_ = true;
- return Success();
-}
-
-Error<DatabaseError> InMemoryDatabase::domainNotFoundError(
- const std::string& domain) const {
- return createError(DatabaseError::DomainNotFound)
- << "Can't find domain: " << domain;
-}
-
-template <typename T>
-Expected<T, DatabaseError> InMemoryDatabase::getValue(const std::string& domain,
- const std::string& key) {
- debug_only::verifyTrue(is_open_, "database is not open");
- if (!is_open_) {
- return createError(DatabaseError::DbIsNotOpen) << "Database is closed";
- }
- auto storage_iter = storage_.find(domain);
- if (storage_iter == storage_.end()) {
- return domainNotFoundError(domain);
- }
- std::lock_guard<std::mutex> lock(storage_iter->second->getMutex());
- auto result = storage_iter->second->get(key);
- if (result) {
- DataType value = result.take();
- if (value.type() == typeid(T)) {
- return boost::get<T>(value);
- } else {
- auto error = createError(DatabaseError::KeyNotFound)
- << "Requested wrong type for: " << domain << ":" << key
- << " stored type: " << value.type().name()
- << " requested type "
- << boost::core::demangle(typeid(T).name());
- LOG(ERROR) << error.getMessage();
- debug_only::fail(error.getMessage().c_str());
- return std::move(error);
- }
- }
- return result.takeError();
-}
-
-template <typename T>
-ExpectedSuccess<DatabaseError> InMemoryDatabase::putValue(
- const std::string& domain, const std::string& key, const T& value) {
- debug_only::verifyTrue(is_open_, "database is not open");
- if (!is_open_) {
- return createError(DatabaseError::DbIsNotOpen) << "Database is closed";
- }
- auto storage_iter = storage_.find(domain);
- if (storage_iter == storage_.end()) {
- return domainNotFoundError(domain);
- }
- std::lock_guard<std::mutex> lock(storage_iter->second->getMutex());
- debug_only::verify(
- [&storage_iter, &key]() {
- auto result = storage_iter->second->get(key);
- return result ? result.get().type() == typeid(T) : true;
- },
- "changing type is not allowed");
- storage_iter->second->put(key, value);
- return Success();
-}
-
-Expected<std::string, DatabaseError> InMemoryDatabase::getString(
- const std::string& domain, const std::string& key) {
- return getValue<std::string>(domain, key);
-}
-
-ExpectedSuccess<DatabaseError> InMemoryDatabase::putString(
- const std::string& domain,
- const std::string& key,
- const std::string& value) {
- return putValue(domain, key, value);
-}
-
-Expected<int, DatabaseError> InMemoryDatabase::getInt32(
- const std::string& domain, const std::string& key) {
- return getValue<int32_t>(domain, key);
-}
-
-ExpectedSuccess<DatabaseError> InMemoryDatabase::putInt32(
- const std::string& domain, const std::string& key, const int32_t value) {
- return putValue(domain, key, value);
-}
-
-Expected<std::vector<std::string>, DatabaseError> InMemoryDatabase::getKeys(
- const std::string& domain, const std::string& prefix) {
- debug_only::verifyTrue(is_open_, "database is not open");
- auto storage_iter = storage_.find(domain);
- if (storage_iter == storage_.end()) {
- return domainNotFoundError(domain);
- }
- return storage_iter->second->getKeys(prefix);
-}
-
-ExpectedSuccess<DatabaseError> InMemoryDatabase::putStringsUnsafe(
- const std::string& domain,
- const std::vector<std::pair<std::string, std::string>>& data) {
- debug_only::verifyTrue(is_open_, "database is not open");
- auto storage_iter = storage_.find(domain);
- if (storage_iter == storage_.end()) {
- return domainNotFoundError(domain);
- }
- std::lock_guard<std::mutex> lock(storage_iter->second->getMutex());
- for (const auto& pair : data) {
- storage_iter->second->put(pair.first, pair.second);
- }
- return Success();
-}
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2018-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 <boost/variant.hpp>
-#include <unordered_map>
-#include <mutex>
-
-#include <osquery/core/database/database.h>
-
-namespace osquery {
-
-template <typename StorageType>
-class InMemoryStorage final {
- public:
- void put(const std::string& key, const StorageType value);
- Expected<StorageType, DatabaseError> get(const std::string& key) const;
- std::vector<std::string> getKeys(const std::string& prefix = "") const;
-
- std::mutex& getMutex() {
- return mutex_;
- }
-
- private:
- std::unordered_map<std::string, StorageType> storage_;
- std::mutex mutex_;
-};
-
-class InMemoryDatabase final : public Database {
- public:
- explicit InMemoryDatabase(std::string name) : Database(std::move(name)){};
- ~InMemoryDatabase() override {}
-
- ExpectedSuccess<DatabaseError> destroyDB() override;
- ExpectedSuccess<DatabaseError> open() override;
-
- void close() override;
-
- Expected<int32_t, DatabaseError> getInt32(const std::string& domain,
- const std::string& key) override;
- Expected<std::string, DatabaseError> getString(
- const std::string& domain, const std::string& key) override;
-
- ExpectedSuccess<DatabaseError> putInt32(const std::string& domain,
- const std::string& key,
- const int32_t value) override;
- ExpectedSuccess<DatabaseError> putString(const std::string& domain,
- const std::string& key,
- const std::string& value) override;
-
- Expected<std::vector<std::string>, DatabaseError> getKeys(
- const std::string& domain, const std::string& prefix = "") override;
-
- // This method bypass type validation and will silently update value
- // even if type was changed (e.g int->string)
- ExpectedSuccess<DatabaseError> putStringsUnsafe(
- const std::string& domain,
- const std::vector<std::pair<std::string, std::string>>& data) override;
-
- private:
- template <typename T>
- Expected<T, DatabaseError> getValue(const std::string& domain,
- const std::string& key);
- template <typename T>
- ExpectedSuccess<DatabaseError> putValue(const std::string& domain,
- const std::string& key,
- const T& value);
-
- Error<DatabaseError> domainNotFoundError(const std::string& domain) const;
-
- private:
- bool is_open_ = false;
-
- using DataType = boost::variant<std::string, int32_t>;
- using InMemoryStorageRef = std::unique_ptr<InMemoryStorage<DataType>>;
-
- // storage map is built on open, so no need to protect it with locks
- std::unordered_map<std::string, InMemoryStorageRef> storage_;
-};
-
-} // namespace osquery