Merge pull request #1687 from theopolis/more_certs

[Fix #1686] Add 'subject' and 'signing_algorithm' to certificates
This commit is contained in:
Teddy Reed 2015-11-29 18:59:27 -08:00
commit 58456a659a
6 changed files with 51 additions and 25 deletions

View File

@ -19,8 +19,8 @@ namespace sqlite {
int xOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor) {
int rc = SQLITE_NOMEM;
BaseCursor *pCur = new BaseCursor;
if (pCur) {
memset(pCur, 0, sizeof(BaseCursor));
if (pCur != nullptr) {
pCur->base.pVtab = nullptr;
*ppCursor = (sqlite3_vtab_cursor *)pCur;
rc = SQLITE_OK;
}

View File

@ -36,10 +36,16 @@ void genCertificate(const SecCertificateRef& SecCert, QueryData& results) {
return;
}
r["common_name"] = genCommonName(cert);
// Generate the common name and subject.
// They are very similar OpenSSL API accessors so save some logic and
// generate them using output parameters.
genCommonName(cert, r["subject"], r["common_name"]);
// Same with algorithm strings.
genAlgorithmProperties(cert, r["key_algorithm"], r["signing_algorithm"]);
// Most certificate field accessors return strings.
r["not_valid_before"] = INTEGER(genEpoch(X509_get_notBefore(cert)));
r["not_valid_after"] = INTEGER(genEpoch(X509_get_notAfter(cert)));
r["key_algorithm"] = genAlgProperty(cert);
// Get the keychain for the certificate.
r["path"] = getKeychainPath((SecKeychainItemRef)SecCert);

View File

@ -64,8 +64,14 @@ std::string getKeychainPath(const SecKeychainItemRef& item);
/// Certificate property parsing functions.
std::string genKIDProperty(const unsigned char* data, int len);
std::string genAlgProperty(const X509* cert);
std::string genCommonName(X509* cert);
/// Generate the public key algorithm and signing algorithm.
void genAlgorithmProperties(const X509* cert,
std::string& key,
std::string& sig);
/// Generate common name and subject.
void genCommonName(X509* cert, std::string& subject, std::string& common_name);
time_t genEpoch(ASN1_TIME* time);
std::string genSHA1ForCertificate(const CFDataRef& raw_cert);

View File

@ -81,17 +81,19 @@ std::string genKIDProperty(const unsigned char* data, int len) {
return key_id.str();
}
std::string genAlgProperty(const X509* cert) {
void genAlgorithmProperties(const X509* cert,
std::string& key,
std::string& sig) {
int nid = 0;
OSX_OPENSSL(nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm));
if (nid == NID_undef) {
// Unknown algorithm OID.
return "";
if (nid != NID_undef) {
OSX_OPENSSL(key = std::string(OBJ_nid2ln(nid)));
}
std::string property;
OSX_OPENSSL(property = std::string(OBJ_nid2ln(nid)));
return property;
OSX_OPENSSL(nid = OBJ_obj2nid(cert->cert_info->signature->algorithm));
if (nid != NID_undef) {
OSX_OPENSSL(sig = std::string(OBJ_nid2ln(nid)));
}
}
std::string genSHA1ForCertificate(const CFDataRef& raw_cert) {
@ -105,30 +107,38 @@ bool CertificateIsCA(X509* cert) {
return (ca > 0);
}
std::string genCommonName(X509* cert) {
void genCommonName(X509* cert, std::string& subject, std::string& common_name) {
if (cert == nullptr) {
return "";
return;
}
X509_NAME* subject_name = nullptr;
OSX_OPENSSL(subject_name = X509_get_subject_name(cert));
if (subject_name == nullptr) {
return "";
X509_NAME* subjectName = nullptr;
OSX_OPENSSL(subjectName = X509_get_subject_name(cert));
if (subjectName == nullptr) {
return;
}
// Generate the string representation of the subject.
char* subjectBytes = nullptr;
OSX_OPENSSL(subjectBytes = X509_NAME_oneline(subjectName, nullptr, 0));
if (subjectBytes != nullptr) {
subject = std::string(subjectBytes);
OSX_OPENSSL(OPENSSL_free(subjectBytes));
}
int nid = 0;
OSX_OPENSSL(nid = OBJ_txt2nid("CN"));
int index = 0;
OSX_OPENSSL(index = X509_NAME_get_index_by_NID(subject_name, nid, -1));
OSX_OPENSSL(index = X509_NAME_get_index_by_NID(subjectName, nid, -1));
if (index == -1) {
return "";
return;
}
X509_NAME_ENTRY* commonNameEntry = nullptr;
OSX_OPENSSL(commonNameEntry = X509_NAME_get_entry(subject_name, index));
OSX_OPENSSL(commonNameEntry = X509_NAME_get_entry(subjectName, index));
if (commonNameEntry == nullptr) {
return "";
return;
}
ASN1_STRING* commonNameData = nullptr;
@ -136,7 +146,7 @@ std::string genCommonName(X509* cert) {
unsigned char* data = nullptr;
OSX_OPENSSL(data = ASN1_STRING_data(commonNameData));
return std::string(reinterpret_cast<char*>(data));
common_name = std::string(reinterpret_cast<char*>(data));
}
std::string genHumanReadableDateTime(ASN1_TIME* time) {

View File

@ -60,7 +60,9 @@ TEST_F(CACertsTests, test_certificate_sha1) {
}
TEST_F(CACertsTests, test_certificate_properties) {
EXPECT_EQ("localhost.localdomain", genCommonName(x_cert));
std::string subject, common_name;
genCommonName(x_cert, subject, common_name);
EXPECT_EQ("localhost.localdomain", common_name);
OSX_OPENSSL(X509_check_ca(x_cert));
auto skid = genKIDProperty(x_cert->skid->data, x_cert->skid->length);

View File

@ -2,9 +2,11 @@ table_name("certificates")
description("Certificate Authorities installed in Keychains/ca-bundles.")
schema([
Column("common_name", TEXT, "Certificate CommonName"),
Column("subject", TEXT, "Certificate distinguished name"),
Column("ca", INTEGER, "1 if CA: true (certificate is an authority) else 0"),
Column("not_valid_before", DATETIME, "Lower bound of valid date"),
Column("not_valid_after", DATETIME, "Certificate expiration data"),
Column("signing_algorithm", TEXT, "Signing algorithm used"),
Column("key_algorithm", TEXT, "Key algorithm used"),
Column("key_usage", TEXT, "Certificate key usage and extended key usage"),
Column("subject_key_id", TEXT, "SKID an optionally included SHA1"),