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

📄 sslconn.c

📁 安全开发库。含客户端建立ssl连接、签名、证书验证、证书发布和撤销等。编译用到nss
💻 C
📖 第 1 页 / 共 5 页
字号:
                    goto loser;                }                newitem.data[0] = (unsigned char)0x30;                newitem.data[1] = (unsigned char)0x81;                newitem.data[2] = (unsigned char)dername->len;                (void)memcpy(&newitem.data[3], dername->data, dername->len);            }            else {                /* greater than 256, better be less than 64k */                newitem.data = (unsigned char *) PR_Malloc(dername->len + 4);                if (newitem.data == NULL) {                    goto loser;                }                newitem.data[0] = (unsigned char)0x30;                newitem.data[1] = (unsigned char)0x82;                newitem.data[2] = (unsigned char)((dername->len >> 8) & 0xff);                newitem.data[3] = (unsigned char)(dername->len & 0xff);                memcpy(&newitem.data[4], dername->data, dername->len);            }            dername = &newitem;        }        namestring = CERT_DerNameToAscii(dername);        if (namestring == NULL) {            /* XXX - keep going until we fail to convert the name */            caNameStrings[n] = "";        }        else {            caNameStrings[n] = PORT_ArenaStrdup(arena, namestring);            PR_Free(namestring);            if (caNameStrings[n] == NULL) {                goto loser;            }        }        if (newitem.data != NULL) {            PR_Free(newitem.data);        }    }    return SECSuccess;loser:    if (newitem.data != NULL) {        PR_Free(newitem.data);    }    return SECFailure;}/* * Function: SSMStatus ssm_client_auth_prepare_nicknames() * Purpose: (private) picks out the filtered nicknames and populates the *          nicknames field of the SSL connection object with them * Arguments and return values: * - conn: SSL connection object to be manipulated * - nicknames: nickname list * * Note: the valid nickname list is not empty if this function was called *       Also the memory for the nickname list is allocated here; the caller *       is responsible for freeing the nickname list before the client *       auth callback function returns */SSMStatus ssm_client_auth_prepare_nicknames(SSMSSLDataConnection* conn,                                            CERTCertNicknames* nicknames){    int i;    int number;    PR_ASSERT(conn != NULL && conn->m_UIInfo.numFilteredCerts > 0 && 	      nicknames != NULL);    number = conn->m_UIInfo.numFilteredCerts;    /* allocate memory for nickname list */    conn->m_UIInfo.certNicknames = (char**)PR_Calloc(number, sizeof(char*));    if (conn->m_UIInfo.certNicknames == NULL) {        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);        goto loser;    }    /* fill in cert nicknames */    for (i = 0; i < number; i++) {        conn->m_UIInfo.certNicknames[i] = PL_strdup(nicknames->nicknames[i]);        if (conn->m_UIInfo.certNicknames[i] == NULL) {            goto loser;        }    }        return SSM_SUCCESS;loser:    return SSM_FAILURE;}void SSM_SSLHandshakeCallback(PRFileDesc* socket, void* clientData){	SSMSSLDataConnection* conn;		PR_ASSERT(socket != NULL);	PR_ASSERT(clientData != NULL);		SSM_DEBUG("Handshake callback called.\n");		conn = (SSMSSLDataConnection*)clientData;		/* update the security status info */    (void)SSMSSLDataConnection_UpdateSecurityStatus(conn);    /* we want to proceed even if the update has failed... */	/* check everything is hunky-dorey */    	SSMSSLSocketStatus_Invariant(conn->m_sockStat);}/* * Function: PRBool SSM_SSLErrorNeedsDialog() * Purpose: sorts out errors that require dialogs * * Arguments and return values * - error: error code * - returns: PR_TRUE if dialog needed; PR_FALSE otherwise */PRBool SSM_SSLErrorNeedsDialog(int error){	return ((error == SEC_ERROR_UNKNOWN_ISSUER) ||            (error == SEC_ERROR_UNTRUSTED_ISSUER) ||            (error == SSL_ERROR_BAD_CERT_DOMAIN) ||            (error == SSL_ERROR_POST_WARNING) ||            (error == SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) ||            (error == SEC_ERROR_CA_CERT_INVALID) ||            (error == SEC_ERROR_EXPIRED_CERTIFICATE));}SECStatus SSM_SSLMakeBadServerCertDialog(int error,                                          CERTCertificate* cert,                                         SSMSSLDataConnection* conn){    SECStatus rv;    if ((error == SEC_ERROR_UNKNOWN_ISSUER) ||        (error == SEC_ERROR_CA_CERT_INVALID) ||        (error == SEC_ERROR_UNTRUSTED_ISSUER)) {        rv = SSM_SSLMakeUnknownIssuerDialog(cert, conn);    }     else if (error == SSL_ERROR_BAD_CERT_DOMAIN) {        rv = SSM_SSLMakeCertBadDomainDialog(cert, conn);    }    else if (error == SSL_ERROR_POST_WARNING) {        /*rv = SEC_MakeCertPostWarnDialog(proto_win, cert);*/        rv = SECSuccess;    }    else if (error == SEC_ERROR_EXPIRED_CERTIFICATE) {        rv = SSM_SSLMakeCertExpiredDialog(cert, conn);    }     else if (error == SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) {        /*rv = SEC_MakeCAExpiredDialog(proto_win, cert);*/        rv = SECSuccess;    }    else {        rv = SECFailure;    }    return rv;}SECStatus SSM_DoubleCheckServerCert(CERTCertificate* cert,                                    SSMSSLDataConnection* conn){    PRBool checkSig = PR_FALSE;    /* ### sjlee: it is bit discomforting to set checkSig to false, but     *     the user already decided to be generous about the cert, so it     *     could be OK???     */    SSM_DEBUG("One server cert problem was handled.  See if there's more.\n");    return SSM_SSLVerifyServerCert(SSMCONTROLCONNECTION(conn)->m_certdb, cert,                                    checkSig, conn);}/* This function does the same thing as SSL_AuthCertificate(),** but takes different arguments.  */SECStatus SSM_SSLVerifyServerCert(CERTCertDBHandle* handle,                                  CERTCertificate* cert, PRBool checkSig,                                   SSMSSLDataConnection* conn){    SECStatus rv;    char* hostname = NULL;    rv = CERT_VerifyCertNow(handle, cert, checkSig, certUsageSSLServer,                            (void*)conn);    if (rv != SECSuccess) {	return rv;    }    /* cert is OK. we will check the name field in the cert against the     * desired hostname.     */    hostname = SSL_RevealURL(conn->socketSSL);    if (hostname && hostname[0]) {        rv = CERT_VerifyCertName(cert, hostname);    }    else {        rv = SECFailure;    }    if (rv != SECSuccess) {	PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);    }    if (hostname)    	PR_Free(hostname);    return rv;}/* The following routines are callbacks and assorted functions that are used * with SSL/LDAP. *//* SSL client-auth callback used for SSL/LDAP */SECStatus SSM_LDAPSSLGetClientAuthData(void* arg, PRFileDesc* socket,                                       CERTDistNames* caNames,                                       CERTCertificate** pRetCert,                                       SECKEYPrivateKey** pRetKey){    SECStatus rv = SECFailure;    void* wincx = NULL;    PRArenaPool* arena = NULL;    char** caNameStrings = NULL;    CERTCertList* certList = NULL;    CERTCertListNode* node;    CERTCertificate* cert = NULL;    SECKEYPrivateKey* privKey = NULL;    CERTCertDBHandle* certdb;    SSM_DEBUG("Doing client auth for LDAP/SSL.\n");    /* check arguments */    if ((arg == NULL) || (socket == NULL) || (caNames == NULL) ||         (pRetCert == NULL) || (pRetKey == NULL)) {        PR_SetError(SEC_ERROR_INVALID_ARGS, 0);        return (SECStatus) SEC_ERROR_INVALID_ARGS;    }    /* get PKCS11 pin argument */    wincx = SSL_RevealPinArg(socket);    if (wincx == NULL) {        return SECFailure;    }    /* 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;    }    /* XXX to do: publish the following function in sslconn.h */    rv = SSM_ConvertCANamesToStrings(arena, caNameStrings, caNames);    if (rv != SECSuccess) {        goto loser;    }    /* we will just do automatic cert selection for SSL/LDAP */    /* get the cert DB */    certdb = (CERTCertDBHandle*)arg;    /* find all user certs that are valid and for SSL */    certList = CERT_FindUserCertsByUsage(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;        }        node = CERT_LIST_NEXT(node);    }    if (cert == NULL) {        rv = (SECStatus)SEC_ERROR_NO_KEY;        goto noCert;    }    goto done;noCert:    PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0);    rv = (SECStatus) SSL_ERROR_NO_CERTIFICATE;loser:    if (rv == SECSuccess) {        rv = SECFailure;    }    if (cert != NULL) {        CERT_DestroyCertificate(cert);        cert = NULL;    }done:    if (certList != NULL) {        CERT_DestroyCertList(certList);    }    if (arena != NULL) {        PORT_FreeArena(arena, PR_FALSE);    }    *pRetCert = cert;    *pRetKey = privKey;    return rv;}/* This function must get called when the socket was created but was not * SSL-ified or connected */SECStatus SSM_LDAPSetupSSL(PRFileDesc* socket, PRFileDesc** sslSocket,                           CERTCertDBHandle* certdb, const char* hostname,                            SSMResource* caller){    SECStatus rv = SECFailure;    /* check arguments */    if ((socket == NULL) || (sslSocket == NULL) || (certdb == NULL) ||        (hostname == NULL) || (caller == NULL)) {        goto loser;    }    *sslSocket = NULL;    /* import the socket into SSL layer */    *sslSocket = SSL_ImportFD(NULL, socket);    if (*sslSocket == NULL) {        goto loser;    }    /* set some SSL settings for the socket */    rv = SSL_Enable(*sslSocket, SSL_SECURITY, PR_TRUE);    if (rv != SECSuccess) {        goto loser;    }    rv = SSL_Enable(*sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);    if (rv != SECSuccess) {        goto loser;    }    /* set callbacks */    rv = SSL_GetClientAuthDataHook(*sslSocket,                                    (SSLGetClientAuthData)SSM_LDAPSSLGetClientAuthData,                                   (void*)certdb) == 0 ? SECSuccess : SECFailure;    if (rv != SECSuccess) {        goto loser;    }    rv = SSL_AuthCertificateHook(*sslSocket,                                  (SSLAuthCertificate)SSM_SSLAuthCertificate,                                 (void*)certdb) == 0 ? SECSuccess : SECFailure;    if (rv != SECSuccess) {        goto loser;    }    rv = SSL_SetPKCS11PinArg(*sslSocket, (void*)caller) == 0 ? SECSuccess : SECFailure;    if (rv != SECSuccess) {        goto loser;    }    rv = SSL_SetURL(*sslSocket, hostname) == 0 ? SECSuccess : SECFailure;    if (rv != SECSuccess) {        goto loser;    }    return rv;loser:    if (*sslSocket == NULL) {        if (socket != NULL) {            PR_Close(socket);        }    }    else {        PR_Close(*sslSocket);        *sslSocket = NULL;    }    return rv;}

⌨️ 快捷键说明

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