diff --git a/toolkit/components/maintenanceservice/registrycertificates.cpp b/toolkit/components/maintenanceservice/registrycertificates.cpp index 7fcaf920e14..2702de7f7f7 100644 --- a/toolkit/components/maintenanceservice/registrycertificates.cpp +++ b/toolkit/components/maintenanceservice/registrycertificates.cpp @@ -67,17 +67,16 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath) // force the non redirected registry under Wow6432Node. // This flag is ignored on 32bit systems. HKEY baseKeyRaw; - LSTATUS retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - maintenanceServiceKey, 0, - KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw); + LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + maintenanceServiceKey, 0, + KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw); if (retCode != ERROR_SUCCESS) { LOG(("Could not open key. (%d)\n", retCode)); // Our tests run with a different apply directory for each test. // We use this registry key on our test slaves to store the // allowed name/issuers. retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Mozilla\\MaintenanceService" - L"\\3932ecacee736d366d6436db0f55bce4", 0, + TEST_ONLY_FALLBACK_KEY_PATH, 0, KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw); if (retCode != ERROR_SUCCESS) { LOG(("Could not open fallback key. (%d)\n", retCode)); diff --git a/toolkit/components/maintenanceservice/workmonitor.cpp b/toolkit/components/maintenanceservice/workmonitor.cpp index 859c908d8ac..09c22755764 100644 --- a/toolkit/components/maintenanceservice/workmonitor.cpp +++ b/toolkit/components/maintenanceservice/workmonitor.cpp @@ -357,7 +357,8 @@ ProcessWorkItem(LPCWSTR monitoringBasePath, BOOL updaterIsCorrect; if (result && !VerifySameFiles(updaterPath, installDirUpdater, updaterIsCorrect)) { - LOG(("Error checking if the updaters are the same.\n")); + LOG(("Error checking if the updaters are the same.\n" + "Path 1: %ls\nPath 2: %ls\n", updaterPath, installDirUpdater)); result = FALSE; } diff --git a/toolkit/mozapps/update/common/pathhash.h b/toolkit/mozapps/update/common/pathhash.h index e9f47380eba..52bbffa411e 100644 --- a/toolkit/mozapps/update/common/pathhash.h +++ b/toolkit/mozapps/update/common/pathhash.h @@ -49,4 +49,13 @@ BOOL CalculateRegistryPathFromFilePath(const LPCWSTR filePath, LPWSTR registryPath); +// The test only fallback key, as its name implies, is only present on machines +// that will use automated tests. Since automated tests always run from a +// different directory for each test, the presence of this key bypasses the +// "This is a valid installation directory" check. This key also stores +// the allowed name and issuer for cert checks so that the cert check +// code can still be run unchanged. +#define TEST_ONLY_FALLBACK_KEY_PATH \ + L"SOFTWARE\\Mozilla\\MaintenanceService\\3932ecacee736d366d6436db0f55bce4" + #endif diff --git a/toolkit/mozapps/update/test/unit/head_update.js.in b/toolkit/mozapps/update/test/unit/head_update.js.in index 688b4105b81..e596861efe2 100644 --- a/toolkit/mozapps/update/test/unit/head_update.js.in +++ b/toolkit/mozapps/update/test/unit/head_update.js.in @@ -547,6 +547,21 @@ function runUpdateUsingService(aInitialStatus, aExpectedStatus, setEnvironment(); + // There is a security check done by the service to make sure the updater + // we are executing is the same as the one in the apply-to dir. + // To make sure they match from tests we copy updater.exe to the apply-to dir. + let binDir = getGREDir(); + let updater = binDir.clone(); + updater.append(UPDATER_BIN_FILE); + if (!updater.exists()) { + do_throw("Unable to find updater binary!"); + } + let applyToUpdater = getApplyDirFile(null, true); + if (applyToUpdater.path != binDir.path) { + do_print("copying " + updater.path + " to: " + applyToUpdater.path); + updater.copyTo(applyToUpdater, UPDATER_BIN_FILE); + } + // We can't get sync behavior here since Firefox does not wait for the // process launched through the service to finish. Since the service // launches the updater in the background, providing an observer argument @@ -563,7 +578,11 @@ function runUpdateUsingService(aInitialStatus, aExpectedStatus, if (aExpectedStatus == STATE_FAILED) { status = status.split(": ")[0]; } - if (status == STATE_PENDING) { + // status will probably always be equal to STATE_APPLYING but there is a + // race condition where it would be possible on slower machines where status + // could be equal to STATE_PENDING_SVC. + if (status == STATE_APPLYING || + status == STATE_PENDING_SVC) { logTestInfo("Still waiting to see the " + aExpectedStatus + " status, got " + status + " for now..."); return; diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp index ba7fa579e70..ad98fc1e662 100644 --- a/toolkit/mozapps/update/updater/updater.cpp +++ b/toolkit/mozapps/update/updater/updater.cpp @@ -1446,7 +1446,7 @@ WriteStatusApplying() if (file == NULL) return false; - static const char kApplying[] = "Applying\n"; + static const char kApplying[] = "applying"; if (fwrite(kApplying, strlen(kApplying), 1, file) != 1) return false; @@ -1597,10 +1597,24 @@ int NS_main(int argc, NS_tchar **argv) UACHelper::DisablePrivileges(NULL); bool useService = false; + bool testOnlyFallbackKeyExists = false; + // We never want the service to be used unless we build with // the maintenance service. #ifdef MOZ_MAINTENANCE_SERVICE IsUpdateStatusPending(useService); + // Our tests run with a different apply directory for each test. + // We use this registry key on our test slaves to store the + // allowed name/issuers. + HKEY testOnlyFallbackKey; + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + TEST_ONLY_FALLBACK_KEY_PATH, 0, + KEY_READ | KEY_WOW64_64KEY, + &testOnlyFallbackKey) == ERROR_SUCCESS) { + testOnlyFallbackKeyExists = true; + RegCloseKey(testOnlyFallbackKey); + } + #endif #endif @@ -1689,7 +1703,8 @@ int NS_main(int argc, NS_tchar **argv) sizeof(elevatedLockFilePath)/sizeof(elevatedLockFilePath[0]), NS_T("%s/update_elevated.lock"), argv[1]); - if (updateLockFileHandle == INVALID_HANDLE_VALUE) { + if (updateLockFileHandle == INVALID_HANDLE_VALUE || + (useService && testOnlyFallbackKeyExists)) { if (!_waccess(elevatedLockFilePath, F_OK) && NS_tremove(elevatedLockFilePath) != 0) { fprintf(stderr, "Update already elevated! Exiting\n"); @@ -1722,21 +1737,14 @@ int NS_main(int argc, NS_tchar **argv) WCHAR maintenanceServiceKey[MAX_PATH + 1]; if (CalculateRegistryPathFromFilePath(argv[2], maintenanceServiceKey)) { HKEY baseKey; - LSTATUS retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - maintenanceServiceKey, 0, - KEY_READ | KEY_WOW64_64KEY, - &baseKey); - if (retCode != ERROR_SUCCESS) { - // Our tests run with a different apply directory for each test. - // We use this registry key on our test slaves to store the - // allowed name/issuers. - retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Mozilla\\MaintenanceService" - L"\\3932ecacee736d366d6436db0f55bce4", 0, - KEY_READ | KEY_WOW64_64KEY, &baseKey); + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + maintenanceServiceKey, 0, + KEY_READ | KEY_WOW64_64KEY, + &baseKey) == ERROR_SUCCESS) { + RegCloseKey(baseKey); + } else { + useService = testOnlyFallbackKeyExists; } - useService = retCode == ERROR_SUCCESS; - RegCloseKey(baseKey); } else { useService = FALSE; }