| Index: crypto/mock_apple_keychain.h
|
| diff --git a/crypto/mock_apple_keychain.h b/crypto/mock_apple_keychain.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f73d3a6466ed23c5420ffc001c75d7cf57541f52
|
| --- /dev/null
|
| +++ b/crypto/mock_apple_keychain.h
|
| @@ -0,0 +1,256 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef CRYPTO_MOCK_KEYCHAIN_MAC_H_
|
| +#define CRYPTO_MOCK_KEYCHAIN_MAC_H_
|
| +
|
| +#include <stdint.h>
|
| +
|
| +#include <map>
|
| +#include <set>
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/compiler_specific.h"
|
| +#include "crypto/apple_keychain.h"
|
| +
|
| +namespace crypto {
|
| +
|
| +// Mock Keychain wrapper for testing code that interacts with the OS X
|
| +// Keychain. Implemented by storing SecKeychainAttributeList and
|
| +// KeychainPasswordData values in separate mutable containers and
|
| +// mapping them to integer keys.
|
| +//
|
| +// Note that "const" is pretty much meaningless for this class; the const-ness
|
| +// of AppleKeychain doesn't apply to the actual keychain data, so all of the
|
| +// Mock data is mutable; don't assume that it won't change over the life of
|
| +// tests.
|
| +class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain {
|
| + public:
|
| + MockAppleKeychain();
|
| + ~MockAppleKeychain() override;
|
| +
|
| + // AppleKeychain implementation.
|
| + OSStatus FindGenericPassword(CFTypeRef keychainOrArray,
|
| + UInt32 serviceNameLength,
|
| + const char* serviceName,
|
| + UInt32 accountNameLength,
|
| + const char* accountName,
|
| + UInt32* passwordLength,
|
| + void** passwordData,
|
| + SecKeychainItemRef* itemRef) const override;
|
| + OSStatus ItemFreeContent(SecKeychainAttributeList* attrList,
|
| + void* data) const override;
|
| + OSStatus AddGenericPassword(SecKeychainRef keychain,
|
| + UInt32 serviceNameLength,
|
| + const char* serviceName,
|
| + UInt32 accountNameLength,
|
| + const char* accountName,
|
| + UInt32 passwordLength,
|
| + const void* passwordData,
|
| + SecKeychainItemRef* itemRef) const override;
|
| +
|
| + // Returns the password that OSCrypt uses to generate its encryption key.
|
| + std::string GetEncryptionPassword() const;
|
| +
|
| +#if !defined(OS_IOS)
|
| + OSStatus ItemCopyAttributesAndData(SecKeychainItemRef itemRef,
|
| + SecKeychainAttributeInfo* info,
|
| + SecItemClass* itemClass,
|
| + SecKeychainAttributeList** attrList,
|
| + UInt32* length,
|
| + void** outData) const override;
|
| + // Pass "fail_me" as the data to get errSecAuthFailed.
|
| + OSStatus ItemModifyAttributesAndData(SecKeychainItemRef itemRef,
|
| + const SecKeychainAttributeList* attrList,
|
| + UInt32 length,
|
| + const void* data) const override;
|
| + OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList,
|
| + void* data) const override;
|
| + OSStatus ItemDelete(SecKeychainItemRef itemRef) const override;
|
| + OSStatus SearchCreateFromAttributes(
|
| + CFTypeRef keychainOrArray,
|
| + SecItemClass itemClass,
|
| + const SecKeychainAttributeList* attrList,
|
| + SecKeychainSearchRef* searchRef) const override;
|
| + OSStatus SearchCopyNext(SecKeychainSearchRef searchRef,
|
| + SecKeychainItemRef* itemRef) const override;
|
| + // Pass "some.domain.com" as the serverName to get errSecDuplicateItem.
|
| + OSStatus AddInternetPassword(SecKeychainRef keychain,
|
| + UInt32 serverNameLength,
|
| + const char* serverName,
|
| + UInt32 securityDomainLength,
|
| + const char* securityDomain,
|
| + UInt32 accountNameLength,
|
| + const char* accountName,
|
| + UInt32 pathLength,
|
| + const char* path,
|
| + UInt16 port,
|
| + SecProtocolType protocol,
|
| + SecAuthenticationType authenticationType,
|
| + UInt32 passwordLength,
|
| + const void* passwordData,
|
| + SecKeychainItemRef* itemRef) const override;
|
| + void Free(CFTypeRef ref) const override;
|
| +
|
| + // Return the counts of objects returned by Create/Copy functions but never
|
| + // Free'd as they should have been.
|
| + int UnfreedSearchCount() const;
|
| + int UnfreedKeychainItemCount() const;
|
| + int UnfreedAttributeDataCount() const;
|
| +
|
| + // Returns true if all items added with AddInternetPassword have a creator
|
| + // code set.
|
| + bool CreatorCodesSetForAddedItems() const;
|
| +
|
| + struct KeychainTestData {
|
| + const SecAuthenticationType auth_type;
|
| + const char* server;
|
| + const SecProtocolType protocol;
|
| + const char* path;
|
| + const UInt32 port;
|
| + const char* security_domain;
|
| + const char* creation_date;
|
| + const char* username;
|
| + const char* password;
|
| + const bool negative_item;
|
| + };
|
| + // Adds a keychain item with the given info to the test set.
|
| + void AddTestItem(const KeychainTestData& item_data);
|
| +
|
| + void set_locked(bool locked) { locked_ = locked; }
|
| +#endif // !defined(OS_IOS)
|
| +
|
| + // |FindGenericPassword()| can return different results depending on user
|
| + // interaction with the system Keychain. For mocking purposes we allow the
|
| + // user of this class to specify the result code of the
|
| + // |FindGenericPassword()| call so we can simulate the result of different
|
| + // user interactions.
|
| + void set_find_generic_result(OSStatus result) {
|
| + find_generic_result_ = result;
|
| + }
|
| +
|
| + // Returns the true if |AddGenericPassword()| was called.
|
| + bool called_add_generic() const { return called_add_generic_; }
|
| +
|
| + // Returns the value of the password set when |AddGenericPassword()| was
|
| + // called.
|
| + std::string add_generic_password() const { return add_generic_password_; }
|
| +
|
| + // Returns the number of allocations - deallocations for password data.
|
| + int password_data_count() const { return password_data_count_; }
|
| +
|
| + private:
|
| + // Type used for the keys in the std::map(s) and MockAppleKeychain items.
|
| + typedef uintptr_t MockKeychainItemType;
|
| +
|
| + // Type of the map holding the mock keychain attributes.
|
| + typedef std::map<MockKeychainItemType, SecKeychainAttributeList>
|
| + MockKeychainAttributesMap;
|
| +
|
| +#if !defined(OS_IOS)
|
| + // Returns true if the keychain already contains a password that matches the
|
| + // attributes provided.
|
| + bool AlreadyContainsInternetPassword(
|
| + UInt32 serverNameLength,
|
| + const char* serverName,
|
| + UInt32 securityDomainLength,
|
| + const char* securityDomain,
|
| + UInt32 accountNameLength,
|
| + const char* accountName,
|
| + UInt32 pathLength,
|
| + const char* path,
|
| + UInt16 port,
|
| + SecProtocolType protocol,
|
| + SecAuthenticationType authenticationType) const;
|
| + // Initializes storage for keychain data at |key|.
|
| + void InitializeKeychainData(MockKeychainItemType key) const;
|
| + // Sets the data and length of |tag| in the item-th test item.
|
| + void SetTestDataBytes(
|
| + MockKeychainItemType item,
|
| + UInt32 tag,
|
| + const void* data,
|
| + size_t length);
|
| + // Sets the data and length of |tag| in the item-th test item based on
|
| + // |value|. The null-terminator will not be included; the Keychain Services
|
| + // docs don't indicate whether it is or not, so clients should not assume
|
| + // that it will be.
|
| + void SetTestDataString(MockKeychainItemType item,
|
| + UInt32 tag,
|
| + const char* value);
|
| + // Sets the data of the corresponding attribute of the item-th test item to
|
| + // |value|. Assumes that the space has alread been allocated, and the length
|
| + // set.
|
| + void SetTestDataPort(MockKeychainItemType item, UInt32 value);
|
| + void SetTestDataProtocol(MockKeychainItemType item, SecProtocolType value);
|
| + void SetTestDataAuthType(MockKeychainItemType item,
|
| + SecAuthenticationType value);
|
| + void SetTestDataNegativeItem(MockKeychainItemType item, Boolean value);
|
| + void SetTestDataCreator(MockKeychainItemType item, OSType value);
|
| + // Sets the password data and length for the item-th test item.
|
| + void SetTestDataPasswordBytes(MockKeychainItemType item,
|
| + const void* data,
|
| + size_t length);
|
| + // Sets the password for the item-th test item. As with SetTestDataString,
|
| + // the data will not be null-terminated.
|
| + void SetTestDataPasswordString(MockKeychainItemType item, const char* value);
|
| +
|
| + // Returns the address of the attribute in attribute_list with tag |tag|.
|
| + static SecKeychainAttribute* AttributeWithTag(
|
| + const SecKeychainAttributeList& attribute_list,
|
| + UInt32 tag);
|
| +
|
| + static const SecKeychainSearchRef kDummySearchRef;
|
| +
|
| + // Simulates the state when the user refuses to unclock the Keychain.
|
| + // If true, reading and modifying a password value result in errSecAuthFailed.
|
| + bool locked_;
|
| +
|
| + typedef struct KeychainPasswordData {
|
| + KeychainPasswordData() : data(NULL), length(0) {}
|
| + void* data;
|
| + UInt32 length;
|
| + } KeychainPasswordData;
|
| +
|
| + // Mutable because the MockAppleKeychain API requires its internal keychain
|
| + // storage to be modifiable by users of this class.
|
| + mutable MockKeychainAttributesMap keychain_attr_list_;
|
| + mutable std::map<MockKeychainItemType,
|
| + KeychainPasswordData> keychain_data_;
|
| + mutable MockKeychainItemType next_item_key_;
|
| +
|
| + // Tracks the items that should be returned in subsequent calls to
|
| + // SearchCopyNext, based on the last call to SearchCreateFromAttributes.
|
| + // We can't handle multiple active searches, since we don't track the search
|
| + // ref we return, but we don't need to for our mocking.
|
| + mutable std::vector<MockKeychainItemType> remaining_search_results_;
|
| +
|
| + // Track copies and releases to make sure they balance. Really these should
|
| + // be maps to track per item, but this should be good enough to catch
|
| + // real mistakes.
|
| + mutable int search_copy_count_;
|
| + mutable int keychain_item_copy_count_;
|
| + mutable int attribute_data_copy_count_;
|
| +
|
| + // Tracks which items (by key) were added with AddInternetPassword.
|
| + mutable std::set<MockKeychainItemType> added_via_api_;
|
| +#endif // !defined(OS_IOS)
|
| +
|
| + // Result code for the |FindGenericPassword()| method.
|
| + OSStatus find_generic_result_;
|
| +
|
| + // Records whether |AddGenericPassword()| gets called.
|
| + mutable bool called_add_generic_;
|
| +
|
| + // Tracks the allocations and frees of password data in |FindGenericPassword|
|
| + // and |ItemFreeContent|.
|
| + mutable int password_data_count_;
|
| +
|
| + // Records the password being set when |AddGenericPassword()| gets called.
|
| + mutable std::string add_generic_password_;
|
| +};
|
| +
|
| +} // namespace crypto
|
| +
|
| +#endif // CRYPTO_MOCK_KEYCHAIN_MAC_H_
|
|
|