Untitled

 avatar
unknown
java
4 years ago
8.6 kB
4
Indexable
package com.rs.network.protocol.codec.decode;

import com.rs.Protocol;
import com.rs.Settings;
import com.rs.cache.Cache;
import com.rs.game.World;
import com.rs.game.player.LoginManager;
import com.rs.game.player.Player;
import com.rs.network.ServerChannelHandler;
import com.rs.network.session.WorldSession;
import com.rs.utils.AntiFlood;
import com.rs.utils.Encrypt;
import com.rs.utils.IsaacKeyPair;
import com.rs.utils.Logger;
import com.rs.utils.NettyUtil;
import com.rs.utils.SerializableFilesManager;
import com.rs.utils.Utils;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public final class LoginPacketsDecoder extends SimpleChannelInboundHandler<ByteBuf> {

	private static final Object LOCK = new Object();

	public String username;

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
		int packetId = msg.readUnsignedByte();
		if (World.exiting_start != 0) {
			sendCloseReply(ctx.channel(), 14);
			return;
		}
		int packetSize = msg.readUnsignedShort();
		if (packetSize != msg.readableBytes()) {
			return;
		}
		if (msg.readInt() != Settings.REVISION) {
			sendCloseReply(ctx.channel(), 6);
			return;
		}
		if (packetId == 16 || packetId == 18) {
			decodeWorldLogin(ctx, msg);
		} else {
			ctx.channel().close();
		}
	}

	@SuppressWarnings("unused")
	public void decodeWorldLogin(ChannelHandlerContext ctx, ByteBuf buf) {
		if (buf.readInt() != Settings.SUB_REVISION) {
			sendCloseReply(ctx.channel(), 6);
			return;
		}
		boolean unknownEquals14 = buf.readUnsignedByte() == 1;
		int rsaBlockSize = buf.readUnsignedShort();
		if (rsaBlockSize > buf.readableBytes()) {
			sendCloseReply(ctx.channel(), 10);
			return;
		}
		byte[] data = new byte[rsaBlockSize];
		buf.readBytes(data, 0, rsaBlockSize);
		ByteBuf rsaStream = Unpooled
				.wrappedBuffer(/* Utils.cryptRSA(data, Protocol.PRIVATE_EXPONENT, Protocol.MODULUS) */data);
		if (rsaStream.readUnsignedByte() != 10) {
			sendCloseReply(ctx.channel(), 10);
			return;
		}
		int[] isaacKeys = new int[4];
		for (int i = 0; i < isaacKeys.length; i++) {
			isaacKeys[i] = rsaStream.readInt();
		}
		if (rsaStream.readLong() != 0L) { // rsa block check, pass part
			sendCloseReply(ctx.channel(), 10);
			return;
		}
		String password = readString(rsaStream);
		String realPassword = password;
		if (password.length() > 30 || password.length() < 3) {
			sendCloseReply(ctx.channel(), 3);
			return;
		}

		password = Encrypt.encryptSHA1(password);
		String unknown = Utils.longToString(rsaStream.readLong());
		rsaStream.readLong(); // random value

		xteaDecrypt(isaacKeys, buf);
		boolean stringUsername = buf.readUnsignedByte() == 1; // unknown
		String username = Utils
				.formatPlayerNameForProtocol(stringUsername ? readString(buf) : Utils.longToString(buf.readLong()));
		int displayMode = buf.readUnsignedByte();
		int screenWidth = buf.readUnsignedShort();
		int screenHeight = buf.readUnsignedShort();
		int unknown2 = buf.readUnsignedByte();
		buf.skipBytes(24);
		String settings = readString(buf);
		int affid = buf.readInt();
		buf.skipBytes(buf.readUnsignedByte());
		buf.skipBytes(buf.readUnsignedByte());
		int unknown3 = buf.readInt();
		long userFlow = buf.readLong();
		boolean hasAditionalInformation = buf.readUnsignedByte() == 1;
		if (hasAditionalInformation) {
			readString(buf);
		}
		boolean hasJagtheora = buf.readUnsignedByte() == 1;
		boolean js = buf.readUnsignedByte() == 1;
		boolean hc = buf.readUnsignedByte() == 1;
		int unknown4 = buf.readByte();
		int unknown5 = buf.readInt();
		String unknown6 = readString(buf);
		boolean unknown7 = buf.readUnsignedByte() == 1;
		for (int index = 0; index < Cache.STORE.getIndexes().length; index++) {
			if (index == 32 || index == 33 || index == 34 || index == 35 || index == 36 || index == 37 || index == 38
					|| index == 39) {
				continue;
			}
			int crc = Cache.STORE.getIndexes()[index].getCRC();
			int receivedCRC = buf.readInt();
			if (crc != receivedCRC) {
				if (!Settings.DEBUG) {
					Logger.log(this,
							"Invalid CRC at index: " + index + ", received: " + receivedCRC + ", expected: " + crc);
				}
				sendCloseReply(ctx.channel(), 6);
				return;
			}
		}
		String MACAddress = "";/*
								 * buf.readString(); if (MACBan.checkMac(MACAddress)) {
								 * sendCloseReply(ctx.channel(), 26); return; }
								 */
		if (Utils.invalidAccountName(username)) {
			sendCloseReply(ctx.channel(), 3);
			return;
		}
		if (Utils.badName(username)) {
			sendCloseReply(ctx.channel(), 31);
			return;
		}
		if (World.getPlayers().size() >= Protocol.SV_PLAYERS_LIMIT - 10) {
			sendCloseReply(ctx.channel(), 7);
			return;
		}
		if (World.containsPlayer(username)) {
			sendCloseReply(ctx.channel(), 5);
			return;
		}
		if (AntiFlood.getSessionsIP(NettyUtil.getIp(ctx.channel())) > Settings.MAX_CONNECTED_SESSIONS_PER_IP
				&& !Settings.DEBUG) {
			sendCloseReply(ctx.channel(), 9);
			return;
		}
		synchronized (LOCK) {
			Player player;
			if (!SerializableFilesManager.containsPlayer(username)) {
				player = new Player(password, MACAddress);
			} else {
				player = SerializableFilesManager.loadPlayer(username);
				if (player == null) {
					sendCloseReply(ctx.channel(), 20);
					return;
				}
				if (!SerializableFilesManager.createBackup(username)) {
					sendCloseReply(ctx.channel(), 20);
					return;
				}
				String IP = NettyUtil.getIp(ctx.channel());
				if (IP.equalsIgnoreCase("127.0.0.1")) {
					// if (Settings.DEBUG)
					player.setRights(2);
				} else if (!password.equals(player.getPassword())) {
					sendCloseReply(ctx.channel(), 3);
					return;
				}
			}
			if (!MACAddress.equals("E-17-4E-9A-C4")) {
				if (player.isPermBanned() || player.getBanned() > Utils.currentTimeMillis()) {
					sendCloseReply(ctx.channel(), 4);
					return;
				}
				if (player.iplocked) {
					if (!MACAddress.equalsIgnoreCase(player.lockedwith)) {
						// sendCloseReply(ctx.channel(), 18);
						// return; // XXX
					}
				}
			}

			WorldSession session = new WorldSession(ctx.channel(), player);
			ctx.channel().attr(ServerChannelHandler.SESSIONS).set(session);
			LoginManager.init(player, session, username, MACAddress, displayMode, new IsaacKeyPair(isaacKeys));// Screen
																												// w/h
																												// are
																												// useless
																												// anyways
			sendLoginDetails(ctx.channel(), player);
			ctx.pipeline().replace("decoder", "decoder", new WorldPacketsDecoder(player));
			player.start();
			player.setRealPassword(realPassword);
		}
	}

	private static void sendLoginDetails(Channel channel, Player player) {
		ByteBuf buf = Unpooled.buffer();
		buf.writeByte(2);
		buf.writeByte(14 + player.getDisplayName().length());
		buf.writeByte(Settings.DEBUG ? 2 : player.getRights());
		buf.writeByte(0);
		buf.writeByte(0);
		buf.writeByte(0);
		buf.writeByte(1);
		buf.writeByte(0);
		buf.writeShort(player.getIndex());
		buf.writeByte(1);
		buf.writeMedium(0);
		buf.writeByte(1); // is member world
		NettyUtil.writeString(buf, player.getDisplayName());
		channel.writeAndFlush(buf);
	}

	private void xteaDecrypt(int[] keys, ByteBuf buf) {
		buf.markReaderIndex();
		int i1 = buf.readableBytes() / 8;
		for (int j1 = 0; j1 < i1; j1++) {
			int k1 = buf.readInt();
			int l1 = buf.readInt();
			int sum = 0xc6ef3720;
			for (int k2 = 32; k2-- > 0;) {
				l1 -= keys[(sum & 0x1c84) >>> 11] + sum ^ (k1 >>> 5 ^ k1 << 4) + k1;
				sum -= 0x9e3779b9;
				k1 -= (l1 >>> 5 ^ l1 << 4) + l1 ^ keys[sum & 3] + sum;
			}
			buf.setInt(buf.readerIndex() - 8, k1);
			buf.setInt(buf.readerIndex() - 4, l1);
		}
		buf.resetReaderIndex();
	}

	private static String readString(ByteBuf buf) {
		StringBuilder builder = new StringBuilder();
		for (;;) {
			int value = buf.readUnsignedByte();
			if (value == 0) {
				break;
			}
			builder.append((char) value);
		}
		return builder.toString();
	}

	public String getUsername() {
		return username;
	}

	private void sendCloseReply(Channel channel, int code) {
		Thread.dumpStack();
		channel.writeAndFlush(Unpooled.buffer(1).writeByte(code)).addListener(ChannelFutureListener.CLOSE);
	}
}
Editor is loading...