Bug 1296219 - Use the Mozilla Base64 functions instead of the NSPR ones in PSM. r=keeler draft
authorCykesiopka <cykesiopka.bmo@gmail.com>
Tue, 23 Aug 2016 13:29:15 +0800
changeset 404299 9d07db1bcefc9d9ed6a1f7e102f5c01bd9caa522
parent 404288 d7e99ab4ba803ee782b85336b4590ad8a20367a8
child 529136 d45b304173c50e7da1aa88bf76ebbb6b5a840cab
push id27159
push usercykesiopka.bmo@gmail.com
push dateTue, 23 Aug 2016 05:40:03 +0000
reviewerskeeler
bugs1296219, 1251050
milestone51.0a1
Bug 1296219 - Use the Mozilla Base64 functions instead of the NSPR ones in PSM. r=keeler NSPR should generally be avoided in favour of modern C++ code. This patch does not convert uses of the NSS Base64 functions. It does however take the opportunity to switch over some IDL functions to use the safer Mozilla string classes, and fixes Bug 1251050 along the way. MozReview-Commit-ID: CM8g9DzIcnC
security/manager/ssl/nsIX509CertDB.idl
security/manager/ssl/nsNSSCertificate.cpp
security/manager/ssl/nsNSSCertificateDB.cpp
security/manager/ssl/nsNTLMAuthModule.cpp
--- a/security/manager/ssl/nsIX509CertDB.idl
+++ b/security/manager/ssl/nsIX509CertDB.idl
@@ -186,17 +186,17 @@ interface nsIX509CertDB : nsISupports {
                     in unsigned long trust);
 
   /**
    * @param cert        The certificate for which to modify trust.
    * @param trustString decoded by CERT_DecodeTrustString. 3 comma separated
    *                    characters, indicating SSL, Email, and Obj signing
    *                    trust.
    */
-  void setCertTrustFromString(in nsIX509Cert cert, in string trustString);
+  void setCertTrustFromString(in nsIX509Cert cert, in ACString trustString);
 
   /**
    *  Query whether a certificate is trusted for a particular use.
    *
    *  @param cert Obtain the stored trust of this certificate.
    *  @param certType The type of the certificate. See nsIX509Cert.
    *  @param trustType A single bit from the usages constants defined
    *                   within this interface.
@@ -248,17 +248,17 @@ interface nsIX509CertDB : nsISupports {
 
   /*
    *  Decode a raw data presentation and instantiate an object in memory.
    *
    *  @param base64 The raw representation of a certificate,
    *                encoded as Base 64.
    *  @return The new certificate object.
    */
-  nsIX509Cert constructX509FromBase64(in string base64);
+  nsIX509Cert constructX509FromBase64(in ACString base64);
 
   /*
    *  Decode a raw data presentation and instantiate an object in memory.
    *
    *  @param certDER The raw representation of a certificate,
    *                 encoded as raw DER.
    *  @param length  The length of the DER string.
    *  @return The new certificate object.
@@ -336,18 +336,20 @@ interface nsIX509CertDB : nsISupports {
 
   /*
    * Add a cert to a cert DB from a binary string.
    *
    * @param certDER The raw DER encoding of a certificate.
    * @param aTrust decoded by CERT_DecodeTrustString. 3 comma separated characters,
    *                indicating SSL, Email, and Obj signing trust
    * @param aName name of the cert for display purposes.
+   *              TODO(bug 857627): aName is currently ignored. It should either
+   *              not be ignored, or be removed.
    */
-  void addCert(in ACString certDER, in string aTrust, in string aName);
+  void addCert(in ACString certDER, in ACString aTrust, in AUTF8String aName);
 
   // Flags for verifyCertNow (these must match the values in CertVerifier.cpp):
   // Prevent network traffic. Doesn't work with classic verification.
   const uint32_t FLAG_LOCAL_ONLY = 1 << 0;
   // Do not fall back to DV verification after attempting EV validation.
   // Actually does prevent network traffic, but can cause a valid EV
   // certificate to not be considered valid.
   const uint32_t FLAG_MUST_BE_EV = 1 << 1;
@@ -405,18 +407,21 @@ interface nsIX509CertDB : nsISupports {
   /*
    * Add a cert to a cert DB from a base64 encoded string.
    *
    * @param base64 The raw representation of a certificate,
    *                encoded as Base 64.
    * @param aTrust decoded by CERT_DecodeTrustString. 3 comma separated characters,
    *                indicating SSL, Email, and Obj signing trust
    * @param aName name of the cert for display purposes.
+   *              TODO(bug 857627): aName is currently ignored. It should either
+   *              not be ignored, or be removed.
    */
-  void addCertFromBase64(in string base64, in string aTrust, in string aName);
+  void addCertFromBase64(in ACString base64, in ACString aTrust,
+                         in AUTF8String aName);
 
   /*
    * Get all the known certs in the database
    */
   nsIX509CertList getCerts();
 
   /*
    * Get a list of imported enterprise root certificates (currently only
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -31,21 +31,19 @@
 #include "nsPKCS12Blob.h"
 #include "nsProxyRelease.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsXULAppAPI.h"
 #include "nspr.h"
-#include "nssb64.h"
 #include "pkix/pkixnss.h"
 #include "pkix/pkixtypes.h"
 #include "pkix/Result.h"
-#include "plbase64.h"
 #include "prerror.h"
 #include "prmem.h"
 #include "prprf.h"
 #include "secasn1.h"
 #include "secder.h"
 #include "secerr.h"
 #include "ssl.h"
 
--- a/security/manager/ssl/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/nsNSSCertificateDB.cpp
@@ -4,16 +4,17 @@
 
 #include "nsNSSCertificateDB.h"
 
 #include "CertVerifier.h"
 #include "CryptoTask.h"
 #include "ExtendedValidation.h"
 #include "NSSCertDBTrustDomain.h"
 #include "SharedSSLState.h"
+#include "certdb.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Casting.h"
 #include "mozilla/unused.h"
 #include "nsArray.h"
 #include "nsArrayUtils.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include "nsComponentManagerUtils.h"
@@ -27,30 +28,27 @@
 #include "nsNSSCertHelper.h"
 #include "nsNSSCertTrust.h"
 #include "nsNSSCertificate.h"
 #include "nsNSSComponent.h"
 #include "nsNSSHelper.h"
 #include "nsNSSShutDown.h"
 #include "nsPK11TokenDB.h"
 #include "nsPKCS12Blob.h"
+#include "nsPromiseFlatString.h"
 #include "nsProxyRelease.h"
 #include "nsReadableUtils.h"
 #include "nsThreadUtils.h"
+#include "nspr.h"
 #include "pkix/Time.h"
 #include "pkix/pkixtypes.h"
-
-#include "nspr.h"
-#include "certdb.h"
-#include "secerr.h"
-#include "nssb64.h"
 #include "secasn1.h"
 #include "secder.h"
+#include "secerr.h"
 #include "ssl.h"
-#include "plbase64.h"
 
 #ifdef XP_WIN
 #include <winsock.h> // for ntohl
 #endif
 
 using namespace mozilla;
 using namespace mozilla::psm;
 using mozilla::psm::SharedSSLState;
@@ -1163,51 +1161,41 @@ nsNSSCertificateDB::FindCertByEmailAddre
   if (!nssCert)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nssCert.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNSSCertificateDB::ConstructX509FromBase64(const char *base64,
-                                            nsIX509Cert **_retval)
+nsNSSCertificateDB::ConstructX509FromBase64(const nsACString& base64,
+                                    /*out*/ nsIX509Cert** _retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
-  if (NS_WARN_IF(!_retval)) {
+  if (!_retval) {
     return NS_ERROR_INVALID_POINTER;
   }
 
-  // sure would be nice to have a smart pointer class for PL_ allocations
-  // unfortunately, we cannot distinguish out-of-memory from bad-input here
-  uint32_t len = base64 ? strlen(base64) : 0;
-  char *certDER = PL_Base64Decode(base64, len, nullptr);
-  if (!certDER)
-    return NS_ERROR_ILLEGAL_VALUE;
-  if (!*certDER) {
-    PL_strfree(certDER);
+  // Base64Decode() doesn't consider a zero length input as an error, and just
+  // returns the empty string. We don't want this behavior, so the below check
+  // catches this case.
+  if (base64.Length() < 1) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
-  // If we get to this point, we know we had well-formed base64 input;
-  // therefore the input string cannot have been less than two
-  // characters long.  Compute the unpadded length of the decoded data.
-  uint32_t lengthDER = (len * 3) / 4;
-  if (base64[len-1] == '=') {
-    lengthDER--;
-    if (base64[len-2] == '=')
-      lengthDER--;
+  nsAutoCString certDER;
+  nsresult rv = Base64Decode(base64, certDER);
+  if (NS_FAILED(rv)) {
+    return rv;
   }
 
-  nsresult rv = ConstructX509(certDER, lengthDER, _retval);
-  PL_strfree(certDER);
-  return rv;
+  return ConstructX509(certDER.get(), certDER.Length(), _retval);
 }
 
 NS_IMETHODIMP
 nsNSSCertificateDB::ConstructX509(const char* certDER,
                                   uint32_t lengthDER,
                                   nsIX509Cert** _retval)
 {
   nsNSSShutDownPreventionLock locker;
@@ -1336,35 +1324,36 @@ nsNSSCertificateDB::get_default_nickname
     if (!dummycert) {
       break;
     }
     count++;
   }
 }
 
 NS_IMETHODIMP
-nsNSSCertificateDB::AddCertFromBase64(const char* aBase64, const char* aTrust,
-                                      const char* /*aName*/)
+nsNSSCertificateDB::AddCertFromBase64(const nsACString& aBase64,
+                                      const nsACString& aTrust,
+                                      const nsACString& /*aName*/)
 {
-  NS_ENSURE_ARG_POINTER(aBase64);
-  NS_ENSURE_ARG_POINTER(aTrust);
-
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsNSSCertTrust trust;
-  if (CERT_DecodeTrustString(trust.GetTrust(), aTrust) != SECSuccess) {
+  if (CERT_DecodeTrustString(trust.GetTrust(), PromiseFlatCString(aTrust).get())
+        != SECSuccess) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIX509Cert> newCert;
   nsresult rv = ConstructX509FromBase64(aBase64, getter_AddRefs(newCert));
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
 
   UniqueCERTCertificate tmpCert(newCert->GetCert());
   if (!tmpCert) {
     return NS_ERROR_FAILURE;
   }
 
   // If there's already a certificate that matches this one in the database, we
   // still want to set its trust to the given value.
@@ -1382,36 +1371,36 @@ nsNSSCertificateDB::AddCertFromBase64(co
   }
 
   SECStatus srv = CERT_AddTempCertToPerm(tmpCert.get(), nickname.get(),
                                          trust.GetTrust());
   return MapSECStatus(srv);
 }
 
 NS_IMETHODIMP
-nsNSSCertificateDB::AddCert(const nsACString & aCertDER, const char *aTrust,
-                            const char *aName)
+nsNSSCertificateDB::AddCert(const nsACString& aCertDER, const nsACString& aTrust,
+                            const nsACString& aName)
 {
   nsCString base64;
   nsresult rv = Base64Encode(aCertDER, base64);
   NS_ENSURE_SUCCESS(rv, rv);
-  return AddCertFromBase64(base64.get(), aTrust, aName);
+  return AddCertFromBase64(base64, aTrust, aName);
 }
 
 NS_IMETHODIMP
 nsNSSCertificateDB::SetCertTrustFromString(nsIX509Cert* cert,
-                                           const char* trustString)
+                                           const nsACString& trustString)
 {
-  CERTCertTrust trust;
+  NS_ENSURE_ARG(cert);
 
-  // need to calculate the trust bits from the aTrust string.
+  CERTCertTrust trust;
   SECStatus srv = CERT_DecodeTrustString(&trust,
-                                         const_cast<char *>(trustString));
+                                         PromiseFlatCString(trustString).get());
   if (srv != SECSuccess) {
-    return MapSECStatus(SECFailure);
+    return MapSECStatus(srv);
   }
   UniqueCERTCertificate nssCert(cert->GetCert());
 
   nsresult rv = attemptToLogInWithDefaultPassword();
   if (NS_WARN_IF(rv != NS_OK)) {
     return rv;
   }
 
--- a/security/manager/ssl/nsNTLMAuthModule.cpp
+++ b/security/manager/ssl/nsNTLMAuthModule.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsNTLMAuthModule.h"
 
 #include <time.h>
 
 #include "ScopedNSSTypes.h"
 #include "md4.h"
+#include "mozilla/Base64.h"
 #include "mozilla/Casting.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/EndianUtils.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/Telemetry.h"
@@ -203,35 +204,37 @@ LogBuf(const char *tag, const uint8_t *b
     }
     PR_LogPrint("%s\n", line);
 
     bufLen -= count;
     buf += count;
   }
 }
 
-#include "plbase64.h"
-#include "prmem.h"
 /**
  * Print base64-encoded token to the NSPR Log.
  * @param name Description of the token, will be printed in front
  * @param token The token to print
  * @param tokenLen length of the data in token
  */
-static void LogToken(const char *name, const void *token, uint32_t tokenLen)
+static void
+LogToken(const char* name, const void* token, uint32_t tokenLen)
 {
-  if (!LOG_ENABLED())
+  if (!LOG_ENABLED()) {
     return;
+  }
 
-  char *b64data = PL_Base64Encode((const char *) token, tokenLen, nullptr);
-  if (b64data)
-  {
-    PR_LogPrint("%s: %s\n", name, b64data);
-    PR_Free(b64data);
+  nsDependentCSubstring tokenString(static_cast<const char*>(token), tokenLen);
+  nsAutoCString base64Token;
+  nsresult rv = mozilla::Base64Encode(tokenString, base64Token);
+  if (NS_FAILED(rv)) {
+    return;
   }
+
+  PR_LogPrint("%s: %s\n", name, base64Token.get());
 }
 
 //-----------------------------------------------------------------------------
 
 // byte order swapping
 #define SWAP16(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff))
 #define SWAP32(x) ((SWAP16((x) & 0xffff) << 16) | (SWAP16((x) >> 16)))