2014-12-18 18:50:47 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
2015-01-09 01:01:40 +00:00
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
2014-12-18 18:50:47 +00:00
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*
|
|
|
|
*/
|
2014-08-21 21:35:51 +00:00
|
|
|
|
2014-12-09 07:52:38 +00:00
|
|
|
#include <sstream>
|
|
|
|
|
2014-11-18 02:42:36 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <signal.h>
|
|
|
|
|
2014-11-13 20:09:07 +00:00
|
|
|
#if !defined(__FreeBSD__)
|
2014-11-04 02:08:13 +00:00
|
|
|
#include <uuid/uuid.h>
|
2014-11-13 20:09:07 +00:00
|
|
|
#endif
|
2014-08-21 21:35:51 +00:00
|
|
|
|
|
|
|
#include <boost/algorithm/string/trim.hpp>
|
2014-11-04 19:39:15 +00:00
|
|
|
#include <boost/filesystem.hpp>
|
2014-11-25 20:30:29 +00:00
|
|
|
#include <boost/lexical_cast.hpp>
|
2014-11-04 02:08:13 +00:00
|
|
|
#include <boost/uuid/uuid.hpp>
|
|
|
|
#include <boost/uuid/uuid_generators.hpp>
|
|
|
|
#include <boost/uuid/uuid_io.hpp>
|
2014-11-04 19:39:15 +00:00
|
|
|
|
2014-12-03 23:14:02 +00:00
|
|
|
#include <osquery/core.h>
|
|
|
|
#include <osquery/database/db_handle.h>
|
|
|
|
#include <osquery/filesystem.h>
|
2015-01-21 21:36:55 +00:00
|
|
|
#include <osquery/logger.h>
|
2014-12-03 23:14:02 +00:00
|
|
|
#include <osquery/sql.h>
|
2014-11-04 19:39:15 +00:00
|
|
|
|
|
|
|
namespace fs = boost::filesystem;
|
2014-08-21 21:35:51 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
2014-11-18 02:42:36 +00:00
|
|
|
/// The path to the pidfile for osqueryd
|
|
|
|
DEFINE_osquery_flag(string,
|
2014-11-18 03:17:07 +00:00
|
|
|
pidfile,
|
2014-11-18 02:42:36 +00:00
|
|
|
"/var/osquery/osqueryd.pidfile",
|
|
|
|
"The path to the pidfile for osqueryd.");
|
|
|
|
|
2014-08-21 21:35:51 +00:00
|
|
|
std::string getHostname() {
|
2014-11-22 01:08:33 +00:00
|
|
|
char hostname[256]; // Linux max should be 64.
|
2015-01-09 01:01:40 +00:00
|
|
|
memset(hostname, 0, sizeof(hostname));
|
|
|
|
gethostname(hostname, sizeof(hostname) - 1);
|
2014-08-21 21:35:51 +00:00
|
|
|
std::string hostname_string = std::string(hostname);
|
|
|
|
boost::algorithm::trim(hostname_string);
|
|
|
|
return hostname_string;
|
|
|
|
}
|
|
|
|
|
2014-11-04 02:08:13 +00:00
|
|
|
std::string generateNewUuid() {
|
|
|
|
boost::uuids::uuid uuid = boost::uuids::random_generator()();
|
|
|
|
return boost::uuids::to_string(uuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string generateHostUuid() {
|
|
|
|
#ifdef __APPLE__
|
|
|
|
// Use the hardware uuid available on OSX to identify this machine
|
|
|
|
char uuid[128];
|
2015-01-09 01:01:40 +00:00
|
|
|
memset(uuid, 0, sizeof(uuid));
|
2014-11-04 02:08:13 +00:00
|
|
|
uuid_t id;
|
|
|
|
// wait at most 5 seconds for gethostuuid to return
|
|
|
|
const timespec wait = {5, 0};
|
|
|
|
int result = gethostuuid(id, &wait);
|
|
|
|
if (result == 0) {
|
|
|
|
char out[128];
|
|
|
|
uuid_unparse(id, out);
|
|
|
|
std::string uuid_string = std::string(out);
|
|
|
|
boost::algorithm::trim(uuid_string);
|
|
|
|
return uuid_string;
|
|
|
|
} else {
|
|
|
|
// unable to get the hardware uuid, just return a new uuid
|
|
|
|
return generateNewUuid();
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
return generateNewUuid();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-08-21 21:35:51 +00:00
|
|
|
std::string getAsciiTime() {
|
|
|
|
std::time_t result = std::time(NULL);
|
|
|
|
std::string time_str = std::string(std::asctime(std::localtime(&result)));
|
|
|
|
boost::algorithm::trim(time_str);
|
|
|
|
return time_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getUnixTime() {
|
|
|
|
std::time_t result = std::time(NULL);
|
|
|
|
return result;
|
|
|
|
}
|
2014-11-04 19:39:15 +00:00
|
|
|
|
|
|
|
std::vector<fs::path> getHomeDirectories() {
|
2014-11-22 01:08:33 +00:00
|
|
|
auto sql = SQL(
|
|
|
|
"SELECT DISTINCT directory FROM users WHERE directory != '/var/empty';");
|
2014-11-04 19:39:15 +00:00
|
|
|
std::vector<fs::path> results;
|
|
|
|
if (sql.ok()) {
|
2014-11-22 01:08:33 +00:00
|
|
|
for (const auto& row : sql.rows()) {
|
2014-11-04 19:39:15 +00:00
|
|
|
results.push_back(row.at("directory"));
|
|
|
|
}
|
|
|
|
} else {
|
2014-11-22 01:08:33 +00:00
|
|
|
LOG(ERROR)
|
|
|
|
<< "Error executing query to return users: " << sql.getMessageString();
|
2014-11-04 19:39:15 +00:00
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
2014-11-18 02:42:36 +00:00
|
|
|
|
2015-01-07 23:22:50 +00:00
|
|
|
Status checkStalePid(const std::string& pidfile_content) {
|
|
|
|
int pid;
|
|
|
|
try {
|
|
|
|
pid = stoi(pidfile_content);
|
|
|
|
} catch (const std::invalid_argument& e) {
|
|
|
|
return Status(1, std::string("Could not parse pidfile: ") + e.what());
|
|
|
|
}
|
|
|
|
|
|
|
|
int status = kill(pid, 0);
|
|
|
|
if (status != ESRCH) {
|
|
|
|
// The pid is running, check if it is an osqueryd process by name.
|
|
|
|
std::stringstream query_text;
|
|
|
|
query_text << "SELECT name FROM processes WHERE pid = " << pid << ";";
|
|
|
|
auto q = SQL(query_text.str());
|
|
|
|
if (!q.ok()) {
|
|
|
|
return Status(1, "Error querying processes: " + q.getMessageString());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (q.rows().size() >= 1 && q.rows().front()["name"] == "osqueryd") {
|
|
|
|
// If the process really is osqueryd, return an "error" status.
|
|
|
|
return Status(1,
|
|
|
|
std::string("osqueryd (") + pidfile_content +
|
|
|
|
") is already running");
|
|
|
|
} else {
|
|
|
|
LOG(INFO) << "Found stale process for osqueryd (" << pidfile_content
|
|
|
|
<< ") removing pidfile.";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now the pidfile is either the wrong pid or the pid is not running.
|
|
|
|
try {
|
|
|
|
boost::filesystem::remove(FLAGS_pidfile);
|
|
|
|
} catch (boost::filesystem::filesystem_error& e) {
|
|
|
|
// Unable to remove old pidfile.
|
|
|
|
LOG(WARNING) << "Unable to remove the osqueryd pidfile.";
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
2014-11-18 02:42:36 +00:00
|
|
|
Status createPidFile() {
|
|
|
|
// check if pidfile exists
|
2014-11-18 03:17:07 +00:00
|
|
|
auto exists = pathExists(FLAGS_pidfile);
|
2014-11-18 03:25:06 +00:00
|
|
|
if (exists.ok()) {
|
2015-01-07 23:22:50 +00:00
|
|
|
// if it exists, check if that pid is running.
|
2014-11-18 02:42:36 +00:00
|
|
|
std::string content;
|
2014-11-18 03:17:07 +00:00
|
|
|
auto read_status = readFile(FLAGS_pidfile, content);
|
2014-11-18 02:42:36 +00:00
|
|
|
if (!read_status.ok()) {
|
|
|
|
return Status(1, "Could not read pidfile: " + read_status.toString());
|
|
|
|
}
|
|
|
|
|
2015-01-07 23:22:50 +00:00
|
|
|
auto stale_status = checkStalePid(content);
|
|
|
|
if (!stale_status.ok()) {
|
|
|
|
return stale_status;
|
2014-11-18 02:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-07 23:22:50 +00:00
|
|
|
|
|
|
|
// If no pidfile exists or the existing pid was stale, write, log, and run.
|
|
|
|
auto pid = boost::lexical_cast<std::string>(getpid());
|
|
|
|
LOG(INFO) << "Writing osqueryd pid (" << pid << ") to " << FLAGS_pidfile;
|
|
|
|
auto status = writeTextFile(FLAGS_pidfile, pid, 0644);
|
|
|
|
return status;
|
2014-11-18 02:42:36 +00:00
|
|
|
}
|
2014-08-21 21:35:51 +00:00
|
|
|
}
|