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)
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(sbuf.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)) {
418 if (!(security_info & SECINFO_SACL)) {
422 TALLOC_FREE(blob.data);
425 if (DEBUGLEVEL >= 10) {
426 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
428 NDR_PRINT_DEBUG(security_descriptor, psd);
434 /*********************************************************************
435 Create a default ACL by inheriting from the parent. If no inheritance
436 from the parent available, don't set anything. This will leave the actual
437 permissions the new file or directory already got from the filesystem
438 as the NT ACL when read.
439 *********************************************************************/
441 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
443 struct security_descriptor *parent_desc,
446 TALLOC_CTX *ctx = talloc_tos();
447 NTSTATUS status = NT_STATUS_OK;
448 struct security_descriptor *psd = NULL;
451 if (!sd_has_inheritable_components(parent_desc, is_directory)) {
455 /* Create an inherited descriptor from the parent. */
457 if (DEBUGLEVEL >= 10) {
458 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
460 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
463 status = se_create_child_secdesc(ctx,
467 &handle->conn->session_info->security_token->sids[PRIMARY_USER_SID_INDEX],
468 &handle->conn->session_info->security_token->sids[PRIMARY_GROUP_SID_INDEX],
470 if (!NT_STATUS_IS_OK(status)) {
474 if (DEBUGLEVEL >= 10) {
475 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
477 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
480 return SMB_VFS_FSET_NT_ACL(fsp,
487 static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
489 uint32_t access_mask,
490 struct security_descriptor **pp_parent_desc)
492 char *parent_name = NULL;
493 struct security_descriptor *parent_desc = NULL;
494 uint32_t access_granted = 0;
497 if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) {
498 return NT_STATUS_NO_MEMORY;
501 status = get_nt_acl_internal(handle,
509 if (!NT_STATUS_IS_OK(status)) {
510 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
511 "on directory %s for "
512 "path %s returned %s\n",
515 nt_errstr(status) ));
518 if (pp_parent_desc) {
519 *pp_parent_desc = parent_desc;
521 status = smb1_file_se_access_check(handle->conn,
523 get_current_nttok(handle->conn),
526 if(!NT_STATUS_IS_OK(status)) {
527 DEBUG(10,("check_parent_acl_common: access check "
528 "on directory %s for "
529 "path %s for mask 0x%x returned %s\n",
533 nt_errstr(status) ));
539 static void free_sd_common(void **ptr)
544 /*********************************************************************
545 Check ACL on open. For new files inherit from parent directory.
546 *********************************************************************/
548 static int open_acl_common(vfs_handle_struct *handle,
549 struct smb_filename *smb_fname,
554 uint32_t access_granted = 0;
555 struct security_descriptor *pdesc = NULL;
556 struct security_descriptor *parent_desc = NULL;
557 bool file_existed = true;
562 /* Stream open. Base filename open already did the ACL check. */
563 DEBUG(10,("open_acl_common: stream open on %s\n",
565 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
568 status = get_full_smb_filename(talloc_tos(), smb_fname,
570 if (!NT_STATUS_IS_OK(status)) {
574 status = get_nt_acl_internal(handle,
581 if (NT_STATUS_IS_OK(status)) {
582 /* See if we can access it. */
583 status = smb1_file_se_access_check(handle->conn,
585 get_current_nttok(handle->conn),
588 if (!NT_STATUS_IS_OK(status)) {
589 DEBUG(10,("open_acl_xattr: %s open "
590 "refused with error %s\n",
592 nt_errstr(status) ));
595 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
596 file_existed = false;
598 * If O_CREAT is true then we're trying to create a file.
599 * Check the parent directory ACL will allow this.
601 if (flags & O_CREAT) {
602 struct security_descriptor *psd = NULL;
604 status = check_parent_acl_common(handle, fname,
605 SEC_DIR_ADD_FILE, &parent_desc);
606 if (!NT_STATUS_IS_OK(status)) {
609 /* Cache the parent security descriptor for
610 * later use. We do have an fsp here, but to
611 * keep the code consistent with the directory
612 * case which doesn't, use the handle. */
614 /* Attach this to the conn, move from talloc_tos(). */
615 psd = (struct security_descriptor *)talloc_move(handle->conn,
619 status = NT_STATUS_NO_MEMORY;
622 status = NT_STATUS_NO_MEMORY;
623 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
624 struct security_descriptor *, goto err);
625 status = NT_STATUS_OK;
629 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
632 nt_errstr(status) ));
634 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
639 errno = map_errno_from_nt_status(status);
643 static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode)
647 SMB_STRUCT_STAT sbuf;
649 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
650 if (ret == -1 && errno == ENOENT) {
651 struct security_descriptor *parent_desc = NULL;
652 struct security_descriptor *psd = NULL;
654 /* We're creating a new directory. */
655 status = check_parent_acl_common(handle, path,
656 SEC_DIR_ADD_SUBDIR, &parent_desc);
657 if (!NT_STATUS_IS_OK(status)) {
658 errno = map_errno_from_nt_status(status);
662 /* Cache the parent security descriptor for
663 * later use. We don't have an fsp here so
666 /* Attach this to the conn, move from talloc_tos(). */
667 psd = (struct security_descriptor *)talloc_move(handle->conn,
673 SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common,
674 struct security_descriptor *, return -1);
677 return SMB_VFS_NEXT_MKDIR(handle, path, mode);
680 /*********************************************************************
681 Fetch a security descriptor given an fsp.
682 *********************************************************************/
684 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
685 uint32_t security_info, struct security_descriptor **ppdesc)
687 return get_nt_acl_internal(handle, fsp,
688 NULL, security_info, ppdesc);
691 /*********************************************************************
692 Fetch a security descriptor given a pathname.
693 *********************************************************************/
695 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
696 const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
698 return get_nt_acl_internal(handle, NULL,
699 name, security_info, ppdesc);
702 /*********************************************************************
703 Store a security descriptor given an fsp.
704 *********************************************************************/
706 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
707 uint32_t security_info_sent, const struct security_descriptor *orig_psd)
711 struct security_descriptor *pdesc_next = NULL;
712 struct security_descriptor *psd = NULL;
713 uint8_t hash[XATTR_SD_HASH_SIZE];
715 if (DEBUGLEVEL >= 10) {
716 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
718 NDR_PRINT_DEBUG(security_descriptor,
719 CONST_DISCARD(struct security_descriptor *,orig_psd));
722 status = get_nt_acl_internal(handle, fsp,
724 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
727 if (!NT_STATUS_IS_OK(status)) {
731 psd->revision = orig_psd->revision;
732 /* All our SD's are self relative. */
733 psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE;
735 if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
736 psd->owner_sid = orig_psd->owner_sid;
738 if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
739 psd->group_sid = orig_psd->group_sid;
741 if (security_info_sent & SECINFO_DACL) {
742 psd->dacl = orig_psd->dacl;
743 psd->type |= SEC_DESC_DACL_PRESENT;
745 if (security_info_sent & SECINFO_SACL) {
746 psd->sacl = orig_psd->sacl;
747 psd->type |= SEC_DESC_SACL_PRESENT;
750 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
751 if (!NT_STATUS_IS_OK(status)) {
755 /* Get the full underlying sd, then hash. */
756 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
761 if (!NT_STATUS_IS_OK(status)) {
765 status = hash_sd_sha256(pdesc_next, hash);
766 if (!NT_STATUS_IS_OK(status)) {
770 if (DEBUGLEVEL >= 10) {
771 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
773 NDR_PRINT_DEBUG(security_descriptor,
774 CONST_DISCARD(struct security_descriptor *,psd));
776 create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
777 store_acl_blob_fsp(handle, fsp, &blob);
782 static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
783 const char *fname, const char *mask, uint32 attr)
785 NTSTATUS status = check_parent_acl_common(handle, fname,
788 if (!NT_STATUS_IS_OK(status)) {
789 errno = map_errno_from_nt_status(status);
792 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
795 static int acl_common_remove_object(vfs_handle_struct *handle,
799 connection_struct *conn = handle->conn;
801 files_struct *fsp = NULL;
803 char *parent_dir = NULL;
804 const char *final_component = NULL;
805 struct smb_filename local_fname;
808 if (!parent_dirname(talloc_tos(), path,
809 &parent_dir, &final_component)) {
810 saved_errno = ENOMEM;
814 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
815 is_directory ? "directory" : "file",
816 parent_dir, final_component ));
818 /* cd into the parent dir to pin it. */
819 ret = SMB_VFS_CHDIR(conn, parent_dir);
825 ZERO_STRUCT(local_fname);
826 local_fname.base_name = CONST_DISCARD(char *,final_component);
828 /* Must use lstat here. */
829 ret = SMB_VFS_LSTAT(conn, &local_fname);
835 /* Ensure we have this file open with DELETE access. */
836 id = vfs_file_id_from_sbuf(conn, &local_fname.st);
837 for (fsp = file_find_di_first(conn->sconn, id); fsp;
838 file_find_di_next(fsp)) {
839 if (fsp->access_mask & DELETE_ACCESS &&
840 fsp->delete_on_close) {
841 /* We did open this for delete,
842 * allow the delete as root.
849 DEBUG(10,("acl_common_remove_object: %s %s/%s "
850 "not an open file\n",
851 is_directory ? "directory" : "file",
852 parent_dir, final_component ));
853 saved_errno = EACCES;
859 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
861 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
871 TALLOC_FREE(parent_dir);
873 vfs_ChDir(conn, conn->connectpath);
880 static int rmdir_acl_common(struct vfs_handle_struct *handle,
885 ret = SMB_VFS_NEXT_RMDIR(handle, path);
886 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
887 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
893 return acl_common_remove_object(handle,
898 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
899 struct smb_request *req,
900 uint16_t root_dir_fid,
901 struct smb_filename *smb_fname,
902 uint32_t access_mask,
903 uint32_t share_access,
904 uint32_t create_disposition,
905 uint32_t create_options,
906 uint32_t file_attributes,
907 uint32_t oplock_request,
908 uint64_t allocation_size,
909 uint32_t private_flags,
910 struct security_descriptor *sd,
911 struct ea_list *ea_list,
912 files_struct **result,
915 NTSTATUS status, status1;
916 files_struct *fsp = NULL;
918 struct security_descriptor *parent_sd = NULL;
920 status = SMB_VFS_NEXT_CREATE_FILE(handle,
937 if (!NT_STATUS_IS_OK(status)) {
941 if (info != FILE_WAS_CREATED) {
942 /* File/directory was opened, not created. */
949 /* Only handle success. */
954 /* Security descriptor already set. */
964 /* We must have a cached parent sd in this case.
965 * attached to the handle. */
967 SMB_VFS_HANDLE_GET_DATA(handle, parent_sd,
968 struct security_descriptor,
975 /* New directory - inherit from parent. */
976 status1 = inherit_new_acl(handle, fsp, parent_sd, fsp->is_directory);
978 if (!NT_STATUS_IS_OK(status1)) {
979 DEBUG(1,("create_file_acl_common: error setting "
982 nt_errstr(status1) ));
987 /* Ensure we never leave attached data around. */
988 SMB_VFS_HANDLE_FREE_DATA(handle);
990 if (NT_STATUS_IS_OK(status) && pinfo) {
997 smb_panic("create_file_acl_common: logic error.\n");
1002 static int unlink_acl_common(struct vfs_handle_struct *handle,
1003 const struct smb_filename *smb_fname)
1007 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1008 if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
1009 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1010 smb_fname->base_name,
1014 /* Don't do anything fancy for streams. */
1015 if (smb_fname->stream_name) {
1019 return acl_common_remove_object(handle,
1020 smb_fname->base_name,
1024 static int chmod_acl_module_common(struct vfs_handle_struct *handle,
1025 const char *path, mode_t mode)
1027 if (lp_posix_pathnames()) {
1028 /* Only allow this on POSIX pathnames. */
1029 return SMB_VFS_NEXT_CHMOD(handle, path, mode);
1034 static int fchmod_acl_module_common(struct vfs_handle_struct *handle,
1035 struct files_struct *fsp, mode_t mode)
1037 if (fsp->posix_open) {
1038 /* Only allow this on POSIX opens. */
1039 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1044 static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1045 const char *name, mode_t mode)
1047 if (lp_posix_pathnames()) {
1048 /* Only allow this on POSIX pathnames. */
1049 return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode);
1054 static int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1055 struct files_struct *fsp, mode_t mode)
1057 if (fsp->posix_open) {
1058 /* Only allow this on POSIX opens. */
1059 return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);