Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit 8b086b7

Browse files
committed
Add opt-in hash based module.zip verification system.
1 parent 6414bd8 commit 8b086b7

File tree

12 files changed

+124
-13
lines changed

12 files changed

+124
-13
lines changed

app/src/main/java/com/fox2code/mmm/ActionButtonType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ public void doAction(ImageButton button, ModuleHolder moduleHolder) {
4747
if (moduleInfo == null) return;
4848
String updateZipUrl = moduleHolder.getUpdateZipUrl();
4949
if (updateZipUrl == null) return;
50+
String updateZipChecksum = moduleHolder.getUpdateZipChecksum();
5051
IntentHelper.openInstaller(button.getContext(), updateZipUrl,
51-
moduleInfo.name, moduleInfo.config);
52+
moduleInfo.name, moduleInfo.config, updateZipChecksum);
5253
}
5354
},
5455
UNINSTALL() {

app/src/main/java/com/fox2code/mmm/Constants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class Constants {
1313
public static final String EXTRA_INSTALL_PATH = "extra_install_path";
1414
public static final String EXTRA_INSTALL_NAME = "extra_install_name";
1515
public static final String EXTRA_INSTALL_CONFIG = "extra_install_config";
16+
public static final String EXTRA_INSTALL_CHECKSUM = "extra_install_checksum";
1617
public static final String EXTRA_INSTALL_NO_PATCH = "extra_install_no_patch";
1718
public static final String EXTRA_INSTALL_NO_EXTENSIONS = "extra_install_no_extensions";
1819
public static final String EXTRA_INSTALL_TEST_ROOTLESS = "extra_install_test_rootless";

app/src/main/java/com/fox2code/mmm/ModuleHolder.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,18 @@ public ModuleInfo getMainModuleInfo() {
6969

7070
public String getUpdateZipUrl() {
7171
return this.moduleInfo == null || (this.repoModule != null &&
72-
this.moduleInfo.updateVersionCode < this.repoModule.lastUpdated) ?
72+
this.moduleInfo.updateVersionCode <
73+
this.repoModule.moduleInfo.versionCode) ?
7374
this.repoModule.zipUrl : this.moduleInfo.updateZipUrl;
7475
}
7576

77+
public String getUpdateZipChecksum() {
78+
return this.moduleInfo == null || (this.repoModule != null &&
79+
this.moduleInfo.updateVersionCode <
80+
this.repoModule.moduleInfo.versionCode) ?
81+
this.repoModule.checksum : this.moduleInfo.updateChecksum;
82+
}
83+
7684
public String getMainModuleName() {
7785
ModuleInfo moduleInfo = this.getMainModuleInfo();
7886
if (moduleInfo == null || moduleInfo.name == null)

app/src/main/java/com/fox2code/mmm/NotificationType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public boolean shouldRemove() {
8989
} else {
9090
IntentHelper.openInstaller(compatActivity, d.getAbsolutePath(),
9191
compatActivity.getString(
92-
R.string.local_install_title), null, false,
92+
R.string.local_install_title), null, null, false,
9393
BuildConfig.DEBUG && // Use debug mode if no root
9494
InstallerInitializer.peekMagiskPath() == null);
9595
}
@@ -102,7 +102,7 @@ public boolean shouldRemove() {
102102
} else if (s == IntentHelper.RESPONSE_URL) {
103103
IntentHelper.openInstaller(compatActivity, u.toString(),
104104
compatActivity.getString(
105-
R.string.remote_install_title), null, false,
105+
R.string.remote_install_title), null, null, false,
106106
BuildConfig.DEBUG && // Use debug mode if no root
107107
InstallerInitializer.peekMagiskPath() == null);
108108
}

app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyWebAPI.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public void install(String moduleUrl, String installTitle,String checksum) {
7979
moduleUrl + " " + installTitle + " " + checksum);
8080
Uri uri = Uri.parse(moduleUrl);
8181
if (uri.getScheme().equals("https") && uri.getHost().endsWith(".androidacy.com")) {
82-
IntentHelper.openInstaller(this.activity, moduleUrl, installTitle, null);
82+
IntentHelper.openInstaller(this.activity,
83+
moduleUrl, installTitle, null, checksum);
8384
} else {
8485
this.activity.forceBackPressed();
8586
}

app/src/main/java/com/fox2code/mmm/installer/InstallerActivity.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.fox2code.mmm.compat.CompatActivity;
2323
import com.fox2code.mmm.utils.FastException;
2424
import com.fox2code.mmm.utils.Files;
25+
import com.fox2code.mmm.utils.Hashes;
2526
import com.fox2code.mmm.utils.Http;
2627
import com.fox2code.mmm.utils.IntentHelper;
2728
import com.google.android.material.progressindicator.LinearProgressIndicator;
@@ -54,6 +55,7 @@ protected void onCreate(Bundle savedInstanceState) {
5455
final Intent intent = this.getIntent();
5556
final String target;
5657
final String name;
58+
final String checksum;
5759
final boolean noPatch;
5860
final boolean noExtensions;
5961
final boolean rootless;
@@ -66,6 +68,7 @@ protected void onCreate(Bundle savedInstanceState) {
6668
}
6769
target = intent.getStringExtra(Constants.EXTRA_INSTALL_PATH);
6870
name = intent.getStringExtra(Constants.EXTRA_INSTALL_NAME);
71+
checksum = intent.getStringExtra(Constants.EXTRA_INSTALL_CHECKSUM);
6972
noPatch = intent.getBooleanExtra(Constants.EXTRA_INSTALL_NO_PATCH, false);
7073
noExtensions = intent.getBooleanExtra(// Allow intent to disable extensions
7174
Constants.EXTRA_INSTALL_NO_EXTENSIONS, false);
@@ -122,6 +125,15 @@ protected void onCreate(Bundle savedInstanceState) {
122125
this.progressIndicator.setProgressCompat(progress, true);
123126
});
124127
});
128+
if (checksum != null && !checksum.isEmpty()) {
129+
Log.d(TAG, "Checking for checksum: " + checksum);
130+
this.installerTerminal.addLine("- Checking file integrity");
131+
if (!Hashes.checkSumMatch(rawModule, checksum)) {
132+
this.setInstallStateFinished(false,
133+
"! File integrity check failed", "");
134+
return;
135+
}
136+
}
125137
if (noPatch) {
126138
try (OutputStream outputStream = new FileOutputStream(moduleCache)) {
127139
outputStream.write(rawModule);
@@ -152,13 +164,31 @@ protected void onCreate(Bundle savedInstanceState) {
152164
}
153165
}, "Module download Thread").start();
154166
} else {
167+
final File moduleFile = new File(target);
168+
if (checksum != null && !checksum.isEmpty()) {
169+
Log.d(TAG, "Checking for checksum: " + checksum);
170+
this.installerTerminal.addLine("- Checking file integrity");
171+
try {
172+
if (!Hashes.checkSumMatch(Files.readSU(moduleFile), checksum)) {
173+
this.setInstallStateFinished(false,
174+
"! File integrity check failed", "");
175+
return;
176+
}
177+
} catch (IOException e) {
178+
Log.e(TAG, "Failed to read file for checksum check", e);
179+
this.setInstallStateFinished(false,
180+
"! File integrity check failed", "");
181+
return;
182+
}
183+
}
155184
this.installerTerminal.addLine("- Installing " + name);
156185
new Thread(() -> this.doInstall(
157-
this.toDelete = new File(target), noExtensions, rootless),
186+
this.toDelete = moduleFile, noExtensions, rootless),
158187
"Install Thread").start();
159188
}
160189
}
161190

191+
162192
private void doInstall(File file,boolean noExtensions,boolean rootless) {
163193
Log.i(TAG, "Installing: " + moduleCache.getName());
164194
InstallerController installerController = new InstallerController(

app/src/main/java/com/fox2code/mmm/manager/LocalModuleInfo.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class LocalModuleInfo extends ModuleInfo {
1515
public long updateVersionCode = Long.MIN_VALUE;
1616
public String updateZipUrl;
1717
public String updateChangeLog;
18+
public String updateChecksum;
1819

1920
public LocalModuleInfo(String id) {
2021
super(id);
@@ -29,6 +30,7 @@ public void checkModuleUpdate() {
2930
this.updateVersionCode = jsonUpdate.getLong("versionCode");
3031
this.updateZipUrl = jsonUpdate.getString("zipUrl");
3132
this.updateChangeLog = jsonUpdate.optString("changelog");
33+
this.updateChecksum = jsonUpdate.optString("checksum");
3234
if (this.updateZipUrl.isEmpty()) throw FastException.INSTANCE;
3335
this.updateVersion = PropUtils.shortenVersionName(
3436
this.updateVersion.trim(), this.updateVersionCode);
@@ -37,6 +39,7 @@ public void checkModuleUpdate() {
3739
this.updateVersionCode = Long.MIN_VALUE;
3840
this.updateZipUrl = null;
3941
this.updateChangeLog = null;
42+
this.updateChecksum = null;
4043
Log.w("LocalModuleInfo",
4144
"Failed update checking for module: " + this.id, e);
4245
}

app/src/main/java/com/fox2code/mmm/repo/RepoData.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ List<RepoModule> populate(JSONObject jsonObject) throws JSONException {
118118
String moduleNotesUrl = module.getString("notes_url");
119119
String modulePropsUrl = module.getString("prop_url");
120120
String moduleZipUrl = module.getString("zip_url");
121+
String moduleChecksum = module.optString("checksum");
121122
if (moduleLastUpdateSpecial != null) { // Fix last update time
122123
Log.d("RepoData", "Data: " + moduleLastUpdate + " -> " +
123124
moduleLastUpdateSpecial + " for " + moduleId);
@@ -147,6 +148,7 @@ List<RepoModule> populate(JSONObject jsonObject) throws JSONException {
147148
repoModule.notesUrl = moduleNotesUrl;
148149
repoModule.propUrl = modulePropsUrl;
149150
repoModule.zipUrl = moduleZipUrl;
151+
repoModule.checksum = moduleChecksum;
150152
}
151153
// Remove no longer existing modules
152154
Iterator<RepoModule> moduleInfoIterator = this.moduleHashMap.values().iterator();

app/src/main/java/com/fox2code/mmm/repo/RepoManager.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.fox2code.mmm.utils.PropUtils;
1313

1414
import java.io.File;
15+
import java.nio.charset.StandardCharsets;
1516
import java.util.HashMap;
1617
import java.util.LinkedHashMap;
1718
import java.util.List;
@@ -230,7 +231,8 @@ public static String internalIdOfUrl(String url) {
230231
case MAGISK_ALT_REPO_JSDELIVR:
231232
return "magisk_alt_repo";
232233
default:
233-
return "repo_" + Hashes.hashSha1(url);
234+
return "repo_" + Hashes.hashSha1(
235+
url.getBytes(StandardCharsets.UTF_8));
234236
}
235237
}
236238

app/src/main/java/com/fox2code/mmm/repo/RepoModule.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public class RepoModule {
1010
public String propUrl;
1111
public String zipUrl;
1212
public String notesUrl;
13+
public String checksum;
1314
boolean processed;
1415

1516
public RepoModule(String id) {

0 commit comments

Comments
 (0)