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 "system/filesys.h"
23 #include "../libcli/security/security.h"
24 #include "../librpc/gen_ndr/ndr_security.h"
26 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
29 uint8_t hash[XATTR_SD_HASH_SIZE]);
31 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
32 vfs_handle_struct *handle,
37 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
41 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
46 /*******************************************************************
47 Hash a security descriptor.
48 *******************************************************************/
50 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
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)) {
64 SHA256_Update(&tctx, blob.data, blob.length);
65 SHA256_Final(hash, &tctx);
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;
84 ndr_err = ndr_pull_struct_blob(pblob, ctx, &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) {
95 *ppdesc = make_sec_desc(ctx, SD_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,
102 /* No hash - null out. */
103 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
104 memset(hash, '\0', XATTR_SD_HASH_SIZE);
107 *ppdesc = make_sec_desc(ctx, SD_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,
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);
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,
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();
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(
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);
163 /*******************************************************************
164 Add in 3 inheritable components for a non-inheritable directory ACL.
165 CREATOR_OWNER/CREATOR_GROUP/WORLD.
166 *******************************************************************/
168 static void add_directory_inheritable_components(vfs_handle_struct *handle,
170 SMB_STRUCT_STAT *psbuf,
171 struct security_descriptor *psd)
173 struct connection_struct *conn = handle->conn;
174 int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
175 struct smb_filename smb_fname;
176 enum security_ace_type acltype;
177 uint32_t access_mask;
181 struct security_ace *new_ace_list = TALLOC_ZERO_ARRAY(talloc_tos(),
185 if (new_ace_list == NULL) {
189 /* Fake a quick smb_filename. */
190 ZERO_STRUCT(smb_fname);
191 smb_fname.st = *psbuf;
192 smb_fname.base_name = CONST_DISCARD(char *, name);
194 dir_mode = unix_mode(conn,
195 FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
196 file_mode = unix_mode(conn,
197 FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
199 mode = dir_mode | file_mode;
201 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
204 (unsigned int)mode ));
207 memcpy(new_ace_list, psd->dacl->aces,
208 num_aces * sizeof(struct security_ace));
210 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
213 init_sec_ace(&new_ace_list[num_aces],
214 &global_sid_Creator_Owner,
217 SEC_ACE_FLAG_CONTAINER_INHERIT|
218 SEC_ACE_FLAG_OBJECT_INHERIT|
219 SEC_ACE_FLAG_INHERIT_ONLY);
220 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
221 (mode << 3) & 0700, false);
222 init_sec_ace(&new_ace_list[num_aces+1],
223 &global_sid_Creator_Group,
226 SEC_ACE_FLAG_CONTAINER_INHERIT|
227 SEC_ACE_FLAG_OBJECT_INHERIT|
228 SEC_ACE_FLAG_INHERIT_ONLY);
229 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
230 (mode << 6) & 0700, false);
231 init_sec_ace(&new_ace_list[num_aces+2],
235 SEC_ACE_FLAG_CONTAINER_INHERIT|
236 SEC_ACE_FLAG_OBJECT_INHERIT|
237 SEC_ACE_FLAG_INHERIT_ONLY);
238 psd->dacl->aces = new_ace_list;
239 psd->dacl->num_aces += 3;
242 /*******************************************************************
243 Pull a DATA_BLOB from an xattr given a pathname.
244 If the hash doesn't match, or doesn't exist - return the underlying
246 *******************************************************************/
248 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
251 uint32_t security_info,
252 struct security_descriptor **ppdesc)
256 uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
257 uint8_t hash[XATTR_SD_HASH_SIZE];
258 uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
259 struct security_descriptor *psd = NULL;
260 struct security_descriptor *pdesc_next = NULL;
261 bool ignore_file_system_acl = lp_parm_bool(SNUM(handle->conn),
263 "ignore system acls",
266 if (fsp && name == NULL) {
267 name = fsp->fsp_name->base_name;
270 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
272 /* Get the full underlying sd for the hash
273 or to return as backup. */
275 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
280 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
286 if (!NT_STATUS_IS_OK(status)) {
287 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
294 status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
295 if (!NT_STATUS_IS_OK(status)) {
296 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
302 status = parse_acl_blob(&blob, &psd,
303 &hash_type, &hash[0]);
304 if (!NT_STATUS_IS_OK(status)) {
305 DEBUG(10, ("parse_acl_blob returned %s\n",
311 /* Ensure the hash type is one we know. */
313 case XATTR_SD_HASH_TYPE_NONE:
314 /* No hash, just return blob sd. */
316 case XATTR_SD_HASH_TYPE_SHA256:
319 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
320 "mismatch (%u) for file %s\n",
321 (unsigned int)hash_type,
328 if (ignore_file_system_acl) {
332 status = hash_sd_sha256(pdesc_next, hash_tmp);
333 if (!NT_STATUS_IS_OK(status)) {
339 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
340 /* Hash matches, return blob sd. */
341 DEBUG(10, ("get_nt_acl_internal: blob hash "
342 "matches for file %s\n",
347 /* Hash doesn't match, return underlying sd. */
353 if (psd != pdesc_next) {
354 /* We're returning the blob, throw
355 * away the filesystem SD. */
356 TALLOC_FREE(pdesc_next);
358 SMB_STRUCT_STAT sbuf;
359 SMB_STRUCT_STAT *psbuf = &sbuf;
360 bool is_directory = false;
362 * We're returning the underlying ACL from the
363 * filesystem. If it's a directory, and has no
364 * inheritable ACE entries we have to fake them.
367 status = vfs_stat_fsp(fsp);
368 if (!NT_STATUS_IS_OK(status)) {
371 psbuf = &fsp->fsp_name->st;
373 int ret = vfs_stat_smb_fname(handle->conn,
377 return map_nt_error_from_unix(errno);
380 is_directory = S_ISDIR(sbuf.st_ex_mode);
382 if (ignore_file_system_acl) {
383 TALLOC_FREE(pdesc_next);
384 status = make_default_filesystem_acl(talloc_tos(),
388 if (!NT_STATUS_IS_OK(status)) {
393 !sd_has_inheritable_components(psd,
395 add_directory_inheritable_components(handle,
400 /* The underlying POSIX module always sets
401 the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
402 can't be inherited in this way under POSIX.
403 Remove it for Windows-style ACLs. */
404 psd->type &= ~SEC_DESC_DACL_PROTECTED;
408 if (!(security_info & SECINFO_OWNER)) {
409 psd->owner_sid = NULL;
411 if (!(security_info & SECINFO_GROUP)) {
412 psd->group_sid = NULL;
414 if (!(security_info & SECINFO_DACL)) {
417 if (!(security_info & SECINFO_SACL)) {
421 TALLOC_FREE(blob.data);
424 if (DEBUGLEVEL >= 10) {
425 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
427 NDR_PRINT_DEBUG(security_descriptor, psd);
433 /*********************************************************************
434 Create a default ACL by inheriting from the parent. If no inheritance
435 from the parent available, don't set anything. This will leave the actual
436 permissions the new file or directory already got from the filesystem
437 as the NT ACL when read.
438 *********************************************************************/
440 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
442 struct security_descriptor *parent_desc,
445 TALLOC_CTX *ctx = talloc_tos();
446 NTSTATUS status = NT_STATUS_OK;
447 struct security_descriptor *psd = NULL;
450 if (!sd_has_inheritable_components(parent_desc, is_directory)) {
454 /* Create an inherited descriptor from the parent. */
456 if (DEBUGLEVEL >= 10) {
457 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
459 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
462 status = se_create_child_secdesc(ctx,
466 &handle->conn->session_info->security_token->sids[PRIMARY_USER_SID_INDEX],
467 &handle->conn->session_info->security_token->sids[PRIMARY_GROUP_SID_INDEX],
469 if (!NT_STATUS_IS_OK(status)) {
473 if (DEBUGLEVEL >= 10) {
474 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
476 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
479 return SMB_VFS_FSET_NT_ACL(fsp,
486 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
488 uint32_t access_mask,
489 struct security_descriptor **pp_parent_desc)
491 char *parent_name = NULL;
492 struct security_descriptor *parent_desc = NULL;
493 uint32_t access_granted = 0;
496 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
497 return NT_STATUS_NO_MEMORY;
500 status = get_nt_acl_internal(handle,
508 if (!NT_STATUS_IS_OK(status)) {
509 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
510 "on directory %s for "
511 "path %s returned %s\n",
514 nt_errstr(status) ));
517 if (pp_parent_desc) {
518 *pp_parent_desc = parent_desc;
520 status = smb1_file_se_access_check(handle->conn,
522 get_current_nttok(handle->conn),
525 if(!NT_STATUS_IS_OK(status)) {
526 DEBUG(10,("check_parent_acl_common: access check "
527 "on directory %s for "
528 "path %s for mask 0x%x returned %s\n",
532 nt_errstr(status) ));
538 static void free_sd_common(void **ptr)
543 /*********************************************************************
544 Check ACL on open. For new files inherit from parent directory.
545 *********************************************************************/
547 static int open_acl_common(vfs_handle_struct *handle,
548 struct smb_filename *smb_fname,
553 uint32_t access_granted = 0;
554 struct security_descriptor *pdesc = NULL;
555 struct security_descriptor *parent_desc = NULL;
556 bool file_existed = true;
561 /* Stream open. Base filename open already did the ACL check. */
562 DEBUG(10,("open_acl_common: stream open on %s\n",
564 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
567 status = get_full_smb_filename(talloc_tos(), smb_fname,
569 if (!NT_STATUS_IS_OK(status)) {
573 status = get_nt_acl_internal(handle,
580 if (NT_STATUS_IS_OK(status)) {
581 /* See if we can access it. */
582 status = smb1_file_se_access_check(handle->conn,
584 get_current_nttok(handle->conn),
587 if (!NT_STATUS_IS_OK(status)) {
588 DEBUG(10,("open_acl_xattr: %s open "
589 "refused with error %s\n",
591 nt_errstr(status) ));
594 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
595 file_existed = false;
597 * If O_CREAT is true then we're trying to create a file.
598 * Check the parent directory ACL will allow this.
600 if (flags & O_CREAT) {
601 struct security_descriptor *psd = NULL;
603 status = check_parent_acl_common(handle, fname,
604 SEC_DIR_ADD_FILE, &parent_desc);
605 if (!NT_STATUS_IS_OK(status)) {
608 /* Cache the parent security descriptor for
609 * later use. We do have an fsp here, but to
610 * keep the code consistent with the directory
611 * case which doesn't, use the handle. */
613 /* Attach this to the conn, move from talloc_tos(). */
614 psd = (struct security_descriptor *)talloc_move(handle->conn,
618 status = NT_STATUS_NO_MEMORY;
621 status = NT_STATUS_NO_MEMORY;
622 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
623 struct security_descriptor *, goto err);
624 status = NT_STATUS_OK;
628 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
631 nt_errstr(status) ));
633 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
638 errno = map_errno_from_nt_status(status);
642 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
646 SMB_STRUCT_STAT sbuf;
648 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
649 if (ret == -1 && errno == ENOENT) {
650 struct security_descriptor *parent_desc = NULL;
651 struct security_descriptor *psd = NULL;
653 /* We're creating a new directory. */
654 status = check_parent_acl_common(handle, path,
655 SEC_DIR_ADD_SUBDIR, &parent_desc);
656 if (!NT_STATUS_IS_OK(status)) {
657 errno = map_errno_from_nt_status(status);
661 /* Cache the parent security descriptor for
662 * later use. We don't have an fsp here so
665 /* Attach this to the conn, move from talloc_tos(). */
666 psd = (struct security_descriptor *)talloc_move(handle->conn,
672 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
673 struct security_descriptor *, return -1);
676 return SMB_VFS_NEXT_MKDIR(handle, path, mode);
679 /*********************************************************************
680 Fetch a security descriptor given an fsp.
681 *********************************************************************/
683 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
684 uint32_t security_info, struct security_descriptor **ppdesc)
686 return get_nt_acl_internal(handle, fsp,
687 NULL, security_info, ppdesc);
690 /*********************************************************************
691 Fetch a security descriptor given a pathname.
692 *********************************************************************/
694 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
695 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
697 return get_nt_acl_internal(handle, NULL,
698 name, security_info, ppdesc);
701 /*********************************************************************
702 Store a security descriptor given an fsp.
703 *********************************************************************/
705 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
706 uint32_t security_info_sent, const struct security_descriptor *orig_psd)
710 struct security_descriptor *pdesc_next = NULL;
711 struct security_descriptor *psd = NULL;
712 uint8_t hash[XATTR_SD_HASH_SIZE];
714 if (DEBUGLEVEL >= 10) {
715 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
717 NDR_PRINT_DEBUG(security_descriptor,
718 CONST_DISCARD(struct security_descriptor *,orig_psd));
721 status = get_nt_acl_internal(handle, fsp,
723 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
726 if (!NT_STATUS_IS_OK(status)) {
730 psd->revision = orig_psd->revision;
731 /* All our SD's are self relative. */
732 psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE;
734 if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
735 psd->owner_sid = orig_psd->owner_sid;
737 if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
738 psd->group_sid = orig_psd->group_sid;
740 if (security_info_sent & SECINFO_DACL) {
741 psd->dacl = orig_psd->dacl;
742 psd->type |= SEC_DESC_DACL_PRESENT;
744 if (security_info_sent & SECINFO_SACL) {
745 psd->sacl = orig_psd->sacl;
746 psd->type |= SEC_DESC_SACL_PRESENT;
749 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
750 if (!NT_STATUS_IS_OK(status)) {
754 /* Get the full underlying sd, then hash. */
755 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
760 if (!NT_STATUS_IS_OK(status)) {
764 status = hash_sd_sha256(pdesc_next, hash);
765 if (!NT_STATUS_IS_OK(status)) {
769 if (DEBUGLEVEL >= 10) {
770 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
772 NDR_PRINT_DEBUG(security_descriptor,
773 CONST_DISCARD(struct security_descriptor *,psd));
775 create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
776 store_acl_blob_fsp(handle, fsp, &blob);
781 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
782 const char *fname, const char *mask, uint32 attr)
784 NTSTATUS status = check_parent_acl_common(handle, fname,
787 if (!NT_STATUS_IS_OK(status)) {
788 errno = map_errno_from_nt_status(status);
791 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
794 static int acl_common_remove_object(vfs_handle_struct *handle,
798 connection_struct *conn = handle->conn;
800 files_struct *fsp = NULL;
802 char *parent_dir = NULL;
803 const char *final_component = NULL;
804 struct smb_filename local_fname;
807 if (!parent_dirname(talloc_tos(), path,
808 &parent_dir, &final_component)) {
809 saved_errno = ENOMEM;
813 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
814 is_directory ? "directory" : "file",
815 parent_dir, final_component ));
817 /* cd into the parent dir to pin it. */
818 ret = SMB_VFS_CHDIR(conn, parent_dir);
824 ZERO_STRUCT(local_fname);
825 local_fname.base_name = CONST_DISCARD(char *,final_component);
827 /* Must use lstat here. */
828 ret = SMB_VFS_LSTAT(conn, &local_fname);
834 /* Ensure we have this file open with DELETE access. */
835 id = vfs_file_id_from_sbuf(conn, &local_fname.st);
836 for (fsp = file_find_di_first(conn->sconn, id); fsp;
837 file_find_di_next(fsp)) {
838 if (fsp->access_mask & DELETE_ACCESS &&
839 fsp->delete_on_close) {
840 /* We did open this for delete,
841 * allow the delete as root.
848 DEBUG(10,("acl_common_remove_object: %s %s/%s "
849 "not an open file\n",
850 is_directory ? "directory" : "file",
851 parent_dir, final_component ));
852 saved_errno = EACCES;
858 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
860 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
870 TALLOC_FREE(parent_dir);
872 vfs_ChDir(conn, conn->connectpath);
879 static int rmdir_acl_common(struct vfs_handle_struct *handle,
884 ret = SMB_VFS_NEXT_RMDIR(handle, path);
885 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
886 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
892 return acl_common_remove_object(handle,
897 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
898 struct smb_request *req,
899 uint16_t root_dir_fid,
900 struct smb_filename *smb_fname,
901 uint32_t access_mask,
902 uint32_t share_access,
903 uint32_t create_disposition,
904 uint32_t create_options,
905 uint32_t file_attributes,
906 uint32_t oplock_request,
907 uint64_t allocation_size,
908 uint32_t private_flags,
909 struct security_descriptor *sd,
910 struct ea_list *ea_list,
911 files_struct **result,
914 NTSTATUS status, status1;
915 files_struct *fsp = NULL;
917 struct security_descriptor *parent_sd = NULL;
919 status = SMB_VFS_NEXT_CREATE_FILE(handle,
936 if (!NT_STATUS_IS_OK(status)) {
940 if (info != FILE_WAS_CREATED) {
941 /* File/directory was opened, not created. */
948 /* Only handle success. */
953 /* Security descriptor already set. */
963 /* We must have a cached parent sd in this case.
964 * attached to the handle. */
966 SMB_VFS_HANDLE_GET_DATA(handle, parent_sd,
967 struct security_descriptor,
974 /* New directory - inherit from parent. */
975 status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
977 if (!NT_STATUS_IS_OK(status1)) {
978 DEBUG(1,("create_file_acl_common: error setting "
981 nt_errstr(status1) ));
986 /* Ensure we never leave attached data around. */
987 SMB_VFS_HANDLE_FREE_DATA(handle);
989 if (NT_STATUS_IS_OK(status) && pinfo) {
996 smb_panic("create_file_acl_common: logic error.\n");
1001 static int unlink_acl_common(struct vfs_handle_struct *handle,
1002 const struct smb_filename *smb_fname)
1006 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1007 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
1008 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1009 smb_fname->base_name,
1013 /* Don't do anything fancy for streams. */
1014 if (smb_fname->stream_name) {
1018 return acl_common_remove_object(handle,
1019 smb_fname->base_name,