diff --git a/src/main/java/com/viaversion/aas/codec/CompressionCodec.java b/src/main/java/com/viaversion/aas/codec/CompressionCodec.java index c9b654b..383d365 100644 --- a/src/main/java/com/viaversion/aas/codec/CompressionCodec.java +++ b/src/main/java/com/viaversion/aas/codec/CompressionCodec.java @@ -32,6 +32,10 @@ public class CompressionCodec extends MessageToMessageCodec { this.threshold = threshold; } + public int getThreshold() { + return threshold; + } + @Override public void handlerAdded(ChannelHandlerContext ctx) { var level = VIAaaSConfig.INSTANCE.getCompressionLevel(); diff --git a/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt b/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt index fb23477..0dce461 100644 --- a/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt +++ b/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt @@ -20,6 +20,7 @@ import com.viaversion.viaversion.protocols.protocol1_15to1_14_4.ClientboundPacke import com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.ClientboundPackets1_16_2 import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.ClientboundPackets1_16 import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.ClientboundPackets1_17 +import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.ClientboundPackets1_18 import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8 import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9 import io.netty.buffer.ByteBuf @@ -59,7 +60,8 @@ object PacketRegistry { ProtocolVersion.v1_15..ProtocolVersion.v1_15_2 to ClientboundPackets1_15.DISCONNECT.id, ProtocolVersion.v1_16..ProtocolVersion.v1_16_1 to ClientboundPackets1_16.DISCONNECT.id, ProtocolVersion.v1_16_2..ProtocolVersion.v1_16_4 to ClientboundPackets1_16_2.DISCONNECT.id, - ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.DISCONNECT.id + ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.DISCONNECT.id, + ProtocolVersion.v1_18.singleton to ClientboundPackets1_18.DISCONNECT.id ) ) @@ -72,7 +74,8 @@ object PacketRegistry { ProtocolVersion.v1_15..ProtocolVersion.v1_15_2 to ClientboundPackets1_15.PLUGIN_MESSAGE.id, ProtocolVersion.v1_16..ProtocolVersion.v1_16_1 to ClientboundPackets1_16.PLUGIN_MESSAGE.id, ProtocolVersion.v1_16_2..ProtocolVersion.v1_16_4 to ClientboundPackets1_16_2.PLUGIN_MESSAGE.id, - ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.PLUGIN_MESSAGE.id + ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.PLUGIN_MESSAGE.id, + ProtocolVersion.v1_18.singleton to ClientboundPackets1_18.PLUGIN_MESSAGE.id ) ) diff --git a/src/main/kotlin/com/viaversion/aas/handler/ConnectionData.kt b/src/main/kotlin/com/viaversion/aas/handler/ConnectionData.kt index 2d1016b..ce0b436 100644 --- a/src/main/kotlin/com/viaversion/aas/handler/ConnectionData.kt +++ b/src/main/kotlin/com/viaversion/aas/handler/ConnectionData.kt @@ -1,5 +1,6 @@ package com.viaversion.aas.handler +import com.viaversion.aas.codec.CompressionCodec import com.viaversion.aas.codec.CryptoCodec import com.viaversion.aas.handler.state.ConnectionState import com.viaversion.aas.handler.state.HandshakeState @@ -15,4 +16,5 @@ class ConnectionData( val frontHandler get() = frontChannel.pipeline()[MinecraftHandler::class.java] val backHandler get() = backChannel?.pipeline()?.get(MinecraftHandler::class.java) val frontEncrypted get() = frontChannel.pipeline()[CryptoCodec::class.java] != null + val compressionLevel get() = frontChannel.pipeline()[CompressionCodec::class.java]?.threshold ?: -1 } \ No newline at end of file diff --git a/src/main/kotlin/com/viaversion/aas/handler/state/LoginState.kt b/src/main/kotlin/com/viaversion/aas/handler/state/LoginState.kt index 28a33f8..b3f4b8e 100644 --- a/src/main/kotlin/com/viaversion/aas/handler/state/LoginState.kt +++ b/src/main/kotlin/com/viaversion/aas/handler/state/LoginState.kt @@ -18,6 +18,7 @@ import io.netty.buffer.ByteBufAllocator import io.netty.channel.Channel import io.netty.channel.ChannelHandlerContext import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.future.await import kotlinx.coroutines.launch import java.security.KeyPair @@ -98,25 +99,40 @@ class LoginState : ConnectionState { fun reauthMessage(handler: MinecraftHandler, backName: String, backHash: String): CompletableFuture { if (!handler.data.frontEncrypted - || handler.data.frontVer!! < ProtocolVersion.v1_13.version || !frontName.equals(backName, ignoreCase = true) ) { callbackPluginReauth.complete(false) return callbackPluginReauth } - val buf = ByteBufAllocator.DEFAULT.buffer() - try { - Type.STRING.write(buf, backHash) + if (handler.data.frontVer!! < ProtocolVersion.v1_13.version) { + encodeOpenAuth(backHash).forEach { data -> + send(handler.data.frontChannel, SetCompression().also { it.threshold = data }) + } + send( + handler.data.frontChannel, + SetCompression().also { it.threshold = handler.data.compressionLevel }, + flush = true + ) - val packet = PluginRequest() - packet.id = ThreadLocalRandom.current().nextInt() - packet.channel = "openauthmod:join" - packet.data = readRemainingBytes(buf) - send(handler.data.frontChannel, packet, true) - pendingReauth = packet.id - } finally { - buf.release() + handler.coroutineScope.launch { + delay(5000) + callbackPluginReauth.complete(false) + } + } else { + val buf = ByteBufAllocator.DEFAULT.buffer() + try { + Type.STRING.write(buf, backHash) + + val packet = PluginRequest() + packet.id = ThreadLocalRandom.current().nextInt() + packet.channel = "openauthmod:join" + packet.data = readRemainingBytes(buf) + send(handler.data.frontChannel, packet, true) + pendingReauth = packet.id + } finally { + buf.release() + } } return callbackPluginReauth } @@ -192,7 +208,13 @@ class LoginState : ConnectionState { } fun handleLoginStart(handler: MinecraftHandler, loginStart: LoginStart) { - if (started) throw StacklessException("Login already started") + if (started) { + if (loginStart.username.startsWith(OPENAUTH_MAGIC_PREFIX)) { + callbackPluginReauth.complete(loginStart.username.removePrefix(OPENAUTH_MAGIC_PREFIX).toBoolean()) + return + } + throw StacklessException("Login already started") + } started = true VIAaaSConfig.maxPlayers?.let { diff --git a/src/main/kotlin/com/viaversion/aas/handler/state/Util.kt b/src/main/kotlin/com/viaversion/aas/handler/state/Util.kt index 3d50d66..d62cd52 100644 --- a/src/main/kotlin/com/viaversion/aas/handler/state/Util.kt +++ b/src/main/kotlin/com/viaversion/aas/handler/state/Util.kt @@ -13,6 +13,7 @@ import com.viaversion.viaversion.api.protocol.packet.State import com.viaversion.viaversion.api.protocol.version.ProtocolVersion import io.ktor.server.netty.* import io.netty.bootstrap.Bootstrap +import io.netty.buffer.Unpooled import io.netty.channel.Channel import io.netty.channel.ChannelOption import io.netty.channel.socket.SocketChannel @@ -20,9 +21,11 @@ import io.netty.handler.proxy.ProxyHandler import io.netty.resolver.NoopAddressResolverGroup import kotlinx.coroutines.future.await import kotlinx.coroutines.withTimeout +import java.math.BigInteger import java.net.Inet4Address import java.net.InetSocketAddress import java.net.URI +import kotlin.math.ceil private suspend fun createBackChannel( handler: MinecraftHandler, @@ -151,3 +154,30 @@ suspend fun connectBack( tryBackAddresses(handler, addresses, state, extraData) } + +// https://github.com/RaphiMC/OpenAuthMod/blob/fa66e78fe5c0e748c1b8c61624bf283fb8bc06dd/src/main/java/com/github/oam/utils/IntTo3ByteCodec.java#L16 +fun encodeOpenAuth(hash: String): IntArray { + val buffer = Unpooled.wrappedBuffer(BigInteger(hash, 16).toByteArray()) + val out = IntArray(2 + ceil(buffer.readableBytes().toDouble() / 3.0).toInt()) + val magic = 0xfdebf3fd.toInt() + + out[0] = magic + out[out.size - 1] = magic + + for (i in 1 until out.size - 1) { + var int = 1.shl(31) + .or(1.shl(30)).or(buffer.readUnsignedByte().toInt().shl(16)) + if (buffer.isReadable) { + int = int.or(1.shl(29)).or(buffer.readUnsignedByte().toInt().shl(8)) + } + if (buffer.isReadable) { + int = int.or(1.shl(28)).or(buffer.readUnsignedByte().toInt()) + } + + out[i] = int + } + + return out +} + +val OPENAUTH_MAGIC_PREFIX = String(byteArrayOf(2, 20, 12, 3), Charsets.UTF_8) \ No newline at end of file