📄 sslconn.c
字号:
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 + -