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/connect.c8
-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.h7
-rw-r--r--source4/libcli/smb_composite/smb2.c194
-rw-r--r--source4/libcli/smb_composite/smb_composite.h1
12 files changed, 256 insertions, 26 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 dbd05b57bc..68d718abaf 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/connect.c b/source4/libcli/smb2/connect.c
index 59d4e6ea2d..867af14c92 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);
@@ -142,7 +142,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..964dcf320c 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;
@@ -165,7 +168,7 @@ struct smb2_request {
*/
struct {
void (*fn)(struct smb2_request *);
- void *private;
+ void *private_data;
} async;
};
@@ -282,3 +285,5 @@ struct smb2_request {
return NT_STATUS_INVALID_PARAMETER; \
} \
} while (0)
+
+#endif
diff --git a/source4/libcli/smb_composite/smb2.c b/source4/libcli/smb_composite/smb2.c
new file mode 100644
index 0000000000..7fccbe3a3c
--- /dev/null
+++ b/source4/libcli/smb_composite/smb2.c
@@ -0,0 +1,194 @@
+/*
+ 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;
+ 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);
+}
+
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"
/*