Client:
Code:
public void login(String s, String s1, boolean flag) {
signlink.errorname = s;
try {
if (!flag) {
loginMessage1 = "";
loginMessage2 = "Connecting to server...";
myUsername = capitalize(myUsername);
drawLoginScreen(true);
}
socketStream = new RSSocket(this, openSocket(43594 + portOff));
long l = TextClass.longForName(s);
int i = (int) (l >> 16 & 31L);
stream.currentOffset = 0;
stream.writeWordBigEndian(14);
stream.writeWordBigEndian(i);
socketStream.queueBytes(2, stream.buffer);
for (int j = 0; j < 8; j++)
socketStream.read();
int k = socketStream.read();
int i1 = k;
System.out.println(k);
if (k == 0) {
socketStream.flushInputStream(inStream.buffer, 8);
inStream.currentOffset = 0;
aLong1215 = inStream.readQWord();
int ai[] = new int[4];
ai[0] = (int) (Math.random() * 99999999D);
ai[1] = (int) (Math.random() * 99999999D);
ai[2] = (int) (aLong1215 >> 32);
ai[3] = (int) aLong1215;
stream.currentOffset = 0;
stream.writeWordBigEndian(10);
stream.writeDWord(ai[0]);
stream.writeDWord(ai[1]);
stream.writeDWord(ai[2]);
stream.writeDWord(ai[3]);
stream.writeDWord(signlink.uid);
stream.writeString(s);
stream.writeString(s1);
stream.doKeys();
aStream_847.currentOffset = 0;
if (flag)
aStream_847.writeWordBigEndian(18);
else
aStream_847.writeWordBigEndian(16);
aStream_847.writeWordBigEndian(stream.currentOffset + 36 + 1 + 1 + 2);
aStream_847.writeWordBigEndian(255);
aStream_847.writeWord(317);
aStream_847.writeWordBigEndian(lowMemory ? 1 : 0);
for (int l1 = 0; l1 < 9; l1++)
aStream_847.writeDWord(expectedCRCs[l1]);
aStream_847.writeBytes(stream.buffer, stream.currentOffset, 0);
stream.encryption = new ISAACRandomGen(ai);
for (int j2 = 0; j2 < 4; j2++)
ai[j2] += 50;
encryption = new ISAACRandomGen(ai);
socketStream.queueBytes(aStream_847.currentOffset, aStream_847.buffer);
k = socketStream.read();
}
if (k == 1) {
try {
Thread.sleep(2000L);
} catch (Exception _ex) {
}
login(s, s1, flag);
return;
}
if (k == 2) {
myPrivilege = socketStream.read();
if (music_enabled) {
SoundProvider.getInstance().stopMidi();
try {
Thread.sleep(700);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
aLong1220 = 0L;
super.awtFocus = true;
aBoolean954 = true;
loggedIn = true;
drawStuff = false;
setScrollPosition();
atLoginMenu = false;
stream.currentOffset = 0;
inStream.currentOffset = 0;
opCode = -1;
anInt841 = -1;
anInt842 = -1;
anInt843 = -1;
pktSize = 0;
timeoutCounter = 0;
systemUpdateTime = 0;
anInt1011 = 0;
hintType = 0;
menuActionRow = 0;
menuOpen = false;
super.idleTime = 0;
for (int j1 = 0; j1 < 100; j1++)
chatMessages[j1] = null;
itemSelected = 0;
spellSelected = 0;
loadingStage = 0;
currentSound = 0;
setNorth();
hideMinimap = 0;
anInt985 = -1;
destX = 0;
destY = 0;
playerCount = 0;
npcCount = 0;
for (int i2 = 0; i2 < maxPlayers; i2++) {
playerArray[i2] = null;
aStreamArray895s[i2] = null;
}
for (int k2 = 0; k2 < 16384; k2++)
npcArray[k2] = null;
myPlayer = playerArray[myPlayerIndex] = new Player();
aClass19_1013.removeAll();
aClass19_1056.removeAll();
for (int l2 = 0; l2 < 4; l2++) {
for (int i3 = 0; i3 < 104; i3++) {
for (int k3 = 0; k3 < 104; k3++)
groundArray[l2][i3][k3] = null;
}
}
aClass19_1179 = new NodeList();
fullscreenInterfaceID = -1;
anInt900 = 0;
friendsCount = 0;
dialogID = -1;
backDialogID = -1;
openInterfaceID = -1;
invOverlayInterfaceID = -1;
walkableInterface = -1;
aBoolean1149 = false;
tabID = 3;
inputDialogState = 0;
menuOpen = false;
messagePromptRaised = false;
aString844 = null;
drawMultiIcon = 0;
anInt1054 = -1;
aBoolean1047 = true;
method45();
for (int j3 = 0; j3 < 5; j3++)
anIntArray990[j3] = 0;
for (int l3 = 0; l3 < 5; l3++) {
atPlayerActions[l3] = null;
atPlayerArray[l3] = false;
}
resetImageProducers2();
return;
}
if (k == 3) {
loginMessage1 = "";
loginMessage2 = "Invalid username or password.";
return;
}
if (k == 4) {
loginMessage1 = "Your account has been disabled.";
loginMessage2 = "Please check your message-center for details.";
return;
}
if (k == 5) {
loginMessage1 = "Your account is already logged in.";
loginMessage2 = "Try again in 60 secs...";
return;
}
if (k == 6) {
loginMessage1 = "RuneScape has been updated!";
loginMessage2 = "Please reload this page.";
return;
}
if (k == 7) {
loginMessage1 = "This world is full.";
loginMessage2 = "Please use a different world.";
return;
}
if (k == 8) {
loginMessage1 = "Unable to connect.";
loginMessage2 = "Login server offline.";
return;
}
if (k == 9) {
loginMessage1 = "Login limit exceeded.";
loginMessage2 = "Too many connections from your address.";
return;
}
if (k == 10) {
loginMessage1 = "Unable to connect.";
loginMessage2 = "Bad session id.";
return;
}
if (k == 11) {
loginMessage2 = "Login server rejected session.";
loginMessage2 = "Please try again.";
return;
}
if (k == 12) {
loginMessage1 = "You need a members account to login to this world.";
loginMessage2 = "Please subscribe, or use a different world.";
return;
}
if (k == 13) {
loginMessage1 = "Could not complete login.";
loginMessage2 = "Please try using a different world.";
return;
}
if (k == 14) {
loginMessage1 = "The server is being updated.";
loginMessage2 = "Please wait 1 minute and try again.";
return;
}
if (k == 15) {
loggedIn = true;
stream.currentOffset = 0;
inStream.currentOffset = 0;
opCode = -1;
anInt841 = -1;
anInt842 = -1;
anInt843 = -1;
pktSize = 0;
timeoutCounter = 0;
systemUpdateTime = 0;
menuActionRow = 0;
menuOpen = false;
aLong824 = System.currentTimeMillis();
return;
}
if (k == 16) {
loginMessage1 = "Login attempts exceeded.";
loginMessage2 = "Please wait 5 minutes and try again.";
return;
}
if (k == 17) {
loginMessage1 = "You are standing in a members-only area.";
loginMessage2 = "To play on this world move to a free area first";
return;
}
if (k == 20) {
loginMessage1 = "Invalid loginserver requested";
loginMessage2 = "Please try using a different world.";
return;
}
if (k == 21) {
for (int k1 = socketStream.read(); k1 >= 0; k1--) {
loginMessage1 = "You have only just left another world";
loginMessage2 = "Your profile will be transferred in: " + k1 + " seconds";
drawLoginScreen(true);
try {
Thread.sleep(1000L);
} catch (Exception _ex) {
}
}
login(s, s1, flag);
return;
}
if (k == -1) {
if (i1 == 0) {
if (loginFailures < 2) {
try {
Thread.sleep(2000L);
} catch (Exception _ex) {
}
loginFailures++;
login(s, s1, flag);
return;
} else {
loginMessage1 = "No response from loginserver";
loginMessage2 = "Please wait 1 minute and try again.";
return;
}
} else {
loginMessage1 = "No response from server";
loginMessage2 = "Please try using a different world.";
return;
}
} else {
loginMessage1 = "Unexpected server response";
loginMessage2 = "Please try using a different world.";
return;
}
} catch (IOException _ex) {
loginMessage1 = "";
}
loginMessage2 = "Error connecting to server.";
}
Server:
ActionSender
Code:
public ActionSender sendLogin() {
player.setActive(true);
sendPrivateMessageConfig(World.getWorld().getLoginServerConnector() == null && Constants.CONNNECT_TO_LOGIN_SERVER ? 0 : 2);
sendDetails();
sendMapRegion();
System.out.println("Logged in");
if(player.getFightStyle() == -1)
player.setFightStyle((byte) 0);
sendMessage("Welcome to "+Constants.SERVER_NAME+", Owner is "+Constants.OWNER+".");
player.setRights(Rights.PLAYER);;
Prayer.resetPrayers(player, true);
sendSidebarInterfaces();
sendEnergy(player.getWalkingQueue().getRunEnergy());
sendWeight(player.getEquipment().getWeight() + (player.getInventory().getWeight() < 0 ? 0 : player.getInventory().getWeight()));
if(Constants.PVP_WORLD)
sendPlayerOption("Attack",1,1);
else
sendPlayerOption("null",1,0);
//sendPlayerOption("Challenge",2,0);
sendSkills();
sendPlayerOption("Trade With",4,0);
sendPlayerOption("Follow",3,0);
InterfaceContainerListener inventoryListener = new InterfaceContainerListener(player, Inventory.INTERFACE);
player.getInventory().addListener(inventoryListener);
InterfaceContainerListener equipmentListener = new InterfaceContainerListener(player, Equipment.INTERFACE);
player.getEquipment().addListener(equipmentListener);
player.getEquipment().addListener(new EquipmentContainerListener(player));
player.getEquipment().addListener(new WeaponContainerListener(player));
sendConfig(107, player.getFightStyle());
return this;
}
RS2LoginDecoder
Code:
@Override
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
int state = (Integer) session.getAttribute("state", STATE_OPCODE);
switch(state) {
case STATE_OPCODE:
if(in.remaining() >= 1) {
/*
* Here we read the first opcode which indicates the type
* of connection.
*
* 14 = game
* 15 = update
*
* Updating is disabled in the vast majority of 317
* clients.
*/
int opcode = in.get() & 0xFF;
switch(opcode) {
case OPCODE_GAME:
session.setAttribute("state", STATE_LOGIN);
return true;
case OPCODE_UPDATE:
session.setAttribute("state", STATE_UPDATE);
session.write(new PacketBuilder().put(INITIAL_RESPONSE).toPacket());
return true;
default:
logger.info("Invalid opcode : " + opcode);
session.close(false);
break;
}
} else {
in.rewind();
return false;
}
break;
case STATE_LOGIN:
if(in.remaining() >= 1) {
/*
* The name hash is a simple hash of the name which is
* suspected to be used to select the appropriate login
* server.
*/
@SuppressWarnings("unused")
int nameHash = in.get() & 0xFF;
/*
* We generated the server session key using a SecureRandom
* class for security.
*/
long serverKey = RANDOM.nextLong();
/*
* The initial response is just 0s which the client is set
* to ignore (probably some sort of modification).
*/
session.write(new PacketBuilder().put(INITIAL_RESPONSE).put((byte) 0).putLong(serverKey).toPacket());
session.setAttribute("state", STATE_PRECRYPTED);
session.setAttribute("serverKey", serverKey);
return true;
}
break;
case STATE_PRECRYPTED:
if(in.remaining() >= 2) {
/*
* We read the type of login.
*
* 16 = normal
* 18 = reconnection
*/
int loginOpcode = in.get() & 0xFF;
if(loginOpcode != 16 && loginOpcode != 18) {
logger.info("Invalid login opcode : " + loginOpcode);
session.close(false);
in.rewind();
return false;
}
/*
* We read the size of the login packet.
*/
int loginSize = in.get() & 0xFF;
/*
* And calculated how long the encrypted block will be.
*/
int loginEncryptSize = loginSize - (36 + 1 + 1 + 2);
/*
* This could be invalid so if it is we ignore it.
*/
if(loginEncryptSize <= 0) {
logger.info("Encrypted packet size zero or negative : " + loginEncryptSize);
session.close(false);
in.rewind();
return false;
}
session.setAttribute("state", STATE_CRYPTED);
session.setAttribute("size", loginSize);
session.setAttribute("encryptSize", loginEncryptSize);
return true;
}
break;
case STATE_CRYPTED:
int size = (Integer) session.getAttribute("size");
int encryptSize = (Integer) session.getAttribute("encryptSize");
if(in.remaining() >= size) {
/*
* We read the magic ID which is 255 (0xFF) which indicates
* this is the real login packet.
*/
int magicId = in.get() & 0xFF;
if(magicId != 255) {
logger.info("Incorrect magic id : " + magicId);
session.close(false);
in.rewind();
return false;
}
/*
* We now read a short which is the client version and
* check if it equals 317.
*/
int version = in.getShort() & 0xFFFF;
if(version != Server.VERSION) {
logger.info("Incorrect version : " + version);
session.close(false);
in.rewind();
return false;
}
/*
* The following byte indicates if we are using a low
* memory version.
*/
@SuppressWarnings("unused")
boolean lowMemoryVersion = (in.get() & 0xFF) == 1;
/*
* We know read the cache indices.
*/
for(int i = 0; i < 9; i++) {
in.getInt();
}
/*
* The encrypted size includes the size byte which we don't
* need.
*/
encryptSize--;
/*
* We check if there is a mismatch in the sizing.
*/
int reportedSize = in.get() & 0xFF;
if(reportedSize != encryptSize) {
logger.info("Packet size mismatch (expected : " + encryptSize + ", reported : " + reportedSize + ")");
session.close(false);
in.rewind();
return false;
}
byte[] encryptionBytes = new byte[encryptSize];
in.get(encryptionBytes);
IoBuffer rsaBuffer = IoBuffer.wrap(new BigInteger(encryptionBytes)
.modPow(RSA_EXPONENT, RSA_MODULUS).toByteArray());
/*
* We now read the encrypted block opcode (although in most
* 317 clients and this server the RSA is disabled) and
* check it is equal to 10.
*/
int blockOpcode = rsaBuffer.get() & 0xFF;
if(blockOpcode != 10) {
logger.info("Invalid login block opcode : " + blockOpcode);
session.close(false);
in.rewind();
return false;
}
/*
* We read the client's session key.
*/
long clientKey = rsaBuffer.getLong();
/*
* And verify it has the correct server session key.
*/
long serverKey = (Long) session.getAttribute("serverKey");
long reportedServerKey = rsaBuffer.getLong();
if(reportedServerKey != serverKey) {
logger.info("Server key mismatch (expected : " + serverKey + ", reported : " + reportedServerKey + ")");
session.close(false);
in.rewind();
return false;
}
/*
* The UID, found in random.dat in newer clients and
* uid.dat in older clients is a way of identifying a
* computer.
*
* However, some clients send a hardcoded or random UID,
* making it useless in the private server scene.
*/
int uid = rsaBuffer.getInt();
/*
* We read and format the name and passwords.
*/
String name = NameUtils.formatName(IoBufferUtils.getRS2String(rsaBuffer).trim());
String pass = IoBufferUtils.getRS2String(rsaBuffer);
logger.info("Login request : username=" + name + " password=" + pass);
/*
* And setup the ISAAC cipher which is used to encrypt and
* decrypt opcodes.
*
* However, without RSA, this is rendered useless anyway.
*/
int[] sessionKey = new int[4];
sessionKey[0] = (int) (clientKey >> 32);
sessionKey[1] = (int) clientKey;
sessionKey[2] = (int) (serverKey >> 32);
sessionKey[3] = (int) serverKey;
session.removeAttribute("state");
session.removeAttribute("serverKey");
session.removeAttribute("size");
session.removeAttribute("encryptSize");
ISAACCipher inCipher = new ISAACCipher(sessionKey);
for(int i = 0; i < 4; i++) {
sessionKey[i] += 50;
}
ISAACCipher outCipher = new ISAACCipher(sessionKey);
/*
* Now, the login has completed, and we do the appropriate
* things to fire off the chain of events which will load
* and check the saved games etc.
*/
session.getFilterChain().remove("protocol");
session.getFilterChain().addFirst("protocol", new ProtocolCodecFilter(RS2CodecFactory.GAME));
PlayerDetails pd = new PlayerDetails(session, name, pass, uid, inCipher, outCipher);
World.getWorld().load(pd);
}
break;
}
in.rewind();
return false;
}
Those?