diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/include/structs.h | 2 | ||||
-rw-r--r-- | source4/libcli/composite/appendacl.c | 311 | ||||
-rw-r--r-- | source4/libcli/composite/composite.h | 37 | ||||
-rw-r--r-- | source4/libcli/composite/fsinfo.c | 200 | ||||
-rw-r--r-- | source4/libcli/config.mk | 4 | ||||
-rw-r--r-- | source4/libcli/security/security_descriptor.c | 80 | ||||
-rw-r--r-- | source4/torture/raw/composite.c | 187 |
7 files changed, 817 insertions, 4 deletions
diff --git a/source4/include/structs.h b/source4/include/structs.h index b7c9abfe8b..906846ba67 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -158,6 +158,8 @@ struct smb_composite_savefile; struct smb_composite_connect; struct smb_composite_sesssetup; struct smb_composite_fetchfile; +struct smb_composite_appendacl; +struct smb_composite_fsinfo; struct rpc_composite_userinfo; struct nbt_name; diff --git a/source4/libcli/composite/appendacl.c b/source4/libcli/composite/appendacl.c new file mode 100644 index 0000000000..76702e6bca --- /dev/null +++ b/source4/libcli/composite/appendacl.c @@ -0,0 +1,311 @@ +#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.h b/source4/libcli/composite/composite.h index 18922127ee..87e7a7b6ad 100644 --- a/source4/libcli/composite/composite.h +++ b/source4/libcli/composite/composite.h @@ -135,3 +135,40 @@ struct smb_composite_sesssetup { 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/fsinfo.c b/source4/libcli/composite/fsinfo.c new file mode 100644 index 0000000000..1ad8a18149 --- /dev/null +++ b/source4/libcli/composite/fsinfo.c @@ -0,0 +1,200 @@ +/* + 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); + return 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); + return 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/config.mk b/source4/libcli/config.mk index def7bd0f27..816bff4ca4 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -22,7 +22,9 @@ ADD_OBJ_FILES = \ libcli/composite/savefile.o \ libcli/composite/connect.o \ libcli/composite/sesssetup.o \ - libcli/composite/fetchfile.o + libcli/composite/fetchfile.o \ + libcli/composite/appendacl.o \ + libcli/composite/fsinfo.o REQUIRED_SUBSYSTEMS = LIBCLI_COMPOSITE_BASE [SUBSYSTEM::LIBCLI_NBT] diff --git a/source4/libcli/security/security_descriptor.c b/source4/libcli/security/security_descriptor.c index 77d296235a..54c4bcb6cb 100644 --- a/source4/libcli/security/security_descriptor.c +++ b/source4/libcli/security/security_descriptor.c @@ -50,6 +50,46 @@ struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx) return sd; } +static struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, + const struct security_acl *oacl) +{ + struct security_acl *nacl; + int i; + + nacl = talloc (mem_ctx, struct security_acl); + if (nacl == NULL) { + return NULL; + } + + nacl->aces = talloc_memdup (nacl, oacl->aces, sizeof(struct security_ace) * oacl->num_aces); + if ((nacl->aces == NULL) && (oacl->num_aces > 0)) { + goto failed; + } + + /* remapping array in trustee dom_sid from old acl to new acl */ + + for (i = 0; i < oacl->num_aces; i++) { + nacl->aces[i].trustee.sub_auths = + talloc_memdup(nacl->aces, nacl->aces[i].trustee.sub_auths, + sizeof(uint32_t) * nacl->aces[i].trustee.num_auths); + + if ((nacl->aces[i].trustee.sub_auths == NULL) && (nacl->aces[i].trustee.num_auths > 0)) { + goto failed; + } + } + + nacl->revision = oacl->revision; + nacl->size = oacl->size; + nacl->num_aces = oacl->num_aces; + + return nacl; + + failed: + talloc_free (nacl); + return NULL; + +} + /* talloc and copy a security descriptor */ @@ -58,11 +98,45 @@ struct security_descriptor *security_descriptor_copy(TALLOC_CTX *mem_ctx, { struct security_descriptor *nsd; - /* FIXME */ - DEBUG(1, ("security_descriptor_copy(): sorry unimplemented yet\n")); - nsd = NULL; + nsd = talloc_zero(mem_ctx, struct security_descriptor); + if (!nsd) { + return NULL; + } + + if (osd->owner_sid) { + nsd->owner_sid = dom_sid_dup(nsd, osd->owner_sid); + if (nsd->owner_sid == NULL) { + goto failed; + } + } + + if (osd->group_sid) { + nsd->group_sid = dom_sid_dup(nsd, osd->group_sid); + if (nsd->group_sid == NULL) { + goto failed; + } + } + + if (osd->sacl) { + nsd->sacl = security_acl_dup(nsd, osd->sacl); + if (nsd->sacl == NULL) { + goto failed; + } + } + + if (osd->dacl) { + nsd->dacl = security_acl_dup(nsd, osd->dacl); + if (nsd->dacl == NULL) { + goto failed; + } + } return nsd; + + failed: + talloc_free(nsd); + + return NULL; } /* diff --git a/source4/torture/raw/composite.c b/source4/torture/raw/composite.c index f836e1eb4b..98615b7de4 100644 --- a/source4/torture/raw/composite.c +++ b/source4/torture/raw/composite.c @@ -25,6 +25,7 @@ #include "libcli/raw/libcliraw.h" #include "libcli/composite/composite.h" #include "lib/cmdline/popt_common.h" +#include "librpc/gen_ndr/ndr_security.h" #define BASEDIR "\\composite" @@ -201,6 +202,190 @@ static BOOL test_fetchfile(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) return ret; } +/* + test setfileacl +*/ +static BOOL test_appendacl(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) +{ + struct smb_composite_appendacl **io; + struct smb_composite_appendacl **io_orig; + struct composite_context **c; + struct event_context *event_ctx; + + struct security_descriptor *test_sd; + struct security_ace *ace; + struct dom_sid *test_sid; + + const int num_ops = 50; + int *count = talloc_zero(mem_ctx, int); + struct smb_composite_savefile io1; + + NTSTATUS status; + int i; + + io_orig = talloc_array(mem_ctx, struct smb_composite_appendacl *, num_ops); + + printf ("creating %d empty files and getting their acls with appendacl\n", num_ops); + + for (i = 0; i < num_ops; i++) { + io1.in.fname = talloc_asprintf(io_orig, BASEDIR "\\test%d.txt", i); + io1.in.data = NULL; + io1.in.size = 0; + + status = smb_composite_savefile(cli->tree, &io1); + if (!NT_STATUS_IS_OK(status)) { + printf("savefile failed: %s\n", nt_errstr(status)); + return False; + } + + io_orig[i] = talloc (io_orig, struct smb_composite_appendacl); + io_orig[i]->in.fname = talloc_steal(io_orig[i], io1.in.fname); + io_orig[i]->in.sd = security_descriptor_initialise(io_orig[i]); + status = smb_composite_appendacl(cli->tree, io_orig[i], io_orig[i]); + if (!NT_STATUS_IS_OK(status)) { + printf("appendacl failed: %s\n", nt_errstr(status)); + return False; + } + } + + + /* fill Security Descriptor with aces to be added */ + + test_sd = security_descriptor_initialise(mem_ctx); + test_sid = dom_sid_parse_talloc (mem_ctx, "S-1-5-32-1234-5432"); + + ace = talloc_zero(mem_ctx, struct security_ace); + + ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED; + ace->flags = 0; + ace->access_mask = SEC_STD_ALL; + ace->trustee = *test_sid; + + status = security_descriptor_dacl_add(test_sd, ace); + if (!NT_STATUS_IS_OK(status)) { + printf("appendacl failed: %s\n", nt_errstr(status)); + return False; + } + + /* set parameters for appendacl async call */ + + printf("testing parallel appendacl with %d ops\n", num_ops); + + c = talloc_array(mem_ctx, struct composite_context *, num_ops); + io = talloc_array(mem_ctx, struct smb_composite_appendacl *, num_ops); + + for (i=0; i < num_ops; i++) { + io[i] = talloc (io, struct smb_composite_appendacl); + io[i]->in.sd = test_sd; + io[i]->in.fname = talloc_asprintf(io[i], BASEDIR "\\test%d.txt", i); + + c[i] = smb_composite_appendacl_send(cli->tree, io[i]); + c[i]->async.fn = loadfile_complete; + c[i]->async.private = count; + } + + event_ctx = talloc_reference(mem_ctx, cli->tree->session->transport->socket->event.ctx); + printf("waiting for completion\n"); + while (*count != num_ops) { + event_loop_once(event_ctx); + printf("count=%d\r", *count); + fflush(stdout); + } + printf("count=%d\n", *count); + + for (i=0; i < num_ops; i++) { + struct security_descriptor sd; + + status = smb_composite_appendacl_recv(c[i], io[i]); + if (!NT_STATUS_IS_OK(status)) { + printf("appendacl[%d] failed - %s\n", i, nt_errstr(status)); + return False; + } + + security_descriptor_dacl_add(io_orig[i]->out.sd, ace); + if (!security_acl_equal(io_orig[i]->out.sd->dacl, io[i]->out.sd->dacl)) { + printf("appendacl[%d] failed - needed acl isn't set\n", i); + return False; + } + } + + + talloc_free (ace); + talloc_free (test_sid); + talloc_free (test_sd); + + return True; +} + +/* test a query FS info by asking for share's GUID */ +static BOOL test_fsinfo(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) +{ + char *guid = NULL; + NTSTATUS status; + struct smb_composite_fsinfo io1; + struct composite_context **c; + + int i; + extern int torture_numops; + struct event_context *event_ctx; + int *count = talloc_zero(mem_ctx, int); + BOOL ret = True; + + io1.in.dest_host = lp_parm_string(-1, "torture", "host"); + io1.in.port = 0; + io1.in.called_name = lp_parm_string(-1, "torture", "host"); + io1.in.service = lp_parm_string(-1, "torture", "share"); + io1.in.service_type = "A:"; + io1.in.credentials = cmdline_credentials; + io1.in.workgroup = lp_workgroup(); + io1.in.level = RAW_QFS_OBJECTID_INFORMATION; + + printf("testing parallel queryfsinfo [Object ID] with %d ops\n", torture_numops); + + event_ctx = talloc_reference(mem_ctx, cli->tree->session->transport->socket->event.ctx); + c = talloc_array(mem_ctx, struct composite_context *, torture_numops); + + for (i=0; i<torture_numops; i++) { + c[i] = smb_composite_fsinfo_send(cli->tree,&io1); + c[i]->async.fn = loadfile_complete; + c[i]->async.private = count; + } + + printf("waiting for completion\n"); + + while (*count < torture_numops) { + event_loop_once(event_ctx); + printf("count=%d\r", *count); + fflush(stdout); + } + printf("count=%d\n", *count); + + for (i=0;i<torture_numops;i++) { + status = smb_composite_fsinfo_recv(c[i], mem_ctx); + if (!NT_STATUS_IS_OK(status)) { + printf("fsinfo[%d] failed - %s\n", i, nt_errstr(status)); + ret = False; + continue; + } + + if (io1.out.fsinfo->generic.level != RAW_QFS_OBJECTID_INFORMATION) { + printf("wrong level in returned info - %d " + "should be %d\n", + io1.out.fsinfo->generic.level, RAW_QFS_OBJECTID_INFORMATION); + ret = False; + continue; + } + + guid=GUID_string(mem_ctx, &io1.out.fsinfo->objectid_information.out.guid); + printf("[%d] GUID: %s\n", i, guid); + + + } + + return ret; +} + + /* basic testing of libcli composite calls */ @@ -222,6 +407,8 @@ BOOL torture_raw_composite(void) ret &= test_fetchfile(cli, mem_ctx); ret &= test_loadfile(cli, mem_ctx); + ret &= test_appendacl(cli, mem_ctx); + ret &= test_fsinfo(cli, mem_ctx); smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); |