Advertisement
Guest User

Untitled

a guest
Jan 21st, 2017
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.61 KB | None | 0 0
  1. package org.hyperion.rs2.net.codec;
  2.  
  3. import org.apache.mina.core.buffer.IoBuffer;
  4. import org.apache.mina.core.session.IoSession;
  5. import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
  6. import org.apache.mina.filter.codec.ProtocolCodecFilter;
  7. import org.apache.mina.filter.codec.ProtocolDecoderOutput;
  8. import org.hyperion.rs2.Constants;
  9. import org.hyperion.rs2.RS2Server;
  10. import org.hyperion.rs2.model.PlayerDetails;
  11. import org.hyperion.rs2.model.World;
  12. import org.hyperion.rs2.net.PacketBuilder;
  13. import org.hyperion.rs2.util.IoBufferUtils;
  14. import org.hyperion.rs2.util.NameUtils;
  15.  
  16. import java.security.SecureRandom;
  17. import java.util.logging.Logger;
  18.  
  19. public class RS2LoginDecoder extends CumulativeProtocolDecoder {
  20.  
  21. /**
  22. * Logger instance.
  23. */
  24. private static final Logger logger = Logger.getLogger(RS2LoginDecoder.class.getName());
  25. /**
  26. * Opcode stage.
  27. */
  28. public static final int STATE_OPCODE = 0;
  29. /**
  30. * Login stage.
  31. */
  32. public static final int STATE_LOGIN = 1;
  33. /**
  34. * Precrypted stage.
  35. */
  36. public static final int STATE_PRECRYPTED = 2;
  37. /**
  38. * Crypted stage.
  39. */
  40. public static final int STATE_CRYPTED = 3;
  41. /**
  42. * Version check stage.
  43. */
  44. public static final int CHECK_UPDATE_VERSION = -1;
  45. /**
  46. * Update stage.
  47. */
  48. public static final int STATE_UPDATE = -2;
  49. /**
  50. * World list state.
  51. */
  52. public static final int STATE_WORLD_LIST = -3;
  53. /**
  54. * Game opcode.
  55. */
  56. public static final int OPCODE_GAME = 14;
  57. /**
  58. * Update opcode.
  59. */
  60. public static final int OPCODE_UPDATE = 15;
  61. /**
  62. * World list opcode.
  63. */
  64. public static final int OPCODE_WORLD_LIST = 131;
  65. /**
  66. * Secure random number generator.
  67. */
  68. private static final SecureRandom RANDOM = new SecureRandom();
  69.  
  70. @Override
  71. protected boolean doDecode(IoSession session, IoBuffer in,
  72. ProtocolDecoderOutput out) throws Exception {
  73. final int state = (Integer) session.getAttribute("state", STATE_OPCODE);
  74. switch (state) {
  75.  
  76. case STATE_OPCODE:
  77. if (in.remaining() >= 1) { /*
  78. * Here we read the first opcode which indicates the type of
  79. * connection.
  80. *
  81. * 14 = game 15 = update 131: world list
  82. *
  83. * Updating is done by sending keys in many 525 servers
  84. */
  85. final int opcode = in.get() & 0xFF;
  86. switch (opcode) {
  87. case OPCODE_WORLD_LIST:
  88. session.setAttribute("state", STATE_WORLD_LIST);
  89. break;
  90. case OPCODE_GAME:
  91. session.setAttribute("state", STATE_LOGIN);
  92. break;
  93. case OPCODE_UPDATE:
  94. session.setAttribute("state", CHECK_UPDATE_VERSION);
  95. break;
  96. }
  97. return true;
  98. }
  99. in.rewind();
  100. break;
  101.  
  102. /*
  103. * Checks the client version for updating
  104. */
  105. case CHECK_UPDATE_VERSION:
  106. if (in.remaining() >= 4) {
  107. final int version = in.getInt();
  108. if (version != 508) {
  109. logger.info("Incorrect version : " + version);
  110. session.write(new PacketBuilder().put((byte) 6).toPacket());
  111. session.close(false);
  112. in.rewind();
  113. return false;
  114. }
  115. session.write(new PacketBuilder().put((byte) 0).toPacket());
  116. session.setAttribute("state", STATE_UPDATE);
  117. return true;
  118. }
  119. in.rewind();
  120. break;
  121. /*
  122. * WorldList writing
  123. */
  124. case STATE_WORLD_LIST:
  125. if (in.remaining() >= 4) {
  126. final int loginOpcode = in.getInt();
  127. if (loginOpcode == 0) {
  128. session.write(RS2WorldListEncoder.encode(true, true));
  129. } else {
  130. session.write(RS2WorldListEncoder.encode(false, true));
  131. }
  132. return true;
  133. }
  134. in.rewind();
  135. break;
  136. /*
  137. * Sends the update keys (as i dont have an cache updater implemented
  138. */
  139. case STATE_UPDATE:
  140. if (4 <= in.remaining()) {
  141. in.skip(4);
  142. final PacketBuilder ukeys = new PacketBuilder();
  143. for (final int key : Constants.UPDATE_KEYS) {
  144. ukeys.put((byte) key);
  145. }
  146. session.write(ukeys.toPacket());
  147. return true;
  148. }
  149. in.rewind();
  150. break;
  151.  
  152. case STATE_LOGIN:
  153. if (in.remaining() >= 1) {
  154. /*
  155. * The name hash is a simple hash of the name which is suspected
  156. * to be used to select the appropriate login server.
  157. */
  158. @SuppressWarnings("unused")
  159. final int nameHash = in.get() & 0xFF;
  160.  
  161. /*
  162. * We generated the server session key using a SecureRandom
  163. * class for security.
  164. */
  165. final long serverKey = RANDOM.nextLong();
  166.  
  167. /*
  168. * The initial response is just 0s which the client is set to
  169. * ignore (probably some sort of modification).
  170. */
  171. session.write(new PacketBuilder().put((byte) 0).putLong(serverKey).toPacket());
  172. session.setAttribute("state", STATE_PRECRYPTED);
  173. session.setAttribute("serverKey", serverKey);
  174. return true;
  175. }
  176. in.rewind();
  177. break;
  178. /*
  179. * Checks if the login opcodes are correct
  180. */
  181. case STATE_PRECRYPTED:
  182. if (3 <= in.remaining()) {
  183. /*
  184. * We read the type of login.
  185. *
  186. * 16 = normal 18 = reconnection
  187. */
  188. final int loginOpcode = in.get() & 0xff;
  189. final int loginSize = in.getUnsignedShort();
  190. if (loginOpcode != 16 && loginOpcode != 18) {
  191. logger.info("Invalid login opcode : " + loginOpcode);
  192. session.close(false);
  193. in.rewind();
  194. return false;
  195. }
  196. session.setAttribute("state", STATE_CRYPTED);
  197. session.setAttribute("size", loginSize);
  198. return true;
  199. }
  200. in.rewind();
  201. break;
  202.  
  203. /*
  204. * Main login information here
  205. */
  206. case STATE_CRYPTED:
  207. final int size = (Integer) session.getAttribute("size");
  208. if (in.remaining() >= size) {
  209.  
  210. /*
  211. * Reads the client version as an <code>in.getInt()</code>
  212. */
  213. final int version = in.getInt();
  214. if (version != RS2Server.VERSION) {
  215. logger.info("Incorrect version : " + version);
  216. session.close(false);
  217. in.rewind();
  218. return false;
  219. }
  220.  
  221. /*
  222. * checks if the client is on low memory Most likely to tell the
  223. * server not to play sounds and such
  224. */
  225.  
  226. boolean isHD = in.get() == 1 ? true : false;
  227.  
  228. /*
  229. * The hd type,
  230. */
  231. final byte hdType = (byte) (in.get() & 0xff);
  232.  
  233. in.getInt();
  234. for (int i = 0; i < 24; i++) {
  235. in.get();
  236. }
  237. IoBufferUtils.getRS2String(in);
  238.  
  239. for (int i = 0; i < 29; i++) {
  240. in.getInt();
  241. }
  242.  
  243. /*
  244. * We now read the encrypted block opcode (although in most 317
  245. * clients and this server the RSA is disabled) and check it is
  246. * equal to 10.
  247. */
  248. final int blockOpcode = in.get() & 0xFF;
  249. if (blockOpcode != 10) {
  250. @SuppressWarnings("unused")
  251. long encryptPacketId = in.get() & 0xFF;
  252. }
  253.  
  254. /*
  255. * We read the client's session key.
  256. */
  257. final long clientKey = in.getLong();
  258.  
  259. /*
  260. * And verify it has the correct server session key.
  261. */
  262. final long reportedServerKey = in.getLong();
  263. if (reportedServerKey != (Long) session.getAttribute("serverKey")) {
  264. logger.info("Server key mismatch (expected : "
  265. + ", reported : " + reportedServerKey + ")");
  266. session.close(false);
  267. in.rewind();
  268. return false;
  269. }
  270.  
  271. final String name = NameUtils.longToName(in.getLong());
  272. final String pass = IoBufferUtils.getRS2String(in);
  273. logger.info("Login request : username=" + name + " password=" + pass);
  274.  
  275. /*
  276. * And setup the ISAAC cipher which is used to encrypt and
  277. * decrypt opcodes.
  278. */
  279. final int[] sessionKey = new int[4];
  280. sessionKey[0] = (int) (clientKey >> 32);
  281. sessionKey[1] = (int) clientKey;
  282. sessionKey[2] = (int) (reportedServerKey >> 32);
  283. sessionKey[3] = (int) reportedServerKey;
  284.  
  285. //for (int i = 0; i < 4; i++)
  286. // sessionKey[i] += 50;
  287.  
  288. session.removeAttribute("state");
  289. session.removeAttribute("serverKey");
  290. session.removeAttribute("size");
  291. session.removeAttribute("encryptSize");
  292.  
  293. /*
  294. * Now, the login has completed, and we do the appropriate
  295. * things to fire off the chain of events which will load and
  296. * check the saved games etc.
  297. */
  298. session.getFilterChain().remove("protocol");
  299. session.getFilterChain().addFirst("protocol", new ProtocolCodecFilter(RS2CodecFactory.GAME));
  300.  
  301. final PlayerDetails pd = new PlayerDetails(session, NameUtils.formatName(name), pass, isHD, hdType);
  302. World.getWorld().load(pd);
  303. }
  304. break;
  305. }
  306. in.rewind();
  307. return false;
  308. }
  309. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement