]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_keychain/lib/IdentityCursor.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / IdentityCursor.cpp
diff --git a/Security/libsecurity_keychain/lib/IdentityCursor.cpp b/Security/libsecurity_keychain/lib/IdentityCursor.cpp
deleted file mode 100644 (file)
index e7f24d8..0000000
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (c) 2002-2008,2011-2012 Apple Inc. All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- *
- * IdentityCursor.cpp -- Working with IdentityCursor
- */
-
-#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_keychain/Globals.h>
-#include <security_cdsa_utilities/Schema.h>
-#include <security_cdsa_utilities/KeySchema.h>
-#include <Security/oidsalg.h>
-#include <Security/SecKeychainItemPriv.h>
-#include <security_utilities/simpleprefs.h>
-#include <sys/param.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),
-       mPreferredIdentityChecked(false),
-       mPreferredIdentity(nil)
-{
-    if (mPolicy)
-        CFRetain(mPolicy);
-
-    if (mIDString)
-        CFRetain(mIDString);
-}
-
-IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() throw()
-{
-    if (mPolicy)
-        CFRelease(mPolicy);
-
-    if (mIDString)
-        CFRelease(mIDString);
-}
-
-void
-IdentityCursorPolicyAndID::findPreferredIdentity()
-{
-       char idUTF8[MAXPATHLEN];
-       if (!mIDString || !CFStringGetCString(mIDString, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
-               idUTF8[0] = (char)'\0';
-       uint32_t iprfValue = 'iprf'; // value is specified in host byte order, since kSecTypeItemAttr has type uint32 in the db schema
-       SecKeychainAttribute sAttrs[] = {
-               { kSecTypeItemAttr, sizeof(uint32_t), &iprfValue },
-               { kSecServiceItemAttr, (UInt32)strlen(idUTF8), (char *)idUTF8 }
-       };
-       SecKeychainAttributeList sAttrList = { sizeof(sAttrs) / sizeof(sAttrs[0]), sAttrs };
-
-//     StorageManager::KeychainList keychains;
-//     globals().storageManager.optionalSearchList((CFTypeRef)nil, keychains);
-
-       Item item;
-       KCCursor cursor(mSearchList /*keychains*/, kSecGenericPasswordItemClass, &sAttrList);
-       if (!cursor->next(item))
-               return;
-
-       // get persistent certificate reference
-       SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } };
-       SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
-       item->getContent(NULL, &itemAttrList, NULL, NULL);
-
-       // find certificate, given persistent reference data
-       CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull);
-       SecKeychainItemRef certItemRef = nil;
-       OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef);
-       if (pItemRef)
-               CFRelease(pItemRef);
-       item->freeContent(&itemAttrList, NULL);
-       if (status || !certItemRef)
-               return;
-
-       // create identity reference, given certificate
-       Item certItem = ItemImpl::required(SecKeychainItemRef(certItemRef));
-       SecPointer<Certificate> certificate(static_cast<Certificate *>(certItem.get()));
-       SecPointer<Identity> identity(new Identity(mSearchList /*keychains*/, certificate));
-
-       mPreferredIdentity = identity;
-       
-       if (certItemRef)
-               CFRelease(certItemRef);
-}
-
-bool
-IdentityCursorPolicyAndID::next(SecPointer<Identity> &identity)
-{
-       SecPointer<Identity> currIdentity;
-       Boolean identityOK = true;
-
-       if (!mPreferredIdentityChecked)
-       {
-        try
-        {
-            findPreferredIdentity();
-        }
-        catch(...) {}
-               mPreferredIdentityChecked = true;
-               if (mPreferredIdentity)
-               {
-                       identity = mPreferredIdentity;
-                       return true;
-               }
-       }
-
-       for (;;)
-       {
-               bool result = IdentityCursor::next(currIdentity);   // base class finds the next identity by keyUsage
-               if ( result )
-               {
-                       if (mPreferredIdentity && (currIdentity == mPreferredIdentity))
-                       {
-                               identityOK = false;     // we already returned this one, move on to the next
-                               continue;
-                       }
-
-                       // If there was no policy specified, we're done.
-                       if ( !mPolicy )
-                       {
-                               identityOK = true; // return this identity
-                               break;
-                       }
-
-                       // To reduce the number of (potentially expensive) trust evaluations performed, we need
-                       // to do some pre-processing to filter out certs that don't match the search criteria.
-                       // Rather than try to duplicate the TP's policy logic here, we'll just call the TP with
-                       // a single-element certificate array, no anchors, and no keychains to search.
-
-                       SecPointer<Certificate> certificate = currIdentity->certificate();
-                       CFRef<SecCertificateRef> certRef(certificate->handle());
-                       CFRef<CFMutableArrayRef> anchorsArray(CFArrayCreateMutable(NULL, 1, NULL));
-                       CFRef<CFMutableArrayRef> certArray(CFArrayCreateMutable(NULL, 1, NULL));
-                       if ( !certArray || !anchorsArray )
-                       {
-                               identityOK = false; // skip this and move on to the next one
-                               continue;
-                       }
-                       CFArrayAppendValue(certArray, certRef);
-
-                       SecPointer<Trust> trustLite = new Trust(certArray, mPolicy);
-                       StorageManager::KeychainList emptyList;
-                       // Set the anchors and keychain search list to be empty
-                       trustLite->anchors(anchorsArray);
-                       trustLite->searchLibs(emptyList);
-                       trustLite->evaluate();
-                       SecTrustResultType trustResult = trustLite->result();
-
-                       if (trustResult == kSecTrustResultRecoverableTrustFailure ||
-                               trustResult == kSecTrustResultFatalTrustFailure)
-                       {
-                               CFArrayRef certChain = NULL;
-                               CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL, *evInfo = NULL;
-                               trustLite->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
-                               if (statusChain)
-                                       evInfo = &statusChain[0];
-                               if (!evInfo || evInfo->NumStatusCodes > 0) // per-cert codes means we can't use this cert for this policy
-                                       trustResult = kSecTrustResultInvalid; // handled below
-                               if (certChain)
-                                       CFRelease(certChain);
-                       }
-                       if (trustResult == kSecTrustResultInvalid)
-                       {
-                               identityOK = false; // move on to the next one
-                               continue;
-                       }
-
-                       // If trust evaluation isn't requested, we're done.
-                       if ( !mReturnOnlyValidIdentities )
-                       {
-                               identityOK = true; // return this identity
-                               break;
-                       }
-
-                       // Perform a full trust evaluation on the certificate with the specified policy.
-                       SecPointer<Trust> trust = new Trust(certArray, mPolicy);
-                       trust->evaluate();
-                       trustResult = trust->result();
-
-                       if (trustResult == kSecTrustResultInvalid ||
-                               trustResult == kSecTrustResultRecoverableTrustFailure ||
-                               trustResult == kSecTrustResultFatalTrustFailure)
-                       {
-                               identityOK = false; // move on to the next one
-                               continue;
-                       }
-
-                       identityOK = true; // this one was OK; return it.
-                       break;
-               }
-               else
-               {
-                       identityOK = false; // no more left.
-                       break;
-               }
-       }   // for(;;)
-       
-       if ( identityOK )
-       {
-               identity = currIdentity; // caller will release the identity
-               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),
-       mMutex(Mutex::recursive)
-{
-       StLock<Mutex>_(mMutex);
-
-       // If keyUsage is CSSM_KEYUSE_ANY then we need a key that can do everything
-       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()
-{
-}
-
-CFDataRef
-IdentityCursor::pubKeyHashForSystemIdentity(CFStringRef domain)
-{
-       StLock<Mutex>_(mMutex);
-
-    CFDataRef entryValue = nil;
-       auto_ptr<Dictionary> identDict;
-       Dictionary* d = Dictionary::CreateDictionary("com.apple.security.systemidentities", Dictionary::US_System);
-       if (d)
-       {
-               identDict.reset(d);
-        entryValue = identDict->getDataValue(domain);
-        if (entryValue == nil) {
-            /* try for default entry if we're not already looking for default */
-            if(!CFEqual(domain, kSecIdentityDomainDefault)) {
-                entryValue = identDict->getDataValue(kSecIdentityDomainDefault);
-            }
-        }
-    }
-
-    if (entryValue) {
-        CFRetain(entryValue);
-    }
-    return entryValue;
-}
-
-bool
-IdentityCursor::next(SecPointer<Identity> &identity)
-{
-       StLock<Mutex>_(mMutex);
-
-       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);
-
-            // if we have entries for the system identities, exclude their public key hashes in the search
-            CFDataRef systemDefaultCertPubKeyHash = pubKeyHashForSystemIdentity(kSecIdentityDomainDefault);
-            if (systemDefaultCertPubKeyHash) {
-                CssmData pkHash((void *)CFDataGetBytePtr(systemDefaultCertPubKeyHash), CFDataGetLength(systemDefaultCertPubKeyHash));
-                mCertificateCursor->add(CSSM_DB_NOT_EQUAL, Schema::kX509CertificatePublicKeyHash, pkHash);
-                CFRelease(systemDefaultCertPubKeyHash);
-            }
-            CFDataRef kerbKDCCertPubKeyHash = pubKeyHashForSystemIdentity(kSecIdentityDomainKerberosKDC);
-            if (kerbKDCCertPubKeyHash) {
-                CssmData pkHash((void *)CFDataGetBytePtr(kerbKDCCertPubKeyHash), CFDataGetLength(kerbKDCCertPubKeyHash));
-                mCertificateCursor->add(CSSM_DB_NOT_EQUAL, Schema::kX509CertificatePublicKeyHash, pkHash);
-                CFRelease(kerbKDCCertPubKeyHash);
-            }
-               }
-       
-               Item cert;
-               if (mCertificateCursor->next(cert))
-               {
-                       SecPointer<Certificate> certificate(static_cast<Certificate *>(cert.get()));
-                       identity = new Identity(mCurrentKey, certificate);
-                       return true;
-               }
-               else
-                       mCertificateCursor = KCCursor();
-       }
-}