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 "smbd/smbd.h"
23 #include "system/filesys.h"
24 #include "../libcli/security/security.h"
25 #include "../librpc/gen_ndr/ndr_security.h"
26 #include "../lib/util/bitmap.h"
28 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
31 uint8_t hash[XATTR_SD_HASH_SIZE]);
33 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
34 vfs_handle_struct *handle,
39 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
43 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
48 /*******************************************************************
49 Hash a security descriptor.
50 *******************************************************************/
52 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
59 memset(hash, '\0', XATTR_SD_HASH_SIZE);
60 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
61 if (!NT_STATUS_IS_OK(status)) {
65 samba_SHA256_Init(&tctx);
66 samba_SHA256_Update(&tctx, blob.data, blob.length);
67 samba_SHA256_Final(hash, &tctx);
72 /*******************************************************************
73 Parse out a struct security_descriptor from a DATA_BLOB.
74 *******************************************************************/
76 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
77 struct security_descriptor **ppdesc,
78 uint16_t *p_hash_type,
79 uint8_t hash[XATTR_SD_HASH_SIZE])
81 TALLOC_CTX *ctx = talloc_tos();
82 struct xattr_NTACL xacl;
83 enum ndr_err_code ndr_err;
86 ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
87 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
89 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
90 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
91 ndr_errstr(ndr_err)));
92 return ndr_map_error2ntstatus(ndr_err);
95 switch (xacl.version) {
97 *ppdesc = make_sec_desc(ctx, SD_REVISION,
98 xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
99 xacl.info.sd_hs2->sd->owner_sid,
100 xacl.info.sd_hs2->sd->group_sid,
101 xacl.info.sd_hs2->sd->sacl,
102 xacl.info.sd_hs2->sd->dacl,
104 /* No hash - null out. */
105 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
106 memset(hash, '\0', XATTR_SD_HASH_SIZE);
109 *ppdesc = make_sec_desc(ctx, SD_REVISION,
110 xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
111 xacl.info.sd_hs3->sd->owner_sid,
112 xacl.info.sd_hs3->sd->group_sid,
113 xacl.info.sd_hs3->sd->sacl,
114 xacl.info.sd_hs3->sd->dacl,
116 *p_hash_type = xacl.info.sd_hs3->hash_type;
117 /* Current version 3. */
118 memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
121 return NT_STATUS_REVISION_MISMATCH;
124 TALLOC_FREE(xacl.info.sd);
126 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
129 /*******************************************************************
130 Create a DATA_BLOB from a security descriptor.
131 *******************************************************************/
133 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
136 uint8_t hash[XATTR_SD_HASH_SIZE])
138 struct xattr_NTACL xacl;
139 struct security_descriptor_hash_v3 sd_hs3;
140 enum ndr_err_code ndr_err;
141 TALLOC_CTX *ctx = talloc_tos();
147 xacl.info.sd_hs3 = &sd_hs3;
148 xacl.info.sd_hs3->sd = discard_const_p(struct security_descriptor, psd);
149 xacl.info.sd_hs3->hash_type = hash_type;
150 memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
152 ndr_err = ndr_push_struct_blob(
154 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
156 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
157 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
158 ndr_errstr(ndr_err)));
159 return ndr_map_error2ntstatus(ndr_err);
165 /*******************************************************************
166 Add in 3 inheritable components for a non-inheritable directory ACL.
167 CREATOR_OWNER/CREATOR_GROUP/WORLD.
168 *******************************************************************/
170 static void add_directory_inheritable_components(vfs_handle_struct *handle,
172 SMB_STRUCT_STAT *psbuf,
173 struct security_descriptor *psd)
175 struct connection_struct *conn = handle->conn;
176 int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
177 struct smb_filename smb_fname;
178 enum security_ace_type acltype;
179 uint32_t access_mask;
183 struct security_ace *new_ace_list = talloc_zero_array(talloc_tos(),
187 if (new_ace_list == NULL) {
191 /* Fake a quick smb_filename. */
192 ZERO_STRUCT(smb_fname);
193 smb_fname.st = *psbuf;
194 smb_fname.base_name = discard_const_p(char, name);
196 dir_mode = unix_mode(conn,
197 FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
198 file_mode = unix_mode(conn,
199 FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
201 mode = dir_mode | file_mode;
203 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
206 (unsigned int)mode ));
209 memcpy(new_ace_list, psd->dacl->aces,
210 num_aces * sizeof(struct security_ace));
212 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
215 init_sec_ace(&new_ace_list[num_aces],
216 &global_sid_Creator_Owner,
219 SEC_ACE_FLAG_CONTAINER_INHERIT|
220 SEC_ACE_FLAG_OBJECT_INHERIT|
221 SEC_ACE_FLAG_INHERIT_ONLY);
222 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
223 (mode << 3) & 0700, false);
224 init_sec_ace(&new_ace_list[num_aces+1],
225 &global_sid_Creator_Group,
228 SEC_ACE_FLAG_CONTAINER_INHERIT|
229 SEC_ACE_FLAG_OBJECT_INHERIT|
230 SEC_ACE_FLAG_INHERIT_ONLY);
231 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
232 (mode << 6) & 0700, false);
233 init_sec_ace(&new_ace_list[num_aces+2],
237 SEC_ACE_FLAG_CONTAINER_INHERIT|
238 SEC_ACE_FLAG_OBJECT_INHERIT|
239 SEC_ACE_FLAG_INHERIT_ONLY);
240 psd->dacl->aces = new_ace_list;
241 psd->dacl->num_aces += 3;
244 /*******************************************************************
245 Pull a DATA_BLOB from an xattr given a pathname.
246 If the hash doesn't match, or doesn't exist - return the underlying
248 *******************************************************************/
250 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
253 uint32_t security_info,
254 struct security_descriptor **ppdesc)
258 uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
259 uint8_t hash[XATTR_SD_HASH_SIZE];
260 uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
261 struct security_descriptor *psd = NULL;
262 struct security_descriptor *pdesc_next = NULL;
263 bool ignore_file_system_acl = lp_parm_bool(SNUM(handle->conn),
265 "ignore system acls",
268 if (fsp && name == NULL) {
269 name = fsp->fsp_name->base_name;
272 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
274 /* Get the full underlying sd for the hash
275 or to return as backup. */
277 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
282 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
288 if (!NT_STATUS_IS_OK(status)) {
289 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
296 status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
297 if (!NT_STATUS_IS_OK(status)) {
298 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
304 status = parse_acl_blob(&blob, &psd,
305 &hash_type, &hash[0]);
306 if (!NT_STATUS_IS_OK(status)) {
307 DEBUG(10, ("parse_acl_blob returned %s\n",
313 /* Ensure the hash type is one we know. */
315 case XATTR_SD_HASH_TYPE_NONE:
316 /* No hash, just return blob sd. */
318 case XATTR_SD_HASH_TYPE_SHA256:
321 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
322 "mismatch (%u) for file %s\n",
323 (unsigned int)hash_type,
330 if (ignore_file_system_acl) {
334 status = hash_sd_sha256(pdesc_next, hash_tmp);
335 if (!NT_STATUS_IS_OK(status)) {
341 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
342 /* Hash matches, return blob sd. */
343 DEBUG(10, ("get_nt_acl_internal: blob hash "
344 "matches for file %s\n",
349 /* Hash doesn't match, return underlying sd. */
355 if (psd != pdesc_next) {
356 /* We're returning the blob, throw
357 * away the filesystem SD. */
358 TALLOC_FREE(pdesc_next);
360 SMB_STRUCT_STAT sbuf;
361 SMB_STRUCT_STAT *psbuf = &sbuf;
362 bool is_directory = false;
364 * We're returning the underlying ACL from the
365 * filesystem. If it's a directory, and has no
366 * inheritable ACE entries we have to fake them.
369 status = vfs_stat_fsp(fsp);
370 if (!NT_STATUS_IS_OK(status)) {
373 psbuf = &fsp->fsp_name->st;
375 int ret = vfs_stat_smb_fname(handle->conn,
379 return map_nt_error_from_unix(errno);
382 is_directory = S_ISDIR(sbuf.st_ex_mode);
384 if (ignore_file_system_acl) {
385 TALLOC_FREE(pdesc_next);
386 status = make_default_filesystem_acl(talloc_tos(),
390 if (!NT_STATUS_IS_OK(status)) {
395 !sd_has_inheritable_components(psd,
397 add_directory_inheritable_components(handle,
402 /* The underlying POSIX module always sets
403 the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
404 can't be inherited in this way under POSIX.
405 Remove it for Windows-style ACLs. */
406 psd->type &= ~SEC_DESC_DACL_PROTECTED;
410 if (!(security_info & SECINFO_OWNER)) {
411 psd->owner_sid = NULL;
413 if (!(security_info & SECINFO_GROUP)) {
414 psd->group_sid = NULL;
416 if (!(security_info & SECINFO_DACL)) {
419 if (!(security_info & SECINFO_SACL)) {
423 TALLOC_FREE(blob.data);
426 if (DEBUGLEVEL >= 10) {
427 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
429 NDR_PRINT_DEBUG(security_descriptor, psd);
435 /*********************************************************************
436 Create a default ACL by inheriting from the parent. If no inheritance
437 from the parent available, don't set anything. This will leave the actual
438 permissions the new file or directory already got from the filesystem
439 as the NT ACL when read.
440 *********************************************************************/
442 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
444 struct security_descriptor *parent_desc,
447 TALLOC_CTX *ctx = talloc_tos();
448 NTSTATUS status = NT_STATUS_OK;
449 struct security_descriptor *psd = NULL;
450 struct dom_sid *owner_sid = NULL;
451 struct dom_sid *group_sid = NULL;
452 uint32_t security_info_sent = (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL);
453 bool inherit_owner = lp_inherit_owner(SNUM(handle->conn));
454 bool inheritable_components = sd_has_inheritable_components(parent_desc,
458 if (!inheritable_components && !inherit_owner) {
459 /* Nothing to inherit and not setting owner. */
463 /* Create an inherited descriptor from the parent. */
465 if (DEBUGLEVEL >= 10) {
466 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
468 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
471 /* Inherit from parent descriptor if "inherit owner" set. */
473 owner_sid = parent_desc->owner_sid;
474 group_sid = parent_desc->group_sid;
477 if (owner_sid == NULL) {
478 owner_sid = &handle->conn->session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
480 if (group_sid == NULL) {
481 group_sid = &handle->conn->session_info->security_token->sids[PRIMARY_GROUP_SID_INDEX];
484 status = se_create_child_secdesc(ctx,
491 if (!NT_STATUS_IS_OK(status)) {
495 /* If inheritable_components == false,
496 se_create_child_secdesc()
497 creates a security desriptor with a NULL dacl
498 entry, but with SEC_DESC_DACL_PRESENT. We need
499 to remove that flag. */
501 if (!inheritable_components) {
502 security_info_sent &= ~SECINFO_DACL;
503 psd->type &= ~SEC_DESC_DACL_PRESENT;
506 if (DEBUGLEVEL >= 10) {
507 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
509 NDR_PRINT_DEBUG(security_descriptor, psd);
513 /* We need to be root to force this. */
516 status = SMB_VFS_FSET_NT_ACL(fsp,
525 static NTSTATUS get_parent_acl_common(vfs_handle_struct *handle,
527 struct security_descriptor **pp_parent_desc)
529 char *parent_name = NULL;
532 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
533 return NT_STATUS_NO_MEMORY;
536 status = get_nt_acl_internal(handle,
544 if (!NT_STATUS_IS_OK(status)) {
545 DEBUG(10,("get_parent_acl_common: get_nt_acl_internal "
546 "on directory %s for "
547 "path %s returned %s\n",
550 nt_errstr(status) ));
555 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
557 uint32_t access_mask,
558 struct security_descriptor **pp_parent_desc)
560 char *parent_name = NULL;
561 struct security_descriptor *parent_desc = NULL;
562 uint32_t access_granted = 0;
565 status = get_parent_acl_common(handle, path, &parent_desc);
566 if (!NT_STATUS_IS_OK(status)) {
569 if (pp_parent_desc) {
570 *pp_parent_desc = parent_desc;
572 status = smb1_file_se_access_check(handle->conn,
574 get_current_nttok(handle->conn),
577 if(!NT_STATUS_IS_OK(status)) {
578 DEBUG(10,("check_parent_acl_common: access check "
579 "on directory %s for "
580 "path %s for mask 0x%x returned %s\n",
584 nt_errstr(status) ));
590 /*********************************************************************
591 Check ACL on open. For new files inherit from parent directory.
592 *********************************************************************/
594 static int open_acl_common(vfs_handle_struct *handle,
595 struct smb_filename *smb_fname,
600 uint32_t access_granted = 0;
601 struct security_descriptor *pdesc = NULL;
602 bool file_existed = true;
607 /* Stream open. Base filename open already did the ACL check. */
608 DEBUG(10,("open_acl_common: stream open on %s\n",
610 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
613 status = get_full_smb_filename(talloc_tos(), smb_fname,
615 if (!NT_STATUS_IS_OK(status)) {
619 status = get_nt_acl_internal(handle,
626 if (NT_STATUS_IS_OK(status)) {
627 /* See if we can access it. */
628 status = smb1_file_se_access_check(handle->conn,
630 get_current_nttok(handle->conn),
633 if (!NT_STATUS_IS_OK(status)) {
634 DEBUG(10,("open_acl_xattr: %s open "
635 "refused with error %s\n",
637 nt_errstr(status) ));
640 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
641 file_existed = false;
643 * If O_CREAT is true then we're trying to create a file.
644 * Check the parent directory ACL will allow this.
646 if (flags & O_CREAT) {
647 struct security_descriptor *parent_desc = NULL;
648 struct security_descriptor **pp_psd = NULL;
650 status = check_parent_acl_common(handle, fname,
651 SEC_DIR_ADD_FILE, &parent_desc);
652 if (!NT_STATUS_IS_OK(status)) {
656 /* Cache the parent security descriptor for
659 pp_psd = VFS_ADD_FSP_EXTENSION(handle,
661 struct security_descriptor *,
664 status = NT_STATUS_NO_MEMORY;
668 *pp_psd = parent_desc;
669 status = NT_STATUS_OK;
673 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
676 nt_errstr(status) ));
678 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
683 errno = map_errno_from_nt_status(status);
687 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
691 SMB_STRUCT_STAT sbuf;
693 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
694 if (ret == -1 && errno == ENOENT) {
695 /* We're creating a new directory. */
696 status = check_parent_acl_common(handle, path,
697 SEC_DIR_ADD_SUBDIR, NULL);
698 if (!NT_STATUS_IS_OK(status)) {
699 errno = map_errno_from_nt_status(status);
704 return SMB_VFS_NEXT_MKDIR(handle, path, mode);
707 /*********************************************************************
708 Fetch a security descriptor given an fsp.
709 *********************************************************************/
711 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
712 uint32_t security_info, struct security_descriptor **ppdesc)
714 return get_nt_acl_internal(handle, fsp,
715 NULL, security_info, ppdesc);
718 /*********************************************************************
719 Fetch a security descriptor given a pathname.
720 *********************************************************************/
722 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
723 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
725 return get_nt_acl_internal(handle, NULL,
726 name, security_info, ppdesc);
729 /*********************************************************************
730 Store a security descriptor given an fsp.
731 *********************************************************************/
733 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
734 uint32_t security_info_sent, const struct security_descriptor *orig_psd)
738 struct security_descriptor *pdesc_next = NULL;
739 struct security_descriptor *psd = NULL;
740 uint8_t hash[XATTR_SD_HASH_SIZE];
742 if (DEBUGLEVEL >= 10) {
743 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
745 NDR_PRINT_DEBUG(security_descriptor,
746 discard_const_p(struct security_descriptor, orig_psd));
749 status = get_nt_acl_internal(handle, fsp,
751 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
754 if (!NT_STATUS_IS_OK(status)) {
758 psd->revision = orig_psd->revision;
759 /* All our SD's are self relative. */
760 psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE;
762 if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
763 psd->owner_sid = orig_psd->owner_sid;
765 if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
766 psd->group_sid = orig_psd->group_sid;
768 if (security_info_sent & SECINFO_DACL) {
769 psd->dacl = orig_psd->dacl;
770 psd->type |= SEC_DESC_DACL_PRESENT;
772 if (security_info_sent & SECINFO_SACL) {
773 psd->sacl = orig_psd->sacl;
774 psd->type |= SEC_DESC_SACL_PRESENT;
777 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
778 if (!NT_STATUS_IS_OK(status)) {
782 /* Get the full underlying sd, then hash. */
783 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
788 if (!NT_STATUS_IS_OK(status)) {
792 status = hash_sd_sha256(pdesc_next, hash);
793 if (!NT_STATUS_IS_OK(status)) {
797 if (DEBUGLEVEL >= 10) {
798 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
800 NDR_PRINT_DEBUG(security_descriptor,
801 discard_const_p(struct security_descriptor, psd));
803 create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
804 store_acl_blob_fsp(handle, fsp, &blob);
809 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
810 const char *fname, const char *mask, uint32 attr)
812 NTSTATUS status = check_parent_acl_common(handle, fname,
815 if (!NT_STATUS_IS_OK(status)) {
816 errno = map_errno_from_nt_status(status);
819 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
822 static int acl_common_remove_object(vfs_handle_struct *handle,
826 connection_struct *conn = handle->conn;
828 files_struct *fsp = NULL;
830 char *parent_dir = NULL;
831 const char *final_component = NULL;
832 struct smb_filename local_fname;
835 if (!parent_dirname(talloc_tos(), path,
836 &parent_dir, &final_component)) {
837 saved_errno = ENOMEM;
841 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
842 is_directory ? "directory" : "file",
843 parent_dir, final_component ));
845 /* cd into the parent dir to pin it. */
846 ret = SMB_VFS_CHDIR(conn, parent_dir);
852 ZERO_STRUCT(local_fname);
853 local_fname.base_name = discard_const_p(char, final_component);
855 /* Must use lstat here. */
856 ret = SMB_VFS_LSTAT(conn, &local_fname);
862 /* Ensure we have this file open with DELETE access. */
863 id = vfs_file_id_from_sbuf(conn, &local_fname.st);
864 for (fsp = file_find_di_first(conn->sconn, id); fsp;
865 file_find_di_next(fsp)) {
866 if (fsp->access_mask & DELETE_ACCESS &&
867 fsp->delete_on_close) {
868 /* We did open this for delete,
869 * allow the delete as root.
876 DEBUG(10,("acl_common_remove_object: %s %s/%s "
877 "not an open file\n",
878 is_directory ? "directory" : "file",
879 parent_dir, final_component ));
880 saved_errno = EACCES;
886 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
888 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
898 TALLOC_FREE(parent_dir);
900 vfs_ChDir(conn, conn->connectpath);
907 static int rmdir_acl_common(struct vfs_handle_struct *handle,
912 ret = SMB_VFS_NEXT_RMDIR(handle, path);
913 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
914 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
920 return acl_common_remove_object(handle,
925 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
926 struct smb_request *req,
927 uint16_t root_dir_fid,
928 struct smb_filename *smb_fname,
929 uint32_t access_mask,
930 uint32_t share_access,
931 uint32_t create_disposition,
932 uint32_t create_options,
933 uint32_t file_attributes,
934 uint32_t oplock_request,
935 uint64_t allocation_size,
936 uint32_t private_flags,
937 struct security_descriptor *sd,
938 struct ea_list *ea_list,
939 files_struct **result,
942 NTSTATUS status, status1;
943 files_struct *fsp = NULL;
945 struct security_descriptor *parent_sd = NULL;
946 struct security_descriptor **pp_parent_sd = NULL;
948 status = SMB_VFS_NEXT_CREATE_FILE(handle,
965 if (!NT_STATUS_IS_OK(status)) {
969 if (info != FILE_WAS_CREATED) {
970 /* File/directory was opened, not created. */
977 /* Only handle success. */
982 /* Security descriptor already set. */
991 /* See if we have a cached parent sd, if so, use it. */
992 pp_parent_sd = (struct security_descriptor **)VFS_FETCH_FSP_EXTENSION(handle, fsp);
994 /* Must be a directory, fetch again (sigh). */
995 status = get_parent_acl_common(handle,
996 fsp->fsp_name->base_name,
998 if (!NT_STATUS_IS_OK(status)) {
1002 parent_sd = *pp_parent_sd;
1009 /* New directory - inherit from parent. */
1010 status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
1012 if (!NT_STATUS_IS_OK(status1)) {
1013 DEBUG(1,("create_file_acl_common: error setting "
1016 nt_errstr(status1) ));
1022 VFS_REMOVE_FSP_EXTENSION(handle, fsp);
1025 if (NT_STATUS_IS_OK(status) && pinfo) {
1032 smb_panic("create_file_acl_common: logic error.\n");
1037 static int unlink_acl_common(struct vfs_handle_struct *handle,
1038 const struct smb_filename *smb_fname)
1042 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1043 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
1044 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1045 smb_fname->base_name,
1049 /* Don't do anything fancy for streams. */
1050 if (smb_fname->stream_name) {
1054 return acl_common_remove_object(handle,
1055 smb_fname->base_name,
1059 static int chmod_acl_module_common(struct vfs_handle_struct *handle,
1060 const char *path, mode_t mode)
1062 if (lp_posix_pathnames()) {
1063 /* Only allow this on POSIX pathnames. */
1064 return SMB_VFS_NEXT_CHMOD(handle, path, mode);
1069 static int fchmod_acl_module_common(struct vfs_handle_struct *handle,
1070 struct files_struct *fsp, mode_t mode)
1072 if (fsp->posix_open) {
1073 /* Only allow this on POSIX opens. */
1074 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1079 static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1080 const char *name, mode_t mode)
1082 if (lp_posix_pathnames()) {
1083 /* Only allow this on POSIX pathnames. */
1084 return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode);
1089 static int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1090 struct files_struct *fsp, mode_t mode)
1092 if (fsp->posix_open) {
1093 /* Only allow this on POSIX opens. */
1094 return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);