⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 password.c

📁 安全开发库。含客户端建立ssl连接、签名、证书验证、证书发布和撤销等。编译用到nss
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- 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 "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 PSM 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 PSM-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);    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: %d\n", 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: %d\n", PR_GetError());    goto loser;  }  PK11_DestroyContext(context, PR_TRUE);  /*if (session != CK_INVALID_SESSION)

⌨️ 快捷键说明

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