libcli/smb: Fix failure of Smb3UnixTests.test_create_context_reparse
[Samba.git] / libcli / security / secdesc.c
blobcb8037cc3cf87c73aa08ce871db1b482bf8718ef
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.
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.
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.
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/>.
23 #include "replace.h"
24 #include "lib/util/debug.h"
25 #include "lib/util/fault.h"
26 #include "librpc/gen_ndr/ndr_security.h"
27 #include "libcli/security/security.h"
29 /* Map generic permissions to file object specific permissions */
31 const struct generic_mapping file_generic_mapping = {
32 FILE_GENERIC_READ,
33 FILE_GENERIC_WRITE,
34 FILE_GENERIC_EXECUTE,
35 FILE_GENERIC_ALL
38 /*******************************************************************
39 Given a security_descriptor return the sec_info.
40 ********************************************************************/
42 uint32_t get_sec_info(const struct security_descriptor *sd)
44 uint32_t sec_info = 0;
46 SMB_ASSERT(sd);
48 if (sd->owner_sid != NULL) {
49 sec_info |= SECINFO_OWNER;
51 if (sd->group_sid != NULL) {
52 sec_info |= SECINFO_GROUP;
54 if (sd->sacl != NULL) {
55 sec_info |= SECINFO_SACL;
57 if (sd->dacl != NULL) {
58 sec_info |= SECINFO_DACL;
61 if (sd->type & SEC_DESC_SACL_PROTECTED) {
62 sec_info |= SECINFO_PROTECTED_SACL;
63 } else if (sd->type & SEC_DESC_SACL_AUTO_INHERITED) {
64 sec_info |= SECINFO_UNPROTECTED_SACL;
66 if (sd->type & SEC_DESC_DACL_PROTECTED) {
67 sec_info |= SECINFO_PROTECTED_DACL;
68 } else if (sd->type & SEC_DESC_DACL_AUTO_INHERITED) {
69 sec_info |= SECINFO_UNPROTECTED_DACL;
72 return sec_info;
76 /*******************************************************************
77 Merge part of security descriptor old_sec in to the empty sections of
78 security descriptor new_sec.
79 ********************************************************************/
81 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
83 struct dom_sid *owner_sid, *group_sid;
84 struct sec_desc_buf *return_sdb;
85 struct security_acl *dacl, *sacl;
86 struct security_descriptor *psd = NULL;
87 uint16_t secdesc_type;
88 size_t secdesc_size;
90 /* Copy over owner and group sids. There seems to be no flag for
91 this so just check the pointer values. */
93 owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
94 old_sdb->sd->owner_sid;
96 group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
97 old_sdb->sd->group_sid;
99 secdesc_type = new_sdb->sd->type;
101 /* Ignore changes to the system ACL. This has the effect of making
102 changes through the security tab audit button not sticking.
103 Perhaps in future Samba could implement these settings somehow. */
105 sacl = NULL;
106 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
108 /* Copy across discretionary ACL */
110 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
111 dacl = new_sdb->sd->dacl;
112 } else {
113 dacl = old_sdb->sd->dacl;
116 /* Create new security descriptor from bits */
118 psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
119 owner_sid, group_sid, sacl, dacl, &secdesc_size);
121 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
123 return(return_sdb);
126 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
128 struct dom_sid *owner_sid, *group_sid;
129 struct security_acl *dacl, *sacl;
130 struct security_descriptor *psd = NULL;
131 uint16_t secdesc_type;
132 size_t secdesc_size;
134 /* Copy over owner and group sids. There seems to be no flag for
135 this so just check the pointer values. */
137 owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
138 old_sdb->owner_sid;
140 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
141 old_sdb->group_sid;
143 secdesc_type = new_sdb->type;
145 /* Ignore changes to the system ACL. This has the effect of making
146 changes through the security tab audit button not sticking.
147 Perhaps in future Samba could implement these settings somehow. */
149 sacl = NULL;
150 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
152 /* Copy across discretionary ACL */
154 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
155 dacl = new_sdb->dacl;
156 } else {
157 dacl = old_sdb->dacl;
160 /* Create new security descriptor from bits */
161 psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
162 owner_sid, group_sid, sacl, dacl, &secdesc_size);
164 return psd;
167 /*******************************************************************
168 Creates a struct security_descriptor structure
169 ********************************************************************/
170 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
171 enum security_descriptor_revision revision,
172 uint16_t type,
173 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
174 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
176 struct security_descriptor *dst;
178 if (sd_size != NULL) {
179 *sd_size = 0;
182 dst = security_descriptor_initialise(ctx);
183 if (dst == NULL) {
184 return NULL;
187 dst->revision = revision;
188 dst->type = type;
190 if (sacl != NULL) {
191 dst->sacl = security_acl_dup(dst, sacl);
192 if (dst->sacl == NULL) {
193 goto err_sd_free;
195 dst->type |= SEC_DESC_SACL_PRESENT;
198 if (dacl != NULL) {
199 dst->dacl = security_acl_dup(dst, dacl);
200 if (dst->dacl == NULL) {
201 goto err_sd_free;
203 dst->type |= SEC_DESC_DACL_PRESENT;
206 if (owner_sid != NULL) {
207 dst->owner_sid = dom_sid_dup(dst, owner_sid);
208 if (dst->owner_sid == NULL) {
209 goto err_sd_free;
213 if (grp_sid != NULL) {
214 dst->group_sid = dom_sid_dup(dst, grp_sid);
215 if (dst->group_sid == NULL) {
216 goto err_sd_free;
220 if (sd_size != NULL) {
221 *sd_size = ndr_size_security_descriptor(dst, 0);
224 return dst;
226 err_sd_free:
227 talloc_free(dst);
228 return NULL;
231 /*******************************************************************
232 Convert a secdesc into a byte stream
233 ********************************************************************/
234 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
235 const struct security_descriptor *secdesc,
236 uint8_t **data, size_t *len)
238 DATA_BLOB blob;
239 enum ndr_err_code ndr_err;
241 ndr_err = ndr_push_struct_blob(
242 &blob, mem_ctx, secdesc,
243 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
245 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
246 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
247 ndr_errstr(ndr_err)));
248 return ndr_map_error2ntstatus(ndr_err);
251 *data = blob.data;
252 *len = blob.length;
253 return NT_STATUS_OK;
256 /*******************************************************************
257 Convert a secdesc_buf into a byte stream
258 ********************************************************************/
260 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
261 const struct sec_desc_buf *secdesc_buf,
262 uint8_t **data, size_t *len)
264 DATA_BLOB blob;
265 enum ndr_err_code ndr_err;
267 ndr_err = ndr_push_struct_blob(
268 &blob, mem_ctx, secdesc_buf,
269 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
271 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
272 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
273 ndr_errstr(ndr_err)));
274 return ndr_map_error2ntstatus(ndr_err);
277 *data = blob.data;
278 *len = blob.length;
279 return NT_STATUS_OK;
282 /*******************************************************************
283 Parse a byte stream into a secdesc
284 ********************************************************************/
285 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
286 struct security_descriptor **psecdesc)
288 DATA_BLOB blob;
289 enum ndr_err_code ndr_err;
290 struct security_descriptor *result;
292 if ((data == NULL) || (len == 0)) {
293 return NT_STATUS_INVALID_PARAMETER;
296 result = talloc_zero(mem_ctx, struct security_descriptor);
297 if (result == NULL) {
298 return NT_STATUS_NO_MEMORY;
301 blob = data_blob_const(data, len);
303 ndr_err = ndr_pull_struct_blob(&blob, result, result,
304 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
306 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
307 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
308 ndr_errstr(ndr_err)));
309 TALLOC_FREE(result);
310 return ndr_map_error2ntstatus(ndr_err);
313 *psecdesc = result;
314 return NT_STATUS_OK;
317 /*******************************************************************
318 Parse a byte stream into a sec_desc_buf
319 ********************************************************************/
321 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
322 struct sec_desc_buf **psecdesc_buf)
324 DATA_BLOB blob;
325 enum ndr_err_code ndr_err;
326 struct sec_desc_buf *result;
328 if ((data == NULL) || (len == 0)) {
329 return NT_STATUS_INVALID_PARAMETER;
332 result = talloc_zero(mem_ctx, struct sec_desc_buf);
333 if (result == NULL) {
334 return NT_STATUS_NO_MEMORY;
337 blob = data_blob_const(data, len);
339 ndr_err = ndr_pull_struct_blob(&blob, result, result,
340 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
342 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
343 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
344 ndr_errstr(ndr_err)));
345 TALLOC_FREE(result);
346 return ndr_map_error2ntstatus(ndr_err);
349 *psecdesc_buf = result;
350 return NT_STATUS_OK;
353 /*******************************************************************
354 Creates a struct security_descriptor structure with typical defaults.
355 ********************************************************************/
357 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
358 struct security_acl *dacl, size_t *sd_size)
360 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
361 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
362 dacl, sd_size);
365 /*******************************************************************
366 Creates a struct sec_desc_buf structure.
367 ********************************************************************/
369 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
371 struct sec_desc_buf *dst;
373 if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL)
374 return NULL;
376 /* max buffer size (allocated size) */
377 dst->sd_size = (uint32_t)len;
379 if (sec_desc != NULL) {
380 dst->sd = security_descriptor_copy(ctx, sec_desc);
381 if (dst->sd == NULL) {
382 return NULL;
386 return dst;
390 * Determine if an struct security_ace is inheritable
393 static bool is_inheritable_ace(const struct security_ace *ace,
394 bool container)
396 if (!container) {
397 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
400 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
401 return true;
404 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
405 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
406 return true;
409 return false;
413 * Does a security descriptor have any inheritable components for
414 * the newly created type ?
417 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
419 unsigned int i;
420 const struct security_acl *the_acl = parent_ctr->dacl;
422 if (the_acl == NULL) {
423 return false;
426 for (i = 0; i < the_acl->num_aces; i++) {
427 const struct security_ace *ace = &the_acl->aces[i];
429 if (is_inheritable_ace(ace, container)) {
430 return true;
433 return false;
436 /* Create a child security descriptor using another security descriptor as
437 the parent container. This child object can either be a container or
438 non-container object. */
440 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
441 struct security_descriptor **ppsd,
442 size_t *psize,
443 const struct security_descriptor *parent_ctr,
444 const struct dom_sid *owner_sid,
445 const struct dom_sid *group_sid,
446 bool container)
448 struct security_acl *new_dacl = NULL, *the_acl = NULL;
449 struct security_ace *new_ace_list = NULL;
450 unsigned int new_ace_list_ndx = 0, i;
451 bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED);
453 *ppsd = NULL;
454 *psize = 0;
456 /* Currently we only process the dacl when creating the child. The
457 sacl should also be processed but this is left out as sacls are
458 not implemented in Samba at the moment.*/
460 the_acl = parent_ctr->dacl;
462 if (the_acl->num_aces) {
463 if (2*the_acl->num_aces < the_acl->num_aces) {
464 return NT_STATUS_NO_MEMORY;
467 if (!(new_ace_list = talloc_array(ctx, struct security_ace,
468 2*the_acl->num_aces))) {
469 return NT_STATUS_NO_MEMORY;
471 } else {
472 new_ace_list = NULL;
475 for (i = 0; i < the_acl->num_aces; i++) {
476 const struct security_ace *ace = &the_acl->aces[i];
477 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
478 const struct dom_sid *ptrustee = &ace->trustee;
479 const struct dom_sid *creator = NULL;
480 uint8_t new_flags = ace->flags;
481 struct dom_sid_buf sidbuf1, sidbuf2;
483 if (!is_inheritable_ace(ace, container)) {
484 continue;
487 /* see the RAW-ACLS inheritance test for details on these rules */
488 if (!container) {
489 new_flags = 0;
490 } else {
492 * We need to remove SEC_ACE_FLAG_INHERITED_ACE here
493 * if present because it should only be set if the
494 * parent has the AUTO_INHERITED bit set in the
495 * type/control field. If we don't it will slip through
496 * and create DACLs with incorrectly ordered ACEs
497 * when there are CREATOR_OWNER or CREATOR_GROUP
498 * ACEs.
500 new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY
501 | SEC_ACE_FLAG_INHERITED_ACE);
503 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
504 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
506 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
507 new_flags = 0;
511 /* The CREATOR sids are special when inherited */
512 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
513 creator = &global_sid_Creator_Owner;
514 ptrustee = owner_sid;
515 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
516 creator = &global_sid_Creator_Group;
517 ptrustee = group_sid;
520 if (creator && container &&
521 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
523 /* First add the regular ACE entry. */
524 init_sec_ace(new_ace, ptrustee, ace->type,
525 ace->access_mask,
526 set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
528 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
529 " inherited as %s:%d/0x%02x/0x%08x\n",
530 dom_sid_str_buf(&ace->trustee, &sidbuf1),
531 ace->type, ace->flags, ace->access_mask,
532 dom_sid_str_buf(&new_ace->trustee, &sidbuf2),
533 new_ace->type, new_ace->flags,
534 new_ace->access_mask));
536 new_ace_list_ndx++;
538 /* Now add the extra creator ACE. */
539 new_ace = &new_ace_list[new_ace_list_ndx];
541 ptrustee = creator;
542 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
544 } else if (container &&
545 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
546 ptrustee = &ace->trustee;
549 init_sec_ace(new_ace, ptrustee, ace->type,
550 ace->access_mask, new_flags |
551 (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
553 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
554 " inherited as %s:%d/0x%02x/0x%08x\n",
555 dom_sid_str_buf(&ace->trustee, &sidbuf1),
556 ace->type, ace->flags, ace->access_mask,
557 dom_sid_str_buf(&new_ace->trustee, &sidbuf2),
558 new_ace->type, new_ace->flags,
559 new_ace->access_mask));
561 new_ace_list_ndx++;
565 * remove duplicates
567 for (i=1; i < new_ace_list_ndx;) {
568 struct security_ace *ai = &new_ace_list[i];
569 unsigned int remaining, j;
570 bool remove_ace = false;
572 for (j=0; j < i; j++) {
573 struct security_ace *aj = &new_ace_list[j];
575 if (!security_ace_equal(ai, aj)) {
576 continue;
579 remove_ace = true;
580 break;
583 if (!remove_ace) {
584 i++;
585 continue;
588 new_ace_list_ndx--;
589 remaining = new_ace_list_ndx - i;
590 if (remaining == 0) {
591 ZERO_STRUCT(new_ace_list[i]);
592 continue;
594 memmove(&new_ace_list[i], &new_ace_list[i+1],
595 sizeof(new_ace_list[i]) * remaining);
598 /* Create child security descriptor to return */
599 if (new_ace_list_ndx) {
600 new_dacl = make_sec_acl(ctx,
601 NT4_ACL_REVISION,
602 new_ace_list_ndx,
603 new_ace_list);
605 if (!new_dacl) {
606 return NT_STATUS_NO_MEMORY;
610 *ppsd = make_sec_desc(ctx,
611 SECURITY_DESCRIPTOR_REVISION_1,
612 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
613 (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
614 owner_sid,
615 group_sid,
616 NULL,
617 new_dacl,
618 psize);
619 if (!*ppsd) {
620 return NT_STATUS_NO_MEMORY;
622 return NT_STATUS_OK;