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 #include "../librpc/gen_ndr/ndr_security.h"
24 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
27 uint8_t hash[XATTR_SD_HASH_SIZE]);
29 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
30 vfs_handle_struct *handle,
35 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
39 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
44 /*******************************************************************
45 Hash a security descriptor.
46 *******************************************************************/
48 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
55 memset(hash, '\0', XATTR_SD_HASH_SIZE);
56 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
57 if (!NT_STATUS_IS_OK(status)) {
62 SHA256_Update(&tctx, blob.data, blob.length);
63 SHA256_Final(hash, &tctx);
68 /*******************************************************************
69 Parse out a struct security_descriptor from a DATA_BLOB.
70 *******************************************************************/
72 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
73 struct security_descriptor **ppdesc,
74 uint16_t *p_hash_type,
75 uint8_t hash[XATTR_SD_HASH_SIZE])
77 TALLOC_CTX *ctx = talloc_tos();
78 struct xattr_NTACL xacl;
79 enum ndr_err_code ndr_err;
82 ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
83 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
85 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
86 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
87 ndr_errstr(ndr_err)));
88 return ndr_map_error2ntstatus(ndr_err);;
91 switch (xacl.version) {
93 *ppdesc = make_sec_desc(ctx, SD_REVISION,
94 xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
95 xacl.info.sd_hs2->sd->owner_sid,
96 xacl.info.sd_hs2->sd->group_sid,
97 xacl.info.sd_hs2->sd->sacl,
98 xacl.info.sd_hs2->sd->dacl,
100 /* No hash - null out. */
101 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
102 memset(hash, '\0', XATTR_SD_HASH_SIZE);
105 *ppdesc = make_sec_desc(ctx, SD_REVISION,
106 xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
107 xacl.info.sd_hs3->sd->owner_sid,
108 xacl.info.sd_hs3->sd->group_sid,
109 xacl.info.sd_hs3->sd->sacl,
110 xacl.info.sd_hs3->sd->dacl,
112 *p_hash_type = xacl.info.sd_hs3->hash_type;
113 /* Current version 3. */
114 memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
117 return NT_STATUS_REVISION_MISMATCH;
120 TALLOC_FREE(xacl.info.sd);
122 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
125 /*******************************************************************
126 Create a DATA_BLOB from a security descriptor.
127 *******************************************************************/
129 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
132 uint8_t hash[XATTR_SD_HASH_SIZE])
134 struct xattr_NTACL xacl;
135 struct security_descriptor_hash_v3 sd_hs3;
136 enum ndr_err_code ndr_err;
137 TALLOC_CTX *ctx = talloc_tos();
143 xacl.info.sd_hs3 = &sd_hs3;
144 xacl.info.sd_hs3->sd = CONST_DISCARD(struct security_descriptor *, psd);
145 xacl.info.sd_hs3->hash_type = hash_type;
146 memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
148 ndr_err = ndr_push_struct_blob(
150 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
152 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
153 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
154 ndr_errstr(ndr_err)));
155 return ndr_map_error2ntstatus(ndr_err);;
161 /*******************************************************************
162 Add in 3 inheritable components for a non-inheritable directory ACL.
163 CREATOR_OWNER/CREATOR_GROUP/WORLD.
164 *******************************************************************/
166 static void add_directory_inheritable_components(vfs_handle_struct *handle,
168 SMB_STRUCT_STAT *psbuf,
169 struct security_descriptor *psd)
171 struct connection_struct *conn = handle->conn;
172 int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
173 struct smb_filename smb_fname;
174 enum security_ace_type acltype;
175 uint32_t access_mask;
179 struct security_ace *new_ace_list = TALLOC_ZERO_ARRAY(talloc_tos(),
183 if (new_ace_list == NULL) {
187 /* Fake a quick smb_filename. */
188 ZERO_STRUCT(smb_fname);
189 smb_fname.st = *psbuf;
190 smb_fname.base_name = CONST_DISCARD(char *, name);
192 dir_mode = unix_mode(conn,
193 FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
194 file_mode = unix_mode(conn,
195 FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
197 mode = dir_mode | file_mode;
199 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
202 (unsigned int)mode ));
205 memcpy(new_ace_list, psd->dacl->aces,
206 num_aces * sizeof(struct security_ace));
208 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
211 init_sec_ace(&new_ace_list[num_aces],
212 &global_sid_Creator_Owner,
215 SEC_ACE_FLAG_CONTAINER_INHERIT|
216 SEC_ACE_FLAG_OBJECT_INHERIT|
217 SEC_ACE_FLAG_INHERIT_ONLY);
218 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
219 (mode << 3) & 0700, false);
220 init_sec_ace(&new_ace_list[num_aces+1],
221 &global_sid_Creator_Group,
224 SEC_ACE_FLAG_CONTAINER_INHERIT|
225 SEC_ACE_FLAG_OBJECT_INHERIT|
226 SEC_ACE_FLAG_INHERIT_ONLY);
227 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
228 (mode << 6) & 0700, false);
229 init_sec_ace(&new_ace_list[num_aces+2],
233 SEC_ACE_FLAG_CONTAINER_INHERIT|
234 SEC_ACE_FLAG_OBJECT_INHERIT|
235 SEC_ACE_FLAG_INHERIT_ONLY);
236 psd->dacl->aces = new_ace_list;
237 psd->dacl->num_aces += 3;
240 /*******************************************************************
241 Pull a DATA_BLOB from an xattr given a pathname.
242 If the hash doesn't match, or doesn't exist - return the underlying
244 *******************************************************************/
246 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
249 uint32_t security_info,
250 struct security_descriptor **ppdesc)
254 uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
255 uint8_t hash[XATTR_SD_HASH_SIZE];
256 uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
257 struct security_descriptor *psd = NULL;
258 struct security_descriptor *pdesc_next = NULL;
260 if (fsp && name == NULL) {
261 name = fsp->fsp_name->base_name;
264 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
266 /* Get the full underlying sd for the hash
267 or to return as backup. */
269 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
274 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
280 if (!NT_STATUS_IS_OK(status)) {
281 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
288 status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
289 if (!NT_STATUS_IS_OK(status)) {
290 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
296 status = parse_acl_blob(&blob, &psd,
297 &hash_type, &hash[0]);
298 if (!NT_STATUS_IS_OK(status)) {
299 DEBUG(10, ("parse_acl_blob returned %s\n",
305 /* Ensure the hash type is one we know. */
307 case XATTR_SD_HASH_TYPE_NONE:
308 /* No hash, just return blob sd. */
310 case XATTR_SD_HASH_TYPE_SHA256:
313 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
314 "mismatch (%u) for file %s\n",
315 (unsigned int)hash_type,
323 status = hash_sd_sha256(pdesc_next, hash_tmp);
324 if (!NT_STATUS_IS_OK(status)) {
330 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
331 /* Hash matches, return blob sd. */
332 DEBUG(10, ("get_nt_acl_internal: blob hash "
333 "matches for file %s\n",
338 /* Hash doesn't match, return underlying sd. */
344 if (psd != pdesc_next) {
345 /* We're returning the blob, throw
346 * away the filesystem SD. */
347 TALLOC_FREE(pdesc_next);
349 SMB_STRUCT_STAT sbuf;
350 SMB_STRUCT_STAT *psbuf = &sbuf;
351 bool is_directory = false;
353 * We're returning the underlying ACL from the
354 * filesystem. If it's a directory, and has no
355 * inheritable ACE entries we have to fake them.
358 is_directory = fsp->is_directory;
359 psbuf = &fsp->fsp_name->st;
361 if (vfs_stat_smb_fname(handle->conn,
364 is_directory = S_ISDIR(sbuf.st_ex_mode);
368 !sd_has_inheritable_components(psd,
370 add_directory_inheritable_components(handle,
375 /* The underlying POSIX module always sets
376 the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
377 can't be inherited in this way under POSIX.
378 Remove it for Windows-style ACLs. */
379 psd->type &= ~SEC_DESC_DACL_PROTECTED;
382 if (!(security_info & SECINFO_OWNER)) {
383 psd->owner_sid = NULL;
385 if (!(security_info & SECINFO_GROUP)) {
386 psd->group_sid = NULL;
388 if (!(security_info & SECINFO_DACL)) {
391 if (!(security_info & SECINFO_SACL)) {
395 TALLOC_FREE(blob.data);
400 /*********************************************************************
401 Create a default ACL by inheriting from the parent. If no inheritance
402 from the parent available, don't set anything. This will leave the actual
403 permissions the new file or directory already got from the filesystem
404 as the NT ACL when read.
405 *********************************************************************/
407 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
409 struct security_descriptor *parent_desc,
412 TALLOC_CTX *ctx = talloc_tos();
413 NTSTATUS status = NT_STATUS_OK;
414 struct security_descriptor *psd = NULL;
417 if (!sd_has_inheritable_components(parent_desc, is_directory)) {
421 /* Create an inherited descriptor from the parent. */
423 if (DEBUGLEVEL >= 10) {
424 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
426 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
429 status = se_create_child_secdesc(ctx,
433 &handle->conn->server_info->ptok->sids[PRIMARY_USER_SID_INDEX],
434 &handle->conn->server_info->ptok->sids[PRIMARY_GROUP_SID_INDEX],
436 if (!NT_STATUS_IS_OK(status)) {
440 if (DEBUGLEVEL >= 10) {
441 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
443 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
446 return SMB_VFS_FSET_NT_ACL(fsp,
453 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
455 uint32_t access_mask,
456 struct security_descriptor **pp_parent_desc)
458 char *parent_name = NULL;
459 struct security_descriptor *parent_desc = NULL;
460 uint32_t access_granted = 0;
463 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
464 return NT_STATUS_NO_MEMORY;
467 status = get_nt_acl_internal(handle,
475 if (!NT_STATUS_IS_OK(status)) {
476 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
477 "on directory %s for "
478 "path %s returned %s\n",
481 nt_errstr(status) ));
484 if (pp_parent_desc) {
485 *pp_parent_desc = parent_desc;
487 status = smb1_file_se_access_check(handle->conn,
489 get_current_nttok(handle->conn),
492 if(!NT_STATUS_IS_OK(status)) {
493 DEBUG(10,("check_parent_acl_common: access check "
494 "on directory %s for "
495 "path %s for mask 0x%x returned %s\n",
499 nt_errstr(status) ));
505 static void free_sd_common(void **ptr)
510 /*********************************************************************
511 Check ACL on open. For new files inherit from parent directory.
512 *********************************************************************/
514 static int open_acl_common(vfs_handle_struct *handle,
515 struct smb_filename *smb_fname,
520 uint32_t access_granted = 0;
521 struct security_descriptor *pdesc = NULL;
522 struct security_descriptor *parent_desc = NULL;
523 bool file_existed = true;
528 /* Stream open. Base filename open already did the ACL check. */
529 DEBUG(10,("open_acl_common: stream open on %s\n",
531 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
534 status = get_full_smb_filename(talloc_tos(), smb_fname,
536 if (!NT_STATUS_IS_OK(status)) {
540 status = get_nt_acl_internal(handle,
547 if (NT_STATUS_IS_OK(status)) {
548 /* See if we can access it. */
549 status = smb1_file_se_access_check(handle->conn,
551 get_current_nttok(handle->conn),
554 if (!NT_STATUS_IS_OK(status)) {
555 DEBUG(10,("open_acl_xattr: %s open "
556 "refused with error %s\n",
558 nt_errstr(status) ));
561 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
562 file_existed = false;
564 * If O_CREAT is true then we're trying to create a file.
565 * Check the parent directory ACL will allow this.
567 if (flags & O_CREAT) {
568 struct security_descriptor *psd = NULL;
570 status = check_parent_acl_common(handle, fname,
571 SEC_DIR_ADD_FILE, &parent_desc);
572 if (!NT_STATUS_IS_OK(status)) {
575 /* Cache the parent security descriptor for
576 * later use. We do have an fsp here, but to
577 * keep the code consistent with the directory
578 * case which doesn't, use the handle. */
580 /* Attach this to the conn, move from talloc_tos(). */
581 psd = (struct security_descriptor *)talloc_move(handle->conn,
585 status = NT_STATUS_NO_MEMORY;
588 status = NT_STATUS_NO_MEMORY;
589 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
590 struct security_descriptor *, goto err);
591 status = NT_STATUS_OK;
595 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
598 nt_errstr(status) ));
600 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
605 errno = map_errno_from_nt_status(status);
609 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
613 SMB_STRUCT_STAT sbuf;
615 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
616 if (ret == -1 && errno == ENOENT) {
617 struct security_descriptor *parent_desc = NULL;
618 struct security_descriptor *psd = NULL;
620 /* We're creating a new directory. */
621 status = check_parent_acl_common(handle, path,
622 SEC_DIR_ADD_SUBDIR, &parent_desc);
623 if (!NT_STATUS_IS_OK(status)) {
624 errno = map_errno_from_nt_status(status);
628 /* Cache the parent security descriptor for
629 * later use. We don't have an fsp here so
632 /* Attach this to the conn, move from talloc_tos(). */
633 psd = (struct security_descriptor *)talloc_move(handle->conn,
639 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
640 struct security_descriptor *, return -1);
643 return SMB_VFS_NEXT_MKDIR(handle, path, mode);
646 /*********************************************************************
647 Fetch a security descriptor given an fsp.
648 *********************************************************************/
650 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
651 uint32_t security_info, struct security_descriptor **ppdesc)
653 return get_nt_acl_internal(handle, fsp,
654 NULL, security_info, ppdesc);
657 /*********************************************************************
658 Fetch a security descriptor given a pathname.
659 *********************************************************************/
661 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
662 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
664 return get_nt_acl_internal(handle, NULL,
665 name, security_info, ppdesc);
668 /*********************************************************************
669 Store a security descriptor given an fsp.
670 *********************************************************************/
672 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
673 uint32_t security_info_sent, const struct security_descriptor *orig_psd)
677 struct security_descriptor *pdesc_next = NULL;
678 struct security_descriptor *psd = NULL;
679 uint8_t hash[XATTR_SD_HASH_SIZE];
681 if (DEBUGLEVEL >= 10) {
682 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
684 NDR_PRINT_DEBUG(security_descriptor,
685 CONST_DISCARD(struct security_descriptor *,orig_psd));
688 status = get_nt_acl_internal(handle, fsp,
690 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
693 if (!NT_STATUS_IS_OK(status)) {
697 if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
698 psd->owner_sid = orig_psd->owner_sid;
700 if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
701 psd->group_sid = orig_psd->group_sid;
703 if (security_info_sent & SECINFO_DACL) {
704 psd->dacl = orig_psd->dacl;
706 if (security_info_sent & SECINFO_SACL) {
707 psd->sacl = orig_psd->sacl;
710 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
711 if (!NT_STATUS_IS_OK(status)) {
715 /* Get the full underlying sd, then hash. */
716 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
721 if (!NT_STATUS_IS_OK(status)) {
725 status = hash_sd_sha256(pdesc_next, hash);
726 if (!NT_STATUS_IS_OK(status)) {
730 if (DEBUGLEVEL >= 10) {
731 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
733 NDR_PRINT_DEBUG(security_descriptor,
734 CONST_DISCARD(struct security_descriptor *,psd));
736 create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
737 store_acl_blob_fsp(handle, fsp, &blob);
742 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
743 const char *fname, const char *mask, uint32 attr)
745 NTSTATUS status = check_parent_acl_common(handle, fname,
748 if (!NT_STATUS_IS_OK(status)) {
749 errno = map_errno_from_nt_status(status);
752 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
755 static int acl_common_remove_object(vfs_handle_struct *handle,
759 connection_struct *conn = handle->conn;
761 files_struct *fsp = NULL;
763 char *parent_dir = NULL;
764 const char *final_component = NULL;
765 struct smb_filename local_fname;
768 if (!parent_dirname(talloc_tos(), path,
769 &parent_dir, &final_component)) {
770 saved_errno = ENOMEM;
774 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
775 is_directory ? "directory" : "file",
776 parent_dir, final_component ));
778 /* cd into the parent dir to pin it. */
779 ret = SMB_VFS_CHDIR(conn, parent_dir);
785 ZERO_STRUCT(local_fname);
786 local_fname.base_name = CONST_DISCARD(char *,final_component);
788 /* Must use lstat here. */
789 ret = SMB_VFS_LSTAT(conn, &local_fname);
795 /* Ensure we have this file open with DELETE access. */
796 id = vfs_file_id_from_sbuf(conn, &local_fname.st);
797 for (fsp = file_find_di_first(conn->sconn, id); fsp;
798 file_find_di_next(fsp)) {
799 if (fsp->access_mask & DELETE_ACCESS &&
800 fsp->delete_on_close) {
801 /* We did open this for delete,
802 * allow the delete as root.
809 DEBUG(10,("acl_common_remove_object: %s %s/%s "
810 "not an open file\n",
811 is_directory ? "directory" : "file",
812 parent_dir, final_component ));
813 saved_errno = EACCES;
819 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
821 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
831 TALLOC_FREE(parent_dir);
833 vfs_ChDir(conn, conn->connectpath);
840 static int rmdir_acl_common(struct vfs_handle_struct *handle,
845 ret = SMB_VFS_NEXT_RMDIR(handle, path);
846 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
847 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
853 return acl_common_remove_object(handle,
858 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
859 struct smb_request *req,
860 uint16_t root_dir_fid,
861 struct smb_filename *smb_fname,
862 uint32_t access_mask,
863 uint32_t share_access,
864 uint32_t create_disposition,
865 uint32_t create_options,
866 uint32_t file_attributes,
867 uint32_t oplock_request,
868 uint64_t allocation_size,
869 uint32_t private_flags,
870 struct security_descriptor *sd,
871 struct ea_list *ea_list,
872 files_struct **result,
875 NTSTATUS status, status1;
876 files_struct *fsp = NULL;
878 struct security_descriptor *parent_sd = NULL;
880 status = SMB_VFS_NEXT_CREATE_FILE(handle,
897 if (info != FILE_WAS_CREATED) {
898 /* File/directory was opened, not created. */
904 if (!NT_STATUS_IS_OK(status) || fsp == NULL) {
905 /* Only handle success. */
910 /* Security descriptor already set. */
920 /* We must have a cached parent sd in this case.
921 * attached to the handle. */
923 SMB_VFS_HANDLE_GET_DATA(handle, parent_sd,
924 struct security_descriptor,
931 /* New directory - inherit from parent. */
932 status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
934 if (!NT_STATUS_IS_OK(status1)) {
935 DEBUG(1,("create_file_acl_common: error setting "
938 nt_errstr(status1) ));
943 /* Ensure we never leave attached data around. */
944 SMB_VFS_HANDLE_FREE_DATA(handle);
946 if (NT_STATUS_IS_OK(status) && pinfo) {
953 smb_panic("create_file_acl_common: logic error.\n");
958 static int unlink_acl_common(struct vfs_handle_struct *handle,
959 const struct smb_filename *smb_fname)
963 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
964 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
965 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
966 smb_fname->base_name,
970 /* Don't do anything fancy for streams. */
971 if (smb_fname->stream_name) {
975 return acl_common_remove_object(handle,
976 smb_fname->base_name,