Line data Source code
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 :
26 100 : static NTSTATUS appendacl_open(struct composite_context *c,
27 : struct smb_composite_appendacl *io)
28 : {
29 100 : struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
30 100 : struct smbcli_tree *tree = state->req->tree;
31 : NTSTATUS status;
32 :
33 100 : status = smb_raw_open_recv(state->req, c, state->io_open);
34 100 : NT_STATUS_NOT_OK_RETURN(status);
35 :
36 : /* setup structures for getting fileinfo */
37 100 : state->io_fileinfo = talloc(c, union smb_fileinfo);
38 100 : NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
39 :
40 100 : state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
41 100 : state->io_fileinfo->query_secdesc.in.file.fnum = state->io_open->ntcreatex.out.file.fnum;
42 100 : state->io_fileinfo->query_secdesc.in.secinfo_flags = SECINFO_DACL;
43 :
44 100 : state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
45 100 : NT_STATUS_HAVE_NO_MEMORY(state->req);
46 :
47 : /* set the handler */
48 100 : state->req->async.fn = appendacl_handler;
49 100 : state->req->async.private_data = c;
50 100 : state->stage = APPENDACL_GET;
51 :
52 100 : talloc_free (state->io_open);
53 :
54 100 : return NT_STATUS_OK;
55 : }
56 :
57 100 : static NTSTATUS appendacl_get(struct composite_context *c,
58 : struct smb_composite_appendacl *io)
59 : {
60 100 : struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
61 100 : struct smbcli_tree *tree = state->req->tree;
62 : NTSTATUS status;
63 :
64 100 : status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo);
65 100 : NT_STATUS_NOT_OK_RETURN(status);
66 :
67 : /* setup structures for setting fileinfo */
68 100 : state->io_setfileinfo = talloc(c, union smb_setfileinfo);
69 100 : NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo);
70 :
71 100 : state->io_setfileinfo->set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
72 100 : state->io_setfileinfo->set_secdesc.in.file.fnum = state->io_fileinfo->query_secdesc.in.file.fnum;
73 :
74 100 : state->io_setfileinfo->set_secdesc.in.secinfo_flags = SECINFO_DACL;
75 100 : state->io_setfileinfo->set_secdesc.in.sd = state->io_fileinfo->query_secdesc.out.sd;
76 100 : talloc_steal(state->io_setfileinfo, state->io_setfileinfo->set_secdesc.in.sd);
77 :
78 : /* append all aces from io->in.sd->dacl to new security descriptor */
79 100 : if (io->in.sd->dacl != NULL) {
80 : uint32_t i;
81 100 : for (i = 0; i < io->in.sd->dacl->num_aces; i++) {
82 50 : security_descriptor_dacl_add(state->io_setfileinfo->set_secdesc.in.sd,
83 50 : &(io->in.sd->dacl->aces[i]));
84 : }
85 : }
86 :
87 100 : status = smb_raw_setfileinfo(tree, state->io_setfileinfo);
88 100 : NT_STATUS_NOT_OK_RETURN(status);
89 :
90 100 : state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo);
91 100 : NT_STATUS_HAVE_NO_MEMORY(state->req);
92 :
93 : /* call handler when done setting new security descriptor on file */
94 100 : state->req->async.fn = appendacl_handler;
95 100 : state->req->async.private_data = c;
96 100 : state->stage = APPENDACL_SET;
97 :
98 100 : talloc_free (state->io_fileinfo);
99 :
100 100 : return NT_STATUS_OK;
101 : }
102 :
103 100 : static NTSTATUS appendacl_set(struct composite_context *c,
104 : struct smb_composite_appendacl *io)
105 : {
106 100 : struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
107 100 : struct smbcli_tree *tree = state->req->tree;
108 : NTSTATUS status;
109 :
110 100 : status = smbcli_request_simple_recv(state->req);
111 100 : NT_STATUS_NOT_OK_RETURN(status);
112 :
113 : /* setup structures for getting fileinfo */
114 100 : state->io_fileinfo = talloc(c, union smb_fileinfo);
115 100 : NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
116 :
117 :
118 100 : state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
119 100 : state->io_fileinfo->query_secdesc.in.file.fnum = state->io_setfileinfo->set_secdesc.in.file.fnum;
120 100 : state->io_fileinfo->query_secdesc.in.secinfo_flags = SECINFO_DACL;
121 :
122 100 : state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
123 100 : NT_STATUS_HAVE_NO_MEMORY(state->req);
124 :
125 : /* set the handler */
126 100 : state->req->async.fn = appendacl_handler;
127 100 : state->req->async.private_data = c;
128 100 : state->stage = APPENDACL_GETAGAIN;
129 :
130 100 : talloc_free (state->io_setfileinfo);
131 :
132 100 : return NT_STATUS_OK;
133 : }
134 :
135 :
136 100 : static NTSTATUS appendacl_getagain(struct composite_context *c,
137 : struct smb_composite_appendacl *io)
138 : {
139 100 : struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
140 100 : struct smbcli_tree *tree = state->req->tree;
141 : union smb_close *io_close;
142 : NTSTATUS status;
143 :
144 100 : status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo);
145 100 : NT_STATUS_NOT_OK_RETURN(status);
146 :
147 100 : io->out.sd = state->io_fileinfo->query_secdesc.out.sd;
148 :
149 : /* setup structures for close */
150 100 : io_close = talloc(c, union smb_close);
151 100 : NT_STATUS_HAVE_NO_MEMORY(io_close);
152 :
153 100 : io_close->close.level = RAW_CLOSE_CLOSE;
154 100 : io_close->close.in.file.fnum = state->io_fileinfo->query_secdesc.in.file.fnum;
155 100 : io_close->close.in.write_time = 0;
156 :
157 100 : state->req = smb_raw_close_send(tree, io_close);
158 100 : NT_STATUS_HAVE_NO_MEMORY(state->req);
159 :
160 : /* call the handler */
161 100 : state->req->async.fn = appendacl_handler;
162 100 : state->req->async.private_data = c;
163 100 : state->stage = APPENDACL_CLOSEPATH;
164 :
165 100 : talloc_free (state->io_fileinfo);
166 :
167 100 : return NT_STATUS_OK;
168 : }
169 :
170 :
171 :
172 100 : static NTSTATUS appendacl_close(struct composite_context *c,
173 : struct smb_composite_appendacl *io)
174 : {
175 100 : struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
176 : NTSTATUS status;
177 :
178 100 : status = smbcli_request_simple_recv(state->req);
179 100 : NT_STATUS_NOT_OK_RETURN(status);
180 :
181 100 : c->state = COMPOSITE_STATE_DONE;
182 :
183 100 : return NT_STATUS_OK;
184 : }
185 :
186 : /*
187 : handler for completion of a sub-request in appendacl
188 : */
189 500 : static void appendacl_handler(struct smbcli_request *req)
190 : {
191 500 : struct composite_context *c = (struct composite_context *)req->async.private_data;
192 500 : 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 500 : switch (state->stage) {
197 100 : case APPENDACL_OPENPATH:
198 100 : c->status = appendacl_open(c, state->io);
199 100 : break;
200 :
201 100 : case APPENDACL_GET:
202 100 : c->status = appendacl_get(c, state->io);
203 100 : break;
204 :
205 100 : case APPENDACL_SET:
206 100 : c->status = appendacl_set(c, state->io);
207 100 : break;
208 :
209 100 : case APPENDACL_GETAGAIN:
210 100 : c->status = appendacl_getagain(c, state->io);
211 100 : break;
212 :
213 100 : case APPENDACL_CLOSEPATH:
214 100 : c->status = appendacl_close(c, state->io);
215 100 : break;
216 : }
217 :
218 : /* We should get here if c->state >= SMBCLI_REQUEST_DONE */
219 500 : if (!NT_STATUS_IS_OK(c->status)) {
220 0 : c->state = COMPOSITE_STATE_ERROR;
221 : }
222 :
223 600 : if (c->state >= COMPOSITE_STATE_DONE &&
224 100 : c->async.fn) {
225 50 : c->async.fn(c);
226 : }
227 500 : }
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 : */
234 100 : 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 100 : c = talloc_zero(tree, struct composite_context);
241 100 : if (c == NULL) goto failed;
242 :
243 100 : state = talloc(c, struct appendacl_state);
244 100 : if (state == NULL) goto failed;
245 :
246 100 : state->io = io;
247 :
248 100 : c->private_data = state;
249 100 : c->state = COMPOSITE_STATE_IN_PROGRESS;
250 100 : c->event_ctx = tree->session->transport->ev;
251 :
252 : /* setup structures for opening file */
253 100 : state->io_open = talloc_zero(c, union smb_open);
254 100 : if (state->io_open == NULL) goto failed;
255 :
256 100 : state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX;
257 100 : state->io_open->ntcreatex.in.root_fid.fnum = 0;
258 100 : state->io_open->ntcreatex.in.flags = 0;
259 100 : state->io_open->ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
260 100 : state->io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
261 100 : state->io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
262 100 : state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
263 100 : state->io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
264 100 : state->io_open->ntcreatex.in.security_flags = 0;
265 100 : state->io_open->ntcreatex.in.fname = io->in.fname;
266 :
267 : /* send the open on its way */
268 100 : state->req = smb_raw_open_send(tree, state->io_open);
269 100 : if (state->req == NULL) goto failed;
270 :
271 : /* setup the callback handler */
272 100 : state->req->async.fn = appendacl_handler;
273 100 : state->req->async.private_data = c;
274 100 : state->stage = APPENDACL_OPENPATH;
275 :
276 100 : return c;
277 :
278 0 : failed:
279 0 : talloc_free(c);
280 0 : return NULL;
281 : }
282 :
283 :
284 : /*
285 : composite appendacl call - recv side
286 : */
287 100 : NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
288 : {
289 : NTSTATUS status;
290 :
291 100 : status = composite_wait(c);
292 :
293 100 : if (NT_STATUS_IS_OK(status)) {
294 100 : struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
295 100 : state->io->out.sd = security_descriptor_copy (mem_ctx, state->io->out.sd);
296 : }
297 :
298 100 : talloc_free(c);
299 100 : return status;
300 : }
301 :
302 :
303 : /*
304 : composite appendacl call - sync interface
305 : */
306 50 : NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree,
307 : TALLOC_CTX *mem_ctx,
308 : struct smb_composite_appendacl *io)
309 : {
310 50 : struct composite_context *c = smb_composite_appendacl_send(tree, io);
311 50 : return smb_composite_appendacl_recv(c, mem_ctx);
312 : }
313 :
|