0

Remove depprecated methods in AppleKeychain.

BUG=595468

Review-Url: https://codereview.chromium.org/2932473004
Cr-Commit-Position: refs/heads/master@{#478050}
This commit is contained in:
vasilii
2017-06-08 12:22:40 -07:00
committed by Commit Bot
parent 023fd36f83
commit 5baf4fded7
5 changed files with 4 additions and 800 deletions

@ -54,50 +54,7 @@ class CRYPTO_EXPORT AppleKeychain {
SecKeychainItemRef* itemRef) const;
#if !defined(OS_IOS)
virtual OSStatus ItemCopyAttributesAndData(
SecKeychainItemRef itemRef,
SecKeychainAttributeInfo* info,
SecItemClass* itemClass,
SecKeychainAttributeList** attrList,
UInt32* length,
void** outData) const;
virtual OSStatus ItemModifyAttributesAndData(
SecKeychainItemRef itemRef,
const SecKeychainAttributeList* attrList,
UInt32 length,
const void* data) const;
virtual OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList,
void* data) const;
virtual OSStatus ItemDelete(SecKeychainItemRef itemRef) const;
virtual OSStatus SearchCreateFromAttributes(
CFTypeRef keychainOrArray,
SecItemClass itemClass,
const SecKeychainAttributeList* attrList,
SecKeychainSearchRef* searchRef) const;
virtual OSStatus SearchCopyNext(SecKeychainSearchRef searchRef,
SecKeychainItemRef* itemRef) const;
virtual 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;
// Calls CFRelease on the given ref, after checking that |ref| is non-NULL.
virtual void Free(CFTypeRef ref) const;
#endif // !defined(OS_IOS)
private:

@ -15,93 +15,11 @@ AppleKeychain::AppleKeychain() {}
AppleKeychain::~AppleKeychain() {}
OSStatus AppleKeychain::ItemCopyAttributesAndData(
SecKeychainItemRef itemRef,
SecKeychainAttributeInfo* info,
SecItemClass* itemClass,
SecKeychainAttributeList** attrList,
UInt32* length,
void** outData) const {
base::AutoLock lock(GetMacSecurityServicesLock());
return SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
attrList, length, outData);
}
OSStatus AppleKeychain::ItemModifyAttributesAndData(
SecKeychainItemRef itemRef,
const SecKeychainAttributeList* attrList,
UInt32 length,
const void* data) const {
base::AutoLock lock(GetMacSecurityServicesLock());
return SecKeychainItemModifyAttributesAndData(itemRef, attrList, length,
data);
}
OSStatus AppleKeychain::ItemFreeAttributesAndData(
SecKeychainAttributeList* attrList,
void* data) const {
base::AutoLock lock(GetMacSecurityServicesLock());
return SecKeychainItemFreeAttributesAndData(attrList, data);
}
OSStatus AppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
base::AutoLock lock(GetMacSecurityServicesLock());
return SecKeychainItemDelete(itemRef);
}
OSStatus AppleKeychain::SearchCreateFromAttributes(
CFTypeRef keychainOrArray,
SecItemClass itemClass,
const SecKeychainAttributeList* attrList,
SecKeychainSearchRef* searchRef) const {
base::AutoLock lock(GetMacSecurityServicesLock());
// Eventually, this deprecated method should be removed entirely.
// https://crbug.com/595468
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return SecKeychainSearchCreateFromAttributes(keychainOrArray, itemClass,
attrList, searchRef);
#pragma clang diagnostic pop
}
OSStatus AppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
SecKeychainItemRef* itemRef) const {
base::AutoLock lock(GetMacSecurityServicesLock());
// Eventually, this deprecated method should be removed entirely.
// https://crbug.com/595468
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return SecKeychainSearchCopyNext(searchRef, itemRef);
#pragma clang diagnostic pop
}
OSStatus AppleKeychain::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 {
base::AutoLock lock(GetMacSecurityServicesLock());
return SecKeychainAddInternetPassword(keychain,
serverNameLength, serverName,
securityDomainLength, securityDomain,
accountNameLength, accountName,
pathLength, path,
port, protocol, authenticationType,
passwordLength, passwordData,
itemRef);
}
OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
UInt32 serviceNameLength,
const char* serviceName,
@ -146,9 +64,4 @@ OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain,
itemRef);
}
void AppleKeychain::Free(CFTypeRef ref) const {
if (ref)
CFRelease(ref);
}
} // namespace crypto

@ -72,9 +72,6 @@ OSStatus MockAppleKeychain::AddGenericPassword(
DCHECK_GT(passwordLength, 0U);
DCHECK(passwordData);
add_generic_password_ =
std::string(const_cast<char*>(static_cast<const char*>(passwordData)),
passwordLength);
return noErr;
}

@ -19,9 +19,7 @@
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.
// Keychain.
//
// 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
@ -56,71 +54,7 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain {
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
@ -135,109 +69,10 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain {
// 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(nullptr), 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_;
@ -248,8 +83,7 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain {
// and |ItemFreeContent|.
mutable int password_data_count_;
// Records the password being set when |AddGenericPassword()| gets called.
mutable std::string add_generic_password_;
DISALLOW_COPY_AND_ASSIGN(MockAppleKeychain);
};
} // namespace crypto

@ -11,512 +11,15 @@
namespace crypto {
// static
const SecKeychainSearchRef MockAppleKeychain::kDummySearchRef =
reinterpret_cast<SecKeychainSearchRef>(1000);
MockAppleKeychain::MockAppleKeychain()
: locked_(false),
next_item_key_(0),
search_copy_count_(0),
keychain_item_copy_count_(0),
attribute_data_copy_count_(0),
find_generic_result_(noErr),
: find_generic_result_(noErr),
called_add_generic_(false),
password_data_count_(0) {}
void MockAppleKeychain::InitializeKeychainData(MockKeychainItemType key) const {
UInt32 tags[] = { kSecAccountItemAttr,
kSecServerItemAttr,
kSecPortItemAttr,
kSecPathItemAttr,
kSecProtocolItemAttr,
kSecAuthenticationTypeItemAttr,
kSecSecurityDomainItemAttr,
kSecCreationDateItemAttr,
kSecNegativeItemAttr,
kSecCreatorItemAttr };
keychain_attr_list_[key] = SecKeychainAttributeList();
keychain_data_[key] = KeychainPasswordData();
keychain_attr_list_[key].count = arraysize(tags);
keychain_attr_list_[key].attr = static_cast<SecKeychainAttribute*>(
calloc(keychain_attr_list_[key].count, sizeof(SecKeychainAttribute)));
for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) {
keychain_attr_list_[key].attr[i].tag = tags[i];
size_t data_size = 0;
switch (tags[i]) {
case kSecPortItemAttr:
data_size = sizeof(UInt32);
break;
case kSecProtocolItemAttr:
data_size = sizeof(SecProtocolType);
break;
case kSecAuthenticationTypeItemAttr:
data_size = sizeof(SecAuthenticationType);
break;
case kSecNegativeItemAttr:
data_size = sizeof(Boolean);
break;
case kSecCreatorItemAttr:
data_size = sizeof(OSType);
break;
}
if (data_size > 0) {
keychain_attr_list_[key].attr[i].length = data_size;
keychain_attr_list_[key].attr[i].data = calloc(1, data_size);
}
}
}
MockAppleKeychain::~MockAppleKeychain() {
for (MockKeychainAttributesMap::iterator it = keychain_attr_list_.begin();
it != keychain_attr_list_.end();
++it) {
for (unsigned int i = 0; i < it->second.count; ++i) {
if (it->second.attr[i].data)
free(it->second.attr[i].data);
}
free(it->second.attr);
if (keychain_data_[it->first].data)
free(keychain_data_[it->first].data);
}
keychain_attr_list_.clear();
keychain_data_.clear();
}
SecKeychainAttribute* MockAppleKeychain::AttributeWithTag(
const SecKeychainAttributeList& attribute_list,
UInt32 tag) {
int attribute_index = -1;
for (unsigned int i = 0; i < attribute_list.count; ++i) {
if (attribute_list.attr[i].tag == tag) {
attribute_index = i;
break;
}
}
if (attribute_index == -1) {
NOTREACHED() << "Unsupported attribute: " << tag;
return NULL;
}
return &(attribute_list.attr[attribute_index]);
}
void MockAppleKeychain::SetTestDataBytes(MockKeychainItemType item,
UInt32 tag,
const void* data,
size_t length) {
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
tag);
attribute->length = length;
if (length > 0) {
if (attribute->data)
free(attribute->data);
attribute->data = malloc(length);
CHECK(attribute->data);
memcpy(attribute->data, data, length);
} else {
attribute->data = NULL;
}
}
void MockAppleKeychain::SetTestDataString(MockKeychainItemType item,
UInt32 tag,
const char* value) {
SetTestDataBytes(item, tag, value, value ? strlen(value) : 0);
}
void MockAppleKeychain::SetTestDataPort(MockKeychainItemType item,
UInt32 value) {
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
kSecPortItemAttr);
UInt32* data = static_cast<UInt32*>(attribute->data);
*data = value;
}
void MockAppleKeychain::SetTestDataProtocol(MockKeychainItemType item,
SecProtocolType value) {
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
kSecProtocolItemAttr);
SecProtocolType* data = static_cast<SecProtocolType*>(attribute->data);
*data = value;
}
void MockAppleKeychain::SetTestDataAuthType(MockKeychainItemType item,
SecAuthenticationType value) {
SecKeychainAttribute* attribute = AttributeWithTag(
keychain_attr_list_[item], kSecAuthenticationTypeItemAttr);
SecAuthenticationType* data = static_cast<SecAuthenticationType*>(
attribute->data);
*data = value;
}
void MockAppleKeychain::SetTestDataNegativeItem(MockKeychainItemType item,
Boolean value) {
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
kSecNegativeItemAttr);
Boolean* data = static_cast<Boolean*>(attribute->data);
*data = value;
}
void MockAppleKeychain::SetTestDataCreator(MockKeychainItemType item,
OSType value) {
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
kSecCreatorItemAttr);
OSType* data = static_cast<OSType*>(attribute->data);
*data = value;
}
void MockAppleKeychain::SetTestDataPasswordBytes(MockKeychainItemType item,
const void* data,
size_t length) {
keychain_data_[item].length = length;
if (length > 0) {
if (keychain_data_[item].data)
free(keychain_data_[item].data);
keychain_data_[item].data = malloc(length);
memcpy(keychain_data_[item].data, data, length);
} else {
keychain_data_[item].data = NULL;
}
}
void MockAppleKeychain::SetTestDataPasswordString(MockKeychainItemType item,
const char* value) {
SetTestDataPasswordBytes(item, value, value ? strlen(value) : 0);
}
OSStatus MockAppleKeychain::ItemCopyAttributesAndData(
SecKeychainItemRef itemRef,
SecKeychainAttributeInfo* info,
SecItemClass* itemClass,
SecKeychainAttributeList** attrList,
UInt32* length,
void** outData) const {
DCHECK(itemRef);
MockKeychainItemType key =
reinterpret_cast<MockKeychainItemType>(itemRef) - 1;
if (keychain_attr_list_.find(key) == keychain_attr_list_.end())
return errSecInvalidItemRef;
DCHECK(!itemClass); // itemClass not implemented in the Mock.
if (locked_ && outData)
return errSecAuthFailed;
if (attrList)
*attrList = &(keychain_attr_list_[key]);
if (outData) {
*outData = keychain_data_[key].data;
DCHECK(length);
*length = keychain_data_[key].length;
}
++attribute_data_copy_count_;
return noErr;
}
OSStatus MockAppleKeychain::ItemModifyAttributesAndData(
SecKeychainItemRef itemRef,
const SecKeychainAttributeList* attrList,
UInt32 length,
const void* data) const {
DCHECK(itemRef);
if (locked_)
return errSecAuthFailed;
const char* fail_trigger = "fail_me";
if (length == strlen(fail_trigger) &&
memcmp(data, fail_trigger, length) == 0) {
return errSecAuthFailed;
}
MockKeychainItemType key =
reinterpret_cast<MockKeychainItemType>(itemRef) - 1;
if (keychain_attr_list_.find(key) == keychain_attr_list_.end())
return errSecInvalidItemRef;
MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this);
if (attrList) {
for (UInt32 change_attr = 0; change_attr < attrList->count; ++change_attr) {
if (attrList->attr[change_attr].tag == kSecCreatorItemAttr) {
void* data = attrList->attr[change_attr].data;
mutable_this->SetTestDataCreator(key, *(static_cast<OSType*>(data)));
} else {
NOTIMPLEMENTED();
}
}
}
if (data)
mutable_this->SetTestDataPasswordBytes(key, data, length);
return noErr;
}
OSStatus MockAppleKeychain::ItemFreeAttributesAndData(
SecKeychainAttributeList* attrList,
void* data) const {
--attribute_data_copy_count_;
return noErr;
}
MockAppleKeychain::~MockAppleKeychain() {}
OSStatus MockAppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
if (locked_)
return errSecAuthFailed;
MockKeychainItemType key =
reinterpret_cast<MockKeychainItemType>(itemRef) - 1;
for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) {
if (keychain_attr_list_[key].attr[i].data)
free(keychain_attr_list_[key].attr[i].data);
}
free(keychain_attr_list_[key].attr);
if (keychain_data_[key].data)
free(keychain_data_[key].data);
keychain_attr_list_.erase(key);
keychain_data_.erase(key);
added_via_api_.erase(key);
return noErr;
}
OSStatus MockAppleKeychain::SearchCreateFromAttributes(
CFTypeRef keychainOrArray,
SecItemClass itemClass,
const SecKeychainAttributeList* attrList,
SecKeychainSearchRef* searchRef) const {
// Figure out which of our mock items matches, and set up the array we'll use
// to generate results out of SearchCopyNext.
remaining_search_results_.clear();
for (MockKeychainAttributesMap::const_iterator it =
keychain_attr_list_.begin();
it != keychain_attr_list_.end();
++it) {
bool mock_item_matches = true;
for (UInt32 search_attr = 0; search_attr < attrList->count; ++search_attr) {
SecKeychainAttribute* mock_attribute =
AttributeWithTag(it->second, attrList->attr[search_attr].tag);
if (mock_attribute->length != attrList->attr[search_attr].length ||
memcmp(mock_attribute->data, attrList->attr[search_attr].data,
attrList->attr[search_attr].length) != 0) {
mock_item_matches = false;
break;
}
}
if (mock_item_matches)
remaining_search_results_.push_back(it->first);
}
DCHECK(searchRef);
*searchRef = kDummySearchRef;
++search_copy_count_;
return noErr;
}
bool MockAppleKeychain::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 {
for (MockKeychainAttributesMap::const_iterator it =
keychain_attr_list_.begin();
it != keychain_attr_list_.end();
++it) {
SecKeychainAttribute* attribute;
attribute = AttributeWithTag(it->second, kSecServerItemAttr);
if ((attribute->length != serverNameLength) ||
(attribute->data == NULL && *serverName != '\0') ||
(attribute->data != NULL && *serverName == '\0') ||
strncmp(serverName,
(const char*) attribute->data,
serverNameLength) != 0) {
continue;
}
attribute = AttributeWithTag(it->second, kSecSecurityDomainItemAttr);
if ((attribute->length != securityDomainLength) ||
(attribute->data == NULL && *securityDomain != '\0') ||
(attribute->data != NULL && *securityDomain == '\0') ||
strncmp(securityDomain,
(const char*) attribute->data,
securityDomainLength) != 0) {
continue;
}
attribute = AttributeWithTag(it->second, kSecAccountItemAttr);
if ((attribute->length != accountNameLength) ||
(attribute->data == NULL && *accountName != '\0') ||
(attribute->data != NULL && *accountName == '\0') ||
strncmp(accountName,
(const char*) attribute->data,
accountNameLength) != 0) {
continue;
}
attribute = AttributeWithTag(it->second, kSecPathItemAttr);
if ((attribute->length != pathLength) ||
(attribute->data == NULL && *path != '\0') ||
(attribute->data != NULL && *path == '\0') ||
strncmp(path,
(const char*) attribute->data,
pathLength) != 0) {
continue;
}
attribute = AttributeWithTag(it->second, kSecPortItemAttr);
if ((attribute->data == NULL) ||
(port != *(static_cast<UInt32*>(attribute->data)))) {
continue;
}
attribute = AttributeWithTag(it->second, kSecProtocolItemAttr);
if ((attribute->data == NULL) ||
(protocol != *(static_cast<SecProtocolType*>(attribute->data)))) {
continue;
}
attribute = AttributeWithTag(it->second, kSecAuthenticationTypeItemAttr);
if ((attribute->data == NULL) ||
(authenticationType !=
*(static_cast<SecAuthenticationType*>(attribute->data)))) {
continue;
}
// The keychain already has this item, since all fields other than the
// password match.
return true;
}
return false;
}
OSStatus MockAppleKeychain::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 {
if (locked_)
return errSecAuthFailed;
// Check for the magic duplicate item trigger.
if (strcmp(serverName, "some.domain.com") == 0)
return errSecDuplicateItem;
// If the account already exists in the keychain, we don't add it.
if (AlreadyContainsInternetPassword(serverNameLength, serverName,
securityDomainLength, securityDomain,
accountNameLength, accountName,
pathLength, path,
port, protocol,
authenticationType)) {
return errSecDuplicateItem;
}
// Pick the next unused slot.
MockKeychainItemType key = next_item_key_++;
// Initialize keychain data storage at the target location.
InitializeKeychainData(key);
MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this);
mutable_this->SetTestDataBytes(key, kSecServerItemAttr, serverName,
serverNameLength);
mutable_this->SetTestDataBytes(key, kSecSecurityDomainItemAttr,
securityDomain, securityDomainLength);
mutable_this->SetTestDataBytes(key, kSecAccountItemAttr, accountName,
accountNameLength);
mutable_this->SetTestDataBytes(key, kSecPathItemAttr, path, pathLength);
mutable_this->SetTestDataPort(key, port);
mutable_this->SetTestDataProtocol(key, protocol);
mutable_this->SetTestDataAuthType(key, authenticationType);
mutable_this->SetTestDataPasswordBytes(key, passwordData,
passwordLength);
base::Time::Exploded exploded_time;
base::Time::Now().UTCExplode(&exploded_time);
char time_string[128];
snprintf(time_string, sizeof(time_string), "%04d%02d%02d%02d%02d%02dZ",
exploded_time.year, exploded_time.month, exploded_time.day_of_month,
exploded_time.hour, exploded_time.minute, exploded_time.second);
mutable_this->SetTestDataString(key, kSecCreationDateItemAttr, time_string);
added_via_api_.insert(key);
if (itemRef) {
*itemRef = reinterpret_cast<SecKeychainItemRef>(key + 1);
++keychain_item_copy_count_;
}
return noErr;
}
OSStatus MockAppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
SecKeychainItemRef* itemRef) const {
if (remaining_search_results_.empty())
return errSecItemNotFound;
MockKeychainItemType key = remaining_search_results_.front();
remaining_search_results_.erase(remaining_search_results_.begin());
*itemRef = reinterpret_cast<SecKeychainItemRef>(key + 1);
++keychain_item_copy_count_;
return noErr;
}
void MockAppleKeychain::Free(CFTypeRef ref) const {
if (!ref)
return;
if (ref == kDummySearchRef) {
--search_copy_count_;
} else {
--keychain_item_copy_count_;
}
}
int MockAppleKeychain::UnfreedSearchCount() const {
return search_copy_count_;
}
int MockAppleKeychain::UnfreedKeychainItemCount() const {
return keychain_item_copy_count_;
}
int MockAppleKeychain::UnfreedAttributeDataCount() const {
return attribute_data_copy_count_;
}
bool MockAppleKeychain::CreatorCodesSetForAddedItems() const {
for (std::set<MockKeychainItemType>::const_iterator
i = added_via_api_.begin();
i != added_via_api_.end();
++i) {
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[*i],
kSecCreatorItemAttr);
OSType* data = static_cast<OSType*>(attribute->data);
if (*data == 0)
return false;
}
return true;
}
void MockAppleKeychain::AddTestItem(const KeychainTestData& item_data) {
MockKeychainItemType key = next_item_key_++;
InitializeKeychainData(key);
SetTestDataAuthType(key, item_data.auth_type);
SetTestDataString(key, kSecServerItemAttr, item_data.server);
SetTestDataProtocol(key, item_data.protocol);
SetTestDataString(key, kSecPathItemAttr, item_data.path);
SetTestDataPort(key, item_data.port);
SetTestDataString(key, kSecSecurityDomainItemAttr,
item_data.security_domain);
SetTestDataString(key, kSecCreationDateItemAttr, item_data.creation_date);
SetTestDataString(key, kSecAccountItemAttr, item_data.username);
SetTestDataPasswordString(key, item_data.password);
SetTestDataNegativeItem(key, item_data.negative_item);
}
} // namespace crypto