Advertisement
Guest User

Untitled

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