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;
259 bool ignore_file_system_acl = lp_parm_bool(SNUM(handle->conn),
261 "ignore system acls",
264 if (fsp && name == NULL) {
265 name = fsp->fsp_name->base_name;
268 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
270 /* Get the full underlying sd for the hash
271 or to return as backup. */
273 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
278 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
284 if (!NT_STATUS_IS_OK(status)) {
285 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
292 status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
293 if (!NT_STATUS_IS_OK(status)) {
294 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
300 status = parse_acl_blob(&blob, &psd,
301 &hash_type, &hash[0]);
302 if (!NT_STATUS_IS_OK(status)) {
303 DEBUG(10, ("parse_acl_blob returned %s\n",
309 /* Ensure the hash type is one we know. */
311 case XATTR_SD_HASH_TYPE_NONE:
312 /* No hash, just return blob sd. */
314 case XATTR_SD_HASH_TYPE_SHA256:
317 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
318 "mismatch (%u) for file %s\n",
319 (unsigned int)hash_type,
326 if (ignore_file_system_acl) {
330 status = hash_sd_sha256(pdesc_next, hash_tmp);
331 if (!NT_STATUS_IS_OK(status)) {
337 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
338 /* Hash matches, return blob sd. */
339 DEBUG(10, ("get_nt_acl_internal: blob hash "
340 "matches for file %s\n",
345 /* Hash doesn't match, return underlying sd. */
351 if (psd != pdesc_next) {
352 /* We're returning the blob, throw
353 * away the filesystem SD. */
354 TALLOC_FREE(pdesc_next);
356 SMB_STRUCT_STAT sbuf;
357 SMB_STRUCT_STAT *psbuf = &sbuf;
358 bool is_directory = false;
360 * We're returning the underlying ACL from the
361 * filesystem. If it's a directory, and has no
362 * inheritable ACE entries we have to fake them.
365 status = vfs_stat_fsp(fsp);
366 if (!NT_STATUS_IS_OK(status)) {
369 psbuf = &fsp->fsp_name->st;
371 int ret = vfs_stat_smb_fname(handle->conn,
375 return map_nt_error_from_unix(errno);
378 is_directory = S_ISDIR(sbuf.st_ex_mode);
380 if (ignore_file_system_acl) {
381 TALLOC_FREE(pdesc_next);
382 status = make_default_filesystem_acl(talloc_tos(),
386 if (!NT_STATUS_IS_OK(status)) {
391 !sd_has_inheritable_components(psd,
393 add_directory_inheritable_components(handle,
398 /* The underlying POSIX module always sets
399 the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
400 can't be inherited in this way under POSIX.
401 Remove it for Windows-style ACLs. */
402 psd->type &= ~SEC_DESC_DACL_PROTECTED;
406 if (!(security_info & SECINFO_OWNER)) {
407 psd->owner_sid = NULL;
409 if (!(security_info & SECINFO_GROUP)) {
410 psd->group_sid = NULL;
412 if (!(security_info & SECINFO_DACL)) {
415 if (!(security_info & SECINFO_SACL)) {
419 TALLOC_FREE(blob.data);
422 if (DEBUGLEVEL >= 10) {
423 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
425 NDR_PRINT_DEBUG(security_descriptor, psd);
431 /*********************************************************************
432 Create a default ACL by inheriting from the parent. If no inheritance
433 from the parent available, don't set anything. This will leave the actual
434 permissions the new file or directory already got from the filesystem
435 as the NT ACL when read.
436 *********************************************************************/
438 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
440 struct security_descriptor *parent_desc,
443 TALLOC_CTX *ctx = talloc_tos();
444 NTSTATUS status = NT_STATUS_OK;
445 struct security_descriptor *psd = NULL;
448 if (!sd_has_inheritable_components(parent_desc, is_directory)) {
452 /* Create an inherited descriptor from the parent. */
454 if (DEBUGLEVEL >= 10) {
455 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
457 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
460 status = se_create_child_secdesc(ctx,
464 &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
465 &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
467 if (!NT_STATUS_IS_OK(status)) {
471 if (DEBUGLEVEL >= 10) {
472 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
474 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
477 return SMB_VFS_FSET_NT_ACL(fsp,
484 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
486 uint32_t access_mask,
487 struct security_descriptor **pp_parent_desc)
489 char *parent_name = NULL;
490 struct security_descriptor *parent_desc = NULL;
491 uint32_t access_granted = 0;
494 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
495 return NT_STATUS_NO_MEMORY;
498 status = get_nt_acl_internal(handle,
506 if (!NT_STATUS_IS_OK(status)) {
507 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
508 "on directory %s for "
509 "path %s returned %s\n",
512 nt_errstr(status) ));
515 if (pp_parent_desc) {
516 *pp_parent_desc = parent_desc;
518 status = smb1_file_se_access_check(handle->conn,
520 get_current_nttok(handle->conn),
523 if(!NT_STATUS_IS_OK(status)) {
524 DEBUG(10,("check_parent_acl_common: access check "
525 "on directory %s for "
526 "path %s for mask 0x%x returned %s\n",
530 nt_errstr(status) ));
536 static void free_sd_common(void **ptr)
541 /*********************************************************************
542 Check ACL on open. For new files inherit from parent directory.
543 *********************************************************************/
545 static int open_acl_common(vfs_handle_struct *handle,
546 struct smb_filename *smb_fname,
551 uint32_t access_granted = 0;
552 struct security_descriptor *pdesc = NULL;
553 struct security_descriptor *parent_desc = NULL;
554 bool file_existed = true;
559 /* Stream open. Base filename open already did the ACL check. */
560 DEBUG(10,("open_acl_common: stream open on %s\n",
562 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
565 status = get_full_smb_filename(talloc_tos(), smb_fname,
567 if (!NT_STATUS_IS_OK(status)) {
571 status = get_nt_acl_internal(handle,
578 if (NT_STATUS_IS_OK(status)) {
579 /* See if we can access it. */
580 status = smb1_file_se_access_check(handle->conn,
582 get_current_nttok(handle->conn),
585 if (!NT_STATUS_IS_OK(status)) {
586 DEBUG(10,("open_acl_xattr: %s open "
587 "refused with error %s\n",
589 nt_errstr(status) ));
592 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
593 file_existed = false;
595 * If O_CREAT is true then we're trying to create a file.
596 * Check the parent directory ACL will allow this.
598 if (flags & O_CREAT) {
599 struct security_descriptor *psd = NULL;
601 status = check_parent_acl_common(handle, fname,
602 SEC_DIR_ADD_FILE, &parent_desc);
603 if (!NT_STATUS_IS_OK(status)) {
606 /* Cache the parent security descriptor for
607 * later use. We do have an fsp here, but to
608 * keep the code consistent with the directory
609 * case which doesn't, use the handle. */
611 /* Attach this to the conn, move from talloc_tos(). */
612 psd = (struct security_descriptor *)talloc_move(handle->conn,
616 status = NT_STATUS_NO_MEMORY;
619 status = NT_STATUS_NO_MEMORY;
620 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
621 struct security_descriptor *, goto err);
622 status = NT_STATUS_OK;
626 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
629 nt_errstr(status) ));
631 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
636 errno = map_errno_from_nt_status(status);
640 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
644 SMB_STRUCT_STAT sbuf;
646 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
647 if (ret == -1 && errno == ENOENT) {
648 struct security_descriptor *parent_desc = NULL;
649 struct security_descriptor *psd = NULL;
651 /* We're creating a new directory. */
652 status = check_parent_acl_common(handle, path,
653 SEC_DIR_ADD_SUBDIR, &parent_desc);
654 if (!NT_STATUS_IS_OK(status)) {
655 errno = map_errno_from_nt_status(status);
659 /* Cache the parent security descriptor for
660 * later use. We don't have an fsp here so
663 /* Attach this to the conn, move from talloc_tos(). */
664 psd = (struct security_descriptor *)talloc_move(handle->conn,
670 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
671 struct security_descriptor *, return -1);
674 return SMB_VFS_NEXT_MKDIR(handle, path, mode);
677 /*********************************************************************
678 Fetch a security descriptor given an fsp.
679 *********************************************************************/
681 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
682 uint32_t security_info, struct security_descriptor **ppdesc)
684 return get_nt_acl_internal(handle, fsp,
685 NULL, security_info, ppdesc);
688 /*********************************************************************
689 Fetch a security descriptor given a pathname.
690 *********************************************************************/
692 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
693 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
695 return get_nt_acl_internal(handle, NULL,
696 name, security_info, ppdesc);
699 /*********************************************************************
700 Store a security descriptor given an fsp.
701 *********************************************************************/
703 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
704 uint32_t security_info_sent, const struct security_descriptor *orig_psd)
708 struct security_descriptor *pdesc_next = NULL;
709 struct security_descriptor *psd = NULL;
710 uint8_t hash[XATTR_SD_HASH_SIZE];
712 if (DEBUGLEVEL >= 10) {
713 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
715 NDR_PRINT_DEBUG(security_descriptor,
716 CONST_DISCARD(struct security_descriptor *,orig_psd));
719 status = get_nt_acl_internal(handle, fsp,
721 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
724 if (!NT_STATUS_IS_OK(status)) {
728 if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
729 psd->owner_sid = orig_psd->owner_sid;
731 if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
732 psd->group_sid = orig_psd->group_sid;
734 if (security_info_sent & SECINFO_DACL) {
735 psd->dacl = orig_psd->dacl;
737 if (security_info_sent & SECINFO_SACL) {
738 psd->sacl = orig_psd->sacl;
741 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
742 if (!NT_STATUS_IS_OK(status)) {
746 /* Get the full underlying sd, then hash. */
747 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
752 if (!NT_STATUS_IS_OK(status)) {
756 status = hash_sd_sha256(pdesc_next, hash);
757 if (!NT_STATUS_IS_OK(status)) {
761 if (DEBUGLEVEL >= 10) {
762 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
764 NDR_PRINT_DEBUG(security_descriptor,
765 CONST_DISCARD(struct security_descriptor *,psd));
767 create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
768 store_acl_blob_fsp(handle, fsp, &blob);
773 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
774 const char *fname, const char *mask, uint32 attr)
776 NTSTATUS status = check_parent_acl_common(handle, fname,
779 if (!NT_STATUS_IS_OK(status)) {
780 errno = map_errno_from_nt_status(status);
783 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
786 static int acl_common_remove_object(vfs_handle_struct *handle,
790 connection_struct *conn = handle->conn;
792 files_struct *fsp = NULL;
794 char *parent_dir = NULL;
795 const char *final_component = NULL;
796 struct smb_filename local_fname;
799 if (!parent_dirname(talloc_tos(), path,
800 &parent_dir, &final_component)) {
801 saved_errno = ENOMEM;
805 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
806 is_directory ? "directory" : "file",
807 parent_dir, final_component ));
809 /* cd into the parent dir to pin it. */
810 ret = SMB_VFS_CHDIR(conn, parent_dir);
816 ZERO_STRUCT(local_fname);
817 local_fname.base_name = CONST_DISCARD(char *,final_component);
819 /* Must use lstat here. */
820 ret = SMB_VFS_LSTAT(conn, &local_fname);
826 /* Ensure we have this file open with DELETE access. */
827 id = vfs_file_id_from_sbuf(conn, &local_fname.st);
828 for (fsp = file_find_di_first(id); fsp; file_find_di_next(fsp)) {
829 if (fsp->access_mask & DELETE_ACCESS &&
830 fsp->delete_on_close) {
831 /* We did open this for delete,
832 * allow the delete as root.
839 DEBUG(10,("acl_common_remove_object: %s %s/%s "
840 "not an open file\n",
841 is_directory ? "directory" : "file",
842 parent_dir, final_component ));
843 saved_errno = EACCES;
849 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
851 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
861 TALLOC_FREE(parent_dir);
863 vfs_ChDir(conn, conn->connectpath);
870 static int rmdir_acl_common(struct vfs_handle_struct *handle,
875 ret = SMB_VFS_NEXT_RMDIR(handle, path);
876 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
877 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
883 return acl_common_remove_object(handle,
888 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
889 struct smb_request *req,
890 uint16_t root_dir_fid,
891 struct smb_filename *smb_fname,
892 uint32_t access_mask,
893 uint32_t share_access,
894 uint32_t create_disposition,
895 uint32_t create_options,
896 uint32_t file_attributes,
897 uint32_t oplock_request,
898 uint64_t allocation_size,
899 uint32_t private_flags,
900 struct security_descriptor *sd,
901 struct ea_list *ea_list,
902 files_struct **result,
905 NTSTATUS status, status1;
906 files_struct *fsp = NULL;
908 struct security_descriptor *parent_sd = NULL;
910 status = SMB_VFS_NEXT_CREATE_FILE(handle,
927 if (!NT_STATUS_IS_OK(status)) {
931 if (info != FILE_WAS_CREATED) {
932 /* File/directory was opened, not created. */
939 /* Only handle success. */
944 /* Security descriptor already set. */
954 /* We must have a cached parent sd in this case.
955 * attached to the handle. */
957 SMB_VFS_HANDLE_GET_DATA(handle, parent_sd,
958 struct security_descriptor,
965 /* New directory - inherit from parent. */
966 status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
968 if (!NT_STATUS_IS_OK(status1)) {
969 DEBUG(1,("create_file_acl_common: error setting "
972 nt_errstr(status1) ));
977 /* Ensure we never leave attached data around. */
978 SMB_VFS_HANDLE_FREE_DATA(handle);
980 if (NT_STATUS_IS_OK(status) && pinfo) {
987 smb_panic("create_file_acl_common: logic error.\n");
992 static int unlink_acl_common(struct vfs_handle_struct *handle,
993 const struct smb_filename *smb_fname)
997 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
998 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
999 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1000 smb_fname->base_name,
1004 /* Don't do anything fancy for streams. */
1005 if (smb_fname->stream_name) {
1009 return acl_common_remove_object(handle,
1010 smb_fname->base_name,