فهرست منبع

Fix a very dangerous typo (sizeof wrong struct) that was causing random segfault. Handle reassembling tcp packets

Julien 'Lta' BALLET 11 سال پیش
والد
کامیت
c8ef5449b9
6فایلهای تغییر یافته به همراه66 افزوده شده و 41 حذف شده
  1. 24 21
      bin/dsm.c
  2. 2 2
      include/bdsm/smb_message.h
  3. 30 11
      src/netbios_session.c
  4. 3 3
      src/smb_message.c
  5. 1 1
      src/smb_session.c
  6. 6 3
      src/smb_trans2.c

+ 24 - 21
bin/dsm.c

@@ -41,7 +41,7 @@
 
 /* *INDENT-OFF* */
 char usage_str[] = {
-  "usage: %s [options] host login password file\n"
+  "usage: %s [options] host login password share file\n"
   "  -h, --help         Show this help screen.\n"
   "  -v, --version      Print the version and quit.\n"
 };
@@ -86,22 +86,26 @@ static int parse_options(int argc, char * argv[])
 
 int main(int ac, char **av)
 {
-  const char          *pname, *host, *login, *password, *fname;
+  const char          *pname, *host, *login, *password, *fname, *share;
   struct sockaddr_in  addr;
-  netbios_ns        *ns;
-  smb_session       *session;
+  netbios_ns          *ns;
+  smb_session         *session;
   int                 argoffset;
+  char                **share_list;
+  smb_file            *files;
+
 
   pname     = ((pname = strrchr(av[0], '/')) != NULL) ? pname + 1 : av[0];
   argoffset = parse_options(ac, av);
 
-  if (argoffset >= ac || ac - argoffset != 4) {
+  if (argoffset >= ac || ac - argoffset != 5) {
     print_usage(pname, -1);
   }
 
   host      = av[argoffset++];
   login     = av[argoffset++];
   password  = av[argoffset++];
+  share     = av[argoffset++];
   fname     = av[argoffset++];
 
   ns = netbios_ns_new();
@@ -159,12 +163,24 @@ int main(int ac, char **av)
     exit(42);
   }
 
-  smb_tid test = smb_tree_connect(session, "test");
+  if (!smb_share_get_list(session, &share_list))
+  {
+    fprintf(stderr, "Unable to list share for %s\n", host);
+    exit(42);
+  }
+
+  fprintf(stderr, "Share list : \n");
+  for (size_t j = 0; share_list[j] != NULL; j++)
+    fprintf(stderr, "- %s\n", share_list[j]);
+  smb_share_list_destroy(share_list);
+
+
+  smb_tid test = smb_tree_connect(session, share);
   if (test)
-    fprintf(stderr, "Connected to Test share\n");
+    fprintf(stderr, "Connected to %s share\n", share);
   else
   {
-    fprintf(stderr, "Unable to connect to Test share\n");
+    fprintf(stderr, "Unable to connect to %s share\n", share);
     exit(42);
   }
 
@@ -178,25 +194,12 @@ int main(int ac, char **av)
   // }
 
   //char              data[1024];
-  char              **share_list;
-  smb_file          *files;
 
 
   // smb_fread(session, fd, data, 1024);
   // fprintf(stderr, "Read from file:\n%s\n", data);
   // smb_fclose(session, fd);
 
-  if (!smb_share_get_list(session, &share_list))
-  {
-    fprintf(stderr, "Unable to list share for %s\n", host);
-    exit(42);
-  }
-
-  fprintf(stderr, "Share list : \n");
-  for (size_t j = 0; share_list[j] != NULL; j++)
-    fprintf(stderr, "- %s\n", share_list[j]);
-  smb_share_list_destroy(share_list);
-
   fprintf(stderr, "Let's find files at share's root :\n");
   files = smb_find(session, test, "\\*");
   if (files != NULL)

+ 2 - 2
include/bdsm/smb_message.h

@@ -22,8 +22,8 @@
 #include "bdsm/smb_defs.h"
 #include "bdsm/smb_types.h"
 
-smb_message   *smb_message_new(uint8_t cmd, size_t payload_size);
-smb_message   *smb_message_grow(smb_message *msg, size_t size);
+smb_message     *smb_message_new(uint8_t cmd, size_t payload_size);
+smb_message     *smb_message_grow(smb_message *msg, size_t size);
 void            smb_message_destroy(smb_message *msg);
 int             smb_message_advance(smb_message *msg, size_t size);
 int             smb_message_append(smb_message *msg, const void *data,

+ 30 - 11
src/netbios_session.c

@@ -132,7 +132,8 @@ void              netbios_session_packet_init(netbios_session *s)
 {
   assert(s != NULL);
 
-  s->packet_cursor = 0;
+  s->packet_cursor  = 0;
+  s->packet->flags  = 0;
   s->packet->opcode = NETBIOS_OP_SESSION_MSG;
 }
 
@@ -175,30 +176,48 @@ int               netbios_session_packet_send(netbios_session *s)
 
 ssize_t           netbios_session_packet_recv(netbios_session *s, void **data)
 {
-  ssize_t         recv_size;
-  size_t          len;
+  ssize_t         res;
+  size_t          total, sofar;
 
   assert(s != NULL && s->packet != NULL && s->socket && s->state > 0);
 
-  recv_size = recv(s->socket, (void *)(s->packet), s->packet_payload_size, 0);
-
-  if (recv_size < 0)
+  res = recv(s->socket, (void *)(s->packet), s->packet_payload_size, 0);
+  if (res < 0)
+  {
     perror("netbios_session_packet_recv: ");
+    return (-1);
+  }
 
-  if (recv_size >= sizeof(netbios_session_packet) && data != NULL)
+  if (res > sizeof(netbios_session_packet) && data != NULL)
     *data = (void *)s->packet->payload;
   else if (data != NULL)
     *data = NULL;
 
-  len  = ntohs(s->packet->length);
-  len |= (s->packet->flags & 0x01) << 16;
+  total  = ntohs(s->packet->length);
+  total |= (s->packet->flags & 0x01) << 16;
+  sofar  = res - sizeof(netbios_session_packet);
+
+  //fprintf(stderr, "Total = %ld, sofar = %ld\n", total, sofar);
+
+  while (sofar < total)
+  {
+    res = recv(s->socket, (void *)(s->packet) + 4 + sofar, total - sofar, 0);
+    //xfprintf(stderr, "Total = %ld, sofar = %ld, res = %ld\n", total, sofar, res);
+
+    if (res < 0)
+    {
+      perror("netbios_session_packet_recv: ");
+      return (-1);
+    }
+    sofar += res;
+  }
 
-  if (len != recv_size - sizeof(netbios_session_packet))
+  if (sofar > total)
   {
     BDSM_dbg("netbios_session_packet_recv: Packet size mismatch\n");
     return(-1);
   }
 
-  return (len);
+  return (sofar);
 }
 

+ 3 - 3
src/smb_message.c

@@ -35,7 +35,7 @@ smb_message   *smb_message_new(uint8_t cmd, size_t payload_size)
   msg = (smb_message *)calloc(1, sizeof(smb_message));
   assert(msg != NULL);
 
-  msg->packet = (smb_packet *)calloc(1, sizeof(smb_message) + payload_size);
+  msg->packet = (smb_packet *)calloc(1, sizeof(smb_packet) + payload_size);
   assert(msg != NULL);
 
   msg->payload_size = payload_size;
@@ -138,8 +138,8 @@ size_t          smb_message_put_utf16(smb_message *msg, const char *src_enc,
   res = smb_message_append(msg, utf_str, utf_str_len);
   free(utf_str);
 
-  //fprintf(stderr, "put_utf16, adds %d bytes, cursor is at %d\n",
-  //        utf_str_len, msg->cursor);
+  // fprintf(stderr, "put_utf16, adds %d bytes, cursor is at %d\n",
+  //         utf_str_len, msg->cursor);
 
   if (res)
     return(utf_str_len);

+ 1 - 1
src/smb_session.c

@@ -153,7 +153,7 @@ static int        smb_negotiate(smb_session *s)
   smb_negotiate_resp  *nego;
 
 
-  msg = smb_message_new(SMB_CMD_NEGOTIATE, 64);
+  msg = smb_message_new(SMB_CMD_NEGOTIATE, 128);
   smb_message_set_default_flags(msg);
 
   smb_message_put8(msg, 0);   // wct

+ 6 - 3
src/smb_trans2.c

@@ -133,7 +133,7 @@ smb_file  *smb_find(smb_session *s, smb_tid tid, const char *pattern)
   tr2->data_offset        = 88; // Offset of pattern in packet
   tr2->setup_count        = 1;
   tr2->cmd                = SMB_TR2_FIND_FIRST;
-  tr2->bct                = sizeof(smb_tr2_find2) + pattern_len * 2 + 3;
+  tr2->bct                = sizeof(smb_tr2_find2) + pattern_len * 2;
 
   find = (smb_tr2_find2 *) tr2->payload;
   find->attrs     = SMB_FIND2_ATTR_DEFAULT;
@@ -146,8 +146,11 @@ smb_file  *smb_find(smb_session *s, smb_tid tid, const char *pattern)
   smb_message_put_utf16(msg, "", pattern, pattern_len);
 
   // Adds padding at the end if necessary.
-  if (tr2->bct % 4)
-    smb_message_advance(msg, 4 - tr2->bct % 4);
+  while (tr2->bct % 4)
+  {
+    smb_message_put8(msg, 0);
+    tr2->bct++;
+  }
 
   res = smb_session_send_msg(s, msg);
   smb_message_destroy(msg);