/src/dissectors/ec_smtp.c

https://github.com/bonsaiviking/ettercap · C · 193 lines · 82 code · 51 blank · 60 comment · 20 complexity · 2519236d1fbc665c4a673df09ddb1768 MD5 · raw file

  1. /*
  2. ettercap -- dissector SMTP -- TCP 25
  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. */
  16. #include <ec.h>
  17. #include <ec_decode.h>
  18. #include <ec_dissect.h>
  19. #include <ec_session.h>
  20. #include <ec_sslwrap.h>
  21. /* protos */
  22. FUNC_DECODER(dissector_smtp);
  23. void smtp_init(void);
  24. /************************************************/
  25. /*
  26. * this function is the initializer.
  27. * it adds the entry in the table of registered decoder
  28. */
  29. void __init smtp_init(void)
  30. {
  31. dissect_add("smtp", APP_LAYER_TCP, 25, dissector_smtp);
  32. sslw_dissect_add("ssmtp", 465, dissector_smtp, SSL_ENABLED);
  33. }
  34. FUNC_DECODER(dissector_smtp)
  35. {
  36. DECLARE_DISP_PTR_END(ptr, end);
  37. struct ec_session *s = NULL;
  38. void *ident = NULL;
  39. char tmp[MAX_ASCII_ADDR_LEN];
  40. /* the connection is starting... create the session */
  41. CREATE_SESSION_ON_SYN_ACK("smtp", s, dissector_smtp);
  42. CREATE_SESSION_ON_SYN_ACK("ssmtp", s, dissector_smtp);
  43. /* check if it is the first packet sent by the server */
  44. IF_FIRST_PACKET_FROM_SERVER_SSL("smtp", "ssmtp", s, ident, dissector_smtp) {
  45. DEBUG_MSG("\tdissector_smtp BANNER");
  46. /*
  47. * get the banner
  48. * ptr + 4 to skip the initial 220 response
  49. */
  50. if (!strncmp(ptr, "220", 3)) {
  51. PACKET->DISSECTOR.banner = strdup(ptr + 4);
  52. /* remove the \r\n */
  53. if ( (ptr = strchr(PACKET->DISSECTOR.banner, '\r')) != NULL )
  54. *ptr = '\0';
  55. }
  56. } ENDIF_FIRST_PACKET_FROM_SERVER(s, ident)
  57. /* skip messages coming from the server */
  58. if (FROM_SERVER("smtp", PACKET) || FROM_SERVER("ssmtp", PACKET))
  59. return NULL;
  60. /* skip empty packets (ACK packets) */
  61. if (PACKET->DATA.len == 0)
  62. return NULL;
  63. DEBUG_MSG("SMTP --> TCP dissector_smtp");
  64. /* skip the number, move to the command */
  65. while(*ptr == ' ' && ptr != end) ptr++;
  66. /* reached the end */
  67. if (ptr == end) return NULL;
  68. /*
  69. * AUTH LOGIN
  70. *
  71. * digest(user)
  72. * digest(pass)
  73. *
  74. * the digests are in base64
  75. */
  76. if ( !strncasecmp(ptr, "AUTH LOGIN", 10) ) {
  77. DEBUG_MSG("\tDissector_smtp AUTH LOGIN");
  78. /* destroy any previous session */
  79. dissect_wipe_session(PACKET, DISSECT_CODE(dissector_smtp));
  80. /* create the new session */
  81. dissect_create_session(&s, PACKET, DISSECT_CODE(dissector_smtp));
  82. /* remember the state (used later) */
  83. s->data = strdup("AUTH");
  84. /* save the session */
  85. session_put(s);
  86. /* username is in the next packet */
  87. return NULL;
  88. }
  89. /* search the session (if it exist) */
  90. dissect_create_ident(&ident, PACKET, DISSECT_CODE(dissector_smtp));
  91. if (session_get(&s, ident, DISSECT_IDENT_LEN) == -ENOTFOUND) {
  92. SAFE_FREE(ident);
  93. return NULL;
  94. }
  95. SAFE_FREE(ident);
  96. /* the session is invalid */
  97. if (s->data == NULL) {
  98. dissect_wipe_session(PACKET, DISSECT_CODE(dissector_smtp));
  99. return NULL;
  100. }
  101. if (!strcmp(s->data, "AUTH")) {
  102. char *user;
  103. int i;
  104. DEBUG_MSG("\tDissector_smtp AUTH LOGIN USER");
  105. SAFE_CALLOC(user, strlen(ptr), sizeof(char));
  106. /* username is encoded in base64 */
  107. i = base64_decode(user, ptr);
  108. SAFE_FREE(s->data);
  109. /* store the username in the session */
  110. SAFE_CALLOC(s->data, strlen("AUTH USER ") + i + 1, sizeof(char) );
  111. sprintf(s->data, "AUTH USER %s", user);
  112. SAFE_FREE(user);
  113. /* pass is in the next packet */
  114. return NULL;
  115. }
  116. if (!strncmp(s->data, "AUTH USER", 9)) {
  117. char *pass;
  118. DEBUG_MSG("\tDissector_smtp AUTH LOGIN PASS");
  119. SAFE_CALLOC(pass, strlen(ptr), sizeof(char));
  120. /* password is encoded in base64 */
  121. base64_decode(pass, ptr);
  122. /* fill the structure */
  123. PACKET->DISSECTOR.user = strdup(s->data + strlen("AUTH USER "));
  124. PACKET->DISSECTOR.pass = strdup(pass);
  125. SAFE_FREE(pass);
  126. /* destroy the session */
  127. dissect_wipe_session(PACKET, DISSECT_CODE(dissector_smtp));
  128. /* print the message */
  129. DISSECT_MSG("SMTP : %s:%d -> USER: %s PASS: %s\n", ip_addr_ntoa(&PACKET->L3.dst, tmp),
  130. ntohs(PACKET->L4.dst),
  131. PACKET->DISSECTOR.user,
  132. PACKET->DISSECTOR.pass);
  133. return NULL;
  134. }
  135. return NULL;
  136. }
  137. /* EOF */
  138. // vim:ts=3:expandtab