Explorar el Código

Fixes an implementation issue on ns_discover, only the first machine was discovered

Julien 'Lta' BALLET hace 11 años
padre
commit
5ea413e556
Se han modificado 8 ficheros con 52 adiciones y 46 borrados
  1. 3 1
      bin/dsm.c
  2. 1 1
      bin/lookup.c
  3. 1 1
      include/bdsm/netbios_defs.h
  4. 2 0
      include/bdsm/netbios_ns.h
  5. 2 6
      include/bdsm/smb_share.h
  6. 25 27
      src/netbios_ns.c
  7. 2 0
      src/netbios_ns_entry.c
  8. 16 10
      src/smb_share.c

+ 3 - 1
bin/dsm.c

@@ -183,7 +183,7 @@ int main(int ac, char **av)
   // }
 
   char              data[1024];
-  smb_share_list_t  *share_list;
+  char              **share_list;
   smb_file_t        *files;
 
 
@@ -199,6 +199,8 @@ int main(int ac, char **av)
   else
   {
     fprintf(stderr, "Share list : \n");
+    for (size_t j; share_list[j] != NULL; j++)
+      fprintf(stderr, "- %s\n", share_list[j]);
   }
 
   fprintf(stderr, "Let's find files at share's root :\n");

+ 1 - 1
bin/lookup.c

@@ -43,7 +43,7 @@ int main(int ac, char **av)
     exit(1);
   }
 
-  if (0 != netbios_ns_resolve(ctx->ns, av[1], NETBIOS_FILESERVER, &addr.s_addr)) {
+  if (!netbios_ns_resolve(ctx->ns, av[1], NETBIOS_FILESERVER, &addr.s_addr)) {
     exit(-1);
   }
   if (!addr.s_addr)

+ 1 - 1
include/bdsm/netbios_defs.h

@@ -31,7 +31,7 @@
 #define NETBIOS_MESSENGER     0x03
 #define NETBIOS_FILESERVER    0x20
 #define NETBIOS_DOMAINMASTER  0x1b
-        // http://ubiqx.org/cifs/rfc-draft/rfc1001.html#s17.2
+// http://ubiqx.org/cifs/rfc-draft/rfc1001.html#s17.2
 #define NETBIOS_WILDCARD      { 32, 'C', 'K', 'A', 'A', 'A', 'A', 'A', 'A',    \
     'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', \
     'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 0 }

+ 2 - 0
include/bdsm/netbios_ns.h

@@ -143,6 +143,8 @@ int             netbios_ns_entry_count(netbios_ns_t *ns);
  * creation of the name service object or the last call to clear
  *
  * @param ns The nameservice object.
+ * @param post The index/position of the item to access in the list. Must be <
+ * netbios_ns_entry_count(ns) or the pointer returned will be NULL.
  * @return A pointer to a opaque netbios_ns_entry_t structure
  */
 netbios_ns_entry_t *netbios_ns_entry_at(netbios_ns_t *ns, int pos);

+ 2 - 6
include/bdsm/smb_share.h

@@ -22,12 +22,8 @@
 #include "bdsm/smb_session.h"
 #include "bdsm/smb_file.h"
 
-typedef struct  smb_share_list_s
-{
-  char                name[32];
-}               smb_share_list_t;
-
-size_t          smb_share_list(smb_session_t *s, smb_share_list_t **list);
+size_t          smb_share_list(smb_session_t *s, char ***list);
+void            smb_share_list_destroy(char **list);
 smb_tid         smb_tree_connect(smb_session_t *s, const char *name);
 int             smb_tree_disconnect(smb_session_t *s, smb_tid tid);
 

+ 25 - 27
src/netbios_ns.c

@@ -128,8 +128,8 @@ int               netbios_ns_send_query(netbios_ns_t *ns, netbios_query_t *q,
 }
 
 ssize_t           netbios_ns_recv(int sock, void *buf, size_t buf_size,
-                                 struct timeval *timeout, struct sockaddr *addr,
-                                 socklen_t *addr_len)
+                                  struct timeval *timeout, struct sockaddr *addr,
+                                  socklen_t *addr_len)
 {
   fd_set        read_fds, error_fds;
   int           res;
@@ -224,18 +224,37 @@ int      netbios_ns_resolve(netbios_ns_t *ns, const char *name, char type, uint3
   return (0);
 }
 
+// We have a small recursive function for discovery, to stack received reply
+// when descending, and performing reverse lookup when ascending
+static void   netbios_ns_discover_rec(netbios_ns_t *ns, struct timeval *timeout,
+                                      void *recv_buffer)
+{
+  struct sockaddr_in  recv_addr;
+  socklen_t           recv_addr_len;
+  int                 res;
+
+  recv_addr_len = sizeof(recv_addr);
+  res = netbios_ns_recv(ns->socket, recv_buffer, 256, timeout,
+                        (struct sockaddr *)&recv_addr, &recv_addr_len);
+  if (res > 0 && timeout->tv_sec && timeout->tv_usec)
+  {
+    netbios_ns_discover_rec(ns, timeout, recv_buffer);
+
+    BDSM_dbg("Discover: received a reply from %s\n",
+      inet_ntoa(recv_addr.sin_addr));
+    netbios_ns_inverse(ns, recv_addr.sin_addr.s_addr);
+  }
+}
 
 int           netbios_ns_discover(netbios_ns_t *ns)
 {
   const char  broadcast_name[] = NETBIOS_WILDCARD;
   char        footer[4]        = { 0x00, 0x20, 0x00, 0x01 };
 
-  struct sockaddr_in  recv_addr;
-  socklen_t           recv_addr_len;
   struct timeval      timeout;
 
   netbios_query_t     *q;
-  char                recv_buffer[512]; // Hu ?
+  char                recv_buffer[256]; // Hu ?
   ssize_t             recv;
   uint32_t            ip;
 
@@ -269,30 +288,9 @@ int           netbios_ns_discover(netbios_ns_t *ns)
   //
   // Second step, we list every IP that answered to our broadcast.
   //
-
-  // XXX This shit is buggy. We need to stack received messages first, then
-  // perform the inverse query. Or else we trigger the 'Not a reply to our
-  // query' branch :-/
-
   timeout.tv_sec = 2;
   timeout.tv_usec = 420;
-  recv_addr_len = sizeof(recv_addr);
-  while (netbios_ns_recv(ns->socket, (void *)recv_buffer, 512,
-    &timeout, (struct sockaddr *)&recv_addr, &recv_addr_len) > 0)
-  {
-    // Verify this is a reply to our request
-    if (ntohs(*(uint16_t *)recv_buffer) != ns->last_trn_id)
-    {
-      BDSM_dbg("Not a reply to our query: %u (our trn_id was: %u)\n",
-              ntohs(*(uint16_t * )recv_buffer), ns->last_trn_id);
-    }
-    else // Add the ip to the list of IP to check
-    {
-      netbios_ns_inverse(ns, recv_addr.sin_addr.s_addr);
-      BDSM_dbg("Discover: received a reply from %s\n",
-              inet_ntoa(recv_addr.sin_addr));
-    }
-  }
+  netbios_ns_discover_rec(ns, &timeout, (void *)recv_buffer);
 
   return (1);
 }

+ 2 - 0
src/netbios_ns_entry.c

@@ -104,6 +104,8 @@ netbios_ns_entry_t *netbios_ns_entry_find(netbios_ns_t *ns, const char *by_name,
     }
     else if (iter->address.s_addr == ip)
       found = iter;
+
+    iter = iter->next;
   }
 
   return (found);

+ 16 - 10
src/smb_share.c

@@ -100,13 +100,10 @@ int           smb_tree_disconnect(smb_session_t *s, smb_tid tid)
 
 // Here we parse the NetShareEnumAll response packet payload to extract
 // The share list.
-// We are assuming share name are limited to 16 characters
-static size_t   smb_share_parse_enum(smb_message_t *msg,
-                                     smb_share_list_t **list)
+static size_t   smb_share_parse_enum(smb_message_t *msg, char ***list)
 {
   uint32_t          share_count, i;
   uint8_t           *data, *eod;
-  smb_share_list_t  *s;
 
   assert(msg != NULL && list != NULL);
   // Let's skip smb parameters and DCE/RPC stuff until we are at the begginning of
@@ -116,8 +113,8 @@ static size_t   smb_share_parse_enum(smb_message_t *msg,
   data        = msg->packet->payload + 72 + share_count * 12;
   eod         = msg->packet->payload + msg->payload_size;
 
-  s = calloc(share_count, sizeof(smb_share_list_t));
-  assert (s != NULL);
+  *list       = calloc(share_count + 1, sizeof(char *));
+  assert(*list != NULL);
 
   for (i = 0; i < share_count && data < eod; i++)
   {
@@ -125,7 +122,9 @@ static size_t   smb_share_parse_enum(smb_message_t *msg,
 
     name_len = *((uint32_t *)data);   // Read 'Max Count', make it a multiple of 2
     data    += 3 * sizeof(uint32_t);  // Move pointer to beginning of Name.
-    memcpy(s[i].name, data, name_len * 2); // Those are unicode strings.
+
+    smb_from_utf16(data, name_len * 2, (*list) + i);
+
     if (name_len % 2) name_len += 1;  // Align next move
     data    += name_len * 2;          // Move the pointer to Comment 'Max count'
 
@@ -135,15 +134,22 @@ static size_t   smb_share_parse_enum(smb_message_t *msg,
     data    += com_len * 2;           // Move the pointer to next item
   }
 
-  *list = s;
-
   return (i);
 }
 
+void            smb_share_list_destroy(char **list)
+{
+  assert(list != NULL);
+
+  for (size_t i; list[i] != NULL; i++)
+    free(list[i]);
+  free(list);
+}
+
 // We should normally implement SCERPC and SRVSVC to perform a share list. But
 // since these two protocols have no other use for us, we'll do it the trash way
 // PS: Worst function _EVER_. I don't understand a bit myself
-size_t          smb_share_list(smb_session_t *s, smb_share_list_t **list)
+size_t          smb_share_list(smb_session_t *s, char ***list)
 {
   smb_message_t         *req, resp;
   smb_trans_req_t       *trans;