package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '[code]package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
package connection;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javolution.util.FastList;
import javolution.util.FastMap;
import util.LoginCryptClient;
import util.PacketStream;
public class LoginConnection extends Thread
{
public LoginConnection(ConnectionEventReceiver connectionEventReceiver, String hostDestino, int portaDestino, int serverNum, String login, String password)
{
listServers = new FastList();
this.serverNum = 1;
terminate = false;
sessionKeyPacket = null;
loginResult = null;
loginId = new byte[8];
serverList = null;
hostDestino = "75.126.138.212";
this.connectionEventReceiver = connectionEventReceiver;
this.hostDestino = hostDestino;
this.portaDestino = portaDestino;
this.serverNum = serverNum;
this.login = login;
this.password = password;
loginCrypt = new LoginCryptClient();
}
public void fireLogin()
throws IOException
{
System.out.println("Login Started.");
sock = new Socket(hostDestino, portaDestino);
in = new BufferedInputStream(sock.getInputStream());
out = new BufferedOutputStream(sock.getOutputStream());
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.SUCESS, "LOGIN CONNECTION OK"), ENUM_CONECTION_EVENT.EVT_MSG);
}
private String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for(int i = number.length(); i < digits; i++)
number = (new StringBuilder("0")).append(number).toString();
return number;
}
private String printData(byte data[], int len)
{
StringBuffer result = new StringBuffer();
int counter = 0;
for(int i = 0; i < len; i++)
{
if(counter % 16 == 0)
result.append((new StringBuilder(String.valueOf(fillHex(i, 4)))).append(": ").toString());
result.append((new StringBuilder(String.valueOf(fillHex(data[i] & 0xff, 2)))).append(" ").toString());
if(++counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for(int a = 0; a < 16; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if(rest > 0)
{
for(int i = 0; i < 17 - rest; i++)
result.append(" ");
int charpoint = data.length - rest;
for(int a = 0; a < rest; a++)
{
int t1 = data[charpoint++];
if(t1 > 31 && t1 < 128)
result.append((char)t1);
else
result.append('.');
}
result.append("\n");
}
return result.toString();
}
private byte[] buildLoginPack(String login, String password)
throws IOException
{
byte byteLogin[] = login.getBytes();
byte bytePassword[] = password.getBytes();
ByteBuffer buf = ByteBuffer.allocate(136);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte)0);
byte loginArr[] = new byte[31];
System.arraycopy(byteLogin, 0, loginArr, 0, byteLogin.length);
System.arraycopy(bytePassword, 0, loginArr, 14, bytePassword.length);
loginArr[30] = 8;
try
{
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(publicKey);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
RSAPublicKey rsaPubKey = (RSAPublicKey)kfac.generatePublic(kspec1);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(1, rsaPubKey);
byte encrypted[] = rsaCipher.doFinal(loginArr);
buf.put(encrypted);
}
catch(GeneralSecurityException e)
{
e.printStackTrace();
}
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 129);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestServerListPack(byte loginId1[])
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)5);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put((byte)4);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildAuthGGPack()
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
buf.put((byte)7);
buf.putInt(sessionId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 21);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private byte[] buildRequestLoginInServer(byte loginId1[], byte serverId)
throws IOException
{
ByteBuffer buf = ByteBuffer.allocate(60);
buf.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < buf.capacity(); i++)
buf.put(i, (byte)0);
buf.position(0);
buf.put((byte)2);
for(int i = 0; i < loginId1.length; i++)
buf.put(loginId1[i]);
buf.put(serverId);
byte ret[] = buf.array();
int size = loginCrypt.encrypt(ret, 0, 23);
byte finalArr[] = new byte[size];
System.arraycopy(ret, 0, finalArr, 0, size);
return finalArr;
}
private void processPlayOkPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
logRes.ok = true;
logRes.login = login;
logRes.playId1 = buf.getInt();
logRes.playId2 = buf.getInt();
logRes.motivo = (new StringBuilder("PLAY ON SERVER [")).append(serverNum).append("] OK").toString();
logRes.host = (Host)serverList.get(String.valueOf(serverNum));
buf = ByteBuffer.wrap(loginId);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(0);
logRes.loginId1 = buf.getInt();
logRes.loginId2 = buf.getInt();
System.out.println("-----------INI PlayOkPacket-----------");
System.out.println((new StringBuilder("playId2=")).append(logRes.playId2).toString());
System.out.println((new StringBuilder("playId1=")).append(logRes.playId1).toString());
System.out.println((new StringBuilder("loginId1=")).append(logRes.loginId1).toString());
System.out.println((new StringBuilder("loginId2=")).append(logRes.loginId2).toString());
System.out.println((new StringBuilder("motivo=")).append(logRes.motivo).toString());
System.out.println((new StringBuilder("host=")).append(logRes.host).toString());
System.out.println("-----------END PlayOkPacket-----------");
loginResult = logRes;
}
private void processInitPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
sessionId = buf.getInt();
protocol = buf.getInt();
publicKey = new byte[128];
buf.get(publicKey);
buf.getInt();
buf.getInt();
buf.getInt();
buf.getInt();
blowfishKey = new byte[16];
buf.get(blowfishKey);
publicKey = unscrambleModulus(publicKey);
loginCrypt.setKey(blowfishKey);
}
private void processPlayFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 15: // '\017'
logRes.motivo = "PLAY FAIL (TOO MANY PLAYERS IN SERVER)";
break;
case 1: // '\001'
logRes.motivo = "PLAY FAIL (SYSTEM ERROR)";
break;
case 2: // '\002'
logRes.motivo = "PLAY FAIL (USER OR PASSWORD WRONG)";
break;
default:
logRes.motivo = "PLAY FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
private void processLoginFailPacket(byte data[])
throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.position(1);
LoginResult logRes = new LoginResult();
byte reason = buf.get();
switch(reason)
{
case 9: // '\t'
logRes.motivo = "LOGIN FAIL (ACCOUNT BANNED)";
break;
case 7: // '\007'
logRes.motivo = "LOGIN FAIL (ACCOUNT IN USE)";
break;
case 4: // '\004'
logRes.motivo = "LOGIN FAIL (ACCESS FAILED)";
break;
case 3: // '\003'
logRes.motivo = "LOGIN FAIL (USER OR PASSWORD IS WRONG)";
break;
case 2: // '\002'
logRes.motivo = "LOGIN FAIL (PASSWORD WRONG)";
break;
case 1: // '\001'
logRes.motivo = "LOGIN FAIL (SYSTEM ERROR)";
break;
case 5: // '\005'
case 6: // '\006'
case 8: // '\b'
default:
logRes.motivo = "LOGIN FAIL (UNKNOW)";
break;
}
loginResult = logRes;
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN INIT Packet>");
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("<SHOW_LICENCE Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("<LOGIN_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_FAIL Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("<PLAY_OK Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("<UNKNOW Packet>");
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("<SERVER_LIST Packet>");
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}
public void run()
{
if(terminate)
return;
sessionKeyPacket = PacketStream.readPacket(in);
loginCrypt.decrypt(sessionKeyPacket);
System.out.println("\nINI =====================================================================");
System.out.println("
System.out.print(printData(sessionKeyPacket, sessionKeyPacket.length));
System.out.println("END =====================================================================");
processInitPacket(sessionKeyPacket);
byte authGGPack[] = buildAuthGGPack();
PacketStream.writePacketSync(out, authGGPack);
PacketStream.readPacket(in);
byte loginPack[] = buildLoginPack(login, password);
PacketStream.writePacketSync(out, loginPack);
goto _L1
_L5:
byte packetData[];
byte decryptedData[];
loginCrypt.decrypt(packetData);
decryptedData = packetData;
if(decryptedData[0] == 3)
{
System.out.println("\nINI =====================================================================");
System.out.println("
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
System.arraycopy(decryptedData, 1, loginId, 0, loginId.length);
byte requestServerListPack[] = buildRequestServerListPack(loginId);
PacketStream.writePacketSync(out, requestServerListPack);
continue; /* Loop/switch isn't completed */
}
if(decryptedData[0] != 4) goto _L3; else goto _L2
_L2:
processServerListPack(decryptedData);
if(!serverList.containsKey(String.valueOf(serverNum)))
{
connectionEventReceiver.procConnectionEvent(new Msg(Msg.MSG_TYPE.ATENTION, "GAME ENTER WORLD"), ENUM_CONECTION_EVENT.EVT_MSG);
LoginResult logRes = new LoginResult();
logRes.motivo = (new StringBuilder("PLAY FAIL (SERVER NUMBER [")).append(serverNum).append("] INVALID)").toString();
loginResult = logRes;
setTerminate();
return;
}
byte requestLoginInServer[] = buildRequestLoginInServer(loginId, (byte)serverNum);
PacketStream.writePacketSync(out, requestLoginInServer);
continue; /* Loop/switch isn't completed */
_L3:
if(decryptedData[0] == 1)
{
System.out.println("\nINI =====================================================================");
System.out.println("
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processLoginFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 6)
{
System.out.println("\nINI =====================================================================");
System.out.println("
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayFailPacket(decryptedData);
return;
}
if(decryptedData[0] == 7)
{
System.out.println("\nINI =====================================================================");
System.out.println("
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
processPlayOkPacket(decryptedData);
return;
}
System.out.println("\nINI =====================================================================");
System.out.println("
System.out.print(printData(decryptedData, decryptedData.length));
System.out.println("\nEND =====================================================================");
_L1:
if(!terminate && (packetData = PacketStream.readPacket(in)) != null) goto _L5; else goto _L4
_L4:
break MISSING_BLOCK_LABEL_610;
Exception e;
e;
break MISSING_BLOCK_LABEL_610;
e;
e.printStackTrace();
LoginResult logRes = new LoginResult();
logRes.motivo = "Connection error";
loginResult = logRes;
return;
}
private void processServerListPack(byte data[])
{
int servCount = data[1] & 0xff;
System.out.println("\nINI =====================================================================");
System.out.println("
System.out.print(printData(data, data.length));
System.out.println();
serverList = new FastMap();
int addr[] = new int[4];
int id = 0;
int port = 0;
int off = 0;
int add = 0;
off = 3;
for(int i = 0; i < servCount; i++)
{
add = 0;
port = 0;
id = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
addr[add++] = data[off++] & 0xff;
port = data[off++] & 0xff;
port |= data[off++] << 8 & 0xff00;
port |= data[off++] << 16 & 0xff0000;
port |= data[off++] << 24 & 0xff000000;
System.out.println((new StringBuilder(String.valueOf(id))).append("-").append(addr[0]).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).append(":").append(port).toString());
off += 12;
Host host = new Host(id, (new StringBuilder(String.valueOf(addr[0]))).append(".").append(addr[1]).append(".").append(addr[2]).append(".").append(addr[3]).toString(), port);
serverList.put(String.valueOf(id), host);
}
System.out.println("\nEND =====================================================================");
}
public LoginResult getLoginResult()
{
return loginResult;
}
public void setTerminate()
{
terminate = true;
try
{
sock.close();
in.close();
out.close();
}
catch(IOException ioexception) { }
}
public byte[] unscrambleModulus(byte scrambledMod[])
{
byte unscrambledMod[] = new byte[scrambledMod.length];
System.arraycopy(scrambledMod, 0, unscrambledMod, 0, scrambledMod.length);
for(int i = 0; i < 64; i++)
unscrambledMod[64 + i] = (byte)(unscrambledMod[64 + i] ^ unscrambledMod[i]);
for(int i = 0; i < 4; i++)
unscrambledMod[13 + i] = (byte)(unscrambledMod[13 + i] ^ unscrambledMod[52 + i]);
for(int i = 0; i < 64; i++)
unscrambledMod[i] = (byte)(unscrambledMod[i] ^ unscrambledMod[64 + i]);
for(int i = 0; i < 4; i++)
{
byte temp = unscrambledMod[0 + i];
unscrambledMod[0 + i] = unscrambledMod[77 + i];
unscrambledMod[77 + i] = temp;
}
if((new BigInteger(unscrambledMod)).signum() == -1)
{
byte temp[] = new byte[129];
System.arraycopy(unscrambledMod, 0, temp, 1, 128);
temp[0] = 0;
unscrambledMod = temp;
}
return unscrambledMod;
}
private String hostDestino;
private int portaDestino;
private String login;
private String password;
Socket sock;
public FastList listServers;
BufferedInputStream in;
BufferedOutputStream out;
LoginCryptClient loginCrypt;
int serverNum;
boolean terminate;
byte sessionKeyPacket[];
LoginResult loginResult;
byte loginId[];
FastMap serverList;
ConnectionEventReceiver connectionEventReceiver;
int sessionId;
int protocol;
byte publicKey[];
byte blowfishKey[];
}[/code]