security/manager/ssl/src/nsPK11TokenDB.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:70c87f43011b
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsISupports.h"
7 #include "nsISupportsArray.h"
8 #include "nsIPK11TokenDB.h"
9 #include "prerror.h"
10 #include "secerr.h"
11 #include "nsReadableUtils.h"
12 #include "nsNSSComponent.h"
13 #include "nsServiceManagerUtils.h"
14
15 #include "nsPK11TokenDB.h"
16
17 #ifdef PR_LOGGING
18 extern PRLogModuleInfo* gPIPNSSLog;
19 #endif
20
21 NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
22
23 nsPK11Token::nsPK11Token(PK11SlotInfo *slot)
24 {
25 nsNSSShutDownPreventionLock locker;
26 if (isAlreadyShutDown())
27 return;
28
29 PK11_ReferenceSlot(slot);
30 mSlot = slot;
31 mSeries = PK11_GetSlotSeries(slot);
32
33 refreshTokenInfo();
34 mUIContext = new PipUIContext();
35 }
36
37 void
38 nsPK11Token::refreshTokenInfo()
39 {
40 mTokenName = NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot));
41
42 SECStatus srv;
43
44 CK_TOKEN_INFO tok_info;
45 srv = PK11_GetTokenInfo(mSlot, &tok_info);
46 if (srv == SECSuccess) {
47 // Set the Label field
48
49 const char *ccLabel = (const char*)tok_info.label;
50 const nsACString &cLabel = Substring(
51 ccLabel,
52 ccLabel+PL_strnlen(ccLabel, sizeof(tok_info.label)));
53 mTokenLabel = NS_ConvertUTF8toUTF16(cLabel);
54 mTokenLabel.Trim(" ", false, true);
55
56 // Set the Manufacturer field
57 const char *ccManID = (const char*)tok_info.manufacturerID;
58 const nsACString &cManID = Substring(
59 ccManID,
60 ccManID+PL_strnlen(ccManID, sizeof(tok_info.manufacturerID)));
61 mTokenManID = NS_ConvertUTF8toUTF16(cManID);
62 mTokenManID.Trim(" ", false, true);
63
64 // Set the Hardware Version field
65 mTokenHWVersion.AppendInt(tok_info.hardwareVersion.major);
66 mTokenHWVersion.AppendLiteral(".");
67 mTokenHWVersion.AppendInt(tok_info.hardwareVersion.minor);
68 // Set the Firmware Version field
69 mTokenFWVersion.AppendInt(tok_info.firmwareVersion.major);
70 mTokenFWVersion.AppendLiteral(".");
71 mTokenFWVersion.AppendInt(tok_info.firmwareVersion.minor);
72 // Set the Serial Number field
73 const char *ccSerial = (const char*)tok_info.serialNumber;
74 const nsACString &cSerial = Substring(
75 ccSerial,
76 ccSerial+PL_strnlen(ccSerial, sizeof(tok_info.serialNumber)));
77 mTokenSerialNum = NS_ConvertUTF8toUTF16(cSerial);
78 mTokenSerialNum.Trim(" ", false, true);
79 }
80
81 }
82
83 nsPK11Token::~nsPK11Token()
84 {
85 nsNSSShutDownPreventionLock locker;
86 if (isAlreadyShutDown()) {
87 return;
88 }
89 destructorSafeDestroyNSSReference();
90 shutdown(calledFromObject);
91 }
92
93 void nsPK11Token::virtualDestroyNSSReference()
94 {
95 destructorSafeDestroyNSSReference();
96 }
97
98 void nsPK11Token::destructorSafeDestroyNSSReference()
99 {
100 if (mSlot) {
101 PK11_FreeSlot(mSlot);
102 mSlot = nullptr;
103 }
104 }
105
106 /* readonly attribute wstring tokenName; */
107 NS_IMETHODIMP nsPK11Token::GetTokenName(char16_t * *aTokenName)
108 {
109 // handle removals/insertions
110 if (mSeries != PK11_GetSlotSeries(mSlot)) {
111 refreshTokenInfo();
112 }
113 *aTokenName = ToNewUnicode(mTokenName);
114 if (!*aTokenName) return NS_ERROR_OUT_OF_MEMORY;
115
116 return NS_OK;
117 }
118
119 /* readonly attribute wstring tokenDesc; */
120 NS_IMETHODIMP nsPK11Token::GetTokenLabel(char16_t **aTokLabel)
121 {
122 // handle removals/insertions
123 if (mSeries != PK11_GetSlotSeries(mSlot)) {
124 refreshTokenInfo();
125 }
126 *aTokLabel = ToNewUnicode(mTokenLabel);
127 if (!*aTokLabel) return NS_ERROR_OUT_OF_MEMORY;
128 return NS_OK;
129 }
130
131 /* readonly attribute wstring tokenManID; */
132 NS_IMETHODIMP nsPK11Token::GetTokenManID(char16_t **aTokManID)
133 {
134 // handle removals/insertions
135 if (mSeries != PK11_GetSlotSeries(mSlot)) {
136 refreshTokenInfo();
137 }
138 *aTokManID = ToNewUnicode(mTokenManID);
139 if (!*aTokManID) return NS_ERROR_OUT_OF_MEMORY;
140 return NS_OK;
141 }
142
143 /* readonly attribute wstring tokenHWVersion; */
144 NS_IMETHODIMP nsPK11Token::GetTokenHWVersion(char16_t **aTokHWVersion)
145 {
146 // handle removals/insertions
147 if (mSeries != PK11_GetSlotSeries(mSlot)) {
148 refreshTokenInfo();
149 }
150 *aTokHWVersion = ToNewUnicode(mTokenHWVersion);
151 if (!*aTokHWVersion) return NS_ERROR_OUT_OF_MEMORY;
152 return NS_OK;
153 }
154
155 /* readonly attribute wstring tokenFWVersion; */
156 NS_IMETHODIMP nsPK11Token::GetTokenFWVersion(char16_t **aTokFWVersion)
157 {
158 // handle removals/insertions
159 if (mSeries != PK11_GetSlotSeries(mSlot)) {
160 refreshTokenInfo();
161 }
162 *aTokFWVersion = ToNewUnicode(mTokenFWVersion);
163 if (!*aTokFWVersion) return NS_ERROR_OUT_OF_MEMORY;
164 return NS_OK;
165 }
166
167 /* readonly attribute wstring tokenSerialNumber; */
168 NS_IMETHODIMP nsPK11Token::GetTokenSerialNumber(char16_t **aTokSerialNum)
169 {
170 // handle removals/insertions
171 if (mSeries != PK11_GetSlotSeries(mSlot)) {
172 refreshTokenInfo();
173 }
174 *aTokSerialNum = ToNewUnicode(mTokenSerialNum);
175 if (!*aTokSerialNum) return NS_ERROR_OUT_OF_MEMORY;
176 return NS_OK;
177 }
178
179 /* boolean isLoggedIn (); */
180 NS_IMETHODIMP nsPK11Token::IsLoggedIn(bool *_retval)
181 {
182 nsNSSShutDownPreventionLock locker;
183 if (isAlreadyShutDown())
184 return NS_ERROR_NOT_AVAILABLE;
185
186 nsresult rv = NS_OK;
187
188 *_retval = PK11_IsLoggedIn(mSlot, 0);
189
190 return rv;
191 }
192
193 /* void logout (in boolean force); */
194 NS_IMETHODIMP
195 nsPK11Token::Login(bool force)
196 {
197 nsNSSShutDownPreventionLock locker;
198 if (isAlreadyShutDown())
199 return NS_ERROR_NOT_AVAILABLE;
200
201 nsresult rv;
202 SECStatus srv;
203 bool test;
204 rv = this->NeedsLogin(&test);
205 if (NS_FAILED(rv)) return rv;
206 if (test && force) {
207 rv = this->LogoutSimple();
208 if (NS_FAILED(rv)) return rv;
209 }
210 rv = setPassword(mSlot, mUIContext);
211 if (NS_FAILED(rv)) return rv;
212 srv = PK11_Authenticate(mSlot, true, mUIContext);
213 return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
214 }
215
216 NS_IMETHODIMP nsPK11Token::LogoutSimple()
217 {
218 nsNSSShutDownPreventionLock locker;
219 if (isAlreadyShutDown())
220 return NS_ERROR_NOT_AVAILABLE;
221
222 // PK11_MapError sets CKR_USER_NOT_LOGGED_IN to SEC_ERROR_LIBRARY_FAILURE,
223 // so not going to learn anything here by a failure. Treat it like void.
224 PK11_Logout(mSlot);
225 return NS_OK;
226 }
227
228 NS_IMETHODIMP nsPK11Token::LogoutAndDropAuthenticatedResources()
229 {
230 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
231
232 nsresult rv = LogoutSimple();
233
234 if (NS_FAILED(rv))
235 return rv;
236
237 nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
238 if (NS_FAILED(rv))
239 return rv;
240
241 return nssComponent->LogoutAuthenticatedPK11();
242 }
243
244 /* void reset (); */
245 NS_IMETHODIMP nsPK11Token::Reset()
246 {
247 nsNSSShutDownPreventionLock locker;
248 if (isAlreadyShutDown())
249 return NS_ERROR_NOT_AVAILABLE;
250
251 PK11_ResetToken(mSlot, 0);
252 return NS_OK;
253 }
254
255 /* readonly attribute long minimumPasswordLength; */
256 NS_IMETHODIMP nsPK11Token::GetMinimumPasswordLength(int32_t *aMinimumPasswordLength)
257 {
258 nsNSSShutDownPreventionLock locker;
259 if (isAlreadyShutDown())
260 return NS_ERROR_NOT_AVAILABLE;
261
262 *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot);
263
264 return NS_OK;
265 }
266
267 /* readonly attribute boolean needsUserInit; */
268 NS_IMETHODIMP nsPK11Token::GetNeedsUserInit(bool *aNeedsUserInit)
269 {
270 nsNSSShutDownPreventionLock locker;
271 if (isAlreadyShutDown())
272 return NS_ERROR_NOT_AVAILABLE;
273
274 *aNeedsUserInit = PK11_NeedUserInit(mSlot);
275 return NS_OK;
276 }
277
278 /* boolean checkPassword (in wstring password); */
279 NS_IMETHODIMP nsPK11Token::CheckPassword(const char16_t *password, bool *_retval)
280 {
281 nsNSSShutDownPreventionLock locker;
282 if (isAlreadyShutDown())
283 return NS_ERROR_NOT_AVAILABLE;
284
285 SECStatus srv;
286 int32_t prerr;
287 NS_ConvertUTF16toUTF8 aUtf8Password(password);
288 srv = PK11_CheckUserPassword(mSlot,
289 const_cast<char *>(aUtf8Password.get()));
290 if (srv != SECSuccess) {
291 *_retval = false;
292 prerr = PR_GetError();
293 if (prerr != SEC_ERROR_BAD_PASSWORD) {
294 /* something really bad happened - throw an exception */
295 return NS_ERROR_FAILURE;
296 }
297 } else {
298 *_retval = true;
299 }
300 return NS_OK;
301 }
302
303 /* void initPassword (in wstring initialPassword); */
304 NS_IMETHODIMP nsPK11Token::InitPassword(const char16_t *initialPassword)
305 {
306 nsNSSShutDownPreventionLock locker;
307 if (isAlreadyShutDown())
308 return NS_ERROR_NOT_AVAILABLE;
309
310 nsresult rv = NS_OK;
311 SECStatus status;
312
313 NS_ConvertUTF16toUTF8 aUtf8InitialPassword(initialPassword);
314 status = PK11_InitPin(mSlot, "", const_cast<char*>(aUtf8InitialPassword.get()));
315 if (status == SECFailure) { rv = NS_ERROR_FAILURE; goto done; }
316
317 done:
318 return rv;
319 }
320
321 /* long getAskPasswordTimes(); */
322 NS_IMETHODIMP
323 nsPK11Token::GetAskPasswordTimes(int32_t *rvAskTimes)
324 {
325 nsNSSShutDownPreventionLock locker;
326 if (isAlreadyShutDown())
327 return NS_ERROR_NOT_AVAILABLE;
328
329 int askTimes, askTimeout;
330 PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
331 *rvAskTimes = askTimes;
332 return NS_OK;
333 }
334
335 /* long getAskPasswordTimeout(); */
336 NS_IMETHODIMP
337 nsPK11Token::GetAskPasswordTimeout(int32_t *rvAskTimeout)
338 {
339 nsNSSShutDownPreventionLock locker;
340 if (isAlreadyShutDown())
341 return NS_ERROR_NOT_AVAILABLE;
342
343 int askTimes, askTimeout;
344 PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
345 *rvAskTimeout = askTimeout;
346 return NS_OK;
347 }
348
349 /* void setAskPasswordDefaults(in unsigned long askTimes,
350 * in unsigned long timeout);
351 */
352 NS_IMETHODIMP
353 nsPK11Token::SetAskPasswordDefaults(const int32_t askTimes,
354 const int32_t askTimeout)
355 {
356 nsNSSShutDownPreventionLock locker;
357 if (isAlreadyShutDown())
358 return NS_ERROR_NOT_AVAILABLE;
359
360 PK11_SetSlotPWValues(mSlot, askTimes, askTimeout);
361 return NS_OK;
362 }
363
364 /* void changePassword (in wstring oldPassword, in wstring newPassword); */
365 NS_IMETHODIMP nsPK11Token::ChangePassword(const char16_t *oldPassword, const char16_t *newPassword)
366 {
367 nsNSSShutDownPreventionLock locker;
368 if (isAlreadyShutDown())
369 return NS_ERROR_NOT_AVAILABLE;
370
371 SECStatus rv;
372 NS_ConvertUTF16toUTF8 aUtf8OldPassword(oldPassword);
373 NS_ConvertUTF16toUTF8 aUtf8NewPassword(newPassword);
374
375 rv = PK11_ChangePW(mSlot,
376 (oldPassword ? const_cast<char *>(aUtf8OldPassword.get()) : nullptr),
377 (newPassword ? const_cast<char *>(aUtf8NewPassword.get()) : nullptr));
378 return (rv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
379 }
380
381 /* boolean isHardwareToken (); */
382 NS_IMETHODIMP nsPK11Token::IsHardwareToken(bool *_retval)
383 {
384 nsNSSShutDownPreventionLock locker;
385 if (isAlreadyShutDown())
386 return NS_ERROR_NOT_AVAILABLE;
387
388 nsresult rv = NS_OK;
389
390 *_retval = PK11_IsHW(mSlot);
391
392 return rv;
393 }
394
395 /* boolean needsLogin (); */
396 NS_IMETHODIMP nsPK11Token::NeedsLogin(bool *_retval)
397 {
398 nsNSSShutDownPreventionLock locker;
399 if (isAlreadyShutDown())
400 return NS_ERROR_NOT_AVAILABLE;
401
402 nsresult rv = NS_OK;
403
404 *_retval = PK11_NeedLogin(mSlot);
405
406 return rv;
407 }
408
409 /* boolean isFriendly (); */
410 NS_IMETHODIMP nsPK11Token::IsFriendly(bool *_retval)
411 {
412 nsNSSShutDownPreventionLock locker;
413 if (isAlreadyShutDown())
414 return NS_ERROR_NOT_AVAILABLE;
415
416 nsresult rv = NS_OK;
417
418 *_retval = PK11_IsFriendly(mSlot);
419
420 return rv;
421 }
422
423 /*=========================================================*/
424
425 NS_IMPL_ISUPPORTS(nsPK11TokenDB, nsIPK11TokenDB)
426
427 nsPK11TokenDB::nsPK11TokenDB()
428 {
429 /* member initializers and constructor code */
430 }
431
432 nsPK11TokenDB::~nsPK11TokenDB()
433 {
434 /* destructor code */
435 }
436
437 /* nsIPK11Token getInternalKeyToken (); */
438 NS_IMETHODIMP nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token **_retval)
439 {
440 nsNSSShutDownPreventionLock locker;
441 nsresult rv = NS_OK;
442 PK11SlotInfo *slot = 0;
443 nsCOMPtr<nsIPK11Token> token;
444
445 slot = PK11_GetInternalKeySlot();
446 if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
447
448 token = new nsPK11Token(slot);
449 *_retval = token;
450 NS_ADDREF(*_retval);
451
452 done:
453 if (slot) PK11_FreeSlot(slot);
454 return rv;
455 }
456
457 /* nsIPK11Token findTokenByName (in wchar tokenName); */
458 NS_IMETHODIMP nsPK11TokenDB::
459 FindTokenByName(const char16_t* tokenName, nsIPK11Token **_retval)
460 {
461 nsNSSShutDownPreventionLock locker;
462 nsresult rv = NS_OK;
463 PK11SlotInfo *slot = 0;
464 NS_ConvertUTF16toUTF8 aUtf8TokenName(tokenName);
465 slot = PK11_FindSlotByName(const_cast<char*>(aUtf8TokenName.get()));
466 if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
467
468 *_retval = new nsPK11Token(slot);
469 NS_ADDREF(*_retval);
470
471 done:
472 if (slot) PK11_FreeSlot(slot);
473 return rv;
474 }
475
476 /* nsIEnumerator listTokens (); */
477 NS_IMETHODIMP nsPK11TokenDB::ListTokens(nsIEnumerator* *_retval)
478 {
479 nsNSSShutDownPreventionLock locker;
480 nsCOMPtr<nsISupportsArray> array;
481 PK11SlotList *list = 0;
482 PK11SlotListElement *le;
483
484 *_retval = nullptr;
485 nsresult rv = NS_NewISupportsArray(getter_AddRefs(array));
486 if (NS_FAILED(rv)) { goto done; }
487
488 /* List all tokens, creating PK11Token objects and putting them
489 * into the array.
490 */
491 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, false, false, 0);
492 if (!list) { rv = NS_ERROR_FAILURE; goto done; }
493
494 for (le = PK11_GetFirstSafe(list); le; le = PK11_GetNextSafe(list, le, false)) {
495 nsCOMPtr<nsIPK11Token> token = new nsPK11Token(le->slot);
496 rv = array->AppendElement(token);
497 if (NS_FAILED(rv)) {
498 PK11_FreeSlotListElement(list, le);
499 rv = NS_ERROR_OUT_OF_MEMORY;
500 goto done;
501 }
502 }
503
504 rv = array->Enumerate(_retval);
505
506 done:
507 if (list) PK11_FreeSlotList(list);
508 return rv;
509 }
510

mercurial