libsmb: remove mode from struct file_info
[samba.git] / source3 / libsmb / clisecdesc.c
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 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         struct tevent_req *req = NULL, *subreq = NULL;
42         struct cli_query_security_descriptor_state *state = NULL;
43
44         req = tevent_req_create(
45                 mem_ctx, &state, struct cli_query_security_descriptor_state);
46         if (req == NULL) {
47                 return NULL;
48         }
49
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);
64                 }
65                 tevent_req_set_callback(
66                         subreq, cli_query_security_descriptor_done2, req);
67                 return req;
68         }
69
70         PUSH_LE_U32(state->param, 0, fnum);
71         PUSH_LE_U32(state->param, 4, sec_info);
72
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);
94         }
95         tevent_req_set_callback(
96                 subreq, cli_query_security_descriptor_done1, req);
97         return req;
98 }
99
100 static void cli_query_security_descriptor_done1(struct tevent_req *subreq)
101 {
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;
108
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;
125         }
126         state->outbuf.length = len; /* uint32_t -> size_t */
127         tevent_req_done(req);
128 }
129
130 static void cli_query_security_descriptor_done2(struct tevent_req *subreq)
131 {
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;
137
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;
142         }
143         tevent_req_done(req);
144 }
145
146 NTSTATUS cli_query_security_descriptor_recv(
147         struct tevent_req *req,
148         TALLOC_CTX *mem_ctx,
149         struct security_descriptor **sd)
150 {
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;
154
155         if (tevent_req_is_nterror(req, &status)) {
156                 goto done;
157         }
158         if (sd != NULL) {
159                 status = unmarshall_sec_desc(
160                         mem_ctx, state->outbuf.data, state->outbuf.length, sd);
161         }
162 done:
163         tevent_req_received(req);
164         return status;
165 }
166
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)
172 {
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;
177
178         if (smbXcli_conn_has_async_calls(cli->conn)) {
179                 status = NT_STATUS_INVALID_PARAMETER;
180                 goto fail;
181         }
182         ev = samba_tevent_context_init(frame);
183         if (ev == NULL) {
184                 goto fail;
185         }
186         req = cli_query_security_descriptor_send(
187                 frame, ev, cli, fnum, sec_info);
188         if (req == NULL) {
189                 goto fail;
190         }
191         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
192                 goto fail;
193         }
194         status = cli_query_security_descriptor_recv(req, mem_ctx, sd);
195  fail:
196         TALLOC_FREE(frame);
197         return status;
198 }
199
200 NTSTATUS cli_query_secdesc(struct cli_state *cli, uint16_t fnum,
201                            TALLOC_CTX *mem_ctx, struct security_descriptor **sd)
202 {
203         uint32_t sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
204
205         return cli_query_security_descriptor(cli, fnum, sec_info, mem_ctx, sd);
206 }
207
208 NTSTATUS cli_query_mxac(struct cli_state *cli,
209                         const char *filename,
210                         uint32_t *mxac)
211 {
212         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
213                 return NT_STATUS_NOT_SUPPORTED;
214         }
215
216         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 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         struct tevent_req *req = NULL, *subreq = NULL;
236         struct cli_set_security_descriptor_state *state = NULL;
237         NTSTATUS status;
238
239         req = tevent_req_create(
240                 mem_ctx, &state, struct cli_set_security_descriptor_state);
241         if (req == NULL) {
242                 return NULL;
243         }
244
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);
249         }
250
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);
263                 }
264                 tevent_req_set_callback(
265                         subreq, cli_set_security_descriptor_done2, req);
266                 return req;
267         }
268
269         SIVAL(state->param, 0, fnum);
270         SIVAL(state->param, 4, sec_info);
271
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);
293         }
294         tevent_req_set_callback(
295                 subreq, cli_set_security_descriptor_done1, req);
296         return req;
297 }
298
299 static void cli_set_security_descriptor_done1(struct tevent_req *subreq)
300 {
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);
305 }
306
307 static void cli_set_security_descriptor_done2(struct tevent_req *subreq)
308 {
309         NTSTATUS status = cli_smb2_set_info_fnum_recv(subreq);
310         tevent_req_simple_finish_ntstatus(subreq, status);
311 }
312
313 NTSTATUS cli_set_security_descriptor_recv(struct tevent_req *req)
314 {
315         return tevent_req_simple_recv_ntstatus(req);
316 }
317
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)
325 {
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;
330
331         if (smbXcli_conn_has_async_calls(cli->conn)) {
332                 status = NT_STATUS_INVALID_PARAMETER;
333                 goto fail;
334         }
335         ev = samba_tevent_context_init(frame);
336         if (ev == NULL) {
337                 goto fail;
338         }
339         req = cli_set_security_descriptor_send(
340                 frame, ev, cli, fnum, sec_info, sd);
341         if (req == NULL) {
342                 goto fail;
343         }
344         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
345                 goto fail;
346         }
347         status = cli_set_security_descriptor_recv(req);
348  fail:
349         TALLOC_FREE(frame);
350         return status;
351 }
352
353 NTSTATUS cli_set_secdesc(struct cli_state *cli, uint16_t fnum,
354                          const struct security_descriptor *sd)
355 {
356         uint32_t sec_info = 0;
357
358         if (sd->dacl || (sd->type & SEC_DESC_DACL_PRESENT)) {
359                 sec_info |= SECINFO_DACL;
360         }
361         if (sd->sacl || (sd->type & SEC_DESC_SACL_PRESENT)) {
362                 sec_info |= SECINFO_SACL;
363         }
364         if (sd->owner_sid) {
365                 sec_info |= SECINFO_OWNER;
366         }
367         if (sd->group_sid) {
368                 sec_info |= SECINFO_GROUP;
369         }
370
371         return cli_set_security_descriptor(cli, fnum, sec_info, sd);
372 }