diff --git a/security/manager/ssl/src/nsNSSCallbacks.cpp b/security/manager/ssl/src/nsNSSCallbacks.cpp index f8f4798eb106..4571652e1bf1 100644 --- a/security/manager/ssl/src/nsNSSCallbacks.cpp +++ b/security/manager/ssl/src/nsNSSCallbacks.cpp @@ -260,3 +260,22 @@ void PR_CALLBACK HandshakeCallback(PRFileDesc* fd, void* client_data) { } } +SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd, + PRBool checksig, PRBool isServer) { + // first the default action + SECStatus rv = SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer); + + if (SECSuccess == rv) { + nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret; + if (infoObject) { + CERTCertificate *serverCert = SSL_PeerCertificate(fd); + if (serverCert) { + CERTCertList *certList = CERT_GetCertChainFromCert(serverCert, PR_Now(), certUsageSSLCA); + infoObject->RememberCAChain(certList); + CERT_DestroyCertificate(serverCert); + } + } + } + + return rv; +} diff --git a/security/manager/ssl/src/nsNSSCallbacks.h b/security/manager/ssl/src/nsNSSCallbacks.h index 8e785331e592..8cb5caf847b3 100644 --- a/security/manager/ssl/src/nsNSSCallbacks.h +++ b/security/manager/ssl/src/nsNSSCallbacks.h @@ -29,6 +29,8 @@ char* PK11PasswordPrompt(PK11SlotInfo *slot, PRBool retry, void* arg); void PR_CALLBACK HandshakeCallback(PRFileDesc *fd, void *client_data); +SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd, + PRBool checksig, PRBool isServer); #endif // _NSNSSCALLBACKS_H_ diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 31351a7970a7..eff0840a369a 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -153,13 +153,18 @@ nsNSSSocketInfo::nsNSSSocketInfo() mForceHandshake(PR_FALSE), mForTLSStepUp(PR_FALSE), mFirstWrite(PR_TRUE), - mTLSIntolerant(PR_FALSE) + mTLSIntolerant(PR_FALSE), + mPort(0), + mCAChain(nsnull) { NS_INIT_ISUPPORTS(); } nsNSSSocketInfo::~nsNSSSocketInfo() { + if (mCAChain) { + CERT_DestroyCertList(mCAChain); + } } NS_IMPL_THREADSAFE_ISUPPORTS4(nsNSSSocketInfo, @@ -362,6 +367,15 @@ nsresult nsNSSSocketInfo::GetSSLStatus(nsISSLStatus** _result) return NS_OK; } +nsresult nsNSSSocketInfo::RememberCAChain(CERTCertList *aCertList) +{ + if (mCAChain) { + CERT_DestroyCertList(mCAChain); + } + mCAChain = aCertList; + return NS_OK; +} + nsresult nsNSSSocketInfo::SetSSLStatus(nsISSLStatus *aSSLStatus) { mSSLStatus = aSSLStatus; @@ -1949,6 +1963,7 @@ nsSSLIOLayerImportFD(PRFileDesc *fd, SSL_GetClientAuthDataHook(sslSock, (SSLGetClientAuthData)nsNSS_SSLGetClientAuthData, infoObject); + SSL_AuthCertificateHook(sslSock, AuthCertificateCallback, 0); PRInt32 ret = SSL_SetURL(sslSock, host); if (ret == -1) { diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h index 076ea6a0e646..3911075492b4 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.h +++ b/security/manager/ssl/src/nsNSSIOLayer.h @@ -26,6 +26,7 @@ #include "prtypes.h" #include "prio.h" +#include "certt.h" #include "nsString.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" @@ -72,6 +73,8 @@ public: nsresult GetTLSIntolerant(PRBool *aTLSIntolerant); nsresult SetTLSIntolerant(PRBool aTLSIntolerant); + nsresult RememberCAChain(CERTCertList *aCertList); + /* Set SSL Status values */ nsresult SetSSLStatus(nsISSLStatus *aSSLStatus); @@ -86,6 +89,7 @@ protected: PRBool mTLSIntolerant; PRInt32 mPort; nsXPIDLCString mHostName; + CERTCertList *mCAChain; /* SSL Status */ nsCOMPtr mSSLStatus;