]> git.saurik.com Git - apple/security.git/blob - Keychain/KCCursor.cpp
11f88e2d12185e95bbc87b7772d0a2acfa30d57d
[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 {
44 recordType(Schema::recordTypeFor(itemClass));
45
46 if (!attrList) // No additional selectionPredicates: we are done
47 return;
48
49 conjunctive(CSSM_DB_AND);
50 const SecKeychainAttribute *end=&attrList->attr[attrList->count];
51 // Add all the attrs in attrs list to the cursor.
52 for (const SecKeychainAttribute *attr=attrList->attr; attr != end; ++attr)
53 {
54 const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag);
55 void *buf = attr->data;
56 UInt32 length = attr->length;
57 uint8 timeString[16];
58
59 // XXX This code is duplicated in NewItemImpl::setAttribute()
60 // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
61 // style attribute value.
62 if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE)
63 {
64 if (length == sizeof(UInt32))
65 {
66 MacSecondsToTimeString(*reinterpret_cast<const UInt32 *>(buf),
67 16, &timeString);
68 buf = &timeString;
69 length = 16;
70 }
71 else if (length == sizeof(SInt64))
72 {
73 MacLongDateTimeToTimeString(*reinterpret_cast<const SInt64 *>(buf),
74 16, &timeString);
75 buf = &timeString;
76 length = 16;
77 }
78 }
79 add(CSSM_DB_EQUAL,info, CssmData(buf,length));
80 }
81 }
82
83 KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList) :
84 mSearchList(searchList),
85 mCurrent(mSearchList.begin())
86 {
87 if (!attrList) // No additional selectionPredicates: we are done
88 return;
89
90 conjunctive(CSSM_DB_AND);
91 bool foundClassAttribute=false;
92 const SecKeychainAttribute *end=&attrList->attr[attrList->count];
93 // Add all the attrs in attrs list to the cursor.
94 for (const SecKeychainAttribute *attr=attrList->attr; attr != end; ++attr)
95 {
96 if (attr->tag!=kSecClassItemAttr) // a regular attribute
97 {
98 const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag);
99 void *buf = attr->data;
100 UInt32 length = attr->length;
101 uint8 timeString[16];
102
103 // XXX This code is duplicated in NewItemImpl::setAttribute()
104 // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
105 // style attribute value.
106 if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE)
107 {
108 if (length == sizeof(UInt32))
109 {
110 MacSecondsToTimeString(*reinterpret_cast<const UInt32 *>(buf),
111 16, &timeString);
112 buf = &timeString;
113 length = 16;
114 }
115 else if (length == sizeof(SInt64))
116 {
117 MacLongDateTimeToTimeString(*reinterpret_cast<const SInt64 *>(buf),
118 16, &timeString);
119 buf = &timeString;
120 length = 16;
121 }
122 }
123 add(CSSM_DB_EQUAL,info, CssmData(buf,length));
124
125 continue;
126 }
127
128 // the class attribute
129 if (foundClassAttribute || attr->length != sizeof(SecItemClass))
130 MacOSError::throwMe(paramErr); // We have 2 different 'clas' attributes
131
132 recordType(Schema::recordTypeFor(*reinterpret_cast<SecItemClass *>(attr->data)));
133 foundClassAttribute=true;
134 }
135 }
136
137 KCCursorImpl::~KCCursorImpl()
138 {
139 }
140
141 bool
142 KCCursorImpl::next(Item &item)
143 {
144 DbAttributes dbAttributes;
145 DbUniqueRecord uniqueId;
146
147 for (;;)
148 {
149 if (!mDbCursor)
150 {
151 if (mCurrent == mSearchList.end())
152 {
153 // No more keychains to search so we are done.
154 return false;
155 }
156
157 mDbCursor = DbCursor((*mCurrent)->database(), *this);
158 }
159
160 bool gotRecord;
161 try
162 {
163 gotRecord = mDbCursor->next(&dbAttributes, NULL, uniqueId);
164 }
165 catch(const CssmCommonError &err)
166 {
167 OSStatus status = err.osStatus();
168 if (status != CSSMERR_DL_DATASTORE_DOESNOT_EXIST
169 && status != CSSMERR_DL_INVALID_RECORDTYPE)
170 throw;
171
172 gotRecord = false;
173 }
174
175 // If we did not get a record from the current keychain or the current
176 // keychain did not exist skip to the next keychain in the list.
177 if (!gotRecord)
178 {
179 ++mCurrent;
180 mDbCursor = DbCursor();
181 continue;
182 }
183
184 // If doing a search for all records skip the db blob added by the
185 // CSP/DL and skip symmetric key items.
186 // @@@ This is wrong since we should only skip symmetric keys that are
187 // group keys and not user generated symmetric keys.
188 if (mDbCursor->recordType() == CSSM_DL_DB_RECORD_ANY &&
189 (dbAttributes.recordType() == 0x80008000
190 || dbAttributes.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY))
191 continue;
192
193 break;
194 }
195
196 // Go though Keychain since item might already exist.
197 item = (*mCurrent)->item(dbAttributes.recordType(), uniqueId);
198 return true;
199 }