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