Bug 1453778 - port bug 1453741: Move nsIX509CertDB::FindCertByEmailAddress to C-C. r=mkmelin a=jorgk
authorJorg K <jorgk@jorgk.com>
Thu, 12 Apr 2018 15:44:00 +0200
changeset 31773 ec8bf728b3afad67d3c4bbef2bd7a4adb925f03b
parent 31772 8f858087cadf77d6504744f84844fe6776b4ad92
child 31774 2af4d611dc8a6f42c106f5444d44de69a65feb7f
push id56
push usermozilla@jorgk.com
push dateSat, 25 Aug 2018 19:35:49 +0000
treeherdercomm-esr60@a69b790612e7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin, jorgk
bugs1453778, 1453741
Bug 1453778 - port bug 1453741: Move nsIX509CertDB::FindCertByEmailAddress to C-C. r=mkmelin a=jorgk
mailnews/extensions/smime/src/nsMsgComposeSecure.cpp
mailnews/extensions/smime/src/nsMsgComposeSecure.h
mailnews/extensions/smime/src/nsSMimeJSHelper.cpp
--- a/mailnews/extensions/smime/src/nsMsgComposeSecure.cpp
+++ b/mailnews/extensions/smime/src/nsMsgComposeSecure.cpp
@@ -22,16 +22,17 @@
 #include "nsIX509CertDB.h"
 #include "nsMemory.h"
 #include "nsMimeTypes.h"
 #include "nsMsgMimeCID.h"
 #include "nsNSSComponent.h"
 #include "nsServiceManagerUtils.h"
 #include "nspr.h"
 #include "pkix/Result.h"
+#include "nsNSSCertificate.h"
 
 using namespace mozilla::mailnews;
 using namespace mozilla;
 using namespace mozilla::psm;
 
 #define MK_MIME_ERROR_WRITING_FILE -1
 
 #define SMIME_STRBUNDLE_URL "chrome://messenger/locale/am-smime.properties"
@@ -955,18 +956,17 @@ nsresult nsMsgComposeSecure::MimeCryptoH
     uint32_t count = mailboxes.Length();
 
     bool already_added_self_cert = false;
 
     for (uint32_t i = 0; i < count; i++) {
       nsCString mailbox_lowercase;
       ToLowerCase(mailboxes[i], mailbox_lowercase);
       nsCOMPtr<nsIX509Cert> cert;
-      res = certdb->FindCertByEmailAddress(mailbox_lowercase,
-                                           getter_AddRefs(cert));
+      res = FindCertByEmailAddress(mailbox_lowercase, getter_AddRefs(cert));
       if (NS_FAILED(res)) {
         // Failure to find a valid encryption cert is fatal.
         // Here I assume that mailbox is ascii rather than utf8.
         SetErrorWithParam(sendReport,
                           "MissingRecipientEncryptionCert",
                           mailboxes[i].get());
 
         return res;
@@ -1179,8 +1179,65 @@ mime_nested_encoder_output_fn (const cha
   nsMsgComposeSecure *state = (nsMsgComposeSecure *) closure;
 
   // Copy to new null-terminated string so JS glue doesn't crash when
   // MimeCryptoWriteBlock() is implemented in JS.
   nsCString bufWithNull;
   bufWithNull.Assign(buf, size);
   return state->MimeCryptoWriteBlock(bufWithNull.get(), size);
 }
+
+nsresult
+nsMsgComposeSecure::FindCertByEmailAddress(const nsACString& aEmailAddress,
+                                                 nsIX509Cert** _retval)
+{
+  nsresult rv = BlockUntilLoadableRootsLoaded();
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
+  NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
+
+  const nsCString& flatEmailAddress = PromiseFlatCString(aEmailAddress);
+  UniqueCERTCertList certlist(
+    PK11_FindCertsFromEmailAddress(flatEmailAddress.get(), nullptr));
+  if (!certlist)
+    return NS_ERROR_FAILURE;
+
+  // certlist now contains certificates with the right email address,
+  // but they might not have the correct usage or might even be invalid
+
+  if (CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist))
+    return NS_ERROR_FAILURE; // no certs found
+
+  CERTCertListNode *node;
+  // search for a valid certificate
+  for (node = CERT_LIST_HEAD(certlist);
+       !CERT_LIST_END(node, certlist);
+       node = CERT_LIST_NEXT(node)) {
+
+    UniqueCERTCertList unusedCertChain;
+    mozilla::pkix::Result result =
+      certVerifier->VerifyCert(node->cert, certificateUsageEmailRecipient,
+                               mozilla::pkix::Now(),
+                               nullptr /*XXX pinarg*/,
+                               nullptr /*hostname*/,
+                               unusedCertChain,
+                               CertVerifier::FLAG_LOCAL_ONLY);
+    if (result == mozilla::pkix::Success) {
+      break;
+    }
+  }
+
+  if (CERT_LIST_END(node, certlist)) {
+    // no valid cert found
+    return NS_ERROR_FAILURE;
+  }
+
+  // node now contains the first valid certificate with correct usage
+  RefPtr<nsNSSCertificate> nssCert = nsNSSCertificate::Create(node->cert);
+  if (!nssCert)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  nssCert.forget(_retval);
+  return NS_OK;
+}
--- a/mailnews/extensions/smime/src/nsMsgComposeSecure.h
+++ b/mailnews/extensions/smime/src/nsMsgComposeSecure.h
@@ -53,16 +53,19 @@ class nsMsgComposeSecure : public nsIMsg
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMSGCOMPOSESECURE
 
   nsMsgComposeSecure();
 
   void GetOutputStream(nsIOutputStream **stream) { NS_IF_ADDREF(*stream = mStream);}
   nsresult GetSMIMEBundleString(const char16_t *name, nsString &outString);
+  static nsresult
+  FindCertByEmailAddress(const nsACString& aEmailAddress,
+                         nsIX509Cert** _retval);
 
 private:
   virtual ~nsMsgComposeSecure();
   typedef mozilla::mailnews::MimeEncoder MimeEncoder;
   nsresult MimeInitMultipartSigned(bool aOuter, nsIMsgSendReport *sendReport);
   nsresult MimeInitEncryption(bool aSign, nsIMsgSendReport *sendReport);
   nsresult MimeFinishMultipartSigned (bool aOuter, nsIMsgSendReport *sendReport);
   nsresult MimeFinishEncryption (bool aSign, nsIMsgSendReport *sendReport);
--- a/mailnews/extensions/smime/src/nsSMimeJSHelper.cpp
+++ b/mailnews/extensions/smime/src/nsSMimeJSHelper.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/mailnews/MimeHeaderParser.h"
 #include "nspr.h"
 #include "nsSMimeJSHelper.h"
+#include "nsMsgComposeSecure.h"
 #include "nsCOMPtr.h"
 #include "nsMemory.h"
 #include "nsString.h"
 #include "nsIX509CertDB.h"
 #include "nsIX509CertValidity.h"
 #include "nsIServiceManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsCRTGlue.h"
@@ -109,17 +110,17 @@ NS_IMETHODIMP nsSMimeJSHelper::GetRecipi
           memory_failure = true;
           continue;
         }
 
         nsCString email_lowercase;
         ToLowerCase(email, email_lowercase);
 
         nsCOMPtr<nsIX509Cert> cert;
-        if (NS_SUCCEEDED(certdb->FindCertByEmailAddress(
+        if (NS_SUCCEEDED(nsMsgComposeSecure::FindCertByEmailAddress(
                            email_lowercase, getter_AddRefs(cert))))
         {
           cert.forget(iCert);
 
           nsCOMPtr<nsIX509CertValidity> validity;
           rv = (*iCert)->GetValidity(getter_AddRefs(validity));
 
           if (NS_SUCCEEDED(rv)) {
@@ -216,17 +217,17 @@ NS_IMETHODIMP nsSMimeJSHelper::GetNoCert
     for (uint32_t i = 0; i < mailbox_count; ++i)
     {
       haveCert[i] = false;
 
       nsCString email_lowercase;
       ToLowerCase(mailboxes[i], email_lowercase);
 
       nsCOMPtr<nsIX509Cert> cert;
-      if (NS_SUCCEEDED(certdb->FindCertByEmailAddress(
+      if (NS_SUCCEEDED(nsMsgComposeSecure::FindCertByEmailAddress(
                          email_lowercase, getter_AddRefs(cert))))
         haveCert[i] = true;
 
       if (!haveCert[i])
         ++missing_count;
     }
   }