public bool fetchWordList(ref WorldList wl) { // Doesnt exist by default wl.setExistance(false); conn.Open(); string sqlQuery = "SELECT * FROM users WHERE username='******' AND passwordmd5='"+wl.getPassword()+"' LIMIT 1;"; queryExecuter= conn.CreateCommand(); queryExecuter.CommandText = sqlQuery; dr= queryExecuter.ExecuteReader(); while(dr.Read()){ // Player is on the DB wl.setExistance(true); wl.setUserID((int) dr.GetDecimal(0)); dr.GetBytes(5,0,wl.getPublicModulus(),0,96); dr.GetBytes(6,0,wl.getPrivateExponent(),0,96); wl.setTimeCreated((int)dr.GetDecimal(7)); } dr.Close(); // If doesnt exist... should not do more things if (!wl.getExistance()){ String msg = "Player not found on DB with #"+wl.getUsername()+"# and #"+wl.getPassword()+"#"; Output.WriteLine(msg); conn.Close(); return false; } // If exist, get the player values // Count the values first int totalChars = 0; string sqlCount = "SELECT charId FROM characters WHERE userId='" + wl.getUserID() + "' AND is_deleted='0' "; queryExecuter= conn.CreateCommand(); queryExecuter.CommandText = sqlCount; dr= queryExecuter.ExecuteReader(); while (dr.Read()){ totalChars++; } dr.Close(); wl.getCharPack().setTotalChars(totalChars); // Prepare to read characters string sqlQueryForChars = "SELECT * FROM characters WHERE userId='" + wl.getUserID() + "' AND is_deleted='0' "; queryExecuter= conn.CreateCommand(); queryExecuter.CommandText = sqlQueryForChars; dr= queryExecuter.ExecuteReader(); // Read characters while(dr.Read()){ //totalChars = (int) dr.GetDecimal(8); string charName = dr.GetString(4); int charId = (int)dr.GetDecimal(0); int status = (int)dr.GetDecimal(3); int worldId = (int)dr.GetDecimal(2); wl.getCharPack().addCharacter(charName,charId,status,worldId); } dr.Close(); // Read worlds string sqlQueryForWorlds = "SELECT * FROM worlds ORDER BY worldId ASC"; queryExecuter.CommandText = sqlQueryForWorlds; dr= queryExecuter.ExecuteReader(); while (dr.Read()){ string worldName = dr.GetString(1); int worldId = (int) dr.GetDecimal(0); int worldType = (int) dr.GetDecimal(2); int worldStatus = (int) dr.GetDecimal(3); int worldPopulation = (int) dr.GetDecimal(4); wl.getWorldPack().addWorld(worldName,worldId,worldStatus,worldType,worldPopulation); } dr.Close(); conn.Close(); return true; }
public byte[] processHandleAuthChallenge_Response(byte[] data, int maxBytes) { int blobSize = (int)data[4]; byte[] encryptedBlob = new byte[blobSize]; byte[] decryptedBlob = new byte[blobSize]; ArrayUtils.copy(data, 6, encryptedBlob, 0, blobSize); // Reset IV to 0 tf.setIV(blankIV); tf.decrypt(encryptedBlob, decryptedBlob); byte[] receivedMD5 = new byte[16]; ArrayUtils.copy(decryptedBlob, 1, receivedMD5, 0, 16); // Security says that must be the same if (!ArrayUtils.equal(receivedMD5, md5edChallenge)) { Output.WriteLine("The Md5 from client and Our Md5 are not same, aborting"); Output.WriteLine("Decrypted (TF) blob:" + StringUtils.bytesToString(decryptedBlob)); Output.WriteLine("Stored MD5ed Challenge:" + StringUtils.bytesToString(md5edChallenge)); throw new AuthException("Md5 challenge differs"); } // We take the pass from the decrypted Blob and subtract 1 byte, the ending "0" int passSize = ((int)decryptedBlob[23]) - 1; byte[] passwordB = new byte[passSize]; ArrayUtils.copy(decryptedBlob, 25, passwordB, 0, passSize); Output.OptWriteLine("-> Password decrypted, size:" + passSize); // Set WorldList password wl.setPassword(StringUtils.bytesToString_NS(md5.digest(passwordB))); if (Store.dbManager.AuthDbHandler.fetchWordList(ref wl)) { // Do calculations magic byte[] hexUserID = NumericalUtils.uint32ToByteArray((UInt32)wl.getUserID(), 1); byte[] nameH = new byte[33]; string name = wl.getUsername(); for (int i = 0; i < name.Length; i++) { nameH[i] = (byte)name[i]; } byte[] padding = new byte[4]; // 4 empty byte ==> [0x00,0x00,0x00,0x00] // +10 mins from now, so 60secs per min byte[] expiredTime = TimeUtils.getUnixTime(60 * 10); byte[] padding2 = new byte[32]; // 32 empty byte ==> [0x00,0x00,0x00,0x00,...] byte[] pubModulusH = wl.getPublicModulus(); byte[] createdTime = NumericalUtils.uint32ToByteArray((UInt32)wl.getTimeCreated(), 1); // Create signed data DynamicArray signedData = new DynamicArray(); signedData.append(new byte[] { 0x01 }); signedData.append(hexUserID); signedData.append(nameH); signedData.append(new byte[] { 0x00, 0x01 }); signedData.append(padding); signedData.append(expiredTime); signedData.append(padding2); signedData.append(new byte[] { 0x00, 0x11 }); signedData.append(pubModulusH); signedData.append(createdTime); byte[] md5FromStructure = md5.digest(signedData.getBytes()); // Do MD5 to the signed data and RSA encrypt the result byte[] signature = rsa.signWithMD5(md5FromStructure); Output.OptWriteLine("-> Signing with RSA"); // Do: privExp = Twofish(privExp) byte[] privExp = wl.getPrivateExponent(); byte[] buffer = new byte[privExp.Length]; // We keep the Key from before this part // Set the challenge we saved before as IV tf.setIV(challenge); tf.encrypt(privExp, buffer); privExp = buffer; byte [] privExpSize = NumericalUtils.uint16ToByteArray((UInt16)privExp.Length, 1); // Calculate offsets int offsetAuthData = 33 + wl.getCharPack().getPackLength() + wl.getWorldPack().getTotalSize(); int offsetEncryptedData = offsetAuthData + signature.Length + signedData.getSize() + 2; int offsetCharData = 33; int offsetServerData = 33 + wl.getCharPack().getPackLength(); int offsetUsernameLast = offsetEncryptedData + 2 + privExp.Length; // Create the auth header DynamicArray authHeader = new DynamicArray(); authHeader.append(new byte[] { 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); authHeader.append(NumericalUtils.uint16ToByteArray((UInt16)offsetAuthData, 1)); authHeader.append(NumericalUtils.uint16ToByteArray((UInt16)offsetEncryptedData, 1)); authHeader.append(new byte[] { 0x1f, 0x00, 0x00, 0x00 }); authHeader.append(NumericalUtils.uint16ToByteArray((UInt16)offsetCharData, 1)); authHeader.append(new byte[] { 0x6E, 0xD1, 0x00, 0x00 }); authHeader.append(NumericalUtils.uint32ToByteArray((UInt32)offsetServerData, 1)); authHeader.append(NumericalUtils.uint32ToByteArray((UInt32)offsetUsernameLast, 1)); byte [] usernameSize = NumericalUtils.uint16ToByteArray((UInt16)(name.Length + 1), 1); // Create the semiResponse (full data, except the total size) DynamicArray semiResponse = new DynamicArray(); semiResponse.append(authHeader.getBytes()); semiResponse.append(wl.getCharPack().getByteContents()); semiResponse.append(wl.getWorldPack().getByteContents()); semiResponse.append(new byte[] { 0x36, 0x01 }); semiResponse.append(signature); semiResponse.append(signedData.getBytes()); semiResponse.append(privExpSize); semiResponse.append(privExp); semiResponse.append(usernameSize); byte [] tempName = new byte[name.Length]; for (int i = 0; i < name.Length; i++) { tempName[i] = (byte)name[i]; } semiResponse.append(tempName); semiResponse.append(new byte[] { 0x00 }); int bigSize = semiResponse.getSize(); bigSize += 0x8000; // Add TCP Len Var byte [] finalSize = NumericalUtils.uint16ToByteArray((UInt16)bigSize, 0); // Create the finalResponse (full data, plus total size) DynamicArray finalResponse = new DynamicArray(); finalResponse.append(finalSize); finalResponse.append(semiResponse.getBytes()); Output.OptWriteLine("Sending world list."); status = -1; return(finalResponse.getBytes()); } byte [] worldListPacket = { 0x00, 0x00 }; status = -1; // trick return(worldListPacket); }
public bool fetchWordList(ref WorldList wl) { // Doesnt exist by default wl.setExistance(false); conn.Open(); string sqlQuery = "SELECT * FROM users WHERE username='******' AND passwordmd5='" + wl.getPassword() + "' LIMIT 1;"; queryExecuter = conn.CreateCommand(); queryExecuter.CommandText = sqlQuery; dr = queryExecuter.ExecuteReader(); while (dr.Read()) { // Player is on the DB wl.setExistance(true); wl.setUserID((int)dr.GetDecimal(0)); dr.GetBytes(5, 0, wl.getPublicModulus(), 0, 96); dr.GetBytes(6, 0, wl.getPrivateExponent(), 0, 96); wl.setTimeCreated((int)dr.GetDecimal(7)); } dr.Close(); // If doesnt exist... should not do more things if (!wl.getExistance()) { String msg = "Player not found on DB with #" + wl.getUsername() + "# and #" + wl.getPassword() + "#"; Output.WriteLine(msg); conn.Close(); return(false); } // If exist, get the player values // Count the values first int totalChars = 0; string sqlCount = "SELECT charId FROM characters WHERE userId='" + wl.getUserID() + "' AND is_deleted='0' "; queryExecuter = conn.CreateCommand(); queryExecuter.CommandText = sqlCount; dr = queryExecuter.ExecuteReader(); while (dr.Read()) { totalChars++; } dr.Close(); wl.getCharPack().setTotalChars(totalChars); // Prepare to read characters string sqlQueryForChars = "SELECT * FROM characters WHERE userId='" + wl.getUserID() + "' AND is_deleted='0' "; queryExecuter = conn.CreateCommand(); queryExecuter.CommandText = sqlQueryForChars; dr = queryExecuter.ExecuteReader(); // Read characters while (dr.Read()) { //totalChars = (int) dr.GetDecimal(8); string charName = dr.GetString(4); int charId = (int)dr.GetDecimal(0); int status = (int)dr.GetDecimal(3); int worldId = (int)dr.GetDecimal(2); wl.getCharPack().addCharacter(charName, charId, status, worldId); } dr.Close(); // Read worlds string sqlQueryForWorlds = "SELECT * FROM worlds ORDER BY worldId ASC"; queryExecuter.CommandText = sqlQueryForWorlds; dr = queryExecuter.ExecuteReader(); while (dr.Read()) { string worldName = dr.GetString(1); int worldId = (int)dr.GetDecimal(0); int worldType = (int)dr.GetDecimal(2); int worldStatus = (int)dr.GetDecimal(3); int worldPopulation = (int)dr.GetDecimal(4); wl.getWorldPack().addWorld(worldName, worldId, worldStatus, worldType, worldPopulation); } dr.Close(); conn.Close(); return(true); }