Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.runescape.networking.codec.login;
- import java.math.BigInteger;
- import org.jboss.netty.buffer.ChannelBuffer;
- import org.jboss.netty.buffer.ChannelBuffers;
- import org.jboss.netty.channel.Channel;
- import org.jboss.netty.channel.ChannelHandlerContext;
- import org.jboss.netty.handler.codec.frame.FrameDecoder;
- import com.runescape.game.model.player.Player;
- import com.runescape.networking.codec.login.RS2LoginDecoder.Stage;
- import com.runescape.utility.BufferUtility;
- import com.runescape.utility.Misc;
- import com.runescape.utility.game.FileLoader;
- import com.runescape.utility.game.LoginResponse;
- import com.runescape.utility.game.LoginResponse.Response;
- import com.runescape.utility.game.XTEA;
- /**
- * An {@link FrameDecoder} implementation used to decode the world login
- * procedure.
- *
- * @author Tyluur
- *
- */
- public class RS2LoginDecoder extends StagedFrameDecoder<Stage> {
- /**
- * The Standard login type.
- */
- public static final int LOGIN_TYPE = 16;
- /**
- * The Reconnection login type.
- */
- public static final int RECONNECTION_TYPE = 18;
- /**
- * The lobby login type.
- */
- public static final int LOBBY_TYPE = 19;
- /**
- * The remaining bytes left in the login block.
- */
- private int loginSize;
- /**
- * The login type
- */
- private int loginType;
- /**
- * The rsa exponent.
- */
- public static final BigInteger EXPONENT = new BigInteger("90587072701551327129007891668787349509347630408215045082807628285770049664232156776755654198505412956586289981306433146503308411067358680117206732091608088418458220580479081111360656446804397560752455367862620370537461050334224448167071367743407184852057833323917170323302797356352672118595769338616589092625");
- /**
- * The rsa modulus.
- */
- public static final BigInteger MODULUS = new BigInteger("102876637271116124732338500663639643113504464789339249490399312659674772039314875904176809267475033772367707882873773291786014475222178654932442254125731622781524413208523465520758537060408541610254619166907142593731337618490879831401461945679478046811438574041131738117063340726565226753787565780501845348613");
- /**
- * The different stages of login.
- *
- * @author Thomas Le Godais
- *
- */
- public enum Stage {
- CONNECTION_TYPE,
- CLIENT_DETAILS,
- WORLD_PAYLOAD;
- }
- /**
- * Constrcuts a new WorldLoginDecoder.
- */
- public RS2LoginDecoder() {
- super(Stage.CONNECTION_TYPE);
- }
- @Override
- protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
- switch(stage) {
- case CONNECTION_TYPE:
- return decodeConnectionType(channel, buffer);
- case CLIENT_DETAILS:
- return decodeClientDetails(channel, buffer);
- case WORLD_PAYLOAD:
- return decodeWorldPayload(channel, buffer);
- }
- return null;
- }
- /**
- * Decodes the connection type.
- *
- * @param channel The channel.
- * @param buffer The buffer.
- * @return The object.
- */
- private Object decodeConnectionType(Channel channel, ChannelBuffer buffer) {
- if(buffer.readable()) {
- loginType = buffer.readUnsignedByte();
- if(loginType != LOGIN_TYPE && loginType != RECONNECTION_TYPE) {
- sendResponse(channel, 13);
- }
- loginSize = buffer.readUnsignedShort();
- setStage(Stage.CLIENT_DETAILS);
- }
- return null;
- }
- /**
- * Decodes the client details.
- *
- * @param channel The channel.
- * @param buffer The buffer.
- * @return The object.
- */
- private Object decodeClientDetails(Channel channel, ChannelBuffer buffer) {
- if(buffer.readableBytes() >= loginSize) {
- int version = buffer.readInt();
- buffer.readInt();
- if(version != 718) {
- sendResponse(channel, 6);
- }
- if(loginType != LOBBY_TYPE) {
- setStage(Stage.WORLD_PAYLOAD);
- }
- }
- return null;
- }
- /**
- * Decodes the world login payload.
- *
- * @param channel The channel.
- * @param buffer The buffer.
- * @return The object.
- */
- @SuppressWarnings("unused")
- private Object decodeWorldPayload(Channel channel, ChannelBuffer buffer) {
- buffer.readUnsignedByte();
- int blockSize = buffer.readShort() & 0xFFFF;
- if(!(blockSize > buffer.readableBytes())) {
- byte[] rsaData = new byte[blockSize];
- buffer.readBytes(rsaData, 0, blockSize);
- ChannelBuffer rsaPayload = ChannelBuffers.wrappedBuffer(new BigInteger(rsaData).modPow(EXPONENT, MODULUS).toByteArray());
- int rsaBlock = rsaPayload.readByte() & 0xFF;
- if(rsaBlock != 10) {
- sendResponse(channel, 10);
- return null;
- }
- int[] isaacKeys = new int[4];
- for(int i = 0; i < isaacKeys.length; i++) {
- isaacKeys[i] = rsaPayload.readInt();
- }
- long rsaPass = rsaPayload.readLong();
- if(rsaPass != 0L) {
- sendResponse(channel, 10);
- return null;
- }
- String password = BufferUtility.readString(rsaPayload);
- if(password.length() > 30 || password.length() < 3) {
- sendResponse(channel, Response.WEAK_PASSWORD.getOpcode());
- return null;
- }
- String unknown = Misc.longToString(rsaPayload.readLong());
- byte[] block = new byte[buffer.readableBytes()];
- buffer.readBytes(block);
- ChannelBuffer xteaBuffer = ChannelBuffers.wrappedBuffer(XTEA.decipher(isaacKeys, block));
- boolean decodeAsString = (xteaBuffer.readByte() & 0xff) == 1;
- String username = Misc.formatPlayerNameForProtocol(decodeAsString ? BufferUtility.readString(xteaBuffer) : Misc.longToString(xteaBuffer.readLong()));
- int displayMode = xteaBuffer.readByte() & 0xff;
- xteaBuffer.readUnsignedShort();
- xteaBuffer.readUnsignedShort();
- xteaBuffer.readUnsignedByte();
- xteaBuffer.skipBytes(24);
- String clientSettings = BufferUtility.readString(xteaBuffer);
- xteaBuffer.readInt();
- int skipLen = xteaBuffer.readByte() & 0xff;
- xteaBuffer.skipBytes(skipLen);
- xteaBuffer.readInt();
- xteaBuffer.readLong();
- boolean additInfo = (xteaBuffer.readByte() & 0xFF) == 1;
- if(additInfo) {
- BufferUtility.readString(xteaBuffer);
- }
- for(int i = 0; i < 3; i++) {
- xteaBuffer.readUnsignedByte();
- }
- xteaBuffer.readByte();
- xteaBuffer.readInt();
- String unknownString = BufferUtility.readString(xteaBuffer);
- xteaBuffer.readUnsignedByte();
- System.out.println("Login Request [username=" + username + " password=" + password + " displayMode=" + displayMode + "]");
- Player player;
- if (!FileLoader.containsPlayer(username)) {
- player = new Player();
- } else {
- player = FileLoader.loadPlayer(username);
- if (!player.getFeatures().getPassword().equals(password)) {
- sendResponse(channel, Response.INVALID_CREDENTIALS.getOpcode());
- return null;
- }
- }
- player.init(channel, username, password);
- player.start();
- } else {
- channel.close();
- }
- return null;
- }
- /**
- * Sends a response.
- *
- * @param channel The channel to write the response.
- * @param rOpcode The response opcode.
- */
- private void sendResponse(Channel channel, int rOpcode) {
- channel.write(new LoginResponse(Response.forId(rOpcode)));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement