Import 1.9b4 NSS tag from cvs
[mozilla-nss.git] / security / nss / lib / pk11wrap / pk11auth.c
blobef45b152c599967a0b1899da0968ed576739e267
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 * This file deals with PKCS #11 passwords and authentication.
39 #include "seccomon.h"
40 #include "secmod.h"
41 #include "secmodi.h"
42 #include "secmodti.h"
43 #include "pkcs11t.h"
44 #include "pk11func.h"
45 #include "secitem.h"
46 #include "secerr.h"
48 #include "pkim.h"
51 /*************************************************************
52 * local static and global data
53 *************************************************************/
55 * This structure keeps track of status that spans all the Slots.
56 * NOTE: This is a global data structure. It semantics expect thread crosstalk
57 * be very careful when you see it used.
58 * It's major purpose in life is to allow the user to log in one PER
59 * Tranaction, even if a transaction spans threads. The problem is the user
60 * may have to enter a password one just to be able to look at the
61 * personalities/certificates (s)he can use. Then if Auth every is one, they
62 * may have to enter the password again to use the card. See PK11_StartTransac
63 * and PK11_EndTransaction.
65 static struct PK11GlobalStruct {
66 int transaction;
67 PRBool inTransaction;
68 char *(PR_CALLBACK *getPass)(PK11SlotInfo *,PRBool,void *);
69 PRBool (PR_CALLBACK *verifyPass)(PK11SlotInfo *,void *);
70 PRBool (PR_CALLBACK *isLoggedIn)(PK11SlotInfo *,void *);
71 } PK11_Global = { 1, PR_FALSE, NULL, NULL, NULL };
73 /***********************************************************
74 * Password Utilities
75 ***********************************************************/
77 * Check the user's password. Log into the card if it's correct.
78 * succeed if the user is already logged in.
80 SECStatus
81 pk11_CheckPassword(PK11SlotInfo *slot,char *pw)
83 int len = 0;
84 CK_RV crv;
85 SECStatus rv;
86 int64 currtime = PR_Now();
87 PRBool mustRetry;
88 int retry = 0;
90 if (slot->protectedAuthPath) {
91 len = 0;
92 pw = NULL;
93 } else if (pw == NULL) {
94 PORT_SetError(SEC_ERROR_INVALID_ARGS);
95 return SECFailure;
96 } else {
97 len = PORT_Strlen(pw);
100 do {
101 PK11_EnterSlotMonitor(slot);
102 crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
103 (unsigned char *)pw,len);
104 slot->lastLoginCheck = 0;
105 mustRetry = PR_FALSE;
106 PK11_ExitSlotMonitor(slot);
107 switch (crv) {
108 /* if we're already logged in, we're good to go */
109 case CKR_OK:
110 slot->authTransact = PK11_Global.transaction;
111 /* Fall through */
112 case CKR_USER_ALREADY_LOGGED_IN:
113 slot->authTime = currtime;
114 rv = SECSuccess;
115 break;
116 case CKR_PIN_INCORRECT:
117 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
118 rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
119 break;
120 /* someone called reset while we fetched the password, try again once
121 * if the token is still there. */
122 case CKR_SESSION_HANDLE_INVALID:
123 case CKR_SESSION_CLOSED:
124 if (retry++ == 0) {
125 rv = PK11_InitToken(slot,PR_FALSE);
126 if (rv == SECSuccess) {
127 if (slot->session != CK_INVALID_SESSION) {
128 mustRetry = PR_TRUE;
129 } else {
130 PORT_SetError(PK11_MapError(crv));
131 rv = SECFailure;
134 break;
136 /* Fall through */
137 default:
138 PORT_SetError(PK11_MapError(crv));
139 rv = SECFailure; /* some failure we can't fix by retrying */
141 } while (mustRetry);
142 return rv;
146 * Check the user's password. Logout before hand to make sure that
147 * we are really checking the password.
149 SECStatus
150 PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw)
152 int len = 0;
153 CK_RV crv;
154 SECStatus rv;
155 int64 currtime = PR_Now();
157 if (slot->protectedAuthPath) {
158 len = 0;
159 pw = NULL;
160 } else if (pw == NULL) {
161 PORT_SetError(SEC_ERROR_INVALID_ARGS);
162 return SECFailure;
163 } else {
164 len = PORT_Strlen(pw);
167 /* force a logout */
168 PK11_EnterSlotMonitor(slot);
169 PK11_GETTAB(slot)->C_Logout(slot->session);
171 crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
172 (unsigned char *)pw,len);
173 slot->lastLoginCheck = 0;
174 PK11_ExitSlotMonitor(slot);
175 switch (crv) {
176 /* if we're already logged in, we're good to go */
177 case CKR_OK:
178 slot->authTransact = PK11_Global.transaction;
179 slot->authTime = currtime;
180 rv = SECSuccess;
181 break;
182 case CKR_PIN_INCORRECT:
183 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
184 rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
185 break;
186 default:
187 PORT_SetError(PK11_MapError(crv));
188 rv = SECFailure; /* some failure we can't fix by retrying */
190 return rv;
193 SECStatus
194 PK11_Logout(PK11SlotInfo *slot)
196 CK_RV crv;
198 /* force a logout */
199 PK11_EnterSlotMonitor(slot);
200 crv = PK11_GETTAB(slot)->C_Logout(slot->session);
201 slot->lastLoginCheck = 0;
202 PK11_ExitSlotMonitor(slot);
203 if (crv != CKR_OK) {
204 PORT_SetError(PK11_MapError(crv));
205 return SECFailure;
207 return SECSuccess;
211 * transaction stuff is for when we test for the need to do every
212 * time auth to see if we already did it for this slot/transaction
214 void PK11_StartAuthTransaction(void)
216 PK11_Global.transaction++;
217 PK11_Global.inTransaction = PR_TRUE;
220 void PK11_EndAuthTransaction(void)
222 PK11_Global.transaction++;
223 PK11_Global.inTransaction = PR_FALSE;
227 * before we do a private key op, we check to see if we
228 * need to reauthenticate.
230 void
231 PK11_HandlePasswordCheck(PK11SlotInfo *slot,void *wincx)
233 int askpw = slot->askpw;
234 PRBool NeedAuth = PR_FALSE;
236 if (!slot->needLogin) return;
238 if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
239 PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
241 if (def_slot) {
242 askpw = def_slot->askpw;
243 PK11_FreeSlot(def_slot);
247 /* timeouts are handled by isLoggedIn */
248 if (!PK11_IsLoggedIn(slot,wincx)) {
249 NeedAuth = PR_TRUE;
250 } else if (askpw == -1) {
251 if (!PK11_Global.inTransaction ||
252 (PK11_Global.transaction != slot->authTransact)) {
253 PK11_EnterSlotMonitor(slot);
254 PK11_GETTAB(slot)->C_Logout(slot->session);
255 slot->lastLoginCheck = 0;
256 PK11_ExitSlotMonitor(slot);
257 NeedAuth = PR_TRUE;
260 if (NeedAuth) PK11_DoPassword(slot,PR_TRUE,wincx);
263 void
264 PK11_SlotDBUpdate(PK11SlotInfo *slot)
266 SECMOD_UpdateModule(slot->module);
270 * set new askpw and timeout values
272 void
273 PK11_SetSlotPWValues(PK11SlotInfo *slot,int askpw, int timeout)
275 slot->askpw = askpw;
276 slot->timeout = timeout;
277 slot->defaultFlags |= PK11_OWN_PW_DEFAULTS;
278 PK11_SlotDBUpdate(slot);
282 * Get the askpw and timeout values for this slot
284 void
285 PK11_GetSlotPWValues(PK11SlotInfo *slot,int *askpw, int *timeout)
287 *askpw = slot->askpw;
288 *timeout = slot->timeout;
290 if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
291 PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
293 if (def_slot) {
294 *askpw = def_slot->askpw;
295 *timeout = def_slot->timeout;
296 PK11_FreeSlot(def_slot);
302 * Returns true if the token is needLogin and isn't logged in.
303 * This function is used to determine if authentication is needed
304 * before attempting a potentially privelleged operation.
306 PRBool
307 pk11_LoginStillRequired(PK11SlotInfo *slot, void *wincx)
309 return slot->needLogin && !PK11_IsLoggedIn(slot,wincx);
313 * make sure a slot is authenticated...
314 * This function only does the authentication if it is needed.
316 SECStatus
317 PK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) {
318 if (pk11_LoginStillRequired(slot,wincx)) {
319 return PK11_DoPassword(slot,loadCerts,wincx);
321 return SECSuccess;
325 * Authenticate to "unfriendly" tokens (tokens which need to be logged
326 * in to find the certs.
328 SECStatus
329 pk11_AuthenticateUnfriendly(PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
331 SECStatus rv = SECSuccess;
332 if (!PK11_IsFriendly(slot)) {
333 rv = PK11_Authenticate(slot, loadCerts, wincx);
335 return rv;
340 * NOTE: this assumes that we are logged out of the card before hand
342 SECStatus
343 PK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw)
345 CK_SESSION_HANDLE rwsession;
346 CK_RV crv;
347 SECStatus rv = SECFailure;
348 int len = 0;
350 /* get a rwsession */
351 rwsession = PK11_GetRWSession(slot);
352 if (rwsession == CK_INVALID_SESSION) {
353 PORT_SetError(SEC_ERROR_BAD_DATA);
354 return rv;
357 if (slot->protectedAuthPath) {
358 len = 0;
359 ssopw = NULL;
360 } else if (ssopw == NULL) {
361 PORT_SetError(SEC_ERROR_INVALID_ARGS);
362 return SECFailure;
363 } else {
364 len = PORT_Strlen(ssopw);
367 /* check the password */
368 crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,
369 (unsigned char *)ssopw,len);
370 slot->lastLoginCheck = 0;
371 switch (crv) {
372 /* if we're already logged in, we're good to go */
373 case CKR_OK:
374 rv = SECSuccess;
375 break;
376 case CKR_PIN_INCORRECT:
377 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
378 rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
379 break;
380 default:
381 PORT_SetError(PK11_MapError(crv));
382 rv = SECFailure; /* some failure we can't fix by retrying */
384 PK11_GETTAB(slot)->C_Logout(rwsession);
385 slot->lastLoginCheck = 0;
387 /* release rwsession */
388 PK11_RestoreROSession(slot,rwsession);
389 return rv;
393 * make sure the password conforms to your token's requirements.
395 SECStatus
396 PK11_VerifyPW(PK11SlotInfo *slot,char *pw)
398 int len = PORT_Strlen(pw);
400 if ((slot->minPassword > len) || (slot->maxPassword < len)) {
401 PORT_SetError(SEC_ERROR_BAD_DATA);
402 return SECFailure;
404 return SECSuccess;
408 * initialize a user PIN Value
410 SECStatus
411 PK11_InitPin(PK11SlotInfo *slot, const char *ssopw, const char *userpw)
413 CK_SESSION_HANDLE rwsession = CK_INVALID_SESSION;
414 CK_RV crv;
415 SECStatus rv = SECFailure;
416 int len;
417 int ssolen;
419 if (userpw == NULL) userpw = "";
420 if (ssopw == NULL) ssopw = "";
422 len = PORT_Strlen(userpw);
423 ssolen = PORT_Strlen(ssopw);
425 /* get a rwsession */
426 rwsession = PK11_GetRWSession(slot);
427 if (rwsession == CK_INVALID_SESSION) {
428 PORT_SetError(SEC_ERROR_BAD_DATA);
429 slot->lastLoginCheck = 0;
430 return rv;
433 if (slot->protectedAuthPath) {
434 len = 0;
435 ssolen = 0;
436 ssopw = NULL;
437 userpw = NULL;
440 /* check the password */
441 crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,
442 (unsigned char *)ssopw,ssolen);
443 slot->lastLoginCheck = 0;
444 if (crv != CKR_OK) {
445 PORT_SetError(PK11_MapError(crv));
446 goto done;
449 crv = PK11_GETTAB(slot)->C_InitPIN(rwsession,(unsigned char *)userpw,len);
450 if (crv != CKR_OK) {
451 PORT_SetError(PK11_MapError(crv));
452 } else {
453 rv = SECSuccess;
456 done:
457 PK11_GETTAB(slot)->C_Logout(rwsession);
458 slot->lastLoginCheck = 0;
459 PK11_RestoreROSession(slot,rwsession);
460 if (rv == SECSuccess) {
461 /* update our view of the world */
462 PK11_InitToken(slot,PR_TRUE);
463 PK11_EnterSlotMonitor(slot);
464 PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
465 (unsigned char *)userpw,len);
466 slot->lastLoginCheck = 0;
467 PK11_ExitSlotMonitor(slot);
469 return rv;
473 * Change an existing user password
475 SECStatus
476 PK11_ChangePW(PK11SlotInfo *slot, const char *oldpw, const char *newpw)
478 CK_RV crv;
479 SECStatus rv = SECFailure;
480 int newLen;
481 int oldLen;
482 CK_SESSION_HANDLE rwsession;
484 if (newpw == NULL) newpw = "";
485 if (oldpw == NULL) oldpw = "";
486 newLen = PORT_Strlen(newpw);
487 oldLen = PORT_Strlen(oldpw);
489 /* get a rwsession */
490 rwsession = PK11_GetRWSession(slot);
491 if (rwsession == CK_INVALID_SESSION) {
492 PORT_SetError(SEC_ERROR_BAD_DATA);
493 return rv;
496 crv = PK11_GETTAB(slot)->C_SetPIN(rwsession,
497 (unsigned char *)oldpw,oldLen,(unsigned char *)newpw,newLen);
498 if (crv == CKR_OK) {
499 rv = SECSuccess;
500 } else {
501 PORT_SetError(PK11_MapError(crv));
504 PK11_RestoreROSession(slot,rwsession);
506 /* update our view of the world */
507 PK11_InitToken(slot,PR_TRUE);
508 return rv;
511 static char *
512 pk11_GetPassword(PK11SlotInfo *slot, PRBool retry, void * wincx)
514 if (PK11_Global.getPass == NULL) return NULL;
515 return (*PK11_Global.getPass)(slot, retry, wincx);
518 void
519 PK11_SetPasswordFunc(PK11PasswordFunc func)
521 PK11_Global.getPass = func;
524 void
525 PK11_SetVerifyPasswordFunc(PK11VerifyPasswordFunc func)
527 PK11_Global.verifyPass = func;
530 void
531 PK11_SetIsLoggedInFunc(PK11IsLoggedInFunc func)
533 PK11_Global.isLoggedIn = func;
538 * authenticate to a slot. This loops until we can't recover, the user
539 * gives up, or we succeed. If we're already logged in and this function
540 * is called we will still prompt for a password, but we will probably
541 * succeed no matter what the password was (depending on the implementation
542 * of the PKCS 11 module.
544 SECStatus
545 PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
547 SECStatus rv = SECFailure;
548 char * password;
549 PRBool attempt = PR_FALSE;
551 if (PK11_NeedUserInit(slot)) {
552 PORT_SetError(SEC_ERROR_IO);
553 return SECFailure;
558 * Central server type applications which control access to multiple
559 * slave applications to single crypto devices need to virtuallize the
560 * login state. This is done by a callback out of PK11_IsLoggedIn and
561 * here. If we are actually logged in, then we got here because the
562 * higher level code told us that the particular client application may
563 * still need to be logged in. If that is the case, we simply tell the
564 * server code that it should now verify the clients password and tell us
565 * the results.
567 if (PK11_IsLoggedIn(slot,NULL) &&
568 (PK11_Global.verifyPass != NULL)) {
569 if (!PK11_Global.verifyPass(slot,wincx)) {
570 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
571 return SECFailure;
573 return SECSuccess;
576 /* get the password. This can drop out of the while loop
577 * for the following reasons:
578 * (1) the user refused to enter a password.
579 * (return error to caller)
580 * (2) the token user password is disabled [usually due to
581 * too many failed authentication attempts].
582 * (return error to caller)
583 * (3) the password was successful.
585 while ((password = pk11_GetPassword(slot, attempt, wincx)) != NULL) {
586 /* if the token has a protectedAuthPath, the application may have
587 * already issued the C_Login as part of it's pk11_GetPassword call.
588 * In this case the application will tell us what the results were in
589 * the password value (retry or the authentication was successful) so
590 * we can skip our own C_Login call (which would force the token to
591 * try to login again).
593 * Applications that don't know about protectedAuthPath will return a
594 * password, which we will ignore and trigger the token to
595 * 'authenticate' itself anyway. Hopefully the blinking display on
596 * the reader, or the flashing light under the thumbprint reader will
597 * attract the user's attention */
598 attempt = PR_TRUE;
599 if (slot->protectedAuthPath) {
600 /* application tried to authenticate and failed. it wants to try
601 * again, continue looping */
602 if (strcmp(password, PK11_PW_RETRY) == 0) {
603 rv = SECWouldBlock;
604 PORT_Free(password);
605 continue;
607 /* applicaton tried to authenticate and succeeded we're done */
608 if (strcmp(password, PK11_PW_AUTHENTICATED) == 0) {
609 rv = SECSuccess;
610 PORT_Free(password);
611 break;
614 rv = pk11_CheckPassword(slot,password);
615 PORT_Memset(password, 0, PORT_Strlen(password));
616 PORT_Free(password);
617 if (rv != SECWouldBlock) break;
619 if (rv == SECSuccess) {
620 rv = pk11_CheckVerifyTest(slot);
621 if (!PK11_IsFriendly(slot)) {
622 nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain,
623 slot->nssToken);
625 } else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD);
626 return rv;
629 void PK11_LogoutAll(void)
631 SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
632 SECMODModuleList *modList = SECMOD_GetDefaultModuleList();
633 SECMODModuleList *mlp = NULL;
634 int i;
636 /* NSS is not initialized, there are not tokens to log out */
637 if (lock == NULL) {
638 return;
641 SECMOD_GetReadLock(lock);
642 /* find the number of entries */
643 for (mlp = modList; mlp != NULL; mlp = mlp->next) {
644 for (i=0; i < mlp->module->slotCount; i++) {
645 PK11_Logout(mlp->module->slots[i]);
649 SECMOD_ReleaseReadLock(lock);
653 PK11_GetMinimumPwdLength(PK11SlotInfo *slot)
655 return ((int)slot->minPassword);
658 /* Does this slot have a protected pin path? */
659 PRBool
660 PK11_ProtectedAuthenticationPath(PK11SlotInfo *slot)
662 return slot->protectedAuthPath;
666 * we can initialize the password if 1) The toke is not inited
667 * (need login == true and see need UserInit) or 2) the token has
668 * a NULL password. (slot->needLogin = false & need user Init = false).
670 PRBool PK11_NeedPWInitForSlot(PK11SlotInfo *slot)
672 if (slot->needLogin && PK11_NeedUserInit(slot)) {
673 return PR_TRUE;
675 if (!slot->needLogin && !PK11_NeedUserInit(slot)) {
676 return PR_TRUE;
678 return PR_FALSE;
681 PRBool PK11_NeedPWInit()
683 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
684 PRBool ret = PK11_NeedPWInitForSlot(slot);
686 PK11_FreeSlot(slot);
687 return ret;
690 PRBool
691 pk11_InDelayPeriod(PRIntervalTime lastTime, PRIntervalTime delayTime,
692 PRIntervalTime *retTime)
694 PRIntervalTime time;
696 *retTime = time = PR_IntervalNow();
697 return (PRBool) (lastTime) && ((time-lastTime) < delayTime);
701 * Determine if the token is logged in. We have to actually query the token,
702 * because it's state can change without intervention from us.
704 PRBool
705 PK11_IsLoggedIn(PK11SlotInfo *slot,void *wincx)
707 CK_SESSION_INFO sessionInfo;
708 int askpw = slot->askpw;
709 int timeout = slot->timeout;
710 CK_RV crv;
711 PRIntervalTime curTime;
712 static PRIntervalTime login_delay_time = 0;
714 if (login_delay_time == 0) {
715 login_delay_time = PR_SecondsToInterval(1);
718 /* If we don't have our own password default values, use the system
719 * ones */
720 if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
721 PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
723 if (def_slot) {
724 askpw = def_slot->askpw;
725 timeout = def_slot->timeout;
726 PK11_FreeSlot(def_slot);
730 if ((wincx != NULL) && (PK11_Global.isLoggedIn != NULL) &&
731 (*PK11_Global.isLoggedIn)(slot, wincx) == PR_FALSE) { return PR_FALSE; }
734 /* forget the password if we've been inactive too long */
735 if (askpw == 1) {
736 int64 currtime = PR_Now();
737 int64 result;
738 int64 mult;
740 LL_I2L(result, timeout);
741 LL_I2L(mult, 60*1000*1000);
742 LL_MUL(result,result,mult);
743 LL_ADD(result, result, slot->authTime);
744 if (LL_CMP(result, <, currtime) ) {
745 PK11_EnterSlotMonitor(slot);
746 PK11_GETTAB(slot)->C_Logout(slot->session);
747 slot->lastLoginCheck = 0;
748 PK11_ExitSlotMonitor(slot);
749 } else {
750 slot->authTime = currtime;
754 PK11_EnterSlotMonitor(slot);
755 if (pk11_InDelayPeriod(slot->lastLoginCheck,login_delay_time, &curTime)) {
756 sessionInfo.state = slot->lastState;
757 crv = CKR_OK;
758 } else {
759 crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session,&sessionInfo);
760 if (crv == CKR_OK) {
761 slot->lastState = sessionInfo.state;
762 slot->lastLoginCheck = curTime;
765 PK11_ExitSlotMonitor(slot);
766 /* if we can't get session info, something is really wrong */
767 if (crv != CKR_OK) {
768 slot->session = CK_INVALID_SESSION;
769 return PR_FALSE;
772 switch (sessionInfo.state) {
773 case CKS_RW_PUBLIC_SESSION:
774 case CKS_RO_PUBLIC_SESSION:
775 default:
776 break; /* fail */
777 case CKS_RW_USER_FUNCTIONS:
778 case CKS_RW_SO_FUNCTIONS:
779 case CKS_RO_USER_FUNCTIONS:
780 return PR_TRUE;
782 return PR_FALSE;