Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package org.kainos.rs2.network.gameserver.codec.protocol.login;
- import java.math.BigInteger;
- import java.util.List;
- import org.kainos.rs2.game.world.visual.Display;
- import org.kainos.rs2.network.gameserver.codec.protocol.Protocol;
- import org.kainos.rs2.network.gameserver.codec.protocol.login.message.LoginRequestMessage;
- import org.kainos.utilities.Utilities;
- import org.kainos.utilities.base37.Base37Utils;
- import org.kainos.utilities.buffer.BufferUtilities;
- import org.kainos.utilities.crypto.BCrypt;
- import org.kainos.utilities.crypto.XTEA;
- import org.kainos.utilities.isaac.IsaacRandom;
- import io.netty.buffer.ByteBuf;
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.handler.codec.ByteToMessageDecoder;
- /**
- * The class that contains the decoding of the entire Login process.
- *
- * @author Waterfiend
- * @date August 11 2015
- */
- public class LoginDecoder extends ByteToMessageDecoder {
- /**
- * The attempted {@link LoginType}.
- */
- private LoginType loginType;
- /**
- * The {@link Display} used during login.
- */
- private Display display;
- /*
- * (non-Javadoc)
- *
- * @see io.netty.handler.codec.ByteToMessageDecoder#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf,
- * java.util.List)
- */
- @Override
- protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
- if (!in.isReadable()) {
- return;
- }
- int opcode = in.readUnsignedByte(); //The login opcode to read.
- if (opcode != 16 && opcode != 18 && opcode != 19) { //Checks if the opcodes match the following incase of lobby,
- // world or even reconnecting to the world
- ctx.channel().close();
- return;
- }
- switch (opcode) {
- case 19:// Lobby
- loginType = LoginType.LOBBY; //The lobby "instance" type of login.
- break;
- case 16:// World
- case 18:// Reconnection of the World
- loginType = LoginType.WORLD; //The actual instance of the world.
- break;
- }
- int length = in.readUnsignedShort(); //The length
- if (in.readableBytes() < length) { //Checks the length
- ctx.channel().close();
- return;
- }
- decodeClientRequest(ctx, in, out); //Performs the decoding request of the client.... Checks if the opcodes match //the login, world & world re-connection [opcodes, etc].
- }
- /**
- * Decodes the client request procedure.
- * @param ctx The connected {@link ChannelHandlerContext}.
- * @param in The used {@link ByteBuf}.
- * @param out The used output {@link Object}.
- */
- private void decodeClientRequest(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
- int majorVersion = in.readInt(); //The major version (Server revision - 742) - AKA Cache Version/Revision
- int minorVersion = in.readInt(); //The minor version (Sub revision: 1/any number) AKA Client Version/Revision
- if (majorVersion != Protocol.MAJOR_VERSION || minorVersion != Protocol.MINOR_VERSION) {
- ctx.channel().close();
- return;
- }
- if (loginType.equals(LoginType.WORLD)) { //Checks if the login type matches the world login type to process the //request
- in.readByte();
- }
- decodeLoginRequest(ctx, in, out); //Performs the decoding of the request of login (Checks if the major/minor //versions match the actual ones to load.
- }
- /**
- * Decodes the login request procedure.
- * @param ctx The connected {@link ChannelHandlerContext}.
- * @param in The used {@link ByteBuf}.
- * @param out The used output {@link Object}.
- */
- private void decodeLoginRequest(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
- if (!in.isReadable()) { //If the buffer is readable.
- ctx.channel().close();
- return;
- }
- int secureBufferSize = in.readUnsignedShort(); //The size of the buffer to read
- if (in.readableBytes() < secureBufferSize) {
- ctx.channel().close();
- return;
- }
- byte[] secureBytes = new byte[secureBufferSize];
- in.readBytes(secureBytes);
- ByteBuf secureBuffer = Unpooled.wrappedBuffer(new BigInteger(secureBytes).modPow(Protocol.LOGIN_RSA_EXPONENT, Protocol.LOGIN_RSA_MODULUS).toByteArray());
- int blockOpcode = secureBuffer.readUnsignedByte();
- if (blockOpcode != 10) {
- ctx.channel().close();
- return;
- }
- int[] xteaKey = new int[4];
- for (int i = 0; i < xteaKey.length; i++) {
- xteaKey[i] = secureBuffer.readInt();
- }
- long loginHash = secureBuffer.readLong();
- if (loginHash != 0L) {
- ctx.channel().close();
- return;
- }
- String password = BufferUtilities.readBufferedString(secureBuffer); //The password to hash.
- String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt()); //The hashed password.
- secureBuffer.readLong();
- secureBuffer.readLong();
- byte[] xteaBlock = new byte[in.readableBytes()];
- in.readBytes(xteaBlock);
- XTEA xtea = new XTEA(xteaKey);
- xtea.decrypt(xteaBlock, 0, xteaBlock.length);
- ByteBuf xteaBuffer = Unpooled.wrappedBuffer(xteaBlock);
- boolean decodeAsString = xteaBuffer.readByte() == 1;
- String username = Utilities.formatPlayerNameForProtocol(decodeAsString ? BufferUtilities.readBufferedString(xteaBuffer) : Base37Utils.decodeBase37(xteaBuffer.readLong())); //The player username
- switch (loginType) {
- case LOBBY: /
- xteaBuffer.readUnsignedByte();
- xteaBuffer.readUnsignedByte();
- break;
- case WORLD:
- int displayId = xteaBuffer.readUnsignedByte();
- display = (displayId == 1 ? Display.FIXED_DISPLAY : Display.RESIZEABLE_DISPLAY);
- xteaBuffer.readUnsignedShort();
- xteaBuffer.readUnsignedShort();
- xteaBuffer.readUnsignedByte();
- break;
- }
- int[] randomData = new int[24];
- for (int index = 0; index < randomData.length; index++) {
- randomData[index] = xteaBuffer.readUnsignedByte();
- }
- String loginToken = BufferUtilities.readBufferedString(xteaBuffer);
- if (!loginToken.equals(Protocol.LOGIN_TOKEN)) {
- ctx.channel().close();
- return;
- }
- int[] serverKeys = new int[xteaKey.length]; //The 23 CRC keys.
- for (int i = 0; i < xteaKey.length; i++) {
- serverKeys[i] = xteaKey[i] + 50;
- }
- int[] clientKeys = xteaKey;
- IsaacRandom encodingRandom = new IsaacRandom(serverKeys);
- IsaacRandom decodingRandom = new IsaacRandom(clientKeys);
- out.add(new LoginRequestMessage(username, password, hashedPassword, loginType, display, encodingRandom, decodingRandom)); //Decodes the logging in request,
- }
- /**
- * An enumeration created that is defining the types of login.
- */
- public enum LoginType {
- LOBBY, WORLD;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement