diff options
-rw-r--r-- | chrome/browser/importer/firefox2_importer.cc | 1 | ||||
-rw-r--r-- | chrome/browser/importer/firefox3_importer.cc | 1 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_unittest.cc | 1 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils.cc | 300 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils.h | 154 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils_linux.cc | 20 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils_mac.cc | 15 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils_win.cc | 85 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor.cc | 225 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor.h | 18 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor_linux.cc | 17 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor_linux.h | 43 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor_mac.h | 158 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor_win.cc | 178 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor_win.h | 168 | ||||
-rw-r--r-- | chrome/chrome.gyp | 7 |
16 files changed, 817 insertions, 574 deletions
diff --git a/chrome/browser/importer/firefox2_importer.cc b/chrome/browser/importer/firefox2_importer.cc index 83e391e..38fe89e 100644 --- a/chrome/browser/importer/firefox2_importer.cc +++ b/chrome/browser/importer/firefox2_importer.cc @@ -14,6 +14,7 @@ #include "base/values.h" #include "chrome/browser/importer/firefox_importer_utils.h" #include "chrome/browser/importer/mork_reader.h" +#include "chrome/browser/importer/nss_decryptor.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_parser.h" #include "chrome/common/time_format.h" diff --git a/chrome/browser/importer/firefox3_importer.cc b/chrome/browser/importer/firefox3_importer.cc index cad7044..ffdf407 100644 --- a/chrome/browser/importer/firefox3_importer.cc +++ b/chrome/browser/importer/firefox3_importer.cc @@ -14,6 +14,7 @@ #include "base/string_util.h" #include "chrome/browser/importer/firefox2_importer.h" #include "chrome/browser/importer/firefox_importer_utils.h" +#include "chrome/browser/importer/nss_decryptor.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/common/time_format.h" #include "chrome/common/sqlite_utils.h" diff --git a/chrome/browser/importer/firefox_importer_unittest.cc b/chrome/browser/importer/firefox_importer_unittest.cc index ea4c37c..38d3073 100644 --- a/chrome/browser/importer/firefox_importer_unittest.cc +++ b/chrome/browser/importer/firefox_importer_unittest.cc @@ -10,6 +10,7 @@ #include "chrome/browser/importer/firefox2_importer.h" #include "chrome/browser/importer/firefox_importer_utils.h" #include "chrome/browser/importer/firefox_profile_lock.h" +#include "chrome/browser/importer/nss_decryptor.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/file_test_utils.h" diff --git a/chrome/browser/importer/firefox_importer_utils.cc b/chrome/browser/importer/firefox_importer_utils.cc index 0b2b89f..28a9365 100644 --- a/chrome/browser/importer/firefox_importer_utils.cc +++ b/chrome/browser/importer/firefox_importer_utils.cc @@ -9,16 +9,11 @@ #include "base/file_util.h" #include "base/logging.h" #include "base/string_util.h" -#include "base/sys_string_conversions.h" #include "base/values.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/search_engines/template_url_parser.h" #include "googleurl/src/gurl.h" -#include "net/base/base64.h" -#include "webkit/glue/password_form.h" - -using webkit_glue::PasswordForm; namespace { @@ -335,298 +330,3 @@ bool IsDefaultHomepage(const GURL& homepage, return false; } - -// class NSSDecryptor. - -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 std::wstring& 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).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; -} - -// This method is based on some Firefox code in -// security/manager/ssl/src/nsSDR.cpp -// The license block is: - -/* ***** BEGIN LICENSE BLOCK ***** -* Version: MPL 1.1/GPL 2.0/LGPL 2.1 -* -* The contents of this file are subject to the Mozilla Public License Version -* 1.1 (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS IS" basis, -* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -* for the specific language governing rights and limitations under the -* License. -* -* The Original Code is the Netscape security libraries. -* -* The Initial Developer of the Original Code is -* Netscape Communications Corporation. -* Portions created by the Initial Developer are Copyright (C) 1994-2000 -* the Initial Developer. All Rights Reserved. -* -* Contributor(s): -* -* Alternatively, the contents of this file may be used under the terms of -* either the GNU General Public License Version 2 or later (the "GPL"), or -* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -* in which case the provisions of the GPL or the LGPL are applicable instead -* of those above. If you wish to allow use of your version of this file only -* under the terms of either the GPL or the LGPL, and not to allow others to -* use your version of this file under the terms of the MPL, indicate your -* decision by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL or the LGPL. If you do not delete -* the provisions above, a recipient may use your version of this file under -* the terms of any one of the MPL, the GPL or the LGPL. -* -* ***** END LICENSE BLOCK ***** */ - -std::wstring NSSDecryptor::Decrypt(const std::string& crypt) const { - // Do nothing if NSS is not loaded. - if (!nss3_dll_) - return std::wstring(); - - // The old style password is encoded in base64. They are identified - // by a leading '~'. Otherwise, we should decrypt the text. - std::string plain; - if (crypt[0] != '~') { - std::string decoded_data; - net::Base64Decode(crypt, &decoded_data); - PK11SlotInfo* slot = NULL; - slot = PK11_GetInternalKeySlot(); - SECStatus result = PK11_Authenticate(slot, PR_TRUE, NULL); - if (result != SECSuccess) { - PK11_FreeSlot(slot); - return std::wstring(); - } - - SECItem request; - request.data = reinterpret_cast<unsigned char*>( - const_cast<char*>(decoded_data.data())); - request.len = static_cast<unsigned int>(decoded_data.size()); - SECItem reply; - reply.data = NULL; - reply.len = 0; - result = PK11SDR_Decrypt(&request, &reply, NULL); - if (result == SECSuccess) - plain.assign(reinterpret_cast<char*>(reply.data), reply.len); - - SECITEM_FreeItem(&reply, PR_FALSE); - PK11_FreeSlot(slot); - } else { - // Deletes the leading '~' before decoding. - net::Base64Decode(crypt.substr(1), &plain); - } - - return UTF8ToWide(plain); -} - -// There are three versions of password filess. They store saved user -// names and passwords. -// References: -// http://kb.mozillazine.org/Signons.txt -// http://kb.mozillazine.org/Signons2.txt -// http://kb.mozillazine.org/Signons3.txt -void NSSDecryptor::ParseSignons(const std::string& content, - std::vector<PasswordForm>* forms) { - forms->clear(); - - // Splits the file content into lines. - std::vector<std::string> lines; - SplitString(content, '\n', &lines); - - // The first line is the file version. We skip the unknown versions. - if (lines.empty()) - return; - int version; - if (lines[0] == "#2c") - version = 1; - else if (lines[0] == "#2d") - version = 2; - else if (lines[0] == "#2e") - version = 3; - else - return; - - GURL::Replacements rep; - rep.ClearQuery(); - rep.ClearRef(); - rep.ClearUsername(); - rep.ClearPassword(); - - // Reads never-saved list. Domains are stored one per line. - size_t i; - for (i = 1; i < lines.size() && lines[i].compare(".") != 0; ++i) { - PasswordForm form; - form.origin = GURL(lines[i]).ReplaceComponents(rep); - form.signon_realm = form.origin.GetOrigin().spec(); - form.blacklisted_by_user = true; - forms->push_back(form); - } - ++i; - - // Reads saved passwords. The information is stored in blocks - // seperated by lines that only contain a dot. We find a block - // by the seperator and parse them one by one. - while (i < lines.size()) { - size_t begin = i; - size_t end = i + 1; - while (end < lines.size() && lines[end].compare(".") != 0) - ++end; - i = end + 1; - - // A block has at least five lines. - if (end - begin < 5) - continue; - - PasswordForm form; - - // The first line is the site URL. - // For HTTP authentication logins, the URL may contain http realm, - // which will be in bracket: - // sitename:8080 (realm) - GURL url; - std::string realm; - const char kRealmBracketBegin[] = " ("; - const char kRealmBracketEnd[] = ")"; - if (lines[begin].find(kRealmBracketBegin) != std::string::npos) { - // In this case, the scheme may not exsit. We assume that the - // scheme is HTTP. - if (lines[begin].find("://") == std::string::npos) - lines[begin] = "http://" + lines[begin]; - - size_t start = lines[begin].find(kRealmBracketBegin); - url = GURL(lines[begin].substr(0, start)); - - start += std::string(kRealmBracketBegin).size(); - size_t end = lines[begin].rfind(kRealmBracketEnd); - realm = lines[begin].substr(start, end - start); - } else { - // Don't have http realm. It is the URL that the following passwords - // belong to. - url = GURL(lines[begin]); - } - // Skips this block if the URL is not valid. - if (!url.is_valid()) - continue; - form.origin = url.ReplaceComponents(rep); - form.signon_realm = form.origin.GetOrigin().spec(); - if (!realm.empty()) - form.signon_realm += realm; - form.ssl_valid = form.origin.SchemeIsSecure(); - ++begin; - - // There may be multiple username/password pairs for this site. - // In this case, they are saved in one block without a seperated - // line (contains a dot). - while (begin + 4 < end) { - // The user name. - form.username_element = UTF8ToWide(lines[begin++]); - form.username_value = Decrypt(lines[begin++]); - // The element name has a leading '*'. - if (lines[begin].at(0) == '*') { - form.password_element = UTF8ToWide(lines[begin++].substr(1)); - form.password_value = Decrypt(lines[begin++]); - } else { - // Maybe the file is bad, we skip to next block. - break; - } - // The action attribute from the form element. This line exists - // in versin 2 or above. - if (version >= 2) { - if (begin < end) - form.action = GURL(lines[begin]).ReplaceComponents(rep); - ++begin; - } - // Version 3 has an extra line for further use. - if (version == 3) { - ++begin; - } - - forms->push_back(form); - } - } -} diff --git a/chrome/browser/importer/firefox_importer_utils.h b/chrome/browser/importer/firefox_importer_utils.h index 21fb43d..41b88fa 100644 --- a/chrome/browser/importer/firefox_importer_utils.h +++ b/chrome/browser/importer/firefox_importer_utils.h @@ -9,17 +9,12 @@ #include "base/basictypes.h" #include "base/file_path.h" -#include "base/native_library.h" #include "build/build_config.h" class DictionaryValue; class GURL; class TemplateURL; -namespace webkit_glue { -struct PasswordForm; -} - #if defined(OS_WIN) // Detects which version of Firefox is installed from registry. Returns its // major version, and drops the minor version. Returns 0 if @@ -79,154 +74,5 @@ GURL GetHomepage(const std::wstring& profile_path); // directory. bool IsDefaultHomepage(const GURL& homepage, const std::wstring& app_path); -// The following declarations of functions and types are from Firefox -// NSS library. -// source code: -// security/nss/lib/util/seccomon.h -// security/nss/lib/nss/nss.h -// The license block is: - -/* ***** BEGIN LICENSE BLOCK ***** -* Version: MPL 1.1/GPL 2.0/LGPL 2.1 -* -* The contents of this file are subject to the Mozilla Public License Version -* 1.1 (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS IS" basis, -* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -* for the specific language governing rights and limitations under the -* License. -* -* The Original Code is the Netscape security libraries. -* -* The Initial Developer of the Original Code is -* Netscape Communications Corporation. -* Portions created by the Initial Developer are Copyright (C) 1994-2000 -* the Initial Developer. All Rights Reserved. -* -* Contributor(s): -* -* Alternatively, the contents of this file may be used under the terms of -* either the GNU General Public License Version 2 or later (the "GPL"), or -* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -* in which case the provisions of the GPL or the LGPL are applicable instead -* of those above. If you wish to allow use of your version of this file only -* under the terms of either the GPL or the LGPL, and not to allow others to -* use your version of this file under the terms of the MPL, indicate your -* decision by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL or the LGPL. If you do not delete -* the provisions above, a recipient may use your version of this file under -* the terms of any one of the MPL, the GPL or the LGPL. -* -* ***** END LICENSE BLOCK ***** */ - -enum SECItemType { - siBuffer = 0, - siClearDataBuffer = 1, - siCipherDataBuffer = 2, - siDERCertBuffer = 3, - siEncodedCertBuffer = 4, - siDERNameBuffer = 5, - siEncodedNameBuffer = 6, - siAsciiNameString = 7, - siAsciiString = 8, - siDEROID = 9, - siUnsignedInteger = 10, - siUTCTime = 11, - siGeneralizedTime = 12 -}; - -struct SECItem { - SECItemType type; - unsigned char *data; - unsigned int len; -}; - -enum SECStatus { - SECWouldBlock = -2, - SECFailure = -1, - SECSuccess = 0 -}; - -typedef int PRBool; -#define PR_TRUE 1 -#define PR_FALSE 0 - -typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; - -typedef struct PK11SlotInfoStr PK11SlotInfo; - -typedef SECStatus (*NSSInitFunc)(const char *configdir); -typedef SECStatus (*NSSShutdownFunc)(void); -typedef PK11SlotInfo* (*PK11GetInternalKeySlotFunc)(void); -typedef void (*PK11FreeSlotFunc)(PK11SlotInfo *slot); -typedef SECStatus (*PK11CheckUserPasswordFunc)(PK11SlotInfo *slot, char *pw); -typedef SECStatus - (*PK11AuthenticateFunc)(PK11SlotInfo *slot, PRBool loadCerts, void *wincx); -typedef SECStatus - (*PK11SDRDecryptFunc)(SECItem *data, SECItem *result, void *cx); -typedef void (*SECITEMFreeItemFunc)(SECItem *item, PRBool free_it); -typedef void (*PLArenaFinishFunc)(void); -typedef PRStatus (*PRCleanupFunc)(void); - -// A wrapper for Firefox NSS decrypt component. -class NSSDecryptor { - public: - NSSDecryptor(); - ~NSSDecryptor(); - - // Loads NSS3 library and returns true if successful. - // |dll_path| indicates the location of NSS3 DLL files, and |db_path| - // is the location of the database file that stores the keys. - bool Init(const std::wstring& dll_path, const std::wstring& db_path); - - // Frees the libraries. - void Free(); - - // Decrypts Firefox stored passwords. Before using this method, - // make sure Init() returns true. - std::wstring Decrypt(const std::string& crypt) const; - - // Parses the Firefox password file content, decrypts the - // username/password and reads other related information. - // The result will be stored in |forms|. - void ParseSignons(const std::string& content, - std::vector<webkit_glue::PasswordForm>* forms); - - private: - // Performs tasks common across all platforms to initialize NSS. - bool InitNSS(const std::wstring& db_path, - base::NativeLibrary plds4_dll, - base::NativeLibrary nspr4_dll); - - // Methods in Firefox security components. - NSSInitFunc NSS_Init; - NSSShutdownFunc NSS_Shutdown; - PK11GetInternalKeySlotFunc PK11_GetInternalKeySlot; - PK11CheckUserPasswordFunc PK11_CheckUserPassword; - PK11FreeSlotFunc PK11_FreeSlot; - PK11AuthenticateFunc PK11_Authenticate; - PK11SDRDecryptFunc PK11SDR_Decrypt; - SECITEMFreeItemFunc SECITEM_FreeItem; - PLArenaFinishFunc PL_ArenaFinish; - PRCleanupFunc PR_Cleanup; - - // Libraries necessary for decrypting the passwords. - static const wchar_t kNSS3Library[]; - static const wchar_t kSoftokn3Library[]; - static const wchar_t kPLDS4Library[]; - static const wchar_t kNSPR4Library[]; - - // NSS3 module handles. - base::NativeLibrary nss3_dll_; - base::NativeLibrary softokn3_dll_; - - // True if NSS_Init() has been called - bool is_nss_initialized_; - - DISALLOW_COPY_AND_ASSIGN(NSSDecryptor); -}; #endif // CHROME_BROWSER_IMPORTER_FIREFOX_IMPORTER_UTILS_H_ diff --git a/chrome/browser/importer/firefox_importer_utils_linux.cc b/chrome/browser/importer/firefox_importer_utils_linux.cc index 3dff06c..cb815dc 100644 --- a/chrome/browser/importer/firefox_importer_utils_linux.cc +++ b/chrome/browser/importer/firefox_importer_utils_linux.cc @@ -19,23 +19,3 @@ FilePath GetProfilesINI() { return FilePath(); } - -// static -const wchar_t NSSDecryptor::kNSS3Library[] = L"libnss3.so"; -const wchar_t NSSDecryptor::kSoftokn3Library[] = L"libsoftokn3.so"; -const wchar_t NSSDecryptor::kPLDS4Library[] = L"libplds4.so"; -const wchar_t NSSDecryptor::kNSPR4Library[] = L"libnspr4.so"; - -bool NSSDecryptor::Init(const std::wstring& dll_path, - const std::wstring& db_path) { - nss3_dll_ = base::LoadNativeLibrary( - FilePath::FromWStringHack(kNSS3Library)); - if (nss3_dll_ == NULL) - return false; - base::NativeLibrary plds4_lib = base::LoadNativeLibrary( - FilePath::FromWStringHack(kPLDS4Library)); - base::NativeLibrary nspr4_lib = base::LoadNativeLibrary( - FilePath::FromWStringHack(kNSPR4Library)); - - return InitNSS(db_path, plds4_lib, nspr4_lib); -} diff --git a/chrome/browser/importer/firefox_importer_utils_mac.cc b/chrome/browser/importer/firefox_importer_utils_mac.cc index 7b510ac..26a4f4b 100644 --- a/chrome/browser/importer/firefox_importer_utils_mac.cc +++ b/chrome/browser/importer/firefox_importer_utils_mac.cc @@ -5,7 +5,6 @@ #include "chrome/browser/importer/firefox_importer_utils.h" #include "base/file_util.h" -#include "base/logging.h" FilePath GetProfilesINI() { FilePath ini_file; @@ -22,17 +21,3 @@ FilePath GetProfilesINI() { return FilePath(); } - -// static -const wchar_t NSSDecryptor::kNSS3Library[] = L"libnss3.dylib"; -const wchar_t NSSDecryptor::kSoftokn3Library[] = L"libsoftokn3.dylib"; -const wchar_t NSSDecryptor::kPLDS4Library[] = L"libplds4.dylib"; -const wchar_t NSSDecryptor::kNSPR4Library[] = L"libnspr4.dylib"; - -bool NSSDecryptor::Init(const std::wstring& dll_path, - const std::wstring& db_path) { - // TODO(port): Load the NSS libraries and call InitNSS() - // http://code.google.com/p/chromium/issues/detail?id=15455 - NOTIMPLEMENTED(); - return false; -} diff --git a/chrome/browser/importer/firefox_importer_utils_win.cc b/chrome/browser/importer/firefox_importer_utils_win.cc index cb09aa1..370ec68 100644 --- a/chrome/browser/importer/firefox_importer_utils_win.cc +++ b/chrome/browser/importer/firefox_importer_utils_win.cc @@ -9,30 +9,6 @@ #include "base/file_util.h" #include "base/registry.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 - // NOTE: Keep these in order since we need test all those paths according // to priority. For example. One machine has multiple users. One non-admin // user installs Firefox 2, which causes there is a Firefox2 entry under HKCU. @@ -95,64 +71,3 @@ FilePath GetProfilesINI() { return FilePath(); } - -// 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 std::wstring& dll_path, - const std::wstring& 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.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. - std::wstring path = dll_path; - file_util::AppendToPath(&path, kNSS3Library); - nss3_dll_ = LoadLibraryEx(path.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 = dll_path; - file_util::AppendToPath(&path, kSoftokn3Library); - softokn3_dll_ = LoadLibraryEx(path.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); -} diff --git a/chrome/browser/importer/nss_decryptor.cc b/chrome/browser/importer/nss_decryptor.cc new file mode 100644 index 0000000..85c2ffc --- /dev/null +++ b/chrome/browser/importer/nss_decryptor.cc @@ -0,0 +1,225 @@ +// Copyright (c) 2009 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/importer/nss_decryptor.h" + +#include "build/build_config.h" + +#if defined(OS_LINUX) +#include <pk11pub.h> +#include <pk11sdr.h> +#endif // defined(OS_LINUX) + +#include "base/string_util.h" +#include "net/base/base64.h" +#include "webkit/glue/password_form.h" + +using webkit_glue::PasswordForm; + +// This method is based on some Firefox code in +// security/manager/ssl/src/nsSDR.cpp +// The license block is: + +/* ***** BEGIN LICENSE BLOCK ***** +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License Version +* 1.1 (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +* for the specific language governing rights and limitations under the +* License. +* +* The Original Code is the Netscape security libraries. +* +* The Initial Developer of the Original Code is +* Netscape Communications Corporation. +* Portions created by the Initial Developer are Copyright (C) 1994-2000 +* the Initial Developer. All Rights Reserved. +* +* Contributor(s): +* +* Alternatively, the contents of this file may be used under the terms of +* either the GNU General Public License Version 2 or later (the "GPL"), or +* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +* in which case the provisions of the GPL or the LGPL are applicable instead +* of those above. If you wish to allow use of your version of this file only +* under the terms of either the GPL or the LGPL, and not to allow others to +* use your version of this file under the terms of the MPL, indicate your +* decision by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL or the LGPL. If you do not delete +* the provisions above, a recipient may use your version of this file under +* the terms of any one of the MPL, the GPL or the LGPL. +* +* ***** END LICENSE BLOCK ***** */ + +std::wstring NSSDecryptor::Decrypt(const std::string& crypt) const { + // Do nothing if NSS is not loaded. + if (!is_nss_initialized_) + return std::wstring(); + + // The old style password is encoded in base64. They are identified + // by a leading '~'. Otherwise, we should decrypt the text. + std::string plain; + if (crypt[0] != '~') { + std::string decoded_data; + net::Base64Decode(crypt, &decoded_data); + PK11SlotInfo* slot = NULL; + slot = PK11_GetInternalKeySlot(); + SECStatus result = PK11_Authenticate(slot, PR_TRUE, NULL); + if (result != SECSuccess) { + PK11_FreeSlot(slot); + return std::wstring(); + } + + SECItem request; + request.data = reinterpret_cast<unsigned char*>( + const_cast<char*>(decoded_data.data())); + request.len = static_cast<unsigned int>(decoded_data.size()); + SECItem reply; + reply.data = NULL; + reply.len = 0; + result = PK11SDR_Decrypt(&request, &reply, NULL); + if (result == SECSuccess) + plain.assign(reinterpret_cast<char*>(reply.data), reply.len); + + SECITEM_FreeItem(&reply, PR_FALSE); + PK11_FreeSlot(slot); + } else { + // Deletes the leading '~' before decoding. + net::Base64Decode(crypt.substr(1), &plain); + } + + return UTF8ToWide(plain); +} + +// There are three versions of password filess. They store saved user +// names and passwords. +// References: +// http://kb.mozillazine.org/Signons.txt +// http://kb.mozillazine.org/Signons2.txt +// http://kb.mozillazine.org/Signons3.txt +void NSSDecryptor::ParseSignons(const std::string& content, + std::vector<PasswordForm>* forms) { + forms->clear(); + + // Splits the file content into lines. + std::vector<std::string> lines; + SplitString(content, '\n', &lines); + + // The first line is the file version. We skip the unknown versions. + if (lines.empty()) + return; + int version; + if (lines[0] == "#2c") + version = 1; + else if (lines[0] == "#2d") + version = 2; + else if (lines[0] == "#2e") + version = 3; + else + return; + + GURL::Replacements rep; + rep.ClearQuery(); + rep.ClearRef(); + rep.ClearUsername(); + rep.ClearPassword(); + + // Reads never-saved list. Domains are stored one per line. + size_t i; + for (i = 1; i < lines.size() && lines[i].compare(".") != 0; ++i) { + PasswordForm form; + form.origin = GURL(lines[i]).ReplaceComponents(rep); + form.signon_realm = form.origin.GetOrigin().spec(); + form.blacklisted_by_user = true; + forms->push_back(form); + } + ++i; + + // Reads saved passwords. The information is stored in blocks + // seperated by lines that only contain a dot. We find a block + // by the seperator and parse them one by one. + while (i < lines.size()) { + size_t begin = i; + size_t end = i + 1; + while (end < lines.size() && lines[end].compare(".") != 0) + ++end; + i = end + 1; + + // A block has at least five lines. + if (end - begin < 5) + continue; + + PasswordForm form; + + // The first line is the site URL. + // For HTTP authentication logins, the URL may contain http realm, + // which will be in bracket: + // sitename:8080 (realm) + GURL url; + std::string realm; + const char kRealmBracketBegin[] = " ("; + const char kRealmBracketEnd[] = ")"; + if (lines[begin].find(kRealmBracketBegin) != std::string::npos) { + // In this case, the scheme may not exsit. We assume that the + // scheme is HTTP. + if (lines[begin].find("://") == std::string::npos) + lines[begin] = "http://" + lines[begin]; + + size_t start = lines[begin].find(kRealmBracketBegin); + url = GURL(lines[begin].substr(0, start)); + + start += std::string(kRealmBracketBegin).size(); + size_t end = lines[begin].rfind(kRealmBracketEnd); + realm = lines[begin].substr(start, end - start); + } else { + // Don't have http realm. It is the URL that the following passwords + // belong to. + url = GURL(lines[begin]); + } + // Skips this block if the URL is not valid. + if (!url.is_valid()) + continue; + form.origin = url.ReplaceComponents(rep); + form.signon_realm = form.origin.GetOrigin().spec(); + if (!realm.empty()) + form.signon_realm += realm; + form.ssl_valid = form.origin.SchemeIsSecure(); + ++begin; + + // There may be multiple username/password pairs for this site. + // In this case, they are saved in one block without a seperated + // line (contains a dot). + while (begin + 4 < end) { + // The user name. + form.username_element = UTF8ToWide(lines[begin++]); + form.username_value = Decrypt(lines[begin++]); + // The element name has a leading '*'. + if (lines[begin].at(0) == '*') { + form.password_element = UTF8ToWide(lines[begin++].substr(1)); + form.password_value = Decrypt(lines[begin++]); + } else { + // Maybe the file is bad, we skip to next block. + break; + } + // The action attribute from the form element. This line exists + // in versin 2 or above. + if (version >= 2) { + if (begin < end) + form.action = GURL(lines[begin]).ReplaceComponents(rep); + ++begin; + } + // Version 3 has an extra line for further use. + if (version == 3) { + ++begin; + } + + forms->push_back(form); + } + } +} diff --git a/chrome/browser/importer/nss_decryptor.h b/chrome/browser/importer/nss_decryptor.h new file mode 100644 index 0000000..d2ef391 --- /dev/null +++ b/chrome/browser/importer/nss_decryptor.h @@ -0,0 +1,18 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_H_ +#define CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_H_ + +#include "build/build_config.h" + +#if defined(OS_LINUX) +#include "chrome/browser/importer/nss_decryptor_linux.h" +#elif defined(OS_MACOSX) +#include "chrome/browser/importer/nss_decryptor_mac.h" +#elif defined(OS_WIN) +#include "chrome/browser/importer/nss_decryptor_win.h" +#endif + +#endif // CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_H_ diff --git a/chrome/browser/importer/nss_decryptor_linux.cc b/chrome/browser/importer/nss_decryptor_linux.cc new file mode 100644 index 0000000..cde9e57 --- /dev/null +++ b/chrome/browser/importer/nss_decryptor_linux.cc @@ -0,0 +1,17 @@ +// Copyright (c) 2009 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/importer/nss_decryptor_linux.h" + +#include "base/nss_init.h" + +NSSDecryptor::NSSDecryptor() : is_nss_initialized_(false) {} +NSSDecryptor::~NSSDecryptor() {} + +bool NSSDecryptor::Init(const std::wstring& /* dll_path */, + const std::wstring& /* db_path */) { + base::EnsureNSSInit(); + is_nss_initialized_ = true; + return true; +} diff --git a/chrome/browser/importer/nss_decryptor_linux.h b/chrome/browser/importer/nss_decryptor_linux.h new file mode 100644 index 0000000..6a9b7ca --- /dev/null +++ b/chrome/browser/importer/nss_decryptor_linux.h @@ -0,0 +1,43 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_LINUX_H_ +#define CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_LINUX_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" + +namespace webkit_glue { +struct PasswordForm; +} + +// A wrapper for Firefox NSS decrypt component. +class NSSDecryptor { + public: + NSSDecryptor(); + ~NSSDecryptor(); + + // Initializes NSS if it hasn't already been initialized. + bool Init(const std::wstring& /* dll_path */, + const std::wstring& /* db_path */); + + // Decrypts Firefox stored passwords. Before using this method, + // make sure Init() returns true. + std::wstring Decrypt(const std::string& crypt) const; + + // Parses the Firefox password file content, decrypts the + // username/password and reads other related information. + // The result will be stored in |forms|. + void ParseSignons(const std::string& content, + std::vector<webkit_glue::PasswordForm>* forms); + + private: + bool is_nss_initialized_; + + DISALLOW_COPY_AND_ASSIGN(NSSDecryptor); +}; + +#endif // CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_LINUX_H_ diff --git a/chrome/browser/importer/nss_decryptor_mac.h b/chrome/browser/importer/nss_decryptor_mac.h new file mode 100644 index 0000000..babf1d0 --- /dev/null +++ b/chrome/browser/importer/nss_decryptor_mac.h @@ -0,0 +1,158 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_MAC_H_ +#define CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_MAC_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/logging.h" + +// The following declarations of functions and types are from Firefox +// NSS library. +// source code: +// security/nss/lib/util/seccomon.h +// security/nss/lib/nss/nss.h +// The license block is: + +/* ***** BEGIN LICENSE BLOCK ***** +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License Version +* 1.1 (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +* for the specific language governing rights and limitations under the +* License. +* +* The Original Code is the Netscape security libraries. +* +* The Initial Developer of the Original Code is +* Netscape Communications Corporation. +* Portions created by the Initial Developer are Copyright (C) 1994-2000 +* the Initial Developer. All Rights Reserved. +* +* Contributor(s): +* +* Alternatively, the contents of this file may be used under the terms of +* either the GNU General Public License Version 2 or later (the "GPL"), or +* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +* in which case the provisions of the GPL or the LGPL are applicable instead +* of those above. If you wish to allow use of your version of this file only +* under the terms of either the GPL or the LGPL, and not to allow others to +* use your version of this file under the terms of the MPL, indicate your +* decision by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL or the LGPL. If you do not delete +* the provisions above, a recipient may use your version of this file under +* the terms of any one of the MPL, the GPL or the LGPL. +* +* ***** END LICENSE BLOCK ***** */ + +enum SECItemType { + siBuffer = 0, + siClearDataBuffer = 1, + siCipherDataBuffer = 2, + siDERCertBuffer = 3, + siEncodedCertBuffer = 4, + siDERNameBuffer = 5, + siEncodedNameBuffer = 6, + siAsciiNameString = 7, + siAsciiString = 8, + siDEROID = 9, + siUnsignedInteger = 10, + siUTCTime = 11, + siGeneralizedTime = 12 +}; + +struct SECItem { + SECItemType type; + unsigned char *data; + unsigned int len; +}; + +enum SECStatus { + SECWouldBlock = -2, + SECFailure = -1, + SECSuccess = 0 +}; + +typedef int PRBool; +#define PR_TRUE 1 +#define PR_FALSE 0 + +typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; + +typedef struct PK11SlotInfoStr PK11SlotInfo; + +typedef SECStatus (*NSSInitFunc)(const char *configdir); +typedef SECStatus (*NSSShutdownFunc)(void); +typedef PK11SlotInfo* (*PK11GetInternalKeySlotFunc)(void); +typedef void (*PK11FreeSlotFunc)(PK11SlotInfo *slot); +typedef SECStatus (*PK11CheckUserPasswordFunc)(PK11SlotInfo *slot, char *pw); +typedef SECStatus + (*PK11AuthenticateFunc)(PK11SlotInfo *slot, PRBool loadCerts, void *wincx); +typedef SECStatus + (*PK11SDRDecryptFunc)(SECItem *data, SECItem *result, void *cx); +typedef void (*SECITEMFreeItemFunc)(SECItem *item, PRBool free_it); +typedef void (*PLArenaFinishFunc)(void); +typedef PRStatus (*PRCleanupFunc)(void); +namespace webkit_glue { +struct PasswordForm; +} + +// A wrapper for Firefox NSS decrypt component. +class NSSDecryptor { + public: + 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), + is_nss_initialized_(false) {} + ~NSSDecryptor() {} + + // Initializes NSS if it hasn't already been initialized. + bool Init(const std::wstring& /* dll_path */, + const std::wstring& /* db_path */) { + // TODO(port): Load the NSS libraries and call InitNSS() + // http://code.google.com/p/chromium/issues/detail?id=15455 + NOTIMPLEMENTED(); + return false; + } + + // Decrypts Firefox stored passwords. Before using this method, + // make sure Init() returns true. + std::wstring Decrypt(const std::string& crypt) const; + + // Parses the Firefox password file content, decrypts the + // username/password and reads other related information. + // The result will be stored in |forms|. + void ParseSignons(const std::string& content, + std::vector<webkit_glue::PasswordForm>* forms); + + private: + // Methods in Firefox security components. + NSSInitFunc NSS_Init; + NSSShutdownFunc NSS_Shutdown; + PK11GetInternalKeySlotFunc PK11_GetInternalKeySlot; + PK11CheckUserPasswordFunc PK11_CheckUserPassword; + PK11FreeSlotFunc PK11_FreeSlot; + PK11AuthenticateFunc PK11_Authenticate; + PK11SDRDecryptFunc PK11SDR_Decrypt; + SECITEMFreeItemFunc SECITEM_FreeItem; + PLArenaFinishFunc PL_ArenaFinish; + PRCleanupFunc PR_Cleanup; + + // True if NSS_Init() has been called + bool is_nss_initialized_; + + DISALLOW_COPY_AND_ASSIGN(NSSDecryptor); +}; + +#endif // CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_MAC_H_ diff --git a/chrome/browser/importer/nss_decryptor_win.cc b/chrome/browser/importer/nss_decryptor_win.cc new file mode 100644 index 0000000..a662abb --- /dev/null +++ b/chrome/browser/importer/nss_decryptor_win.cc @@ -0,0 +1,178 @@ +// Copyright (c) 2009 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/importer/nss_decryptor_win.h" +#include "base/file_util.h" +#include "base/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 std::wstring& dll_path, + const std::wstring& 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.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. + std::wstring path = dll_path; + file_util::AppendToPath(&path, kNSS3Library); + nss3_dll_ = LoadLibraryEx(path.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 = dll_path; + file_util::AppendToPath(&path, kSoftokn3Library); + softokn3_dll_ = LoadLibraryEx(path.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 std::wstring& 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).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; +} diff --git a/chrome/browser/importer/nss_decryptor_win.h b/chrome/browser/importer/nss_decryptor_win.h new file mode 100644 index 0000000..861c55c --- /dev/null +++ b/chrome/browser/importer/nss_decryptor_win.h @@ -0,0 +1,168 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_WIN_H_ +#define CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_WIN_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/native_library.h" + +// The following declarations of functions and types are from Firefox +// NSS library. +// source code: +// security/nss/lib/util/seccomon.h +// security/nss/lib/nss/nss.h +// The license block is: + +/* ***** BEGIN LICENSE BLOCK ***** +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License Version +* 1.1 (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +* for the specific language governing rights and limitations under the +* License. +* +* The Original Code is the Netscape security libraries. +* +* The Initial Developer of the Original Code is +* Netscape Communications Corporation. +* Portions created by the Initial Developer are Copyright (C) 1994-2000 +* the Initial Developer. All Rights Reserved. +* +* Contributor(s): +* +* Alternatively, the contents of this file may be used under the terms of +* either the GNU General Public License Version 2 or later (the "GPL"), or +* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +* in which case the provisions of the GPL or the LGPL are applicable instead +* of those above. If you wish to allow use of your version of this file only +* under the terms of either the GPL or the LGPL, and not to allow others to +* use your version of this file under the terms of the MPL, indicate your +* decision by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL or the LGPL. If you do not delete +* the provisions above, a recipient may use your version of this file under +* the terms of any one of the MPL, the GPL or the LGPL. +* +* ***** END LICENSE BLOCK ***** */ + +enum SECItemType { + siBuffer = 0, + siClearDataBuffer = 1, + siCipherDataBuffer = 2, + siDERCertBuffer = 3, + siEncodedCertBuffer = 4, + siDERNameBuffer = 5, + siEncodedNameBuffer = 6, + siAsciiNameString = 7, + siAsciiString = 8, + siDEROID = 9, + siUnsignedInteger = 10, + siUTCTime = 11, + siGeneralizedTime = 12 +}; + +struct SECItem { + SECItemType type; + unsigned char *data; + unsigned int len; +}; + +enum SECStatus { + SECWouldBlock = -2, + SECFailure = -1, + SECSuccess = 0 +}; + +typedef int PRBool; +#define PR_TRUE 1 +#define PR_FALSE 0 + +typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; + +typedef struct PK11SlotInfoStr PK11SlotInfo; + +typedef SECStatus (*NSSInitFunc)(const char *configdir); +typedef SECStatus (*NSSShutdownFunc)(void); +typedef PK11SlotInfo* (*PK11GetInternalKeySlotFunc)(void); +typedef void (*PK11FreeSlotFunc)(PK11SlotInfo *slot); +typedef SECStatus (*PK11CheckUserPasswordFunc)(PK11SlotInfo *slot, char *pw); +typedef SECStatus + (*PK11AuthenticateFunc)(PK11SlotInfo *slot, PRBool loadCerts, void *wincx); +typedef SECStatus + (*PK11SDRDecryptFunc)(SECItem *data, SECItem *result, void *cx); +typedef void (*SECITEMFreeItemFunc)(SECItem *item, PRBool free_it); +typedef void (*PLArenaFinishFunc)(void); +typedef PRStatus (*PRCleanupFunc)(void); + +namespace webkit_glue { +struct PasswordForm; +} + +// A wrapper for Firefox NSS decrypt component. +class NSSDecryptor { + public: + NSSDecryptor(); + ~NSSDecryptor(); + + // Loads NSS3 library and returns true if successful. + // |dll_path| indicates the location of NSS3 DLL files, and |db_path| + // is the location of the database file that stores the keys. + bool Init(const std::wstring& dll_path, const std::wstring& db_path); + + // Frees the libraries. + void Free(); + + // Decrypts Firefox stored passwords. Before using this method, + // make sure Init() returns true. + std::wstring Decrypt(const std::string& crypt) const; + + // Parses the Firefox password file content, decrypts the + // username/password and reads other related information. + // The result will be stored in |forms|. + void ParseSignons(const std::string& content, + std::vector<webkit_glue::PasswordForm>* forms); + + private: + // Performs tasks common across all platforms to initialize NSS. + bool InitNSS(const std::wstring& db_path, + base::NativeLibrary plds4_dll, + base::NativeLibrary nspr4_dll); + + // Methods in Firefox security components. + NSSInitFunc NSS_Init; + NSSShutdownFunc NSS_Shutdown; + PK11GetInternalKeySlotFunc PK11_GetInternalKeySlot; + PK11CheckUserPasswordFunc PK11_CheckUserPassword; + PK11FreeSlotFunc PK11_FreeSlot; + PK11AuthenticateFunc PK11_Authenticate; + PK11SDRDecryptFunc PK11SDR_Decrypt; + SECITEMFreeItemFunc SECITEM_FreeItem; + PLArenaFinishFunc PL_ArenaFinish; + PRCleanupFunc PR_Cleanup; + + // Libraries necessary for decrypting the passwords. + static const wchar_t kNSS3Library[]; + static const wchar_t kSoftokn3Library[]; + static const wchar_t kPLDS4Library[]; + static const wchar_t kNSPR4Library[]; + + // NSS3 module handles. + base::NativeLibrary nss3_dll_; + base::NativeLibrary softokn3_dll_; + + // True if NSS_Init() has been called + bool is_nss_initialized_; + + DISALLOW_COPY_AND_ASSIGN(NSSDecryptor); +}; + +#endif // CHROME_BROWSER_IMPORTER_NSS_DECRYPTOR_WIN_H_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 04df059..7d227aa 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1227,6 +1227,13 @@ 'browser/importer/importer.h', 'browser/importer/mork_reader.cc', 'browser/importer/mork_reader.h', + 'browser/importer/nss_decryptor.cc', + 'browser/importer/nss_decryptor.h', + 'browser/importer/nss_decryptor_linux.cc', + 'browser/importer/nss_decryptor_linux.h', + 'browser/importer/nss_decryptor_mac.h', + 'browser/importer/nss_decryptor_win.cc', + 'browser/importer/nss_decryptor_win.h', 'browser/importer/toolbar_importer.cc', 'browser/importer/toolbar_importer.h', 'browser/in_process_webkit/browser_webkitclient_impl.cc', |