зеркало из https://github.com/mozilla/gecko-dev.git
Bug 708690 - Updater enhancements for product information blocks. r=rstrong
This commit is contained in:
Родитель
80084f79ea
Коммит
dbab800567
|
@ -59,6 +59,10 @@
|
|||
#define CERT_LOAD_ERROR 17
|
||||
#define CERT_HANDLING_ERROR 18
|
||||
#define CERT_VERIFY_ERROR 19
|
||||
#define ARCHIVE_NOT_OPEN 20
|
||||
#define COULD_NOT_READ_PRODUCT_INFO_BLOCK_ERROR 21
|
||||
#define MAR_CHANNEL_MISMATCH_ERROR 22
|
||||
#define VERSION_DOWNGRADE_ERROR 23
|
||||
|
||||
// The following error codes are only used by updater.exe
|
||||
// when a fallback key exists and XPCShell tests are being run.
|
||||
|
|
|
@ -112,7 +112,10 @@ endif
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -DNS_NO_XPCOM
|
||||
DEFINES += -DNS_NO_XPCOM \
|
||||
-DMAR_CHANNEL_ID='"$(MAR_CHANNEL_ID)"' \
|
||||
-DMOZ_APP_VERSION='"$(MOZ_APP_VERSION)"' \
|
||||
$(NULL)
|
||||
|
||||
ifdef _MSC_VER
|
||||
WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
|
||||
|
|
|
@ -42,6 +42,12 @@
|
|||
#include "bzlib.h"
|
||||
#include "archivereader.h"
|
||||
#include "errors.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "updatehelper.h"
|
||||
|
||||
#define UPDATER_NO_STRING_GLUE_STL
|
||||
#include "../../../../xpcom/build/nsVersionComparator.cpp"
|
||||
#undef UPDATER_NO_STRING_GLUE_STL
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
# include <sys/types.h>
|
||||
|
@ -113,7 +119,7 @@ VerifyLoadedCert(MarFile *archive, int name, int type)
|
|||
return CERT_LOAD_ERROR;
|
||||
}
|
||||
|
||||
if (!archive || mar_verify_signatureW(archive, data, size)) {
|
||||
if (mar_verify_signatureW(archive, data, size)) {
|
||||
return CERT_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
|
@ -133,6 +139,10 @@ VerifyLoadedCert(MarFile *archive, int name, int type)
|
|||
int
|
||||
ArchiveReader::VerifySignature()
|
||||
{
|
||||
if (!mArchive) {
|
||||
return ARCHIVE_NOT_OPEN;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
int rv = VerifyLoadedCert(mArchive, IDR_PRIMARY_CERT, TYPE_CERT);
|
||||
if (rv != OK) {
|
||||
|
@ -144,6 +154,70 @@ ArchiveReader::VerifySignature()
|
|||
#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
|
||||
* for the channel name in the product information block.
|
||||
* @param appVersion The application version to use, only MARs with an
|
||||
* application version >= to appVersion will be applied.
|
||||
* @return OK on success
|
||||
* COULD_NOT_READ_PRODUCT_INFO_BLOCK if the product info block
|
||||
* could not be read.
|
||||
* MARCHANNEL_MISMATCH_ERROR if update-settings.ini's MAR
|
||||
* channel ID doesn't match the MAR
|
||||
* file's MAR channel ID.
|
||||
* VERSION_DOWNGRADE_ERROR if the application version for
|
||||
* this updater is newer than the
|
||||
* one in the MAR.
|
||||
*/
|
||||
int
|
||||
ArchiveReader::VerifyProductInformation(const char *MARChannelID,
|
||||
const char *appVersion)
|
||||
{
|
||||
if (!mArchive) {
|
||||
return ARCHIVE_NOT_OPEN;
|
||||
}
|
||||
|
||||
ProductInformationBlock productInfoBlock;
|
||||
int rv = mar_read_product_info_block(mArchive,
|
||||
&productInfoBlock);
|
||||
if (rv != OK) {
|
||||
return COULD_NOT_READ_PRODUCT_INFO_BLOCK_ERROR;
|
||||
}
|
||||
|
||||
// Only check the MAR channel name if specified, it should be passed in from
|
||||
// the update-settings.ini file.
|
||||
if (MARChannelID && strlen(MARChannelID)) {
|
||||
if (rv == OK && strcmp(MARChannelID, productInfoBlock.MARChannelID)) {
|
||||
rv = MAR_CHANNEL_MISMATCH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv == OK) {
|
||||
/* Compare both versions to ensure we don't have a downgrade
|
||||
1 if appVersion is older than productInfoBlock.productVersion
|
||||
-1 if appVersion is newer than productInfoBlock.productVersion
|
||||
0 if appVersion is the same as productInfoBlock.productVersion
|
||||
This even works with strings like:
|
||||
- 12.0a1 being older than 12.0a2
|
||||
- 12.0a2 being older than 12.0b1
|
||||
- 12.0a1 being older than 12.0
|
||||
- 12.0 being older than 12.1a1 */
|
||||
int versionCompareResult =
|
||||
NS_CompareVersions(appVersion, productInfoBlock.productVersion);
|
||||
if (-1 == versionCompareResult) {
|
||||
rv = VERSION_DOWNGRADE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
free((void *)productInfoBlock.MARChannelID);
|
||||
free((void *)productInfoBlock.productVersion);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
ArchiveReader::Open(const NS_tchar *path)
|
||||
{
|
||||
|
|
|
@ -57,6 +57,8 @@ public:
|
|||
|
||||
int Open(const NS_tchar *path);
|
||||
int VerifySignature();
|
||||
int VerifyProductInformation(const char *MARChannelID,
|
||||
const char *appVersion);
|
||||
void Close();
|
||||
|
||||
int ExtractFile(const char *item, const NS_tchar *destination);
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "bspatch.h"
|
||||
#include "progressui.h"
|
||||
#include "archivereader.h"
|
||||
#include "readstrings.h"
|
||||
#include "errors.h"
|
||||
#include "bzlib.h"
|
||||
|
||||
|
@ -191,6 +192,15 @@ private:
|
|||
FILE* mFile;
|
||||
};
|
||||
|
||||
struct MARChannelStringTable {
|
||||
MARChannelStringTable()
|
||||
{
|
||||
MARChannelID[0] = '\0';
|
||||
}
|
||||
|
||||
char MARChannelID[MAX_TEXT_LEN];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef void (* ThreadFunc)(void *param);
|
||||
|
@ -1530,6 +1540,29 @@ WaitForServiceFinishThread(void *param)
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function reads in the MAR_CHANNEL_ID from update-settings.ini
|
||||
*
|
||||
* @param path The path to the ini file that is to be read
|
||||
* @param results A pointer to the location to store the read strings
|
||||
* @return OK on success
|
||||
*/
|
||||
static int
|
||||
ReadMARChannelIDs(const NS_tchar *path, MARChannelStringTable *results)
|
||||
{
|
||||
const unsigned int kNumStrings = 1;
|
||||
const char *kUpdaterKeys = "MAR_CHANNEL_ID\0";
|
||||
char updater_strings[kNumStrings][MAX_TEXT_LEN];
|
||||
|
||||
int result = ReadStrings(path, kUpdaterKeys, kNumStrings,
|
||||
updater_strings, "Settings");
|
||||
|
||||
strncpy(results->MARChannelID, updater_strings[0], MAX_TEXT_LEN - 1);
|
||||
results->MARChannelID[MAX_TEXT_LEN - 1] = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateThreadFunc(void *param)
|
||||
{
|
||||
|
@ -1548,6 +1581,22 @@ UpdateThreadFunc(void *param)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (rv == OK) {
|
||||
NS_tchar updateSettingsPath[MAX_TEXT_LEN];
|
||||
NS_tsnprintf(updateSettingsPath,
|
||||
sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]),
|
||||
NS_T("%supdate-settings.ini"), gDestPath);
|
||||
MARChannelStringTable MARStrings;
|
||||
if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK) {
|
||||
// If we can't read from update-settings.ini then we shouldn't impose
|
||||
// a MAR restriction. Some installatins won't even include this file.
|
||||
MARStrings.MARChannelID[0] = '\0';
|
||||
}
|
||||
|
||||
rv = gArchiveReader.VerifyProductInformation(MARStrings.MARChannelID,
|
||||
MOZ_APP_VERSION);
|
||||
}
|
||||
|
||||
if (rv == OK) {
|
||||
rv = DoUpdate();
|
||||
gArchiveReader.Close();
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef XP_WIN
|
||||
#if defined(XP_WIN) && !defined(UPDATER_NO_STRING_GLUE_STL)
|
||||
#include <wchar.h>
|
||||
#include "nsStringGlue.h"
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче