From 0abc2e2020f40d018587eb265f2a1467fdba4c89 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 May 2008 20:45:30 +1000 Subject: use a newer fsinfo level in smbclient, to support larger disks (This used to be commit 1acc8077fb86c1e78724b010d149db166d98238d) --- source4/libcli/clifile.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source4/libcli') 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); -- cgit From 8846981807a08e86c19b585be135b738eb9edf61 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 May 2008 20:46:10 +1000 Subject: update some SMB2 find flags (This used to be commit b7560afd4bab984c0083e9687b69bc42970ad932) --- source4/libcli/raw/interfaces.h | 7 ++++--- source4/libcli/smb2/find.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'source4/libcli') 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/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); -- cgit From de99db1084c73007f1d6f66fe7efb7a1a9271dfc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 May 2008 15:02:14 +1000 Subject: started adding SMB2 composite functions that emulate common SMB calls (such as unlink) (This used to be commit 433038f3fea60087bdca07dcc856d0be4a4753f3) --- source4/libcli/smb_composite/smb2.c | 122 ++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 source4/libcli/smb_composite/smb2.c (limited to 'source4/libcli') diff --git a/source4/libcli/smb_composite/smb2.c b/source4/libcli/smb_composite/smb2.c new file mode 100644 index 0000000000..7bce65fb27 --- /dev/null +++ b/source4/libcli/smb_composite/smb2.c @@ -0,0 +1,122 @@ +/* + 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 . +*/ +/* + 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); +} + -- cgit From 14ca2b5b5db4abb1e6ab624365fdebfd9ec422e0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 May 2008 15:02:58 +1000 Subject: - added a composite_wait_free() call - allow composite_error() to take NT_STATUS_OK (This used to be commit 5240e1e25655af1f9b92da99e85d845bf30c4e9e) --- source4/libcli/composite/composite.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'source4/libcli') 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, -- cgit From c02b0f47a0c85250715a1c511415a6cb4fe7a082 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 May 2008 15:03:12 +1000 Subject: declare composite_wait_free() (This used to be commit 5b6f80aba30fc8ade26f73b0a1336c22e40b66a9) --- source4/libcli/composite/composite.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/libcli') 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__ */ -- cgit From 9bfafcfc213477a4f117ab07ce8f37bc18e74293 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 May 2008 15:03:24 +1000 Subject: build the smb2 composite calls (This used to be commit ac10e3ad15dd17b96424987d1a2b7a0e4dc67cd0) --- source4/libcli/config.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/libcli') diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 95b45003be..4350cd7b04 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -33,7 +33,8 @@ LIBCLI_SMB_COMPOSITE_OBJ_FILES = $(addprefix libcli/smb_composite/, \ sesssetup.o \ fetchfile.o \ appendacl.o \ - fsinfo.o) + fsinfo.o \ + smb2.o) [SUBSYSTEM::NDR_NBT_BUF] -- cgit From c7d7577fb978dfa822b4aab238440816188099c6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 May 2008 15:03:58 +1000 Subject: private -> private_data for struct smb2_request (This used to be commit 67290e0ad69df2f2fe651249c6550b8e32dd641b) --- source4/libcli/smb2/connect.c | 8 ++++---- source4/libcli/smb2/request.c | 25 +++++++++++++++++-------- source4/libcli/smb2/session.c | 4 ++-- source4/libcli/smb2/smb2.h | 7 ++++++- source4/libcli/smb_composite/smb_composite.h | 1 + 5 files changed, 30 insertions(+), 15 deletions(-) (limited to 'source4/libcli') 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/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 . */ +#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/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" /* -- cgit From 66cbf7eb59ab4a29dca1d30850c9aeb35a598b3d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 19 May 2008 11:39:16 +1000 Subject: added mkdir to SMB2 proxy (This used to be commit 1323aab11fbf346e19c4cef227d727ddfcaa7d60) --- source4/libcli/smb_composite/smb2.c | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'source4/libcli') diff --git a/source4/libcli/smb_composite/smb2.c b/source4/libcli/smb_composite/smb2.c index 7bce65fb27..7fccbe3a3c 100644 --- a/source4/libcli/smb_composite/smb2.c +++ b/source4/libcli/smb_composite/smb2.c @@ -120,3 +120,75 @@ NTSTATUS smb2_composite_unlink(struct smb2_tree *tree, union smb_unlink *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); +} + -- cgit From e7d993b8b26e121ff37640825b4d2f2c4d6332bf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 19 May 2008 13:05:08 +1000 Subject: added SMB2 proxying of rmdir (This used to be commit 1e0c24b2760f2a632333b51710cd9581f0cee851) --- source4/libcli/smb_composite/smb2.c | 74 ++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) (limited to 'source4/libcli') diff --git a/source4/libcli/smb_composite/smb2.c b/source4/libcli/smb_composite/smb2.c index 7fccbe3a3c..84b4f66b61 100644 --- a/source4/libcli/smb_composite/smb2.c +++ b/source4/libcli/smb_composite/smb2.c @@ -98,7 +98,9 @@ struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree, 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.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++; @@ -192,3 +194,73 @@ NTSTATUS smb2_composite_mkdir(struct smb2_tree *tree, union smb_mkdir *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); +} -- cgit From 9c6a35ad9ba9458fe9d3a73ba1f785a61305e2aa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 May 2008 11:57:43 +1000 Subject: remember the server time fields on negotiate. Needed for gentest (This used to be commit 7989ca861dcc700b52be3a47ea5ae8b03fbb9330) --- source4/libcli/smb2/connect.c | 3 +++ source4/libcli/smb2/smb2.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'source4/libcli') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 867af14c92..eabfa410ad 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -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; diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 964dcf320c..b55da05e21 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -35,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 */ -- cgit From 803c076450da4075c71faaba3f0882f0b8e6208a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 May 2008 11:58:04 +1000 Subject: added some SMB2 utility functions (This used to be commit 6a3b1cd6698faa460c6258bb41b4936e363f4387) --- source4/libcli/smb2/config.mk | 2 +- source4/libcli/smb2/util.c | 178 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 source4/libcli/smb2/util.c (limited to 'source4/libcli') 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/util.c b/source4/libcli/smb2/util.c new file mode 100644 index 0000000000..0fc03b48c5 --- /dev/null +++ b/source4/libcli/smb2/util.c @@ -0,0 +1,178 @@ +/* + 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 . +*/ + +#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); +} + + + + +/* + 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 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; +} -- cgit From d6f1dd1a422cc2b5d443e82693021e93dc98fe75 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 May 2008 13:37:27 +1000 Subject: added SMB2 setpathinfo composite wrapper (This used to be commit e90c7587385598a1dd976c2420798f9bd682b43d) --- source4/libcli/smb_composite/smb2.c | 105 ++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) (limited to 'source4/libcli') diff --git a/source4/libcli/smb_composite/smb2.c b/source4/libcli/smb_composite/smb2.c index 84b4f66b61..6e005e03c0 100644 --- a/source4/libcli/smb_composite/smb2.c +++ b/source4/libcli/smb_composite/smb2.c @@ -264,3 +264,108 @@ 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); +} -- cgit From 2214e6d9bfdc52db0558e831691b4500405ab9ae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 May 2008 13:37:51 +1000 Subject: added smb2_util_setatr (This used to be commit d4f41db964ce82c8889017d0f932d60100b3cd32) --- source4/libcli/smb2/util.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source4/libcli') diff --git a/source4/libcli/smb2/util.c b/source4/libcli/smb2/util.c index 0fc03b48c5..9eb344e83f 100644 --- a/source4/libcli/smb2/util.c +++ b/source4/libcli/smb2/util.c @@ -82,6 +82,22 @@ NTSTATUS smb2_util_mkdir(struct smb2_tree *tree, const char *dname) } +/* + 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); +} + + /* @@ -151,6 +167,12 @@ int smb2_deltree(struct smb2_tree *tree, const char *dname) } 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); -- cgit