IdentityCursor.cpp [plain text]
#include <security_keychain/IdentityCursor.h>
#include <security_keychain/Identity.h>
#include <security_keychain/Trust.h>
#include <security_keychain/Item.h>
#include <security_keychain/Certificate.h>
#include <security_keychain/KeyItem.h>
#include <security_cdsa_utilities/Schema.h>
#include <security_cdsa_utilities/KeySchema.h>
#include <Security/oidsalg.h>
using namespace KeychainCore;
IdentityCursorPolicyAndID::IdentityCursorPolicyAndID(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage, CFStringRef idString, SecPolicyRef policy, bool returnOnlyValidIdentities) :
IdentityCursor(searchList, keyUsage),
mPolicy(policy),
mIDString(idString),
mReturnOnlyValidIdentities(returnOnlyValidIdentities)
{
}
bool
IdentityCursorPolicyAndID::next(SecPointer<Identity> &identity)
{
SecPointer<Identity> currIdentity;
Boolean identityOK = true;
for (;;)
{
bool result = IdentityCursor::next(currIdentity); if ( result )
{
SecPointer<Certificate> certificate = currIdentity->certificate();
CSSM_OID policyOID;
SecPolicyGetOID(mPolicy, &policyOID); CFComparisonResult compareResult = kCFCompareGreaterThan; if ( 0 && mIDString )
{
}
else
{
CssmOid oid1 = CssmOid::overlay(CSSMOID_APPLE_TP_SMIME);
CssmOid oid2 = CssmOid::overlay(policyOID);
if ( oid1 == oid2 )
{
CFArrayRef emailAddressArray = NULL;
emailAddressArray = certificate->copyEmailAddresses();
if ( !emailAddressArray )
{
identityOK = false;
break;
}
else
{
short arrayIndex = 0;
CFIndex emailArraySize = CFArrayGetCount(emailAddressArray);
for (arrayIndex = 0;arrayIndex < emailArraySize; arrayIndex++)
{
CFStringRef compareToStr = (CFStringRef)CFArrayGetValueAtIndex(emailAddressArray, arrayIndex);
compareResult = CFStringCompare(mIDString, compareToStr, 0);
if ( compareResult == kCFCompareEqualTo )
break; }
CFRelease(emailAddressArray);
}
}
else
; }
if ( compareResult == kCFCompareEqualTo )
{
if ( mReturnOnlyValidIdentities && mPolicy )
{
CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 1, NULL);
if ( !certArray )
{
identityOK = false;
break; }
CFArrayAppendValue(certArray, (void*)(certificate->handle()));
Trust* trust = new Trust(certArray, mPolicy);
trust->evaluate();
SecTrustResultType trustResult = trust->result();
delete trust;
CFRelease(certArray); if ( trustResult == kSecTrustResultInvalid )
identityOK = false; else
break; }
}
}
else
{
identityOK = false;
break; }
}
if ( identityOK )
{
identity = currIdentity; return true;
}
else
return false;
}
IdentityCursor::IdentityCursor(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage) :
mSearchList(searchList),
mKeyCursor(mSearchList, CSSM_DL_DB_RECORD_PRIVATE_KEY, NULL)
{
if (keyUsage & CSSM_KEYUSE_ANY)
keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT
| CSSM_KEYUSE_DERIVE | CSSM_KEYUSE_SIGN
| CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_SIGN_RECOVER
| CSSM_KEYUSE_VERIFY_RECOVER | CSSM_KEYUSE_WRAP
| CSSM_KEYUSE_UNWRAP;
if (keyUsage & CSSM_KEYUSE_ENCRYPT)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Encrypt, true);
if (keyUsage & CSSM_KEYUSE_DECRYPT)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Decrypt, true);
if (keyUsage & CSSM_KEYUSE_DERIVE)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Derive, true);
if (keyUsage & CSSM_KEYUSE_SIGN)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Sign, true);
if (keyUsage & CSSM_KEYUSE_VERIFY)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Verify, true);
if (keyUsage & CSSM_KEYUSE_SIGN_RECOVER)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::SignRecover, true);
if (keyUsage & CSSM_KEYUSE_VERIFY_RECOVER)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::VerifyRecover, true);
if (keyUsage & CSSM_KEYUSE_WRAP)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Wrap, true);
if (keyUsage & CSSM_KEYUSE_UNWRAP)
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Unwrap, true);
}
IdentityCursor::~IdentityCursor() throw()
{
}
bool
IdentityCursor::next(SecPointer<Identity> &identity)
{
for (;;)
{
if (!mCertificateCursor)
{
Item key;
if (!mKeyCursor->next(key))
return false;
mCurrentKey = static_cast<KeyItem *>(key.get());
CssmClient::DbUniqueRecord uniqueId = mCurrentKey->dbUniqueRecord();
CssmClient::DbAttributes dbAttributes(uniqueId->database(), 1);
dbAttributes.add(KeySchema::Label);
uniqueId->get(&dbAttributes, NULL);
const CssmData &keyHash = dbAttributes[0];
mCertificateCursor = KCCursor(mSearchList, CSSM_DL_DB_RECORD_X509_CERTIFICATE, NULL);
mCertificateCursor->add(CSSM_DB_EQUAL, Schema::kX509CertificatePublicKeyHash, keyHash);
}
Item cert;
if (mCertificateCursor->next(cert))
{
SecPointer<Certificate> certificate(static_cast<Certificate *>(cert.get()));
identity = new Identity(mCurrentKey, certificate);
return true;
}
else
mCertificateCursor = KCCursor();
}
}