// Copyright (c) 2009 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 "chrome/browser/keychain_mock_mac.h"

MockKeychain::MockKeychain(unsigned int item_capacity)
    : item_capacity_(item_capacity), item_count_(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) {
  UInt32 tags[] = { kSecAccountItemAttr,
                    kSecServerItemAttr,
                    kSecPortItemAttr,
                    kSecPathItemAttr,
                    kSecProtocolItemAttr,
                    kSecAuthenticationTypeItemAttr,
                    kSecSecurityDomainItemAttr,
                    kSecCreationDateItemAttr,
                    kSecNegativeItemAttr,
                    kSecCreatorItemAttr };

  // Create the test keychain data storage.
  keychain_attr_list_ = static_cast<SecKeychainAttributeList*>(
      calloc(item_capacity_, sizeof(SecKeychainAttributeList)));
  keychain_data_ = static_cast<KeychainPasswordData*>(
      calloc(item_capacity_, sizeof(KeychainPasswordData)));
  for (unsigned int i = 0; i < item_capacity_; ++i) {
    keychain_attr_list_[i].count = arraysize(tags);
    keychain_attr_list_[i].attr = static_cast<SecKeychainAttribute*>(
        calloc(keychain_attr_list_[i].count, sizeof(SecKeychainAttribute)));
    for (unsigned int j = 0; j < keychain_attr_list_[i].count; ++j) {
      keychain_attr_list_[i].attr[j].tag = tags[j];
      size_t data_size = 0;
      switch (tags[j]) {
        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_[i].attr[j].length = data_size;
        keychain_attr_list_[i].attr[j].data = calloc(1, data_size);
      }
    }
  }
}

MockKeychain::~MockKeychain() {
  for (unsigned int i = 0; i < item_capacity_; ++i) {
    for (unsigned int j = 0; j < keychain_attr_list_[i].count; ++j) {
      if (keychain_attr_list_[i].attr[j].data) {
        free(keychain_attr_list_[i].attr[j].data);
      }
    }
    free(keychain_attr_list_[i].attr);
    if (keychain_data_[i].data) {
      free(keychain_data_[i].data);
    }
  }
  free(keychain_attr_list_);
  free(keychain_data_);
}


SecKeychainAttribute* MockKeychain::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 MockKeychain::SetTestDataBytes(int 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 MockKeychain::SetTestDataString(int item, UInt32 tag, const char* value) {
  SetTestDataBytes(item, tag, value, value ? strlen(value) : 0);
}

void MockKeychain::SetTestDataPort(int item, UInt32 value) {
  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
                                                     kSecPortItemAttr);
  UInt32* data = static_cast<UInt32*>(attribute->data);
  *data = value;
}

void MockKeychain::SetTestDataProtocol(int item, SecProtocolType value) {
  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
                                                     kSecProtocolItemAttr);
  SecProtocolType* data = static_cast<SecProtocolType*>(attribute->data);
  *data = value;
}

void MockKeychain::SetTestDataAuthType(int item, SecAuthenticationType value) {
  SecKeychainAttribute* attribute = AttributeWithTag(
      keychain_attr_list_[item], kSecAuthenticationTypeItemAttr);
  SecAuthenticationType* data = static_cast<SecAuthenticationType*>(
      attribute->data);
  *data = value;
}

void MockKeychain::SetTestDataNegativeItem(int item, Boolean value) {
  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
                                                     kSecNegativeItemAttr);
  Boolean* data = static_cast<Boolean*>(attribute->data);
  *data = value;
}

void MockKeychain::SetTestDataCreator(int item, OSType value) {
  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
                                                     kSecCreatorItemAttr);
  OSType* data = static_cast<OSType*>(attribute->data);
  *data = value;
}

void MockKeychain::SetTestDataPasswordBytes(int 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 MockKeychain::SetTestDataPasswordString(int item, const char* value) {
  SetTestDataPasswordBytes(item, value, value ? strlen(value) : 0);
}

OSStatus MockKeychain::ItemCopyAttributesAndData(
    SecKeychainItemRef itemRef, SecKeychainAttributeInfo *info,
    SecItemClass *itemClass, SecKeychainAttributeList **attrList,
    UInt32 *length, void **outData) const {
  DCHECK(itemRef);
  unsigned int item_index = reinterpret_cast<unsigned int>(itemRef) - 1;
  if (item_index >= item_count_) {
    return errSecInvalidItemRef;
  }

  DCHECK(!itemClass);  // itemClass not implemented in the Mock.
  if (attrList) {
    *attrList  = &(keychain_attr_list_[item_index]);
  }
  if (outData) {
    *outData = keychain_data_[item_index].data;
    DCHECK(length);
    *length = keychain_data_[item_index].length;
  }

  ++attribute_data_copy_count_;
  return noErr;
}

OSStatus MockKeychain::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;
  }

  unsigned int item_index = reinterpret_cast<unsigned int>(itemRef) - 1;
  if (item_index >= item_count_) {
    return errSecInvalidItemRef;
  }

  MockKeychain* mutable_this = const_cast<MockKeychain*>(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(item_index,
                                         *(static_cast<OSType*>(data)));
      } else {
        NOTIMPLEMENTED();
      }
    }
  }
  if (data) {
    mutable_this->SetTestDataPasswordBytes(item_index, data, length);
  }
  return noErr;
}

OSStatus MockKeychain::ItemFreeAttributesAndData(
    SecKeychainAttributeList *attrList,
    void *data) const {
  --attribute_data_copy_count_;
  return noErr;
}

OSStatus MockKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
  unsigned int item_index = reinterpret_cast<unsigned int>(itemRef) - 1;
  // The mock only supports deleting the last item.
  if (item_index != item_count_ - 1) {
    NOTIMPLEMENTED();
  }
  --item_count_;
  return noErr;
}

OSStatus MockKeychain::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 (unsigned int mock_item = 0; mock_item < item_count_; ++mock_item) {
    bool mock_item_matches = true;
    for (UInt32 search_attr = 0; search_attr < attrList->count; ++search_attr) {
      SecKeychainAttribute* mock_attribute =
          AttributeWithTag(keychain_attr_list_[mock_item],
                           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(mock_item);
    }
  }

  DCHECK(searchRef);
  *searchRef = reinterpret_cast<SecKeychainSearchRef>(kDummySearchRef);
  ++search_copy_count_;
  return noErr;
}

OSStatus MockKeychain::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;
  }

  // Use empty slots until they run out, then just keep replacing the last item.
  int target_item = (item_count_ == item_capacity_) ? item_capacity_ - 1
                                                    : item_count_++;

  MockKeychain* mutable_this = const_cast<MockKeychain*>(this);
  mutable_this->SetTestDataBytes(target_item, kSecServerItemAttr, serverName,
                                 serverNameLength);
  mutable_this->SetTestDataBytes(target_item, kSecSecurityDomainItemAttr,
                                 securityDomain, securityDomainLength);
  mutable_this->SetTestDataBytes(target_item, kSecAccountItemAttr, accountName,
                                 accountNameLength);
  mutable_this->SetTestDataBytes(target_item, kSecPathItemAttr, path,
                                 pathLength);
  mutable_this->SetTestDataPort(target_item, port);
  mutable_this->SetTestDataProtocol(target_item, protocol);
  mutable_this->SetTestDataAuthType(target_item, authenticationType);
  mutable_this->SetTestDataPasswordBytes(target_item, 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(target_item, kSecCreationDateItemAttr,
                                  time_string);

  added_via_api_.insert(target_item);

  if (itemRef) {
    *itemRef = reinterpret_cast<SecKeychainItemRef>(target_item + 1);
    ++keychain_item_copy_count_;
  }
  return noErr;
}

OSStatus MockKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
                                      SecKeychainItemRef *itemRef) const {
  if (remaining_search_results_.empty()) {
    return errSecItemNotFound;
  }
  unsigned int index = remaining_search_results_.front();
  remaining_search_results_.erase(remaining_search_results_.begin());
  *itemRef = reinterpret_cast<SecKeychainItemRef>(index + 1);
  ++keychain_item_copy_count_;
  return noErr;
}

OSStatus MockKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
                                           UInt32 serviceNameLength,
                                           const char *serviceName,
                                           UInt32 accountNameLength,
                                           const char *accountName,
                                           UInt32 *passwordLength,
                                           void **passwordData,
                                           SecKeychainItemRef *itemRef) const {
  // When simulating |noErr| we return canned |passwordData| and
  // |passwordLenght|.  Otherwise, just return given code.
  if (find_generic_result_ == noErr) {
    static char password[] = "my_password";

    DCHECK(passwordData);
    *passwordData = static_cast<void*>(password);
    DCHECK(passwordLength);
    *passwordLength = strlen(password);
    password_data_count_++;
  }

  return find_generic_result_;
}

OSStatus MockKeychain::ItemFreeContent(SecKeychainAttributeList *attrList,
                                       void *data) const {
  // No-op.
  password_data_count_--;
  return noErr;
}

OSStatus MockKeychain::AddGenericPassword(SecKeychainRef keychain,
                                          UInt32 serviceNameLength,
                                          const char *serviceName,
                                          UInt32 accountNameLength,
                                          const char *accountName,
                                          UInt32 passwordLength,
                                          const void *passwordData,
                                          SecKeychainItemRef *itemRef) const {
  called_add_generic_ = true;

  DCHECK(passwordLength > 0);
  DCHECK(passwordData);
  add_generic_password_ =
      std::string(const_cast<char*>(static_cast<const char*>(passwordData)),
                  passwordLength);
  return noErr;
}

void MockKeychain::Free(CFTypeRef ref) const {
  if (!ref) {
    return;
  }

  if (reinterpret_cast<int>(ref) == kDummySearchRef) {
    --search_copy_count_;
  } else {
    --keychain_item_copy_count_;
  }
}

int MockKeychain::UnfreedSearchCount() const {
  return search_copy_count_;
}

int MockKeychain::UnfreedKeychainItemCount() const {
  return keychain_item_copy_count_;
}

int MockKeychain::UnfreedAttributeDataCount() const {
  return attribute_data_copy_count_;
}

bool MockKeychain::CreatorCodesSetForAddedItems() const {
  for (std::set<unsigned int>::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 MockKeychain::AddTestItem(const KeychainTestData& item_data) {
  unsigned int index = item_count_++;
  CHECK(index < item_capacity_);

  SetTestDataAuthType(index, item_data.auth_type);
  SetTestDataString(index, kSecServerItemAttr, item_data.server);
  SetTestDataProtocol(index, item_data.protocol);
  SetTestDataString(index, kSecPathItemAttr, item_data.path);
  SetTestDataPort(index, item_data.port);
  SetTestDataString(index, kSecSecurityDomainItemAttr,
                    item_data.security_domain);
  SetTestDataString(index, kSecCreationDateItemAttr, item_data.creation_date);
  SetTestDataString(index, kSecAccountItemAttr, item_data.username);
  SetTestDataPasswordString(index, item_data.password);
  SetTestDataNegativeItem(index, item_data.negative_item);
}
