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

📄 sslconn.c

📁 安全开发库。含客户端建立ssl连接、签名、证书验证、证书发布和撤销等。编译用到nss
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Function: SECStatus SSM_SSLBadCertHandler() * Purpose: this callback function is used to handle a situation in which  *			server certificate verification has failed. * * Arguments and return values * - arg: the SSL data connection * - socket: SSL socket * - returns: SECSuccess if the case is handled and it is authorized to *			  continue connection; otherwise SECFailure */SECStatus SSM_SSLBadCertHandler(void* arg, PRFileDesc* socket){	int error;    SSMSSLDataConnection* conn;    CERTCertificate* cert = NULL;    SECStatus rv = SECFailure;	    if (socket == NULL || arg == NULL) {        return SECFailure;    }    conn = (SSMSSLDataConnection*)arg;    if (SSMCONTROLCONNECTION(conn)->m_doesUI == PR_FALSE) {        /* UI-less application.  We choose to reject the server cert. */        goto loser;    }    cert = SSL_PeerCertificate(conn->socketSSL);    if (cert == NULL) {        goto loser;    }    while (rv != SECSuccess) {        error = PR_GetError();	/* first of all, get error code */	        SSM_DEBUG("Got a bad server cert: error %d (%s).\n", error,                   SSL_Strerror(error));			/* Save error for socket status */		conn->m_sslServerError = error;        if (SSM_SSLErrorNeedsDialog(error) == PR_FALSE) {            SSM_DEBUG("Exiting abnormally...\n");            break;        }        if (SSM_SSLMakeBadServerCertDialog(error, cert, conn) != SECSuccess) {            break;        }        /* check the server cert again for more errors */        rv = SSM_DoubleCheckServerCert(cert, conn);    }loser:    if (rv != SECSuccess) {        (void)SSMSSLDataConnection_UpdateErrorCode(conn);    }    if (cert != NULL) {        CERT_DestroyCertificate(cert);    }    return rv;}/* * Function: SECStatus SSM_SSLGetClientAuthData() * Purpose: this callback function is used to pull client certificate *			information upon server request * * Arguments and return values * - arg: SSL data connection * - socket: SSL socket we're dealing with * - caNames: list of CA names * - pRetCert: returns a pointer to a pointer to a valid certificate if *			   successful; otherwise NULL * - pRetKey: returns a pointer to a pointer to the corresponding key if *			  successful; otherwise NULL * - returns: SECSuccess if successful; error code otherwise */SECStatus SSM_SSLGetClientAuthData(void* arg, PRFileDesc* socket,								   CERTDistNames* caNames,								   CERTCertificate** pRetCert,								   SECKEYPrivateKey** pRetKey){	void* wincx = NULL;	SECStatus rv = SECFailure;	SSMSSLDataConnection* conn;	SSMControlConnection* ctrlconn;    PRArenaPool* arena = NULL;    char** caNameStrings = NULL;    CERTCertificate* cert = NULL;    SECKEYPrivateKey* privKey = NULL;    CERTCertList* certList = NULL;    CERTCertListNode* node;    CERTCertNicknames* nicknames = NULL;    char* extracted = NULL;    PRIntn keyError = 0; /* used for private key retrieval error */		SSM_DEBUG("Client authentication callback function called.\n");		/* do some argument checking */	if (socket == NULL || caNames == NULL || pRetCert == NULL ||		pRetKey == NULL) {        rv = (SECStatus) SEC_ERROR_INVALID_ARGS;		return rv;	}		/* get PKCS11 pin argument */	wincx = SSL_RevealPinArg(socket);	if (wincx == NULL) {		return SECFailure;	}		/* get the right connections */	conn = (SSMSSLDataConnection*)wincx;	ctrlconn = (SSMControlConnection*)(SSMCONNECTION(conn)->m_parent);	PR_ASSERT(ctrlconn);    /* create caNameStrings */    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if (arena == NULL) {        goto loser;    }    caNameStrings = (char**)PORT_ArenaAlloc(arena,                                             sizeof(char*)*(caNames->nnames));    if (caNameStrings == NULL) {        goto loser;    }    rv = SSM_ConvertCANamesToStrings(arena, caNameStrings, caNames);    if (rv != SECSuccess) {        goto loser;    }    /* get the preference */	if (SSM_SetUserCertChoice(conn) != SSM_SUCCESS) {		goto loser;	}	/* find valid user cert and key pair */		if (certChoice == AUTO) {		/* automatically find the right cert */        /* find all user certs that are valid and for SSL */        certList = CERT_FindUserCertsByUsage(ctrlconn->m_certdb,                                              certUsageSSLClient, PR_TRUE,                                             PR_TRUE, wincx);        if (certList == NULL) {            goto noCert;        }        /* filter the list to those issued by CAs supported by the server */        rv = CERT_FilterCertListByCANames(certList, caNames->nnames,                                          caNameStrings, certUsageSSLClient);        if (rv != SECSuccess) {            goto noCert;        }        /* make sure the list is not empty */        node = CERT_LIST_HEAD(certList);        if (CERT_LIST_END(node, certList)) {            goto noCert;        }        /* loop through the list until we find a cert with a key */        while (!CERT_LIST_END(node, certList)) {            privKey = PK11_FindKeyByAnyCert(node->cert, wincx);            if (privKey != NULL) {                /* this is a good cert to present */                cert = CERT_DupCertificate(node->cert);                break;            }            keyError = PR_GetError();            if (keyError == SEC_ERROR_BAD_PASSWORD) {                /* problem with password: bail */                goto loser;            }            node = CERT_LIST_NEXT(node);        }        if (cert == NULL) {            rv = (SECStatus) SEC_ERROR_NO_KEY;            goto noCert;        }	}	else {        /* user selects a cert to present */        int i;        /* find all user certs that are valid and for SSL */        /* note that we are allowing expired certs in this list */        certList = CERT_FindUserCertsByUsage(ctrlconn->m_certdb,                                              certUsageSSLClient, PR_TRUE,                                              PR_FALSE, wincx);        if (certList == NULL) {            goto noCert;        }        if (caNames->nnames != 0) {            /* filter the list to those issued by CAs supported by the              * server              */            rv = CERT_FilterCertListByCANames(certList, caNames->nnames,                                               caNameStrings,                                               certUsageSSLClient);            if (rv != SECSuccess) {                goto loser;            }        }        if (CERT_LIST_END(CERT_LIST_HEAD(certList), certList)) {            /* list is empty - no matching certs */            goto noCert;        }        nicknames = CERT_NicknameStringsFromCertList(certList,                                                     NICKNAME_EXPIRED_STRING,                                                     NICKNAME_NOT_YET_VALID_STRING);        if (nicknames == NULL) {            goto loser;        }        SSM_DEBUG("%d valid user certs found.\n", nicknames->numnicknames);        conn->m_UIInfo.numFilteredCerts = nicknames->numnicknames;        if (ssm_client_auth_prepare_nicknames(conn, nicknames) !=             SSM_SUCCESS) {            goto loser;        }        /* create a cert selection dialog and get back the chosen nickname */        if (SSM_SSLMakeClientAuthDialog(conn) != SSM_SUCCESS) {            goto loser;        }        PR_ASSERT(conn->m_UIInfo.chosen >= 0);        i = conn->m_UIInfo.chosen;        SSM_DEBUG("Cert %s was selected.\n", conn->m_UIInfo.certNicknames[i]);        /* first we need to extract the real nickname in case the cert         * is an expired or not a valid one yet         */        extracted = CERT_ExtractNicknameString(conn->m_UIInfo.certNicknames[i],                                               NICKNAME_EXPIRED_STRING,                                               NICKNAME_NOT_YET_VALID_STRING);        if (extracted == NULL) {            goto loser;        }        /* find the cert under that nickname */        node = CERT_LIST_HEAD(certList);        while (!CERT_LIST_END(node, certList)) {            if (PL_strcmp(node->cert->nickname, extracted) == 0) {                cert = CERT_DupCertificate(node->cert);                break;            }            node = CERT_LIST_NEXT(node);        }        if (cert == NULL) {            goto loser;        }	        /* go get the private key */        privKey = PK11_FindKeyByAnyCert(cert, wincx);        if (privKey == NULL) {            keyError = PR_GetError();            if (keyError == SEC_ERROR_BAD_PASSWORD) {                /* problem with password: bail */                goto loser;            }            else {                goto noCert;            }        }	}	/* rv == SECSuccess */	SSM_DEBUG("Client auth complete.\n");	goto done;noCert:    /* we display the no cert dialog only if the app is UI-capable */    if (SSMCONTROLCONNECTION(conn)->m_doesUI == PR_TRUE) {        if (SSM_SSLMakeBadClientAuthDialog(conn) != SSM_SUCCESS) {            SSM_DEBUG("client auth failure UI display failed.\n");        }    }loser:    if (rv == SECSuccess) {        rv = SECFailure;    }    if (cert != NULL) {        CERT_DestroyCertificate(cert);        cert = NULL;    }done:    if (extracted != NULL) {        PR_Free(extracted);    }    if (nicknames != NULL) {        CERT_FreeNicknames(nicknames);    }    if (certList != NULL) {        CERT_DestroyCertList(certList);    }    if (arena != NULL) {        PORT_FreeArena(arena, PR_FALSE);    }    *pRetCert = cert;    *pRetKey = privKey;	return rv;}/* * Function: SSMStatus SSM_SetUserCertChoice() * Purpose: sets certChoice by reading the preference * * Arguments and return values * - conn: SSMSSLDataConnection * - returns: SSM_SUCCESS if successful; SSM_FAILURE otherwise * * Note: If done properly, this function will read the identifier strings *		 for ASK and AUTO modes, read the selected strings from the *		 preference, compare the strings, and determine in which mode it is *		 in. *       We currently use ASK mode for UI apps and AUTO mode for UI-less *       apps without really asking for preferences. */SSMStatus SSM_SetUserCertChoice(SSMSSLDataConnection* conn){    SSMStatus rv;    SSMControlConnection* parent;    parent = SSMCONTROLCONNECTION(conn);    if (parent->m_doesUI == PR_TRUE) {        char* mode = NULL;        rv = PREF_GetStringPref(parent->m_prefs,                                 "security.default_personal_cert", &mode);        if (rv != PR_SUCCESS) {            return SSM_FAILURE;        }        if (PL_strcmp(mode, "Select Automatically") == 0) {            certChoice = AUTO;        }        else if (PL_strcmp(mode, "Ask Every Time") == 0) {            certChoice = ASK;        }        else {            return SSM_FAILURE;        }    }    else {        SSM_DEBUG("UI-less app: use auto cert selection.\n");        certChoice = AUTO;    }	return SSM_SUCCESS;}/* * Function: SECStatus SSM_ConvertCANamesToStrings() * Purpose: creates CA names strings from (CERTDistNames* caNames) * * Arguments and return values * - arena: arena to allocate strings on * - caNameStrings: filled with CA names strings on return * - caNames: CERTDistNames to extract strings from * - return: SECSuccess if successful; error code otherwise */SECStatus SSM_ConvertCANamesToStrings(PRArenaPool* arena, char** caNameStrings,                                      CERTDistNames* caNames){    SECItem* dername;    SECStatus rv;    int headerlen;    uint32 contentlen;    SECItem newitem;    int n;    char* namestring;    for (n = 0; n < caNames->nnames; n++) {        newitem.data = NULL;        dername = &caNames->names[n];        rv = DER_Lengths(dername, &headerlen, &contentlen);        if (rv != SECSuccess) {            goto loser;        }        if (headerlen + contentlen != dername->len) {            if (dername->len <= 127) {                newitem.data = (unsigned char *) PR_Malloc(dername->len + 2);                if (newitem.data == NULL) {                    goto loser;                }                newitem.data[0] = (unsigned char)0x30;                newitem.data[1] = (unsigned char)dername->len;                (void)memcpy(&newitem.data[2], dername->data, dername->len);            }            else if (dername->len <= 255) {                newitem.data = (unsigned char *) PR_Malloc(dername->len + 3);                if (newitem.data == NULL) {

⌨️ 快捷键说明

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