// 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.

#include "base/logging.h"
#include "base/time.h"
#include "crypto/mock_apple_keychain.h"

namespace crypto {

// static
const SecKeychainSearchRef MockAppleKeychain::kDummySearchRef =
    reinterpret_cast<SecKeychainSearchRef>(1000);

MockAppleKeychain::MockAppleKeychain()
    : next_item_key_(0),
      search_copy_count_(0),
      keychain_item_copy_count_(0),
      attribute_data_copy_count_(0),
      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 (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);
  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;
}

OSStatus MockAppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
  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 {

  // 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
