mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2025-01-24 22:01:49 +01:00
update for new OpenAuthMod
This commit is contained in:
parent
b415fd5223
commit
2bf8b65337
@ -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 {
|
||||||
|
@ -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)
|
|
Loading…
Reference in New Issue
Block a user