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.type.Type
import io.netty.buffer.ByteBufAllocator
import io.netty.buffer.Unpooled
import io.netty.channel.Channel
import io.netty.channel.ChannelHandlerContext
import kotlinx.coroutines.Dispatchers
@ -37,11 +38,9 @@ class LoginState : ConnectionState {
var extraData: String? = null
var backName: String? = null
var started = false
override val state: State
get() = State.LOGIN
override val logDcInfo: Boolean
get() = true
var callbackPluginReauth = CompletableFuture<Boolean>()
override val state: State get() = State.LOGIN
override val logDcInfo: Boolean get() = true
val callbackReauth = CompletableFuture<Boolean>()
var pendingReauth: Int? = null
override fun handlePacket(handler: MinecraftHandler, ctx: ChannelHandlerContext, packet: Packet) {
@ -59,15 +58,21 @@ class LoginState : ConnectionState {
}
private fun handlePluginResponse(handler: MinecraftHandler, packet: PluginResponse) {
if (packet.id == pendingReauth) {
callbackPluginReauth.complete(packet.success)
pendingReauth = null
return
}
if (handleReauthResponse(packet)) return
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) {
handler.data.state = PlayState
forward(handler, loginSuccess)
@ -77,9 +82,7 @@ class LoginState : ConnectionState {
val threshold = setCompression.threshold
setCompression(handler.data.backChannel!!, threshold)
forward(handler, setCompression)
setCompression(handler.data.frontChannel, threshold)
}
@ -102,13 +105,25 @@ class LoginState : ConnectionState {
|| !frontName.equals(backName, ignoreCase = true)
|| handler.data.frontVer!! < ProtocolVersion.v1_8.version
) {
callbackPluginReauth.complete(false)
return callbackPluginReauth
callbackReauth.complete(false)
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) {
encodeOpenAuth(backHash).forEach { data ->
send(handler.data.frontChannel, SetCompression().also { it.threshold = data })
encodeCompressionOpenAuth(channel, id, data).forEach { entry ->
send(handler.data.frontChannel, SetCompression().also { it.threshold = entry })
}
send(
handler.data.frontChannel,
@ -118,24 +133,15 @@ class LoginState : ConnectionState {
handler.coroutineScope.launch {
delay(5000)
callbackPluginReauth.complete(false)
callbackReauth.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()
}
val packet = PluginRequest()
packet.id = id
packet.channel = channel
packet.data = data
send(handler.data.frontChannel, packet, true)
}
return callbackPluginReauth
}
fun handleCryptoRequest(handler: MinecraftHandler, cryptoRequest: CryptoRequest) {
@ -182,6 +188,17 @@ class LoginState : ConnectionState {
}
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 frontKey = decryptRsa(cryptoKey.private, cryptoResponse.encryptedKey)
if (cryptoResponse.encryptedNonce != null) {
@ -212,13 +229,7 @@ class LoginState : ConnectionState {
}
fun handleLoginStart(handler: MinecraftHandler, loginStart: LoginStart) {
if (started) {
if (loginStart.username.startsWith(OPENAUTH_MAGIC_PREFIX)) {
callbackPluginReauth.complete(loginStart.username.removePrefix(OPENAUTH_MAGIC_PREFIX).toBoolean())
return
}
throw StacklessException("Login already started")
}
if (started) throw StacklessException("Login already started")
started = true
VIAaaSConfig.maxPlayers?.let {

View File

@ -11,9 +11,10 @@ import com.viaversion.aas.handler.forward
import com.viaversion.aas.util.StacklessException
import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import io.ktor.server.netty.*
import io.netty.bootstrap.Bootstrap
import io.netty.buffer.Unpooled
import io.netty.buffer.ByteBufAllocator
import io.netty.channel.Channel
import io.netty.channel.ChannelOption
import io.netty.channel.socket.SocketChannel
@ -21,7 +22,6 @@ 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
@ -154,29 +154,34 @@ suspend fun connectBack(
tryBackAddresses(handler, addresses, state, extraData)
}
val openAuthMagic = 0xfdebf3fd.toInt()
// 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()
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] = magic
out[out.size - 1] = magic
out[0] = openAuthMagic
out[out.size - 1] = openAuthMagic
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())
for (i in 1 until out.size - 1) {
var entry = 0xC0000000.toInt().or(buffer.readUnsignedByte().toInt().shl(16))
if (buffer.isReadable) {
entry = entry.or(0x20000000).or(buffer.readUnsignedByte().toInt().shl(8))
}
if (buffer.isReadable) {
entry = entry.or(0x10000000).or(buffer.readUnsignedByte().toInt())
}
out[i] = entry
}
out[i] = int
return out
} finally {
buffer.release()
}
return out
}
val OPENAUTH_MAGIC_PREFIX = String(byteArrayOf(2, 20, 12, 3), Charsets.UTF_8)
}