password.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,046 行 · 第 1/3 页

C
1,046
字号
/* -*- 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);}#endifPRInt32 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 table\n", conn);      goto loser;    }    rv = SSM_AskUserPassword(res, slot, retry, init);    if (rv != PR_SUCCESS) {      SSM_DEBUG("%ld: error sending password request event\n", 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 table\n");    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 password\n.", 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 entry\n", 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 encrPasswdTable\n",                conn, tokenKey);      goto loser;    }        SSM_DEBUG("%ld: wait untill others are done with passwd, remove it\n",              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 encrPasswdTable\n",              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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?