/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This 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. */ // // KCCursor.cpp // #include "KCCursor.h" #include "Item.h" #include "Schema.h" #include "cssmdatetime.h" #include "Globals.h" #include "StorageManager.h" #include #include using namespace KeychainCore; using namespace CssmClient; using namespace CSSMDateTimeUtils; // // KCCursorImpl // KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, SecItemClass itemClass, const SecKeychainAttributeList *attrList) : mSearchList(searchList), mCurrent(mSearchList.begin()) { recordType(Schema::recordTypeFor(itemClass)); if (!attrList) // No additional selectionPredicates: we are done return; conjunctive(CSSM_DB_AND); const SecKeychainAttribute *end=&attrList->attr[attrList->count]; // Add all the attrs in attrs list to the cursor. for (const SecKeychainAttribute *attr=attrList->attr; attr != end; ++attr) { const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag); void *buf = attr->data; UInt32 length = attr->length; uint8 timeString[16]; // XXX This code is duplicated in NewItemImpl::setAttribute() // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE // style attribute value. if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) { if (length == sizeof(UInt32)) { MacSecondsToTimeString(*reinterpret_cast(buf), 16, &timeString); buf = &timeString; length = 16; } else if (length == sizeof(SInt64)) { MacLongDateTimeToTimeString(*reinterpret_cast(buf), 16, &timeString); buf = &timeString; length = 16; } } add(CSSM_DB_EQUAL,info, CssmData(buf,length)); } } KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList) : mSearchList(searchList), mCurrent(mSearchList.begin()) { if (!attrList) // No additional selectionPredicates: we are done return; conjunctive(CSSM_DB_AND); bool foundClassAttribute=false; const SecKeychainAttribute *end=&attrList->attr[attrList->count]; // Add all the attrs in attrs list to the cursor. for (const SecKeychainAttribute *attr=attrList->attr; attr != end; ++attr) { if (attr->tag!=kSecClassItemAttr) // a regular attribute { const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag); void *buf = attr->data; UInt32 length = attr->length; uint8 timeString[16]; // XXX This code is duplicated in NewItemImpl::setAttribute() // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE // style attribute value. if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) { if (length == sizeof(UInt32)) { MacSecondsToTimeString(*reinterpret_cast(buf), 16, &timeString); buf = &timeString; length = 16; } else if (length == sizeof(SInt64)) { MacLongDateTimeToTimeString(*reinterpret_cast(buf), 16, &timeString); buf = &timeString; length = 16; } } add(CSSM_DB_EQUAL,info, CssmData(buf,length)); continue; } // the class attribute if (foundClassAttribute || attr->length != sizeof(SecItemClass)) MacOSError::throwMe(paramErr); // We have 2 different 'clas' attributes recordType(Schema::recordTypeFor(*reinterpret_cast(attr->data))); foundClassAttribute=true; } } KCCursorImpl::~KCCursorImpl() { } bool KCCursorImpl::next(Item &item) { DbAttributes dbAttributes; DbUniqueRecord uniqueId; for (;;) { if (!mDbCursor) { if (mCurrent == mSearchList.end()) { // No more keychains to search so we are done. return false; } mDbCursor = DbCursor((*mCurrent)->database(), *this); } bool gotRecord; try { gotRecord = mDbCursor->next(&dbAttributes, NULL, uniqueId); } catch(const CssmCommonError &err) { OSStatus status = err.osStatus(); if (status != CSSMERR_DL_DATASTORE_DOESNOT_EXIST && status != CSSMERR_DL_INVALID_RECORDTYPE) throw; gotRecord = false; } // If we did not get a record from the current keychain or the current // keychain did not exist skip to the next keychain in the list. if (!gotRecord) { ++mCurrent; mDbCursor = DbCursor(); continue; } // If doing a search for all records skip the db blob added by the // CSP/DL and skip symmetric key items. // @@@ This is wrong since we should only skip symmetric keys that are // group keys and not user generated symmetric keys. if (mDbCursor->recordType() == CSSM_DL_DB_RECORD_ANY && (dbAttributes.recordType() == 0x80008000 || dbAttributes.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY)) continue; break; } // Go though Keychain since item might already exist. item = (*mCurrent)->item(dbAttributes.recordType(), uniqueId); return true; }