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"
7
8 /* the stages of this call */
9 enum appendacl_stage {APPENDACL_OPENPATH, APPENDACL_GET,
10 APPENDACL_SET, APPENDACL_GETAGAIN, APPENDACL_CLOSEPATH};
11
12 static void appendacl_handler(struct smbcli_request *req);
13
14 struct appendacl_state {
15 enum appendacl_stage stage;
16 struct smb_composite_appendacl *io;
17
18 union smb_open *io_open;
19 union smb_setfileinfo *io_setfileinfo;
20 union smb_fileinfo *io_fileinfo;
21
22 struct smbcli_request *req;
23 };
24
25
appendacl_open(struct composite_context * c,struct smb_composite_appendacl * io)26 static NTSTATUS appendacl_open(struct composite_context *c,
27 struct smb_composite_appendacl *io)
28 {
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;
32
33 status = smb_raw_open_recv(state->req, c, state->io_open);
34 NT_STATUS_NOT_OK_RETURN(status);
35
36 /* setup structures for getting fileinfo */
37 state->io_fileinfo = talloc(c, union smb_fileinfo);
38 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
39
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;
43
44 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
45 NT_STATUS_HAVE_NO_MEMORY(state->req);
46
47 /* set the handler */
48 state->req->async.fn = appendacl_handler;
49 state->req->async.private_data = c;
50 state->stage = APPENDACL_GET;
51
52 talloc_free (state->io_open);
53
54 return NT_STATUS_OK;
55 }
56
appendacl_get(struct composite_context * c,struct smb_composite_appendacl * io)57 static NTSTATUS appendacl_get(struct composite_context *c,
58 struct smb_composite_appendacl *io)
59 {
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;
64
65 status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo);
66 NT_STATUS_NOT_OK_RETURN(status);
67
68 /* setup structures for setting fileinfo */
69 state->io_setfileinfo = talloc(c, union smb_setfileinfo);
70 NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo);
71
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;
74
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);
78
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]));
84 }
85 }
86
87 status = smb_raw_setfileinfo(tree, state->io_setfileinfo);
88 NT_STATUS_NOT_OK_RETURN(status);
89
90 state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo);
91 NT_STATUS_HAVE_NO_MEMORY(state->req);
92
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;
97
98 talloc_free (state->io_fileinfo);
99
100 return NT_STATUS_OK;
101 }
102
appendacl_set(struct composite_context * c,struct smb_composite_appendacl * io)103 static NTSTATUS appendacl_set(struct composite_context *c,
104 struct smb_composite_appendacl *io)
105 {
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;
109
110 status = smbcli_request_simple_recv(state->req);
111 NT_STATUS_NOT_OK_RETURN(status);
112
113 /* setup structures for getting fileinfo */
114 state->io_fileinfo = talloc(c, union smb_fileinfo);
115 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
116
117
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;
121
122 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
123 NT_STATUS_HAVE_NO_MEMORY(state->req);
124
125 /* set the handler */
126 state->req->async.fn = appendacl_handler;
127 state->req->async.private_data = c;
128 state->stage = APPENDACL_GETAGAIN;
129
130 talloc_free (state->io_setfileinfo);
131
132 return NT_STATUS_OK;
133 }
134
135
appendacl_getagain(struct composite_context * c,struct smb_composite_appendacl * io)136 static NTSTATUS appendacl_getagain(struct composite_context *c,
137 struct smb_composite_appendacl *io)
138 {
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;
143
144 status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo);
145 NT_STATUS_NOT_OK_RETURN(status);
146
147 io->out.sd = state->io_fileinfo->query_secdesc.out.sd;
148
149 /* setup structures for close */
150 io_close = talloc(c, union smb_close);
151 NT_STATUS_HAVE_NO_MEMORY(io_close);
152
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;
156
157 state->req = smb_raw_close_send(tree, io_close);
158 NT_STATUS_HAVE_NO_MEMORY(state->req);
159
160 /* call the handler */
161 state->req->async.fn = appendacl_handler;
162 state->req->async.private_data = c;
163 state->stage = APPENDACL_CLOSEPATH;
164
165 talloc_free (state->io_fileinfo);
166
167 return NT_STATUS_OK;
168 }
169
170
171
appendacl_close(struct composite_context * c,struct smb_composite_appendacl * io)172 static NTSTATUS appendacl_close(struct composite_context *c,
173 struct smb_composite_appendacl *io)
174 {
175 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
176 NTSTATUS status;
177
178 status = smbcli_request_simple_recv(state->req);
179 NT_STATUS_NOT_OK_RETURN(status);
180
181 c->state = COMPOSITE_STATE_DONE;
182
183 return NT_STATUS_OK;
184 }
185
186 /*
187 handler for completion of a sub-request in appendacl
188 */
appendacl_handler(struct smbcli_request * req)189 static void appendacl_handler(struct smbcli_request *req)
190 {
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);
193
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;
200
201 case APPENDACL_GET:
202 c->status = appendacl_get(c, state->io);
203 break;
204
205 case APPENDACL_SET:
206 c->status = appendacl_set(c, state->io);
207 break;
208
209 case APPENDACL_GETAGAIN:
210 c->status = appendacl_getagain(c, state->io);
211 break;
212
213 case APPENDACL_CLOSEPATH:
214 c->status = appendacl_close(c, state->io);
215 break;
216 }
217
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;
221 }
222
223 if (c->state >= COMPOSITE_STATE_DONE &&
224 c->async.fn) {
225 c->async.fn(c);
226 }
227 }
228
229
230 /*
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
233 */
smb_composite_appendacl_send(struct smbcli_tree * tree,struct smb_composite_appendacl * io)234 struct composite_context *smb_composite_appendacl_send(struct smbcli_tree *tree,
235 struct smb_composite_appendacl *io)
236 {
237 struct composite_context *c;
238 struct appendacl_state *state;
239
240 c = talloc_zero(tree, struct composite_context);
241 if (c == NULL) goto failed;
242
243 state = talloc(c, struct appendacl_state);
244 if (state == NULL) goto failed;
245
246 state->io = io;
247
248 c->private_data = state;
249 c->state = COMPOSITE_STATE_IN_PROGRESS;
250 c->event_ctx = tree->session->transport->ev;
251
252 /* setup structures for opening file */
253 state->io_open = talloc_zero(c, union smb_open);
254 if (state->io_open == NULL) goto failed;
255
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;
266
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;
270
271 /* setup the callback handler */
272 state->req->async.fn = appendacl_handler;
273 state->req->async.private_data = c;
274 state->stage = APPENDACL_OPENPATH;
275
276 return c;
277
278 failed:
279 talloc_free(c);
280 return NULL;
281 }
282
283
284 /*
285 composite appendacl call - recv side
286 */
smb_composite_appendacl_recv(struct composite_context * c,TALLOC_CTX * mem_ctx)287 NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
288 {
289 NTSTATUS status;
290
291 status = composite_wait(c);
292
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);
296 }
297
298 talloc_free(c);
299 return status;
300 }
301
302
303 /*
304 composite appendacl call - sync interface
305 */
smb_composite_appendacl(struct smbcli_tree * tree,TALLOC_CTX * mem_ctx,struct smb_composite_appendacl * io)306 NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree,
307 TALLOC_CTX *mem_ctx,
308 struct smb_composite_appendacl *io)
309 {
310 struct composite_context *c = smb_composite_appendacl_send(tree, io);
311 return smb_composite_appendacl_recv(c, mem_ctx);
312 }
313
314