test setinfo FULL_EA_INFORMATION in gentest
[gd/samba/.git] / source3 / lib / secdesc.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  SEC_DESC handling functions
4  *  Copyright (C) Andrew Tridgell              1992-1998,
5  *  Copyright (C) Jeremy R. Allison            1995-2003.
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7  *  Copyright (C) Paul Ashton                  1997-1998.
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 3 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include "includes.h"
24
25 /* Map generic permissions to file object specific permissions */
26
27 const struct generic_mapping file_generic_mapping = {
28         FILE_GENERIC_READ,
29         FILE_GENERIC_WRITE,
30         FILE_GENERIC_EXECUTE,
31         FILE_GENERIC_ALL
32 };
33
34 /*******************************************************************
35  Compares two SEC_DESC structures
36 ********************************************************************/
37
38 bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
39 {
40         /* Trivial case */
41
42         if (!s1 && !s2) {
43                 goto done;
44         }
45
46         if (!s1 || !s2) {
47                 return False;
48         }
49
50         /* Check top level stuff */
51
52         if (s1->revision != s2->revision) {
53                 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
54                            s1->revision, s2->revision));
55                 return False;
56         }
57
58         if (s1->type!= s2->type) {
59                 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
60                            s1->type, s2->type));
61                 return False;
62         }
63
64         /* Check owner and group */
65
66         if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
67                 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
68                            sid_string_dbg(s1->owner_sid),
69                            sid_string_dbg(s2->owner_sid)));
70                 return False;
71         }
72
73         if (!sid_equal(s1->group_sid, s2->group_sid)) {
74                 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
75                            sid_string_dbg(s1->group_sid),
76                            sid_string_dbg(s2->group_sid)));
77                 return False;
78         }
79
80         /* Check ACLs present in one but not the other */
81
82         if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
83             (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
84                 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
85                 return False;
86         }
87
88         /* Sigh - we have to do it the hard way by iterating over all
89            the ACEs in the ACLs */
90
91         if (!sec_acl_equal(s1->dacl, s2->dacl) ||
92             !sec_acl_equal(s1->sacl, s2->sacl)) {
93                 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
94                 return False;
95         }
96
97  done:
98         DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
99         return True;
100 }
101
102 /*******************************************************************
103  Merge part of security descriptor old_sec in to the empty sections of 
104  security descriptor new_sec.
105 ********************************************************************/
106
107 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
108 {
109         DOM_SID *owner_sid, *group_sid;
110         SEC_DESC_BUF *return_sdb;
111         SEC_ACL *dacl, *sacl;
112         SEC_DESC *psd = NULL;
113         uint16 secdesc_type;
114         size_t secdesc_size;
115
116         /* Copy over owner and group sids.  There seems to be no flag for
117            this so just check the pointer values. */
118
119         owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
120                 old_sdb->sd->owner_sid;
121
122         group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
123                 old_sdb->sd->group_sid;
124         
125         secdesc_type = new_sdb->sd->type;
126
127         /* Ignore changes to the system ACL.  This has the effect of making
128            changes through the security tab audit button not sticking. 
129            Perhaps in future Samba could implement these settings somehow. */
130
131         sacl = NULL;
132         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
133
134         /* Copy across discretionary ACL */
135
136         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
137                 dacl = new_sdb->sd->dacl;
138         } else {
139                 dacl = old_sdb->sd->dacl;
140         }
141
142         /* Create new security descriptor from bits */
143
144         psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
145                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
146
147         return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
148
149         return(return_sdb);
150 }
151
152 /*******************************************************************
153  Creates a SEC_DESC structure
154 ********************************************************************/
155
156 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx,
157                         enum security_descriptor_revision revision,
158                         uint16 type,
159                         const DOM_SID *owner_sid, const DOM_SID *grp_sid,
160                         SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
161 {
162         SEC_DESC *dst;
163         uint32 offset     = 0;
164
165         *sd_size = 0;
166
167         if(( dst = TALLOC_ZERO_P(ctx, SEC_DESC)) == NULL)
168                 return NULL;
169
170         dst->revision = revision;
171         dst->type = type;
172
173         if (sacl)
174                 dst->type |= SEC_DESC_SACL_PRESENT;
175         if (dacl)
176                 dst->type |= SEC_DESC_DACL_PRESENT;
177
178         dst->owner_sid = NULL;
179         dst->group_sid   = NULL;
180         dst->sacl      = NULL;
181         dst->dacl      = NULL;
182
183         if(owner_sid && ((dst->owner_sid = sid_dup_talloc(dst,owner_sid)) == NULL))
184                 goto error_exit;
185
186         if(grp_sid && ((dst->group_sid = sid_dup_talloc(dst,grp_sid)) == NULL))
187                 goto error_exit;
188
189         if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
190                 goto error_exit;
191
192         if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
193                 goto error_exit;
194
195         offset = SEC_DESC_HEADER_SIZE;
196
197         /*
198          * Work out the linearization sizes.
199          */
200
201         if (dst->sacl != NULL) {
202                 offset += dst->sacl->size;
203         }
204         if (dst->dacl != NULL) {
205                 offset += dst->dacl->size;
206         }
207
208         if (dst->owner_sid != NULL) {
209                 offset += ndr_size_dom_sid(dst->owner_sid, 0);
210         }
211
212         if (dst->group_sid != NULL) {
213                 offset += ndr_size_dom_sid(dst->group_sid, 0);
214         }
215
216         *sd_size = (size_t)offset;
217         return dst;
218
219 error_exit:
220
221         *sd_size = 0;
222         return NULL;
223 }
224
225 /*******************************************************************
226  Duplicate a SEC_DESC structure.  
227 ********************************************************************/
228
229 SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src)
230 {
231         size_t dummy;
232
233         if(src == NULL)
234                 return NULL;
235
236         return make_sec_desc( ctx, src->revision, src->type,
237                                 src->owner_sid, src->group_sid, src->sacl,
238                                 src->dacl, &dummy);
239 }
240
241 /*******************************************************************
242  Convert a secdesc into a byte stream
243 ********************************************************************/
244 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
245                            struct security_descriptor *secdesc,
246                            uint8 **data, size_t *len)
247 {
248         DATA_BLOB blob;
249         enum ndr_err_code ndr_err;
250
251         ndr_err = ndr_push_struct_blob(
252                 &blob, mem_ctx, secdesc,
253                 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
254
255         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
256                 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
257                           ndr_errstr(ndr_err)));
258                 return ndr_map_error2ntstatus(ndr_err);;
259         }
260
261         *data = blob.data;
262         *len = blob.length;
263         return NT_STATUS_OK;
264 }
265
266 /*******************************************************************
267  Parse a byte stream into a secdesc
268 ********************************************************************/
269 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
270                              struct security_descriptor **psecdesc)
271 {
272         DATA_BLOB blob;
273         enum ndr_err_code ndr_err;
274         struct security_descriptor *result;
275
276         if ((data == NULL) || (len == 0)) {
277                 return NT_STATUS_INVALID_PARAMETER;
278         }
279
280         result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor);
281         if (result == NULL) {
282                 return NT_STATUS_NO_MEMORY;
283         }
284
285         blob = data_blob_const(data, len);
286
287         ndr_err = ndr_pull_struct_blob(
288                 &blob, result, result,
289                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
290
291         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
292                 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
293                           ndr_errstr(ndr_err)));
294                 TALLOC_FREE(result);
295                 return ndr_map_error2ntstatus(ndr_err);;
296         }
297
298         *psecdesc = result;
299         return NT_STATUS_OK;
300 }
301
302 /*******************************************************************
303  Creates a SEC_DESC structure with typical defaults.
304 ********************************************************************/
305
306 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *grp_sid,
307                                  SEC_ACL *dacl, size_t *sd_size)
308 {
309         return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
310                              SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
311                              dacl, sd_size);
312 }
313
314 /*******************************************************************
315  Creates a SEC_DESC_BUF structure.
316 ********************************************************************/
317
318 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
319 {
320         SEC_DESC_BUF *dst;
321
322         if((dst = TALLOC_ZERO_P(ctx, SEC_DESC_BUF)) == NULL)
323                 return NULL;
324
325         /* max buffer size (allocated size) */
326         dst->sd_size = (uint32)len;
327         
328         if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
329                 return NULL;
330         }
331
332         return dst;
333 }
334
335 /*******************************************************************
336  Duplicates a SEC_DESC_BUF structure.
337 ********************************************************************/
338
339 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
340 {
341         if(src == NULL)
342                 return NULL;
343
344         return make_sec_desc_buf( ctx, src->sd_size, src->sd);
345 }
346
347 /*******************************************************************
348  Add a new SID with its permissions to SEC_DESC.
349 ********************************************************************/
350
351 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
352 {
353         SEC_DESC *sd   = 0;
354         SEC_ACL  *dacl = 0;
355         SEC_ACE  *ace  = 0;
356         NTSTATUS  status;
357
358         if (!ctx || !psd || !sid || !sd_size)
359                 return NT_STATUS_INVALID_PARAMETER;
360
361         *sd_size = 0;
362
363         status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
364         
365         if (!NT_STATUS_IS_OK(status))
366                 return status;
367
368         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
369                 return NT_STATUS_UNSUCCESSFUL;
370         
371         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
372                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
373                 return NT_STATUS_UNSUCCESSFUL;
374
375         *psd = sd;
376          sd  = 0;
377         return NT_STATUS_OK;
378 }
379
380 /*******************************************************************
381  Modify a SID's permissions in a SEC_DESC.
382 ********************************************************************/
383
384 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
385 {
386         NTSTATUS status;
387
388         if (!sd || !sid)
389                 return NT_STATUS_INVALID_PARAMETER;
390
391         status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
392
393         if (!NT_STATUS_IS_OK(status))
394                 return status;
395         
396         return NT_STATUS_OK;
397 }
398
399 /*******************************************************************
400  Delete a SID from a SEC_DESC.
401 ********************************************************************/
402
403 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
404 {
405         SEC_DESC *sd   = 0;
406         SEC_ACL  *dacl = 0;
407         SEC_ACE  *ace  = 0;
408         NTSTATUS  status;
409
410         if (!ctx || !psd[0] || !sid || !sd_size)
411                 return NT_STATUS_INVALID_PARAMETER;
412
413         *sd_size = 0;
414         
415         status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
416
417         if (!NT_STATUS_IS_OK(status))
418                 return status;
419
420         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
421                 return NT_STATUS_UNSUCCESSFUL;
422         
423         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
424                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
425                 return NT_STATUS_UNSUCCESSFUL;
426
427         *psd = sd;
428          sd  = 0;
429         return NT_STATUS_OK;
430 }
431
432 /* Create a child security descriptor using another security descriptor as
433    the parent container.  This child object can either be a container or
434    non-container object. */
435
436 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
437                                       bool child_container)
438 {
439         SEC_DESC_BUF *sdb;
440         SEC_DESC *sd;
441         SEC_ACL *new_dacl, *the_acl;
442         SEC_ACE *new_ace_list = NULL;
443         unsigned int new_ace_list_ndx = 0, i;
444         size_t size;
445
446         /* Currently we only process the dacl when creating the child.  The
447            sacl should also be processed but this is left out as sacls are
448            not implemented in Samba at the moment.*/
449
450         the_acl = parent_ctr->dacl;
451
452         if (the_acl->num_aces) {
453                 if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces))) 
454                         return NULL;
455         } else {
456                 new_ace_list = NULL;
457         }
458
459         for (i = 0; i < the_acl->num_aces; i++) {
460                 SEC_ACE *ace = &the_acl->aces[i];
461                 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
462                 uint8 new_flags = 0;
463                 bool inherit = False;
464
465                 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
466                    inherited by non-container children objects.  Container
467                    children objects will inherit it as an INHERIT_ONLY
468                    ACE. */
469
470                 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
471
472                         if (!child_container) {
473                                 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
474                         } else {
475                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
476                         }
477
478                         inherit = True;
479                 }
480
481                 /* The CONAINER_INHERIT_ACE flag means all child container
482                    objects will inherit and use the ACE. */
483
484                 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
485                         if (!child_container) {
486                                 inherit = False;
487                         } else {
488                                 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
489                         }
490                 }
491
492                 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
493                    function for the parent container, but is inherited by
494                    all child objects as a normal ACE. */
495
496                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
497                         /* Move along, nothing to see here */
498                 }
499
500                 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
501                    is inherited by child objects but not grandchildren
502                    objects.  We clear the object inherit and container
503                    inherit flags in the inherited ACE. */
504
505                 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
506                         new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
507                                        SEC_ACE_FLAG_CONTAINER_INHERIT);
508                 }
509
510                 /* Add ACE to ACE list */
511
512                 if (!inherit)
513                         continue;
514
515                 init_sec_access(&new_ace->access_mask, ace->access_mask);
516                 init_sec_ace(new_ace, &ace->trustee, ace->type,
517                              new_ace->access_mask, new_flags);
518
519                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
520                           " inherited as %s:%d/0x%02x/0x%08x\n",
521                           sid_string_dbg(&ace->trustee),
522                           ace->type, ace->flags, ace->access_mask,
523                           sid_string_dbg(&ace->trustee),
524                           new_ace->type, new_ace->flags,
525                           new_ace->access_mask));
526
527                 new_ace_list_ndx++;
528         }
529
530         /* Create child security descriptor to return */
531         
532         new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
533
534         /* Use the existing user and group sids.  I don't think this is
535            correct.  Perhaps the user and group should be passed in as
536            parameters by the caller? */
537
538         sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
539                            SEC_DESC_SELF_RELATIVE,
540                            parent_ctr->owner_sid,
541                            parent_ctr->group_sid,
542                            parent_ctr->sacl,
543                            new_dacl, &size);
544
545         sdb = make_sec_desc_buf(ctx, size, sd);
546
547         return sdb;
548 }
549
550 /*******************************************************************
551  Sets up a SEC_ACCESS structure.
552 ********************************************************************/
553
554 void init_sec_access(uint32 *t, uint32 mask)
555 {
556         *t = mask;
557 }
558
559