df853366039f1d4cbb2b1205fec849406234962c
[abartlet/samba.git/.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, NULL, 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, NULL, 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 /*
433  * Determine if an ACE is inheritable
434  */
435
436 static bool is_inheritable_ace(const SEC_ACE *ace,
437                                 bool container)
438 {
439         if (!container) {
440                 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
441         }
442
443         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
444                 return true;
445         }
446
447         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
448                         !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
449                 return true;
450         }
451
452         return false;
453 }
454
455 /* Create a child security descriptor using another security descriptor as
456    the parent container.  This child object can either be a container or
457    non-container object. */
458
459 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
460                                         SEC_DESC **ppsd,
461                                         size_t *psize,
462                                         const SEC_DESC *parent_ctr,
463                                         const DOM_SID *owner_sid,
464                                         const DOM_SID *group_sid,
465                                         bool container)
466 {
467         SEC_ACL *new_dacl = NULL, *the_acl = NULL;
468         SEC_ACE *new_ace_list = NULL;
469         unsigned int new_ace_list_ndx = 0, i;
470
471         *ppsd = NULL;
472         *psize = 0;
473
474         /* Currently we only process the dacl when creating the child.  The
475            sacl should also be processed but this is left out as sacls are
476            not implemented in Samba at the moment.*/
477
478         the_acl = parent_ctr->dacl;
479
480         if (the_acl->num_aces) {
481                 if (2*the_acl->num_aces < the_acl->num_aces) {
482                         return NT_STATUS_NO_MEMORY;
483                 }
484
485                 if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE,
486                                                 2*the_acl->num_aces))) {
487                         return NT_STATUS_NO_MEMORY;
488                 }
489         } else {
490                 new_ace_list = NULL;
491         }
492
493         for (i = 0; i < the_acl->num_aces; i++) {
494                 const SEC_ACE *ace = &the_acl->aces[i];
495                 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
496                 const DOM_SID *ptrustee = &ace->trustee;
497                 const DOM_SID *creator = NULL;
498                 uint8 new_flags = ace->flags;
499
500                 if (!is_inheritable_ace(ace, container)) {
501                         continue;
502                 }
503
504                 /* see the RAW-ACLS inheritance test for details on these rules */
505                 if (!container) {
506                         new_flags = 0;
507                 } else {
508                         new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
509
510                         if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
511                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
512                         }
513                         if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
514                                 new_flags = 0;
515                         }
516                 }
517
518                 /* The CREATOR sids are special when inherited */
519                 if (sid_equal(ptrustee, &global_sid_Creator_Owner)) {
520                         creator = &global_sid_Creator_Owner;
521                         ptrustee = owner_sid;
522                 } else if (sid_equal(ptrustee, &global_sid_Creator_Group)) {
523                         creator = &global_sid_Creator_Group;
524                         ptrustee = group_sid;
525                 }
526
527                 if (creator && container &&
528                                 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
529
530                         /* First add the regular ACE entry. */
531                         init_sec_ace(new_ace, ptrustee, ace->type,
532                                 ace->access_mask, 0);
533
534                         DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
535                                 " inherited as %s:%d/0x%02x/0x%08x\n",
536                                 sid_string_dbg(&ace->trustee),
537                                 ace->type, ace->flags, ace->access_mask,
538                                 sid_string_dbg(&new_ace->trustee),
539                                 new_ace->type, new_ace->flags,
540                                 new_ace->access_mask));
541
542                         new_ace_list_ndx++;
543
544                         /* Now add the extra creator ACE. */
545                         new_ace = &new_ace_list[new_ace_list_ndx];
546
547                         ptrustee = creator;
548                         new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
549                 } else if (container &&
550                                 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
551                         ptrustee = &ace->trustee;
552                 }
553
554                 init_sec_ace(new_ace, ptrustee, ace->type,
555                              ace->access_mask, new_flags);
556
557                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
558                           " inherited as %s:%d/0x%02x/0x%08x\n",
559                           sid_string_dbg(&ace->trustee),
560                           ace->type, ace->flags, ace->access_mask,
561                           sid_string_dbg(&ace->trustee),
562                           new_ace->type, new_ace->flags,
563                           new_ace->access_mask));
564
565                 new_ace_list_ndx++;
566         }
567
568         /* Create child security descriptor to return */
569         if (new_ace_list_ndx) {
570                 new_dacl = make_sec_acl(ctx,
571                                 NT4_ACL_REVISION,
572                                 new_ace_list_ndx,
573                                 new_ace_list);
574
575                 if (!new_dacl) {
576                         return NT_STATUS_NO_MEMORY;
577                 }
578         }
579
580         *ppsd = make_sec_desc(ctx,
581                         SECURITY_DESCRIPTOR_REVISION_1,
582                         SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
583                         owner_sid,
584                         group_sid,
585                         NULL,
586                         new_dacl,
587                         psize);
588         if (!*ppsd) {
589                 return NT_STATUS_NO_MEMORY;
590         }
591         return NT_STATUS_OK;
592 }
593
594 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
595                                         SEC_DESC_BUF **ppsdb,
596                                         const SEC_DESC *parent_ctr,
597                                         bool container)
598 {
599         NTSTATUS status;
600         size_t size = 0;
601         SEC_DESC *sd = NULL;
602
603         *ppsdb = NULL;
604         status = se_create_child_secdesc(ctx,
605                                         &sd,
606                                         &size,
607                                         parent_ctr,
608                                         parent_ctr->owner_sid,
609                                         parent_ctr->group_sid,
610                                         container);
611         if (!NT_STATUS_IS_OK(status)) {
612                 return status;
613         }
614
615         *ppsdb = make_sec_desc_buf(ctx, size, sd);
616         if (!*ppsdb) {
617                 return NT_STATUS_NO_MEMORY;
618         }
619         return NT_STATUS_OK;
620 }