[tor-commits] [tor-browser/tor-browser-78.12.0esr-10.5-1] Bug 13379: Sign our MAR files.

sysrqb at torproject.org sysrqb at torproject.org
Fri Jul 9 02:28:00 UTC 2021


commit a944f69f3f2e380d86e5db6e1ba3cf22717cecf4
Author: Kathy Brade <brade at pearlcrescent.com>
Date:   Wed Dec 17 16:37:11 2014 -0500

    Bug 13379: Sign our MAR files.
    
    Configure with --enable-verify-mar (when updating, require a valid
      signature on the MAR file before it is applied).
    Use the Tor Browser version instead of the Firefox version inside the
      MAR file info block (necessary to prevent downgrade attacks).
    Use NSS on all platforms for checking MAR signatures (instead of using
      OS-native APIs, which Mozilla does on Mac OS and Windows). So that the
      NSS and NSPR libraries the updater depends on can be found at runtime,
      we add the firefox directory to the shared library search path on macOS.
      On Linux, rpath is used by Mozilla to solve that problem, but that
      approach won't work on macOS because the updater executable is copied
      during the update process to a location that is under TorBrowser-Data,
      and the location of TorBrowser-Data varies.
    
    Also includes the fix for bug 18900.
---
 .mozconfig                                         |  1 +
 .mozconfig-asan                                    |  1 +
 .mozconfig-mac                                     |  1 +
 .mozconfig-mingw                                   |  1 +
 modules/libmar/tool/mar.c                          |  6 +--
 modules/libmar/tool/moz.build                      | 12 ++++--
 modules/libmar/verify/moz.build                    | 14 +++---
 .../mozapps/update/updater/updater-common.build    | 24 +++++++++--
 toolkit/mozapps/update/updater/updater.cpp         | 25 +++++++----
 toolkit/xre/moz.build                              |  3 ++
 toolkit/xre/nsUpdateDriver.cpp                     | 50 ++++++++++++++++++++++
 11 files changed, 113 insertions(+), 25 deletions(-)

diff --git a/.mozconfig b/.mozconfig
index 18cd1f9b6487..c50c57d410de 100755
--- a/.mozconfig
+++ b/.mozconfig
@@ -37,3 +37,4 @@ ac_add_options MOZ_TELEMETRY_REPORTING=
 ac_add_options --disable-tor-launcher
 ac_add_options --with-tor-browser-version=dev-build
 ac_add_options --disable-tor-browser-update
+ac_add_options --enable-verify-mar
diff --git a/.mozconfig-asan b/.mozconfig-asan
index 98ea6ac6f3fe..8bee813bfee8 100644
--- a/.mozconfig-asan
+++ b/.mozconfig-asan
@@ -30,6 +30,7 @@ ac_add_options --enable-official-branding
 ac_add_options --enable-default-toolkit=cairo-gtk3
 
 ac_add_options --enable-tor-browser-update
+ac_add_options --enable-verify-mar
 
 ac_add_options --disable-strip
 ac_add_options --disable-install-strip
diff --git a/.mozconfig-mac b/.mozconfig-mac
index 26e2b6b92fdb..5b4624ef1f67 100644
--- a/.mozconfig-mac
+++ b/.mozconfig-mac
@@ -43,6 +43,7 @@ ac_add_options --disable-debug
 
 ac_add_options --enable-tor-browser-data-outside-app-dir
 ac_add_options --enable-tor-browser-update
+ac_add_options --enable-verify-mar
 
 ac_add_options --disable-crashreporter
 ac_add_options --disable-webrtc
diff --git a/.mozconfig-mingw b/.mozconfig-mingw
index 3ec6ff18a3e9..ce6ace1dad67 100644
--- a/.mozconfig-mingw
+++ b/.mozconfig-mingw
@@ -15,6 +15,7 @@ ac_add_options --enable-strip
 ac_add_options --enable-official-branding
 
 ac_add_options --enable-tor-browser-update
+ac_add_options --enable-verify-mar
 ac_add_options --disable-bits-download
 
 # Let's make sure no preference is enabling either Adobe's or Google's CDM.
diff --git a/modules/libmar/tool/mar.c b/modules/libmar/tool/mar.c
index 0bf2cb4bd1d4..ea2b79924914 100644
--- a/modules/libmar/tool/mar.c
+++ b/modules/libmar/tool/mar.c
@@ -65,7 +65,7 @@ static void print_usage() {
       "signed_input_archive.mar base_64_encoded_signature_file "
       "changed_signed_output.mar\n");
   printf("(i) is the index of the certificate to extract\n");
-#  if defined(XP_MACOSX) || (defined(XP_WIN) && !defined(MAR_NSS))
+#  if (defined(XP_MACOSX) || defined(XP_WIN)) && !defined(MAR_NSS)
   printf("Verify a MAR file:\n");
   printf("  mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n");
   printf(
@@ -149,7 +149,7 @@ int main(int argc, char** argv) {
   memset((void*)certBuffers, 0, sizeof(certBuffers));
 #endif
 #if !defined(NO_SIGN_VERIFY) && \
-    ((!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX))
+    (!defined(MAR_NSS) && (defined(XP_WIN) || defined(XP_MACOSX)))
   memset(DERFilePaths, 0, sizeof(DERFilePaths));
   memset(fileSizes, 0, sizeof(fileSizes));
 #endif
@@ -181,7 +181,7 @@ int main(int argc, char** argv) {
       argc -= 2;
     }
 #if !defined(NO_SIGN_VERIFY)
-#  if (!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX)
+#  if (!defined(MAR_NSS) && (defined(XP_WIN) || defined(XP_MACOSX)))
     /* -D DERFilePath, also matches -D[index] DERFilePath
        We allow an index for verifying to be symmetric
        with the import and export command line arguments. */
diff --git a/modules/libmar/tool/moz.build b/modules/libmar/tool/moz.build
index 19653fb0b073..8953af0bb15c 100644
--- a/modules/libmar/tool/moz.build
+++ b/modules/libmar/tool/moz.build
@@ -35,15 +35,21 @@ if CONFIG['MOZ_BUILD_APP'] != 'tools/update-packaging':
         'verifymar',
     ]
 
+    if CONFIG['TOR_BROWSER_UPDATE']:
+        DEFINES['MAR_NSS'] = True
+
     if CONFIG['OS_ARCH'] == 'WINNT':
         USE_STATIC_LIBS = True
 
         OS_LIBS += [
             'ws2_32',
-            'crypt32',
-            'advapi32',
         ]
-    elif CONFIG['OS_ARCH'] == 'Darwin':
+        if not CONFIG['TOR_BROWSER_UPDATE']:
+            OS_LIBS += [
+                'crypt32',
+                'advapi32',
+            ]
+    elif CONFIG['OS_ARCH'] == 'Darwin' and not CONFIG['TOR_BROWSER_UPDATE']:
         OS_LIBS += [
           '-framework Security',
         ]
diff --git a/modules/libmar/verify/moz.build b/modules/libmar/verify/moz.build
index 9f7dc56f8f8a..e1c6ced31c37 100644
--- a/modules/libmar/verify/moz.build
+++ b/modules/libmar/verify/moz.build
@@ -16,15 +16,12 @@ FORCE_STATIC_LIB = True
 if CONFIG['OS_ARCH'] == 'WINNT':
     USE_STATIC_LIBS = True
 elif CONFIG['OS_ARCH'] == 'Darwin':
-    UNIFIED_SOURCES += [
-      'MacVerifyCrypto.cpp',
-    ]
-    OS_LIBS += [
-      '-framework Security',
+    USE_LIBS += [
+        'nspr',
+        'nss',
+        'signmar',
     ]
 else:
-    DEFINES['MAR_NSS'] = True
-    LOCAL_INCLUDES += ['../sign']
     USE_LIBS += [
         'nspr',
         'nss',
@@ -38,6 +35,9 @@ else:
         '-Wl,-rpath=\\$$ORIGIN',
     ]
 
+DEFINES['MAR_NSS'] = True
+LOCAL_INCLUDES += ['../sign']
+
 LOCAL_INCLUDES += [
     '../src',
 ]
diff --git a/toolkit/mozapps/update/updater/updater-common.build b/toolkit/mozapps/update/updater/updater-common.build
index 5898e92d465d..9f8365df8ade 100644
--- a/toolkit/mozapps/update/updater/updater-common.build
+++ b/toolkit/mozapps/update/updater/updater-common.build
@@ -4,6 +4,10 @@
 # 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/.
 
+DEFINES['MAR_NSS'] = True
+
+link_with_nss = DEFINES['MAR_NSS'] or (CONFIG['OS_ARCH'] == 'Linux' and CONFIG['MOZ_VERIFY_MAR_SIGNATURE'])
+
 srcs = [
     'archivereader.cpp',
     'updater.cpp',
@@ -36,10 +40,14 @@ if CONFIG['OS_ARCH'] == 'WINNT':
         'ws2_32',
         'shell32',
         'shlwapi',
-        'crypt32',
-        'advapi32',
     ]
 
+    if not link_with_nss:
+        OS_LIBS += [
+            'crypt32',
+            'advapi32',
+        ]
+
 USE_LIBS += [
     'bspatch',
     'mar',
@@ -47,6 +55,13 @@ USE_LIBS += [
     'xz-embedded',
 ]
 
+if link_with_nss:
+    USE_LIBS += [
+        'nspr',
+        'nss',
+        'signmar',
+    ]
+
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
     have_progressui = 1
     srcs += [
@@ -61,9 +76,12 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     ]
     OS_LIBS += [
         '-framework Cocoa',
-        '-framework Security',
         '-framework SystemConfiguration',
     ]
+    if not link_with_nss:
+        OS_LIBS += [
+            '-framework Security',
+        ]
     UNIFIED_SOURCES += [
         '/toolkit/xre/updaterfileutils_osx.mm',
     ]
diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
index 9a95c3b17761..aaec0b38dda0 100644
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -106,9 +106,11 @@ struct UpdateServerThreadArgs {
 #  define USE_EXECV
 #endif
 
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
-#  include "nss.h"
-#  include "prerror.h"
+#if defined(MOZ_VERIFY_MAR_SIGNATURE)
+#  if defined(MAR_NSS) || (!defined(XP_WIN) && !defined(XP_MACOSX))
+#    include "nss.h"
+#    include "prerror.h"
+#  endif
 #endif
 
 #include "crctable.h"
@@ -2738,8 +2740,13 @@ static void UpdateThreadFunc(void* param) {
         if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK) {
           rv = UPDATE_SETTINGS_FILE_CHANNEL;
         } else {
+#  ifdef TOR_BROWSER_UPDATE
+          const char* appVersion = TOR_BROWSER_VERSION_QUOTED;
+#  else
+          const char* appVersion = MOZ_APP_VERSION;
+#  endif
           rv = gArchiveReader.VerifyProductInformation(MARStrings.MARChannelID,
-                                                       MOZ_APP_VERSION);
+                                                       appVersion);
         }
       }
     }
@@ -2940,11 +2947,10 @@ int NS_main(int argc, NS_tchar** argv) {
   }
 #endif
 
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
-  // On Windows and Mac we rely on native APIs 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 defined(MOZ_VERIFY_MAR_SIGNATURE)
+#  if defined(MAR_NSS) || (!defined(XP_WIN) && !defined(XP_MACOSX))
+  // If using NSS for signature verification, initialize NSS but minimize
+  // the portion we depend on by avoiding all of the NSS databases.
   if (NSS_NoDB_Init(nullptr) != SECSuccess) {
     PRErrorCode error = PR_GetError();
     fprintf(stderr, "Could not initialize NSS: %s (%d)", PR_ErrorToName(error),
@@ -2952,6 +2958,7 @@ int NS_main(int argc, NS_tchar** argv) {
     _exit(1);
   }
 #endif
+#endif
 
 #ifdef XP_MACOSX
   if (!isElevated) {
diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build
index 7ba3be2fe241..6afab145c2b6 100644
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -214,6 +214,9 @@ for var in ('APP_VERSION', 'APP_ID'):
 if CONFIG['MOZ_BUILD_APP'] == 'browser':
     DEFINES['MOZ_BUILD_APP_IS_BROWSER'] = True
 
+if CONFIG['TOR_BROWSER_UPDATE']:
+     DEFINES['MAR_NSS'] = True
+
 LOCAL_INCLUDES += [
     '../../other-licenses/nsis/Contrib/CityHash/cityhash',
     '../components/find',
diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp
index 55d1982504ed..1cbee302719f 100644
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -360,6 +360,42 @@ static nsresult GetUpdateDirFromAppDir(nsIFile* aAppDir, nsIFile** aResult) {
 #  endif
 #endif
 
+#if defined(TOR_BROWSER_UPDATE) && defined(MOZ_VERIFY_MAR_SIGNATURE) && \
+    defined(MAR_NSS) && defined(XP_MACOSX)
+/**
+ * Ideally we would save and restore the original library path value after
+ * the updater finishes its work (and before firefox is re-launched).
+ * Doing so would avoid potential problems like the following bug:
+ *   https://bugzilla.mozilla.org/show_bug.cgi?id=1434033
+ */
+/**
+ * Appends the specified path to the library path.
+ * This is used so that the updater can find libnss3.dylib and other
+ * shared libs.
+ *
+ * @param pathToAppend A new library path to prepend to the dynamic linker's
+ * search path.
+ */
+#  include "prprf.h"
+#  define PATH_SEPARATOR ":"
+#  define LD_LIBRARY_PATH_ENVVAR_NAME "DYLD_LIBRARY_PATH"
+static void AppendToLibPath(const char* pathToAppend) {
+  char* pathValue = getenv(LD_LIBRARY_PATH_ENVVAR_NAME);
+  if (nullptr == pathValue || '\0' == *pathValue) {
+    // Leak the string because that is required by PR_SetEnv.
+    char* s =
+        Smprintf("%s=%s", LD_LIBRARY_PATH_ENVVAR_NAME, pathToAppend).release();
+    PR_SetEnv(s);
+  } else {
+    // Leak the string because that is required by PR_SetEnv.
+    char* s = Smprintf("%s=%s" PATH_SEPARATOR "%s", LD_LIBRARY_PATH_ENVVAR_NAME,
+                       pathToAppend, pathValue)
+                  .release();
+    PR_SetEnv(s);
+  }
+}
+#endif
+
 /**
  * Applies, switches, or stages an update.
  *
@@ -606,6 +642,20 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
     PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
   }
 
+#if defined(TOR_BROWSER_UPDATE) && defined(MOZ_VERIFY_MAR_SIGNATURE) && \
+    defined(MAR_NSS) && defined(XP_MACOSX)
+  // On macOS, append the app directory to the shared library search path
+  // so the system can locate the shared libraries that are needed by the
+  // updater, e.g., libnss3.dylib).
+  nsAutoCString appPath;
+  nsresult rv2 = appDir->GetNativePath(appPath);
+  if (NS_SUCCEEDED(rv2)) {
+    AppendToLibPath(appPath.get());
+  } else {
+    LOG(("ApplyUpdate -- appDir->GetNativePath() failed (0x%x)\n", rv2));
+  }
+#endif
+
   LOG(("spawning updater process [%s]\n", updaterPath.get()));
 #ifdef DEBUG
   dump_argv("ApplyUpdate updater", argv, argc);





More information about the tor-commits mailing list