Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -270,30 +270,26 @@ public void downloadPackage(JSONObject updatePackage, String expectedBundleFileN
String signaturePath = CodePushUpdateUtils.getSignatureFilePath(newUpdateFolderPath);
boolean isSignatureAppearedInBundle = FileUtils.fileAtPathExists(signaturePath);

if (isSignatureVerificationEnabled && !isSignatureAppearedInBundle) {
throw new CodePushInvalidUpdateException(
"Error! Public key was provided but there is no JWT signature within app bundle to verify. " +
"Possible reasons, why that might happen: \n" +
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" +
"2. You've been released CodePush bundle update without providing --privateKeyPath option."
);
}

if (!isSignatureVerificationEnabled && isSignatureAppearedInBundle) {
CodePushUtils.log(
"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed because there is no public key configured. " +
"Please ensure that public key is properly configured within your application."
);
}

CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);

if (isSignatureVerificationEnabled) {
if (isSignatureAppearedInBundle) {
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
CodePushUpdateUtils.verifyUpdateSignature(newUpdateFolderPath, newUpdateHash, stringPublicKey);
} else {
throw new CodePushInvalidUpdateException(
"Error! Public key was provided but there is no JWT signature within app bundle to verify. " +
"Possible reasons, why that might happen: \n" +
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" +
"2. You've been released CodePush bundle update without providing --privateKeyPath option."
);
}
} else {
if (isSignatureAppearedInBundle) {
CodePushUtils.log(
"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed because there is no public key configured. " +
"Please ensure that public key is properly configured within your application."
);
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
} else {
if (isDiffUpdate) {
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
}
}
CodePushUpdateUtils.verifyUpdateSignature(newUpdateFolderPath, newUpdateHash, stringPublicKey);
}

CodePushUtils.setJSONValueForKey(updatePackage, CodePushConstants.RELATIVE_BUNDLE_PATH_KEY, relativeBundlePath);
Expand Down
35 changes: 35 additions & 0 deletions code-push-plugin-testing-framework/script/serverUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function setupServer(targetPlatform) {
});
app.get("/v0.1/public/codepush/update_check", function (req, res) {
exports.updateCheckCallback && exports.updateCheckCallback(req);
applyKnownPackageHash();
res.send(exports.updateResponse);
console.log("Update check called from the app.");
console.log("Request: " + JSON.stringify(req.query));
Expand Down Expand Up @@ -53,6 +54,40 @@ function setupServer(targetPlatform) {
exports.server = app.listen(+targetPlatform.getServerUrl().match(serverPortRegEx)[1]);
}
exports.setupServer = setupServer;
/**
* The real content hash of each update archive built during this run, keyed by archive path.
* Populated by setPackageHashForPath (called once when an archive is built) and applied to
* exports.updateResponse both immediately (see the updatePackagePath setter below) and again
* right before every update_check response - a test may set updateResponse and updatePackagePath
* in either order, or point updatePackagePath at an already-built archive again (e.g. after an
* app restart) without rebuilding it or recomputing its hash.
*/
var packageHashesByPath = {};
var _updatePackagePath;
Object.defineProperty(exports, "updatePackagePath", {
enumerable: true,
configurable: true,
get: function () { return _updatePackagePath; },
set: function (value) {
_updatePackagePath = value;
applyKnownPackageHash();
}
});
/**
* Records the real content hash for an update archive, so that any update_check response
* pointing exports.updatePackagePath at this archive gets the matching package_hash instead
* of the arbitrary/random one createUpdateResponse() fills in by default.
*/
function setPackageHashForPath(archivePath, packageHash) {
packageHashesByPath[archivePath] = packageHash;
}
exports.setPackageHashForPath = setPackageHashForPath;
function applyKnownPackageHash() {
var knownHash = _updatePackagePath && packageHashesByPath[_updatePackagePath];
if (knownHash && exports.updateResponse && exports.updateResponse.update_info) {
exports.updateResponse.update_info.package_hash = knownHash;
}
}
/**
* Closes the server.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ declare module 'code-push-plugin-testing-framework/script/serverUtil' {
* Closes the server.
*/
export function cleanupServer(): void;
/**
* Records the real content hash for an update archive at archivePath, so any future
* update_check response pointing updatePackagePath at it gets a matching package_hash.
*/
export function setPackageHashForPath(archivePath: string, packageHash: string): void;
/**
* Class used to mock the codePush.checkForUpdate() response from the server.
*/
Expand Down
97 changes: 39 additions & 58 deletions ios/CodePush/CodePushPackage.m
Original file line number Diff line number Diff line change
Expand Up @@ -243,69 +243,50 @@ + (void)downloadPackage:(NSDictionary *)updatePackage
NSString *signatureFilePath = [CodePushUpdateUtils getSignatureFilePath:newUpdateFolderPath];
BOOL isSignatureAppearedInBundle = [[NSFileManager defaultManager] fileExistsAtPath:signatureFilePath];

if (isSignatureVerificationEnabled && !isSignatureAppearedInBundle) {
error = [CodePushErrorUtils errorWithMessage:
@"Error! Public key was provided but there is no JWT signature within app bundle to verify " \
"Possible reasons, why that might happen: \n" \
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" \
"2. You've been released CodePush bundle update without providing --privateKeyPath option."];
failCallback(error);
return;
}

if (!isSignatureVerificationEnabled && isSignatureAppearedInBundle) {
CPLog(@"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed" \
" because there is no public key configured. " \
"Please ensure that public key is properly configured within your application.");
}

if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
expectedHash:newUpdateHash
error:&error]) {
CPLog(@"The update contents failed the data integrity check.");
if (!error) {
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
}

failCallback(error);
return;
} else {
CPLog(@"The update contents succeeded the data integrity check.");
}

if (isSignatureVerificationEnabled) {
if (isSignatureAppearedInBundle) {
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
expectedHash:newUpdateHash
error:&error]) {
CPLog(@"The update contents failed the data integrity check.");
if (!error) {
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
}

failCallback(error);
return;
} else {
CPLog(@"The update contents succeeded the data integrity check.");
BOOL isSignatureValid = [CodePushUpdateUtils verifyUpdateSignatureFor:newUpdateFolderPath
expectedHash:newUpdateHash
withPublicKey:publicKey
error:&error];
if (!isSignatureValid) {
CPLog(@"The update contents failed code signing check.");
if (!error) {
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed code signing check."];
}
BOOL isSignatureValid = [CodePushUpdateUtils verifyUpdateSignatureFor:newUpdateFolderPath
expectedHash:newUpdateHash
withPublicKey:publicKey
error:&error];
if (!isSignatureValid) {
CPLog(@"The update contents failed code signing check.");
if (!error) {
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed code signing check."];
}
failCallback(error);
return;
} else {
CPLog(@"The update contents succeeded the code signing check.");
}
} else {
error = [CodePushErrorUtils errorWithMessage:
@"Error! Public key was provided but there is no JWT signature within app bundle to verify " \
"Possible reasons, why that might happen: \n" \
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" \
"2. You've been released CodePush bundle update without providing --privateKeyPath option."];
failCallback(error);
return;
}

} else {
BOOL needToVerifyHash;
if (isSignatureAppearedInBundle) {
CPLog(@"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed" \
" because there is no public key configured. " \
"Please ensure that public key is properly configured within your application.");
needToVerifyHash = true;
} else {
needToVerifyHash = isDiffUpdate;
}
if(needToVerifyHash){
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
expectedHash:newUpdateHash
error:&error]) {
CPLog(@"The update contents failed the data integrity check.");
if (!error) {
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
}

failCallback(error);
return;
} else {
CPLog(@"The update contents succeeded the data integrity check.");
}
CPLog(@"The update contents succeeded the code signing check.");
}
}
} else {
Expand Down
Loading