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