9b59634e97c46443206261f285ce4a95a9827f10
[metze/samba/wip.git] / libcli / security / 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 #include "librpc/gen_ndr/ndr_security.h"
25 #include "libcli/security/security.h"
26
27 /* Map generic permissions to file object specific permissions */
28
29 const struct generic_mapping file_generic_mapping = {
30         FILE_GENERIC_READ,
31         FILE_GENERIC_WRITE,
32         FILE_GENERIC_EXECUTE,
33         FILE_GENERIC_ALL
34 };
35
36 /*******************************************************************
37  Given a security_descriptor return the sec_info.
38 ********************************************************************/
39
40 uint32_t get_sec_info(const struct security_descriptor *sd)
41 {
42         uint32_t sec_info = 0;
43
44         SMB_ASSERT(sd);
45
46         if (sd->owner_sid != NULL) {
47                 sec_info |= SECINFO_OWNER;
48         }
49         if (sd->group_sid != NULL) {
50                 sec_info |= SECINFO_GROUP;
51         }
52         if (sd->sacl != NULL) {
53                 sec_info |= SECINFO_SACL;
54         }
55         if (sd->dacl != NULL) {
56                 sec_info |= SECINFO_DACL;
57         }
58
59         if (sd->type & SEC_DESC_SACL_PROTECTED) {
60                 sec_info |= SECINFO_PROTECTED_SACL;
61         } else if (sd->type & SEC_DESC_SACL_AUTO_INHERITED) {
62                 sec_info |= SECINFO_UNPROTECTED_SACL;
63         }
64         if (sd->type & SEC_DESC_DACL_PROTECTED) {
65                 sec_info |= SECINFO_PROTECTED_DACL;
66         } else if (sd->type & SEC_DESC_DACL_AUTO_INHERITED) {
67                 sec_info |= SECINFO_UNPROTECTED_DACL;
68         }
69
70         return sec_info;
71 }
72
73
74 /*******************************************************************
75  Merge part of security descriptor old_sec in to the empty sections of
76  security descriptor new_sec.
77 ********************************************************************/
78
79 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
80 {
81         struct dom_sid *owner_sid, *group_sid;
82         struct sec_desc_buf *return_sdb;
83         struct security_acl *dacl, *sacl;
84         struct security_descriptor *psd = NULL;
85         uint16_t secdesc_type;
86         size_t secdesc_size;
87
88         /* Copy over owner and group sids.  There seems to be no flag for
89            this so just check the pointer values. */
90
91         owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
92                 old_sdb->sd->owner_sid;
93
94         group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
95                 old_sdb->sd->group_sid;
96
97         secdesc_type = new_sdb->sd->type;
98
99         /* Ignore changes to the system ACL.  This has the effect of making
100            changes through the security tab audit button not sticking.
101            Perhaps in future Samba could implement these settings somehow. */
102
103         sacl = NULL;
104         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
105
106         /* Copy across discretionary ACL */
107
108         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
109                 dacl = new_sdb->sd->dacl;
110         } else {
111                 dacl = old_sdb->sd->dacl;
112         }
113
114         /* Create new security descriptor from bits */
115
116         psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
117                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
118
119         return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
120
121         return(return_sdb);
122 }
123
124 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
125 {
126         struct dom_sid *owner_sid, *group_sid;
127         struct security_acl *dacl, *sacl;
128         struct security_descriptor *psd = NULL;
129         uint16_t secdesc_type;
130         size_t secdesc_size;
131
132         /* Copy over owner and group sids.  There seems to be no flag for
133            this so just check the pointer values. */
134
135         owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
136                 old_sdb->owner_sid;
137
138         group_sid = new_sdb->group_sid ? new_sdb->group_sid :
139                 old_sdb->group_sid;
140
141         secdesc_type = new_sdb->type;
142
143         /* Ignore changes to the system ACL.  This has the effect of making
144            changes through the security tab audit button not sticking.
145            Perhaps in future Samba could implement these settings somehow. */
146
147         sacl = NULL;
148         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
149
150         /* Copy across discretionary ACL */
151
152         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
153                 dacl = new_sdb->dacl;
154         } else {
155                 dacl = old_sdb->dacl;
156         }
157
158         /* Create new security descriptor from bits */
159         psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
160                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
161
162         return psd;
163 }
164
165 /*******************************************************************
166  Creates a struct security_descriptor structure
167 ********************************************************************/
168 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
169                         enum security_descriptor_revision revision,
170                         uint16_t type,
171                         const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
172                         struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
173 {
174         struct security_descriptor *dst;
175
176         if (sd_size != NULL) {
177                 *sd_size = 0;
178         }
179
180         dst = security_descriptor_initialise(ctx);
181         if (dst == NULL) {
182                 return NULL;
183         }
184
185         dst->revision = revision;
186         dst->type = type;
187
188         if (sacl != NULL) {
189                 dst->sacl = security_acl_dup(dst, sacl);
190                 if (dst->sacl == NULL) {
191                         goto err_sd_free;
192                 }
193                 dst->type |= SEC_DESC_SACL_PRESENT;
194         }
195
196         if (dacl != NULL) {
197                 dst->dacl = security_acl_dup(dst, dacl);
198                 if (dst->dacl == NULL) {
199                         goto err_sd_free;
200                 }
201                 dst->type |= SEC_DESC_DACL_PRESENT;
202         }
203
204         if (owner_sid != NULL) {
205                 dst->owner_sid = dom_sid_dup(dst, owner_sid);
206                 if (dst->owner_sid == NULL) {
207                         goto err_sd_free;
208                 }
209         }
210
211         if (grp_sid != NULL) {
212                 dst->group_sid = dom_sid_dup(dst, grp_sid);
213                 if (dst->group_sid == NULL) {
214                         goto err_sd_free;
215                 }
216         }
217
218         if (sd_size != NULL) {
219                 *sd_size = ndr_size_security_descriptor(dst, 0);
220         }
221
222         return dst;
223
224 err_sd_free:
225         talloc_free(dst);
226         return NULL;
227 }
228
229 /*******************************************************************
230  Convert a secdesc into a byte stream
231 ********************************************************************/
232 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
233                            const struct security_descriptor *secdesc,
234                            uint8_t **data, size_t *len)
235 {
236         DATA_BLOB blob;
237         enum ndr_err_code ndr_err;
238
239         ndr_err = ndr_push_struct_blob(
240                 &blob, mem_ctx, secdesc,
241                 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
242
243         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
244                 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
245                           ndr_errstr(ndr_err)));
246                 return ndr_map_error2ntstatus(ndr_err);
247         }
248
249         *data = blob.data;
250         *len = blob.length;
251         return NT_STATUS_OK;
252 }
253
254 /*******************************************************************
255  Convert a secdesc_buf into a byte stream
256 ********************************************************************/
257
258 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
259                                const struct sec_desc_buf *secdesc_buf,
260                                uint8_t **data, size_t *len)
261 {
262         DATA_BLOB blob;
263         enum ndr_err_code ndr_err;
264
265         ndr_err = ndr_push_struct_blob(
266                 &blob, mem_ctx, secdesc_buf,
267                 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
268
269         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
270                 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
271                           ndr_errstr(ndr_err)));
272                 return ndr_map_error2ntstatus(ndr_err);
273         }
274
275         *data = blob.data;
276         *len = blob.length;
277         return NT_STATUS_OK;
278 }
279
280 /*******************************************************************
281  Parse a byte stream into a secdesc
282 ********************************************************************/
283 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
284                              struct security_descriptor **psecdesc)
285 {
286         DATA_BLOB blob;
287         enum ndr_err_code ndr_err;
288         struct security_descriptor *result;
289
290         if ((data == NULL) || (len == 0)) {
291                 return NT_STATUS_INVALID_PARAMETER;
292         }
293
294         result = talloc_zero(mem_ctx, struct security_descriptor);
295         if (result == NULL) {
296                 return NT_STATUS_NO_MEMORY;
297         }
298
299         blob = data_blob_const(data, len);
300
301         ndr_err = ndr_pull_struct_blob(&blob, result, result,
302                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
303
304         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
305                 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
306                           ndr_errstr(ndr_err)));
307                 TALLOC_FREE(result);
308                 return ndr_map_error2ntstatus(ndr_err);
309         }
310
311         *psecdesc = result;
312         return NT_STATUS_OK;
313 }
314
315 /*******************************************************************
316  Parse a byte stream into a sec_desc_buf
317 ********************************************************************/
318
319 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
320                                  struct sec_desc_buf **psecdesc_buf)
321 {
322         DATA_BLOB blob;
323         enum ndr_err_code ndr_err;
324         struct sec_desc_buf *result;
325
326         if ((data == NULL) || (len == 0)) {
327                 return NT_STATUS_INVALID_PARAMETER;
328         }
329
330         result = talloc_zero(mem_ctx, struct sec_desc_buf);
331         if (result == NULL) {
332                 return NT_STATUS_NO_MEMORY;
333         }
334
335         blob = data_blob_const(data, len);
336
337         ndr_err = ndr_pull_struct_blob(&blob, result, result,
338                 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
339
340         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341                 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
342                           ndr_errstr(ndr_err)));
343                 TALLOC_FREE(result);
344                 return ndr_map_error2ntstatus(ndr_err);
345         }
346
347         *psecdesc_buf = result;
348         return NT_STATUS_OK;
349 }
350
351 /*******************************************************************
352  Creates a struct security_descriptor structure with typical defaults.
353 ********************************************************************/
354
355 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
356                                  struct security_acl *dacl, size_t *sd_size)
357 {
358         return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
359                              SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
360                              dacl, sd_size);
361 }
362
363 /*******************************************************************
364  Creates a struct sec_desc_buf structure.
365 ********************************************************************/
366
367 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
368 {
369         struct sec_desc_buf *dst;
370
371         if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL)
372                 return NULL;
373
374         /* max buffer size (allocated size) */
375         dst->sd_size = (uint32_t)len;
376
377         if (sec_desc != NULL) {
378                 dst->sd = security_descriptor_copy(ctx, sec_desc);
379                 if (dst->sd == NULL) {
380                         return NULL;
381                 }
382         }
383
384         return dst;
385 }
386
387 /*******************************************************************
388  Duplicates a struct sec_desc_buf structure.
389 ********************************************************************/
390
391 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
392 {
393         if(src == NULL)
394                 return NULL;
395
396         return make_sec_desc_buf( ctx, src->sd_size, src->sd);
397 }
398
399 /*
400  * Determine if an struct security_ace is inheritable
401  */
402
403 static bool is_inheritable_ace(const struct security_ace *ace,
404                                 bool container)
405 {
406         if (!container) {
407                 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
408         }
409
410         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
411                 return true;
412         }
413
414         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
415                         !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
416                 return true;
417         }
418
419         return false;
420 }
421
422 /*
423  * Does a security descriptor have any inheritable components for
424  * the newly created type ?
425  */
426
427 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
428 {
429         unsigned int i;
430         const struct security_acl *the_acl = parent_ctr->dacl;
431
432         if (the_acl == NULL) {
433                 return false;
434         }
435
436         for (i = 0; i < the_acl->num_aces; i++) {
437                 const struct security_ace *ace = &the_acl->aces[i];
438
439                 if (is_inheritable_ace(ace, container)) {
440                         return true;
441                 }
442         }
443         return false;
444 }
445
446 /* Create a child security descriptor using another security descriptor as
447    the parent container.  This child object can either be a container or
448    non-container object. */
449
450 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
451                                         struct security_descriptor **ppsd,
452                                         size_t *psize,
453                                         const struct security_descriptor *parent_ctr,
454                                         const struct dom_sid *owner_sid,
455                                         const struct dom_sid *group_sid,
456                                         bool container)
457 {
458         struct security_acl *new_dacl = NULL, *the_acl = NULL;
459         struct security_ace *new_ace_list = NULL;
460         unsigned int new_ace_list_ndx = 0, i;
461         bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED);
462
463         TALLOC_CTX *frame;
464
465         *ppsd = NULL;
466         *psize = 0;
467
468         /* Currently we only process the dacl when creating the child.  The
469            sacl should also be processed but this is left out as sacls are
470            not implemented in Samba at the moment.*/
471
472         the_acl = parent_ctr->dacl;
473
474         if (the_acl->num_aces) {
475                 if (2*the_acl->num_aces < the_acl->num_aces) {
476                         return NT_STATUS_NO_MEMORY;
477                 }
478
479                 if (!(new_ace_list = talloc_array(ctx, struct security_ace,
480                                                   2*the_acl->num_aces))) {
481                         return NT_STATUS_NO_MEMORY;
482                 }
483         } else {
484                 new_ace_list = NULL;
485         }
486
487         frame = talloc_stackframe();
488
489         for (i = 0; i < the_acl->num_aces; i++) {
490                 const struct security_ace *ace = &the_acl->aces[i];
491                 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
492                 const struct dom_sid *ptrustee = &ace->trustee;
493                 const struct dom_sid *creator = NULL;
494                 uint8_t new_flags = ace->flags;
495                 struct dom_sid_buf sidbuf1, sidbuf2;
496
497                 if (!is_inheritable_ace(ace, container)) {
498                         continue;
499                 }
500
501                 /* see the RAW-ACLS inheritance test for details on these rules */
502                 if (!container) {
503                         new_flags = 0;
504                 } else {
505                         /*
506                          * We need to remove SEC_ACE_FLAG_INHERITED_ACE here
507                          * if present because it should only be set if the
508                          * parent has the AUTO_INHERITED bit set in the
509                          * type/control field. If we don't it will slip through
510                          * and create DACLs with incorrectly ordered ACEs
511                          * when there are CREATOR_OWNER or CREATOR_GROUP
512                          * ACEs.
513                          */
514                         new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY
515                                         | SEC_ACE_FLAG_INHERITED_ACE);
516
517                         if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
518                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
519                         }
520                         if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
521                                 new_flags = 0;
522                         }
523                 }
524
525                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
526                         creator = &ace->trustee;
527                         ptrustee = &ace->trustee;
528                 }
529
530                 /* The CREATOR sids are special when inherited */
531                 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
532                         creator = &global_sid_Creator_Owner;
533                         ptrustee = owner_sid;
534                 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
535                         creator = &global_sid_Creator_Group;
536                         ptrustee = group_sid;
537                 }
538
539                 if (creator && container &&
540                                 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
541
542                         /* First add the regular ACE entry. */
543                         init_sec_ace(new_ace, ptrustee, ace->type,
544                                 ace->access_mask,
545                                 set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
546
547                         DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
548                                  " inherited as %s:%d/0x%02x/0x%08x\n",
549                                  dom_sid_str_buf(&ace->trustee, &sidbuf1),
550                                  ace->type, ace->flags, ace->access_mask,
551                                  dom_sid_str_buf(&new_ace->trustee, &sidbuf2),
552                                  new_ace->type, new_ace->flags,
553                                  new_ace->access_mask));
554
555                         new_ace_list_ndx++;
556
557                         /* Now add the extra creator ACE. */
558                         new_ace = &new_ace_list[new_ace_list_ndx];
559
560                         ptrustee = creator;
561                         new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
562
563                 } else if (container &&
564                                 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
565                         ptrustee = &ace->trustee;
566                 }
567
568                 init_sec_ace(new_ace, ptrustee, ace->type,
569                              ace->access_mask, new_flags |
570                                 (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
571
572                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
573                           " inherited as %s:%d/0x%02x/0x%08x\n",
574                           dom_sid_str_buf(&ace->trustee, &sidbuf1),
575                           ace->type, ace->flags, ace->access_mask,
576                           dom_sid_str_buf(&new_ace->trustee, &sidbuf2),
577                           new_ace->type, new_ace->flags,
578                           new_ace->access_mask));
579
580                 new_ace_list_ndx++;
581         }
582
583         talloc_free(frame);
584
585         /*
586          * remove duplicates
587          */
588         for (i=1; i < new_ace_list_ndx;) {
589                 struct security_ace *ai = &new_ace_list[i];
590                 unsigned int remaining, j;
591                 bool remove_ace = false;
592
593                 for (j=0; j < i; j++) {
594                         struct security_ace *aj = &new_ace_list[j];
595
596                         if (!security_ace_equal(ai, aj)) {
597                                 continue;
598                         }
599
600                         remove_ace = true;
601                         break;
602                 }
603
604                 if (!remove_ace) {
605                         i++;
606                         continue;
607                 }
608
609                 new_ace_list_ndx--;
610                 remaining = new_ace_list_ndx - i;
611                 if (remaining == 0) {
612                         ZERO_STRUCT(new_ace_list[i]);
613                         continue;
614                 }
615                 memmove(&new_ace_list[i], &new_ace_list[i+1],
616                         sizeof(new_ace_list[i]) * remaining);
617         }
618
619         /* Create child security descriptor to return */
620         if (new_ace_list_ndx) {
621                 new_dacl = make_sec_acl(ctx,
622                                 NT4_ACL_REVISION,
623                                 new_ace_list_ndx,
624                                 new_ace_list);
625
626                 if (!new_dacl) {
627                         return NT_STATUS_NO_MEMORY;
628                 }
629         }
630
631         security_acl_map_generic(new_dacl, &file_generic_mapping);
632
633         *ppsd = make_sec_desc(ctx,
634                         SECURITY_DESCRIPTOR_REVISION_1,
635                         SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
636                                 (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
637                         owner_sid,
638                         group_sid,
639                         NULL,
640                         new_dacl,
641                         psize);
642         if (!*ppsd) {
643                 return NT_STATUS_NO_MEMORY;
644         }
645         return NT_STATUS_OK;
646 }