2017-12-19 00:04:06 +00:00
|
|
|
/**
|
2016-02-11 19:48:58 +00:00
|
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
2014-12-18 18:50:47 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
2017-12-19 00:04:06 +00:00
|
|
|
* 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.
|
2014-12-18 18:50:47 +00:00
|
|
|
*/
|
2015-02-05 00:54:44 +00:00
|
|
|
|
2017-10-30 05:25:49 +00:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstring>
|
2015-02-05 00:54:44 +00:00
|
|
|
|
2016-07-01 21:56:07 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
|
|
|
|
2016-03-11 08:30:20 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
2016-07-14 21:15:32 +00:00
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
|
|
|
|
2014-12-03 23:14:02 +00:00
|
|
|
#include <osquery/core.h>
|
2016-03-20 23:05:13 +00:00
|
|
|
#include <osquery/database.h>
|
2015-05-11 08:21:57 +00:00
|
|
|
#include <osquery/extensions.h>
|
2015-11-22 04:36:32 +00:00
|
|
|
#include <osquery/flags.h>
|
2016-07-14 21:15:32 +00:00
|
|
|
#include <osquery/logger.h>
|
2016-07-07 22:16:28 +00:00
|
|
|
#include <osquery/system.h>
|
2015-03-18 19:01:58 +00:00
|
|
|
|
2016-07-07 22:16:28 +00:00
|
|
|
#include "osquery/core/process.h"
|
2016-09-02 22:04:03 +00:00
|
|
|
#include "osquery/core/utils.h"
|
2015-05-11 08:21:57 +00:00
|
|
|
#include "osquery/core/watcher.h"
|
2015-03-18 19:01:58 +00:00
|
|
|
#include "osquery/devtools/devtools.h"
|
2017-08-27 18:09:25 +00:00
|
|
|
#include "osquery/dispatcher/distributed.h"
|
2018-02-11 09:48:24 +00:00
|
|
|
#include "osquery/dispatcher/io_service.h"
|
2017-08-27 18:09:25 +00:00
|
|
|
#include "osquery/dispatcher/scheduler.h"
|
2016-07-01 21:56:07 +00:00
|
|
|
#include "osquery/filesystem/fileops.h"
|
2017-08-27 18:09:25 +00:00
|
|
|
#include "osquery/main/main.h"
|
2015-11-22 04:36:32 +00:00
|
|
|
#include "osquery/sql/sqlite_util.h"
|
|
|
|
|
2018-05-02 03:47:22 +00:00
|
|
|
namespace fs = boost::filesystem;
|
|
|
|
|
2015-11-22 04:36:32 +00:00
|
|
|
namespace osquery {
|
|
|
|
|
|
|
|
SHELL_FLAG(int32,
|
|
|
|
profile,
|
|
|
|
0,
|
|
|
|
"Enable profile mode when non-0, set number of iterations");
|
2017-08-27 18:09:25 +00:00
|
|
|
|
2015-11-22 04:36:32 +00:00
|
|
|
HIDDEN_FLAG(int32,
|
|
|
|
profile_delay,
|
|
|
|
0,
|
|
|
|
"Sleep a number of seconds before and after the profiling");
|
2016-03-20 23:05:13 +00:00
|
|
|
|
2017-08-27 18:09:25 +00:00
|
|
|
CLI_FLAG(bool, install, false, "Install osqueryd as a service");
|
|
|
|
|
|
|
|
CLI_FLAG(bool, uninstall, false, "Uninstall osqueryd as a service");
|
|
|
|
|
2016-03-20 23:05:13 +00:00
|
|
|
DECLARE_bool(disable_caching);
|
2017-08-27 18:09:25 +00:00
|
|
|
|
|
|
|
const std::string kWatcherWorkerName{"osqueryd: worker"};
|
2015-11-22 04:36:32 +00:00
|
|
|
|
2016-10-19 17:25:32 +00:00
|
|
|
int profile(int argc, char* argv[]) {
|
2015-11-22 04:36:32 +00:00
|
|
|
std::string query;
|
2016-07-01 21:56:07 +00:00
|
|
|
if (!osquery::platformIsatty(stdin)) {
|
2015-11-22 04:36:32 +00:00
|
|
|
std::getline(std::cin, query);
|
|
|
|
} else if (argc < 2) {
|
|
|
|
// No query input provided via stdin or as a positional argument.
|
|
|
|
fprintf(stderr, "No query provided via stdin or args to profile...\n");
|
|
|
|
return 2;
|
|
|
|
} else {
|
|
|
|
query = std::string(argv[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (osquery::FLAGS_profile_delay > 0) {
|
2016-08-11 14:49:55 +00:00
|
|
|
osquery::sleepFor(osquery::FLAGS_profile_delay * 1000);
|
2015-11-22 04:36:32 +00:00
|
|
|
}
|
|
|
|
|
2016-03-20 23:05:13 +00:00
|
|
|
// Perform some duplication from Initializer with respect to database setup.
|
|
|
|
osquery::DatabasePlugin::setAllowOpen(true);
|
2017-01-07 20:21:35 +00:00
|
|
|
osquery::RegistryFactory::get().setActive("database", "ephemeral");
|
2016-03-20 23:05:13 +00:00
|
|
|
|
2015-11-22 04:36:32 +00:00
|
|
|
auto dbc = osquery::SQLiteDBManager::get();
|
|
|
|
for (size_t i = 0; i < static_cast<size_t>(osquery::FLAGS_profile); ++i) {
|
|
|
|
osquery::QueryData results;
|
2017-10-24 18:40:26 +00:00
|
|
|
auto status = osquery::queryInternal(query, results, dbc);
|
2016-02-25 01:58:58 +00:00
|
|
|
dbc->clearAffectedTables();
|
2015-11-22 04:36:32 +00:00
|
|
|
if (!status) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Query failed (%d): %s\n",
|
|
|
|
status.getCode(),
|
|
|
|
status.what().c_str());
|
|
|
|
return status.getCode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (osquery::FLAGS_profile_delay > 0) {
|
2016-08-15 15:30:20 +00:00
|
|
|
osquery::sleepFor(osquery::FLAGS_profile_delay * 1000);
|
2015-11-22 04:36:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2015-02-05 01:53:27 +00:00
|
|
|
|
2017-08-27 18:09:25 +00:00
|
|
|
int startDaemon(Initializer& runner) {
|
|
|
|
runner.start();
|
2016-02-09 05:50:08 +00:00
|
|
|
|
2017-08-27 18:09:25 +00:00
|
|
|
// Conditionally begin the distributed query service
|
|
|
|
auto s = startDistributed();
|
|
|
|
if (!s.ok()) {
|
|
|
|
VLOG(1) << "Not starting the distributed query service: " << s.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Begin the schedule runloop.
|
|
|
|
startScheduler();
|
|
|
|
|
|
|
|
// Finally wait for a signal / interrupt to shutdown.
|
|
|
|
runner.waitForShutdown();
|
|
|
|
return 0;
|
|
|
|
}
|
2016-02-09 05:50:08 +00:00
|
|
|
|
2017-08-27 18:09:25 +00:00
|
|
|
int startShell(osquery::Initializer& runner, int argc, char* argv[]) {
|
2016-02-09 05:50:08 +00:00
|
|
|
// Check for shell-specific switches and positional arguments.
|
2016-08-11 14:49:55 +00:00
|
|
|
if (argc > 1 || !osquery::platformIsatty(stdin) ||
|
2017-10-30 05:25:49 +00:00
|
|
|
!osquery::FLAGS_A.empty() || !osquery::FLAGS_pack.empty() ||
|
2016-08-11 14:49:55 +00:00
|
|
|
osquery::FLAGS_L || osquery::FLAGS_profile > 0) {
|
2015-11-22 04:36:32 +00:00
|
|
|
// A query was set as a positional argument, via stdin, or profiling is on.
|
2015-04-27 23:40:05 +00:00
|
|
|
osquery::FLAGS_disable_events = true;
|
2016-03-20 23:05:13 +00:00
|
|
|
osquery::FLAGS_disable_caching = true;
|
2015-05-11 08:21:57 +00:00
|
|
|
// The shell may have loaded table extensions, if not, disable the manager.
|
2017-10-16 20:46:14 +00:00
|
|
|
if (!osquery::Watcher::get().hasManagedExtensions() &&
|
|
|
|
Flag::isDefault("disable_extensions")) {
|
2015-05-11 08:21:57 +00:00
|
|
|
osquery::FLAGS_disable_extensions = true;
|
|
|
|
}
|
2015-04-27 23:40:05 +00:00
|
|
|
}
|
|
|
|
|
2015-11-22 04:36:32 +00:00
|
|
|
int retcode = 0;
|
|
|
|
if (osquery::FLAGS_profile <= 0) {
|
|
|
|
runner.start();
|
2014-09-23 01:35:12 +00:00
|
|
|
|
2015-11-22 04:36:32 +00:00
|
|
|
// Virtual tables will be attached to the shell's in-memory SQLite DB.
|
|
|
|
retcode = osquery::launchIntoShell(argc, argv);
|
2016-03-20 23:05:13 +00:00
|
|
|
// Finally shutdown.
|
|
|
|
runner.requestShutdown();
|
2015-11-22 04:36:32 +00:00
|
|
|
} else {
|
|
|
|
retcode = profile(argc, argv);
|
|
|
|
}
|
2014-09-23 01:35:12 +00:00
|
|
|
return retcode;
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
2017-08-27 18:09:25 +00:00
|
|
|
|
|
|
|
int startOsquery(int argc, char* argv[], std::function<void()> shutdown) {
|
|
|
|
// Parse/apply flags, start registry, load logger/config plugins.
|
|
|
|
osquery::Initializer runner(argc, argv, osquery::ToolType::SHELL_DAEMON);
|
|
|
|
|
|
|
|
// Options for installing or uninstalling the osqueryd as a service
|
|
|
|
if (FLAGS_install) {
|
2018-05-02 03:47:22 +00:00
|
|
|
auto binPath = fs::system_complete(fs::path(argv[0]));
|
|
|
|
if (!installService(binPath.string())) {
|
2017-08-27 18:09:25 +00:00
|
|
|
LOG(ERROR) << "Unable to install the osqueryd service";
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
} else if (FLAGS_uninstall) {
|
|
|
|
if (!uninstallService()) {
|
|
|
|
LOG(ERROR) << "Unable to uninstall the osqueryd service";
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
runner.installShutdown(shutdown);
|
|
|
|
runner.initDaemon();
|
|
|
|
|
|
|
|
// When a watchdog is used, the current daemon will fork/exec into a worker.
|
|
|
|
// In either case the watcher may start optionally loaded extensions.
|
|
|
|
runner.initWorkerWatcher(kWatcherWorkerName);
|
|
|
|
|
2018-02-11 09:48:24 +00:00
|
|
|
// Begin adhoc io service thread.
|
|
|
|
startIOService();
|
|
|
|
|
2017-08-27 18:09:25 +00:00
|
|
|
if (runner.isDaemon()) {
|
|
|
|
return startDaemon(runner);
|
|
|
|
}
|
|
|
|
return startShell(runner, argc, argv);
|
|
|
|
}
|
|
|
|
} // namespace osquery
|