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