b=100215 r=relyea sr=blizzard
Fix certificate verification chain display. git-svn-id: svn://10.0.0.236/trunk@104316 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -265,15 +265,52 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
|
||||
// first the default action
|
||||
SECStatus rv = SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
|
||||
|
||||
// We want to remember the CA certs in the temp db, so that the application can find the
|
||||
// complete chain at any time it might need it.
|
||||
// But we keep only those CA certs in the temp db, that we didn't already know.
|
||||
|
||||
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);
|
||||
CERTCertificate *serverCert = SSL_PeerCertificate(fd);
|
||||
if (serverCert) {
|
||||
CERTCertList *certList = CERT_GetCertChainFromCert(serverCert, PR_Now(), certUsageSSLCA);
|
||||
|
||||
nsCOMPtr<nsINSSComponent> nssComponent;
|
||||
|
||||
for (CERTCertListNode *node = CERT_LIST_HEAD(certList);
|
||||
!CERT_LIST_END(node, certList);
|
||||
node = CERT_LIST_NEXT(node)) {
|
||||
|
||||
if (node->cert->slot) {
|
||||
// This cert was found on a token, no need to remember it in the temp db.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->cert->isperm) {
|
||||
// We don't need to remember certs already stored in perm db.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->cert == serverCert) {
|
||||
// We don't want to remember the server cert,
|
||||
// the code that cares for displaying page info does this already.
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have found a signer cert that we want to remember.
|
||||
|
||||
if (!nssComponent) {
|
||||
// delay getting the service until we really need it
|
||||
nsresult rv;
|
||||
nssComponent = do_GetService(kNSSComponentCID, &rv);
|
||||
}
|
||||
|
||||
if (nssComponent) {
|
||||
nssComponent->RememberCert(node->cert);
|
||||
}
|
||||
}
|
||||
|
||||
CERT_DestroyCertList(certList);
|
||||
CERT_DestroyCertificate(serverCert);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,9 +100,81 @@ extern char * pk11PasswordPrompt(PK11SlotInfo *slot, PRBool retry, void *arg);
|
||||
#define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties"
|
||||
|
||||
|
||||
static PLHashNumber PR_CALLBACK certHashtable_keyHash(const void *key)
|
||||
{
|
||||
if (!key)
|
||||
return 0;
|
||||
|
||||
SECItem *certKey = (SECItem*)key;
|
||||
|
||||
// lazy hash function, sum up all char values of SECItem
|
||||
|
||||
PLHashNumber hash = 0;
|
||||
unsigned int i = 0;
|
||||
unsigned char *c = certKey->data;
|
||||
|
||||
for (i = 0; i < certKey->len; ++i, ++c) {
|
||||
hash += *c;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static PRIntn PR_CALLBACK certHashtable_keyCompare(const void *k1, const void *k2)
|
||||
{
|
||||
// return type is a bool, answering the question "are the keys equal?"
|
||||
|
||||
if (!k1 || !k2)
|
||||
return PR_FALSE;
|
||||
|
||||
SECItem *certKey1 = (SECItem*)k1;
|
||||
SECItem *certKey2 = (SECItem*)k2;
|
||||
|
||||
if (certKey1->len != certKey2->len) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned char *c1 = certKey1->data;
|
||||
unsigned char *c2 = certKey2->data;
|
||||
|
||||
for (i = 0; i < certKey1->len; ++i, ++c1, ++c2) {
|
||||
if (*c1 != *c2) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRIntn PR_CALLBACK certHashtable_valueCompare(const void *v1, const void *v2)
|
||||
{
|
||||
// two values are identical if their keys are identical
|
||||
|
||||
if (!v1 || !v2)
|
||||
return PR_FALSE;
|
||||
|
||||
CERTCertificate *cert1 = (CERTCertificate*)v1;
|
||||
CERTCertificate *cert2 = (CERTCertificate*)v2;
|
||||
|
||||
return certHashtable_keyCompare(&cert1->certKey, &cert2->certKey);
|
||||
}
|
||||
|
||||
static PRIntn PR_CALLBACK certHashtable_clearEntry(PLHashEntry *he, PRIntn /*index*/, void * /*userdata*/)
|
||||
{
|
||||
if (he && he->value) {
|
||||
CERT_DestroyCertificate((CERTCertificate*)he->value);
|
||||
}
|
||||
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
nsNSSComponent::nsNSSComponent()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
|
||||
hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare,
|
||||
certHashtable_valueCompare, 0, 0 );
|
||||
}
|
||||
|
||||
nsNSSComponent::~nsNSSComponent()
|
||||
@@ -119,6 +191,12 @@ nsNSSComponent::~nsNSSComponent()
|
||||
mPref->UnregisterCallback("security.", nsNSSComponent::PrefChangedCallback,
|
||||
(void*) this);
|
||||
|
||||
if (hashTableCerts) {
|
||||
PL_HashTableEnumerateEntries(hashTableCerts, certHashtable_clearEntry, 0);
|
||||
PL_HashTableDestroy(hashTableCerts);
|
||||
hashTableCerts = 0;
|
||||
}
|
||||
|
||||
if (mNSSInitialized)
|
||||
NSS_Shutdown();
|
||||
|
||||
@@ -806,6 +884,35 @@ nsNSSComponent::RegisterProfileChangeObserver()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSComponent::RememberCert(CERTCertificate *cert)
|
||||
{
|
||||
if (!hashTableCerts || !cert)
|
||||
return NS_OK;
|
||||
|
||||
void *found = PL_HashTableLookup(hashTableCerts, (void*)&cert->certKey);
|
||||
|
||||
if (found) {
|
||||
// we remember that cert already
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
CERTCertificate *myDupCert = CERT_DupCertificate(cert);
|
||||
|
||||
if (!myDupCert)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (!PL_HashTableAdd(hashTableCerts, (void*)&myDupCert->certKey, myDupCert)) {
|
||||
CERT_DestroyCertificate(myDupCert);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(PipUIContext, nsIInterfaceRequestor)
|
||||
|
||||
PipUIContext::PipUIContext()
|
||||
|
||||
@@ -76,6 +76,7 @@ class NS_NO_VTABLE nsINSSComponent : public nsISupports {
|
||||
// values in the preferences.
|
||||
NS_IMETHOD EnableOCSP() = 0;
|
||||
|
||||
NS_IMETHOD RememberCert(CERTCertificate *cert) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -111,6 +112,7 @@ public:
|
||||
NS_IMETHOD DisableOCSP();
|
||||
NS_IMETHOD EnableOCSP();
|
||||
nsresult InitializeNSS();
|
||||
NS_IMETHOD RememberCert(CERTCertificate *cert);
|
||||
|
||||
private:
|
||||
|
||||
@@ -128,6 +130,7 @@ private:
|
||||
nsCOMPtr<nsIURIContentListener> mPSMContentListener;
|
||||
nsCOMPtr<nsIPref> mPref;
|
||||
static PRBool mNSSInitialized;
|
||||
PLHashTable *hashTableCerts;
|
||||
};
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
@@ -155,17 +155,13 @@ nsNSSSocketInfo::nsNSSSocketInfo()
|
||||
mForTLSStepUp(PR_FALSE),
|
||||
mFirstWrite(PR_TRUE),
|
||||
mTLSIntolerant(PR_FALSE),
|
||||
mPort(0),
|
||||
mCAChain(nsnull)
|
||||
mPort(0)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
nsNSSSocketInfo::~nsNSSSocketInfo()
|
||||
{
|
||||
if (mCAChain) {
|
||||
CERT_DestroyCertList(mCAChain);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS4(nsNSSSocketInfo,
|
||||
@@ -368,15 +364,6 @@ 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;
|
||||
|
||||
@@ -73,8 +73,6 @@ public:
|
||||
nsresult GetTLSIntolerant(PRBool *aTLSIntolerant);
|
||||
nsresult SetTLSIntolerant(PRBool aTLSIntolerant);
|
||||
|
||||
nsresult RememberCAChain(CERTCertList *aCertList);
|
||||
|
||||
/* Set SSL Status values */
|
||||
nsresult SetSSLStatus(nsISSLStatus *aSSLStatus);
|
||||
|
||||
@@ -89,7 +87,6 @@ protected:
|
||||
PRBool mTLSIntolerant;
|
||||
PRInt32 mPort;
|
||||
nsXPIDLCString mHostName;
|
||||
CERTCertList *mCAChain;
|
||||
|
||||
/* SSL Status */
|
||||
nsCOMPtr<nsISSLStatus> mSSLStatus;
|
||||
|
||||
Reference in New Issue
Block a user