summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-22 00:53:48 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-22 00:53:48 +0000
commita1f55c87febb264d1c89afaadf8f8631b7155fa7 (patch)
tree633e7e27a0c2c07603b1c6edb13e0eda834eec0f /chrome
parente82fafcd66be3f5c0cef28ee0c08ae4f9e0338b4 (diff)
downloadchromium_src-a1f55c87febb264d1c89afaadf8f8631b7155fa7.zip
chromium_src-a1f55c87febb264d1c89afaadf8f8631b7155fa7.tar.gz
chromium_src-a1f55c87febb264d1c89afaadf8f8631b7155fa7.tar.bz2
Split NSSDecryptor out into platform specific files.
This lets Linux not bother to initialize NSS in the same way as the rest, but instead use the NSS symbols linked into the library, thereby preventing the NSS_Shutdown related bugs. BUG=http://crbug.com/13929 TEST=Case 1: Start chrome. Use firefox import utility. Browse to some https site. Shouldn't crash. Case 2: Start chrome. Browse to some https site. Use firefox import utility. Continue browsing https sites. Shouldn't crash. Review URL: http://codereview.chromium.org/159165 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21251 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/importer/firefox2_importer.cc1
-rw-r--r--chrome/browser/importer/firefox3_importer.cc1
-rw-r--r--chrome/browser/importer/firefox_importer_unittest.cc1
-rw-r--r--chrome/browser/importer/firefox_importer_utils.cc300
-rw-r--r--chrome/browser/importer/firefox_importer_utils.h154
-rw-r--r--chrome/browser/importer/firefox_importer_utils_linux.cc20
-rw-r--r--chrome/browser/importer/firefox_importer_utils_mac.cc15
-rw-r--r--chrome/browser/importer/firefox_importer_utils_win.cc85
-rw-r--r--chrome/browser/importer/nss_decryptor.cc225
-rw-r--r--chrome/browser/importer/nss_decryptor.h18
-rw-r--r--chrome/browser/importer/nss_decryptor_linux.cc17
-rw-r--r--chrome/browser/importer/nss_decryptor_linux.h43
-rw-r--r--chrome/browser/importer/nss_decryptor_mac.h158
-rw-r--r--chrome/browser/importer/nss_decryptor_win.cc178
-rw-r--r--chrome/browser/importer/nss_decryptor_win.h168
-rw-r--r--chrome/chrome.gyp7
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',