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:
kaie%netscape.com
2001-10-01 14:57:35 +00:00
parent ad65c1d519
commit 6c73f7c10a
5 changed files with 155 additions and 24 deletions

View File

@@ -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);
}
}

View File

@@ -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()

View File

@@ -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;
};
//--------------------------------------------

View File

@@ -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;

View File

@@ -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;