/* * 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 #include #include #include #include #include namespace osquery { namespace tables { const std::string kSystemCron = "/etc/crontab"; const std::vector kUserCronPaths = { "/var/at/tabs/", "/var/spool/cron/", "/var/spool/cron/crontabs/", }; std::vector cronFromFile(const std::string& path) { std::string content; std::vector cron_lines; if (!isReadable(path).ok()) { return cron_lines; } if (!readFile(path, content).ok()) { return cron_lines; } auto lines = split(content, "\n"); // Only populate the lines that are not comments or blank. for (auto& line : lines) { // Cheat and use a non-const iteration, to inline trim. boost::trim(line); if (line.size() > 0 && line.at(0) != '#') { cron_lines.push_back(line); } } return cron_lines; } void genCronLine(const std::string& path, const std::string& line, QueryData& results) { Row r; r["path"] = path; auto columns = split(line, " \t"); size_t index = 0; auto iterator = columns.begin(); for (; iterator != columns.end(); ++iterator) { if (index == 0) { if ((*iterator).at(0) == '@') { // If the first value is an 'at' then skip to the command. r["event"] = *iterator; index = 5; continue; } r["minute"] = *iterator; } else if (index == 1) { r["hour"] = *iterator; } else if (index == 2) { r["day_of_month"] = *iterator; } else if (index == 3) { r["month"] = *iterator; } else if (index == 4) { r["day_of_week"] = *iterator; } else if (index == 5) { r["command"] = *iterator; } else { // Long if switch to handle command breaks from space delim. r["command"] += " " + *iterator; } index++; } if (r["command"].size() == 0) { // The line was not well-formed, perhaps it was a variable? return; } results.push_back(r); } QueryData genCronTab(QueryContext& context) { QueryData results; auto system_lines = cronFromFile(kSystemCron); for (const auto& line : system_lines) { genCronLine(kSystemCron, line, results); } std::vector user_crons; for (const auto cron_path : kUserCronPaths) { osquery::listFilesInDirectory(cron_path, user_crons); } // The user-based crons are identified by their path. for (const auto& user_path : user_crons) { auto user_lines = cronFromFile(user_path); for (const auto& line : user_lines) { genCronLine(user_path, line, results); } } return results; } } }