"Fossies" - the Fresh Open Source Software Archive

Member "osquery-4.3.0/osquery/tables/system/darwin/apps.mm" (14 Apr 2020, 12717 Bytes) of package /linux/misc/osquery-4.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "apps.mm" see the Fossies "Dox" file reference documentation.

    1 /**
    2  *  Copyright (c) 2014-present, Facebook, Inc.
    3  *  All rights reserved.
    4  *
    5  *  This source code is licensed in accordance with the terms specified in
    6  *  the LICENSE file found in the root directory of this source tree.
    7  */
    8 
    9 #import <Foundation/Foundation.h>
   10 
   11 #include <CoreServices/CoreServices.h>
   12 
   13 #include <boost/algorithm/string/join.hpp>
   14 #include <boost/filesystem/operations.hpp>
   15 #include <boost/filesystem/path.hpp>
   16 
   17 #include <osquery/core.h>
   18 #include <osquery/filesystem/filesystem.h>
   19 #include <osquery/logger.h>
   20 #include <osquery/sql.h>
   21 #include <osquery/tables.h>
   22 #include <osquery/utils/darwin/plist.h>
   23 #include <osquery/utils/conversions/darwin/cfstring.h>
   24 
   25 namespace fs = boost::filesystem;
   26 namespace pt = boost::property_tree;
   27 
   28 namespace osquery {
   29 namespace tables {
   30 
   31 const std::map<std::string, std::string> kAppsInfoPlistTopLevelStringKeys = {
   32     {"CFBundleExecutable", "bundle_executable"},
   33     {"CFBundleIdentifier", "bundle_identifier"},
   34     {"CFBundleName", "bundle_name"},
   35     {"CFBundleShortVersionString", "bundle_short_version"},
   36     {"CFBundleVersion", "bundle_version"},
   37     {"CFBundlePackageType", "bundle_package_type"},
   38     {"LSEnvironment", "environment"},
   39     {"LSUIElement", "element"},
   40     {"CFBundleDevelopmentRegion", "development_region"},
   41     {"CFBundleDisplayName", "display_name"},
   42     {"CFBundleGetInfoString", "info_string"},
   43     {"DTCompiler", "compiler"},
   44     {"LSMinimumSystemVersion", "minimum_system_version"},
   45     {"LSApplicationCategoryType", "category"},
   46     {"NSAppleScriptEnabled", "applescript_enabled"},
   47     {"NSHumanReadableCopyright", "copyright"},
   48 };
   49 
   50 const std::vector<std::string> kHomeDirSearchPaths = {
   51     "Applications", "Desktop", "Downloads",
   52 };
   53 
   54 const std::vector<std::string> kSystemSearchPaths = {
   55     "/Applications",
   56     "/System/Library/Core Services/Applications",
   57     "/Users/Shared/Applications",
   58 };
   59 
   60 enum AppSchemeFlags {
   61   kSchemeNormal = 0,
   62   // Default flag from the list of schemes on a default OS X 10.10 install.
   63   kSchemeSystemDefault = 1,
   64   // Protected flag from Apple Reference: Inter-app Communication
   65   kSchemeProtected = 2,
   66 };
   67 
   68 const std::map<std::string, unsigned short> kApplicationSchemes = {
   69     {"account", 0},
   70     {"addressbook", kSchemeSystemDefault},
   71     {"afp", kSchemeSystemDefault | kSchemeProtected},
   72     {"aim", kSchemeSystemDefault},
   73     {"alfred", 0},
   74     {"alfredapp", 0},
   75     {"app-prefs", 0},
   76     {"applefeedback", kSchemeSystemDefault},
   77     {"applescript", kSchemeSystemDefault},
   78     {"apupdate", kSchemeSystemDefault},
   79     {"at", kSchemeSystemDefault | kSchemeProtected},
   80     {"atom", 0},
   81     {"bluejeans", 0},
   82     {"calinvite", 0},
   83     {"calinvitelist", 0},
   84     {"callto", 0},
   85     {"calshow", 0},
   86     {"cloudphoto", kSchemeSystemDefault},
   87     {"conf", 0},
   88     {"daap", kSchemeSystemDefault},
   89     {"dict", kSchemeSystemDefault},
   90     {"facetime", kSchemeSystemDefault | kSchemeProtected},
   91     {"fb", kSchemeSystemDefault},
   92     {"fbauth", 0},
   93     {"file", kSchemeSystemDefault | kSchemeProtected},
   94     {"ftp", kSchemeSystemDefault | kSchemeProtected},
   95     {"gamecenter", kSchemeSystemDefault},
   96     {"gopher", 0},
   97     {"grammar", 0},
   98     {"h323", 0},
   99     {"help", kSchemeSystemDefault},
  100     {"http", kSchemeSystemDefault | kSchemeProtected},
  101     {"https", kSchemeSystemDefault | kSchemeProtected},
  102     {"iadoptout", 0},
  103     {"ibooks", kSchemeSystemDefault},
  104     {"ical", kSchemeSystemDefault},
  105     {"ichat", kSchemeSystemDefault},
  106     {"icloud-sharing", kSchemeSystemDefault},
  107     {"im", kSchemeSystemDefault},
  108     {"imessage", kSchemeSystemDefault},
  109     {"ipps", kSchemeSystemDefault},
  110     {"irc", 0},
  111     {"itls", kSchemeSystemDefault},
  112     {"itms", kSchemeSystemDefault},
  113     {"itms-books", kSchemeSystemDefault},
  114     {"itms-bookss", kSchemeSystemDefault},
  115     {"itmsp-app", 0},
  116     {"itunesradio", kSchemeSystemDefault},
  117     {"macappstore", kSchemeSystemDefault},
  118     {"macappstores", kSchemeSystemDefault},
  119     {"mailto", kSchemeSystemDefault | kSchemeProtected},
  120     {"map", 0},
  121     {"maps", kSchemeSystemDefault},
  122     {"message", kSchemeSystemDefault},
  123     {"messages", kSchemeSystemDefault},
  124     {"ms-excel", 0},
  125     {"ms-word", 0},
  126     {"munki", 0},
  127     {"news", kSchemeSystemDefault | kSchemeProtected},
  128     {"nntp", 0},
  129     {"nwnode", kSchemeSystemDefault | kSchemeProtected},
  130     {"omnifocus", 0},
  131     {"ophttp", 0},
  132     {"pcast", kSchemeSystemDefault},
  133     {"photos", kSchemeSystemDefault},
  134     {"photos-event", 0},
  135     {"photos-migrate-iphoto", 0},
  136     {"photos-redirect", 0},
  137     {"powerpoint", 0},
  138     {"prefs", 0},
  139     {"qs", 0},
  140     {"qsinstall", 0},
  141     {"qss-http", 0},
  142     {"qssp-http", 0},
  143     {"reminders", kSchemeSystemDefault},
  144     {"rtsp", kSchemeSystemDefault},
  145     {"shoebox", 0},
  146     {"slack", 0},
  147     {"smb", kSchemeSystemDefault | kSchemeProtected},
  148     {"sms", kSchemeSystemDefault | kSchemeProtected},
  149     {"ssh", kSchemeSystemDefault},
  150     {"tel", kSchemeSystemDefault | kSchemeProtected},
  151     {"telnet", kSchemeSystemDefault},
  152     {"twitter", kSchemeSystemDefault},
  153     {"txmt", 0},
  154     {"vnc", kSchemeSystemDefault | kSchemeProtected},
  155     {"wais", 0},
  156     {"webapp", 0},
  157     {"webcal", kSchemeSystemDefault},
  158     {"whois", 0},
  159     {"wunderlist", 0},
  160     {"xmpp", kSchemeSystemDefault},
  161     {"yelp", 0},
  162 };
  163 
  164 void genApplicationsFromPath(const fs::path& path,
  165                              std::set<std::string>& apps) {
  166   std::vector<std::string> new_apps;
  167   if (!osquery::listDirectoriesInDirectory(path.string(), new_apps).ok()) {
  168     return;
  169   }
  170 
  171   for (const auto& app : new_apps) {
  172     if (pathExists(app + "/Contents/Info.plist")) {
  173       apps.insert(app + "/Contents/Info.plist");
  174     }
  175   }
  176 }
  177 
  178 void genApplication(const pt::ptree& tree,
  179                     const fs::path& path,
  180                     QueryData& results) {
  181   Row r;
  182   r["name"] = path.parent_path().parent_path().filename().string();
  183   r["path"] = path.parent_path().parent_path().string();
  184 
  185   NSString* filePath =
  186       [NSString stringWithUTF8String:path.parent_path().parent_path().c_str()];
  187   MDItemRef mdItem = MDItemCreate(NULL, (CFStringRef)filePath);
  188 
  189   if (mdItem != nullptr) {
  190     NSDate* lastOpened = static_cast<NSDate*>(
  191         CFBridgingRelease(MDItemCopyAttribute(mdItem, kMDItemLastUsedDate)));
  192     if (lastOpened != nullptr) {
  193       r["last_opened_time"] = INTEGER([lastOpened timeIntervalSince1970]);
  194     } else {
  195       r["last_opened_time"] = INTEGER(-1);
  196     }
  197     CFRelease(mdItem);
  198     mdItem = NULL;
  199   } else {
  200     r["last_opened_time"] = INTEGER(-1);
  201   }
  202 
  203   // Loop through each column and its mapped Info.plist key name.
  204   for (const auto& item : kAppsInfoPlistTopLevelStringKeys) {
  205     r[item.second] = tree.get<std::string>(item.first, "");
  206     // Change boolean values into integer 1, 0.
  207     if (r[item.second] == "true" || r[item.second] == "YES" ||
  208         r[item.second] == "Yes") {
  209       r[item.second] = INTEGER(1);
  210     } else if (r[item.second] == "false" || r[item.second] == "NO" ||
  211                r[item.second] == "No") {
  212       r[item.second] = INTEGER(0);
  213     }
  214   }
  215   results.push_back(std::move(r));
  216 }
  217 
  218 Status genAppsFromLaunchServices(std::set<std::string>& apps) {
  219   // Resolve the protected/private symbol safely.
  220   CFBundleRef ls_bundle =
  221       CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
  222   if (ls_bundle == nullptr) {
  223     return Status(1, "LaunchServices list missing");
  224   }
  225 
  226   auto LSCopyAllApplicationURLs =
  227       (OSStatus(*)(CFArrayRef*))CFBundleGetFunctionPointerForName(
  228           ls_bundle, CFSTR("_LSCopyAllApplicationURLs"));
  229   // If the symbol did not exist we will not have a handle.
  230   if (LSCopyAllApplicationURLs == nullptr) {
  231     return Status(1, "LaunchServices list missing");
  232   }
  233 
  234   CFArrayRef ls_apps = nullptr;
  235   if (LSCopyAllApplicationURLs(&ls_apps) != noErr || ls_apps == nullptr) {
  236     return Status(1, "Could not list LaunchServices applications");
  237   }
  238 
  239   for (id app in (__bridge NSArray*)ls_apps) {
  240     if (app != nil && [app isKindOfClass:[NSURL class]]) {
  241       apps.insert(std::string([[app path] UTF8String]) +
  242                   "/Contents/Info.plist");
  243     }
  244   }
  245 
  246   CFRelease(ls_apps);
  247   return Status(0, "OK");
  248 }
  249 
  250 QueryData genApps(QueryContext& context) {
  251   QueryData results;
  252 
  253   // Application path accumulator.
  254   std::set<std::string> apps;
  255   @autoreleasepool {
  256     // Try to use the OS X LaunchServices API.
  257     if (!genAppsFromLaunchServices(apps).ok()) {
  258       // Otherwise, the LaunchServices API failed, 'manually' search for apps.
  259       // Walk through several groups of common search paths that may contain
  260       // apps.
  261       if (context.constraints["path"].exists(EQUALS)) {
  262         auto app_constraints = context.constraints["path"].getAll(EQUALS);
  263         for (const auto& app : app_constraints) {
  264           apps.insert(app + "/Contents/Info.plist");
  265         }
  266       } else {
  267         for (const auto& path : kSystemSearchPaths) {
  268           genApplicationsFromPath(path, apps);
  269         }
  270 
  271         // List all users on the system, and walk common search paths with
  272         // homes.
  273         auto homes = osquery::getHomeDirectories();
  274         for (const auto& home : homes) {
  275           for (const auto& path : kHomeDirSearchPaths) {
  276             genApplicationsFromPath(home / path, apps);
  277           }
  278         }
  279       }
  280     }
  281 
  282     // The osquery::parsePlist method will reset/clear a property tree.
  283     // Keeping the data structure in a larger scope preserves allocations
  284     // between similar-sized trees.
  285     pt::ptree tree;
  286 
  287     // For each found application (path with an Info.plist) parse the plist.
  288     for (const auto& path : apps) {
  289       if (!osquery::pathExists(path)) {
  290         continue;
  291       }
  292 
  293       if (!osquery::parsePlist(path, tree).ok()) {
  294         TLOG << "Error parsing application plist: " << path;
  295         continue;
  296       }
  297 
  298       // Using the parsed plist, pull out each interesting key.
  299       genApplication(tree, path, results);
  300     }
  301   }
  302   return results;
  303 }
  304 
  305 QueryData genAppSchemes(QueryContext& context) {
  306   QueryData results;
  307 
  308   @autoreleasepool {
  309     for (const auto& scheme : kApplicationSchemes) {
  310       auto protocol = scheme.first + "://";
  311       auto cfprotocol = CFStringCreateWithCString(
  312           kCFAllocatorDefault, protocol.c_str(), protocol.length());
  313       if (cfprotocol == nullptr) {
  314         continue;
  315       }
  316 
  317       // Create a "fake" URL that only contains the protocol component of a URI.
  318       auto url =
  319           CFURLCreateWithString(kCFAllocatorDefault, cfprotocol, nullptr);
  320       CFRelease(cfprotocol);
  321       if (url == nullptr) {
  322         continue;
  323       }
  324 
  325       // List all application bundles that request this protocol scheme.
  326       auto apps = LSCopyApplicationURLsForURL(url, kLSRolesAll);
  327       if (apps == nullptr) {
  328         CFRelease(url);
  329         continue;
  330       }
  331 
  332       // Check the default handler assigned to the protocol scheme.
  333       // This only applies to 10.10, so resolve the symbol at runtime.
  334       CFBundleRef ls_bundle =
  335           CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
  336       CFURLRef default_app = nullptr;
  337       if (ls_bundle != nullptr) {
  338         auto _LSCopyDefaultApplicationURLForURL =
  339             (CFURLRef(*)(CFURLRef, LSRolesMask, CFErrorRef*))
  340                 CFBundleGetFunctionPointerForName(
  341                     ls_bundle, CFSTR("LSCopyDefaultApplicationURLForURL"));
  342         // If the symbol did not exist we will not have a handle.
  343         if (_LSCopyDefaultApplicationURLForURL != nullptr) {
  344           default_app =
  345               _LSCopyDefaultApplicationURLForURL(url, kLSRolesAll, nullptr);
  346         }
  347       }
  348 
  349       CFRelease(url);
  350       for (CFIndex i = 0; i < CFArrayGetCount(apps); i++) {
  351         Row r;
  352         r["scheme"] = scheme.first;
  353 
  354         auto app = CFArrayGetValueAtIndex(apps, i);
  355         if (app == nullptr || CFGetTypeID(app) != CFURLGetTypeID()) {
  356           // Handle problems with application listings.
  357           continue;
  358         }
  359 
  360         auto path =
  361             CFURLCopyFileSystemPath((CFURLRef)app, kCFURLPOSIXPathStyle);
  362         if (path == nullptr) {
  363           continue;
  364         }
  365 
  366         r["handler"] = stringFromCFString(path);
  367         CFRelease(path);
  368         // Check if the handler is set (in the OS) as the default.
  369         if (default_app != nullptr &&
  370             CFEqual((CFTypeRef)app, (CFTypeRef)default_app)) {
  371           r["enabled"] = "1";
  372         } else {
  373           r["enabled"] = "0";
  374         }
  375 
  376         r["external"] = (scheme.second & kSchemeSystemDefault) ? "0" : "1";
  377         r["protected"] = (scheme.second & kSchemeProtected) ? "1" : "0";
  378         results.push_back(r);
  379       }
  380 
  381       if (default_app != nullptr) {
  382         CFRelease(default_app);
  383       }
  384       CFRelease(apps);
  385     }
  386   }
  387   return results;
  388 }
  389 }
  390 }