From 68d2830ee9df50961e481e81c1baaa290c33f03e Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 3 Dec 2012 13:17:50 +0100 Subject: [PATCH] nss: prevent NSS from crashing on client auth hook failure Although it is not explicitly stated in the documentation, NSS uses *pRetCert and *pRetKey even if the client authentication hook returns a failure. Namely, if we destroy *pRetCert without clearing *pRetCert afterwards, NSS destroys the certificate once again, which causes a double free. Reported by: Bob Relyea --- RELEASE-NOTES | 4 ++-- lib/nss.c | 17 +++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index a482dd7fa..b40c13aa1 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -13,7 +13,7 @@ This release includes the following changes: This release includes the following bugfixes: - o + o nss: prevent NSS from crashing on client auth hook failure This release includes the following known bugs: @@ -28,4 +28,4 @@ advice from friends like these: References to bug reports and discussions on issues: - \ No newline at end of file + diff --git a/lib/nss.c b/lib/nss.c index 22b53bfd8..794eccbd4 100644 --- a/lib/nss.c +++ b/lib/nss.c @@ -757,6 +757,8 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, static const char pem_slotname[] = "PEM Token #1"; SECItem cert_der = { 0, NULL, 0 }; void *proto_win = SSL_RevealPinArg(sock); + struct CERTCertificateStr *cert; + struct SECKEYPrivateKeyStr *key; PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname); if(NULL == slot) { @@ -771,24 +773,27 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, return SECFailure; } - *pRetCert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win); + cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win); SECITEM_FreeItem(&cert_der, PR_FALSE); - if(NULL == *pRetCert) { + if(NULL == cert) { failf(data, "NSS: client certificate from file not found"); PK11_FreeSlot(slot); return SECFailure; } - *pRetKey = PK11_FindPrivateKeyFromCert(slot, *pRetCert, NULL); + key = PK11_FindPrivateKeyFromCert(slot, cert, NULL); PK11_FreeSlot(slot); - if(NULL == *pRetKey) { + if(NULL == key) { failf(data, "NSS: private key from file not found"); - CERT_DestroyCertificate(*pRetCert); + CERT_DestroyCertificate(cert); return SECFailure; } infof(data, "NSS: client certificate from file\n"); - display_cert_info(data, *pRetCert); + display_cert_info(data, cert); + + *pRetCert = cert; + *pRetKey = key; return SECSuccess; }