Advertisement
Tyluur

Untitled

Jul 13th, 2012
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.77 KB | None | 0 0
  1. package com.runescape.networking.codec.login;
  2.  
  3. import java.math.BigInteger;
  4.  
  5. import org.jboss.netty.buffer.ChannelBuffer;
  6. import org.jboss.netty.buffer.ChannelBuffers;
  7. import org.jboss.netty.channel.Channel;
  8. import org.jboss.netty.channel.ChannelHandlerContext;
  9. import org.jboss.netty.handler.codec.frame.FrameDecoder;
  10.  
  11. import com.runescape.game.model.player.Player;
  12. import com.runescape.networking.codec.login.RS2LoginDecoder.Stage;
  13. import com.runescape.utility.BufferUtility;
  14. import com.runescape.utility.Misc;
  15. import com.runescape.utility.game.FileLoader;
  16. import com.runescape.utility.game.LoginResponse;
  17. import com.runescape.utility.game.LoginResponse.Response;
  18. import com.runescape.utility.game.XTEA;
  19.  
  20. /**
  21. * An {@link FrameDecoder} implementation used to decode the world login
  22. * procedure.
  23. *
  24. * @author Tyluur
  25. *
  26. */
  27. public class RS2LoginDecoder extends StagedFrameDecoder<Stage> {
  28.  
  29. /**
  30. * The Standard login type.
  31. */
  32. public static final int LOGIN_TYPE = 16;
  33.  
  34. /**
  35. * The Reconnection login type.
  36. */
  37. public static final int RECONNECTION_TYPE = 18;
  38.  
  39. /**
  40. * The lobby login type.
  41. */
  42. public static final int LOBBY_TYPE = 19;
  43.  
  44. /**
  45. * The remaining bytes left in the login block.
  46. */
  47. private int loginSize;
  48.  
  49. /**
  50. * The login type
  51. */
  52. private int loginType;
  53.  
  54. /**
  55. * The rsa exponent.
  56. */
  57. public static final BigInteger EXPONENT = new BigInteger("90587072701551327129007891668787349509347630408215045082807628285770049664232156776755654198505412956586289981306433146503308411067358680117206732091608088418458220580479081111360656446804397560752455367862620370537461050334224448167071367743407184852057833323917170323302797356352672118595769338616589092625");
  58.  
  59. /**
  60. * The rsa modulus.
  61. */
  62. public static final BigInteger MODULUS = new BigInteger("102876637271116124732338500663639643113504464789339249490399312659674772039314875904176809267475033772367707882873773291786014475222178654932442254125731622781524413208523465520758537060408541610254619166907142593731337618490879831401461945679478046811438574041131738117063340726565226753787565780501845348613");
  63.  
  64. /**
  65. * The different stages of login.
  66. *
  67. * @author Thomas Le Godais
  68. *
  69. */
  70. public enum Stage {
  71.  
  72. CONNECTION_TYPE,
  73.  
  74. CLIENT_DETAILS,
  75.  
  76. WORLD_PAYLOAD;
  77. }
  78.  
  79. /**
  80. * Constrcuts a new WorldLoginDecoder.
  81. */
  82. public RS2LoginDecoder() {
  83. super(Stage.CONNECTION_TYPE);
  84. }
  85.  
  86.  
  87. @Override
  88. protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
  89. switch(stage) {
  90. case CONNECTION_TYPE:
  91. return decodeConnectionType(channel, buffer);
  92. case CLIENT_DETAILS:
  93. return decodeClientDetails(channel, buffer);
  94. case WORLD_PAYLOAD:
  95. return decodeWorldPayload(channel, buffer);
  96. }
  97. return null;
  98. }
  99.  
  100. /**
  101. * Decodes the connection type.
  102. *
  103. * @param channel The channel.
  104. * @param buffer The buffer.
  105. * @return The object.
  106. */
  107. private Object decodeConnectionType(Channel channel, ChannelBuffer buffer) {
  108. if(buffer.readable()) {
  109. loginType = buffer.readUnsignedByte();
  110. if(loginType != LOGIN_TYPE && loginType != RECONNECTION_TYPE) {
  111. sendResponse(channel, 13);
  112. }
  113. loginSize = buffer.readUnsignedShort();
  114. setStage(Stage.CLIENT_DETAILS);
  115. }
  116. return null;
  117. }
  118.  
  119. /**
  120. * Decodes the client details.
  121. *
  122. * @param channel The channel.
  123. * @param buffer The buffer.
  124. * @return The object.
  125. */
  126. private Object decodeClientDetails(Channel channel, ChannelBuffer buffer) {
  127. if(buffer.readableBytes() >= loginSize) {
  128. int version = buffer.readInt();
  129. buffer.readInt();
  130. if(version != 718) {
  131. sendResponse(channel, 6);
  132. }
  133. if(loginType != LOBBY_TYPE) {
  134. setStage(Stage.WORLD_PAYLOAD);
  135. }
  136. }
  137. return null;
  138. }
  139.  
  140. /**
  141. * Decodes the world login payload.
  142. *
  143. * @param channel The channel.
  144. * @param buffer The buffer.
  145. * @return The object.
  146. */
  147. @SuppressWarnings("unused")
  148. private Object decodeWorldPayload(Channel channel, ChannelBuffer buffer) {
  149. buffer.readUnsignedByte();
  150.  
  151. int blockSize = buffer.readShort() & 0xFFFF;
  152. if(!(blockSize > buffer.readableBytes())) {
  153.  
  154. byte[] rsaData = new byte[blockSize];
  155. buffer.readBytes(rsaData, 0, blockSize);
  156. ChannelBuffer rsaPayload = ChannelBuffers.wrappedBuffer(new BigInteger(rsaData).modPow(EXPONENT, MODULUS).toByteArray());
  157.  
  158. int rsaBlock = rsaPayload.readByte() & 0xFF;
  159. if(rsaBlock != 10) {
  160. sendResponse(channel, 10);
  161. return null;
  162. }
  163.  
  164. int[] isaacKeys = new int[4];
  165. for(int i = 0; i < isaacKeys.length; i++) {
  166. isaacKeys[i] = rsaPayload.readInt();
  167. }
  168.  
  169. long rsaPass = rsaPayload.readLong();
  170. if(rsaPass != 0L) {
  171. sendResponse(channel, 10);
  172. return null;
  173. }
  174.  
  175. String password = BufferUtility.readString(rsaPayload);
  176. if(password.length() > 30 || password.length() < 3) {
  177. sendResponse(channel, Response.WEAK_PASSWORD.getOpcode());
  178. return null;
  179. }
  180.  
  181. String unknown = Misc.longToString(rsaPayload.readLong());
  182. byte[] block = new byte[buffer.readableBytes()];
  183. buffer.readBytes(block);
  184. ChannelBuffer xteaBuffer = ChannelBuffers.wrappedBuffer(XTEA.decipher(isaacKeys, block));
  185.  
  186. boolean decodeAsString = (xteaBuffer.readByte() & 0xff) == 1;
  187. String username = Misc.formatPlayerNameForProtocol(decodeAsString ? BufferUtility.readString(xteaBuffer) : Misc.longToString(xteaBuffer.readLong()));
  188.  
  189. int displayMode = xteaBuffer.readByte() & 0xff;
  190. xteaBuffer.readUnsignedShort();
  191. xteaBuffer.readUnsignedShort();
  192. xteaBuffer.readUnsignedByte();
  193.  
  194. xteaBuffer.skipBytes(24);
  195. String clientSettings = BufferUtility.readString(xteaBuffer);
  196.  
  197. xteaBuffer.readInt();
  198. int skipLen = xteaBuffer.readByte() & 0xff;
  199. xteaBuffer.skipBytes(skipLen);
  200.  
  201. xteaBuffer.readInt();
  202. xteaBuffer.readLong();
  203.  
  204. boolean additInfo = (xteaBuffer.readByte() & 0xFF) == 1;
  205. if(additInfo) {
  206. BufferUtility.readString(xteaBuffer);
  207. }
  208. for(int i = 0; i < 3; i++) {
  209. xteaBuffer.readUnsignedByte();
  210. }
  211. xteaBuffer.readByte();
  212. xteaBuffer.readInt();
  213.  
  214. String unknownString = BufferUtility.readString(xteaBuffer);
  215.  
  216. xteaBuffer.readUnsignedByte();
  217.  
  218. System.out.println("Login Request [username=" + username + " password=" + password + " displayMode=" + displayMode + "]");
  219. Player player;
  220. if (!FileLoader.containsPlayer(username)) {
  221. player = new Player();
  222. } else {
  223. player = FileLoader.loadPlayer(username);
  224. if (!player.getFeatures().getPassword().equals(password)) {
  225. sendResponse(channel, Response.INVALID_CREDENTIALS.getOpcode());
  226. return null;
  227. }
  228. }
  229. player.init(channel, username, password);
  230. player.start();
  231. } else {
  232. channel.close();
  233. }
  234. return null;
  235. }
  236.  
  237. /**
  238. * Sends a response.
  239. *
  240. * @param channel The channel to write the response.
  241. * @param rOpcode The response opcode.
  242. */
  243. private void sendResponse(Channel channel, int rOpcode) {
  244. channel.write(new LoginResponse(Response.forId(rOpcode)));
  245. }
  246. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement