SecKeychainSearch.cpp
1 /* 2 * Copyright (c) 2000-2004,2011-2016 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 #include <Security/SecKeychainSearch.h> 25 #include <Security/SecKeychainSearchPriv.h> 26 #include <Security/SecCertificatePriv.h> 27 #include <security_keychain/KCCursor.h> 28 #include <security_keychain/Certificate.h> 29 #include <security_keychain/Item.h> 30 #include <security_cdsa_utilities/Schema.h> 31 #include <syslog.h> 32 #include <os/activity.h> 33 34 #include "SecBridge.h" 35 #include "LegacyAPICounts.h" 36 37 CFTypeID 38 SecKeychainSearchGetTypeID(void) 39 { 40 BEGIN_SECAPI 41 return gTypes().KCCursorImpl.typeID; 42 43 END_SECAPI1(_kCFRuntimeNotATypeID) 44 } 45 46 47 OSStatus 48 SecKeychainSearchCreateFromAttributes(CFTypeRef keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef) 49 { 50 BEGIN_SECAPI 51 os_activity_t activity = os_activity_create("SecKeychainSearchCreateFromAttributes", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 52 os_activity_scope(activity); 53 os_release(activity); 54 55 Required(searchRef); 56 57 StorageManager::KeychainList keychains; 58 globals().storageManager.optionalSearchList(keychainOrArray, keychains); 59 KCCursor cursor(keychains, itemClass, attrList); 60 *searchRef = cursor->handle(); 61 62 END_SECAPI 63 } 64 65 66 OSStatus 67 SecKeychainSearchCreateFromAttributesExtended(CFTypeRef keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList *attrList, CSSM_DB_CONJUNCTIVE dbConjunctive, CSSM_DB_OPERATOR dbOperator, SecKeychainSearchRef *searchRef) 68 { 69 BEGIN_SECAPI 70 os_activity_t activity = os_activity_create("SecKeychainSearchCreateFromAttributesExtended", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 71 os_activity_scope(activity); 72 os_release(activity); 73 74 Required(searchRef); // Make sure that searchRef is an invalid SearchRef 75 76 StorageManager::KeychainList keychains; 77 globals().storageManager.optionalSearchList(keychainOrArray, keychains); 78 KCCursor cursor(keychains, itemClass, attrList, dbConjunctive, dbOperator); 79 80 *searchRef = cursor->handle(); 81 82 END_SECAPI 83 } 84 85 86 87 OSStatus 88 SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *itemRef) 89 { 90 BEGIN_SECAPI 91 os_activity_t activity = os_activity_create("SecKeychainSearchCopyNext", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 92 os_activity_scope(activity); 93 os_release(activity); 94 95 RequiredParam(itemRef); 96 Item item; 97 KCCursorImpl *itemCursor = KCCursorImpl::required(searchRef); 98 if (!itemCursor->next(item)) 99 return errSecItemNotFound; 100 101 *itemRef=item->handle(); 102 103 bool itemChecked = false; 104 do { 105 /* see if we should convert outgoing item to a unified SecCertificateRef */ 106 SecItemClass tmpItemClass = Schema::itemClassFor(item->recordType()); 107 if (tmpItemClass == kSecCertificateItemClass) { 108 SecPointer<Certificate> certificate(static_cast<Certificate *>(&*item)); 109 CssmData certData = certificate->data(); 110 CFDataRef data = NULL; 111 if (certData.Data && certData.Length) { 112 data = CFDataCreate(NULL, certData.Data, certData.Length); 113 } 114 if (!data) { 115 /* zero-length or otherwise bad cert data; skip to next item */ 116 if (*itemRef) { 117 CFRelease(*itemRef); 118 *itemRef = NULL; 119 } 120 if (!itemCursor->next(item)) 121 return errSecItemNotFound; 122 *itemRef=item->handle(); 123 continue; 124 } 125 SecKeychainItemRef tmpRef = *itemRef; 126 *itemRef = (SecKeychainItemRef) SecCertificateCreateWithKeychainItem(NULL, data, tmpRef); 127 if (data) 128 CFRelease(data); 129 if (tmpRef) 130 CFRelease(tmpRef); 131 if (NULL == *itemRef) { 132 /* unable to create unified certificate item; skip to next item */ 133 if (!itemCursor->next(item)) 134 return errSecItemNotFound; 135 *itemRef=item->handle(); 136 continue; 137 } 138 itemChecked = true; 139 } 140 else { 141 itemChecked = true; 142 } 143 } while (!itemChecked); 144 145 if (NULL == *itemRef) { 146 /* never permit a NULL item reference to be returned without an error result */ 147 return errSecItemNotFound; 148 } 149 150 END_SECAPI 151 }