From 828a26286d22b61b28de6cf356806731560b3805 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 24 Apr 2009 21:55:18 +0000 Subject: [PATCH] - Kamil Dudka fixed another NSS-related leak when client certs were used. --- CHANGES | 2 ++ RELEASE-NOTES | 2 +- lib/nss.c | 32 ++++++++++++++++++++------------ lib/urldata.h | 1 + 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 33b31d01b..33bff528c 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,8 @@ Changelog Daniel Stenberg (24 Apr 2009) +- Kamil Dudka fixed another NSS-related leak when client certs were used. + - bug report #2779245 (http://curl.haxx.se/bug/view.cgi?id=2779245) by Rainer Koenig pointed out that the man page didn't tell that the *_proxy environment variables can be specified lower case or UPPER CASE and the diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 48c5ee984..ace20e532 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -26,7 +26,7 @@ This release includes the following bugfixes: o properly return an error code in curl_easy_recv o Sun compilers specific preprocessor block removed from curlbuild.h.dist o allow creation of four way fat libcurl Mac OS X Framework - o memory leaks in libcurl+NSS + o several memory leaks in libcurl+NSS o improved the CURLOPT_NOBODY set to 0 confusions o persistent connections when doing FTP over a HTTP proxy o --libcurl bogus strings where other data was pointed to diff --git a/lib/nss.c b/lib/nss.c index e8d2b555b..3fdc18dad 100644 --- a/lib/nss.c +++ b/lib/nss.c @@ -527,6 +527,7 @@ static int nss_load_key(struct connectdata *conn, int sockindex, char *key_file) return 0; } free(parg); + PK11_FreeSlot(slot); return 1; #else @@ -819,9 +820,9 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, struct CERTCertificateStr **pRetCert, struct SECKEYPrivateKeyStr **pRetKey) { - CERTCertificate *cert; SECKEYPrivateKey *privKey; - char *nickname = (char *)arg; + struct ssl_connect_data *connssl = (struct ssl_connect_data *) arg; + char *nickname = connssl->client_nickname; void *proto_win = NULL; SECStatus secStatus = SECFailure; PK11SlotInfo *slot; @@ -832,34 +833,35 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, if(!nickname) return secStatus; - cert = PK11_FindCertFromNickname(nickname, proto_win); - if(cert) { + connssl->client_cert = PK11_FindCertFromNickname(nickname, proto_win); + if(connssl->client_cert) { if(!strncmp(nickname, "PEM Token", 9)) { CK_SLOT_ID slotID = 1; /* hardcoded for now */ char slotname[SLOTSIZE]; snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID); slot = PK11_FindSlotByName(slotname); - privKey = PK11_FindPrivateKeyFromCert(slot, cert, NULL); + privKey = PK11_FindPrivateKeyFromCert(slot, connssl->client_cert, NULL); PK11_FreeSlot(slot); if(privKey) { secStatus = SECSuccess; } } else { - privKey = PK11_FindKeyByAnyCert(cert, proto_win); + privKey = PK11_FindKeyByAnyCert(connssl->client_cert, proto_win); if(privKey) secStatus = SECSuccess; } } if(secStatus == SECSuccess) { - *pRetCert = cert; + *pRetCert = connssl->client_cert; *pRetKey = privKey; } else { - if(cert) - CERT_DestroyCertificate(cert); + if(connssl->client_cert) + CERT_DestroyCertificate(connssl->client_cert); + connssl->client_cert = NULL; } return secStatus; @@ -891,8 +893,12 @@ void Curl_nss_cleanup(void) * as a safety feature. */ PR_Lock(nss_initlock); - if (initialized) + if (initialized) { + if(mod) + SECMOD_DestroyModule(mod); + mod = NULL; NSS_Shutdown(); + } PR_Unlock(nss_initlock); PR_DestroyLock(nss_initlock); @@ -940,6 +946,8 @@ void Curl_nss_close(struct connectdata *conn, int sockindex) free(connssl->client_nickname); connssl->client_nickname = NULL; } + if(connssl->client_cert) + CERT_DestroyCertificate(connssl->client_cert); if(connssl->key) (void)PK11_DestroyGenericObject(connssl->key); if(connssl->cacert[1]) @@ -981,6 +989,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) if (connssl->state == ssl_connection_complete) return CURLE_OK; + connssl->client_cert = NULL; connssl->cacert[0] = NULL; connssl->cacert[1] = NULL; connssl->key = NULL; @@ -1207,8 +1216,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) if(SSL_GetClientAuthDataHook(model, (SSLGetClientAuthData) SelectClientCert, - (void *)connssl->client_nickname) != - SECSuccess) { + (void *)connssl) != SECSuccess) { curlerr = CURLE_SSL_CERTPROBLEM; goto error; } diff --git a/lib/urldata.h b/lib/urldata.h index 60742e5b9..dc4f57420 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -211,6 +211,7 @@ struct ssl_connect_data { #ifdef USE_NSS PRFileDesc *handle; char *client_nickname; + CERTCertificate *client_cert; #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11GenericObject *key; PK11GenericObject *cacert[2];