aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-04-27 15:05:18 +0200
committerGitHub <noreply@github.com>2024-04-27 15:05:18 +0200
commitc266561e0cd048a7e0c2f8617a35bc1a827df318 (patch)
treeb1a457c0451857634c0feb64a515da0483018b35
parent9547ebec0edd8c512f55f510acd93e180771e87a (diff)
downloadNotEnoughUpdates-c266561e0cd048a7e0c2f8617a35bc1a827df318.tar.gz
NotEnoughUpdates-c266561e0cd048a7e0c2f8617a35bc1a827df318.tar.bz2
NotEnoughUpdates-c266561e0cd048a7e0c2f8617a35bc1a827df318.zip
Fix access transformer crash and invalid SSL context for auto updater (#1121)
-rw-r--r--.github/workflows/publish.yml5
-rw-r--r--build.gradle.kts3
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SignedGithubUpdateData.kt70
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SigningGithubSource.kt31
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.kt25
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/ConfigVersionGuiOption.kt2
6 files changed, 101 insertions, 35 deletions
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index de01458a..621072f9 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -23,7 +23,10 @@ jobs:
- name: Set up gradle cache
uses: gradle/gradle-build-action@v2
- name: Build with Gradle
- run: ./gradlew clean test includeBackupRepo remapJar --no-daemon
+ run: |
+ ./gradlew clean
+ ./gradlew includeBackupRepo
+ ./gradlew test remapJar
env:
NEU_RELEASE: true
- uses: actions/upload-artifact@v3
diff --git a/build.gradle.kts b/build.gradle.kts
index 087212ef..7dccd301 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -163,7 +163,7 @@ dependencies {
"oneconfigAnnotationProcessor"("org.projectlombok:lombok:1.18.24")
shadowImplementation("com.mojang:brigadier:1.0.18")
- shadowImplementation("moe.nea:libautoupdate:1.2.0")
+ shadowImplementation("moe.nea:libautoupdate:1.3.1")
mixinRTDependencies("org.spongepowered:mixin:0.7.11-SNAPSHOT") {
isTransitive = false // Dependencies of mixin are already bundled by minecraft
@@ -227,6 +227,7 @@ tasks.withType(Jar::class) {
this["FMLCorePluginContainsFMLMod"] = "true"
this["ForceLoadAsMod"] = "true"
this["Manifest-Version"] = "1.0"
+ this["FMLAT"] = "accesstransformer.cfg"
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SignedGithubUpdateData.kt b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SignedGithubUpdateData.kt
new file mode 100644
index 00000000..7cea041c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SignedGithubUpdateData.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.updater
+
+import com.google.gson.JsonElement
+import moe.nea.libautoupdate.GithubReleaseUpdateSource.GithubRelease
+import moe.nea.libautoupdate.UpdateData
+import moe.nea.libautoupdate.UpdateUtils
+import java.io.ByteArrayInputStream
+import java.net.URL
+
+class SignedGithubUpdateData(
+ versionName: String,
+ versionNumber: JsonElement,
+ sha256: String,
+ download: String,
+ val signatures: List<GithubRelease.Download>
+) : UpdateData(
+ versionName,
+ versionNumber,
+ sha256,
+ download
+) {
+ override fun toString(): String {
+ return "${super.toString()} + Signatures(signatures = ${signatures.map { it.name }}})"
+ }
+
+ fun verifyAnySignature(): Boolean {
+ val signatories = validSignatories
+ for (signatory in signatories) {
+ println("Accepted signature from ${signatory.name}")
+ }
+ return signatories.size >= 2
+ }
+
+ val validSignatories by lazy {
+ findValidSignatories()
+ }
+
+
+ private fun findValidSignatories(): List<GithubRelease.Download> {
+ val signatures = signatures
+ return signatures.filter { verifySignature(it) }
+ }
+
+ private fun verifySignature(signatureDownload: GithubRelease.Download): Boolean {
+ val name = signatureDownload.name.substringBeforeLast('.').substringAfterLast("_")
+ val signatureBytes = UpdateUtils.openUrlConnection(URL(signatureDownload.browserDownloadUrl)).readBytes()
+ val hashBytes = ByteArrayInputStream(sha256.uppercase().encodeToByteArray())
+ return SigningPool.verifySignature(name, hashBytes, signatureBytes)
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SigningGithubSource.kt b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SigningGithubSource.kt
index b8c804ff..5b7c08df 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SigningGithubSource.kt
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SigningGithubSource.kt
@@ -21,44 +21,19 @@ package io.github.moulberry.notenoughupdates.miscfeatures.updater
import moe.nea.libautoupdate.GithubReleaseUpdateSource
import moe.nea.libautoupdate.UpdateData
-import java.io.ByteArrayInputStream
-import java.io.File
-import java.net.URL
class SigningGithubSource(username: String, repo: String) :
GithubReleaseUpdateSource(username, repo) {
val hashRegex = "sha256sum: `(?<hash>[a-fA-F0-9]{64})`".toPattern()
override fun findAsset(release: GithubRelease): UpdateData? {
- var asset = super.findAsset(release) ?: return null
+ val asset = super.findAsset(release) ?: return null
val match = release.body.lines()
.firstNotNullOfOrNull { line -> hashRegex.matcher(line).takeIf { it.matches() } }
?: return null
// Inject our custom sha256sum
- asset = UpdateData(asset.versionName, asset.versionNumber, match.group("hash"), asset.download)
- // Verify at least 2 signatures are present on this release
- if (!verifyAnySignature(release, asset))
- return null
- return asset
+ return SignedGithubUpdateData(asset.versionName, asset.versionNumber, match.group("hash"), asset.download,
+ release.assets.filter { it.name.endsWith(".asc") })
}
- private fun verifyAnySignature(release: GithubRelease, asset: UpdateData): Boolean {
- val signatories = findValidSignatories(release, asset)
- for (signatory in signatories) {
- println("Accepted signature from ${signatory.name}")
- }
- return signatories.size >= 2
- }
-
- fun findValidSignatories(release: GithubRelease, asset: UpdateData): List<GithubRelease.Download> {
- val signatures = release.assets?.filter { it.name.endsWith(".asc") } ?: emptyList()
- return signatures.filter { verifySignature(it, asset) }
- }
-
- fun verifySignature(signatureDownload: GithubRelease.Download, asset: UpdateData): Boolean {
- val name = signatureDownload.name.substringBeforeLast('.').removePrefix("_")
- val signatureBytes = URL(signatureDownload.browserDownloadUrl).openStream().readBytes()
- val hashBytes = ByteArrayInputStream(asset.sha256.uppercase().encodeToByteArray())
- return SigningPool.verifySignature(name, hashBytes, signatureBytes)
- }
}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.kt
index b9ce28b2..a522cb47 100644
--- a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.kt
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.kt
@@ -22,12 +22,10 @@ package io.github.moulberry.notenoughupdates.miscfeatures.updater
import io.github.moulberry.notenoughupdates.NotEnoughUpdates
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
import io.github.moulberry.notenoughupdates.events.RegisterBrigadierCommandEvent
+import io.github.moulberry.notenoughupdates.util.ApiUtil
import io.github.moulberry.notenoughupdates.util.MinecraftExecutor
import io.github.moulberry.notenoughupdates.util.brigadier.thenExecute
-import moe.nea.libautoupdate.CurrentVersion
-import moe.nea.libautoupdate.PotentialUpdate
-import moe.nea.libautoupdate.UpdateContext
-import moe.nea.libautoupdate.UpdateTarget
+import moe.nea.libautoupdate.*
import net.minecraft.client.Minecraft
import net.minecraft.event.ClickEvent
import net.minecraft.util.ChatComponentText
@@ -36,6 +34,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.common.gameevent.TickEvent
import org.apache.logging.log4j.LogManager
import java.util.concurrent.CompletableFuture
+import javax.net.ssl.HttpsURLConnection
@NEUAutoSubscribe
object AutoUpdater {
@@ -45,6 +44,15 @@ object AutoUpdater {
CurrentVersion.ofTag(NotEnoughUpdates.VERSION.substringBefore("+")),
"notenoughupdates"
)
+
+ init {
+ UpdateUtils.patchConnection {
+ if (it is HttpsURLConnection) {
+ ApiUtil.patchHttpsRequest(it)
+ }
+ }
+ }
+
val logger = LogManager.getLogger("NEUUpdater")
private var activePromise: CompletableFuture<*>? = null
set(value) {
@@ -80,6 +88,11 @@ object AutoUpdater {
logger.info("Starting update check")
val updateStream = config.updateStream.get()
activePromise = updateContext.checkUpdate(updateStream.stream)
+ .thenApplyAsync({
+ if (it.isUpdateAvailable)
+ (it.update as? SignedGithubUpdateData)?.verifyAnySignature()
+ it
+ }, MinecraftExecutor.OffThread)
.thenAcceptAsync({
logger.info("Update check completed")
if (updateState != UpdateState.NONE) {
@@ -88,6 +101,10 @@ object AutoUpdater {
}
potentialUpdate = it
if (it.isUpdateAvailable) {
+ if ((it.update as? SignedGithubUpdateData)?.verifyAnySignature() != true) {
+ logger.error("Found unsigned github update: ${it.update}")
+ return@thenAcceptAsync
+ }
updateState = UpdateState.AVAILABLE
Minecraft.getMinecraft().thePlayer?.addChatMessage(ChatComponentText("§e[NEU] §aNEU found a new update: ${it.update.versionName}. Click here to automatically install this update.").apply {
this.chatStyle = this.chatStyle.setChatClickEvent(
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/ConfigVersionGuiOption.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/ConfigVersionGuiOption.kt
index 3a920aec..da74ce22 100644
--- a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/ConfigVersionGuiOption.kt
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/updater/ConfigVersionGuiOption.kt
@@ -62,7 +62,7 @@ class ConfigVersionGuiOption(option: ProcessedOption) : GuiOptionEditor(option)
GlStateManager.scale(2F, 2F, 1F)
TextRenderUtils.drawStringCenteredScaledMaxWidth(
"${if (AutoUpdater.updateState == AutoUpdater.UpdateState.NONE) GREEN else RED}${AutoUpdater.getCurrentVersion()}" +
- if (nextVersion != null) "➜ ${GREEN}${nextVersion}" else "",
+ if (nextVersion != null && AutoUpdater.updateState != AutoUpdater.UpdateState.NONE) "➜ ${GREEN}${nextVersion}" else "",
widthRemaining / 4F,
10F,
true,