dcerpc: add example of NetShareGetInfo
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Fri, 6 Mar 2020 01:29:04 +0000 (11:29 +1000)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Mon, 9 Mar 2020 01:49:34 +0000 (11:49 +1000)
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
examples/CMakeLists.txt
examples/Makefile.am
examples/smb2-share-enum.c
examples/smb2-share-info.c [new file with mode: 0644]
include/smb2/libsmb2-dcerpc-srvsvc.h
include/smb2/libsmb2-dcerpc.h
include/smb2/libsmb2.h
lib/dcerpc-srvsvc.c
lib/dcerpc.c
lib/libsmb2.syms
lib/smb2-share-enum.c

index 056377ec2c208fdd31ed894cab1131cd465f32f9..8d79a36a9628f1ae0028e9b98105952070e846a4 100644 (file)
@@ -11,6 +11,7 @@ set(SOURCES smb2-cat-async
             smb2-raw-getsd-async
             smb2-readlink
             smb2-share-enum
+            smb2-share-info
             smb2-stat-sync
             smb2-truncate-sync)
 
index df734d9481db31a76135c911b89a52f8a5b86d37..7a1b78fd2f705602cd53b5f81862f91c7563f5e4 100644 (file)
@@ -8,6 +8,7 @@ noinst_PROGRAMS = smb2-cat-async smb2-cat-sync \
        smb2-raw-stat-async \
        smb2-readlink \
        smb2-share-enum \
+       smb2-share-info \
        smb2-stat-sync \
        smb2-statvfs-sync \
        smb2-truncate-sync
@@ -31,6 +32,7 @@ smb2_raw_getsd_async_LDADD = $(COMMON_LIBS)
 smb2_raw_stat_async_LDADD = $(COMMON_LIBS)
 smb2_readlink_LDADD = $(COMMON_LIBS)
 smb2_share_enum_LDADD = $(COMMON_LIBS)
+smb2_share_info_LDADD = $(COMMON_LIBS)
 smb2_stat_sync_LDADD = $(COMMON_LIBS)
 smb2_statvfs_sync_LDADD = $(COMMON_LIBS)
 smb2_truncate_sync_LDADD = $(COMMON_LIBS)
index 4c489036ae3de6115c14356ae89d177d9f4253a8..9c2106f9d3a998d9ef98e9a9435fc74c837495db 100644 (file)
@@ -24,6 +24,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 #include "smb2.h"
 #include "libsmb2.h"
 #include "libsmb2-raw.h"
+#include "libsmb2-dcerpc-srvsvc.h"
 
 int is_finished;
 
diff --git a/examples/smb2-share-info.c b/examples/smb2-share-info.c
new file mode 100644 (file)
index 0000000..72493b0
--- /dev/null
@@ -0,0 +1,139 @@
+/* -*-  mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil;  -*- */
+/*
+   Copyright (C) 2020 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define _GNU_SOURCE
+
+#include <inttypes.h>
+#include <poll.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "smb2.h"
+#include "libsmb2.h"
+#include "libsmb2-raw.h"
+#include "libsmb2-dcerpc-srvsvc.h"
+
+int is_finished;
+
+int usage(void)
+{
+        fprintf(stderr, "Usage:\n"
+                "smb2-share-info <smb2-url>\n\n"
+                "URL format: "
+                "smb://[<domain;][<username>@]<host>[:<port>]/share\n");
+        exit(1);
+}
+
+void si_cb(struct smb2_context *smb2, int status,
+                void *command_data, void *private_data)
+{
+        struct srvsvc_netsharegetinfo_rep *rep = command_data;
+
+        if (status) {
+                printf("failed to get info for share (%s) %s\n",
+                       strerror(-status), smb2_get_error(smb2));
+                exit(10);
+        }
+        printf("%-20s %-20s", rep->info->info1.name,
+               rep->info->info1.comment);
+        if ((rep->info->info1.type & 3) == SHARE_TYPE_DISKTREE) {
+                        printf(" DISKTREE");
+        }
+        if ((rep->info->info1.type & 3) == SHARE_TYPE_PRINTQ) {
+                printf(" PRINTQ");
+        }
+        if ((rep->info->info1.type & 3) == SHARE_TYPE_DEVICE) {
+                printf(" DEVICE");
+        }
+        if ((rep->info->info1.type & 3) == SHARE_TYPE_IPC) {
+                printf(" IPC");
+        }
+        if (rep->info->info1.type & SHARE_TYPE_TEMPORARY) {
+                printf(" TEMPORARY");
+        }
+        if (rep->info->info1.type & SHARE_TYPE_HIDDEN) {
+                printf(" HIDDEN");
+        }
+
+        printf("\n");
+        smb2_free_data(smb2, rep);
+
+        is_finished = 1;
+}
+
+int main(int argc, char *argv[])
+{
+        struct smb2_context *smb2;
+        struct smb2_url *url;
+       struct pollfd pfd;
+
+        if (argc < 2) {
+                usage();
+        }
+
+       smb2 = smb2_init_context();
+        if (smb2 == NULL) {
+                fprintf(stderr, "Failed to init context\n");
+                exit(0);
+        }
+
+        url = smb2_parse_url(smb2, argv[1]);
+        if (url == NULL) {
+                fprintf(stderr, "Failed to parse url: %s\n",
+                        smb2_get_error(smb2));
+                exit(0);
+        }
+        if (url->user) {
+                smb2_set_user(smb2, url->user);
+        }
+
+        smb2_set_security_mode(smb2, SMB2_NEGOTIATE_SIGNING_ENABLED);
+
+        if (smb2_connect_share(smb2, url->server, "IPC$", NULL) < 0) {
+               printf("Failed to connect to IPC$. %s\n",
+                       smb2_get_error(smb2));
+               exit(10);
+        }
+
+       if (smb2_share_info_async(smb2, url->share, si_cb, NULL) != 0) {
+               printf("smb2_share_info failed. %s\n", smb2_get_error(smb2));
+               exit(10);
+       }
+
+        while (!is_finished) {
+               pfd.fd = smb2_get_fd(smb2);
+               pfd.events = smb2_which_events(smb2);
+
+               if (poll(&pfd, 1, 1000) < 0) {
+                       printf("Poll failed");
+                       exit(10);
+               }
+                if (pfd.revents == 0) {
+                        continue;
+                }
+               if (smb2_service(smb2, pfd.revents) < 0) {
+                       printf("smb2_service failed with : %s\n",
+                               smb2_get_error(smb2));
+                       break;
+               }
+       }
+
+        smb2_disconnect_share(smb2);
+        smb2_destroy_url(url);
+        smb2_destroy_context(smb2);
+        
+       return 0;
+}
index 83574b48bbb083441568e190eee441ca386bfe73..49a42329688097bab3e58c09cfdd86ae22aa6305 100644 (file)
 extern "C" {
 #endif
 
-#define SRVSVC_NETSHAREENUMALL 15
+#define SRVSVC_NETSHAREENUMALL    0x0f
+#define SRVSVC_NETSHAREGETINFO    0x10
 
 struct dcerpc_context;
 struct dcerpc_pdu;
 
-int srvsvc_netshareenumall_decoder(struct dcerpc_context *dce,
+
+/* Low 2 bits desctibe the type */
+#define SHARE_TYPE_DISKTREE  0
+#define SHARE_TYPE_PRINTQ    1
+#define SHARE_TYPE_DEVICE    2
+#define SHARE_TYPE_IPC       3
+
+#define SHARE_TYPE_TEMPORARY 0x40000000
+#define SHARE_TYPE_HIDDEN    0x80000000
+
+struct srvsvc_netshareinfo1 {
+        const char *name;
+        uint32_t type;
+       const char *comment;
+};
+
+struct srvsvc_netsharectr1 {
+        uint32_t count;
+        struct srvsvc_netshareinfo1 *array;
+};
+
+struct srvsvc_netsharectr {
+        uint32_t level;
+        union {
+                struct srvsvc_netsharectr1 ctr1;
+        };
+};
+
+struct srvsvc_netshareenumall_req {
+        const char *server;
+        uint32_t level;
+        struct srvsvc_netsharectr *ctr;
+        uint32_t max_buffer;
+        uint32_t resume_handle;
+};
+
+struct srvsvc_netshareenumall_rep {
+        uint32_t status;
+
+        uint32_t level;
+        struct srvsvc_netsharectr *ctr;
+        uint32_t total_entries;
+        uint32_t resume_handle;
+};
+
+struct srvsvc_netshareinfo {
+        uint32_t level;
+        union {
+                struct srvsvc_netshareinfo1 info1;
+        };
+};
+struct srvsvc_netsharegetinfo_req {
+        const char *server;
+        const char *share;
+        uint32_t level;
+};
+
+struct srvsvc_netsharegetinfo_rep {
+        uint32_t status;
+
+        struct srvsvc_netshareinfo *info;
+};
+
+struct srvsvc_rep {
+        uint32_t status;
+};
+
+/*
+ * Async share_enum()
+ * This function only works when connected to the IPC$ share.
+ *
+ * Returns
+ *  0     : The operation was initiated. Result of the operation will be
+ *          reported through the callback function.
+ * -errno : There was an error. The callback function will not be invoked.
+ *
+ * When the callback is invoked, status indicates the result:
+ *      0 : Success. Command_data is struct srvsvc_netshareenumall_rep *
+ *          This pointer must be freed using smb2_free_data().
+ * -errno : An error occured.
+ */
+int smb2_share_enum_async(struct smb2_context *smb2,
+                          smb2_command_cb cb, void *cb_data);
+
+/*
+ * Async share_info()
+ * This function only works when connected to the IPC$ share.
+ *
+ * Returns
+ *  0     : The operation was initiated. Result of the operation will be
+ *          reported through the callback function.
+ * -errno : There was an error. The callback function will not be invoked.
+ *
+ * When the callback is invoked, status indicates the result:
+ *      0 : Success. Command_data is struct srvsvc_netshareinfo_rep *
+ *          This pointer must be freed using smb2_free_data().
+ * -errno : An error occured.
+ */
+int smb2_share_info_async(struct smb2_context *smb2, const char *share,
+                          smb2_command_cb cb, void *cb_data);
+
+        
+int srvsvc_NetShareEnumAll_decoder(struct dcerpc_context *dce,
+                                   struct dcerpc_pdu *pdu,
+                                   struct smb2_iovec *iov, int offset,
+                                   void *ptr);
+int srvsvc_NetShareEnumAll_encoder(struct dcerpc_context *ctx,
+                                   struct dcerpc_pdu *pdu,
+                                   struct smb2_iovec *iov, int offset,
+                                   void *ptr);
+int srvsvc_NetShareGetInfo_decoder(struct dcerpc_context *dce,
                                    struct dcerpc_pdu *pdu,
                                    struct smb2_iovec *iov, int offset,
                                    void *ptr);
-int srvsvc_netshareenumall_encoder(struct dcerpc_context *ctx,
+int srvsvc_NetShareGetInfo_encoder(struct dcerpc_context *ctx,
                                    struct dcerpc_pdu *pdu,
                                    struct smb2_iovec *iov, int offset,
                                    void *ptr);
index c3d7fff91330f90110653965ac90395e62180afb..27a3ccea113ccecb642175cf31eee8ba44830e3b 100644 (file)
@@ -41,7 +41,8 @@ typedef int (*dcerpc_coder)(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
 
 enum ptr_type {
         PTR_REF    = 0,
-        PTR_UNIQUE = 1
+        PTR_UNIQUE = 1,
+        PTR_FULL   = 2
 };
 
 struct dcerpc_uuid {
@@ -76,7 +77,6 @@ struct smb2_context *dcerpc_get_smb2_context(struct dcerpc_context *dce);
 void *dcerpc_get_pdu_payload(struct dcerpc_pdu *pdu);
 
 int dcerpc_open_async(struct dcerpc_context *dce, dcerpc_cb cb, void *cb_data);
-int dcerpc_bind_async(struct dcerpc_context *dce, dcerpc_cb cb, void *cb_data);
 int dcerpc_call_async(struct dcerpc_context *dce, int opnum,
                       dcerpc_coder encoder, void *ptr,
                       dcerpc_coder decoder, int decode_size,
index 4dd60423c98d06806293f235ecc97f73886ec4c0..1aa4df114abb51b6be6e58d16964d66d5b0ab3c1 100644 (file)
@@ -899,68 +899,6 @@ int smb2_echo_async(struct smb2_context *smb2,
  */
 int smb2_echo(struct smb2_context *smb2);
 
-
-/* Low 2 bits desctibe the type */
-#define SHARE_TYPE_DISKTREE  0
-#define SHARE_TYPE_PRINTQ    1
-#define SHARE_TYPE_DEVICE    2
-#define SHARE_TYPE_IPC       3
-
-#define SHARE_TYPE_TEMPORARY 0x40000000
-#define SHARE_TYPE_HIDDEN    0x80000000
-
-struct srvsvc_netshareinfo1 {
-        const char *name;
-        uint32_t type;
-       const char *comment;
-};
-
-struct srvsvc_netsharectr1 {
-        uint32_t count;
-        struct srvsvc_netshareinfo1 *array;
-};
-
-struct srvsvc_netsharectr {
-        uint32_t level;
-        union {
-                struct srvsvc_netsharectr1 ctr1;
-        };
-};
-
-struct srvsvc_netshareenumall_req {
-        const char *server;
-        uint32_t level;
-        struct srvsvc_netsharectr *ctr;
-        uint32_t max_buffer;
-        uint32_t resume_handle;
-};
-
-struct srvsvc_netshareenumall_rep {
-        uint32_t level;
-        struct srvsvc_netsharectr *ctr;
-        uint32_t total_entries;
-        uint32_t resume_handle;
-
-        uint32_t status;
-};
-
-/*
- * Async share_enum()
- * This function only works when connected to the IPC$ share.
- *
- * Returns
- *  0     : The operation was initiated. Result of the operation will be
- *          reported through the callback function.
- * -errno : There was an error. The callback function will not be invoked.
- *
- * When the callback is invoked, status indicates the result:
- *      0 : Success. Command_data is struct srvsvc_netshareenumall_rep *
- *          This pointer must be freed using smb2_free_data().
- * -errno : An error occured.
- */
-int smb2_share_enum_async(struct smb2_context *smb2,
-                          smb2_command_cb cb, void *cb_data);
-
 #ifdef __cplusplus
 }
 #endif
index ed7d2bdf51dab3e38afc4f111ef31200bad2dc14..df52ac5e4ceb46f94f6926ad7228d0c49939a0fb 100644 (file)
                srvsvc_ShareType type;
                [string,charset(UTF16)] uint16 *comment;
        } srvsvc_NetShareInfo1;
-
-       typedef struct {
-               uint32 count;
-               [size_is(count)] srvsvc_NetShareInfo1 *array;
-       } srvsvc_NetShareCtr1;
-
-       typedef union {
-               [case(0)] srvsvc_NetShareCtr0 *ctr0;
-               [case(1)] srvsvc_NetShareCtr1 *ctr1;
-               [case(2)] srvsvc_NetShareCtr2 *ctr2;
-               [case(501)] srvsvc_NetShareCtr501 *ctr501;
-               [case(502)] srvsvc_NetShareCtr502 *ctr502;
-               [case(1004)] srvsvc_NetShareCtr1004 *ctr1004;
-               [case(1005)] srvsvc_NetShareCtr1005 *ctr1005;
-               [case(1006)] srvsvc_NetShareCtr1006 *ctr1006;
-               [case(1007)] srvsvc_NetShareCtr1007 *ctr1007;
-               [case(1501)] srvsvc_NetShareCtr1501 *ctr1501;
-               [default] ;
-       } srvsvc_NetShareCtr;
 */
-/*****************
- * Function: 0x0f
-       WERROR srvsvc_NetShareEnumAll (
-               [in]   [string,charset(UTF16)] uint16 *server_unc,
-               [in,out,ref]   uint32 *level,
-               [in,out,switch_is(level),ref] srvsvc_NetShareCtr *ctr,
-               [in]   uint32 max_buffer,
-               [out,ref]  uint32 *totalentries,
-               [in,out]   uint32 *resume_handle
-               );
-******************/
 static int
-srvsvc_NetShareCtr1_encoder(struct dcerpc_context *ctx,
-                            struct dcerpc_pdu *pdu,
-                            struct smb2_iovec *iov, int offset,
-                            void *ptr)
+srvsvc_NetShareInfo1_decoder(struct dcerpc_context *ctx,
+                             struct dcerpc_pdu *pdu,
+                             struct smb2_iovec *iov, int offset,
+                             void *ptr)
 {
-        /* just encode a fake array with 0 count and no pointer */
-        offset = dcerpc_encode_3264(ctx, pdu, iov, offset, 0);
-        offset = dcerpc_encode_3264(ctx, pdu, iov, offset, 0);
-
-        offset = dcerpc_process_deferred_pointers(ctx, pdu, iov, offset);
-        return offset;
-}
-
-static int
-srvsvc_NetShareCtr_encoder(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
-                           struct smb2_iovec *iov, int offset,
-                           void *ptr)
-{
-        /* just encode a fake union with case 1 */
-        offset = dcerpc_encode_3264(dce, pdu, iov, offset, 1);
-        offset = dcerpc_encode_ptr(dce, pdu, iov, offset, "dummy pointer",
-                                   PTR_UNIQUE, srvsvc_NetShareCtr1_encoder);
-
-        offset = dcerpc_process_deferred_pointers(dce, pdu, iov, offset);
+        struct srvsvc_netshareinfo1 *nsi1 = ptr;
+        
+        offset = dcerpc_decode_ptr(ctx, pdu, iov, offset, &nsi1->name,
+                                   PTR_UNIQUE,
+                                   dcerpc_decode_ucs2z);
+        offset = dcerpc_decode_32(ctx, pdu, iov, offset, &nsi1->type);
+        offset = dcerpc_decode_ptr(ctx, pdu, iov, offset, &nsi1->comment,
+                                   PTR_UNIQUE,
+                                   dcerpc_decode_ucs2z);
         return offset;
 }
 
 static int
-srvsvc_NetShareCtr1_array_decoder(struct dcerpc_context *ctx,
-                                  struct dcerpc_pdu *pdu,
-                                  struct smb2_iovec *iov, int offset,
-                                  void *ptr)
+srvsvc_NetShareInfo1_array_decoder(struct dcerpc_context *ctx,
+                                   struct dcerpc_pdu *pdu,
+                                   struct smb2_iovec *iov, int offset,
+                                   void *ptr)
 {
         struct srvsvc_netshareinfo1 *nsi1 = ptr;
         uint64_t p;
@@ -141,13 +101,8 @@ srvsvc_NetShareCtr1_array_decoder(struct dcerpc_context *ctx,
         offset = dcerpc_decode_3264(ctx, pdu, iov, offset, &p);
 
         while (p--) {
-                offset = dcerpc_decode_ptr(ctx, pdu, iov, offset, &nsi1->name,
-                                           PTR_UNIQUE,
-                                           dcerpc_decode_ucs2z);
-                offset = dcerpc_decode_32(ctx, pdu, iov, offset, &nsi1->type);
-                offset = dcerpc_decode_ptr(ctx, pdu, iov, offset, &nsi1->comment,
-                                           PTR_UNIQUE,
-                                           dcerpc_decode_ucs2z);
+                offset = srvsvc_NetShareInfo1_decoder(ctx, pdu, iov, offset,
+                                                      nsi1);
                 nsi1++;
         }
 
@@ -155,6 +110,26 @@ srvsvc_NetShareCtr1_array_decoder(struct dcerpc_context *ctx,
         return offset;
 }
 
+/*
+       typedef struct {
+               uint32 count;
+               [size_is(count)] srvsvc_NetShareInfo1 *array;
+       } srvsvc_NetShareCtr1;
+*/
+static int
+srvsvc_NetShareCtr1_encoder(struct dcerpc_context *ctx,
+                            struct dcerpc_pdu *pdu,
+                            struct smb2_iovec *iov, int offset,
+                            void *ptr)
+{
+        /* just encode a fake array with 0 count and no pointer */
+        offset = dcerpc_encode_3264(ctx, pdu, iov, offset, 0);
+        offset = dcerpc_encode_3264(ctx, pdu, iov, offset, 0);
+
+        offset = dcerpc_process_deferred_pointers(ctx, pdu, iov, offset);
+        return offset;
+}
+
 static int
 srvsvc_NetShareCtr1_decoder(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
                             struct smb2_iovec *iov, int offset,
@@ -173,7 +148,36 @@ srvsvc_NetShareCtr1_decoder(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
 
         offset = dcerpc_decode_ptr(dce, pdu, iov, offset, ctr1->array,
                                    PTR_UNIQUE,
-                                   srvsvc_NetShareCtr1_array_decoder);
+                                   srvsvc_NetShareInfo1_array_decoder);
+
+        offset = dcerpc_process_deferred_pointers(dce, pdu, iov, offset);
+        return offset;
+}
+
+/*
+       typedef union {
+               [case(0)] srvsvc_NetShareCtr0 *ctr0;
+               [case(1)] srvsvc_NetShareCtr1 *ctr1;
+               [case(2)] srvsvc_NetShareCtr2 *ctr2;
+               [case(501)] srvsvc_NetShareCtr501 *ctr501;
+               [case(502)] srvsvc_NetShareCtr502 *ctr502;
+               [case(1004)] srvsvc_NetShareCtr1004 *ctr1004;
+               [case(1005)] srvsvc_NetShareCtr1005 *ctr1005;
+               [case(1006)] srvsvc_NetShareCtr1006 *ctr1006;
+               [case(1007)] srvsvc_NetShareCtr1007 *ctr1007;
+               [case(1501)] srvsvc_NetShareCtr1501 *ctr1501;
+               [default] ;
+       } srvsvc_NetShareCtr;
+*/
+static int
+srvsvc_NetShareCtr_encoder(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
+                           struct smb2_iovec *iov, int offset,
+                           void *ptr)
+{
+        /* just encode a fake union with case 1 */
+        offset = dcerpc_encode_3264(dce, pdu, iov, offset, 1);
+        offset = dcerpc_encode_ptr(dce, pdu, iov, offset, "dummy pointer",
+                                   PTR_UNIQUE, srvsvc_NetShareCtr1_encoder);
 
         offset = dcerpc_process_deferred_pointers(dce, pdu, iov, offset);
         return offset;
@@ -202,8 +206,19 @@ srvsvc_NetShareCtr_decoder(struct dcerpc_context *ctx, struct dcerpc_pdu *pdu,
         return offset;
 }
 
+/*****************
+ * Function: 0x0f
+ *     WERROR srvsvc_NetShareEnumAll (
+ *             [in]   [string,charset(UTF16)] uint16 *server_unc,
+ *             [in,out,ref]   uint32 *level,
+ *             [in,out,switch_is(level),ref] srvsvc_NetShareCtr *ctr,
+ *             [in]   uint32 max_buffer,
+ *             [out,ref]  uint32 *totalentries,
+ *             [in,out]   uint32 *resume_handle
+ *             );
+ ******************/
 int
-srvsvc_netshareenumall_encoder(struct dcerpc_context *ctx,
+srvsvc_NetShareEnumAll_encoder(struct dcerpc_context *ctx,
                                struct dcerpc_pdu *pdu,
                                struct smb2_iovec *iov, int offset,
                                void *ptr)
@@ -244,7 +259,7 @@ srvsvc_netshareenumall_encoder(struct dcerpc_context *ctx,
 }
 
 int
-srvsvc_netshareenumall_decoder(struct dcerpc_context *dce,
+srvsvc_NetShareEnumAll_decoder(struct dcerpc_context *dce,
                                struct dcerpc_pdu *pdu,
                                struct smb2_iovec *iov, int offset,
                                void *ptr)
@@ -276,3 +291,117 @@ srvsvc_netshareenumall_decoder(struct dcerpc_context *dce,
         
         return offset;
 }
+
+/*
+ *     typedef union {
+ *             [case(0)] srvsvc_NetShareInfo0 *info0;
+ *             [case(1)] srvsvc_NetShareInfo1 *info1;
+ *             [case(2)] srvsvc_NetShareInfo2 *info2;
+ *             [case(501)] srvsvc_NetShareInfo501 *info501;
+ *             [case(502)] srvsvc_NetShareInfo502 *info502;
+ *             [case(1004)] srvsvc_NetShareInfo1004 *info1004;
+ *             [case(1005)] srvsvc_NetShareInfo1005 *info1005;
+ *             [case(1006)] srvsvc_NetShareInfo1006 *info1006;
+ *             [case(1007)] srvsvc_NetShareInfo1007 *info1007;
+ *             [case(1501)] sec_desc_buf *info1501;
+ *             [default] ;
+ *     } srvsvc_NetShareInfo;
+ */
+static int
+srvsvc_NetShareInfo_decoder(struct dcerpc_context *ctx, struct dcerpc_pdu *pdu,
+                           struct smb2_iovec *iov, int offset,
+                           void *ptr)
+{
+        struct srvsvc_netshareinfo *info = ptr;
+        uint64_t p;
+
+        offset = dcerpc_decode_3264(ctx, pdu, iov, offset, &p);
+        info->level = (uint32_t)p;
+
+        switch (info->level) {
+        case 1:
+                offset = dcerpc_decode_ptr(ctx, pdu, iov, offset, &info->info1,
+                                           PTR_UNIQUE,
+                                           srvsvc_NetShareInfo1_decoder);
+                break;
+        };
+        offset = dcerpc_process_deferred_pointers(ctx, pdu, iov, offset);
+        return offset;
+}
+
+/******************
+ * Function: 0x10
+ *     WERROR srvsvc_NetShareGetInfo(
+ *             [in]   [string,charset(UTF16)] uint16 *server_unc,
+ *             [in]   [string,charset(UTF16)] uint16 share_name[],
+ *             [in]   uint32 level,
+ *             [out,switch_is(level),ref] srvsvc_NetShareInfo *info
+ *             );
+ ******************/
+int
+srvsvc_NetShareGetInfo_encoder(struct dcerpc_context *dce,
+                               struct dcerpc_pdu *pdu,
+                               struct smb2_iovec *iov, int offset,
+                               void *ptr)
+{
+        struct srvsvc_netsharegetinfo_req *req = ptr;
+        int len;
+        char *server;
+        struct ucs2 *ucs2_unc, *ucs2_share;
+
+        len = strlen(req->server) + 3;
+        server = malloc(len);
+        if (server == NULL) {
+                return -1;
+        }
+
+        snprintf(server, len, "\\\\%s", req->server);
+        ucs2_unc = utf8_to_ucs2(server);
+        free(server);
+        if (ucs2_unc == NULL) {
+                return -1;
+        }
+        ucs2_share = utf8_to_ucs2(req->share);
+        if (ucs2_unc == NULL) {
+                free(ucs2_unc);
+                return -1;
+        }
+
+        offset = dcerpc_encode_ptr(dce, pdu, iov, offset, ucs2_unc,
+                                   PTR_UNIQUE, dcerpc_encode_ucs2z);
+        offset = dcerpc_encode_ptr(dce, pdu, iov, offset, ucs2_share,
+                                   PTR_REF, dcerpc_encode_ucs2z);
+        offset = dcerpc_encode_ptr(dce, pdu, iov, offset, &req->level,
+                                   PTR_REF, dcerpc_encode_32);
+        offset = dcerpc_process_deferred_pointers(dce, pdu, iov, offset);
+
+        free(ucs2_unc);
+        free(ucs2_share);
+
+        return offset;
+}
+
+int
+srvsvc_NetShareGetInfo_decoder(struct dcerpc_context *dce,
+                               struct dcerpc_pdu *pdu,
+                               struct smb2_iovec *iov, int offset,
+                               void *ptr)
+{
+        struct srvsvc_netsharegetinfo_rep *rep = ptr;
+        struct srvsvc_netshareinfo *info;
+
+        info = smb2_alloc_data(dcerpc_get_smb2_context(dce),
+                               dcerpc_get_pdu_payload(pdu),
+                               sizeof(struct srvsvc_netshareinfo));
+        if (info == NULL) {
+                return -1;
+        }
+
+        rep->info = info;
+        offset = dcerpc_decode_ptr(dce, pdu, iov, offset, rep->info,
+                                   PTR_REF, srvsvc_NetShareInfo_decoder);
+
+        offset = dcerpc_decode_32(dce, pdu, iov, offset, &rep->status);
+
+        return offset;
+}
index 4bf3b37a9bd277c103a4b205e2f5a1474714c047..9fcdc7e6c1b163c2fa9d80c81a6f73baa49fb8fc 100644 (file)
@@ -516,6 +516,8 @@ dcerpc_decode_3264(struct dcerpc_context *ctx, struct dcerpc_pdu *pdu,
         return offset;
 }
 
+#define RPTR 0x5270747272747052
+#define UPTR 0x5570747272747055
 int
 dcerpc_encode_ptr(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
                   struct smb2_iovec *iov,
@@ -545,11 +547,10 @@ dcerpc_encode_ptr(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
                         return offset;
                 }
                 
-                pdu->ptr_id++;
-                offset = dcerpc_encode_3264(dce, pdu, iov, offset, pdu->ptr_id);
+                offset = dcerpc_encode_3264(dce, pdu, iov, offset, RPTR);
                 dcerpc_add_deferred_pointer(dce, pdu, coder, ptr);
                 break;
-        case PTR_UNIQUE:
+        case PTR_FULL:
                 if (ptr == NULL) {
                         offset = dcerpc_encode_3264(dce, pdu, iov, offset, 0);
                         return offset;
@@ -565,6 +566,21 @@ dcerpc_encode_ptr(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
                         dcerpc_add_deferred_pointer(dce, pdu, coder, ptr);
                 }
                 break;
+        case PTR_UNIQUE:
+                if (ptr == NULL) {
+                        offset = dcerpc_encode_3264(dce, pdu, iov, offset, 0);
+                        return offset;
+                }
+
+                offset = dcerpc_encode_3264(dce, pdu, iov, offset, UPTR);
+                if (pdu->top_level) {
+                        pdu->top_level = 0;
+                        offset = coder(dce, pdu, iov, offset, ptr);
+                        pdu->top_level = top_level;
+                } else {
+                        dcerpc_add_deferred_pointer(dce, pdu, coder, ptr);
+                }
+                break;
         }
 
         return offset;
@@ -614,6 +630,9 @@ dcerpc_decode_ptr(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
                         dcerpc_add_deferred_pointer(dce, pdu, coder, ptr);
                 }
                 break;
+        case PTR_FULL:
+                /* not implemented yet */
+                break;
         }
 
         return offset;
@@ -1229,8 +1248,24 @@ dcerpc_call_async(struct dcerpc_context *dce,
 }
 
 static void
-dcerpc_bind_cb(struct smb2_context *smb2, int status,
-               void *command_data, void *private_data)
+dcerpc_bind_cb(struct dcerpc_context *dce, int status,
+               void *command_data, void *cb_data)
+{
+        struct dcerpc_cb_data *data = cb_data;
+
+        if (status != SMB2_STATUS_SUCCESS) {
+                data->cb(dce, status, NULL, data->cb_data);
+                free(data);
+                return;
+        }
+
+        data->cb(dce, 0, NULL, data->cb_data);
+        free(data);
+}
+
+static void
+smb2_bind_cb(struct smb2_context *smb2, int status,
+             void *command_data, void *private_data)
 {
         struct dcerpc_pdu *pdu = private_data;
         struct dcerpc_context *dce = pdu->dce;
@@ -1298,7 +1333,7 @@ dcerpc_bind_cb(struct smb2_context *smb2, int status,
         dcerpc_free_pdu(dce, pdu);
 }
 
-int
+static int
 dcerpc_bind_async(struct dcerpc_context *dce, dcerpc_cb cb,
                   void *cb_data)
 {
@@ -1351,7 +1386,7 @@ dcerpc_bind_async(struct dcerpc_context *dce, dcerpc_cb cb,
         req.input = iov.buf;
         req.flags = SMB2_0_IOCTL_IS_FSCTL;
 
-        smb2_pdu = smb2_cmd_ioctl_async(dce->smb2, &req, dcerpc_bind_cb, pdu);
+        smb2_pdu = smb2_cmd_ioctl_async(dce->smb2, &req, smb2_bind_cb, pdu);
         if (smb2_pdu == NULL) {
                 dcerpc_free_pdu(dce, pdu);
                 return -ENOMEM;
@@ -1362,24 +1397,30 @@ dcerpc_bind_async(struct dcerpc_context *dce, dcerpc_cb cb,
 }
 
 static void
-dcerpc_open_cb(struct smb2_context *smb2, int status,
-               void *command_data, void *private_data)
+smb2_open_cb(struct smb2_context *smb2, int status,
+             void *command_data, void *private_data)
 {
-        struct dcerpc_cb_data *cb_data = private_data;
+        struct dcerpc_cb_data *data = private_data;
         struct smb2_create_reply *rep = command_data;
-        struct dcerpc_context *dce = cb_data->dce;
+        struct dcerpc_context *dce = data->dce;
 
         if (status != SMB2_STATUS_SUCCESS) {
-                cb_data->cb(dce, -nterror_to_errno(status),
-                            NULL, cb_data->cb_data);
-                free(cb_data);
+                data->cb(dce, -nterror_to_errno(status),
+                         NULL, data->cb_data);
+                free(data);
                 return;
         }
         
         memcpy(dce->file_id, rep->file_id, SMB2_FD_SIZE);
 
-        cb_data->cb(dce, 0, NULL, cb_data->cb_data);
-        free(cb_data);
+        status = dcerpc_bind_async(dce, dcerpc_bind_cb, data);
+        if (status) {
+                data->cb(dce, status, NULL, data->cb_data);
+                free(data);
+                return;
+        }
+
+        return;
 }
 
 int
@@ -1390,7 +1431,7 @@ dcerpc_open_async(struct dcerpc_context *dce, dcerpc_cb cb,
         struct smb2_pdu *pdu;
         struct dcerpc_cb_data *data;
 
-        data = malloc(sizeof(struct dcerpc_cb_data));
+        data = calloc(1, sizeof(struct dcerpc_cb_data));
         if (data == NULL) {
                 smb2_set_error(dce->smb2, "Failed to allocate dcerpc callback "
                                "data");
@@ -1420,7 +1461,7 @@ dcerpc_open_async(struct dcerpc_context *dce, dcerpc_cb cb,
         req.create_options = 0;
         req.name = dce->path;
 
-        pdu = smb2_cmd_create_async(dce->smb2, &req, dcerpc_open_cb, data);
+        pdu = smb2_cmd_create_async(dce->smb2, &req, smb2_open_cb, data);
         if (pdu == NULL) {
                 free(data);
                 return -ENOMEM;
index 5bc6f06473b8f4c546b4e228f4fdbf89463074a4..862a276177fed31ef436b6701d01b0b92f6df107 100644 (file)
@@ -41,6 +41,7 @@ smb2_init_context
 smb2_mkdir
 smb2_mkdir_async
 smb2_share_enum_async
+smb2_share_info_async
 smb2_open
 smb2_open_async
 smb2_opendir
index c01da50a03158019f69d4b77b61e43a0eccb9b08..435ed76d5012e48bdec2ba64cc4166bee603eea8 100644 (file)
 #include "libsmb2-private.h"
 
 struct smb2nse {
-        struct srvsvc_netshareenumall_req ea_req;
-
         smb2_command_cb cb;
         void *cb_data;
+        union {
+                struct srvsvc_netshareenumall_req se_req;
+                struct srvsvc_netsharegetinfo_req si_req;
+        };
 };
 
 static void
@@ -75,11 +77,11 @@ nse_free(struct smb2nse *nse)
 }
 
 static void
-share_enum_ioctl_cb(struct dcerpc_context *dce, int status,
-                    void *command_data, void *cb_data)
+srvsvc_ioctl_cb(struct dcerpc_context *dce, int status,
+                void *command_data, void *cb_data)
 {
         struct smb2nse *nse = cb_data;
-        struct srvsvc_netshareenumall_rep *rep = command_data;
+        struct srvsvc_rep *rep = command_data;
         struct smb2_context *smb2 = dcerpc_get_smb2_context(dce);
 
         if (status != SMB2_STATUS_SUCCESS) {
@@ -88,7 +90,7 @@ share_enum_ioctl_cb(struct dcerpc_context *dce, int status,
                 dcerpc_destroy_context(dce);
                 return;
         }
-
+        
         nse->cb(smb2, rep->status, rep, nse->cb_data);
         nse_free(nse);
         dcerpc_destroy_context(dce);
@@ -110,10 +112,10 @@ share_enum_bind_cb(struct dcerpc_context *dce, int status,
 
         status = dcerpc_call_async(dce,
                                    SRVSVC_NETSHAREENUMALL,
-                                   srvsvc_netshareenumall_encoder, &nse->ea_req,
-                                   srvsvc_netshareenumall_decoder,
+                                   srvsvc_NetShareEnumAll_encoder, &nse->se_req,
+                                   srvsvc_NetShareEnumAll_decoder,
                                    sizeof(struct srvsvc_netshareenumall_rep),
-                                   share_enum_ioctl_cb, nse);
+                                   srvsvc_ioctl_cb, nse);
         if (status) {
                 nse->cb(smb2, status, NULL, nse->cb_data);
                 nse_free(nse);
@@ -122,9 +124,47 @@ share_enum_bind_cb(struct dcerpc_context *dce, int status,
         }
 }
 
+int
+smb2_share_enum_async(struct smb2_context *smb2,
+                      smb2_command_cb cb, void *cb_data)
+{
+        struct dcerpc_context *dce;
+        struct smb2nse *nse;
+        int rc;
+
+        dce = dcerpc_create_context(smb2, "srvsvc", &srvsvc_interface);
+        if (dce == NULL) {
+                return -ENOMEM;
+        }
+        
+        nse = calloc(1, sizeof(struct smb2nse));
+        if (nse == NULL) {
+                smb2_set_error(smb2, "Failed to allocate nse");
+                dcerpc_destroy_context(dce);
+                return -ENOMEM;
+        }
+        nse->cb = cb;
+        nse->cb_data = cb_data;
+
+        nse->se_req.server = smb2->server;
+        nse->se_req.level = 1;
+        nse->se_req.ctr = NULL;
+        nse->se_req.max_buffer = 0xffffffff;
+        nse->se_req.resume_handle = 0;
+
+        rc = dcerpc_open_async(dce, share_enum_bind_cb, nse);
+        if (rc) {
+                free(nse);
+                dcerpc_destroy_context(dce);
+                return rc;
+        }
+        
+        return 0;
+}
+
 static void
-share_enum_connect_cb(struct dcerpc_context *dce, int status,
-                      void *command_data, void *cb_data)
+share_info_bind_cb(struct dcerpc_context *dce, int status,
+                   void *command_data, void *cb_data)
 {
         struct smb2nse *nse = cb_data;
         struct smb2_context *smb2 = dcerpc_get_smb2_context(dce);
@@ -136,7 +176,12 @@ share_enum_connect_cb(struct dcerpc_context *dce, int status,
                 return;
         }
 
-        status = dcerpc_bind_async(dce, share_enum_bind_cb, nse);
+        status = dcerpc_call_async(dce,
+                                   SRVSVC_NETSHAREGETINFO,
+                                   srvsvc_NetShareGetInfo_encoder, &nse->si_req,
+                                   srvsvc_NetShareGetInfo_decoder,
+                                   sizeof(struct srvsvc_netsharegetinfo_rep),
+                                   srvsvc_ioctl_cb, nse);
         if (status) {
                 nse->cb(smb2, status, NULL, nse->cb_data);
                 nse_free(nse);
@@ -146,7 +191,7 @@ share_enum_connect_cb(struct dcerpc_context *dce, int status,
 }
 
 int
-smb2_share_enum_async(struct smb2_context *smb2,
+smb2_share_info_async(struct smb2_context *smb2, const char *share,
                       smb2_command_cb cb, void *cb_data)
 {
         struct dcerpc_context *dce;
@@ -157,7 +202,7 @@ smb2_share_enum_async(struct smb2_context *smb2,
         if (dce == NULL) {
                 return -ENOMEM;
         }
-        
+
         nse = calloc(1, sizeof(struct smb2nse));
         if (nse == NULL) {
                 smb2_set_error(smb2, "Failed to allocate nse");
@@ -167,18 +212,16 @@ smb2_share_enum_async(struct smb2_context *smb2,
         nse->cb = cb;
         nse->cb_data = cb_data;
 
-        nse->ea_req.server = smb2->server;
-        nse->ea_req.level = 1;
-        nse->ea_req.ctr = NULL;
-        nse->ea_req.max_buffer = 0xffffffff;
-        nse->ea_req.resume_handle = 0;
+        nse->si_req.server = smb2->server;
+        nse->si_req.share = share;
+        nse->si_req.level = 1;
 
-        rc = dcerpc_open_async(dce, share_enum_connect_cb, nse);
+        rc = dcerpc_open_async(dce, share_info_bind_cb, nse);
         if (rc) {
                 free(nse);
                 dcerpc_destroy_context(dce);
                 return rc;
         }
-        
+
         return 0;
 }