Przeglądaj źródła

Split packets format code to its own header file. '''Implement''' the first stage of server share listing

Julien 'Lta' BALLET 11 lat temu
rodzic
commit
61609b0e6e

+ 13 - 13
Makefile

@@ -14,7 +14,7 @@
 ## permitted by applicable law. You can redistribute it and/or modify it under
 ## the terms of the Do What The Fuck You Want To Public License, Version 2, as
 ## published by Sam Hocevar. See the COPYING file for more details.
-	##----------------------------------------------------------------------------
+##----------------------------------------------------------------------------
 
 
 
@@ -26,18 +26,18 @@ UTIL				= dsm
 LIB					= libdsm.so
 
 UTIL_SRC		= dsm.c 							    \
-							src/netbios_utils.c	    \
-							src/netbios_ns.c		    \
-							src/netbios_ns_entry.c	\
-							src/netbios_query.c     \
-							src/netbios_session.c		\
-							src/smb_utils.c					\
-							src/smb_message.c				\
-							src/smb_session.c				\
-							src/smb_ntlm.c					\
-							src/smb_share.c					\
-							src/smb_file.c					\
-							src/context.c
+			src/netbios_utils.c				\
+			src/netbios_ns.c				\
+			src/netbios_ns_entry.c				\
+			src/netbios_query.c				\
+			src/netbios_session.c				\
+			src/smb_utils.c					\
+			src/smb_message.c				\
+			src/smb_session.c				\
+			src/smb_ntlm.c					\
+			src/smb_share.c					\
+			src/smb_file.c					\
+			src/context.c
 
 UTIL_OBJS		= $(UTIL_SRC:.c=.o)
 

+ 21 - 9
dsm.c

@@ -21,6 +21,8 @@
 #include <string.h>
 #include <assert.h>
 #include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <errno.h>
 
 #include <sys/socket.h>
@@ -97,7 +99,7 @@ int main(int ac, char **av)
     exit(42);
   }
 
-  smb_tid ipc  = smb_tree_connect(session, "\\\\CERBERE\\IPC$");
+  smb_tid ipc  = smb_tree_connect(session, "IPC$");
 
   if (ipc == 0)
   {
@@ -106,7 +108,7 @@ int main(int ac, char **av)
   }
   fprintf(stderr, "Connected to IPC$ share\n");
 
-  smb_tid test = smb_tree_connect(session, "\\\\CERBERE\\TEST");
+  smb_tid test = smb_tree_connect(session, "TEST");
   if (test)
     fprintf(stderr, "Connected to Test share\n");
   else
@@ -115,24 +117,34 @@ int main(int ac, char **av)
     exit(42);
   }
 
-  smb_fd fd = smb_fopen(session, test, "\\test.txt", SMB_MOD_RO);
+  smb_fd fd = smb_fopen(session, test, "\\test.avi", SMB_MOD_RO);
   if (fd)
-    fprintf(stderr, "Successfully opened \\test.txt: fd = 0x%.8x\n", fd);
+    fprintf(stderr, "Successfully opened \\test.avi: fd = 0x%.8x\n", fd);
   else
   {
-    fprintf(stderr, "Unable to open \\test.txt\n");
+    fprintf(stderr, "Unable to open \\test.avi\n");
     exit(42);
   }
 
-  char    data[512];
+  char              data[1024];
+  smb_share_list_t  *share_list;
 
-  memset(data, 0, 512);
-  smb_fread(session, fd, data, 512);
 
+  smb_fread(session, fd, data, 1024);
   fprintf(stderr, "Read from file:\n%s\n", data);
-
   smb_fclose(session, fd);
 
+  if (!smb_share_list(session, &share_list))
+  {
+    fprintf(stderr, "Unable to list share for %s\n", av[1]);
+    exit(42);
+  }
+  else
+  {
+    fprintf(stderr, "Share list : \n");
+  }
+
+
   smb_session_destroy(session);
   bdsm_context_destroy(ctx);
 

+ 2 - 213
include/bdsm/smb_defs.h

@@ -19,7 +19,7 @@
 #ifndef __BSDM_SMB_DEFS_H_
 #define __BSDM_SMB_DEFS_H_
 
-#include <stdint.h>
+#include <bdsm/smb_packets.h>
 
 #define SMB_MAGIC               { 0xff, 0x53, 0x4d, 0x42 } // aka "\xffSMB"
 
@@ -34,6 +34,7 @@
 #define SMB_DIALECT_NTLM        1
 
 #define SMB_CMD_CLOSE           0x04
+#define SMD_CMD_TRANS           0x25
 #define SMB_CMD_TRANS2          0x32
 #define SMB_CMD_TREE_DISCONNECT 0x71
 #define SMB_CMD_NEGOTIATE       0x72
@@ -139,217 +140,5 @@
 #define NT_STATUS_MORE_PROCESSING_REQUIRED  0xc0000016
 #define NT_STATUS_ACCESS_DENIED             0xc0000022
 
-#define SMB_ANDX_MEMBERS  \
-  uint8_t         andx;           /* 0xff when no other command (do this :)*/  \
-  uint8_t         andx_reserved;  /* 0x00 */                                   \
-  uint16_t        andx_offset;    /* 0x00 when no other command */
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Individual SMB command payload description
-
-
-//// Negotiate Protocol
-
-typedef struct
-{
-  uint8_t         wct; // zero
-  uint16_t        bct;
-  char            dialects[];
-
-} __attribute__((packed))   smb_negotiate_req_t;
-
-typedef struct
-{
-  uint8_t         wct;            // +-17 :)
-  uint16_t        dialect_index;  //
-  uint8_t         security_mode;  // Share/User. Plaintext/Challenge
-  uint32_t        diplodocus;
-  uint32_t        max_bufsize;    // Max buffer size requested by server.
-  uint32_t        max_rawbuffer;  // Max raw buffer size requested by serv.
-  uint32_t        session_key;    // 'MUST' be returned to server
-  uint32_t        caps;
-  uint64_t        ts;             // I don't give a fuck (or do i?)
-  uint16_t        tz;             // Even less fuck given
-  uint8_t         key_length;     // Size of challenge key, if != 8 then shit
-  uint16_t        bct;
-  uint64_t        challenge;      // Normally 8 bytes, if not then wtf monkey
-  uint8_t         payload[];      // The rest isn't really meaningfull for us
-} __attribute__((packed))   smb_negotiate_resp_t;
-
-
-
-//// Session Setup
-
-typedef struct
-{
-  uint8_t         wct;          // +-13 :)
-  SMB_ANDX_MEMBERS
-  uint16_t        max_buffer;   // Maximum size we can receive
-  uint16_t        mpx_count;    // maximum multiplexed session
-  uint16_t        vc_count;     // Virtual ciruits -> 1!
-  uint32_t        session_key;  // 0x00000000
-  uint16_t        oem_pass_len; // Length of LM2 response
-  uint16_t        uni_pass_len; // Length of NTLM2 response
-  uint32_t        reserved2;    // 0x00000000
-  uint32_t        caps;         // Capabilities
-  uint16_t        payload_size;
-  uint8_t         payload[];
-} __attribute__((packed))   smb_session_req_t;
-
-typedef struct
-{
-  uint8_t         wct;
-  SMB_ANDX_MEMBERS
-  uint16_t        action;
-  uint16_t        bct;
-  uint8_t         bullshit[];
-} __attribute__((packed))   smb_session_resp_t;
-
-
-
-//// Tree Connect
-
-typedef struct
-{
-  uint8_t         wct;              // 4
-  SMB_ANDX_MEMBERS
-  uint16_t        flags;
-  uint16_t        passwd_len;       // 1 if not used. Used in Share Level Auth
-  uint16_t        bct;
-  uint8_t         payload[];        // Password | Path | Service
-
-} __attribute__((packed))   smb_tree_connect_req_t;
-
-typedef struct
-{
-  uint8_t         wct;              // 7
-  SMB_ANDX_MEMBERS
-  uint16_t        opt_support;
-  uint32_t        max_rights;
-  uint32_t        guest_rights;
-  uint16_t        bct;
-  uint8_t         payload[];
-} __attribute__((packed))   smb_tree_connect_resp_t;
-
-
-
-//// Create (or Open) File
-
-typedef struct
-{
-  uint8_t         wct;                // 24
-  SMB_ANDX_MEMBERS
-  uint8_t         reserved2;
-  uint16_t        path_length;
-  uint32_t        flags;
-  uint32_t        root_fid;
-  uint32_t        access_mask;
-  uint64_t        alloc_size;
-  uint32_t        file_attr;
-  uint32_t        share_access;
-  uint32_t        disposition;
-  uint32_t        create_opts;
-  uint32_t        impersonation;
-  uint8_t         security_flags;
-  uint16_t        bct;
-  uint8_t         path[];             // UTF16 Path, starting with '\'
-} __attribute__((packed))   smb_create_req_t;
-
-typedef struct
-{
-  uint8_t         wct;                // 34
-  SMB_ANDX_MEMBERS
-  uint8_t         oplock_level;
-  uint16_t        fid;
-  uint32_t        action;
-  uint64_t        created;            // File creation time
-  uint64_t        accessed;           // File last access time
-  uint64_t        written;            // File last write time
-  uint64_t        changed;            // File last modification time
-  uint32_t        attr;
-  uint64_t        alloc_size;
-  uint64_t        size;
-  uint16_t        filetype;
-  uint16_t        ipc_state;
-  uint8_t         is_dir;
-  uint16_t        bct;                // 0
-} __attribute__((packed))   smb_create_resp_t;
-
-
-
-//// Close File
-
-typedef struct
-{
-  uint8_t         wct;                // 3
-  uint16_t        fid;
-  uint32_t        last_write;         // Not defined == 0xffffffff
-  uint16_t        bct;                // 0
-} __attribute__((packed))   smb_close_req_t;
-
-
-
-//// Read File
-
-typedef struct
-{
-  uint8_t         wct;                // 12
-  SMB_ANDX_MEMBERS
-  uint16_t        fid;
-  uint32_t        offset;
-  uint16_t        max_count;
-  uint16_t        min_count;
-  uint32_t        max_count_high;     // Continuation of max_count field
-  uint16_t        remaining;
-  uint32_t        offset_high;        // Continuation of offset field'
-  uint16_t        bct;                // 0
-} __attribute__((packed))   smb_read_req_t;
-
-typedef struct
-{
-  uint8_t         wct;                // 12
-  SMB_ANDX_MEMBERS
-  uint16_t        remaining;
-  uint16_t        compact_mode;
-  uint16_t        reserved;
-  uint16_t        data_len;
-  uint16_t        data_offset;
-  uint32_t        data_len_high;
-  uint32_t        reserved2;
-  uint16_t        reserved3;
-  uint16_t        bct;
-  uint8_t         padding;
-  uint8_t         file[];
-} __attribute__((packed))   smb_read_resp_t;
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Main structures for holding packet data and building packets
-
-typedef struct
-{
-  uint8_t         magic[4];     // { 0xff, 0x53, 0x4d, 0x42 } "\xffSMB"
-  uint8_t         command;      // The actual SMB command
-  uint32_t        status;       // 'NT Status'
-  uint8_t         flags;        // Packet flags
-  uint16_t        flags2;       // More flags ? (lol)
-  uint16_t        pid_high;     // Unused ?
-  uint64_t        signature;    // Unused ?
-  uint16_t        reserved;     // More usuned bit (we have so much BW :)
-  uint16_t        tid;          // A kind of fd for share. (tree_connect)
-  uint16_t        pid;          // Process ID.
-  uint16_t        uid;          // User ID.
-  uint16_t        mux_id;       // Multiplex ID. Increment it sometimes.
-} __attribute__((packed))       smb_header_t;
-
-typedef struct
-{
-  smb_header_t    header;       // A packet header full of gorgeous goodness.
-  uint8_t         payload[];    // Ze yummy data inside. Eat 5 fruits/day !
-} __attribute__((packed))       smb_packet_t;
-
 
 #endif

+ 1 - 1
include/bdsm/smb_file.h

@@ -22,7 +22,7 @@
 #include "bdsm/smb_session.h"
 
 smb_fd    smb_fopen(smb_session_t *s, smb_tid tid, const char *path,
-                   uint32_t mod);
+                    uint32_t mod);
 void      smb_fclose(smb_session_t *s, smb_fd);
 ssize_t   smb_fread(smb_session_t *s, smb_fd fd, void *buf, size_t buf_size);
 ssize_t   smb_fseek(smb_session_t *s, smb_fd fd, ssize_t offset, int whence);

+ 3 - 1
include/bdsm/smb_message.h

@@ -38,9 +38,11 @@ int             smb_message_append(smb_message_t *msg, const void *data,
 int             smb_message_put8(smb_message_t *msg, uint8_t data);
 int             smb_message_put16(smb_message_t *msg, uint16_t data);
 int             smb_message_put32(smb_message_t *msg, uint32_t data);
-int             smb_message_put64(smb_message_t *msg, uint32_t data);
+int             smb_message_put64(smb_message_t *msg, uint64_t data);
 size_t          smb_message_put_utf16(smb_message_t *msg, const char *src_enc,
                                       const char *str, size_t str_len);
+int             smb_message_put_uuid(smb_message_t *msg, uint32_t a, uint16_t b,
+                                     uint16_t c, const uint8_t e[8]);
 
 void            smb_message_set_default_flags(smb_message_t *msg);
 void            smb_message_set_andx_members(smb_message_t *msg);

+ 275 - 0
include/bdsm/smb_packets.h

@@ -0,0 +1,275 @@
+//---------------------------------------------------------------------------
+//  __________________    _________  _____            _____  .__         ._.
+//  \______   \______ \  /   _____/ /     \          /  _  \ |__| ____   | |
+//   |    |  _/|    |  \ \_____  \ /  \ /  \        /  /_\  \|  _/ __ \  | |
+//   |    |   \|    `   \/        /    Y    \      /    |    |  \  ___/   \|
+//   |______  /_______  /_______  \____|__  / /\   \____|__  |__|\___ |   __
+//          \/        \/        \/        \/  )/           \/        \/   \/
+//
+// This file is part of libdsm. Copyright © 2014 VideoLabs SAS
+//
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+//
+// This program is free software. It comes without any warranty, to the extent
+// permitted by applicable law. You can redistribute it and/or modify it under
+// the terms of the Do What The Fuck You Want To Public License, Version 2, as
+// published by Sam Hocevar. See the COPYING file for more details.
+//----------------------------------------------------------------------------
+
+#ifndef __BSDM_SMB_PACKETS_H_
+#define __BSDM_SMB_PACKETS_H_
+
+#include <stdint.h>
+
+#define SMB_ANDX_MEMBERS  \
+  uint8_t         andx;           /* 0xff when no other command (do this :)*/  \
+  uint8_t         andx_reserved;  /* 0x00 */                                   \
+  uint16_t        andx_offset;    /* 0x00 when no other command */
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Main structures for holding packet data and building packets
+
+typedef struct
+{
+  uint8_t         magic[4];     // { 0xff, 0x53, 0x4d, 0x42 } "\xffSMB"
+  uint8_t         command;      // The actual SMB command
+  uint32_t        status;       // 'NT Status'
+  uint8_t         flags;        // Packet flags
+  uint16_t        flags2;       // More flags ? (lol)
+  uint16_t        pid_high;     // Unused ?
+  uint64_t        signature;    // Unused ?
+  uint16_t        reserved;     // More usuned bit (we have so much BW :)
+  uint16_t        tid;          // A kind of fd for share. (tree_connect)
+  uint16_t        pid;          // Process ID.
+  uint16_t        uid;          // User ID.
+  uint16_t        mux_id;       // Multiplex ID. Increment it sometimes.
+} __attribute__((packed))       smb_header_t;
+
+typedef struct
+{
+  smb_header_t    header;       // A packet header full of gorgeous goodness.
+  uint8_t         payload[];    // Ze yummy data inside. Eat 5 fruits/day !
+} __attribute__((packed))       smb_packet_t;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Individual SMB command payload description
+
+//-> Negotiate Protocol
+typedef struct
+{
+  uint8_t         wct; // zero
+  uint16_t        bct;
+  char            dialects[];
+
+} __attribute__((packed))   smb_negotiate_req_t;
+
+//<- Negotiate Protocol
+typedef struct
+{
+  uint8_t         wct;            // +-17 :)
+  uint16_t        dialect_index;  //
+  uint8_t         security_mode;  // Share/User. Plaintext/Challenge
+  uint32_t        diplodocus;
+  uint32_t        max_bufsize;    // Max buffer size requested by server.
+  uint32_t        max_rawbuffer;  // Max raw buffer size requested by serv.
+  uint32_t        session_key;    // 'MUST' be returned to server
+  uint32_t        caps;
+  uint64_t        ts;             // I don't give a fuck (or do i?)
+  uint16_t        tz;             // Even less fuck given
+  uint8_t         key_length;     // Size of challenge key, if != 8 then shit
+  uint16_t        bct;
+  uint64_t        challenge;      // Normally 8 bytes, if not then wtf monkey
+  uint8_t         payload[];      // The rest isn't really meaningfull for us
+} __attribute__((packed))   smb_negotiate_resp_t;
+
+
+
+//-> Session Setup
+typedef struct
+{
+  uint8_t         wct;          // +-13 :)
+  SMB_ANDX_MEMBERS
+  uint16_t        max_buffer;   // Maximum size we can receive
+  uint16_t        mpx_count;    // maximum multiplexed session
+  uint16_t        vc_count;     // Virtual ciruits -> 1!
+
+  uint32_t        session_key;  // 0x00000000
+  uint16_t        oem_pass_len; // Length of LM2 response
+  uint16_t        uni_pass_len; // Length of NTLM2 response
+  uint32_t        reserved2;    // 0x00000000
+  uint32_t        caps;         // Capabilities
+  uint16_t        payload_size;
+  uint8_t         payload[];
+} __attribute__((packed))   smb_session_req_t;
+
+//<- Session Setup
+typedef struct
+{
+  uint8_t         wct;
+  SMB_ANDX_MEMBERS
+  uint16_t        action;
+  uint16_t        bct;
+  uint8_t         bullshit[];
+} __attribute__((packed))   smb_session_resp_t;
+
+
+
+//-> Tree Connect
+typedef struct
+{
+  uint8_t         wct;              // 4
+  SMB_ANDX_MEMBERS
+  uint16_t        flags;
+  uint16_t        passwd_len;       // 1 if not used. Used in Share Level Auth
+  uint16_t        bct;
+  uint8_t         payload[];        // Password | Path | Service
+
+} __attribute__((packed))   smb_tree_connect_req_t;
+
+//<- Tree Connect
+typedef struct
+{
+  uint8_t         wct;              // 7
+  SMB_ANDX_MEMBERS
+  uint16_t        opt_support;
+  uint32_t        max_rights;
+  uint32_t        guest_rights;
+  uint16_t        bct;
+  uint8_t         payload[];
+} __attribute__((packed))   smb_tree_connect_resp_t;
+
+
+
+//-> Create File
+typedef struct
+{
+  uint8_t         wct;                // 24
+  SMB_ANDX_MEMBERS
+  uint8_t         reserved2;
+  uint16_t        path_length;
+  uint32_t        flags;
+  uint32_t        root_fid;
+  uint32_t        access_mask;
+  uint64_t        alloc_size;
+  uint32_t        file_attr;
+  uint32_t        share_access;
+  uint32_t        disposition;
+  uint32_t        create_opts;
+  uint32_t        impersonation;
+  uint8_t         security_flags;
+  uint16_t        bct;
+  uint8_t         path[];             // UTF16 Path, starting with '\'
+} __attribute__((packed))   smb_create_req_t;
+
+//<- Create File
+typedef struct
+{
+  uint8_t         wct;                // 34
+  SMB_ANDX_MEMBERS
+  uint8_t         oplock_level;
+  uint16_t        fid;
+  uint32_t        action;
+  uint64_t        created;            // File creation time
+  uint64_t        accessed;           // File last access time
+  uint64_t        written;            // File last write time
+  uint64_t        changed;            // File last modification time
+  uint32_t        attr;
+  uint64_t        alloc_size;
+  uint64_t        size;
+  uint16_t        filetype;
+  uint16_t        ipc_state;
+  uint8_t         is_dir;
+  uint16_t        bct;                // 0
+} __attribute__((packed))   smb_create_resp_t;
+
+
+
+//-> Close File
+typedef struct
+{
+  uint8_t         wct;                // 3
+  uint16_t        fid;
+  uint32_t        last_write;         // Not defined == 0xffffffff
+  uint16_t        bct;                // 0
+} __attribute__((packed))   smb_close_req_t;
+
+
+
+//-> Read File
+typedef struct
+{
+  uint8_t         wct;                // 12
+  SMB_ANDX_MEMBERS
+  uint16_t        fid;
+  uint32_t        offset;
+  uint16_t        max_count;
+  uint16_t        min_count;
+  uint32_t        max_count_high;     // Continuation of max_count field
+  uint16_t        remaining;
+  uint32_t        offset_high;        // Continuation of offset field'
+  uint16_t        bct;                // 0
+} __attribute__((packed))   smb_read_req_t;
+
+//<- Read File
+typedef struct
+{
+  uint8_t         wct;                // 12
+  SMB_ANDX_MEMBERS
+  uint16_t        remaining;
+  uint16_t        compact_mode;
+  uint16_t        reserved;
+  uint16_t        data_len;
+  uint16_t        data_offset;
+  uint32_t        data_len_high;
+  uint32_t        reserved2;
+  uint16_t        reserved3;
+  uint16_t        bct;
+  uint8_t         padding;
+  uint8_t         file[];
+} __attribute__((packed))   smb_read_resp_t;
+
+//-> Trans
+typedef struct
+{
+  uint8_t       wct;                    // 16
+  uint16_t      total_param_count;
+  uint16_t      total_data_count;
+  uint16_t      max_param_count;
+  uint16_t      max_data_count;
+  uint8_t       max_setup_count;
+  uint8_t       reserved;
+  uint16_t      flags;
+  uint32_t      timeout;
+  uint16_t      reserved2;
+  uint16_t      param_count;
+  uint16_t      param_offset;
+  uint16_t      data_count;
+  uint16_t      data_offset;
+  uint8_t       setup_count;
+  uint8_t       reserved3;
+  uint16_t      pipe_function;
+  uint16_t      fid;
+  uint16_t      bct;
+  uint8_t       padding;
+  uint8_t       payload[];
+} __attribute__((packed))   smb_trans_req_t;
+
+
+
+
+
+//-> Example
+typedef struct
+{
+  uint8_t         wct;                // ??
+  SMB_ANDX_MEMBERS
+  // Fill me
+  uint16_t        bct;
+  //uint8_t         padding;
+  uint8_t         file[];
+} __attribute__((packed))   smb_example_t;
+
+
+#endif

+ 8 - 2
include/bdsm/smb_session.h

@@ -19,10 +19,12 @@
 #ifndef __BDSM_SMB_SESSION_H_
 #define __BDSM_SMB_SESSION_H_
 
+
 #include "bdsm/netbios_session.h"
 #include "bdsm/smb_defs.h"
 #include "bdsm/smb_message.h"
 
+
 #define SMB_STATE_SESSION_OK    3 // We are authenticated and can do stuff
 #define SMB_STATE_DIALECT_OK    2
 #define SMB_STATE_NETBIOS_OK    1
@@ -56,6 +58,7 @@ typedef struct smb_file_s
   uint64_t            size;
   uint32_t            attr;
   uint32_t            readp;          // Current read pointer (position);
+  int                 is_dir;         // 0 -> file, 1 -> directory
 } smb_file_t;
 
 typedef struct smb_share_s
@@ -65,7 +68,7 @@ typedef struct smb_share_s
   uint16_t            opts;           // Optionnal support opts
   uint16_t            rights;         // Maximum rights field
   uint16_t            guest_rights;
-  smb_file_t          *files;         // List of all open files for this share
+  struct smb_file_s   *files;         // List of all open files for this share
 } smb_share_t;
 
 typedef struct
@@ -77,6 +80,7 @@ typedef struct
 
   // Informations about the smb server we are connected to.
   struct {
+    char                name[16];       // The server name
     uint16_t            dialect;        // The selected dialect
     uint16_t            security_mode;  // Security mode
     uint32_t            caps;           // Server caps replyed during negotiate
@@ -85,10 +89,12 @@ typedef struct
     uint64_t            ts;             // It seems Win7 requires it :-/
   }                   srv;
 
-  smb_share_t         *shares;          // shares->files | Map fd <-> smb_file_t
+  struct smb_share_s  *shares;          // shares->files | Map fd <-> smb_file_t
 }                   smb_session_t;
 
 
+
+
 smb_session_t   *smb_session_new();
 void            smb_session_destroy(smb_session_t *s);
 

+ 8 - 1
include/bdsm/smb_share.h

@@ -20,8 +20,15 @@
 #define __BDSM_SMB_SHARE_H_
 
 #include "bdsm/smb_session.h"
+#include "bdsm/smb_file.h"
 
-smb_tid         smb_tree_connect(smb_session_t *s, const char *path);
+typedef struct  smb_share_list_s
+{
+  char                name[16];
+}               smb_share_list_t;
+
+size_t          smb_share_list(smb_session_t *s, smb_share_list_t **list);
+smb_tid         smb_tree_connect(smb_session_t *s, const char *name);
 int             smb_tree_disconnect(smb_session_t *s, smb_tid tid);
 
 #endif

+ 1 - 0
src/smb_file.c

@@ -92,6 +92,7 @@ smb_fd      smb_fopen(smb_session_t *s, smb_tid tid, const char *path,
   file->alloc_size    = resp->alloc_size;
   file->size          = resp->size;
   file->attr          = resp->attr;
+  file->is_dir        = resp->is_dir;
 
   smb_session_file_add(s, tid, file); // XXX Check return
 

+ 19 - 1
src/smb_message.c

@@ -100,7 +100,7 @@ int             smb_message_put32(smb_message_t *msg, uint32_t data)
     return(smb_message_append(msg, (void *)&data, 4));
 }
 
-int             smb_message_put64(smb_message_t *msg, uint32_t data)
+int             smb_message_put64(smb_message_t *msg, uint64_t data)
 {
     return(smb_message_append(msg, (void *)&data, 8));
 }
@@ -121,6 +121,24 @@ size_t          smb_message_put_utf16(smb_message_t *msg, const char *src_enc,
   return (0);
 }
 
+int             smb_message_put_uuid(smb_message_t *msg, uint32_t a, uint16_t b,
+                                     uint16_t c, const uint8_t d[8])
+{
+  assert(msg != NULL);
+
+  if (!smb_message_put32(msg, a))
+    return (0);
+  if (!smb_message_put16(msg, b))
+    return (0);
+  if (!smb_message_put16(msg, c))
+    return (0);
+  for (int i = 0; i < 8; i++)
+    if (!smb_message_put8(msg, d[i]))
+      return (0);
+
+  return (1);
+}
+
 void            smb_message_flag(smb_message_t *msg, uint32_t flag, int value)
 {
   uint32_t      *flags;

+ 1 - 0
src/smb_session.c

@@ -54,6 +54,7 @@ int             smb_session_connect(smb_session_t *s, char *name, uint32_t ip)
   if (!netbios_session_connect(s->nb_session, name))
     goto error;
 
+  memcpy(s->srv.name, name, strlen(name) + 1);
   s->state = SMB_STATE_NETBIOS_OK;
   return (1);
 

+ 124 - 3
src/smb_share.c

@@ -24,17 +24,25 @@
 
 #include "bdsm/smb_utils.h"
 #include "bdsm/smb_share.h"
+#include "bdsm/smb_file.h"
 
 
-smb_tid         smb_tree_connect(smb_session_t *s, const char *path)
+smb_tid         smb_tree_connect(smb_session_t *s, const char *name)
 {
   smb_tree_connect_req_t  *req;
   smb_tree_connect_resp_t *resp;
   smb_message_t   resp_msg;
   smb_message_t   *req_msg;
   smb_share_t     *share;
+  size_t          path_len;
+  char            *path;
 
-  assert(s != NULL && path != NULL);
+  assert(s != NULL && name != NULL);
+
+  // Build \\SERVER\Share path from name
+  path_len  = strlen(name) + strlen(s->srv.name) + 4;
+  path      = alloca(path_len);
+  snprintf(path, path_len, "\\\\%s\\%s", s->srv.name, name);
 
   req_msg = smb_message_new(SMB_CMD_TREE_CONNECT, 128);
 
@@ -84,7 +92,120 @@ smb_tid         smb_tree_connect(smb_session_t *s, const char *path)
 int           smb_tree_disconnect(smb_session_t *s, smb_tid tid)
 {
   assert(s != NULL && tid);
-
+  fprintf(stderr, "smb_tree_disconnect: NOT IMPLEMENTED YET\n");
   return (0);
 }
 
+// We should normally implement SCERPC and SRVSVC to perform a share list. But
+// since these two protocols have no other use for use, 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)
+{
+  smb_message_t         *req, resp;
+  smb_trans_req_t       *trans;
+  smb_tid               ipc_tid;
+  smb_fd                srvscv_fd;
+  uint16_t              rpc_len;
+  ssize_t               res;
+
+  assert(s != NULL && list != NULL);
+  *list = NULL;
+
+  ipc_tid = smb_tree_connect(s, "IPC$");
+  if (!ipc_tid)
+    return (0);
+
+  srvscv_fd = smb_fopen(s, ipc_tid, "\\srvsvc", SMB_MOD_RW);
+  if (!srvscv_fd)
+    return (0);
+
+  //// Phase 1:
+  // We bind a context or whatever for DCE/RPC
+
+  req = smb_message_new(SMD_CMD_TRANS, 256);
+  smb_message_set_default_flags(req);
+  req->packet->header.tid = ipc_tid;
+
+  smb_message_advance(req, sizeof(smb_trans_req_t));
+  trans = (smb_trans_req_t *)req->packet->payload;
+
+  memset((void *)trans, 0, sizeof(smb_trans_req_t));
+
+  rpc_len = NETBIOS_SESSION_PAYLOAD - 256; // XXX
+
+  trans->wct                    = 16;
+  trans->total_data_count       = 72;
+  trans->max_data_count         = rpc_len;
+  trans->param_offset           = 84;
+  trans->data_count             = 72;
+  trans->data_offset            = 84;
+  trans->setup_count            = 2;
+  trans->pipe_function          = 0x26;
+  trans->fid                    = SMB_FD_FID(srvscv_fd);
+  trans->bct                    = 89;
+
+  smb_message_put_utf16(req, "", "\\PIPE\\", strlen("\\PIPE\\") + 1);
+  smb_message_put16(req, 0); // Padding to be aligned with wtf boundary :-/
+
+  // Now we'll 'build' the DCE/RPC Packet. This basically a copycat
+  // from wireshark values.
+  smb_message_put8(req, 5);     // version major
+  smb_message_put8(req, 0);     // minor
+  smb_message_put8(req, 0x0b);  // Packet type = 'bind'
+  smb_message_put8(req, 0x03);  // Packet flags = ??
+  smb_message_put32(req, 0x10); // Representation = little endian/ASCII. Damn
+  smb_message_put16(req, 72);   // Data len again
+  smb_message_put16(req, 0);    // Auth len ?
+  smb_message_put32(req, 19);   // Call ID ?
+  smb_message_put16(req, rpc_len);      // Max Xmit size
+  smb_message_put16(req, rpc_len);      // Max Recv size
+  smb_message_put32(req, 0);    // Assoc group ?
+
+  smb_message_put32(req, 1);    // Num Ctx Item
+  // Adding the CtxItem, whatever could that be
+  smb_message_put16(req, 0);    // ContextID
+  smb_message_put16(req, 1);    // Num Trans Item
+  // SRVSVC UUID
+  const uint8_t uuid_e[8] = {0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88};
+  smb_message_put_uuid(req, 0x4b324fc8, 0x1670, 0x01d3, uuid_e);
+  smb_message_put16(req, 3);    // Version
+  smb_message_put16(req, 0);    // Minor
+  // Another UUID
+  const uint8_t uuid_e2[8] = {0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60};
+  smb_message_put_uuid(req, 0x8a885d04, 0x1ceb, 0x11c9, uuid_e2);
+  smb_message_put32(req, 2);    // Another version
+
+  // Let's send this ugly pile of shit over the network !
+  res = smb_session_send_msg(s, req);
+  smb_message_destroy(req);
+  if (!res)
+    return (0);
+
+  // Is the server throwing pile of shit back at me ?
+  res = smb_session_recv_msg(s, &resp);
+  if (!res || resp.packet->payload[68])
+  {
+    if (BDSM_DEBUG)
+      fprintf(stderr, "Bind call failed: 0x%hhx (reason = 0x%hhx)\n",
+              resp.packet->payload[68], resp.packet->payload[70]);
+    return (0);
+  }
+
+
+  //// Phase 2:
+  // Now we have the 'bind' (regarless of what it is), we'll call
+  // NetShareEnumAll
+
+  req = smb_message_new(SMD_CMD_TRANS, 256);
+  smb_message_set_default_flags(req);
+  req->packet->header.tid = ipc_tid;
+
+  smb_message_advance(req, sizeof(smb_trans_req_t));
+  trans = (smb_trans_req_t *)req->packet->payload;
+
+  memset((void *)trans, 0, sizeof(smb_trans_req_t));
+
+
+  return (1);
+}