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"
27 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
30 uint8_t hash[XATTR_SD_HASH_SIZE]);
32 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
33 vfs_handle_struct *handle,
38 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
42 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
47 /*******************************************************************
48 Hash a security descriptor.
49 *******************************************************************/
51 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
58 memset(hash, '\0', XATTR_SD_HASH_SIZE);
59 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
60 if (!NT_STATUS_IS_OK(status)) {
65 SHA256_Update(&tctx, blob.data, blob.length);
66 SHA256_Final(hash, &tctx);
71 /*******************************************************************
72 Parse out a struct security_descriptor from a DATA_BLOB.
73 *******************************************************************/
75 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
76 struct security_descriptor **ppdesc,
77 uint16_t *p_hash_type,
78 uint8_t hash[XATTR_SD_HASH_SIZE])
80 TALLOC_CTX *ctx = talloc_tos();
81 struct xattr_NTACL xacl;
82 enum ndr_err_code ndr_err;
85 ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
86 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
88 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
89 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
90 ndr_errstr(ndr_err)));
91 return ndr_map_error2ntstatus(ndr_err);
94 switch (xacl.version) {
96 *ppdesc = make_sec_desc(ctx, SD_REVISION,
97 xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
98 xacl.info.sd_hs2->sd->owner_sid,
99 xacl.info.sd_hs2->sd->group_sid,
100 xacl.info.sd_hs2->sd->sacl,
101 xacl.info.sd_hs2->sd->dacl,
103 /* No hash - null out. */
104 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
105 memset(hash, '\0', XATTR_SD_HASH_SIZE);
108 *ppdesc = make_sec_desc(ctx, SD_REVISION,
109 xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
110 xacl.info.sd_hs3->sd->owner_sid,
111 xacl.info.sd_hs3->sd->group_sid,
112 xacl.info.sd_hs3->sd->sacl,
113 xacl.info.sd_hs3->sd->dacl,
115 *p_hash_type = xacl.info.sd_hs3->hash_type;
116 /* Current version 3. */
117 memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
120 return NT_STATUS_REVISION_MISMATCH;
123 TALLOC_FREE(xacl.info.sd);
125 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
128 /*******************************************************************
129 Create a DATA_BLOB from a security descriptor.
130 *******************************************************************/
132 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
135 uint8_t hash[XATTR_SD_HASH_SIZE])
137 struct xattr_NTACL xacl;
138 struct security_descriptor_hash_v3 sd_hs3;
139 enum ndr_err_code ndr_err;
140 TALLOC_CTX *ctx = talloc_tos();
146 xacl.info.sd_hs3 = &sd_hs3;
147 xacl.info.sd_hs3->sd = CONST_DISCARD(struct security_descriptor *, psd);
148 xacl.info.sd_hs3->hash_type = hash_type;
149 memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
151 ndr_err = ndr_push_struct_blob(
153 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
155 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
156 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
157 ndr_errstr(ndr_err)));
158 return ndr_map_error2ntstatus(ndr_err);
164 /*******************************************************************
165 Add in 3 inheritable components for a non-inheritable directory ACL.
166 CREATOR_OWNER/CREATOR_GROUP/WORLD.
167 *******************************************************************/
169 static void add_directory_inheritable_components(vfs_handle_struct *handle,
171 SMB_STRUCT_STAT *psbuf,
172 struct security_descriptor *psd)
174 struct connection_struct *conn = handle->conn;
175 int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
176 struct smb_filename smb_fname;
177 enum security_ace_type acltype;
178 uint32_t access_mask;
182 struct security_ace *new_ace_list = TALLOC_ZERO_ARRAY(talloc_tos(),
186 if (new_ace_list == NULL) {
190 /* Fake a quick smb_filename. */
191 ZERO_STRUCT(smb_fname);
192 smb_fname.st = *psbuf;
193 smb_fname.base_name = CONST_DISCARD(char *, name);
195 dir_mode = unix_mode(conn,
196 FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
197 file_mode = unix_mode(conn,
198 FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
200 mode = dir_mode | file_mode;
202 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
205 (unsigned int)mode ));
208 memcpy(new_ace_list, psd->dacl->aces,
209 num_aces * sizeof(struct security_ace));
211 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
214 init_sec_ace(&new_ace_list[num_aces],
215 &global_sid_Creator_Owner,
218 SEC_ACE_FLAG_CONTAINER_INHERIT|
219 SEC_ACE_FLAG_OBJECT_INHERIT|
220 SEC_ACE_FLAG_INHERIT_ONLY);
221 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
222 (mode << 3) & 0700, false);
223 init_sec_ace(&new_ace_list[num_aces+1],
224 &global_sid_Creator_Group,
227 SEC_ACE_FLAG_CONTAINER_INHERIT|
228 SEC_ACE_FLAG_OBJECT_INHERIT|
229 SEC_ACE_FLAG_INHERIT_ONLY);
230 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
231 (mode << 6) & 0700, false);
232 init_sec_ace(&new_ace_list[num_aces+2],
236 SEC_ACE_FLAG_CONTAINER_INHERIT|
237 SEC_ACE_FLAG_OBJECT_INHERIT|
238 SEC_ACE_FLAG_INHERIT_ONLY);
239 psd->dacl->aces = new_ace_list;
240 psd->dacl->num_aces += 3;
243 /*******************************************************************
244 Pull a DATA_BLOB from an xattr given a pathname.
245 If the hash doesn't match, or doesn't exist - return the underlying
247 *******************************************************************/
249 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
252 uint32_t security_info,
253 struct security_descriptor **ppdesc)
255 DATA_BLOB blob = data_blob_null;
257 uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
258 uint8_t hash[XATTR_SD_HASH_SIZE];
259 uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
260 struct security_descriptor *psd = NULL;
261 struct security_descriptor *pdesc_next = NULL;
262 bool ignore_file_system_acl = lp_parm_bool(SNUM(handle->conn),
264 "ignore system acls",
267 if (fsp && name == NULL) {
268 name = fsp->fsp_name->base_name;
271 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
273 /* Get the full underlying sd for the hash
274 or to return as backup. */
276 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
281 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
287 if (!NT_STATUS_IS_OK(status)) {
288 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
295 status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
296 if (!NT_STATUS_IS_OK(status)) {
297 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
303 status = parse_acl_blob(&blob, &psd,
304 &hash_type, &hash[0]);
305 if (!NT_STATUS_IS_OK(status)) {
306 DEBUG(10, ("parse_acl_blob returned %s\n",
312 /* Ensure the hash type is one we know. */
314 case XATTR_SD_HASH_TYPE_NONE:
315 /* No hash, just return blob sd. */
317 case XATTR_SD_HASH_TYPE_SHA256:
320 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
321 "mismatch (%u) for file %s\n",
322 (unsigned int)hash_type,
329 if (ignore_file_system_acl) {
333 status = hash_sd_sha256(pdesc_next, hash_tmp);
334 if (!NT_STATUS_IS_OK(status)) {
340 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
341 /* Hash matches, return blob sd. */
342 DEBUG(10, ("get_nt_acl_internal: blob hash "
343 "matches for file %s\n",
348 /* Hash doesn't match, return underlying sd. */
354 if (psd != pdesc_next) {
355 /* We're returning the blob, throw
356 * away the filesystem SD. */
357 TALLOC_FREE(pdesc_next);
359 SMB_STRUCT_STAT sbuf;
360 SMB_STRUCT_STAT *psbuf = &sbuf;
361 bool is_directory = false;
363 * We're returning the underlying ACL from the
364 * filesystem. If it's a directory, and has no
365 * inheritable ACE entries we have to fake them.
368 status = vfs_stat_fsp(fsp);
369 if (!NT_STATUS_IS_OK(status)) {
372 psbuf = &fsp->fsp_name->st;
374 int ret = vfs_stat_smb_fname(handle->conn,
378 return map_nt_error_from_unix(errno);
381 is_directory = S_ISDIR(psbuf->st_ex_mode);
383 if (ignore_file_system_acl) {
384 TALLOC_FREE(pdesc_next);
385 status = make_default_filesystem_acl(talloc_tos(),
389 if (!NT_STATUS_IS_OK(status)) {
394 !sd_has_inheritable_components(psd,
396 add_directory_inheritable_components(handle,
401 /* The underlying POSIX module always sets
402 the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
403 can't be inherited in this way under POSIX.
404 Remove it for Windows-style ACLs. */
405 psd->type &= ~SEC_DESC_DACL_PROTECTED;
409 if (!(security_info & SECINFO_OWNER)) {
410 psd->owner_sid = NULL;
412 if (!(security_info & SECINFO_GROUP)) {
413 psd->group_sid = NULL;
415 if (!(security_info & SECINFO_DACL)) {
416 psd->type &= ~SEC_DESC_DACL_PRESENT;
419 if (!(security_info & SECINFO_SACL)) {
420 psd->type &= ~SEC_DESC_SACL_PRESENT;
424 TALLOC_FREE(blob.data);
427 if (DEBUGLEVEL >= 10) {
428 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
430 NDR_PRINT_DEBUG(security_descriptor, psd);
436 /*********************************************************************
437 Create a default ACL by inheriting from the parent. If no inheritance
438 from the parent available, don't set anything. This will leave the actual
439 permissions the new file or directory already got from the filesystem
440 as the NT ACL when read.
441 *********************************************************************/
443 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
445 struct security_descriptor *parent_desc,
448 TALLOC_CTX *ctx = talloc_tos();
449 NTSTATUS status = NT_STATUS_OK;
450 struct security_descriptor *psd = NULL;
451 struct dom_sid *owner_sid = NULL;
452 struct dom_sid *group_sid = NULL;
453 uint32_t security_info_sent = (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL);
454 bool inherit_owner = lp_inherit_owner(SNUM(handle->conn));
455 bool inheritable_components = sd_has_inheritable_components(parent_desc,
459 if (!inheritable_components && !inherit_owner) {
460 /* Nothing to inherit and not setting owner. */
464 /* Create an inherited descriptor from the parent. */
466 if (DEBUGLEVEL >= 10) {
467 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
469 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
472 /* Inherit from parent descriptor if "inherit owner" set. */
474 owner_sid = parent_desc->owner_sid;
475 group_sid = parent_desc->group_sid;
478 if (owner_sid == NULL) {
479 owner_sid = &handle->conn->session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
481 if (group_sid == NULL) {
482 group_sid = &handle->conn->session_info->security_token->sids[PRIMARY_GROUP_SID_INDEX];
485 status = se_create_child_secdesc(ctx,
492 if (!NT_STATUS_IS_OK(status)) {
496 /* If inheritable_components == false,
497 se_create_child_secdesc()
498 creates a security desriptor with a NULL dacl
499 entry, but with SEC_DESC_DACL_PRESENT. We need
500 to remove that flag. */
502 if (!inheritable_components) {
503 security_info_sent &= ~SECINFO_DACL;
504 psd->type &= ~SEC_DESC_DACL_PRESENT;
507 if (DEBUGLEVEL >= 10) {
508 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
510 NDR_PRINT_DEBUG(security_descriptor, psd);
514 /* We need to be root to force this. */
517 status = SMB_VFS_FSET_NT_ACL(fsp,
526 static NTSTATUS get_parent_acl_common(vfs_handle_struct *handle,
528 struct security_descriptor **pp_parent_desc)
530 char *parent_name = NULL;
533 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
534 return NT_STATUS_NO_MEMORY;
537 status = get_nt_acl_internal(handle,
546 if (!NT_STATUS_IS_OK(status)) {
547 DEBUG(10,("get_parent_acl_common: get_nt_acl_internal "
548 "on directory %s for "
549 "path %s returned %s\n",
552 nt_errstr(status) ));
557 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
559 uint32_t access_mask,
560 struct security_descriptor **pp_parent_desc)
562 struct security_descriptor *parent_desc = NULL;
563 uint32_t access_granted = 0;
566 status = get_parent_acl_common(handle, path, &parent_desc);
567 if (!NT_STATUS_IS_OK(status)) {
570 if (pp_parent_desc) {
571 *pp_parent_desc = parent_desc;
573 status = smb1_file_se_access_check(handle->conn,
575 get_current_nttok(handle->conn),
578 if(!NT_STATUS_IS_OK(status)) {
579 DEBUG(10,("check_parent_acl_common: access check "
580 "on parent directory of "
581 "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,
627 if (NT_STATUS_IS_OK(status)) {
628 /* See if we can access it. */
629 status = smb1_file_se_access_check(handle->conn,
631 get_current_nttok(handle->conn),
634 if (!NT_STATUS_IS_OK(status)) {
635 DEBUG(10,("open_acl_xattr: %s open "
636 "for access 0x%x (0x%x) "
637 "refused with error %s\n",
639 (unsigned int)fsp->access_mask,
640 (unsigned int)access_granted,
641 nt_errstr(status) ));
644 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
645 file_existed = false;
647 * If O_CREAT is true then we're trying to create a file.
648 * Check the parent directory ACL will allow this.
650 if (flags & O_CREAT) {
651 struct security_descriptor *parent_desc = NULL;
652 struct security_descriptor **pp_psd = NULL;
654 status = check_parent_acl_common(handle, fname,
655 SEC_DIR_ADD_FILE, &parent_desc);
656 if (!NT_STATUS_IS_OK(status)) {
660 /* Cache the parent security descriptor for
663 pp_psd = VFS_ADD_FSP_EXTENSION(handle,
665 struct security_descriptor *,
668 status = NT_STATUS_NO_MEMORY;
672 *pp_psd = parent_desc;
673 status = NT_STATUS_OK;
677 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
680 nt_errstr(status) ));
682 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
687 errno = map_errno_from_nt_status(status);
691 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
695 SMB_STRUCT_STAT sbuf;
697 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
698 if (ret == -1 && errno == ENOENT) {
699 /* We're creating a new directory. */
700 status = check_parent_acl_common(handle, path,
701 SEC_DIR_ADD_SUBDIR, NULL);
702 if (!NT_STATUS_IS_OK(status)) {
703 errno = map_errno_from_nt_status(status);
708 return SMB_VFS_NEXT_MKDIR(handle, path, mode);
711 /*********************************************************************
712 Fetch a security descriptor given an fsp.
713 *********************************************************************/
715 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
716 uint32_t security_info, struct security_descriptor **ppdesc)
718 return get_nt_acl_internal(handle, fsp,
719 NULL, security_info, ppdesc);
722 /*********************************************************************
723 Fetch a security descriptor given a pathname.
724 *********************************************************************/
726 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
727 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
729 return get_nt_acl_internal(handle, NULL,
730 name, security_info, ppdesc);
733 /*********************************************************************
734 Store a security descriptor given an fsp.
735 *********************************************************************/
737 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
738 uint32_t security_info_sent, const struct security_descriptor *orig_psd)
742 struct security_descriptor *pdesc_next = NULL;
743 struct security_descriptor *psd = NULL;
744 uint8_t hash[XATTR_SD_HASH_SIZE];
746 if (DEBUGLEVEL >= 10) {
747 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
749 NDR_PRINT_DEBUG(security_descriptor,
750 CONST_DISCARD(struct security_descriptor *,orig_psd));
753 status = get_nt_acl_internal(handle, fsp,
755 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
758 if (!NT_STATUS_IS_OK(status)) {
762 psd->revision = orig_psd->revision;
763 /* All our SD's are self relative. */
764 psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE;
766 if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
767 psd->owner_sid = orig_psd->owner_sid;
769 if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
770 psd->group_sid = orig_psd->group_sid;
772 if (security_info_sent & SECINFO_DACL) {
773 psd->dacl = orig_psd->dacl;
774 psd->type |= SEC_DESC_DACL_PRESENT;
776 if (security_info_sent & SECINFO_SACL) {
777 psd->sacl = orig_psd->sacl;
778 psd->type |= SEC_DESC_SACL_PRESENT;
781 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
782 if (!NT_STATUS_IS_OK(status)) {
786 /* Get the full underlying sd, then hash. */
787 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
792 if (!NT_STATUS_IS_OK(status)) {
796 status = hash_sd_sha256(pdesc_next, hash);
797 if (!NT_STATUS_IS_OK(status)) {
801 if (DEBUGLEVEL >= 10) {
802 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
804 NDR_PRINT_DEBUG(security_descriptor,
805 CONST_DISCARD(struct security_descriptor *,psd));
807 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
808 if (!NT_STATUS_IS_OK(status)) {
809 DEBUG(10, ("fset_nt_acl_xattr: create_acl_blob failed\n"));
813 status = store_acl_blob_fsp(handle, fsp, &blob);
818 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
819 const char *fname, const char *mask, uint32 attr)
822 uint32_t access_granted = 0;
823 struct security_descriptor *sd = NULL;
825 status = get_nt_acl_internal(handle,
833 if (!NT_STATUS_IS_OK(status)) {
834 DEBUG(10,("opendir_acl_common: "
835 "get_nt_acl_internal for dir %s "
836 "failed with error %s\n",
838 nt_errstr(status) ));
839 errno = map_errno_from_nt_status(status);
843 /* See if we can access it. */
844 status = smb1_file_se_access_check(handle->conn,
846 get_current_nttok(handle->conn),
849 if (!NT_STATUS_IS_OK(status)) {
850 DEBUG(10,("opendir_acl_common: %s open "
851 "for access SEC_DIR_LIST "
852 "refused with error %s\n",
854 nt_errstr(status) ));
855 errno = map_errno_from_nt_status(status);
859 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
862 static int acl_common_remove_object(vfs_handle_struct *handle,
866 connection_struct *conn = handle->conn;
868 files_struct *fsp = NULL;
870 char *parent_dir = NULL;
871 const char *final_component = NULL;
872 struct smb_filename local_fname;
874 char *saved_dir = NULL;
876 saved_dir = vfs_GetWd(talloc_tos(),conn);
882 if (!parent_dirname(talloc_tos(), path,
883 &parent_dir, &final_component)) {
884 saved_errno = ENOMEM;
888 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
889 is_directory ? "directory" : "file",
890 parent_dir, final_component ));
892 /* cd into the parent dir to pin it. */
893 ret = vfs_ChDir(conn, parent_dir);
899 ZERO_STRUCT(local_fname);
900 local_fname.base_name = CONST_DISCARD(char *,final_component);
902 /* Must use lstat here. */
903 ret = SMB_VFS_LSTAT(conn, &local_fname);
909 /* Ensure we have this file open with DELETE access. */
910 id = vfs_file_id_from_sbuf(conn, &local_fname.st);
911 for (fsp = file_find_di_first(conn->sconn, id); fsp;
912 fsp = file_find_di_next(fsp)) {
913 if (fsp->access_mask & DELETE_ACCESS &&
914 fsp->delete_on_close) {
915 /* We did open this for delete,
916 * allow the delete as root.
923 DEBUG(10,("acl_common_remove_object: %s %s/%s "
924 "not an open file\n",
925 is_directory ? "directory" : "file",
926 parent_dir, final_component ));
927 saved_errno = EACCES;
933 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
935 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
945 TALLOC_FREE(parent_dir);
948 vfs_ChDir(conn, saved_dir);
956 static int rmdir_acl_common(struct vfs_handle_struct *handle,
961 /* Try the normal rmdir first. */
962 ret = SMB_VFS_NEXT_RMDIR(handle, path);
966 if (errno == EACCES || errno == EPERM) {
967 /* Failed due to access denied,
968 see if we need to root override. */
969 return acl_common_remove_object(handle,
974 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
980 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
981 struct smb_request *req,
982 uint16_t root_dir_fid,
983 struct smb_filename *smb_fname,
984 uint32_t access_mask,
985 uint32_t share_access,
986 uint32_t create_disposition,
987 uint32_t create_options,
988 uint32_t file_attributes,
989 uint32_t oplock_request,
990 uint64_t allocation_size,
991 uint32_t private_flags,
992 struct security_descriptor *sd,
993 struct ea_list *ea_list,
994 files_struct **result,
997 NTSTATUS status, status1;
998 files_struct *fsp = NULL;
1000 struct security_descriptor *parent_sd = NULL;
1001 struct security_descriptor **pp_parent_sd = NULL;
1003 status = SMB_VFS_NEXT_CREATE_FILE(handle,
1020 if (!NT_STATUS_IS_OK(status)) {
1024 if (info != FILE_WAS_CREATED) {
1025 /* File/directory was opened, not created. */
1032 /* Only handle success. */
1037 /* Security descriptor already set. */
1041 if (fsp->base_fsp) {
1046 /* See if we have a cached parent sd, if so, use it. */
1047 pp_parent_sd = (struct security_descriptor **)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1048 if (!pp_parent_sd) {
1049 /* Must be a directory, fetch again (sigh). */
1050 status = get_parent_acl_common(handle,
1051 fsp->fsp_name->base_name,
1053 if (!NT_STATUS_IS_OK(status)) {
1057 parent_sd = *pp_parent_sd;
1064 /* New directory - inherit from parent. */
1065 status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
1067 if (!NT_STATUS_IS_OK(status1)) {
1068 DEBUG(1,("create_file_acl_common: error setting "
1071 nt_errstr(status1) ));
1077 VFS_REMOVE_FSP_EXTENSION(handle, fsp);
1080 if (NT_STATUS_IS_OK(status) && pinfo) {
1087 smb_panic("create_file_acl_common: logic error.\n");
1092 static int unlink_acl_common(struct vfs_handle_struct *handle,
1093 const struct smb_filename *smb_fname)
1097 /* Try the normal unlink first. */
1098 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1102 if (errno == EACCES || errno == EPERM) {
1103 /* Failed due to access denied,
1104 see if we need to root override. */
1106 /* Don't do anything fancy for streams. */
1107 if (smb_fname->stream_name) {
1110 return acl_common_remove_object(handle,
1111 smb_fname->base_name,
1115 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1116 smb_fname->base_name,
1121 static int chmod_acl_module_common(struct vfs_handle_struct *handle,
1122 const char *path, mode_t mode)
1124 if (lp_posix_pathnames()) {
1125 /* Only allow this on POSIX pathnames. */
1126 return SMB_VFS_NEXT_CHMOD(handle, path, mode);
1131 static int fchmod_acl_module_common(struct vfs_handle_struct *handle,
1132 struct files_struct *fsp, mode_t mode)
1134 if (fsp->posix_open) {
1135 /* Only allow this on POSIX opens. */
1136 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1141 static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1142 const char *name, mode_t mode)
1144 if (lp_posix_pathnames()) {
1145 /* Only allow this on POSIX pathnames. */
1146 return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode);
1151 static int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1152 struct files_struct *fsp, mode_t mode)
1154 if (fsp->posix_open) {
1155 /* Only allow this on POSIX opens. */
1156 return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);