Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: base/nss_util.cc

Issue 1730001: Enable Chrome OS to load the user's nssdb later. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/nss_util.h ('k') | base/nss_util_internal.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2008-2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2008-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 7
7 #include <nss.h> 8 #include <nss.h>
8 #include <plarena.h> 9 #include <plarena.h>
9 #include <prerror.h> 10 #include <prerror.h>
10 #include <prinit.h> 11 #include <prinit.h>
11 #include <prtime.h> 12 #include <prtime.h>
12 #include <pk11pub.h> 13 #include <pk11pub.h>
13 #include <secmod.h> 14 #include <secmod.h>
14 15
15 #include "base/file_util.h" 16 #include "base/file_util.h"
(...skipping 19 matching lines...) Expand all
35 } 36 }
36 FilePath dir(home); 37 FilePath dir(home);
37 dir = dir.AppendASCII(".pki").AppendASCII("nssdb"); 38 dir = dir.AppendASCII(".pki").AppendASCII("nssdb");
38 if (!file_util::CreateDirectory(dir)) { 39 if (!file_util::CreateDirectory(dir)) {
39 LOG(ERROR) << "Failed to create ~/.pki/nssdb directory."; 40 LOG(ERROR) << "Failed to create ~/.pki/nssdb directory.";
40 return ""; 41 return "";
41 } 42 }
42 return dir.value(); 43 return dir.value();
43 } 44 }
44 45
46 // On non-chromeos platforms, return the default config directory.
47 // On chromeos, return a read-only directory with fake root CA certs for testing
48 // (which will not exist on non-testing images). These root CA certs are used
49 // by the local Google Accounts server mock we use when testing our login code.
50 // If this directory is not present, NSS_Init() will fail. It is up to the
51 // caller to failover to NSS_NoDB_Init() at that point.
52 std::string GetInitialConfigDirectory() {
53 #if defined(OS_CHROMEOS)
54 static const char kReadOnlyCertDB[] = "/etc/fake_root_ca/nssdb";
55 return std::string(kReadOnlyCertDB);
56 #else
57 return GetDefaultConfigDirectory();
58 #endif // defined(OS_CHROMEOS)
59 }
60
45 // Load nss's built-in root certs. 61 // Load nss's built-in root certs.
46 SECMODModule *InitDefaultRootCerts() { 62 SECMODModule *InitDefaultRootCerts() {
47 const char* kModulePath = "libnssckbi.so"; 63 const char* kModulePath = "libnssckbi.so";
48 char modparams[1024]; 64 char modparams[1024];
49 snprintf(modparams, sizeof(modparams), 65 snprintf(modparams, sizeof(modparams),
50 "name=\"Root Certs\" library=\"%s\"", kModulePath); 66 "name=\"Root Certs\" library=\"%s\"", kModulePath);
51 SECMODModule *root = SECMOD_LoadUserModule(modparams, NULL, PR_FALSE); 67 SECMODModule *root = SECMOD_LoadUserModule(modparams, NULL, PR_FALSE);
52 if (root) 68 if (root)
53 return root; 69 return root;
54 70
(...skipping 16 matching lines...) Expand all
71 PL_ArenaFinish(); 87 PL_ArenaFinish();
72 PRStatus prstatus = PR_Cleanup(); 88 PRStatus prstatus = PR_Cleanup();
73 if (prstatus != PR_SUCCESS) { 89 if (prstatus != PR_SUCCESS) {
74 LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?"; 90 LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?";
75 } 91 }
76 } 92 }
77 }; 93 };
78 94
79 class NSSInitSingleton { 95 class NSSInitSingleton {
80 public: 96 public:
81 NSSInitSingleton() : root_(NULL) { 97 NSSInitSingleton()
98 : real_db_slot_(NULL),
99 root_(NULL),
100 chromeos_user_logged_in_(false) {
82 base::EnsureNSPRInit(); 101 base::EnsureNSPRInit();
83 102
84 // We *must* have NSS >= 3.12.3. See bug 26448. 103 // We *must* have NSS >= 3.12.3. See bug 26448.
85 COMPILE_ASSERT( 104 COMPILE_ASSERT(
86 (NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH >= 3) || 105 (NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH >= 3) ||
87 (NSS_VMAJOR == 3 && NSS_VMINOR > 12) || 106 (NSS_VMAJOR == 3 && NSS_VMINOR > 12) ||
88 (NSS_VMAJOR > 3), 107 (NSS_VMAJOR > 3),
89 nss_version_check_failed); 108 nss_version_check_failed);
90 // Also check the run-time NSS version. 109 // Also check the run-time NSS version.
91 // NSS_VersionCheck is a >= check, not strict equality. 110 // NSS_VersionCheck is a >= check, not strict equality.
(...skipping 12 matching lines...) Expand all
104 123
105 SECStatus status = SECFailure; 124 SECStatus status = SECFailure;
106 #if defined(USE_NSS_FOR_SSL_ONLY) 125 #if defined(USE_NSS_FOR_SSL_ONLY)
107 // Use the system certificate store, so initialize NSS without database. 126 // Use the system certificate store, so initialize NSS without database.
108 status = NSS_NoDB_Init(NULL); 127 status = NSS_NoDB_Init(NULL);
109 if (status != SECSuccess) { 128 if (status != SECSuccess) {
110 LOG(ERROR) << "Error initializing NSS without a persistent " 129 LOG(ERROR) << "Error initializing NSS without a persistent "
111 "database: NSS error code " << PR_GetError(); 130 "database: NSS error code " << PR_GetError();
112 } 131 }
113 #else 132 #else
114 std::string database_dir = GetDefaultConfigDirectory(); 133 std::string database_dir = GetInitialConfigDirectory();
115 if (!database_dir.empty()) { 134 if (!database_dir.empty()) {
116 // Initialize with a persistant database (~/.pki/nssdb). 135 // Initialize with a persistent database (likely, ~/.pki/nssdb).
117 // Use "sql:" which can be shared by multiple processes safely. 136 // Use "sql:" which can be shared by multiple processes safely.
118 std::string nss_config_dir = 137 std::string nss_config_dir =
119 StringPrintf("sql:%s", database_dir.c_str()); 138 StringPrintf("sql:%s", database_dir.c_str());
139 #if defined(OS_CHROMEOS)
140 status = NSS_Init(nss_config_dir.c_str());
141 #else
120 status = NSS_InitReadWrite(nss_config_dir.c_str()); 142 status = NSS_InitReadWrite(nss_config_dir.c_str());
143 #endif
121 if (status != SECSuccess) { 144 if (status != SECSuccess) {
122 LOG(ERROR) << "Error initializing NSS with a persistent " 145 LOG(ERROR) << "Error initializing NSS with a persistent "
123 "database (" << nss_config_dir 146 "database (" << nss_config_dir
124 << "): NSS error code " << PR_GetError(); 147 << "): NSS error code " << PR_GetError();
125 } 148 }
126 } 149 }
127 if (status != SECSuccess) { 150 if (status != SECSuccess) {
128 LOG(WARNING) << "Initialize NSS without a persistent database " 151 LOG(WARNING) << "Initialize NSS without a persistent database "
129 "(~/.pki/nssdb)."; 152 "(~/.pki/nssdb).";
130 status = NSS_NoDB_Init(NULL); 153 status = NSS_NoDB_Init(NULL);
(...skipping 12 matching lines...) Expand all
143 if (PK11_NeedUserInit(slot)) 166 if (PK11_NeedUserInit(slot))
144 PK11_InitPin(slot, NULL, NULL); 167 PK11_InitPin(slot, NULL, NULL);
145 PK11_FreeSlot(slot); 168 PK11_FreeSlot(slot);
146 } 169 }
147 170
148 root_ = InitDefaultRootCerts(); 171 root_ = InitDefaultRootCerts();
149 #endif // defined(USE_NSS_FOR_SSL_ONLY) 172 #endif // defined(USE_NSS_FOR_SSL_ONLY)
150 } 173 }
151 174
152 ~NSSInitSingleton() { 175 ~NSSInitSingleton() {
176 if (real_db_slot_) {
177 SECMOD_CloseUserDB(real_db_slot_);
178 PK11_FreeSlot(real_db_slot_);
179 real_db_slot_ = NULL;
180 }
153 if (root_) { 181 if (root_) {
154 SECMOD_UnloadUserModule(root_); 182 SECMOD_UnloadUserModule(root_);
155 SECMOD_DestroyModule(root_); 183 SECMOD_DestroyModule(root_);
156 root_ = NULL; 184 root_ = NULL;
157 } 185 }
158 186
159 SECStatus status = NSS_Shutdown(); 187 SECStatus status = NSS_Shutdown();
160 if (status != SECSuccess) { 188 if (status != SECSuccess) {
161 // We LOG(INFO) because this failure is relatively harmless 189 // We LOG(INFO) because this failure is relatively harmless
162 // (leaking, but we're shutting down anyway). 190 // (leaking, but we're shutting down anyway).
163 LOG(INFO) << "NSS_Shutdown failed; see " 191 LOG(INFO) << "NSS_Shutdown failed; see "
164 "http://code.google.com/p/chromium/issues/detail?id=4609"; 192 "http://code.google.com/p/chromium/issues/detail?id=4609";
165 } 193 }
166 } 194 }
167 195
196 #if defined(OS_CHROMEOS)
197 void OpenPersistentNSSDB() {
198 if (!chromeos_user_logged_in_) {
199 chromeos_user_logged_in_ = true;
200
201 const std::string modspec =
202 StringPrintf("configDir='%s' tokenDescription='Real NSS database'",
203 GetDefaultConfigDirectory().c_str());
204 real_db_slot_ = SECMOD_OpenUserDB(modspec.c_str());
205 if (real_db_slot_ == NULL) {
206 LOG(ERROR) << "Error opening persistent database (" << modspec
207 << "): NSS error code " << PR_GetError();
208 } else {
209 if (PK11_NeedUserInit(real_db_slot_))
210 PK11_InitPin(real_db_slot_, NULL, NULL);
211 }
212 }
213 }
214 #endif // defined(OS_CHROMEOS)
215
216 PK11SlotInfo* GetDefaultKeySlot() {
217 if (real_db_slot_)
218 return real_db_slot_;
219 return PK11_GetInternalKeySlot();
220 }
221
168 private: 222 private:
223 PK11SlotInfo* real_db_slot_; // Overrides internal key slot if non-NULL.
169 SECMODModule *root_; 224 SECMODModule *root_;
225 bool chromeos_user_logged_in_;
170 }; 226 };
171 227
172 } // namespace 228 } // namespace
173 229
174 namespace base { 230 namespace base {
175 231
176 void EnsureNSPRInit() { 232 void EnsureNSPRInit() {
177 Singleton<NSPRInitSingleton>::get(); 233 Singleton<NSPRInitSingleton>::get();
178 } 234 }
179 235
180 void EnsureNSSInit() { 236 void EnsureNSSInit() {
181 Singleton<NSSInitSingleton>::get(); 237 Singleton<NSSInitSingleton>::get();
182 } 238 }
183 239
240 #if defined(OS_CHROMEOS)
241 void OpenPersistentNSSDB() {
242 Singleton<NSSInitSingleton>::get()->OpenPersistentNSSDB();
243 }
244 #endif
245
184 // TODO(port): Implement this more simply. We can convert by subtracting an 246 // TODO(port): Implement this more simply. We can convert by subtracting an
185 // offset (the difference between NSPR's and base::Time's epochs). 247 // offset (the difference between NSPR's and base::Time's epochs).
186 Time PRTimeToBaseTime(PRTime prtime) { 248 Time PRTimeToBaseTime(PRTime prtime) {
187 PRExplodedTime prxtime; 249 PRExplodedTime prxtime;
188 PR_ExplodeTime(prtime, PR_GMTParameters, &prxtime); 250 PR_ExplodeTime(prtime, PR_GMTParameters, &prxtime);
189 251
190 base::Time::Exploded exploded; 252 base::Time::Exploded exploded;
191 exploded.year = prxtime.tm_year; 253 exploded.year = prxtime.tm_year;
192 exploded.month = prxtime.tm_month + 1; 254 exploded.month = prxtime.tm_month + 1;
193 exploded.day_of_week = prxtime.tm_wday; 255 exploded.day_of_week = prxtime.tm_wday;
194 exploded.day_of_month = prxtime.tm_mday; 256 exploded.day_of_month = prxtime.tm_mday;
195 exploded.hour = prxtime.tm_hour; 257 exploded.hour = prxtime.tm_hour;
196 exploded.minute = prxtime.tm_min; 258 exploded.minute = prxtime.tm_min;
197 exploded.second = prxtime.tm_sec; 259 exploded.second = prxtime.tm_sec;
198 exploded.millisecond = prxtime.tm_usec / 1000; 260 exploded.millisecond = prxtime.tm_usec / 1000;
199 261
200 return Time::FromUTCExploded(exploded); 262 return Time::FromUTCExploded(exploded);
201 } 263 }
202 264
265 PK11SlotInfo* GetDefaultNSSKeySlot() {
266 return Singleton<NSSInitSingleton>::get()->GetDefaultKeySlot();
267 }
268
203 } // namespace base 269 } // namespace base
OLDNEW
« no previous file with comments | « base/nss_util.h ('k') | base/nss_util_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698