From 760075e9140c01a55711fa2d2cf09ae27252e74e Mon Sep 17 00:00:00 2001
From: sandtechnology <a1294790523@hotmail.com>
Date: Sun, 18 Jun 2023 19:58:50 +0800
Subject: [PATCH] [core] Fix wrong SSOReserveField proto and packet codec
 1.Body is a lambda function, so invoke it by only once 2.Fix wrong protoBuf
 serializer, use protocol one 3.Pass all packets to EncryptService (which
 packet should be sign should judge by service itself) 4.Fix wrong proto
 number and add missed default value, also fix proto naming

---
 .../protocol/data/proto/SSOReserveField.kt    | 74 +++++++++----------
 .../network/protocol/packet/OutgoingPacket.kt | 50 ++++++-------
 2 files changed, 61 insertions(+), 63 deletions(-)

diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/SSOReserveField.kt b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/SSOReserveField.kt
index 467050106..7e6f86f08 100644
--- a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/SSOReserveField.kt
+++ b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/SSOReserveField.kt
@@ -17,46 +17,46 @@ import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY
 internal class SSOReserveField {
     @Serializable
     internal class ReserveFields(
-        @JvmField @ProtoNumber(1) val client_ipcookie: ByteArray = EMPTY_BYTE_ARRAY,
-        @JvmField @ProtoNumber(2) val flag: Int = 0,
-        @JvmField @ProtoNumber(3) val env_id: Int = 0,
-        @JvmField @ProtoNumber(4) val locale_id: Int = 0,
-        @JvmField @ProtoNumber(5) val qimei: ByteArray = EMPTY_BYTE_ARRAY,
-        @JvmField @ProtoNumber(6) val env: String = "",
-        @JvmField @ProtoNumber(7) val newconn_flag: Int = 0,
-        @JvmField @ProtoNumber(8) val trace_parent: String = "",
-        @JvmField @ProtoNumber(9) val uid: String = "",
-        @JvmField @ProtoNumber(10) val imsi: Int = 0,
-        @JvmField @ProtoNumber(11) val network_type: Int = 0,
-        @JvmField @ProtoNumber(12) val ip_stack_type: Int = 0,
-        @JvmField @ProtoNumber(13) val message_type: Int = 0,
-        @JvmField @ProtoNumber(14) val trpc_rsp: SsoTrpcResponse? = null,
-        @JvmField @ProtoNumber(15) val trans_info: List<SsoMapEntry>? = null,
-        @JvmField @ProtoNumber(16) val sec_info: SsoSecureInfo? = null,
-        @JvmField @ProtoNumber(17) val sec_sig_flag: Int = 0,
-        @JvmField @ProtoNumber(18) val nt_core_version: Int = 0,
-        @JvmField @ProtoNumber(19) val sso_route_cost: Int = 0,
-        @JvmField @ProtoNumber(20) val sso_ip_origin: Int = 0,
-        @JvmField @ProtoNumber(21) val presure_token: ByteArray = EMPTY_BYTE_ARRAY,
-    ) : ProtoBuf
-
-    @Serializable
-    internal class SsoSecureInfo(
-        @JvmField @ProtoNumber(1) val sec_sig: ByteArray = EMPTY_BYTE_ARRAY,
-        @JvmField @ProtoNumber(2) val sec_device_token: ByteArray = EMPTY_BYTE_ARRAY,
-        @JvmField @ProtoNumber(3) val sec_extra: ByteArray = EMPTY_BYTE_ARRAY,
-    ) : ProtoBuf
-
-    @Serializable
-    internal class SsoTrpcResponse(
-        @JvmField @ProtoNumber(1) val ret: Int = 0,
-        @JvmField @ProtoNumber(2) val func_ret: Int = 0,
-        @JvmField @ProtoNumber(3) val error_msg: ByteArray = EMPTY_BYTE_ARRAY,
+        @ProtoNumber(8) @JvmField val clientIpcookie: ByteArray = EMPTY_BYTE_ARRAY,
+        @ProtoNumber(9) @JvmField val flag: Int = 0,
+        @ProtoNumber(10) @JvmField val envId: Int = 0,
+        @ProtoNumber(11) @JvmField val localeId: Int = 2052,
+        @ProtoNumber(12) @JvmField val qimei: ByteArray = EMPTY_BYTE_ARRAY,
+        @ProtoNumber(13) @JvmField val env: String = "",
+        @ProtoNumber(14) @JvmField val newconnFlag: Int = 0,
+        @ProtoNumber(15) @JvmField val traceParent: String = "",
+        @ProtoNumber(16) @JvmField val uid: String = "",
+        @ProtoNumber(18) @JvmField val imsi: Int = 0,
+        @ProtoNumber(19) @JvmField val networkType: Int = 0,
+        @ProtoNumber(20) @JvmField val ipStackType: Int = 0,
+        @ProtoNumber(21) @JvmField val messageType: Int = 0,
+        @ProtoNumber(22) @JvmField val trpcRsp: SsoTrpcResponse? = null,
+        @ProtoNumber(23) @JvmField val transInfo: List<SsoMapEntry> = emptyList(),
+        @ProtoNumber(24) @JvmField val secInfo: SsoSecureInfo? = null,
+        @ProtoNumber(25) @JvmField val secSigFlag: Int = 0,
+        @ProtoNumber(26) @JvmField val ntCoreVersion: Int = 0,
+        @ProtoNumber(27) @JvmField val ssoRouteCost: Int = 0,
+        @ProtoNumber(28) @JvmField val ssoIpOrigin: Int = 0,
+        @ProtoNumber(30) @JvmField val presureToken: ByteArray = EMPTY_BYTE_ARRAY
     ) : ProtoBuf
 
     @Serializable
     internal class SsoMapEntry(
-        @JvmField @ProtoNumber(1) val key: String = "",
-        @JvmField @ProtoNumber(2) val value: ByteArray = EMPTY_BYTE_ARRAY,
+        @ProtoNumber(1) @JvmField val key: String = "",
+        @ProtoNumber(2) @JvmField val value: ByteArray = EMPTY_BYTE_ARRAY
+    ) : ProtoBuf
+
+    @Serializable
+    internal class SsoSecureInfo(
+        @ProtoNumber(1) @JvmField val secSig: ByteArray = EMPTY_BYTE_ARRAY,
+        @ProtoNumber(2) @JvmField val secDeviceToken: ByteArray = EMPTY_BYTE_ARRAY,
+        @ProtoNumber(3) @JvmField val secExtra: ByteArray = EMPTY_BYTE_ARRAY
+    ) : ProtoBuf
+
+    @Serializable
+    internal class SsoTrpcResponse(
+        @ProtoNumber(1) @JvmField val ret: Int = 0,
+        @ProtoNumber(2) @JvmField val funcRet: Int = 0,
+        @ProtoNumber(3) @JvmField val errorMsg: ByteArray = EMPTY_BYTE_ARRAY
     ) : ProtoBuf
 }
\ No newline at end of file
diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/OutgoingPacket.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/OutgoingPacket.kt
index b71f02a62..a2f8a2dfd 100644
--- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/OutgoingPacket.kt
+++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/OutgoingPacket.kt
@@ -12,11 +12,11 @@ package net.mamoe.mirai.internal.network.protocol.packet
 
 import io.ktor.utils.io.core.*
 import kotlinx.serialization.encodeToByteArray
+import kotlinx.serialization.protobuf.ProtoBuf
 import net.mamoe.mirai.internal.QQAndroidBot
 import net.mamoe.mirai.internal.network.*
 import net.mamoe.mirai.internal.network.components.EcdhInitialPublicKeyUpdater
 import net.mamoe.mirai.internal.network.protocol.data.proto.SSOReserveField
-import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbSendMsg
 import net.mamoe.mirai.internal.network.protocol.packet.sso.TRpcRawPacket
 import net.mamoe.mirai.internal.spi.EncryptService
 import net.mamoe.mirai.internal.spi.EncryptServiceContext
@@ -314,14 +314,10 @@ internal inline fun BytePacketBuilder.writeSsoPacket(
      * 00 00 00 04
      */
     val encryptWorker = EncryptService.instance
+    val bodyBytes = buildPacket(body).readBytes()
+    val reserveField = if (encryptWorker != null) {
 
-    val reserveField = if (
-        commandName.startsWith("wtlogin")
-        || commandName == MessageSvcPbSendMsg.commandName
-        || encryptWorker != null
-    ) {
-
-        val signResult = encryptWorker?.qSecurityGetSign(
+        val signResult = encryptWorker.qSecurityGetSign(
             EncryptServiceContext(client.uin, buildTypeSafeMap {
                 set(EncryptServiceContext.KEY_APP_QUA, "V1_AND_SQ_8.9.58_4106_YYB_D") // 8.9.58
                 set(EncryptServiceContext.KEY_CHANNEL_PROXY, createChannelProxy(client.bot))
@@ -330,25 +326,27 @@ internal inline fun BytePacketBuilder.writeSsoPacket(
             }),
             sequenceId,
             commandName,
-            buildPacket(body).readBytes()
+            bodyBytes
         )
-        if (signResult != null) ProtoBufForCache.encodeToByteArray(
-            SSOReserveField.ReserveFields(
-                flag = 0,
-                qimei = client.qimei16?.toByteArray() ?: EMPTY_BYTE_ARRAY,
-                newconn_flag = 0,
-                uid = client.uin.toString(),
-                imsi = 0,
-                network_type = 1,
-                ip_stack_type = 1,
-                message_type = 0,
-                sec_info = SSOReserveField.SsoSecureInfo(
-                    sec_sig = signResult.sign,
-                    sec_device_token = signResult.token,
-                    sec_extra = signResult.extra
+        if (signResult != null)
+            ProtoBuf.encodeToByteArray(
+                SSOReserveField.ReserveFields(
+                    flag = 0,
+                    qimei = client.qimei16?.toByteArray() ?: EMPTY_BYTE_ARRAY,
+                    newconnFlag = 0,
+                    uid = client.uin.toString(),
+                    imsi = 0,
+                    networkType = 1,
+                    ipStackType = 1,
+                    messageType = 0,
+                    secInfo = SSOReserveField.SsoSecureInfo(
+                        secSig = signResult.sign,
+                        secDeviceToken = signResult.token,
+                        secExtra = signResult.extra
+                    ),
+                    ssoIpOrigin = 0,
                 )
-            )
-        ) else EMPTY_BYTE_ARRAY
+            ) else EMPTY_BYTE_ARRAY
     } else EMPTY_BYTE_ARRAY
 
     writeIntLVPacket(lengthOffset = { it + 4 }) {
@@ -387,7 +385,7 @@ internal inline fun BytePacketBuilder.writeSsoPacket(
     }
 
     // body
-    writeIntLVPacket(lengthOffset = { it + 4 }, builder = body)
+    writeIntLVPacket(lengthOffset = { it + 4 }, builder = { writeFully(bodyBytes) })
 }
 
 internal fun BytePacketBuilder.writeOicqRequestPacket(