OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef CRYPTO_MOCK_KEYCHAIN_MAC_H_ | |
6 #define CRYPTO_MOCK_KEYCHAIN_MAC_H_ | |
7 | |
8 #include <stdint.h> | |
9 | |
10 #include <map> | |
11 #include <set> | |
12 #include <string> | |
13 #include <vector> | |
14 | |
15 #include "base/compiler_specific.h" | |
16 #include "crypto/keychain_mac.h" | |
17 | |
18 namespace crypto { | |
19 | |
20 // Type used for the keys in the std::map(s) and MockKeychain items. | |
21 typedef uintptr_t MockKeychainItemType; | |
22 | |
23 // Mock Keychain wrapper for testing code that interacts with the OS X | |
24 // Keychain. Implemented by storing SecKeychainAttributeList and | |
25 // KeychainPasswordData values in separate mutable containers and | |
26 // mapping them to integer keys. | |
27 // | |
28 // Note that "const" is pretty much meaningless for this class; the const-ness | |
29 // of MacKeychain doesn't apply to the actual keychain data, so all of the Mock | |
30 // data is mutable; don't assume that it won't change over the life of tests. | |
31 class CRYPTO_EXPORT MockKeychain : public MacKeychain { | |
32 public: | |
33 MockKeychain(); | |
34 virtual ~MockKeychain(); | |
35 | |
36 // MacKeychain implementation. | |
37 virtual OSStatus ItemCopyAttributesAndData( | |
38 SecKeychainItemRef itemRef, | |
39 SecKeychainAttributeInfo* info, | |
40 SecItemClass* itemClass, | |
41 SecKeychainAttributeList** attrList, | |
42 UInt32* length, | |
43 void** outData) const OVERRIDE; | |
44 // Pass "fail_me" as the data to get errSecAuthFailed. | |
45 virtual OSStatus ItemModifyAttributesAndData( | |
46 SecKeychainItemRef itemRef, | |
47 const SecKeychainAttributeList* attrList, | |
48 UInt32 length, | |
49 const void* data) const OVERRIDE; | |
50 virtual OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList, | |
51 void* data) const OVERRIDE; | |
52 virtual OSStatus ItemDelete(SecKeychainItemRef itemRef) const OVERRIDE; | |
53 virtual OSStatus SearchCreateFromAttributes( | |
54 CFTypeRef keychainOrArray, | |
55 SecItemClass itemClass, | |
56 const SecKeychainAttributeList* attrList, | |
57 SecKeychainSearchRef* searchRef) const OVERRIDE; | |
58 virtual OSStatus SearchCopyNext(SecKeychainSearchRef searchRef, | |
59 SecKeychainItemRef* itemRef) const OVERRIDE; | |
60 // Pass "some.domain.com" as the serverName to get errSecDuplicateItem. | |
61 virtual OSStatus AddInternetPassword( | |
62 SecKeychainRef keychain, | |
63 UInt32 serverNameLength, | |
64 const char* serverName, | |
65 UInt32 securityDomainLength, | |
66 const char* securityDomain, | |
67 UInt32 accountNameLength, | |
68 const char* accountName, | |
69 UInt32 pathLength, const char* path, | |
70 UInt16 port, SecProtocolType protocol, | |
71 SecAuthenticationType authenticationType, | |
72 UInt32 passwordLength, | |
73 const void* passwordData, | |
74 SecKeychainItemRef* itemRef) const OVERRIDE; | |
75 virtual OSStatus FindGenericPassword( | |
76 CFTypeRef keychainOrArray, | |
77 UInt32 serviceNameLength, | |
78 const char* serviceName, | |
79 UInt32 accountNameLength, | |
80 const char* accountName, | |
81 UInt32* passwordLength, | |
82 void** passwordData, | |
83 SecKeychainItemRef* itemRef) const OVERRIDE; | |
84 virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, | |
85 void* data) const OVERRIDE; | |
86 virtual OSStatus AddGenericPassword( | |
87 SecKeychainRef keychain, | |
88 UInt32 serviceNameLength, | |
89 const char* serviceName, | |
90 UInt32 accountNameLength, | |
91 const char* accountName, | |
92 UInt32 passwordLength, | |
93 const void* passwordData, | |
94 SecKeychainItemRef* itemRef) const OVERRIDE; | |
95 virtual void Free(CFTypeRef ref) const OVERRIDE; | |
96 | |
97 // Return the counts of objects returned by Create/Copy functions but never | |
98 // Free'd as they should have been. | |
99 int UnfreedSearchCount() const; | |
100 int UnfreedKeychainItemCount() const; | |
101 int UnfreedAttributeDataCount() const; | |
102 | |
103 // Returns true if all items added with AddInternetPassword have a creator | |
104 // code set. | |
105 bool CreatorCodesSetForAddedItems() const; | |
106 | |
107 struct KeychainTestData { | |
108 const SecAuthenticationType auth_type; | |
109 const char* server; | |
110 const SecProtocolType protocol; | |
111 const char* path; | |
112 const UInt32 port; | |
113 const char* security_domain; | |
114 const char* creation_date; | |
115 const char* username; | |
116 const char* password; | |
117 const bool negative_item; | |
118 }; | |
119 // Adds a keychain item with the given info to the test set. | |
120 void AddTestItem(const KeychainTestData& item_data); | |
121 | |
122 // |FindGenericPassword()| can return different results depending on user | |
123 // interaction with the system Keychain. For mocking purposes we allow the | |
124 // user of this class to specify the result code of the | |
125 // |FindGenericPassword()| call so we can simulate the result of different | |
126 // user interactions. | |
127 void set_find_generic_result(OSStatus result) { | |
128 find_generic_result_ = result; | |
129 } | |
130 | |
131 // Returns the true if |AddGenericPassword()| was called. | |
132 bool called_add_generic() const { return called_add_generic_; } | |
133 | |
134 // Returns the value of the password set when |AddGenericPassword()| was | |
135 // called. | |
136 std::string add_generic_password() const { return add_generic_password_; } | |
137 | |
138 // Returns the number of allocations - deallocations for password data. | |
139 int password_data_count() const { return password_data_count_; } | |
140 | |
141 private: | |
142 // Returns true if the keychain already contains a password that matches the | |
143 // attributes provided. | |
144 bool AlreadyContainsInternetPassword( | |
145 UInt32 serverNameLength, | |
146 const char* serverName, | |
147 UInt32 securityDomainLength, | |
148 const char* securityDomain, | |
149 UInt32 accountNameLength, | |
150 const char* accountName, | |
151 UInt32 pathLength, | |
152 const char* path, | |
153 UInt16 port, | |
154 SecProtocolType protocol, | |
155 SecAuthenticationType authenticationType) const; | |
156 // Initializes storage for keychain data at |key|. | |
157 void InitializeKeychainData(MockKeychainItemType key) const; | |
158 // Sets the data and length of |tag| in the item-th test item. | |
159 void SetTestDataBytes( | |
160 MockKeychainItemType item, | |
161 UInt32 tag, | |
162 const void* data, | |
163 size_t length); | |
164 // Sets the data and length of |tag| in the item-th test item based on | |
165 // |value|. The null-terminator will not be included; the Keychain Services | |
166 // docs don't indicate whether it is or not, so clients should not assume | |
167 // that it will be. | |
168 void SetTestDataString(MockKeychainItemType item, | |
169 UInt32 tag, | |
170 const char* value); | |
171 // Sets the data of the corresponding attribute of the item-th test item to | |
172 // |value|. Assumes that the space has alread been allocated, and the length | |
173 // set. | |
174 void SetTestDataPort(MockKeychainItemType item, UInt32 value); | |
175 void SetTestDataProtocol(MockKeychainItemType item, SecProtocolType value); | |
176 void SetTestDataAuthType(MockKeychainItemType item, | |
177 SecAuthenticationType value); | |
178 void SetTestDataNegativeItem(MockKeychainItemType item, Boolean value); | |
179 void SetTestDataCreator(MockKeychainItemType item, OSType value); | |
180 // Sets the password data and length for the item-th test item. | |
181 void SetTestDataPasswordBytes( | |
182 MockKeychainItemType item, | |
183 const void* data, | |
184 size_t length); | |
185 // Sets the password for the item-th test item. As with SetTestDataString, | |
186 // the data will not be null-terminated. | |
187 void SetTestDataPasswordString(MockKeychainItemType item, const char* value); | |
188 | |
189 // Returns the address of the attribute in attribute_list with tag |tag|. | |
190 static SecKeychainAttribute* AttributeWithTag( | |
191 const SecKeychainAttributeList& attribute_list, | |
192 UInt32 tag); | |
193 | |
194 static const SecKeychainSearchRef kDummySearchRef; | |
195 | |
196 typedef struct KeychainPasswordData { | |
197 KeychainPasswordData() : data(NULL), length(0) {} | |
198 void* data; | |
199 UInt32 length; | |
200 } KeychainPasswordData; | |
201 | |
202 // Mutable because the MockKeychain API requires its internal keychain storage | |
203 // to be modifiable by users of this class. | |
204 mutable std::map<MockKeychainItemType, | |
205 SecKeychainAttributeList> keychain_attr_list_; | |
206 mutable std::map<MockKeychainItemType, KeychainPasswordData> keychain_data_; | |
207 mutable MockKeychainItemType next_item_key_; | |
208 | |
209 // Tracks the items that should be returned in subsequent calls to | |
210 // SearchCopyNext, based on the last call to SearchCreateFromAttributes. | |
211 // We can't handle multiple active searches, since we don't track the search | |
212 // ref we return, but we don't need to for our mocking. | |
213 mutable std::vector<MockKeychainItemType> remaining_search_results_; | |
214 | |
215 // Track copies and releases to make sure they balance. Really these should | |
216 // be maps to track per item, but this should be good enough to catch | |
217 // real mistakes. | |
218 mutable int search_copy_count_; | |
219 mutable int keychain_item_copy_count_; | |
220 mutable int attribute_data_copy_count_; | |
221 | |
222 // Tracks which items (by key) were added with AddInternetPassword. | |
223 mutable std::set<MockKeychainItemType> added_via_api_; | |
224 | |
225 // Result code for the |FindGenericPassword()| method. | |
226 OSStatus find_generic_result_; | |
227 | |
228 // Records whether |AddGenericPassword()| gets called. | |
229 mutable bool called_add_generic_; | |
230 | |
231 // Tracks the allocations and frees of password data in |FindGenericPassword| | |
232 // and |ItemFreeContent|. | |
233 mutable int password_data_count_; | |
234 | |
235 // Records the password being set when |AddGenericPassword()| gets called. | |
236 mutable std::string add_generic_password_; | |
237 }; | |
238 | |
239 } // namespace crypto | |
240 | |
241 #endif // CRYPTO_MOCK_KEYCHAIN_MAC_H_ | |
OLD | NEW |