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 "../libcli/security/security.h"
23 #include "../librpc/gen_ndr/ndr_security.h"
25 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
28 uint8_t hash[XATTR_SD_HASH_SIZE]);
30 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
31 vfs_handle_struct *handle,
36 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
40 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
45 /*******************************************************************
46 Hash a security descriptor.
47 *******************************************************************/
49 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
56 memset(hash, '\0', XATTR_SD_HASH_SIZE);
57 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
58 if (!NT_STATUS_IS_OK(status)) {
63 SHA256_Update(&tctx, blob.data, blob.length);
64 SHA256_Final(hash, &tctx);
69 /*******************************************************************
70 Parse out a struct security_descriptor from a DATA_BLOB.
71 *******************************************************************/
73 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
74 struct security_descriptor **ppdesc,
75 uint16_t *p_hash_type,
76 uint8_t hash[XATTR_SD_HASH_SIZE])
78 TALLOC_CTX *ctx = talloc_tos();
79 struct xattr_NTACL xacl;
80 enum ndr_err_code ndr_err;
83 ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
84 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
86 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
87 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
88 ndr_errstr(ndr_err)));
89 return ndr_map_error2ntstatus(ndr_err);;
92 switch (xacl.version) {
94 *ppdesc = make_sec_desc(ctx, SD_REVISION,
95 xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
96 xacl.info.sd_hs2->sd->owner_sid,
97 xacl.info.sd_hs2->sd->group_sid,
98 xacl.info.sd_hs2->sd->sacl,
99 xacl.info.sd_hs2->sd->dacl,
101 /* No hash - null out. */
102 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
103 memset(hash, '\0', XATTR_SD_HASH_SIZE);
106 *ppdesc = make_sec_desc(ctx, SD_REVISION,
107 xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
108 xacl.info.sd_hs3->sd->owner_sid,
109 xacl.info.sd_hs3->sd->group_sid,
110 xacl.info.sd_hs3->sd->sacl,
111 xacl.info.sd_hs3->sd->dacl,
113 *p_hash_type = xacl.info.sd_hs3->hash_type;
114 /* Current version 3. */
115 memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
118 return NT_STATUS_REVISION_MISMATCH;
121 TALLOC_FREE(xacl.info.sd);
123 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
126 /*******************************************************************
127 Create a DATA_BLOB from a security descriptor.
128 *******************************************************************/
130 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
133 uint8_t hash[XATTR_SD_HASH_SIZE])
135 struct xattr_NTACL xacl;
136 struct security_descriptor_hash_v3 sd_hs3;
137 enum ndr_err_code ndr_err;
138 TALLOC_CTX *ctx = talloc_tos();
144 xacl.info.sd_hs3 = &sd_hs3;
145 xacl.info.sd_hs3->sd = CONST_DISCARD(struct security_descriptor *, psd);
146 xacl.info.sd_hs3->hash_type = hash_type;
147 memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
149 ndr_err = ndr_push_struct_blob(
151 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
153 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
154 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
155 ndr_errstr(ndr_err)));
156 return ndr_map_error2ntstatus(ndr_err);;
162 /*******************************************************************
163 Add in 3 inheritable components for a non-inheritable directory ACL.
164 CREATOR_OWNER/CREATOR_GROUP/WORLD.
165 *******************************************************************/
167 static void add_directory_inheritable_components(vfs_handle_struct *handle,
169 SMB_STRUCT_STAT *psbuf,
170 struct security_descriptor *psd)
172 struct connection_struct *conn = handle->conn;
173 int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
174 struct smb_filename smb_fname;
175 enum security_ace_type acltype;
176 uint32_t access_mask;
180 struct security_ace *new_ace_list = TALLOC_ZERO_ARRAY(talloc_tos(),
184 if (new_ace_list == NULL) {
188 /* Fake a quick smb_filename. */
189 ZERO_STRUCT(smb_fname);
190 smb_fname.st = *psbuf;
191 smb_fname.base_name = CONST_DISCARD(char *, name);
193 dir_mode = unix_mode(conn,
194 FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
195 file_mode = unix_mode(conn,
196 FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
198 mode = dir_mode | file_mode;
200 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
203 (unsigned int)mode ));
206 memcpy(new_ace_list, psd->dacl->aces,
207 num_aces * sizeof(struct security_ace));
209 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
212 init_sec_ace(&new_ace_list[num_aces],
213 &global_sid_Creator_Owner,
216 SEC_ACE_FLAG_CONTAINER_INHERIT|
217 SEC_ACE_FLAG_OBJECT_INHERIT|
218 SEC_ACE_FLAG_INHERIT_ONLY);
219 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
220 (mode << 3) & 0700, false);
221 init_sec_ace(&new_ace_list[num_aces+1],
222 &global_sid_Creator_Group,
225 SEC_ACE_FLAG_CONTAINER_INHERIT|
226 SEC_ACE_FLAG_OBJECT_INHERIT|
227 SEC_ACE_FLAG_INHERIT_ONLY);
228 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
229 (mode << 6) & 0700, false);
230 init_sec_ace(&new_ace_list[num_aces+2],
234 SEC_ACE_FLAG_CONTAINER_INHERIT|
235 SEC_ACE_FLAG_OBJECT_INHERIT|
236 SEC_ACE_FLAG_INHERIT_ONLY);
237 psd->dacl->aces = new_ace_list;
238 psd->dacl->num_aces += 3;
241 /*******************************************************************
242 Pull a DATA_BLOB from an xattr given a pathname.
243 If the hash doesn't match, or doesn't exist - return the underlying
245 *******************************************************************/
247 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
250 uint32_t security_info,
251 struct security_descriptor **ppdesc)
255 uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
256 uint8_t hash[XATTR_SD_HASH_SIZE];
257 uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
258 struct security_descriptor *psd = NULL;
259 struct security_descriptor *pdesc_next = NULL;
261 if (fsp && name == NULL) {
262 name = fsp->fsp_name->base_name;
265 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
267 /* Get the full underlying sd for the hash
268 or to return as backup. */
270 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
275 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
281 if (!NT_STATUS_IS_OK(status)) {
282 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
289 status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
290 if (!NT_STATUS_IS_OK(status)) {
291 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
297 status = parse_acl_blob(&blob, &psd,
298 &hash_type, &hash[0]);
299 if (!NT_STATUS_IS_OK(status)) {
300 DEBUG(10, ("parse_acl_blob returned %s\n",
306 /* Ensure the hash type is one we know. */
308 case XATTR_SD_HASH_TYPE_NONE:
309 /* No hash, just return blob sd. */
311 case XATTR_SD_HASH_TYPE_SHA256:
314 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
315 "mismatch (%u) for file %s\n",
316 (unsigned int)hash_type,
324 status = hash_sd_sha256(pdesc_next, hash_tmp);
325 if (!NT_STATUS_IS_OK(status)) {
331 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
332 /* Hash matches, return blob sd. */
333 DEBUG(10, ("get_nt_acl_internal: blob hash "
334 "matches for file %s\n",
339 /* Hash doesn't match, return underlying sd. */
345 if (psd != pdesc_next) {
346 /* We're returning the blob, throw
347 * away the filesystem SD. */
348 TALLOC_FREE(pdesc_next);
350 SMB_STRUCT_STAT sbuf;
351 SMB_STRUCT_STAT *psbuf = &sbuf;
352 bool is_directory = false;
354 * We're returning the underlying ACL from the
355 * filesystem. If it's a directory, and has no
356 * inheritable ACE entries we have to fake them.
359 is_directory = fsp->is_directory;
360 psbuf = &fsp->fsp_name->st;
362 if (vfs_stat_smb_fname(handle->conn,
365 is_directory = S_ISDIR(sbuf.st_ex_mode);
369 !sd_has_inheritable_components(psd,
371 add_directory_inheritable_components(handle,
376 /* The underlying POSIX module always sets
377 the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
378 can't be inherited in this way under POSIX.
379 Remove it for Windows-style ACLs. */
380 psd->type &= ~SEC_DESC_DACL_PROTECTED;
383 if (!(security_info & SECINFO_OWNER)) {
384 psd->owner_sid = NULL;
386 if (!(security_info & SECINFO_GROUP)) {
387 psd->group_sid = NULL;
389 if (!(security_info & SECINFO_DACL)) {
392 if (!(security_info & SECINFO_SACL)) {
396 TALLOC_FREE(blob.data);
399 if (DEBUGLEVEL >= 10) {
400 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
402 NDR_PRINT_DEBUG(security_descriptor, psd);
408 /*********************************************************************
409 Create a default ACL by inheriting from the parent. If no inheritance
410 from the parent available, don't set anything. This will leave the actual
411 permissions the new file or directory already got from the filesystem
412 as the NT ACL when read.
413 *********************************************************************/
415 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
417 struct security_descriptor *parent_desc,
420 TALLOC_CTX *ctx = talloc_tos();
421 NTSTATUS status = NT_STATUS_OK;
422 struct security_descriptor *psd = NULL;
425 if (!sd_has_inheritable_components(parent_desc, is_directory)) {
429 /* Create an inherited descriptor from the parent. */
431 if (DEBUGLEVEL >= 10) {
432 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
434 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
437 status = se_create_child_secdesc(ctx,
441 &handle->conn->server_info->ptok->sids[PRIMARY_USER_SID_INDEX],
442 &handle->conn->server_info->ptok->sids[PRIMARY_GROUP_SID_INDEX],
444 if (!NT_STATUS_IS_OK(status)) {
448 if (DEBUGLEVEL >= 10) {
449 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
451 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
454 return SMB_VFS_FSET_NT_ACL(fsp,
461 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
463 uint32_t access_mask,
464 struct security_descriptor **pp_parent_desc)
466 char *parent_name = NULL;
467 struct security_descriptor *parent_desc = NULL;
468 uint32_t access_granted = 0;
471 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
472 return NT_STATUS_NO_MEMORY;
475 status = get_nt_acl_internal(handle,
483 if (!NT_STATUS_IS_OK(status)) {
484 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
485 "on directory %s for "
486 "path %s returned %s\n",
489 nt_errstr(status) ));
492 if (pp_parent_desc) {
493 *pp_parent_desc = parent_desc;
495 status = smb1_file_se_access_check(handle->conn,
497 get_current_nttok(handle->conn),
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",
507 nt_errstr(status) ));
513 static void free_sd_common(void **ptr)
518 /*********************************************************************
519 Check ACL on open. For new files inherit from parent directory.
520 *********************************************************************/
522 static int open_acl_common(vfs_handle_struct *handle,
523 struct smb_filename *smb_fname,
528 uint32_t access_granted = 0;
529 struct security_descriptor *pdesc = NULL;
530 struct security_descriptor *parent_desc = NULL;
531 bool file_existed = true;
536 /* Stream open. Base filename open already did the ACL check. */
537 DEBUG(10,("open_acl_common: stream open on %s\n",
539 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
542 status = get_full_smb_filename(talloc_tos(), smb_fname,
544 if (!NT_STATUS_IS_OK(status)) {
548 status = get_nt_acl_internal(handle,
555 if (NT_STATUS_IS_OK(status)) {
556 /* See if we can access it. */
557 status = smb1_file_se_access_check(handle->conn,
559 get_current_nttok(handle->conn),
562 if (!NT_STATUS_IS_OK(status)) {
563 DEBUG(10,("open_acl_xattr: %s open "
564 "refused with error %s\n",
566 nt_errstr(status) ));
569 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
570 file_existed = false;
572 * If O_CREAT is true then we're trying to create a file.
573 * Check the parent directory ACL will allow this.
575 if (flags & O_CREAT) {
576 struct security_descriptor *psd = NULL;
578 status = check_parent_acl_common(handle, fname,
579 SEC_DIR_ADD_FILE, &parent_desc);
580 if (!NT_STATUS_IS_OK(status)) {
583 /* Cache the parent security descriptor for
584 * later use. We do have an fsp here, but to
585 * keep the code consistent with the directory
586 * case which doesn't, use the handle. */
588 /* Attach this to the conn, move from talloc_tos(). */
589 psd = (struct security_descriptor *)talloc_move(handle->conn,
593 status = NT_STATUS_NO_MEMORY;
596 status = NT_STATUS_NO_MEMORY;
597 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
598 struct security_descriptor *, goto err);
599 status = NT_STATUS_OK;
603 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
606 nt_errstr(status) ));
608 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
613 errno = map_errno_from_nt_status(status);
617 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
621 SMB_STRUCT_STAT sbuf;
623 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
624 if (ret == -1 && errno == ENOENT) {
625 struct security_descriptor *parent_desc = NULL;
626 struct security_descriptor *psd = NULL;
628 /* We're creating a new directory. */
629 status = check_parent_acl_common(handle, path,
630 SEC_DIR_ADD_SUBDIR, &parent_desc);
631 if (!NT_STATUS_IS_OK(status)) {
632 errno = map_errno_from_nt_status(status);
636 /* Cache the parent security descriptor for
637 * later use. We don't have an fsp here so
640 /* Attach this to the conn, move from talloc_tos(). */
641 psd = (struct security_descriptor *)talloc_move(handle->conn,
647 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
648 struct security_descriptor *, return -1);
651 return SMB_VFS_NEXT_MKDIR(handle, path, mode);
654 /*********************************************************************
655 Fetch a security descriptor given an fsp.
656 *********************************************************************/
658 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
659 uint32_t security_info, struct security_descriptor **ppdesc)
661 return get_nt_acl_internal(handle, fsp,
662 NULL, security_info, ppdesc);
665 /*********************************************************************
666 Fetch a security descriptor given a pathname.
667 *********************************************************************/
669 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
670 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
672 return get_nt_acl_internal(handle, NULL,
673 name, security_info, ppdesc);
676 /*********************************************************************
677 Store a security descriptor given an fsp.
678 *********************************************************************/
680 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
681 uint32_t security_info_sent, const struct security_descriptor *orig_psd)
685 struct security_descriptor *pdesc_next = NULL;
686 struct security_descriptor *psd = NULL;
687 uint8_t hash[XATTR_SD_HASH_SIZE];
689 if (DEBUGLEVEL >= 10) {
690 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
692 NDR_PRINT_DEBUG(security_descriptor,
693 CONST_DISCARD(struct security_descriptor *,orig_psd));
696 status = get_nt_acl_internal(handle, fsp,
698 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
701 if (!NT_STATUS_IS_OK(status)) {
705 if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
706 psd->owner_sid = orig_psd->owner_sid;
708 if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
709 psd->group_sid = orig_psd->group_sid;
711 if (security_info_sent & SECINFO_DACL) {
712 psd->dacl = orig_psd->dacl;
714 if (security_info_sent & SECINFO_SACL) {
715 psd->sacl = orig_psd->sacl;
718 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
719 if (!NT_STATUS_IS_OK(status)) {
723 /* Get the full underlying sd, then hash. */
724 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
729 if (!NT_STATUS_IS_OK(status)) {
733 status = hash_sd_sha256(pdesc_next, hash);
734 if (!NT_STATUS_IS_OK(status)) {
738 if (DEBUGLEVEL >= 10) {
739 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
741 NDR_PRINT_DEBUG(security_descriptor,
742 CONST_DISCARD(struct security_descriptor *,psd));
744 create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
745 store_acl_blob_fsp(handle, fsp, &blob);
750 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
751 const char *fname, const char *mask, uint32 attr)
753 NTSTATUS status = check_parent_acl_common(handle, fname,
756 if (!NT_STATUS_IS_OK(status)) {
757 errno = map_errno_from_nt_status(status);
760 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
763 static int acl_common_remove_object(vfs_handle_struct *handle,
767 connection_struct *conn = handle->conn;
769 files_struct *fsp = NULL;
771 char *parent_dir = NULL;
772 const char *final_component = NULL;
773 struct smb_filename local_fname;
776 if (!parent_dirname(talloc_tos(), path,
777 &parent_dir, &final_component)) {
778 saved_errno = ENOMEM;
782 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
783 is_directory ? "directory" : "file",
784 parent_dir, final_component ));
786 /* cd into the parent dir to pin it. */
787 ret = SMB_VFS_CHDIR(conn, parent_dir);
793 ZERO_STRUCT(local_fname);
794 local_fname.base_name = CONST_DISCARD(char *,final_component);
796 /* Must use lstat here. */
797 ret = SMB_VFS_LSTAT(conn, &local_fname);
803 /* Ensure we have this file open with DELETE access. */
804 id = vfs_file_id_from_sbuf(conn, &local_fname.st);
805 for (fsp = file_find_di_first(conn->sconn, id); fsp;
806 file_find_di_next(fsp)) {
807 if (fsp->access_mask & DELETE_ACCESS &&
808 fsp->delete_on_close) {
809 /* We did open this for delete,
810 * allow the delete as root.
817 DEBUG(10,("acl_common_remove_object: %s %s/%s "
818 "not an open file\n",
819 is_directory ? "directory" : "file",
820 parent_dir, final_component ));
821 saved_errno = EACCES;
827 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
829 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
839 TALLOC_FREE(parent_dir);
841 vfs_ChDir(conn, conn->connectpath);
848 static int rmdir_acl_common(struct vfs_handle_struct *handle,
853 ret = SMB_VFS_NEXT_RMDIR(handle, path);
854 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
855 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
861 return acl_common_remove_object(handle,
866 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
867 struct smb_request *req,
868 uint16_t root_dir_fid,
869 struct smb_filename *smb_fname,
870 uint32_t access_mask,
871 uint32_t share_access,
872 uint32_t create_disposition,
873 uint32_t create_options,
874 uint32_t file_attributes,
875 uint32_t oplock_request,
876 uint64_t allocation_size,
877 uint32_t private_flags,
878 struct security_descriptor *sd,
879 struct ea_list *ea_list,
880 files_struct **result,
883 NTSTATUS status, status1;
884 files_struct *fsp = NULL;
886 struct security_descriptor *parent_sd = NULL;
888 status = SMB_VFS_NEXT_CREATE_FILE(handle,
905 if (!NT_STATUS_IS_OK(status)) {
909 if (info != FILE_WAS_CREATED) {
910 /* File/directory was opened, not created. */
917 /* Only handle success. */
922 /* Security descriptor already set. */
932 /* We must have a cached parent sd in this case.
933 * attached to the handle. */
935 SMB_VFS_HANDLE_GET_DATA(handle, parent_sd,
936 struct security_descriptor,
943 /* New directory - inherit from parent. */
944 status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
946 if (!NT_STATUS_IS_OK(status1)) {
947 DEBUG(1,("create_file_acl_common: error setting "
950 nt_errstr(status1) ));
955 /* Ensure we never leave attached data around. */
956 SMB_VFS_HANDLE_FREE_DATA(handle);
958 if (NT_STATUS_IS_OK(status) && pinfo) {
965 smb_panic("create_file_acl_common: logic error.\n");
970 static int unlink_acl_common(struct vfs_handle_struct *handle,
971 const struct smb_filename *smb_fname)
975 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
976 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
977 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
978 smb_fname->base_name,
982 /* Don't do anything fancy for streams. */
983 if (smb_fname->stream_name) {
987 return acl_common_remove_object(handle,
988 smb_fname->base_name,