MySQL.java 4.1 KB

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