libsmb: Add cli_create_send/recv
[Samba.git] / source4 / libcli / smb_composite / appendacl.c
blob792ea5a47ebfd823a85b5957fb793ab6b64e7293
1 #include "includes.h"
2 #include "libcli/raw/libcliraw.h"
3 #include "libcli/raw/raw_proto.h"
4 #include "libcli/composite/composite.h"
5 #include "libcli/security/security.h"
6 #include "libcli/smb_composite/smb_composite.h"
8 /* the stages of this call */
9 enum appendacl_stage {APPENDACL_OPENPATH, APPENDACL_GET,
10 APPENDACL_SET, APPENDACL_GETAGAIN, APPENDACL_CLOSEPATH};
12 static void appendacl_handler(struct smbcli_request *req);
14 struct appendacl_state {
15 enum appendacl_stage stage;
16 struct smb_composite_appendacl *io;
18 union smb_open *io_open;
19 union smb_setfileinfo *io_setfileinfo;
20 union smb_fileinfo *io_fileinfo;
22 struct smbcli_request *req;
26 static NTSTATUS appendacl_open(struct composite_context *c,
27 struct smb_composite_appendacl *io)
29 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
30 struct smbcli_tree *tree = state->req->tree;
31 NTSTATUS status;
33 status = smb_raw_open_recv(state->req, c, state->io_open);
34 NT_STATUS_NOT_OK_RETURN(status);
36 /* setup structures for getting fileinfo */
37 state->io_fileinfo = talloc(c, union smb_fileinfo);
38 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
40 state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
41 state->io_fileinfo->query_secdesc.in.file.fnum = state->io_open->ntcreatex.out.file.fnum;
42 state->io_fileinfo->query_secdesc.in.secinfo_flags = SECINFO_DACL;
44 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
45 NT_STATUS_HAVE_NO_MEMORY(state->req);
47 /* set the handler */
48 state->req->async.fn = appendacl_handler;
49 state->req->async.private_data = c;
50 state->stage = APPENDACL_GET;
52 talloc_free (state->io_open);
54 return NT_STATUS_OK;
57 static NTSTATUS appendacl_get(struct composite_context *c,
58 struct smb_composite_appendacl *io)
60 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
61 struct smbcli_tree *tree = state->req->tree;
62 int i;
63 NTSTATUS status;
65 status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo);
66 NT_STATUS_NOT_OK_RETURN(status);
68 /* setup structures for setting fileinfo */
69 state->io_setfileinfo = talloc(c, union smb_setfileinfo);
70 NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo);
72 state->io_setfileinfo->set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
73 state->io_setfileinfo->set_secdesc.in.file.fnum = state->io_fileinfo->query_secdesc.in.file.fnum;
75 state->io_setfileinfo->set_secdesc.in.secinfo_flags = SECINFO_DACL;
76 state->io_setfileinfo->set_secdesc.in.sd = state->io_fileinfo->query_secdesc.out.sd;
77 talloc_steal(state->io_setfileinfo, state->io_setfileinfo->set_secdesc.in.sd);
79 /* append all aces from io->in.sd->dacl to new security descriptor */
80 if (io->in.sd->dacl != NULL) {
81 for (i = 0; i < io->in.sd->dacl->num_aces; i++) {
82 security_descriptor_dacl_add(state->io_setfileinfo->set_secdesc.in.sd,
83 &(io->in.sd->dacl->aces[i]));
87 status = smb_raw_setfileinfo(tree, state->io_setfileinfo);
88 NT_STATUS_NOT_OK_RETURN(status);
90 state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo);
91 NT_STATUS_HAVE_NO_MEMORY(state->req);
93 /* call handler when done setting new security descriptor on file */
94 state->req->async.fn = appendacl_handler;
95 state->req->async.private_data = c;
96 state->stage = APPENDACL_SET;
98 talloc_free (state->io_fileinfo);
100 return NT_STATUS_OK;
103 static NTSTATUS appendacl_set(struct composite_context *c,
104 struct smb_composite_appendacl *io)
106 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
107 struct smbcli_tree *tree = state->req->tree;
108 NTSTATUS status;
110 status = smbcli_request_simple_recv(state->req);
111 NT_STATUS_NOT_OK_RETURN(status);
113 /* setup structures for getting fileinfo */
114 state->io_fileinfo = talloc(c, union smb_fileinfo);
115 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
118 state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
119 state->io_fileinfo->query_secdesc.in.file.fnum = state->io_setfileinfo->set_secdesc.in.file.fnum;
120 state->io_fileinfo->query_secdesc.in.secinfo_flags = SECINFO_DACL;
122 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
123 NT_STATUS_HAVE_NO_MEMORY(state->req);
125 /* set the handler */
126 state->req->async.fn = appendacl_handler;
127 state->req->async.private_data = c;
128 state->stage = APPENDACL_GETAGAIN;
130 talloc_free (state->io_setfileinfo);
132 return NT_STATUS_OK;
136 static NTSTATUS appendacl_getagain(struct composite_context *c,
137 struct smb_composite_appendacl *io)
139 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
140 struct smbcli_tree *tree = state->req->tree;
141 union smb_close *io_close;
142 NTSTATUS status;
144 status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo);
145 NT_STATUS_NOT_OK_RETURN(status);
147 io->out.sd = state->io_fileinfo->query_secdesc.out.sd;
149 /* setup structures for close */
150 io_close = talloc(c, union smb_close);
151 NT_STATUS_HAVE_NO_MEMORY(io_close);
153 io_close->close.level = RAW_CLOSE_CLOSE;
154 io_close->close.in.file.fnum = state->io_fileinfo->query_secdesc.in.file.fnum;
155 io_close->close.in.write_time = 0;
157 state->req = smb_raw_close_send(tree, io_close);
158 NT_STATUS_HAVE_NO_MEMORY(state->req);
160 /* call the handler */
161 state->req->async.fn = appendacl_handler;
162 state->req->async.private_data = c;
163 state->stage = APPENDACL_CLOSEPATH;
165 talloc_free (state->io_fileinfo);
167 return NT_STATUS_OK;
172 static NTSTATUS appendacl_close(struct composite_context *c,
173 struct smb_composite_appendacl *io)
175 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
176 NTSTATUS status;
178 status = smbcli_request_simple_recv(state->req);
179 NT_STATUS_NOT_OK_RETURN(status);
181 c->state = COMPOSITE_STATE_DONE;
183 return NT_STATUS_OK;
187 handler for completion of a sub-request in appendacl
189 static void appendacl_handler(struct smbcli_request *req)
191 struct composite_context *c = (struct composite_context *)req->async.private_data;
192 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
194 /* when this handler is called, the stage indicates what
195 call has just finished */
196 switch (state->stage) {
197 case APPENDACL_OPENPATH:
198 c->status = appendacl_open(c, state->io);
199 break;
201 case APPENDACL_GET:
202 c->status = appendacl_get(c, state->io);
203 break;
205 case APPENDACL_SET:
206 c->status = appendacl_set(c, state->io);
207 break;
209 case APPENDACL_GETAGAIN:
210 c->status = appendacl_getagain(c, state->io);
211 break;
213 case APPENDACL_CLOSEPATH:
214 c->status = appendacl_close(c, state->io);
215 break;
218 /* We should get here if c->state >= SMBCLI_REQUEST_DONE */
219 if (!NT_STATUS_IS_OK(c->status)) {
220 c->state = COMPOSITE_STATE_ERROR;
223 if (c->state >= COMPOSITE_STATE_DONE &&
224 c->async.fn) {
225 c->async.fn(c);
231 composite appendacl call - does an open followed by a number setfileinfo,
232 after that new acls are read with fileinfo, followed by a close
234 struct composite_context *smb_composite_appendacl_send(struct smbcli_tree *tree,
235 struct smb_composite_appendacl *io)
237 struct composite_context *c;
238 struct appendacl_state *state;
240 c = talloc_zero(tree, struct composite_context);
241 if (c == NULL) goto failed;
243 state = talloc(c, struct appendacl_state);
244 if (state == NULL) goto failed;
246 state->io = io;
248 c->private_data = state;
249 c->state = COMPOSITE_STATE_IN_PROGRESS;
250 c->event_ctx = tree->session->transport->ev;
252 /* setup structures for opening file */
253 state->io_open = talloc_zero(c, union smb_open);
254 if (state->io_open == NULL) goto failed;
256 state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX;
257 state->io_open->ntcreatex.in.root_fid.fnum = 0;
258 state->io_open->ntcreatex.in.flags = 0;
259 state->io_open->ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
260 state->io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
261 state->io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
262 state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
263 state->io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
264 state->io_open->ntcreatex.in.security_flags = 0;
265 state->io_open->ntcreatex.in.fname = io->in.fname;
267 /* send the open on its way */
268 state->req = smb_raw_open_send(tree, state->io_open);
269 if (state->req == NULL) goto failed;
271 /* setup the callback handler */
272 state->req->async.fn = appendacl_handler;
273 state->req->async.private_data = c;
274 state->stage = APPENDACL_OPENPATH;
276 return c;
278 failed:
279 talloc_free(c);
280 return NULL;
285 composite appendacl call - recv side
287 NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
289 NTSTATUS status;
291 status = composite_wait(c);
293 if (NT_STATUS_IS_OK(status)) {
294 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
295 state->io->out.sd = security_descriptor_copy (mem_ctx, state->io->out.sd);
298 talloc_free(c);
299 return status;
304 composite appendacl call - sync interface
306 NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree,
307 TALLOC_CTX *mem_ctx,
308 struct smb_composite_appendacl *io)
310 struct composite_context *c = smb_composite_appendacl_send(tree, io);
311 return smb_composite_appendacl_recv(c, mem_ctx);