2 #include "libcli/raw/libcliraw.h"
3 #include "libcli/composite/composite.h"
4 #include "libcli/security/proto.h"
5 #include "libcli/smb_composite/smb_composite.h"
7 /* the stages of this call */
8 enum appendacl_stage {APPENDACL_OPENPATH, APPENDACL_GET,
9 APPENDACL_SET, APPENDACL_GETAGAIN, APPENDACL_CLOSEPATH};
11 static void appendacl_handler(struct smbcli_request *req);
13 struct appendacl_state {
14 enum appendacl_stage stage;
15 struct smb_composite_appendacl *io;
17 union smb_open *io_open;
18 union smb_setfileinfo *io_setfileinfo;
19 union smb_fileinfo *io_fileinfo;
21 struct smbcli_request *req;
25 static NTSTATUS appendacl_open(struct composite_context *c,
26 struct smb_composite_appendacl *io)
28 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
29 struct smbcli_tree *tree = state->req->tree;
32 status = smb_raw_open_recv(state->req, c, state->io_open);
33 NT_STATUS_NOT_OK_RETURN(status);
35 /* setup structures for getting fileinfo */
36 state->io_fileinfo = talloc(c, union smb_fileinfo);
37 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
39 state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
40 state->io_fileinfo->query_secdesc.file.fnum = state->io_open->ntcreatex.file.fnum;
41 state->io_fileinfo->query_secdesc.in.secinfo_flags = SECINFO_DACL;
43 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
44 NT_STATUS_HAVE_NO_MEMORY(state->req);
47 state->req->async.fn = appendacl_handler;
48 state->req->async.private = c;
49 state->stage = APPENDACL_GET;
51 talloc_free (state->io_open);
56 static NTSTATUS appendacl_get(struct composite_context *c,
57 struct smb_composite_appendacl *io)
59 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
60 struct smbcli_tree *tree = state->req->tree;
64 status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo);
65 NT_STATUS_NOT_OK_RETURN(status);
67 /* setup structures for setting fileinfo */
68 state->io_setfileinfo = talloc(c, union smb_setfileinfo);
69 NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo);
71 state->io_setfileinfo->set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
72 state->io_setfileinfo->set_secdesc.file.fnum = state->io_fileinfo->query_secdesc.file.fnum;
74 state->io_setfileinfo->set_secdesc.in.secinfo_flags = SECINFO_DACL;
75 state->io_setfileinfo->set_secdesc.in.sd = state->io_fileinfo->query_secdesc.out.sd;
76 talloc_steal(state->io_setfileinfo, state->io_setfileinfo->set_secdesc.in.sd);
78 /* append all aces from io->in.sd->dacl to new security descriptor */
79 if (io->in.sd->dacl != NULL) {
80 for (i = 0; i < io->in.sd->dacl->num_aces; i++) {
81 security_descriptor_dacl_add(state->io_setfileinfo->set_secdesc.in.sd,
82 &(io->in.sd->dacl->aces[i]));
86 status = smb_raw_setfileinfo(tree, state->io_setfileinfo);
87 NT_STATUS_NOT_OK_RETURN(status);
89 state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo);
90 NT_STATUS_HAVE_NO_MEMORY(state->req);
92 /* call handler when done setting new security descriptor on file */
93 state->req->async.fn = appendacl_handler;
94 state->req->async.private = c;
95 state->stage = APPENDACL_SET;
97 talloc_free (state->io_fileinfo);
102 static NTSTATUS appendacl_set(struct composite_context *c,
103 struct smb_composite_appendacl *io)
105 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
106 struct smbcli_tree *tree = state->req->tree;
109 status = smbcli_request_simple_recv(state->req);
110 NT_STATUS_NOT_OK_RETURN(status);
112 /* setup structures for getting fileinfo */
113 state->io_fileinfo = talloc(c, union smb_fileinfo);
114 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
117 state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
118 state->io_fileinfo->query_secdesc.file.fnum = state->io_setfileinfo->set_secdesc.file.fnum;
119 state->io_fileinfo->query_secdesc.in.secinfo_flags = SECINFO_DACL;
121 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
122 NT_STATUS_HAVE_NO_MEMORY(state->req);
124 /* set the handler */
125 state->req->async.fn = appendacl_handler;
126 state->req->async.private = c;
127 state->stage = APPENDACL_GETAGAIN;
129 talloc_free (state->io_setfileinfo);
135 static NTSTATUS appendacl_getagain(struct composite_context *c,
136 struct smb_composite_appendacl *io)
138 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
139 struct smbcli_tree *tree = state->req->tree;
140 union smb_close *io_close;
143 status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo);
144 NT_STATUS_NOT_OK_RETURN(status);
146 io->out.sd = state->io_fileinfo->query_secdesc.out.sd;
148 /* setup structures for close */
149 io_close = talloc(c, union smb_close);
150 NT_STATUS_HAVE_NO_MEMORY(io_close);
152 io_close->close.level = RAW_CLOSE_CLOSE;
153 io_close->close.file.fnum = state->io_fileinfo->query_secdesc.file.fnum;
154 io_close->close.in.write_time = 0;
156 state->req = smb_raw_close_send(tree, io_close);
157 NT_STATUS_HAVE_NO_MEMORY(state->req);
159 /* call the handler */
160 state->req->async.fn = appendacl_handler;
161 state->req->async.private = c;
162 state->stage = APPENDACL_CLOSEPATH;
164 talloc_free (state->io_fileinfo);
171 static NTSTATUS appendacl_close(struct composite_context *c,
172 struct smb_composite_appendacl *io)
174 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
177 status = smbcli_request_simple_recv(state->req);
178 NT_STATUS_NOT_OK_RETURN(status);
180 c->state = COMPOSITE_STATE_DONE;
186 handler for completion of a sub-request in appendacl
188 static void appendacl_handler(struct smbcli_request *req)
190 struct composite_context *c = req->async.private;
191 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
193 /* when this handler is called, the stage indicates what
194 call has just finished */
195 switch (state->stage) {
196 case APPENDACL_OPENPATH:
197 c->status = appendacl_open(c, state->io);
201 c->status = appendacl_get(c, state->io);
205 c->status = appendacl_set(c, state->io);
208 case APPENDACL_GETAGAIN:
209 c->status = appendacl_getagain(c, state->io);
212 case APPENDACL_CLOSEPATH:
213 c->status = appendacl_close(c, state->io);
217 /* We should get here if c->state >= SMBCLI_REQUEST_DONE */
218 if (!NT_STATUS_IS_OK(c->status)) {
219 c->state = COMPOSITE_STATE_ERROR;
222 if (c->state >= COMPOSITE_STATE_DONE &&
230 composite appendacl call - does an open followed by a number setfileinfo,
231 after that new acls are read with fileinfo, followed by a close
233 struct composite_context *smb_composite_appendacl_send(struct smbcli_tree *tree,
234 struct smb_composite_appendacl *io)
236 struct composite_context *c;
237 struct appendacl_state *state;
239 c = talloc_zero(tree, struct composite_context);
240 if (c == NULL) goto failed;
242 state = talloc(c, struct appendacl_state);
243 if (state == NULL) goto failed;
247 c->private_data = state;
248 c->state = COMPOSITE_STATE_IN_PROGRESS;
249 c->event_ctx = tree->session->transport->socket->event.ctx;
251 /* setup structures for opening file */
252 state->io_open = talloc_zero(c, union smb_open);
253 if (state->io_open == NULL) goto failed;
255 state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX;
256 state->io_open->ntcreatex.in.root_fid = 0;
257 state->io_open->ntcreatex.in.flags = 0;
258 state->io_open->ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
259 state->io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
260 state->io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
261 state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
262 state->io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
263 state->io_open->ntcreatex.in.security_flags = 0;
264 state->io_open->ntcreatex.in.fname = io->in.fname;
266 /* send the open on its way */
267 state->req = smb_raw_open_send(tree, state->io_open);
268 if (state->req == NULL) goto failed;
270 /* setup the callback handler */
271 state->req->async.fn = appendacl_handler;
272 state->req->async.private = c;
273 state->stage = APPENDACL_OPENPATH;
284 composite appendacl call - recv side
286 NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
290 status = composite_wait(c);
292 if (NT_STATUS_IS_OK(status)) {
293 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
294 state->io->out.sd = security_descriptor_copy (mem_ctx, state->io->out.sd);
303 composite appendacl call - sync interface
305 NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree,
307 struct smb_composite_appendacl *io)
309 struct composite_context *c = smb_composite_appendacl_send(tree, io);
310 return smb_composite_appendacl_recv(c, mem_ctx);