smb2-raw-getsd-async
smb2-readlink
smb2-share-enum
+ smb2-share-info
smb2-stat-sync
smb2-truncate-sync)
smb2-raw-stat-async \
smb2-readlink \
smb2-share-enum \
+ smb2-share-info \
smb2-stat-sync \
smb2-statvfs-sync \
smb2-truncate-sync
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)
#include "smb2.h"
#include "libsmb2.h"
#include "libsmb2-raw.h"
+#include "libsmb2-dcerpc-srvsvc.h"
int is_finished;
--- /dev/null
+/* -*- 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;
+}
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);
enum ptr_type {
PTR_REF = 0,
- PTR_UNIQUE = 1
+ PTR_UNIQUE = 1,
+ PTR_FULL = 2
};
struct dcerpc_uuid {
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,
*/
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
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;
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++;
}
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,
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;
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)
}
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)
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;
+}
return offset;
}
+#define RPTR 0x5270747272747052
+#define UPTR 0x5570747272747055
int
dcerpc_encode_ptr(struct dcerpc_context *dce, struct dcerpc_pdu *pdu,
struct smb2_iovec *iov,
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;
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;
dcerpc_add_deferred_pointer(dce, pdu, coder, ptr);
}
break;
+ case PTR_FULL:
+ /* not implemented yet */
+ break;
}
return offset;
}
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;
dcerpc_free_pdu(dce, pdu);
}
-int
+static int
dcerpc_bind_async(struct dcerpc_context *dce, dcerpc_cb cb,
void *cb_data)
{
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;
}
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
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");
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;
smb2_mkdir
smb2_mkdir_async
smb2_share_enum_async
+smb2_share_info_async
smb2_open
smb2_open_async
smb2_opendir
#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
}
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) {
dcerpc_destroy_context(dce);
return;
}
-
+
nse->cb(smb2, rep->status, rep, nse->cb_data);
nse_free(nse);
dcerpc_destroy_context(dce);
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);
}
}
+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);
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);
}
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;
if (dce == NULL) {
return -ENOMEM;
}
-
+
nse = calloc(1, sizeof(struct smb2nse));
if (nse == NULL) {
smb2_set_error(smb2, "Failed to allocate nse");
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;
}