From ab4d635b92b116b02b88843b4ec4f5b7517bab1a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 26 Sep 2005 11:47:55 +0000 Subject: r10504: - seperate implementation specific stuff, from the generic composite stuff. - don't use SMBCLI_REQUEST_* state's in the genreic composite stuff - move monitor_fn to libnet. NOTE: I have maybe found some bugs, in code that is dirrectly in DONE or ERROR state in the _send() function. I haven't fixed this bugs in this commit! We may need some composite_trigger_*() functions or so. And maybe some other generic helper functions... metze (This used to be commit 4527815a0a9b96e460f301cb1f0c0b3964c166fc) --- source4/libcli/cliconnect.c | 1 + source4/libcli/composite/appendacl.c | 311 ------------------ source4/libcli/composite/composite.c | 4 +- source4/libcli/composite/composite.h | 147 +-------- source4/libcli/composite/connect.c | 395 ----------------------- source4/libcli/composite/fetchfile.c | 186 ----------- source4/libcli/composite/fsinfo.c | 200 ------------ source4/libcli/composite/loadfile.c | 293 ----------------- source4/libcli/composite/monitor.h | 42 --- source4/libcli/composite/savefile.c | 288 ----------------- source4/libcli/composite/sesssetup.c | 458 -------------------------- source4/libcli/config.mk | 24 +- source4/libcli/nbt/namerefresh.c | 23 +- source4/libcli/nbt/nameregister.c | 43 ++- source4/libcli/raw/clisocket.c | 16 +- source4/libcli/raw/clitree.c | 1 + source4/libcli/resolve/host.c | 18 +- source4/libcli/resolve/nbtlist.c | 20 +- source4/libcli/resolve/resolve.c | 46 +-- source4/libcli/smb_composite/appendacl.c | 312 ++++++++++++++++++ source4/libcli/smb_composite/connect.c | 396 +++++++++++++++++++++++ source4/libcli/smb_composite/fetchfile.c | 187 +++++++++++ source4/libcli/smb_composite/fsinfo.c | 201 ++++++++++++ source4/libcli/smb_composite/loadfile.c | 294 +++++++++++++++++ source4/libcli/smb_composite/savefile.c | 289 +++++++++++++++++ source4/libcli/smb_composite/sesssetup.c | 459 +++++++++++++++++++++++++++ source4/libcli/smb_composite/smb_composite.h | 152 +++++++++ source4/libnet/composite.h | 19 ++ source4/libnet/domain.c | 20 +- source4/libnet/libnet_lookup.c | 7 +- source4/libnet/userinfo.c | 24 +- source4/libnet/userman.c | 67 ++-- source4/nbt_server/register.c | 21 +- source4/nbt_server/wins/winsclient.c | 21 +- source4/ntvfs/cifs/vfs_cifs.c | 1 + source4/torture/basic/secleak.c | 1 + source4/torture/libnet/domain.c | 1 - source4/torture/libnet/libnet_lookup.c | 1 - source4/torture/libnet/libnet_rpc.c | 1 - source4/torture/libnet/libnet_user.c | 1 - source4/torture/libnet/userinfo.c | 1 - source4/torture/libnet/userman.c | 3 +- source4/torture/raw/composite.c | 11 +- source4/torture/raw/context.c | 1 + source4/winbind/wb_async_helpers.c | 37 ++- source4/winbind/wb_samba3_cmd.c | 4 +- 46 files changed, 2525 insertions(+), 2523 deletions(-) delete mode 100644 source4/libcli/composite/appendacl.c delete mode 100644 source4/libcli/composite/connect.c delete mode 100644 source4/libcli/composite/fetchfile.c delete mode 100644 source4/libcli/composite/fsinfo.c delete mode 100644 source4/libcli/composite/loadfile.c delete mode 100644 source4/libcli/composite/monitor.h delete mode 100644 source4/libcli/composite/savefile.c delete mode 100644 source4/libcli/composite/sesssetup.c create mode 100644 source4/libcli/smb_composite/appendacl.c create mode 100644 source4/libcli/smb_composite/connect.c create mode 100644 source4/libcli/smb_composite/fetchfile.c create mode 100644 source4/libcli/smb_composite/fsinfo.c create mode 100644 source4/libcli/smb_composite/loadfile.c create mode 100644 source4/libcli/smb_composite/savefile.c create mode 100644 source4/libcli/smb_composite/sesssetup.c create mode 100644 source4/libcli/smb_composite/smb_composite.h (limited to 'source4') diff --git a/source4/libcli/cliconnect.c b/source4/libcli/cliconnect.c index aba7f361a2..00c5012074 100644 --- a/source4/libcli/cliconnect.c +++ b/source4/libcli/cliconnect.c @@ -23,6 +23,7 @@ #include "includes.h" #include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" /* wrapper around smbcli_sock_connect() diff --git a/source4/libcli/composite/appendacl.c b/source4/libcli/composite/appendacl.c deleted file mode 100644 index 76702e6bca..0000000000 --- a/source4/libcli/composite/appendacl.c +++ /dev/null @@ -1,311 +0,0 @@ -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/composite/composite.h" -#include "librpc/gen_ndr/ndr_security.h" - -/* the stages of this call */ -enum appendacl_stage {APPENDACL_OPENPATH, APPENDACL_GET, - APPENDACL_SET, APPENDACL_GETAGAIN, APPENDACL_CLOSEPATH}; - -static void appendacl_handler(struct smbcli_request *req); - -struct appendacl_state { - enum appendacl_stage stage; - struct smb_composite_appendacl *io; - - union smb_open *io_open; - union smb_setfileinfo *io_setfileinfo; - union smb_fileinfo *io_fileinfo; - - struct smbcli_request *req; -}; - - -static NTSTATUS appendacl_open(struct composite_context *c, - struct smb_composite_appendacl *io) -{ - struct appendacl_state *state = talloc_get_type(c->private, struct appendacl_state); - struct smbcli_tree *tree = state->req->tree; - NTSTATUS status; - - status = smb_raw_open_recv(state->req, c, state->io_open); - NT_STATUS_NOT_OK_RETURN(status); - - /* setup structures for getting fileinfo */ - state->io_fileinfo = talloc(c, union smb_fileinfo); - NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo); - - state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC; - state->io_fileinfo->query_secdesc.in.fnum = state->io_open->ntcreatex.out.fnum; - state->io_fileinfo->query_secdesc.secinfo_flags = SECINFO_DACL; - - state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* set the handler */ - state->req->async.fn = appendacl_handler; - state->req->async.private = c; - state->stage = APPENDACL_GET; - - talloc_free (state->io_open); - - return NT_STATUS_OK; -} - -static NTSTATUS appendacl_get(struct composite_context *c, - struct smb_composite_appendacl *io) -{ - struct appendacl_state *state = talloc_get_type(c->private, struct appendacl_state); - struct smbcli_tree *tree = state->req->tree; - int i; - NTSTATUS status; - - status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo); - NT_STATUS_NOT_OK_RETURN(status); - - /* setup structures for setting fileinfo */ - state->io_setfileinfo = talloc(c, union smb_setfileinfo); - NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo); - - state->io_setfileinfo->set_secdesc.level = RAW_SFILEINFO_SEC_DESC; - state->io_setfileinfo->set_secdesc.file.fnum = state->io_fileinfo->query_secdesc.in.fnum; - - state->io_setfileinfo->set_secdesc.in.secinfo_flags = SECINFO_DACL; - state->io_setfileinfo->set_secdesc.in.sd = state->io_fileinfo->query_secdesc.out.sd; - talloc_steal(state->io_setfileinfo, state->io_setfileinfo->set_secdesc.in.sd); - - /* append all aces from io->in.sd->dacl to new security descriptor */ - if (io->in.sd->dacl != NULL) { - for (i = 0; i < io->in.sd->dacl->num_aces; i++) { - security_descriptor_dacl_add(state->io_setfileinfo->set_secdesc.in.sd, - &(io->in.sd->dacl->aces[i])); - } - } - - status = smb_raw_setfileinfo(tree, state->io_setfileinfo); - NT_STATUS_NOT_OK_RETURN(status); - - state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* call handler when done setting new security descriptor on file */ - state->req->async.fn = appendacl_handler; - state->req->async.private = c; - state->stage = APPENDACL_SET; - - talloc_free (state->io_fileinfo); - - return NT_STATUS_OK; -} - -static NTSTATUS appendacl_set(struct composite_context *c, - struct smb_composite_appendacl *io) -{ - struct appendacl_state *state = talloc_get_type(c->private, struct appendacl_state); - struct smbcli_tree *tree = state->req->tree; - NTSTATUS status; - - status = smbcli_request_simple_recv(state->req); - NT_STATUS_NOT_OK_RETURN(status); - - /* setup structures for getting fileinfo */ - state->io_fileinfo = talloc(c, union smb_fileinfo); - NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo); - - - state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC; - state->io_fileinfo->query_secdesc.in.fnum = state->io_setfileinfo->set_secdesc.file.fnum; - state->io_fileinfo->query_secdesc.secinfo_flags = SECINFO_DACL; - - state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* set the handler */ - state->req->async.fn = appendacl_handler; - state->req->async.private = c; - state->stage = APPENDACL_GETAGAIN; - - talloc_free (state->io_setfileinfo); - - return NT_STATUS_OK; -} - - -static NTSTATUS appendacl_getagain(struct composite_context *c, - struct smb_composite_appendacl *io) -{ - struct appendacl_state *state = talloc_get_type(c->private, struct appendacl_state); - struct smbcli_tree *tree = state->req->tree; - union smb_close *io_close; - NTSTATUS status; - - status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo); - NT_STATUS_NOT_OK_RETURN(status); - - io->out.sd = state->io_fileinfo->query_secdesc.out.sd; - - /* setup structures for close */ - io_close = talloc(c, union smb_close); - NT_STATUS_HAVE_NO_MEMORY(io_close); - - io_close->close.level = RAW_CLOSE_CLOSE; - io_close->close.in.fnum = state->io_fileinfo->query_secdesc.in.fnum; - io_close->close.in.write_time = 0; - - state->req = smb_raw_close_send(tree, io_close); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* call the handler */ - state->req->async.fn = appendacl_handler; - state->req->async.private = c; - state->stage = APPENDACL_CLOSEPATH; - - talloc_free (state->io_fileinfo); - - return NT_STATUS_OK; -} - - - -static NTSTATUS appendacl_close(struct composite_context *c, - struct smb_composite_appendacl *io) -{ - struct appendacl_state *state = talloc_get_type(c->private, struct appendacl_state); - NTSTATUS status; - - status = smbcli_request_simple_recv(state->req); - NT_STATUS_NOT_OK_RETURN(status); - - c->state = SMBCLI_REQUEST_DONE; - - return NT_STATUS_OK; -} - -/* - handler for completion of a sub-request in appendacl -*/ -static void appendacl_handler(struct smbcli_request *req) -{ - struct composite_context *c = req->async.private; - struct appendacl_state *state = talloc_get_type(c->private, struct appendacl_state); - - /* when this handler is called, the stage indicates what - call has just finished */ - switch (state->stage) { - case APPENDACL_OPENPATH: - c->status = appendacl_open(c, state->io); - break; - - case APPENDACL_GET: - c->status = appendacl_get(c, state->io); - break; - - case APPENDACL_SET: - c->status = appendacl_set(c, state->io); - break; - - case APPENDACL_GETAGAIN: - c->status = appendacl_getagain(c, state->io); - break; - - case APPENDACL_CLOSEPATH: - c->status = appendacl_close(c, state->io); - break; - } - - /* We should get here if c->state >= SMBCLI_REQUEST_DONE */ - if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; - } - - if (c->state >= SMBCLI_REQUEST_DONE && - c->async.fn) { - c->async.fn(c); - } -} - - -/* - composite appendacl call - does an open followed by a number setfileinfo, - after that new acls are read with fileinfo, followed by a close -*/ -struct composite_context *smb_composite_appendacl_send(struct smbcli_tree *tree, - struct smb_composite_appendacl *io) -{ - struct composite_context *c; - struct appendacl_state *state; - - c = talloc_zero(tree, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct appendacl_state); - if (state == NULL) goto failed; - - state->io = io; - - c->private = state; - c->state = SMBCLI_REQUEST_SEND; - c->event_ctx = tree->session->transport->socket->event.ctx; - - /* setup structures for opening file */ - state->io_open = talloc_zero(c, union smb_open); - if (state->io_open == NULL) goto failed; - - state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX; - state->io_open->ntcreatex.in.root_fid = 0; - state->io_open->ntcreatex.in.flags = 0; - state->io_open->ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - state->io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; - state->io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; - state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; - state->io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; - state->io_open->ntcreatex.in.security_flags = 0; - state->io_open->ntcreatex.in.fname = io->in.fname; - - /* send the open on its way */ - state->req = smb_raw_open_send(tree, state->io_open); - if (state->req == NULL) goto failed; - - /* setup the callback handler */ - state->req->async.fn = appendacl_handler; - state->req->async.private = c; - state->stage = APPENDACL_OPENPATH; - - return c; - -failed: - talloc_free(c); - return NULL; -} - - -/* - composite appendacl call - recv side -*/ -NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) -{ - NTSTATUS status; - - status = composite_wait(c); - - if (NT_STATUS_IS_OK(status)) { - struct appendacl_state *state = talloc_get_type(c->private, struct appendacl_state); - state->io->out.sd = security_descriptor_copy (mem_ctx, state->io->out.sd); - } - - talloc_free(c); - return status; -} - - -/* - composite appendacl call - sync interface -*/ -NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree, - TALLOC_CTX *mem_ctx, - struct smb_composite_appendacl *io) -{ - struct composite_context *c = smb_composite_appendacl_send(tree, io); - return smb_composite_appendacl_recv(c, mem_ctx); -} - diff --git a/source4/libcli/composite/composite.c b/source4/libcli/composite/composite.c index f04309bbfb..4a5247c9ea 100644 --- a/source4/libcli/composite/composite.c +++ b/source4/libcli/composite/composite.c @@ -34,7 +34,7 @@ NTSTATUS composite_wait(struct composite_context *c) { if (c == NULL) return NT_STATUS_NO_MEMORY; - while (c->state < SMBCLI_REQUEST_DONE) { + while (c->state < COMPOSITE_STATE_DONE) { if (event_loop_once(c->event_ctx) != 0) { return NT_STATUS_UNSUCCESSFUL; } @@ -51,7 +51,6 @@ static void composite_trigger(struct event_context *ev, struct timed_event *te, struct timeval t, void *ptr) { struct composite_context *c = talloc_get_type(ptr, struct composite_context); - c->state = SMBCLI_REQUEST_DONE; if (c->async.fn) { c->async.fn(c); } @@ -65,6 +64,7 @@ static void composite_trigger(struct event_context *ev, struct timed_event *te, */ void composite_trigger_done(struct composite_context *c) { + c->state = COMPOSITE_STATE_DONE; /* a zero timeout means immediate */ event_add_timed(c->event_ctx, c, timeval_zero(), composite_trigger, c); } diff --git a/source4/libcli/composite/composite.h b/source4/libcli/composite/composite.h index be7fbd9972..83857edd14 100644 --- a/source4/libcli/composite/composite.h +++ b/source4/libcli/composite/composite.h @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. - SMB composite request interfaces + composite request interfaces Copyright (C) Andrew Tridgell 2005 @@ -23,19 +23,28 @@ /* this defines the structures associated with "composite" requests. Composite requests are libcli requests that are internally - implemented as multiple libcli/raw/ calls, but can be treated as a + implemented as multiple async calls, but can be treated as a single call via these composite calls. The composite calls are - particularly designed to be used in async applications + particularly designed to be used in async applications. + you can also stack multiple level of composite call */ +/* + a composite call moves between the following 3 states. +*/ +enum composite_state {COMPOSITE_STATE_INIT, /* we are creating the request */ + COMPOSITE_STATE_IN_PROGRESS, /* the request is in the outgoing socket Q */ + COMPOSITE_STATE_DONE, /* the request is received by the caller finished */ + COMPOSITE_STATE_ERROR}; /* a packet or transport level error has occurred */ +/* the context of one "composite" call */ struct composite_context { /* the external state - will be queried by the caller */ - enum smbcli_request_state state; + enum composite_state state; /* a private pointer for use by the composite function implementation */ - void *private; + void *private_data; /* status code when finished */ NTSTATUS status; @@ -46,132 +55,6 @@ struct composite_context { /* information on what to do on completion */ struct { void (*fn)(struct composite_context *); - void *private; + void *private_data; } async; - - /* information about the progress */ - void (*monitor_fn)(struct monitor_msg *); -}; - - -/* - a composite open/read(s)/close request that loads a whole file - into memory. Used as a demo of the composite system. -*/ -struct smb_composite_loadfile { - struct { - const char *fname; - } in; - struct { - uint8_t *data; - uint32_t size; - } out; -}; - -struct smb_composite_fetchfile { - struct { - const char *dest_host; - int port; - const char *called_name; - const char *service; - const char *service_type; - struct cli_credentials *credentials; - const char *workgroup; - const char *filename; - } in; - struct { - uint8_t *data; - uint32_t size; - } out; -}; - -/* - a composite open/write(s)/close request that saves a whole file from - memory. Used as a demo of the composite system. -*/ -struct smb_composite_savefile { - struct { - const char *fname; - uint8_t *data; - uint32_t size; - } in; -}; - - -/* - a composite request for a full connection to a remote server. Includes - - - socket establishment - - session request - - negprot - - session setup - - tree connect -*/ -struct smb_composite_connect { - struct { - const char *dest_host; - int port; - const char *called_name; - const char *service; - const char *service_type; - struct cli_credentials *credentials; - const char *workgroup; - } in; - struct { - struct smbcli_tree *tree; - } out; -}; - - -/* - generic session setup interface that takes care of which - session setup varient to use -*/ -struct smb_composite_sesssetup { - struct { - uint32_t sesskey; - uint32_t capabilities; - struct cli_credentials *credentials; - const char *workgroup; - } in; - struct { - uint16_t vuid; - } out; -}; - -/* - query file system info -*/ -struct smb_composite_fsinfo { - struct { - const char *dest_host; - int port; - const char *called_name; - const char *service; - const char *service_type; - struct cli_credentials *credentials; - const char *workgroup; - enum smb_fsinfo_level level; - } in; - - struct { - union smb_fsinfo *fsinfo; - } out; -}; - -/* - composite call for appending new acl to the file's security descriptor and get - new full acl -*/ - -struct smb_composite_appendacl { - struct { - const char *fname; - - const struct security_descriptor *sd; - } in; - - struct { - struct security_descriptor *sd; - } out; }; diff --git a/source4/libcli/composite/connect.c b/source4/libcli/composite/connect.c deleted file mode 100644 index a5ce5308e5..0000000000 --- a/source4/libcli/composite/connect.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - a composite API for making a full SMB connection -*/ - -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/composite/composite.h" - -/* the stages of this call */ -enum connect_stage {CONNECT_RESOLVE, - CONNECT_SOCKET, - CONNECT_SESSION_REQUEST, - CONNECT_NEGPROT, - CONNECT_SESSION_SETUP, - CONNECT_TCON}; - -struct connect_state { - enum connect_stage stage; - struct smbcli_socket *sock; - struct smbcli_transport *transport; - struct smbcli_session *session; - struct smb_composite_connect *io; - union smb_tcon *io_tcon; - struct smb_composite_sesssetup *io_setup; - struct smbcli_request *req; - struct composite_context *creq; -}; - - -static void request_handler(struct smbcli_request *); -static void composite_handler(struct composite_context *); - -/* - setup a negprot send -*/ -static NTSTATUS connect_send_negprot(struct composite_context *c, - struct smb_composite_connect *io) -{ - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - - state->req = smb_raw_negotiate_send(state->transport, lp_maxprotocol()); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - state->req->async.fn = request_handler; - state->req->async.private = c; - state->stage = CONNECT_NEGPROT; - - return NT_STATUS_OK; -} - - -/* - a tree connect request has competed -*/ -static NTSTATUS connect_tcon(struct composite_context *c, - struct smb_composite_connect *io) -{ - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - NTSTATUS status; - - status = smb_raw_tcon_recv(state->req, c, state->io_tcon); - NT_STATUS_NOT_OK_RETURN(status); - - io->out.tree->tid = state->io_tcon->tconx.out.tid; - if (state->io_tcon->tconx.out.dev_type) { - io->out.tree->device = talloc_strdup(io->out.tree, - state->io_tcon->tconx.out.dev_type); - } - if (state->io_tcon->tconx.out.fs_type) { - io->out.tree->fs_type = talloc_strdup(io->out.tree, - state->io_tcon->tconx.out.fs_type); - } - - /* all done! */ - c->state = SMBCLI_REQUEST_DONE; - - return NT_STATUS_OK; -} - - -/* - a session setup request has competed -*/ -static NTSTATUS connect_session_setup(struct composite_context *c, - struct smb_composite_connect *io) -{ - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - NTSTATUS status; - - status = smb_composite_sesssetup_recv(state->creq); - NT_STATUS_NOT_OK_RETURN(status); - - state->session->vuid = state->io_setup->out.vuid; - - /* setup for a tconx */ - io->out.tree = smbcli_tree_init(state->session, state, True); - NT_STATUS_HAVE_NO_MEMORY(io->out.tree); - - state->io_tcon = talloc(c, union smb_tcon); - NT_STATUS_HAVE_NO_MEMORY(state->io_tcon); - - /* connect to a share using a tree connect */ - state->io_tcon->generic.level = RAW_TCON_TCONX; - state->io_tcon->tconx.in.flags = 0; - state->io_tcon->tconx.in.password = data_blob(NULL, 0); - - state->io_tcon->tconx.in.path = talloc_asprintf(state->io_tcon, - "\\\\%s\\%s", - io->in.called_name, - io->in.service); - NT_STATUS_HAVE_NO_MEMORY(state->io_tcon->tconx.in.path); - if (!io->in.service_type) { - state->io_tcon->tconx.in.device = "?????"; - } else { - state->io_tcon->tconx.in.device = io->in.service_type; - } - - state->req = smb_raw_tcon_send(io->out.tree, state->io_tcon); - NT_STATUS_HAVE_NO_MEMORY(state->req); - if (state->req->state == SMBCLI_REQUEST_ERROR) { - return state->req->status; - } - - state->req->async.fn = request_handler; - state->req->async.private = c; - state->stage = CONNECT_TCON; - - return NT_STATUS_OK; -} - -/* - a negprot request has competed -*/ -static NTSTATUS connect_negprot(struct composite_context *c, - struct smb_composite_connect *io) -{ - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - NTSTATUS status; - - status = smb_raw_negotiate_recv(state->req); - NT_STATUS_NOT_OK_RETURN(status); - - /* next step is a session setup */ - state->session = smbcli_session_init(state->transport, state, True); - NT_STATUS_HAVE_NO_MEMORY(state->session); - - state->io_setup = talloc(c, struct smb_composite_sesssetup); - NT_STATUS_HAVE_NO_MEMORY(state->io_setup); - - /* prepare a session setup to establish a security context */ - state->io_setup->in.sesskey = state->transport->negotiate.sesskey; - state->io_setup->in.capabilities = state->transport->negotiate.capabilities; - state->io_setup->in.credentials = io->in.credentials; - state->io_setup->in.workgroup = io->in.workgroup; - - state->creq = smb_composite_sesssetup_send(state->session, state->io_setup); - NT_STATUS_HAVE_NO_MEMORY(state->creq); - if (state->creq->state == SMBCLI_REQUEST_ERROR) { - return state->creq->status; - } - - state->creq->async.fn = composite_handler; - state->creq->async.private = c; - state->stage = CONNECT_SESSION_SETUP; - - return NT_STATUS_OK; -} - - -/* - a session request operation has competed -*/ -static NTSTATUS connect_session_request(struct composite_context *c, - struct smb_composite_connect *io) -{ - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - NTSTATUS status; - - status = smbcli_transport_connect_recv(state->req); - NT_STATUS_NOT_OK_RETURN(status); - - /* next step is a negprot */ - return connect_send_negprot(c, io); -} - -/* - a socket connection operation has competed -*/ -static NTSTATUS connect_socket(struct composite_context *c, - struct smb_composite_connect *io) -{ - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - NTSTATUS status; - struct nbt_name calling, called; - - status = smbcli_sock_connect_recv(state->creq); - NT_STATUS_NOT_OK_RETURN(status); - - /* the socket is up - we can initialise the smbcli transport layer */ - state->transport = smbcli_transport_init(state->sock, state, True); - NT_STATUS_HAVE_NO_MEMORY(state->transport); - - make_nbt_name_client(&calling, cli_credentials_get_workstation(io->in.credentials)); - - nbt_choose_called_name(state, &called, io->in.called_name, NBT_NAME_SERVER); - - /* we have a connected socket - next step is a session - request, if needed. Port 445 doesn't need it, so it goes - straight to the negprot */ - if (state->sock->port == 445) { - status = nbt_name_dup(state->transport, &called, - &state->transport->called); - NT_STATUS_NOT_OK_RETURN(status); - return connect_send_negprot(c, io); - } - - state->req = smbcli_transport_connect_send(state->transport, &calling, &called); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - state->req->async.fn = request_handler; - state->req->async.private = c; - state->stage = CONNECT_SESSION_REQUEST; - - return NT_STATUS_OK; -} - - -/* - called when name resolution is finished -*/ -static NTSTATUS connect_resolve(struct composite_context *c, - struct smb_composite_connect *io) -{ - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - NTSTATUS status; - const char *address; - - status = resolve_name_recv(state->creq, state, &address); - NT_STATUS_NOT_OK_RETURN(status); - - state->creq = smbcli_sock_connect_send(state->sock, address, state->io->in.port, io->in.dest_host); - NT_STATUS_HAVE_NO_MEMORY(state->creq); - - state->stage = CONNECT_SOCKET; - state->creq->async.private = c; - state->creq->async.fn = composite_handler; - - return NT_STATUS_OK; -} - - -/* - handle and dispatch state transitions -*/ -static void state_handler(struct composite_context *c) -{ - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - - switch (state->stage) { - case CONNECT_RESOLVE: - c->status = connect_resolve(c, state->io); - break; - case CONNECT_SOCKET: - c->status = connect_socket(c, state->io); - break; - case CONNECT_SESSION_REQUEST: - c->status = connect_session_request(c, state->io); - break; - case CONNECT_NEGPROT: - c->status = connect_negprot(c, state->io); - break; - case CONNECT_SESSION_SETUP: - c->status = connect_session_setup(c, state->io); - break; - case CONNECT_TCON: - c->status = connect_tcon(c, state->io); - break; - } - - if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; - } - - if (c->state >= SMBCLI_REQUEST_DONE && - c->async.fn) { - c->async.fn(c); - } -} - - -/* - handler for completion of a smbcli_request sub-request -*/ -static void request_handler(struct smbcli_request *req) -{ - struct composite_context *c = talloc_get_type(req->async.private, - struct composite_context); - state_handler(c); -} - -/* - handler for completion of a smbcli_composite sub-request -*/ -static void composite_handler(struct composite_context *req) -{ - struct composite_context *c = talloc_get_type(req->async.private, - struct composite_context); - state_handler(c); -} - -/* - a function to establish a smbcli_tree from scratch -*/ -struct composite_context *smb_composite_connect_send(struct smb_composite_connect *io, - struct event_context *event_ctx) -{ - struct composite_context *c; - struct connect_state *state; - struct nbt_name name; - - c = talloc_zero(NULL, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct connect_state); - if (state == NULL) goto failed; - - state->sock = smbcli_sock_init(state, event_ctx); - if (state->sock == NULL) goto failed; - - state->io = io; - - c->state = SMBCLI_REQUEST_SEND; - c->event_ctx = talloc_reference(c, state->sock->event.ctx); - c->private = state; - - state->stage = CONNECT_RESOLVE; - make_nbt_name_server(&name, io->in.dest_host); - state->creq = resolve_name_send(&name, c->event_ctx, lp_name_resolve_order()); - - if (state->creq == NULL) goto failed; - state->creq->async.private = c; - state->creq->async.fn = composite_handler; - - return c; -failed: - talloc_free(c); - return NULL; -} - -/* - recv half of async composite connect code -*/ -NTSTATUS smb_composite_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) -{ - NTSTATUS status; - - status = composite_wait(c); - - if (NT_STATUS_IS_OK(status)) { - struct connect_state *state = talloc_get_type(c->private, struct connect_state); - talloc_steal(mem_ctx, state->io->out.tree); - } - - talloc_free(c); - return status; -} - -/* - sync version of smb_composite_connect -*/ -NTSTATUS smb_composite_connect(struct smb_composite_connect *io, TALLOC_CTX *mem_ctx, - struct event_context *ev) -{ - struct composite_context *c = smb_composite_connect_send(io, ev); - return smb_composite_connect_recv(c, mem_ctx); -} diff --git a/source4/libcli/composite/fetchfile.c b/source4/libcli/composite/fetchfile.c deleted file mode 100644 index c9e8321db2..0000000000 --- a/source4/libcli/composite/fetchfile.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Volker Lendecke 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - a composite API for loading a whole file into memory -*/ - -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/composite/composite.h" - -enum fetchfile_stage {FETCHFILE_CONNECT, - FETCHFILE_READ}; - -struct fetchfile_state { - enum fetchfile_stage stage; - struct smb_composite_fetchfile *io; - struct composite_context *req; - struct smb_composite_connect *connect; - struct smb_composite_loadfile *loadfile; -}; - -static void fetchfile_composite_handler(struct composite_context *req); - -static NTSTATUS fetchfile_connect(struct composite_context *c, - struct smb_composite_fetchfile *io) -{ - NTSTATUS status; - struct fetchfile_state *state; - state = talloc_get_type(c->private, struct fetchfile_state); - - status = smb_composite_connect_recv(state->req, c); - NT_STATUS_NOT_OK_RETURN(status); - - state->loadfile = talloc(state, struct smb_composite_loadfile); - NT_STATUS_HAVE_NO_MEMORY(state->loadfile); - - state->loadfile->in.fname = io->in.filename; - - state->req = smb_composite_loadfile_send(state->connect->out.tree, - state->loadfile); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - state->req->async.private = c; - state->req->async.fn = fetchfile_composite_handler; - - state->stage = FETCHFILE_READ; - c->event_ctx = talloc_reference(c, state->req->event_ctx); - - return NT_STATUS_OK; -} - -static NTSTATUS fetchfile_read(struct composite_context *c, - struct smb_composite_fetchfile *io) -{ - NTSTATUS status; - struct fetchfile_state *state; - state = talloc_get_type(c->private, struct fetchfile_state); - - status = smb_composite_loadfile_recv(state->req, NULL); - NT_STATUS_NOT_OK_RETURN(status); - - io->out.data = state->loadfile->out.data; - io->out.size = state->loadfile->out.size; - - c->state = SMBCLI_REQUEST_DONE; - if (c->async.fn) - c->async.fn(c); - - return NT_STATUS_OK; -} - -static void fetchfile_state_handler(struct composite_context *c) -{ - struct fetchfile_state *state; - NTSTATUS status; - - state = talloc_get_type(c->private, struct fetchfile_state); - - /* when this handler is called, the stage indicates what - call has just finished */ - switch (state->stage) { - case FETCHFILE_CONNECT: - status = fetchfile_connect(c, state->io); - break; - case FETCHFILE_READ: - status = fetchfile_read(c, state->io); - break; - } - - if (!NT_STATUS_IS_OK(status)) { - c->status = status; - c->state = SMBCLI_REQUEST_ERROR; - if (c->async.fn) { - c->async.fn(c); - } - } -} - -static void fetchfile_composite_handler(struct composite_context *req) -{ - struct composite_context *c = talloc_get_type(req->async.private, - struct composite_context); - fetchfile_state_handler(c); -} - -struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetchfile *io, - struct event_context *event_ctx) -{ - struct composite_context *c; - struct fetchfile_state *state; - - c = talloc_zero(NULL, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct fetchfile_state); - if (state == NULL) goto failed; - - state->connect = talloc(state, struct smb_composite_connect); - if (state->connect == NULL) goto failed; - - state->io = io; - - state->connect->in.dest_host = io->in.dest_host; - state->connect->in.port = io->in.port; - state->connect->in.called_name = io->in.called_name; - state->connect->in.service = io->in.service; - state->connect->in.service_type = io->in.service_type; - state->connect->in.credentials = io->in.credentials; - state->connect->in.workgroup = io->in.workgroup; - - state->req = smb_composite_connect_send(state->connect, event_ctx); - if (state->req == NULL) goto failed; - - state->req->async.private = c; - state->req->async.fn = fetchfile_composite_handler; - - c->state = SMBCLI_REQUEST_SEND; - state->stage = FETCHFILE_CONNECT; - c->event_ctx = talloc_reference(c, state->req->event_ctx); - c->private = state; - - return c; - failed: - talloc_free(c); - return NULL; -} - -NTSTATUS smb_composite_fetchfile_recv(struct composite_context *c, - TALLOC_CTX *mem_ctx) -{ - NTSTATUS status; - - status = composite_wait(c); - - if (NT_STATUS_IS_OK(status)) { - struct fetchfile_state *state = talloc_get_type(c->private, struct fetchfile_state); - talloc_steal(mem_ctx, state->io->out.data); - } - - talloc_free(c); - return status; -} - -NTSTATUS smb_composite_fetchfile(struct smb_composite_fetchfile *io, - TALLOC_CTX *mem_ctx) -{ - struct composite_context *c = smb_composite_fetchfile_send(io, NULL); - return smb_composite_fetchfile_recv(c, mem_ctx); -} diff --git a/source4/libcli/composite/fsinfo.c b/source4/libcli/composite/fsinfo.c deleted file mode 100644 index e0accbb6a6..0000000000 --- a/source4/libcli/composite/fsinfo.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - a composite API for quering file system information -*/ - -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/composite/composite.h" -#include "librpc/gen_ndr/ndr_security.h" - -/* the stages of this call */ -enum fsinfo_stage {FSINFO_CONNECT, FSINFO_QUERY}; - - -static void fsinfo_raw_handler(struct smbcli_request *req); -static void fsinfo_composite_handler(struct composite_context *c); -static void fsinfo_state_handler(struct composite_context *c); - -struct fsinfo_state { - enum fsinfo_stage stage; - struct composite_context *creq; - struct smb_composite_fsinfo *io; - struct smb_composite_connect *connect; - union smb_fsinfo *fsinfo; - struct smbcli_tree *tree; - struct smbcli_request *req; -}; - -static NTSTATUS fsinfo_connect(struct composite_context *c, - struct smb_composite_fsinfo *io) -{ - NTSTATUS status; - struct fsinfo_state *state; - state = talloc_get_type(c->private, struct fsinfo_state); - - status = smb_composite_connect_recv(state->creq, c); - NT_STATUS_NOT_OK_RETURN(status); - - state->fsinfo = talloc(state, union smb_fsinfo); - NT_STATUS_HAVE_NO_MEMORY(state->fsinfo); - - state->fsinfo->generic.level = io->in.level; - - state->req = smb_raw_fsinfo_send(state->connect->out.tree, - state, - state->fsinfo); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - state->req->async.private = c; - state->req->async.fn = fsinfo_raw_handler; - - state->stage = FSINFO_QUERY; - c->event_ctx = talloc_reference(c, state->req->session->transport->socket->event.ctx); - - return NT_STATUS_OK; -} - -static NTSTATUS fsinfo_query(struct composite_context *c, - struct smb_composite_fsinfo *io) -{ - NTSTATUS status; - struct fsinfo_state *state; - state = talloc_get_type(c->private, struct fsinfo_state); - - status = smb_raw_fsinfo_recv(state->req, state, state->fsinfo); - NT_STATUS_NOT_OK_RETURN(status); - - state->io->out.fsinfo = state->fsinfo; - - c->state = SMBCLI_REQUEST_DONE; - - if (c->async.fn) - c->async.fn(c); - - return NT_STATUS_OK; - -} - -/* - handler for completion of a sub-request in fsinfo -*/ -static void fsinfo_state_handler(struct composite_context *req) -{ - struct fsinfo_state *state = talloc_get_type(req->private, struct fsinfo_state); - - /* when this handler is called, the stage indicates what - call has just finished */ - switch (state->stage) { - case FSINFO_CONNECT: - req->status = fsinfo_connect(req, state->io); - break; - - case FSINFO_QUERY: - req->status = fsinfo_query(req, state->io); - break; - } - - if (!NT_STATUS_IS_OK(req->status)) { - req->state = SMBCLI_REQUEST_ERROR; - } - - if (req->state >= SMBCLI_REQUEST_DONE && req->async.fn) { - req->async.fn(req); - } -} - -/* - As raw and composite handlers take different requests, we need to handlers - to adapt both for the same state machine in fsinfo_state_handler() -*/ -static void fsinfo_raw_handler(struct smbcli_request *req) -{ - struct composite_context *c = talloc_get_type(req->async.private, - struct composite_context); - fsinfo_state_handler(c); -} - -static void fsinfo_composite_handler(struct composite_context *req) -{ - struct composite_context *c = talloc_get_type(req->async.private, - struct composite_context); - fsinfo_state_handler(c); -} - -/* - composite fsinfo call - connects to a tree and queries a file system information -*/ -struct composite_context *smb_composite_fsinfo_send(struct smbcli_tree *tree, - struct smb_composite_fsinfo *io) -{ - struct composite_context *c; - struct fsinfo_state *state; - - c = talloc_zero(tree, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct fsinfo_state); - if (state == NULL) goto failed; - - state->io = io; - - state->connect = talloc(state, struct smb_composite_connect); - - if (state->connect == NULL) goto failed; - - state->connect->in.dest_host = io->in.dest_host; - state->connect->in.port = io->in.port; - state->connect->in.called_name = io->in.called_name; - state->connect->in.service = io->in.service; - state->connect->in.service_type = io->in.service_type; - state->connect->in.credentials = io->in.credentials; - state->connect->in.workgroup = io->in.workgroup; - - c->state = SMBCLI_REQUEST_SEND; - state->stage = FSINFO_CONNECT; - c->event_ctx = talloc_reference(c, tree->session->transport->socket->event.ctx); - c->private = state; - - state->creq = smb_composite_connect_send(state->connect, c->event_ctx); - - if (state->creq == NULL) goto failed; - - state->creq->async.private = c; - state->creq->async.fn = fsinfo_composite_handler; - - return c; -failed: - talloc_free(c); - return NULL; -} - -/* - composite fsinfo call - recv side -*/ -NTSTATUS smb_composite_fsinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) -{ - NTSTATUS status; - - status = composite_wait(c); - - if (NT_STATUS_IS_OK(status)) { - struct fsinfo_state *state = talloc_get_type(c->private, struct fsinfo_state); - talloc_steal(mem_ctx, state->io->out.fsinfo); - } - - talloc_free(c); - return status; -} - - -/* - composite fsinfo call - sync interface -*/ -NTSTATUS smb_composite_fsinfo(struct smbcli_tree *tree, - TALLOC_CTX *mem_ctx, - struct smb_composite_fsinfo *io) -{ - struct composite_context *c = smb_composite_fsinfo_send(tree, io); - return smb_composite_fsinfo_recv(c, mem_ctx); -} - diff --git a/source4/libcli/composite/loadfile.c b/source4/libcli/composite/loadfile.c deleted file mode 100644 index 69a8219dba..0000000000 --- a/source4/libcli/composite/loadfile.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - a composite API for loading a whole file into memory -*/ - -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/composite/composite.h" -#include "librpc/gen_ndr/ndr_security.h" - -/* the stages of this call */ -enum loadfile_stage {LOADFILE_OPEN, LOADFILE_READ, LOADFILE_CLOSE}; - - -static void loadfile_handler(struct smbcli_request *req); - -struct loadfile_state { - enum loadfile_stage stage; - struct smb_composite_loadfile *io; - struct smbcli_request *req; - union smb_open *io_open; - union smb_read *io_read; -}; - -/* - setup for the close -*/ -static NTSTATUS setup_close(struct composite_context *c, - struct smbcli_tree *tree, uint16_t fnum) -{ - struct loadfile_state *state = talloc_get_type(c->private, struct loadfile_state); - union smb_close *io_close; - - /* nothing to read, setup the close */ - io_close = talloc(c, union smb_close); - NT_STATUS_HAVE_NO_MEMORY(io_close); - - io_close->close.level = RAW_CLOSE_CLOSE; - io_close->close.in.fnum = fnum; - io_close->close.in.write_time = 0; - - state->req = smb_raw_close_send(tree, io_close); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* call the handler again when the close is done */ - state->req->async.fn = loadfile_handler; - state->req->async.private = c; - state->stage = LOADFILE_CLOSE; - - return NT_STATUS_OK; -} - -/* - called when the open is done - pull the results and setup for the - first readx, or close if the file is zero size -*/ -static NTSTATUS loadfile_open(struct composite_context *c, - struct smb_composite_loadfile *io) -{ - struct loadfile_state *state = talloc_get_type(c->private, struct loadfile_state); - struct smbcli_tree *tree = state->req->tree; - NTSTATUS status; - - status = smb_raw_open_recv(state->req, c, state->io_open); - NT_STATUS_NOT_OK_RETURN(status); - - /* don't allow stupidly large loads */ - if (state->io_open->ntcreatex.out.size > 100*1000*1000) { - return NT_STATUS_INSUFFICIENT_RESOURCES; - } - - /* allocate space for the file data */ - io->out.size = state->io_open->ntcreatex.out.size; - io->out.data = talloc_array(c, uint8_t, io->out.size); - NT_STATUS_HAVE_NO_MEMORY(io->out.data); - - if (io->out.size == 0) { - return setup_close(c, tree, state->io_open->ntcreatex.out.fnum); - } - - /* setup for the read */ - state->io_read = talloc(c, union smb_read); - NT_STATUS_HAVE_NO_MEMORY(state->io_read); - - state->io_read->readx.level = RAW_READ_READX; - state->io_read->readx.in.fnum = state->io_open->ntcreatex.out.fnum; - state->io_read->readx.in.offset = 0; - state->io_read->readx.in.mincnt = MIN(32768, io->out.size); - state->io_read->readx.in.maxcnt = state->io_read->readx.in.mincnt; - state->io_read->readx.in.remaining = 0; - state->io_read->readx.out.data = io->out.data; - - state->req = smb_raw_read_send(tree, state->io_read); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* call the handler again when the first read is done */ - state->req->async.fn = loadfile_handler; - state->req->async.private = c; - state->stage = LOADFILE_READ; - - talloc_free(state->io_open); - - return NT_STATUS_OK; -} - - -/* - called when a read is done - pull the results and setup for the - next read, or close if the file is all done -*/ -static NTSTATUS loadfile_read(struct composite_context *c, - struct smb_composite_loadfile *io) -{ - struct loadfile_state *state = talloc_get_type(c->private, struct loadfile_state); - struct smbcli_tree *tree = state->req->tree; - NTSTATUS status; - - status = smb_raw_read_recv(state->req, state->io_read); - NT_STATUS_NOT_OK_RETURN(status); - - /* we might be done */ - if (state->io_read->readx.in.offset + - state->io_read->readx.out.nread == io->out.size) { - return setup_close(c, tree, state->io_read->readx.in.fnum); - } - - /* setup for the next read */ - state->io_read->readx.in.offset += state->io_read->readx.out.nread; - state->io_read->readx.in.mincnt = MIN(32768, io->out.size - state->io_read->readx.in.offset); - state->io_read->readx.out.data = io->out.data + state->io_read->readx.in.offset; - - state->req = smb_raw_read_send(tree, state->io_read); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* call the handler again when the read is done */ - state->req->async.fn = loadfile_handler; - state->req->async.private = c; - - return NT_STATUS_OK; -} - -/* - called when the close is done, check the status and cleanup -*/ -static NTSTATUS loadfile_close(struct composite_context *c, - struct smb_composite_loadfile *io) -{ - struct loadfile_state *state = talloc_get_type(c->private, struct loadfile_state); - NTSTATUS status; - - status = smbcli_request_simple_recv(state->req); - NT_STATUS_NOT_OK_RETURN(status); - - c->state = SMBCLI_REQUEST_DONE; - - return NT_STATUS_OK; -} - - -/* - handler for completion of a sub-request in loadfile -*/ -static void loadfile_handler(struct smbcli_request *req) -{ - struct composite_context *c = req->async.private; - struct loadfile_state *state = talloc_get_type(c->private, struct loadfile_state); - - /* when this handler is called, the stage indicates what - call has just finished */ - switch (state->stage) { - case LOADFILE_OPEN: - c->status = loadfile_open(c, state->io); - break; - - case LOADFILE_READ: - c->status = loadfile_read(c, state->io); - break; - - case LOADFILE_CLOSE: - c->status = loadfile_close(c, state->io); - break; - } - - if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; - } - - if (c->state >= SMBCLI_REQUEST_DONE && - c->async.fn) { - c->async.fn(c); - } -} - -/* - composite loadfile call - does an openx followed by a number of readx calls, - followed by a close -*/ -struct composite_context *smb_composite_loadfile_send(struct smbcli_tree *tree, - struct smb_composite_loadfile *io) -{ - struct composite_context *c; - struct loadfile_state *state; - - c = talloc_zero(tree, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct loadfile_state); - if (state == NULL) goto failed; - - state->io = io; - - c->private = state; - c->state = SMBCLI_REQUEST_SEND; - c->event_ctx = tree->session->transport->socket->event.ctx; - - /* setup for the open */ - state->io_open = talloc_zero(c, union smb_open); - if (state->io_open == NULL) goto failed; - - state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX; - state->io_open->ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; - state->io_open->ntcreatex.in.access_mask = SEC_FILE_READ_DATA; - state->io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; - state->io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; - state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; - state->io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; - state->io_open->ntcreatex.in.fname = io->in.fname; - - /* send the open on its way */ - state->req = smb_raw_open_send(tree, state->io_open); - if (state->req == NULL) goto failed; - - /* setup the callback handler */ - state->req->async.fn = loadfile_handler; - state->req->async.private = c; - state->stage = LOADFILE_OPEN; - - return c; - -failed: - talloc_free(c); - return NULL; -} - - -/* - composite loadfile call - recv side -*/ -NTSTATUS smb_composite_loadfile_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) -{ - NTSTATUS status; - - status = composite_wait(c); - - if (NT_STATUS_IS_OK(status)) { - struct loadfile_state *state = talloc_get_type(c->private, struct loadfile_state); - talloc_steal(mem_ctx, state->io->out.data); - } - - talloc_free(c); - return status; -} - - -/* - composite loadfile call - sync interface -*/ -NTSTATUS smb_composite_loadfile(struct smbcli_tree *tree, - TALLOC_CTX *mem_ctx, - struct smb_composite_loadfile *io) -{ - struct composite_context *c = smb_composite_loadfile_send(tree, io); - return smb_composite_loadfile_recv(c, mem_ctx); -} - diff --git a/source4/libcli/composite/monitor.h b/source4/libcli/composite/monitor.h deleted file mode 100644 index dce9dedc92..0000000000 --- a/source4/libcli/composite/monitor.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Definitions of composite function monitoring messages. - - Copyright (C) Rafal Szczesniak 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - * Monitor structure and message types definitions. Composite function monitoring - * allows client application to be notified on function progress. This enables - * eg. gui client to display progress bars, status messages, etc. - */ - - -#define rpc_create_user (0x00000001) /* userman.h */ -#define rpc_open_user (0x00000002) /* userinfo.h */ -#define rpc_query_user (0x00000003) /* userinfo.h */ -#define rpc_close_user (0x00000004) /* userinfo.h */ -#define rpc_lookup_name (0x00000005) /* userman.h */ -#define rpc_delete_user (0x00000006) /* userman.h */ - - -struct monitor_msg { - uint32_t type; - void *data; - size_t data_size; -}; diff --git a/source4/libcli/composite/savefile.c b/source4/libcli/composite/savefile.c deleted file mode 100644 index 0b08963966..0000000000 --- a/source4/libcli/composite/savefile.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - a composite API for saving a whole file from memory -*/ - -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/composite/composite.h" -#include "librpc/gen_ndr/ndr_security.h" - -/* the stages of this call */ -enum savefile_stage {SAVEFILE_OPEN, SAVEFILE_WRITE, SAVEFILE_CLOSE}; - -static void savefile_handler(struct smbcli_request *req); - -struct savefile_state { - enum savefile_stage stage; - off_t total_written; - struct smb_composite_savefile *io; - union smb_open *io_open; - union smb_write *io_write; - struct smbcli_request *req; -}; - - -/* - setup for the close -*/ -static NTSTATUS setup_close(struct composite_context *c, - struct smbcli_tree *tree, uint16_t fnum) -{ - struct savefile_state *state = talloc_get_type(c->private, struct savefile_state); - union smb_close *io_close; - - /* nothing to write, setup the close */ - io_close = talloc(c, union smb_close); - NT_STATUS_HAVE_NO_MEMORY(io_close); - - io_close->close.level = RAW_CLOSE_CLOSE; - io_close->close.in.fnum = fnum; - io_close->close.in.write_time = 0; - - state->req = smb_raw_close_send(tree, io_close); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* call the handler again when the close is done */ - state->stage = SAVEFILE_CLOSE; - state->req->async.fn = savefile_handler; - state->req->async.private = c; - - return NT_STATUS_OK; -} - -/* - called when the open is done - pull the results and setup for the - first writex, or close if the file is zero size -*/ -static NTSTATUS savefile_open(struct composite_context *c, - struct smb_composite_savefile *io) -{ - struct savefile_state *state = talloc_get_type(c->private, struct savefile_state); - union smb_write *io_write; - struct smbcli_tree *tree = state->req->tree; - NTSTATUS status; - uint32_t max_xmit = tree->session->transport->negotiate.max_xmit; - - status = smb_raw_open_recv(state->req, c, state->io_open); - NT_STATUS_NOT_OK_RETURN(status); - - if (io->in.size == 0) { - return setup_close(c, tree, state->io_open->ntcreatex.out.fnum); - } - - /* setup for the first write */ - io_write = talloc(c, union smb_write); - NT_STATUS_HAVE_NO_MEMORY(io_write); - - io_write->writex.level = RAW_WRITE_WRITEX; - io_write->writex.in.fnum = state->io_open->ntcreatex.out.fnum; - io_write->writex.in.offset = 0; - io_write->writex.in.wmode = 0; - io_write->writex.in.remaining = 0; - io_write->writex.in.count = MIN(max_xmit - 100, io->in.size); - io_write->writex.in.data = io->in.data; - state->io_write = io_write; - - state->req = smb_raw_write_send(tree, io_write); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* call the handler again when the first write is done */ - state->stage = SAVEFILE_WRITE; - state->req->async.fn = savefile_handler; - state->req->async.private = c; - talloc_free(state->io_open); - - return NT_STATUS_OK; -} - - -/* - called when a write is done - pull the results and setup for the - next write, or close if the file is all done -*/ -static NTSTATUS savefile_write(struct composite_context *c, - struct smb_composite_savefile *io) -{ - struct savefile_state *state = talloc_get_type(c->private, struct savefile_state); - struct smbcli_tree *tree = state->req->tree; - NTSTATUS status; - uint32_t max_xmit = tree->session->transport->negotiate.max_xmit; - - status = smb_raw_write_recv(state->req, state->io_write); - NT_STATUS_NOT_OK_RETURN(status); - - state->total_written += state->io_write->writex.out.nwritten; - - /* we might be done */ - if (state->io_write->writex.out.nwritten != state->io_write->writex.in.count || - state->total_written == io->in.size) { - return setup_close(c, tree, state->io_write->writex.in.fnum); - } - - /* setup for the next write */ - state->io_write->writex.in.offset = state->total_written; - state->io_write->writex.in.count = MIN(max_xmit - 100, - io->in.size - state->total_written); - state->io_write->writex.in.data = io->in.data + state->total_written; - - state->req = smb_raw_write_send(tree, state->io_write); - NT_STATUS_HAVE_NO_MEMORY(state->req); - - /* call the handler again when the write is done */ - state->req->async.fn = savefile_handler; - state->req->async.private = c; - - return NT_STATUS_OK; -} - -/* - called when the close is done, check the status and cleanup -*/ -static NTSTATUS savefile_close(struct composite_context *c, - struct smb_composite_savefile *io) -{ - struct savefile_state *state = talloc_get_type(c->private, struct savefile_state); - NTSTATUS status; - - status = smbcli_request_simple_recv(state->req); - NT_STATUS_NOT_OK_RETURN(status); - - if (state->total_written != io->in.size) { - return NT_STATUS_DISK_FULL; - } - - c->state = SMBCLI_REQUEST_DONE; - - return NT_STATUS_OK; -} - - -/* - handler for completion of a sub-request in savefile -*/ -static void savefile_handler(struct smbcli_request *req) -{ - struct composite_context *c = req->async.private; - struct savefile_state *state = talloc_get_type(c->private, struct savefile_state); - - /* when this handler is called, the stage indicates what - call has just finished */ - switch (state->stage) { - case SAVEFILE_OPEN: - c->status = savefile_open(c, state->io); - break; - - case SAVEFILE_WRITE: - c->status = savefile_write(c, state->io); - break; - - case SAVEFILE_CLOSE: - c->status = savefile_close(c, state->io); - break; - } - - if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; - } - - if (c->state >= SMBCLI_REQUEST_DONE && - c->async.fn) { - c->async.fn(c); - } -} - -/* - composite savefile call - does an openx followed by a number of writex calls, - followed by a close -*/ -struct composite_context *smb_composite_savefile_send(struct smbcli_tree *tree, - struct smb_composite_savefile *io) -{ - struct composite_context *c; - struct savefile_state *state; - union smb_open *io_open; - - c = talloc_zero(tree, struct composite_context); - if (c == NULL) goto failed; - - c->state = SMBCLI_REQUEST_SEND; - c->event_ctx = tree->session->transport->socket->event.ctx; - - state = talloc(c, struct savefile_state); - if (state == NULL) goto failed; - - state->stage = SAVEFILE_OPEN; - state->total_written = 0; - state->io = io; - - /* setup for the open */ - io_open = talloc_zero(c, union smb_open); - if (io_open == NULL) goto failed; - - io_open->ntcreatex.level = RAW_OPEN_NTCREATEX; - io_open->ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; - io_open->ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA; - io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; - io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; - io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; - io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; - io_open->ntcreatex.in.fname = io->in.fname; - state->io_open = io_open; - - /* send the open on its way */ - state->req = smb_raw_open_send(tree, io_open); - if (state->req == NULL) goto failed; - - /* setup the callback handler */ - state->req->async.fn = savefile_handler; - state->req->async.private = c; - c->private = state; - - return c; - -failed: - talloc_free(c); - return NULL; -} - - -/* - composite savefile call - recv side -*/ -NTSTATUS smb_composite_savefile_recv(struct composite_context *c) -{ - NTSTATUS status; - status = composite_wait(c); - talloc_free(c); - return status; -} - - -/* - composite savefile call - sync interface -*/ -NTSTATUS smb_composite_savefile(struct smbcli_tree *tree, - struct smb_composite_savefile *io) -{ - struct composite_context *c = smb_composite_savefile_send(tree, io); - return smb_composite_savefile_recv(c); -} diff --git a/source4/libcli/composite/sesssetup.c b/source4/libcli/composite/sesssetup.c deleted file mode 100644 index 3bd9ed285d..0000000000 --- a/source4/libcli/composite/sesssetup.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - a composite API for making handling a generic async session setup -*/ - -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/composite/composite.h" -#include "auth/auth.h" -#include "version.h" - -struct sesssetup_state { - union smb_sesssetup setup; - NTSTATUS gensec_status; - struct smb_composite_sesssetup *io; - struct smbcli_request *req; -}; - - -/* - form an encrypted lanman password from a plaintext password - and the server supplied challenge -*/ -static DATA_BLOB lanman_blob(TALLOC_CTX *mem_ctx, const char *pass, DATA_BLOB challenge) -{ - DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24); - SMBencrypt(pass, challenge.data, blob.data); - return blob; -} - -/* - form an encrypted NT password from a plaintext password - and the server supplied challenge -*/ -static DATA_BLOB nt_blob(TALLOC_CTX *mem_ctx, const struct samr_Password *nt_hash, DATA_BLOB challenge) -{ - DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24); - SMBOWFencrypt(nt_hash->hash, challenge.data, blob.data); - return blob; -} - -/* - store the user session key for a transport -*/ -static void set_user_session_key(struct smbcli_session *session, - const DATA_BLOB *session_key) -{ - session->user_session_key = data_blob_talloc(session, - session_key->data, - session_key->length); -} - -/* - handler for completion of a smbcli_request sub-request -*/ -static void request_handler(struct smbcli_request *req) -{ - struct composite_context *c = req->async.private; - struct sesssetup_state *state = talloc_get_type(c->private, struct sesssetup_state); - struct smbcli_session *session = req->session; - DATA_BLOB session_key = data_blob(NULL, 0); - DATA_BLOB null_data_blob = data_blob(NULL, 0); - NTSTATUS session_key_err; - - c->status = smb_raw_sesssetup_recv(req, state, &state->setup); - - switch (state->setup.old.level) { - case RAW_SESSSETUP_OLD: - state->io->out.vuid = state->setup.old.out.vuid; - break; - - case RAW_SESSSETUP_NT1: - state->io->out.vuid = state->setup.nt1.out.vuid; - break; - - case RAW_SESSSETUP_SPNEGO: - session->vuid = state->io->out.vuid = state->setup.spnego.out.vuid; - if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && - !NT_STATUS_IS_OK(c->status)) { - break; - } - if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - - /* The status value here, from the earlier pass at GENSEC is - * vital to the security of the system. Even if the other end - * accepts, if GENSEC claims 'MORE_PROCESSING_REQUIRED' then - * you must keep feeding it blobs, or else the remote - * host/attacker might avoid mutal authentication - * requirements */ - - state->gensec_status = gensec_update(session->gensec, state, - state->setup.spnego.out.secblob, - &state->setup.spnego.in.secblob); - c->status = state->gensec_status; - if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && - !NT_STATUS_IS_OK(c->status)) { - break; - } - } else { - state->setup.spnego.in.secblob = data_blob(NULL, 0); - } - - /* we need to do another round of session setup. We keep going until both sides - are happy */ - session_key_err = gensec_session_key(session->gensec, &session_key); - if (NT_STATUS_IS_OK(session_key_err)) { - set_user_session_key(session, &session_key); - smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); - } - - if (state->setup.spnego.in.secblob.length) { - state->req = smb_raw_sesssetup_send(session, &state->setup); - state->req->async.fn = request_handler; - state->req->async.private = c; - return; - } - } - - /* enforce the local signing required flag */ - if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) { - if (!session->transport->negotiate.sign_info.doing_signing - && session->transport->negotiate.sign_info.mandatory_signing) { - DEBUG(0, ("SMB signing required, but server does not support it\n")); - c->status = NT_STATUS_ACCESS_DENIED; - } - } - - if (NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_DONE; - } else { - c->state = SMBCLI_REQUEST_ERROR; - } - if (c->async.fn) { - c->async.fn(c); - } -} - - -/* - send a nt1 style session setup -*/ -static NTSTATUS session_setup_nt1(struct composite_context *c, - struct smbcli_session *session, - struct smb_composite_sesssetup *io, - struct smbcli_request **req) -{ - struct sesssetup_state *state = talloc_get_type(c->private, struct sesssetup_state); - const struct samr_Password *nt_hash = cli_credentials_get_nt_hash(io->in.credentials, state); - const char *password = cli_credentials_get_password(io->in.credentials); - - state->setup.nt1.level = RAW_SESSSETUP_NT1; - state->setup.nt1.in.bufsize = session->transport->options.max_xmit; - state->setup.nt1.in.mpx_max = session->transport->options.max_mux; - state->setup.nt1.in.vc_num = 1; - state->setup.nt1.in.sesskey = io->in.sesskey; - state->setup.nt1.in.capabilities = io->in.capabilities; - state->setup.nt1.in.os = "Unix"; - state->setup.nt1.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING); - cli_credentials_get_ntlm_username_domain(io->in.credentials, state, - &state->setup.nt1.in.user, - &state->setup.nt1.in.domain); - - if (!password) { - state->setup.nt1.in.password1 = data_blob(NULL, 0); - state->setup.nt1.in.password2 = data_blob(NULL, 0); - } else if (session->transport->negotiate.sec_mode & - NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { - DATA_BLOB session_key; - if (lp_client_ntlmv2_auth()) { - DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, lp_netbios_name(), lp_workgroup()); - DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key; - - if (!SMBNTLMv2encrypt_hash(state, - state->setup.nt1.in.user, state->setup.nt1.in.domain, - nt_hash->hash, &session->transport->negotiate.secblob, - &names_blob, - &lmv2_response, &ntlmv2_response, - &lmv2_session_key, &session_key)) { - data_blob_free(&names_blob); - return NT_STATUS_NO_MEMORY; - } - data_blob_free(&names_blob); - state->setup.nt1.in.password1 = lmv2_response; - state->setup.nt1.in.password2 = ntlmv2_response; - - smbcli_transport_simple_set_signing(session->transport, session_key, - state->setup.nt1.in.password2); - set_user_session_key(session, &session_key); - - data_blob_free(&lmv2_session_key); - data_blob_free(&session_key); - } else { - - state->setup.nt1.in.password2 = nt_blob(state, nt_hash, - session->transport->negotiate.secblob); - if (lp_client_lanman_auth()) { - state->setup.nt1.in.password1 = lanman_blob(state, password, - session->transport->negotiate.secblob); - } else { - /* if not sending the LM password, send the NT password twice */ - state->setup.nt1.in.password1 = state->setup.nt1.in.password2; - } - - session_key = data_blob_talloc(session, NULL, 16); - SMBsesskeygen_ntv1(nt_hash->hash, session_key.data); - smbcli_transport_simple_set_signing(session->transport, session_key, - state->setup.nt1.in.password2); - set_user_session_key(session, &session_key); - - data_blob_free(&session_key); - } - - } else if (lp_client_plaintext_auth()) { - state->setup.nt1.in.password1 = data_blob_talloc(state, password, strlen(password)); - state->setup.nt1.in.password2 = data_blob(NULL, 0); - } else { - /* could match windows client and return 'cannot logon from this workstation', but it just confuses everybody */ - return NT_STATUS_INVALID_PARAMETER; - } - - *req = smb_raw_sesssetup_send(session, &state->setup); - if (!*req) { - return NT_STATUS_NO_MEMORY; - } - return (*req)->status; -} - - -/* - old style session setup (pre NT1 protocol level) -*/ -static NTSTATUS session_setup_old(struct composite_context *c, - struct smbcli_session *session, - struct smb_composite_sesssetup *io, - struct smbcli_request **req) -{ - struct sesssetup_state *state = talloc_get_type(c->private, struct sesssetup_state); - const char *password = cli_credentials_get_password(io->in.credentials); - - state->setup.old.level = RAW_SESSSETUP_OLD; - state->setup.old.in.bufsize = session->transport->options.max_xmit; - state->setup.old.in.mpx_max = session->transport->options.max_mux; - state->setup.old.in.vc_num = 1; - state->setup.old.in.sesskey = io->in.sesskey; - state->setup.old.in.os = "Unix"; - state->setup.old.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING); - cli_credentials_get_ntlm_username_domain(io->in.credentials, state, - &state->setup.old.in.user, - &state->setup.old.in.domain); - - if (!password) { - state->setup.old.in.password = data_blob(NULL, 0); - } else if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { - state->setup.old.in.password = lanman_blob(state, password, - session->transport->negotiate.secblob); - } else { - state->setup.old.in.password = data_blob_talloc(state, - password, - strlen(password)); - } - - *req = smb_raw_sesssetup_send(session, &state->setup); - if (!*req) { - return NT_STATUS_NO_MEMORY; - } - return (*req)->status; -} - - -/* - Modern, all singing, all dancing extended security (and possibly SPNEGO) request -*/ -static NTSTATUS session_setup_spnego(struct composite_context *c, - struct smbcli_session *session, - struct smb_composite_sesssetup *io, - struct smbcli_request **req) -{ - struct sesssetup_state *state = talloc_get_type(c->private, struct sesssetup_state); - NTSTATUS status, session_key_err; - DATA_BLOB session_key = data_blob(NULL, 0); - DATA_BLOB null_data_blob = data_blob(NULL, 0); - const char *chosen_oid = NULL; - - state->setup.spnego.level = RAW_SESSSETUP_SPNEGO; - state->setup.spnego.in.bufsize = session->transport->options.max_xmit; - state->setup.spnego.in.mpx_max = session->transport->options.max_mux; - state->setup.spnego.in.vc_num = 1; - state->setup.spnego.in.sesskey = io->in.sesskey; - state->setup.spnego.in.capabilities = io->in.capabilities; - state->setup.spnego.in.os = "Unix"; - state->setup.spnego.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING); - state->setup.spnego.in.workgroup = io->in.workgroup; - - state->setup.spnego.out.vuid = session->vuid; - - smbcli_temp_set_signing(session->transport); - - status = gensec_client_start(session, &session->gensec, c->event_ctx); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status))); - return status; - } - - gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY); - - status = gensec_set_credentials(session->gensec, io->in.credentials); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client credentails: %s\n", - nt_errstr(status))); - return status; - } - - status = gensec_set_target_hostname(session->gensec, session->transport->socket->hostname); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", - nt_errstr(status))); - return status; - } - - status = gensec_set_target_service(session->gensec, "cifs"); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC target service: %s\n", - nt_errstr(status))); - return status; - } - - if (session->transport->negotiate.secblob.length) { - chosen_oid = GENSEC_OID_SPNEGO; - } else { - /* without a sec blob, means raw NTLMSSP */ - chosen_oid = GENSEC_OID_NTLMSSP; - } - - status = gensec_start_mech_by_oid(session->gensec, chosen_oid); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism %s: %s\n", - gensec_get_name_by_oid(chosen_oid), nt_errstr(status))); - return status; - } - - status = gensec_update(session->gensec, state, - session->transport->negotiate.secblob, - &state->setup.spnego.in.secblob); - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && - !NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed initial gensec_update with mechanism %s: %s\n", - gensec_get_name_by_oid(chosen_oid), nt_errstr(status))); - return status; - } - state->gensec_status = status; - - session_key_err = gensec_session_key(session->gensec, &session_key); - if (NT_STATUS_IS_OK(session_key_err)) { - smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); - } - - *req = smb_raw_sesssetup_send(session, &state->setup); - if (!*req) { - return NT_STATUS_NO_MEMORY; - } - return (*req)->status; -} - - -/* - composite session setup function that hides the details of all the - different session setup varients, including the multi-pass nature of - the spnego varient -*/ -struct composite_context *smb_composite_sesssetup_send(struct smbcli_session *session, - struct smb_composite_sesssetup *io) -{ - struct composite_context *c; - struct sesssetup_state *state; - NTSTATUS status; - - c = talloc_zero(session, struct composite_context); - if (c == NULL) return NULL; - - state = talloc(c, struct sesssetup_state); - if (state == NULL) { - c->state = SMBCLI_REQUEST_ERROR; - c->status = NT_STATUS_NO_MEMORY; - } - - state->io = io; - - c->state = SMBCLI_REQUEST_SEND; - c->private = state; - c->event_ctx = session->transport->socket->event.ctx; - - /* no session setup at all in earliest protocol varients */ - if (session->transport->negotiate.protocol < PROTOCOL_LANMAN1) { - ZERO_STRUCT(io->out); - c->state = SMBCLI_REQUEST_DONE; - return c; - } - - /* see what session setup interface we will use */ - if (session->transport->negotiate.protocol < PROTOCOL_NT1) { - status = session_setup_old(c, session, io, &state->req); - } else if (!session->transport->options.use_spnego || - !(io->in.capabilities & CAP_EXTENDED_SECURITY)) { - status = session_setup_nt1(c, session, io, &state->req); - } else { - status = session_setup_spnego(c, session, io, &state->req); - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || - NT_STATUS_IS_OK(status)) { - state->req->async.fn = request_handler; - state->req->async.private = c; - return c; - } - - c->state = SMBCLI_REQUEST_ERROR; - c->status = status; - return c; -} - - -/* - receive a composite session setup reply -*/ -NTSTATUS smb_composite_sesssetup_recv(struct composite_context *c) -{ - NTSTATUS status; - status = composite_wait(c); - talloc_free(c); - return status; -} - -/* - sync version of smb_composite_sesssetup -*/ -NTSTATUS smb_composite_sesssetup(struct smbcli_session *session, struct smb_composite_sesssetup *io) -{ - struct composite_context *c = smb_composite_sesssetup_send(session, io); - return smb_composite_sesssetup_recv(c); -} diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 248e0c2b95..62530ed64b 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -10,21 +10,21 @@ ADD_OBJ_FILES = libcli/util/asn1.o \ ADD_OBJ_FILES = libcli/util/clilsa.o REQUIRED_SUBSYSTEMS = RPC_NDR_LSA -[SUBSYSTEM::LIBCLI_COMPOSITE_BASE] +[SUBSYSTEM::LIBCLI_COMPOSITE] ADD_OBJ_FILES = \ libcli/composite/composite.o REQUIRED_SUBSYSTEMS = LIBEVENTS -[SUBSYSTEM::LIBCLI_COMPOSITE] +[SUBSYSTEM::LIBCLI_SMB_COMPOSITE] ADD_OBJ_FILES = \ - libcli/composite/loadfile.o \ - libcli/composite/savefile.o \ - libcli/composite/connect.o \ - libcli/composite/sesssetup.o \ - libcli/composite/fetchfile.o \ - libcli/composite/appendacl.o \ - libcli/composite/fsinfo.o -REQUIRED_SUBSYSTEMS = LIBCLI_COMPOSITE_BASE + libcli/smb_composite/loadfile.o \ + libcli/smb_composite/savefile.o \ + libcli/smb_composite/connect.o \ + libcli/smb_composite/sesssetup.o \ + libcli/smb_composite/fetchfile.o \ + libcli/smb_composite/appendacl.o \ + libcli/smb_composite/fsinfo.o +REQUIRED_SUBSYSTEMS = LIBCLI_COMPOSITE [SUBSYSTEM::LIBCLI_NBT] ADD_OBJ_FILES = \ @@ -34,7 +34,7 @@ ADD_OBJ_FILES = \ libcli/nbt/nameregister.o \ libcli/nbt/namerefresh.o \ libcli/nbt/namerelease.o -REQUIRED_SUBSYSTEMS = NDR_RAW NDR_NBT SOCKET LIBCLI_COMPOSITE_BASE LIBEVENTS \ +REQUIRED_SUBSYSTEMS = NDR_RAW NDR_NBT SOCKET LIBCLI_COMPOSITE LIBEVENTS \ LIB_SECURITY_NDR [SUBSYSTEM::LIBCLI_DGRAM] @@ -69,7 +69,7 @@ REQUIRED_SUBSYSTEMS = LIBCLI_NBT [SUBSYSTEM::LIBCLI] REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBCLI_UTILS LIBCLI_AUTH \ - LIBCLI_COMPOSITE LIBCLI_NBT LIB_SECURITY LIBCLI_RESOLVE \ + LIBCLI_SMB_COMPOSITE LIBCLI_NBT LIB_SECURITY LIBCLI_RESOLVE \ LIBCLI_DGRAM [SUBSYSTEM::LIBSMB] diff --git a/source4/libcli/nbt/namerefresh.c b/source4/libcli/nbt/namerefresh.c index a344f2c6e8..d9f2070d4c 100644 --- a/source4/libcli/nbt/namerefresh.c +++ b/source4/libcli/nbt/namerefresh.c @@ -22,7 +22,6 @@ #include "includes.h" #include "libcli/nbt/libnbt.h" -#include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" /* @@ -154,7 +153,7 @@ static void name_refresh_wins_handler(struct nbt_name_request *req) { struct composite_context *c = talloc_get_type(req->async.private, struct composite_context); - struct refresh_wins_state *state = talloc_get_type(c->private, + struct refresh_wins_state *state = talloc_get_type(c->private_data, struct refresh_wins_state); NTSTATUS status; @@ -164,7 +163,7 @@ static void name_refresh_wins_handler(struct nbt_name_request *req) state->wins_servers++; state->address_idx = 0; if (state->wins_servers[0] == NULL) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = status; goto done; } @@ -172,14 +171,14 @@ static void name_refresh_wins_handler(struct nbt_name_request *req) state->io->in.address = state->addresses[0]; state->req = nbt_name_refresh_send(state->nbtsock, state->io); if (state->req == NULL) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_refresh_wins_handler; state->req->async.private = c; } } else if (!NT_STATUS_IS_OK(status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = status; } else { if (state->io->out.rcode == 0 && @@ -188,20 +187,20 @@ static void name_refresh_wins_handler(struct nbt_name_request *req) state->io->in.address = state->addresses[++(state->address_idx)]; state->req = nbt_name_refresh_send(state->nbtsock, state->io); if (state->req == NULL) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_refresh_wins_handler; state->req->async.private = c; } } else { - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; c->status = NT_STATUS_OK; } } done: - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -251,9 +250,9 @@ struct composite_context *nbt_name_refresh_wins_send(struct nbt_name_socket *nbt state->req->async.fn = name_refresh_wins_handler; state->req->async.private = c; - c->private = state; - c->state = SMBCLI_REQUEST_SEND; - c->event_ctx = nbtsock->event_ctx; + c->private_data = state; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->event_ctx = nbtsock->event_ctx; return c; @@ -272,7 +271,7 @@ NTSTATUS nbt_name_refresh_wins_recv(struct composite_context *c, TALLOC_CTX *mem status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { struct refresh_wins_state *state = - talloc_get_type(c->private, struct refresh_wins_state); + talloc_get_type(c->private_data, struct refresh_wins_state); io->out.wins_server = talloc_steal(mem_ctx, state->wins_servers[0]); io->out.rcode = state->io->out.rcode; } diff --git a/source4/libcli/nbt/nameregister.c b/source4/libcli/nbt/nameregister.c index 276b8e4ac3..4dac500780 100644 --- a/source4/libcli/nbt/nameregister.c +++ b/source4/libcli/nbt/nameregister.c @@ -22,7 +22,6 @@ #include "includes.h" #include "libcli/nbt/libnbt.h" -#include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" /* @@ -156,14 +155,14 @@ struct register_bcast_state { static void name_register_bcast_handler(struct nbt_name_request *req) { struct composite_context *c = talloc_get_type(req->async.private, struct composite_context); - struct register_bcast_state *state = talloc_get_type(c->private, struct register_bcast_state); + struct register_bcast_state *state = talloc_get_type(c->private_data, struct register_bcast_state); NTSTATUS status; status = nbt_name_register_recv(state->req, state, state->io); if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { if (state->io->in.register_demand == True) { /* all done */ - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; c->status = NT_STATUS_OK; goto done; } @@ -173,17 +172,17 @@ static void name_register_bcast_handler(struct nbt_name_request *req) state->io->in.retries = 0; state->req = nbt_name_register_send(state->nbtsock, state->io); if (state->req == NULL) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_register_bcast_handler; state->req->async.private = c; } } else if (!NT_STATUS_IS_OK(status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = status; } else { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = NT_STATUS_CONFLICTING_ADDRESSES; DEBUG(3,("Name registration conflict from %s for %s with ip %s - rcode %d\n", state->io->out.reply_from, @@ -193,7 +192,7 @@ static void name_register_bcast_handler(struct nbt_name_request *req) } done: - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -203,7 +202,7 @@ done: the async send call for a 4 stage name registration */ struct composite_context *nbt_name_register_bcast_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register_bcast *io) + struct nbt_name_register_bcast *io) { struct composite_context *c; struct register_bcast_state *state; @@ -236,9 +235,9 @@ struct composite_context *nbt_name_register_bcast_send(struct nbt_name_socket *n state->req->async.fn = name_register_bcast_handler; state->req->async.private = c; - c->private = state; - c->state = SMBCLI_REQUEST_SEND; - c->event_ctx = nbtsock->event_ctx; + c->private_data = state; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->event_ctx = nbtsock->event_ctx; return c; @@ -291,7 +290,7 @@ static void name_register_wins_handler(struct nbt_name_request *req) { struct composite_context *c = talloc_get_type(req->async.private, struct composite_context); - struct register_wins_state *state = talloc_get_type(c->private, + struct register_wins_state *state = talloc_get_type(c->private_data, struct register_wins_state); NTSTATUS status; @@ -301,7 +300,7 @@ static void name_register_wins_handler(struct nbt_name_request *req) state->wins_servers++; state->address_idx = 0; if (state->wins_servers[0] == NULL) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = status; goto done; } @@ -309,14 +308,14 @@ static void name_register_wins_handler(struct nbt_name_request *req) state->io->in.address = state->addresses[0]; state->req = nbt_name_register_send(state->nbtsock, state->io); if (state->req == NULL) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_register_wins_handler; state->req->async.private = c; } } else if (!NT_STATUS_IS_OK(status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = status; } else { if (state->io->out.rcode == 0 && @@ -325,20 +324,20 @@ static void name_register_wins_handler(struct nbt_name_request *req) state->io->in.address = state->addresses[++(state->address_idx)]; state->req = nbt_name_register_send(state->nbtsock, state->io); if (state->req == NULL) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_register_wins_handler; state->req->async.private = c; } } else { - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; c->status = NT_STATUS_OK; } } done: - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -390,9 +389,9 @@ struct composite_context *nbt_name_register_wins_send(struct nbt_name_socket *nb state->req->async.fn = name_register_wins_handler; state->req->async.private = c; - c->private = state; - c->state = SMBCLI_REQUEST_SEND; - c->event_ctx = nbtsock->event_ctx; + c->private_data = state; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->event_ctx = nbtsock->event_ctx; return c; @@ -411,7 +410,7 @@ NTSTATUS nbt_name_register_wins_recv(struct composite_context *c, TALLOC_CTX *me status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { struct register_wins_state *state = - talloc_get_type(c->private, struct register_wins_state); + talloc_get_type(c->private_data, struct register_wins_state); io->out.wins_server = talloc_steal(mem_ctx, state->wins_servers[0]); io->out.rcode = state->io->out.rcode; } diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c index 90fb98603e..688ee8a78b 100644 --- a/source4/libcli/raw/clisocket.c +++ b/source4/libcli/raw/clisocket.c @@ -78,17 +78,17 @@ static NTSTATUS smbcli_sock_connect_one(struct smbcli_socket *sock, has either completed the connect() or has returned an error */ static void smbcli_sock_connect_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private) + uint16_t flags, void *private_data) { - struct composite_context *c = talloc_get_type(private, struct composite_context); - struct clisocket_connect *conn = talloc_get_type(c->private, struct clisocket_connect); + struct composite_context *c = talloc_get_type(private_data, struct composite_context); + struct clisocket_connect *conn = talloc_get_type(c->private_data, struct clisocket_connect); int i; c->status = socket_connect_complete(conn->sock->sock, 0); if (NT_STATUS_IS_OK(c->status)) { socket_set_option(conn->sock->sock, lp_socket_options(), NULL); conn->sock->hostname = talloc_strdup(conn->sock, conn->dest_hostname); - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; if (c->async.fn) { c->async.fn(c); } @@ -107,7 +107,7 @@ static void smbcli_sock_connect_handler(struct event_context *ev, struct fd_even } } - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; if (c->async.fn) { c->async.fn(c); } @@ -195,8 +195,8 @@ struct composite_context *smbcli_sock_connect_send(struct smbcli_socket *sock, conn->dest_hostname = talloc_strdup(c, host_name); if (conn->dest_hostname == NULL) goto failed; - c->private = conn; - c->state = SMBCLI_REQUEST_SEND; + c->private_data = conn; + c->state = COMPOSITE_STATE_IN_PROGRESS; /* startup the connect process for each port in turn until one succeeds or tells us that it is pending */ @@ -212,7 +212,7 @@ struct composite_context *smbcli_sock_connect_send(struct smbcli_socket *sock, } } - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; return c; failed: diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c index 74e14db591..cae93bdbe2 100644 --- a/source4/libcli/raw/clitree.c +++ b/source4/libcli/raw/clitree.c @@ -24,6 +24,7 @@ #include "includes.h" #include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" #define SETUP_REQUEST_TREE(cmd, wct, buflen) do { \ req = smbcli_request_setup(tree, cmd, wct, buflen); \ diff --git a/source4/libcli/resolve/host.c b/source4/libcli/resolve/host.c index a5edfcbc8a..13503b66b3 100644 --- a/source4/libcli/resolve/host.c +++ b/source4/libcli/resolve/host.c @@ -66,7 +66,7 @@ static int host_destructor(void *ptr) */ static void run_child(struct composite_context *c, int fd) { - struct host_state *state = talloc_get_type(c->private, struct host_state); + struct host_state *state = talloc_get_type(c->private_data, struct host_state); struct ipv4_addr ip; const char *address; @@ -84,10 +84,10 @@ static void run_child(struct composite_context *c, int fd) handle a read event on the pipe */ static void pipe_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private) + uint16_t flags, void *private_data) { - struct composite_context *c = talloc_get_type(private, struct composite_context); - struct host_state *state = talloc_get_type(c->private, struct host_state); + struct composite_context *c = talloc_get_type(private_data, struct composite_context); + struct host_state *state = talloc_get_type(c->private_data, struct host_state); char address[128]; int ret; @@ -113,7 +113,7 @@ static void pipe_handler(struct event_context *ev, struct fd_event *fde, if (state->reply_addr == NULL) goto failed; c->status = NT_STATUS_OK; - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; if (c->async.fn) { c->async.fn(c); } @@ -121,7 +121,7 @@ static void pipe_handler(struct event_context *ev, struct fd_event *fde, failed: c->status = NT_STATUS_BAD_NETWORK_NAME; - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; if (c->async.fn) { c->async.fn(c); } @@ -148,8 +148,8 @@ struct composite_context *resolve_name_host_send(struct nbt_name *name, status = nbt_name_dup(state, name, &state->name); if (!NT_STATUS_IS_OK(status)) goto failed; - c->state = SMBCLI_REQUEST_SEND; - c->private = state; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = state; c->event_ctx = talloc_reference(c, event_ctx); /* setup a pipe to chat to our child */ @@ -206,7 +206,7 @@ NTSTATUS resolve_name_host_recv(struct composite_context *c, status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { - struct host_state *state = talloc_get_type(c->private, struct host_state); + struct host_state *state = talloc_get_type(c->private_data, struct host_state); *reply_addr = talloc_steal(mem_ctx, state->reply_addr); } diff --git a/source4/libcli/resolve/nbtlist.c b/source4/libcli/resolve/nbtlist.c index 7080c62e43..4fb4ccbb20 100644 --- a/source4/libcli/resolve/nbtlist.c +++ b/source4/libcli/resolve/nbtlist.c @@ -44,8 +44,8 @@ struct nbtlist_state { static void nbtlist_handler(struct nbt_name_request *req) { struct composite_context *c = talloc_get_type(req->async.private, - struct composite_context); - struct nbtlist_state *state = talloc_get_type(c->private, struct nbtlist_state); + struct composite_context); + struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state); int i; for (i=0;inum_queries;i++) { @@ -54,20 +54,20 @@ static void nbtlist_handler(struct nbt_name_request *req) if (i == state->num_queries) { /* not for us?! */ c->status = NT_STATUS_INTERNAL_ERROR; - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; goto done; - } + } c->status = nbt_name_query_recv(req, state, &state->io_queries[i]); if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; } else { if (state->io_queries[i].out.num_addrs < 1) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; c->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; } else { struct nbt_name_query *q = &state->io_queries[i]; - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; /* favor a local address if possible */ state->reply_addr = NULL; for (i=0;iout.num_addrs;i++) { @@ -150,8 +150,8 @@ struct composite_context *resolve_name_nbtlist_send(struct nbt_name *name, state->queries[i]->async.private = c; } - c->state = SMBCLI_REQUEST_SEND; - c->private = state; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = state; c->event_ctx = talloc_reference(c, state->nbtsock->event_ctx); return c; @@ -172,7 +172,7 @@ NTSTATUS resolve_name_nbtlist_recv(struct composite_context *c, status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { - struct nbtlist_state *state = talloc_get_type(c->private, struct nbtlist_state); + struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state); *reply_addr = talloc_steal(mem_ctx, state->reply_addr); } diff --git a/source4/libcli/resolve/resolve.c b/source4/libcli/resolve/resolve.c index c21b29b57f..c9e2fa503b 100644 --- a/source4/libcli/resolve/resolve.c +++ b/source4/libcli/resolve/resolve.c @@ -28,7 +28,7 @@ struct resolve_state { struct nbt_name name; const char **methods; - struct composite_context *req; + struct composite_context *creq; const char *reply_addr; }; @@ -65,26 +65,26 @@ static const struct resolve_method *find_method(const char *name) /* handle completion of one name resolve method */ -static void resolve_handler(struct composite_context *req) +static void resolve_handler(struct composite_context *creq) { - struct composite_context *c = req->async.private; - struct resolve_state *state = talloc_get_type(c->private, struct resolve_state); + struct composite_context *c = creq->async.private_data; + struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state); const struct resolve_method *method = find_method(state->methods[0]); - c->status = method->recv_fn(req, state, &state->reply_addr); + c->status = method->recv_fn(creq, state, &state->reply_addr); if (!NT_STATUS_IS_OK(c->status)) { state->methods++; - state->req = setup_next_method(c); - if (state->req != NULL) { + state->creq = setup_next_method(c); + if (state->creq != NULL) { return; } } if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; } else { - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; } if (c->async.fn) { c->async.fn(c); @@ -94,23 +94,23 @@ static void resolve_handler(struct composite_context *req) static struct composite_context *setup_next_method(struct composite_context *c) { - struct resolve_state *state = talloc_get_type(c->private, struct resolve_state); - struct composite_context *req = NULL; + struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state); + struct composite_context *creq = NULL; do { const struct resolve_method *method = find_method(state->methods[0]); if (method) { - req = method->send_fn(&state->name, c->event_ctx); + creq = method->send_fn(&state->name, c->event_ctx); } - if (req == NULL && state->methods[0]) state->methods++; - } while (!req && state->methods[0]); + if (creq == NULL && state->methods[0]) state->methods++; + } while (!creq && state->methods[0]); - if (req) { - req->async.fn = resolve_handler; - req->async.private = c; + if (creq) { + creq->async.fn = resolve_handler; + creq->async.private_data = c; } - return req; + return creq; } /* @@ -136,8 +136,8 @@ struct composite_context *resolve_name_send(struct nbt_name *name, struct event_ state->methods = str_list_copy(state, methods); if (state->methods == NULL) goto failed; - c->state = SMBCLI_REQUEST_SEND; - c->private = state; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = state; if (event_ctx == NULL) { c->event_ctx = event_context_init(c); if (c->event_ctx == NULL) goto failed; @@ -154,8 +154,8 @@ struct composite_context *resolve_name_send(struct nbt_name *name, struct event_ return c; } - state->req = setup_next_method(c); - if (state->req == NULL) goto failed; + state->creq = setup_next_method(c); + if (state->creq == NULL) goto failed; return c; @@ -175,7 +175,7 @@ NTSTATUS resolve_name_recv(struct composite_context *c, status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { - struct resolve_state *state = talloc_get_type(c->private, struct resolve_state); + struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state); *reply_addr = talloc_steal(mem_ctx, state->reply_addr); } diff --git a/source4/libcli/smb_composite/appendacl.c b/source4/libcli/smb_composite/appendacl.c new file mode 100644 index 0000000000..b47a41a43b --- /dev/null +++ b/source4/libcli/smb_composite/appendacl.c @@ -0,0 +1,312 @@ +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" +#include "librpc/gen_ndr/ndr_security.h" + +/* the stages of this call */ +enum appendacl_stage {APPENDACL_OPENPATH, APPENDACL_GET, + APPENDACL_SET, APPENDACL_GETAGAIN, APPENDACL_CLOSEPATH}; + +static void appendacl_handler(struct smbcli_request *req); + +struct appendacl_state { + enum appendacl_stage stage; + struct smb_composite_appendacl *io; + + union smb_open *io_open; + union smb_setfileinfo *io_setfileinfo; + union smb_fileinfo *io_fileinfo; + + struct smbcli_request *req; +}; + + +static NTSTATUS appendacl_open(struct composite_context *c, + struct smb_composite_appendacl *io) +{ + struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); + struct smbcli_tree *tree = state->req->tree; + NTSTATUS status; + + status = smb_raw_open_recv(state->req, c, state->io_open); + NT_STATUS_NOT_OK_RETURN(status); + + /* setup structures for getting fileinfo */ + state->io_fileinfo = talloc(c, union smb_fileinfo); + NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo); + + state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC; + state->io_fileinfo->query_secdesc.in.fnum = state->io_open->ntcreatex.out.fnum; + state->io_fileinfo->query_secdesc.secinfo_flags = SECINFO_DACL; + + state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* set the handler */ + state->req->async.fn = appendacl_handler; + state->req->async.private = c; + state->stage = APPENDACL_GET; + + talloc_free (state->io_open); + + return NT_STATUS_OK; +} + +static NTSTATUS appendacl_get(struct composite_context *c, + struct smb_composite_appendacl *io) +{ + struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); + struct smbcli_tree *tree = state->req->tree; + int i; + NTSTATUS status; + + status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo); + NT_STATUS_NOT_OK_RETURN(status); + + /* setup structures for setting fileinfo */ + state->io_setfileinfo = talloc(c, union smb_setfileinfo); + NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo); + + state->io_setfileinfo->set_secdesc.level = RAW_SFILEINFO_SEC_DESC; + state->io_setfileinfo->set_secdesc.file.fnum = state->io_fileinfo->query_secdesc.in.fnum; + + state->io_setfileinfo->set_secdesc.in.secinfo_flags = SECINFO_DACL; + state->io_setfileinfo->set_secdesc.in.sd = state->io_fileinfo->query_secdesc.out.sd; + talloc_steal(state->io_setfileinfo, state->io_setfileinfo->set_secdesc.in.sd); + + /* append all aces from io->in.sd->dacl to new security descriptor */ + if (io->in.sd->dacl != NULL) { + for (i = 0; i < io->in.sd->dacl->num_aces; i++) { + security_descriptor_dacl_add(state->io_setfileinfo->set_secdesc.in.sd, + &(io->in.sd->dacl->aces[i])); + } + } + + status = smb_raw_setfileinfo(tree, state->io_setfileinfo); + NT_STATUS_NOT_OK_RETURN(status); + + state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* call handler when done setting new security descriptor on file */ + state->req->async.fn = appendacl_handler; + state->req->async.private = c; + state->stage = APPENDACL_SET; + + talloc_free (state->io_fileinfo); + + return NT_STATUS_OK; +} + +static NTSTATUS appendacl_set(struct composite_context *c, + struct smb_composite_appendacl *io) +{ + struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); + struct smbcli_tree *tree = state->req->tree; + NTSTATUS status; + + status = smbcli_request_simple_recv(state->req); + NT_STATUS_NOT_OK_RETURN(status); + + /* setup structures for getting fileinfo */ + state->io_fileinfo = talloc(c, union smb_fileinfo); + NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo); + + + state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC; + state->io_fileinfo->query_secdesc.in.fnum = state->io_setfileinfo->set_secdesc.file.fnum; + state->io_fileinfo->query_secdesc.secinfo_flags = SECINFO_DACL; + + state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* set the handler */ + state->req->async.fn = appendacl_handler; + state->req->async.private = c; + state->stage = APPENDACL_GETAGAIN; + + talloc_free (state->io_setfileinfo); + + return NT_STATUS_OK; +} + + +static NTSTATUS appendacl_getagain(struct composite_context *c, + struct smb_composite_appendacl *io) +{ + struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); + struct smbcli_tree *tree = state->req->tree; + union smb_close *io_close; + NTSTATUS status; + + status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo); + NT_STATUS_NOT_OK_RETURN(status); + + io->out.sd = state->io_fileinfo->query_secdesc.out.sd; + + /* setup structures for close */ + io_close = talloc(c, union smb_close); + NT_STATUS_HAVE_NO_MEMORY(io_close); + + io_close->close.level = RAW_CLOSE_CLOSE; + io_close->close.in.fnum = state->io_fileinfo->query_secdesc.in.fnum; + io_close->close.in.write_time = 0; + + state->req = smb_raw_close_send(tree, io_close); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* call the handler */ + state->req->async.fn = appendacl_handler; + state->req->async.private = c; + state->stage = APPENDACL_CLOSEPATH; + + talloc_free (state->io_fileinfo); + + return NT_STATUS_OK; +} + + + +static NTSTATUS appendacl_close(struct composite_context *c, + struct smb_composite_appendacl *io) +{ + struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); + NTSTATUS status; + + status = smbcli_request_simple_recv(state->req); + NT_STATUS_NOT_OK_RETURN(status); + + c->state = COMPOSITE_STATE_DONE; + + return NT_STATUS_OK; +} + +/* + handler for completion of a sub-request in appendacl +*/ +static void appendacl_handler(struct smbcli_request *req) +{ + struct composite_context *c = req->async.private; + struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); + + /* when this handler is called, the stage indicates what + call has just finished */ + switch (state->stage) { + case APPENDACL_OPENPATH: + c->status = appendacl_open(c, state->io); + break; + + case APPENDACL_GET: + c->status = appendacl_get(c, state->io); + break; + + case APPENDACL_SET: + c->status = appendacl_set(c, state->io); + break; + + case APPENDACL_GETAGAIN: + c->status = appendacl_getagain(c, state->io); + break; + + case APPENDACL_CLOSEPATH: + c->status = appendacl_close(c, state->io); + break; + } + + /* We should get here if c->state >= SMBCLI_REQUEST_DONE */ + if (!NT_STATUS_IS_OK(c->status)) { + c->state = COMPOSITE_STATE_ERROR; + } + + if (c->state >= COMPOSITE_STATE_DONE && + c->async.fn) { + c->async.fn(c); + } +} + + +/* + composite appendacl call - does an open followed by a number setfileinfo, + after that new acls are read with fileinfo, followed by a close +*/ +struct composite_context *smb_composite_appendacl_send(struct smbcli_tree *tree, + struct smb_composite_appendacl *io) +{ + struct composite_context *c; + struct appendacl_state *state; + + c = talloc_zero(tree, struct composite_context); + if (c == NULL) goto failed; + + state = talloc(c, struct appendacl_state); + if (state == NULL) goto failed; + + state->io = io; + + c->private_data = state; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->event_ctx = tree->session->transport->socket->event.ctx; + + /* setup structures for opening file */ + state->io_open = talloc_zero(c, union smb_open); + if (state->io_open == NULL) goto failed; + + state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX; + state->io_open->ntcreatex.in.root_fid = 0; + state->io_open->ntcreatex.in.flags = 0; + state->io_open->ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + state->io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + state->io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; + state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; + state->io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + state->io_open->ntcreatex.in.security_flags = 0; + state->io_open->ntcreatex.in.fname = io->in.fname; + + /* send the open on its way */ + state->req = smb_raw_open_send(tree, state->io_open); + if (state->req == NULL) goto failed; + + /* setup the callback handler */ + state->req->async.fn = appendacl_handler; + state->req->async.private = c; + state->stage = APPENDACL_OPENPATH; + + return c; + +failed: + talloc_free(c); + return NULL; +} + + +/* + composite appendacl call - recv side +*/ +NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + status = composite_wait(c); + + if (NT_STATUS_IS_OK(status)) { + struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); + state->io->out.sd = security_descriptor_copy (mem_ctx, state->io->out.sd); + } + + talloc_free(c); + return status; +} + + +/* + composite appendacl call - sync interface +*/ +NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree, + TALLOC_CTX *mem_ctx, + struct smb_composite_appendacl *io) +{ + struct composite_context *c = smb_composite_appendacl_send(tree, io); + return smb_composite_appendacl_recv(c, mem_ctx); +} + diff --git a/source4/libcli/smb_composite/connect.c b/source4/libcli/smb_composite/connect.c new file mode 100644 index 0000000000..56d9d988c3 --- /dev/null +++ b/source4/libcli/smb_composite/connect.c @@ -0,0 +1,396 @@ +/* + Unix SMB/CIFS implementation. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + a composite API for making a full SMB connection +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" + +/* the stages of this call */ +enum connect_stage {CONNECT_RESOLVE, + CONNECT_SOCKET, + CONNECT_SESSION_REQUEST, + CONNECT_NEGPROT, + CONNECT_SESSION_SETUP, + CONNECT_TCON}; + +struct connect_state { + enum connect_stage stage; + struct smbcli_socket *sock; + struct smbcli_transport *transport; + struct smbcli_session *session; + struct smb_composite_connect *io; + union smb_tcon *io_tcon; + struct smb_composite_sesssetup *io_setup; + struct smbcli_request *req; + struct composite_context *creq; +}; + + +static void request_handler(struct smbcli_request *); +static void composite_handler(struct composite_context *); + +/* + setup a negprot send +*/ +static NTSTATUS connect_send_negprot(struct composite_context *c, + struct smb_composite_connect *io) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + + state->req = smb_raw_negotiate_send(state->transport, lp_maxprotocol()); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + state->req->async.fn = request_handler; + state->req->async.private = c; + state->stage = CONNECT_NEGPROT; + + return NT_STATUS_OK; +} + + +/* + a tree connect request has competed +*/ +static NTSTATUS connect_tcon(struct composite_context *c, + struct smb_composite_connect *io) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + NTSTATUS status; + + status = smb_raw_tcon_recv(state->req, c, state->io_tcon); + NT_STATUS_NOT_OK_RETURN(status); + + io->out.tree->tid = state->io_tcon->tconx.out.tid; + if (state->io_tcon->tconx.out.dev_type) { + io->out.tree->device = talloc_strdup(io->out.tree, + state->io_tcon->tconx.out.dev_type); + } + if (state->io_tcon->tconx.out.fs_type) { + io->out.tree->fs_type = talloc_strdup(io->out.tree, + state->io_tcon->tconx.out.fs_type); + } + + /* all done! */ + c->state = COMPOSITE_STATE_DONE; + + return NT_STATUS_OK; +} + + +/* + a session setup request has competed +*/ +static NTSTATUS connect_session_setup(struct composite_context *c, + struct smb_composite_connect *io) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + NTSTATUS status; + + status = smb_composite_sesssetup_recv(state->creq); + NT_STATUS_NOT_OK_RETURN(status); + + state->session->vuid = state->io_setup->out.vuid; + + /* setup for a tconx */ + io->out.tree = smbcli_tree_init(state->session, state, True); + NT_STATUS_HAVE_NO_MEMORY(io->out.tree); + + state->io_tcon = talloc(c, union smb_tcon); + NT_STATUS_HAVE_NO_MEMORY(state->io_tcon); + + /* connect to a share using a tree connect */ + state->io_tcon->generic.level = RAW_TCON_TCONX; + state->io_tcon->tconx.in.flags = 0; + state->io_tcon->tconx.in.password = data_blob(NULL, 0); + + state->io_tcon->tconx.in.path = talloc_asprintf(state->io_tcon, + "\\\\%s\\%s", + io->in.called_name, + io->in.service); + NT_STATUS_HAVE_NO_MEMORY(state->io_tcon->tconx.in.path); + if (!io->in.service_type) { + state->io_tcon->tconx.in.device = "?????"; + } else { + state->io_tcon->tconx.in.device = io->in.service_type; + } + + state->req = smb_raw_tcon_send(io->out.tree, state->io_tcon); + NT_STATUS_HAVE_NO_MEMORY(state->req); + if (state->req->state == SMBCLI_REQUEST_ERROR) { + return state->req->status; + } + + state->req->async.fn = request_handler; + state->req->async.private = c; + state->stage = CONNECT_TCON; + + return NT_STATUS_OK; +} + +/* + a negprot request has competed +*/ +static NTSTATUS connect_negprot(struct composite_context *c, + struct smb_composite_connect *io) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + NTSTATUS status; + + status = smb_raw_negotiate_recv(state->req); + NT_STATUS_NOT_OK_RETURN(status); + + /* next step is a session setup */ + state->session = smbcli_session_init(state->transport, state, True); + NT_STATUS_HAVE_NO_MEMORY(state->session); + + state->io_setup = talloc(c, struct smb_composite_sesssetup); + NT_STATUS_HAVE_NO_MEMORY(state->io_setup); + + /* prepare a session setup to establish a security context */ + state->io_setup->in.sesskey = state->transport->negotiate.sesskey; + state->io_setup->in.capabilities = state->transport->negotiate.capabilities; + state->io_setup->in.credentials = io->in.credentials; + state->io_setup->in.workgroup = io->in.workgroup; + + state->creq = smb_composite_sesssetup_send(state->session, state->io_setup); + NT_STATUS_HAVE_NO_MEMORY(state->creq); + if (state->creq->state == COMPOSITE_STATE_ERROR) { + return state->creq->status; + } + + state->creq->async.fn = composite_handler; + state->creq->async.private_data = c; + state->stage = CONNECT_SESSION_SETUP; + + return NT_STATUS_OK; +} + + +/* + a session request operation has competed +*/ +static NTSTATUS connect_session_request(struct composite_context *c, + struct smb_composite_connect *io) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + NTSTATUS status; + + status = smbcli_transport_connect_recv(state->req); + NT_STATUS_NOT_OK_RETURN(status); + + /* next step is a negprot */ + return connect_send_negprot(c, io); +} + +/* + a socket connection operation has competed +*/ +static NTSTATUS connect_socket(struct composite_context *c, + struct smb_composite_connect *io) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + NTSTATUS status; + struct nbt_name calling, called; + + status = smbcli_sock_connect_recv(state->creq); + NT_STATUS_NOT_OK_RETURN(status); + + /* the socket is up - we can initialise the smbcli transport layer */ + state->transport = smbcli_transport_init(state->sock, state, True); + NT_STATUS_HAVE_NO_MEMORY(state->transport); + + make_nbt_name_client(&calling, cli_credentials_get_workstation(io->in.credentials)); + + nbt_choose_called_name(state, &called, io->in.called_name, NBT_NAME_SERVER); + + /* we have a connected socket - next step is a session + request, if needed. Port 445 doesn't need it, so it goes + straight to the negprot */ + if (state->sock->port == 445) { + status = nbt_name_dup(state->transport, &called, + &state->transport->called); + NT_STATUS_NOT_OK_RETURN(status); + return connect_send_negprot(c, io); + } + + state->req = smbcli_transport_connect_send(state->transport, &calling, &called); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + state->req->async.fn = request_handler; + state->req->async.private = c; + state->stage = CONNECT_SESSION_REQUEST; + + return NT_STATUS_OK; +} + + +/* + called when name resolution is finished +*/ +static NTSTATUS connect_resolve(struct composite_context *c, + struct smb_composite_connect *io) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + NTSTATUS status; + const char *address; + + status = resolve_name_recv(state->creq, state, &address); + NT_STATUS_NOT_OK_RETURN(status); + + state->creq = smbcli_sock_connect_send(state->sock, address, state->io->in.port, io->in.dest_host); + NT_STATUS_HAVE_NO_MEMORY(state->creq); + + state->stage = CONNECT_SOCKET; + state->creq->async.private_data = c; + state->creq->async.fn = composite_handler; + + return NT_STATUS_OK; +} + + +/* + handle and dispatch state transitions +*/ +static void state_handler(struct composite_context *c) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + + switch (state->stage) { + case CONNECT_RESOLVE: + c->status = connect_resolve(c, state->io); + break; + case CONNECT_SOCKET: + c->status = connect_socket(c, state->io); + break; + case CONNECT_SESSION_REQUEST: + c->status = connect_session_request(c, state->io); + break; + case CONNECT_NEGPROT: + c->status = connect_negprot(c, state->io); + break; + case CONNECT_SESSION_SETUP: + c->status = connect_session_setup(c, state->io); + break; + case CONNECT_TCON: + c->status = connect_tcon(c, state->io); + break; + } + + if (!NT_STATUS_IS_OK(c->status)) { + c->state = COMPOSITE_STATE_ERROR; + } + + if (c->state >= COMPOSITE_STATE_DONE && + c->async.fn) { + c->async.fn(c); + } +} + + +/* + handler for completion of a smbcli_request sub-request +*/ +static void request_handler(struct smbcli_request *req) +{ + struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context); + state_handler(c); +} + +/* + handler for completion of a smbcli_composite sub-request +*/ +static void composite_handler(struct composite_context *creq) +{ + struct composite_context *c = talloc_get_type(creq->async.private_data, + struct composite_context); + state_handler(c); +} + +/* + a function to establish a smbcli_tree from scratch +*/ +struct composite_context *smb_composite_connect_send(struct smb_composite_connect *io, + struct event_context *event_ctx) +{ + struct composite_context *c; + struct connect_state *state; + struct nbt_name name; + + c = talloc_zero(NULL, struct composite_context); + if (c == NULL) goto failed; + + state = talloc(c, struct connect_state); + if (state == NULL) goto failed; + + state->sock = smbcli_sock_init(state, event_ctx); + if (state->sock == NULL) goto failed; + + state->io = io; + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->event_ctx = talloc_reference(c, state->sock->event.ctx); + c->private_data = state; + + state->stage = CONNECT_RESOLVE; + make_nbt_name_server(&name, io->in.dest_host); + state->creq = resolve_name_send(&name, c->event_ctx, lp_name_resolve_order()); + + if (state->creq == NULL) goto failed; + state->creq->async.private_data = c; + state->creq->async.fn = composite_handler; + + return c; +failed: + talloc_free(c); + return NULL; +} + +/* + recv half of async composite connect code +*/ +NTSTATUS smb_composite_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + status = composite_wait(c); + + if (NT_STATUS_IS_OK(status)) { + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + talloc_steal(mem_ctx, state->io->out.tree); + } + + talloc_free(c); + return status; +} + +/* + sync version of smb_composite_connect +*/ +NTSTATUS smb_composite_connect(struct smb_composite_connect *io, TALLOC_CTX *mem_ctx, + struct event_context *ev) +{ + struct composite_context *c = smb_composite_connect_send(io, ev); + return smb_composite_connect_recv(c, mem_ctx); +} diff --git a/source4/libcli/smb_composite/fetchfile.c b/source4/libcli/smb_composite/fetchfile.c new file mode 100644 index 0000000000..9e88fb669d --- /dev/null +++ b/source4/libcli/smb_composite/fetchfile.c @@ -0,0 +1,187 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Volker Lendecke 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + a composite API for loading a whole file into memory +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" + +enum fetchfile_stage {FETCHFILE_CONNECT, + FETCHFILE_READ}; + +struct fetchfile_state { + enum fetchfile_stage stage; + struct smb_composite_fetchfile *io; + struct composite_context *creq; + struct smb_composite_connect *connect; + struct smb_composite_loadfile *loadfile; +}; + +static void fetchfile_composite_handler(struct composite_context *req); + +static NTSTATUS fetchfile_connect(struct composite_context *c, + struct smb_composite_fetchfile *io) +{ + NTSTATUS status; + struct fetchfile_state *state; + state = talloc_get_type(c->private_data, struct fetchfile_state); + + status = smb_composite_connect_recv(state->creq, c); + NT_STATUS_NOT_OK_RETURN(status); + + state->loadfile = talloc(state, struct smb_composite_loadfile); + NT_STATUS_HAVE_NO_MEMORY(state->loadfile); + + state->loadfile->in.fname = io->in.filename; + + state->creq = smb_composite_loadfile_send(state->connect->out.tree, + state->loadfile); + NT_STATUS_HAVE_NO_MEMORY(state->creq); + + state->creq->async.private_data = c; + state->creq->async.fn = fetchfile_composite_handler; + + state->stage = FETCHFILE_READ; + c->event_ctx = talloc_reference(c, state->creq->event_ctx); + + return NT_STATUS_OK; +} + +static NTSTATUS fetchfile_read(struct composite_context *c, + struct smb_composite_fetchfile *io) +{ + NTSTATUS status; + struct fetchfile_state *state; + state = talloc_get_type(c->private_data, struct fetchfile_state); + + status = smb_composite_loadfile_recv(state->creq, NULL); + NT_STATUS_NOT_OK_RETURN(status); + + io->out.data = state->loadfile->out.data; + io->out.size = state->loadfile->out.size; + + c->state = COMPOSITE_STATE_DONE; + if (c->async.fn) + c->async.fn(c); + + return NT_STATUS_OK; +} + +static void fetchfile_state_handler(struct composite_context *c) +{ + struct fetchfile_state *state; + NTSTATUS status; + + state = talloc_get_type(c->private_data, struct fetchfile_state); + + /* when this handler is called, the stage indicates what + call has just finished */ + switch (state->stage) { + case FETCHFILE_CONNECT: + status = fetchfile_connect(c, state->io); + break; + case FETCHFILE_READ: + status = fetchfile_read(c, state->io); + break; + } + + if (!NT_STATUS_IS_OK(status)) { + c->status = status; + c->state = COMPOSITE_STATE_ERROR; + if (c->async.fn) { + c->async.fn(c); + } + } +} + +static void fetchfile_composite_handler(struct composite_context *creq) +{ + struct composite_context *c = talloc_get_type(creq->async.private_data, + struct composite_context); + fetchfile_state_handler(c); +} + +struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetchfile *io, + struct event_context *event_ctx) +{ + struct composite_context *c; + struct fetchfile_state *state; + + c = talloc_zero(NULL, struct composite_context); + if (c == NULL) goto failed; + + state = talloc(c, struct fetchfile_state); + if (state == NULL) goto failed; + + state->connect = talloc(state, struct smb_composite_connect); + if (state->connect == NULL) goto failed; + + state->io = io; + + state->connect->in.dest_host = io->in.dest_host; + state->connect->in.port = io->in.port; + state->connect->in.called_name = io->in.called_name; + state->connect->in.service = io->in.service; + state->connect->in.service_type = io->in.service_type; + state->connect->in.credentials = io->in.credentials; + state->connect->in.workgroup = io->in.workgroup; + + state->creq = smb_composite_connect_send(state->connect, event_ctx); + if (state->creq == NULL) goto failed; + + state->creq->async.private_data = c; + state->creq->async.fn = fetchfile_composite_handler; + + c->state = COMPOSITE_STATE_IN_PROGRESS; + state->stage = FETCHFILE_CONNECT; + c->event_ctx = talloc_reference(c, state->creq->event_ctx); + c->private_data = state; + + return c; + failed: + talloc_free(c); + return NULL; +} + +NTSTATUS smb_composite_fetchfile_recv(struct composite_context *c, + TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + status = composite_wait(c); + + if (NT_STATUS_IS_OK(status)) { + struct fetchfile_state *state = talloc_get_type(c->private_data, struct fetchfile_state); + talloc_steal(mem_ctx, state->io->out.data); + } + + talloc_free(c); + return status; +} + +NTSTATUS smb_composite_fetchfile(struct smb_composite_fetchfile *io, + TALLOC_CTX *mem_ctx) +{ + struct composite_context *c = smb_composite_fetchfile_send(io, NULL); + return smb_composite_fetchfile_recv(c, mem_ctx); +} diff --git a/source4/libcli/smb_composite/fsinfo.c b/source4/libcli/smb_composite/fsinfo.c new file mode 100644 index 0000000000..e870225906 --- /dev/null +++ b/source4/libcli/smb_composite/fsinfo.c @@ -0,0 +1,201 @@ +/* + a composite API for quering file system information +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" +#include "librpc/gen_ndr/ndr_security.h" + +/* the stages of this call */ +enum fsinfo_stage {FSINFO_CONNECT, FSINFO_QUERY}; + + +static void fsinfo_raw_handler(struct smbcli_request *req); +static void fsinfo_composite_handler(struct composite_context *c); +static void fsinfo_state_handler(struct composite_context *c); + +struct fsinfo_state { + enum fsinfo_stage stage; + struct composite_context *creq; + struct smb_composite_fsinfo *io; + struct smb_composite_connect *connect; + union smb_fsinfo *fsinfo; + struct smbcli_tree *tree; + struct smbcli_request *req; +}; + +static NTSTATUS fsinfo_connect(struct composite_context *c, + struct smb_composite_fsinfo *io) +{ + NTSTATUS status; + struct fsinfo_state *state; + state = talloc_get_type(c->private_data, struct fsinfo_state); + + status = smb_composite_connect_recv(state->creq, c); + NT_STATUS_NOT_OK_RETURN(status); + + state->fsinfo = talloc(state, union smb_fsinfo); + NT_STATUS_HAVE_NO_MEMORY(state->fsinfo); + + state->fsinfo->generic.level = io->in.level; + + state->req = smb_raw_fsinfo_send(state->connect->out.tree, + state, + state->fsinfo); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + state->req->async.private = c; + state->req->async.fn = fsinfo_raw_handler; + + state->stage = FSINFO_QUERY; + c->event_ctx = talloc_reference(c, state->req->session->transport->socket->event.ctx); + + return NT_STATUS_OK; +} + +static NTSTATUS fsinfo_query(struct composite_context *c, + struct smb_composite_fsinfo *io) +{ + NTSTATUS status; + struct fsinfo_state *state; + state = talloc_get_type(c->private_data, struct fsinfo_state); + + status = smb_raw_fsinfo_recv(state->req, state, state->fsinfo); + NT_STATUS_NOT_OK_RETURN(status); + + state->io->out.fsinfo = state->fsinfo; + + c->state = COMPOSITE_STATE_DONE; + + if (c->async.fn) + c->async.fn(c); + + return NT_STATUS_OK; + +} + +/* + handler for completion of a sub-request in fsinfo +*/ +static void fsinfo_state_handler(struct composite_context *creq) +{ + struct fsinfo_state *state = talloc_get_type(creq->private_data, struct fsinfo_state); + + /* when this handler is called, the stage indicates what + call has just finished */ + switch (state->stage) { + case FSINFO_CONNECT: + creq->status = fsinfo_connect(creq, state->io); + break; + + case FSINFO_QUERY: + creq->status = fsinfo_query(creq, state->io); + break; + } + + if (!NT_STATUS_IS_OK(creq->status)) { + creq->state = COMPOSITE_STATE_ERROR; + } + + if (creq->state >= COMPOSITE_STATE_DONE && creq->async.fn) { + creq->async.fn(creq); + } +} + +/* + As raw and composite handlers take different requests, we need to handlers + to adapt both for the same state machine in fsinfo_state_handler() +*/ +static void fsinfo_raw_handler(struct smbcli_request *req) +{ + struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context); + fsinfo_state_handler(c); +} + +static void fsinfo_composite_handler(struct composite_context *creq) +{ + struct composite_context *c = talloc_get_type(creq->async.private_data, + struct composite_context); + fsinfo_state_handler(c); +} + +/* + composite fsinfo call - connects to a tree and queries a file system information +*/ +struct composite_context *smb_composite_fsinfo_send(struct smbcli_tree *tree, + struct smb_composite_fsinfo *io) +{ + struct composite_context *c; + struct fsinfo_state *state; + + c = talloc_zero(tree, struct composite_context); + if (c == NULL) goto failed; + + state = talloc(c, struct fsinfo_state); + if (state == NULL) goto failed; + + state->io = io; + + state->connect = talloc(state, struct smb_composite_connect); + + if (state->connect == NULL) goto failed; + + state->connect->in.dest_host = io->in.dest_host; + state->connect->in.port = io->in.port; + state->connect->in.called_name = io->in.called_name; + state->connect->in.service = io->in.service; + state->connect->in.service_type = io->in.service_type; + state->connect->in.credentials = io->in.credentials; + state->connect->in.workgroup = io->in.workgroup; + + c->state = COMPOSITE_STATE_IN_PROGRESS; + state->stage = FSINFO_CONNECT; + c->event_ctx = talloc_reference(c, tree->session->transport->socket->event.ctx); + c->private_data = state; + + state->creq = smb_composite_connect_send(state->connect, c->event_ctx); + + if (state->creq == NULL) goto failed; + + state->creq->async.private_data = c; + state->creq->async.fn = fsinfo_composite_handler; + + return c; +failed: + talloc_free(c); + return NULL; +} + +/* + composite fsinfo call - recv side +*/ +NTSTATUS smb_composite_fsinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + status = composite_wait(c); + + if (NT_STATUS_IS_OK(status)) { + struct fsinfo_state *state = talloc_get_type(c->private_data, struct fsinfo_state); + talloc_steal(mem_ctx, state->io->out.fsinfo); + } + + talloc_free(c); + return status; +} + + +/* + composite fsinfo call - sync interface +*/ +NTSTATUS smb_composite_fsinfo(struct smbcli_tree *tree, + TALLOC_CTX *mem_ctx, + struct smb_composite_fsinfo *io) +{ + struct composite_context *c = smb_composite_fsinfo_send(tree, io); + return smb_composite_fsinfo_recv(c, mem_ctx); +} + diff --git a/source4/libcli/smb_composite/loadfile.c b/source4/libcli/smb_composite/loadfile.c new file mode 100644 index 0000000000..93122e287f --- /dev/null +++ b/source4/libcli/smb_composite/loadfile.c @@ -0,0 +1,294 @@ +/* + Unix SMB/CIFS implementation. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + a composite API for loading a whole file into memory +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" +#include "librpc/gen_ndr/ndr_security.h" + +/* the stages of this call */ +enum loadfile_stage {LOADFILE_OPEN, LOADFILE_READ, LOADFILE_CLOSE}; + + +static void loadfile_handler(struct smbcli_request *req); + +struct loadfile_state { + enum loadfile_stage stage; + struct smb_composite_loadfile *io; + struct smbcli_request *req; + union smb_open *io_open; + union smb_read *io_read; +}; + +/* + setup for the close +*/ +static NTSTATUS setup_close(struct composite_context *c, + struct smbcli_tree *tree, uint16_t fnum) +{ + struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state); + union smb_close *io_close; + + /* nothing to read, setup the close */ + io_close = talloc(c, union smb_close); + NT_STATUS_HAVE_NO_MEMORY(io_close); + + io_close->close.level = RAW_CLOSE_CLOSE; + io_close->close.in.fnum = fnum; + io_close->close.in.write_time = 0; + + state->req = smb_raw_close_send(tree, io_close); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* call the handler again when the close is done */ + state->req->async.fn = loadfile_handler; + state->req->async.private = c; + state->stage = LOADFILE_CLOSE; + + return NT_STATUS_OK; +} + +/* + called when the open is done - pull the results and setup for the + first readx, or close if the file is zero size +*/ +static NTSTATUS loadfile_open(struct composite_context *c, + struct smb_composite_loadfile *io) +{ + struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state); + struct smbcli_tree *tree = state->req->tree; + NTSTATUS status; + + status = smb_raw_open_recv(state->req, c, state->io_open); + NT_STATUS_NOT_OK_RETURN(status); + + /* don't allow stupidly large loads */ + if (state->io_open->ntcreatex.out.size > 100*1000*1000) { + return NT_STATUS_INSUFFICIENT_RESOURCES; + } + + /* allocate space for the file data */ + io->out.size = state->io_open->ntcreatex.out.size; + io->out.data = talloc_array(c, uint8_t, io->out.size); + NT_STATUS_HAVE_NO_MEMORY(io->out.data); + + if (io->out.size == 0) { + return setup_close(c, tree, state->io_open->ntcreatex.out.fnum); + } + + /* setup for the read */ + state->io_read = talloc(c, union smb_read); + NT_STATUS_HAVE_NO_MEMORY(state->io_read); + + state->io_read->readx.level = RAW_READ_READX; + state->io_read->readx.in.fnum = state->io_open->ntcreatex.out.fnum; + state->io_read->readx.in.offset = 0; + state->io_read->readx.in.mincnt = MIN(32768, io->out.size); + state->io_read->readx.in.maxcnt = state->io_read->readx.in.mincnt; + state->io_read->readx.in.remaining = 0; + state->io_read->readx.out.data = io->out.data; + + state->req = smb_raw_read_send(tree, state->io_read); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* call the handler again when the first read is done */ + state->req->async.fn = loadfile_handler; + state->req->async.private = c; + state->stage = LOADFILE_READ; + + talloc_free(state->io_open); + + return NT_STATUS_OK; +} + + +/* + called when a read is done - pull the results and setup for the + next read, or close if the file is all done +*/ +static NTSTATUS loadfile_read(struct composite_context *c, + struct smb_composite_loadfile *io) +{ + struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state); + struct smbcli_tree *tree = state->req->tree; + NTSTATUS status; + + status = smb_raw_read_recv(state->req, state->io_read); + NT_STATUS_NOT_OK_RETURN(status); + + /* we might be done */ + if (state->io_read->readx.in.offset + + state->io_read->readx.out.nread == io->out.size) { + return setup_close(c, tree, state->io_read->readx.in.fnum); + } + + /* setup for the next read */ + state->io_read->readx.in.offset += state->io_read->readx.out.nread; + state->io_read->readx.in.mincnt = MIN(32768, io->out.size - state->io_read->readx.in.offset); + state->io_read->readx.out.data = io->out.data + state->io_read->readx.in.offset; + + state->req = smb_raw_read_send(tree, state->io_read); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* call the handler again when the read is done */ + state->req->async.fn = loadfile_handler; + state->req->async.private = c; + + return NT_STATUS_OK; +} + +/* + called when the close is done, check the status and cleanup +*/ +static NTSTATUS loadfile_close(struct composite_context *c, + struct smb_composite_loadfile *io) +{ + struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state); + NTSTATUS status; + + status = smbcli_request_simple_recv(state->req); + NT_STATUS_NOT_OK_RETURN(status); + + c->state = COMPOSITE_STATE_DONE; + + return NT_STATUS_OK; +} + + +/* + handler for completion of a sub-request in loadfile +*/ +static void loadfile_handler(struct smbcli_request *req) +{ + struct composite_context *c = req->async.private; + struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state); + + /* when this handler is called, the stage indicates what + call has just finished */ + switch (state->stage) { + case LOADFILE_OPEN: + c->status = loadfile_open(c, state->io); + break; + + case LOADFILE_READ: + c->status = loadfile_read(c, state->io); + break; + + case LOADFILE_CLOSE: + c->status = loadfile_close(c, state->io); + break; + } + + if (!NT_STATUS_IS_OK(c->status)) { + c->state = COMPOSITE_STATE_ERROR; + } + + if (c->state >= COMPOSITE_STATE_DONE && + c->async.fn) { + c->async.fn(c); + } +} + +/* + composite loadfile call - does an openx followed by a number of readx calls, + followed by a close +*/ +struct composite_context *smb_composite_loadfile_send(struct smbcli_tree *tree, + struct smb_composite_loadfile *io) +{ + struct composite_context *c; + struct loadfile_state *state; + + c = talloc_zero(tree, struct composite_context); + if (c == NULL) goto failed; + + state = talloc(c, struct loadfile_state); + if (state == NULL) goto failed; + + state->io = io; + + c->private_data = state; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->event_ctx = tree->session->transport->socket->event.ctx; + + /* setup for the open */ + state->io_open = talloc_zero(c, union smb_open); + if (state->io_open == NULL) goto failed; + + state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX; + state->io_open->ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; + state->io_open->ntcreatex.in.access_mask = SEC_FILE_READ_DATA; + state->io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + state->io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; + state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; + state->io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + state->io_open->ntcreatex.in.fname = io->in.fname; + + /* send the open on its way */ + state->req = smb_raw_open_send(tree, state->io_open); + if (state->req == NULL) goto failed; + + /* setup the callback handler */ + state->req->async.fn = loadfile_handler; + state->req->async.private = c; + state->stage = LOADFILE_OPEN; + + return c; + +failed: + talloc_free(c); + return NULL; +} + + +/* + composite loadfile call - recv side +*/ +NTSTATUS smb_composite_loadfile_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + status = composite_wait(c); + + if (NT_STATUS_IS_OK(status)) { + struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state); + talloc_steal(mem_ctx, state->io->out.data); + } + + talloc_free(c); + return status; +} + + +/* + composite loadfile call - sync interface +*/ +NTSTATUS smb_composite_loadfile(struct smbcli_tree *tree, + TALLOC_CTX *mem_ctx, + struct smb_composite_loadfile *io) +{ + struct composite_context *c = smb_composite_loadfile_send(tree, io); + return smb_composite_loadfile_recv(c, mem_ctx); +} + diff --git a/source4/libcli/smb_composite/savefile.c b/source4/libcli/smb_composite/savefile.c new file mode 100644 index 0000000000..0e11031dab --- /dev/null +++ b/source4/libcli/smb_composite/savefile.c @@ -0,0 +1,289 @@ +/* + Unix SMB/CIFS implementation. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + a composite API for saving a whole file from memory +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" +#include "librpc/gen_ndr/ndr_security.h" + +/* the stages of this call */ +enum savefile_stage {SAVEFILE_OPEN, SAVEFILE_WRITE, SAVEFILE_CLOSE}; + +static void savefile_handler(struct smbcli_request *req); + +struct savefile_state { + enum savefile_stage stage; + off_t total_written; + struct smb_composite_savefile *io; + union smb_open *io_open; + union smb_write *io_write; + struct smbcli_request *req; +}; + + +/* + setup for the close +*/ +static NTSTATUS setup_close(struct composite_context *c, + struct smbcli_tree *tree, uint16_t fnum) +{ + struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state); + union smb_close *io_close; + + /* nothing to write, setup the close */ + io_close = talloc(c, union smb_close); + NT_STATUS_HAVE_NO_MEMORY(io_close); + + io_close->close.level = RAW_CLOSE_CLOSE; + io_close->close.in.fnum = fnum; + io_close->close.in.write_time = 0; + + state->req = smb_raw_close_send(tree, io_close); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* call the handler again when the close is done */ + state->stage = SAVEFILE_CLOSE; + state->req->async.fn = savefile_handler; + state->req->async.private = c; + + return NT_STATUS_OK; +} + +/* + called when the open is done - pull the results and setup for the + first writex, or close if the file is zero size +*/ +static NTSTATUS savefile_open(struct composite_context *c, + struct smb_composite_savefile *io) +{ + struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state); + union smb_write *io_write; + struct smbcli_tree *tree = state->req->tree; + NTSTATUS status; + uint32_t max_xmit = tree->session->transport->negotiate.max_xmit; + + status = smb_raw_open_recv(state->req, c, state->io_open); + NT_STATUS_NOT_OK_RETURN(status); + + if (io->in.size == 0) { + return setup_close(c, tree, state->io_open->ntcreatex.out.fnum); + } + + /* setup for the first write */ + io_write = talloc(c, union smb_write); + NT_STATUS_HAVE_NO_MEMORY(io_write); + + io_write->writex.level = RAW_WRITE_WRITEX; + io_write->writex.in.fnum = state->io_open->ntcreatex.out.fnum; + io_write->writex.in.offset = 0; + io_write->writex.in.wmode = 0; + io_write->writex.in.remaining = 0; + io_write->writex.in.count = MIN(max_xmit - 100, io->in.size); + io_write->writex.in.data = io->in.data; + state->io_write = io_write; + + state->req = smb_raw_write_send(tree, io_write); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* call the handler again when the first write is done */ + state->stage = SAVEFILE_WRITE; + state->req->async.fn = savefile_handler; + state->req->async.private = c; + talloc_free(state->io_open); + + return NT_STATUS_OK; +} + + +/* + called when a write is done - pull the results and setup for the + next write, or close if the file is all done +*/ +static NTSTATUS savefile_write(struct composite_context *c, + struct smb_composite_savefile *io) +{ + struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state); + struct smbcli_tree *tree = state->req->tree; + NTSTATUS status; + uint32_t max_xmit = tree->session->transport->negotiate.max_xmit; + + status = smb_raw_write_recv(state->req, state->io_write); + NT_STATUS_NOT_OK_RETURN(status); + + state->total_written += state->io_write->writex.out.nwritten; + + /* we might be done */ + if (state->io_write->writex.out.nwritten != state->io_write->writex.in.count || + state->total_written == io->in.size) { + return setup_close(c, tree, state->io_write->writex.in.fnum); + } + + /* setup for the next write */ + state->io_write->writex.in.offset = state->total_written; + state->io_write->writex.in.count = MIN(max_xmit - 100, + io->in.size - state->total_written); + state->io_write->writex.in.data = io->in.data + state->total_written; + + state->req = smb_raw_write_send(tree, state->io_write); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + /* call the handler again when the write is done */ + state->req->async.fn = savefile_handler; + state->req->async.private = c; + + return NT_STATUS_OK; +} + +/* + called when the close is done, check the status and cleanup +*/ +static NTSTATUS savefile_close(struct composite_context *c, + struct smb_composite_savefile *io) +{ + struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state); + NTSTATUS status; + + status = smbcli_request_simple_recv(state->req); + NT_STATUS_NOT_OK_RETURN(status); + + if (state->total_written != io->in.size) { + return NT_STATUS_DISK_FULL; + } + + c->state = COMPOSITE_STATE_DONE; + + return NT_STATUS_OK; +} + + +/* + handler for completion of a sub-request in savefile +*/ +static void savefile_handler(struct smbcli_request *req) +{ + struct composite_context *c = req->async.private; + struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state); + + /* when this handler is called, the stage indicates what + call has just finished */ + switch (state->stage) { + case SAVEFILE_OPEN: + c->status = savefile_open(c, state->io); + break; + + case SAVEFILE_WRITE: + c->status = savefile_write(c, state->io); + break; + + case SAVEFILE_CLOSE: + c->status = savefile_close(c, state->io); + break; + } + + if (!NT_STATUS_IS_OK(c->status)) { + c->state = COMPOSITE_STATE_ERROR; + } + + if (c->state >= COMPOSITE_STATE_DONE && + c->async.fn) { + c->async.fn(c); + } +} + +/* + composite savefile call - does an openx followed by a number of writex calls, + followed by a close +*/ +struct composite_context *smb_composite_savefile_send(struct smbcli_tree *tree, + struct smb_composite_savefile *io) +{ + struct composite_context *c; + struct savefile_state *state; + union smb_open *io_open; + + c = talloc_zero(tree, struct composite_context); + if (c == NULL) goto failed; + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->event_ctx = tree->session->transport->socket->event.ctx; + + state = talloc(c, struct savefile_state); + if (state == NULL) goto failed; + + state->stage = SAVEFILE_OPEN; + state->total_written = 0; + state->io = io; + + /* setup for the open */ + io_open = talloc_zero(c, union smb_open); + if (io_open == NULL) goto failed; + + io_open->ntcreatex.level = RAW_OPEN_NTCREATEX; + io_open->ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; + io_open->ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA; + io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; + io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; + io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + io_open->ntcreatex.in.fname = io->in.fname; + state->io_open = io_open; + + /* send the open on its way */ + state->req = smb_raw_open_send(tree, io_open); + if (state->req == NULL) goto failed; + + /* setup the callback handler */ + state->req->async.fn = savefile_handler; + state->req->async.private = c; + c->private_data = state; + + return c; + +failed: + talloc_free(c); + return NULL; +} + + +/* + composite savefile call - recv side +*/ +NTSTATUS smb_composite_savefile_recv(struct composite_context *c) +{ + NTSTATUS status; + status = composite_wait(c); + talloc_free(c); + return status; +} + + +/* + composite savefile call - sync interface +*/ +NTSTATUS smb_composite_savefile(struct smbcli_tree *tree, + struct smb_composite_savefile *io) +{ + struct composite_context *c = smb_composite_savefile_send(tree, io); + return smb_composite_savefile_recv(c); +} diff --git a/source4/libcli/smb_composite/sesssetup.c b/source4/libcli/smb_composite/sesssetup.c new file mode 100644 index 0000000000..2ca862fb2f --- /dev/null +++ b/source4/libcli/smb_composite/sesssetup.c @@ -0,0 +1,459 @@ +/* + Unix SMB/CIFS implementation. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + a composite API for making handling a generic async session setup +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" +#include "auth/auth.h" +#include "version.h" + +struct sesssetup_state { + union smb_sesssetup setup; + NTSTATUS gensec_status; + struct smb_composite_sesssetup *io; + struct smbcli_request *req; +}; + + +/* + form an encrypted lanman password from a plaintext password + and the server supplied challenge +*/ +static DATA_BLOB lanman_blob(TALLOC_CTX *mem_ctx, const char *pass, DATA_BLOB challenge) +{ + DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24); + SMBencrypt(pass, challenge.data, blob.data); + return blob; +} + +/* + form an encrypted NT password from a plaintext password + and the server supplied challenge +*/ +static DATA_BLOB nt_blob(TALLOC_CTX *mem_ctx, const struct samr_Password *nt_hash, DATA_BLOB challenge) +{ + DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24); + SMBOWFencrypt(nt_hash->hash, challenge.data, blob.data); + return blob; +} + +/* + store the user session key for a transport +*/ +static void set_user_session_key(struct smbcli_session *session, + const DATA_BLOB *session_key) +{ + session->user_session_key = data_blob_talloc(session, + session_key->data, + session_key->length); +} + +/* + handler for completion of a smbcli_request sub-request +*/ +static void request_handler(struct smbcli_request *req) +{ + struct composite_context *c = req->async.private; + struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); + struct smbcli_session *session = req->session; + DATA_BLOB session_key = data_blob(NULL, 0); + DATA_BLOB null_data_blob = data_blob(NULL, 0); + NTSTATUS session_key_err; + + c->status = smb_raw_sesssetup_recv(req, state, &state->setup); + + switch (state->setup.old.level) { + case RAW_SESSSETUP_OLD: + state->io->out.vuid = state->setup.old.out.vuid; + break; + + case RAW_SESSSETUP_NT1: + state->io->out.vuid = state->setup.nt1.out.vuid; + break; + + case RAW_SESSSETUP_SPNEGO: + session->vuid = state->io->out.vuid = state->setup.spnego.out.vuid; + if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && + !NT_STATUS_IS_OK(c->status)) { + break; + } + if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + + /* The status value here, from the earlier pass at GENSEC is + * vital to the security of the system. Even if the other end + * accepts, if GENSEC claims 'MORE_PROCESSING_REQUIRED' then + * you must keep feeding it blobs, or else the remote + * host/attacker might avoid mutal authentication + * requirements */ + + state->gensec_status = gensec_update(session->gensec, state, + state->setup.spnego.out.secblob, + &state->setup.spnego.in.secblob); + c->status = state->gensec_status; + if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && + !NT_STATUS_IS_OK(c->status)) { + break; + } + } else { + state->setup.spnego.in.secblob = data_blob(NULL, 0); + } + + /* we need to do another round of session setup. We keep going until both sides + are happy */ + session_key_err = gensec_session_key(session->gensec, &session_key); + if (NT_STATUS_IS_OK(session_key_err)) { + set_user_session_key(session, &session_key); + smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); + } + + if (state->setup.spnego.in.secblob.length) { + state->req = smb_raw_sesssetup_send(session, &state->setup); + state->req->async.fn = request_handler; + state->req->async.private = c; + return; + } + } + + /* enforce the local signing required flag */ + if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) { + if (!session->transport->negotiate.sign_info.doing_signing + && session->transport->negotiate.sign_info.mandatory_signing) { + DEBUG(0, ("SMB signing required, but server does not support it\n")); + c->status = NT_STATUS_ACCESS_DENIED; + } + } + + if (NT_STATUS_IS_OK(c->status)) { + c->state = COMPOSITE_STATE_DONE; + } else { + c->state = COMPOSITE_STATE_ERROR; + } + if (c->async.fn) { + c->async.fn(c); + } +} + + +/* + send a nt1 style session setup +*/ +static NTSTATUS session_setup_nt1(struct composite_context *c, + struct smbcli_session *session, + struct smb_composite_sesssetup *io, + struct smbcli_request **req) +{ + struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); + const struct samr_Password *nt_hash = cli_credentials_get_nt_hash(io->in.credentials, state); + const char *password = cli_credentials_get_password(io->in.credentials); + + state->setup.nt1.level = RAW_SESSSETUP_NT1; + state->setup.nt1.in.bufsize = session->transport->options.max_xmit; + state->setup.nt1.in.mpx_max = session->transport->options.max_mux; + state->setup.nt1.in.vc_num = 1; + state->setup.nt1.in.sesskey = io->in.sesskey; + state->setup.nt1.in.capabilities = io->in.capabilities; + state->setup.nt1.in.os = "Unix"; + state->setup.nt1.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING); + cli_credentials_get_ntlm_username_domain(io->in.credentials, state, + &state->setup.nt1.in.user, + &state->setup.nt1.in.domain); + + if (!password) { + state->setup.nt1.in.password1 = data_blob(NULL, 0); + state->setup.nt1.in.password2 = data_blob(NULL, 0); + } else if (session->transport->negotiate.sec_mode & + NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { + DATA_BLOB session_key; + if (lp_client_ntlmv2_auth()) { + DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, lp_netbios_name(), lp_workgroup()); + DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key; + + if (!SMBNTLMv2encrypt_hash(state, + state->setup.nt1.in.user, state->setup.nt1.in.domain, + nt_hash->hash, &session->transport->negotiate.secblob, + &names_blob, + &lmv2_response, &ntlmv2_response, + &lmv2_session_key, &session_key)) { + data_blob_free(&names_blob); + return NT_STATUS_NO_MEMORY; + } + data_blob_free(&names_blob); + state->setup.nt1.in.password1 = lmv2_response; + state->setup.nt1.in.password2 = ntlmv2_response; + + smbcli_transport_simple_set_signing(session->transport, session_key, + state->setup.nt1.in.password2); + set_user_session_key(session, &session_key); + + data_blob_free(&lmv2_session_key); + data_blob_free(&session_key); + } else { + + state->setup.nt1.in.password2 = nt_blob(state, nt_hash, + session->transport->negotiate.secblob); + if (lp_client_lanman_auth()) { + state->setup.nt1.in.password1 = lanman_blob(state, password, + session->transport->negotiate.secblob); + } else { + /* if not sending the LM password, send the NT password twice */ + state->setup.nt1.in.password1 = state->setup.nt1.in.password2; + } + + session_key = data_blob_talloc(session, NULL, 16); + SMBsesskeygen_ntv1(nt_hash->hash, session_key.data); + smbcli_transport_simple_set_signing(session->transport, session_key, + state->setup.nt1.in.password2); + set_user_session_key(session, &session_key); + + data_blob_free(&session_key); + } + + } else if (lp_client_plaintext_auth()) { + state->setup.nt1.in.password1 = data_blob_talloc(state, password, strlen(password)); + state->setup.nt1.in.password2 = data_blob(NULL, 0); + } else { + /* could match windows client and return 'cannot logon from this workstation', but it just confuses everybody */ + return NT_STATUS_INVALID_PARAMETER; + } + + *req = smb_raw_sesssetup_send(session, &state->setup); + if (!*req) { + return NT_STATUS_NO_MEMORY; + } + return (*req)->status; +} + + +/* + old style session setup (pre NT1 protocol level) +*/ +static NTSTATUS session_setup_old(struct composite_context *c, + struct smbcli_session *session, + struct smb_composite_sesssetup *io, + struct smbcli_request **req) +{ + struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); + const char *password = cli_credentials_get_password(io->in.credentials); + + state->setup.old.level = RAW_SESSSETUP_OLD; + state->setup.old.in.bufsize = session->transport->options.max_xmit; + state->setup.old.in.mpx_max = session->transport->options.max_mux; + state->setup.old.in.vc_num = 1; + state->setup.old.in.sesskey = io->in.sesskey; + state->setup.old.in.os = "Unix"; + state->setup.old.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING); + cli_credentials_get_ntlm_username_domain(io->in.credentials, state, + &state->setup.old.in.user, + &state->setup.old.in.domain); + + if (!password) { + state->setup.old.in.password = data_blob(NULL, 0); + } else if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { + state->setup.old.in.password = lanman_blob(state, password, + session->transport->negotiate.secblob); + } else { + state->setup.old.in.password = data_blob_talloc(state, + password, + strlen(password)); + } + + *req = smb_raw_sesssetup_send(session, &state->setup); + if (!*req) { + return NT_STATUS_NO_MEMORY; + } + return (*req)->status; +} + + +/* + Modern, all singing, all dancing extended security (and possibly SPNEGO) request +*/ +static NTSTATUS session_setup_spnego(struct composite_context *c, + struct smbcli_session *session, + struct smb_composite_sesssetup *io, + struct smbcli_request **req) +{ + struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); + NTSTATUS status, session_key_err; + DATA_BLOB session_key = data_blob(NULL, 0); + DATA_BLOB null_data_blob = data_blob(NULL, 0); + const char *chosen_oid = NULL; + + state->setup.spnego.level = RAW_SESSSETUP_SPNEGO; + state->setup.spnego.in.bufsize = session->transport->options.max_xmit; + state->setup.spnego.in.mpx_max = session->transport->options.max_mux; + state->setup.spnego.in.vc_num = 1; + state->setup.spnego.in.sesskey = io->in.sesskey; + state->setup.spnego.in.capabilities = io->in.capabilities; + state->setup.spnego.in.os = "Unix"; + state->setup.spnego.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING); + state->setup.spnego.in.workgroup = io->in.workgroup; + + state->setup.spnego.out.vuid = session->vuid; + + smbcli_temp_set_signing(session->transport); + + status = gensec_client_start(session, &session->gensec, c->event_ctx); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status))); + return status; + } + + gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY); + + status = gensec_set_credentials(session->gensec, io->in.credentials); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to start set GENSEC client credentails: %s\n", + nt_errstr(status))); + return status; + } + + status = gensec_set_target_hostname(session->gensec, session->transport->socket->hostname); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", + nt_errstr(status))); + return status; + } + + status = gensec_set_target_service(session->gensec, "cifs"); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to start set GENSEC target service: %s\n", + nt_errstr(status))); + return status; + } + + if (session->transport->negotiate.secblob.length) { + chosen_oid = GENSEC_OID_SPNEGO; + } else { + /* without a sec blob, means raw NTLMSSP */ + chosen_oid = GENSEC_OID_NTLMSSP; + } + + status = gensec_start_mech_by_oid(session->gensec, chosen_oid); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism %s: %s\n", + gensec_get_name_by_oid(chosen_oid), nt_errstr(status))); + return status; + } + + status = gensec_update(session->gensec, state, + session->transport->negotiate.secblob, + &state->setup.spnego.in.secblob); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && + !NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed initial gensec_update with mechanism %s: %s\n", + gensec_get_name_by_oid(chosen_oid), nt_errstr(status))); + return status; + } + state->gensec_status = status; + + session_key_err = gensec_session_key(session->gensec, &session_key); + if (NT_STATUS_IS_OK(session_key_err)) { + smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); + } + + *req = smb_raw_sesssetup_send(session, &state->setup); + if (!*req) { + return NT_STATUS_NO_MEMORY; + } + return (*req)->status; +} + + +/* + composite session setup function that hides the details of all the + different session setup varients, including the multi-pass nature of + the spnego varient +*/ +struct composite_context *smb_composite_sesssetup_send(struct smbcli_session *session, + struct smb_composite_sesssetup *io) +{ + struct composite_context *c; + struct sesssetup_state *state; + NTSTATUS status; + + c = talloc_zero(session, struct composite_context); + if (c == NULL) return NULL; + + state = talloc(c, struct sesssetup_state); + if (state == NULL) { + c->state = COMPOSITE_STATE_ERROR; + c->status = NT_STATUS_NO_MEMORY; + } + + state->io = io; + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = state; + c->event_ctx = session->transport->socket->event.ctx; + + /* no session setup at all in earliest protocol varients */ + if (session->transport->negotiate.protocol < PROTOCOL_LANMAN1) { + ZERO_STRUCT(io->out); + c->state = COMPOSITE_STATE_DONE; + return c; + } + + /* see what session setup interface we will use */ + if (session->transport->negotiate.protocol < PROTOCOL_NT1) { + status = session_setup_old(c, session, io, &state->req); + } else if (!session->transport->options.use_spnego || + !(io->in.capabilities & CAP_EXTENDED_SECURITY)) { + status = session_setup_nt1(c, session, io, &state->req); + } else { + status = session_setup_spnego(c, session, io, &state->req); + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || + NT_STATUS_IS_OK(status)) { + state->req->async.fn = request_handler; + state->req->async.private = c; + return c; + } + + c->state = COMPOSITE_STATE_ERROR; + c->status = status; + return c; +} + + +/* + receive a composite session setup reply +*/ +NTSTATUS smb_composite_sesssetup_recv(struct composite_context *c) +{ + NTSTATUS status; + status = composite_wait(c); + talloc_free(c); + return status; +} + +/* + sync version of smb_composite_sesssetup +*/ +NTSTATUS smb_composite_sesssetup(struct smbcli_session *session, struct smb_composite_sesssetup *io) +{ + struct composite_context *c = smb_composite_sesssetup_send(session, io); + return smb_composite_sesssetup_recv(c); +} diff --git a/source4/libcli/smb_composite/smb_composite.h b/source4/libcli/smb_composite/smb_composite.h new file mode 100644 index 0000000000..08031c2f4b --- /dev/null +++ b/source4/libcli/smb_composite/smb_composite.h @@ -0,0 +1,152 @@ +/* + Unix SMB/CIFS implementation. + + SMB composite request interfaces + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + this defines the structures associated with "composite" + requests. Composite requests are libcli requests that are internally + implemented as multiple libcli/raw/ calls, but can be treated as a + single call via these composite calls. The composite calls are + particularly designed to be used in async applications +*/ + + +/* + a composite open/read(s)/close request that loads a whole file + into memory. Used as a demo of the composite system. +*/ +struct smb_composite_loadfile { + struct { + const char *fname; + } in; + struct { + uint8_t *data; + uint32_t size; + } out; +}; + +struct smb_composite_fetchfile { + struct { + const char *dest_host; + int port; + const char *called_name; + const char *service; + const char *service_type; + struct cli_credentials *credentials; + const char *workgroup; + const char *filename; + } in; + struct { + uint8_t *data; + uint32_t size; + } out; +}; + +/* + a composite open/write(s)/close request that saves a whole file from + memory. Used as a demo of the composite system. +*/ +struct smb_composite_savefile { + struct { + const char *fname; + uint8_t *data; + uint32_t size; + } in; +}; + + +/* + a composite request for a full connection to a remote server. Includes + + - socket establishment + - session request + - negprot + - session setup + - tree connect +*/ +struct smb_composite_connect { + struct { + const char *dest_host; + int port; + const char *called_name; + const char *service; + const char *service_type; + struct cli_credentials *credentials; + const char *workgroup; + } in; + struct { + struct smbcli_tree *tree; + } out; +}; + + +/* + generic session setup interface that takes care of which + session setup varient to use +*/ +struct smb_composite_sesssetup { + struct { + uint32_t sesskey; + uint32_t capabilities; + struct cli_credentials *credentials; + const char *workgroup; + } in; + struct { + uint16_t vuid; + } out; +}; + +/* + query file system info +*/ +struct smb_composite_fsinfo { + struct { + const char *dest_host; + int port; + const char *called_name; + const char *service; + const char *service_type; + struct cli_credentials *credentials; + const char *workgroup; + enum smb_fsinfo_level level; + } in; + + struct { + union smb_fsinfo *fsinfo; + } out; +}; + +/* + composite call for appending new acl to the file's security descriptor and get + new full acl +*/ + +struct smb_composite_appendacl { + struct { + const char *fname; + + const struct security_descriptor *sd; + } in; + + struct { + struct security_descriptor *sd; + } out; +}; diff --git a/source4/libnet/composite.h b/source4/libnet/composite.h index 6d805812c0..0500e19f5a 100644 --- a/source4/libnet/composite.h +++ b/source4/libnet/composite.h @@ -24,6 +24,25 @@ #include "librpc/gen_ndr/ndr_samr.h" +/* + * Monitor structure and message types definitions. Composite function monitoring + * allows client application to be notified on function progress. This enables + * eg. gui client to display progress bars, status messages, etc. + */ + + +#define rpc_create_user (0x00000001) /* userman.h */ +#define rpc_open_user (0x00000002) /* userinfo.h */ +#define rpc_query_user (0x00000003) /* userinfo.h */ +#define rpc_close_user (0x00000004) /* userinfo.h */ +#define rpc_lookup_name (0x00000005) /* userman.h */ +#define rpc_delete_user (0x00000006) /* userman.h */ + +struct monitor_msg { + uint32_t type; + void *data; + size_t data_size; +}; struct libnet_rpc_userinfo { struct { diff --git a/source4/libnet/domain.c b/source4/libnet/domain.c index 94a2412261..3a5aecb92e 100644 --- a/source4/libnet/domain.c +++ b/source4/libnet/domain.c @@ -23,9 +23,7 @@ */ #include "includes.h" -#include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" -#include "libcli/composite/monitor.h" #include "librpc/gen_ndr/ndr_samr.h" #include "libnet/composite.h" @@ -119,7 +117,7 @@ static NTSTATUS domain_open_open(struct composite_context *c, c->status = dcerpc_ndr_request_recv(s->req); NT_STATUS_NOT_OK_RETURN(c->status); - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; return NT_STATUS_OK; } @@ -134,8 +132,7 @@ static NTSTATUS domain_open_open(struct composite_context *c, static void domain_open_handler(struct rpc_request *req) { struct composite_context *c = req->async.private; - struct domain_open_state *s = talloc_get_type(c->private, struct domain_open_state); - struct monitor_msg msg; + struct domain_open_state *s = talloc_get_type(c->private_data, struct domain_open_state); /* Stages of the call */ switch (s->stage) { @@ -151,11 +148,7 @@ static void domain_open_handler(struct rpc_request *req) } if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; - } - - if (c->monitor_fn) { - c->monitor_fn(&msg); + c->state = COMPOSITE_STATE_ERROR; } } @@ -179,10 +172,9 @@ struct composite_context *libnet_rpc_domain_open_send(struct dcerpc_pipe *p, s = talloc_zero(c, struct domain_open_state); if (s == NULL) goto failure; - c->state = SMBCLI_REQUEST_SEND; - c->private = s; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data= s; c->event_ctx = dcerpc_event_context(p); - c->monitor_fn = monitor; s->pipe = p; s->access_mask = io->in.access_mask; @@ -227,7 +219,7 @@ NTSTATUS libnet_rpc_domain_open_recv(struct composite_context *c, TALLOC_CTX *me status = composite_wait(c); if (NT_STATUS_IS_OK(status) && io) { - s = talloc_get_type(c->private, struct domain_open_state); + s = talloc_get_type(c->private_data, struct domain_open_state); io->out.domain_handle = s->domain_handle; } diff --git a/source4/libnet/libnet_lookup.c b/source4/libnet/libnet_lookup.c index ba806e4e44..010d30ac4a 100644 --- a/source4/libnet/libnet_lookup.c +++ b/source4/libnet/libnet_lookup.c @@ -27,7 +27,6 @@ #include "lib/events/events.h" #include "libnet/libnet.h" #include "libcli/composite/composite.h" -#include "libcli/composite/monitor.h" #include "libnet/composite.h" #include "librpc/gen_ndr/ndr_nbt.h" @@ -78,8 +77,8 @@ struct composite_context *libnet_Lookup_send(struct libnet_context *ctx, methods = (const char**)ctx->name_res_methods; } - c->private = s; - c->state = SMBCLI_REQUEST_SEND; + c->private_data = s; + c->state = COMPOSITE_STATE_IN_PROGRESS; /* send resolve request */ s->resolve_ctx = resolve_name_send(&s->hostname, c->event_ctx, methods); @@ -107,7 +106,7 @@ NTSTATUS libnet_Lookup_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, NTSTATUS status; struct lookup_state *s; - s = talloc_get_type(c->private, struct lookup_state); + s = talloc_get_type(c->private_data, struct lookup_state); status = resolve_name_recv(s->resolve_ctx, mem_ctx, s->address); return status; diff --git a/source4/libnet/userinfo.c b/source4/libnet/userinfo.c index def9c87147..378bc814bd 100644 --- a/source4/libnet/userinfo.c +++ b/source4/libnet/userinfo.c @@ -23,9 +23,7 @@ */ #include "includes.h" -#include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" -#include "libcli/composite/monitor.h" #include "librpc/gen_ndr/ndr_samr.h" #include "libnet/composite.h" #include "libnet/userinfo.h" @@ -44,6 +42,8 @@ struct userinfo_state { struct samr_QueryUserInfo queryuserinfo; struct samr_Close samrclose; union samr_UserInfo *info; + /* information about the progress */ + void (*monitor_fn)(struct monitor_msg *); }; @@ -113,7 +113,7 @@ static NTSTATUS userinfo_closeuser(struct composite_context *c, c->status = dcerpc_ndr_request_recv(s->req); NT_STATUS_NOT_OK_RETURN(c->status); - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; return NT_STATUS_OK; } @@ -128,7 +128,7 @@ static NTSTATUS userinfo_closeuser(struct composite_context *c, static void userinfo_handler(struct rpc_request *req) { struct composite_context *c = req->async.private; - struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state); + struct userinfo_state *s = talloc_get_type(c->private_data, struct userinfo_state); struct monitor_msg msg; struct msg_rpc_open_user *msg_open; struct msg_rpc_query_user *msg_query; @@ -169,14 +169,14 @@ static void userinfo_handler(struct rpc_request *req) } if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; } - if (c->monitor_fn) { - c->monitor_fn(&msg); + if (s->monitor_fn) { + s->monitor_fn(&msg); } - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -207,13 +207,13 @@ struct composite_context *libnet_rpc_userinfo_send(struct dcerpc_pipe *p, s->level = io->in.level; s->pipe = p; + s->monitor_fn = monitor; sid = dom_sid_parse_talloc(s, io->in.sid); if (sid == NULL) goto failure; - c->state = SMBCLI_REQUEST_SEND; - c->private = s; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data= s; c->event_ctx = dcerpc_event_context(p); - c->monitor_fn = monitor; /* preparing parameters to send rpc request */ s->openuser.in.domain_handle = &io->in.domain_handle; @@ -256,7 +256,7 @@ NTSTATUS libnet_rpc_userinfo_recv(struct composite_context *c, TALLOC_CTX *mem_c status = composite_wait(c); if (NT_STATUS_IS_OK(status) && io) { - s = talloc_get_type(c->private, struct userinfo_state); + s = talloc_get_type(c->private_data, struct userinfo_state); talloc_steal(mem_ctx, s->info); io->out.info = *s->info; } diff --git a/source4/libnet/userman.c b/source4/libnet/userman.c index eacc1a2b42..e38f4dcb7c 100644 --- a/source4/libnet/userman.c +++ b/source4/libnet/userman.c @@ -23,9 +23,7 @@ */ #include "includes.h" -#include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" -#include "libcli/composite/monitor.h" #include "librpc/gen_ndr/ndr_samr.h" #include "libnet/composite.h" #include "libnet/userman.h" @@ -47,6 +45,8 @@ struct useradd_state { struct samr_CreateUser createuser; struct policy_handle user_handle; uint32_t user_rid; + /* information about the progress */ + void (*monitor_fn)(struct monitor_msg *); }; @@ -59,7 +59,7 @@ static NTSTATUS useradd_create(struct composite_context *c, c->status = dcerpc_ndr_request_recv(s->req); NT_STATUS_NOT_OK_RETURN(c->status); - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; return NT_STATUS_OK; } @@ -73,7 +73,7 @@ static NTSTATUS useradd_create(struct composite_context *c, static void useradd_handler(struct rpc_request *req) { struct composite_context *c = req->async.private; - struct useradd_state *s = talloc_get_type(c->private, struct useradd_state); + struct useradd_state *s = talloc_get_type(c->private_data, struct useradd_state); struct monitor_msg msg; struct msg_rpc_create_user *rpc_create; @@ -90,14 +90,14 @@ static void useradd_handler(struct rpc_request *req) } if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; } - if (c->monitor_fn) { - c->monitor_fn(&msg); + if (s->monitor_fn) { + s->monitor_fn(&msg); } - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -126,11 +126,11 @@ struct composite_context *libnet_rpc_useradd_send(struct dcerpc_pipe *p, s->domain_handle = io->in.domain_handle; s->pipe = p; + s->monitor_fn = monitor; - c->state = SMBCLI_REQUEST_SEND; - c->private = s; + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data= s; c->event_ctx = dcerpc_event_context(p); - c->monitor_fn = monitor; /* preparing parameters to send rpc request */ s->createuser.in.domain_handle = &io->in.domain_handle; @@ -174,7 +174,7 @@ NTSTATUS libnet_rpc_useradd_recv(struct composite_context *c, TALLOC_CTX *mem_ct if (NT_STATUS_IS_OK(status) && io) { /* get and return result of the call */ - s = talloc_get_type(c->private, struct useradd_state); + s = talloc_get_type(c->private_data, struct useradd_state); io->out.user_handle = s->user_handle; } @@ -218,6 +218,8 @@ struct userdel_state { struct samr_LookupNames lookupname; struct samr_OpenUser openuser; struct samr_DeleteUser deleteuser; + /* information about the progress */ + void (*monitor_fn)(struct monitor_msg *); }; @@ -287,7 +289,7 @@ static NTSTATUS userdel_delete(struct composite_context *c, c->status = dcerpc_ndr_request_recv(s->req); NT_STATUS_NOT_OK_RETURN(c->status); - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; return NT_STATUS_OK; } @@ -302,7 +304,7 @@ static NTSTATUS userdel_delete(struct composite_context *c, static void userdel_handler(struct rpc_request *req) { struct composite_context *c = req->async.private; - struct userdel_state *s = talloc_get_type(c->private, struct userdel_state); + struct userdel_state *s = talloc_get_type(c->private_data, struct userdel_state); struct monitor_msg msg; struct msg_rpc_lookup_name *msg_lookup; struct msg_rpc_open_user *msg_open; @@ -340,14 +342,14 @@ static void userdel_handler(struct rpc_request *req) } if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; } - if (c->monitor_fn) { - c->monitor_fn(&msg); + if (s->monitor_fn) { + s->monitor_fn(&msg); } - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -373,9 +375,9 @@ struct composite_context *libnet_rpc_userdel_send(struct dcerpc_pipe *p, s = talloc_zero(c, struct userdel_state); if (s == NULL) goto failure; - c->state = SMBCLI_REQUEST_SEND; - c->private = s; - c->event_ctx = dcerpc_event_context(p); + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data= s; + c->event_ctx = dcerpc_event_context(p); s->pipe = p; s->domain_handle = io->in.domain_handle; @@ -403,7 +405,7 @@ failure: /** - * Waits for and receives results of asynchronous userdel call +1 * Waits for and receives results of asynchronous userdel call * * @param c composite context returned by asynchronous userdel call * @param mem_ctx memory context of the call @@ -420,7 +422,7 @@ NTSTATUS libnet_rpc_userdel_recv(struct composite_context *c, TALLOC_CTX *mem_ct status = composite_wait(c); if (NT_STATUS_IS_OK(status) && io) { - s = talloc_get_type(c->private, struct userdel_state); + s = talloc_get_type(c->private_data, struct userdel_state); io->out.user_handle = s->user_handle; } @@ -672,7 +674,7 @@ static NTSTATUS usermod_modify(struct composite_context *c, c->status = dcerpc_ndr_request_recv(s->req); NT_STATUS_NOT_OK_RETURN(c->status); - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; return NT_STATUS_OK; } @@ -688,8 +690,7 @@ static NTSTATUS usermod_modify(struct composite_context *c, static void usermod_handler(struct rpc_request *req) { struct composite_context *c = req->async.private; - struct usermod_state *s = talloc_get_type(c->private, struct usermod_state); - struct monitor_msg msg; + struct usermod_state *s = talloc_get_type(c->private_data, struct usermod_state); switch (s->stage) { case USERMOD_LOOKUP: @@ -710,14 +711,10 @@ static void usermod_handler(struct rpc_request *req) } if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; - } - - if (c->monitor_fn) { - c->monitor_fn(&msg); + c->state = COMPOSITE_STATE_ERROR; } - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -743,9 +740,9 @@ struct composite_context *libnet_rpc_usermod_send(struct dcerpc_pipe *p, s = talloc_zero(c, struct usermod_state); if (s == NULL) goto failure; - c->state = SMBCLI_REQUEST_SEND; - c->private = s; - c->event_ctx = dcerpc_event_context(p); + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = s; + c->event_ctx = dcerpc_event_context(p); s->pipe = p; s->domain_handle = io->in.domain_handle; diff --git a/source4/nbt_server/register.c b/source4/nbt_server/register.c index 0d0526b94e..4ff95b8887 100644 --- a/source4/nbt_server/register.c +++ b/source4/nbt_server/register.c @@ -25,7 +25,6 @@ #include "dlinklist.h" #include "nbt_server/nbt_server.h" #include "smbd/service_task.h" -#include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" #include "librpc/gen_ndr/ndr_samr.h" @@ -77,9 +76,9 @@ static void refresh_completion_handler(struct nbt_name_request *req) handle name refresh timer events */ static void name_refresh_handler(struct event_context *ev, struct timed_event *te, - struct timeval t, void *private) + struct timeval t, void *private_data) { - struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name); + struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name); struct nbtd_interface *iface = iname->iface; struct nbt_name_register io; struct nbt_name_request *req; @@ -130,14 +129,14 @@ static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname) /* a name registration has completed */ -static void nbtd_register_handler(struct composite_context *req) +static void nbtd_register_handler(struct composite_context *creq) { - struct nbtd_iface_name *iname = talloc_get_type(req->async.private, + struct nbtd_iface_name *iname = talloc_get_type(creq->async.private_data, struct nbtd_iface_name); NTSTATUS status; TALLOC_CTX *tmp_ctx = talloc_new(iname); - status = nbt_name_register_bcast_recv(req); + status = nbt_name_register_bcast_recv(creq); if (NT_STATUS_IS_OK(status)) { /* good - nobody complained about our registration */ iname->nb_flags |= NBT_NM_ACTIVE; @@ -170,7 +169,7 @@ static void nbtd_register_name_iface(struct nbtd_interface *iface, struct nbtd_iface_name *iname; const char *scope = lp_netbios_scope(); struct nbt_name_register_bcast io; - struct composite_context *req; + struct composite_context *creq; struct nbtd_server *nbtsrv = iface->nbtsrv; iname = talloc(iface, struct nbtd_iface_name); @@ -213,11 +212,11 @@ static void nbtd_register_name_iface(struct nbtd_interface *iface, io.in.ttl = iname->ttl; nbtsrv->stats.total_sent++; - req = nbt_name_register_bcast_send(iface->nbtsock, &io); - if (req == NULL) return; + creq = nbt_name_register_bcast_send(iface->nbtsock, &io); + if (creq == NULL) return; - req->async.fn = nbtd_register_handler; - req->async.private = iname; + creq->async.fn = nbtd_register_handler; + creq->async.private_data = iname; } diff --git a/source4/nbt_server/wins/winsclient.c b/source4/nbt_server/wins/winsclient.c index cfb68a3aaf..fdfdc8f0ed 100644 --- a/source4/nbt_server/wins/winsclient.c +++ b/source4/nbt_server/wins/winsclient.c @@ -22,7 +22,6 @@ #include "includes.h" #include "nbt_server/nbt_server.h" -#include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" #include "lib/events/events.h" #include "smbd/service_task.h" @@ -38,15 +37,15 @@ static struct nbt_name_socket *wins_socket(struct nbtd_interface *iface) static void nbtd_wins_refresh(struct event_context *ev, struct timed_event *te, - struct timeval t, void *private); + struct timeval t, void *private_data); /* retry a WINS name registration */ static void nbtd_wins_register_retry(struct event_context *ev, struct timed_event *te, - struct timeval t, void *private) + struct timeval t, void *private_data) { - struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name); + struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name); nbtd_winsclient_register(iname); } @@ -58,7 +57,7 @@ static void nbtd_wins_refresh_handler(struct composite_context *c) { NTSTATUS status; struct nbt_name_refresh_wins io; - struct nbtd_iface_name *iname = talloc_get_type(c->async.private, + struct nbtd_iface_name *iname = talloc_get_type(c->async.private_data, struct nbtd_iface_name); TALLOC_CTX *tmp_ctx = talloc_new(iname); @@ -78,7 +77,7 @@ static void nbtd_wins_refresh_handler(struct composite_context *c) nbt_name_string(tmp_ctx, &iname->name), nt_errstr(status))); talloc_free(tmp_ctx); return; - } + } if (io.out.rcode != 0) { DEBUG(1,("WINS server %s rejected name refresh of %s - %s\n", @@ -113,9 +112,9 @@ static void nbtd_wins_refresh_handler(struct composite_context *c) refresh a WINS name registration */ static void nbtd_wins_refresh(struct event_context *ev, struct timed_event *te, - struct timeval t, void *private) + struct timeval t, void *private_data) { - struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name); + struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name); struct nbtd_interface *iface = iname->iface; struct nbt_name_refresh_wins io; struct composite_context *c; @@ -136,7 +135,7 @@ static void nbtd_wins_refresh(struct event_context *ev, struct timed_event *te, talloc_steal(c, io.in.addresses); c->async.fn = nbtd_wins_refresh_handler; - c->async.private = iname; + c->async.private_data = iname; talloc_free(tmp_ctx); } @@ -149,7 +148,7 @@ static void nbtd_wins_register_handler(struct composite_context *c) { NTSTATUS status; struct nbt_name_register_wins io; - struct nbtd_iface_name *iname = talloc_get_type(c->async.private, + struct nbtd_iface_name *iname = talloc_get_type(c->async.private_data, struct nbtd_iface_name); TALLOC_CTX *tmp_ctx = talloc_new(iname); @@ -227,5 +226,5 @@ void nbtd_winsclient_register(struct nbtd_iface_name *iname) talloc_steal(c, io.in.addresses); c->async.fn = nbtd_wins_register_handler; - c->async.private = iname; + c->async.private_data = iname; } diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index f263299cd7..789f24259a 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -29,6 +29,7 @@ #include "lib/events/events.h" #include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" #include "smb_server/smb_server.h" #include "smbd/service_stream.h" diff --git a/source4/torture/basic/secleak.c b/source4/torture/basic/secleak.c index 005eb5f213..f77b399874 100644 --- a/source4/torture/basic/secleak.c +++ b/source4/torture/basic/secleak.c @@ -24,6 +24,7 @@ #include "libcli/raw/libcliraw.h" #include "system/time.h" #include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" static BOOL try_failed_login(struct smbcli_state *cli) { diff --git a/source4/torture/libnet/domain.c b/source4/torture/libnet/domain.c index 7edbd5742d..98c44cd942 100644 --- a/source4/torture/libnet/domain.c +++ b/source4/torture/libnet/domain.c @@ -22,7 +22,6 @@ #include "includes.h" #include "librpc/gen_ndr/ndr_samr.h" #include "libnet/composite.h" -#include "libcli/composite/monitor.h" static BOOL test_domainopen(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct lsa_String *domname, diff --git a/source4/torture/libnet/libnet_lookup.c b/source4/torture/libnet/libnet_lookup.c index 320b3c11cc..b0cdc8c93e 100644 --- a/source4/torture/libnet/libnet_lookup.c +++ b/source4/torture/libnet/libnet_lookup.c @@ -23,7 +23,6 @@ #include "lib/cmdline/popt_common.h" #include "libnet/libnet.h" #include "libnet/composite.h" -#include "libcli/composite/monitor.h" #include "librpc/gen_ndr/ndr_nbt.h" diff --git a/source4/torture/libnet/libnet_rpc.c b/source4/torture/libnet/libnet_rpc.c index ee51ac15a2..4cd04ecb42 100644 --- a/source4/torture/libnet/libnet_rpc.c +++ b/source4/torture/libnet/libnet_rpc.c @@ -23,7 +23,6 @@ #include "lib/cmdline/popt_common.h" #include "libnet/libnet.h" #include "libnet/composite.h" -#include "libcli/composite/monitor.h" BOOL test_lsa_connect(struct libnet_context *ctx) diff --git a/source4/torture/libnet/libnet_user.c b/source4/torture/libnet/libnet_user.c index 4db0028481..60c8bce935 100644 --- a/source4/torture/libnet/libnet_user.c +++ b/source4/torture/libnet/libnet_user.c @@ -24,7 +24,6 @@ #include "lib/cmdline/popt_common.h" #include "libnet/libnet.h" #include "libnet/composite.h" -#include "libcli/composite/monitor.h" #define TEST_USERNAME "libnetusertest" diff --git a/source4/torture/libnet/userinfo.c b/source4/torture/libnet/userinfo.c index aa1e64301a..63724bc8b1 100644 --- a/source4/torture/libnet/userinfo.c +++ b/source4/torture/libnet/userinfo.c @@ -23,7 +23,6 @@ #include "librpc/gen_ndr/ndr_samr.h" #include "libnet/composite.h" #include "libnet/userinfo.h" -#include "libcli/composite/monitor.h" #define TEST_USERNAME "libnetuserinfotest" diff --git a/source4/torture/libnet/userman.c b/source4/torture/libnet/userman.c index 8ddd956608..fc2a32c913 100644 --- a/source4/torture/libnet/userman.c +++ b/source4/torture/libnet/userman.c @@ -23,7 +23,6 @@ #include "librpc/gen_ndr/ndr_samr.h" #include "libnet/composite.h" #include "libnet/userman.h" -#include "libcli/composite/monitor.h" #define TEST_USERNAME "libnetusermantest" @@ -412,7 +411,7 @@ BOOL torture_usermod(void) struct dcerpc_pipe *p; struct policy_handle h; struct lsa_String domain_name; - char *name = TEST_USERNAME; + const char *name = TEST_USERNAME; TALLOC_CTX *mem_ctx; BOOL ret = True; int i; diff --git a/source4/torture/raw/composite.c b/source4/torture/raw/composite.c index 457bcea7f9..fafdb90ec3 100644 --- a/source4/torture/raw/composite.c +++ b/source4/torture/raw/composite.c @@ -24,6 +24,7 @@ #include "lib/events/events.h" #include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" #include "lib/cmdline/popt_common.h" #include "librpc/gen_ndr/ndr_security.h" @@ -31,7 +32,7 @@ static void loadfile_complete(struct composite_context *c) { - int *count = talloc_get_type(c->async.private, int); + int *count = talloc_get_type(c->async.private_data, int); (*count)++; } @@ -76,7 +77,7 @@ static BOOL test_loadfile(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) for (i=0;itree, &io2); c[i]->async.fn = loadfile_complete; - c[i]->async.private = count; + c[i]->async.private_data = count; } printf("waiting for completion\n"); @@ -163,7 +164,7 @@ static BOOL test_fetchfile(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) for (i=0; iasync.fn = loadfile_complete; - c[i]->async.private = count; + c[i]->async.private_data = count; } printf("waiting for completion\n"); @@ -281,7 +282,7 @@ static BOOL test_appendacl(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) c[i] = smb_composite_appendacl_send(cli->tree, io[i]); c[i]->async.fn = loadfile_complete; - c[i]->async.private = count; + c[i]->async.private_data = count; } event_ctx = talloc_reference(mem_ctx, cli->tree->session->transport->socket->event.ctx); @@ -346,7 +347,7 @@ static BOOL test_fsinfo(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) for (i=0; itree,&io1); c[i]->async.fn = loadfile_complete; - c[i]->async.private = count; + c[i]->async.private_data = count; } printf("waiting for completion\n"); diff --git a/source4/torture/raw/context.c b/source4/torture/raw/context.c index d76882d84d..0fe2c894af 100644 --- a/source4/torture/raw/context.c +++ b/source4/torture/raw/context.c @@ -22,6 +22,7 @@ #include "libcli/raw/libcliraw.h" #include "librpc/gen_ndr/ndr_security.h" #include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" #include "lib/cmdline/popt_common.h" #include "lib/events/events.h" diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c index 17efd06c81..d6f2f1cac4 100644 --- a/source4/winbind/wb_async_helpers.c +++ b/source4/winbind/wb_async_helpers.c @@ -22,7 +22,6 @@ */ #include "includes.h" -#include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" #include "winbind/wb_async_helpers.h" @@ -40,14 +39,14 @@ struct finddcs_state { struct irpc_request *ireq; }; -static void finddcs_getdc(struct irpc_request *req) +static void finddcs_getdc(struct irpc_request *ireq) { - struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context *c = talloc_get_type(ireq->async.private, struct composite_context); - struct finddcs_state *state = - talloc_get_type(c->private, struct finddcs_state); + struct finddcs_state *state = talloc_get_type(c->private_data, + struct finddcs_state); - c->status = irpc_call_recv(req); + c->status = irpc_call_recv(ireq); if (!NT_STATUS_IS_OK(c->status)) { goto done; } @@ -56,14 +55,14 @@ static void finddcs_getdc(struct irpc_request *req) state->r->out.dcname); c->status = NT_STATUS_OK; - c->state = SMBCLI_REQUEST_DONE; + c->state = COMPOSITE_STATE_DONE; done: if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; } - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -74,10 +73,10 @@ static void finddcs_getdc(struct irpc_request *req) */ static void finddcs_resolve(struct composite_context *res_ctx) { - struct composite_context *c = talloc_get_type(res_ctx->async.private, + struct composite_context *c = talloc_get_type(res_ctx->async.private_data, struct composite_context); - struct finddcs_state *state = - talloc_get_type(c->private, struct finddcs_state); + struct finddcs_state *state = talloc_get_type(c->private_data, + struct finddcs_state); uint32_t *nbt_servers; state->io->out.num_dcs = 1; @@ -141,10 +140,10 @@ static void finddcs_resolve(struct composite_context *res_ctx) done: if (!NT_STATUS_IS_OK(c->status)) { - c->state = SMBCLI_REQUEST_ERROR; + c->state = COMPOSITE_STATE_ERROR; } - if (c->state >= SMBCLI_REQUEST_DONE && + if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); } @@ -159,7 +158,7 @@ struct composite_context *wb_finddcs_send(struct wb_finddcs *io, c = talloc_zero(NULL, struct composite_context); if (c == NULL) goto failed; - c->state = SMBCLI_REQUEST_SEND; + c->state = COMPOSITE_STATE_IN_PROGRESS; c->event_ctx = event_ctx; state = talloc(c, struct finddcs_state); @@ -172,9 +171,9 @@ struct composite_context *wb_finddcs_send(struct wb_finddcs *io, lp_name_resolve_order()); if (state->creq == NULL) goto failed; - state->creq->async.private = c; + state->creq->async.private_data = c; state->creq->async.fn = finddcs_resolve; - c->private = state; + c->private_data = state; return c; failed: @@ -189,8 +188,8 @@ NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { - struct finddcs_state *state = - talloc_get_type(c->private, struct finddcs_state); + struct finddcs_state *state = talloc_get_type(c->private_data, + struct finddcs_state); talloc_steal(mem_ctx, state->io->out.dcs); } diff --git a/source4/winbind/wb_samba3_cmd.c b/source4/winbind/wb_samba3_cmd.c index 4ff54e25b4..5f79e74a92 100644 --- a/source4/winbind/wb_samba3_cmd.c +++ b/source4/winbind/wb_samba3_cmd.c @@ -60,7 +60,7 @@ struct check_machacc_state { static void wbsrv_samba3_check_machacc_reply(struct composite_context *action) { struct wbsrv_samba3_call *s3call = - talloc_get_type(action->async.private, + talloc_get_type(action->async.private_data, struct wbsrv_samba3_call); struct check_machacc_state *state = talloc_get_type(s3call->private_data, @@ -106,7 +106,7 @@ NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call) /* setup the callbacks */ resolve_req->async.fn = wbsrv_samba3_check_machacc_reply; - resolve_req->async.private = s3call; + resolve_req->async.private_data = s3call; /* tell the caller we reply later */ s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC; -- cgit