Added custom path functions (#4265)

This commit is contained in:
Max Kareta 2018-05-24 12:26:43 +01:00 committed by GitHub
parent 584c5ddcbd
commit 6047e7d6f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 231 additions and 48 deletions

View File

@ -8,6 +8,7 @@ set(OSQUERY_SQL_INTERNAL
"sqlite_hashing.cpp"
"sqlite_encoding.cpp"
"virtual_table.cpp"
"sqlite_filesystem.cpp"
"virtual_sqlite_table.cpp"
)

View File

@ -75,7 +75,7 @@ void registerEncodingExtensions(sqlite3* db) {
sqlite3_create_function(db,
"conditional_to_base64",
1,
SQLITE_UTF8,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
sqliteB64ConditionalEncFunc,
nullptr,
@ -83,7 +83,7 @@ void registerEncodingExtensions(sqlite3* db) {
sqlite3_create_function(db,
"to_base64",
1,
SQLITE_UTF8,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
sqliteB64EncFunc,
nullptr,
@ -91,10 +91,10 @@ void registerEncodingExtensions(sqlite3* db) {
sqlite3_create_function(db,
"from_base64",
1,
SQLITE_UTF8,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
sqliteB64DecFunc,
nullptr,
nullptr);
}
}
} // namespace osquery

View File

@ -0,0 +1,164 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
#include <sqlite3.h>
namespace osquery {
static boost::optional<std::string> findExistingProgramPathFromCommand(
const char* path, char escape_symbol, bool allow_quoting, bool shortest) {
size_t length = strlen(path);
std::string result;
size_t pos = 0;
// Skip spaces
for (; pos < length; ++pos) {
if (!isspace(path[pos])) {
break;
}
}
std::string temp_string;
bool is_quoted = false;
bool is_escaped = false;
for (; pos < length; ++pos) {
if (is_escaped) {
temp_string += path[pos];
is_escaped = false;
continue;
}
if (allow_quoting && path[pos] == '"') {
is_quoted = !is_quoted;
continue;
}
if (path[pos] == escape_symbol) {
is_escaped = true;
continue;
}
if (!is_quoted && isspace(path[pos])) {
// validate temp string
boost::filesystem::path test_path = temp_string;
auto status = boost::filesystem::status(test_path);
if (boost::filesystem::exists(status) &&
!boost::filesystem::is_directory(status)) {
result = temp_string;
if (shortest) {
break;
}
}
}
temp_string += path[pos];
}
if (result.length() == 0 || !shortest) {
boost::filesystem::path test_path = temp_string;
auto status = boost::filesystem::status(test_path);
if (boost::filesystem::exists(status) &&
!boost::filesystem::is_directory(status)) {
result = temp_string;
}
}
return result;
}
static boost::optional<std::string> findExistingProgramPathFromCommandSqlArgs(
int argc, sqlite3_value** argv, bool shortest) {
if (argc == 0) {
return boost::none;
}
// NULLs are not allowed
for (int i = 0; i < argc; i++) {
if (SQLITE_NULL == sqlite3_value_type(argv[i])) {
return boost::none;
}
}
const char* path = reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
bool allow_quoting = false;
if (argc > 1) {
allow_quoting = sqlite3_value_int(argv[1]) != 0 ? true : false;
}
#ifdef WIN32
char escape_symbol = '^';
#else
char escape_symbol = '\\';
#endif
if (argc > 2) {
const char* escape_symbol_string =
reinterpret_cast<const char*>(sqlite3_value_text(argv[2]));
if (escape_symbol_string == NULL ||
std::strlen(escape_symbol_string) != 1) {
return boost::none;
}
escape_symbol = escape_symbol_string[0];
}
return findExistingProgramPathFromCommand(
path, escape_symbol, allow_quoting, shortest);
}
static void findFilePathInLaunchCommand(sqlite3_context* context,
int argc,
sqlite3_value** argv) {
auto result = findExistingProgramPathFromCommandSqlArgs(argc, argv, true);
if (result) {
sqlite3_result_text(context,
result->c_str(),
static_cast<int>(result->size()),
SQLITE_TRANSIENT);
} else {
sqlite3_result_error(
context, "Invalid inputs to find_binary_path_from_cmd", -1);
}
}
static void isPathDeterministic(sqlite3_context* context,
int argc,
sqlite3_value** argv) {
auto shortest = findExistingProgramPathFromCommandSqlArgs(argc, argv, true);
if (shortest) {
const char* path = (const char*)sqlite3_value_text(argv[0]);
if (shortest->length() == 0 || shortest->length() == strlen(path)) {
// There are 2 cases:
// 1 - empty string, all parts of path are invalid,
// so path is deterministic
// 2 - short == full, then there is only 1 valid path
sqlite3_result_int(context, 1);
return;
} else {
auto longest =
findExistingProgramPathFromCommandSqlArgs(argc, argv, false);
if (longest) {
sqlite3_result_int(context,
shortest->length() == longest->length() ? 1 : 0);
return;
}
}
}
sqlite3_result_error(context, "Invalid inputs to is_path_deterministic", -1);
}
void registerFilesystemExtensions(sqlite3* db) {
sqlite3_create_function(db,
"is_path_deterministic",
-1,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
isPathDeterministic,
nullptr,
nullptr);
sqlite3_create_function(db,
"find_file_path_in_cmd",
-1,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
findFilePathInLaunchCommand,
nullptr,
nullptr);
}
} // namespace osquery

View File

@ -58,17 +58,29 @@ static void sqliteSHA256Func(sqlite3_context* context,
}
void registerHashingExtensions(sqlite3* db) {
sqlite3_create_function(
db, "md5", 1, SQLITE_UTF8, nullptr, sqliteMD5Func, nullptr, nullptr);
sqlite3_create_function(
db, "sha1", 1, SQLITE_UTF8, nullptr, sqliteSHA1Func, nullptr, nullptr);
sqlite3_create_function(db,
"md5",
1,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
sqliteMD5Func,
nullptr,
nullptr);
sqlite3_create_function(db,
"sha1",
1,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
sqliteSHA1Func,
nullptr,
nullptr);
sqlite3_create_function(db,
"sha256",
1,
SQLITE_UTF8,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
sqliteSHA256Func,
nullptr,
nullptr);
}
}
} // namespace osquery

View File

@ -52,9 +52,9 @@ using DoubleDoubleFunction = std::function<double(double)>;
/**
* @brief Call a math function that takes a double and returns a double.
*/
static void callDoubleFunc(sqlite3_context *context,
static void callDoubleFunc(sqlite3_context* context,
int argc,
sqlite3_value **argv,
sqlite3_value** argv,
DoubleDoubleFunction f) {
double rVal = 0.0, val;
assert(argc == 1);
@ -75,27 +75,27 @@ static void callDoubleFunc(sqlite3_context *context,
}
}
static void sinFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void sinFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, SIN_FUNC);
}
static void cosFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void cosFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, COS_FUNC);
}
static void tanFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void tanFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, TAN_FUNC);
}
static void asinFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void asinFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, ASIN_FUNC);
}
static void acosFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void acosFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, ACOS_FUNC);
}
static void atanFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void atanFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, ATAN_FUNC);
}
@ -103,31 +103,31 @@ static double cot(double x) {
return 1.0 / tan(x);
}
static void cotFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void cotFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, cot);
}
static void logFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void logFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, LOG_FUNC);
}
static void log10Func(sqlite3_context *context,
static void log10Func(sqlite3_context* context,
int argc,
sqlite3_value **argv) {
sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, LOG10_FUNC);
}
static void sqrtFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void sqrtFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, SQRT_FUNC);
}
static void expFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void expFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, EXP_FUNC);
}
static void powerFunc(sqlite3_context *context,
static void powerFunc(sqlite3_context* context,
int argc,
sqlite3_value **argv) {
sqlite3_value** argv) {
assert(argc == 2);
if (sqlite3_value_type(argv[0]) == SQLITE_NULL ||
@ -146,9 +146,9 @@ static void powerFunc(sqlite3_context *context,
}
}
static void callCastedDoubleFunc(sqlite3_context *context,
static void callCastedDoubleFunc(sqlite3_context* context,
int argc,
sqlite3_value **argv,
sqlite3_value** argv,
DoubleDoubleFunction f) {
double rVal = 0.0;
assert(argc == 1);
@ -168,13 +168,13 @@ static void callCastedDoubleFunc(sqlite3_context *context,
}
}
static void ceilFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void ceilFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
callCastedDoubleFunc(context, argc, argv, CEIL_FUNC);
}
static void floorFunc(sqlite3_context *context,
static void floorFunc(sqlite3_context* context,
int argc,
sqlite3_value **argv) {
sqlite3_value** argv) {
callCastedDoubleFunc(context, argc, argv, FLOOR_FUNC);
}
@ -188,29 +188,29 @@ static double rad2deg(double x) {
return 180.0 * x / M_PI;
}
static void rad2degFunc(sqlite3_context *context,
static void rad2degFunc(sqlite3_context* context,
int argc,
sqlite3_value **argv) {
sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, rad2deg);
}
static void deg2radFunc(sqlite3_context *context,
static void deg2radFunc(sqlite3_context* context,
int argc,
sqlite3_value **argv) {
sqlite3_value** argv) {
callDoubleFunc(context, argc, argv, deg2rad);
}
static void piFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
static void piFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
sqlite3_result_double(context, M_PI);
}
struct FuncDef {
const char *zFunctionName;
const char* zFunctionName;
int nArg;
void (*xFunc)(sqlite3_context *, int, sqlite3_value **);
void (*xFunc)(sqlite3_context*, int, sqlite3_value**);
};
void registerMathExtensions(sqlite3 *db) {
void registerMathExtensions(sqlite3* db) {
// This approach to adding non-standard Math functions was inspired by the
// somewhat deprecated/legacy work by Liam Healy from 2010 in the extension
// functions contribution.
@ -238,11 +238,11 @@ void registerMathExtensions(sqlite3 *db) {
sqlite3_create_function(db,
aFuncs[i].zFunctionName,
aFuncs[i].nArg,
SQLITE_UTF8,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
aFuncs[i].xFunc,
nullptr,
nullptr);
}
}
}
} // namespace osquery

View File

@ -68,4 +68,4 @@ void registerOperationExtensions(sqlite3* db) {
addCarveFile,
executeCarve);
}
}
} // namespace osquery

View File

@ -156,7 +156,7 @@ void registerStringExtensions(sqlite3* db) {
sqlite3_create_function(db,
"split",
3,
SQLITE_UTF8,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
tokenStringSplitFunc,
nullptr,
@ -164,7 +164,7 @@ void registerStringExtensions(sqlite3* db) {
sqlite3_create_function(db,
"regex_split",
3,
SQLITE_UTF8,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
regexStringSplitFunc,
nullptr,
@ -172,10 +172,10 @@ void registerStringExtensions(sqlite3* db) {
sqlite3_create_function(db,
"inet_aton",
1,
SQLITE_UTF8,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
nullptr,
ip4StringToDecimalFunc,
nullptr,
nullptr);
}
}
} // namespace osquery

View File

@ -236,6 +236,7 @@ static inline void openOptimized(sqlite3*& db) {
#if !defined(SKIP_CARVER)
registerOperationExtensions(db);
#endif
registerFilesystemExtensions(db);
registerHashingExtensions(db);
registerEncodingExtensions(db);
}
@ -549,4 +550,4 @@ Status getQueryColumnsInternal(const std::string& q,
return status;
}
}
} // namespace osquery

View File

@ -405,6 +405,11 @@ void registerOperationExtensions(sqlite3* db);
*/
void registerEncodingExtensions(sqlite3* db);
/**
* @brief Register filesystem-related 'custom' functions.
*/
void registerFilesystemExtensions(sqlite3* db);
/**
* @brief Generate the data for auto-constructed sqlite tables
*
@ -419,4 +424,4 @@ void registerEncodingExtensions(sqlite3* db);
Status genQueryDataForSqliteTable(const boost::filesystem::path& sqlite_db,
const std::string& sqlite_query,
QueryData& results);
}
} // namespace osquery