예제 #1
0
std::string DiskArbitrationEventPublisher::getProperty(
    const CFStringRef& property, const CFDictionaryRef& dict) {
  CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(dict, property);
  if (value == nullptr) {
    return "";
  }

  if (CFStringCompare(property, CFSTR(kDAAppearanceTime_), kNilOptions) ==
      kCFCompareEqualTo) {
    return stringFromCFAbsoluteTime((CFDataRef)value);
  }

  if (CFGetTypeID(value) == CFNumberGetTypeID()) {
    return stringFromCFNumber((CFDataRef)value,
                              CFNumberGetType((CFNumberRef)value));
  } else if (CFGetTypeID(value) == CFStringGetTypeID()) {
    return stringFromCFString((CFStringRef)value);
  } else if (CFGetTypeID(value) == CFBooleanGetTypeID()) {
    return (CFBooleanGetValue((CFBooleanRef)value)) ? "1" : "0";
  } else if (CFGetTypeID(value) == CFUUIDGetTypeID()) {
    return stringFromCFString(
        CFUUIDCreateString(kCFAllocatorDefault, (CFUUIDRef)value));
  }
  return "";
}
예제 #2
0
std::string genCAProperty(const CFDataRef& constraints) {
  // Must return an array of constraints.
  if (CFGetTypeID(constraints) != CFArrayGetTypeID()) {
    return "-1";
  }

  std::string expected_label = "Certificate Authority";
  std::string expected_value = "Yes";

  CFStringRef label, value;
  CFDictionaryRef constraint;
  // Find the expected value/label combination constraint.
  for (CFIndex i = 0; i < CFArrayGetCount((CFArrayRef)constraints); i++) {
    constraint =
        (CFDictionaryRef)CFArrayGetValueAtIndex((CFArrayRef)constraints, i);
    label = (CFStringRef)CFDictionaryGetValue(constraint, kSecPropertyKeyLabel);
    value = (CFStringRef)CFDictionaryGetValue(constraint, kSecPropertyKeyValue);

    if (expected_label.compare(stringFromCFString(label)) == 0 &&
        expected_value.compare(stringFromCFString(value)) == 0) {
      return "1";
    }
  }

  return "0";
}
예제 #3
0
void extractQuarantineProperty(const std::string &table_key_name,
                               CFTypeRef property,
                               const std::string &path,
                               QueryData &results) {
  std::string value;
  if (CFGetTypeID(property) == CFStringGetTypeID()) {
    value = stringFromCFString((CFStringRef)property);
  } else if (CFGetTypeID(property) == CFDateGetTypeID()) {
    auto unix_time = CFDateGetAbsoluteTime((CFDateRef)property) +
                     kCFAbsoluteTimeIntervalSince1970;
    value = INTEGER(std::llround(unix_time));
  } else if (CFGetTypeID(property) == CFURLGetTypeID()) {
    value = stringFromCFString(CFURLGetString((CFURLRef)property));
  }
  setRow(results, path, table_key_name, value);
}
예제 #4
0
void parseWhereFrom(QueryData &results, const std::string &path) {

  CFStringRef CFPath = CFStringCreateWithCString(
      kCFAllocatorDefault, path.c_str(), kCFStringEncodingUTF8);

  MDItemRef metadata = MDItemCreate(kCFAllocatorDefault, CFPath);
  CFRelease(CFPath);

  if (metadata == nullptr) {
    VLOG(1) << "Metadata for " << path << " is null";
    return;
  }

  CFTypeRef attributes;
  attributes = MDItemCopyAttribute(metadata, kMDItemWhereFroms);
  CFRelease(metadata);

  if (attributes == nullptr) {
    VLOG(1) << "No attributes found for " << path;
    return;
  }

  CFArrayRef attribs = (CFArrayRef)attributes;
  CFIndex count = CFArrayGetCount(attribs);

  for (CFIndex i = 0; i < count; i++) {
    CFStringRef attribute = (CFStringRef)CFArrayGetValueAtIndex(attribs, i);
    auto where_from_attribute = stringFromCFString(attribute);
    if (!where_from_attribute.empty()) {
      setRow(results, path, "where_from", where_from_attribute);
    }
  }

  CFRelease(attributes);
}
예제 #5
0
std::string getIOKitProperty(const CFMutableDictionaryRef& details,
                             const std::string& key) {
  std::string value;

  // Get a property from the device.
  auto cfkey = CFStringCreateWithCString(
      kCFAllocatorDefault, key.c_str(), kCFStringEncodingUTF8);
  auto property = CFDictionaryGetValue(details, cfkey);
  CFRelease(cfkey);

  // Several supported ways of parsing IOKit-encoded data.
  if (property) {
    if (CFGetTypeID(property) == CFNumberGetTypeID()) {
      value = stringFromCFNumber((CFDataRef)property);
    } else if (CFGetTypeID(property) == CFStringGetTypeID()) {
      value = stringFromCFString((CFStringRef)property);
    } else if (CFGetTypeID(property) == CFDataGetTypeID()) {
      value = stringFromCFData((CFDataRef)property);
    } else if (CFGetTypeID(property) == CFBooleanGetTypeID()) {
      value = (CFBooleanGetValue((CFBooleanRef)property)) ? "1" : "0";
    }
  }

  return value;
}
예제 #6
0
Status parseApplicationAliasData(const std::string& data, std::string& result) {
  std::string decoded_data = base64Decode(data);
  if (decoded_data.empty()) {
    return Status(1, "Failed to base64 decode data");
  }

  CFDataRef resourceData = CFDataCreate(
      nullptr,
      static_cast<const UInt8*>(static_cast<const void*>(decoded_data.c_str())),
      decoded_data.length());
  if (resourceData == nullptr) {
    return Status(1, "Failed to allocate resource data");
  }

  auto alias = (CFDataRef)CFPropertyListCreateWithData(kCFAllocatorDefault,
                                                       resourceData,
                                                       kCFPropertyListImmutable,
                                                       nullptr,
                                                       nullptr);
  CFRelease(resourceData);
  if (alias == nullptr) {
    return Status(1, "Failed to allocate alias data");
  }

  auto bookmark =
      CFURLCreateBookmarkDataFromAliasRecord(kCFAllocatorDefault, alias);
  CFRelease(alias);
  if (bookmark == nullptr) {
    return Status(1, "Alias data is not a bookmark");
  }

  auto url = CFURLCreateByResolvingBookmarkData(
      kCFAllocatorDefault, bookmark, 0, nullptr, nullptr, nullptr, nullptr);
  CFRelease(bookmark);
  if (url == nullptr) {
    return Status(1, "Alias data is not a URL bookmark");
  }

  auto replaced = CFURLCreateStringByReplacingPercentEscapes(
      kCFAllocatorDefault, CFURLGetString(url), CFSTR(""));
  CFRelease(url);
  if (replaced == nullptr) {
    return Status(1, "Failed to replace percent escapes.");
  }

  // Get the URL-formatted path.
  result = stringFromCFString(replaced);
  CFRelease(replaced);
  if (result.empty()) {
    return Status(1, "Return result is zero size");
  }
  if (result.length() > 6 && result.substr(0, 7) == "file://") {
    result = result.substr(7);
  }

  return Status(0, "OK");
}
예제 #7
0
std::string genAlgProperty(const CFDataRef& alg) {
  std::string expected_label = "Algorithm";
  CFStringRef label, value;
  CFDictionaryRef alg_item;

  // Find the key identifier data within the property mess.
  for (CFIndex i = 0; i < CFArrayGetCount((CFArrayRef)alg); i++) {
    alg_item = (CFDictionaryRef)CFArrayGetValueAtIndex((CFArrayRef)alg, i);
    label = (CFStringRef)CFDictionaryGetValue(alg_item, kSecPropertyKeyLabel);
    value = (CFStringRef)CFDictionaryGetValue(alg_item, kSecPropertyKeyValue);

    if (expected_label.compare(stringFromCFString(label)) == 0) {
      return stringFromCFString(value);
    }
  }

  // Unknown algorithm OID.
  return "";
}
예제 #8
0
void DiskArbitrationEventPublisher::DiskAppearedCallback(DADiskRef disk,
                                                         void* context) {
  auto ec = createEventContext();

  CFDictionaryRef disk_properties = DADiskCopyDescription(disk);
  CFTypeRef devicePathKey;
  if (!CFDictionaryGetValueIfPresent(
          disk_properties, kDADiskDescriptionDevicePathKey, &devicePathKey)) {
    CFRelease(disk_properties);
    return;
  }

  auto device_path = stringFromCFString((CFStringRef)devicePathKey);
  ec->device_path = device_path;

  auto entry =
      IORegistryEntryFromPath(kIOMasterPortDefault, device_path.c_str());
  if (entry == MACH_PORT_NULL) {
    CFRelease(disk_properties);
    return;
  }

  auto protocol_properties = (CFDictionaryRef)IORegistryEntryCreateCFProperty(
      entry,
      CFSTR(kIOPropertyProtocolCharacteristicsKey_),
      kCFAllocatorDefault,
      kNilOptions);

  if (protocol_properties != nullptr) {
    CFDataRef path = (CFDataRef)CFDictionaryGetValue(
        protocol_properties, CFSTR(kVirtualInterfaceLocation_));
    if (path != nullptr) {
      ec->path = stringFromCFData(path);
      // extract checksum once on the whole disk and not for every partition
      if (CFBooleanGetValue((CFBooleanRef)CFDictionaryGetValue(
              disk_properties, kDADiskDescriptionMediaWholeKey))) {
        ec->checksum = extractUdifChecksum(ec->path);
      }
    } else {
      // There was no interface location.
      ec->path = getProperty(kDADiskDescriptionDevicePathKey, disk_properties);
    }
    CFRelease(protocol_properties);
  } else {
    ec->path = "";
  }

  if (ec->path.find("/SSD0@0") == std::string::npos) {
    // This is not an internal SSD.
    fire("add", ec, disk_properties);
  }

  CFRelease(disk_properties);
  IOObjectRelease(entry);
}
예제 #9
0
void genACPITable(const void* key, const void* value, void* results) {
  Row r;
  auto data = (CFDataRef)value;
  auto length = CFDataGetLength(data);

  r["name"] = stringFromCFString((CFStringRef)key);
  r["size"] = INTEGER(length);
  r["md5"] = hashFromBuffer(HASH_TYPE_MD5, CFDataGetBytePtr(data), length);

  ((QueryData*)results)->push_back(r);
}
예제 #10
0
inline std::string getKextString(const CFDictionaryRef &value,
                                 const CFStringRef key) {
  // Some values are optional, meaning the key is empty or does not exist.
  if (!CFDictionaryContainsKey(value, key)) {
    return "";
  }
  auto string = (CFStringRef)CFDictionaryGetValue(value, key);
  if (string == nullptr) {
    return "";
  }

  return stringFromCFString(string);
}
예제 #11
0
std::string IOKitHIDEventPublisher::getProperty(const IOHIDDeviceRef &device,
                                                const CFStringRef &property) {
  CFTypeRef value = IOHIDDeviceGetProperty(device, property);
  if (value == nullptr) {
    return "";
  }

  // Only support CFNumber and CFString types.
  if (CFGetTypeID(value) == CFNumberGetTypeID()) {
    return stringFromCFNumber((CFDataRef)value);
  } else if (CFGetTypeID(value) == CFStringGetTypeID()) {
    return stringFromCFString((CFStringRef)value);
  }
  return "";
}
예제 #12
0
std::string getUSBProperty(const CFMutableDictionaryRef& details,
                           const std::string& key) {
  // Get a property from the device.
  auto cfkey = CFStringCreateWithCString(kCFAllocatorDefault, key.c_str(),
    kCFStringEncodingUTF8);
  auto property = CFDictionaryGetValue(details, cfkey);
  CFRelease(cfkey);
  if (property) {
    if (CFGetTypeID(property) == CFNumberGetTypeID()) {
      return stringFromCFNumber((CFDataRef)property);
    } else if (CFGetTypeID(property) == CFStringGetTypeID()) {
      return stringFromCFString((CFStringRef)property);
    }
  }
  return "";
}
예제 #13
0
void genOSXHashPref(const void* key, const void* value, void* tref) {
  if (key == nullptr || value == nullptr || tref == nullptr) {
    // Paranoia: don't expect the callback application to yield nullptrs.
    return;
  }

  const TRowResults* trow = (const TRowResults*)tref;
  Row r = *(trow->base);
  if (CFGetTypeID((CFTypeRef)key) == CFStringGetTypeID()) {
    if (r["subkey"].size() > 0) {
      r["subkey"] += "/";
    }
    // The subkey is the hash map key.
    r["subkey"] += stringFromCFString((CFStringRef)key);
  }
  genOSXPrefValues(
      static_cast<CFTypeRef>(value), r, *(trow->results), trow->depth);
}
예제 #14
0
void genOSXPrefValues(const CFTypeRef& value,
                      const Row& base,
                      QueryData& results,
                      size_t depth) {
  if (value == nullptr) {
    return;
  }

  // Since we recurse when parsing Arrays/Dicts, monitor stack limits.
  if (++depth > kPreferenceDepthLimit) {
    TLOG << "The macOS preference: " << base.at("domain")
         << " exceeded subkey depth limit: " << kPreferenceDepthLimit;
    return;
  }

  // Emit a string representation for each preference type.
  Row r = base;
  if (CFGetTypeID(value) == CFNumberGetTypeID()) {
    r["value"] = stringFromCFNumber(static_cast<CFDataRef>(value));
  } else if (CFGetTypeID(value) == CFStringGetTypeID()) {
    r["value"] = stringFromCFString(static_cast<CFStringRef>(value));
  } else if (CFGetTypeID(value) == CFDateGetTypeID()) {
    auto unix_time = CFDateGetAbsoluteTime(static_cast<CFDateRef>(value)) +
                     kCFAbsoluteTimeIntervalSince1970;
    r["value"] = boost::lexical_cast<std::string>(std::llround(unix_time));
  } else if (CFGetTypeID(value) == CFBooleanGetTypeID()) {
    r["value"] = (CFBooleanGetValue(static_cast<CFBooleanRef>(value)) == TRUE)
                     ? "true"
                     : "false";
  } else if (CFGetTypeID(value) == CFDataGetTypeID()) {
    // Do not include data preferences.
  } else if (CFGetTypeID(value) == CFArrayGetTypeID()) {
    genOSXListPref(static_cast<CFArrayRef>(value), base, results, depth);
    return;
  } else if (CFGetTypeID(value) == CFDictionaryGetTypeID()) {
    // Generate a row for each hash key.
    TRowResults trow(base, results, depth);
    CFDictionaryApplyFunction(
        static_cast<CFDictionaryRef>(value), &genOSXHashPref, &trow);
    return;
  }

  results.push_back(std::move(r));
}
예제 #15
0
std::string genCommonNameProperty(const CFDataRef& ca) {
  CFDataRef ca_data = nullptr;
  CFStringRef ca_string = nullptr;

  // Find the key identifier data within the property mess.
  for (CFIndex i = 0; i < CFArrayGetCount((CFArrayRef)ca); i++) {
    ca_data = (CFDataRef)CFArrayGetValueAtIndex((CFArrayRef)ca, i);
    if (CFGetTypeID(ca_data) == CFStringGetTypeID()) {
      ca_string = (CFStringRef)ca_data;
      break;
    }
  }

  if (ca_string == nullptr) {
    // Could not find a CFString reference within the common name array.
    return "";
  }

  // Access, then convert the CFString. CFStringGetCStringPtr is less-safe.
  return stringFromCFString(ca_string);
}
예제 #16
0
/// Parse a Login Items Plist Alias data for bin path
Status parseAliasData(const std::string& data, std::string& result) {
  auto decoded = base64Decode(data);
  if (decoded.size() == 0) {
    // Base64 encoded data (from plist parsing) failed to decode.
    return Status(1, "Failed base64 decode");
  }

  auto alias = CFDataCreate(
      kCFAllocatorDefault, (const UInt8*)decoded.c_str(), decoded.size());
  if (alias == nullptr) {
    // Failed to create CFData object.
    return Status(2, "CFData allocation failed");
  }

  auto bookmark =
      CFURLCreateBookmarkDataFromAliasRecord(kCFAllocatorDefault, alias);
  if (bookmark == nullptr) {
    CFRelease(alias);
    return Status(1, "Alias data is not a bookmark");
  }

  auto url = CFURLCreateByResolvingBookmarkData(
      kCFAllocatorDefault, bookmark, 0, nullptr, nullptr, nullptr, nullptr);
  if (url == nullptr) {
    CFRelease(alias);
    CFRelease(bookmark);
    return Status(1, "Alias data is not a URL bookmark");
  }

  // Get the URL-formatted path.
  result = stringFromCFString(CFURLGetString(url));
  if (result.substr(0, 7) == "file://") {
    result = result.substr(7);
  }

  CFRelease(alias);
  CFRelease(bookmark);
  CFRelease(url);
  return Status(0, "OK");
}
예제 #17
0
void genOSXDomainPrefs(const CFStringRef& username,
                       const CFStringRef& domain,
                       bool current_host,
                       QueryData& results) {
  const auto* user = (username != nullptr)
                         ? &username
                         : (isUserAdmin()) ? &kCFPreferencesAnyUser
                                           : &kCFPreferencesCurrentUser;
  const auto* host =
      (current_host) ? &kCFPreferencesCurrentHost : &kCFPreferencesAnyHost;
  auto keys = CFPreferencesCopyKeyList(domain, *user, *host);
  if (keys == nullptr) {
    return;
  }

  auto values = CFPreferencesCopyMultiple(keys, domain, *user, *host);
  if (values == nullptr) {
    CFRelease(keys);
    return;
  }

  std::string username_string;
  if (username != nullptr) {
    username_string = stringFromCFString(username);
  }

  // Iterate over each preference domain's preference name.
  for (CFIndex j = 0; j < CFArrayGetCount(keys); ++j) {
    Row r;

    r["username"] = username_string;
    r["host"] = (current_host) ? "current" : "any";
    r["domain"] = stringFromCFString(domain);
    auto key = static_cast<CFStringRef>(CFArrayGetValueAtIndex(keys, j));
    if (CFStringGetTypeID() != CFGetTypeID(key)) {
      continue;
    }

    // Interesting results/behavior from Microsoft products.
    r["key"] = stringFromCFString(key);
    if (r.at("key").find('>') != std::string::npos ||
        r.at("key").find('<') != std::string::npos || r.at("key").size() == 0) {
      continue;
    }

    // Check if the preference key is managed by a profile.
    auto forced = CFPreferencesAppValueIsForced(key, domain);
    r["forced"] = (forced) ? '1' : '0';

    CFTypeRef value = nullptr;
    if (forced) {
      value = static_cast<CFTypeRef>(CFPreferencesCopyAppValue(key, domain));
    } else {
      // Check the key and key type (which may be any CF type).
      value = static_cast<CFTypeRef>(CFDictionaryGetValue(values, key));
    }
    genOSXPrefValues(value, r, results, 0);
    if (forced) {
      CFRelease(value);
    }
  }

  CFRelease(values);
  CFRelease(keys);
}
예제 #18
0
QueryData genKernelInfo(QueryContext& context) {
  QueryData results;

  mach_port_t master_port;
  auto kr = IOMasterPort(bootstrap_port, &master_port);
  if (kr != KERN_SUCCESS) {
    VLOG(1) << "Could not get the IOMaster port";
    return {};
  }

  // NVRAM registry entry is :/options.
  auto chosen = IORegistryEntryFromPath(master_port, kIODTChosenPath_);
  if (chosen == 0) {
    VLOG(1) << "Could not get IOKit boot device";
    return {};
  }

  // Parse the boot arguments, usually none.
  CFMutableDictionaryRef properties;
  kr = IORegistryEntryCreateCFProperties(
      chosen, &properties, kCFAllocatorDefault, 0);
  IOObjectRelease(chosen);

  if (kr != KERN_SUCCESS) {
    VLOG(1) << "Could not get IOKit boot device properties";
    return {};
  }

  Row r;
  CFTypeRef property;
  if (CFDictionaryGetValueIfPresent(
          properties, CFSTR("boot-args"), &property)) {
    r["arguments"] = stringFromCFData((CFDataRef)property);
  }

  if (CFDictionaryGetValueIfPresent(
          properties, CFSTR("boot-device-path"), &property)) {
    r["device"] = getCanonicalEfiDevicePath((CFDataRef)property);
  }

  if (CFDictionaryGetValueIfPresent(
          properties, CFSTR("boot-file"), &property)) {
    r["path"] = stringFromCFData((CFDataRef)property);
    std::replace(r["path"].begin(), r["path"].end(), '\\', '/');
    boost::trim(r["path"]);
    if (!r["path"].empty() && r["path"][0] != '/') {
      r["path"] = "/" + r["path"];
    }
  }
  // No longer need chosen properties.
  CFRelease(properties);

  // The kernel version, signature, and build information is stored in Root.
  auto root = IORegistryGetRootEntry(master_port);
  if (root != 0) {
    property = (CFDataRef)IORegistryEntryCreateCFProperty(
        root, CFSTR(kIOKitBuildVersionKey), kCFAllocatorDefault, 0);
    if (property != nullptr) {
      // The version is in the form:
      // Darwin Kernel Version VERSION: DATE; root:BUILD/TAG
      auto signature = stringFromCFString((CFStringRef)property);
      CFRelease(property);

      r["version"] = signature.substr(22, signature.find(":") - 22);
    }
  }

  results.push_back(r);
  return results;
}