Bug 903135 - Multi platform MAR verification updater support. r=rstrong
authorBrian R. Bondy <netzen@gmail.com>
Wed, 22 Oct 2014 21:00:26 -0400
changeset 491338 e6a3d69990a4c20e552f2447104b4d349628a485
parent 491337 64255585a5b787d2cc86b3be79aa20ff468f7fdc
child 491339 c0eb0b629dc0aae5c4f7c83df8d9d2dca952d542
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
reviewersrstrong
bugs903135
milestone36.0a1
Bug 903135 - Multi platform MAR verification updater support. r=rstrong
toolkit/mozapps/update/updater/archivereader.cpp
toolkit/mozapps/update/updater/updater.cpp
--- a/toolkit/mozapps/update/updater/archivereader.cpp
+++ b/toolkit/mozapps/update/updater/archivereader.cpp
@@ -10,96 +10,88 @@
 #include "bzlib.h"
 #include "archivereader.h"
 #include "errors.h"
 #ifdef XP_WIN
 #include "nsAlgorithm.h" // Needed by nsVersionComparator.cpp
 #include "updatehelper.h"
 #endif
 
-#ifdef XP_WIN
 // These are generated at compile time based on the DER file for the channel
 // being used
 #include "primaryCert.h"
 #include "secondaryCert.h"
 #include "xpcshellCert.h"
-#endif
 
 #define UPDATER_NO_STRING_GLUE_STL
 #include "nsVersionComparator.cpp"
 #undef UPDATER_NO_STRING_GLUE_STL
 
 #if defined(XP_UNIX)
 # include <sys/types.h>
 #elif defined(XP_WIN)
 # include <io.h>
 #endif
 
 static int inbuf_size  = 262144;
 static int outbuf_size = 262144;
 static char *inbuf  = nullptr;
 static char *outbuf = nullptr;
 
-#ifdef XP_WIN
-#include "resource.h"
-
 /**
  * Performs a verification on the opened MAR file with the passed in
  * certificate name ID and type ID.
  *
  * @param  archive   The MAR file to verify the signature on.
  * @param  certData  The certificate data.
  * @return OK on success, CERT_VERIFY_ERROR on failure.
 */
 template<uint32_t SIZE>
 int
 VerifyLoadedCert(MarFile *archive, const uint8_t (&certData)[SIZE])
 {
   const uint32_t size = SIZE;
-  const uint8_t * const data = &certData[0];
-  if (mar_verify_signaturesW(archive, &data, &size, 1)) {
+  const uint8_t* const data = &certData[0];
+  if (mar_verify_signatures(archive, &data, &size, 1)) {
     return CERT_VERIFY_ERROR;
   }
 
   return OK;
 }
-#endif
-
 
 /**
  * Performs a verification on the opened MAR file.  Both the primary and backup 
  * keys stored are stored in the current process and at least the primary key 
  * will be tried.  Success will be returned as long as one of the two 
  * signatures verify.
  *
  * @return OK on success
 */
 int
 ArchiveReader::VerifySignature()
 {
   if (!mArchive) {
     return ARCHIVE_NOT_OPEN;
   }
 
-#ifdef XP_WIN
   // If the fallback key exists we're running an XPCShell test and we should
   // use the XPCShell specific cert for the signed MAR.
-  int rv;
+  int rv = OK;
+#ifdef XP_WIN
   if (DoesFallbackKeyExist()) {
     rv = VerifyLoadedCert(mArchive, xpcshellCertData);
-  } else {
+  } else
+#endif
+  {
     rv = VerifyLoadedCert(mArchive, primaryCertData);
     if (rv != OK) {
       rv = VerifyLoadedCert(mArchive, secondaryCertData);
     }
   }
   return rv;
-#else
-  return OK;
-#endif
 }
 
 /**
  * Verifies that the MAR file matches the current product, channel, and version
  * 
  * @param MARChannelID   The MAR channel name to use, only updates from MARs
  *                       with a matching MAR channel name will succeed.
  *                       If an empty string is passed, no check will be done
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -104,16 +104,21 @@ void LaunchMacPostProcess(const char* aA
 extern "C" MOZ_EXPORT int ioprio_set(int which, int who, int ioprio);
 
 # define MAYBE_USE_HARD_LINKS 1
 static bool sUseHardLinks = true;
 #else
 # define MAYBE_USE_HARD_LINKS 0
 #endif
 
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
+#include "nss.h"
+#include "prerror.h"
+#endif
+
 #ifdef XP_WIN
 #include "updatehelper.h"
 
 // Closes the handle if valid and if the updater is elevated returns with the
 // return code specified. This prevents multiple launches of the callback
 // application by preventing the elevated process from launching the callback.
 #define EXIT_WHEN_ELEVATED(path, handle, retCode) \
   { \
@@ -2226,16 +2231,30 @@ int NS_main(int argc, NS_tchar **argv)
     // in the parent process, so we do it here.
     unsetenv("LD_PRELOAD");
     execv(argv[0], argv);
     __android_log_print(ANDROID_LOG_INFO, "updater",
                         "execve failed: errno: %d. Exiting...", errno);
     _exit(1);
   }
 #endif
+
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
+  // On Windows we rely on CyrptoAPI to do verifications so we don't need to
+  // initialize NSS at all there.
+  // Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS
+  // databases.
+  if (NSS_NoDB_Init(NULL) != SECSuccess) {
+   PRErrorCode error = PR_GetError();
+   fprintf(stderr, "Could not initialize NSS: %s (%d)",
+           PR_ErrorToName(error), (int) error);
+    _exit(1);
+  }
+#endif
+
   InitProgressUI(&argc, &argv);
 
   // To process an update the updater command line must at a minimum have the
   // directory path containing the updater.mar file to process as the first
   // argument, the install directory as the second argument, and the directory
   // to apply the update to as the third argument. When the updater is launched
   // by another process the PID of the parent process should be provided in the
   // optional fourth argument and the updater will wait on the parent process to