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
->type
| SEC_DESC_SELF_RELATIVE
,
99 xacl
.info
.sd
->owner_sid
,
100 xacl
.info
.sd
->group_sid
,
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_hs2
->sd
->type
| SEC_DESC_SELF_RELATIVE
,
111 xacl
.info
.sd_hs2
->sd
->owner_sid
,
112 xacl
.info
.sd_hs2
->sd
->group_sid
,
113 xacl
.info
.sd_hs2
->sd
->sacl
,
114 xacl
.info
.sd_hs2
->sd
->dacl
,
116 /* No hash - null out. */
117 *p_hash_type
= XATTR_SD_HASH_TYPE_NONE
;
118 memset(hash
, '\0', XATTR_SD_HASH_SIZE
);
121 *ppdesc
= make_sec_desc(ctx
, SD_REVISION
,
122 xacl
.info
.sd_hs3
->sd
->type
| SEC_DESC_SELF_RELATIVE
,
123 xacl
.info
.sd_hs3
->sd
->owner_sid
,
124 xacl
.info
.sd_hs3
->sd
->group_sid
,
125 xacl
.info
.sd_hs3
->sd
->sacl
,
126 xacl
.info
.sd_hs3
->sd
->dacl
,
128 *p_hash_type
= xacl
.info
.sd_hs3
->hash_type
;
129 /* Current version 3. */
130 memcpy(hash
, xacl
.info
.sd_hs3
->hash
, XATTR_SD_HASH_SIZE
);
133 return NT_STATUS_REVISION_MISMATCH
;
136 TALLOC_FREE(xacl
.info
.sd
);
138 return (*ppdesc
!= NULL
) ? NT_STATUS_OK
: NT_STATUS_NO_MEMORY
;
141 /*******************************************************************
142 Create a DATA_BLOB from a security descriptor.
143 *******************************************************************/
145 static NTSTATUS
create_acl_blob(const struct security_descriptor
*psd
,
148 uint8_t hash
[XATTR_SD_HASH_SIZE
])
150 struct xattr_NTACL xacl
;
151 struct security_descriptor_hash_v3 sd_hs3
;
152 enum ndr_err_code ndr_err
;
153 TALLOC_CTX
*ctx
= talloc_tos();
159 xacl
.info
.sd_hs3
= &sd_hs3
;
160 xacl
.info
.sd_hs3
->sd
= discard_const_p(struct security_descriptor
, psd
);
161 xacl
.info
.sd_hs3
->hash_type
= hash_type
;
162 memcpy(&xacl
.info
.sd_hs3
->hash
[0], hash
, XATTR_SD_HASH_SIZE
);
164 ndr_err
= ndr_push_struct_blob(
166 (ndr_push_flags_fn_t
)ndr_push_xattr_NTACL
);
168 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
169 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
170 ndr_errstr(ndr_err
)));
171 return ndr_map_error2ntstatus(ndr_err
);
177 /*******************************************************************
178 Add in 3 inheritable components for a non-inheritable directory ACL.
179 CREATOR_OWNER/CREATOR_GROUP/WORLD.
180 *******************************************************************/
182 static void add_directory_inheritable_components(vfs_handle_struct
*handle
,
184 SMB_STRUCT_STAT
*psbuf
,
185 struct security_descriptor
*psd
)
187 struct connection_struct
*conn
= handle
->conn
;
188 int num_aces
= (psd
->dacl
? psd
->dacl
->num_aces
: 0);
189 struct smb_filename smb_fname
;
190 enum security_ace_type acltype
;
191 uint32_t access_mask
;
195 struct security_ace
*new_ace_list
= talloc_zero_array(talloc_tos(),
199 if (new_ace_list
== NULL
) {
203 /* Fake a quick smb_filename. */
204 ZERO_STRUCT(smb_fname
);
205 smb_fname
.st
= *psbuf
;
206 smb_fname
.base_name
= discard_const_p(char, name
);
208 dir_mode
= unix_mode(conn
,
209 FILE_ATTRIBUTE_DIRECTORY
, &smb_fname
, NULL
);
210 file_mode
= unix_mode(conn
,
211 FILE_ATTRIBUTE_ARCHIVE
, &smb_fname
, NULL
);
213 mode
= dir_mode
| file_mode
;
215 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
218 (unsigned int)mode
));
221 memcpy(new_ace_list
, psd
->dacl
->aces
,
222 num_aces
* sizeof(struct security_ace
));
224 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
227 init_sec_ace(&new_ace_list
[num_aces
],
228 &global_sid_Creator_Owner
,
231 SEC_ACE_FLAG_CONTAINER_INHERIT
|
232 SEC_ACE_FLAG_OBJECT_INHERIT
|
233 SEC_ACE_FLAG_INHERIT_ONLY
);
234 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
235 (mode
<< 3) & 0700, false);
236 init_sec_ace(&new_ace_list
[num_aces
+1],
237 &global_sid_Creator_Group
,
240 SEC_ACE_FLAG_CONTAINER_INHERIT
|
241 SEC_ACE_FLAG_OBJECT_INHERIT
|
242 SEC_ACE_FLAG_INHERIT_ONLY
);
243 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
244 (mode
<< 6) & 0700, false);
245 init_sec_ace(&new_ace_list
[num_aces
+2],
249 SEC_ACE_FLAG_CONTAINER_INHERIT
|
250 SEC_ACE_FLAG_OBJECT_INHERIT
|
251 SEC_ACE_FLAG_INHERIT_ONLY
);
252 psd
->dacl
->aces
= new_ace_list
;
253 psd
->dacl
->num_aces
+= 3;
256 /*******************************************************************
257 Pull a DATA_BLOB from an xattr given a pathname.
258 If the hash doesn't match, or doesn't exist - return the underlying
260 *******************************************************************/
262 static NTSTATUS
get_nt_acl_internal(vfs_handle_struct
*handle
,
265 uint32_t security_info
,
266 struct security_descriptor
**ppdesc
)
268 DATA_BLOB blob
= data_blob_null
;
270 uint16_t hash_type
= XATTR_SD_HASH_TYPE_NONE
;
271 uint8_t hash
[XATTR_SD_HASH_SIZE
];
272 uint8_t hash_tmp
[XATTR_SD_HASH_SIZE
];
273 struct security_descriptor
*psd
= NULL
;
274 struct security_descriptor
*pdesc_next
= NULL
;
275 bool ignore_file_system_acl
= lp_parm_bool(SNUM(handle
->conn
),
277 "ignore system acls",
280 if (fsp
&& name
== NULL
) {
281 name
= fsp
->fsp_name
->base_name
;
284 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name
));
286 /* Get the full underlying sd for the hash
287 or to return as backup. */
289 status
= SMB_VFS_NEXT_FGET_NT_ACL(handle
,
294 status
= SMB_VFS_NEXT_GET_NT_ACL(handle
,
300 if (!NT_STATUS_IS_OK(status
)) {
301 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
308 status
= get_acl_blob(talloc_tos(), handle
, fsp
, name
, &blob
);
309 if (!NT_STATUS_IS_OK(status
)) {
310 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
316 status
= parse_acl_blob(&blob
, &psd
,
317 &hash_type
, &hash
[0]);
318 if (!NT_STATUS_IS_OK(status
)) {
319 DEBUG(10, ("parse_acl_blob returned %s\n",
325 /* Ensure the hash type is one we know. */
327 case XATTR_SD_HASH_TYPE_NONE
:
328 /* No hash, just return blob sd. */
330 case XATTR_SD_HASH_TYPE_SHA256
:
333 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
334 "mismatch (%u) for file %s\n",
335 (unsigned int)hash_type
,
342 if (ignore_file_system_acl
) {
346 status
= hash_sd_sha256(pdesc_next
, hash_tmp
);
347 if (!NT_STATUS_IS_OK(status
)) {
353 if (memcmp(&hash
[0], &hash_tmp
[0], XATTR_SD_HASH_SIZE
) == 0) {
354 /* Hash matches, return blob sd. */
355 DEBUG(10, ("get_nt_acl_internal: blob hash "
356 "matches for file %s\n",
361 /* Hash doesn't match, return underlying sd. */
367 if (psd
!= pdesc_next
) {
368 /* We're returning the blob, throw
369 * away the filesystem SD. */
370 TALLOC_FREE(pdesc_next
);
372 SMB_STRUCT_STAT sbuf
;
373 SMB_STRUCT_STAT
*psbuf
= &sbuf
;
374 bool is_directory
= false;
376 * We're returning the underlying ACL from the
377 * filesystem. If it's a directory, and has no
378 * inheritable ACE entries we have to fake them.
381 status
= vfs_stat_fsp(fsp
);
382 if (!NT_STATUS_IS_OK(status
)) {
385 psbuf
= &fsp
->fsp_name
->st
;
387 int ret
= vfs_stat_smb_fname(handle
->conn
,
391 return map_nt_error_from_unix(errno
);
394 is_directory
= S_ISDIR(sbuf
.st_ex_mode
);
396 if (ignore_file_system_acl
) {
397 TALLOC_FREE(pdesc_next
);
398 status
= make_default_filesystem_acl(talloc_tos(),
402 if (!NT_STATUS_IS_OK(status
)) {
407 !sd_has_inheritable_components(psd
,
409 add_directory_inheritable_components(handle
,
414 /* The underlying POSIX module always sets
415 the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
416 can't be inherited in this way under POSIX.
417 Remove it for Windows-style ACLs. */
418 psd
->type
&= ~SEC_DESC_DACL_PROTECTED
;
422 if (!(security_info
& SECINFO_OWNER
)) {
423 psd
->owner_sid
= NULL
;
425 if (!(security_info
& SECINFO_GROUP
)) {
426 psd
->group_sid
= NULL
;
428 if (!(security_info
& SECINFO_DACL
)) {
431 if (!(security_info
& SECINFO_SACL
)) {
435 TALLOC_FREE(blob
.data
);
438 if (DEBUGLEVEL
>= 10) {
439 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
441 NDR_PRINT_DEBUG(security_descriptor
, psd
);
447 /*********************************************************************
448 Create a default ACL by inheriting from the parent. If no inheritance
449 from the parent available, don't set anything. This will leave the actual
450 permissions the new file or directory already got from the filesystem
451 as the NT ACL when read.
452 *********************************************************************/
454 static NTSTATUS
inherit_new_acl(vfs_handle_struct
*handle
,
456 struct security_descriptor
*parent_desc
,
459 TALLOC_CTX
*ctx
= talloc_tos();
460 NTSTATUS status
= NT_STATUS_OK
;
461 struct security_descriptor
*psd
= NULL
;
462 struct dom_sid
*owner_sid
= NULL
;
463 struct dom_sid
*group_sid
= NULL
;
464 uint32_t security_info_sent
= (SECINFO_OWNER
| SECINFO_GROUP
| SECINFO_DACL
);
465 bool inherit_owner
= lp_inherit_owner(SNUM(handle
->conn
));
466 bool inheritable_components
= sd_has_inheritable_components(parent_desc
,
470 if (!inheritable_components
&& !inherit_owner
) {
471 /* Nothing to inherit and not setting owner. */
475 /* Create an inherited descriptor from the parent. */
477 if (DEBUGLEVEL
>= 10) {
478 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
480 NDR_PRINT_DEBUG(security_descriptor
, parent_desc
);
483 /* Inherit from parent descriptor if "inherit owner" set. */
485 owner_sid
= parent_desc
->owner_sid
;
486 group_sid
= parent_desc
->group_sid
;
489 if (owner_sid
== NULL
) {
490 owner_sid
= &handle
->conn
->session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
492 if (group_sid
== NULL
) {
493 group_sid
= &handle
->conn
->session_info
->security_token
->sids
[PRIMARY_GROUP_SID_INDEX
];
496 status
= se_create_child_secdesc(ctx
,
503 if (!NT_STATUS_IS_OK(status
)) {
507 /* If inheritable_components == false,
508 se_create_child_secdesc()
509 creates a security desriptor with a NULL dacl
510 entry, but with SEC_DESC_DACL_PRESENT. We need
511 to remove that flag. */
513 if (!inheritable_components
) {
514 security_info_sent
&= ~SECINFO_DACL
;
515 psd
->type
&= ~SEC_DESC_DACL_PRESENT
;
518 if (DEBUGLEVEL
>= 10) {
519 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
521 NDR_PRINT_DEBUG(security_descriptor
, psd
);
525 /* We need to be root to force this. */
528 status
= SMB_VFS_FSET_NT_ACL(fsp
,
537 static NTSTATUS
get_parent_acl_common(vfs_handle_struct
*handle
,
539 struct security_descriptor
**pp_parent_desc
)
541 char *parent_name
= NULL
;
544 if (!parent_dirname(talloc_tos(), path
, &parent_name
, NULL
)) {
545 return NT_STATUS_NO_MEMORY
;
548 status
= get_nt_acl_internal(handle
,
556 if (!NT_STATUS_IS_OK(status
)) {
557 DEBUG(10,("get_parent_acl_common: get_nt_acl_internal "
558 "on directory %s for "
559 "path %s returned %s\n",
562 nt_errstr(status
) ));
567 /*********************************************************************
568 Fetch a security descriptor given an fsp.
569 *********************************************************************/
571 static NTSTATUS
fget_nt_acl_common(vfs_handle_struct
*handle
, files_struct
*fsp
,
572 uint32_t security_info
, struct security_descriptor
**ppdesc
)
574 return get_nt_acl_internal(handle
, fsp
,
575 NULL
, security_info
, ppdesc
);
578 /*********************************************************************
579 Fetch a security descriptor given a pathname.
580 *********************************************************************/
582 static NTSTATUS
get_nt_acl_common(vfs_handle_struct
*handle
,
583 const char *name
, uint32_t security_info
, struct security_descriptor
**ppdesc
)
585 return get_nt_acl_internal(handle
, NULL
,
586 name
, security_info
, ppdesc
);
589 /*********************************************************************
590 Store a security descriptor given an fsp.
591 *********************************************************************/
593 static NTSTATUS
fset_nt_acl_common(vfs_handle_struct
*handle
, files_struct
*fsp
,
594 uint32_t security_info_sent
, const struct security_descriptor
*orig_psd
)
598 struct security_descriptor
*pdesc_next
= NULL
;
599 struct security_descriptor
*psd
= NULL
;
600 uint8_t hash
[XATTR_SD_HASH_SIZE
];
602 if (DEBUGLEVEL
>= 10) {
603 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
605 NDR_PRINT_DEBUG(security_descriptor
,
606 discard_const_p(struct security_descriptor
, orig_psd
));
609 status
= get_nt_acl_internal(handle
, fsp
,
611 SECINFO_OWNER
|SECINFO_GROUP
|SECINFO_DACL
|SECINFO_SACL
,
614 if (!NT_STATUS_IS_OK(status
)) {
618 psd
->revision
= orig_psd
->revision
;
619 /* All our SD's are self relative. */
620 psd
->type
= orig_psd
->type
| SEC_DESC_SELF_RELATIVE
;
622 if ((security_info_sent
& SECINFO_OWNER
) && (orig_psd
->owner_sid
!= NULL
)) {
623 psd
->owner_sid
= orig_psd
->owner_sid
;
625 if ((security_info_sent
& SECINFO_GROUP
) && (orig_psd
->group_sid
!= NULL
)) {
626 psd
->group_sid
= orig_psd
->group_sid
;
628 if (security_info_sent
& SECINFO_DACL
) {
629 psd
->dacl
= orig_psd
->dacl
;
630 psd
->type
|= SEC_DESC_DACL_PRESENT
;
632 if (security_info_sent
& SECINFO_SACL
) {
633 psd
->sacl
= orig_psd
->sacl
;
634 psd
->type
|= SEC_DESC_SACL_PRESENT
;
637 status
= SMB_VFS_NEXT_FSET_NT_ACL(handle
, fsp
, security_info_sent
, psd
);
638 if (!NT_STATUS_IS_OK(status
)) {
642 /* Get the full underlying sd, then hash. */
643 status
= SMB_VFS_NEXT_FGET_NT_ACL(handle
,
648 if (!NT_STATUS_IS_OK(status
)) {
652 status
= hash_sd_sha256(pdesc_next
, hash
);
653 if (!NT_STATUS_IS_OK(status
)) {
657 if (DEBUGLEVEL
>= 10) {
658 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
660 NDR_PRINT_DEBUG(security_descriptor
,
661 discard_const_p(struct security_descriptor
, psd
));
663 create_acl_blob(psd
, &blob
, XATTR_SD_HASH_TYPE_SHA256
, hash
);
664 store_acl_blob_fsp(handle
, fsp
, &blob
);
669 static int acl_common_remove_object(vfs_handle_struct
*handle
,
673 connection_struct
*conn
= handle
->conn
;
675 files_struct
*fsp
= NULL
;
677 char *parent_dir
= NULL
;
678 const char *final_component
= NULL
;
679 struct smb_filename local_fname
;
681 char *saved_dir
= NULL
;
683 saved_dir
= vfs_GetWd(talloc_tos(),conn
);
689 if (!parent_dirname(talloc_tos(), path
,
690 &parent_dir
, &final_component
)) {
691 saved_errno
= ENOMEM
;
695 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
696 is_directory
? "directory" : "file",
697 parent_dir
, final_component
));
699 /* cd into the parent dir to pin it. */
700 ret
= vfs_ChDir(conn
, parent_dir
);
706 ZERO_STRUCT(local_fname
);
707 local_fname
.base_name
= discard_const_p(char, final_component
);
709 /* Must use lstat here. */
710 ret
= SMB_VFS_LSTAT(conn
, &local_fname
);
716 /* Ensure we have this file open with DELETE access. */
717 id
= vfs_file_id_from_sbuf(conn
, &local_fname
.st
);
718 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
719 fsp
= file_find_di_next(fsp
)) {
720 if (fsp
->access_mask
& DELETE_ACCESS
&&
721 fsp
->delete_on_close
) {
722 /* We did open this for delete,
723 * allow the delete as root.
730 DEBUG(10,("acl_common_remove_object: %s %s/%s "
731 "not an open file\n",
732 is_directory
? "directory" : "file",
733 parent_dir
, final_component
));
734 saved_errno
= EACCES
;
740 ret
= SMB_VFS_NEXT_RMDIR(handle
, final_component
);
742 ret
= SMB_VFS_NEXT_UNLINK(handle
, &local_fname
);
752 TALLOC_FREE(parent_dir
);
755 vfs_ChDir(conn
, saved_dir
);
763 static int rmdir_acl_common(struct vfs_handle_struct
*handle
,
768 ret
= SMB_VFS_NEXT_RMDIR(handle
, path
);
769 if (!(ret
== -1 && (errno
== EACCES
|| errno
== EPERM
))) {
770 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
776 return acl_common_remove_object(handle
,
781 static NTSTATUS
create_file_acl_common(struct vfs_handle_struct
*handle
,
782 struct smb_request
*req
,
783 uint16_t root_dir_fid
,
784 struct smb_filename
*smb_fname
,
785 uint32_t access_mask
,
786 uint32_t share_access
,
787 uint32_t create_disposition
,
788 uint32_t create_options
,
789 uint32_t file_attributes
,
790 uint32_t oplock_request
,
791 uint64_t allocation_size
,
792 uint32_t private_flags
,
793 struct security_descriptor
*sd
,
794 struct ea_list
*ea_list
,
795 files_struct
**result
,
798 NTSTATUS status
, status1
;
799 files_struct
*fsp
= NULL
;
801 struct security_descriptor
*parent_sd
= NULL
;
803 status
= SMB_VFS_NEXT_CREATE_FILE(handle
,
820 if (!NT_STATUS_IS_OK(status
)) {
824 if (info
!= FILE_WAS_CREATED
) {
825 /* File/directory was opened, not created. */
832 /* Only handle success. */
837 /* Security descriptor already set. */
846 status
= get_parent_acl_common(handle
,
847 fsp
->fsp_name
->base_name
,
849 if (!NT_STATUS_IS_OK(status
)) {
857 /* New directory - inherit from parent. */
858 status1
= inherit_new_acl(handle
, fsp
, parent_sd
, fsp
->is_directory
);
860 if (!NT_STATUS_IS_OK(status1
)) {
861 DEBUG(1,("create_file_acl_common: error setting "
864 nt_errstr(status1
) ));
869 TALLOC_FREE(parent_sd
);
871 if (NT_STATUS_IS_OK(status
) && pinfo
) {
878 smb_panic("create_file_acl_common: logic error.\n");
883 static int unlink_acl_common(struct vfs_handle_struct
*handle
,
884 const struct smb_filename
*smb_fname
)
888 ret
= SMB_VFS_NEXT_UNLINK(handle
, smb_fname
);
889 if (!(ret
== -1 && (errno
== EACCES
|| errno
== EPERM
))) {
890 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
891 smb_fname
->base_name
,
895 /* Don't do anything fancy for streams. */
896 if (smb_fname
->stream_name
) {
900 return acl_common_remove_object(handle
,
901 smb_fname
->base_name
,
905 static int chmod_acl_module_common(struct vfs_handle_struct
*handle
,
906 const char *path
, mode_t mode
)
908 if (lp_posix_pathnames()) {
909 /* Only allow this on POSIX pathnames. */
910 return SMB_VFS_NEXT_CHMOD(handle
, path
, mode
);
915 static int fchmod_acl_module_common(struct vfs_handle_struct
*handle
,
916 struct files_struct
*fsp
, mode_t mode
)
918 if (fsp
->posix_open
) {
919 /* Only allow this on POSIX opens. */
920 return SMB_VFS_NEXT_FCHMOD(handle
, fsp
, mode
);
925 static int chmod_acl_acl_module_common(struct vfs_handle_struct
*handle
,
926 const char *name
, mode_t mode
)
928 if (lp_posix_pathnames()) {
929 /* Only allow this on POSIX pathnames. */
930 return SMB_VFS_NEXT_CHMOD_ACL(handle
, name
, mode
);
935 static int fchmod_acl_acl_module_common(struct vfs_handle_struct
*handle
,
936 struct files_struct
*fsp
, mode_t mode
)
938 if (fsp
->posix_open
) {
939 /* Only allow this on POSIX opens. */
940 return SMB_VFS_NEXT_FCHMOD_ACL(handle
, fsp
, mode
);