/ OSX / libsecurity_keychain / lib / SecKeychainSearch.cpp
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  }