summaryrefslogtreecommitdiff
path: root/source4/libcli
diff options
context:
space:
mode:
Diffstat (limited to 'source4/libcli')
-rw-r--r--source4/libcli/clifile.c11
-rw-r--r--source4/libcli/composite/composite.c19
-rw-r--r--source4/libcli/composite/composite.h1
-rw-r--r--source4/libcli/config.mk3
-rw-r--r--source4/libcli/raw/interfaces.h7
-rw-r--r--source4/libcli/smb2/config.mk2
-rw-r--r--source4/libcli/smb2/connect.c11
-rw-r--r--source4/libcli/smb2/find.c2
-rw-r--r--source4/libcli/smb2/request.c25
-rw-r--r--source4/libcli/smb2/session.c4
-rw-r--r--source4/libcli/smb2/smb2.h9
-rw-r--r--source4/libcli/smb2/util.c200
-rw-r--r--source4/libcli/smb_composite/smb2.c371
-rw-r--r--source4/libcli/smb_composite/smb_composite.h1
14 files changed, 639 insertions, 27 deletions
diff --git a/source4/libcli/clifile.c b/source4/libcli/clifile.c
index e59b7f9af3..2cf174060b 100644
--- a/source4/libcli/clifile.c
+++ b/source4/libcli/clifile.c
@@ -650,7 +650,8 @@ NTSTATUS smbcli_chkpath(struct smbcli_tree *tree, const char *path)
/****************************************************************************
Query disk space.
****************************************************************************/
-NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, int *bsize, int *total, int *avail)
+NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, uint32_t *bsize,
+ uint64_t *total, uint64_t *avail)
{
union smb_fsinfo fsinfo_parms;
TALLOC_CTX *mem_ctx;
@@ -658,12 +659,12 @@ NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, int *bsize, int *total, int *a
mem_ctx = talloc_init("smbcli_dskattr");
- fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
+ fsinfo_parms.dskattr.level = RAW_QFS_SIZE_INFO;
status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
if (NT_STATUS_IS_OK(status)) {
- *bsize = fsinfo_parms.dskattr.out.block_size;
- *total = fsinfo_parms.dskattr.out.units_total;
- *avail = fsinfo_parms.dskattr.out.units_free;
+ *bsize = fsinfo_parms.size_info.out.bytes_per_sector * fsinfo_parms.size_info.out.sectors_per_unit;
+ *total = fsinfo_parms.size_info.out.total_alloc_units;
+ *avail = fsinfo_parms.size_info.out.avail_alloc_units;
}
talloc_free(mem_ctx);
diff --git a/source4/libcli/composite/composite.c b/source4/libcli/composite/composite.c
index 966f56cba8..3e3f224f47 100644
--- a/source4/libcli/composite/composite.c
+++ b/source4/libcli/composite/composite.c
@@ -69,6 +69,17 @@ _PUBLIC_ NTSTATUS composite_wait(struct composite_context *c)
return c->status;
}
+/*
+ block until a composite function has completed, then return the status.
+ Free the composite context before returning
+*/
+_PUBLIC_ NTSTATUS composite_wait_free(struct composite_context *c)
+{
+ NTSTATUS status = composite_wait(c);
+ talloc_free(c);
+ return status;
+}
+
/*
callback from composite_done() and composite_error()
@@ -94,6 +105,12 @@ static void composite_trigger(struct event_context *ev, struct timed_event *te,
_PUBLIC_ void composite_error(struct composite_context *ctx, NTSTATUS status)
{
+ /* you are allowed to pass NT_STATUS_OK to composite_error(), in which
+ case it is equivalent to composite_done() */
+ if (NT_STATUS_IS_OK(status)) {
+ composite_done(ctx);
+ return;
+ }
if (!ctx->used_wait && !ctx->async.fn) {
event_add_timed(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx);
}
@@ -187,7 +204,7 @@ _PUBLIC_ void composite_continue_smb2(struct composite_context *ctx,
{
if (composite_nomem(new_req, ctx)) return;
new_req->async.fn = continuation;
- new_req->async.private = private_data;
+ new_req->async.private_data = private_data;
}
_PUBLIC_ void composite_continue_nbt(struct composite_context *ctx,
diff --git a/source4/libcli/composite/composite.h b/source4/libcli/composite/composite.h
index f1bed20361..28cd6a88dc 100644
--- a/source4/libcli/composite/composite.h
+++ b/source4/libcli/composite/composite.h
@@ -101,6 +101,7 @@ bool composite_is_ok(struct composite_context *ctx);
void composite_done(struct composite_context *ctx);
void composite_error(struct composite_context *ctx, NTSTATUS status);
NTSTATUS composite_wait(struct composite_context *c);
+NTSTATUS composite_wait_free(struct composite_context *c);
#endif /* __COMPOSITE_H__ */
diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk
index 0cc97c058a..f502091b07 100644
--- a/source4/libcli/config.mk
+++ b/source4/libcli/config.mk
@@ -33,7 +33,8 @@ LIBCLI_SMB_COMPOSITE_OBJ_FILES = $(addprefix $(libclisrcdir)/smb_composite/, \
sesssetup.o \
fetchfile.o \
appendacl.o \
- fsinfo.o)
+ fsinfo.o \
+ smb2.o)
$(eval $(call proto_header_template,$(libclisrcdir)/smb_composite/proto.h,$(LIBCLI_SMB_COMPOSITE_OBJ_FILES:.o=.c)))
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index bad3743721..871bab01db 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -2354,10 +2354,11 @@ union smb_search_first {
#define SMB2_FIND_ID_BOTH_DIRECTORY_INFO 0x25
#define SMB2_FIND_ID_FULL_DIRECTORY_INFO 0x26
-/* flags for RAW_FILEINFO_SMB2_ALL_EAS */
+/* flags for SMB2 find */
#define SMB2_CONTINUE_FLAG_RESTART 0x01
#define SMB2_CONTINUE_FLAG_SINGLE 0x02
-#define SMB2_CONTINUE_FLAG_NEW 0x10
+#define SMB2_CONTINUE_FLAG_INDEX 0x04
+#define SMB2_CONTINUE_FLAG_REOPEN 0x10
/* SMB2 Find */
struct smb2_find {
@@ -2370,7 +2371,7 @@ union smb_search_first {
/* uint16_t buffer_code; 0x21 = 0x20 + 1 */
uint8_t level;
uint8_t continue_flags; /* SMB2_CONTINUE_FLAG_* */
- uint32_t unknown; /* perhaps a continue token? */
+ uint32_t file_index;
/* struct smb2_handle handle; */
/* uint16_t pattern_ofs; */
/* uint16_t pattern_size; */
diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk
index e653fbac1c..00b6305def 100644
--- a/source4/libcli/smb2/config.mk
+++ b/source4/libcli/smb2/config.mk
@@ -5,6 +5,6 @@ LIBCLI_SMB2_OBJ_FILES = $(addprefix $(libclisrcdir)/smb2/, \
transport.o request.o negprot.o session.o tcon.o \
create.o close.o connect.o getinfo.o write.o read.o \
setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \
- lock.o notify.o cancel.o keepalive.o break.o)
+ lock.o notify.o cancel.o keepalive.o break.o util.o)
$(eval $(call proto_header_template,$(libclisrcdir)/smb2/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c)))
diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c
index 59d4e6ea2d..eabfa410ad 100644
--- a/source4/libcli/smb2/connect.c
+++ b/source4/libcli/smb2/connect.c
@@ -44,7 +44,7 @@ struct smb2_connect_state {
*/
static void continue_tcon(struct smb2_request *req)
{
- struct composite_context *c = talloc_get_type(req->async.private,
+ struct composite_context *c = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_connect_state *state = talloc_get_type(c->private_data,
struct smb2_connect_state);
@@ -83,7 +83,7 @@ static void continue_session(struct composite_context *creq)
if (composite_nomem(req, c)) return;
req->async.fn = continue_tcon;
- req->async.private = c;
+ req->async.private_data = c;
}
/*
@@ -91,7 +91,7 @@ static void continue_session(struct composite_context *creq)
*/
static void continue_negprot(struct smb2_request *req)
{
- struct composite_context *c = talloc_get_type(req->async.private,
+ struct composite_context *c = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_connect_state *state = talloc_get_type(c->private_data,
struct smb2_connect_state);
@@ -101,6 +101,9 @@ static void continue_negprot(struct smb2_request *req)
c->status = smb2_negprot_recv(req, c, &state->negprot);
if (!composite_is_ok(c)) return;
+ transport->negotiate.system_time = state->negprot.out.system_time;
+ transport->negotiate.server_start_time = state->negprot.out.server_start_time;
+
state->session = smb2_session_init(transport, global_loadparm, state, true);
if (composite_nomem(state->session, c)) return;
@@ -142,7 +145,7 @@ static void continue_socket(struct composite_context *creq)
if (composite_nomem(req, c)) return;
req->async.fn = continue_negprot;
- req->async.private = c;
+ req->async.private_data = c;
}
diff --git a/source4/libcli/smb2/find.c b/source4/libcli/smb2/find.c
index 6b4902a026..8ebfd81bcd 100644
--- a/source4/libcli/smb2/find.c
+++ b/source4/libcli/smb2/find.c
@@ -38,7 +38,7 @@ struct smb2_request *smb2_find_send(struct smb2_tree *tree, struct smb2_find *io
SCVAL(req->out.body, 0x02, io->in.level);
SCVAL(req->out.body, 0x03, io->in.continue_flags);
- SIVAL(req->out.body, 0x04, io->in.unknown);
+ SIVAL(req->out.body, 0x04, io->in.file_index);
smb2_push_handle(req->out.body+0x08, &io->in.file.handle);
status = smb2_push_o16s16_string(&req->out, 0x18, io->in.pattern);
diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c
index f52b0ceef2..64d427f889 100644
--- a/source4/libcli/smb2/request.c
+++ b/source4/libcli/smb2/request.c
@@ -43,6 +43,18 @@ void smb2_setup_bufinfo(struct smb2_request *req)
}
}
+
+/* destroy a request structure */
+static int smb2_request_destructor(struct smb2_request *req)
+{
+ if (req->transport) {
+ /* remove it from the list of pending requests (a null op if
+ its not in the list) */
+ DLIST_REMOVE(req->transport->pending_recv, req);
+ }
+ return 0;
+}
+
/*
initialise a smb2 request
*/
@@ -122,6 +134,8 @@ struct smb2_request *smb2_request_init(struct smb2_transport *transport, uint16_
SCVAL(req->out.dynamic, 0, 0);
}
+ talloc_set_destructor(req, smb2_request_destructor);
+
return req;
}
@@ -154,18 +168,13 @@ NTSTATUS smb2_request_destroy(struct smb2_request *req)
_send() call fails completely */
if (!req) return NT_STATUS_UNSUCCESSFUL;
- if (req->transport) {
- /* remove it from the list of pending requests (a null op if
- its not in the list) */
- DLIST_REMOVE(req->transport->pending_recv, req);
- }
-
if (req->state == SMB2_REQUEST_ERROR &&
NT_STATUS_IS_OK(req->status)) {
- req->status = NT_STATUS_INTERNAL_ERROR;
+ status = NT_STATUS_INTERNAL_ERROR;
+ } else {
+ status = req->status;
}
- status = req->status;
talloc_free(req);
return status;
}
diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c
index 18fe3486a4..29af6652f2 100644
--- a/source4/libcli/smb2/session.c
+++ b/source4/libcli/smb2/session.c
@@ -145,7 +145,7 @@ struct smb2_session_state {
*/
static void session_request_handler(struct smb2_request *req)
{
- struct composite_context *c = talloc_get_type(req->async.private,
+ struct composite_context *c = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_session_state *state = talloc_get_type(c->private_data,
struct smb2_session_state);
@@ -178,7 +178,7 @@ static void session_request_handler(struct smb2_request *req)
}
state->req->async.fn = session_request_handler;
- state->req->async.private = c;
+ state->req->async.private_data = c;
return;
}
diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h
index ae66a6e0d3..b55da05e21 100644
--- a/source4/libcli/smb2/smb2.h
+++ b/source4/libcli/smb2/smb2.h
@@ -19,6 +19,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifndef __LIBCLI_SMB2_SMB2_H__
+#define __LIBCLI_SMB2_SMB2_H__
+
#include "libcli/raw/request.h"
struct smb2_handle;
@@ -32,6 +35,8 @@ struct smb2_options {
*/
struct smb2_negotiate {
DATA_BLOB secblob;
+ NTTIME system_time;
+ NTTIME server_start_time;
};
/* this is the context for the smb2 transport layer */
@@ -165,7 +170,7 @@ struct smb2_request {
*/
struct {
void (*fn)(struct smb2_request *);
- void *private;
+ void *private_data;
} async;
};
@@ -282,3 +287,5 @@ struct smb2_request {
return NT_STATUS_INVALID_PARAMETER; \
} \
} while (0)
+
+#endif
diff --git a/source4/libcli/smb2/util.c b/source4/libcli/smb2/util.c
new file mode 100644
index 0000000000..9eb344e83f
--- /dev/null
+++ b/source4/libcli/smb2/util.c
@@ -0,0 +1,200 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ SMB2 client utility functions
+
+ Copyright (C) Andrew Tridgell 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "libcli/smb_composite/smb_composite.h"
+
+/*
+ simple close wrapper with SMB2
+*/
+NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
+{
+ struct smb2_close c;
+
+ ZERO_STRUCT(c);
+ c.in.file.handle = h;
+
+ return smb2_close(tree, &c);
+}
+
+/*
+ unlink a file with SMB2
+*/
+NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
+{
+ union smb_unlink io;
+
+ ZERO_STRUCT(io);
+ io.unlink.in.pattern = fname;
+
+ return smb2_composite_unlink(tree, &io);
+}
+
+
+/*
+ rmdir with SMB2
+*/
+NTSTATUS smb2_util_rmdir(struct smb2_tree *tree, const char *dname)
+{
+ struct smb_rmdir io;
+
+ ZERO_STRUCT(io);
+ io.in.path = dname;
+
+ return smb2_composite_rmdir(tree, &io);
+}
+
+
+/*
+ mkdir with SMB2
+*/
+NTSTATUS smb2_util_mkdir(struct smb2_tree *tree, const char *dname)
+{
+ union smb_mkdir io;
+
+ ZERO_STRUCT(io);
+ io.mkdir.level = RAW_MKDIR_MKDIR;
+ io.mkdir.in.path = dname;
+
+ return smb2_composite_mkdir(tree, &io);
+}
+
+
+/*
+ set file attribute with SMB2
+*/
+NTSTATUS smb2_util_setatr(struct smb2_tree *tree, const char *name, uint32_t attrib)
+{
+ union smb_setfileinfo io;
+
+ ZERO_STRUCT(io);
+ io.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION;
+ io.basic_info.in.file.path = name;
+ io.basic_info.in.attrib = attrib;
+
+ return smb2_composite_setpathinfo(tree, &io);
+}
+
+
+
+
+/*
+ recursively descend a tree deleting all files
+ returns the number of files deleted, or -1 on error
+*/
+int smb2_deltree(struct smb2_tree *tree, const char *dname)
+{
+ NTSTATUS status;
+ uint32_t total_deleted = 0;
+ uint_t count, i;
+ union smb_search_data *list;
+ TALLOC_CTX *tmp_ctx = talloc_new(tree);
+ struct smb2_find f;
+ struct smb2_create create_parm;
+
+ /* it might be a file */
+ status = smb2_util_unlink(tree, dname);
+ if (NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return 1;
+ }
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) {
+ talloc_free(tmp_ctx);
+ return 0;
+ }
+
+ ZERO_STRUCT(create_parm);
+ create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ create_parm.in.share_access =
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create_parm.in.fname = dname;
+
+ status = smb2_create(tree, tmp_ctx, &create_parm);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(2,("Failed to open %s - %s\n", dname, nt_errstr(status)));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+
+ ZERO_STRUCT(f);
+ f.in.file.handle = create_parm.out.file.handle;
+ f.in.max_response_size = 0x10000;
+ f.in.level = SMB2_FIND_NAME_INFO;
+ f.in.pattern = "*";
+
+ status = smb2_find_level(tree, tmp_ctx, &f, &count, &list);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(2,("Failed to list %s - %s\n",
+ dname, nt_errstr(status)));
+ smb2_util_close(tree, create_parm.out.file.handle);
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ for (i=0;i<count;i++) {
+ char *name;
+ if (strcmp(".", list[i].name_info.name.s) == 0 ||
+ strcmp("..", list[i].name_info.name.s) == 0) {
+ continue;
+ }
+ name = talloc_asprintf(tmp_ctx, "%s\\%s", dname, list[i].name_info.name.s);
+ status = smb2_util_unlink(tree, name);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
+ /* it could be read-only */
+ status = smb2_util_setatr(tree, name, FILE_ATTRIBUTE_NORMAL);
+ status = smb2_util_unlink(tree, name);
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
+ int ret;
+ ret = smb2_deltree(tree, name);
+ if (ret > 0) total_deleted += ret;
+ }
+ talloc_free(name);
+ if (NT_STATUS_IS_OK(status)) {
+ total_deleted++;
+ }
+ }
+
+ smb2_util_close(tree, create_parm.out.file.handle);
+
+ status = smb2_util_rmdir(tree, dname);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(2,("Failed to delete %s - %s\n",
+ dname, nt_errstr(status)));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ talloc_free(tmp_ctx);
+
+ return total_deleted;
+}
diff --git a/source4/libcli/smb_composite/smb2.c b/source4/libcli/smb_composite/smb2.c
new file mode 100644
index 0000000000..6e005e03c0
--- /dev/null
+++ b/source4/libcli/smb_composite/smb2.c
@@ -0,0 +1,371 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+/*
+ a composite API for making SMB-like calls using SMB2. This is useful
+ as SMB2 often requires more than one requests where a single SMB
+ request would do. In converting code that uses SMB to use SMB2,
+ these routines make life a lot easier
+*/
+
+
+#include "includes.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "libcli/composite/composite.h"
+#include "libcli/smb_composite/smb_composite.h"
+#include "param/param.h"
+#include "libcli/smb2/smb2_calls.h"
+
+/*
+ continue after a SMB2 close
+ */
+static void continue_close(struct smb2_request *req)
+{
+ struct composite_context *ctx = talloc_get_type(req->async.private_data,
+ struct composite_context);
+ NTSTATUS status;
+ struct smb2_close close_parm;
+
+ status = smb2_close_recv(req, &close_parm);
+ composite_error(ctx, status);
+}
+
+/*
+ continue after the create in a composite unlink
+ */
+static void continue_unlink(struct smb2_request *req)
+{
+ struct composite_context *ctx = talloc_get_type(req->async.private_data,
+ struct composite_context);
+ struct smb2_tree *tree = req->tree;
+ struct smb2_create create_parm;
+ struct smb2_close close_parm;
+ NTSTATUS status;
+
+ status = smb2_create_recv(req, ctx, &create_parm);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(ctx, status);
+ return;
+ }
+
+ ZERO_STRUCT(close_parm);
+ close_parm.in.file.handle = create_parm.out.file.handle;
+
+ req = smb2_close_send(tree, &close_parm);
+ composite_continue_smb2(ctx, req, continue_close, ctx);
+}
+
+/*
+ composite SMB2 unlink call
+*/
+struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree,
+ union smb_unlink *io)
+{
+ struct composite_context *ctx;
+ struct smb2_create create_parm;
+ struct smb2_request *req;
+
+ ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
+ if (ctx == NULL) return NULL;
+
+ /* check for wildcards - we could support these with a
+ search, but for now they aren't necessary */
+ if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) {
+ composite_error(ctx, NT_STATUS_NOT_SUPPORTED);
+ return ctx;
+ }
+
+ ZERO_STRUCT(create_parm);
+ create_parm.in.desired_access = SEC_STD_DELETE;
+ create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create_parm.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ create_parm.in.create_options =
+ NTCREATEX_OPTIONS_DELETE_ON_CLOSE |
+ NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
+ create_parm.in.fname = io->unlink.in.pattern;
+ if (create_parm.in.fname[0] == '\\') {
+ create_parm.in.fname++;
+ }
+
+ req = smb2_create_send(tree, &create_parm);
+
+ composite_continue_smb2(ctx, req, continue_unlink, ctx);
+ return ctx;
+}
+
+
+/*
+ composite unlink call - sync interface
+*/
+NTSTATUS smb2_composite_unlink(struct smb2_tree *tree, union smb_unlink *io)
+{
+ struct composite_context *c = smb2_composite_unlink_send(tree, io);
+ return composite_wait_free(c);
+}
+
+
+
+
+/*
+ continue after the create in a composite mkdir
+ */
+static void continue_mkdir(struct smb2_request *req)
+{
+ struct composite_context *ctx = talloc_get_type(req->async.private_data,
+ struct composite_context);
+ struct smb2_tree *tree = req->tree;
+ struct smb2_create create_parm;
+ struct smb2_close close_parm;
+ NTSTATUS status;
+
+ status = smb2_create_recv(req, ctx, &create_parm);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(ctx, status);
+ return;
+ }
+
+ ZERO_STRUCT(close_parm);
+ close_parm.in.file.handle = create_parm.out.file.handle;
+
+ req = smb2_close_send(tree, &close_parm);
+ composite_continue_smb2(ctx, req, continue_close, ctx);
+}
+
+/*
+ composite SMB2 mkdir call
+*/
+struct composite_context *smb2_composite_mkdir_send(struct smb2_tree *tree,
+ union smb_mkdir *io)
+{
+ struct composite_context *ctx;
+ struct smb2_create create_parm;
+ struct smb2_request *req;
+
+ ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
+ if (ctx == NULL) return NULL;
+
+ ZERO_STRUCT(create_parm);
+
+ create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ create_parm.in.share_access =
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ create_parm.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ create_parm.in.create_disposition = NTCREATEX_DISP_CREATE;
+ create_parm.in.fname = io->mkdir.in.path;
+ if (create_parm.in.fname[0] == '\\') {
+ create_parm.in.fname++;
+ }
+
+ req = smb2_create_send(tree, &create_parm);
+
+ composite_continue_smb2(ctx, req, continue_mkdir, ctx);
+
+ return ctx;
+}
+
+
+/*
+ composite mkdir call - sync interface
+*/
+NTSTATUS smb2_composite_mkdir(struct smb2_tree *tree, union smb_mkdir *io)
+{
+ struct composite_context *c = smb2_composite_mkdir_send(tree, io);
+ return composite_wait_free(c);
+}
+
+
+
+/*
+ continue after the create in a composite rmdir
+ */
+static void continue_rmdir(struct smb2_request *req)
+{
+ struct composite_context *ctx = talloc_get_type(req->async.private_data,
+ struct composite_context);
+ struct smb2_tree *tree = req->tree;
+ struct smb2_create create_parm;
+ struct smb2_close close_parm;
+ NTSTATUS status;
+
+ status = smb2_create_recv(req, ctx, &create_parm);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(ctx, status);
+ return;
+ }
+
+ ZERO_STRUCT(close_parm);
+ close_parm.in.file.handle = create_parm.out.file.handle;
+
+ req = smb2_close_send(tree, &close_parm);
+ composite_continue_smb2(ctx, req, continue_close, ctx);
+}
+
+/*
+ composite SMB2 rmdir call
+*/
+struct composite_context *smb2_composite_rmdir_send(struct smb2_tree *tree,
+ struct smb_rmdir *io)
+{
+ struct composite_context *ctx;
+ struct smb2_create create_parm;
+ struct smb2_request *req;
+
+ ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
+ if (ctx == NULL) return NULL;
+
+ ZERO_STRUCT(create_parm);
+ create_parm.in.desired_access = SEC_STD_DELETE;
+ create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create_parm.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ create_parm.in.create_options =
+ NTCREATEX_OPTIONS_DIRECTORY |
+ NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+ create_parm.in.fname = io->in.path;
+ if (create_parm.in.fname[0] == '\\') {
+ create_parm.in.fname++;
+ }
+
+ req = smb2_create_send(tree, &create_parm);
+
+ composite_continue_smb2(ctx, req, continue_rmdir, ctx);
+ return ctx;
+}
+
+
+/*
+ composite rmdir call - sync interface
+*/
+NTSTATUS smb2_composite_rmdir(struct smb2_tree *tree, struct smb_rmdir *io)
+{
+ struct composite_context *c = smb2_composite_rmdir_send(tree, io);
+ return composite_wait_free(c);
+}
+
+
+/*
+ continue after the setfileinfo in a composite setpathinfo
+ */
+static void continue_setpathinfo_close(struct smb2_request *req)
+{
+ struct composite_context *ctx = talloc_get_type(req->async.private_data,
+ struct composite_context);
+ struct smb2_tree *tree = req->tree;
+ struct smb2_close close_parm;
+ NTSTATUS status;
+ union smb_setfileinfo *io2 = talloc_get_type(ctx->private_data,
+ union smb_setfileinfo);
+
+ status = smb2_setinfo_recv(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(ctx, status);
+ return;
+ }
+
+ ZERO_STRUCT(close_parm);
+ close_parm.in.file.handle = io2->generic.in.file.handle;
+
+ req = smb2_close_send(tree, &close_parm);
+ composite_continue_smb2(ctx, req, continue_close, ctx);
+}
+
+
+/*
+ continue after the create in a composite setpathinfo
+ */
+static void continue_setpathinfo(struct smb2_request *req)
+{
+ struct composite_context *ctx = talloc_get_type(req->async.private_data,
+ struct composite_context);
+ struct smb2_tree *tree = req->tree;
+ struct smb2_create create_parm;
+ NTSTATUS status;
+ union smb_setfileinfo *io2 = talloc_get_type(ctx->private_data,
+ union smb_setfileinfo);
+
+ status = smb2_create_recv(req, ctx, &create_parm);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(ctx, status);
+ return;
+ }
+
+ io2->generic.in.file.handle = create_parm.out.file.handle;
+
+ req = smb2_setinfo_file_send(tree, io2);
+ composite_continue_smb2(ctx, req, continue_setpathinfo_close, ctx);
+}
+
+
+/*
+ composite SMB2 setpathinfo call
+*/
+struct composite_context *smb2_composite_setpathinfo_send(struct smb2_tree *tree,
+ union smb_setfileinfo *io)
+{
+ struct composite_context *ctx;
+ struct smb2_create create_parm;
+ struct smb2_request *req;
+ union smb_setfileinfo *io2;
+
+ ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
+ if (ctx == NULL) return NULL;
+
+ ZERO_STRUCT(create_parm);
+ create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create_parm.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ create_parm.in.create_options = 0;
+ create_parm.in.fname = io->generic.in.file.path;
+ if (create_parm.in.fname[0] == '\\') {
+ create_parm.in.fname++;
+ }
+
+ req = smb2_create_send(tree, &create_parm);
+
+ io2 = talloc(ctx, union smb_setfileinfo);
+ if (composite_nomem(io2, ctx)) {
+ return ctx;
+ }
+ *io2 = *io;
+
+ ctx->private_data = io2;
+
+ composite_continue_smb2(ctx, req, continue_setpathinfo, ctx);
+ return ctx;
+}
+
+
+/*
+ composite setpathinfo call
+ */
+NTSTATUS smb2_composite_setpathinfo(struct smb2_tree *tree, union smb_setfileinfo *io)
+{
+ struct composite_context *c = smb2_composite_setpathinfo_send(tree, io);
+ return composite_wait_free(c);
+}
diff --git a/source4/libcli/smb_composite/smb_composite.h b/source4/libcli/smb_composite/smb_composite.h
index afee11ce3b..7f4b9d73e4 100644
--- a/source4/libcli/smb_composite/smb_composite.h
+++ b/source4/libcli/smb_composite/smb_composite.h
@@ -29,6 +29,7 @@
#include "libcli/raw/signing.h"
#include "libcli/raw/libcliraw.h"
+#include "libcli/smb2/smb2.h"
/*