diff options
Diffstat (limited to 'source4/libcli/smb_composite')
-rw-r--r-- | source4/libcli/smb_composite/smb2.c | 211 |
1 files changed, 144 insertions, 67 deletions
diff --git a/source4/libcli/smb_composite/smb2.c b/source4/libcli/smb_composite/smb2.c index d71708a974..5c93869b5c 100644 --- a/source4/libcli/smb_composite/smb2.c +++ b/source4/libcli/smb_composite/smb2.c @@ -25,6 +25,8 @@ #include "includes.h" +#include <tevent.h> +#include "lib/util/tevent_ntstatus.h" #include "libcli/raw/libcliraw.h" #include "libcli/raw/raw_proto.h" #include "libcli/composite/composite.h" @@ -264,107 +266,182 @@ NTSTATUS smb2_composite_rmdir(struct smb2_tree *tree, struct smb_rmdir *io) return composite_wait_free(c); } +struct smb2_composite_setpathinfo_state { + struct smb2_tree *tree; + union smb_setfileinfo io; + NTSTATUS set_status; + struct smb2_create cr; + struct smb2_close cl; +}; + +static void smb2_composite_setpathinfo_create_done(struct smb2_request *smb2req); /* - continue after the setfileinfo in a composite setpathinfo - */ -static void continue_setpathinfo_close(struct smb2_request *req) + composite SMB2 setpathinfo call +*/ +struct tevent_req *smb2_composite_setpathinfo_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smb2_tree *tree, + const union smb_setfileinfo *io) { - 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); + struct tevent_req *req; + struct smb2_composite_setpathinfo_state *state; + struct smb2_request *smb2req; + + req = tevent_req_create(mem_ctx, &state, + struct smb2_composite_setpathinfo_state); + if (req == NULL) { + return NULL; + } - status = smb2_setinfo_recv(req); - if (!NT_STATUS_IS_OK(status)) { - composite_error(ctx, status); - return; + state->tree = tree; + state->io = *io; + + state->cr.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; + state->cr.in.create_disposition = NTCREATEX_DISP_OPEN; + state->cr.in.share_access = + NTCREATEX_SHARE_ACCESS_DELETE| + NTCREATEX_SHARE_ACCESS_READ| + NTCREATEX_SHARE_ACCESS_WRITE; + state->cr.in.create_options = 0; + state->cr.in.fname = state->io.generic.in.file.path; + if (state->cr.in.fname[0] == '\\') { + state->cr.in.fname++; } - 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); + smb2req = smb2_create_send(tree, &state->cr); + if (tevent_req_nomem(smb2req, req)) { + return tevent_req_post(req, ev); + } + smb2req->async.fn = smb2_composite_setpathinfo_create_done; + smb2req->async.private_data = req; + + return req; } +static void smb2_composite_setpathinfo_setinfo_done(struct smb2_request *smb2req); -/* - continue after the create in a composite setpathinfo - */ -static void continue_setpathinfo(struct smb2_request *req) +static void smb2_composite_setpathinfo_create_done(struct smb2_request *smb2req) { - 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 tevent_req *req = + talloc_get_type_abort(smb2req->async.private_data, + struct tevent_req); + struct smb2_composite_setpathinfo_state *state = + tevent_req_data(req, + struct smb2_composite_setpathinfo_state); 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); + status = smb2_create_recv(smb2req, state, &state->cr); + if (tevent_req_nterror(req, status)) { return; } - io2->generic.in.file.handle = create_parm.out.file.handle; + state->io.generic.in.file.handle = state->cr.out.file.handle; - req = smb2_setinfo_file_send(tree, io2); - composite_continue_smb2(ctx, req, continue_setpathinfo_close, ctx); + smb2req = smb2_setinfo_file_send(state->tree, &state->io); + if (tevent_req_nomem(smb2req, req)) { + return; + } + smb2req->async.fn = smb2_composite_setpathinfo_setinfo_done; + smb2req->async.private_data = req; } +static void smb2_composite_setpathinfo_close_done(struct smb2_request *smb2req); -/* - composite SMB2 setpathinfo call -*/ -struct composite_context *smb2_composite_setpathinfo_send(struct smb2_tree *tree, - union smb_setfileinfo *io) +static void smb2_composite_setpathinfo_setinfo_done(struct smb2_request *smb2req) { - struct composite_context *ctx; - struct smb2_create create_parm; - struct smb2_request *req; - union smb_setfileinfo *io2; + struct tevent_req *req = + talloc_get_type_abort(smb2req->async.private_data, + struct tevent_req); + struct smb2_composite_setpathinfo_state *state = + tevent_req_data(req, + struct smb2_composite_setpathinfo_state); + NTSTATUS status; - ctx = composite_create(tree, tree->session->transport->socket->event.ctx); - if (ctx == NULL) return NULL; + status = smb2_setinfo_recv(smb2req); + state->set_status = status; - 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++; + state->cl.in.file.handle = state->io.generic.in.file.handle; + + smb2req = smb2_close_send(state->tree, &state->cl); + if (tevent_req_nomem(smb2req, req)) { + return; } + smb2req->async.fn = smb2_composite_setpathinfo_close_done; + smb2req->async.private_data = req; +} - req = smb2_create_send(tree, &create_parm); +static void smb2_composite_setpathinfo_close_done(struct smb2_request *smb2req) +{ + struct tevent_req *req = + talloc_get_type_abort(smb2req->async.private_data, + struct tevent_req); + struct smb2_composite_setpathinfo_state *state = + tevent_req_data(req, + struct smb2_composite_setpathinfo_state); + NTSTATUS status; - io2 = talloc(ctx, union smb_setfileinfo); - if (composite_nomem(io2, ctx)) { - return ctx; + status = smb2_close_recv(smb2req, &state->cl); + + if (tevent_req_nterror(req, state->set_status)) { + return; } - *io2 = *io; - ctx->private_data = io2; + if (tevent_req_nterror(req, status)) { + return; + } - composite_continue_smb2(ctx, req, continue_setpathinfo, ctx); - return ctx; + tevent_req_done(req); } +NTSTATUS smb2_composite_setpathinfo_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; + } + + tevent_req_received(req); + return NT_STATUS_OK; +} /* 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); + struct tevent_req *subreq; + NTSTATUS status; + bool ok; + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev = tree->session->transport->socket->event.ctx; + + if (frame == NULL) { + return NT_STATUS_NO_MEMORY; + } + + subreq = smb2_composite_setpathinfo_send(frame, ev, tree, io); + if (subreq == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + ok = tevent_req_poll(subreq, ev); + if (!ok) { + status = map_nt_error_from_unix_common(errno); + TALLOC_FREE(frame); + return status; + } + + status = smb2_composite_setpathinfo_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + TALLOC_FREE(frame); + return NT_STATUS_OK; } |