// Copyright 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 "sync/syncable/nigori_util.h"

#include <queue>
#include <string>
#include <vector>

#include "base/json/json_writer.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/entry.h"
#include "sync/syncable/nigori_handler.h"
#include "sync/syncable/mutable_entry.h"
#include "sync/syncable/syncable_util.h"
#include "sync/syncable/syncable_write_transaction.h"
#include "sync/util/cryptographer.h"

namespace syncer {
namespace syncable {

bool ProcessUnsyncedChangesForEncryption(
    WriteTransaction* const trans) {
  NigoriHandler* nigori_handler = trans->directory()->GetNigoriHandler();
  ModelTypeSet encrypted_types = nigori_handler->GetEncryptedTypes(trans);
  Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans);
  DCHECK(cryptographer->is_ready());

  // Get list of all datatypes with unsynced changes. It's possible that our
  // local changes need to be encrypted if encryption for that datatype was
  // just turned on (and vice versa).
  // Note: we do not attempt to re-encrypt data with a new key here as key
  // changes in this code path are likely due to consistency issues (we have
  // to be updated to a key we already have, e.g. an old key).
  std::vector<int64> handles;
  GetUnsyncedEntries(trans, &handles);
  for (size_t i = 0; i < handles.size(); ++i) {
    MutableEntry entry(trans, GET_BY_HANDLE, handles[i]);
    const sync_pb::EntitySpecifics& specifics = entry.GetSpecifics();
    // Ignore types that don't need encryption or entries that are already
    // encrypted.
    if (!SpecificsNeedsEncryption(encrypted_types, specifics))
      continue;
    if (!UpdateEntryWithEncryption(trans, specifics, &entry))
      return false;
  }
  return true;
}

bool VerifyUnsyncedChangesAreEncrypted(
    BaseTransaction* const trans,
    ModelTypeSet encrypted_types) {
  std::vector<int64> handles;
  GetUnsyncedEntries(trans, &handles);
  for (size_t i = 0; i < handles.size(); ++i) {
    Entry entry(trans, GET_BY_HANDLE, handles[i]);
    if (!entry.good()) {
      NOTREACHED();
      return false;
    }
    if (EntryNeedsEncryption(encrypted_types, entry))
      return false;
  }
  return true;
}

bool EntryNeedsEncryption(ModelTypeSet encrypted_types,
                          const Entry& entry) {
  if (!entry.GetUniqueServerTag().empty())
    return false;  // We don't encrypt unique server nodes.
  ModelType type = entry.GetModelType();
  if (type == PASSWORDS || IsControlType(type))
    return false;
  // Checking NON_UNIQUE_NAME is not necessary for the correctness of encrypting
  // the data, nor for determining if data is encrypted. We simply ensure it has
  // been overwritten to avoid any possible leaks of sensitive data.
  return SpecificsNeedsEncryption(encrypted_types, entry.GetSpecifics()) ||
         (encrypted_types.Has(type) &&
          entry.GetNonUniqueName() != kEncryptedString);
}

bool SpecificsNeedsEncryption(ModelTypeSet encrypted_types,
                              const sync_pb::EntitySpecifics& specifics) {
  const ModelType type = GetModelTypeFromSpecifics(specifics);
  if (type == PASSWORDS || IsControlType(type))
    return false;  // These types have their own encryption schemes.
  if (!encrypted_types.Has(type))
    return false;  // This type does not require encryption
  return !specifics.has_encrypted();
}

// Mainly for testing.
bool VerifyDataTypeEncryptionForTest(
    BaseTransaction* const trans,
    ModelType type,
    bool is_encrypted) {
  Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans);
  if (type == PASSWORDS || IsControlType(type)) {
    NOTREACHED();
    return true;
  }
  Entry type_root(trans, GET_TYPE_ROOT, type);
  if (!type_root.good()) {
    NOTREACHED();
    return false;
  }

  std::queue<Id> to_visit;
  Id id_string = type_root.GetFirstChildId();
  to_visit.push(id_string);
  while (!to_visit.empty()) {
    id_string = to_visit.front();
    to_visit.pop();
    if (id_string.IsNull())
      continue;

    Entry child(trans, GET_BY_ID, id_string);
    if (!child.good()) {
      NOTREACHED();
      return false;
    }
    if (child.GetIsDir()) {
      Id child_id_string = child.GetFirstChildId();
      // Traverse the children.
      to_visit.push(child_id_string);
    }
    const sync_pb::EntitySpecifics& specifics = child.GetSpecifics();
    DCHECK_EQ(type, child.GetModelType());
    DCHECK_EQ(type, GetModelTypeFromSpecifics(specifics));
    // We don't encrypt the server's permanent items.
    if (child.GetUniqueServerTag().empty()) {
      if (specifics.has_encrypted() != is_encrypted)
        return false;
      if (specifics.has_encrypted()) {
        if (child.GetNonUniqueName() != kEncryptedString)
          return false;
        if (!cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted()))
          return false;
      }
    }
    // Push the successor.
    to_visit.push(child.GetSuccessorId());
  }
  return true;
}

bool UpdateEntryWithEncryption(
    BaseTransaction* const trans,
    const sync_pb::EntitySpecifics& new_specifics,
    syncable::MutableEntry* entry) {
  NigoriHandler* nigori_handler = trans->directory()->GetNigoriHandler();
  Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans);
  ModelType type = GetModelTypeFromSpecifics(new_specifics);
  DCHECK_GE(type, FIRST_REAL_MODEL_TYPE);
  const sync_pb::EntitySpecifics& old_specifics = entry->GetSpecifics();
  const ModelTypeSet encrypted_types =
      nigori_handler?
          nigori_handler->GetEncryptedTypes(trans) : ModelTypeSet();
  // It's possible the nigori lost the set of encrypted types. If the current
  // specifics are already encrypted, we want to ensure we continue encrypting.
  bool was_encrypted = old_specifics.has_encrypted();
  sync_pb::EntitySpecifics generated_specifics;
  if (new_specifics.has_encrypted()) {
    NOTREACHED() << "New specifics already has an encrypted blob.";
    return false;
  }
  if ((!SpecificsNeedsEncryption(encrypted_types, new_specifics) &&
       !was_encrypted) ||
      !cryptographer || !cryptographer->is_initialized()) {
    // No encryption required or we are unable to encrypt.
    generated_specifics.CopyFrom(new_specifics);
  } else {
    // Encrypt new_specifics into generated_specifics.
    if (VLOG_IS_ON(2)) {
      scoped_ptr<base::DictionaryValue> value(entry->ToValue(NULL));
      std::string info;
      base::JSONWriter::WriteWithOptions(
          *value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &info);
      DVLOG(2) << "Encrypting specifics of type "
               << ModelTypeToString(type)
               << " with content: "
               << info;
    }
    // Only copy over the old specifics if it is of the right type and already
    // encrypted. The first time we encrypt a node we start from scratch, hence
    // removing all the unencrypted data, but from then on we only want to
    // update the node if the data changes or the encryption key changes.
    if (GetModelTypeFromSpecifics(old_specifics) == type &&
        was_encrypted) {
      generated_specifics.CopyFrom(old_specifics);
    } else {
      AddDefaultFieldValue(type, &generated_specifics);
    }
    // Does not change anything if underlying encrypted blob was already up
    // to date and encrypted with the default key.
    if (!cryptographer->Encrypt(new_specifics,
                                generated_specifics.mutable_encrypted())) {
      NOTREACHED() << "Could not encrypt data for node of type "
                   << ModelTypeToString(type);
      return false;
    }
  }

  // It's possible this entry was encrypted but didn't properly overwrite the
  // non_unique_name (see crbug.com/96314).
  bool encrypted_without_overwriting_name = (was_encrypted &&
      entry->GetNonUniqueName() != kEncryptedString);

  // If we're encrypted but the name wasn't overwritten properly we still want
  // to rewrite the entry, irrespective of whether the specifics match.
  if (!encrypted_without_overwriting_name &&
      old_specifics.SerializeAsString() ==
          generated_specifics.SerializeAsString()) {
    DVLOG(2) << "Specifics of type " << ModelTypeToString(type)
             << " already match, dropping change.";
    return true;
  }

  if (generated_specifics.has_encrypted()) {
    // Overwrite the possibly sensitive non-specifics data.
    entry->PutNonUniqueName(kEncryptedString);
    // For bookmarks we actually put bogus data into the unencrypted specifics,
    // else the server will try to do it for us.
    if (type == BOOKMARKS) {
      sync_pb::BookmarkSpecifics* bookmark_specifics =
          generated_specifics.mutable_bookmark();
      if (!entry->GetIsDir())
        bookmark_specifics->set_url(kEncryptedString);
      bookmark_specifics->set_title(kEncryptedString);
    }
  }
  entry->PutSpecifics(generated_specifics);
  DVLOG(1) << "Overwriting specifics of type "
           << ModelTypeToString(type)
           << " and marking for syncing.";
  syncable::MarkForSyncing(entry);
  return true;
}

void UpdateNigoriFromEncryptedTypes(ModelTypeSet encrypted_types,
                                    bool encrypt_everything,
                                    sync_pb::NigoriSpecifics* nigori) {
  nigori->set_encrypt_everything(encrypt_everything);
  static_assert(36 == MODEL_TYPE_COUNT, "update encrypted types");
  nigori->set_encrypt_bookmarks(
      encrypted_types.Has(BOOKMARKS));
  nigori->set_encrypt_preferences(
      encrypted_types.Has(PREFERENCES));
  nigori->set_encrypt_autofill_profile(
      encrypted_types.Has(AUTOFILL_PROFILE));
  nigori->set_encrypt_autofill(encrypted_types.Has(AUTOFILL));
  nigori->set_encrypt_autofill_wallet_metadata(
      encrypted_types.Has(AUTOFILL_WALLET_METADATA));
  nigori->set_encrypt_themes(encrypted_types.Has(THEMES));
  nigori->set_encrypt_typed_urls(
      encrypted_types.Has(TYPED_URLS));
  nigori->set_encrypt_extension_settings(
      encrypted_types.Has(EXTENSION_SETTINGS));
  nigori->set_encrypt_extensions(
      encrypted_types.Has(EXTENSIONS));
  nigori->set_encrypt_search_engines(
      encrypted_types.Has(SEARCH_ENGINES));
  nigori->set_encrypt_sessions(encrypted_types.Has(SESSIONS));
  nigori->set_encrypt_app_settings(
      encrypted_types.Has(APP_SETTINGS));
  nigori->set_encrypt_apps(encrypted_types.Has(APPS));
  nigori->set_encrypt_app_notifications(
      encrypted_types.Has(APP_NOTIFICATIONS));
  nigori->set_encrypt_dictionary(encrypted_types.Has(DICTIONARY));
  nigori->set_encrypt_favicon_images(encrypted_types.Has(FAVICON_IMAGES));
  nigori->set_encrypt_favicon_tracking(encrypted_types.Has(FAVICON_TRACKING));
  nigori->set_encrypt_articles(encrypted_types.Has(ARTICLES));
  nigori->set_encrypt_app_list(encrypted_types.Has(APP_LIST));
}

ModelTypeSet GetEncryptedTypesFromNigori(
    const sync_pb::NigoriSpecifics& nigori) {
  if (nigori.encrypt_everything())
    return ModelTypeSet::All();

  ModelTypeSet encrypted_types;
  static_assert(36 == MODEL_TYPE_COUNT, "update encrypted types");
  if (nigori.encrypt_bookmarks())
    encrypted_types.Put(BOOKMARKS);
  if (nigori.encrypt_preferences())
    encrypted_types.Put(PREFERENCES);
  if (nigori.encrypt_autofill_profile())
    encrypted_types.Put(AUTOFILL_PROFILE);
  if (nigori.encrypt_autofill())
    encrypted_types.Put(AUTOFILL);
  if (nigori.encrypt_autofill_wallet_metadata())
    encrypted_types.Put(AUTOFILL_WALLET_METADATA);
  if (nigori.encrypt_themes())
    encrypted_types.Put(THEMES);
  if (nigori.encrypt_typed_urls())
    encrypted_types.Put(TYPED_URLS);
  if (nigori.encrypt_extension_settings())
    encrypted_types.Put(EXTENSION_SETTINGS);
  if (nigori.encrypt_extensions())
    encrypted_types.Put(EXTENSIONS);
  if (nigori.encrypt_search_engines())
    encrypted_types.Put(SEARCH_ENGINES);
  if (nigori.encrypt_sessions())
    encrypted_types.Put(SESSIONS);
  if (nigori.encrypt_app_settings())
    encrypted_types.Put(APP_SETTINGS);
  if (nigori.encrypt_apps())
    encrypted_types.Put(APPS);
  if (nigori.encrypt_app_notifications())
    encrypted_types.Put(APP_NOTIFICATIONS);
  if (nigori.encrypt_dictionary())
    encrypted_types.Put(DICTIONARY);
  if (nigori.encrypt_favicon_images())
    encrypted_types.Put(FAVICON_IMAGES);
  if (nigori.encrypt_favicon_tracking())
    encrypted_types.Put(FAVICON_TRACKING);
  if (nigori.encrypt_articles())
    encrypted_types.Put(ARTICLES);
  if (nigori.encrypt_app_list())
    encrypted_types.Put(APP_LIST);
  return encrypted_types;
}

}  // namespace syncable
}  // namespace syncer
