diff --git a/src/main/java/net/flashii/mcexts/RPC.java b/src/main/java/net/flashii/mcexts/RPC.java index 1b7a789..7c6089c 100644 --- a/src/main/java/net/flashii/mcexts/RPC.java +++ b/src/main/java/net/flashii/mcexts/RPC.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.UUID; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import net.flashii.mcexts.Tools; public class RPC { private static final String DEFAULT_SECRET = "meow"; @@ -74,6 +75,9 @@ public class RPC { throws GeneralSecurityException, IOException, InterruptedException { boolean hasBody = bodyStr != null; String time = getRequestTimestamp(); + + Tools.Log.info("[FII RPC] {} {} @ {}", hasBody ? "POST" : "GET", path, time); + String hash = createRequestSignature(time, URLs.getRpcPath(path), sigStr); URI url; diff --git a/src/main/java/net/flashii/mcexts/Tools.java b/src/main/java/net/flashii/mcexts/Tools.java new file mode 100644 index 0000000..e1c1c1b --- /dev/null +++ b/src/main/java/net/flashii/mcexts/Tools.java @@ -0,0 +1,8 @@ +package net.flashii.mcexts; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Tools { + public static final Logger Log = LoggerFactory.getLogger("fiiexts"); +} diff --git a/src/main/java/net/flashii/mcexts/mixin/PlayerListHudMixin.java b/src/main/java/net/flashii/mcexts/mixin/PlayerListHudMixin.java index 31ce59c..8acf596 100644 --- a/src/main/java/net/flashii/mcexts/mixin/PlayerListHudMixin.java +++ b/src/main/java/net/flashii/mcexts/mixin/PlayerListHudMixin.java @@ -1,5 +1,6 @@ package net.flashii.mcexts.mixin; +import net.flashii.mcexts.Tools; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.PlayerListHud; import org.spongepowered.asm.mixin.Mixin; @@ -15,7 +16,9 @@ public abstract class PlayerListHudMixin { target = "Lnet/minecraft/client/MinecraftClient;isInSingleplayer()Z" ) ) - public boolean redirectIsInSinglePlayer(MinecraftClient client) { + public boolean isInSinglePlayer(MinecraftClient client) { + Tools.Log.info("[FII MIXIN] Redirected isInSingleplayer call in PlayerListHud.render!!!"); + // always enable BL return true; } diff --git a/src/main/java/net/flashii/mcexts/mixin/PlayerManagerMixin.java b/src/main/java/net/flashii/mcexts/mixin/PlayerManagerMixin.java index afb19e2..21c1626 100644 --- a/src/main/java/net/flashii/mcexts/mixin/PlayerManagerMixin.java +++ b/src/main/java/net/flashii/mcexts/mixin/PlayerManagerMixin.java @@ -6,6 +6,7 @@ import java.security.GeneralSecurityException; import com.mojang.authlib.GameProfile; import net.flashii.mcexts.RPC; import net.flashii.mcexts.RPCPayload; +import net.flashii.mcexts.Tools; import net.minecraft.server.PlayerManager; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -29,13 +30,15 @@ public abstract class PlayerManagerMixin { if(!payload.is("auth:ok")) { if(payload.is("error")) { - authText = Text.literal( - payload.getAttrStr(payload.hasAttr("text") ? "text" : "code") - ).formatted(Formatting.RED); + String errorCode = payload.getAttrStr("code"); + String errorText = payload.hasAttr("text") ? payload.getAttrStr("text") : errorCode; + Tools.Log.info("[FII AUTH] <{}:{}:{}> Error: {} {}", profile.getId(), profile.getName(), sockAddr, errorCode, errorText); + authText = Text.literal(errorText).formatted(Formatting.RED); } else if(payload.is("auth:authorise")) { String userName = payload.getAttrStr("user_name"); int userColour = payload.hasAttr("user_colour") ? payload.getAttrInt("user_colour") : 0xFFFFFF; String url = payload.getAttrStr("url"); + Tools.Log.info("[FII AUTH] <{}:{}:{}> Authorising: {} {} {}", profile.getId(), profile.getName(), sockAddr, userName, userColour, url); authText = Text.literal("Welcome back, ") .append(Text.literal(userName).styled(style -> style.withColor(userColour).withBold(true))) @@ -47,6 +50,7 @@ public abstract class PlayerManagerMixin { } else if(payload.is("auth:link")) { String code = payload.getAttrStr("code"); String url = payload.getAttrStr("url"); + Tools.Log.info("[FII AUTH] <{}:{}:{}> Linking: {} {}", profile.getId(), profile.getName(), sockAddr, code, url); authText = Text.literal("This seems to be the first time you're connecting!\n") .append(Text.literal("Visit ")) @@ -55,16 +59,22 @@ public abstract class PlayerManagerMixin { .append(Text.literal(code).formatted(Formatting.LIGHT_PURPLE)) .append(Text.literal("\n\nAfter you've approved the attempt, connect to the server again and you should be good to go.")); } else { + Tools.Log.info("[FII AUTH] <{}:{}:{}> Unknown response: {}", profile.getId(), profile.getName(), sockAddr, payload.getName()); authText = Text.literal("Flashii authentication server returned an unknown response, yell at flashwave about this.").formatted(Formatting.RED); } + } else { + Tools.Log.info("[FII AUTH] <{}:{}:{}> Authentication successful!", profile.getId(), profile.getName(), sockAddr); } } catch(IOException ex) { + Tools.Log.error("[FII AUTH] <{}:{}:{}> IOException!!", profile.getId(), profile.getName(), sockAddr); authText = Text.literal("Flashii authentication server failed to respond, yell at flashwave about this.").formatted(Formatting.RED); ex.printStackTrace(); } catch(GeneralSecurityException ex) { + Tools.Log.error("[FII AUTH] <{}:{}:{}> GeneralSecurityException!!", profile.getId(), profile.getName(), sockAddr); authText = Text.literal("Problem with request verification, yell at flashwave about this.").formatted(Formatting.RED); ex.printStackTrace(); } catch(InterruptedException ex) { + Tools.Log.error("[FII AUTH] <{}:{}:{}> InterruptedException!!", profile.getId(), profile.getName(), sockAddr); authText = Text.literal("Problem with connecting to the Flashii authentication server, yell at flashwave about this.").formatted(Formatting.RED); ex.printStackTrace(); } diff --git a/src/main/java/net/flashii/mcexts/mixin/PlayerSkinProviderMixin.java b/src/main/java/net/flashii/mcexts/mixin/PlayerSkinProviderMixin.java index 7602d40..cc3ea29 100644 --- a/src/main/java/net/flashii/mcexts/mixin/PlayerSkinProviderMixin.java +++ b/src/main/java/net/flashii/mcexts/mixin/PlayerSkinProviderMixin.java @@ -4,6 +4,7 @@ import com.mojang.authlib.GameProfile; import java.util.concurrent.CompletableFuture; import net.minecraft.client.texture.PlayerSkinProvider; import net.minecraft.client.util.SkinTextures; +import net.flashii.mcexts.Tools; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,16 +17,27 @@ public abstract class PlayerSkinProviderMixin { at = @At("RETURN"), cancellable = true ) - private void modifyFetchSkinTexturesReturn(GameProfile profile, CallbackInfoReturnable> cir) { + private void fetchSkinTextures(GameProfile profile, CallbackInfoReturnable> cir) { + Tools.Log.info("[FII MIXIN] Intercepted PlayerSkinProvider.fetchSkinTextures!!!"); + CompletableFuture future = cir.getReturnValue(); cir.setReturnValue(future.thenApply(st -> { + Tools.Log.info( + "[FII MIXIN] future texture:{} textureUrl:{} capeTexture:{} elytraTexture:{} model:{} secure:{}", + st.texture(), + st.textureUrl(), + st.capeTexture(), + st.elytraTexture(), + st.model(), + st.secure() + ); return new SkinTextures( st.texture(), st.textureUrl(), st.capeTexture(), st.elytraTexture(), st.model(), - true + st.secure() ); })); cir.cancel(); diff --git a/src/main/java/net/flashii/mcexts/mixin/TextureUrlCheckerMixin.java b/src/main/java/net/flashii/mcexts/mixin/TextureUrlCheckerMixin.java index 30b7723..ce03238 100644 --- a/src/main/java/net/flashii/mcexts/mixin/TextureUrlCheckerMixin.java +++ b/src/main/java/net/flashii/mcexts/mixin/TextureUrlCheckerMixin.java @@ -2,6 +2,7 @@ package net.flashii.mcexts.mixin; import com.mojang.authlib.yggdrasil.TextureUrlChecker; import net.flashii.mcexts.URLs; +import net.flashii.mcexts.Tools; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,6 +17,8 @@ public abstract class TextureUrlCheckerMixin { remap = false ) private static void isAllowedTextureDomain(String url, CallbackInfoReturnable cir) { + Tools.Log.info("[FII MIXIN] Intercepted TextureUrlChecker.isAllowedTextureDomain!!!"); + if(url == null || url.startsWith(URLs.getTexturesHostPrefix())) { cir.setReturnValue(true); cir.cancel(); diff --git a/src/main/java/net/flashii/mcexts/mixin/YggdrasilEnvironmentMixin.java b/src/main/java/net/flashii/mcexts/mixin/YggdrasilEnvironmentMixin.java index 6aaf5b6..e45eb29 100644 --- a/src/main/java/net/flashii/mcexts/mixin/YggdrasilEnvironmentMixin.java +++ b/src/main/java/net/flashii/mcexts/mixin/YggdrasilEnvironmentMixin.java @@ -17,7 +17,7 @@ public abstract class YggdrasilEnvironmentMixin { ordinal = 0 ) ) - private Environment redirectEnvironmentCreation(String sessionHost, String servicesHost, String name) { + private Environment init(String sessionHost, String servicesHost, String name) { return new Environment(URLs.getSessionHost(), servicesHost, name); } } diff --git a/src/main/java/net/flashii/mcexts/mixin/YggdrasilMinecraftSessionServiceMixin.java b/src/main/java/net/flashii/mcexts/mixin/YggdrasilMinecraftSessionServiceMixin.java new file mode 100644 index 0000000..2b4b5ec --- /dev/null +++ b/src/main/java/net/flashii/mcexts/mixin/YggdrasilMinecraftSessionServiceMixin.java @@ -0,0 +1,101 @@ +package net.flashii.mcexts.mixin; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.SignatureState; +import com.mojang.authlib.minecraft.MinecraftProfileTextures; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.yggdrasil.ProfileResult; +import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import net.minecraft.client.util.SkinTextures; +import net.flashii.mcexts.Tools; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(YggdrasilMinecraftSessionService.class) +public abstract class YggdrasilMinecraftSessionServiceMixin { + @Inject( + method = "getPackedTextures(Lcom/mojang/authlib/GameProfile;)Lcom/mojang/authlib/properties/Property;", + at = @At("RETURN"), + cancellable = true, + remap = false + ) + private void getPackedTextures(GameProfile profile, CallbackInfoReturnable cir) { + Tools.Log.info("[FII MIXIN] Intercepted YggdrasilMinecraftSessionService.getPackedTextures!!!"); + Tools.Log.info("[FII MIXIN] {}", profile); + + Property prop = cir.getReturnValue(); + if(prop == null) + Tools.Log.info("[FII MIXIN] prop is null"); + else + Tools.Log.info("[FII MIXIN] name:{} value:{} signature:{}", prop.name(), prop.value(), prop.signature()); + } + + @Inject( + method = "unpackTextures(Lcom/mojang/authlib/properties/Property;)Lcom/mojang/authlib/minecraft/MinecraftProfileTextures;", + at = @At("RETURN"), + cancellable = true, + remap = false + ) + private void unpackTextures(Property packedTextures, CallbackInfoReturnable cir) { + Tools.Log.info("[FII MIXIN] Intercepted YggdrasilMinecraftSessionService.unpackTextures!!!"); + + MinecraftProfileTextures textures = cir.getReturnValue(); + Tools.Log.info("[FII MIXIN] skin:{} cape:{} elytra:{} signature:{}", textures.skin(), textures.cape(), textures.elytra(), textures.signatureState()); + } + + @Inject( + method = "getSecurePropertyValue(Lcom/mojang/authlib/properties/Property;)Ljava/lang/String;", + at = @At("HEAD"), + cancellable = true, + remap = false + ) + private void getSecurePropertyValue(Property property, CallbackInfoReturnable cir) { + Tools.Log.info("[FII MIXIN] Intercepted YggdrasilMinecraftSessionService.getSecurePropertyValue!!!"); + + cir.setReturnValue(property.value()); + cir.cancel(); + } + + @Inject( + method = "getPropertySignatureState(Lcom/mojang/authlib/properties/Property;)Lcom/mojang/authlib/SignatureState;", + at = @At("HEAD"), + cancellable = true, + remap = false + ) + private void getPropertySignatureState(Property property, CallbackInfoReturnable cir) { + Tools.Log.info("[FII MIXIN] Intercepted YggdrasilMinecraftSessionService.getPropertySignatureState!!!"); + + cir.setReturnValue(SignatureState.SIGNED); + cir.cancel(); + } + + @Inject( + method = "fetchProfileUncached(Ljava/util/UUID;Z)Lcom/mojang/authlib/yggdrasil/ProfileResult;", + at = @At("RETURN"), + cancellable = true, + remap = false + ) + private void fetchProfileUncached(UUID profileId, boolean requireSecure, CallbackInfoReturnable cir) { + Tools.Log.info("[FII MIXIN] Intercepted YggdrasilMinecraftSessionService.fetchProfileUncached!!!"); + Tools.Log.info("[FII MIXIN] {}", cir.getReturnValue().profile()); + } + + @ModifyArg( + method = "fetchProfile", + at = @At( + value = "INVOKE", + target = "Lcom/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService;fetchProfileUncached(Ljava/util/UUID;Z)Lcom/mojang/authlib/yggdrasil/ProfileResult;" + ), + index = 1, + remap = false + ) + private boolean modifyFetchProfileUncachedArg(boolean requireSecure) { + Tools.Log.info("[FII MIXIN] Intercepted requireSecure argument for YggdrasilMinecraftSessionService.fetchProfileUncached in fetchProfile!!!"); + return false; + } +} diff --git a/src/main/resources/flashii-extensions.mixins.json b/src/main/resources/flashii-extensions.mixins.json index c73f99f..e904762 100644 --- a/src/main/resources/flashii-extensions.mixins.json +++ b/src/main/resources/flashii-extensions.mixins.json @@ -6,7 +6,8 @@ "PlayerSkinProviderMixin", "PlayerListHudMixin", "TextureUrlCheckerMixin", - "YggdrasilEnvironmentMixin" + "YggdrasilEnvironmentMixin", + "YggdrasilMinecraftSessionServiceMixin" ], "server": [ "PlayerManagerMixin",