| Index: base/nss_util.cc
|
| ===================================================================
|
| --- base/nss_util.cc (revision 52342)
|
| +++ base/nss_util.cc (working copy)
|
| @@ -13,39 +13,41 @@
|
| #include <pk11pub.h>
|
| #include <secmod.h>
|
|
|
| +#if defined(OS_LINUX)
|
| +#include <linux/magic.h>
|
| +#include <sys/vfs.h>
|
| +#endif
|
| +
|
| #include "base/file_util.h"
|
| #include "base/logging.h"
|
| #include "base/singleton.h"
|
| #include "base/string_util.h"
|
|
|
| +// USE_NSS means we use NSS for everything crypto-related. If USE_NSS is not
|
| +// defined, such as on Mac and Windows, we use NSS for SSL only -- we don't
|
| +// use NSS for crypto or certificate verification, and we don't use the NSS
|
| +// certificate and key databases.
|
| #if defined(USE_NSS)
|
| +#include "base/env_var.h"
|
| #include "base/lock.h"
|
| #include "base/scoped_ptr.h"
|
| -#endif // defined(USE_NSS)
|
| +#endif // defined(USE_NSS)
|
|
|
| -// On some platforms, we use NSS for SSL only -- we don't use NSS for crypto
|
| -// or certificate verification, and we don't use the NSS certificate and key
|
| -// databases.
|
| -#if defined(OS_MACOSX) || defined(OS_WIN)
|
| -#define USE_NSS_FOR_SSL_ONLY 1
|
| -#endif
|
| -
|
| namespace {
|
|
|
| -#if !defined(USE_NSS_FOR_SSL_ONLY)
|
| -std::string GetDefaultConfigDirectory() {
|
| - FilePath home = file_util::GetHomeDir();
|
| - if (home.empty()) {
|
| - LOG(ERROR) << "$HOME is not set.";
|
| - return std::string();
|
| +#if defined(USE_NSS)
|
| +FilePath GetDefaultConfigDirectory() {
|
| + FilePath dir = file_util::GetHomeDir();
|
| + if (dir.empty()) {
|
| + LOG(ERROR) << "Failed to get home directory.";
|
| + return dir;
|
| }
|
| - FilePath dir(home);
|
| dir = dir.AppendASCII(".pki").AppendASCII("nssdb");
|
| if (!file_util::CreateDirectory(dir)) {
|
| LOG(ERROR) << "Failed to create ~/.pki/nssdb directory.";
|
| - return std::string();
|
| + dir.clear();
|
| }
|
| - return dir.value();
|
| + return dir;
|
| }
|
|
|
| // On non-chromeos platforms, return the default config directory.
|
| @@ -54,15 +56,39 @@
|
| // by the local Google Accounts server mock we use when testing our login code.
|
| // If this directory is not present, NSS_Init() will fail. It is up to the
|
| // caller to failover to NSS_NoDB_Init() at that point.
|
| -std::string GetInitialConfigDirectory() {
|
| +FilePath GetInitialConfigDirectory() {
|
| #if defined(OS_CHROMEOS)
|
| - static const char kReadOnlyCertDB[] = "/etc/fake_root_ca/nssdb";
|
| - return std::string(kReadOnlyCertDB);
|
| + static const FilePath::CharType kReadOnlyCertDB[] =
|
| + FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb");
|
| + return FilePath(kReadOnlyCertDB);
|
| #else
|
| return GetDefaultConfigDirectory();
|
| #endif // defined(OS_CHROMEOS)
|
| }
|
|
|
| +// NSS creates a local cache of the sqlite database if it detects that the
|
| +// filesystem the database is on is much slower than the local disk. The
|
| +// detection doesn't work with the latest versions of sqlite, such as 3.6.22
|
| +// (NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=578561). So we set
|
| +// the NSS environment variable NSS_SDB_USE_CACHE to "yes" to override NSS's
|
| +// detection when database_dir is on NFS. See http://crbug.com/48585.
|
| +//
|
| +// TODO(wtc): port this function to other USE_NSS platforms. It is defined
|
| +// only for OS_LINUX simply because the statfs structure is OS-specific.
|
| +void UseLocalCacheOfNSSDatabaseIfNFS(const FilePath& database_dir) {
|
| +#if defined(OS_LINUX)
|
| + struct statfs buf;
|
| + if (statfs(database_dir.value().c_str(), &buf) == 0) {
|
| + if (buf.f_type == NFS_SUPER_MAGIC) {
|
| + scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
|
| + const char* use_cache_env_var = "NSS_SDB_USE_CACHE";
|
| + if (!env->HasEnv(use_cache_env_var))
|
| + env->SetEnv(use_cache_env_var, "yes");
|
| + }
|
| + }
|
| +#endif // defined(OS_LINUX)
|
| +}
|
| +
|
| // Load nss's built-in root certs.
|
| SECMODModule *InitDefaultRootCerts() {
|
| const char* kModulePath = "libnssckbi.so";
|
| @@ -78,7 +104,7 @@
|
| NOTREACHED();
|
| return NULL;
|
| }
|
| -#endif // !defined(USE_NSS_FOR_SSL_ONLY)
|
| +#endif // defined(USE_NSS)
|
|
|
| // A singleton to initialize/deinitialize NSPR.
|
| // Separate from the NSS singleton because we initialize NSPR on the UI thread.
|
| @@ -127,7 +153,7 @@
|
| }
|
|
|
| SECStatus status = SECFailure;
|
| -#if defined(USE_NSS_FOR_SSL_ONLY)
|
| +#if !defined(USE_NSS)
|
| // Use the system certificate store, so initialize NSS without database.
|
| status = NSS_NoDB_Init(NULL);
|
| if (status != SECSuccess) {
|
| @@ -135,12 +161,14 @@
|
| "database: NSS error code " << PR_GetError();
|
| }
|
| #else
|
| - std::string database_dir = GetInitialConfigDirectory();
|
| + FilePath database_dir = GetInitialConfigDirectory();
|
| if (!database_dir.empty()) {
|
| + UseLocalCacheOfNSSDatabaseIfNFS(database_dir);
|
| +
|
| // Initialize with a persistent database (likely, ~/.pki/nssdb).
|
| // Use "sql:" which can be shared by multiple processes safely.
|
| std::string nss_config_dir =
|
| - StringPrintf("sql:%s", database_dir.c_str());
|
| + StringPrintf("sql:%s", database_dir.value().c_str());
|
| #if defined(OS_CHROMEOS)
|
| status = NSS_Init(nss_config_dir.c_str());
|
| #else
|
| @@ -181,7 +209,7 @@
|
| write_lock_.reset(new Lock());
|
|
|
| root_ = InitDefaultRootCerts();
|
| -#endif // defined(USE_NSS_FOR_SSL_ONLY)
|
| +#endif // !defined(USE_NSS)
|
| }
|
|
|
| ~NSSInitSingleton() {
|
| @@ -212,7 +240,7 @@
|
|
|
| const std::string modspec =
|
| StringPrintf("configDir='%s' tokenDescription='Real NSS database'",
|
| - GetDefaultConfigDirectory().c_str());
|
| + GetDefaultConfigDirectory().value().c_str());
|
| real_db_slot_ = SECMOD_OpenUserDB(modspec.c_str());
|
| if (real_db_slot_ == NULL) {
|
| LOG(ERROR) << "Error opening persistent database (" << modspec
|
| @@ -235,7 +263,7 @@
|
| Lock* write_lock() {
|
| return write_lock_.get();
|
| }
|
| -#endif // defined(USE_NSS)
|
| +#endif // defined(USE_NSS)
|
|
|
| private:
|
| PK11SlotInfo* real_db_slot_; // Overrides internal key slot if non-NULL.
|
| @@ -243,7 +271,7 @@
|
| bool chromeos_user_logged_in_;
|
| #if defined(USE_NSS)
|
| scoped_ptr<Lock> write_lock_;
|
| -#endif // defined(USE_NSS)
|
| +#endif // defined(USE_NSS)
|
| };
|
|
|
| } // namespace
|
|
|