Explorar o código

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

Julien 'Lta' BALLET %!s(int64=11) %!d(string=hai) anos
pai
achega
c8ef5449b9
Modificáronse 6 ficheiros con 66 adicións e 41 borrados
  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);