// 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 "net/cert/nss_cert_database.h"

#include <cert.h>
#include <certdb.h>
#include <keyhi.h>
#include <pk11pub.h>
#include <secmod.h>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/observer_list_threadsafe.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "crypto/scoped_nss_types.h"
#include "net/base/crypto_module.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_database.h"
#include "net/cert/x509_certificate.h"
#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
#include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h"

// In NSS 3.13, CERTDB_VALID_PEER was renamed CERTDB_TERMINAL_RECORD. So we use
// the new name of the macro.
#if !defined(CERTDB_TERMINAL_RECORD)
#define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER
#endif

// PSM = Mozilla's Personal Security Manager.
namespace psm = mozilla_security_manager;

namespace net {

NSSCertDatabase::ImportCertFailure::ImportCertFailure(
    const scoped_refptr<X509Certificate>& cert,
    int err)
    : certificate(cert), net_error(err) {}

NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {}

// static
NSSCertDatabase* NSSCertDatabase::GetInstance() {
  return Singleton<NSSCertDatabase,
                   LeakySingletonTraits<NSSCertDatabase> >::get();
}

NSSCertDatabase::NSSCertDatabase()
    : observer_list_(new ObserverListThreadSafe<Observer>) {
  crypto::EnsureNSSInit();
  psm::EnsurePKCS12Init();
}

NSSCertDatabase::~NSSCertDatabase() {}

void NSSCertDatabase::ListCerts(CertificateList* certs) {
  certs->clear();

  CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL);
  CERTCertListNode* node;
  for (node = CERT_LIST_HEAD(cert_list);
       !CERT_LIST_END(node, cert_list);
       node = CERT_LIST_NEXT(node)) {
    certs->push_back(X509Certificate::CreateFromHandle(
        node->cert, X509Certificate::OSCertHandles()));
  }
  CERT_DestroyCertList(cert_list);
}

crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const {
  return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot());
}

crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const {
  return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot());
}

CryptoModule* NSSCertDatabase::GetPublicModule() const {
  crypto::ScopedPK11Slot slot(GetPublicSlot());
  return CryptoModule::CreateFromHandle(slot.get());
}

CryptoModule* NSSCertDatabase::GetPrivateModule() const {
  crypto::ScopedPK11Slot slot(GetPrivateSlot());
  return CryptoModule::CreateFromHandle(slot.get());
}

void NSSCertDatabase::ListModules(CryptoModuleList* modules,
                                  bool need_rw) const {
  modules->clear();

  // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
  crypto::ScopedPK11SlotList slot_list(
      PK11_GetAllTokens(CKM_INVALID_MECHANISM,
                        need_rw ? PR_TRUE : PR_FALSE,  // needRW
                        PR_TRUE,                       // loadCerts (unused)
                        NULL));                        // wincx
  if (!slot_list) {
    LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError();
    return;
  }

  PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list.get());
  while (slot_element) {
    modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot));
    slot_element = PK11_GetNextSafe(slot_list.get(), slot_element,
                                    PR_FALSE);  // restart
  }
}

int NSSCertDatabase::ImportFromPKCS12(
    CryptoModule* module,
    const std::string& data,
    const base::string16& password,
    bool is_extractable,
    net::CertificateList* imported_certs) {
  int result = psm::nsPKCS12Blob_Import(module->os_module_handle(),
                                        data.data(), data.size(),
                                        password,
                                        is_extractable,
                                        imported_certs);
  if (result == net::OK)
    NotifyObserversOfCertAdded(NULL);

  return result;
}

int NSSCertDatabase::ExportToPKCS12(
    const CertificateList& certs,
    const base::string16& password,
    std::string* output) const {
  return psm::nsPKCS12Blob_Export(output, certs, password);
}

X509Certificate* NSSCertDatabase::FindRootInList(
    const CertificateList& certificates) const {
  DCHECK_GT(certificates.size(), 0U);

  if (certificates.size() == 1)
    return certificates[0].get();

  X509Certificate* cert0 = certificates[0].get();
  X509Certificate* cert1 = certificates[1].get();
  X509Certificate* certn_2 = certificates[certificates.size() - 2].get();
  X509Certificate* certn_1 = certificates[certificates.size() - 1].get();

  if (CERT_CompareName(&cert1->os_cert_handle()->issuer,
                       &cert0->os_cert_handle()->subject) == SECEqual)
    return cert0;
  if (CERT_CompareName(&certn_2->os_cert_handle()->issuer,
                       &certn_1->os_cert_handle()->subject) == SECEqual)
    return certn_1;

  VLOG(1) << "certificate list is not a hierarchy";
  return cert0;
}

bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates,
                                    TrustBits trust_bits,
                                    ImportCertFailureList* not_imported) {
  crypto::ScopedPK11Slot slot(GetPublicSlot());
  X509Certificate* root = FindRootInList(certificates);
  bool success = psm::ImportCACerts(
      slot.get(), certificates, root, trust_bits, not_imported);
  if (success)
    NotifyObserversOfCACertChanged(NULL);

  return success;
}

bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates,
                                       TrustBits trust_bits,
                                       ImportCertFailureList* not_imported) {
  crypto::ScopedPK11Slot slot(GetPublicSlot());
  return psm::ImportServerCert(
      slot.get(), certificates, trust_bits, not_imported);
}

NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust(
    const X509Certificate* cert,
    CertType type) const {
  CERTCertTrust trust;
  SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust);
  if (srv != SECSuccess) {
    LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError();
    return TRUST_DEFAULT;
  }
  // We define our own more "friendly" TrustBits, which means we aren't able to
  // round-trip all possible NSS trust flag combinations.  We try to map them in
  // a sensible way.
  switch (type) {
    case CA_CERT: {
      const unsigned kTrustedCA = CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;
      const unsigned kCAFlags = kTrustedCA | CERTDB_TERMINAL_RECORD;

      TrustBits trust_bits = TRUST_DEFAULT;
      if ((trust.sslFlags & kCAFlags) == CERTDB_TERMINAL_RECORD)
        trust_bits |= DISTRUSTED_SSL;
      else if (trust.sslFlags & kTrustedCA)
        trust_bits |= TRUSTED_SSL;

      if ((trust.emailFlags & kCAFlags) == CERTDB_TERMINAL_RECORD)
        trust_bits |= DISTRUSTED_EMAIL;
      else if (trust.emailFlags & kTrustedCA)
        trust_bits |= TRUSTED_EMAIL;

      if ((trust.objectSigningFlags & kCAFlags) == CERTDB_TERMINAL_RECORD)
        trust_bits |= DISTRUSTED_OBJ_SIGN;
      else if (trust.objectSigningFlags & kTrustedCA)
        trust_bits |= TRUSTED_OBJ_SIGN;

      return trust_bits;
    }
    case SERVER_CERT:
      if (trust.sslFlags & CERTDB_TERMINAL_RECORD) {
        if (trust.sslFlags & CERTDB_TRUSTED)
          return TRUSTED_SSL;
        return DISTRUSTED_SSL;
      }
      return TRUST_DEFAULT;
    default:
      return TRUST_DEFAULT;
  }
}

bool NSSCertDatabase::IsUntrusted(const X509Certificate* cert) const {
  CERTCertTrust nsstrust;
  SECStatus rv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust);
  if (rv != SECSuccess) {
    LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError();
    return false;
  }

  // The CERTCertTrust structure contains three trust records:
  // sslFlags, emailFlags, and objectSigningFlags.  The three
  // trust records are independent of each other.
  //
  // If the CERTDB_TERMINAL_RECORD bit in a trust record is set,
  // then that trust record is a terminal record.  A terminal
  // record is used for explicit trust and distrust of an
  // end-entity or intermediate CA cert.
  //
  // In a terminal record, if neither CERTDB_TRUSTED_CA nor
  // CERTDB_TRUSTED is set, then the terminal record means
  // explicit distrust.  On the other hand, if the terminal
  // record has either CERTDB_TRUSTED_CA or CERTDB_TRUSTED bit
  // set, then the terminal record means explicit trust.
  //
  // For a root CA, the trust record does not have
  // the CERTDB_TERMINAL_RECORD bit set.

  static const unsigned int kTrusted = CERTDB_TRUSTED_CA | CERTDB_TRUSTED;
  if ((nsstrust.sslFlags & CERTDB_TERMINAL_RECORD) != 0 &&
      (nsstrust.sslFlags & kTrusted) == 0) {
    return true;
  }
  if ((nsstrust.emailFlags & CERTDB_TERMINAL_RECORD) != 0 &&
      (nsstrust.emailFlags & kTrusted) == 0) {
    return true;
  }
  if ((nsstrust.objectSigningFlags & CERTDB_TERMINAL_RECORD) != 0 &&
      (nsstrust.objectSigningFlags & kTrusted) == 0) {
    return true;
  }

  // Self-signed certificates that don't have any trust bits set are untrusted.
  // Other certificates that don't have any trust bits set may still be trusted
  // if they chain up to a trust anchor.
  if (CERT_CompareName(&cert->os_cert_handle()->issuer,
                       &cert->os_cert_handle()->subject) == SECEqual) {
    return (nsstrust.sslFlags & kTrusted) == 0 &&
           (nsstrust.emailFlags & kTrusted) == 0 &&
           (nsstrust.objectSigningFlags & kTrusted) == 0;
  }

  return false;
}

bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert,
                                CertType type,
                                TrustBits trust_bits) {
  bool success = psm::SetCertTrust(cert, type, trust_bits);
  if (success)
    NotifyObserversOfCACertChanged(cert);

  return success;
}

bool NSSCertDatabase::DeleteCertAndKey(const X509Certificate* cert) {
  // For some reason, PK11_DeleteTokenCertAndKey only calls
  // SEC_DeletePermCertificate if the private key is found.  So, we check
  // whether a private key exists before deciding which function to call to
  // delete the cert.
  SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(),
                                                    NULL);
  if (privKey) {
    SECKEY_DestroyPrivateKey(privKey);
    if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) {
      LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError();
      return false;
    }
  } else {
    if (SEC_DeletePermCertificate(cert->os_cert_handle())) {
      LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError();
      return false;
    }
  }

  NotifyObserversOfCertRemoved(cert);

  return true;
}

bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const {
  PK11SlotInfo* slot = cert->os_cert_handle()->slot;
  return slot && PK11_IsReadOnly(slot);
}

bool NSSCertDatabase::IsHardwareBacked(const X509Certificate* cert) const {
  PK11SlotInfo* slot = cert->os_cert_handle()->slot;
  return slot && PK11_IsHW(slot);
}

void NSSCertDatabase::AddObserver(Observer* observer) {
  observer_list_->AddObserver(observer);
}

void NSSCertDatabase::RemoveObserver(Observer* observer) {
  observer_list_->RemoveObserver(observer);
}

void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) {
  observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert));
}

void NSSCertDatabase::NotifyObserversOfCertRemoved(
    const X509Certificate* cert) {
  observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert));
}

void NSSCertDatabase::NotifyObserversOfCACertChanged(
    const X509Certificate* cert) {
  observer_list_->Notify(
      &Observer::OnCACertChanged, make_scoped_refptr(cert));
}

}  // namespace net
