nss: prevent NSS from crashing on client auth hook failure
authorKamil Dudka <kdudka@redhat.com>
Mon, 3 Dec 2012 12:17:50 +0000 (13:17 +0100)
committerKamil Dudka <kdudka@redhat.com>
Mon, 3 Dec 2012 12:34:36 +0000 (13:34 +0100)
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
lib/nss.c

index a482dd7..b40c13a 100644 (file)
@@ -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
index 22b53bf..794eccb 100644 (file)
--- 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;
   }