// 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 "components/password_manager/core/browser/login_database.h"

#import <Security/Security.h>
#include <stddef.h>

#include <memory>

#include "base/base64.h"
#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/password_manager/core/common/passwords_directory_util_ios.h"
#include "sql/statement.h"

using base::ScopedCFTypeRef;
using autofill::PasswordForm;

namespace password_manager {

namespace {

void DeleteEncryptedPasswordFromKeychain(const std::string& cipher_text) {
  if (cipher_text.empty())
    return;

  ScopedCFTypeRef<CFMutableDictionaryRef> query(
      CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
                                &kCFTypeDictionaryValueCallBacks));
  CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);

  ScopedCFTypeRef<CFStringRef> item_ref(
      base::SysUTF8ToCFStringRef(cipher_text));
  // We are using the account attribute to store item references.
  CFDictionarySetValue(query, kSecAttrAccount, item_ref);

  OSStatus status = SecItemDelete(query);
  if (status != errSecSuccess && status != errSecItemNotFound) {
    NOTREACHED() << "Unable to remove password from keychain: " << status;
  }

  // Delete the temporary passwords directory, since there might be leftover
  // temporary files used for password export that contain the password being
  // deleted. It can be called for a removal triggered by sync, which might
  // happen at the same time as an export operation. In the unlikely event
  // that the file is still needed by the consumer app, the export operation
  // will fail.
  password_manager::DeletePasswordsDirectory();
}

}  // namespace

// On iOS, the LoginDatabase uses Keychain API to store passwords. The
// "encrypted" version of the password is a unique ID (UUID) that is
// stored as an attribute along with the password in the keychain.
// A side effect of this approach is that the same password saved multiple
// times will have different "encrypted" values.

// TODO(ios): Use |Encryptor| to encrypt the login database. b/6976257

LoginDatabase::EncryptionResult LoginDatabase::EncryptedString(
    const base::string16& plain_text,
    std::string* cipher_text) const {
  if (plain_text.size() == 0) {
    *cipher_text = std::string();
    return ENCRYPTION_RESULT_SUCCESS;
  }

  ScopedCFTypeRef<CFUUIDRef> uuid(CFUUIDCreate(NULL));
  ScopedCFTypeRef<CFStringRef> item_ref(CFUUIDCreateString(NULL, uuid));
  ScopedCFTypeRef<CFMutableDictionaryRef> attributes(
      CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
                                &kCFTypeDictionaryValueCallBacks));
  CFDictionarySetValue(attributes, kSecClass, kSecClassGenericPassword);

  // It does not matter which attribute we use to identify the keychain
  // item as long as it uniquely identifies it. We are arbitrarily choosing the
  // |kSecAttrAccount| attribute for this purpose.
  CFDictionarySetValue(attributes, kSecAttrAccount, item_ref);
  std::string plain_text_utf8 = base::UTF16ToUTF8(plain_text);
  ScopedCFTypeRef<CFDataRef> data(
      CFDataCreate(NULL, reinterpret_cast<const UInt8*>(plain_text_utf8.data()),
                   plain_text_utf8.size()));
  CFDictionarySetValue(attributes, kSecValueData, data);

  // Only allow access when the device has been unlocked.
  CFDictionarySetValue(attributes, kSecAttrAccessible,
                       kSecAttrAccessibleWhenUnlocked);

  OSStatus status = SecItemAdd(attributes, NULL);
  if (status != errSecSuccess) {
    NOTREACHED() << "Unable to save password in keychain: " << status;
    if (status == errSecDuplicateItem || status == errSecDecode)
      return ENCRYPTION_RESULT_ITEM_FAILURE;
    else
      return ENCRYPTION_RESULT_SERVICE_FAILURE;
  }

  *cipher_text = base::SysCFStringRefToUTF8(item_ref);
  return ENCRYPTION_RESULT_SUCCESS;
}

LoginDatabase::EncryptionResult LoginDatabase::DecryptedString(
    const std::string& cipher_text,
    base::string16* plain_text) const {
  if (cipher_text.size() == 0) {
    *plain_text = base::string16();
    return ENCRYPTION_RESULT_SUCCESS;
  }

  ScopedCFTypeRef<CFStringRef> item_ref(
      base::SysUTF8ToCFStringRef(cipher_text));
  ScopedCFTypeRef<CFMutableDictionaryRef> query(
      CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
                                &kCFTypeDictionaryValueCallBacks));
  CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);

  // We are using the account attribute to store item references.
  CFDictionarySetValue(query, kSecAttrAccount, item_ref);
  CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);

  CFDataRef data;
  OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)&data);
  if (status != errSecSuccess) {
    OSSTATUS_LOG(INFO, status) << "Failed to retrieve password from keychain";
    if (status == errSecItemNotFound || status == errSecDecode)
      return ENCRYPTION_RESULT_ITEM_FAILURE;
    else
      return ENCRYPTION_RESULT_SERVICE_FAILURE;
  }

  const size_t size = CFDataGetLength(data);
  std::unique_ptr<UInt8[]> buffer(new UInt8[size]);
  CFDataGetBytes(data, CFRangeMake(0, size), buffer.get());
  CFRelease(data);

  *plain_text = base::UTF8ToUTF16(
      std::string(static_cast<char*>(static_cast<void*>(buffer.get())),
                  static_cast<size_t>(size)));
  return ENCRYPTION_RESULT_SUCCESS;
}

void LoginDatabase::DeleteEncryptedPassword(const PasswordForm& form) {
  std::string cipher_text = GetEncryptedPassword(form);
  DeleteEncryptedPasswordFromKeychain(cipher_text);
}

void LoginDatabase::DeleteEncryptedPasswordById(int id) {
  std::string cipher_text = GetEncryptedPasswordById(id);
  DeleteEncryptedPasswordFromKeychain(cipher_text);
}

std::string LoginDatabase::GetEncryptedPasswordById(int id) const {
  DCHECK(!encrypted_password_statement_by_id_.empty());
  sql::Statement s(db_.GetCachedStatement(
      SQL_FROM_HERE, encrypted_password_statement_by_id_.c_str()));

  s.BindInt(0, id);

  std::string encrypted_password;
  if (s.Step()) {
    s.ColumnBlobAsString(0, &encrypted_password);
  }
  return encrypted_password;
}

}  // namespace password_manager
