Skip to content

Commit 5529153

Browse files
committed
Fix missing hash verification
1 parent 4e73f5a commit 5529153

5 files changed

Lines changed: 150 additions & 91 deletions

File tree

android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -270,30 +270,26 @@ public void downloadPackage(JSONObject updatePackage, String expectedBundleFileN
270270
String signaturePath = CodePushUpdateUtils.getSignatureFilePath(newUpdateFolderPath);
271271
boolean isSignatureAppearedInBundle = FileUtils.fileAtPathExists(signaturePath);
272272

273+
if (isSignatureVerificationEnabled && !isSignatureAppearedInBundle) {
274+
throw new CodePushInvalidUpdateException(
275+
"Error! Public key was provided but there is no JWT signature within app bundle to verify. " +
276+
"Possible reasons, why that might happen: \n" +
277+
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" +
278+
"2. You've been released CodePush bundle update without providing --privateKeyPath option."
279+
);
280+
}
281+
282+
if (!isSignatureVerificationEnabled && isSignatureAppearedInBundle) {
283+
CodePushUtils.log(
284+
"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed because there is no public key configured. " +
285+
"Please ensure that public key is properly configured within your application."
286+
);
287+
}
288+
289+
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
290+
273291
if (isSignatureVerificationEnabled) {
274-
if (isSignatureAppearedInBundle) {
275-
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
276-
CodePushUpdateUtils.verifyUpdateSignature(newUpdateFolderPath, newUpdateHash, stringPublicKey);
277-
} else {
278-
throw new CodePushInvalidUpdateException(
279-
"Error! Public key was provided but there is no JWT signature within app bundle to verify. " +
280-
"Possible reasons, why that might happen: \n" +
281-
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" +
282-
"2. You've been released CodePush bundle update without providing --privateKeyPath option."
283-
);
284-
}
285-
} else {
286-
if (isSignatureAppearedInBundle) {
287-
CodePushUtils.log(
288-
"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed because there is no public key configured. " +
289-
"Please ensure that public key is properly configured within your application."
290-
);
291-
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
292-
} else {
293-
if (isDiffUpdate) {
294-
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
295-
}
296-
}
292+
CodePushUpdateUtils.verifyUpdateSignature(newUpdateFolderPath, newUpdateHash, stringPublicKey);
297293
}
298294

299295
CodePushUtils.setJSONValueForKey(updatePackage, CodePushConstants.RELATIVE_BUNDLE_PATH_KEY, relativeBundlePath);

code-push-plugin-testing-framework/script/serverUtil.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ function setupServer(targetPlatform) {
2222
});
2323
app.get("/v0.1/public/codepush/update_check", function (req, res) {
2424
exports.updateCheckCallback && exports.updateCheckCallback(req);
25+
applyKnownPackageHash();
2526
res.send(exports.updateResponse);
2627
console.log("Update check called from the app.");
2728
console.log("Request: " + JSON.stringify(req.query));
@@ -53,6 +54,36 @@ function setupServer(targetPlatform) {
5354
exports.server = app.listen(+targetPlatform.getServerUrl().match(serverPortRegEx)[1]);
5455
}
5556
exports.setupServer = setupServer;
57+
/**
58+
* The real content hash of each update archive built during this run, keyed by archive path.
59+
* Populated by setPackageHashForPath and applied to exports.updateResponse.
60+
*/
61+
var packageHashesByPath = {};
62+
var _updatePackagePath;
63+
Object.defineProperty(exports, "updatePackagePath", {
64+
enumerable: true,
65+
configurable: true,
66+
get: function () { return _updatePackagePath; },
67+
set: function (value) {
68+
_updatePackagePath = value;
69+
applyKnownPackageHash();
70+
}
71+
});
72+
/**
73+
* Records the real content hash for an update archive, so that any update_check response
74+
* pointing exports.updatePackagePath at this archive gets the matching package_hash instead
75+
* of the one filled in by default.
76+
*/
77+
function setPackageHashForPath(archivePath, packageHash) {
78+
packageHashesByPath[archivePath] = packageHash;
79+
}
80+
exports.setPackageHashForPath = setPackageHashForPath;
81+
function applyKnownPackageHash() {
82+
var knownHash = _updatePackagePath && packageHashesByPath[_updatePackagePath];
83+
if (knownHash && exports.updateResponse && exports.updateResponse.update_info) {
84+
exports.updateResponse.update_info.package_hash = knownHash;
85+
}
86+
}
5687
/**
5788
* Closes the server.
5889
*/

code-push-plugin-testing-framework/typings/code-push-plugin-testing-framework.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,11 @@ declare module 'code-push-plugin-testing-framework/script/serverUtil' {
290290
* Closes the server.
291291
*/
292292
export function cleanupServer(): void;
293+
/**
294+
* Records the real content hash for an update archive at archivePath, so any future
295+
* update_check response pointing updatePackagePath at it gets a matching package_hash.
296+
*/
297+
export function setPackageHashForPath(archivePath: string, packageHash: string): void;
293298
/**
294299
* Class used to mock the codePush.checkForUpdate() response from the server.
295300
*/

ios/CodePush/CodePushPackage.m

Lines changed: 39 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -243,69 +243,50 @@ + (void)downloadPackage:(NSDictionary *)updatePackage
243243
NSString *signatureFilePath = [CodePushUpdateUtils getSignatureFilePath:newUpdateFolderPath];
244244
BOOL isSignatureAppearedInBundle = [[NSFileManager defaultManager] fileExistsAtPath:signatureFilePath];
245245

246+
if (isSignatureVerificationEnabled && !isSignatureAppearedInBundle) {
247+
error = [CodePushErrorUtils errorWithMessage:
248+
@"Error! Public key was provided but there is no JWT signature within app bundle to verify " \
249+
"Possible reasons, why that might happen: \n" \
250+
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" \
251+
"2. You've been released CodePush bundle update without providing --privateKeyPath option."];
252+
failCallback(error);
253+
return;
254+
}
255+
256+
if (!isSignatureVerificationEnabled && isSignatureAppearedInBundle) {
257+
CPLog(@"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed" \
258+
" because there is no public key configured. " \
259+
"Please ensure that public key is properly configured within your application.");
260+
}
261+
262+
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
263+
expectedHash:newUpdateHash
264+
error:&error]) {
265+
CPLog(@"The update contents failed the data integrity check.");
266+
if (!error) {
267+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
268+
}
269+
270+
failCallback(error);
271+
return;
272+
} else {
273+
CPLog(@"The update contents succeeded the data integrity check.");
274+
}
275+
246276
if (isSignatureVerificationEnabled) {
247-
if (isSignatureAppearedInBundle) {
248-
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
249-
expectedHash:newUpdateHash
250-
error:&error]) {
251-
CPLog(@"The update contents failed the data integrity check.");
252-
if (!error) {
253-
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
254-
}
255-
256-
failCallback(error);
257-
return;
258-
} else {
259-
CPLog(@"The update contents succeeded the data integrity check.");
277+
BOOL isSignatureValid = [CodePushUpdateUtils verifyUpdateSignatureFor:newUpdateFolderPath
278+
expectedHash:newUpdateHash
279+
withPublicKey:publicKey
280+
error:&error];
281+
if (!isSignatureValid) {
282+
CPLog(@"The update contents failed code signing check.");
283+
if (!error) {
284+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed code signing check."];
260285
}
261-
BOOL isSignatureValid = [CodePushUpdateUtils verifyUpdateSignatureFor:newUpdateFolderPath
262-
expectedHash:newUpdateHash
263-
withPublicKey:publicKey
264-
error:&error];
265-
if (!isSignatureValid) {
266-
CPLog(@"The update contents failed code signing check.");
267-
if (!error) {
268-
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed code signing check."];
269-
}
270-
failCallback(error);
271-
return;
272-
} else {
273-
CPLog(@"The update contents succeeded the code signing check.");
274-
}
275-
} else {
276-
error = [CodePushErrorUtils errorWithMessage:
277-
@"Error! Public key was provided but there is no JWT signature within app bundle to verify " \
278-
"Possible reasons, why that might happen: \n" \
279-
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" \
280-
"2. You've been released CodePush bundle update without providing --privateKeyPath option."];
281286
failCallback(error);
282287
return;
283-
}
284-
285-
} else {
286-
BOOL needToVerifyHash;
287-
if (isSignatureAppearedInBundle) {
288-
CPLog(@"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed" \
289-
" because there is no public key configured. " \
290-
"Please ensure that public key is properly configured within your application.");
291-
needToVerifyHash = true;
292288
} else {
293-
needToVerifyHash = isDiffUpdate;
294-
}
295-
if(needToVerifyHash){
296-
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
297-
expectedHash:newUpdateHash
298-
error:&error]) {
299-
CPLog(@"The update contents failed the data integrity check.");
300-
if (!error) {
301-
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
302-
}
303-
304-
failCallback(error);
305-
return;
306-
} else {
307-
CPLog(@"The update contents succeeded the data integrity check.");
308-
}
289+
CPLog(@"The update contents succeeded the code signing check.");
309290
}
310291
}
311292
} else {

0 commit comments

Comments
 (0)