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

Side by Side Diff: nss/lib/pk11wrap/pk11auth.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 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
« no previous file with comments | « nss/lib/pk11wrap/pk11akey.c ('k') | nss/lib/pk11wrap/pk11cert.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /*
5 * This file deals with PKCS #11 passwords and authentication.
6 */
7 #include "seccomon.h"
8 #include "secmod.h"
9 #include "secmodi.h"
10 #include "secmodti.h"
11 #include "pkcs11t.h"
12 #include "pk11func.h"
13 #include "secitem.h"
14 #include "secerr.h"
15
16 #include "pkim.h"
17
18
19 /*************************************************************
20 * local static and global data
21 *************************************************************/
22 /*
23 * This structure keeps track of status that spans all the Slots.
24 * NOTE: This is a global data structure. It semantics expect thread crosstalk
25 * be very careful when you see it used.
26 * It's major purpose in life is to allow the user to log in one PER
27 * Tranaction, even if a transaction spans threads. The problem is the user
28 * may have to enter a password one just to be able to look at the
29 * personalities/certificates (s)he can use. Then if Auth every is one, they
30 * may have to enter the password again to use the card. See PK11_StartTransac
31 * and PK11_EndTransaction.
32 */
33 static struct PK11GlobalStruct {
34 int transaction;
35 PRBool inTransaction;
36 char *(PR_CALLBACK *getPass)(PK11SlotInfo *,PRBool,void *);
37 PRBool (PR_CALLBACK *verifyPass)(PK11SlotInfo *,void *);
38 PRBool (PR_CALLBACK *isLoggedIn)(PK11SlotInfo *,void *);
39 } PK11_Global = { 1, PR_FALSE, NULL, NULL, NULL };
40
41 /***********************************************************
42 * Password Utilities
43 ***********************************************************/
44 /*
45 * Check the user's password. Log into the card if it's correct.
46 * succeed if the user is already logged in.
47 */
48 static SECStatus
49 pk11_CheckPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
50 char *pw, PRBool alreadyLocked, PRBool contextSpecific)
51 {
52 int len = 0;
53 CK_RV crv;
54 SECStatus rv;
55 PRTime currtime = PR_Now();
56 PRBool mustRetry;
57 int retry = 0;
58
59 if (slot->protectedAuthPath) {
60 len = 0;
61 pw = NULL;
62 } else if (pw == NULL) {
63 PORT_SetError(SEC_ERROR_INVALID_ARGS);
64 return SECFailure;
65 } else {
66 len = PORT_Strlen(pw);
67 }
68
69 do {
70 if (!alreadyLocked) PK11_EnterSlotMonitor(slot);
71 crv = PK11_GETTAB(slot)->C_Login(session,
72 contextSpecific ? CKU_CONTEXT_SPECIFIC : CKU_USER,
73 (unsigned char *)pw,len);
74 slot->lastLoginCheck = 0;
75 mustRetry = PR_FALSE;
76 if (!alreadyLocked) PK11_ExitSlotMonitor(slot);
77 switch (crv) {
78 /* if we're already logged in, we're good to go */
79 case CKR_OK:
80 /* TODO If it was for CKU_CONTEXT_SPECIFIC should we do this */
81 slot->authTransact = PK11_Global.transaction;
82 /* Fall through */
83 case CKR_USER_ALREADY_LOGGED_IN:
84 slot->authTime = currtime;
85 rv = SECSuccess;
86 break;
87 case CKR_PIN_INCORRECT:
88 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
89 rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
90 break;
91 /* someone called reset while we fetched the password, try again once
92 * if the token is still there. */
93 case CKR_SESSION_HANDLE_INVALID:
94 case CKR_SESSION_CLOSED:
95 if (session != slot->session) {
96 /* don't bother retrying, we were in a middle of an operation,
97 * which is now lost. Just fail. */
98 PORT_SetError(PK11_MapError(crv));
99 rv = SECFailure;
100 break;
101 }
102 if (retry++ == 0) {
103 rv = PK11_InitToken(slot,PR_FALSE);
104 if (rv == SECSuccess) {
105 if (slot->session != CK_INVALID_SESSION) {
106 session = slot->session; /* we should have
107 * a new session now */
108 mustRetry = PR_TRUE;
109 } else {
110 PORT_SetError(PK11_MapError(crv));
111 rv = SECFailure;
112 }
113 }
114 break;
115 }
116 /* Fall through */
117 default:
118 PORT_SetError(PK11_MapError(crv));
119 rv = SECFailure; /* some failure we can't fix by retrying */
120 }
121 } while (mustRetry);
122 return rv;
123 }
124
125 /*
126 * Check the user's password. Logout before hand to make sure that
127 * we are really checking the password.
128 */
129 SECStatus
130 PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw)
131 {
132 int len = 0;
133 CK_RV crv;
134 SECStatus rv;
135 PRTime currtime = PR_Now();
136
137 if (slot->protectedAuthPath) {
138 len = 0;
139 pw = NULL;
140 } else if (pw == NULL) {
141 PORT_SetError(SEC_ERROR_INVALID_ARGS);
142 return SECFailure;
143 } else {
144 len = PORT_Strlen(pw);
145 }
146
147 /*
148 * If the token doesn't need a login, don't try to relogin because the
149 * effect is undefined. It's not clear what it means to check a non-empty
150 * password with such a token, so treat that as an error.
151 */
152 if (!slot->needLogin) {
153 if (len == 0) {
154 rv = SECSuccess;
155 } else {
156 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
157 rv = SECFailure;
158 }
159 return rv;
160 }
161
162 /* force a logout */
163 PK11_EnterSlotMonitor(slot);
164 PK11_GETTAB(slot)->C_Logout(slot->session);
165
166 crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
167 (unsigned char *)pw,len);
168 slot->lastLoginCheck = 0;
169 PK11_ExitSlotMonitor(slot);
170 switch (crv) {
171 /* if we're already logged in, we're good to go */
172 case CKR_OK:
173 slot->authTransact = PK11_Global.transaction;
174 slot->authTime = currtime;
175 rv = SECSuccess;
176 break;
177 case CKR_PIN_INCORRECT:
178 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
179 rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
180 break;
181 default:
182 PORT_SetError(PK11_MapError(crv));
183 rv = SECFailure; /* some failure we can't fix by retrying */
184 }
185 return rv;
186 }
187
188 SECStatus
189 PK11_Logout(PK11SlotInfo *slot)
190 {
191 CK_RV crv;
192
193 /* force a logout */
194 PK11_EnterSlotMonitor(slot);
195 crv = PK11_GETTAB(slot)->C_Logout(slot->session);
196 slot->lastLoginCheck = 0;
197 PK11_ExitSlotMonitor(slot);
198 if (crv != CKR_OK) {
199 PORT_SetError(PK11_MapError(crv));
200 return SECFailure;
201 }
202 return SECSuccess;
203 }
204
205 /*
206 * transaction stuff is for when we test for the need to do every
207 * time auth to see if we already did it for this slot/transaction
208 */
209 void PK11_StartAuthTransaction(void)
210 {
211 PK11_Global.transaction++;
212 PK11_Global.inTransaction = PR_TRUE;
213 }
214
215 void PK11_EndAuthTransaction(void)
216 {
217 PK11_Global.transaction++;
218 PK11_Global.inTransaction = PR_FALSE;
219 }
220
221 /*
222 * before we do a private key op, we check to see if we
223 * need to reauthenticate.
224 */
225 void
226 PK11_HandlePasswordCheck(PK11SlotInfo *slot,void *wincx)
227 {
228 int askpw = slot->askpw;
229 PRBool NeedAuth = PR_FALSE;
230
231 if (!slot->needLogin) return;
232
233 if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
234 PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
235
236 if (def_slot) {
237 askpw = def_slot->askpw;
238 PK11_FreeSlot(def_slot);
239 }
240 }
241
242 /* timeouts are handled by isLoggedIn */
243 if (!PK11_IsLoggedIn(slot,wincx)) {
244 NeedAuth = PR_TRUE;
245 } else if (askpw == -1) {
246 if (!PK11_Global.inTransaction ||
247 (PK11_Global.transaction != slot->authTransact)) {
248 PK11_EnterSlotMonitor(slot);
249 PK11_GETTAB(slot)->C_Logout(slot->session);
250 slot->lastLoginCheck = 0;
251 PK11_ExitSlotMonitor(slot);
252 NeedAuth = PR_TRUE;
253 }
254 }
255 if (NeedAuth) PK11_DoPassword(slot, slot->session, PR_TRUE,
256 wincx, PR_FALSE, PR_FALSE);
257 }
258
259 void
260 PK11_SlotDBUpdate(PK11SlotInfo *slot)
261 {
262 SECMOD_UpdateModule(slot->module);
263 }
264
265 /*
266 * set new askpw and timeout values
267 */
268 void
269 PK11_SetSlotPWValues(PK11SlotInfo *slot,int askpw, int timeout)
270 {
271 slot->askpw = askpw;
272 slot->timeout = timeout;
273 slot->defaultFlags |= PK11_OWN_PW_DEFAULTS;
274 PK11_SlotDBUpdate(slot);
275 }
276
277 /*
278 * Get the askpw and timeout values for this slot
279 */
280 void
281 PK11_GetSlotPWValues(PK11SlotInfo *slot,int *askpw, int *timeout)
282 {
283 *askpw = slot->askpw;
284 *timeout = slot->timeout;
285
286 if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
287 PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
288
289 if (def_slot) {
290 *askpw = def_slot->askpw;
291 *timeout = def_slot->timeout;
292 PK11_FreeSlot(def_slot);
293 }
294 }
295 }
296
297 /*
298 * Returns true if the token is needLogin and isn't logged in.
299 * This function is used to determine if authentication is needed
300 * before attempting a potentially privelleged operation.
301 */
302 PRBool
303 pk11_LoginStillRequired(PK11SlotInfo *slot, void *wincx)
304 {
305 return slot->needLogin && !PK11_IsLoggedIn(slot,wincx);
306 }
307
308 /*
309 * make sure a slot is authenticated...
310 * This function only does the authentication if it is needed.
311 */
312 SECStatus
313 PK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) {
314 if (pk11_LoginStillRequired(slot,wincx)) {
315 return PK11_DoPassword(slot, slot->session, loadCerts, wincx,
316 PR_FALSE, PR_FALSE);
317 }
318 return SECSuccess;
319 }
320
321 /*
322 * Authenticate to "unfriendly" tokens (tokens which need to be logged
323 * in to find the certs.
324 */
325 SECStatus
326 pk11_AuthenticateUnfriendly(PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
327 {
328 SECStatus rv = SECSuccess;
329 if (!PK11_IsFriendly(slot)) {
330 rv = PK11_Authenticate(slot, loadCerts, wincx);
331 }
332 return rv;
333 }
334
335
336 /*
337 * NOTE: this assumes that we are logged out of the card before hand
338 */
339 SECStatus
340 PK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw)
341 {
342 CK_SESSION_HANDLE rwsession;
343 CK_RV crv;
344 SECStatus rv = SECFailure;
345 int len = 0;
346
347 /* get a rwsession */
348 rwsession = PK11_GetRWSession(slot);
349 if (rwsession == CK_INVALID_SESSION) {
350 PORT_SetError(SEC_ERROR_BAD_DATA);
351 return rv;
352 }
353
354 if (slot->protectedAuthPath) {
355 len = 0;
356 ssopw = NULL;
357 } else if (ssopw == NULL) {
358 PORT_SetError(SEC_ERROR_INVALID_ARGS);
359 return SECFailure;
360 } else {
361 len = PORT_Strlen(ssopw);
362 }
363
364 /* check the password */
365 crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,
366 (unsigned char *)ssopw,len);
367 slot->lastLoginCheck = 0;
368 switch (crv) {
369 /* if we're already logged in, we're good to go */
370 case CKR_OK:
371 rv = SECSuccess;
372 break;
373 case CKR_PIN_INCORRECT:
374 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
375 rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
376 break;
377 default:
378 PORT_SetError(PK11_MapError(crv));
379 rv = SECFailure; /* some failure we can't fix by retrying */
380 }
381 PK11_GETTAB(slot)->C_Logout(rwsession);
382 slot->lastLoginCheck = 0;
383
384 /* release rwsession */
385 PK11_RestoreROSession(slot,rwsession);
386 return rv;
387 }
388
389 /*
390 * make sure the password conforms to your token's requirements.
391 */
392 SECStatus
393 PK11_VerifyPW(PK11SlotInfo *slot,char *pw)
394 {
395 int len = PORT_Strlen(pw);
396
397 if ((slot->minPassword > len) || (slot->maxPassword < len)) {
398 PORT_SetError(SEC_ERROR_BAD_DATA);
399 return SECFailure;
400 }
401 return SECSuccess;
402 }
403
404 /*
405 * initialize a user PIN Value
406 */
407 SECStatus
408 PK11_InitPin(PK11SlotInfo *slot, const char *ssopw, const char *userpw)
409 {
410 CK_SESSION_HANDLE rwsession = CK_INVALID_SESSION;
411 CK_RV crv;
412 SECStatus rv = SECFailure;
413 int len;
414 int ssolen;
415
416 if (userpw == NULL) userpw = "";
417 if (ssopw == NULL) ssopw = "";
418
419 len = PORT_Strlen(userpw);
420 ssolen = PORT_Strlen(ssopw);
421
422 /* get a rwsession */
423 rwsession = PK11_GetRWSession(slot);
424 if (rwsession == CK_INVALID_SESSION) {
425 PORT_SetError(SEC_ERROR_BAD_DATA);
426 slot->lastLoginCheck = 0;
427 return rv;
428 }
429
430 if (slot->protectedAuthPath) {
431 len = 0;
432 ssolen = 0;
433 ssopw = NULL;
434 userpw = NULL;
435 }
436
437 /* check the password */
438 crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,
439 (unsigned char *)ssopw,ssolen);
440 slot->lastLoginCheck = 0;
441 if (crv != CKR_OK) {
442 PORT_SetError(PK11_MapError(crv));
443 goto done;
444 }
445
446 crv = PK11_GETTAB(slot)->C_InitPIN(rwsession,(unsigned char *)userpw,len);
447 if (crv != CKR_OK) {
448 PORT_SetError(PK11_MapError(crv));
449 } else {
450 rv = SECSuccess;
451 }
452
453 done:
454 PK11_GETTAB(slot)->C_Logout(rwsession);
455 slot->lastLoginCheck = 0;
456 PK11_RestoreROSession(slot,rwsession);
457 if (rv == SECSuccess) {
458 /* update our view of the world */
459 PK11_InitToken(slot,PR_TRUE);
460 if (slot->needLogin) {
461 PK11_EnterSlotMonitor(slot);
462 PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
463 (unsigned char *)userpw,len);
464 slot->lastLoginCheck = 0;
465 PK11_ExitSlotMonitor(slot);
466 }
467 }
468 return rv;
469 }
470
471 /*
472 * Change an existing user password
473 */
474 SECStatus
475 PK11_ChangePW(PK11SlotInfo *slot, const char *oldpw, const char *newpw)
476 {
477 CK_RV crv;
478 SECStatus rv = SECFailure;
479 int newLen = 0;
480 int oldLen = 0;
481 CK_SESSION_HANDLE rwsession;
482
483 /* use NULL values to trigger the protected authentication path */
484 if (!slot->protectedAuthPath) {
485 if (newpw == NULL) newpw = "";
486 if (oldpw == NULL) oldpw = "";
487 }
488 if (newpw) newLen = PORT_Strlen(newpw);
489 if (oldpw) oldLen = PORT_Strlen(oldpw);
490
491 /* get a rwsession */
492 rwsession = PK11_GetRWSession(slot);
493 if (rwsession == CK_INVALID_SESSION) {
494 PORT_SetError(SEC_ERROR_BAD_DATA);
495 return rv;
496 }
497
498 crv = PK11_GETTAB(slot)->C_SetPIN(rwsession,
499 (unsigned char *)oldpw,oldLen,(unsigned char *)newpw,newLen);
500 if (crv == CKR_OK) {
501 rv = SECSuccess;
502 } else {
503 PORT_SetError(PK11_MapError(crv));
504 }
505
506 PK11_RestoreROSession(slot,rwsession);
507
508 /* update our view of the world */
509 PK11_InitToken(slot,PR_TRUE);
510 return rv;
511 }
512
513 static char *
514 pk11_GetPassword(PK11SlotInfo *slot, PRBool retry, void * wincx)
515 {
516 if (PK11_Global.getPass == NULL) return NULL;
517 return (*PK11_Global.getPass)(slot, retry, wincx);
518 }
519
520 void
521 PK11_SetPasswordFunc(PK11PasswordFunc func)
522 {
523 PK11_Global.getPass = func;
524 }
525
526 void
527 PK11_SetVerifyPasswordFunc(PK11VerifyPasswordFunc func)
528 {
529 PK11_Global.verifyPass = func;
530 }
531
532 void
533 PK11_SetIsLoggedInFunc(PK11IsLoggedInFunc func)
534 {
535 PK11_Global.isLoggedIn = func;
536 }
537
538
539 /*
540 * authenticate to a slot. This loops until we can't recover, the user
541 * gives up, or we succeed. If we're already logged in and this function
542 * is called we will still prompt for a password, but we will probably
543 * succeed no matter what the password was (depending on the implementation
544 * of the PKCS 11 module.
545 */
546 SECStatus
547 PK11_DoPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
548 PRBool loadCerts, void *wincx, PRBool alreadyLocked,
549 PRBool contextSpecific)
550 {
551 SECStatus rv = SECFailure;
552 char * password;
553 PRBool attempt = PR_FALSE;
554
555 if (PK11_NeedUserInit(slot)) {
556 PORT_SetError(SEC_ERROR_IO);
557 return SECFailure;
558 }
559
560
561 /*
562 * Central server type applications which control access to multiple
563 * slave applications to single crypto devices need to virtuallize the
564 * login state. This is done by a callback out of PK11_IsLoggedIn and
565 * here. If we are actually logged in, then we got here because the
566 * higher level code told us that the particular client application may
567 * still need to be logged in. If that is the case, we simply tell the
568 * server code that it should now verify the clients password and tell us
569 * the results.
570 */
571 if (PK11_IsLoggedIn(slot,NULL) &&
572 (PK11_Global.verifyPass != NULL)) {
573 if (!PK11_Global.verifyPass(slot,wincx)) {
574 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
575 return SECFailure;
576 }
577 return SECSuccess;
578 }
579
580 /* get the password. This can drop out of the while loop
581 * for the following reasons:
582 * (1) the user refused to enter a password.
583 * (return error to caller)
584 * (2) the token user password is disabled [usually due to
585 * too many failed authentication attempts].
586 * (return error to caller)
587 * (3) the password was successful.
588 */
589 while ((password = pk11_GetPassword(slot, attempt, wincx)) != NULL) {
590 /* if the token has a protectedAuthPath, the application may have
591 * already issued the C_Login as part of it's pk11_GetPassword call.
592 * In this case the application will tell us what the results were in
593 * the password value (retry or the authentication was successful) so
594 * we can skip our own C_Login call (which would force the token to
595 * try to login again).
596 *
597 * Applications that don't know about protectedAuthPath will return a
598 * password, which we will ignore and trigger the token to
599 * 'authenticate' itself anyway. Hopefully the blinking display on
600 * the reader, or the flashing light under the thumbprint reader will
601 * attract the user's attention */
602 attempt = PR_TRUE;
603 if (slot->protectedAuthPath) {
604 /* application tried to authenticate and failed. it wants to try
605 * again, continue looping */
606 if (strcmp(password, PK11_PW_RETRY) == 0) {
607 rv = SECWouldBlock;
608 PORT_Free(password);
609 continue;
610 }
611 /* applicaton tried to authenticate and succeeded we're done */
612 if (strcmp(password, PK11_PW_AUTHENTICATED) == 0) {
613 rv = SECSuccess;
614 PORT_Free(password);
615 break;
616 }
617 }
618 rv = pk11_CheckPassword(slot, session, password,
619 alreadyLocked, contextSpecific);
620 PORT_Memset(password, 0, PORT_Strlen(password));
621 PORT_Free(password);
622 if (rv != SECWouldBlock) break;
623 }
624 if (rv == SECSuccess) {
625 if (!PK11_IsFriendly(slot)) {
626 nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain,
627 slot->nssToken);
628 }
629 } else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD);
630 return rv;
631 }
632
633 void PK11_LogoutAll(void)
634 {
635 SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
636 SECMODModuleList *modList;
637 SECMODModuleList *mlp = NULL;
638 int i;
639
640 /* NSS is not initialized, there are not tokens to log out */
641 if (lock == NULL) {
642 return;
643 }
644
645 SECMOD_GetReadLock(lock);
646 modList = SECMOD_GetDefaultModuleList();
647 /* find the number of entries */
648 for (mlp = modList; mlp != NULL; mlp = mlp->next) {
649 for (i=0; i < mlp->module->slotCount; i++) {
650 PK11_Logout(mlp->module->slots[i]);
651 }
652 }
653
654 SECMOD_ReleaseReadLock(lock);
655 }
656
657 int
658 PK11_GetMinimumPwdLength(PK11SlotInfo *slot)
659 {
660 return ((int)slot->minPassword);
661 }
662
663 /* Does this slot have a protected pin path? */
664 PRBool
665 PK11_ProtectedAuthenticationPath(PK11SlotInfo *slot)
666 {
667 return slot->protectedAuthPath;
668 }
669
670 /*
671 * we can initialize the password if 1) The toke is not inited
672 * (need login == true and see need UserInit) or 2) the token has
673 * a NULL password. (slot->needLogin = false & need user Init = false).
674 */
675 PRBool PK11_NeedPWInitForSlot(PK11SlotInfo *slot)
676 {
677 if (slot->needLogin && PK11_NeedUserInit(slot)) {
678 return PR_TRUE;
679 }
680 if (!slot->needLogin && !PK11_NeedUserInit(slot)) {
681 return PR_TRUE;
682 }
683 return PR_FALSE;
684 }
685
686 PRBool PK11_NeedPWInit()
687 {
688 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
689 PRBool ret = PK11_NeedPWInitForSlot(slot);
690
691 PK11_FreeSlot(slot);
692 return ret;
693 }
694
695 PRBool
696 pk11_InDelayPeriod(PRIntervalTime lastTime, PRIntervalTime delayTime,
697 PRIntervalTime *retTime)
698 {
699 PRIntervalTime time;
700
701 *retTime = time = PR_IntervalNow();
702 return (PRBool) (lastTime) && ((time-lastTime) < delayTime);
703 }
704
705 /*
706 * Determine if the token is logged in. We have to actually query the token,
707 * because it's state can change without intervention from us.
708 */
709 PRBool
710 PK11_IsLoggedIn(PK11SlotInfo *slot,void *wincx)
711 {
712 CK_SESSION_INFO sessionInfo;
713 int askpw = slot->askpw;
714 int timeout = slot->timeout;
715 CK_RV crv;
716 PRIntervalTime curTime;
717 static PRIntervalTime login_delay_time = 0;
718
719 if (login_delay_time == 0) {
720 login_delay_time = PR_SecondsToInterval(1);
721 }
722
723 /* If we don't have our own password default values, use the system
724 * ones */
725 if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
726 PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
727
728 if (def_slot) {
729 askpw = def_slot->askpw;
730 timeout = def_slot->timeout;
731 PK11_FreeSlot(def_slot);
732 }
733 }
734
735 if ((wincx != NULL) && (PK11_Global.isLoggedIn != NULL) &&
736 (*PK11_Global.isLoggedIn)(slot, wincx) == PR_FALSE) { return PR_FALSE; }
737
738
739 /* forget the password if we've been inactive too long */
740 if (askpw == 1) {
741 PRTime currtime = PR_Now();
742 PRTime result;
743 PRTime mult;
744
745 LL_I2L(result, timeout);
746 LL_I2L(mult, 60*1000*1000);
747 LL_MUL(result,result,mult);
748 LL_ADD(result, result, slot->authTime);
749 if (LL_CMP(result, <, currtime) ) {
750 PK11_EnterSlotMonitor(slot);
751 PK11_GETTAB(slot)->C_Logout(slot->session);
752 slot->lastLoginCheck = 0;
753 PK11_ExitSlotMonitor(slot);
754 } else {
755 slot->authTime = currtime;
756 }
757 }
758
759 PK11_EnterSlotMonitor(slot);
760 if (pk11_InDelayPeriod(slot->lastLoginCheck,login_delay_time, &curTime)) {
761 sessionInfo.state = slot->lastState;
762 crv = CKR_OK;
763 } else {
764 crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session,&sessionInfo);
765 if (crv == CKR_OK) {
766 slot->lastState = sessionInfo.state;
767 slot->lastLoginCheck = curTime;
768 }
769 }
770 PK11_ExitSlotMonitor(slot);
771 /* if we can't get session info, something is really wrong */
772 if (crv != CKR_OK) {
773 slot->session = CK_INVALID_SESSION;
774 return PR_FALSE;
775 }
776
777 switch (sessionInfo.state) {
778 case CKS_RW_PUBLIC_SESSION:
779 case CKS_RO_PUBLIC_SESSION:
780 default:
781 break; /* fail */
782 case CKS_RW_USER_FUNCTIONS:
783 case CKS_RW_SO_FUNCTIONS:
784 case CKS_RO_USER_FUNCTIONS:
785 return PR_TRUE;
786 }
787 return PR_FALSE;
788 }
OLDNEW
« no previous file with comments | « nss/lib/pk11wrap/pk11akey.c ('k') | nss/lib/pk11wrap/pk11cert.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698