Compare commits

...

2 Commits

Author SHA1 Message Date
~keith fffcd7f2bb
Reject unpatched clients on patched server & warn about unpatched servers 2022-01-20 20:24:44 +00:00
~keith f99a04b405 Add README.md 2022-01-18 00:09:42 +00:00
7 changed files with 73 additions and 4 deletions

32
README.md Normal file
View File

@ -0,0 +1,32 @@
# keith/ForgePatch
This is a modified version of Minecraft Forge 1.16.4-25.1.32, with its Log4j version updated to 2.17.1.
## The Backstory
A bit over a week ago, I decided to attempt to make a properly patched modification of the Forge version I was using prior to the Log4j bug being duscivered. It *should* have been as simple as modifying the version numbers specified in the Gradle build script, and rewriting any code that referenced nonexistent Log4j methods/classes.
However, I underestimated the Genius of the Minecraft Forge dev team.
See, 1.16.4 isn't officially supported by Forge anymore. I knew that going in, but I didn't want to update to 1.16.5, because that would require getting *every player* to update their version of Forge as well (and potentially also their mods if some broke in the transition). However, L\*x M\*nos and his team, in their Infinite Wisdom, decided to break the build scripts for all versions they no longer supported, *and* change the Maven repository URL listed in the build script to throw me off the scent. "No worries," I thought, "surely I can just change `files.minecraftforge.net/maven` to `maven.minecraftforge.net` in the build script and everything will work, right?" Nope - Gradle adamantly refused to look for dependencies at the new URL (which, it turns out, wasn't actually the cause of the problem, but I believed it was at this point). The hyper-intelligent superior life forms over at Forge, whose ways a lowly Earth being like me simply cannot comprehend, had hard-coded the URL in somewhere. Either that or Gradle was being a bitch. Probably both.
So, being the primitive, foolish Homo sapiens that I am, I made the mistake of asking for help in the Forge Discord. Kindly, of course, I mentioned that I was trying to build this specific version of Forge from source, and asked for assistance in fixing the build script errors. When asked why I was trying to do such a thing with an unsupported version of Forge, I mentioned that I was trying to build from source in order to update the Log4j version (since simply forcing the compiled server JAR to load 2.17.1 would crash with an exception). Second mistake. The moment I mention Log4j, it's no longer about my *actual* question, and instead about how I should just download 1.16.5, which still uses a version of Log4j that Apache's website advises against using - because who would *want* to solve a problem themselves when they can simply update their software to a version which *still* doesn't solve that problem? Why use your brain? Get rid of it and just download the latest version of what L\*x M\*nos, Holy King Of Gods, Sacred Be His Name wants you to think!!!1
Anyways, what's really funny about this whole exchange is when I cited Apache's [official Web site for Log4j](https://logging.apache.org/log4j/2.x/index.html), which states that versions below 2.17.1 should be avoided due to security vulnerability CVE-2021-**44832** (as well as CVE-2021-45105 and CVE-2021-45046, which were patched before 2.17.1 but after 2.15.0), and got a canned response saying that CVE-2021-**44228** was patched in 2.15.0, and was then told to "stop arguing with the people who actually write the software I use" - which was said *immediately* after Gex Manuals attempted to convince me that the *official Log4j website* was wrong. Silly me, I forgot that the Forge developers are more highly evolved than I am, and have ascended to inhabit an alternative reality where the numbers 44228 and 44832 are equal, and denial of service vulnerabilities like CVE-2021-45105 don't exist!
I ended up putting this project on hold, since I had other, better things to do. But after picking it back up today, I realized two things. First, the `files.minecraftforge.net/maven`-to-`maven.minecraftforge.net` change was a complete red herring and not the actual source of the compilation problems - the Forge team had deleted the dependencies required by 1.16.4 from their Maven repository. (Not sure why. Disk space constraints, maybe?) And second, the missing dependencies were available at `libraries.minecraft.net`.
## Patching other versions
I may attempt to patch other versions of Forge later. If you want to try and do it yourself, here's how you need to modify `build.gradle`:
1. Search for `log4j` in the file, and replace the version number for both log4j-api and log4j-core with `2.17.1`
2. In the `buildscript { repositories {} }` block at the top of the file, add a line below the existing `maven {}` block which reads:
```
maven { url = 'https://libraries.minecraft.net/' }
```
3. Copy both of those lines into the `repositories {}` block in `project(':clean')` and `project(':forge')`.
To build Forge and the installer, it should be:
```
./gradlew forge:release
./gradlew forge:installerJar
```
The output will be in `./projects/forge/build/libs/`.

View File

@ -128,6 +128,11 @@ public class ClientHooks
if (fmlver > FMLNetworkConstants.FMLNETVERSION) {
extraReason = "fml.menu.multiplayer.clientoutdated";
}
if (!packet.getForgeData().isPatchAdvertised()) {
extraReason = "fml.menu.multiplayer.serverunpatched";
}
target.forgeData = new ExtendedServerListData("FML", extraServerMods.isEmpty() && fmlNetMatches && channelsMatch && modsMatch, mods.size(), extraReason);
} else {
target.forgeData = new ExtendedServerListData("VANILLA", NetworkRegistry.canConnectToVanillaServer(),0, null);
@ -143,11 +148,19 @@ public class ClientHooks
switch (target.forgeData.type) {
case "FML":
if (target.forgeData.isCompatible) {
idx = 0;
tooltip = ForgeI18n.parseMessage("fml.menu.multiplayer.compatible", target.forgeData.numberOfMods);
// HACK: Allow connections to unpatched servers, but show a warning
if (target.forgeData.extraReason != null && target.forgeData.extraReason.equals("fml.menu.multiplayer.serverunpatched")) {
idx = 96;
tooltip = ForgeI18n.parseMessage("fml.menu.multiplayer.incompatible.extra", ForgeI18n.parseMessage(target.forgeData.extraReason));
} else {
idx = 0;
tooltip = ForgeI18n.parseMessage("fml.menu.multiplayer.compatible", target.forgeData.numberOfMods);
}
} else {
idx = 16;
if(target.forgeData.extraReason != null) {
if (target.forgeData.extraReason.equals("fml.menu.multiplayer.serverunpatched"))
idx = 96;
String extraReason = ForgeI18n.parseMessage(target.forgeData.extraReason);
tooltip = ForgeI18n.parseMessage("fml.menu.multiplayer.incompatible.extra", extraReason);
} else {

View File

@ -34,7 +34,8 @@ public class FMLNetworkConstants
{
public static final String FMLNETMARKER = "FML";
public static final int FMLNETVERSION = 2;
public static final String NETVERSION = FMLNETMARKER + FMLNETVERSION;
// HACK: Unpatched servers won't see this leading 0 - but we will.
public static final String NETVERSION = FMLNETMARKER + "0" + FMLNETVERSION;
public static final String NOVERSION = "NONE";
static final Marker NETWORK = MarkerManager.getMarker("FMLNETWORK");

View File

@ -67,6 +67,7 @@ public class FMLStatusPing {
private transient Map<ResourceLocation, Pair<String, Boolean>> channels;
private transient Map<String, String> mods;
private transient int fmlNetworkVer;
private transient boolean patched;
public FMLStatusPing() {
this.channels = NetworkRegistry.buildChannelVersionsForListPing();
this.mods = new HashMap<>();
@ -74,12 +75,20 @@ public class FMLStatusPing {
mods.put(modid, mc.getCustomExtension(ExtensionPoint.DISPLAYTEST).
map(Pair::getLeft).map(Supplier::get).orElse(FMLNetworkConstants.IGNORESERVERONLY)));
this.fmlNetworkVer = FMLNetworkConstants.FMLNETVERSION;
this.patched = true;
}
private FMLStatusPing(Map<ResourceLocation, Pair<String, Boolean>> deserialized, Map<String,String> modMarkers, int fmlNetVer) {
this.channels = ImmutableMap.copyOf(deserialized);
this.mods = modMarkers;
this.fmlNetworkVer = fmlNetVer;
this.patched = false;
}
private FMLStatusPing(Map<ResourceLocation, Pair<String, Boolean>> deserialized, Map<String,String> modMarkers, int fmlNetVer, boolean p) {
this.channels = ImmutableMap.copyOf(deserialized);
this.mods = modMarkers;
this.fmlNetworkVer = fmlNetVer;
this.patched = p;
}
public static class Serializer {
@ -96,7 +105,8 @@ public class FMLStatusPing {
collect(Collectors.toMap(jo -> JSONUtils.getString(jo, "modId"), jo->JSONUtils.getString(jo, "modmarker")));
final int remoteFMLVersion = JSONUtils.getInt(forgeData, "fmlNetworkVersion");
return new FMLStatusPing(channels, mods, remoteFMLVersion);
return new FMLStatusPing(channels, mods, remoteFMLVersion, JSONUtils.hasField(forgeData, "keithPatch"));
} catch (JsonSyntaxException e) {
LOGGER.debug(NETWORK, "Encountered an error parsing status ping data", e);
return null;
@ -125,6 +135,8 @@ public class FMLStatusPing {
});
obj.add("mods", modTestValues);
obj.addProperty("fmlNetworkVersion", forgeData.fmlNetworkVer);
if (forgeData.patched)
obj.addProperty("keithPatch", true);
return obj;
}
}
@ -141,4 +153,8 @@ public class FMLStatusPing {
return fmlNetworkVer;
}
public boolean isPatchAdvertised() {
return patched;
}
}

View File

@ -155,6 +155,12 @@ public class ServerLifecycleHooks
final ConnectionType connectionType = ConnectionType.forVersionFlag(packet.getFMLVersion());
final int versionNumber = connectionType.getFMLVersionNumber(packet.getFMLVersion());
// HACK: Check for missing leading 0. If it's not there, we know the client isn't patched.
if (connectionType == ConnectionType.MODDED && packet.getFMLVersion().substring(FMLNetworkConstants.FMLNETMARKER.length()).charAt(0) != '0') {
rejectConnection(manager, connectionType, "Your client appears to be vulnerable to CVE-2021-44228, 45046, 45105, and/or 44832. To connect to this server, you must install ~keith's patched Forge version: https://bytes.keithhacks.cyou/keith/ForgePatch/releases/");
return false;
}
if (connectionType == ConnectionType.MODDED && versionNumber != FMLNetworkConstants.FMLNETVERSION) {
rejectConnection(manager, connectionType, "This modded server is not network compatible with your modded client. Please verify your Forge version closely matches the server. Got net version "+ versionNumber + " this server is net version "+FMLNetworkConstants.FMLNETVERSION);
return false;

View File

@ -34,6 +34,7 @@
"fml.menu.multiplayer.extraservermods":"Server has additional mods that may be needed on the client",
"fml.menu.multiplayer.modsincompatible":"Server mod list is not compatible",
"fml.menu.multiplayer.networkincompatible":"Server network message list is not compatible",
"fml.menu.multiplayer.serverunpatched": "Server is unpatched, or not advertising keith/ForgePatch",
"fml.menu.loadingmods": "{0,choice,0#No mods|1#1 mod|1<{0} mods} loaded",
"fml.menu.notification.title": "Startup Notification",
"fml.menu.accessdenied.title": "Server Access Denied",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB