keychain: use SearchCopyNext keychain enumeration for System certs as well
SecItemCopyMatching seems to be problematic regarding memory management. And as there does not seem to be a good alternative to enumerate the System Roots keychain using the SecItemCopyMatching API, we stick to the deprecated enumeration functions for now.
This commit is contained in:
@@ -21,10 +21,15 @@
|
|||||||
#include <Security/Security.h>
|
#include <Security/Security.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* System Root certificates keychain
|
* System Roots keychain
|
||||||
*/
|
*/
|
||||||
#define SYSTEM_ROOTS "/System/Library/Keychains/SystemRootCertificates.keychain"
|
#define SYSTEM_ROOTS "/System/Library/Keychains/SystemRootCertificates.keychain"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System keychain
|
||||||
|
*/
|
||||||
|
#define SYSTEM "/Library/Keychains/System.keychain"
|
||||||
|
|
||||||
typedef struct private_keychain_creds_t private_keychain_creds_t;
|
typedef struct private_keychain_creds_t private_keychain_creds_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,9 +54,9 @@ struct private_keychain_creds_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a credential set with System Root certificates
|
* Load a credential sets with certificates from a keychain path
|
||||||
*/
|
*/
|
||||||
static mem_cred_t* load_roots(private_keychain_creds_t *this)
|
static mem_cred_t* load_certs(private_keychain_creds_t *this, char *path)
|
||||||
{
|
{
|
||||||
SecKeychainRef keychain;
|
SecKeychainRef keychain;
|
||||||
SecKeychainSearchRef search;
|
SecKeychainSearchRef search;
|
||||||
@@ -61,8 +66,8 @@ static mem_cred_t* load_roots(private_keychain_creds_t *this)
|
|||||||
|
|
||||||
set = mem_cred_create();
|
set = mem_cred_create();
|
||||||
|
|
||||||
DBG1(DBG_CFG, "loading System Roots certificates:");
|
DBG1(DBG_CFG, "loading certificates from %s:", path);
|
||||||
status = SecKeychainOpen(SYSTEM_ROOTS, &keychain);
|
status = SecKeychainOpen(path, &keychain);
|
||||||
if (status == errSecSuccess)
|
if (status == errSecSuccess)
|
||||||
{
|
{
|
||||||
status = SecKeychainSearchCreateFromAttributes(keychain,
|
status = SecKeychainSearchCreateFromAttributes(keychain,
|
||||||
@@ -98,70 +103,6 @@ static mem_cred_t* load_roots(private_keychain_creds_t *this)
|
|||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a credential set loaded with certificates
|
|
||||||
*/
|
|
||||||
static mem_cred_t* load_creds(private_keychain_creds_t *this)
|
|
||||||
{
|
|
||||||
mem_cred_t *set;
|
|
||||||
OSStatus status;
|
|
||||||
CFDictionaryRef query;
|
|
||||||
CFArrayRef certs;
|
|
||||||
const void* keys[] = {
|
|
||||||
kSecReturnData,
|
|
||||||
kSecMatchLimit,
|
|
||||||
kSecClass,
|
|
||||||
kSecAttrCanVerify,
|
|
||||||
kSecMatchTrustedOnly,
|
|
||||||
};
|
|
||||||
const void* values[] = {
|
|
||||||
kCFBooleanTrue,
|
|
||||||
kSecMatchLimitAll,
|
|
||||||
kSecClassCertificate,
|
|
||||||
kCFBooleanTrue,
|
|
||||||
kCFBooleanTrue,
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
set = mem_cred_create();
|
|
||||||
|
|
||||||
DBG1(DBG_CFG, "loading System certificates:");
|
|
||||||
query = CFDictionaryCreate(NULL, keys, values, countof(keys),
|
|
||||||
&kCFTypeDictionaryKeyCallBacks,
|
|
||||||
&kCFTypeDictionaryValueCallBacks);
|
|
||||||
if (query)
|
|
||||||
{
|
|
||||||
status = SecItemCopyMatching(query, (CFTypeRef*)&certs);
|
|
||||||
CFRelease(query);
|
|
||||||
if (status == errSecSuccess)
|
|
||||||
{
|
|
||||||
for (i = 0; i < CFArrayGetCount(certs); i++)
|
|
||||||
{
|
|
||||||
certificate_t *cert;
|
|
||||||
CFDataRef data;
|
|
||||||
chunk_t chunk;
|
|
||||||
|
|
||||||
data = CFArrayGetValueAtIndex(certs, i);
|
|
||||||
if (data)
|
|
||||||
{
|
|
||||||
chunk = chunk_create((char*)CFDataGetBytePtr(data),
|
|
||||||
CFDataGetLength(data));
|
|
||||||
cert = lib->creds->create(lib->creds,
|
|
||||||
CRED_CERTIFICATE, CERT_X509,
|
|
||||||
BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
|
|
||||||
if (cert)
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, " loaded '%Y'", cert->get_subject(cert));
|
|
||||||
set->add_cert(set, TRUE, cert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CFRelease(certs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
|
|
||||||
METHOD(keychain_creds_t, destroy, void,
|
METHOD(keychain_creds_t, destroy, void,
|
||||||
private_keychain_creds_t *this)
|
private_keychain_creds_t *this)
|
||||||
{
|
{
|
||||||
@@ -185,8 +126,8 @@ keychain_creds_t *keychain_creds_create()
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this->roots = load_roots(this);
|
this->roots = load_certs(this, SYSTEM_ROOTS);
|
||||||
this->set = load_creds(this);
|
this->set = load_certs(this, SYSTEM);
|
||||||
|
|
||||||
lib->credmgr->add_set(lib->credmgr, &this->roots->set);
|
lib->credmgr->add_set(lib->credmgr, &this->roots->set);
|
||||||
lib->credmgr->add_set(lib->credmgr, &this->set->set);
|
lib->credmgr->add_set(lib->credmgr, &this->set->set);
|
||||||
|
|||||||
Reference in New Issue
Block a user