// Copyright (c) 2011 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/utility/importer/nss_decryptor_win.h"

#include "base/files/file_path.h"
#include "base/strings/sys_string_conversions.h"

namespace {

typedef BOOL (WINAPI* SetDllDirectoryFunc)(LPCTSTR lpPathName);

// A helper class whose destructor calls SetDllDirectory(NULL) to undo the
// effects of a previous SetDllDirectory call.
class SetDllDirectoryCaller {
 public:
  explicit SetDllDirectoryCaller() : func_(NULL) { }

  ~SetDllDirectoryCaller() {
    if (func_)
      func_(NULL);
  }

  // Sets the SetDllDirectory function pointer to activates this object.
  void set_func(SetDllDirectoryFunc func) { func_ = func; }

 private:
  SetDllDirectoryFunc func_;
};

}  // namespace

// static
const wchar_t NSSDecryptor::kNSS3Library[] = L"nss3.dll";
const wchar_t NSSDecryptor::kSoftokn3Library[] = L"softokn3.dll";
const wchar_t NSSDecryptor::kPLDS4Library[] = L"plds4.dll";
const wchar_t NSSDecryptor::kNSPR4Library[] = L"nspr4.dll";

bool NSSDecryptor::Init(const base::FilePath& dll_path,
                        const base::FilePath& db_path) {
  // We call SetDllDirectory to work around a Purify bug (GetModuleHandle
  // fails inside Purify under certain conditions).  SetDllDirectory only
  // exists on Windows XP SP1 or later, so we look up its address at run time.
  HMODULE kernel32_dll = GetModuleHandle(L"kernel32.dll");
  if (kernel32_dll == NULL)
    return false;
  SetDllDirectoryFunc set_dll_directory =
      (SetDllDirectoryFunc)GetProcAddress(kernel32_dll, "SetDllDirectoryW");
  SetDllDirectoryCaller caller;

  if (set_dll_directory != NULL) {
    if (!set_dll_directory(dll_path.value().c_str()))
      return false;
    caller.set_func(set_dll_directory);
    nss3_dll_ = LoadLibrary(kNSS3Library);
    if (nss3_dll_ == NULL)
      return false;
  } else {
    // Fall back on LoadLibraryEx if SetDllDirectory isn't available.  We
    // actually prefer this method because it doesn't change the DLL search
    // path, which is a process-wide property.
    base::FilePath path = dll_path.Append(kNSS3Library);
    nss3_dll_ = LoadLibraryEx(path.value().c_str(), NULL,
                              LOAD_WITH_ALTERED_SEARCH_PATH);
    if (nss3_dll_ == NULL)
      return false;

    // Firefox 2 uses NSS 3.11.  Firefox 3 uses NSS 3.12.  NSS 3.12 has two
    // changes in its DLLs:
    // 1. nss3.dll is not linked with softokn3.dll at build time, but rather
    //    loads softokn3.dll using LoadLibrary in NSS_Init.
    // 2. softokn3.dll has a new dependency sqlite3.dll.
    // NSS_Init's LoadLibrary call has trouble finding sqlite3.dll.  To help
    // it out, we preload softokn3.dll using LoadLibraryEx with the
    // LOAD_WITH_ALTERED_SEARCH_PATH flag.  This helps because LoadLibrary
    // doesn't load a DLL again if it's already loaded.  This workaround is
    // harmless for NSS 3.11.
    path = base::FilePath(dll_path).Append(kSoftokn3Library);
    softokn3_dll_ = LoadLibraryEx(path.value().c_str(), NULL,
                                  LOAD_WITH_ALTERED_SEARCH_PATH);
    if (softokn3_dll_ == NULL) {
      Free();
      return false;
    }
  }
  HMODULE plds4_dll = GetModuleHandle(kPLDS4Library);
  HMODULE nspr4_dll = GetModuleHandle(kNSPR4Library);

  return InitNSS(db_path, plds4_dll, nspr4_dll);
}

NSSDecryptor::NSSDecryptor()
    : NSS_Init(NULL), NSS_Shutdown(NULL), PK11_GetInternalKeySlot(NULL),
      PK11_CheckUserPassword(NULL), PK11_FreeSlot(NULL),
      PK11_Authenticate(NULL), PK11SDR_Decrypt(NULL), SECITEM_FreeItem(NULL),
      PL_ArenaFinish(NULL), PR_Cleanup(NULL),
      nss3_dll_(NULL), softokn3_dll_(NULL),
      is_nss_initialized_(false) {
}

NSSDecryptor::~NSSDecryptor() {
  Free();
}

bool NSSDecryptor::InitNSS(const base::FilePath& db_path,
                           base::NativeLibrary plds4_dll,
                           base::NativeLibrary nspr4_dll) {
  // NSPR DLLs are already loaded now.
  if (plds4_dll == NULL || nspr4_dll == NULL) {
    Free();
    return false;
  }

  // Gets the function address.
  NSS_Init = (NSSInitFunc)
      base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "NSS_Init");
  NSS_Shutdown = (NSSShutdownFunc)
      base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "NSS_Shutdown");
  PK11_GetInternalKeySlot = (PK11GetInternalKeySlotFunc)
      base::GetFunctionPointerFromNativeLibrary(nss3_dll_,
                                                "PK11_GetInternalKeySlot");
  PK11_FreeSlot = (PK11FreeSlotFunc)
      base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "PK11_FreeSlot");
  PK11_Authenticate = (PK11AuthenticateFunc)
      base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "PK11_Authenticate");
  PK11SDR_Decrypt = (PK11SDRDecryptFunc)
      base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "PK11SDR_Decrypt");
  SECITEM_FreeItem = (SECITEMFreeItemFunc)
      base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "SECITEM_FreeItem");
  PL_ArenaFinish = (PLArenaFinishFunc)
      base::GetFunctionPointerFromNativeLibrary(plds4_dll, "PL_ArenaFinish");
  PR_Cleanup = (PRCleanupFunc)
      base::GetFunctionPointerFromNativeLibrary(nspr4_dll, "PR_Cleanup");

  if (NSS_Init == NULL || NSS_Shutdown == NULL ||
      PK11_GetInternalKeySlot == NULL || PK11_FreeSlot == NULL ||
      PK11_Authenticate == NULL || PK11SDR_Decrypt == NULL ||
      SECITEM_FreeItem == NULL || PL_ArenaFinish == NULL ||
      PR_Cleanup == NULL) {
    Free();
    return false;
  }

  SECStatus result = NSS_Init(base::SysWideToNativeMB(db_path.value()).c_str());
  if (result != SECSuccess) {
    Free();
    return false;
  }

  is_nss_initialized_ = true;
  return true;
}

void NSSDecryptor::Free() {
  if (is_nss_initialized_) {
    NSS_Shutdown();
    PL_ArenaFinish();
    PR_Cleanup();
    is_nss_initialized_ = false;
  }
  if (softokn3_dll_ != NULL)
    base::UnloadNativeLibrary(softokn3_dll_);
  if (nss3_dll_ != NULL)
    base::UnloadNativeLibrary(nss3_dll_);
  NSS_Init = NULL;
  NSS_Shutdown = NULL;
  PK11_GetInternalKeySlot = NULL;
  PK11_FreeSlot = NULL;
  PK11_Authenticate = NULL;
  PK11SDR_Decrypt = NULL;
  SECITEM_FreeItem = NULL;
  PL_ArenaFinish = NULL;
  PR_Cleanup = NULL;
  nss3_dll_ = NULL;
  softokn3_dll_ = NULL;
}
