|
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 |