OLD | NEW |
---|---|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/logging.h" | 5 #include "base/logging.h" |
6 #include "base/time.h" | 6 #include "base/time.h" |
7 #include "chrome/browser/keychain_mock_mac.h" | 7 #include "chrome/browser/keychain_mock_mac.h" |
8 | 8 |
9 MockKeychain::MockKeychain(unsigned int item_capacity) | 9 MockKeychain::MockKeychain(unsigned int item_capacity) |
10 : item_capacity_(item_capacity), item_count_(0), search_copy_count_(0), | 10 : item_capacity_(item_capacity), item_count_(0), search_copy_count_(0), |
11 keychain_item_copy_count_(0), attribute_data_copy_count_(0) { | 11 keychain_item_copy_count_(0), attribute_data_copy_count_(0) { |
12 UInt32 tags[] = { kSecAccountItemAttr, | 12 UInt32 tags[] = { kSecAccountItemAttr, |
13 kSecServerItemAttr, | 13 kSecServerItemAttr, |
14 kSecPortItemAttr, | 14 kSecPortItemAttr, |
15 kSecPathItemAttr, | 15 kSecPathItemAttr, |
16 kSecProtocolItemAttr, | 16 kSecProtocolItemAttr, |
17 kSecAuthenticationTypeItemAttr, | 17 kSecAuthenticationTypeItemAttr, |
18 kSecSecurityDomainItemAttr, | 18 kSecSecurityDomainItemAttr, |
19 kSecCreationDateItemAttr, | 19 kSecCreationDateItemAttr, |
20 kSecNegativeItemAttr }; | 20 kSecNegativeItemAttr, |
21 kSecCreatorItemAttr }; | |
21 | 22 |
22 // Create the test keychain data storage. | 23 // Create the test keychain data storage. |
23 keychain_attr_list_ = static_cast<SecKeychainAttributeList*>( | 24 keychain_attr_list_ = static_cast<SecKeychainAttributeList*>( |
24 calloc(item_capacity_, sizeof(SecKeychainAttributeList))); | 25 calloc(item_capacity_, sizeof(SecKeychainAttributeList))); |
25 keychain_data_ = static_cast<KeychainPasswordData*>( | 26 keychain_data_ = static_cast<KeychainPasswordData*>( |
26 calloc(item_capacity_, sizeof(KeychainPasswordData))); | 27 calloc(item_capacity_, sizeof(KeychainPasswordData))); |
27 for (unsigned int i = 0; i < item_capacity_; ++i) { | 28 for (unsigned int i = 0; i < item_capacity_; ++i) { |
28 keychain_attr_list_[i].count = arraysize(tags); | 29 keychain_attr_list_[i].count = arraysize(tags); |
29 keychain_attr_list_[i].attr = static_cast<SecKeychainAttribute*>( | 30 keychain_attr_list_[i].attr = static_cast<SecKeychainAttribute*>( |
30 calloc(keychain_attr_list_[i].count, sizeof(SecKeychainAttribute))); | 31 calloc(keychain_attr_list_[i].count, sizeof(SecKeychainAttribute))); |
31 for (unsigned int j = 0; j < keychain_attr_list_[i].count; ++j) { | 32 for (unsigned int j = 0; j < keychain_attr_list_[i].count; ++j) { |
32 keychain_attr_list_[i].attr[j].tag = tags[j]; | 33 keychain_attr_list_[i].attr[j].tag = tags[j]; |
33 size_t data_size = 0; | 34 size_t data_size = 0; |
34 switch (tags[j]) { | 35 switch (tags[j]) { |
35 case kSecPortItemAttr: | 36 case kSecPortItemAttr: |
36 data_size = sizeof(UInt32); | 37 data_size = sizeof(UInt32); |
37 break; | 38 break; |
38 case kSecProtocolItemAttr: | 39 case kSecProtocolItemAttr: |
39 data_size = sizeof(SecProtocolType); | 40 data_size = sizeof(SecProtocolType); |
40 break; | 41 break; |
41 case kSecAuthenticationTypeItemAttr: | 42 case kSecAuthenticationTypeItemAttr: |
42 data_size = sizeof(SecAuthenticationType); | 43 data_size = sizeof(SecAuthenticationType); |
43 break; | 44 break; |
44 case kSecNegativeItemAttr: | 45 case kSecNegativeItemAttr: |
45 data_size = sizeof(Boolean); | 46 data_size = sizeof(Boolean); |
46 break; | 47 break; |
48 case kSecCreatorItemAttr: | |
49 data_size = sizeof(OSType); | |
50 break; | |
47 } | 51 } |
48 if (data_size > 0) { | 52 if (data_size > 0) { |
49 keychain_attr_list_[i].attr[j].length = data_size; | 53 keychain_attr_list_[i].attr[j].length = data_size; |
50 keychain_attr_list_[i].attr[j].data = calloc(1, data_size); | 54 keychain_attr_list_[i].attr[j].data = calloc(1, data_size); |
51 } | 55 } |
52 } | 56 } |
53 } | 57 } |
54 } | 58 } |
55 | 59 |
56 MockKeychain::~MockKeychain() { | 60 MockKeychain::~MockKeychain() { |
57 for (unsigned int i = 0; i < item_capacity_; ++i) { | 61 for (unsigned int i = 0; i < item_capacity_; ++i) { |
58 for (unsigned int j = 0; j < keychain_attr_list_[i].count; ++j) { | 62 for (unsigned int j = 0; j < keychain_attr_list_[i].count; ++j) { |
59 if (keychain_attr_list_[i].attr[j].data) { | 63 if (keychain_attr_list_[i].attr[j].data) { |
60 free(keychain_attr_list_[i].attr[j].data); | 64 free(keychain_attr_list_[i].attr[j].data); |
61 } | 65 } |
62 } | 66 } |
63 free(keychain_attr_list_[i].attr); | 67 free(keychain_attr_list_[i].attr); |
64 if (keychain_data_[i].data) { | 68 if (keychain_data_[i].data) { |
65 free(keychain_data_[i].data); | 69 free(keychain_data_[i].data); |
66 } | 70 } |
67 } | 71 } |
68 free(keychain_attr_list_); | 72 free(keychain_attr_list_); |
69 free(keychain_data_); | 73 free(keychain_data_); |
70 } | 74 } |
71 | 75 |
72 int MockKeychain::IndexForTag(const SecKeychainAttributeList& attribute_list, | 76 |
73 UInt32 tag) { | 77 SecKeychainAttribute* MockKeychain::AttributeWithTag( |
78 const SecKeychainAttributeList& attribute_list, UInt32 tag) { | |
79 int attribute_index = -1; | |
74 for (unsigned int i = 0; i < attribute_list.count; ++i) { | 80 for (unsigned int i = 0; i < attribute_list.count; ++i) { |
75 if (attribute_list.attr[i].tag == tag) { | 81 if (attribute_list.attr[i].tag == tag) { |
76 return i; | 82 attribute_index = i; |
83 break; | |
77 } | 84 } |
78 } | 85 } |
79 DCHECK(false); | 86 if (attribute_index == -1) { |
80 return -1; | 87 NOTREACHED(); |
Mark Mentovai
2009/07/02 03:03:33
Do we really need the NOTREACHED? You documented
| |
88 return NULL; | |
89 } | |
90 return &(attribute_list.attr[attribute_index]); | |
81 } | 91 } |
82 | 92 |
83 void MockKeychain::SetTestDataBytes(int item, UInt32 tag, const void* data, | 93 void MockKeychain::SetTestDataBytes(int item, UInt32 tag, const void* data, |
84 size_t length) { | 94 size_t length) { |
85 int attribute_index = IndexForTag(keychain_attr_list_[item], tag); | 95 SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], |
86 keychain_attr_list_[item].attr[attribute_index].length = length; | 96 tag); |
97 attribute->length = length; | |
87 if (length > 0) { | 98 if (length > 0) { |
88 if (keychain_attr_list_[item].attr[attribute_index].data) { | 99 if (attribute->data) { |
89 free(keychain_attr_list_[item].attr[attribute_index].data); | 100 free(attribute->data); |
90 } | 101 } |
91 keychain_attr_list_[item].attr[attribute_index].data = malloc(length); | 102 attribute->data = malloc(length); |
92 CHECK(keychain_attr_list_[item].attr[attribute_index].data); | 103 CHECK(attribute->data); |
93 memcpy(keychain_attr_list_[item].attr[attribute_index].data, data, length); | 104 memcpy(attribute->data, data, length); |
94 } else { | 105 } else { |
95 keychain_attr_list_[item].attr[attribute_index].data = NULL; | 106 attribute->data = NULL; |
96 } | 107 } |
97 } | 108 } |
98 | 109 |
99 void MockKeychain::SetTestDataString(int item, UInt32 tag, const char* value) { | 110 void MockKeychain::SetTestDataString(int item, UInt32 tag, const char* value) { |
100 SetTestDataBytes(item, tag, value, value ? strlen(value) : 0); | 111 SetTestDataBytes(item, tag, value, value ? strlen(value) : 0); |
101 } | 112 } |
102 | 113 |
103 void MockKeychain::SetTestDataPort(int item, UInt32 value) { | 114 void MockKeychain::SetTestDataPort(int item, UInt32 value) { |
104 int attribute_index = IndexForTag(keychain_attr_list_[item], | 115 SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], |
105 kSecPortItemAttr); | 116 kSecPortItemAttr); |
106 void* data = keychain_attr_list_[item].attr[attribute_index].data; | 117 UInt32* data = static_cast<UInt32*>(attribute->data); |
107 *(static_cast<UInt32*>(data)) = value; | 118 *data = value; |
108 } | 119 } |
109 | 120 |
110 void MockKeychain::SetTestDataProtocol(int item, SecProtocolType value) { | 121 void MockKeychain::SetTestDataProtocol(int item, SecProtocolType value) { |
111 int attribute_index = IndexForTag(keychain_attr_list_[item], | 122 SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], |
112 kSecProtocolItemAttr); | 123 kSecProtocolItemAttr); |
113 void* data = keychain_attr_list_[item].attr[attribute_index].data; | 124 SecProtocolType* data = static_cast<SecProtocolType*>(attribute->data); |
114 *(static_cast<SecProtocolType*>(data)) = value; | 125 *data = value; |
115 } | 126 } |
116 | 127 |
117 void MockKeychain::SetTestDataAuthType(int item, SecAuthenticationType value) { | 128 void MockKeychain::SetTestDataAuthType(int item, SecAuthenticationType value) { |
118 int attribute_index = IndexForTag(keychain_attr_list_[item], | 129 SecKeychainAttribute* attribute = AttributeWithTag( |
119 kSecAuthenticationTypeItemAttr); | 130 keychain_attr_list_[item], kSecAuthenticationTypeItemAttr); |
120 void* data = keychain_attr_list_[item].attr[attribute_index].data; | 131 SecAuthenticationType* data = static_cast<SecAuthenticationType*>( |
121 *(static_cast<SecAuthenticationType*>(data)) = value; | 132 attribute->data); |
133 *data = value; | |
122 } | 134 } |
123 | 135 |
124 void MockKeychain::SetTestDataNegativeItem(int item, Boolean value) { | 136 void MockKeychain::SetTestDataNegativeItem(int item, Boolean value) { |
125 int attribute_index = IndexForTag(keychain_attr_list_[item], | 137 SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], |
126 kSecNegativeItemAttr); | 138 kSecNegativeItemAttr); |
127 void* data = keychain_attr_list_[item].attr[attribute_index].data; | 139 Boolean* data = static_cast<Boolean*>(attribute->data); |
128 *(static_cast<Boolean*>(data)) = value; | 140 *data = value; |
141 } | |
142 | |
143 void MockKeychain::SetTestDataCreator(int item, OSType value) { | |
144 SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], | |
145 kSecCreatorItemAttr); | |
146 OSType* data = static_cast<OSType*>(attribute->data); | |
147 *data = value; | |
129 } | 148 } |
130 | 149 |
131 void MockKeychain::SetTestDataPasswordBytes(int item, const void* data, | 150 void MockKeychain::SetTestDataPasswordBytes(int item, const void* data, |
132 size_t length) { | 151 size_t length) { |
133 keychain_data_[item].length = length; | 152 keychain_data_[item].length = length; |
134 if (length > 0) { | 153 if (length > 0) { |
135 if (keychain_data_[item].data) { | 154 if (keychain_data_[item].data) { |
136 free(keychain_data_[item].data); | 155 free(keychain_data_[item].data); |
137 } | 156 } |
138 keychain_data_[item].data = malloc(length); | 157 keychain_data_[item].data = malloc(length); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 if (length == strlen(fail_trigger) && | 197 if (length == strlen(fail_trigger) && |
179 memcmp(data, fail_trigger, length) == 0) { | 198 memcmp(data, fail_trigger, length) == 0) { |
180 return errSecAuthFailed; | 199 return errSecAuthFailed; |
181 } | 200 } |
182 | 201 |
183 unsigned int item_index = reinterpret_cast<unsigned int>(itemRef) - 1; | 202 unsigned int item_index = reinterpret_cast<unsigned int>(itemRef) - 1; |
184 if (item_index >= item_count_) { | 203 if (item_index >= item_count_) { |
185 return errSecInvalidItemRef; | 204 return errSecInvalidItemRef; |
186 } | 205 } |
187 | 206 |
207 MockKeychain* mutable_this = const_cast<MockKeychain*>(this); | |
188 if (attrList) { | 208 if (attrList) { |
189 NOTIMPLEMENTED(); | 209 for (UInt32 change_attr = 0; change_attr < attrList->count; ++change_attr) { |
210 if (attrList->attr[change_attr].tag == kSecCreatorItemAttr) { | |
211 void* data = attrList->attr[change_attr].data; | |
212 mutable_this->SetTestDataCreator(item_index, | |
213 *(static_cast<OSType*>(data))); | |
214 } else { | |
215 NOTIMPLEMENTED(); | |
216 } | |
217 } | |
190 } | 218 } |
191 if (data) { | 219 if (data) { |
192 MockKeychain* mutable_this = const_cast<MockKeychain*>(this); | |
193 mutable_this->SetTestDataPasswordBytes(item_index, data, length); | 220 mutable_this->SetTestDataPasswordBytes(item_index, data, length); |
194 } | 221 } |
195 return noErr; | 222 return noErr; |
196 } | 223 } |
197 | 224 |
198 OSStatus MockKeychain::ItemFreeAttributesAndData( | 225 OSStatus MockKeychain::ItemFreeAttributesAndData( |
199 SecKeychainAttributeList *attrList, | 226 SecKeychainAttributeList *attrList, |
200 void *data) const { | 227 void *data) const { |
201 --attribute_data_copy_count_; | 228 --attribute_data_copy_count_; |
202 return noErr; | 229 return noErr; |
203 } | 230 } |
204 | 231 |
205 OSStatus MockKeychain::SearchCreateFromAttributes( | 232 OSStatus MockKeychain::SearchCreateFromAttributes( |
206 CFTypeRef keychainOrArray, SecItemClass itemClass, | 233 CFTypeRef keychainOrArray, SecItemClass itemClass, |
207 const SecKeychainAttributeList *attrList, | 234 const SecKeychainAttributeList *attrList, |
208 SecKeychainSearchRef *searchRef) const { | 235 SecKeychainSearchRef *searchRef) const { |
209 // Figure out which of our mock items matches, and set up the array we'll use | 236 // Figure out which of our mock items matches, and set up the array we'll use |
210 // to generate results out of SearchCopyNext. | 237 // to generate results out of SearchCopyNext. |
211 remaining_search_results_.clear(); | 238 remaining_search_results_.clear(); |
212 for (unsigned int mock_item = 0; mock_item < item_count_; ++mock_item) { | 239 for (unsigned int mock_item = 0; mock_item < item_count_; ++mock_item) { |
213 bool mock_item_matches = true; | 240 bool mock_item_matches = true; |
214 for (UInt32 search_attr = 0; search_attr < attrList->count; ++search_attr) { | 241 for (UInt32 search_attr = 0; search_attr < attrList->count; ++search_attr) { |
215 int mock_attr = IndexForTag(keychain_attr_list_[mock_item], | |
216 attrList->attr[search_attr].tag); | |
217 SecKeychainAttribute* mock_attribute = | 242 SecKeychainAttribute* mock_attribute = |
218 &(keychain_attr_list_[mock_item].attr[mock_attr]); | 243 AttributeWithTag(keychain_attr_list_[mock_item], |
244 attrList->attr[search_attr].tag); | |
219 if (mock_attribute->length != attrList->attr[search_attr].length || | 245 if (mock_attribute->length != attrList->attr[search_attr].length || |
220 memcmp(mock_attribute->data, attrList->attr[search_attr].data, | 246 memcmp(mock_attribute->data, attrList->attr[search_attr].data, |
221 attrList->attr[search_attr].length) != 0) { | 247 attrList->attr[search_attr].length) != 0) { |
222 mock_item_matches = false; | 248 mock_item_matches = false; |
223 break; | 249 break; |
224 } | 250 } |
225 } | 251 } |
226 if (mock_item_matches) { | 252 if (mock_item_matches) { |
227 remaining_search_results_.push_back(mock_item); | 253 remaining_search_results_.push_back(mock_item); |
228 } | 254 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
270 passwordLength); | 296 passwordLength); |
271 base::Time::Exploded exploded_time; | 297 base::Time::Exploded exploded_time; |
272 base::Time::Now().UTCExplode(&exploded_time); | 298 base::Time::Now().UTCExplode(&exploded_time); |
273 char time_string[128]; | 299 char time_string[128]; |
274 snprintf(time_string, sizeof(time_string), "%04d%02d%02d%02d%02d%02dZ", | 300 snprintf(time_string, sizeof(time_string), "%04d%02d%02d%02d%02d%02dZ", |
275 exploded_time.year, exploded_time.month, exploded_time.day_of_month, | 301 exploded_time.year, exploded_time.month, exploded_time.day_of_month, |
276 exploded_time.hour, exploded_time.minute, exploded_time.second); | 302 exploded_time.hour, exploded_time.minute, exploded_time.second); |
277 mutable_this->SetTestDataString(target_item, kSecCreationDateItemAttr, | 303 mutable_this->SetTestDataString(target_item, kSecCreationDateItemAttr, |
278 time_string); | 304 time_string); |
279 | 305 |
306 added_via_api_.insert(target_item); | |
307 | |
280 if (itemRef) { | 308 if (itemRef) { |
281 *itemRef = reinterpret_cast<SecKeychainItemRef>(target_item + 1); | 309 *itemRef = reinterpret_cast<SecKeychainItemRef>(target_item + 1); |
310 ++keychain_item_copy_count_; | |
282 } | 311 } |
283 return noErr; | 312 return noErr; |
284 } | 313 } |
285 | 314 |
286 OSStatus MockKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, | 315 OSStatus MockKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, |
287 SecKeychainItemRef *itemRef) const { | 316 SecKeychainItemRef *itemRef) const { |
288 if (remaining_search_results_.empty()) { | 317 if (remaining_search_results_.empty()) { |
289 return errSecItemNotFound; | 318 return errSecItemNotFound; |
290 } | 319 } |
291 unsigned int index = remaining_search_results_.front(); | 320 unsigned int index = remaining_search_results_.front(); |
(...skipping 20 matching lines...) Expand all Loading... | |
312 } | 341 } |
313 | 342 |
314 int MockKeychain::UnfreedKeychainItemCount() const { | 343 int MockKeychain::UnfreedKeychainItemCount() const { |
315 return keychain_item_copy_count_; | 344 return keychain_item_copy_count_; |
316 } | 345 } |
317 | 346 |
318 int MockKeychain::UnfreedAttributeDataCount() const { | 347 int MockKeychain::UnfreedAttributeDataCount() const { |
319 return attribute_data_copy_count_; | 348 return attribute_data_copy_count_; |
320 } | 349 } |
321 | 350 |
351 bool MockKeychain::CreatorCodesSetForAddedItems() const { | |
352 for (std::set<unsigned int>::const_iterator i = added_via_api_.begin(); | |
353 i != added_via_api_.end(); ++i) { | |
354 SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[*i], | |
355 kSecCreatorItemAttr); | |
356 OSType* data = static_cast<OSType*>(attribute->data); | |
357 if (*data == 0) { | |
Mark Mentovai
2009/07/02 03:03:33
Oh yeah. Much clearer this way.
| |
358 return false; | |
359 } | |
360 } | |
361 return true; | |
362 } | |
363 | |
322 void MockKeychain::AddTestItem(const KeychainTestData& item_data) { | 364 void MockKeychain::AddTestItem(const KeychainTestData& item_data) { |
323 unsigned int index = item_count_++; | 365 unsigned int index = item_count_++; |
324 CHECK(index < item_capacity_); | 366 CHECK(index < item_capacity_); |
325 | 367 |
326 SetTestDataAuthType(index, item_data.auth_type); | 368 SetTestDataAuthType(index, item_data.auth_type); |
327 SetTestDataString(index, kSecServerItemAttr, item_data.server); | 369 SetTestDataString(index, kSecServerItemAttr, item_data.server); |
328 SetTestDataProtocol(index, item_data.protocol); | 370 SetTestDataProtocol(index, item_data.protocol); |
329 SetTestDataString(index, kSecPathItemAttr, item_data.path); | 371 SetTestDataString(index, kSecPathItemAttr, item_data.path); |
330 SetTestDataPort(index, item_data.port); | 372 SetTestDataPort(index, item_data.port); |
331 SetTestDataString(index, kSecSecurityDomainItemAttr, | 373 SetTestDataString(index, kSecSecurityDomainItemAttr, |
332 item_data.security_domain); | 374 item_data.security_domain); |
333 SetTestDataString(index, kSecCreationDateItemAttr, item_data.creation_date); | 375 SetTestDataString(index, kSecCreationDateItemAttr, item_data.creation_date); |
334 SetTestDataString(index, kSecAccountItemAttr, item_data.username); | 376 SetTestDataString(index, kSecAccountItemAttr, item_data.username); |
335 SetTestDataPasswordString(index, item_data.password); | 377 SetTestDataPasswordString(index, item_data.password); |
336 SetTestDataNegativeItem(index, item_data.negative_item); | 378 SetTestDataNegativeItem(index, item_data.negative_item); |
337 } | 379 } |
OLD | NEW |