/ettercap/src/dissectors/ec_rlogin.c

# · C · 196 lines · 95 code · 38 blank · 63 comment · 34 complexity · f9aa05d862bb8f30f7d8e5e1dbfa511d MD5 · raw file

  1. /*
  2. ettercap -- dissector RLOGIN -- TCP 512 513
  3. Copyright (C) ALoR & NaGA
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. $Id: ec_rlogin.c,v 1.15 2005/07/05 09:41:23 alor Exp $
  16. */
  17. #include <ec.h>
  18. #include <ec_decode.h>
  19. #include <ec_dissect.h>
  20. #include <ec_session.h>
  21. /* protos */
  22. FUNC_DECODER(dissector_rlogin);
  23. void rlogin_init(void);
  24. void skip_rlogin_command(u_char **ptr, u_char *end);
  25. /************************************************/
  26. /*
  27. * this function is the initializer.
  28. * it adds the entry in the table of registered decoder
  29. */
  30. void __init rlogin_init(void)
  31. {
  32. dissect_add("rlogin", APP_LAYER_TCP, 512, dissector_rlogin);
  33. dissect_add("rlogin", APP_LAYER_TCP, 513, dissector_rlogin);
  34. }
  35. /*
  36. * rlogin sends characters one per packet for the password
  37. * but the login is sent all together on the second packet
  38. * sent by the client.
  39. */
  40. FUNC_DECODER(dissector_rlogin)
  41. {
  42. DECLARE_DISP_PTR_END(ptr, end);
  43. struct ec_session *s = NULL;
  44. void *ident = NULL;
  45. char tmp[MAX_ASCII_ADDR_LEN];
  46. /* skip messages from the server */
  47. if (FROM_SERVER("rlogin", PACKET))
  48. return NULL;
  49. /* skip empty packets (ACK packets) */
  50. if (PACKET->DATA.len == 0)
  51. return NULL;
  52. DEBUG_MSG("rlogin --> TCP dissector_rlogin");
  53. /* create an ident to retrieve the session */
  54. dissect_create_ident(&ident, PACKET, DISSECT_CODE(dissector_rlogin));
  55. /* this is the rlogin handshake */
  56. if (*ptr == '\0') {
  57. /* retrieve the session */
  58. if (session_get(&s, ident, DISSECT_IDENT_LEN) == -ENOTFOUND) {
  59. dissect_create_session(&s, PACKET, DISSECT_CODE(dissector_rlogin));
  60. /* remember the state (used later) */
  61. s->data = strdup("HANDSHAKE");
  62. /* save the session */
  63. session_put(s);
  64. SAFE_FREE(ident);
  65. return NULL;
  66. }
  67. }
  68. /* the first packet after handshake */
  69. if (session_get(&s, ident, DISSECT_IDENT_LEN) == ESUCCESS && s->data) {
  70. if (!strcmp(s->data, "HANDSHAKE")) {
  71. u_char *localuser;
  72. u_char *remoteuser;
  73. localuser = ptr;
  74. /* sanity check */
  75. if (localuser + strlen(localuser) + 2 < end)
  76. remoteuser = localuser + strlen(localuser) + 1;
  77. else {
  78. /* bad packet, abort the collection process */
  79. session_del(ident, DISSECT_IDENT_LEN);
  80. SAFE_FREE(ident);
  81. return NULL;
  82. }
  83. SAFE_FREE(s->data);
  84. /* make room for the string */
  85. SAFE_CALLOC(s->data, strlen(localuser) + strlen(remoteuser) + 5, sizeof(char));
  86. snprintf(s->data, strlen(localuser)+strlen(remoteuser) + 5, "%s (%s)\r", remoteuser, localuser);
  87. SAFE_FREE(ident);
  88. return NULL;
  89. }
  90. }
  91. /* concat the pass to the collected user */
  92. if (session_get(&s, ident, DISSECT_IDENT_LEN) == ESUCCESS && s->data) {
  93. size_t i;
  94. u_char *p;
  95. u_char str[strlen(s->data) + PACKET->DATA.disp_len + 2];
  96. memset(str, 0, sizeof(str));
  97. /* concat the char to the previous one */
  98. snprintf(str, strlen(s->data) + PACKET->DATA.disp_len + 2, "%s%s", (char *)s->data, ptr);
  99. /* parse the string for backspaces and erase as wanted */
  100. for (p = str, i = 0; i < strlen(str); i++) {
  101. if (str[i] == '\b' || str[i] == 0x7f) {
  102. /* don't go behind str */
  103. if (p > str)
  104. p--;
  105. } else {
  106. *p = str[i];
  107. p++;
  108. }
  109. }
  110. *p = '\0';
  111. /* save the new string */
  112. SAFE_FREE(s->data);
  113. s->data = strdup(str);
  114. /*
  115. * the user input is terminated
  116. * check if it was the password by checking
  117. * the presence of \r in the string
  118. * we store "user\rpass\r" and then we split it
  119. */
  120. if (strchr(ptr, '\r') || strchr(ptr, '\n')) {
  121. /* there is the \r and it is not the last char */
  122. if ( ((ptr = strchr(s->data, '\r')) || (ptr = strchr(s->data, '\n')))
  123. && ptr != s->data + strlen(s->data) - 1 ) {
  124. /* fill the structure */
  125. PACKET->DISSECTOR.user = strdup(s->data);
  126. if ( (ptr = strchr(PACKET->DISSECTOR.user, '\r')) != NULL )
  127. *ptr = '\0';
  128. else {
  129. SAFE_FREE(PACKET->DISSECTOR.user);
  130. return NULL;
  131. }
  132. PACKET->DISSECTOR.pass = strdup(ptr + 1);
  133. if ( (ptr = strchr(PACKET->DISSECTOR.pass, '\r')) != NULL )
  134. *ptr = '\0';
  135. /*
  136. * delete the session to remember that
  137. * user and pass was collected
  138. */
  139. session_del(ident, DISSECT_IDENT_LEN);
  140. SAFE_FREE(ident);
  141. /* display the message */
  142. DISSECT_MSG("RLOGIN : %s:%d -> USER: %s PASS: %s\n", ip_addr_ntoa(&PACKET->L3.dst, tmp),
  143. ntohs(PACKET->L4.dst),
  144. PACKET->DISSECTOR.user,
  145. PACKET->DISSECTOR.pass);
  146. }
  147. }
  148. }
  149. SAFE_FREE(ident);
  150. return NULL;
  151. }
  152. /* EOF */
  153. // vim:ts=3:expandtab