From 84007f05efb96e71781e2145dbcb31f44459a11a Mon Sep 17 00:00:00 2001 From: Kaspar Brand Date: Sat, 5 Sep 2015 07:52:00 +0200 Subject: [PATCH] Bug 278689 - Multiple Certificates with the same subject are not shown in the digital signature select cert combo (only one is shown) r=dkeeler --- security/manager/ssl/nsCertPicker.cpp | 46 +++++++++++++++++----- security/manager/ssl/nsIUserCertPicker.idl | 7 +++- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/security/manager/ssl/nsCertPicker.cpp b/security/manager/ssl/nsCertPicker.cpp index 417a3c9e8a8..f4b6913611f 100644 --- a/security/manager/ssl/nsCertPicker.cpp +++ b/security/manager/ssl/nsCertPicker.cpp @@ -36,6 +36,7 @@ NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx, int32_t certUsage, bool allowInvalid, bool allowDuplicateNicknames, + const nsAString &emailAddress, bool *canceled, nsIX509Cert **_retval) { @@ -53,7 +54,7 @@ NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx, ScopedCERTCertList allcerts(PK11_ListCerts(PK11CertListUnique, ctx)); } - /* find all user certs that are valid and for SSL */ + /* find all user certs that are valid for the specified usage */ /* note that we are allowing expired certs in this list */ ScopedCERTCertList certList( @@ -66,6 +67,32 @@ NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx, return NS_ERROR_NOT_AVAILABLE; } + /* if a (non-empty) emailAddress argument is supplied to PickByUsage, */ + /* remove non-matching certificates from the candidate list */ + + if (!emailAddress.IsEmpty()) { + node = CERT_LIST_HEAD(certList); + while (!CERT_LIST_END(node, certList)) { + /* if the cert has at least one e-mail address, check if suitable */ + if (CERT_GetFirstEmailAddress(node->cert)) { + RefPtr tempCert(nsNSSCertificate::Create(node->cert)); + bool match = false; + rv = tempCert->ContainsEmailAddress(emailAddress, &match); + if (NS_FAILED(rv)) { + return rv; + } + if (!match) { + /* doesn't contain the specified address, so remove from the list */ + CERTCertListNode* freenode = node; + node = CERT_LIST_NEXT(node); + CERT_RemoveCertListNode(freenode); + continue; + } + } + node = CERT_LIST_NEXT(node); + } + } + ScopedCERTCertNicknames nicknames(getNSSCertNicknamesFromCertList(certList.get())); if (!nicknames) { return NS_ERROR_NOT_AVAILABLE; @@ -88,20 +115,16 @@ NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx, node = CERT_LIST_NEXT(node) ) { - nsNSSCertificate *tempCert = nsNSSCertificate::Create(node->cert); + RefPtr tempCert(nsNSSCertificate::Create(node->cert)); if (tempCert) { - // XXX we really should be using an nsCOMPtr instead of manually add-refing, - // but nsNSSCertificate does not have a default constructor. - - NS_ADDREF(tempCert); - nsAutoString i_nickname(NS_ConvertUTF8toUTF16(nicknames->nicknames[CertsToUse])); nsAutoString nickWithSerial; nsAutoString details; if (!selectionFound) { + /* for the case when selectedNickname refers to a bare nickname */ if (i_nickname == nsDependentString(selectedNickname)) { selectedIndex = CertsToUse; selectionFound = true; @@ -111,14 +134,19 @@ NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx, if (NS_SUCCEEDED(tempCert->FormatUIStrings(i_nickname, nickWithSerial, details))) { certNicknameList[CertsToUse] = ToNewUnicode(nickWithSerial); certDetailsList[CertsToUse] = ToNewUnicode(details); + if (!selectionFound) { + /* for the case when selectedNickname refers to nickname + serial */ + if (nickWithSerial == nsDependentString(selectedNickname)) { + selectedIndex = CertsToUse; + selectionFound = true; + } + } } else { certNicknameList[CertsToUse] = nullptr; certDetailsList[CertsToUse] = nullptr; } - NS_RELEASE(tempCert); - ++CertsToUse; } } diff --git a/security/manager/ssl/nsIUserCertPicker.idl b/security/manager/ssl/nsIUserCertPicker.idl index 50ae2a929dd..e7e673c201f 100644 --- a/security/manager/ssl/nsIUserCertPicker.idl +++ b/security/manager/ssl/nsIUserCertPicker.idl @@ -8,13 +8,18 @@ interface nsIX509Cert; interface nsIInterfaceRequestor; -[scriptable, uuid(06d018e0-d41b-4629-a4fc-daaa6029888e)] +[scriptable, uuid(92396323-23f2-49e0-bf98-a25a725231ab)] interface nsIUserCertPicker : nsISupports { nsIX509Cert pickByUsage(in nsIInterfaceRequestor ctx, in wstring selectedNickname, in long certUsage, // as defined by NSS enum SECCertUsage in boolean allowInvalid, in boolean allowDuplicateNicknames, + in AString emailAddress, // optional - if non-empty, + // skip certificates which + // have at least one e-mail + // address but do not + // include this specific one out boolean canceled); };