Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : client security descriptor functions
4 : Copyright (C) Andrew Tridgell 2000
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "libsmb/libsmb.h"
22 : #include "../libcli/security/secdesc.h"
23 : #include "../libcli/smb/smbXcli_base.h"
24 : #include "lib/util/tevent_ntstatus.h"
25 :
26 : struct cli_query_security_descriptor_state {
27 : uint8_t param[8];
28 : DATA_BLOB outbuf;
29 : };
30 :
31 : static void cli_query_security_descriptor_done1(struct tevent_req *subreq);
32 : static void cli_query_security_descriptor_done2(struct tevent_req *subreq);
33 :
34 3508 : struct tevent_req *cli_query_security_descriptor_send(
35 : TALLOC_CTX *mem_ctx,
36 : struct tevent_context *ev,
37 : struct cli_state *cli,
38 : uint16_t fnum,
39 : uint32_t sec_info)
40 : {
41 3508 : struct tevent_req *req = NULL, *subreq = NULL;
42 3508 : struct cli_query_security_descriptor_state *state = NULL;
43 :
44 3508 : req = tevent_req_create(
45 : mem_ctx, &state, struct cli_query_security_descriptor_state);
46 3508 : if (req == NULL) {
47 0 : return NULL;
48 : }
49 :
50 3508 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
51 3442 : subreq = cli_smb2_query_info_fnum_send(
52 : state, /* mem_ctx */
53 : ev, /* ev */
54 : cli, /* cli */
55 : fnum, /* fnum */
56 : 3, /* in_info_type */
57 : 0, /* in_info_class */
58 : 0xFFFF, /* in_max_output_length */
59 : NULL, /* in_input_buffer */
60 : sec_info, /* in_additional_info */
61 : 0); /* in_flags */
62 3442 : if (tevent_req_nomem(subreq, req)) {
63 0 : return tevent_req_post(req, ev);
64 : }
65 3442 : tevent_req_set_callback(
66 : subreq, cli_query_security_descriptor_done2, req);
67 3442 : return req;
68 : }
69 :
70 66 : PUSH_LE_U32(state->param, 0, fnum);
71 66 : PUSH_LE_U32(state->param, 4, sec_info);
72 :
73 66 : subreq = cli_trans_send(
74 : state, /* mem_ctx */
75 : ev, /* ev */
76 : cli, /* cli */
77 : 0, /* additional_flags2 */
78 : SMBnttrans, /* cmd */
79 : NULL, /* pipe_name */
80 : -1, /* fid */
81 : NT_TRANSACT_QUERY_SECURITY_DESC, /* function */
82 : 0, /* flags */
83 : NULL, /* setup */
84 : 0, /* num_setup */
85 : 0, /* max_setup */
86 66 : state->param, /* param */
87 : 8, /* num_param */
88 : 4, /* max_param */
89 : NULL, /* data */
90 : 0, /* num_data */
91 : 0x10000); /* max_data */
92 66 : if (tevent_req_nomem(subreq, req)) {
93 0 : return tevent_req_post(req, ev);
94 : }
95 66 : tevent_req_set_callback(
96 : subreq, cli_query_security_descriptor_done1, req);
97 66 : return req;
98 : }
99 :
100 66 : static void cli_query_security_descriptor_done1(struct tevent_req *subreq)
101 : {
102 66 : struct tevent_req *req = tevent_req_callback_data(
103 : subreq, struct tevent_req);
104 66 : struct cli_query_security_descriptor_state *state = tevent_req_data(
105 : req, struct cli_query_security_descriptor_state);
106 0 : NTSTATUS status;
107 0 : uint32_t len;
108 :
109 66 : status = cli_trans_recv(
110 : subreq, /* req */
111 : state, /* mem_ctx */
112 : NULL, /* recv_flags2 */
113 : NULL, /* setup */
114 : 0, /* min_setup */
115 : NULL, /* num_setup */
116 : NULL, /* param */
117 : 0, /* min_param */
118 : NULL, /* num_param */
119 : &state->outbuf.data, /* data */
120 : 0, /* min_data */
121 : &len); /* num_data */
122 66 : TALLOC_FREE(subreq);
123 66 : if (tevent_req_nterror(req, status)) {
124 0 : return;
125 : }
126 66 : state->outbuf.length = len; /* uint32_t -> size_t */
127 66 : tevent_req_done(req);
128 : }
129 :
130 3442 : static void cli_query_security_descriptor_done2(struct tevent_req *subreq)
131 : {
132 3442 : struct tevent_req *req = tevent_req_callback_data(
133 : subreq, struct tevent_req);
134 3442 : struct cli_query_security_descriptor_state *state = tevent_req_data(
135 : req, struct cli_query_security_descriptor_state);
136 0 : NTSTATUS status;
137 :
138 3442 : status = cli_smb2_query_info_fnum_recv(subreq, state, &state->outbuf);
139 3442 : TALLOC_FREE(subreq);
140 3442 : if (tevent_req_nterror(req, status)) {
141 8 : return;
142 : }
143 3434 : tevent_req_done(req);
144 : }
145 :
146 3508 : NTSTATUS cli_query_security_descriptor_recv(
147 : struct tevent_req *req,
148 : TALLOC_CTX *mem_ctx,
149 : struct security_descriptor **sd)
150 : {
151 3508 : struct cli_query_security_descriptor_state *state = tevent_req_data(
152 : req, struct cli_query_security_descriptor_state);
153 3508 : NTSTATUS status = NT_STATUS_OK;
154 :
155 3508 : if (tevent_req_is_nterror(req, &status)) {
156 8 : goto done;
157 : }
158 3500 : if (sd != NULL) {
159 3500 : status = unmarshall_sec_desc(
160 : mem_ctx, state->outbuf.data, state->outbuf.length, sd);
161 : }
162 0 : done:
163 3508 : tevent_req_received(req);
164 3508 : return status;
165 : }
166 :
167 3154 : NTSTATUS cli_query_security_descriptor(struct cli_state *cli,
168 : uint16_t fnum,
169 : uint32_t sec_info,
170 : TALLOC_CTX *mem_ctx,
171 : struct security_descriptor **sd)
172 : {
173 3154 : TALLOC_CTX *frame = talloc_stackframe();
174 3154 : struct tevent_context *ev = NULL;
175 3154 : struct tevent_req *req = NULL;
176 3154 : NTSTATUS status = NT_STATUS_NO_MEMORY;
177 :
178 3154 : if (smbXcli_conn_has_async_calls(cli->conn)) {
179 0 : status = NT_STATUS_INVALID_PARAMETER;
180 0 : goto fail;
181 : }
182 3154 : ev = samba_tevent_context_init(frame);
183 3154 : if (ev == NULL) {
184 0 : goto fail;
185 : }
186 3154 : req = cli_query_security_descriptor_send(
187 : frame, ev, cli, fnum, sec_info);
188 3154 : if (req == NULL) {
189 0 : goto fail;
190 : }
191 3154 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
192 0 : goto fail;
193 : }
194 3154 : status = cli_query_security_descriptor_recv(req, mem_ctx, sd);
195 3154 : fail:
196 3154 : TALLOC_FREE(frame);
197 3154 : return status;
198 : }
199 :
200 34 : NTSTATUS cli_query_secdesc(struct cli_state *cli, uint16_t fnum,
201 : TALLOC_CTX *mem_ctx, struct security_descriptor **sd)
202 : {
203 34 : uint32_t sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
204 :
205 34 : return cli_query_security_descriptor(cli, fnum, sec_info, mem_ctx, sd);
206 : }
207 :
208 4 : NTSTATUS cli_query_mxac(struct cli_state *cli,
209 : const char *filename,
210 : uint32_t *mxac)
211 : {
212 4 : if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
213 0 : return NT_STATUS_NOT_SUPPORTED;
214 : }
215 :
216 4 : return cli_smb2_query_mxac(cli, filename, mxac);
217 : }
218 :
219 : struct cli_set_security_descriptor_state {
220 : uint8_t param[8];
221 : DATA_BLOB buf;
222 : };
223 :
224 : static void cli_set_security_descriptor_done1(struct tevent_req *subreq);
225 : static void cli_set_security_descriptor_done2(struct tevent_req *subreq);
226 :
227 2504 : struct tevent_req *cli_set_security_descriptor_send(
228 : TALLOC_CTX *mem_ctx,
229 : struct tevent_context *ev,
230 : struct cli_state *cli,
231 : uint16_t fnum,
232 : uint32_t sec_info,
233 : const struct security_descriptor *sd)
234 : {
235 2504 : struct tevent_req *req = NULL, *subreq = NULL;
236 2504 : struct cli_set_security_descriptor_state *state = NULL;
237 0 : NTSTATUS status;
238 :
239 2504 : req = tevent_req_create(
240 : mem_ctx, &state, struct cli_set_security_descriptor_state);
241 2504 : if (req == NULL) {
242 0 : return NULL;
243 : }
244 :
245 2504 : status = marshall_sec_desc(
246 2504 : state, sd, &state->buf.data, &state->buf.length);
247 2504 : if (tevent_req_nterror(req, status)) {
248 0 : return tevent_req_post(req, ev);
249 : }
250 :
251 2504 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
252 2452 : subreq = cli_smb2_set_info_fnum_send(
253 : state, /* mem_ctx */
254 : ev, /* ev */
255 : cli, /* cli */
256 : fnum, /* fnum */
257 : 3, /* in_info_type */
258 : 0, /* in_file_info_class */
259 2452 : &state->buf, /* in_input_buffer */
260 : sec_info); /* in_additional_info */
261 2452 : if (tevent_req_nomem(subreq, req)) {
262 0 : return tevent_req_post(req, ev);
263 : }
264 2452 : tevent_req_set_callback(
265 : subreq, cli_set_security_descriptor_done2, req);
266 2452 : return req;
267 : }
268 :
269 52 : SIVAL(state->param, 0, fnum);
270 52 : SIVAL(state->param, 4, sec_info);
271 :
272 52 : subreq = cli_trans_send(
273 : state, /* mem_ctx */
274 : ev, /* ev */
275 : cli, /* cli */
276 : 0, /* additional_flags2 */
277 : SMBnttrans, /* cmd */
278 : NULL, /* pipe_name */
279 : -1, /* fid */
280 : NT_TRANSACT_SET_SECURITY_DESC, /* function */
281 : 0, /* flags */
282 : NULL, /* setup */
283 : 0, /* num_setup */
284 : 0, /* max_setup */
285 52 : state->param, /* param */
286 : 8, /* num_param */
287 : 0, /* max_param */
288 52 : state->buf.data, /* data */
289 52 : state->buf.length, /* num_data */
290 : 0); /* max_data */
291 52 : if (tevent_req_nomem(subreq, req)) {
292 0 : return tevent_req_post(req, ev);
293 : }
294 52 : tevent_req_set_callback(
295 : subreq, cli_set_security_descriptor_done1, req);
296 52 : return req;
297 : }
298 :
299 52 : static void cli_set_security_descriptor_done1(struct tevent_req *subreq)
300 : {
301 52 : NTSTATUS status = cli_trans_recv(
302 : subreq, NULL, NULL, NULL, 0, NULL, NULL, 0, NULL,
303 : NULL, 0, NULL);
304 52 : return tevent_req_simple_finish_ntstatus(subreq, status);
305 : }
306 :
307 2452 : static void cli_set_security_descriptor_done2(struct tevent_req *subreq)
308 : {
309 2452 : NTSTATUS status = cli_smb2_set_info_fnum_recv(subreq);
310 2452 : tevent_req_simple_finish_ntstatus(subreq, status);
311 2452 : }
312 :
313 2504 : NTSTATUS cli_set_security_descriptor_recv(struct tevent_req *req)
314 : {
315 2504 : return tevent_req_simple_recv_ntstatus(req);
316 : }
317 :
318 : /****************************************************************************
319 : set the security descriptor for a open file
320 : ****************************************************************************/
321 2050 : NTSTATUS cli_set_security_descriptor(struct cli_state *cli,
322 : uint16_t fnum,
323 : uint32_t sec_info,
324 : const struct security_descriptor *sd)
325 : {
326 2050 : TALLOC_CTX *frame = talloc_stackframe();
327 2050 : struct tevent_context *ev = NULL;
328 2050 : struct tevent_req *req = NULL;
329 2050 : NTSTATUS status = NT_STATUS_NO_MEMORY;
330 :
331 2050 : if (smbXcli_conn_has_async_calls(cli->conn)) {
332 0 : status = NT_STATUS_INVALID_PARAMETER;
333 0 : goto fail;
334 : }
335 2050 : ev = samba_tevent_context_init(frame);
336 2050 : if (ev == NULL) {
337 0 : goto fail;
338 : }
339 2050 : req = cli_set_security_descriptor_send(
340 : frame, ev, cli, fnum, sec_info, sd);
341 2050 : if (req == NULL) {
342 0 : goto fail;
343 : }
344 2050 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
345 0 : goto fail;
346 : }
347 2050 : status = cli_set_security_descriptor_recv(req);
348 2050 : fail:
349 2050 : TALLOC_FREE(frame);
350 2050 : return status;
351 : }
352 :
353 16 : NTSTATUS cli_set_secdesc(struct cli_state *cli, uint16_t fnum,
354 : const struct security_descriptor *sd)
355 : {
356 16 : uint32_t sec_info = 0;
357 :
358 16 : if (sd->dacl || (sd->type & SEC_DESC_DACL_PRESENT)) {
359 16 : sec_info |= SECINFO_DACL;
360 : }
361 16 : if (sd->sacl || (sd->type & SEC_DESC_SACL_PRESENT)) {
362 0 : sec_info |= SECINFO_SACL;
363 : }
364 16 : if (sd->owner_sid) {
365 16 : sec_info |= SECINFO_OWNER;
366 : }
367 16 : if (sd->group_sid) {
368 16 : sec_info |= SECINFO_GROUP;
369 : }
370 :
371 16 : return cli_set_security_descriptor(cli, fnum, sec_info, sd);
372 : }
|