OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/nss_util.h" | 5 #include "base/nss_util.h" |
6 #include "base/nss_util_internal.h" | 6 #include "base/nss_util_internal.h" |
7 | 7 |
8 #include <nss.h> | 8 #include <nss.h> |
9 #include <plarena.h> | 9 #include <plarena.h> |
10 #include <prerror.h> | 10 #include <prerror.h> |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 return PK11_ReferenceSlot(real_db_slot_); | 197 return PK11_ReferenceSlot(real_db_slot_); |
198 return PK11_GetInternalKeySlot(); | 198 return PK11_GetInternalKeySlot(); |
199 } | 199 } |
200 | 200 |
201 #if defined(USE_NSS) | 201 #if defined(USE_NSS) |
202 Lock* write_lock() { | 202 Lock* write_lock() { |
203 return &write_lock_; | 203 return &write_lock_; |
204 } | 204 } |
205 #endif // defined(USE_NSS) | 205 #endif // defined(USE_NSS) |
206 | 206 |
207 // This method is used to force NSS to ne initialized without a DB. | |
wtc
2011/03/15 21:37:20
Typo: ne => be
| |
208 // Call this method before NSSInitSingleton() is constructed. | |
209 static void ForceNoDBInit() { | |
210 force_nodb_init_ = true; | |
211 } | |
212 | |
207 private: | 213 private: |
208 friend struct DefaultLazyInstanceTraits<NSSInitSingleton>; | 214 friend struct DefaultLazyInstanceTraits<NSSInitSingleton>; |
209 | 215 |
210 NSSInitSingleton() | 216 NSSInitSingleton() |
211 : real_db_slot_(NULL), | 217 : real_db_slot_(NULL), |
212 test_db_slot_(NULL), | 218 test_db_slot_(NULL), |
213 root_(NULL), | 219 root_(NULL), |
214 chromeos_user_logged_in_(false) { | 220 chromeos_user_logged_in_(false) { |
215 EnsureNSPRInit(); | 221 EnsureNSPRInit(); |
216 | 222 |
(...skipping 12 matching lines...) Expand all Loading... | |
229 LOG(ERROR) << "NSS_VersionCheck(\"3.12.3\") failed. " | 235 LOG(ERROR) << "NSS_VersionCheck(\"3.12.3\") failed. " |
230 "We depend on NSS >= 3.12.3, and this error is not fatal " | 236 "We depend on NSS >= 3.12.3, and this error is not fatal " |
231 "only because many people have busted NSS setups (for " | 237 "only because many people have busted NSS setups (for " |
232 "example, using the wrong version of NSPR). " | 238 "example, using the wrong version of NSPR). " |
233 "Please upgrade to the latest NSS and NSPR, and if you " | 239 "Please upgrade to the latest NSS and NSPR, and if you " |
234 "still get this error, contact your distribution " | 240 "still get this error, contact your distribution " |
235 "maintainer."; | 241 "maintainer."; |
236 } | 242 } |
237 | 243 |
238 SECStatus status = SECFailure; | 244 SECStatus status = SECFailure; |
245 bool nodb_init = force_nodb_init_; | |
246 | |
239 #if !defined(USE_NSS) | 247 #if !defined(USE_NSS) |
240 // Use the system certificate store, so initialize NSS without database. | 248 // Use the system certificate store, so initialize NSS without database. |
241 status = NSS_NoDB_Init(NULL); | 249 nodb_init = true; |
242 if (status != SECSuccess) { | 250 #endif |
243 LOG(ERROR) << "Error initializing NSS without a persistent " | |
244 "database: NSS error code " << PR_GetError(); | |
245 } | |
246 #else | |
247 FilePath database_dir = GetInitialConfigDirectory(); | |
248 if (!database_dir.empty()) { | |
249 // This duplicates the work which should have been done in | |
250 // EarlySetupForNSSInit. However, this function is idempotent so there's | |
251 // no harm done. | |
252 UseLocalCacheOfNSSDatabaseIfNFS(database_dir); | |
253 | 251 |
254 // Initialize with a persistent database (likely, ~/.pki/nssdb). | 252 if (nodb_init) { |
255 // Use "sql:" which can be shared by multiple processes safely. | |
256 std::string nss_config_dir = | |
257 StringPrintf("sql:%s", database_dir.value().c_str()); | |
258 #if defined(OS_CHROMEOS) | |
259 status = NSS_Init(nss_config_dir.c_str()); | |
260 #else | |
261 status = NSS_InitReadWrite(nss_config_dir.c_str()); | |
262 #endif | |
263 if (status != SECSuccess) { | |
264 LOG(ERROR) << "Error initializing NSS with a persistent " | |
265 "database (" << nss_config_dir | |
266 << "): NSS error code " << PR_GetError(); | |
267 } | |
268 } | |
269 if (status != SECSuccess) { | |
270 LOG(WARNING) << "Initialize NSS without a persistent database " | |
271 "(~/.pki/nssdb)."; | |
272 status = NSS_NoDB_Init(NULL); | 253 status = NSS_NoDB_Init(NULL); |
273 if (status != SECSuccess) { | 254 if (status != SECSuccess) { |
274 LOG(ERROR) << "Error initializing NSS without a persistent " | 255 LOG(ERROR) << "Error initializing NSS without a persistent " |
275 "database: NSS error code " << PR_GetError(); | 256 "database: NSS error code " << PR_GetError(); |
276 return; | |
277 } | 257 } |
258 } else { | |
259 FilePath database_dir = GetInitialConfigDirectory(); | |
260 if (!database_dir.empty()) { | |
261 // This duplicates the work which should have been done in | |
262 // EarlySetupForNSSInit. However, this function is idempotent so | |
263 // there's no harm done. | |
264 UseLocalCacheOfNSSDatabaseIfNFS(database_dir); | |
265 | |
266 // Initialize with a persistent database (likely, ~/.pki/nssdb). | |
267 // Use "sql:" which can be shared by multiple processes safely. | |
268 std::string nss_config_dir = | |
269 StringPrintf("sql:%s", database_dir.value().c_str()); | |
270 #if defined(OS_CHROMEOS) | |
271 status = NSS_Init(nss_config_dir.c_str()); | |
272 #else | |
273 status = NSS_InitReadWrite(nss_config_dir.c_str()); | |
274 #endif | |
275 if (status != SECSuccess) { | |
276 LOG(ERROR) << "Error initializing NSS with a persistent " | |
277 "database (" << nss_config_dir | |
278 << "): NSS error code " << PR_GetError(); | |
279 } | |
280 } | |
281 if (status != SECSuccess) { | |
282 LOG(WARNING) << "Initialize NSS without a persistent database " | |
283 "(~/.pki/nssdb)."; | |
284 status = NSS_NoDB_Init(NULL); | |
285 if (status != SECSuccess) { | |
286 LOG(ERROR) << "Error initializing NSS without a persistent " | |
287 "database: NSS error code " << PR_GetError(); | |
288 return; | |
289 } | |
290 } | |
291 | |
292 PK11_SetPasswordFunc(PKCS11PasswordFunc); | |
293 | |
294 // If we haven't initialized the password for the NSS databases, | |
295 // initialize an empty-string password so that we don't need to | |
296 // log in. | |
297 PK11SlotInfo* slot = PK11_GetInternalKeySlot(); | |
298 if (slot) { | |
299 // PK11_InitPin may write to the keyDB, but no other thread can use NSS | |
300 // yet, so we don't need to lock. | |
301 if (PK11_NeedUserInit(slot)) | |
302 PK11_InitPin(slot, NULL, NULL); | |
303 PK11_FreeSlot(slot); | |
304 } | |
305 | |
306 root_ = InitDefaultRootCerts(); | |
wtc
2011/03/15 21:37:20
This function and PKCS11PasswordFunc at line 292 a
| |
278 } | 307 } |
279 | |
280 PK11_SetPasswordFunc(PKCS11PasswordFunc); | |
281 | |
282 // If we haven't initialized the password for the NSS databases, | |
283 // initialize an empty-string password so that we don't need to | |
284 // log in. | |
285 PK11SlotInfo* slot = PK11_GetInternalKeySlot(); | |
286 if (slot) { | |
287 // PK11_InitPin may write to the keyDB, but no other thread can use NSS | |
288 // yet, so we don't need to lock. | |
289 if (PK11_NeedUserInit(slot)) | |
290 PK11_InitPin(slot, NULL, NULL); | |
291 PK11_FreeSlot(slot); | |
292 } | |
293 | |
294 root_ = InitDefaultRootCerts(); | |
295 #endif // !defined(USE_NSS) | |
296 } | 308 } |
297 | 309 |
298 // NOTE(willchan): We don't actually execute this code since we leak NSS to | 310 // NOTE(willchan): We don't actually execute this code since we leak NSS to |
299 // prevent non-joinable threads from using NSS after it's already been shut | 311 // prevent non-joinable threads from using NSS after it's already been shut |
300 // down. | 312 // down. |
301 ~NSSInitSingleton() { | 313 ~NSSInitSingleton() { |
302 if (real_db_slot_) { | 314 if (real_db_slot_) { |
303 SECMOD_CloseUserDB(real_db_slot_); | 315 SECMOD_CloseUserDB(real_db_slot_); |
304 PK11_FreeSlot(real_db_slot_); | 316 PK11_FreeSlot(real_db_slot_); |
305 real_db_slot_ = NULL; | 317 real_db_slot_ = NULL; |
(...skipping 24 matching lines...) Expand all Loading... | |
330 if (PK11_NeedUserInit(db_slot)) | 342 if (PK11_NeedUserInit(db_slot)) |
331 PK11_InitPin(db_slot, NULL, NULL); | 343 PK11_InitPin(db_slot, NULL, NULL); |
332 } | 344 } |
333 else { | 345 else { |
334 LOG(ERROR) << "Error opening persistent database (" << modspec | 346 LOG(ERROR) << "Error opening persistent database (" << modspec |
335 << "): NSS error code " << PR_GetError(); | 347 << "): NSS error code " << PR_GetError(); |
336 } | 348 } |
337 return db_slot; | 349 return db_slot; |
338 } | 350 } |
339 | 351 |
352 // If this is set to true NSS is forced to be initialized without a DB. | |
353 static bool force_nodb_init_; | |
354 | |
340 PK11SlotInfo* real_db_slot_; // Overrides internal key slot if non-NULL. | 355 PK11SlotInfo* real_db_slot_; // Overrides internal key slot if non-NULL. |
341 PK11SlotInfo* test_db_slot_; // Overrides internal key slot and real_db_slot_ | 356 PK11SlotInfo* test_db_slot_; // Overrides internal key slot and real_db_slot_ |
342 SECMODModule *root_; | 357 SECMODModule *root_; |
343 bool chromeos_user_logged_in_; | 358 bool chromeos_user_logged_in_; |
344 #if defined(USE_NSS) | 359 #if defined(USE_NSS) |
345 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 | 360 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 |
346 // is fixed, we will no longer need the lock. | 361 // is fixed, we will no longer need the lock. |
347 Lock write_lock_; | 362 Lock write_lock_; |
348 #endif // defined(USE_NSS) | 363 #endif // defined(USE_NSS) |
349 }; | 364 }; |
350 | 365 |
366 bool NSSInitSingleton::force_nodb_init_ = false; | |
wtc
2011/03/15 21:37:20
Nit: add a comment:
// static
before this line.
| |
367 | |
351 LazyInstance<NSSInitSingleton, LeakyLazyInstanceTraits<NSSInitSingleton> > | 368 LazyInstance<NSSInitSingleton, LeakyLazyInstanceTraits<NSSInitSingleton> > |
352 g_nss_singleton(LINKER_INITIALIZED); | 369 g_nss_singleton(LINKER_INITIALIZED); |
353 | 370 |
354 } // namespace | 371 } // namespace |
355 | 372 |
356 #if defined(USE_NSS) | 373 #if defined(USE_NSS) |
357 void EarlySetupForNSSInit() { | 374 void EarlySetupForNSSInit() { |
358 FilePath database_dir = GetInitialConfigDirectory(); | 375 FilePath database_dir = GetInitialConfigDirectory(); |
359 if (!database_dir.empty()) | 376 if (!database_dir.empty()) |
360 UseLocalCacheOfNSSDatabaseIfNFS(database_dir); | 377 UseLocalCacheOfNSSDatabaseIfNFS(database_dir); |
361 } | 378 } |
362 #endif | 379 #endif |
363 | 380 |
364 void EnsureNSPRInit() { | 381 void EnsureNSPRInit() { |
365 g_nspr_singleton.Get(); | 382 g_nspr_singleton.Get(); |
366 } | 383 } |
367 | 384 |
368 void EnsureNSSInit() { | 385 void EnsureNSSInit() { |
369 // Initializing SSL causes us to do blocking IO. | 386 // Initializing SSL causes us to do blocking IO. |
370 // Temporarily allow it until we fix | 387 // Temporarily allow it until we fix |
371 // http://code.google.com/p/chromium/issues/detail?id=59847 | 388 // http://code.google.com/p/chromium/issues/detail?id=59847 |
372 ThreadRestrictions::ScopedAllowIO allow_io; | 389 ThreadRestrictions::ScopedAllowIO allow_io; |
373 g_nss_singleton.Get(); | 390 g_nss_singleton.Get(); |
374 } | 391 } |
375 | 392 |
393 void ForceNSSNoDBInit() { | |
394 NSSInitSingleton::ForceNoDBInit(); | |
395 } | |
396 | |
397 void DisableNSSForkCheck() { | |
398 scoped_ptr<Environment> env(Environment::Create()); | |
399 env->SetVar("NSS_STRICT_NOFORK", "DISABLED"); | |
400 } | |
401 | |
376 bool CheckNSSVersion(const char* version) { | 402 bool CheckNSSVersion(const char* version) { |
377 return !!NSS_VersionCheck(version); | 403 return !!NSS_VersionCheck(version); |
378 } | 404 } |
379 | 405 |
380 #if defined(USE_NSS) | 406 #if defined(USE_NSS) |
381 bool OpenTestNSSDB(const FilePath& path, const char* description) { | 407 bool OpenTestNSSDB(const FilePath& path, const char* description) { |
382 return g_nss_singleton.Get().OpenTestNSSDB(path, description); | 408 return g_nss_singleton.Get().OpenTestNSSDB(path, description); |
383 } | 409 } |
384 | 410 |
385 void CloseTestNSSDB() { | 411 void CloseTestNSSDB() { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 exploded.millisecond = prxtime.tm_usec / 1000; | 453 exploded.millisecond = prxtime.tm_usec / 1000; |
428 | 454 |
429 return Time::FromUTCExploded(exploded); | 455 return Time::FromUTCExploded(exploded); |
430 } | 456 } |
431 | 457 |
432 PK11SlotInfo* GetDefaultNSSKeySlot() { | 458 PK11SlotInfo* GetDefaultNSSKeySlot() { |
433 return g_nss_singleton.Get().GetDefaultKeySlot(); | 459 return g_nss_singleton.Get().GetDefaultKeySlot(); |
434 } | 460 } |
435 | 461 |
436 } // namespace base | 462 } // namespace base |
OLD | NEW |