MySQL.java 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package de.tudarmstadt.informatik.hostage.protocol;
  2. import java.nio.ByteBuffer;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
  6. import de.tudarmstadt.informatik.hostage.wrapper.Packet;
  7. /**
  8. * MySQL protocol
  9. * @author Wulf Pfeiffer
  10. */
  11. public class MySQL implements Protocol {
  12. /**
  13. * Represents the states of the protocol
  14. */
  15. private enum STATE {
  16. NONE, CONNECTED, LOGIN_INFO, CLOSED
  17. }
  18. /**
  19. * Denotes in which state the protocol is right now
  20. */
  21. private STATE state = STATE.NONE;
  22. /** last request from client */
  23. private byte[] lastMessage;
  24. @Override
  25. public List<Packet> processMessage(Packet packet) {
  26. byte[] request = null;
  27. if (packet != null) {
  28. request = packet.getMessage();
  29. }
  30. List<Packet> response = new ArrayList<Packet>();
  31. if(request != null)
  32. lastMessage = request;
  33. switch(state) {
  34. case NONE:
  35. response.add(greeting());
  36. state = STATE.CONNECTED;
  37. break;
  38. case CONNECTED:
  39. response.add(responseOK());
  40. state = STATE.LOGIN_INFO;
  41. break;
  42. case LOGIN_INFO:
  43. if(this.lastMessage[4] == 0x01) {
  44. state = STATE.CLOSED;
  45. } else {
  46. response.add(responseError());
  47. }
  48. break;
  49. default:
  50. state = STATE.CLOSED;
  51. break;
  52. }
  53. return response;
  54. }
  55. @Override
  56. public TALK_FIRST whoTalksFirst() {
  57. return TALK_FIRST.SERVER;
  58. }
  59. @Override
  60. public String toString(){
  61. return "MySQL";
  62. }
  63. @Override
  64. public int getPort() {
  65. return 3306;
  66. }
  67. @Override
  68. public boolean isClosed() {
  69. return state == STATE.CLOSED;
  70. }
  71. @Override
  72. public boolean isSecure() {
  73. return false;
  74. }
  75. @Override
  76. public Class<byte[]> getType() {
  77. return byte[].class;
  78. }
  79. /**
  80. * Wraps the response packet with the packet length and number
  81. * @param packet that is wrapped
  82. * @return wrapped packet
  83. */
  84. private Packet wrapPacket(byte[] packet) {
  85. byte[] buffer = ByteBuffer.allocate(4).putInt(packet.length).array();
  86. byte[] packetLength = {buffer[3], buffer[2], buffer[1]};
  87. byte[] packetNumber = new byte[1];
  88. if(lastMessage != null) packetNumber[0] = (byte) (lastMessage[3] + 1);
  89. else packetNumber[0] = 0x00;
  90. byte[] response = HelperUtils.concat(packetLength, packetNumber, packet);
  91. return new Packet(response);
  92. }
  93. /**
  94. * Builds the greeting packet that the server sends as first packet
  95. * @return greeting packet
  96. */
  97. private Packet greeting() {
  98. byte[] protocol = {0x0a};
  99. byte[] version = serverVersion.getBytes();
  100. byte[] versionFin = {0x00};
  101. byte[] thread = {0x2a, 0x00, 0x00, 0x00};
  102. byte[] salt = {0x44, 0x64, 0x49, 0x7e, 0x60, 0x48, 0x25, 0x7e, 0x00};
  103. byte[] capabilities = {(byte) 0xff, (byte) 0xf7};
  104. byte[] language = {0x08};
  105. byte[] status = {0x02, 0x00};
  106. byte[] unused = {0x0f, (byte) 0x80, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  107. byte[] salt2 = {0x6c, 0x26, 0x71, 0x2c, 0x25, 0x72, 0x31, 0x3d, 0x7d, 0x21, 0x26, 0x3b, 0x00};
  108. String payload = "mysql_native_password";
  109. byte[] fin = {0x00};
  110. byte[] response = HelperUtils.concat(protocol, version,versionFin, thread, salt, capabilities, language, status, unused, salt2, payload.getBytes(), fin);
  111. return wrapPacket(response);
  112. }
  113. /**
  114. * Builds the ok-response packet
  115. * @return ok-response packet
  116. */
  117. private Packet responseOK() {
  118. byte[] affectedRows = {0x00, 0x00, 0x00};
  119. byte[] status = {0x02, 0x00};
  120. byte[] warnings = {0x00, 0x00};
  121. byte[] response = HelperUtils.concat(affectedRows, status, warnings);
  122. return wrapPacket(response);
  123. }
  124. /**
  125. * Builds the error-response packet
  126. * @return error-response packet
  127. */
  128. private Packet responseError() {
  129. byte[] fill1 = {(byte) 0xff};
  130. byte[] code = {0x17, 0x04};
  131. byte[] fill2 = {0x23};
  132. String state = "08S01";
  133. String msg = "Unknown command";
  134. byte[] response = HelperUtils.concat(fill1, code, fill2, state.getBytes(), msg.getBytes());
  135. return wrapPacket(response);
  136. }
  137. private static final String serverVersion = ProtocolSettings.getMysqlVersion();
  138. }