// Copyright (c) 2015 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 "chrome/browser/password_manager/native_backend_libsecret.h"

#include <stddef.h>
#include <stdint.h>

#include <libsecret/secret.h>

#include <limits>
#include <list>
#include <memory>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "url/origin.h"

using autofill::PasswordForm;
using base::UTF8ToUTF16;
using base::UTF16ToUTF8;
using password_manager::MatchResult;
using password_manager::PasswordStore;

namespace {
const char kEmptyString[] = "";
const int kMaxPossibleTimeTValue = std::numeric_limits<int>::max();
}  // namespace

namespace {

const char kLibsecretAppString[] = "chrome";

// Schema is analagous to the fields in PasswordForm.
const SecretSchema kLibsecretSchema = {
    "chrome_libsecret_password_schema",
    // We have to use SECRET_SCHEMA_DONT_MATCH_NAME in order to get old
    // passwords stored with gnome_keyring.
    SECRET_SCHEMA_DONT_MATCH_NAME,
    {{"origin_url", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"action_url", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"username_element", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"username_value", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"password_element", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"submit_element", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"signon_realm", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"preferred", SECRET_SCHEMA_ATTRIBUTE_INTEGER},
     {"date_created", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"blacklisted_by_user", SECRET_SCHEMA_ATTRIBUTE_INTEGER},
     {"scheme", SECRET_SCHEMA_ATTRIBUTE_INTEGER},
     {"type", SECRET_SCHEMA_ATTRIBUTE_INTEGER},
     {"times_used", SECRET_SCHEMA_ATTRIBUTE_INTEGER},
     {"date_synced", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"display_name", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"avatar_url", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"federation_url", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {"should_skip_zero_click", SECRET_SCHEMA_ATTRIBUTE_INTEGER},
     {"generation_upload_status", SECRET_SCHEMA_ATTRIBUTE_INTEGER},
     {"form_data", SECRET_SCHEMA_ATTRIBUTE_STRING},
     // This field is always "chrome-profile_id" so that we can search for it.
     {"application", SECRET_SCHEMA_ATTRIBUTE_STRING},
     {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING}}};

const char* GetStringFromAttributes(GHashTable* attrs, const char* keyname) {
  gpointer value = g_hash_table_lookup(attrs, keyname);
  return value ? static_cast<char*>(value) : kEmptyString;
}

uint32_t GetUintFromAttributes(GHashTable* attrs, const char* keyname) {
  gpointer value = g_hash_table_lookup(attrs, keyname);
  if (!value)
    return uint32_t();
  uint32_t result;
  bool value_ok = base::StringToUint(static_cast<char*>(value), &result);
  DCHECK(value_ok);
  return result;
}

// Convert the attributes into a new PasswordForm.
// Note: does *not* get the actual password, as that is not a key attribute!
// Returns nullptr if the attributes are for the wrong application.
std::unique_ptr<PasswordForm> FormOutOfAttributes(GHashTable* attrs) {
  base::StringPiece app_value = GetStringFromAttributes(attrs, "application");
  if (!app_value.starts_with(kLibsecretAppString))
    return std::unique_ptr<PasswordForm>();

  std::unique_ptr<PasswordForm> form(new PasswordForm());
  form->origin = GURL(GetStringFromAttributes(attrs, "origin_url"));
  form->action = GURL(GetStringFromAttributes(attrs, "action_url"));
  form->username_element =
      UTF8ToUTF16(GetStringFromAttributes(attrs, "username_element"));
  form->username_value =
      UTF8ToUTF16(GetStringFromAttributes(attrs, "username_value"));
  form->password_element =
      UTF8ToUTF16(GetStringFromAttributes(attrs, "password_element"));
  form->submit_element =
      UTF8ToUTF16(GetStringFromAttributes(attrs, "submit_element"));
  form->signon_realm = GetStringFromAttributes(attrs, "signon_realm");
  form->preferred = GetUintFromAttributes(attrs, "preferred");
  int64_t date_created = 0;
  bool date_ok = base::StringToInt64(
      GetStringFromAttributes(attrs, "date_created"), &date_created);
  DCHECK(date_ok);
  // In the past |date_created| was stored as time_t. Currently is stored as
  // base::Time's internal value. We need to distinguish, which format the
  // number in |date_created| was stored in. We use the fact that
  // kMaxPossibleTimeTValue interpreted as the internal value corresponds to an
  // unlikely date back in 17th century, and anything above
  // kMaxPossibleTimeTValue clearly must be in the internal value format.
  form->date_created = date_created < kMaxPossibleTimeTValue
                           ? base::Time::FromTimeT(date_created)
                           : base::Time::FromInternalValue(date_created);
  form->blacklisted_by_user =
      GetUintFromAttributes(attrs, "blacklisted_by_user");
  form->type =
      static_cast<PasswordForm::Type>(GetUintFromAttributes(attrs, "type"));
  form->times_used = GetUintFromAttributes(attrs, "times_used");
  form->scheme =
      static_cast<PasswordForm::Scheme>(GetUintFromAttributes(attrs, "scheme"));
  int64_t date_synced = 0;
  base::StringToInt64(GetStringFromAttributes(attrs, "date_synced"),
                      &date_synced);
  form->date_synced = base::Time::FromInternalValue(date_synced);
  form->display_name =
      UTF8ToUTF16(GetStringFromAttributes(attrs, "display_name"));
  form->icon_url = GURL(GetStringFromAttributes(attrs, "avatar_url"));
  form->federation_origin = url::Origin::Create(
      GURL(GetStringFromAttributes(attrs, "federation_url")));
  form->skip_zero_click =
      g_hash_table_lookup(attrs, "should_skip_zero_click")
          ? GetUintFromAttributes(attrs, "should_skip_zero_click")
          : true;
  form->generation_upload_status =
      static_cast<PasswordForm::GenerationUploadStatus>(
          GetUintFromAttributes(attrs, "generation_upload_status"));
  base::StringPiece encoded_form_data =
      GetStringFromAttributes(attrs, "form_data");
  if (!encoded_form_data.empty()) {
    bool success = DeserializeFormDataFromBase64String(encoded_form_data,
                                                       &form->form_data);
    password_manager::metrics_util::FormDeserializationStatus status =
        success ? password_manager::metrics_util::GNOME_SUCCESS
                : password_manager::metrics_util::GNOME_FAILURE;
    LogFormDataDeserializationStatus(status);
  }
  return form;
}

// Generates a profile-specific app string based on profile_id_.
std::string GetProfileSpecificAppString(LocalProfileId id) {
  // Originally, the application string was always just "chrome" and used only
  // so that we had *something* to search for since GNOME Keyring won't search
  // for nothing. Now we use it to distinguish passwords for different profiles.
  return base::StringPrintf("%s-%d", kLibsecretAppString, id);
}

}  // namespace

NativeBackendLibsecret::NativeBackendLibsecret(LocalProfileId id)
    : app_string_(GetProfileSpecificAppString(id)),
      ensured_keyring_unlocked_(false) {}

NativeBackendLibsecret::~NativeBackendLibsecret() {
}

bool NativeBackendLibsecret::Init() {
  return LibsecretLoader::EnsureLibsecretLoaded();
}

password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin(
    const PasswordForm& form) {
  // Based on LoginDatabase::AddLogin(), we search for an existing match based
  // on origin_url, username_element, username_value, password_element and
  // signon_realm first, remove that, and then add the new entry.
  password_manager::PasswordStoreChangeList changes;
  std::vector<std::unique_ptr<PasswordForm>> forms;
  if (!AddUpdateLoginSearch(form, &forms))
    return changes;

  if (forms.size() > 0) {
    password_manager::PasswordStoreChangeList temp_changes;
    if (forms.size() > 1) {
      LOG(WARNING) << "Adding login when there are " << forms.size()
                   << " matching logins already!";
    }
    for (const auto& old_form : forms) {
      if (!RemoveLogin(*old_form, &temp_changes))
        return changes;
    }
    changes.push_back(password_manager::PasswordStoreChange(
        password_manager::PasswordStoreChange::REMOVE, *forms[0]));
  }
  if (RawAddLogin(form)) {
    changes.push_back(password_manager::PasswordStoreChange(
        password_manager::PasswordStoreChange::ADD, form));
  }
  return changes;
}

bool NativeBackendLibsecret::UpdateLogin(
    const PasswordForm& form,
    password_manager::PasswordStoreChangeList* changes) {
  // Based on LoginDatabase::UpdateLogin(), we search for forms to update by
  // origin_url, username_element, username_value, password_element, and
  // signon_realm. We then compare the result to the updated form. If they
  // differ in any of the mutable fields, then we remove the original, and
  // then add the new entry. We'd add the new one first, and then delete the
  // original, but then the delete might actually delete the newly-added entry!
  DCHECK(changes);
  std::vector<std::unique_ptr<PasswordForm>> forms;
  if (!AddUpdateLoginSearch(form, &forms))
    return false;
  if (forms.empty())
    return true;
  if (forms.size() == 1 && *forms.front() == form)
    return true;

  password_manager::PasswordStoreChangeList temp_changes;
  for (const auto& keychain_form : forms) {
    // Remove all the obsolete forms. Note that RemoveLogin can remove any form
    // matching the unique key. Thus, it's important to call it the right number
    // of times.
    if (!RemoveLogin(*keychain_form, &temp_changes))
      return false;
  }

  if (RawAddLogin(form)) {
    password_manager::PasswordStoreChange change(
        password_manager::PasswordStoreChange::UPDATE, form);
    changes->push_back(change);
    return true;
  }
  return false;
}

bool NativeBackendLibsecret::RemoveLogin(
    const PasswordForm& form,
    password_manager::PasswordStoreChangeList* changes) {
  DCHECK(changes);
  GError* error = nullptr;
  if (LibsecretLoader::secret_password_clear_sync(
          &kLibsecretSchema, nullptr, &error, "origin_url",
          form.origin.spec().c_str(), "username_element",
          UTF16ToUTF8(form.username_element).c_str(), "username_value",
          UTF16ToUTF8(form.username_value).c_str(), "password_element",
          UTF16ToUTF8(form.password_element).c_str(), "signon_realm",
          form.signon_realm.c_str(), "application", app_string_.c_str(),
          nullptr)) {
    changes->push_back(password_manager::PasswordStoreChange(
        password_manager::PasswordStoreChange::REMOVE, form));
  }

  if (error) {
    LOG(ERROR) << "Libsecret delete failed: " << error->message;
    g_error_free(error);
    return false;
  }
  return true;
}

bool NativeBackendLibsecret::RemoveLoginsCreatedBetween(
    base::Time delete_begin,
    base::Time delete_end,
    password_manager::PasswordStoreChangeList* changes) {
  return RemoveLoginsBetween(delete_begin, delete_end, CREATION_TIMESTAMP,
                             changes);
}

bool NativeBackendLibsecret::RemoveLoginsSyncedBetween(
    base::Time delete_begin,
    base::Time delete_end,
    password_manager::PasswordStoreChangeList* changes) {
  return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes);
}

bool NativeBackendLibsecret::DisableAutoSignInForOrigins(
    const base::Callback<bool(const GURL&)>& origin_filter,
    password_manager::PasswordStoreChangeList* changes) {
  std::vector<std::unique_ptr<PasswordForm>> all_forms;
  if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms))
    return false;

  for (const std::unique_ptr<PasswordForm>& form : all_forms) {
    if (origin_filter.Run(form->origin) && !form->skip_zero_click) {
      form->skip_zero_click = true;
      if (!UpdateLogin(*form, changes))
        return false;
    }
  }

  return true;
}

bool NativeBackendLibsecret::GetLogins(
    const PasswordStore::FormDigest& form,
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  return GetLoginsList(&form, ALL_LOGINS, forms);
}

bool NativeBackendLibsecret::AddUpdateLoginSearch(
    const PasswordForm& lookup_form,
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  if (!ensured_keyring_unlocked_) {
    LibsecretLoader::EnsureKeyringUnlocked();
    ensured_keyring_unlocked_ = true;
  }

  LibsecretAttributesBuilder attrs;
  attrs.Append("origin_url", lookup_form.origin.spec());
  attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element));
  attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value));
  attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element));
  attrs.Append("signon_realm", lookup_form.signon_realm);
  attrs.Append("application", app_string_);

  GError* error = nullptr;
  GList* found = LibsecretLoader::secret_service_search_sync(
      nullptr,  // default secret service
      &kLibsecretSchema, attrs.Get(),
      static_cast<SecretSearchFlags>(SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK),
      nullptr,  // no cancellable ojbect
      &error);
  if (error) {
    LOG(ERROR) << "Unable to get logins " << error->message;
    g_error_free(error);
    if (found)
      g_list_free_full(found, &g_object_unref);
    return false;
  }

  PasswordStore::FormDigest form(lookup_form);
  *forms = ConvertFormList(found, &form);
  return true;
}

bool NativeBackendLibsecret::RawAddLogin(const PasswordForm& form) {
  int64_t date_created = form.date_created.ToInternalValue();
  // If we are asked to save a password with 0 date, use the current time.
  // We don't want to actually save passwords as though on January 1, 1601.
  if (!date_created)
    date_created = base::Time::Now().ToInternalValue();
  int64_t date_synced = form.date_synced.ToInternalValue();
  std::string form_data;
  SerializeFormDataToBase64String(form.form_data, &form_data);
  GError* error = nullptr;
  // clang-format off
  LibsecretLoader::secret_password_store_sync(
      &kLibsecretSchema,
      nullptr,                     // Default collection.
      form.origin.spec().c_str(),  // Display name.
      UTF16ToUTF8(form.password_value).c_str(),
      nullptr,  // no cancellable ojbect
      &error,
      "origin_url", form.origin.spec().c_str(),
      "action_url", form.action.spec().c_str(),
      "username_element", UTF16ToUTF8(form.username_element).c_str(),
      "username_value", UTF16ToUTF8(form.username_value).c_str(),
      "password_element", UTF16ToUTF8(form.password_element).c_str(),
      "submit_element", UTF16ToUTF8(form.submit_element).c_str(),
      "signon_realm", form.signon_realm.c_str(),
      "preferred", form.preferred,
      "date_created", base::Int64ToString(date_created).c_str(),
      "blacklisted_by_user", form.blacklisted_by_user,
      "type", form.type,
      "times_used", form.times_used,
      "scheme", form.scheme,
      "date_synced", base::Int64ToString(date_synced).c_str(),
      "display_name", UTF16ToUTF8(form.display_name).c_str(),
      "avatar_url", form.icon_url.spec().c_str(),
      // We serialize unique origins as "", in order to make other systems that
      // read from the login database happy. https://crbug.com/591310
      "federation_url", form.federation_origin.unique()
          ? ""
          : form.federation_origin.Serialize().c_str(),
      "should_skip_zero_click", form.skip_zero_click,
      "generation_upload_status", form.generation_upload_status,
      "form_data", form_data.c_str(),
      "application", app_string_.c_str(),
      nullptr);
  // clang-format on

  if (error) {
    LOG(ERROR) << "Libsecret add raw login failed: " << error->message;
    g_error_free(error);
    return false;
  }
  return true;
}

bool NativeBackendLibsecret::GetAutofillableLogins(
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  return GetLoginsList(nullptr, AUTOFILLABLE_LOGINS, forms);
}

bool NativeBackendLibsecret::GetBlacklistLogins(
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  return GetLoginsList(nullptr, BLACKLISTED_LOGINS, forms);
}

bool NativeBackendLibsecret::GetAllLogins(
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  return GetLoginsList(nullptr, ALL_LOGINS, forms);
}

scoped_refptr<base::SequencedTaskRunner>
NativeBackendLibsecret::GetBackgroundTaskRunner() {
  return nullptr;
}

bool NativeBackendLibsecret::GetLoginsList(
    const PasswordStore::FormDigest* lookup_form,
    GetLoginsListOptions options,
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  if (!ensured_keyring_unlocked_) {
    LibsecretLoader::EnsureKeyringUnlocked();
    ensured_keyring_unlocked_ = true;
  }

  LibsecretAttributesBuilder attrs;
  attrs.Append("application", app_string_);
  if (options != ALL_LOGINS)
    attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS);
  if (lookup_form &&
      !password_manager::ShouldPSLDomainMatchingApply(
          password_manager::GetRegistryControlledDomain(
              GURL(lookup_form->signon_realm))) &&
      lookup_form->scheme != PasswordForm::SCHEME_HTML)
    attrs.Append("signon_realm", lookup_form->signon_realm);

  GError* error = nullptr;
  GList* found = LibsecretLoader::secret_service_search_sync(
      nullptr,  // default secret service
      &kLibsecretSchema, attrs.Get(),
      static_cast<SecretSearchFlags>(SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK),
      nullptr,  // no cancellable ojbect
      &error);
  if (error) {
    LOG(ERROR) << "Unable to get logins " << error->message;
    g_error_free(error);
    if (found)
      g_list_free_full(found, &g_object_unref);
    return false;
  }

  *forms = ConvertFormList(found, lookup_form);
  if (lookup_form)
    return true;

  // Get rid of the forms with the same sync tags.
  std::vector<std::unique_ptr<PasswordForm>> duplicates;
  std::vector<std::vector<PasswordForm*>> tag_groups;
  password_manager_util::FindDuplicates(forms, &duplicates, &tag_groups);
  if (duplicates.empty())
    return true;
  for (const auto& group : tag_groups) {
    if (group.size() > 1) {
      // There are duplicates. Readd the first form. AddLogin() is smart enough
      // to clean the previous ones.
      password_manager::PasswordStoreChangeList changes = AddLogin(*group[0]);
      if (changes.empty() ||
          changes.back().type() != password_manager::PasswordStoreChange::ADD)
        return false;
    }
  }
  return true;
}

bool NativeBackendLibsecret::GetLoginsBetween(
    base::Time get_begin,
    base::Time get_end,
    TimestampToCompare date_to_compare,
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  forms->clear();
  std::vector<std::unique_ptr<PasswordForm>> all_forms;
  if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms))
    return false;

  base::Time PasswordForm::*date_member = date_to_compare == CREATION_TIMESTAMP
                                              ? &PasswordForm::date_created
                                              : &PasswordForm::date_synced;
  for (std::unique_ptr<PasswordForm>& saved_form : all_forms) {
    if (get_begin <= saved_form.get()->*date_member &&
        (get_end.is_null() || saved_form.get()->*date_member < get_end)) {
      forms->push_back(std::move(saved_form));
    }
  }

  return true;
}

bool NativeBackendLibsecret::RemoveLoginsBetween(
    base::Time get_begin,
    base::Time get_end,
    TimestampToCompare date_to_compare,
    password_manager::PasswordStoreChangeList* changes) {
  DCHECK(changes);
  changes->clear();
  std::vector<std::unique_ptr<PasswordForm>> forms;
  if (!GetLoginsBetween(get_begin, get_end, date_to_compare, &forms))
    return false;

  for (size_t i = 0; i < forms.size(); ++i) {
    if (!RemoveLogin(*forms[i], changes))
      return false;
  }
  return true;
}

std::vector<std::unique_ptr<PasswordForm>>
NativeBackendLibsecret::ConvertFormList(
    GList* found,
    const PasswordStore::FormDigest* lookup_form) {
  std::vector<std::unique_ptr<PasswordForm>> forms;
  password_manager::PSLDomainMatchMetric psl_domain_match_metric =
      password_manager::PSL_DOMAIN_MATCH_NONE;
  GError* error = nullptr;
  for (GList* element = g_list_first(found); element != nullptr;
       element = g_list_next(element)) {
    SecretItem* secretItem = static_cast<SecretItem*>(element->data);
    LibsecretLoader::secret_item_load_secret_sync(secretItem, nullptr, &error);
    if (error) {
      LOG(ERROR) << "Unable to load secret item" << error->message;
      g_error_free(error);
      error = nullptr;
      continue;
    }
    GHashTable* attrs = LibsecretLoader::secret_item_get_attributes(secretItem);
    std::unique_ptr<PasswordForm> form(FormOutOfAttributes(attrs));
    g_hash_table_unref(attrs);
    if (!form) {
      VLOG(1) << "Could not initialize PasswordForm from attributes!";
      continue;
    }

    if (lookup_form) {
      switch (GetMatchResult(*form, *lookup_form)) {
        case MatchResult::NO_MATCH:
          continue;
        case MatchResult::EXACT_MATCH:
          break;
        case MatchResult::PSL_MATCH:
          psl_domain_match_metric = password_manager::PSL_DOMAIN_MATCH_FOUND;
          form->is_public_suffix_match = true;
          break;
        case MatchResult::FEDERATED_MATCH:
          break;
        case MatchResult::FEDERATED_PSL_MATCH:
          psl_domain_match_metric =
              password_manager::PSL_DOMAIN_MATCH_FOUND_FEDERATED;
          form->is_public_suffix_match = true;
          break;
      }
    }

    SecretValue* secretValue =
        LibsecretLoader::secret_item_get_secret(secretItem);
    if (secretValue) {
      form->password_value =
          UTF8ToUTF16(LibsecretLoader::secret_value_get_text(secretValue));
      LibsecretLoader::secret_value_unref(secretValue);
    } else {
      LOG(WARNING) << "Unable to access password from list element!";
    }
    forms.push_back(std::move(form));
  }

  if (lookup_form) {
    const bool allow_psl_match = password_manager::ShouldPSLDomainMatchingApply(
        password_manager::GetRegistryControlledDomain(
            GURL(lookup_form->signon_realm)));
    UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering",
                              allow_psl_match
                                  ? psl_domain_match_metric
                                  : password_manager::PSL_DOMAIN_MATCH_NOT_USED,
                              password_manager::PSL_DOMAIN_MATCH_COUNT);
  }
  g_list_free_full(found, &g_object_unref);
  return forms;
}
