| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/importer/nss_decryptor_win.h" | |
| 6 | |
| 7 #include "base/files/file_path.h" | |
| 8 #include "base/strings/sys_string_conversions.h" | |
| 9 | |
| 10 namespace { | |
| 11 | |
| 12 typedef BOOL (WINAPI* SetDllDirectoryFunc)(LPCTSTR lpPathName); | |
| 13 | |
| 14 // A helper class whose destructor calls SetDllDirectory(NULL) to undo the | |
| 15 // effects of a previous SetDllDirectory call. | |
| 16 class SetDllDirectoryCaller { | |
| 17 public: | |
| 18 explicit SetDllDirectoryCaller() : func_(NULL) { } | |
| 19 | |
| 20 ~SetDllDirectoryCaller() { | |
| 21 if (func_) | |
| 22 func_(NULL); | |
| 23 } | |
| 24 | |
| 25 // Sets the SetDllDirectory function pointer to activates this object. | |
| 26 void set_func(SetDllDirectoryFunc func) { func_ = func; } | |
| 27 | |
| 28 private: | |
| 29 SetDllDirectoryFunc func_; | |
| 30 }; | |
| 31 | |
| 32 } // namespace | |
| 33 | |
| 34 // static | |
| 35 const wchar_t NSSDecryptor::kNSS3Library[] = L"nss3.dll"; | |
| 36 const wchar_t NSSDecryptor::kSoftokn3Library[] = L"softokn3.dll"; | |
| 37 const wchar_t NSSDecryptor::kPLDS4Library[] = L"plds4.dll"; | |
| 38 const wchar_t NSSDecryptor::kNSPR4Library[] = L"nspr4.dll"; | |
| 39 | |
| 40 bool NSSDecryptor::Init(const base::FilePath& dll_path, | |
| 41 const base::FilePath& db_path) { | |
| 42 // We call SetDllDirectory to work around a Purify bug (GetModuleHandle | |
| 43 // fails inside Purify under certain conditions). SetDllDirectory only | |
| 44 // exists on Windows XP SP1 or later, so we look up its address at run time. | |
| 45 HMODULE kernel32_dll = GetModuleHandle(L"kernel32.dll"); | |
| 46 if (kernel32_dll == NULL) | |
| 47 return false; | |
| 48 SetDllDirectoryFunc set_dll_directory = | |
| 49 (SetDllDirectoryFunc)GetProcAddress(kernel32_dll, "SetDllDirectoryW"); | |
| 50 SetDllDirectoryCaller caller; | |
| 51 | |
| 52 if (set_dll_directory != NULL) { | |
| 53 if (!set_dll_directory(dll_path.value().c_str())) | |
| 54 return false; | |
| 55 caller.set_func(set_dll_directory); | |
| 56 nss3_dll_ = LoadLibrary(kNSS3Library); | |
| 57 if (nss3_dll_ == NULL) | |
| 58 return false; | |
| 59 } else { | |
| 60 // Fall back on LoadLibraryEx if SetDllDirectory isn't available. We | |
| 61 // actually prefer this method because it doesn't change the DLL search | |
| 62 // path, which is a process-wide property. | |
| 63 base::FilePath path = dll_path.Append(kNSS3Library); | |
| 64 nss3_dll_ = LoadLibraryEx(path.value().c_str(), NULL, | |
| 65 LOAD_WITH_ALTERED_SEARCH_PATH); | |
| 66 if (nss3_dll_ == NULL) | |
| 67 return false; | |
| 68 | |
| 69 // Firefox 2 uses NSS 3.11. Firefox 3 uses NSS 3.12. NSS 3.12 has two | |
| 70 // changes in its DLLs: | |
| 71 // 1. nss3.dll is not linked with softokn3.dll at build time, but rather | |
| 72 // loads softokn3.dll using LoadLibrary in NSS_Init. | |
| 73 // 2. softokn3.dll has a new dependency sqlite3.dll. | |
| 74 // NSS_Init's LoadLibrary call has trouble finding sqlite3.dll. To help | |
| 75 // it out, we preload softokn3.dll using LoadLibraryEx with the | |
| 76 // LOAD_WITH_ALTERED_SEARCH_PATH flag. This helps because LoadLibrary | |
| 77 // doesn't load a DLL again if it's already loaded. This workaround is | |
| 78 // harmless for NSS 3.11. | |
| 79 path = base::FilePath(dll_path).Append(kSoftokn3Library); | |
| 80 softokn3_dll_ = LoadLibraryEx(path.value().c_str(), NULL, | |
| 81 LOAD_WITH_ALTERED_SEARCH_PATH); | |
| 82 if (softokn3_dll_ == NULL) { | |
| 83 Free(); | |
| 84 return false; | |
| 85 } | |
| 86 } | |
| 87 HMODULE plds4_dll = GetModuleHandle(kPLDS4Library); | |
| 88 HMODULE nspr4_dll = GetModuleHandle(kNSPR4Library); | |
| 89 | |
| 90 return InitNSS(db_path, plds4_dll, nspr4_dll); | |
| 91 } | |
| 92 | |
| 93 NSSDecryptor::NSSDecryptor() | |
| 94 : NSS_Init(NULL), NSS_Shutdown(NULL), PK11_GetInternalKeySlot(NULL), | |
| 95 PK11_CheckUserPassword(NULL), PK11_FreeSlot(NULL), | |
| 96 PK11_Authenticate(NULL), PK11SDR_Decrypt(NULL), SECITEM_FreeItem(NULL), | |
| 97 PL_ArenaFinish(NULL), PR_Cleanup(NULL), | |
| 98 nss3_dll_(NULL), softokn3_dll_(NULL), | |
| 99 is_nss_initialized_(false) { | |
| 100 } | |
| 101 | |
| 102 NSSDecryptor::~NSSDecryptor() { | |
| 103 Free(); | |
| 104 } | |
| 105 | |
| 106 bool NSSDecryptor::InitNSS(const base::FilePath& db_path, | |
| 107 base::NativeLibrary plds4_dll, | |
| 108 base::NativeLibrary nspr4_dll) { | |
| 109 // NSPR DLLs are already loaded now. | |
| 110 if (plds4_dll == NULL || nspr4_dll == NULL) { | |
| 111 Free(); | |
| 112 return false; | |
| 113 } | |
| 114 | |
| 115 // Gets the function address. | |
| 116 NSS_Init = (NSSInitFunc) | |
| 117 base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "NSS_Init"); | |
| 118 NSS_Shutdown = (NSSShutdownFunc) | |
| 119 base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "NSS_Shutdown"); | |
| 120 PK11_GetInternalKeySlot = (PK11GetInternalKeySlotFunc) | |
| 121 base::GetFunctionPointerFromNativeLibrary(nss3_dll_, | |
| 122 "PK11_GetInternalKeySlot"); | |
| 123 PK11_FreeSlot = (PK11FreeSlotFunc) | |
| 124 base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "PK11_FreeSlot"); | |
| 125 PK11_Authenticate = (PK11AuthenticateFunc) | |
| 126 base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "PK11_Authenticate"); | |
| 127 PK11SDR_Decrypt = (PK11SDRDecryptFunc) | |
| 128 base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "PK11SDR_Decrypt"); | |
| 129 SECITEM_FreeItem = (SECITEMFreeItemFunc) | |
| 130 base::GetFunctionPointerFromNativeLibrary(nss3_dll_, "SECITEM_FreeItem"); | |
| 131 PL_ArenaFinish = (PLArenaFinishFunc) | |
| 132 base::GetFunctionPointerFromNativeLibrary(plds4_dll, "PL_ArenaFinish"); | |
| 133 PR_Cleanup = (PRCleanupFunc) | |
| 134 base::GetFunctionPointerFromNativeLibrary(nspr4_dll, "PR_Cleanup"); | |
| 135 | |
| 136 if (NSS_Init == NULL || NSS_Shutdown == NULL || | |
| 137 PK11_GetInternalKeySlot == NULL || PK11_FreeSlot == NULL || | |
| 138 PK11_Authenticate == NULL || PK11SDR_Decrypt == NULL || | |
| 139 SECITEM_FreeItem == NULL || PL_ArenaFinish == NULL || | |
| 140 PR_Cleanup == NULL) { | |
| 141 Free(); | |
| 142 return false; | |
| 143 } | |
| 144 | |
| 145 SECStatus result = NSS_Init(base::SysWideToNativeMB(db_path.value()).c_str()); | |
| 146 if (result != SECSuccess) { | |
| 147 Free(); | |
| 148 return false; | |
| 149 } | |
| 150 | |
| 151 is_nss_initialized_ = true; | |
| 152 return true; | |
| 153 } | |
| 154 | |
| 155 void NSSDecryptor::Free() { | |
| 156 if (is_nss_initialized_) { | |
| 157 NSS_Shutdown(); | |
| 158 PL_ArenaFinish(); | |
| 159 PR_Cleanup(); | |
| 160 is_nss_initialized_ = false; | |
| 161 } | |
| 162 if (softokn3_dll_ != NULL) | |
| 163 base::UnloadNativeLibrary(softokn3_dll_); | |
| 164 if (nss3_dll_ != NULL) | |
| 165 base::UnloadNativeLibrary(nss3_dll_); | |
| 166 NSS_Init = NULL; | |
| 167 NSS_Shutdown = NULL; | |
| 168 PK11_GetInternalKeySlot = NULL; | |
| 169 PK11_FreeSlot = NULL; | |
| 170 PK11_Authenticate = NULL; | |
| 171 PK11SDR_Decrypt = NULL; | |
| 172 SECITEM_FreeItem = NULL; | |
| 173 PL_ArenaFinish = NULL; | |
| 174 PR_Cleanup = NULL; | |
| 175 nss3_dll_ = NULL; | |
| 176 softokn3_dll_ = NULL; | |
| 177 } | |
| OLD | NEW |