password.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:32k
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
- #include "connect.h"
- #include "ssmerrs.h"
- #include "ctrlconn.h"
- #include "prinrval.h"
- #include "crmf.h"
- #include "newproto.h"
- #include "messages.h"
- #include "minihttp.h"
- #include "textgen.h"
- #include "sechash.h"
- #include "pk11func.h"
- extern SSMHashTable * tokenList;
- extern PRMonitor * tokenLock;
- #define SSMRESOURCE(conn) (&(conn)->super)
- /* Make these into functions? */
- #if 0
- #define SSM_PARENT_CONN(x) ((((SSMConnection *)(x))->m_parent) != NULL)?
- (((SSMControlConnection *)(((SSMConnection *)(x))->m_parent))):
- ((SSMControlConnection *)x)
- #define SSM_PWD_TABLE(x) (SSM_PARENT_CONN(x))->m_passwdTable
-
- #define SSM_OUT_QUEUE(x) (SSM_PARENT_CONN(x))->m_controlOutQ
- #endif
- #if 1
- SSMControlConnection * SSM_PARENT_CONN (SSMConnection * x)
- {
- return (((((SSMConnection *)(x))->m_parent) != NULL)?
- (((SSMControlConnection *)(((SSMConnection *)(x))->m_parent))):
- ((SSMControlConnection *)x));
- }
- SSMHashTable * SSM_PWD_TABLE(SSMConnection * x)
- {
- return (SSM_PARENT_CONN(x)->m_passwdTable);
- }
- SSMCollection * SSM_OUT_QUEUE(SSMConnection * x)
- {
- return (SSM_PARENT_CONN(x)->m_controlOutQ);
- }
- #endif
- PRInt32 SSM_GetTokenKey(PK11SlotInfo * slot)
- {
- return ((PK11_GetSlotID(slot)<<16) | PK11_GetModuleID(slot));
- }
- char * SSM_GetPasswdCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
- {
- return SSM_GetAuthentication(slot, retry, PR_FALSE, (SSMResource*)arg);
- }
- /* Do a couple of things in this functions:
- * 1) Get a password from user, and authenticate to token.
- * 2) Save this password encrypted in the global Cartman tokenList
- * for future reference.
- * Need to save password in case other users will need to authenticate
- * to the same tokens, so we make sure they're using the correct
- * passwords.
- * 3) Save this password encrypted in the control connection table in
- * case we will need to use it again.
- */
- char * SSM_GetAuthentication(PK11SlotInfo * slot, PRBool retry, PRBool init,
- SSMResource * res)
- {
- PRInt32 tokenKey;
- SSMStatus rv = PR_SUCCESS;
- char * passwd = NULL, * tmp = NULL;
- PRBool first = PR_FALSE;
- SSM_TokenInfo * info = NULL, * infoLocal = NULL;
- SSMConnection *conn = &(res->m_connection->super);
-
- tokenKey = SSM_GetTokenKey(slot);
- /* register as interested in a password */
- SSM_PARENT_CONN(conn)->m_waiting++;
-
- /* Get passwd table lock. */
- SSM_LockPasswdTable(conn);
- /* Look for entry for moduleID/slotID. */
- rv = SSM_HashFind(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
- SSM_UnlockPasswdTable(conn);
- if (rv != PR_SUCCESS) {
- first = PR_TRUE;
- /* no entry found, we are the first to authenticate to this slot */
- SSM_DEBUG("%ld: creating passwd table entry for %s n",
- conn, PK11_GetSlotName(slot));
- SSM_LockPasswdTable(conn);
- rv = SSM_HashInsert(SSM_PWD_TABLE(conn),tokenKey,(void *)SSM_NO_PASSWORD);
- SSM_UnlockPasswdTable(conn);
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("%ld: could not create entry in password tablen", conn);
- goto loser;
- }
- rv = SSM_AskUserPassword(res, slot, retry, init);
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("%ld: error sending password request eventn", conn);
- goto loser;
- }
- } /* end of the we-are-first-to-request-this-passwd-clause */
-
- /* If no password found, wait for it */
- if (!passwd || passwd == (char *)SSM_NO_PASSWORD) {
- rv = SSMControlConnection_WaitPassword(conn, tokenKey, &passwd);
- if (rv != PR_SUCCESS)
- goto loser;
- }
- if (((int) passwd) == SSM_CANCEL_PASSWORD) {
- /* no password was provided or user hit "Cancel" */
- SSM_LockPasswdTable(conn);
- rv = SSM_HashRemove(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
- SSM_UnlockPasswdTable(conn);
- if (rv != SSM_SUCCESS)
- SSM_DEBUG("SSM_GetAuthentication: user hit Cancel, can't remove password from connection tablen");
- passwd = NULL;
- goto done;
- }
-
- if (first) {
- /* We were the first to request the password,
- * so we need to enter it in to the token list.
- */
- /* encrypt the password */
- if (SSM_EncryptPasswd(slot, passwd, &info) != SSM_SUCCESS) {
- SSM_DEBUG("%ld: could not encrypt passwordn.", conn);
- goto loser;
- }
-
- /* Place encrypted passwd in Cartman-wide tokenList */
- PR_EnterMonitor(tokenLock);
- /* Remove from tokenList if already on the list - must be stale */
- rv = SSM_HashRemove(tokenList, tokenKey, (void **)&tmp);
- if (rv == SSM_SUCCESS && tmp && tmp != (char *)SSM_NO_PASSWORD
- && tmp != (char *)SSM_CANCEL_PASSWORD) { /* free stale data */
- PR_Free(tmp);
- tmp = NULL;
- }
- rv = SSM_HashInsert(tokenList, tokenKey, info);
- PR_ExitMonitor(tokenLock);
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("%ld: can't create encr passwd entryn", conn, tokenKey);
- goto loser;
- }
-
- /* Store encrypted password in control connection table */
- infoLocal = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
- if (!infoLocal)
- goto loser;
- infoLocal->slot = info->slot;
- infoLocal->tokenID = info->tokenID;
- infoLocal->encryptedLen = info->encryptedLen;
- infoLocal->symKey = info->symKey;
- infoLocal->encrypted = (char *) PORT_ZAlloc(info->encryptedLen);
- if (!infoLocal->encrypted)
- goto loser;
- memcpy(infoLocal->encrypted, info->encrypted, info->encryptedLen);
- PR_EnterMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
- rv = SSM_HashRemove(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
- (void **)&tmp);
- if (rv == SSM_SUCCESS && tmp && tmp != (char *)SSM_NO_PASSWORD &&
- tmp != (char *)SSM_CANCEL_PASSWORD ) {/* free stale data */
- PR_Free(tmp);
- tmp = NULL;
- }
- rv = SSM_HashInsert(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
- infoLocal);
- PR_ExitMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("%ld: cannot insert token %d entry in encrPasswdTablen",
- conn, tokenKey);
- goto loser;
- }
-
- SSM_DEBUG("%ld: wait untill others are done with passwd, remove itn",
- conn);
- /* while ((SSM_PARENT_CONN(conn))->m_waiting > 1)
- * PR_Sleep(SSM_PASSWORD_WAIT_TIME);
- */
- SSM_LockPasswdTable(conn);
- rv = SSM_HashRemove(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("%ld: could not remove passwd.n", conn);
- goto loser;
- }
- SSM_UnlockPasswdTable(conn);
- } /* end of if-first clause */
-
- goto done;
-
- loser:
- /* cleanup */
- PR_FREEIF(passwd);
- passwd = NULL;
- if (info) {
- PR_FREEIF(info->encrypted);
- PR_Free(info);
- }
- if (infoLocal) {
- PR_FREEIF(infoLocal->encrypted);
- PR_Free(infoLocal);
- }
- done:
- /* We are done receiving passwd */
- (SSM_PARENT_CONN(conn))->m_waiting--;
- return passwd ? strdup (passwd) : NULL;
- }
- /*
- * We get this callback if the slot is already logged-in.
- * Need to check client-supplied password against the password stored in
- * tokenList.
- */
- PRBool SSM_VerifyPasswdCallback(PK11SlotInfo * slot, void * arg)
- {
- char * passwd = NULL;
- PRInt32 tokenKey;
- SSM_TokenInfo * info = NULL;
- SSM_TokenInfo * tokenInfo = NULL;
- SSMStatus rv;
- PRBool result = PR_FALSE;
- SSMResource * res = (SSMResource*)arg;
- SSMConnection * conn = &(res->m_connection->super);
- PRInt32 doTry = 0;
- void * tmp = NULL;
-
- if (!slot || !arg)
- goto loser;
-
- tokenKey = PK11_GetSlotID(slot) ^ PK11_GetModuleID(slot);
- info = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
- if (!info) {
- SSM_DEBUG("Could not allocate memory in VerifyPasswdCallback.n");
- goto loser;
- }
-
- /* Get the password for this token.
- * We might have to find it in the local encrypted password table or
- * to request it from the client.
- */
- rv = SSM_HashFind(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
- (void **)&info);
- if (rv != PR_SUCCESS || info == (void *)SSM_NO_PASSWORD) {
- askpassword:
- /* ask user for a password and store it in local passwd table */
- rv = SSM_AskUserPassword(res, slot, doTry?PR_TRUE:PR_FALSE, PR_FALSE);
- if (rv != PR_SUCCESS)
- goto loser;
- doTry++;
- rv = SSMControlConnection_WaitPassword(conn, tokenKey, &passwd);
- if (rv != PR_SUCCESS || !passwd)
- goto loser;
- rv = SSM_EncryptPasswd(slot, passwd, &info);
- if (rv != SSM_SUCCESS)
- goto loser;
- } /* end of no password, ask user */
-
- /* Now get the stored password for this token */
- if (!tokenInfo) {
- PR_EnterMonitor(tokenLock);
- rv = SSM_HashFind(tokenList, tokenKey, (void **)&tokenInfo);
- PR_ExitMonitor(tokenLock);
- if (rv != PR_SUCCESS || !tokenInfo) {
- SSM_DEBUG("Can't find token info in VerifyPasswd.n");
- goto loser;
- }
- }
- /* Check password against tokenList entry */
- if (memcmp(tokenInfo->encrypted, info->encrypted, tokenInfo->encryptedLen)
- != 0 || tokenInfo->encryptedLen != info->encryptedLen) {
- /* Failed compare, bad password */
- /* first clean up */
- if (info) PR_Free(info);
- info = NULL;
- /* If not retry, ask client for password. */
- if (doTry < 2 ) {
- /* ask user again */
- PR_Free(passwd);
- passwd = NULL;
- goto askpassword;
- }
- else
- goto loser;
- } /* end of password not verified */
-
- SSM_DEBUG("Password verified OK.n");
- /* store password for local use */
- PR_EnterMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
- SSM_HashRemove(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
- (void **)&tmp);
- if (tmp && tmp != (char *)SSM_NO_PASSWORD ) {/* free stale data */
- PR_Free(tmp);
- tmp = NULL;
- }
- rv = SSM_HashInsert(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
- info);
- PR_ExitMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("%ld: cannot insert token %d entry in encrPasswdTablen",
- conn, tokenKey);
- goto loser;
- }
-
- result = PR_TRUE;
- goto done;
- loser:
- SSM_DEBUG("Password not verified. n");
- /* log out this slot?? */
- if (info) {
- if (info->encrypted)
- PR_Free(info->encrypted);
- PR_Free(info);
- }
- result = PR_FALSE;
- done:
- if (passwd)
- PR_Free(passwd);
- return result;
- }
- /* Encrypt password for storage */
- #define SSM_PAD_BLOCK_SIZE(x, y) ((((x) + ((y)-1))/(y))*(y))
- SSMStatus SSM_EncryptPasswd(PK11SlotInfo * slot, char * passwd,
- SSM_TokenInfo ** tokenInfo)
- {
- int resultLen;
- char *hashResult = NULL;
- SSMStatus rv = SSM_SUCCESS;
- SECStatus srv;
- SSM_TokenInfo * info;
- /* Hash the password. */
- resultLen = HASH_ResultLen(HASH_AlgSHA1);
- hashResult = (char *) PORT_ZAlloc(resultLen); /* because the original PORT_ZAlloc'd */
- if (!hashResult)
- goto loser;
-
- srv = HASH_HashBuf(HASH_AlgSHA1, (unsigned char *) hashResult, (unsigned char *) passwd, strlen(passwd));
- if (srv != SECSuccess)
- goto loser;
-
- /* fill in the tokenInfo structure */
- info = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
- if (!info) {
- SSM_DEBUG("EncryptPwd: could not allocate memory to token list entry.n");
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- goto loser;
- }
- info->encrypted = hashResult;
- info->encryptedLen = resultLen;
- info->slot = slot;
- info->tokenID = SSM_GetTokenKey(slot);
- *tokenInfo = info;
- goto done;
- loser:
- if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
- PR_FREEIF(hashResult);
- done:
- return rv;
- }
- SSMStatus SSM_NotEncryptPasswd(PK11SlotInfo * slot, char * passwd,
- SSM_TokenInfo * info)
- {
- CK_MECHANISM_TYPE mechanism;
- /* CK_SESSION_HANDLE session = CK_INVALID_SESSION; */
- PRInt32 keyLength, blockSize, outlen;
- PRUint32 encryptedLength;
- PK11SymKey * symKey;
- SECStatus rv;
- char * encrypted = NULL;
- PK11Context * context=NULL;
- SECItem *params;
-
-
- if (!slot || !passwd || !info) {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- goto loser;
- }
- mechanism = CRMF_GetBestWrapPadMechanism(slot);
- keyLength = PK11_GetBestKeyLength(slot, mechanism);
- /* session = PK11_GetRWSession(slot);
- if (session == CK_INVALID_SESSION)
- goto loser;*/
- blockSize = PK11_GetBlockSize(mechanism, NULL);
-
- /*
- * A password is encrypted when we first authenticate to token.
- * In this case, generate a symmetric Key on the slot.
- * If the key is already present, it means that the password for this
- * slot has already been encrypted and stored, need to encrypt
- * new password with the same key to compare against the stored
- * password.
- */
- /* If no symKey found, generate one */
- if (!info->symKey) {
- symKey = PK11_KeyGen(slot, mechanism, NULL, keyLength, NULL);
- if (!symKey) {
- SSM_DEBUG("Failed to generate symKey to encrypt passwd.n");
- goto loser;
- }
- } else
- symKey = info->symKey;
-
- encryptedLength = SSM_PAD_BLOCK_SIZE(strlen(passwd)+1, blockSize);
- encrypted = (char *) PORT_ZAlloc(encryptedLength);
- if (!encrypted) {
- SSM_DEBUG("Could not allocate space for encrypted password. n");
- goto loser;
- }
- params = CRMF_GetIVFromMechanism(mechanism);
- context=PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT,
- symKey, params);
- if (params != NULL) {
- SECITEM_FreeItem(params, PR_TRUE);
- }
- if (!context) {
- SSM_DEBUG("Can't create context to encrypt password: %d.n",
- PR_GetError());
- goto loser;
- }
- rv = PK11_CipherOp(context, (unsigned char *) encrypted, &outlen,
- (int) encryptedLength,
- (unsigned char *) passwd, strlen(passwd));
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("Error encrypting password: %dn", PR_GetError());
- goto loser;
- }
- rv = PK11_DigestFinal(context, (unsigned char *) &encrypted[outlen],
- (unsigned int *) &outlen, (unsigned int) blockSize);
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("Error encrypting password: %dn", PR_GetError());
- goto loser;
- }
- PK11_DestroyContext(context, PR_TRUE);
- /*if (session != CK_INVALID_SESSION)
- PK11_RestoreROSession(slot, session);*/
-
- /* fill in the tokenInfo structure */
- info->encrypted = encrypted;
- info->encryptedLen = encryptedLength;
- info->slot = slot;
- return SSM_SUCCESS;
- loser:
- SSM_DEBUG("Failed to encrypt password.n");
- if (context != NULL)
- PK11_DestroyContext(context, PR_TRUE);
- /*if (session != CK_INVALID_SESSION)
- PK11_RestoreROSession(slot, session);*/
- if (encrypted && *encrypted)
- PR_Free(encrypted);
- return SSM_FAILURE;
- }
- /* Needs to be fixed using NLS lib and proper string storage. -jane */
- char * SSM_GetPrompt(PK11SlotInfo *slot, PRBool retry, PRBool init)
- {
- char * prompt = NULL, * tmp = NULL, * key;
- SSMTextGenContext * cx;
- SSMStatus rv;
- PR_ASSERT(init != PR_TRUE);
-
- rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
- if (rv != SSM_SUCCESS || !cx)
- goto loser;
- if (retry)
- key = "retry_token_password";
- else
- key = "ask_token_password";
-
- rv = SSM_GetAndExpandTextKeyedByString(cx, key, &tmp);
- if (rv != SSM_SUCCESS || !tmp)
- goto loser;
- prompt = PR_smprintf(tmp, PK11_GetTokenName(slot));
-
- loser:
- PR_FREEIF(tmp);
- return prompt;
- }
- /* Send a password request for the client */
- SSMStatus SSM_AskUserPassword(SSMResource * res,
- PK11SlotInfo * slot, PRInt32 retry, PRBool init)
- {
- SECItem message;
- char * prompt = NULL;
- PRInt32 tokenKey = SSM_GetTokenKey(slot);
- SSMStatus rv = PR_FAILURE;
- SSMConnection *conn = (SSMConnection *)res->m_connection;
- PasswordRequest request;
-
- prompt = SSM_GetPrompt(slot, retry, init);
- retry++;
- if (!prompt) {
- SSM_DEBUG("%ld: error getting prompt for password request.n", conn);
- goto loser;
- }
- request.tokenKey = tokenKey;
- request.prompt = prompt;
- request.clientContext = res->m_clientContext;
- if (CMT_EncodeMessage(PasswordRequestTemplate, (CMTItem*)&message, &request) != CMTSuccess) {
- goto loser;
- }
- if (message.len == 0 || !message.data) {
- SSM_DEBUG("%ld: could not create password request message.n", conn);
- goto loser;
- }
- message.type = (SECItemType) (SSM_EVENT_MESSAGE | SSM_AUTH_EVENT);
- rv = SSM_SendQMessage(SSM_OUT_QUEUE(conn), SSM_PRIORITY_UI, message.type,
- message.len, (char *)message.data, PR_TRUE);
- if (rv != PR_SUCCESS) {
- SSM_DEBUG("%ld: Can't enqueue password request. n", conn);
- goto loser;
- }
- loser:
- if (prompt)
- PR_Free(prompt);
- if (message.data)
- PR_Free(message.data);
- return rv;
- }
- SSMStatus SSMControlConnection_WaitPassword(SSMConnection * conn,
- PRInt32 key, char ** str)
- {
- char * passwd;
- PRIntervalTime before;
- SSMStatus rv = PR_FAILURE;
-
- *str = NULL;
- /* Wait no longer than our time-out period. */
- before = PR_IntervalNow();
- SSM_LockPasswdTable(conn);
- wait:
- SSM_DEBUG("%ld : waiting on password table for the passwordn", conn);
- SSM_WaitPasswdTable(conn);
- /* Returned from wait.
- * Look for password.
- */
- rv = SSM_HashFind(SSM_PWD_TABLE(conn), key, (void **)&passwd);
- if (rv!=PR_SUCCESS || !passwd || passwd ==(char *)SSM_NO_PASSWORD) {
- /* password not found, check for timeout */
- if (PR_IntervalNow() - before > SSM_PASSWORD_WAIT_TIME) {
- SSM_DEBUG("%ld:Timed out waiting for password.Bailing out.n",
- conn);
- SSM_UnlockPasswdTable(conn);
- return PR_FAILURE;
- }
- else
- goto wait; /* continue waiting */
- } /* end of no password found */
- SSM_UnlockPasswdTable(conn);
- *str = passwd;
- return rv;
- }
- extern PK11SlotListElement *
- PK11_GetNextSafe(PK11SlotList * list, PK11SlotListElement * element,PRBool start);
-
- PK11SlotListElement *
- ssm_GetSlotWithPwd(PK11SlotList * slotlist, PK11SlotListElement * current,
- PRBool start)
- {
- PK11SlotListElement * next = NULL;
- PR_ASSERT(slotlist);
- if (!current || start)
- next = PK11_GetFirstSafe(slotlist);
- else
- next = PK11_GetNextSafe(slotlist, current, PR_FALSE);
- while (next &&
- PK11_NeedUserInit(next->slot) &&
- !PK11_NeedLogin(next->slot) )
- next = PK11_GetNextSafe(slotlist, next, PR_FALSE);
- return next;
- }
- PRIntn
- ssm_NumSlotsWithPassword(PK11SlotList * slotList)
- {
- PRIntn numslots = 0;
- PK11SlotListElement * element = PK11_GetFirstSafe(slotList);
- while (element) {
- if (PK11_NeedLogin(element->slot) || !PK11_NeedUserInit(element->slot))
- numslots++;
- element = PK11_GetNextSafe(slotList, element,PR_FALSE);
- }
- return numslots;
- }
- char*
- SSM_GetSlotNameForPasswordChange(HTTPRequest * req)
- {
- PK11SlotList *slotList = NULL;
- PK11SlotInfo *slot=NULL;
- PK11SlotListElement *listElem = NULL;
- SSMResource *target;
- char *slotName=NULL;
- SSMStatus rv;
-
- slotName = NULL;
- target = REQ_TARGET(req);
- slotList = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_TRUE,
- PR_TRUE, target);
- if (!slotList || !slotList->head)
- goto loser;
- if (ssm_NumSlotsWithPassword(slotList)>1) {
- char * mech = PR_smprintf("mech=%d&unused1=unused1&unused2=unused2",
- CKM_INVALID_MECHANISM);
- SSM_LockUIEvent(target);
- rv = SSMControlConnection_SendUIEvent(req->ctrlconn,
- "get", "select_token",
- target,mech,
- &target->m_clientContext,
- PR_TRUE);
- SSM_WaitUIEvent(target, PR_INTERVAL_NO_TIMEOUT);
- slot = (PK11SlotInfo *) target->m_uiData;
- if (!slot)
- goto loser;
- } else {
- listElem = ssm_GetSlotWithPwd(slotList, NULL, PR_TRUE);
- slot = listElem->slot;
- }
- if (!slot) {
- goto loser;
- }
- slotName = PK11_GetTokenName(slot);
- PK11_FreeSlot(slot);
- PK11_FreeSlotList(slotList);
- return PL_strdup(slotName);
- loser:
- if (slot)
- PK11_FreeSlot(slot);
- if (slotList)
- PK11_FreeSlotList(slotList);
- return NULL;
- }
- SSMStatus SSM_ReSetPasswordKeywordHandler(SSMTextGenContext * cx)
- {
- char * slotname = NULL;
- PK11SlotInfo * slot;
- char * tmp = NULL;
- SSMStatus rv;
- SSMResource * target = cx->m_request->target;
- PK11SlotList * slotList = NULL;
- PK11SlotListElement * el = NULL;
- PR_ASSERT(cx != NULL);
- PR_ASSERT(cx->m_request != NULL);
- PR_ASSERT(&cx->m_result != NULL);
- rv = SSM_HTTPParamValue(cx->m_request, "action", &slotname);
-
- if (!slotname || strcmp(slotname, "")== 0)
- slot = PK11_GetInternalKeySlot();
- else if (strcmp(slotname, "all") == 0) {
- char *userSlotName = NULL;
- /* ask user */
- userSlotName = SSM_GetSlotNameForPasswordChange(cx->m_request);
- if (!userSlotName)
- goto cancel;
- slot = PK11_FindSlotByName(userSlotName);
- PR_Free(userSlotName);
- }
- else
- slot = PK11_FindSlotByName(slotname);
- if (!slot) {
- SSM_DEBUG("ReSetPasswordKeywordHandler: bad slotname %sn", slotname);
- goto loser;
- }
-
- slotname = PK11_GetTokenName(slot);
- if (PK11_NeedPWInitForSlot(slot))
- rv = SSM_GetAndExpandTextKeyedByString(cx, "set_new_password", &tmp);
- else
- rv = SSM_GetAndExpandTextKeyedByString(cx, "reset_password", &tmp);
- if (rv != SSM_SUCCESS)
- goto loser;
- PR_FREEIF(cx->m_result);
- cx->m_result = PR_smprintf(tmp, slotname);
- return rv;
-
- loser:
- if (cx->m_result)
- PR_Free(cx->m_result);
- cx->m_result = NULL;
- return PR_FAILURE;
- cancel:
- SSM_HTTPCloseWindow(cx->m_request);
- goto loser;
- }
- PRBool
- ssm_VerifyPwdLength(char * password)
- {
- if (!password)
- return (!SSM_MIN_PWD_LEN);
- if (strlen(password) < SSM_MIN_PWD_LEN)
- return PR_FALSE;
- if (strlen(password) > SSM_MAX_PWD_LEN)
- return PR_FALSE;
- return PR_TRUE;
- }
- SSMStatus SSM_PasswordPrefKeywordHandler(SSMTextGenContext * cx)
- {
- char * fmt = NULL, * checked = NULL;
- char * markchecked[] = { "", "", ""};
- SSMStatus rv;
- PRIntn askpw, timeout;
- PR_ASSERT(cx != NULL);
- PR_ASSERT(cx->m_request != NULL);
- PR_ASSERT(cx->m_result != NULL);
-
- /* need to get the table and fill it with current preferences */
- rv = SSM_GetAndExpandTextKeyedByString(cx, "password_lifetime", &fmt);
- if (rv != SSM_SUCCESS || !fmt)
- goto done;
- rv = SSM_GetAndExpandTextKeyedByString(cx, "text_checked", &checked);
- if (rv != SSM_SUCCESS || !checked)
- goto done;
- rv = PREF_GetIntPref(cx->m_request->ctrlconn->m_prefs,
- "security.ask_for_password", &askpw);
- if (rv != SSM_SUCCESS)
- goto done;
- rv = PREF_GetIntPref(cx->m_request->ctrlconn->m_prefs,
- "security.password_lifetime", &timeout);
- if (rv != SSM_SUCCESS)
- goto done;
- markchecked[askpw] = checked;
- PR_FREEIF(cx->m_result);
- cx->m_result = PR_smprintf(fmt, markchecked[0], markchecked[1],
- markchecked[2], timeout);
-
- done:
- return rv;
- }
- SSMStatus SSM_SetDBPasswordHandler(HTTPRequest * req)
- {
- SSMStatus rv = SSM_FAILURE;
- char * oldpassword, * newpassword, *repeatpassword, * action;
- PK11SlotInfo * slot;
- char * responseKey = NULL;
- char * result = NULL;
- char * slotname = NULL, * askpwdoption, * pwdlifetime;
- PRIntn askpw, timeout;
- rv = SSM_HTTPParamValue(req, "baseRef", &action);
- if (rv != SSM_SUCCESS || strcmp(action, "windowclose_doclose_js")!= 0)
- SSM_DEBUG("SetDBPasswordHandler: bad action %sn", action);
-
- rv = SSM_HTTPParamValue(req, "slot", &slotname);
- if (rv != SSM_SUCCESS || !slotname ||
- !(slot = PK11_FindSlotByName(slotname)))
- goto loser;
- /* process password preferences */
- rv = SSM_HTTPParamValue(req, "passwordlife", &askpwdoption);
- if (rv != SSM_SUCCESS || !askpwdoption)
- goto loser;
- rv = SSM_HTTPParamValue(req, "passwordwillexpire", &pwdlifetime);
- if (rv != SSM_SUCCESS || !pwdlifetime)
- goto loser;
- if (strcmp(askpwdoption, "firsttime") == 0)
- askpw = 0;
- else if (strcmp(askpwdoption, "everytime") == 0)
- askpw = 1;
- else if (strcmp(askpwdoption, "expiretime")==0) {
- askpw = 2;
- }
- else {
- SSM_DEBUG("SetDBPasswordHandler: bad password lifetime parameter %sn",
- askpwdoption);
- goto loser;
- }
- timeout = atoi(pwdlifetime);
- if (askpw == 2 && !timeout)
- goto loser;
- PK11_SetSlotPWValues(slot, askpw, timeout);
- rv = SSMControlConnection_SaveIntPref(req->ctrlconn,
- "security.ask_for_password", askpw);
- if (rv != PR_SUCCESS)
- goto loser;
- rv = SSMControlConnection_SaveIntPref(req->ctrlconn,
- "security.password_lifetime", timeout);
- if (rv != SSM_SUCCESS)
- goto loser;
- rv = SSM_HTTPParamValue(req, "newpassword", &newpassword);
- if (rv != SSM_SUCCESS)
- goto loser;
- rv = SSM_HTTPParamValue(req, "repeatpassword", &repeatpassword);
- if (rv != SSM_SUCCESS)
- goto loser;
- if (!PK11_NeedPWInitForSlot(slot)) {
- /* oldpassword doesn't make sense for password initialization dialog */
- rv = SSM_HTTPParamValue(req, "oldpassword", &oldpassword);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- /* we do this check to find the case where the user changed only password
- * settings, not the password itself
- */
- if ((oldpassword[0] == ' ') && (newpassword[0] == ' ') &&
- (repeatpassword[0] == ' ')) {
- rv = SSM_HTTPDefaultCommandHandler(req);
- goto done;
- }
- }
- if (!ssm_VerifyPwdLength(newpassword))
- goto loser;
- if (strcmp(newpassword, repeatpassword) != 0)
- goto loser;
- if (!PK11_NeedPWInitForSlot(slot)) { /* there is some password on the DB */
- if (!oldpassword)
- goto loser;
- if (PK11_CheckUserPassword(slot, oldpassword) !=
- SECSuccess)
- goto loser;
- if (PK11_ChangePW(slot, oldpassword, newpassword) !=
- SECSuccess)
- goto loser;
- }
- else
- {
- if (PK11_NeedUserInit(slot)) {
- if (PK11_InitPin(slot, NULL, newpassword) != SECSuccess)
- goto loser;
- }
- else {
- if (PK11_ChangePW(slot, NULL, newpassword) != SECSuccess)
- goto loser;
- }
- }
- result = PR_smprintf("result=password_success");
- loser:
- if (!result)
- result = PR_smprintf("result=password_failure");
-
- rv = SSM_HTTPCloseAndSleep(req);
- if (rv != SSM_SUCCESS)
- SSM_DEBUG("SetDBPasswordHandler: failure in DefaultCommandHandlern");
- /* post status if password dialog was invoked from the SecurityAdvisor */
- if (SSM_IsA(req->target, SSM_RESTYPE_SECADVISOR_CONTEXT))
- SSMControlConnection_SendUIEvent(req->ctrlconn, "get",
- "show_followup", NULL,
- result,
- &((SSMResource *)req->ctrlconn)->m_clientContext,
- PR_TRUE);
-
- PR_FREEIF(responseKey);
- done:
- if (req->target && req->target->m_UILock)
- SSM_NotifyUIEvent(req->target);
- return rv;
- }
- SSMStatus SSM_ShowFollowupKeywordHandler(SSMTextGenContext * cx)
- {
- char * resultvalue;
- SSMStatus rv;
- PR_ASSERT(cx != NULL);
- PR_ASSERT(cx->m_request != NULL);
- PR_ASSERT(cx->m_result != NULL);
-
- rv = SSM_HTTPParamValue(cx->m_request, "result", &resultvalue);
- if (rv != SSM_SUCCESS || !resultvalue)
- goto loser;
- if (!strcmp(resultvalue, "password_success"))
- rv = SSM_GetAndExpandTextKeyedByString(cx, "set_password_success",
- &cx->m_result);
- else if (!strcmp(resultvalue,"password_failure"))
- rv = SSM_GetAndExpandTextKeyedByString(cx, "set_password_failure",
- &cx->m_result);
- else if (!strcmp(resultvalue, "no_ldap_setup"))
- rv = SSM_GetAndExpandTextKeyedByString(cx, "no_ldap_server_set",
- &cx->m_result);
- loser:
- return rv;
- }
- char *
- SSM_SetPasswordHTMLParamsFromTokenName(char *tokenName)
- {
- char *url = NULL;
- tokenName = SSM_ConvertStringToHTMLString(tokenName);
- url = PR_smprintf("slot=%s&mechanism=%d", tokenName,
- CKM_INVALID_MECHANISM);
- PR_Free(tokenName);
- return url;
- }
- char *
- SSM_SetPasswordHTMLParams(PK11SlotInfo *slot) {
- return SSM_SetPasswordHTMLParamsFromTokenName(PK11_GetTokenName(slot));
- }
- char * SSM_GenerateChangePasswordURL(PK11SlotInfo *slot, SSMResource *target)
- {
- PRUint32 width, height;
- char *slotHTMLName = NULL, *url = NULL, *extraParams = NULL;
- SSMStatus rv;
- if (slot) {
- slotHTMLName =
- SSM_ConvertStringToHTMLString(PK11_GetTokenName(slot));
- } else {
- slotHTMLName = PL_strdup("all");
- }
- extraParams = SSM_SetPasswordHTMLParams(slot);
- rv = SSM_GenerateURL(target->m_connection,"get", "set_password", target,
- extraParams, &width, &height, &url);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- PR_Free(slotHTMLName);
- PR_Free(extraParams);
- return url;
- loser:
- PR_FREEIF(slotHTMLName);
- PR_FREEIF(extraParams);
-
- return NULL;
- }
- SSMStatus SSM_SetUserPassword(PK11SlotInfo * slot, SSMResource * ct)
- {
- SSMStatus rv;
- char *params = SSM_SetPasswordHTMLParams(slot);
- SSM_LockUIEvent(ct);
- rv = SSMControlConnection_SendUIEvent(ct->m_connection,
- "get", "set_password",
- ct, params,
- &ct->m_clientContext,
- PR_TRUE);
- if (rv != SSM_SUCCESS)
- goto loser;
- SSM_WaitUIEvent(ct, PR_INTERVAL_NO_TIMEOUT);
- return rv;
- loser:
- SSM_UnlockUIEvent(ct);
- return rv;
- }
- SSMStatus SSM_ProcessPasswordWindow(HTTPRequest * req)
- {
- SSMStatus rv = SSM_FAILURE;
- SSMResource * target = NULL;
- char *slotName = NULL, *slotHTMLName = NULL;
- char *extraParams = NULL;
-
- if (!req || !req->ctrlconn)
- goto loser;
- /*
- * The window contents aren't going to change, so just send back
- * a NO_CONTENT error which causes leave its content as is.
- */
- rv = SSM_HTTPReportError(req, HTTP_NO_CONTENT);
- target = REQ_TARGET(req);
- /* First let's figure out if there are more than one token installed,
- * if so ask the user which one to change the password on
- */
- slotName = SSM_GetSlotNameForPasswordChange(req);
- if (slotName == NULL) {
- goto loser;
- }
- extraParams = SSM_SetPasswordHTMLParamsFromTokenName(slotName);
- SSM_LockUIEvent(target);
- /* send UI event to bring up the dialog */
- rv = SSMControlConnection_SendUIEvent(req->ctrlconn, "get",
- "set_password", target,
- extraParams,
- &target->m_clientContext,
- PR_TRUE);
- PR_FREEIF(extraParams);
- if (rv != SSM_SUCCESS) {
- SSM_UnlockUIEvent(&req->ctrlconn->super.super);
- goto loser;
- }
- SSM_WaitUIEvent(target, PR_INTERVAL_NO_TIMEOUT);
- loser:
- return rv;
- }