Guest User

Untitled

a guest
Dec 28th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.60 KB | None | 0 0
  1. package server.refactor.net.codec.login;
  2.  
  3. import java.math.BigInteger;
  4. import java.security.SecureRandom;
  5. import java.util.logging.Logger;
  6.  
  7. import org.apache.mina.common.ByteBuffer;
  8. import org.jboss.netty.buffer.ChannelBuffer;
  9. import org.jboss.netty.buffer.ChannelBuffers;
  10. import org.jboss.netty.channel.Channel;
  11. import org.jboss.netty.channel.ChannelHandlerContext;
  12.  
  13. import server.RS2Server;
  14. import server.net.ChannelBufferUtils;
  15. import server.refactor.net.NetworkConstants;
  16. import server.refactor.net.codec.StatefulFrameDecoder;
  17. import server.refactor.security.ISAACRandomGenPair;
  18. import server.refactor.security.PlayerCredentials;
  19. import server.util.ISAACRandomGen;
  20. import server.util.Misc;
  21.  
  22. /**
  23. * A {@link StatefulFrameDecoder} which decodes the login request frames.
  24. */
  25. public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState> {
  26.  
  27. private final Logger logger = Logger.getLogger(LoginDecoder.class.getName());
  28.  
  29. /**
  30. * The secure random number generator.
  31. */
  32. private static final SecureRandom random = new SecureRandom();
  33.  
  34. /**
  35. * The username hash.
  36. */
  37. private int usernameHash;
  38.  
  39. /**
  40. * The server-side session key.
  41. */
  42. private long serverSeed;
  43.  
  44. /**
  45. * The reconnecting flag.
  46. */
  47. private boolean reconnecting;
  48.  
  49. /**
  50. * The login packet length.
  51. */
  52. private int loginLength;
  53.  
  54. /**
  55. * The modifier for encrypted strings
  56. */
  57. private int stringModifier;
  58.  
  59. /**
  60. * Creates the login decoder with the default initial state.
  61. */
  62. public LoginDecoder() {
  63. super(LoginDecoderState.LOGIN_HANDSHAKE, true);
  64. }
  65.  
  66. @Override
  67. protected Object decode(final ChannelHandlerContext ctx, final Channel channel, final ChannelBuffer buffer, final LoginDecoderState state) throws Exception {
  68.  
  69. switch (state) {
  70. case LOGIN_HANDSHAKE:
  71. return decodeHandshake(ctx, channel, buffer);
  72. case LOGIN_HEADER:
  73. return decodeHeader(ctx, channel, buffer);
  74. case LOGIN_PAYLOAD:
  75. return decodePayload(ctx, channel, buffer);
  76. default:
  77. throw new Exception("Invalid login decoder state");
  78. }
  79. }
  80.  
  81. /**
  82. * Decodes in the handshake state.
  83. *
  84. * @param ctx
  85. * The channel handler context.
  86. * @param channel
  87. * The channel.
  88. * @param buffer
  89. * The buffer.
  90. * @return The frame, or {@code null}.
  91. * @throws Exception
  92. * if an error occurs.
  93. */
  94. private Object decodeHandshake(final ChannelHandlerContext ctx, final Channel channel, final ChannelBuffer buffer) throws Exception {
  95. if (buffer.readable()) {
  96. usernameHash = buffer.readUnsignedByte();
  97. // Delay login process in case server startup is not finished.
  98. if (!RS2Server.engineStarted) {
  99. final ChannelBuffer resp = ChannelBuffers.buffer(9);
  100. resp.writeLong(0);
  101. resp.writeByte(LoginConstants.STATUS_DELAY);
  102. channel.write(resp);
  103. channel.close();
  104. } else {
  105. serverSeed = random.nextLong();
  106. final ChannelBuffer resp = ChannelBuffers.buffer(19);
  107. resp.writeLong(0);
  108. resp.writeByte(LoginConstants.STATUS_EXCHANGE_DATA);
  109. // TODO: Send input order
  110. resp.writeLong(serverSeed);
  111. stringModifier = (0xFF + Misc.random(0xFFFF - 0xFF));
  112. // System.out.println("Sending modifier: " + stringModifier);
  113. resp.writeShort(stringModifier);
  114. channel.write(resp);
  115. setState(LoginDecoderState.LOGIN_HEADER);
  116. }
  117. }
  118. return null;
  119. }
  120.  
  121. /**
  122. * Decodes in the header state.
  123. *
  124. * @param ctx
  125. * The channel handler context.
  126. * @param channel
  127. * The channel.
  128. * @param buffer
  129. * The buffer.
  130. * @return The frame, or {@code null}.
  131. * @throws Exception
  132. * if an error occurs.
  133. */
  134. private Object decodeHeader(final ChannelHandlerContext ctx, final Channel channel, final ChannelBuffer buffer) throws Exception {
  135. if (buffer.readableBytes() >= 2) {
  136. final int loginType = buffer.readByte();
  137. if (loginType != LoginConstants.TYPE_STANDARD && loginType != LoginConstants.TYPE_RECONNECTION)
  138. throw new Exception("Invalid login type");
  139. reconnecting = loginType == LoginConstants.TYPE_RECONNECTION;
  140. loginLength = buffer.readUnsignedByte();
  141. setState(LoginDecoderState.LOGIN_PAYLOAD);
  142. }
  143. return null;
  144. }
  145.  
  146.  
  147. /**
  148. * Decodes in the payload state.
  149. *
  150. * @param ctx
  151. * The channel handler context.
  152. * @param channel
  153. * The channel.
  154. * @param buffer
  155. * The buffer.
  156. * @return The frame, or {@code null}.
  157. * @throws Exception
  158. * if an error occurs.
  159. */
  160. private Object decodePayload(final ChannelHandlerContext ctx, final Channel channel, final ChannelBuffer buffer) throws Exception {
  161. if (buffer.readableBytes() >= loginLength) {
  162. final ChannelBuffer payload = buffer.readBytes(loginLength);
  163. if (payload.readUnsignedByte() != 0xFF) {
  164. channel.close();
  165. throw new Exception("Invalid magic id");
  166. }
  167. int release = payload.readUnsignedShort();
  168.  
  169. int memoryStatus = payload.readUnsignedByte();
  170.  
  171. final int[] archiveCrcs = new int[9];
  172. for (int i = 0; i < 9; i++)
  173. archiveCrcs[i] = payload.readInt();
  174.  
  175. int length = payload.readUnsignedByte();
  176. if (length != loginLength - 41) {
  177. channel.close();
  178. logger.warning("FAIL PAYLOAD length " + length + " " + " login length " + loginLength );
  179. throw new Exception("Secure payload length mismatch");
  180. }
  181.  
  182. ChannelBuffer rsaBuffer = payload.readBytes(length);
  183. BigInteger bigInteger = new BigInteger(rsaBuffer.array());
  184. bigInteger = bigInteger.modPow(NetworkConstants.RSA_EXPONENT, NetworkConstants.RSA_MODULUS);
  185.  
  186. rsaBuffer = ChannelBuffers.wrappedBuffer(bigInteger.toByteArray());
  187.  
  188.  
  189. final int securityID = rsaBuffer.readUnsignedByte();
  190. if (securityID != 10) {
  191. channel.close();
  192. logger.warning("FAIL PAYLOAD ID " + securityID);
  193. throw new Exception("Invalid secure payload id");
  194. }
  195. final long clientSeed = rsaBuffer.readLong();
  196. final long reportedServerSeed = rsaBuffer.readLong();
  197. if (reportedServerSeed != serverSeed) {
  198. channel.close();
  199. throw new Exception("Server seed mismatch");
  200. }
  201. int uid = rsaBuffer.readInt(); // The SignLink uid
  202.  
  203. final String playerMacAddress = "";
  204.  
  205. final String clientSerial = "";
  206.  
  207. final String regSerial = "";
  208.  
  209.  
  210. String username = readString(rsaBuffer);
  211. String password = readString(rsaBuffer);
  212.  
  213. final int[] seed = new int[4];
  214. seed[0] = (int) (clientSeed >> 32);
  215. seed[1] = (int) clientSeed;
  216. seed[2] = (int) (serverSeed >> 32);
  217. seed[3] = (int) serverSeed;
  218. final ISAACRandomGen decodingRandom = new ISAACRandomGen(seed);
  219. for (int i = 0; i < seed.length; i++)
  220. seed[i] += 50;
  221.  
  222. final ISAACRandomGen encodingRandom = new ISAACRandomGen(seed);
  223. final ISAACRandomGenPair randomPair = new ISAACRandomGenPair(encodingRandom, decodingRandom);
  224.  
  225. final PlayerCredentials credentials = new PlayerCredentials(username, password, usernameHash, reconnecting, uid, release, playerMacAddress, clientSerial, regSerial, randomPair, ctx.getChannel(), false);
  226.  
  227. final LoginRequest req = new LoginRequest(credentials, randomPair, reconnecting, false, release, null);
  228. //return new Object[] { req, buffer.readBytes(buffer.readableBytes()) };
  229. if (buffer.readable())
  230. return new Object[] { req, buffer.readBytes(buffer.readableBytes()) };
  231. else {
  232. logger.warning("req");
  233. return req;
  234. }
  235. }
  236. return null;
  237. }
  238.  
  239. private String decryptString(byte[] buffer, int multiplier) {
  240. byte[] decrypted = new byte[buffer.length];
  241. for (int i = 0, modifier = 1; i < buffer.length; i++) {
  242. decrypted[i] = (byte) ((buffer[i] ^ (modifier * multiplier) & 0xFF));
  243. modifier *= (i * 2);
  244. }
  245. return new String(decrypted);
  246. }
  247.  
  248. /**
  249. * Reads a string from the specified {@link ByteBuffer}.
  250. *
  251. * @param buffer The buffer.
  252. * @return The string.
  253. */
  254. public static String readString(ByteBuffer buffer) {
  255. StringBuilder bldr = new StringBuilder();
  256. char character;
  257. while ((character = (char) buffer.get()) != STRING_TERMINATOR) {
  258. bldr.append(character);
  259. }
  260. return bldr.toString();
  261. }
  262.  
  263. /**
  264. * Reads a string from the specified {@link ByteBuf}.
  265. *
  266. * @param buffer The buffer.
  267. * @return The string.
  268. */
  269. public static String readString(ChannelBuffer buffer) {
  270. StringBuilder builder = new StringBuilder();
  271. int character;
  272. while (buffer.readable() && (character = buffer.readUnsignedByte()) != STRING_TERMINATOR) {
  273. builder.append((char) character);
  274. }
  275. return builder.toString();
  276. }
  277.  
  278. /**
  279. * The terminator of a string.
  280. */
  281. public static final int STRING_TERMINATOR = 10;
  282. }
Add Comment
Please, Sign In to add comment