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