first cut at password handling. todo: implement transaction-based passwords (at a higher level?)

This commit is contained in:
mcgreer%netscape.com 2001-09-19 19:08:32 +00:00
Родитель 8e3c09a895
Коммит 3763adfb6e
6 изменённых файлов: 315 добавлений и 15 удалений

Просмотреть файл

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: errorval.c,v $ $Revision: 1.1 $ $Date: 2000-03-31 19:50:11 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: errorval.c,v $ $Revision: 1.2 $ $Date: 2001-09-19 19:08:26 $ $Name: $";
#endif /* DEBUG */
/*
@ -75,3 +75,7 @@ const NSSError NSS_ERROR_INVALID_NSSOID = 25;
const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE = 26;
const NSSError NSS_ERROR_NOT_FOUND = 27;
const NSSError NSS_ERROR_INVALID_PASSWORD = 28;
const NSSError NSS_ERROR_USER_CANCELED = 29;

Просмотреть файл

@ -35,7 +35,7 @@
#define DEV_H
#ifdef DEBUG
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.3 $ $Date: 2001-09-19 19:08:28 $ $Name: $";
#endif /* DEBUG */
#ifndef DEVT_H
@ -150,21 +150,50 @@ NSSSlot_Destroy
NSSSlot *slot
);
NSS_EXTERN NSSUTF8 *
NSSSlot_GetName
(
NSSSlot *slot,
NSSArena *arenaOpt
);
NSS_EXTERN PRStatus
NSSSlot_Login
(
NSSSlot *slot
NSSSlot *slot,
PRBool asSO,
NSSCallback pwcb
);
extern const NSSError NSS_ERROR_INVALID_PASSWORD;
extern const NSSError NSS_ERROR_USER_CANCELED;
NSS_EXTERN PRStatus
NSSSlot_Logout
(
NSSSlot *slot
NSSSlot *slot,
nssSession *sessionOpt
);
#define NSSSLOT_ASK_PASSWORD_FIRST_TIME -1
#define NSSSLOT_ASK_PASSWORD_EVERY_TIME 0
NSS_EXTERN void
NSSSlot_SetPasswordDefaults
(
NSSSlot *slot,
PRInt32 askPasswordTimeout
);
NSS_EXTERN PRStatus
NSSSlot_SetPassword
(
NSSSlot *slot,
NSSCallback pwcb
);
extern const NSSError NSS_ERROR_INVALID_PASSWORD;
extern const NSSError NSS_ERROR_USER_CANCELED;
/*
* NSSSlot_IsLoggedIn
* NSSSlot_ChangePassword
*/
NSS_EXTERN nssSession *
@ -172,7 +201,7 @@ NSSSlot_CreateSession
(
NSSSlot *slot,
NSSArena *arenaOpt,
PRBool readOnly /* so far, this is the only flag used */
PRBool readWrite /* so far, this is the only flag used */
);
NSS_EXTERN NSSToken *

Просмотреть файл

@ -35,7 +35,7 @@
#define DEVT_H
#ifdef DEBUG
static const char DEVT_CVS_ID[] = "@(#) $RCSfile: devt.h,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
static const char DEVT_CVS_ID[] = "@(#) $RCSfile: devt.h,v $ $Revision: 1.3 $ $Date: 2001-09-19 19:08:29 $ $Name: $";
#endif /* DEBUG */
/*
@ -89,6 +89,13 @@ struct NSSModuleStr {
#define NSSSLOT_FLAGS_LOGIN_REQUIRED 0x0001 /* needLogin */
/*#define NSSSLOT_FLAGS_READONLY 0x0002*/ /* readOnly */
/* this should track global and per-transaction login information */
struct nssSlotAuthInfoStr
{
PRTime lastLogin;
PRInt32 askPasswordTimeout;
};
struct NSSSlotStr
{
NSSArena *arena;
@ -100,6 +107,7 @@ struct NSSSlotStr
void *epv;
CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */
PRUint32 flags;
struct nssSlotAuthInfoStr authInfo;
};
struct NSSTokenStr

Просмотреть файл

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.3 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.4 $ $Date: 2001-09-19 19:08:29 $ $Name: $";
#endif /* DEBUG */
#ifndef DEV_H
@ -182,12 +182,253 @@ NSSSlot_Destroy
return PR_SUCCESS;
}
NSS_IMPLEMENT NSSUTF8 *
NSSSlot_GetName
(
NSSSlot *slot,
NSSArena *arenaOpt
)
{
if (slot->name) {
return nssUTF8_Duplicate(slot->name, arenaOpt);
}
return (NSSUTF8 *)NULL;
}
static PRStatus
nssslot_login(NSSSlot *slot, nssSession *session,
CK_USER_TYPE userType, NSSCallback pwcb)
{
PRStatus nssrv;
PRUint32 attempts;
PRBool keepTrying;
NSSUTF8 *password = NULL;
CK_ULONG pwLen;
CK_RV ckrv;
if (!pwcb.getPW) {
/* set error INVALID_ARG */
return PR_FAILURE;
}
keepTrying = PR_TRUE;
nssrv = PR_FAILURE;
attempts = 0;
while (keepTrying) {
nssrv = pwcb.getPW(slot->name, &attempts, pwcb.arg, &password);
if (nssrv != PR_SUCCESS) {
nss_SetError(NSS_ERROR_USER_CANCELED);
break;
}
pwLen = (CK_ULONG)nssUTF8_Length(password, &nssrv);
if (nssrv != PR_SUCCESS) {
break;
}
nssSession_EnterMonitor(session);
ckrv = CKAPI(slot)->C_Login(session->handle, userType,
(CK_CHAR_PTR)password, pwLen);
nssSession_ExitMonitor(session);
switch (ckrv) {
case CKR_OK:
case CKR_USER_ALREADY_LOGGED_IN:
slot->authInfo.lastLogin = PR_Now();
nssrv = PR_SUCCESS;
keepTrying = PR_FALSE;
break;
case CKR_PIN_INCORRECT:
nss_SetError(NSS_ERROR_INVALID_PASSWORD);
keepTrying = PR_TRUE; /* received bad pw, keep going */
break;
default:
nssrv = PR_FAILURE;
keepTrying = PR_FALSE;
break;
}
nss_ZFreeIf(password);
password = NULL;
++attempts;
}
nss_ZFreeIf(password);
return nssrv;
}
static PRStatus
nssslot_init_password(NSSSlot *slot, nssSession *rwSession, NSSCallback pwcb)
{
NSSUTF8 *userPW = NULL;
NSSUTF8 *ssoPW = NULL;
PRStatus nssrv;
CK_ULONG userPWLen, ssoPWLen;
CK_RV ckrv;
if (!pwcb.getInitPW) {
/* set error INVALID_ARG */
return PR_FAILURE;
}
/* Get the SO and user passwords */
nssrv = pwcb.getInitPW(slot->name, pwcb.arg, &ssoPW, &userPW);
if (nssrv != PR_SUCCESS) goto loser;
userPWLen = (CK_ULONG)nssUTF8_Length(userPW, &nssrv);
if (nssrv != PR_SUCCESS) goto loser;
ssoPWLen = (CK_ULONG)nssUTF8_Length(ssoPW, &nssrv);
if (nssrv != PR_SUCCESS) goto loser;
/* First log in as SO */
ckrv = CKAPI(slot)->C_Login(rwSession->handle, CKU_SO,
(CK_CHAR_PTR)ssoPW, ssoPWLen);
if (ckrv != CKR_OK) {
/* set error ...SO_LOGIN_FAILED */
goto loser;
}
/* Now change the user PIN */
ckrv = CKAPI(slot)->C_InitPIN(rwSession->handle,
(CK_CHAR_PTR)userPW, userPWLen);
if (ckrv != CKR_OK) {
/* set error */
goto loser;
}
nss_ZFreeIf(ssoPW);
nss_ZFreeIf(userPW);
return PR_SUCCESS;
loser:
nss_ZFreeIf(ssoPW);
nss_ZFreeIf(userPW);
return PR_FAILURE;
}
static PRStatus
nssslot_change_password(NSSSlot *slot, nssSession *rwSession, NSSCallback pwcb)
{
NSSUTF8 *userPW = NULL;
NSSUTF8 *newPW = NULL;
PRUint32 attempts;
PRStatus nssrv;
PRBool keepTrying = PR_TRUE;
CK_ULONG userPWLen, newPWLen;
CK_RV ckrv;
if (!pwcb.getNewPW) {
/* set error INVALID_ARG */
return PR_FAILURE;
}
attempts = 0;
while (keepTrying) {
nssrv = pwcb.getNewPW(slot->name, &attempts, pwcb.arg,
&userPW, &newPW);
if (nssrv != PR_SUCCESS) {
nss_SetError(NSS_ERROR_USER_CANCELED);
break;
}
userPWLen = (CK_ULONG)nssUTF8_Length(userPW, &nssrv);
if (nssrv != PR_SUCCESS) return nssrv;
newPWLen = (CK_ULONG)nssUTF8_Length(newPW, &nssrv);
if (nssrv != PR_SUCCESS) return nssrv;
nssSession_EnterMonitor(rwSession);
ckrv = CKAPI(slot)->C_SetPIN(rwSession->handle,
(CK_CHAR_PTR)userPW, userPWLen,
(CK_CHAR_PTR)newPW, newPWLen);
nssSession_ExitMonitor(rwSession);
switch (ckrv) {
case CKR_OK:
slot->authInfo.lastLogin = PR_Now();
nssrv = PR_SUCCESS;
keepTrying = PR_FALSE;
break;
case CKR_PIN_INCORRECT:
nss_SetError(NSS_ERROR_INVALID_PASSWORD);
keepTrying = PR_TRUE; /* received bad pw, keep going */
break;
default:
nssrv = PR_FAILURE;
keepTrying = PR_FALSE;
break;
}
nss_ZFreeIf(userPW);
nss_ZFreeIf(newPW);
userPW = NULL;
newPW = NULL;
++attempts;
}
nss_ZFreeIf(userPW);
nss_ZFreeIf(newPW);
return nssrv;
}
NSS_IMPLEMENT PRStatus
NSSSlot_Login
(
NSSSlot *slot,
PRBool asSO,
NSSCallback pwcb
)
{
PRBool needsLogin, needsInit;
CK_USER_TYPE userType;
userType = (asSO) ? CKU_SO : CKU_USER;
needsInit = PR_FALSE; /* XXX */
needsLogin = PR_TRUE; /* XXX */
if (needsInit) {
return NSSSlot_SetPassword(slot, pwcb);
} else if (needsLogin) {
return nssslot_login(slot, slot->token->defaultSession,
userType, pwcb);
}
return PR_SUCCESS; /* login not required */
}
NSS_IMPLEMENT PRStatus
NSSSlot_Logout
(
NSSSlot *slot,
nssSession *sessionOpt
)
{
nssSession *session;
PRStatus nssrv = PR_SUCCESS;
CK_RV ckrv;
session = (sessionOpt) ? sessionOpt : slot->token->defaultSession;
nssSession_EnterMonitor(session);
ckrv = CKAPI(slot)->C_Logout(session->handle);
nssSession_ExitMonitor(session);
if (ckrv != CKR_OK) {
/* translate the error */
nssrv = PR_FAILURE;
}
return nssrv;
}
NSS_IMPLEMENT void
NSSSlot_SetPasswordDefaults
(
NSSSlot *slot,
PRInt32 askPasswordTimes
)
{
slot->authInfo.askPasswordTimeout = askPasswordTimeout;
}
NSS_IMPLEMENT PRStatus
NSSSlot_SetPassword
(
NSSSlot *slot,
NSSCallback pwcb
)
{
PRStatus nssrv;
nssSession *rwSession;
PRBool needsInit;
needsInit = PR_FALSE; /* XXX */
rwSession = NSSSlot_CreateSession(slot, NULL, PR_TRUE);
if (needsInit) {
nssrv = nssslot_init_password(slot, rwSession, pwcb);
} else {
nssrv = nssslot_change_password(slot, rwSession, pwcb);
}
nssSession_Destroy(rwSession);
return nssrv;
}
NSS_IMPLEMENT nssSession *
NSSSlot_CreateSession
(
NSSSlot *slot,
NSSArena *arenaOpt,
PRBool readOnly /* so far, this is the only flag used */
PRBool readWrite /* so far, this is the only flag used */
)
{
CK_RV ckrv;
@ -195,7 +436,7 @@ NSSSlot_CreateSession
CK_SESSION_HANDLE session;
nssSession *rvSession;
ckflags = s_ck_readonly_flags;
if (!readOnly) {
if (readWrite) {
ckflags |= CKF_RW_SESSION;
}
/* does the opening and closing of sessions need to be done in a
@ -236,13 +477,15 @@ nssSession_Destroy
nssSession *s
)
{
CK_RV ckrv = CKR_OK;
if (s) {
ckrv = CKAPI(s->slot)->C_CloseSession(s->handle);
if (s->lock) {
PZ_DestroyLock(s->lock);
}
nss_ZFreeIf(s);
}
return PR_SUCCESS;
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
}
NSS_IMPLEMENT PRStatus

Просмотреть файл

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.3 $ $Date: 2001-09-19 19:08:29 $ $Name: $";
#endif /* DEBUG */
#ifndef DEV_H
@ -116,7 +116,7 @@ NSSToken_Create
}
}
/* Open a default session handle for the token. */
session = NSSSlot_CreateSession(parent, arena, PR_TRUE);
session = NSSSlot_CreateSession(parent, arena, PR_FALSE);
if (session == NULL) {
goto loser;
}

Просмотреть файл

@ -35,7 +35,7 @@
#define NSSPKIT_H
#ifdef DEBUG
static const char NSSPKIT_CVS_ID[] = "@(#) $RCSfile: nsspkit.h,v $ $Revision: 1.3 $ $Date: 2001-09-13 22:16:22 $ $Name: $";
static const char NSSPKIT_CVS_ID[] = "@(#) $RCSfile: nsspkit.h,v $ $Revision: 1.4 $ $Date: 2001-09-19 19:08:32 $ $Name: $";
#endif /* DEBUG */
/*
@ -232,9 +232,25 @@ typedef struct NSSAlgorithmAndParametersStr NSSAlgorithmAndParameters;
* How OO do we want to make it?
*/
struct NSSCallbackStr;
typedef struct NSSCallbackStr NSSCallback;
struct NSSCallbackStr {
/* Prompt for a password to initialize a slot. */
PRStatus (* getInitPW)(NSSUTF8 *slotName, void *arg,
NSSUTF8 **ssoPW, NSSUTF8 **userPW);
/* Prompt for oldPW and newPW in order to change the
* password on a slot.
*/
PRStatus (* getNewPW)(NSSUTF8 *slotName, PRUint32 *retries, void *arg,
NSSUTF8 **oldPW, NSSUTF8 **newPW);
/* Prompt for slot password. */
PRStatus (* getPW)(NSSUTF8 *slotName, PRUint32 *retries, void *arg,
NSSUTF8 **password);
void *arg;
};
/* set errors - user cancelled, ... */
typedef PRUint32 NSSOperations;
/* 1) Do we want these to be preprocessor definitions or constants? */
/* 2) What is the correct and complete list? */