Restructure the ACL code some more, get the internal semantics
[Samba/fernandojvsilva.git] / source3 / modules / vfs_acl_common.c
blob570d14b4b2c3df35fd7c30846bd6b3be00163b4a
1 /*
2 * Store Windows ACLs in data store - common functions.
3 * #included into modules/vfs_acl_xattr.c and modules/vfs_acl_tdb.c
5 * Copyright (C) Volker Lendecke, 2008
6 * Copyright (C) Jeremy Allison, 2009
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
23 DATA_BLOB *pblob,
24 uint16_t hash_type,
25 uint8_t hash[XATTR_SD_HASH_SIZE]);
27 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
28 vfs_handle_struct *handle,
29 files_struct *fsp,
30 const char *name,
31 DATA_BLOB *pblob);
33 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
34 files_struct *fsp,
35 DATA_BLOB *pblob);
37 static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
38 const char *fname,
39 DATA_BLOB *pblob);
41 #define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
42 GROUP_SECURITY_INFORMATION | \
43 DACL_SECURITY_INFORMATION | \
44 SACL_SECURITY_INFORMATION)
46 /*******************************************************************
47 Hash a security descriptor.
48 *******************************************************************/
50 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
51 uint8_t *hash)
53 DATA_BLOB blob;
54 SHA256_CTX tctx;
55 NTSTATUS status;
57 memset(hash, '\0', XATTR_SD_HASH_SIZE);
58 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
59 if (!NT_STATUS_IS_OK(status)) {
60 return status;
63 SHA256_Init(&tctx);
64 SHA256_Update(&tctx, blob.data, blob.length);
65 SHA256_Final(hash, &tctx);
67 return NT_STATUS_OK;
70 /*******************************************************************
71 Parse out a struct security_descriptor from a DATA_BLOB.
72 *******************************************************************/
74 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
75 struct security_descriptor **ppdesc,
76 uint16_t *p_hash_type,
77 uint8_t hash[XATTR_SD_HASH_SIZE])
79 TALLOC_CTX *ctx = talloc_tos();
80 struct xattr_NTACL xacl;
81 enum ndr_err_code ndr_err;
82 size_t sd_size;
84 ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
85 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
87 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
88 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
89 ndr_errstr(ndr_err)));
90 return ndr_map_error2ntstatus(ndr_err);;
93 switch (xacl.version) {
94 case 2:
95 *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
96 xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
97 xacl.info.sd_hs2->sd->owner_sid,
98 xacl.info.sd_hs2->sd->group_sid,
99 xacl.info.sd_hs2->sd->sacl,
100 xacl.info.sd_hs2->sd->dacl,
101 &sd_size);
102 /* No hash - null out. */
103 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
104 memset(hash, '\0', XATTR_SD_HASH_SIZE);
105 break;
106 case 3:
107 *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
108 xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
109 xacl.info.sd_hs3->sd->owner_sid,
110 xacl.info.sd_hs3->sd->group_sid,
111 xacl.info.sd_hs3->sd->sacl,
112 xacl.info.sd_hs3->sd->dacl,
113 &sd_size);
114 *p_hash_type = xacl.info.sd_hs3->hash_type;
115 /* Current version 3. */
116 memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
117 break;
118 default:
119 return NT_STATUS_REVISION_MISMATCH;
122 TALLOC_FREE(xacl.info.sd);
124 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
127 /*******************************************************************
128 Create a DATA_BLOB from a security descriptor.
129 *******************************************************************/
131 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
132 DATA_BLOB *pblob,
133 uint16_t hash_type,
134 uint8_t hash[XATTR_SD_HASH_SIZE])
136 struct xattr_NTACL xacl;
137 struct security_descriptor_hash_v3 sd_hs3;
138 enum ndr_err_code ndr_err;
139 TALLOC_CTX *ctx = talloc_tos();
141 ZERO_STRUCT(xacl);
142 ZERO_STRUCT(sd_hs3);
144 xacl.version = 3;
145 xacl.info.sd_hs3 = &sd_hs3;
146 xacl.info.sd_hs3->sd = CONST_DISCARD(struct security_descriptor *, psd);
147 xacl.info.sd_hs3->hash_type = hash_type;
148 memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
150 ndr_err = ndr_push_struct_blob(
151 pblob, ctx, NULL, &xacl,
152 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
154 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
155 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
156 ndr_errstr(ndr_err)));
157 return ndr_map_error2ntstatus(ndr_err);;
160 return NT_STATUS_OK;
163 /*******************************************************************
164 Pull a DATA_BLOB from an xattr given a pathname.
165 If the hash doesn't match, or doesn't exist - return the underlying
166 filesystem sd.
167 *******************************************************************/
169 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
170 files_struct *fsp,
171 const char *name,
172 uint32_t security_info,
173 struct security_descriptor **ppdesc)
175 DATA_BLOB blob;
176 NTSTATUS status;
177 uint16_t hash_type;
178 uint8_t hash[XATTR_SD_HASH_SIZE];
179 uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
180 struct security_descriptor *psd = NULL;
181 struct security_descriptor *pdesc_next = NULL;
183 if (fsp && name == NULL) {
184 name = fsp->fsp_name->base_name;
187 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
189 /* Get the full underlying sd for the hash
190 or to return as backup. */
191 if (fsp) {
192 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
193 fsp,
194 HASH_SECURITY_INFO,
195 &pdesc_next);
196 } else {
197 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
198 name,
199 HASH_SECURITY_INFO,
200 &pdesc_next);
203 if (!NT_STATUS_IS_OK(status)) {
204 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
205 "returned %s\n",
206 name,
207 nt_errstr(status)));
208 return status;
211 status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
212 if (!NT_STATUS_IS_OK(status)) {
213 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
214 nt_errstr(status)));
215 psd = pdesc_next;
216 goto out;
219 status = parse_acl_blob(&blob, &psd,
220 &hash_type, &hash[0]);
221 if (!NT_STATUS_IS_OK(status)) {
222 DEBUG(10, ("parse_acl_blob returned %s\n",
223 nt_errstr(status)));
224 psd = pdesc_next;
225 goto out;
228 /* Ensure the hash type is one we know. */
229 switch (hash_type) {
230 case XATTR_SD_HASH_TYPE_NONE:
231 /* No hash, just return blob sd. */
232 goto out;
233 case XATTR_SD_HASH_TYPE_SHA256:
234 break;
235 default:
236 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
237 "mismatch (%u) for file %s\n",
238 (unsigned int)hash_type,
239 name));
240 TALLOC_FREE(psd);
241 psd = pdesc_next;
242 goto out;
246 status = hash_sd_sha256(pdesc_next, hash_tmp);
247 if (!NT_STATUS_IS_OK(status)) {
248 TALLOC_FREE(psd);
249 psd = pdesc_next;
250 goto out;
253 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
254 /* Hash matches, return blob sd. */
255 goto out;
258 /* Hash doesn't match, return underlying sd. */
259 TALLOC_FREE(psd);
260 psd = pdesc_next;
262 out:
264 if (psd != pdesc_next) {
265 /* We're returning the blob, throw
266 * away the filesystem SD. */
267 TALLOC_FREE(pdesc_next);
270 if (!(security_info & OWNER_SECURITY_INFORMATION)) {
271 psd->owner_sid = NULL;
273 if (!(security_info & GROUP_SECURITY_INFORMATION)) {
274 psd->group_sid = NULL;
276 if (!(security_info & DACL_SECURITY_INFORMATION)) {
277 psd->dacl = NULL;
279 if (!(security_info & SACL_SECURITY_INFORMATION)) {
280 psd->sacl = NULL;
283 TALLOC_FREE(blob.data);
284 *ppdesc = psd;
285 return NT_STATUS_OK;
288 #if 0
289 /*********************************************************************
290 Create a default security descriptor for a file in case no inheritance
291 exists. All permissions to the owner and SYSTEM.
292 *********************************************************************/
294 static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx,
295 SMB_STRUCT_STAT *psbuf,
296 bool force_inherit)
298 struct dom_sid owner_sid, group_sid;
299 size_t sd_size;
300 struct security_ace *pace = NULL;
301 struct security_acl *pacl = NULL;
303 uid_to_sid(&owner_sid, psbuf->st_ex_uid);
304 gid_to_sid(&group_sid, psbuf->st_ex_gid);
306 pace = TALLOC_ARRAY(mem_ctx, struct security_ace, 2);
307 if (!pace) {
308 return NULL;
311 /* If force_inherit is set, this means we are initializing the ACEs for
312 * a container and we want the ACEs for owner_sid and "SYSTEM" to be
313 * inheritable by their children (See Bug #6802).
316 init_sec_ace(&pace[0], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
317 SEC_RIGHTS_FILE_ALL, (force_inherit ?
318 (SEC_ACE_FLAG_OBJECT_INHERIT|
319 SEC_ACE_FLAG_CONTAINER_INHERIT) :
320 0));
322 init_sec_ace(&pace[1], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
323 SEC_RIGHTS_FILE_ALL, (force_inherit ?
324 (SEC_ACE_FLAG_OBJECT_INHERIT|
325 SEC_ACE_FLAG_CONTAINER_INHERIT) :
326 0));
328 pacl = make_sec_acl(mem_ctx,
329 NT4_ACL_REVISION,
331 pace);
332 if (!pacl) {
333 return NULL;
335 return make_sec_desc(mem_ctx,
336 SECURITY_DESCRIPTOR_REVISION_1,
337 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
338 &owner_sid,
339 &group_sid,
340 NULL,
341 pacl,
342 &sd_size);
344 #endif
346 /*********************************************************************
347 Create a default ACL by inheriting from the parent. If no inheritance
348 from the parent available, just use the actual permissions the new
349 file or directory already got from the filesystem.
350 *********************************************************************/
352 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
353 struct smb_filename *smb_fname,
354 files_struct *fsp,
355 struct security_descriptor *parent_desc,
356 bool is_directory)
358 TALLOC_CTX *ctx = talloc_tos();
359 NTSTATUS status = NT_STATUS_OK;
360 struct security_descriptor *psd = NULL;
361 struct security_descriptor *pdesc_next = NULL;
362 DATA_BLOB blob;
363 size_t size;
364 uint8_t hash[XATTR_SD_HASH_SIZE];
366 if (parent_desc == NULL) {
367 /* We don't already have the parent sd, fetch it now. */
368 char *parent_name;
370 if (!parent_dirname(ctx, smb_fname->base_name, &parent_name, NULL)) {
371 return NT_STATUS_NO_MEMORY;
374 DEBUG(10,("inherit_new_acl: check directory %s\n",
375 parent_name));
377 status = get_nt_acl_internal(handle,
378 NULL,
379 parent_name,
380 (OWNER_SECURITY_INFORMATION |
381 GROUP_SECURITY_INFORMATION |
382 DACL_SECURITY_INFORMATION),
383 &parent_desc);
385 if (!NT_STATUS_IS_OK(status)) {
386 DEBUG(10,("inherit_new_acl: directory %s failed "
387 "to get acl BLOB %s\n",
388 parent_name,
389 nt_errstr(status) ));
390 return status;
395 * Object must exist. Read the current SD off the filesystem
396 * for the hash.
398 if (fsp) {
399 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
400 fsp,
401 HASH_SECURITY_INFO,
402 &pdesc_next);
403 } else {
404 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
405 smb_fname->base_name,
406 HASH_SECURITY_INFO,
407 &pdesc_next);
410 if (!NT_STATUS_IS_OK(status)) {
411 DEBUG(10,("inherit_new_acl: get_next_acl \n"
412 "failed for %s (%s)\n",
413 smb_fname_str_dbg(smb_fname),
414 nt_errstr(status) ));
415 return status;
418 if (parent_desc && sd_has_inheritable_components(parent_desc, is_directory)) {
419 /* Create an inherited descriptor from the parent. */
421 if (DEBUGLEVEL >= 10) {
422 DEBUG(10,("inherit_new_acl: parent acl is:\n"));
423 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
426 status = se_create_child_secdesc(ctx,
427 &psd,
428 &size,
429 parent_desc,
430 &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
431 &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
432 is_directory);
433 if (!NT_STATUS_IS_OK(status)) {
434 return status;
437 } else {
438 DEBUG(10,("inherit_new_acl: using current permissions.\n"
439 "to set Windows acl for %s\n",
440 smb_fname_str_dbg(smb_fname) ));
441 psd = pdesc_next;
444 if (DEBUGLEVEL >= 10) {
445 DEBUG(10,("inherit_new_acl: child acl is:\n"));
446 NDR_PRINT_DEBUG(security_descriptor, psd);
449 status = hash_sd_sha256(pdesc_next, hash);
450 if (!NT_STATUS_IS_OK(status)) {
451 return status;
453 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
454 if (!NT_STATUS_IS_OK(status)) {
455 return status;
457 if (fsp) {
458 return store_acl_blob_fsp(handle, fsp, &blob);
459 } else {
460 return store_acl_blob_pathname(handle, smb_fname->base_name,
461 &blob);
465 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
466 const char *path,
467 uint32_t access_mask,
468 struct security_descriptor **pp_parent_desc)
470 char *parent_name = NULL;
471 struct security_descriptor *parent_desc = NULL;
472 uint32_t access_granted = 0;
473 NTSTATUS status;
475 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
476 return NT_STATUS_NO_MEMORY;
479 status = get_nt_acl_internal(handle,
480 NULL,
481 parent_name,
482 (OWNER_SECURITY_INFORMATION |
483 GROUP_SECURITY_INFORMATION |
484 DACL_SECURITY_INFORMATION),
485 &parent_desc);
487 if (!NT_STATUS_IS_OK(status)) {
488 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
489 "on directory %s for "
490 "path %s returned %s\n",
491 parent_name,
492 path,
493 nt_errstr(status) ));
494 return status;
496 status = smb1_file_se_access_check(parent_desc,
497 handle->conn->server_info->ptok,
498 access_mask,
499 &access_granted);
500 if(!NT_STATUS_IS_OK(status)) {
501 DEBUG(10,("check_parent_acl_common: access check "
502 "on directory %s for "
503 "path %s for mask 0x%x returned %s\n",
504 parent_name,
505 path,
506 access_mask,
507 nt_errstr(status) ));
508 return status;
510 if (pp_parent_desc) {
511 *pp_parent_desc = parent_desc;
513 return NT_STATUS_OK;
516 /*********************************************************************
517 Check ACL on open. For new files inherit from parent directory.
518 *********************************************************************/
520 static int open_acl_common(vfs_handle_struct *handle,
521 struct smb_filename *smb_fname,
522 files_struct *fsp,
523 int flags,
524 mode_t mode)
526 uint32_t access_granted = 0;
527 struct security_descriptor *pdesc = NULL;
528 struct security_descriptor *parent_desc = NULL;
529 bool file_existed = true;
530 char *fname = NULL;
531 NTSTATUS status;
533 if (fsp->base_fsp) {
534 /* Stream open. Base filename open already did the ACL check. */
535 DEBUG(10,("open_acl_common: stream open on %s\n",
536 smb_fname_str_dbg(smb_fname) ));
537 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
540 status = get_full_smb_filename(talloc_tos(), smb_fname,
541 &fname);
542 if (!NT_STATUS_IS_OK(status)) {
543 goto err;
546 status = get_nt_acl_internal(handle,
547 NULL,
548 fname,
549 (OWNER_SECURITY_INFORMATION |
550 GROUP_SECURITY_INFORMATION |
551 DACL_SECURITY_INFORMATION),
552 &pdesc);
553 if (NT_STATUS_IS_OK(status)) {
554 /* See if we can access it. */
555 status = smb1_file_se_access_check(pdesc,
556 handle->conn->server_info->ptok,
557 fsp->access_mask,
558 &access_granted);
559 if (!NT_STATUS_IS_OK(status)) {
560 DEBUG(10,("open_acl_xattr: file %s open "
561 "refused with error %s\n",
562 smb_fname_str_dbg(smb_fname),
563 nt_errstr(status) ));
564 goto err;
566 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
567 file_existed = false;
569 * If O_CREAT is true then we're trying to create a file.
570 * Check the parent directory ACL will allow this.
572 if (flags & O_CREAT) {
573 status = check_parent_acl_common(handle, fname,
574 SEC_DIR_ADD_FILE, &parent_desc);
575 if (!NT_STATUS_IS_OK(status)) {
576 goto err;
581 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
582 "file %s returned %s\n",
583 smb_fname_str_dbg(smb_fname),
584 nt_errstr(status) ));
586 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
588 if (!file_existed && fsp->fh->fd != -1) {
589 /* File was created. Inherit from parent directory. */
590 status = fsp_set_smb_fname(fsp, smb_fname);
591 if (!NT_STATUS_IS_OK(status)) {
592 goto err;
594 inherit_new_acl(handle, smb_fname, fsp, parent_desc, false);
597 return fsp->fh->fd;
599 err:
601 errno = map_errno_from_nt_status(status);
602 return -1;
605 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
607 struct smb_filename *smb_fname = NULL;
608 int ret;
609 NTSTATUS status;
610 SMB_STRUCT_STAT sbuf;
611 struct security_descriptor *parent_desc = NULL;
613 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
614 if (ret == -1 && errno == ENOENT) {
615 /* We're creating a new directory. */
616 status = check_parent_acl_common(handle, path,
617 SEC_DIR_ADD_SUBDIR, &parent_desc);
618 if (!NT_STATUS_IS_OK(status)) {
619 errno = map_errno_from_nt_status(status);
620 return -1;
624 ret = SMB_VFS_NEXT_MKDIR(handle, path, mode);
625 if (ret == -1) {
626 return ret;
629 status = create_synthetic_smb_fname(talloc_tos(), path, NULL, NULL,
630 &smb_fname);
631 if (!NT_STATUS_IS_OK(status)) {
632 errno = map_errno_from_nt_status(status);
633 return -1;
636 /* New directory - inherit from parent. */
637 inherit_new_acl(handle, smb_fname, NULL, parent_desc, true);
638 TALLOC_FREE(smb_fname);
639 return ret;
642 /*********************************************************************
643 Fetch a security descriptor given an fsp.
644 *********************************************************************/
646 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
647 uint32_t security_info, struct security_descriptor **ppdesc)
649 return get_nt_acl_internal(handle, fsp,
650 NULL, security_info, ppdesc);
653 /*********************************************************************
654 Fetch a security descriptor given a pathname.
655 *********************************************************************/
657 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
658 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
660 return get_nt_acl_internal(handle, NULL,
661 name, security_info, ppdesc);
664 /*********************************************************************
665 Store a security descriptor given an fsp.
666 *********************************************************************/
668 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
669 uint32_t security_info_sent, const struct security_descriptor *psd)
671 NTSTATUS status;
672 DATA_BLOB blob;
673 struct security_descriptor *pdesc_next = NULL;
674 uint8_t hash[XATTR_SD_HASH_SIZE];
676 if (DEBUGLEVEL >= 10) {
677 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
678 fsp_str_dbg(fsp)));
679 NDR_PRINT_DEBUG(security_descriptor,
680 CONST_DISCARD(struct security_descriptor *,psd));
683 /* Ensure we have OWNER/GROUP/DACL set. */
685 if ((security_info_sent & (OWNER_SECURITY_INFORMATION|
686 GROUP_SECURITY_INFORMATION|
687 DACL_SECURITY_INFORMATION)) !=
688 (OWNER_SECURITY_INFORMATION|
689 GROUP_SECURITY_INFORMATION|
690 DACL_SECURITY_INFORMATION)) {
691 /* No we don't - read from the existing SD. */
692 struct security_descriptor *nc_psd = NULL;
694 status = get_nt_acl_internal(handle, fsp,
695 NULL,
696 (OWNER_SECURITY_INFORMATION|
697 GROUP_SECURITY_INFORMATION|
698 DACL_SECURITY_INFORMATION),
699 &nc_psd);
701 if (!NT_STATUS_IS_OK(status)) {
702 return status;
705 /* This is safe as nc_psd is discarded at fn exit. */
706 if (security_info_sent & OWNER_SECURITY_INFORMATION) {
707 nc_psd->owner_sid = psd->owner_sid;
709 security_info_sent |= OWNER_SECURITY_INFORMATION;
711 if (security_info_sent & GROUP_SECURITY_INFORMATION) {
712 nc_psd->group_sid = psd->group_sid;
714 security_info_sent |= GROUP_SECURITY_INFORMATION;
716 if (security_info_sent & DACL_SECURITY_INFORMATION) {
717 nc_psd->dacl = dup_sec_acl(talloc_tos(), psd->dacl);
718 if (nc_psd->dacl == NULL) {
719 return NT_STATUS_NO_MEMORY;
722 security_info_sent |= DACL_SECURITY_INFORMATION;
723 psd = nc_psd;
726 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
727 if (!NT_STATUS_IS_OK(status)) {
728 return status;
731 /* Get the full underlying sd, then hash. */
732 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
733 fsp,
734 HASH_SECURITY_INFO,
735 &pdesc_next);
737 if (!NT_STATUS_IS_OK(status)) {
738 return status;
741 status = hash_sd_sha256(pdesc_next, hash);
742 if (!NT_STATUS_IS_OK(status)) {
743 return status;
746 if (DEBUGLEVEL >= 10) {
747 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
748 fsp_str_dbg(fsp)));
749 NDR_PRINT_DEBUG(security_descriptor,
750 CONST_DISCARD(struct security_descriptor *,psd));
752 create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
753 store_acl_blob_fsp(handle, fsp, &blob);
755 return NT_STATUS_OK;
758 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
759 const char *fname, const char *mask, uint32 attr)
761 NTSTATUS status = check_parent_acl_common(handle, fname,
762 SEC_DIR_LIST, NULL);
764 if (!NT_STATUS_IS_OK(status)) {
765 errno = map_errno_from_nt_status(status);
766 return NULL;
768 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);