update for new OpenAuthMod

This commit is contained in:
creeper123123321 2022-06-12 12:31:53 -03:00
parent b415fd5223
commit 2bf8b65337
2 changed files with 77 additions and 61 deletions

View File

@ -15,6 +15,7 @@ import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type import com.viaversion.viaversion.api.type.Type
import io.netty.buffer.ByteBufAllocator import io.netty.buffer.ByteBufAllocator
import io.netty.buffer.Unpooled
import io.netty.channel.Channel import io.netty.channel.Channel
import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelHandlerContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -37,11 +38,9 @@ class LoginState : ConnectionState {
var extraData: String? = null var extraData: String? = null
var backName: String? = null var backName: String? = null
var started = false var started = false
override val state: State override val state: State get() = State.LOGIN
get() = State.LOGIN override val logDcInfo: Boolean get() = true
override val logDcInfo: Boolean val callbackReauth = CompletableFuture<Boolean>()
get() = true
var callbackPluginReauth = CompletableFuture<Boolean>()
var pendingReauth: Int? = null var pendingReauth: Int? = null
override fun handlePacket(handler: MinecraftHandler, ctx: ChannelHandlerContext, packet: Packet) { override fun handlePacket(handler: MinecraftHandler, ctx: ChannelHandlerContext, packet: Packet) {
@ -59,15 +58,21 @@ class LoginState : ConnectionState {
} }
private fun handlePluginResponse(handler: MinecraftHandler, packet: PluginResponse) { private fun handlePluginResponse(handler: MinecraftHandler, packet: PluginResponse) {
if (packet.id == pendingReauth) { if (handleReauthResponse(packet)) return
callbackPluginReauth.complete(packet.success)
pendingReauth = null
return
}
forward(handler, packet) forward(handler, packet)
} }
private fun handleReauthResponse(packet: PluginResponse): Boolean {
if (packet.id == pendingReauth) {
pendingReauth = null
val buf = Unpooled.wrappedBuffer(packet.data)
callbackReauth.complete(buf.readBoolean())
return true
}
return false
}
private fun handleLoginSuccess(handler: MinecraftHandler, loginSuccess: LoginSuccess) { private fun handleLoginSuccess(handler: MinecraftHandler, loginSuccess: LoginSuccess) {
handler.data.state = PlayState handler.data.state = PlayState
forward(handler, loginSuccess) forward(handler, loginSuccess)
@ -77,9 +82,7 @@ class LoginState : ConnectionState {
val threshold = setCompression.threshold val threshold = setCompression.threshold
setCompression(handler.data.backChannel!!, threshold) setCompression(handler.data.backChannel!!, threshold)
forward(handler, setCompression) forward(handler, setCompression)
setCompression(handler.data.frontChannel, threshold) setCompression(handler.data.frontChannel, threshold)
} }
@ -102,13 +105,25 @@ class LoginState : ConnectionState {
|| !frontName.equals(backName, ignoreCase = true) || !frontName.equals(backName, ignoreCase = true)
|| handler.data.frontVer!! < ProtocolVersion.v1_8.version || handler.data.frontVer!! < ProtocolVersion.v1_8.version
) { ) {
callbackPluginReauth.complete(false) callbackReauth.complete(false)
return callbackPluginReauth return callbackReauth
} }
pendingReauth = ThreadLocalRandom.current().nextInt()
val buf = ByteBufAllocator.DEFAULT.buffer()
try {
Type.STRING.write(buf, backHash)
sendOpenAuthRequest(handler, "oam:join", pendingReauth!!, readRemainingBytes(buf))
} finally {
buf.release()
}
return callbackReauth
}
private fun sendOpenAuthRequest(handler: MinecraftHandler, channel: String, id: Int, data: ByteArray) {
if (handler.data.frontVer!! < ProtocolVersion.v1_13.version) { if (handler.data.frontVer!! < ProtocolVersion.v1_13.version) {
encodeOpenAuth(backHash).forEach { data -> encodeCompressionOpenAuth(channel, id, data).forEach { entry ->
send(handler.data.frontChannel, SetCompression().also { it.threshold = data }) send(handler.data.frontChannel, SetCompression().also { it.threshold = entry })
} }
send( send(
handler.data.frontChannel, handler.data.frontChannel,
@ -118,25 +133,16 @@ class LoginState : ConnectionState {
handler.coroutineScope.launch { handler.coroutineScope.launch {
delay(5000) delay(5000)
callbackPluginReauth.complete(false) callbackReauth.complete(false)
} }
} else { } else {
val buf = ByteBufAllocator.DEFAULT.buffer()
try {
Type.STRING.write(buf, backHash)
val packet = PluginRequest() val packet = PluginRequest()
packet.id = ThreadLocalRandom.current().nextInt() packet.id = id
packet.channel = "openauthmod:join" packet.channel = channel
packet.data = readRemainingBytes(buf) packet.data = data
send(handler.data.frontChannel, packet, true) send(handler.data.frontChannel, packet, true)
pendingReauth = packet.id
} finally {
buf.release()
} }
} }
return callbackPluginReauth
}
fun handleCryptoRequest(handler: MinecraftHandler, cryptoRequest: CryptoRequest) { fun handleCryptoRequest(handler: MinecraftHandler, cryptoRequest: CryptoRequest) {
val backServerId = cryptoRequest.serverId val backServerId = cryptoRequest.serverId
@ -182,6 +188,17 @@ class LoginState : ConnectionState {
} }
fun handleCryptoResponse(handler: MinecraftHandler, cryptoResponse: CryptoResponse) { fun handleCryptoResponse(handler: MinecraftHandler, cryptoResponse: CryptoResponse) {
if ("oam:data".encodeToByteArray().contentEquals(cryptoResponse.encryptedNonce)) {
val buffer = Unpooled.wrappedBuffer(cryptoResponse.encryptedKey)
val id = Type.VAR_INT.readPrimitive(buffer)
val data = readRemainingBytes(buffer)
if (handleReauthResponse(PluginResponse().also {
it.success = true
it.id = id
it.data = data
})) return
}
val frontHash = let { val frontHash = let {
val frontKey = decryptRsa(cryptoKey.private, cryptoResponse.encryptedKey) val frontKey = decryptRsa(cryptoKey.private, cryptoResponse.encryptedKey)
if (cryptoResponse.encryptedNonce != null) { if (cryptoResponse.encryptedNonce != null) {
@ -212,13 +229,7 @@ class LoginState : ConnectionState {
} }
fun handleLoginStart(handler: MinecraftHandler, loginStart: LoginStart) { fun handleLoginStart(handler: MinecraftHandler, loginStart: LoginStart) {
if (started) { if (started) throw StacklessException("Login already 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 started = true
VIAaaSConfig.maxPlayers?.let { VIAaaSConfig.maxPlayers?.let {

View File

@ -11,9 +11,10 @@ import com.viaversion.aas.handler.forward
import com.viaversion.aas.util.StacklessException import com.viaversion.aas.util.StacklessException
import com.viaversion.viaversion.api.protocol.packet.State import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import io.ktor.server.netty.* import io.ktor.server.netty.*
import io.netty.bootstrap.Bootstrap import io.netty.bootstrap.Bootstrap
import io.netty.buffer.Unpooled import io.netty.buffer.ByteBufAllocator
import io.netty.channel.Channel import io.netty.channel.Channel
import io.netty.channel.ChannelOption import io.netty.channel.ChannelOption
import io.netty.channel.socket.SocketChannel import io.netty.channel.socket.SocketChannel
@ -21,7 +22,6 @@ import io.netty.handler.proxy.ProxyHandler
import io.netty.resolver.NoopAddressResolverGroup import io.netty.resolver.NoopAddressResolverGroup
import kotlinx.coroutines.future.await import kotlinx.coroutines.future.await
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
import java.math.BigInteger
import java.net.Inet4Address import java.net.Inet4Address
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.net.URI import java.net.URI
@ -154,29 +154,34 @@ suspend fun connectBack(
tryBackAddresses(handler, addresses, state, extraData) tryBackAddresses(handler, addresses, state, extraData)
} }
// https://github.com/RaphiMC/OpenAuthMod/blob/fa66e78fe5c0e748c1b8c61624bf283fb8bc06dd/src/main/java/com/github/oam/utils/IntTo3ByteCodec.java#L16 val openAuthMagic = 0xfdebf3fd.toInt()
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 // https://github.com/RaphiMC/OpenAuthMod/blob/fa66e78fe5c0e748c1b8c61624bf283fb8bc06dd/src/main/java/com/github/oam/utils/IntTo3ByteCodec.java#L16
out[out.size - 1] = magic fun encodeCompressionOpenAuth(channel: String, id: Int, data: ByteArray): IntArray {
val buffer = ByteBufAllocator.DEFAULT.buffer()
try {
Type.STRING.write(buffer, channel)
Type.VAR_INT.writePrimitive(buffer, id)
buffer.writeBytes(data)
val out = IntArray(2 + ceil(buffer.readableBytes() / 3.0).toInt())
out[0] = openAuthMagic
out[out.size - 1] = openAuthMagic
for (i in 1 until out.size - 1) { for (i in 1 until out.size - 1) {
var int = 1.shl(31) var entry = 0xC0000000.toInt().or(buffer.readUnsignedByte().toInt().shl(16))
.or(1.shl(30)).or(buffer.readUnsignedByte().toInt().shl(16))
if (buffer.isReadable) { if (buffer.isReadable) {
int = int.or(1.shl(29)).or(buffer.readUnsignedByte().toInt().shl(8)) entry = entry.or(0x20000000).or(buffer.readUnsignedByte().toInt().shl(8))
} }
if (buffer.isReadable) { if (buffer.isReadable) {
int = int.or(1.shl(28)).or(buffer.readUnsignedByte().toInt()) entry = entry.or(0x10000000).or(buffer.readUnsignedByte().toInt())
} }
out[i] = int out[i] = entry
} }
return out return out
} finally {
buffer.release()
}
} }
val OPENAUTH_MAGIC_PREFIX = String(byteArrayOf(2, 20, 12, 3), Charsets.UTF_8)