Allow updates when self verification is disabled (#2639)
* Allow updates when self verification is disabled * clean up IntegrityChecker * Fix: UpdateHandler would transfer the current command properties to the new HMCL. * Fix. * Fix. * update * update * update * update --------- Co-authored-by: Glavo <zjx001202@gmail.com>
This commit is contained in:
@@ -46,6 +46,8 @@ import static org.jackhuang.hmcl.util.Logging.LOG;
|
|||||||
public final class IntegrityChecker {
|
public final class IntegrityChecker {
|
||||||
private IntegrityChecker() {}
|
private IntegrityChecker() {}
|
||||||
|
|
||||||
|
public static final boolean DISABLE_SELF_INTEGRITY_CHECK = "true".equals(System.getProperty("hmcl.self_integrity_check.disable"));
|
||||||
|
|
||||||
private static final String SIGNATURE_FILE = "META-INF/hmcl_signature";
|
private static final String SIGNATURE_FILE = "META-INF/hmcl_signature";
|
||||||
private static final String PUBLIC_KEY_FILE = "assets/hmcl_signature_publickey.der";
|
private static final String PUBLIC_KEY_FILE = "assets/hmcl_signature_publickey.der";
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ public final class IntegrityChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean verifyJar(Path jarPath) throws IOException {
|
static void verifyJar(Path jarPath) throws IOException {
|
||||||
PublicKey publickey = getPublicKey();
|
PublicKey publickey = getPublicKey();
|
||||||
MessageDigest md = DigestUtils.getDigest("SHA-512");
|
MessageDigest md = DigestUtils.getDigest("SHA-512");
|
||||||
|
|
||||||
@@ -96,18 +98,14 @@ public final class IntegrityChecker {
|
|||||||
verifier.update(md.digest(entry.getKey().getBytes(UTF_8)));
|
verifier.update(md.digest(entry.getKey().getBytes(UTF_8)));
|
||||||
verifier.update(entry.getValue());
|
verifier.update(entry.getValue());
|
||||||
}
|
}
|
||||||
return verifier.verify(signature);
|
if (!verifier.verify(signature)) {
|
||||||
|
throw new IOException("Invalid signature: " + jarPath);
|
||||||
|
}
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new IOException("Failed to verify signature", e);
|
throw new IOException("Failed to verify signature", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void requireVerifiedJar(Path jar) throws IOException {
|
|
||||||
if (!verifyJar(jar)) {
|
|
||||||
throw new IOException("Invalid signature: " + jar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static volatile Boolean selfVerified = null;
|
private static volatile Boolean selfVerified = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,7 +123,12 @@ public final class IntegrityChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
verifySelf();
|
Path jarPath = JarUtils.thisJarPath();
|
||||||
|
if (jarPath == null) {
|
||||||
|
throw new IOException("Failed to find current HMCL location");
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyJar(jarPath);
|
||||||
LOG.info("Successfully verified current JAR");
|
LOG.info("Successfully verified current JAR");
|
||||||
selfVerified = true;
|
selfVerified = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -140,12 +143,4 @@ public final class IntegrityChecker {
|
|||||||
public static boolean isOfficial() {
|
public static boolean isOfficial() {
|
||||||
return isSelfVerified() || (Metadata.GITHUB_SHA != null && Metadata.BUILD_CHANNEL.equals("nightly"));
|
return isSelfVerified() || (Metadata.GITHUB_SHA != null && Metadata.BUILD_CHANNEL.equals("nightly"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void verifySelf() throws IOException {
|
|
||||||
Path self = JarUtils.thisJarPath();
|
|
||||||
if (self == null) {
|
|
||||||
throw new IOException("Failed to find current HMCL location");
|
|
||||||
}
|
|
||||||
requireVerifiedJar(self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public final class UpdateChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static RemoteVersion checkUpdate(UpdateChannel channel) throws IOException {
|
private static RemoteVersion checkUpdate(UpdateChannel channel) throws IOException {
|
||||||
if (!IntegrityChecker.isSelfVerified() && !"true".equals(System.getProperty("hmcl.self_integrity_check.disable"))) {
|
if (!IntegrityChecker.DISABLE_SELF_INTEGRITY_CHECK && !IntegrityChecker.isSelfVerified()) {
|
||||||
throw new IOException("Self verification failed");
|
throw new IOException("Self verification failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public final class UpdateHandler {
|
|||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
try {
|
try {
|
||||||
if (!IntegrityChecker.isSelfVerified()) {
|
if (!IntegrityChecker.isSelfVerified() && !IntegrityChecker.DISABLE_SELF_INTEGRITY_CHECK) {
|
||||||
throw new IOException("Current JAR is not verified");
|
throw new IOException("Current JAR is not verified");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +138,9 @@ public final class UpdateHandler {
|
|||||||
LOG.info("Applying update to " + target);
|
LOG.info("Applying update to " + target);
|
||||||
|
|
||||||
Path self = getCurrentLocation();
|
Path self = getCurrentLocation();
|
||||||
IntegrityChecker.requireVerifiedJar(self);
|
if (!IntegrityChecker.DISABLE_SELF_INTEGRITY_CHECK && !IntegrityChecker.isSelfVerified()) {
|
||||||
|
throw new IOException("Self verification failed");
|
||||||
|
}
|
||||||
ExecutableHeaderHelper.copyWithHeader(self, target);
|
ExecutableHeaderHelper.copyWithHeader(self, target);
|
||||||
|
|
||||||
Optional<Path> newFilename = tryRename(target, Metadata.VERSION);
|
Optional<Path> newFilename = tryRename(target, Metadata.VERSION);
|
||||||
@@ -156,13 +158,21 @@ public final class UpdateHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void requestUpdate(Path updateTo, Path self) throws IOException {
|
private static void requestUpdate(Path updateTo, Path self) throws IOException {
|
||||||
IntegrityChecker.requireVerifiedJar(updateTo);
|
if (!IntegrityChecker.DISABLE_SELF_INTEGRITY_CHECK) {
|
||||||
|
IntegrityChecker.verifyJar(updateTo);
|
||||||
|
}
|
||||||
startJava(updateTo, "--apply-to", self.toString());
|
startJava(updateTo, "--apply-to", self.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startJava(Path jar, String... appArgs) throws IOException {
|
private static void startJava(Path jar, String... appArgs) throws IOException {
|
||||||
List<String> commandline = new ArrayList<>();
|
List<String> commandline = new ArrayList<>();
|
||||||
commandline.add(JavaVersion.fromCurrentEnvironment().getBinary().toString());
|
commandline.add(JavaVersion.fromCurrentEnvironment().getBinary().toString());
|
||||||
|
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
|
||||||
|
Object key = entry.getKey();
|
||||||
|
if (key instanceof String && ((String) key).startsWith("hmcl.")) {
|
||||||
|
commandline.add("-D" + key + "=" + entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
commandline.add("-jar");
|
commandline.add("-jar");
|
||||||
commandline.add(jar.toAbsolutePath().toString());
|
commandline.add(jar.toAbsolutePath().toString());
|
||||||
commandline.addAll(Arrays.asList(appArgs));
|
commandline.addAll(Arrays.asList(appArgs));
|
||||||
|
|||||||
Reference in New Issue
Block a user