2 #include "libcli/raw/libcliraw.h"
3 #include "libcli/composite/composite.h"
4 #include "libcli/smb_composite/smb_composite.h"
6 /* the stages of this call */
7 enum appendacl_stage {APPENDACL_OPENPATH, APPENDACL_GET,
8 APPENDACL_SET, APPENDACL_GETAGAIN, APPENDACL_CLOSEPATH};
10 static void appendacl_handler(struct smbcli_request *req);
12 struct appendacl_state {
13 enum appendacl_stage stage;
14 struct smb_composite_appendacl *io;
16 union smb_open *io_open;
17 union smb_setfileinfo *io_setfileinfo;
18 union smb_fileinfo *io_fileinfo;
20 struct smbcli_request *req;
24 static NTSTATUS appendacl_open(struct composite_context *c,
25 struct smb_composite_appendacl *io)
27 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
28 struct smbcli_tree *tree = state->req->tree;
31 status = smb_raw_open_recv(state->req, c, state->io_open);
32 NT_STATUS_NOT_OK_RETURN(status);
34 /* setup structures for getting fileinfo */
35 state->io_fileinfo = talloc(c, union smb_fileinfo);
36 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
38 state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
39 state->io_fileinfo->query_secdesc.in.fnum = state->io_open->ntcreatex.out.fnum;
40 state->io_fileinfo->query_secdesc.secinfo_flags = SECINFO_DACL;
42 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
43 NT_STATUS_HAVE_NO_MEMORY(state->req);
46 state->req->async.fn = appendacl_handler;
47 state->req->async.private = c;
48 state->stage = APPENDACL_GET;
50 talloc_free (state->io_open);
55 static NTSTATUS appendacl_get(struct composite_context *c,
56 struct smb_composite_appendacl *io)
58 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
59 struct smbcli_tree *tree = state->req->tree;
63 status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo);
64 NT_STATUS_NOT_OK_RETURN(status);
66 /* setup structures for setting fileinfo */
67 state->io_setfileinfo = talloc(c, union smb_setfileinfo);
68 NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo);
70 state->io_setfileinfo->set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
71 state->io_setfileinfo->set_secdesc.file.fnum = state->io_fileinfo->query_secdesc.in.fnum;
73 state->io_setfileinfo->set_secdesc.in.secinfo_flags = SECINFO_DACL;
74 state->io_setfileinfo->set_secdesc.in.sd = state->io_fileinfo->query_secdesc.out.sd;
75 talloc_steal(state->io_setfileinfo, state->io_setfileinfo->set_secdesc.in.sd);
77 /* append all aces from io->in.sd->dacl to new security descriptor */
78 if (io->in.sd->dacl != NULL) {
79 for (i = 0; i < io->in.sd->dacl->num_aces; i++) {
80 security_descriptor_dacl_add(state->io_setfileinfo->set_secdesc.in.sd,
81 &(io->in.sd->dacl->aces[i]));
85 status = smb_raw_setfileinfo(tree, state->io_setfileinfo);
86 NT_STATUS_NOT_OK_RETURN(status);
88 state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo);
89 NT_STATUS_HAVE_NO_MEMORY(state->req);
91 /* call handler when done setting new security descriptor on file */
92 state->req->async.fn = appendacl_handler;
93 state->req->async.private = c;
94 state->stage = APPENDACL_SET;
96 talloc_free (state->io_fileinfo);
101 static NTSTATUS appendacl_set(struct composite_context *c,
102 struct smb_composite_appendacl *io)
104 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
105 struct smbcli_tree *tree = state->req->tree;
108 status = smbcli_request_simple_recv(state->req);
109 NT_STATUS_NOT_OK_RETURN(status);
111 /* setup structures for getting fileinfo */
112 state->io_fileinfo = talloc(c, union smb_fileinfo);
113 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
116 state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
117 state->io_fileinfo->query_secdesc.in.fnum = state->io_setfileinfo->set_secdesc.file.fnum;
118 state->io_fileinfo->query_secdesc.secinfo_flags = SECINFO_DACL;
120 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
121 NT_STATUS_HAVE_NO_MEMORY(state->req);
123 /* set the handler */
124 state->req->async.fn = appendacl_handler;
125 state->req->async.private = c;
126 state->stage = APPENDACL_GETAGAIN;
128 talloc_free (state->io_setfileinfo);
134 static NTSTATUS appendacl_getagain(struct composite_context *c,
135 struct smb_composite_appendacl *io)
137 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
138 struct smbcli_tree *tree = state->req->tree;
139 union smb_close *io_close;
142 status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo);
143 NT_STATUS_NOT_OK_RETURN(status);
145 io->out.sd = state->io_fileinfo->query_secdesc.out.sd;
147 /* setup structures for close */
148 io_close = talloc(c, union smb_close);
149 NT_STATUS_HAVE_NO_MEMORY(io_close);
151 io_close->close.level = RAW_CLOSE_CLOSE;
152 io_close->close.in.fnum = state->io_fileinfo->query_secdesc.in.fnum;
153 io_close->close.in.write_time = 0;
155 state->req = smb_raw_close_send(tree, io_close);
156 NT_STATUS_HAVE_NO_MEMORY(state->req);
158 /* call the handler */
159 state->req->async.fn = appendacl_handler;
160 state->req->async.private = c;
161 state->stage = APPENDACL_CLOSEPATH;
163 talloc_free (state->io_fileinfo);
170 static NTSTATUS appendacl_close(struct composite_context *c,
171 struct smb_composite_appendacl *io)
173 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
176 status = smbcli_request_simple_recv(state->req);
177 NT_STATUS_NOT_OK_RETURN(status);
179 c->state = COMPOSITE_STATE_DONE;
185 handler for completion of a sub-request in appendacl
187 static void appendacl_handler(struct smbcli_request *req)
189 struct composite_context *c = req->async.private;
190 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
192 /* when this handler is called, the stage indicates what
193 call has just finished */
194 switch (state->stage) {
195 case APPENDACL_OPENPATH:
196 c->status = appendacl_open(c, state->io);
200 c->status = appendacl_get(c, state->io);
204 c->status = appendacl_set(c, state->io);
207 case APPENDACL_GETAGAIN:
208 c->status = appendacl_getagain(c, state->io);
211 case APPENDACL_CLOSEPATH:
212 c->status = appendacl_close(c, state->io);
216 /* We should get here if c->state >= SMBCLI_REQUEST_DONE */
217 if (!NT_STATUS_IS_OK(c->status)) {
218 c->state = COMPOSITE_STATE_ERROR;
221 if (c->state >= COMPOSITE_STATE_DONE &&
229 composite appendacl call - does an open followed by a number setfileinfo,
230 after that new acls are read with fileinfo, followed by a close
232 struct composite_context *smb_composite_appendacl_send(struct smbcli_tree *tree,
233 struct smb_composite_appendacl *io)
235 struct composite_context *c;
236 struct appendacl_state *state;
238 c = talloc_zero(tree, struct composite_context);
239 if (c == NULL) goto failed;
241 state = talloc(c, struct appendacl_state);
242 if (state == NULL) goto failed;
246 c->private_data = state;
247 c->state = COMPOSITE_STATE_IN_PROGRESS;
248 c->event_ctx = tree->session->transport->socket->event.ctx;
250 /* setup structures for opening file */
251 state->io_open = talloc_zero(c, union smb_open);
252 if (state->io_open == NULL) goto failed;
254 state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX;
255 state->io_open->ntcreatex.in.root_fid = 0;
256 state->io_open->ntcreatex.in.flags = 0;
257 state->io_open->ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
258 state->io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
259 state->io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
260 state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
261 state->io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
262 state->io_open->ntcreatex.in.security_flags = 0;
263 state->io_open->ntcreatex.in.fname = io->in.fname;
265 /* send the open on its way */
266 state->req = smb_raw_open_send(tree, state->io_open);
267 if (state->req == NULL) goto failed;
269 /* setup the callback handler */
270 state->req->async.fn = appendacl_handler;
271 state->req->async.private = c;
272 state->stage = APPENDACL_OPENPATH;
283 composite appendacl call - recv side
285 NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
289 status = composite_wait(c);
291 if (NT_STATUS_IS_OK(status)) {
292 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
293 state->io->out.sd = security_descriptor_copy (mem_ctx, state->io->out.sd);
302 composite appendacl call - sync interface
304 NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree,
306 struct smb_composite_appendacl *io)
308 struct composite_context *c = smb_composite_appendacl_send(tree, io);
309 return smb_composite_appendacl_recv(c, mem_ctx);