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