mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-07 09:58:54 +00:00
Merge pull request #697 from theopolis/sdk_step1
Organizing headers/build for SDK
This commit is contained in:
commit
a4689bc241
@ -6,7 +6,6 @@
|
||||
|
||||
# osquery-specific helper macros
|
||||
macro(SET_OSQUERY_COMPILE TARGET)
|
||||
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${OS_COMPILE_FLAGS})
|
||||
set(OPTIONAL_FLAGS ${ARGN})
|
||||
list(LENGTH OPTIONAL_FLAGS NUM_OPTIONAL_FLAGS)
|
||||
if(${NUM_OPTIONAL_FLAGS} GREATER 0)
|
||||
@ -14,12 +13,12 @@ macro(SET_OSQUERY_COMPILE TARGET)
|
||||
endif()
|
||||
endmacro(SET_OSQUERY_COMPILE)
|
||||
|
||||
macro(ADD_OSQUERY_TEST TEST_NAME SOURCE)
|
||||
if(NOT DEFINED ENV{SKIP_TESTS})
|
||||
macro(ADD_OSQUERY_TEST IS_CORE TEST_NAME SOURCE)
|
||||
if(NOT DEFINED ENV{SKIP_TESTS} AND (${IS_CORE} OR NOT OSQUERY_BUILD_SDK_ONLY))
|
||||
add_executable(${TEST_NAME} ${SOURCE})
|
||||
TARGET_OSQUERY_LINK_WHOLE(${TEST_NAME} libosquery_basic)
|
||||
set(TEST_FLAGS ${ARGN})
|
||||
if(${TEST_FLAGS})
|
||||
TARGET_OSQUERY_LINK_WHOLE(${TEST_NAME} libosquery)
|
||||
set(TEST_LINK_ADDITIONAL ${ARGN})
|
||||
if(NOT ${IS_CORE})
|
||||
target_link_libraries(${TEST_NAME} libosquery_additional)
|
||||
endif()
|
||||
target_link_libraries(${TEST_NAME} gtest)
|
||||
@ -29,14 +28,14 @@ macro(ADD_OSQUERY_TEST TEST_NAME SOURCE)
|
||||
endmacro(ADD_OSQUERY_TEST)
|
||||
|
||||
# Core/non core link helping macros (tell the build to link ALL).
|
||||
macro(ADD_OSQUERY_LINK LINK)
|
||||
ADD_OSQUERY_LINK_INTERNAL("${LINK}" "${ARGN}" OSQUERY_ADDITIONAL_LINKS)
|
||||
macro(ADD_OSQUERY_LINK IS_CORE LINK)
|
||||
if(${IS_CORE})
|
||||
ADD_OSQUERY_LINK_INTERNAL("${LINK}" "${ARGN}" OSQUERY_LINKS)
|
||||
elseif(NOT OSQUERY_BUILD_SDK_ONLY)
|
||||
ADD_OSQUERY_LINK_INTERNAL("${LINK}" "${ARGN}" OSQUERY_ADDITIONAL_LINKS)
|
||||
endif()
|
||||
endmacro(ADD_OSQUERY_LINK)
|
||||
|
||||
macro(ADD_OSQUERY_CORE_LINK LINK)
|
||||
ADD_OSQUERY_LINK_INTERNAL("${LINK}" "${ARGN}" OSQUERY_LINKS)
|
||||
endmacro(ADD_OSQUERY_CORE_LINK)
|
||||
|
||||
macro(ADD_OSQUERY_LINK_INTERNAL LINK LINK_PATHS LINK_SET)
|
||||
if(NOT "${LINK}" MATCHES "(^-.*)")
|
||||
find_library("${LINK}_library" NAMES "lib${LINK}.a" "${LINK}" ${LINK_PATHS})
|
||||
@ -55,39 +54,37 @@ macro(ADD_OSQUERY_LINK_INTERNAL LINK LINK_PATHS LINK_SET)
|
||||
endmacro(ADD_OSQUERY_LINK_INTERNAL)
|
||||
|
||||
# Core/non core lists of target source files.
|
||||
macro(ADD_OSQUERY_LIBRARY TARGET)
|
||||
add_library(${TARGET} OBJECT ${ARGN})
|
||||
add_dependencies(${TARGET} libglog)
|
||||
SET_OSQUERY_COMPILE(${TARGET})
|
||||
list(APPEND OSQUERY_ADDITIONAL_SOURCES $<TARGET_OBJECTS:${TARGET}>)
|
||||
set(OSQUERY_ADDITIONAL_SOURCES ${OSQUERY_ADDITIONAL_SOURCES} PARENT_SCOPE)
|
||||
macro(ADD_OSQUERY_LIBRARY IS_CORE TARGET)
|
||||
if(${IS_CORE} OR NOT OSQUERY_BUILD_SDK_ONLY)
|
||||
add_library(${TARGET} OBJECT ${ARGN})
|
||||
add_dependencies(${TARGET} libglog)
|
||||
SET_OSQUERY_COMPILE(${TARGET} "-static")
|
||||
if(${IS_CORE})
|
||||
list(APPEND OSQUERY_SOURCES $<TARGET_OBJECTS:${TARGET}>)
|
||||
set(OSQUERY_SOURCES ${OSQUERY_SOURCES} PARENT_SCOPE)
|
||||
else()
|
||||
list(APPEND OSQUERY_ADDITIONAL_SOURCES $<TARGET_OBJECTS:${TARGET}>)
|
||||
set(OSQUERY_ADDITIONAL_SOURCES ${OSQUERY_ADDITIONAL_SOURCES} PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endmacro(ADD_OSQUERY_LIBRARY TARGET)
|
||||
|
||||
macro(ADD_OSQUERY_CORE_LIBRARY TARGET)
|
||||
add_library(${TARGET} OBJECT ${ARGN})
|
||||
add_dependencies(${TARGET} libglog)
|
||||
SET_OSQUERY_COMPILE(${TARGET})
|
||||
list(APPEND OSQUERY_SOURCES $<TARGET_OBJECTS:${TARGET}>)
|
||||
set(OSQUERY_SOURCES ${OSQUERY_SOURCES} PARENT_SCOPE)
|
||||
endmacro(ADD_OSQUERY_CORE_LIBRARY TARGET)
|
||||
|
||||
# Core/non core lists of target source files compiled as ObjC++.
|
||||
macro(ADD_OSQUERY_OBJCXX_LIBRARY TARGET)
|
||||
add_library(${TARGET} OBJECT ${ARGN})
|
||||
add_dependencies(${TARGET} libglog)
|
||||
SET_OSQUERY_COMPILE(${TARGET} "${OBJCXX_COMPILE_FLAGS}")
|
||||
list(APPEND OSQUERY_ADDITIONAL_SOURCES $<TARGET_OBJECTS:${TARGET}>)
|
||||
set(OSQUERY_ADDITIONAL_SOURCES ${OSQUERY_SOURCES} PARENT_SCOPE)
|
||||
macro(ADD_OSQUERY_OBJCXX_LIBRARY IS_CORE TARGET)
|
||||
if(${IS_CORE} OR NOT OSQUERY_BUILD_SDK_ONLY)
|
||||
add_library(${TARGET} OBJECT ${ARGN})
|
||||
add_dependencies(${TARGET} libglog)
|
||||
SET_OSQUERY_COMPILE(${TARGET} "${C_COMPILE_FLAGS} ${OBJCXX_COMPILE_FLAGS} -static")
|
||||
if(${IS_CORE})
|
||||
list(APPEND OSQUERY_SOURCES $<TARGET_OBJECTS:${TARGET}>)
|
||||
set(OSQUERY_SOURCES ${OSQUERY_SOURCES} PARENT_SCOPE)
|
||||
else()
|
||||
list(APPEND OSQUERY_ADDITIONAL_SOURCES $<TARGET_OBJECTS:${TARGET}>)
|
||||
set(OSQUERY_ADDITIONAL_SOURCES ${OSQUERY_SOURCES} PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endmacro(ADD_OSQUERY_OBJCXX_LIBRARY TARGET)
|
||||
|
||||
macro(ADD_OSQUERY_CORE_OBJCXX_LIBRARY TARGET)
|
||||
add_library(${TARGET} OBJECT ${ARGN})
|
||||
add_dependencies(${TARGET} libglog)
|
||||
SET_OSQUERY_COMPILE(${TARGET} "${OBJCXX_COMPILE_FLAGS}")
|
||||
list(APPEND OSQUERY_SOURCES $<TARGET_OBJECTS:${TARGET}>)
|
||||
set(OSQUERY_SOURCES ${OSQUERY_SOURCES} PARENT_SCOPE)
|
||||
endmacro(ADD_OSQUERY_CORE_OBJCXX_LIBRARY TARGET)
|
||||
|
||||
# Helper to abstract OS/Compiler whole linking.
|
||||
macro(TARGET_OSQUERY_LINK_WHOLE TARGET OSQUERY_LIB)
|
||||
target_link_libraries(${TARGET} "${OS_WHOLELINK_PRE}")
|
||||
|
@ -1,4 +1,7 @@
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if(POLICY CMP0054)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
|
||||
set(GLOG_ROOT_DIR "${CMAKE_BINARY_DIR}/third-party/glog")
|
||||
set(GLOG_SOURCE_DIR "${CMAKE_SOURCE_DIR}/third-party/glog")
|
||||
@ -17,7 +20,7 @@ if(NOT APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(GLOG_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unnamed-type-template-args")
|
||||
set(GLOG_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unnamed-type-template-args -DHAVE_PREAD")
|
||||
|
||||
INCLUDE(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
@ -32,6 +35,7 @@ ExternalProject_Add(
|
||||
INSTALL_COMMAND make install
|
||||
LOG_CONFIGURE ON
|
||||
LOG_INSTALL ON
|
||||
LOG_BUILD ON
|
||||
)
|
||||
|
||||
set(GLOG_INCLUDE_DIR "${GLOG_ROOT_DIR}/include")
|
||||
|
55
CMake/Packages.cmake
Normal file
55
CMake/Packages.cmake
Normal file
@ -0,0 +1,55 @@
|
||||
# make package
|
||||
if(APPLE)
|
||||
add_custom_target(
|
||||
packages
|
||||
"${CMAKE_SOURCE_DIR}/tools/deployment/make_osx_package.sh"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Building default OS X package (no custom config)" VERBATIM
|
||||
)
|
||||
elseif(LINUX)
|
||||
if(UBUNTU)
|
||||
set(PACKAGE_TYPE "deb")
|
||||
set(PACKAGE_DEPENDENCIES
|
||||
"libc6 (>=2.15)"
|
||||
"zlib1g"
|
||||
"libbz2-1.0"
|
||||
"libapt-pkg4.12"
|
||||
"libreadline6"
|
||||
)
|
||||
if(OSQUERY_BUILD_DISTRO STREQUAL "PRECISE")
|
||||
set(PACKAGE_DEPENDENCIES
|
||||
"${PACKAGE_DEPENDENCIES}"
|
||||
"libstdc++6"
|
||||
"libudev0"
|
||||
)
|
||||
elseif(OSQUERY_BUILD_DISTRO STREQUAL "TRUSTY")
|
||||
set(PACKAGE_DEPENDENCIES
|
||||
"${PACKAGE_DEPENDENCIES}"
|
||||
"libstdc++6 (>= 4.8)"
|
||||
"libudev1"
|
||||
)
|
||||
endif()
|
||||
elseif(CENTOS)
|
||||
set(PACKAGE_TYPE "rpm")
|
||||
set(PACKAGE_DEPENDENCIES
|
||||
"glibc >= 2.12"
|
||||
"openssl >= 1.0"
|
||||
"readline"
|
||||
"zlib"
|
||||
"snappy"
|
||||
"bzip2-libs"
|
||||
"procps"
|
||||
"libudev"
|
||||
"rpm-libs"
|
||||
)
|
||||
endif()
|
||||
JOIN("${PACKAGE_DEPENDENCIES}" ", " PACKAGE_DEPENDENCIES)
|
||||
|
||||
add_custom_target(
|
||||
packages
|
||||
"${CMAKE_SOURCE_DIR}/tools/deployment/make_linux_package.sh"
|
||||
-t ${PACKAGE_TYPE} -d "${PACKAGE_DEPENDENCIES}"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Building linux packages (no custom config)" VERBATIM
|
||||
)
|
||||
endif()
|
@ -4,47 +4,52 @@ set(CMAKE_C_COMPILER "/usr/bin/clang")
|
||||
set(CMAKE_CXX_COMPILER "/usr/bin/clang++")
|
||||
if(APPLE)
|
||||
set(APPLE_MIN_ABI "10.9")
|
||||
set(OS_COMPILE_FLAGS "-std=c++11 -stdlib=libc++ -mmacosx-version-min=${APPLE_MIN_ABI}")
|
||||
# Special compile flags for Objective-C++
|
||||
set(OBJCXX_COMPILE_FLAGS "-x objective-c++ -fobjc-arc -Wno-c++11-extensions")
|
||||
set(CXX_COMPILE_FLAGS "${CXX_COMPILE_FLAGS} -std=c++11 -stdlib=libc++")
|
||||
set(CXX_COMPILE_FLAGS "${CXX_COMPILE_FLAGS} -mmacosx-version-min=${APPLE_MIN_ABI}")
|
||||
set(OS_WHOLELINK_PRE "-Wl,-force_load")
|
||||
set(OS_WHOLELINK_POST "")
|
||||
# Special compile flags for Objective-C++
|
||||
set(OBJCXX_COMPILE_FLAGS "-x objective-c++ -fobjc-arc -Wno-c++11-extensions")
|
||||
else()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
set(FREEBSD TRUE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||
set(CXX_COMPILE_FLAGS "${CXX_COMPILE_FLAGS} -std=c++11 -stdlib=libc++")
|
||||
set(OS_WHOLELINK_PRE "")
|
||||
set(OS_WHOLELINK_POST "")
|
||||
else()
|
||||
set(LINUX TRUE)
|
||||
set(CMAKE_C_FLAGS "-fno-omit-frame-pointer")
|
||||
set(OS_COMPILE_FLAGS "-std=c++11")
|
||||
set(CXX_COMPILE_FLAGS "-std=c++11")
|
||||
set(OS_WHOLELINK_PRE "-Wl,-whole-archive")
|
||||
set(OS_WHOLELINK_POST "-Wl,-no-whole-archive")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# make debug (environment variable from Makefile)
|
||||
if(DEFINED ENV{DEBUG})
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -DDEBUG -O0")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -DDEBUG -O0")
|
||||
set(C_COMPILE_FLAGS "${CMAKE_C_FLAGS} -g -DDEBUG -O0")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
|
||||
set(C_COMPILE_FLAGS "${CMAKE_C_FLAGS} -O2")
|
||||
endif()
|
||||
|
||||
# make analyze (environment variable from Makefile)
|
||||
if(DEFINED ENV{ANALYZE})
|
||||
set(CMAKE_CXX_COMPILER "${CMAKE_SOURCE_DIR}/tools/analysis/clang-analyze.sh")
|
||||
endif()
|
||||
|
||||
# make sanitize (environment variable from Makefile)
|
||||
if(DEFINED ENV{SANITIZE})
|
||||
set(CMAKE_CXX_FLAGS "-g -O0 -fno-omit-frame-pointer")
|
||||
set(OS_COMPILE_FLAGS "${OS_COMPILE_FLAGS} -fsanitize=leak -fsanitize=address")
|
||||
set(CXX_COMPILE_FLAGS "-g -O0 -fno-omit-frame-pointer")
|
||||
set(CXX_COMPILE_FLAGS "${CXX_COMPILE_FLAGS} -fsanitize=leak -fsanitize=address")
|
||||
if(LINUX)
|
||||
set(CMAKE_CXX_FLAGS "${OS_COMPILE_FLAGS} -fsanitize=memory")
|
||||
set(CXX_COMPILE_FLAGS "${CXX_COMPILE_FLAGS} -fsanitize=memory")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Finished setting compiler/compiler flags.
|
||||
set(CMAKE_CXX_FLAGS "${C_COMPILE_FLAGS} ${CXX_COMPILE_FLAGS}"
|
||||
CACHE STRING "compile flags" FORCE)
|
||||
|
||||
project(OSQUERY)
|
||||
|
||||
# Use osquery language to set platform/os
|
||||
@ -59,7 +64,7 @@ string(TOUPPER "${PLATFORM}" PLATFORM)
|
||||
list(GET PLATFORM 0 OSQUERY_BUILD_OS)
|
||||
list(GET PLATFORM 1 OSQUERY_BUILD_DISTRO)
|
||||
|
||||
# Make sure deps were built before compiling
|
||||
# Make sure deps were built before compiling (else show warning)
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_SOURCE_DIR}/tools/provision.sh" check "${CMAKE_BINARY_DIR}"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
@ -67,28 +72,47 @@ execute_process(
|
||||
RESULT_VARIABLE OSQUERY_DEPS_CHECK
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
string(ASCII 27 Esc)
|
||||
if(OSQUERY_DEPS_CHECK)
|
||||
message(WARNING "${Esc}[31m${OSQUERY_DEPS_MESSAGE}${Esc}[m")
|
||||
endif()
|
||||
|
||||
# Generate version from git
|
||||
execute_process(
|
||||
COMMAND git describe --tags HEAD --always
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE OSQUERY_BUILD_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# make extensions (tests building SDK-based extensions)
|
||||
if(DEFINED ENV{SDK})
|
||||
set(OSQUERY_BUILD_SDK_ONLY TRUE)
|
||||
add_definitions(
|
||||
-DOSQUERY_BUILD_SDK
|
||||
-DOSQUERY_BUILD_SDK_VERSION=${OSQUERY_BUILD_VERSION}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Set various platform/platform-version/build version/etc defines.
|
||||
add_definitions(
|
||||
-DOSQUERY_BUILD_VERSION=${OSQUERY_BUILD_VERSION}
|
||||
-D${OSQUERY_BUILD_OS}
|
||||
-D${OSQUERY_BUILD_OS}_${OSQUERY_BUILD_DISTRO}
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
message("-- Building for OS X")
|
||||
elseif(OSQUERY_BUILD_OS STREQUAL "UBUNTU")
|
||||
set(LINUX TRUE)
|
||||
set(UBUNTU TRUE)
|
||||
message("-- Building for Ubuntu")
|
||||
elseif(OSQUERY_BUILD_OS STREQUAL "CENTOS")
|
||||
set(LINUX TRUE)
|
||||
set(CENTOS TRUE)
|
||||
message("-- Building for CentOS")
|
||||
elseif(FREEBSD)
|
||||
message("-- Building for FreeBSD")
|
||||
endif()
|
||||
|
||||
set(USER_COMPILE_FLAGS "-static")
|
||||
set(OS_COMPILE_FLAGS "${OS_COMPILE_FLAGS} ${USER_COMPILE_FLAGS}")
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" "${CMAKE_MODULE_PATH}")
|
||||
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY TRUE)
|
||||
|
||||
@ -119,6 +143,7 @@ link_directories("/usr/local/lib")
|
||||
enable_testing()
|
||||
|
||||
include(CMakeLibs)
|
||||
include(Packages)
|
||||
add_subdirectory(osquery)
|
||||
|
||||
# make docs
|
||||
@ -140,6 +165,7 @@ add_custom_target(
|
||||
COMMENT "Formatting all osquery code with clang-format" VERBATIM
|
||||
)
|
||||
|
||||
# make format
|
||||
add_custom_target(
|
||||
format
|
||||
python "${CMAKE_SOURCE_DIR}/tools/formatting/git-clang-format.py"
|
||||
|
8
Makefile
8
Makefile
@ -31,6 +31,14 @@ sanitize: .setup
|
||||
cd build/$(BUILD_DIR) && SANITIZE=True cmake ../../ && \
|
||||
$(MAKE) --no-print-directory $(MAKEFLAGS)
|
||||
|
||||
sdk: .setup
|
||||
cd build/$(BUILD_DIR) && SDK=True cmake ../../ && \
|
||||
$(MAKE) --no-print-directory $(MAKEFLAGS)
|
||||
|
||||
test_sdk: .setup
|
||||
cd build/$(BUILD_DIR) && SDK=True cmake ../../ && \
|
||||
$(MAKE) test --no-print-directory $(MAKEFLAGS)
|
||||
|
||||
deps: .setup
|
||||
./tools/provision.sh build build/$(BUILD_DIR)
|
||||
|
||||
|
@ -14,9 +14,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <osquery/database/results.h>
|
||||
|
||||
#ifndef STR
|
||||
@ -43,62 +40,6 @@ enum osqueryTool {
|
||||
OSQUERY_TOOL_TEST,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Execute a query
|
||||
*
|
||||
* This is a lower-level version of osquery::SQL. Prefer to use osquery::SQL.
|
||||
*
|
||||
* @code{.cpp}
|
||||
* std::string q = "SELECT * FROM time;";
|
||||
* int i = 0;
|
||||
* auto qd = query(q, i);
|
||||
* if (i == 0) {
|
||||
* for (const auto& each : qd) {
|
||||
* for (const auto& it : each) {
|
||||
* LOG(INFO) << it.first << ": " << it.second;
|
||||
* }
|
||||
* }
|
||||
* } else {
|
||||
* LOG(ERROR) << "Error: " << i;
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param q the query to execute
|
||||
* @param error_return an int indicating the success or failure of the query
|
||||
*
|
||||
* @return the results of the query
|
||||
*/
|
||||
osquery::QueryData query(const std::string& q, int& error_return);
|
||||
|
||||
/**
|
||||
* @brief Execute a query on a specific database
|
||||
*
|
||||
* If you need to use a different database, other than the osquery default,
|
||||
* use this method and pass along a pointer to a SQLite3 database. This is
|
||||
* useful for testing.
|
||||
*
|
||||
* @param q the query to execute
|
||||
* @param error_return an int indicating the success or failure of the query
|
||||
* @param db the SQLite3 database to execute query q against
|
||||
*
|
||||
* @return the results of the query
|
||||
*/
|
||||
osquery::QueryData query(const std::string& q, int& error_return, sqlite3* db);
|
||||
|
||||
/**
|
||||
* @brief Return a fully configured sqlite3 database object
|
||||
*
|
||||
* An osquery database is basically just a SQLite3 database with several
|
||||
* virtual tables attached. This method is the main abstraction for creating
|
||||
* SQLite3 databases within osquery.
|
||||
*
|
||||
* Note: osquery::initOsquery must be called before calling createDB in order
|
||||
* for virtual tables to be registered.
|
||||
*
|
||||
* @return a SQLite3 database with all virtual tables attached
|
||||
*/
|
||||
sqlite3* createDB();
|
||||
|
||||
/**
|
||||
* @brief Sets up various aspects of osquery execution state.
|
||||
*
|
||||
|
@ -14,13 +14,16 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest_prod.h>
|
||||
|
||||
#include <osquery/database/db_handle.h>
|
||||
#include <osquery/database/results.h>
|
||||
#include <osquery/scheduler.h>
|
||||
#include <osquery/status.h>
|
||||
|
||||
#ifndef FRIEND_TEST
|
||||
#define FRIEND_TEST(test_case_name, test_name) \
|
||||
friend class test_case_name##_##test_name##_Test
|
||||
#endif
|
||||
|
||||
namespace osquery {
|
||||
|
||||
/// Error message used when a query name isn't found in the database
|
||||
|
@ -21,16 +21,55 @@
|
||||
|
||||
namespace osquery {
|
||||
|
||||
/**
|
||||
* @brief A boilerplate code helper to create a registry given a name and
|
||||
* plugin base class type.
|
||||
*
|
||||
* Registries are types of plugins, e.g., config, logger, table. They are
|
||||
* defined with a string name and Plugin derived class. There is an expectation
|
||||
* that any 'item' registered will inherit from the registry plugin-derived
|
||||
* type. But there is NO type enforcement on that intermediate class.
|
||||
*
|
||||
* This boilerplate macro puts the registry into a 'registry' namespace for
|
||||
* organization and createa a global const int that may be instanciated
|
||||
* in a header or implementation code without symbol duplication.
|
||||
* The initialization is also boilerplate, whereas the Registry::create method
|
||||
* (a whole-process-lived single instance object) creates and manages the
|
||||
* registry instance.
|
||||
*
|
||||
* @param type A typename that derives from Plugin.
|
||||
* @param name A string identifier for the registry.
|
||||
*/
|
||||
#define CREATE_REGISTRY(type, name) \
|
||||
namespace registry { \
|
||||
const auto type##Registry = Registry::create<type>(name); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A boilerplate code helper to create a registry given a name and
|
||||
* plugin base class type. This 'lazy' registry does not automatically run
|
||||
* Plugin::setUp on all items.
|
||||
*
|
||||
* @param type A typename that derives from Plugin.
|
||||
* @param name A string identifier for the registry.
|
||||
*/
|
||||
#define CREATE_LAZY_REGISTRY(type, name) \
|
||||
namespace registry { \
|
||||
const auto type##Registry = Registry::create<type>(name, false); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A boilerplate code helper to register a plugin.
|
||||
*
|
||||
* Like CREATE_REGISTRY, REGISTER creates a boilerplate global instance to
|
||||
* create an instance of the plugin type within the whole-process-lived registry
|
||||
* single instance. Registry items must derive from the `RegistryType` defined
|
||||
* by the CREATE_REGISTRY and Registry::create call.
|
||||
*
|
||||
* @param type A typename that derives from the RegistryType.
|
||||
* @param registry The string name for the registry.
|
||||
* @param name A string identifier for this registry item.
|
||||
*/
|
||||
#define REGISTER(type, registry, name) \
|
||||
const auto type##RegistryItem = Registry::add<type>(registry, name);
|
||||
|
||||
@ -80,6 +119,11 @@ class RegistryCore {
|
||||
* @brief Add a plugin to this registry by allocating and indexing
|
||||
* a type Item and a key identifier.
|
||||
*
|
||||
* @code{.cpp}
|
||||
* /// Instead of calling RegistryFactory::add use:
|
||||
* REGISTER(Type, "registry_name", "item_name");
|
||||
* @endcode
|
||||
*
|
||||
* @param item_name An identifier for this registry plugin.
|
||||
* @return A success/failure status.
|
||||
*/
|
||||
@ -90,12 +134,11 @@ class RegistryCore {
|
||||
}
|
||||
|
||||
// Run the item's constructor, the setUp call will happen later.
|
||||
auto item = new Item();
|
||||
auto item = (RegistryType*)new Item();
|
||||
item->setName(item_name);
|
||||
// Cast the specific registry-type derived item as the API typ the registry
|
||||
// used when it was created using the registry factory.
|
||||
auto base_item = reinterpret_cast<RegistryType*>(item);
|
||||
std::shared_ptr<RegistryType> shared_item(base_item);
|
||||
std::shared_ptr<RegistryType> shared_item(item);
|
||||
items_[item_name] = shared_item;
|
||||
return Status(0, "OK");
|
||||
}
|
||||
@ -160,6 +203,17 @@ class RegistryCore {
|
||||
|
||||
const std::map<std::string, RegistryTypeRef>& all() { return items_; }
|
||||
|
||||
/**
|
||||
* @brief Allow a plugin to perform some setup functions when osquery starts.
|
||||
*
|
||||
* Doing work in a plugin constructor has unknown behavior. Plugins may
|
||||
* be constructed at anytime during osquery's life, including global variable
|
||||
* instanciation. To have a reliable state (aka, flags have been parsed,
|
||||
* and logs are ready to stream), do construction work in Plugin::setUp.
|
||||
*
|
||||
* The registry `setUp` will iterate over all of its registry items and call
|
||||
* their setup unless the registry is lazy (see CREATE_REGISTRY).
|
||||
*/
|
||||
void setUp() {
|
||||
// If this registry does not auto-setup do NOT setup the registry items.
|
||||
if (!auto_setup_) {
|
||||
@ -216,8 +270,8 @@ class RegistryCore {
|
||||
template <class TypeAPI>
|
||||
class RegistryFactory : private boost::noncopyable {
|
||||
protected:
|
||||
typedef RegistryCore<TypeAPI> RegistryTypeAPI;
|
||||
typedef std::shared_ptr<TypeAPI> TypeAPIRef;
|
||||
typedef RegistryCore<TypeAPI> RegistryTypeAPI;
|
||||
typedef std::shared_ptr<RegistryCore<TypeAPI> > RegistryTypeAPIRef;
|
||||
|
||||
public:
|
||||
@ -249,8 +303,7 @@ class RegistryFactory : private boost::noncopyable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto registry =
|
||||
reinterpret_cast<RegistryTypeAPI*>(new RegistryCore<Type>(auto_setup));
|
||||
auto registry = (RegistryTypeAPI*)new RegistryCore<Type>(auto_setup);
|
||||
registry->setName(registry_name);
|
||||
std::shared_ptr<RegistryTypeAPI> shared_registry(registry);
|
||||
instance().registries_[registry_name] = shared_registry;
|
||||
|
@ -18,19 +18,6 @@
|
||||
#include <osquery/tables.h>
|
||||
|
||||
namespace osquery {
|
||||
|
||||
/**
|
||||
* @brief A map of SQLite status codes to their corresponding message string
|
||||
*
|
||||
* Details of this map are defined at: http://www.sqlite.org/c3ref/c_abort.html
|
||||
*/
|
||||
extern const std::map<int, std::string> kSQLiteReturnCodes;
|
||||
|
||||
/**
|
||||
* @brief Get a string representation of a SQLite return code
|
||||
*/
|
||||
std::string getStringForSQLiteReturnCode(int code);
|
||||
|
||||
/**
|
||||
* @brief The core interface to executing osquery SQL commands
|
||||
*
|
||||
@ -124,4 +111,45 @@ class SQL {
|
||||
/// the internal member which holds the status of the query
|
||||
Status status_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Execute a query
|
||||
*
|
||||
* This is a lower-level version of osquery::SQL. Prefer to use osquery::SQL.
|
||||
*
|
||||
* @code{.cpp}
|
||||
* std::string q = "SELECT * FROM time;";
|
||||
* QueryData results;
|
||||
* auto status = query(q, results);
|
||||
* if (status.ok()) {
|
||||
* for (const auto& each : results) {
|
||||
* for (const auto& it : each) {
|
||||
* LOG(INFO) << it.first << ": " << it.second;
|
||||
* }
|
||||
* }
|
||||
* } else {
|
||||
* LOG(ERROR) << "Error: " << status.what();
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param q the query to execute
|
||||
* @param results A QueryData structure to emit result rows on success.
|
||||
* @return A status indicating query success.
|
||||
*/
|
||||
Status query(const std::string& query, QueryData& results);
|
||||
|
||||
/**
|
||||
* @brief Analyze a query, providing information about the result columns
|
||||
*
|
||||
* This function asks SQLite to determine what the names and types are of the
|
||||
* result columns of the provided query. Only table columns (not expressions or
|
||||
* subqueries) can have their types determined. Types that are not determined
|
||||
* are indicated with the string "UNKNOWN".
|
||||
*
|
||||
* @param q the query to analyze
|
||||
* @param columns the vector to fill with column information
|
||||
*
|
||||
* @return status indicating success or failure of the operation
|
||||
*/
|
||||
Status getQueryColumns(const std::string& q, tables::TableColumns& columns);
|
||||
}
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <osquery/registry.h>
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/database/results.h>
|
||||
@ -300,39 +298,5 @@ class TablePlugin : public Plugin {
|
||||
};
|
||||
|
||||
CREATE_REGISTRY(TablePlugin, "table");
|
||||
|
||||
/**
|
||||
* @brief Analyze a query, providing information about the result columns
|
||||
*
|
||||
* This function asks SQLite to determine what the names and types are of the
|
||||
* result columns of the provided query. Only table columns (not expressions or
|
||||
* subqueries) can have their types determined. Types that are not determined
|
||||
* are indicated with the string "UNKNOWN".
|
||||
*
|
||||
* @param q the query to analyze
|
||||
* @param columns the vector to fill with column information
|
||||
*
|
||||
* @return status indicating success or failure of the operation
|
||||
*/
|
||||
Status getQueryColumns(const std::string& q, TableColumns& columns);
|
||||
|
||||
/**
|
||||
* @brief Analyze a query, providing information about the result columns
|
||||
*
|
||||
* This function asks SQLite to determine what the names and types are of the
|
||||
* result columns of the provided query. Only table columns (not expressions or
|
||||
* subqueries) can have their types determined. Types that are not determined
|
||||
* are indicated with the string "UNKNOWN".
|
||||
*
|
||||
* @param q the query to analyze
|
||||
* @param columns the vector to fill with column information
|
||||
* @param db the SQLite3 database to perform the analysis on
|
||||
*
|
||||
* @return status indicating success or failure of the operation
|
||||
*/
|
||||
Status getQueryColumns(const std::string& q,
|
||||
TableColumns& columns,
|
||||
sqlite3* db);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -28,41 +28,18 @@ set(OSQUERY_LIBS
|
||||
|
||||
# The platform-specific core libraries.
|
||||
if(APPLE)
|
||||
ADD_OSQUERY_CORE_LINK("-mmacosx-version-min=${APPLE_MIN_ABI}")
|
||||
ADD_OSQUERY_CORE_LINK("boost_thread-mt")
|
||||
ADD_OSQUERY_CORE_LINK("lz4")
|
||||
ADD_OSQUERY_LINK(TRUE "-mmacosx-version-min=${APPLE_MIN_ABI}")
|
||||
ADD_OSQUERY_LINK(TRUE "boost_thread-mt")
|
||||
ADD_OSQUERY_LINK(TRUE "lz4")
|
||||
else()
|
||||
ADD_OSQUERY_CORE_LINK("boost_thread")
|
||||
ADD_OSQUERY_CORE_LINK("rt")
|
||||
ADD_OSQUERY_LINK(TRUE "boost_thread")
|
||||
ADD_OSQUERY_LINK(TRUE "rt")
|
||||
endif()
|
||||
|
||||
# The remaining boost libraries are discovered with find_library.
|
||||
ADD_OSQUERY_CORE_LINK("boost_system")
|
||||
ADD_OSQUERY_CORE_LINK("boost_filesystem")
|
||||
ADD_OSQUERY_CORE_LINK("boost_regex")
|
||||
|
||||
# Generate version from git
|
||||
execute_process(
|
||||
COMMAND git describe --tags HEAD --always
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE OSQUERY_BUILD_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
add_definitions("
|
||||
-DOSQUERY_BUILD_VERSION=${OSQUERY_BUILD_VERSION}
|
||||
-D${OSQUERY_BUILD_OS}
|
||||
-D${OSQUERY_BUILD_OS}_${OSQUERY_BUILD_DISTRO}
|
||||
")
|
||||
|
||||
# Make sure deps were built before compiling
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_SOURCE_DIR}/tools/provision.sh" check "${CMAKE_BINARY_DIR}"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE OSQUERY_DEPS_MESSAGE
|
||||
RESULT_VARIABLE OSQUERY_DEPS_CHECK
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
ADD_OSQUERY_LINK(TRUE "boost_system")
|
||||
ADD_OSQUERY_LINK(TRUE "boost_filesystem")
|
||||
ADD_OSQUERY_LINK(TRUE "boost_regex")
|
||||
|
||||
# Construct a set of all object files, starting with third-party and all
|
||||
# of the osquery core objects (sources from ADD_CORE_LIBRARY macros).
|
||||
@ -75,11 +52,11 @@ add_subdirectory(database)
|
||||
add_subdirectory(devtools)
|
||||
add_subdirectory(dispatcher)
|
||||
add_subdirectory(events)
|
||||
add_subdirectory(examples)
|
||||
add_subdirectory(filesystem)
|
||||
add_subdirectory(logger)
|
||||
add_subdirectory(registry)
|
||||
add_subdirectory(scheduler)
|
||||
add_subdirectory(sql)
|
||||
add_subdirectory(tables)
|
||||
|
||||
# Utility tables are table specs that are ALWAYS built into osquery core.
|
||||
@ -89,123 +66,75 @@ GENERATE_UTILITY("time")
|
||||
GENERATE_UTILITY("file")
|
||||
GENERATE_UTILITY("hash")
|
||||
|
||||
# Finally amalgamate all the tables.
|
||||
# Finally amalgamate the tables needed to compile.
|
||||
AMALGAMATE("${CMAKE_SOURCE_DIR}" "utils" AMALGAMATION_UTILS)
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_utils_amalgamation ${AMALGAMATION_UTILS})
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_utils_amalgamation ${AMALGAMATION_UTILS})
|
||||
|
||||
list(APPEND OSQUERY_OBJECTS ${OSQUERY_SOURCES})
|
||||
list(APPEND OSQUERY_LIBS ${OSQUERY_LINKS})
|
||||
|
||||
# Create the static libosquery (target called libosquery_basic).
|
||||
# Create the static libosquery (everything but non-util tables).
|
||||
set(CMAKE_MACOSX_RPATH 0)
|
||||
add_library(libosquery_basic STATIC main/lib.cpp ${OSQUERY_OBJECTS})
|
||||
target_link_libraries(libosquery_basic ${OSQUERY_LIBS})
|
||||
set_target_properties(libosquery_basic PROPERTIES OUTPUT_NAME osquery)
|
||||
install(TARGETS libosquery_basic ARCHIVE DESTINATION lib COMPONENT devel OPTIONAL)
|
||||
add_library(libosquery STATIC main/lib.cpp ${OSQUERY_OBJECTS})
|
||||
target_link_libraries(libosquery ${OSQUERY_LIBS})
|
||||
set_target_properties(libosquery PROPERTIES OUTPUT_NAME osquery)
|
||||
|
||||
# Generate the osquery core tables (the non-util).
|
||||
GENERATE_TABLES("${CMAKE_SOURCE_DIR}/osquery/tables" "${CMAKE_SOURCE_DIR}")
|
||||
AMALGAMATE("${CMAKE_SOURCE_DIR}" "additional" AMALGAMATION)
|
||||
ADD_OSQUERY_LIBRARY(osquery_amalgamation ${AMALGAMATION})
|
||||
|
||||
# Create the static libosquery_additional.
|
||||
add_library(libosquery_additional STATIC ${OSQUERY_ADDITIONAL_SOURCES})
|
||||
target_link_libraries(libosquery_additional ${OSQUERY_ADDITIONAL_LINKS})
|
||||
set_target_properties(libosquery_additional PROPERTIES OUTPUT_NAME osquery_additional)
|
||||
|
||||
# Include the public API includes if make devel.
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/include/" DESTINATION include COMPONENT devel OPTIONAL)
|
||||
|
||||
add_executable(shell main/shell.cpp)
|
||||
TARGET_OSQUERY_LINK_WHOLE(shell libosquery_basic)
|
||||
TARGET_OSQUERY_LINK_WHOLE(shell libosquery_additional)
|
||||
set_target_properties(shell PROPERTIES OUTPUT_NAME osqueryi)
|
||||
set_target_properties(shell PROPERTIES COMPILE_FLAGS ${OS_COMPILE_FLAGS})
|
||||
install(TARGETS shell RUNTIME DESTINATION bin COMPONENT main)
|
||||
|
||||
add_executable(daemon main/daemon.cpp core/watcher.cpp)
|
||||
TARGET_OSQUERY_LINK_WHOLE(daemon libosquery_basic)
|
||||
TARGET_OSQUERY_LINK_WHOLE(daemon libosquery_additional)
|
||||
set_target_properties(daemon PROPERTIES OUTPUT_NAME osqueryd)
|
||||
set_target_properties(daemon PROPERTIES COMPILE_FLAGS ${OS_COMPILE_FLAGS})
|
||||
install(TARGETS daemon RUNTIME DESTINATION bin COMPONENT main)
|
||||
|
||||
add_executable(run main/run.cpp)
|
||||
TARGET_OSQUERY_LINK_WHOLE(run libosquery_basic)
|
||||
TARGET_OSQUERY_LINK_WHOLE(run libosquery_additional)
|
||||
set_target_properties(run PROPERTIES COMPILE_FLAGS ${OS_COMPILE_FLAGS})
|
||||
|
||||
# make devel
|
||||
# make devel (implies install)
|
||||
add_custom_target(devel
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-D COMPONENT=devel
|
||||
-P cmake_install.cmake
|
||||
DEPENDS libosquery_basic
|
||||
)
|
||||
add_dependencies(devel libosquery_basic)
|
||||
add_dependencies(devel libosquery)
|
||||
|
||||
# make install config files
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/tools/deployment/osquery.example.conf"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/osquery/" COMPONENT main)
|
||||
if(APPLE)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/tools/deployment/com.facebook.osqueryd.plist"
|
||||
# Generate the osquery additional tables (the non-util).
|
||||
GENERATE_TABLES("${CMAKE_SOURCE_DIR}/osquery/tables" "${CMAKE_SOURCE_DIR}")
|
||||
AMALGAMATE("${CMAKE_SOURCE_DIR}" "additional" AMALGAMATION)
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_amalgamation ${AMALGAMATION})
|
||||
|
||||
if(NOT OSQUERY_BUILD_SDK_ONLY)
|
||||
# Create the static libosquery_additional.
|
||||
add_library(libosquery_additional STATIC ${OSQUERY_ADDITIONAL_SOURCES})
|
||||
target_link_libraries(libosquery_additional ${OSQUERY_ADDITIONAL_LINKS})
|
||||
set_target_properties(libosquery_additional PROPERTIES OUTPUT_NAME osquery_additional)
|
||||
|
||||
add_executable(shell main/shell.cpp)
|
||||
TARGET_OSQUERY_LINK_WHOLE(shell libosquery)
|
||||
TARGET_OSQUERY_LINK_WHOLE(shell libosquery_additional)
|
||||
set_target_properties(shell PROPERTIES OUTPUT_NAME osqueryi)
|
||||
|
||||
add_executable(daemon main/daemon.cpp core/watcher.cpp)
|
||||
TARGET_OSQUERY_LINK_WHOLE(daemon libosquery)
|
||||
TARGET_OSQUERY_LINK_WHOLE(daemon libosquery_additional)
|
||||
set_target_properties(daemon PROPERTIES OUTPUT_NAME osqueryd)
|
||||
|
||||
add_executable(run main/run.cpp)
|
||||
TARGET_OSQUERY_LINK_WHOLE(run libosquery)
|
||||
TARGET_OSQUERY_LINK_WHOLE(run libosquery_additional)
|
||||
|
||||
# Include the public API includes if make devel.
|
||||
install(TARGETS libosquery ARCHIVE DESTINATION lib COMPONENT devel OPTIONAL)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/include/" DESTINATION include COMPONENT devel OPTIONAL)
|
||||
|
||||
# make install (executables)
|
||||
install(TARGETS shell RUNTIME DESTINATION bin COMPONENT main)
|
||||
install(TARGETS daemon RUNTIME DESTINATION bin COMPONENT main)
|
||||
|
||||
# make install (config files)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/tools/deployment/osquery.example.conf"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/osquery/" COMPONENT main)
|
||||
else()
|
||||
install(PROGRAMS "${CMAKE_SOURCE_DIR}/tools/deployment/osqueryd.initd"
|
||||
DESTINATION "/etc/init.d/" RENAME "osqueryd" COMPONENT main)
|
||||
endif()
|
||||
|
||||
# make package
|
||||
if(APPLE)
|
||||
add_custom_target(
|
||||
packages
|
||||
./tools/deployment/make_osx_package.sh
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Building default OS X package (no custom config)" VERBATIM
|
||||
)
|
||||
elseif(LINUX)
|
||||
if(UBUNTU)
|
||||
set(PACKAGE_TYPE "deb")
|
||||
set(PACKAGE_DEPENDENCIES
|
||||
"libc6 (>=2.15)"
|
||||
"zlib1g"
|
||||
"libbz2-1.0"
|
||||
"libapt-pkg4.12"
|
||||
"libreadline6"
|
||||
)
|
||||
if(OSQUERY_BUILD_DISTRO STREQUAL "PRECISE")
|
||||
set(PACKAGE_DEPENDENCIES
|
||||
"${PACKAGE_DEPENDENCIES}"
|
||||
"libstdc++6"
|
||||
"libudev0"
|
||||
)
|
||||
elseif(OSQUERY_BUILD_DISTRO STREQUAL "TRUSTY")
|
||||
set(PACKAGE_DEPENDENCIES
|
||||
"${PACKAGE_DEPENDENCIES}"
|
||||
"libstdc++6 (>= 4.8)"
|
||||
"libudev1"
|
||||
)
|
||||
endif()
|
||||
elseif(CENTOS)
|
||||
set(PACKAGE_TYPE "rpm")
|
||||
set(PACKAGE_DEPENDENCIES
|
||||
"glibc >= 2.12"
|
||||
"openssl >= 1.0"
|
||||
"readline"
|
||||
"zlib"
|
||||
"snappy"
|
||||
"bzip2-libs"
|
||||
"procps"
|
||||
"libudev"
|
||||
"rpm-libs"
|
||||
)
|
||||
if(APPLE)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/tools/deployment/com.facebook.osqueryd.plist"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/osquery/" COMPONENT main)
|
||||
else()
|
||||
install(PROGRAMS "${CMAKE_SOURCE_DIR}/tools/deployment/osqueryd.initd"
|
||||
DESTINATION "/etc/init.d/" RENAME "osqueryd" COMPONENT main)
|
||||
endif()
|
||||
JOIN("${PACKAGE_DEPENDENCIES}" ", " PACKAGE_DEPENDENCIES)
|
||||
|
||||
add_custom_target(
|
||||
packages
|
||||
./tools/deployment/make_linux_package.sh -t ${PACKAGE_TYPE} -d "${PACKAGE_DEPENDENCIES}"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Building linux packages (no custom config)" VERBATIM
|
||||
)
|
||||
else()
|
||||
# Build the example extension with the SDK
|
||||
add_executable(example_extension examples/example_extension.cpp)
|
||||
TARGET_OSQUERY_LINK_WHOLE(example_extension libosquery)
|
||||
set_target_properties(example_extension PROPERTIES OUTPUT_NAME example_extension)
|
||||
endif()
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_config
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_config
|
||||
config.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_config_plugins
|
||||
plugins/filesystem.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(config_tests config_tests.cpp)
|
||||
ADD_OSQUERY_TEST(FALSE config_tests config_tests.cpp)
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/flags.h>
|
||||
#include <osquery/registry.h>
|
||||
#include <osquery/sql.h>
|
||||
|
||||
#include "osquery/core/test_util.h"
|
||||
|
||||
@ -61,9 +62,9 @@ TEST_F(ConfigTests, test_queries_execute) {
|
||||
|
||||
EXPECT_EQ(queries.size(), 1);
|
||||
for (const auto& i : queries) {
|
||||
int err;
|
||||
auto r = query(i.query, err);
|
||||
EXPECT_EQ(err, 0);
|
||||
QueryData results;
|
||||
auto status = query(i.query, results);
|
||||
EXPECT_TRUE(status.ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,27 +6,24 @@ else()
|
||||
set (OS_CORE_SOURCE "")
|
||||
endif()
|
||||
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_core
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_core
|
||||
conversions.cpp
|
||||
init.cpp
|
||||
sql.cpp
|
||||
sqlite_util.cpp
|
||||
system.cpp
|
||||
test_util.cpp
|
||||
${OS_CORE_SOURCE}
|
||||
tables.cpp
|
||||
virtual_table.cpp
|
||||
text.cpp
|
||||
flags.cpp
|
||||
hash.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(hash_test hash_tests.cpp)
|
||||
ADD_OSQUERY_TEST(status_test status_tests.cpp)
|
||||
ADD_OSQUERY_TEST(sql_test sql_tests.cpp)
|
||||
ADD_OSQUERY_TEST(sqlite_util_tests sqlite_util_tests.cpp)
|
||||
ADD_OSQUERY_TEST(tables_tests tables_tests.cpp)
|
||||
ADD_OSQUERY_TEST(virtual_table_tests virtual_table_tests.cpp)
|
||||
ADD_OSQUERY_TEST(test_util_tests test_util_tests.cpp)
|
||||
ADD_OSQUERY_TEST(text_tests text_tests.cpp)
|
||||
ADD_OSQUERY_TEST(conversions_tests conversions_tests.cpp)
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_test_util
|
||||
test_util.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(TRUE hash_test hash_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE status_test status_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE tables_tests tables_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE test_util_tests test_util_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE text_tests text_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE conversions_tests conversions_tests.cpp)
|
||||
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/logger.h>
|
||||
#include <osquery/sql.h>
|
||||
#include <osquery/tables.h>
|
||||
#include <osquery/registry.h>
|
||||
|
||||
#include "osquery/core/virtual_table.h"
|
||||
|
||||
namespace osquery {
|
||||
|
||||
const std::map<int, std::string> kSQLiteReturnCodes = {
|
||||
{0, "SQLITE_OK: Successful result"},
|
||||
{1, "SQLITE_ERROR: SQL error or missing database"},
|
||||
{2, "SQLITE_INTERNAL: Internal logic error in SQLite"},
|
||||
{3, "SQLITE_PERM: Access permission denied"},
|
||||
{4, "SQLITE_ABORT: Callback routine requested an abort"},
|
||||
{5, "SQLITE_BUSY: The database file is locked"},
|
||||
{6, "SQLITE_LOCKED: A table in the database is locked"},
|
||||
{7, "SQLITE_NOMEM: A malloc() failed"},
|
||||
{8, "SQLITE_READONLY: Attempt to write a readonly database"},
|
||||
{9, "SQLITE_INTERRUPT: Operation terminated by sqlite3_interrupt()"},
|
||||
{10, "SQLITE_IOERR: Some kind of disk I/O error occurred"},
|
||||
{11, "SQLITE_CORRUPT: The database disk image is malformed"},
|
||||
{12, "SQLITE_NOTFOUND: Unknown opcode in sqlite3_file_control()"},
|
||||
{13, "SQLITE_FULL: Insertion failed because database is full"},
|
||||
{14, "SQLITE_CANTOPEN: Unable to open the database file"},
|
||||
{15, "SQLITE_PROTOCOL: Database lock protocol error"},
|
||||
{16, "SQLITE_EMPTY: Database is empty"},
|
||||
{17, "SQLITE_SCHEMA: The database schema changed"},
|
||||
{18, "SQLITE_TOOBIG: String or BLOB exceeds size limit"},
|
||||
{19, "SQLITE_CONSTRAINT: Abort due to constraint violation"},
|
||||
{20, "SQLITE_MISMATCH: Data type mismatch"},
|
||||
{21, "SQLITE_MISUSE: Library used incorrectly"},
|
||||
{22, "SQLITE_NOLFS: Uses OS features not supported on host"},
|
||||
{23, "SQLITE_AUTH: Authorization denied"},
|
||||
{24, "SQLITE_FORMAT: Auxiliary database format error"},
|
||||
{25, "SQLITE_RANGE: 2nd parameter to sqlite3_bind out of range"},
|
||||
{26, "SQLITE_NOTADB: File opened that is not a database file"},
|
||||
{27, "SQLITE_NOTICE: Notifications from sqlite3_log()"},
|
||||
{28, "SQLITE_WARNING: Warnings from sqlite3_log()"},
|
||||
{100, "SQLITE_ROW: sqlite3_step() has another row ready"},
|
||||
{101, "SQLITE_DONE: sqlite3_step() has finished executing"},
|
||||
};
|
||||
|
||||
const std::map<tables::ConstraintOperator, std::string> kSQLOperatorRepr = {
|
||||
{tables::EQUALS, "="},
|
||||
{tables::GREATER_THAN, ">"},
|
||||
{tables::LESS_THAN_OR_EQUALS, "<="},
|
||||
{tables::LESS_THAN, "<"},
|
||||
{tables::GREATER_THAN_OR_EQUALS, ">="}, };
|
||||
|
||||
std::string getStringForSQLiteReturnCode(int code) {
|
||||
if (kSQLiteReturnCodes.find(code) != kSQLiteReturnCodes.end()) {
|
||||
return kSQLiteReturnCodes.at(code);
|
||||
} else {
|
||||
std::ostringstream s;
|
||||
s << "Error: " << code << " is not a valid SQLite result code";
|
||||
return s.str();
|
||||
}
|
||||
}
|
||||
|
||||
SQL::SQL(const std::string& q) {
|
||||
int code = 0;
|
||||
results_ = query(q, code);
|
||||
status_ = Status(code, getStringForSQLiteReturnCode(code));
|
||||
}
|
||||
|
||||
QueryData SQL::rows() { return results_; }
|
||||
|
||||
bool SQL::ok() { return status_.ok(); }
|
||||
|
||||
std::string SQL::getMessageString() { return status_.toString(); }
|
||||
|
||||
std::vector<std::string> SQL::getTableNames() {
|
||||
std::vector<std::string> results;
|
||||
// for (const auto& it : REGISTERED_TABLES) {
|
||||
// results.push_back(it.first);
|
||||
//}
|
||||
for (const auto& name : Registry::names("table")) {
|
||||
results.push_back(name);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
QueryData SQL::selectAllFrom(const std::string& table) {
|
||||
std::string query = "select * from `" + table + "`;";
|
||||
return SQL(query).rows();
|
||||
}
|
||||
|
||||
QueryData SQL::selectAllFrom(const std::string& table,
|
||||
const std::string& column,
|
||||
tables::ConstraintOperator op,
|
||||
const std::string& expr) {
|
||||
std::string query = "select * from `" + table + "` where `" + column + "`";
|
||||
if (kSQLOperatorRepr.count(op) > 0) {
|
||||
query += kSQLOperatorRepr.at(op);
|
||||
} else {
|
||||
LOG(WARNING) << "Cannot query using unknown SQL operator: " << op;
|
||||
return {};
|
||||
}
|
||||
|
||||
query += "'" + expr + "'";
|
||||
return SQL(query).rows();
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/database.h>
|
||||
#include <osquery/logger.h>
|
||||
#include <osquery/tables.h>
|
||||
|
||||
#include "osquery/core/sqlite_util.h"
|
||||
#include "osquery/core/virtual_table.h"
|
||||
|
||||
namespace osquery {
|
||||
|
||||
sqlite3* createDB() {
|
||||
sqlite3* db = nullptr;
|
||||
sqlite3_open(":memory:", &db);
|
||||
osquery::tables::attachVirtualTables(db);
|
||||
return db;
|
||||
}
|
||||
|
||||
QueryData query(const std::string& q, int& error_return) {
|
||||
sqlite3* db = createDB();
|
||||
QueryData results = query(q, error_return, db);
|
||||
sqlite3_close(db);
|
||||
return results;
|
||||
}
|
||||
|
||||
QueryData query(const std::string& q, int& error_return, sqlite3* db) {
|
||||
QueryData d;
|
||||
char* err = nullptr;
|
||||
sqlite3_exec(db, q.c_str(), query_data_callback, &d, &err);
|
||||
if (err != nullptr) {
|
||||
LOG(ERROR) << "Error launching query: " << err;
|
||||
error_return = 1;
|
||||
sqlite3_free(err);
|
||||
} else {
|
||||
error_return = 0;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
int query_data_callback(void* argument,
|
||||
int argc,
|
||||
char* argv[],
|
||||
char* column[]) {
|
||||
if (argument == nullptr) {
|
||||
LOG(ERROR) << "query_data_callback received nullptr as data argument";
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
QueryData* qData = (QueryData*)argument;
|
||||
Row r;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
r[column[i]] = argv[i];
|
||||
}
|
||||
(*qData).push_back(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace osquery {
|
||||
|
||||
// the callback for populating a std::vector<row> set of results. "argument"
|
||||
// should be a non-const reference to a std::vector<row>
|
||||
int query_data_callback(void *argument, int argc, char *argv[], char *column[]);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <osquery/core.h>
|
||||
|
||||
#include "osquery/core/sqlite_util.h"
|
||||
#include "osquery/core/test_util.h"
|
||||
|
||||
namespace osquery {
|
||||
|
||||
class SQLiteUtilTests : public testing::Test {};
|
||||
|
||||
TEST_F(SQLiteUtilTests, test_simple_query_execution) {
|
||||
int err;
|
||||
auto db = createTestDB();
|
||||
auto results = query(kTestQuery, err, db);
|
||||
sqlite3_close(db);
|
||||
EXPECT_EQ(err, 0);
|
||||
EXPECT_EQ(results, getTestDBExpectedResults());
|
||||
}
|
||||
|
||||
TEST_F(SQLiteUtilTests, test_passing_callback_no_data_param) {
|
||||
char* err = nullptr;
|
||||
auto db = createTestDB();
|
||||
sqlite3_exec(db, kTestQuery.c_str(), query_data_callback, nullptr, &err);
|
||||
sqlite3_close(db);
|
||||
EXPECT_TRUE(err != nullptr);
|
||||
if (err != nullptr) {
|
||||
sqlite3_free(err);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SQLiteUtilTests, test_aggregate_query) {
|
||||
int err;
|
||||
auto db = createTestDB();
|
||||
QueryData d = query(kTestQuery, err, db);
|
||||
sqlite3_close(db);
|
||||
EXPECT_EQ(err, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
@ -200,55 +200,5 @@ std::string TablePlugin::statement() {
|
||||
return "CREATE TABLE " + name_ + columnDefinition();
|
||||
}
|
||||
|
||||
Status getQueryColumns(const std::string& q, tables::TableColumns& columns) {
|
||||
sqlite3* db = createDB();
|
||||
Status status = getQueryColumns(q, columns, db);
|
||||
sqlite3_close(db);
|
||||
return status;
|
||||
}
|
||||
|
||||
Status getQueryColumns(const std::string& q,
|
||||
tables::TableColumns& columns,
|
||||
sqlite3* db) {
|
||||
int rc;
|
||||
|
||||
// Will automatically handle calling sqlite3_finalize on the prepared stmt
|
||||
// (Note that sqlite3_finalize is explicitly a nop for nullptr)
|
||||
std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*> stmt_managed(
|
||||
nullptr, sqlite3_finalize);
|
||||
sqlite3_stmt* stmt = stmt_managed.get();
|
||||
|
||||
// Turn the query into a prepared statement
|
||||
rc = sqlite3_prepare_v2(db, q.c_str(), q.length() + 1, &stmt, nullptr);
|
||||
if (rc != SQLITE_OK) {
|
||||
return Status(1, sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
// Get column count
|
||||
int num_columns = sqlite3_column_count(stmt);
|
||||
std::vector<std::pair<std::string, std::string> > results;
|
||||
results.reserve(num_columns);
|
||||
|
||||
// Get column names and types
|
||||
for (int i = 0; i < num_columns; ++i) {
|
||||
const char* col_name = sqlite3_column_name(stmt, i);
|
||||
const char* col_type = sqlite3_column_decltype(stmt, i);
|
||||
if (col_name == nullptr) {
|
||||
return Status(1, "Got nullptr for column name");
|
||||
}
|
||||
if (col_type == nullptr) {
|
||||
// Types are only returned for table columns (not expressions or
|
||||
// subqueries). See docs for column_decltype
|
||||
// (https://www.sqlite.org/c3ref/column_decltype.html).
|
||||
col_type = "UNKNOWN";
|
||||
}
|
||||
results.push_back({col_name, col_type});
|
||||
}
|
||||
|
||||
columns = std::move(results);
|
||||
|
||||
return Status(0, "OK");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -110,50 +110,6 @@ TEST_F(TablesTests, test_constraint_map) {
|
||||
|
||||
EXPECT_TRUE(cm["path"].matches("some"));
|
||||
}
|
||||
|
||||
TEST_F(TablesTests, test_get_query_columns) {
|
||||
std::unique_ptr<sqlite3, decltype(sqlite3_close)*> db_managed(createDB(),
|
||||
sqlite3_close);
|
||||
sqlite3* db = db_managed.get();
|
||||
|
||||
std::string query;
|
||||
Status status;
|
||||
TableColumns results;
|
||||
|
||||
query =
|
||||
"SELECT hour, minutes, seconds, version, config_md5, config_path, \
|
||||
pid FROM time JOIN osquery_info";
|
||||
status = getQueryColumns(query, results, db);
|
||||
ASSERT_TRUE(status.ok());
|
||||
ASSERT_EQ(7, results.size());
|
||||
EXPECT_EQ(std::make_pair(std::string("hour"), std::string("INTEGER")),
|
||||
results[0]);
|
||||
EXPECT_EQ(std::make_pair(std::string("minutes"), std::string("INTEGER")),
|
||||
results[1]);
|
||||
EXPECT_EQ(std::make_pair(std::string("seconds"), std::string("INTEGER")),
|
||||
results[2]);
|
||||
EXPECT_EQ(std::make_pair(std::string("version"), std::string("TEXT")),
|
||||
results[3]);
|
||||
EXPECT_EQ(std::make_pair(std::string("config_md5"), std::string("TEXT")),
|
||||
results[4]);
|
||||
EXPECT_EQ(std::make_pair(std::string("config_path"), std::string("TEXT")),
|
||||
results[5]);
|
||||
EXPECT_EQ(std::make_pair(std::string("pid"), std::string("INTEGER")),
|
||||
results[6]);
|
||||
|
||||
query = "SELECT hour + 1 AS hour1, minutes + 1 FROM time";
|
||||
status = getQueryColumns(query, results, db);
|
||||
ASSERT_TRUE(status.ok());
|
||||
ASSERT_EQ(2, results.size());
|
||||
EXPECT_EQ(std::make_pair(std::string("hour1"), std::string("UNKNOWN")),
|
||||
results[0]);
|
||||
EXPECT_EQ(std::make_pair(std::string("minutes + 1"), std::string("UNKNOWN")),
|
||||
results[1]);
|
||||
|
||||
query = "SELECT * FROM foo";
|
||||
status = getQueryColumns(query, results, db);
|
||||
ASSERT_FALSE(status.ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <osquery/filesystem.h>
|
||||
#include <osquery/logger.h>
|
||||
|
||||
#include "osquery/core/sqlite_util.h"
|
||||
#include "osquery/core/test_util.h"
|
||||
|
||||
namespace pt = boost::property_tree;
|
||||
@ -26,27 +25,6 @@ namespace osquery {
|
||||
const std::string kTestQuery = "SELECT * FROM test_table";
|
||||
const std::string kTestDataPath = "../../../../tools/tests/";
|
||||
|
||||
sqlite3* createTestDB() {
|
||||
sqlite3* db = createDB();
|
||||
char* err = nullptr;
|
||||
std::vector<std::string> queries = {
|
||||
"CREATE TABLE test_table ("
|
||||
"username varchar(30) primary key, "
|
||||
"age int"
|
||||
")",
|
||||
"INSERT INTO test_table VALUES (\"mike\", 23)",
|
||||
"INSERT INTO test_table VALUES (\"matt\", 24)"};
|
||||
for (auto q : queries) {
|
||||
sqlite3_exec(db, q.c_str(), nullptr, nullptr, &err);
|
||||
if (err != nullptr) {
|
||||
LOG(ERROR) << "Error creating test database: " << err;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
QueryData getTestDBExpectedResults() {
|
||||
QueryData d;
|
||||
Row row1;
|
||||
|
@ -31,10 +31,6 @@ namespace osquery {
|
||||
extern const std::string kTestQuery;
|
||||
extern const std::string kTestDataPath;
|
||||
|
||||
// createTestDB instantiates a sqlite3 struct and populates it with some test
|
||||
// data
|
||||
sqlite3* createTestDB();
|
||||
|
||||
// getTestDBExpectedResults returns the results of kTestQuery of the table that
|
||||
// initially gets returned from createTestDB()
|
||||
osquery::QueryData getTestDBExpectedResults();
|
||||
|
@ -21,32 +21,6 @@ namespace osquery {
|
||||
|
||||
class TestUtilTests : public testing::Test {};
|
||||
|
||||
TEST_F(TestUtilTests, test_expected_results) {
|
||||
int err;
|
||||
auto db = createTestDB();
|
||||
auto results = query(kTestQuery, err, db);
|
||||
sqlite3_close(db);
|
||||
EXPECT_EQ(err, 0);
|
||||
EXPECT_EQ(results, getTestDBExpectedResults());
|
||||
}
|
||||
|
||||
TEST_F(TestUtilTests, test_get_test_db_result_stream) {
|
||||
auto db = createTestDB();
|
||||
auto results = getTestDBResultStream();
|
||||
for (auto r : results) {
|
||||
char* err_char = nullptr;
|
||||
sqlite3_exec(db, (r.first).c_str(), nullptr, nullptr, &err_char);
|
||||
EXPECT_TRUE(err_char == nullptr);
|
||||
if (err_char != nullptr) {
|
||||
sqlite3_free(err_char);
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
int err_int;
|
||||
auto expected = query(kTestQuery, err_int, db);
|
||||
EXPECT_EQ(expected, r.second);
|
||||
}
|
||||
sqlite3_close(db);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_database
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_database
|
||||
db_handle.cpp
|
||||
query.cpp
|
||||
results.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(query_tests query_tests.cpp)
|
||||
ADD_OSQUERY_TEST(db_handle_tests db_handle_tests.cpp)
|
||||
ADD_OSQUERY_TEST(results_tests results_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE query_tests query_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE db_handle_tests db_handle_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE results_tests results_tests.cpp)
|
||||
|
@ -1,6 +1,6 @@
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_devtools
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_devtools
|
||||
shell.cpp
|
||||
printer.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(printer_tests printer_tests.cpp)
|
||||
ADD_OSQUERY_TEST(FALSE printer_tests printer_tests.cpp)
|
||||
|
@ -84,7 +84,7 @@
|
||||
#include <osquery/devtools.h>
|
||||
#include <osquery/flags.h>
|
||||
|
||||
#include "osquery/core/virtual_table.h"
|
||||
#include "osquery/sql/virtual_table.h"
|
||||
|
||||
// Json is a specific form of pretty printing.
|
||||
namespace osquery {
|
||||
|
@ -1,7 +1,7 @@
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_dispatcher
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_dispatcher
|
||||
dispatcher.cpp
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
ADD_OSQUERY_TEST(dispatcher_tests dispatcher_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE dispatcher_tests dispatcher_tests.cpp)
|
||||
endif()
|
||||
|
@ -1,36 +1,36 @@
|
||||
SET(OSQUERY_EVENTS_SOURCES "")
|
||||
|
||||
if(APPLE)
|
||||
ADD_OSQUERY_CORE_LINK("-framework CoreServices")
|
||||
ADD_OSQUERY_CORE_LINK("-framework SystemConfiguration")
|
||||
ADD_OSQUERY_CORE_LINK("-framework IOKit")
|
||||
ADD_OSQUERY_LINK(FALSE "-framework CoreServices")
|
||||
ADD_OSQUERY_LINK(FALSE "-framework SystemConfiguration")
|
||||
ADD_OSQUERY_LINK(FALSE "-framework IOKit")
|
||||
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_events_darwin
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_events_darwin
|
||||
darwin/fsevents.cpp
|
||||
darwin/iokit_hid.cpp
|
||||
darwin/scnetwork.cpp
|
||||
)
|
||||
elseif(FREEBSD)
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_events_freebsd
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_events_freebsd
|
||||
)
|
||||
else()
|
||||
ADD_OSQUERY_CORE_LINK("udev")
|
||||
ADD_OSQUERY_LINK(FALSE "udev")
|
||||
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_events_linux
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_events_linux
|
||||
linux/inotify.cpp
|
||||
linux/udev.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_events
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_events
|
||||
events.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(events_tests events_tests.cpp)
|
||||
ADD_OSQUERY_TEST(events_database_tests events_database_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE events_tests events_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE events_database_tests events_database_tests.cpp)
|
||||
|
||||
if(APPLE)
|
||||
ADD_OSQUERY_TEST(fsevents_tests darwin/fsevents_tests.cpp)
|
||||
ADD_OSQUERY_TEST(FALSE fsevents_tests darwin/fsevents_tests.cpp)
|
||||
elseif(LINUX)
|
||||
ADD_OSQUERY_TEST(inotify_tests linux/inotify_tests.cpp)
|
||||
ADD_OSQUERY_TEST(FALSE inotify_tests linux/inotify_tests.cpp)
|
||||
endif()
|
||||
|
@ -1 +0,0 @@
|
||||
ADD_OSQUERY_TEST(example_test example_test.cpp)
|
39
osquery/examples/example_extension.cpp
Normal file
39
osquery/examples/example_extension.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osquery/tables.h>
|
||||
|
||||
namespace osquery {
|
||||
|
||||
class ExampleTable : public tables::TablePlugin {
|
||||
private:
|
||||
tables::TableColumns columns() {
|
||||
return {{"example_text", "TEXT"}, {"example_integer", "INTEGER"}};
|
||||
}
|
||||
|
||||
QueryData generate(tables::QueryContext& request) {
|
||||
QueryData results;
|
||||
|
||||
Row r;
|
||||
r["example_text"] = "example";
|
||||
r["example_integer"] = INTEGER(1);
|
||||
|
||||
results.push_back(r);
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER(ExampleTable, "table", "example");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Do some broadcast of the registry.
|
||||
auto example = std::make_shared<osquery::ExampleTable>();
|
||||
}
|
@ -1,22 +1,22 @@
|
||||
if(APPLE)
|
||||
ADD_OSQUERY_CORE_OBJCXX_LIBRARY(osquery_filesystem_objc
|
||||
ADD_OSQUERY_OBJCXX_LIBRARY(TRUE osquery_filesystem_objc
|
||||
darwin/plist.mm
|
||||
)
|
||||
|
||||
ADD_OSQUERY_CORE_LINK("-framework Foundation")
|
||||
ADD_OSQUERY_LINK(TRUE "-framework Foundation")
|
||||
elseif(UBUNTU OR CENTOS)
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_filesystem_linux
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_filesystem_linux
|
||||
linux/mem.cpp
|
||||
linux/proc.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_filesystem
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_filesystem
|
||||
filesystem.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(filesystem_tests filesystem_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE filesystem_tests filesystem_tests.cpp)
|
||||
if(APPLE)
|
||||
ADD_OSQUERY_TEST(plist_tests darwin/plist_tests.cpp)
|
||||
ADD_OSQUERY_TEST(plist_benchmark darwin/plist_benchmark.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE plist_tests darwin/plist_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE plist_benchmark darwin/plist_benchmark.cpp)
|
||||
endif()
|
||||
|
@ -1,4 +1,10 @@
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_logger logger.cpp plugins/filesystem.cpp)
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_logger
|
||||
logger.cpp
|
||||
)
|
||||
add_dependencies(osquery_logger libglog)
|
||||
|
||||
ADD_OSQUERY_TEST(logger_tests logger_tests.cpp)
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_logger_plugins
|
||||
plugins/filesystem.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(FALSE logger_tests logger_tests.cpp)
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/events.h>
|
||||
#include <osquery/logger.h>
|
||||
#include <osquery/sql.h>
|
||||
|
||||
DEFINE_string(query, "", "query to execute");
|
||||
DEFINE_int32(iterations, 1, "times to run the query in question");
|
||||
@ -41,11 +42,12 @@ int main(int argc, char* argv[]) {
|
||||
::sleep(FLAGS_delay);
|
||||
}
|
||||
|
||||
osquery::QueryData results;
|
||||
for (int i = 0; i < FLAGS_iterations; ++i) {
|
||||
printf("Executing: %s\n", FLAGS_query.c_str());
|
||||
osquery::query(FLAGS_query, result);
|
||||
if (result != 0) {
|
||||
fprintf(stderr, "Query failed: %d\n", result);
|
||||
auto status = osquery::query(FLAGS_query, results);
|
||||
if (!status.ok()) {
|
||||
fprintf(stderr, "Query failed: %d\n", status.getCode());
|
||||
break;
|
||||
} else {
|
||||
if (FLAGS_delay != 0) {
|
||||
|
@ -15,11 +15,13 @@
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
osquery::FLAGS_db_path = "/tmp/rocksdb-osquery-shell";
|
||||
// Parse/apply flags, start registry, load logger/config plugins.
|
||||
osquery::initOsquery(argc, argv, osquery::OSQUERY_TOOL_SHELL);
|
||||
|
||||
// Start event threads.
|
||||
osquery::EventFactory::delay();
|
||||
|
||||
// Virtual tables will be attached to the shell's in-memory SQLite DB.
|
||||
int retcode = osquery::launchIntoShell(argc, argv);
|
||||
|
||||
// Finally shutdown.
|
||||
|
@ -1,5 +1,5 @@
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_registry
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_registry
|
||||
registry.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(core_registry_tests registry_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE registry_tests registry_tests.cpp)
|
||||
|
@ -1,5 +1,5 @@
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_scheduler
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_scheduler
|
||||
scheduler.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(scheduler_tests scheduler_tests.cpp)
|
||||
ADD_OSQUERY_TEST(TRUE scheduler_tests scheduler_tests.cpp)
|
||||
|
16
osquery/sql/CMakeLists.txt
Normal file
16
osquery/sql/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_sql
|
||||
sql.cpp
|
||||
)
|
||||
|
||||
if(NOT OSQUERY_BUILD_SDK_ONLY)
|
||||
set(SQL_INTERNAL TRUE)
|
||||
endif()
|
||||
|
||||
ADD_OSQUERY_LIBRARY(SQL_INTERNAL osquery_sql_internal
|
||||
sqlite_util.cpp
|
||||
virtual_table.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(TRUE sql_test sql_tests.cpp)
|
||||
ADD_OSQUERY_TEST(SQL_INTERNAL sqlite_util_tests sqlite_util_tests.cpp)
|
||||
ADD_OSQUERY_TEST(SQL_INTERNAL virtual_table_tests virtual_table_tests.cpp)
|
89
osquery/sql/sql.cpp
Normal file
89
osquery/sql/sql.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/logger.h>
|
||||
#include <osquery/sql.h>
|
||||
#include <osquery/tables.h>
|
||||
#include <osquery/registry.h>
|
||||
|
||||
#ifndef OSQUERY_BUILD_SDK
|
||||
#include "osquery/sql/sqlite_util.h"
|
||||
#endif
|
||||
|
||||
namespace osquery {
|
||||
|
||||
const std::map<tables::ConstraintOperator, std::string> kSQLOperatorRepr = {
|
||||
{tables::EQUALS, "="},
|
||||
{tables::GREATER_THAN, ">"},
|
||||
{tables::LESS_THAN_OR_EQUALS, "<="},
|
||||
{tables::LESS_THAN, "<"},
|
||||
{tables::GREATER_THAN_OR_EQUALS, ">="},
|
||||
};
|
||||
|
||||
SQL::SQL(const std::string& q) { status_ = query(q, results_); }
|
||||
|
||||
QueryData SQL::rows() { return results_; }
|
||||
|
||||
bool SQL::ok() { return status_.ok(); }
|
||||
|
||||
std::string SQL::getMessageString() { return status_.toString(); }
|
||||
|
||||
std::vector<std::string> SQL::getTableNames() {
|
||||
std::vector<std::string> results;
|
||||
for (const auto& name : Registry::names("table")) {
|
||||
results.push_back(name);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
QueryData SQL::selectAllFrom(const std::string& table) {
|
||||
std::string query = "select * from `" + table + "`;";
|
||||
return SQL(query).rows();
|
||||
}
|
||||
|
||||
QueryData SQL::selectAllFrom(const std::string& table,
|
||||
const std::string& column,
|
||||
tables::ConstraintOperator op,
|
||||
const std::string& expr) {
|
||||
std::string query = "select * from `" + table + "` where `" + column + "`";
|
||||
if (kSQLOperatorRepr.count(op) > 0) {
|
||||
query += kSQLOperatorRepr.at(op);
|
||||
} else {
|
||||
LOG(WARNING) << "Cannot query using unknown SQL operator: " << op;
|
||||
return {};
|
||||
}
|
||||
|
||||
query += "'" + expr + "'";
|
||||
return SQL(query).rows();
|
||||
}
|
||||
|
||||
Status query(const std::string& q, QueryData& results) {
|
||||
// Depending on the build type (core or sdk/extension) osquery will call the
|
||||
// internal SQL implementation or the Thrift API endpoint.
|
||||
#ifndef OSQUERY_BUILD_SDK
|
||||
return queryInternal(q, results);
|
||||
#else
|
||||
return Status(0, "OK");
|
||||
#endif
|
||||
}
|
||||
|
||||
Status getQueryColumns(const std::string& q, tables::TableColumns& columns) {
|
||||
// Depending on the build type (core or sdk/extension) osquery will call the
|
||||
// internal SQL implementation or the Thrift API endpoint.
|
||||
#ifndef OSQUERY_BUILD_SDK
|
||||
return getQueryColumnsInternal(q, columns);
|
||||
#else
|
||||
return Status(0, "OK");
|
||||
#endif
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
@ -20,7 +20,6 @@ class SQLTests : public testing::Test {};
|
||||
TEST_F(SQLTests, test_simple_query_execution) {
|
||||
auto sql = SQL("SELECT * FROM time");
|
||||
EXPECT_TRUE(sql.ok());
|
||||
EXPECT_EQ(sql.getMessageString(), getStringForSQLiteReturnCode(0));
|
||||
EXPECT_EQ(sql.rows().size(), 1);
|
||||
}
|
||||
|
155
osquery/sql/sqlite_util.cpp
Normal file
155
osquery/sql/sqlite_util.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/database.h>
|
||||
#include <osquery/logger.h>
|
||||
#include <osquery/sql.h>
|
||||
|
||||
#include "osquery/sql/sqlite_util.h"
|
||||
#include "osquery/sql/virtual_table.h"
|
||||
|
||||
namespace osquery {
|
||||
|
||||
const std::map<int, std::string> kSQLiteReturnCodes = {
|
||||
{0, "SQLITE_OK: Successful result"},
|
||||
{1, "SQLITE_ERROR: SQL error or missing database"},
|
||||
{2, "SQLITE_INTERNAL: Internal logic error in SQLite"},
|
||||
{3, "SQLITE_PERM: Access permission denied"},
|
||||
{4, "SQLITE_ABORT: Callback routine requested an abort"},
|
||||
{5, "SQLITE_BUSY: The database file is locked"},
|
||||
{6, "SQLITE_LOCKED: A table in the database is locked"},
|
||||
{7, "SQLITE_NOMEM: A malloc() failed"},
|
||||
{8, "SQLITE_READONLY: Attempt to write a readonly database"},
|
||||
{9, "SQLITE_INTERRUPT: Operation terminated by sqlite3_interrupt()"},
|
||||
{10, "SQLITE_IOERR: Some kind of disk I/O error occurred"},
|
||||
{11, "SQLITE_CORRUPT: The database disk image is malformed"},
|
||||
{12, "SQLITE_NOTFOUND: Unknown opcode in sqlite3_file_control()"},
|
||||
{13, "SQLITE_FULL: Insertion failed because database is full"},
|
||||
{14, "SQLITE_CANTOPEN: Unable to open the database file"},
|
||||
{15, "SQLITE_PROTOCOL: Database lock protocol error"},
|
||||
{16, "SQLITE_EMPTY: Database is empty"},
|
||||
{17, "SQLITE_SCHEMA: The database schema changed"},
|
||||
{18, "SQLITE_TOOBIG: String or BLOB exceeds size limit"},
|
||||
{19, "SQLITE_CONSTRAINT: Abort due to constraint violation"},
|
||||
{20, "SQLITE_MISMATCH: Data type mismatch"},
|
||||
{21, "SQLITE_MISUSE: Library used incorrectly"},
|
||||
{22, "SQLITE_NOLFS: Uses OS features not supported on host"},
|
||||
{23, "SQLITE_AUTH: Authorization denied"},
|
||||
{24, "SQLITE_FORMAT: Auxiliary database format error"},
|
||||
{25, "SQLITE_RANGE: 2nd parameter to sqlite3_bind out of range"},
|
||||
{26, "SQLITE_NOTADB: File opened that is not a database file"},
|
||||
{27, "SQLITE_NOTICE: Notifications from sqlite3_log()"},
|
||||
{28, "SQLITE_WARNING: Warnings from sqlite3_log()"},
|
||||
{100, "SQLITE_ROW: sqlite3_step() has another row ready"},
|
||||
{101, "SQLITE_DONE: sqlite3_step() has finished executing"},
|
||||
};
|
||||
|
||||
std::string getStringForSQLiteReturnCode(int code) {
|
||||
if (kSQLiteReturnCodes.find(code) != kSQLiteReturnCodes.end()) {
|
||||
return kSQLiteReturnCodes.at(code);
|
||||
} else {
|
||||
std::ostringstream s;
|
||||
s << "Error: " << code << " is not a valid SQLite result code";
|
||||
return s.str();
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3* createDB() {
|
||||
sqlite3* db = nullptr;
|
||||
sqlite3_open(":memory:", &db);
|
||||
tables::attachVirtualTables(db);
|
||||
return db;
|
||||
}
|
||||
|
||||
int queryDataCallback(void* argument, int argc, char* argv[], char* column[]) {
|
||||
if (argument == nullptr) {
|
||||
LOG(ERROR) << "queryDataCallback received nullptr as data argument";
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
|
||||
QueryData* qData = (QueryData*)argument;
|
||||
Row r;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
r[column[i]] = argv[i];
|
||||
}
|
||||
(*qData).push_back(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status queryInternal(const std::string& q, QueryData& results) {
|
||||
sqlite3* db = createDB();
|
||||
auto status = queryInternal(q, results, db);
|
||||
sqlite3_close(db);
|
||||
return status;
|
||||
}
|
||||
|
||||
Status queryInternal(const std::string& q, QueryData& results, sqlite3* db) {
|
||||
char* err = nullptr;
|
||||
sqlite3_exec(db, q.c_str(), queryDataCallback, &results, &err);
|
||||
if (err != nullptr) {
|
||||
sqlite3_free(err);
|
||||
return Status(1, "Error running query: " + q);
|
||||
}
|
||||
|
||||
return Status(0, "OK");
|
||||
}
|
||||
|
||||
Status getQueryColumnsInternal(const std::string& q,
|
||||
tables::TableColumns& columns) {
|
||||
sqlite3* db = createDB();
|
||||
Status status = getQueryColumnsInternal(q, columns, db);
|
||||
sqlite3_close(db);
|
||||
return status;
|
||||
}
|
||||
|
||||
Status getQueryColumnsInternal(const std::string& q,
|
||||
tables::TableColumns& columns,
|
||||
sqlite3* db) {
|
||||
int rc;
|
||||
|
||||
// Will automatically handle calling sqlite3_finalize on the prepared stmt
|
||||
// (Note that sqlite3_finalize is explicitly a nop for nullptr)
|
||||
std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*> stmt_managed(
|
||||
nullptr, sqlite3_finalize);
|
||||
sqlite3_stmt* stmt = stmt_managed.get();
|
||||
|
||||
// Turn the query into a prepared statement
|
||||
rc = sqlite3_prepare_v2(db, q.c_str(), q.length() + 1, &stmt, nullptr);
|
||||
if (rc != SQLITE_OK) {
|
||||
return Status(1, sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
// Get column count
|
||||
int num_columns = sqlite3_column_count(stmt);
|
||||
std::vector<std::pair<std::string, std::string> > results;
|
||||
results.reserve(num_columns);
|
||||
|
||||
// Get column names and types
|
||||
for (int i = 0; i < num_columns; ++i) {
|
||||
const char* col_name = sqlite3_column_name(stmt, i);
|
||||
const char* col_type = sqlite3_column_decltype(stmt, i);
|
||||
if (col_name == nullptr) {
|
||||
return Status(1, "Got nullptr for column name");
|
||||
}
|
||||
if (col_type == nullptr) {
|
||||
// Types are only returned for table columns (not expressions or
|
||||
// subqueries). See docs for column_decltype
|
||||
// (https://www.sqlite.org/c3ref/column_decltype.html).
|
||||
col_type = "UNKNOWN";
|
||||
}
|
||||
results.push_back({col_name, col_type});
|
||||
}
|
||||
|
||||
columns = std::move(results);
|
||||
|
||||
return Status(0, "OK");
|
||||
}
|
||||
}
|
84
osquery/sql/sqlite_util.h
Normal file
84
osquery/sql/sqlite_util.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
namespace osquery {
|
||||
/**
|
||||
* @brief A map of SQLite status codes to their corresponding message string
|
||||
*
|
||||
* Details of this map are defined at: http://www.sqlite.org/c3ref/c_abort.html
|
||||
*/
|
||||
extern const std::map<int, std::string> kSQLiteReturnCodes;
|
||||
|
||||
/// Internal (core) SQL implementation of the osquery query API.
|
||||
Status queryInternal(const std::string& q, QueryData& results);
|
||||
|
||||
/**
|
||||
* @brief Execute a query on a specific database
|
||||
*
|
||||
* If you need to use a different database, other than the osquery default,
|
||||
* use this method and pass along a pointer to a SQLite3 database. This is
|
||||
* useful for testing.
|
||||
*
|
||||
* @param q the query to execute
|
||||
* @param results The QueryData struct to emit row on query success.
|
||||
* @param db the SQLite3 database to execute query q against
|
||||
*
|
||||
* @return A status indicating SQL query results.
|
||||
*/
|
||||
Status queryInternal(const std::string& q, QueryData& results, sqlite3* db);
|
||||
|
||||
/// Internal (core) SQL implementation of the osquery getQueryColumns API.
|
||||
Status getQueryColumnsInternal(const std::string& q, tables::TableColumns& columns);
|
||||
|
||||
/**
|
||||
* @brief Analyze a query, providing information about the result columns
|
||||
*
|
||||
* This function asks SQLite to determine what the names and types are of the
|
||||
* result columns of the provided query. Only table columns (not expressions or
|
||||
* subqueries) can have their types determined. Types that are not determined
|
||||
* are indicated with the string "UNKNOWN".
|
||||
*
|
||||
* @param q the query to analyze
|
||||
* @param columns the vector to fill with column information
|
||||
* @param db the SQLite3 database to perform the analysis on
|
||||
*
|
||||
* @return status indicating success or failure of the operation
|
||||
*/
|
||||
Status getQueryColumnsInternal(const std::string& q,
|
||||
tables::TableColumns& columns,
|
||||
sqlite3* db);
|
||||
|
||||
/**
|
||||
* @brief Return a fully configured sqlite3 database object
|
||||
*
|
||||
* An osquery database is basically just a SQLite3 database with several
|
||||
* virtual tables attached. This method is the main abstraction for creating
|
||||
* SQLite3 databases within osquery.
|
||||
*
|
||||
* Note: osquery::initOsquery must be called before calling createDB in order
|
||||
* for virtual tables to be registered.
|
||||
*
|
||||
* @return a SQLite3 database with all virtual tables attached
|
||||
*/
|
||||
sqlite3* createDB();
|
||||
|
||||
/**
|
||||
* @brief Get a string representation of a SQLite return code
|
||||
*/
|
||||
std::string getStringForSQLiteReturnCode(int code);
|
||||
|
||||
// the callback for populating a std::vector<row> set of results. "argument"
|
||||
// should be a non-const reference to a std::vector<row>
|
||||
int queryDataCallback(void* argument, int argc, char* argv[], char* column[]);
|
||||
}
|
141
osquery/sql/sqlite_util_tests.cpp
Normal file
141
osquery/sql/sqlite_util_tests.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/sql.h>
|
||||
|
||||
#include "osquery/core/test_util.h"
|
||||
#include "osquery/sql/sqlite_util.h"
|
||||
|
||||
namespace osquery {
|
||||
|
||||
class SQLiteUtilTests : public testing::Test {};
|
||||
|
||||
sqlite3* createTestDB() {
|
||||
sqlite3* db = createDB();
|
||||
char* err = nullptr;
|
||||
std::vector<std::string> queries = {
|
||||
"CREATE TABLE test_table ("
|
||||
"username varchar(30) primary key, "
|
||||
"age int"
|
||||
")",
|
||||
"INSERT INTO test_table VALUES (\"mike\", 23)",
|
||||
"INSERT INTO test_table VALUES (\"matt\", 24)"};
|
||||
for (auto q : queries) {
|
||||
sqlite3_exec(db, q.c_str(), nullptr, nullptr, &err);
|
||||
if (err != nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
TEST_F(SQLiteUtilTests, test_simple_query_execution) {
|
||||
auto db = createTestDB();
|
||||
QueryData results;
|
||||
auto status = queryInternal(kTestQuery, results, db);
|
||||
sqlite3_close(db);
|
||||
EXPECT_TRUE(status.ok());
|
||||
EXPECT_EQ(results, getTestDBExpectedResults());
|
||||
}
|
||||
|
||||
TEST_F(SQLiteUtilTests, test_passing_callback_no_data_param) {
|
||||
char* err = nullptr;
|
||||
auto db = createTestDB();
|
||||
sqlite3_exec(db, kTestQuery.c_str(), queryDataCallback, nullptr, &err);
|
||||
sqlite3_close(db);
|
||||
EXPECT_TRUE(err != nullptr);
|
||||
if (err != nullptr) {
|
||||
sqlite3_free(err);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SQLiteUtilTests, test_aggregate_query) {
|
||||
auto db = createTestDB();
|
||||
QueryData results;
|
||||
auto status = queryInternal(kTestQuery, results, db);
|
||||
sqlite3_close(db);
|
||||
EXPECT_TRUE(status.ok());
|
||||
EXPECT_EQ(results, getTestDBExpectedResults());
|
||||
}
|
||||
|
||||
TEST_F(SQLiteUtilTests, test_get_test_db_result_stream) {
|
||||
auto db = createTestDB();
|
||||
auto results = getTestDBResultStream();
|
||||
for (auto r : results) {
|
||||
char* err_char = nullptr;
|
||||
sqlite3_exec(db, (r.first).c_str(), nullptr, nullptr, &err_char);
|
||||
EXPECT_TRUE(err_char == nullptr);
|
||||
if (err_char != nullptr) {
|
||||
sqlite3_free(err_char);
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
|
||||
QueryData expected;
|
||||
auto status = queryInternal(kTestQuery, expected, db);
|
||||
EXPECT_EQ(expected, r.second);
|
||||
}
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
TEST_F(SQLiteUtilTests, test_get_query_columns) {
|
||||
std::unique_ptr<sqlite3, decltype(sqlite3_close)*> db_managed(createDB(),
|
||||
sqlite3_close);
|
||||
sqlite3* db = db_managed.get();
|
||||
|
||||
std::string query;
|
||||
Status status;
|
||||
tables::TableColumns results;
|
||||
|
||||
query =
|
||||
"SELECT hour, minutes, seconds, version, config_md5, config_path, \
|
||||
pid FROM time JOIN osquery_info";
|
||||
status = getQueryColumnsInternal(query, results, db);
|
||||
ASSERT_TRUE(status.ok());
|
||||
ASSERT_EQ(7, results.size());
|
||||
EXPECT_EQ(std::make_pair(std::string("hour"), std::string("INTEGER")),
|
||||
results[0]);
|
||||
EXPECT_EQ(std::make_pair(std::string("minutes"), std::string("INTEGER")),
|
||||
results[1]);
|
||||
EXPECT_EQ(std::make_pair(std::string("seconds"), std::string("INTEGER")),
|
||||
results[2]);
|
||||
EXPECT_EQ(std::make_pair(std::string("version"), std::string("TEXT")),
|
||||
results[3]);
|
||||
EXPECT_EQ(std::make_pair(std::string("config_md5"), std::string("TEXT")),
|
||||
results[4]);
|
||||
EXPECT_EQ(std::make_pair(std::string("config_path"), std::string("TEXT")),
|
||||
results[5]);
|
||||
EXPECT_EQ(std::make_pair(std::string("pid"), std::string("INTEGER")),
|
||||
results[6]);
|
||||
|
||||
query = "SELECT hour + 1 AS hour1, minutes + 1 FROM time";
|
||||
status = getQueryColumnsInternal(query, results, db);
|
||||
ASSERT_TRUE(status.ok());
|
||||
ASSERT_EQ(2, results.size());
|
||||
EXPECT_EQ(std::make_pair(std::string("hour1"), std::string("UNKNOWN")),
|
||||
results[0]);
|
||||
EXPECT_EQ(std::make_pair(std::string("minutes + 1"), std::string("UNKNOWN")),
|
||||
results[1]);
|
||||
|
||||
query = "SELECT * FROM foo";
|
||||
status = getQueryColumnsInternal(query, results, db);
|
||||
ASSERT_FALSE(status.ok());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <osquery/logger.h>
|
||||
|
||||
#include "osquery/core/virtual_table.h"
|
||||
#include "osquery/sql/virtual_table.h"
|
||||
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
@ -211,8 +211,7 @@ static int xFilter(sqlite3_vtab_cursor *pVtabCursor,
|
||||
for (const auto &column : pVtab->content->columns) {
|
||||
try {
|
||||
pVtab->content->data[column.first].push_back(row.at(column.first));
|
||||
}
|
||||
catch (const std::out_of_range &e) {
|
||||
} catch (const std::out_of_range &e) {
|
||||
VLOG(1) << "Table " << pVtab->content->name << " row "
|
||||
<< pVtab->content->n << " did not include column "
|
||||
<< column.first;
|
||||
@ -272,8 +271,7 @@ void attachVirtualTables(sqlite3 *db) {
|
||||
for (const auto &name : Registry::names("table")) {
|
||||
int status = attachTable(db, name);
|
||||
if (status != SQLITE_OK) {
|
||||
LOG(ERROR) << "Error attaching virtual table: " << name << " (" << status
|
||||
<< ")";
|
||||
LOG(ERROR) << "Error attaching table: " << name << " (" << status << ")";
|
||||
}
|
||||
}
|
||||
}
|
@ -3,17 +3,17 @@
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <osquery/tables.h>
|
||||
|
||||
#include "osquery/sql/sqlite_util.h"
|
||||
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
|
||||
@ -48,7 +48,10 @@ struct VirtualTable {
|
||||
VirtualTableContent *content;
|
||||
};
|
||||
|
||||
/// Attach a table plugin name to an in-memory SQLite datable.
|
||||
int attachTable(sqlite3 *db, const std::string &name);
|
||||
|
||||
/// Attach all table plugins to an in-memory SQLite datable.
|
||||
void attachVirtualTables(sqlite3 *db);
|
||||
}
|
||||
}
|
@ -12,8 +12,9 @@
|
||||
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/registry.h>
|
||||
#include <osquery/sql.h>
|
||||
|
||||
#include "osquery/core/virtual_table.h"
|
||||
#include "osquery/sql/virtual_table.h"
|
||||
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
@ -57,8 +58,8 @@ TEST_F(VirtualTableTests, test_sqlite3_attach_vtable) {
|
||||
EXPECT_EQ(rc, SQLITE_OK);
|
||||
|
||||
std::string q = "SELECT sql FROM sqlite_temp_master WHERE tbl_name='sample';";
|
||||
int error_return;
|
||||
QueryData results = query(q, error_return, db);
|
||||
QueryData results;
|
||||
auto status = queryInternal(q, results, db);
|
||||
EXPECT_EQ("CREATE VIRTUAL TABLE sample USING sample(foo INTEGER, bar TEXT)",
|
||||
results[0]["sql"]);
|
||||
sqlite3_close(db);
|
@ -1,5 +1,5 @@
|
||||
if(APPLE)
|
||||
ADD_OSQUERY_OBJCXX_LIBRARY(osquery_tables_objc
|
||||
ADD_OSQUERY_OBJCXX_LIBRARY(FALSE osquery_tables_objc
|
||||
../core/darwin/NSProcessInfo+PECocoaBackports.mm
|
||||
../core/darwin/NSProcessInfo+PECocoaBackports.h
|
||||
../core/darwin/PECocoaBackportsGlobal.h
|
||||
@ -9,7 +9,7 @@ if(APPLE)
|
||||
system/darwin/ca_certs.mm
|
||||
)
|
||||
|
||||
ADD_OSQUERY_LIBRARY(osquery_tables_darwin
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_tables_darwin
|
||||
events/darwin/passwd_changes.cpp
|
||||
events/darwin/hardware_events.cpp
|
||||
networking/darwin/routes.cpp
|
||||
@ -39,12 +39,12 @@ if(APPLE)
|
||||
system/darwin/xattr.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_LINK("-framework CoreFoundation")
|
||||
ADD_OSQUERY_LINK("-framework Security")
|
||||
ADD_OSQUERY_LINK("-framework OpenDirectory")
|
||||
ADD_OSQUERY_LINK("-framework DiskArbitration")
|
||||
ADD_OSQUERY_LINK(FALSE "-framework CoreFoundation")
|
||||
ADD_OSQUERY_LINK(FALSE "-framework Security")
|
||||
ADD_OSQUERY_LINK(FALSE "-framework OpenDirectory")
|
||||
ADD_OSQUERY_LINK(FALSE "-framework DiskArbitration")
|
||||
elseif(FREEBSD)
|
||||
ADD_OSQUERY_LIBRARY(osquery_tables_freebsd
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_tables_freebsd
|
||||
events/freebsd/passwd_changes.cpp
|
||||
networking/freebsd/routes.cpp
|
||||
system/freebsd/processes.cpp
|
||||
@ -52,7 +52,7 @@ elseif(FREEBSD)
|
||||
system/freebsd/groups.cpp
|
||||
)
|
||||
else()
|
||||
ADD_OSQUERY_LIBRARY(osquery_tables_linux
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_tables_linux
|
||||
events/linux/hardware_events.cpp
|
||||
events/linux/passwd_changes.cpp
|
||||
networking/linux/arp_cache.cpp
|
||||
@ -75,30 +75,30 @@ else()
|
||||
|
||||
if(CENTOS)
|
||||
# CentOS specific tables
|
||||
ADD_OSQUERY_LIBRARY(osquery_tables_redhat
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_tables_redhat
|
||||
system/linux/rpm_packages.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_LINK("rpm")
|
||||
ADD_OSQUERY_LINK("rpmio")
|
||||
ADD_OSQUERY_LINK(FALSE "rpm")
|
||||
ADD_OSQUERY_LINK(FALSE "rpmio")
|
||||
elseif(UBUNTU)
|
||||
# Ubuntu specific tables
|
||||
ADD_OSQUERY_LIBRARY(osquery_tables_ubuntu
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_tables_ubuntu
|
||||
system/linux/deb_packages.cpp
|
||||
system/linux/apt_sources.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_LINK("apt-pkg")
|
||||
ADD_OSQUERY_LINK("dpkg")
|
||||
ADD_OSQUERY_LINK(FALSE "apt-pkg")
|
||||
ADD_OSQUERY_LINK(FALSE "dpkg")
|
||||
endif()
|
||||
|
||||
ADD_OSQUERY_LINK("procps" "proc")
|
||||
ADD_OSQUERY_LINK("blkid")
|
||||
ADD_OSQUERY_LINK("udev")
|
||||
ADD_OSQUERY_LINK("uuid")
|
||||
ADD_OSQUERY_LINK(FALSE "procps" "proc")
|
||||
ADD_OSQUERY_LINK(FALSE "blkid")
|
||||
ADD_OSQUERY_LINK(FALSE "udev")
|
||||
ADD_OSQUERY_LINK(FALSE "uuid")
|
||||
endif()
|
||||
|
||||
ADD_OSQUERY_LIBRARY(osquery_tables
|
||||
ADD_OSQUERY_LIBRARY(FALSE osquery_tables
|
||||
networking/etc_hosts.cpp
|
||||
networking/etc_services.cpp
|
||||
networking/interfaces.cpp
|
||||
@ -113,18 +113,18 @@ ADD_OSQUERY_LIBRARY(osquery_tables
|
||||
system/logged_in_users.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_utility_tables
|
||||
ADD_OSQUERY_LIBRARY(TRUE osquery_utility_tables
|
||||
utility/time.cpp
|
||||
utility/hash.cpp
|
||||
utility/file.cpp
|
||||
utility/osquery.cpp
|
||||
)
|
||||
|
||||
ADD_OSQUERY_TEST(etc_hosts_tests networking/etc_hosts_tests.cpp TRUE)
|
||||
ADD_OSQUERY_TEST(FALSE etc_hosts_tests networking/etc_hosts_tests.cpp)
|
||||
if(APPLE)
|
||||
ADD_OSQUERY_TEST(xattr_tests system/darwin/xattr_tests.cpp TRUE)
|
||||
ADD_OSQUERY_TEST(apps_tests system/darwin/apps_tests.cpp TRUE)
|
||||
ADD_OSQUERY_TEST(ca_certs_tests system/darwin/ca_certs_tests.cpp TRUE)
|
||||
ADD_OSQUERY_TEST(firewall_tests system/darwin/firewall_tests.cpp TRUE)
|
||||
ADD_OSQUERY_TEST(launchd_tests system/darwin/launchd_tests.cpp TRUE)
|
||||
ADD_OSQUERY_TEST(FALSE xattr_tests system/darwin/xattr_tests.cpp)
|
||||
ADD_OSQUERY_TEST(FALSE apps_tests system/darwin/apps_tests.cpp)
|
||||
ADD_OSQUERY_TEST(FALSE ca_certs_tests system/darwin/ca_certs_tests.cpp)
|
||||
ADD_OSQUERY_TEST(FALSE firewall_tests system/darwin/firewall_tests.cpp)
|
||||
ADD_OSQUERY_TEST(FALSE launchd_tests system/darwin/launchd_tests.cpp)
|
||||
endif()
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include <osquery/events.h>
|
||||
#include <osquery/tables.h>
|
||||
|
||||
#include "osquery/core/virtual_table.h"
|
||||
|
||||
namespace osquery { namespace tables {
|
||||
{% for table in tables %}
|
||||
{{table}}
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include <osquery/events.h>
|
||||
#include <osquery/tables.h>
|
||||
|
||||
#include "osquery/core/virtual_table.h"
|
||||
|
||||
namespace osquery { namespace tables {
|
||||
|
||||
/// BEGIN[GENTABLE]
|
||||
|
Loading…
Reference in New Issue
Block a user