Index: base/nss_util.cc |
=================================================================== |
--- base/nss_util.cc (revision 45593) |
+++ base/nss_util.cc (working copy) |
@@ -3,6 +3,7 @@ |
// found in the LICENSE file. |
#include "base/nss_util.h" |
+#include "base/nss_util_internal.h" |
#include <nss.h> |
#include <plarena.h> |
@@ -42,6 +43,21 @@ |
return dir.value(); |
} |
+// On non-chromeos platforms, return the default config directory. |
+// On chromeos, return a read-only directory with fake root CA certs for testing |
+// (which will not exist on non-testing images). These root CA certs are used |
+// 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() { |
+#if defined(OS_CHROMEOS) |
+ static const char kReadOnlyCertDB[] = "/etc/fake_root_ca/nssdb"; |
+ return std::string(kReadOnlyCertDB); |
+#else |
+ return GetDefaultConfigDirectory(); |
+#endif // defined(OS_CHROMEOS) |
+} |
+ |
// Load nss's built-in root certs. |
SECMODModule *InitDefaultRootCerts() { |
const char* kModulePath = "libnssckbi.so"; |
@@ -78,7 +94,10 @@ |
class NSSInitSingleton { |
public: |
- NSSInitSingleton() : root_(NULL) { |
+ NSSInitSingleton() |
+ : real_db_slot_(NULL), |
+ root_(NULL), |
+ chromeos_user_logged_in_(false) { |
base::EnsureNSPRInit(); |
// We *must* have NSS >= 3.12.3. See bug 26448. |
@@ -111,13 +130,17 @@ |
"database: NSS error code " << PR_GetError(); |
} |
#else |
- std::string database_dir = GetDefaultConfigDirectory(); |
+ std::string database_dir = GetInitialConfigDirectory(); |
if (!database_dir.empty()) { |
- // Initialize with a persistant database (~/.pki/nssdb). |
+ // 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()); |
+#if defined(OS_CHROMEOS) |
+ status = NSS_Init(nss_config_dir.c_str()); |
+#else |
status = NSS_InitReadWrite(nss_config_dir.c_str()); |
+#endif |
if (status != SECSuccess) { |
LOG(ERROR) << "Error initializing NSS with a persistent " |
"database (" << nss_config_dir |
@@ -150,6 +173,11 @@ |
} |
~NSSInitSingleton() { |
+ if (real_db_slot_) { |
+ SECMOD_CloseUserDB(real_db_slot_); |
+ PK11_FreeSlot(real_db_slot_); |
+ real_db_slot_ = NULL; |
+ } |
if (root_) { |
SECMOD_UnloadUserModule(root_); |
SECMOD_DestroyModule(root_); |
@@ -165,8 +193,36 @@ |
} |
} |
+#if defined(OS_CHROMEOS) |
+ void OpenPersistentNSSDB() { |
+ if (!chromeos_user_logged_in_) { |
+ chromeos_user_logged_in_ = true; |
+ |
+ const std::string modspec = |
+ StringPrintf("configDir='%s' tokenDescription='Real NSS database'", |
+ GetDefaultConfigDirectory().c_str()); |
+ real_db_slot_ = SECMOD_OpenUserDB(modspec.c_str()); |
+ if (real_db_slot_ == NULL) { |
+ LOG(ERROR) << "Error opening persistent database (" << modspec |
+ << "): NSS error code " << PR_GetError(); |
+ } else { |
+ if (PK11_NeedUserInit(real_db_slot_)) |
+ PK11_InitPin(real_db_slot_, NULL, NULL); |
+ } |
+ } |
+ } |
+#endif // defined(OS_CHROMEOS) |
+ |
+ PK11SlotInfo* GetDefaultKeySlot() { |
+ if (real_db_slot_) |
+ return real_db_slot_; |
+ return PK11_GetInternalKeySlot(); |
+ } |
+ |
private: |
+ PK11SlotInfo* real_db_slot_; // Overrides internal key slot if non-NULL. |
SECMODModule *root_; |
+ bool chromeos_user_logged_in_; |
}; |
} // namespace |
@@ -181,6 +237,12 @@ |
Singleton<NSSInitSingleton>::get(); |
} |
+#if defined(OS_CHROMEOS) |
+void OpenPersistentNSSDB() { |
+ Singleton<NSSInitSingleton>::get()->OpenPersistentNSSDB(); |
+} |
+#endif |
+ |
// TODO(port): Implement this more simply. We can convert by subtracting an |
// offset (the difference between NSPR's and base::Time's epochs). |
Time PRTimeToBaseTime(PRTime prtime) { |
@@ -200,4 +262,8 @@ |
return Time::FromUTCExploded(exploded); |
} |
+PK11SlotInfo* GetDefaultNSSKeySlot() { |
+ return Singleton<NSSInitSingleton>::get()->GetDefaultKeySlot(); |
+} |
+ |
} // namespace base |