samba-tool: Ensure modifying GPO increments GPT.INI vers
[Samba.git] / source3 / libsmb / clisecdesc.c
blob0a5708f7ebd271b07665d0c33268011061b7d301
1 /*
2 Unix SMB/CIFS implementation.
3 client security descriptor functions
4 Copyright (C) Andrew Tridgell 2000
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.
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.
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/>.
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"
26 struct cli_query_security_descriptor_state {
27 uint8_t param[8];
28 DATA_BLOB outbuf;
31 static void cli_query_security_descriptor_done1(struct tevent_req *subreq);
32 static void cli_query_security_descriptor_done2(struct tevent_req *subreq);
34 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)
41 struct tevent_req *req = NULL, *subreq = NULL;
42 struct cli_query_security_descriptor_state *state = NULL;
44 req = tevent_req_create(
45 mem_ctx, &state, struct cli_query_security_descriptor_state);
46 if (req == NULL) {
47 return NULL;
50 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
51 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 if (tevent_req_nomem(subreq, req)) {
63 return tevent_req_post(req, ev);
65 tevent_req_set_callback(
66 subreq, cli_query_security_descriptor_done2, req);
67 return req;
70 PUSH_LE_U32(state->param, 0, fnum);
71 PUSH_LE_U32(state->param, 4, sec_info);
73 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 state->param, /* param */
87 8, /* num_param */
88 4, /* max_param */
89 NULL, /* data */
90 0, /* num_data */
91 0x10000); /* max_data */
92 if (tevent_req_nomem(subreq, req)) {
93 return tevent_req_post(req, ev);
95 tevent_req_set_callback(
96 subreq, cli_query_security_descriptor_done1, req);
97 return req;
100 static void cli_query_security_descriptor_done1(struct tevent_req *subreq)
102 struct tevent_req *req = tevent_req_callback_data(
103 subreq, struct tevent_req);
104 struct cli_query_security_descriptor_state *state = tevent_req_data(
105 req, struct cli_query_security_descriptor_state);
106 NTSTATUS status;
107 uint32_t len;
109 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 TALLOC_FREE(subreq);
123 if (tevent_req_nterror(req, status)) {
124 return;
126 state->outbuf.length = len; /* uint32_t -> size_t */
127 tevent_req_done(req);
130 static void cli_query_security_descriptor_done2(struct tevent_req *subreq)
132 struct tevent_req *req = tevent_req_callback_data(
133 subreq, struct tevent_req);
134 struct cli_query_security_descriptor_state *state = tevent_req_data(
135 req, struct cli_query_security_descriptor_state);
136 NTSTATUS status;
138 status = cli_smb2_query_info_fnum_recv(subreq, state, &state->outbuf);
139 TALLOC_FREE(subreq);
140 if (tevent_req_nterror(req, status)) {
141 return;
143 tevent_req_done(req);
146 NTSTATUS cli_query_security_descriptor_recv(
147 struct tevent_req *req,
148 TALLOC_CTX *mem_ctx,
149 struct security_descriptor **sd)
151 struct cli_query_security_descriptor_state *state = tevent_req_data(
152 req, struct cli_query_security_descriptor_state);
153 NTSTATUS status = NT_STATUS_OK;
155 if (tevent_req_is_nterror(req, &status)) {
156 goto done;
158 if (sd != NULL) {
159 status = unmarshall_sec_desc(
160 mem_ctx, state->outbuf.data, state->outbuf.length, sd);
162 done:
163 tevent_req_received(req);
164 return status;
167 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)
173 TALLOC_CTX *frame = talloc_stackframe();
174 struct tevent_context *ev = NULL;
175 struct tevent_req *req = NULL;
176 NTSTATUS status = NT_STATUS_NO_MEMORY;
178 if (smbXcli_conn_has_async_calls(cli->conn)) {
179 status = NT_STATUS_INVALID_PARAMETER;
180 goto fail;
182 ev = samba_tevent_context_init(frame);
183 if (ev == NULL) {
184 goto fail;
186 req = cli_query_security_descriptor_send(
187 frame, ev, cli, fnum, sec_info);
188 if (req == NULL) {
189 goto fail;
191 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
192 goto fail;
194 status = cli_query_security_descriptor_recv(req, mem_ctx, sd);
195 fail:
196 TALLOC_FREE(frame);
197 return status;
200 NTSTATUS cli_query_secdesc(struct cli_state *cli, uint16_t fnum,
201 TALLOC_CTX *mem_ctx, struct security_descriptor **sd)
203 uint32_t sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
205 return cli_query_security_descriptor(cli, fnum, sec_info, mem_ctx, sd);
208 NTSTATUS cli_query_mxac(struct cli_state *cli,
209 const char *filename,
210 uint32_t *mxac)
212 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
213 return NT_STATUS_NOT_SUPPORTED;
216 return cli_smb2_query_mxac(cli, filename, mxac);
219 struct cli_set_security_descriptor_state {
220 uint8_t param[8];
221 DATA_BLOB buf;
224 static void cli_set_security_descriptor_done1(struct tevent_req *subreq);
225 static void cli_set_security_descriptor_done2(struct tevent_req *subreq);
227 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)
235 struct tevent_req *req = NULL, *subreq = NULL;
236 struct cli_set_security_descriptor_state *state = NULL;
237 NTSTATUS status;
239 req = tevent_req_create(
240 mem_ctx, &state, struct cli_set_security_descriptor_state);
241 if (req == NULL) {
242 return NULL;
245 status = marshall_sec_desc(
246 state, sd, &state->buf.data, &state->buf.length);
247 if (tevent_req_nterror(req, status)) {
248 return tevent_req_post(req, ev);
251 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
252 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 &state->buf, /* in_input_buffer */
260 sec_info); /* in_additional_info */
261 if (tevent_req_nomem(subreq, req)) {
262 return tevent_req_post(req, ev);
264 tevent_req_set_callback(
265 subreq, cli_set_security_descriptor_done2, req);
266 return req;
269 SIVAL(state->param, 0, fnum);
270 SIVAL(state->param, 4, sec_info);
272 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 state->param, /* param */
286 8, /* num_param */
287 0, /* max_param */
288 state->buf.data, /* data */
289 state->buf.length, /* num_data */
290 0); /* max_data */
291 if (tevent_req_nomem(subreq, req)) {
292 return tevent_req_post(req, ev);
294 tevent_req_set_callback(
295 subreq, cli_set_security_descriptor_done1, req);
296 return req;
299 static void cli_set_security_descriptor_done1(struct tevent_req *subreq)
301 NTSTATUS status = cli_trans_recv(
302 subreq, NULL, NULL, NULL, 0, NULL, NULL, 0, NULL,
303 NULL, 0, NULL);
304 return tevent_req_simple_finish_ntstatus(subreq, status);
307 static void cli_set_security_descriptor_done2(struct tevent_req *subreq)
309 NTSTATUS status = cli_smb2_set_info_fnum_recv(subreq);
310 tevent_req_simple_finish_ntstatus(subreq, status);
313 NTSTATUS cli_set_security_descriptor_recv(struct tevent_req *req)
315 return tevent_req_simple_recv_ntstatus(req);
318 /****************************************************************************
319 set the security descriptor for a open file
320 ****************************************************************************/
321 NTSTATUS cli_set_security_descriptor(struct cli_state *cli,
322 uint16_t fnum,
323 uint32_t sec_info,
324 const struct security_descriptor *sd)
326 TALLOC_CTX *frame = talloc_stackframe();
327 struct tevent_context *ev = NULL;
328 struct tevent_req *req = NULL;
329 NTSTATUS status = NT_STATUS_NO_MEMORY;
331 if (smbXcli_conn_has_async_calls(cli->conn)) {
332 status = NT_STATUS_INVALID_PARAMETER;
333 goto fail;
335 ev = samba_tevent_context_init(frame);
336 if (ev == NULL) {
337 goto fail;
339 req = cli_set_security_descriptor_send(
340 frame, ev, cli, fnum, sec_info, sd);
341 if (req == NULL) {
342 goto fail;
344 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
345 goto fail;
347 status = cli_set_security_descriptor_recv(req);
348 fail:
349 TALLOC_FREE(frame);
350 return status;
353 NTSTATUS cli_set_secdesc(struct cli_state *cli, uint16_t fnum,
354 const struct security_descriptor *sd)
356 uint32_t sec_info = 0;
358 if (sd->dacl || (sd->type & SEC_DESC_DACL_PRESENT)) {
359 sec_info |= SECINFO_DACL;
361 if (sd->sacl || (sd->type & SEC_DESC_SACL_PRESENT)) {
362 sec_info |= SECINFO_SACL;
364 if (sd->owner_sid) {
365 sec_info |= SECINFO_OWNER;
367 if (sd->group_sid) {
368 sec_info |= SECINFO_GROUP;
371 return cli_set_security_descriptor(cli, fnum, sec_info, sd);