]> git.saurik.com Git - apple/security.git/blob - Keychain/KCCursor.cpp
Security-179.tar.gz
[apple/security.git] / Keychain / KCCursor.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // KCCursor.cpp
21 //
22
23 #include "KCCursor.h"
24
25 #include "Item.h"
26 #include "Schema.h"
27 #include "cssmdatetime.h"
28 #include "Globals.h"
29 #include "StorageManager.h"
30 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
31 #include <Security/SecKeychainAPIPriv.h>
32
33 using namespace KeychainCore;
34 using namespace CssmClient;
35 using namespace CSSMDateTimeUtils;
36
37 //
38 // KCCursorImpl
39 //
40 KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, SecItemClass itemClass, const SecKeychainAttributeList *attrList) :
41 mSearchList(searchList),
42 mCurrent(mSearchList.begin()),
43 mAllFailed(true)
44 {
45 recordType(Schema::recordTypeFor(itemClass));
46
47 if (!attrList) // No additional selectionPredicates: we are done
48 return;
49
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)
54 {
55 const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag);
56 void *buf = attr->data;
57 UInt32 length = attr->length;
58 uint8 timeString[16];
59
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)
64 {
65 if (length == sizeof(UInt32))
66 {
67 MacSecondsToTimeString(*reinterpret_cast<const UInt32 *>(buf),
68 16, &timeString);
69 buf = &timeString;
70 length = 16;
71 }
72 else if (length == sizeof(SInt64))
73 {
74 MacLongDateTimeToTimeString(*reinterpret_cast<const SInt64 *>(buf),
75 16, &timeString);
76 buf = &timeString;
77 length = 16;
78 }
79 }
80 add(CSSM_DB_EQUAL,info, CssmData(buf,length));
81 }
82 }
83
84 KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList) :
85 mSearchList(searchList),
86 mCurrent(mSearchList.begin()),
87 mAllFailed(true)
88 {
89 if (!attrList) // No additional selectionPredicates: we are done
90 return;
91
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)
97 {
98 if (attr->tag!=kSecClassItemAttr) // a regular attribute
99 {
100 const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag);
101 void *buf = attr->data;
102 UInt32 length = attr->length;
103 uint8 timeString[16];
104
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)
109 {
110 if (length == sizeof(UInt32))
111 {
112 MacSecondsToTimeString(*reinterpret_cast<const UInt32 *>(buf),
113 16, &timeString);
114 buf = &timeString;
115 length = 16;
116 }
117 else if (length == sizeof(SInt64))
118 {
119 MacLongDateTimeToTimeString(*reinterpret_cast<const SInt64 *>(buf),
120 16, &timeString);
121 buf = &timeString;
122 length = 16;
123 }
124 }
125 add(CSSM_DB_EQUAL,info, CssmData(buf,length));
126
127 continue;
128 }
129
130 // the class attribute
131 if (foundClassAttribute || attr->length != sizeof(SecItemClass))
132 MacOSError::throwMe(paramErr); // We have 2 different 'clas' attributes
133
134 recordType(Schema::recordTypeFor(*reinterpret_cast<SecItemClass *>(attr->data)));
135 foundClassAttribute=true;
136 }
137 }
138
139 KCCursorImpl::~KCCursorImpl() throw()
140 {
141 }
142
143 bool
144 KCCursorImpl::next(Item &item)
145 {
146 DbAttributes dbAttributes;
147 DbUniqueRecord uniqueId;
148 OSStatus status = 0;
149
150 for (;;)
151 {
152 if (!mDbCursor)
153 {
154 if (mCurrent == mSearchList.end())
155 {
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);
160
161 // No more keychains to search so we are done.
162 return false;
163 }
164
165 mDbCursor = DbCursor((*mCurrent)->database(), *this);
166 }
167
168 bool gotRecord;
169 try
170 {
171 gotRecord = mDbCursor->next(&dbAttributes, NULL, uniqueId);
172 mAllFailed = false;
173 }
174 catch(const CssmCommonError &err)
175 {
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();
180 gotRecord = false;
181 }
182
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.
185 if (!gotRecord)
186 {
187 ++mCurrent;
188 mDbCursor = DbCursor();
189 continue;
190 }
191
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))
199 continue;
200
201 break;
202 }
203
204 // Go though Keychain since item might already exist.
205 item = (*mCurrent)->item(dbAttributes.recordType(), uniqueId);
206 return true;
207 }