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