2015-03-09 05:21:58 +00:00
|
|
|
/*
|
|
|
|
* 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/logger.h>
|
2015-04-02 21:03:36 +00:00
|
|
|
#include <osquery/tables/applications/browser_utils.h>
|
2015-03-09 05:21:58 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
namespace tables {
|
|
|
|
|
2015-04-02 21:03:36 +00:00
|
|
|
#define kManifestFile "/manifest.json"
|
2015-03-09 05:21:58 +00:00
|
|
|
|
2015-04-02 21:03:36 +00:00
|
|
|
const std::map<std::string, std::string> kExtensionKeys = {
|
2015-03-09 05:21:58 +00:00
|
|
|
{"version", "version"},
|
|
|
|
{"name", "name"},
|
|
|
|
{"description", "description"},
|
|
|
|
{"default_locale", "locale"},
|
|
|
|
{"update_url", "update_url"},
|
|
|
|
{"author", "author"},
|
|
|
|
{"background.persistent", "persistent"},
|
|
|
|
};
|
|
|
|
|
2015-04-02 21:03:36 +00:00
|
|
|
void genExtension(const std::string& path, QueryData& results) {
|
2015-03-09 05:21:58 +00:00
|
|
|
std::string json_data;
|
2015-04-02 21:03:36 +00:00
|
|
|
if (!readFile(path + kManifestFile, json_data).ok()) {
|
|
|
|
VLOG(1) << "Could not read file: " << path + kManifestFile;
|
2015-03-09 05:21:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the extensions data into a JSON blob, then property tree.
|
|
|
|
pt::ptree tree;
|
|
|
|
std::stringstream json_stream;
|
|
|
|
json_stream << json_data;
|
|
|
|
try {
|
|
|
|
pt::read_json(json_stream, tree);
|
|
|
|
} catch (const pt::json_parser::json_parser_error& e) {
|
2015-04-02 21:03:36 +00:00
|
|
|
VLOG(1) << "Could not parse JSON from: " << path + kManifestFile;
|
2015-03-09 05:21:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Row r;
|
|
|
|
// Most of the keys are in the top-level JSON dictionary.
|
2015-04-02 21:03:36 +00:00
|
|
|
for (const auto& it : kExtensionKeys) {
|
2015-03-09 05:21:58 +00:00
|
|
|
try {
|
|
|
|
r[it.second] = tree.get<std::string>(it.first);
|
|
|
|
} catch (const pt::ptree_error& e) {
|
|
|
|
r[it.second] = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert JSON bool-types to an integer.
|
|
|
|
if (r[it.second] == "true") {
|
|
|
|
r[it.second] = INTEGER(1);
|
|
|
|
} else if (r[it.second] == "false") {
|
|
|
|
r[it.second] = INTEGER(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the default persistence setting to false
|
|
|
|
if (r.at("persistent") == "") {
|
|
|
|
r["persistent"] = INTEGER(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
r["identifier"] = fs::path(path).parent_path().leaf().string();
|
|
|
|
r["path"] = path;
|
|
|
|
results.push_back(r);
|
|
|
|
}
|
|
|
|
|
2015-04-02 21:03:36 +00:00
|
|
|
QueryData genChromeBasedExtensions(QueryContext& context, const fs::path sub_dir) {
|
2015-03-09 05:21:58 +00:00
|
|
|
QueryData results;
|
|
|
|
|
|
|
|
auto homes = osquery::getHomeDirectories();
|
|
|
|
for (const auto& home : homes) {
|
2015-04-02 21:03:36 +00:00
|
|
|
// For each user, enumerate all of their opera profiles.
|
2015-03-09 05:21:58 +00:00
|
|
|
std::vector<std::string> extensions;
|
2015-04-02 21:03:36 +00:00
|
|
|
fs::path extension_path = home.string() + sub_dir.string();
|
2015-03-09 05:21:58 +00:00
|
|
|
if (!listDirectoriesInDirectory(extension_path, extensions).ok()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate an addons list from their extensions JSON.
|
|
|
|
for (const auto& extension : extensions) {
|
|
|
|
std::vector<std::string> versions;
|
|
|
|
if (!listDirectoriesInDirectory(extension, versions).ok()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extensions use /<ID>/<VERSION>/manifest.json.
|
|
|
|
for (const auto& version : versions) {
|
2015-04-02 21:03:36 +00:00
|
|
|
genExtension(version, results);
|
2015-03-09 05:21:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
}
|
2015-04-02 21:03:36 +00:00
|
|
|
}
|