diff --git a/FFXIVClassic_Lobby_Server/Database.cs b/FFXIVClassic_Lobby_Server/Database.cs index 83673328..d9e7f3be 100644 --- a/FFXIVClassic_Lobby_Server/Database.cs +++ b/FFXIVClassic_Lobby_Server/Database.cs @@ -128,9 +128,9 @@ namespace FFXIVClassic_Lobby_Server WHERE userId=@userId AND id=@cid; INSERT INTO characters_appearance - (characterId, baseId, size, voice, skinColor, hairStyle, hairColor, hairHighlightColor, eyeColor, faceType, faceEyebrows, faceEyeShape, faceIrisSize, faceNose, faceMouth, faceFeatures, ears, characteristics, characteristicsColor, mainhand, head, body, hands, legs, feet) + (characterId, baseId, size, voice, skinColor, hairStyle, hairColor, hairHighlightColor, eyeColor, faceType, faceEyebrows, faceEyeShape, faceIrisSize, faceNose, faceMouth, faceFeatures, ears, characteristics, characteristicsColor, mainhand, head, body, hands, legs, feet, waist) VALUES - (@cid, 4294967295, @size, @voice, @skinColor, @hairStyle, @hairColor, @hairHighlightColor, @eyeColor, @faceType, @faceEyebrows, @faceEyeShape, @faceIrisSize, @faceNose, @faceMouth, @faceFeatures, @ears, @characteristics, @characteristicsColor, @mainhand, @head, @body, @hands, @legs, @feet) + (@cid, 4294967295, @size, @voice, @skinColor, @hairStyle, @hairColor, @hairHighlightColor, @eyeColor, @faceType, @faceEyebrows, @faceEyeShape, @faceIrisSize, @faceNose, @faceMouth, @faceFeatures, @ears, @characteristics, @characteristicsColor, @mainhand, @head, @body, @hands, @legs, @feet, @waist) "; cmd.Parameters.AddWithValue("@userId", accountId); cmd.Parameters.AddWithValue("@cid", cid); @@ -172,6 +172,7 @@ namespace FFXIVClassic_Lobby_Server cmd.Parameters.AddWithValue("@legs", charaInfo.legs); cmd.Parameters.AddWithValue("@hands", charaInfo.hands); cmd.Parameters.AddWithValue("@feet", charaInfo.feet); + cmd.Parameters.AddWithValue("@waist", charaInfo.belt); cmd.ExecuteNonQuery(); diff --git a/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj b/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj index fec06e67..227a00aa 100644 --- a/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj +++ b/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj @@ -72,6 +72,7 @@ + diff --git a/FFXIVClassic_Lobby_Server/PacketProcessor.cs b/FFXIVClassic_Lobby_Server/PacketProcessor.cs index 5cccc0ae..ef754006 100644 --- a/FFXIVClassic_Lobby_Server/PacketProcessor.cs +++ b/FFXIVClassic_Lobby_Server/PacketProcessor.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -23,6 +24,7 @@ namespace FFXIVClassic_Lobby_Server if ((packet.header.packetSize == 0x288) && (packet.data[0x34] == 'T')) //Test Ticket Data { + packet.debugPrintPacket(); //Crypto handshake ProcessStartSession(client, packet); return; @@ -65,13 +67,12 @@ namespace FFXIVClassic_Lobby_Server private void ProcessStartSession(ClientConnection client, BasePacket packet) { - UInt32 clientTime = BitConverter.ToUInt32(packet.data, 0x74); + SecurityHandshakePacket securityHandshake = new SecurityHandshakePacket(packet.data); - //We assume clientTime is 0x50E0E812, but we need to generate a proper key later - byte[] blowfishKey = { 0xB4, 0xEE, 0x3F, 0x6C, 0x01, 0x6F, 0x5B, 0xD9, 0x71, 0x50, 0x0D, 0xB1, 0x85, 0xA2, 0xAB, 0x43}; + byte[] blowfishKey = GenerateKey(securityHandshake.ticketPhrase, securityHandshake.clientNumber); client.blowfish = new Blowfish(blowfishKey); - Log.info(String.Format("Received encryption key: 0x{0:X}", clientTime)); + Log.info(String.Format("SecCNum: 0x{0:X}", securityHandshake.clientNumber)); //Respond with acknowledgment BasePacket outgoingPacket = new BasePacket(HardCoded_Packets.g_secureConnectionAcknowledgment); @@ -242,21 +243,21 @@ namespace FFXIVClassic_Lobby_Server //Set Initial Position switch (info.initialTown) { - case 1: + case 1: //ocn0Battle02 (Limsa) info.zoneId = 193; info.x = 0.016f; info.y = 10.35f; info.z = -36.91f; info.rot = 0.025f; break; - case 2: + case 2: //fst0Battle03 (Gridania) info.zoneId = 166; info.x = 356.09f; info.y = 3.74f; info.z = -701.62f; info.rot = -1.4f; break; - case 3: + case 3: //wil0Battle01 (Ul'dah) info.zoneId = 184; info.x = 12.63f; info.y = 196.05f; @@ -357,5 +358,32 @@ namespace FFXIVClassic_Lobby_Server client.queuePacket(basePacket); } + private byte[] GenerateKey(string ticketPhrase, uint clientNumber) + { + byte[] key; + using (MemoryStream memStream = new MemoryStream(0x2C)) + { + using (BinaryWriter binWriter = new BinaryWriter(memStream)) + { + binWriter.Write((Byte)0x78); + binWriter.Write((Byte)0x56); + binWriter.Write((Byte)0x34); + binWriter.Write((Byte)0x12); + binWriter.Write((UInt32)clientNumber); + binWriter.Write((Byte)0xE8); + binWriter.Write((Byte)0x03); + binWriter.Write((Byte)0x00); + binWriter.Write((Byte)0x00); + binWriter.Write(Encoding.ASCII.GetBytes(ticketPhrase), 0, Encoding.ASCII.GetByteCount(ticketPhrase) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(ticketPhrase)); + } + byte[] nonMD5edKey = memStream.GetBuffer(); + + using (MD5 md5Hash = MD5.Create()) + { + key = md5Hash.ComputeHash(nonMD5edKey); + } + } + return key; + } } } diff --git a/FFXIVClassic_Lobby_Server/packets/receive/SecurityHandshakePacket.cs b/FFXIVClassic_Lobby_Server/packets/receive/SecurityHandshakePacket.cs new file mode 100644 index 00000000..a5fb8b87 --- /dev/null +++ b/FFXIVClassic_Lobby_Server/packets/receive/SecurityHandshakePacket.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Lobby_Server.packets.receive +{ + class SecurityHandshakePacket + { + public string ticketPhrase; + public uint clientNumber; + + public bool invalidPacket = false; + + public SecurityHandshakePacket(byte[] data) + { + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryReader binReader = new BinaryReader(mem)) + { + try + { + binReader.BaseStream.Seek(0x34, SeekOrigin.Begin); + ticketPhrase = Encoding.ASCII.GetString(binReader.ReadBytes(0x40)).Trim(new[] { '\0' }); + clientNumber = binReader.ReadUInt32(); + } + catch (Exception){ + invalidPacket = true; + } + } + } + } + } +} diff --git a/FFXIVClassic_Lobby_Server/utils/CharacterCreatorUtils.cs b/FFXIVClassic_Lobby_Server/utils/CharacterCreatorUtils.cs index 1e6c23e6..adec38e8 100644 --- a/FFXIVClassic_Lobby_Server/utils/CharacterCreatorUtils.cs +++ b/FFXIVClassic_Lobby_Server/utils/CharacterCreatorUtils.cs @@ -14,7 +14,7 @@ namespace FFXIVClassic_Lobby_Server.utils { 3, new uint[]{79692890,0,0,0,0,0,0,0,31776,4448,1024,25824,6144,0,0,0,0,0,0,0,0,0} }, //GLA { 4, new uint[]{147850310,0,0,0,0,0,0,23713,1184,10016,5472,1152,6144,0,0,0,0,0,0,0,0,0} }, //MRD { 7, new uint[]{210764860,236979210,0,0,0,231736320,0,0,9888,9984,1024,25824,6144,0,0,0,0,0,0,0,0,0} }, //ARC - { 8, new uint[]{210764860,0,0,0,0,0,0,0,13920,7200,1024,10656,6144,0,0,0,0,0,0,0,0,0} }, //LNC + { 8, new uint[]{168823858,0,0,0,0,0,0,0,13920,7200,1024,10656,6144,0,0,0,0,0,0,0,0,0} }, //LNC { 22, new uint[]{294650980,0,0,0,0,0,0,0,7744,5472,1024,5504,4096,0,0,0,0,0,0,0,0,0} }, //THM { 23, new uint[]{347079700,0,0,0,0,0,0,0,4448,2240,1024,4416,4096,0,0,0,0,0,0,0,0,0} }, //CNJ