2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
27 #include "cssmdatetime.h"
29 #include "StorageManager.h"
30 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
31 #include <Security/SecKeychainAPIPriv.h>
33 using namespace KeychainCore
;
34 using namespace CssmClient
;
35 using namespace CSSMDateTimeUtils
;
40 KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList
&searchList
, SecItemClass itemClass
, const SecKeychainAttributeList
*attrList
) :
41 mSearchList(searchList
),
42 mCurrent(mSearchList
.begin()),
45 recordType(Schema::recordTypeFor(itemClass
));
47 if (!attrList
) // No additional selectionPredicates: we are done
50 conjunctive(CSSM_DB_AND
);
51 const SecKeychainAttribute
*end
=&attrList
->attr
[attrList
->count
];
52 // Add all the attrs in attrs list to the cursor.
53 for (const SecKeychainAttribute
*attr
=attrList
->attr
; attr
!= end
; ++attr
)
55 const CssmDbAttributeInfo
&info
= Schema::attributeInfo(attr
->tag
);
56 void *buf
= attr
->data
;
57 UInt32 length
= attr
->length
;
60 // XXX This code is duplicated in NewItemImpl::setAttribute()
61 // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
62 // style attribute value.
63 if (info
.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
)
65 if (length
== sizeof(UInt32
))
67 MacSecondsToTimeString(*reinterpret_cast<const UInt32
*>(buf
),
72 else if (length
== sizeof(SInt64
))
74 MacLongDateTimeToTimeString(*reinterpret_cast<const SInt64
*>(buf
),
80 add(CSSM_DB_EQUAL
,info
, CssmData(buf
,length
));
84 KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList
&searchList
, const SecKeychainAttributeList
*attrList
) :
85 mSearchList(searchList
),
86 mCurrent(mSearchList
.begin()),
89 if (!attrList
) // No additional selectionPredicates: we are done
92 conjunctive(CSSM_DB_AND
);
93 bool foundClassAttribute
=false;
94 const SecKeychainAttribute
*end
=&attrList
->attr
[attrList
->count
];
95 // Add all the attrs in attrs list to the cursor.
96 for (const SecKeychainAttribute
*attr
=attrList
->attr
; attr
!= end
; ++attr
)
98 if (attr
->tag
!=kSecClassItemAttr
) // a regular attribute
100 const CssmDbAttributeInfo
&info
= Schema::attributeInfo(attr
->tag
);
101 void *buf
= attr
->data
;
102 UInt32 length
= attr
->length
;
103 uint8 timeString
[16];
105 // XXX This code is duplicated in NewItemImpl::setAttribute()
106 // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
107 // style attribute value.
108 if (info
.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
)
110 if (length
== sizeof(UInt32
))
112 MacSecondsToTimeString(*reinterpret_cast<const UInt32
*>(buf
),
117 else if (length
== sizeof(SInt64
))
119 MacLongDateTimeToTimeString(*reinterpret_cast<const SInt64
*>(buf
),
125 add(CSSM_DB_EQUAL
,info
, CssmData(buf
,length
));
130 // the class attribute
131 if (foundClassAttribute
|| attr
->length
!= sizeof(SecItemClass
))
132 MacOSError::throwMe(paramErr
); // We have 2 different 'clas' attributes
134 recordType(Schema::recordTypeFor(*reinterpret_cast<SecItemClass
*>(attr
->data
)));
135 foundClassAttribute
=true;
139 KCCursorImpl::~KCCursorImpl() throw()
144 KCCursorImpl::next(Item
&item
)
146 DbAttributes dbAttributes
;
147 DbUniqueRecord uniqueId
;
154 if (mCurrent
== mSearchList
.end())
156 // If we got always failed when calling mDbCursor->next return the error from
157 // the last call to mDbCursor->next now
158 if (mAllFailed
&& status
)
159 CssmError::throwMe(status
);
161 // No more keychains to search so we are done.
165 mDbCursor
= DbCursor((*mCurrent
)->database(), *this);
171 gotRecord
= mDbCursor
->next(&dbAttributes
, NULL
, uniqueId
);
174 catch(const CssmCommonError
&err
)
176 // Catch the last error we get and move on to the next keychain
177 // This error will be returned when we reach the end of our keychain list
178 // iff all calls to KCCursorImpl::next failed
179 status
= err
.osStatus();
183 // If we did not get a record from the current keychain or the current
184 // keychain did not exist skip to the next keychain in the list.
188 mDbCursor
= DbCursor();
192 // If doing a search for all records skip the db blob added by the
193 // CSP/DL and skip symmetric key items.
194 // @@@ This is wrong since we should only skip symmetric keys that are
195 // group keys and not user generated symmetric keys.
196 if (mDbCursor
->recordType() == CSSM_DL_DB_RECORD_ANY
&&
197 (dbAttributes
.recordType() == 0x80008000
198 || dbAttributes
.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY
))
204 // Go though Keychain since item might already exist.
205 item
= (*mCurrent
)->item(dbAttributes
.recordType(), uniqueId
);