2015-02-25 22:18:43 +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/core.h>
|
2015-03-02 05:15:42 +00:00
|
|
|
#include <osquery/filesystem.h>
|
2015-02-25 22:18:43 +00:00
|
|
|
#include <osquery/logger.h>
|
2015-03-02 05:15:42 +00:00
|
|
|
#include <osquery/sql.h>
|
2015-02-25 22:18:43 +00:00
|
|
|
#include <osquery/tables.h>
|
|
|
|
|
2015-03-08 09:59:59 +00:00
|
|
|
#include "osquery/tables/system/darwin/keychain.h"
|
2015-02-25 22:18:43 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
namespace tables {
|
|
|
|
|
2015-03-08 09:59:59 +00:00
|
|
|
const std::map<std::string, CertProperty> kCertificateProperties = {
|
|
|
|
{"common_name", {kSecOIDCommonName, genCommonNameProperty}},
|
|
|
|
{"ca", {kSecOIDBasicConstraints, genCAProperty}},
|
|
|
|
{"not_valid_before", {kSecOIDX509V1ValidityNotBefore, stringFromCFNumber}},
|
|
|
|
{"not_valid_after", {kSecOIDX509V1ValidityNotAfter, stringFromCFNumber}},
|
|
|
|
{"key_algorithm", {kSecOIDX509V1SubjectPublicKeyAlgorithm, genAlgProperty}},
|
|
|
|
{"key_usage", {kSecOIDKeyUsage, stringFromCFNumber}},
|
|
|
|
{"subject_key_id", {kSecOIDSubjectKeyIdentifier, genKIDProperty}},
|
|
|
|
{"authority_key_id", {kSecOIDAuthorityKeyIdentifier, genKIDProperty}},
|
2015-02-25 22:18:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void genCertificate(const SecCertificateRef& cert, QueryData& results) {
|
|
|
|
Row r;
|
|
|
|
|
|
|
|
// Iterate through each selected certificate property.
|
|
|
|
for (const auto &detail : kCertificateProperties) {
|
|
|
|
auto property = CreatePropertyFromCertificate(cert, detail.second.type);
|
|
|
|
if (property == nullptr) {
|
|
|
|
r[detail.first] = "";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Each property may be stored differently, apply a generator function.
|
|
|
|
r[detail.first] = detail.second.generate(property);
|
|
|
|
CFRelease(property);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix missing basic constraints to indicate CA:false.
|
|
|
|
if (r["ca"] == "") {
|
|
|
|
r["ca"] = "0";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the keychain for the certificate.
|
|
|
|
r["path"] = getKeychainPath((SecKeychainItemRef)cert);
|
|
|
|
|
|
|
|
// Hash is not a certificate property, calculate using raw data.
|
|
|
|
r["sha1"] = genSHA1ForCertificate(cert);
|
|
|
|
results.push_back(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
QueryData genCerts(QueryContext &context) {
|
|
|
|
QueryData results;
|
|
|
|
|
2015-03-02 05:15:42 +00:00
|
|
|
// Allow the caller to set an explicit certificate (keychain) search path.
|
|
|
|
std::set<std::string> keychain_paths;
|
|
|
|
if (context.constraints["path"].exists()) {
|
|
|
|
keychain_paths = context.constraints["path"].getAll(EQUALS);
|
2015-03-08 09:59:59 +00:00
|
|
|
} else {
|
|
|
|
for (const auto& path : kSystemKeychainPaths) {
|
|
|
|
keychain_paths.insert(path);
|
|
|
|
}
|
|
|
|
auto homes = osquery::getHomeDirectories();
|
|
|
|
for (const auto& dir : homes) {
|
|
|
|
for (const auto& keychains_dir : kUserKeychainPaths) {
|
|
|
|
keychain_paths.insert((dir / keychains_dir).string());
|
|
|
|
}
|
|
|
|
}
|
2015-03-02 05:15:42 +00:00
|
|
|
}
|
|
|
|
|
2015-02-25 22:18:43 +00:00
|
|
|
// Keychains/certificate stores belonging to the OS.
|
2015-03-08 09:59:59 +00:00
|
|
|
CFArrayRef certs = CreateKeychainItems(keychain_paths, kSecClassCertificate);
|
2015-02-25 22:18:43 +00:00
|
|
|
// Must have returned an array of matching certificates.
|
|
|
|
if (certs == nullptr || CFGetTypeID(certs) != CFArrayGetTypeID()) {
|
|
|
|
VLOG(1) << "Could not find OS X Keychain";
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Evaluate the certificate data, check for CA in Basic constraints.
|
|
|
|
auto certificate_count = CFArrayGetCount(certs);
|
|
|
|
for (CFIndex i = 0; i < certificate_count; i++) {
|
|
|
|
auto cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
|
|
|
|
genCertificate(cert, results);
|
|
|
|
}
|
|
|
|
|
|
|
|
CFRelease(certs);
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|