From f6980bbf247fc1b035bfa852b2f084e43a8686db Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 26 Aug 2011 14:38:18 +0200 Subject: [PATCH] nss: select client certificates by DER ... instead of nicknames, which are not unique. --- RELEASE-NOTES | 1 + lib/nss.c | 45 +++++++++++++++++++++++++++++---------------- lib/urldata.h | 1 + 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index c1a88fb65..a64ac23c7 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -24,6 +24,7 @@ This release includes the following bugfixes: o lots of MinGW build tweaks o Curl_gethostname: return un-qualified machine name o fixed the openssl version number configure check + o nss: certificates from files are no longer looked up by file base names This release includes the following known bugs: diff --git a/lib/nss.c b/lib/nss.c index fb52402a9..0be303cf0 100644 --- a/lib/nss.c +++ b/lib/nss.c @@ -354,6 +354,10 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, return CURLE_OUT_OF_MEMORY; } + if(!cacert && CKO_CERTIFICATE == obj_class) + /* store reference to a client certificate */ + ssl->obj_clicert = obj; + return CURLE_OK; } @@ -398,6 +402,7 @@ static int nss_load_cert(struct ssl_connect_data *ssl, nickname = strdup(filename); if(!nickname) return 0; + goto done; } @@ -797,44 +802,51 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, struct CERTCertificateStr **pRetCert, struct SECKEYPrivateKeyStr **pRetKey) { - static const char pem_nickname[] = "PEM Token #1"; - const char *pem_slotname = pem_nickname; - struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; struct SessionHandle *data = connssl->data; const char *nickname = connssl->client_nickname; - if(mod && nickname && - 0 == strncmp(nickname, pem_nickname, /* length of "PEM Token" */ 9)) { - +#ifdef HAVE_PK11_CREATEGENERICOBJECT + if(connssl->obj_clicert) { /* use the cert/key provided by PEM reader */ - PK11SlotInfo *slot; + static const char pem_slotname[] = "PEM Token #1"; + SECItem cert_der = { 0, NULL, 0 }; void *proto_win = SSL_RevealPinArg(sock); - *pRetKey = NULL; - *pRetCert = PK11_FindCertFromNickname(nickname, proto_win); - if(NULL == *pRetCert) { - failf(data, "NSS: client certificate not found: %s", nickname); + PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname); + if(NULL == slot) { + failf(data, "NSS: PK11 slot not found: %s", pem_slotname); return SECFailure; } - slot = PK11_FindSlotByName(pem_slotname); - if(NULL == slot) { - failf(data, "NSS: PK11 slot not found: %s", pem_slotname); + if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE, + &cert_der) != SECSuccess) { + failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); + PK11_FreeSlot(slot); + return SECFailure; + } + + *pRetCert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win); + SECITEM_FreeItem(&cert_der, PR_FALSE); + if(NULL == *pRetCert) { + failf(data, "NSS: client certificate from file not found"); + PK11_FreeSlot(slot); return SECFailure; } *pRetKey = PK11_FindPrivateKeyFromCert(slot, *pRetCert, NULL); PK11_FreeSlot(slot); if(NULL == *pRetKey) { - failf(data, "NSS: private key not found for certificate: %s", nickname); + failf(data, "NSS: private key from file not found"); + CERT_DestroyCertificate(*pRetCert); return SECFailure; } - infof(data, "NSS: client certificate: %s\n", nickname); + infof(data, "NSS: client certificate from file\n"); display_cert_info(data, *pRetCert); return SECSuccess; } +#endif /* use the default NSS hook */ if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, @@ -1076,6 +1088,7 @@ void Curl_nss_close(struct connectdata *conn, int sockindex) /* destroy all NSS objects in order to avoid failure of NSS shutdown */ Curl_llist_destroy(connssl->obj_list, NULL); connssl->obj_list = NULL; + connssl->obj_clicert = NULL; #endif PR_Close(connssl->handle); connssl->handle = NULL; diff --git a/lib/urldata.h b/lib/urldata.h index 86c1b680a..45ef2434e 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -273,6 +273,7 @@ struct ssl_connect_data { struct SessionHandle *data; #ifdef HAVE_PK11_CREATEGENERICOBJECT struct curl_llist *obj_list; + PK11GenericObject *obj_clicert; #endif #endif /* USE_NSS */ #ifdef USE_QSOSSL