Advertisement
Guest User

Untitled

a guest
Jun 10th, 2017
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.28 KB | None | 0 0
  1. package org.hyperion.rs2.net;
  2.  
  3. import java.security.SecureRandom;
  4. import java.util.logging.Logger;
  5.  
  6. import org.apache.mina.core.buffer.IoBuffer;
  7. import org.apache.mina.core.session.IoSession;
  8. import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
  9. import org.apache.mina.filter.codec.ProtocolCodecFilter;
  10. import org.apache.mina.filter.codec.ProtocolDecoderOutput;
  11. import org.hyperion.Server;
  12. import org.hyperion.rs2.model.PlayerDetails;
  13. import org.hyperion.rs2.model.World;
  14. import org.hyperion.rs2.Constants;
  15. import org.hyperion.rs2.net.ondemand.OnDemandPool;
  16. import org.hyperion.rs2.net.ondemand.OnDemandRequest;
  17. import org.hyperion.rs2.util.IoBufferUtils;
  18. import org.hyperion.rs2.util.NameUtils;
  19. import org.hyperion.rs2.util.TextUtils;
  20.  
  21. /**
  22. * Login protocol decoding class.
  23. * @author Graham Edgecombe
  24. *
  25. */
  26. public class RS2LoginDecoder extends CumulativeProtocolDecoder {
  27.  
  28. /**
  29. * Logger instance.
  30. */
  31. private static final Logger logger = Logger.getLogger(RS2LoginDecoder.class.getName());
  32.  
  33. /**
  34. * The world list opcode.
  35. */
  36. public static final int OPCODE_WORLD_LIST = 131;
  37.  
  38. /**
  39. * Update opcode.
  40. */
  41. public static final int OPCODE_UPDATE = 15;
  42.  
  43. /**
  44. * Game opcode.
  45. */
  46. public static final int OPCODE_GAME = 14;
  47.  
  48. /**
  49. * The JS5 stage.
  50. */
  51. private static final int STATE_JS5 = -1;
  52.  
  53. /**
  54. * Update stage.
  55. */
  56. public static final int STATE_UPDATE = -2;
  57.  
  58. /**
  59. * World stage.
  60. */
  61. public static final int STATE_WORLD = -3;
  62.  
  63. /**
  64. * Opcode stage.
  65. */
  66. public static final int STATE_OPCODE = 0;
  67.  
  68. /**
  69. * Precrypted stage.
  70. */
  71. public static final int STATE_PRECRYPTED = 1;
  72.  
  73. /**
  74. * Crypted stage.
  75. */
  76. public static final int STATE_CRYPTED = 2;
  77.  
  78. /**
  79. * Login stage.
  80. */
  81. public static final int STATE_LOGIN = 3;
  82.  
  83. /**
  84. * Secure random number generator.
  85. */
  86. private static final SecureRandom RANDOM = new SecureRandom();
  87.  
  88. /**
  89. * Initial login response.
  90. */
  91. private static final byte[] INITIAL_RESPONSE = new byte[] {
  92. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
  93. };
  94.  
  95. @Override
  96. protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
  97. synchronized(session) {
  98. int state = (Integer) session.getAttribute("state", STATE_OPCODE);
  99. switch(state) {
  100. case STATE_WORLD:
  101. if(in.remaining() >= 2) {
  102. int worldOpcode = in.getShort();
  103. PacketBuilder worldList = new PacketBuilder();
  104. for(int data : Constants.WORLD_LIST_DATA) {
  105. worldList.put((byte) data);
  106. }
  107. session.write(worldList.toPacket());
  108. session.close(false);
  109. }
  110. return true;
  111. case STATE_UPDATE:
  112. if(in.remaining() >= 4) {
  113. for(int i = 0; i < 4; i++) {
  114. in.get();
  115. }
  116. PacketBuilder uKeys = new PacketBuilder();
  117. for(int key : Constants.UPDATE_KEYS) {
  118. uKeys.put((byte) key);
  119. System.out.println("uKey sent");
  120. }
  121. session.write(uKeys.toPacket());
  122. session.close(false);
  123. return true;
  124. } else {
  125. in.rewind();
  126. return false;
  127. }
  128. case STATE_JS5:
  129. if(in.remaining() >= 4) {
  130. in.get();
  131. int clientVersion = in.getShort();
  132. if(clientVersion == 525) {
  133. PacketBuilder u1Response = new PacketBuilder();
  134. u1Response.put((byte) 0);
  135. session.write(u1Response.toPacket());
  136. session.setAttribute("state", STATE_UPDATE);
  137. }
  138. }
  139. in.rewind();
  140. return false;
  141. case STATE_OPCODE:
  142. int opcode = in.get() & 0xFF;
  143. switch(opcode) {
  144. case OPCODE_GAME:
  145. session.setAttribute("state", STATE_LOGIN);
  146. return true;
  147. case OPCODE_UPDATE:
  148. session.setAttribute("state", STATE_JS5);
  149. return true;
  150. case OPCODE_WORLD_LIST:
  151. session.setAttribute("state", STATE_WORLD);
  152. return true;
  153. default:
  154. logger.info("Invalid opcode : " + opcode);
  155. session.close(false);
  156. break;
  157. }
  158. break;
  159. case STATE_LOGIN:
  160. if(in.remaining() >= 1) {
  161. /*
  162. * The name hash is a simple hash of the name which is
  163. * suspected to be used to select the appropriate login
  164. * server.
  165. */
  166. @SuppressWarnings("unused")
  167. int nameHash = in.get() & 0xFF;
  168.  
  169. /*
  170. * We generated the server session key using a SecureRandom
  171. * class for security.
  172. */
  173. long serverKey = RANDOM.nextLong();
  174.  
  175. /*
  176. * The initial response is just 0s which the client is set
  177. * to ignore (probably some sort of modification).
  178. */
  179. session.write(new PacketBuilder().put((byte) 0).putLong(serverKey).toPacket());
  180. session.setAttribute("state", STATE_PRECRYPTED);
  181. session.setAttribute("serverKey", serverKey);
  182. return true;
  183. }
  184. break;
  185. case STATE_PRECRYPTED:
  186. if(in.remaining() >= 2) {
  187. /*
  188. * We read the type of login.
  189. *
  190. * 16 = normal
  191. * 18 = reconnection
  192. */
  193. int loginOpcode = in.get() & 0xFF;
  194. if(loginOpcode != 16 && loginOpcode != 18) {
  195. logger.info("Invalid login opcode : " + loginOpcode);
  196. session.close(false);
  197. in.rewind();
  198. return false;
  199. }
  200.  
  201. /*
  202. * We read the size of the login packet.
  203. */
  204. int loginSize = in.get() & 0xFF;
  205.  
  206. /*
  207. * And calculated how long the encrypted block will be.
  208. */
  209. int loginEncryptSize = loginSize - (36 + 1 + 1 + 2);
  210.  
  211. session.setAttribute("state", STATE_CRYPTED);
  212. session.setAttribute("size", loginSize);
  213. session.setAttribute("encryptSize", loginEncryptSize);
  214. return true;
  215. }
  216. break;
  217. case STATE_CRYPTED:
  218. int size = (Integer) session.getAttribute("size");
  219. int encryptSize = (Integer) session.getAttribute("encryptSize");
  220. if(in.remaining() >= size) {
  221.  
  222. /*
  223. * We now read a short which is the client version and
  224. * check if it equals 317.
  225. */
  226. int version = in.getInt();
  227. if(version != Server.VERSION) {
  228. logger.info("Incorrect version : " + version);
  229. session.close(false);
  230. in.rewind();
  231. return false;
  232. }
  233.  
  234. for (int byteIdx = 0;byteIdx < 4;byteIdx++) {
  235. in.get();
  236. }
  237. in.getShort();
  238.  
  239. in.getShort();
  240.  
  241. in.get();
  242.  
  243. for (int byteIdx = 0;byteIdx < 24;byteIdx++)
  244. in.get();
  245.  
  246. IoBufferUtils.getRS2String(in);
  247.  
  248. for (int byteIdx = 0;byteIdx < 3;byteIdx++)
  249. in.get();
  250.  
  251. for (int it = 0;it < 2;it++)
  252. in.getInt();
  253.  
  254. in.getShort();
  255.  
  256. for (int i = 0; i < 26; i++) {
  257. in.getInt();
  258. }
  259.  
  260. int junk29 = in.getShort();
  261. int junk30 = in.get();
  262. int junk31 = in.getShort();
  263. int junk32 = in.get();
  264.  
  265. /*
  266. * The encrypted size includes the size byte which we don't
  267. * need.
  268. */
  269. encryptSize--;
  270.  
  271. /*
  272. * We check if there is a mismatch in the sizing.
  273. */
  274. int reportedSize = in.get() & 0xFF;
  275. if(reportedSize != 10) {
  276. in.get();
  277. }
  278.  
  279. /*
  280. * We read the client's session key.
  281. */
  282. long clientKey = in.getLong();
  283.  
  284. /*
  285. * And verify it has the correct server session key.
  286. */
  287. long serverKey = (Long) session.getAttribute("serverKey");
  288. long reportedServerKey = in.getLong();
  289. if(reportedServerKey != serverKey) {
  290. //logger.info("Server key mismatch (expected : " + serverKey + ", reported : " + reportedServerKey + ")");
  291. //session.close(false);
  292. //in.rewind();
  293. //return false;
  294. }
  295.  
  296. /*
  297. * We read and format the name and passwords.
  298. */
  299. String name = NameUtils.formatName(TextUtils.longToPlayerName(in.getLong()));
  300. String pass = IoBufferUtils.getRS2String(in);
  301. logger.info("Login request : username=" + name + " password=" + pass);
  302.  
  303. /*
  304. * And setup the ISAAC cipher which is used to encrypt and
  305. * decrypt opcodes.
  306. *
  307. * However, without RSA, this is rendered useless anyway.
  308. */
  309. int[] sessionKey = new int[4];
  310. sessionKey[0] = (int) (clientKey >> 32);
  311. sessionKey[1] = (int) clientKey;
  312. sessionKey[2] = (int) (serverKey >> 32);
  313. sessionKey[3] = (int) serverKey;
  314.  
  315. session.removeAttribute("state");
  316. session.removeAttribute("serverKey");
  317. session.removeAttribute("size");
  318. session.removeAttribute("encryptSize");
  319.  
  320. ISAACCipher inCipher = null;// new ISAACCipher(sessionKey);
  321. for(int i = 0; i < 4; i++) {
  322. sessionKey[i] += 50;
  323. }
  324. ISAACCipher outCipher = null;// new ISAACCipher(sessionKey);
  325.  
  326. /*
  327. * Now, the login has completed, and we do the appropriate
  328. * things to fire off the chain of events which will load
  329. * and check the saved games etc.
  330. */
  331. session.getFilterChain().remove("protocol");
  332. session.getFilterChain().addFirst("protocol", new ProtocolCodecFilter(RS2CodecFactory.GAME));
  333.  
  334. PlayerDetails pd = new PlayerDetails(session, name, pass, 0, inCipher, outCipher);
  335. World.getWorld().load(pd);
  336. }
  337. break;
  338. }
  339. in.rewind();
  340. return false;
  341. }
  342. }
  343.  
  344. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement