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 static NTSTATUS
create_acl_blob(const struct security_descriptor
*psd
,
25 uint8_t hash
[XATTR_SD_HASH_SIZE
]);
27 static NTSTATUS
get_acl_blob(TALLOC_CTX
*ctx
,
28 vfs_handle_struct
*handle
,
33 static NTSTATUS
store_acl_blob_fsp(vfs_handle_struct
*handle
,
37 #define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
38 GROUP_SECURITY_INFORMATION | \
39 DACL_SECURITY_INFORMATION | \
40 SACL_SECURITY_INFORMATION)
42 /*******************************************************************
43 Hash a security descriptor.
44 *******************************************************************/
46 static NTSTATUS
hash_sd_sha256(struct security_descriptor
*psd
,
53 memset(hash
, '\0', XATTR_SD_HASH_SIZE
);
54 status
= create_acl_blob(psd
, &blob
, XATTR_SD_HASH_TYPE_SHA256
, hash
);
55 if (!NT_STATUS_IS_OK(status
)) {
60 SHA256_Update(&tctx
, blob
.data
, blob
.length
);
61 SHA256_Final(hash
, &tctx
);
66 /*******************************************************************
67 Parse out a struct security_descriptor from a DATA_BLOB.
68 *******************************************************************/
70 static NTSTATUS
parse_acl_blob(const DATA_BLOB
*pblob
,
71 struct security_descriptor
**ppdesc
,
72 uint16_t *p_hash_type
,
73 uint8_t hash
[XATTR_SD_HASH_SIZE
])
75 TALLOC_CTX
*ctx
= talloc_tos();
76 struct xattr_NTACL xacl
;
77 enum ndr_err_code ndr_err
;
80 ndr_err
= ndr_pull_struct_blob(pblob
, ctx
, &xacl
,
81 (ndr_pull_flags_fn_t
)ndr_pull_xattr_NTACL
);
83 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
84 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
85 ndr_errstr(ndr_err
)));
86 return ndr_map_error2ntstatus(ndr_err
);;
89 switch (xacl
.version
) {
91 *ppdesc
= make_sec_desc(ctx
, SD_REVISION
,
92 xacl
.info
.sd_hs2
->sd
->type
| SEC_DESC_SELF_RELATIVE
,
93 xacl
.info
.sd_hs2
->sd
->owner_sid
,
94 xacl
.info
.sd_hs2
->sd
->group_sid
,
95 xacl
.info
.sd_hs2
->sd
->sacl
,
96 xacl
.info
.sd_hs2
->sd
->dacl
,
98 /* No hash - null out. */
99 *p_hash_type
= XATTR_SD_HASH_TYPE_NONE
;
100 memset(hash
, '\0', XATTR_SD_HASH_SIZE
);
103 *ppdesc
= make_sec_desc(ctx
, SD_REVISION
,
104 xacl
.info
.sd_hs3
->sd
->type
| SEC_DESC_SELF_RELATIVE
,
105 xacl
.info
.sd_hs3
->sd
->owner_sid
,
106 xacl
.info
.sd_hs3
->sd
->group_sid
,
107 xacl
.info
.sd_hs3
->sd
->sacl
,
108 xacl
.info
.sd_hs3
->sd
->dacl
,
110 *p_hash_type
= xacl
.info
.sd_hs3
->hash_type
;
111 /* Current version 3. */
112 memcpy(hash
, xacl
.info
.sd_hs3
->hash
, XATTR_SD_HASH_SIZE
);
115 return NT_STATUS_REVISION_MISMATCH
;
118 TALLOC_FREE(xacl
.info
.sd
);
120 return (*ppdesc
!= NULL
) ? NT_STATUS_OK
: NT_STATUS_NO_MEMORY
;
123 /*******************************************************************
124 Create a DATA_BLOB from a security descriptor.
125 *******************************************************************/
127 static NTSTATUS
create_acl_blob(const struct security_descriptor
*psd
,
130 uint8_t hash
[XATTR_SD_HASH_SIZE
])
132 struct xattr_NTACL xacl
;
133 struct security_descriptor_hash_v3 sd_hs3
;
134 enum ndr_err_code ndr_err
;
135 TALLOC_CTX
*ctx
= talloc_tos();
141 xacl
.info
.sd_hs3
= &sd_hs3
;
142 xacl
.info
.sd_hs3
->sd
= CONST_DISCARD(struct security_descriptor
*, psd
);
143 xacl
.info
.sd_hs3
->hash_type
= hash_type
;
144 memcpy(&xacl
.info
.sd_hs3
->hash
[0], hash
, XATTR_SD_HASH_SIZE
);
146 ndr_err
= ndr_push_struct_blob(
148 (ndr_push_flags_fn_t
)ndr_push_xattr_NTACL
);
150 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
151 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
152 ndr_errstr(ndr_err
)));
153 return ndr_map_error2ntstatus(ndr_err
);;
159 /*******************************************************************
160 Add in 3 inheritable components for a non-inheritable directory ACL.
161 CREATOR_OWNER/CREATOR_GROUP/WORLD.
162 *******************************************************************/
164 static void add_directory_inheritable_components(vfs_handle_struct
*handle
,
166 SMB_STRUCT_STAT
*psbuf
,
167 struct security_descriptor
*psd
)
169 struct connection_struct
*conn
= handle
->conn
;
170 int num_aces
= (psd
->dacl
? psd
->dacl
->num_aces
: 0);
171 struct smb_filename smb_fname
;
172 enum security_ace_type acltype
;
173 uint32_t access_mask
;
177 struct security_ace
*new_ace_list
= TALLOC_ZERO_ARRAY(talloc_tos(),
181 if (new_ace_list
== NULL
) {
185 /* Fake a quick smb_filename. */
186 ZERO_STRUCT(smb_fname
);
187 smb_fname
.st
= *psbuf
;
188 smb_fname
.base_name
= CONST_DISCARD(char *, name
);
190 dir_mode
= unix_mode(conn
,
191 FILE_ATTRIBUTE_DIRECTORY
, &smb_fname
, NULL
);
192 file_mode
= unix_mode(conn
,
193 FILE_ATTRIBUTE_ARCHIVE
, &smb_fname
, NULL
);
195 mode
= dir_mode
| file_mode
;
197 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
200 (unsigned int)mode
));
203 memcpy(new_ace_list
, psd
->dacl
->aces
,
204 num_aces
* sizeof(struct security_ace
));
206 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
209 init_sec_ace(&new_ace_list
[num_aces
],
210 &global_sid_Creator_Owner
,
213 SEC_ACE_FLAG_CONTAINER_INHERIT
|
214 SEC_ACE_FLAG_OBJECT_INHERIT
|
215 SEC_ACE_FLAG_INHERIT_ONLY
);
216 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
217 (mode
<< 3) & 0700, false);
218 init_sec_ace(&new_ace_list
[num_aces
+1],
219 &global_sid_Creator_Group
,
222 SEC_ACE_FLAG_CONTAINER_INHERIT
|
223 SEC_ACE_FLAG_OBJECT_INHERIT
|
224 SEC_ACE_FLAG_INHERIT_ONLY
);
225 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
226 (mode
<< 6) & 0700, false);
227 init_sec_ace(&new_ace_list
[num_aces
+2],
231 SEC_ACE_FLAG_CONTAINER_INHERIT
|
232 SEC_ACE_FLAG_OBJECT_INHERIT
|
233 SEC_ACE_FLAG_INHERIT_ONLY
);
234 psd
->dacl
->aces
= new_ace_list
;
235 psd
->dacl
->num_aces
+= 3;
238 /*******************************************************************
239 Pull a DATA_BLOB from an xattr given a pathname.
240 If the hash doesn't match, or doesn't exist - return the underlying
242 *******************************************************************/
244 static NTSTATUS
get_nt_acl_internal(vfs_handle_struct
*handle
,
247 uint32_t security_info
,
248 struct security_descriptor
**ppdesc
)
253 uint8_t hash
[XATTR_SD_HASH_SIZE
];
254 uint8_t hash_tmp
[XATTR_SD_HASH_SIZE
];
255 struct security_descriptor
*psd
= NULL
;
256 struct security_descriptor
*pdesc_next
= NULL
;
258 if (fsp
&& name
== NULL
) {
259 name
= fsp
->fsp_name
->base_name
;
262 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name
));
264 /* Get the full underlying sd for the hash
265 or to return as backup. */
267 status
= SMB_VFS_NEXT_FGET_NT_ACL(handle
,
272 status
= SMB_VFS_NEXT_GET_NT_ACL(handle
,
278 if (!NT_STATUS_IS_OK(status
)) {
279 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
286 status
= get_acl_blob(talloc_tos(), handle
, fsp
, name
, &blob
);
287 if (!NT_STATUS_IS_OK(status
)) {
288 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
294 status
= parse_acl_blob(&blob
, &psd
,
295 &hash_type
, &hash
[0]);
296 if (!NT_STATUS_IS_OK(status
)) {
297 DEBUG(10, ("parse_acl_blob returned %s\n",
303 /* Ensure the hash type is one we know. */
305 case XATTR_SD_HASH_TYPE_NONE
:
306 /* No hash, just return blob sd. */
308 case XATTR_SD_HASH_TYPE_SHA256
:
311 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
312 "mismatch (%u) for file %s\n",
313 (unsigned int)hash_type
,
321 status
= hash_sd_sha256(pdesc_next
, hash_tmp
);
322 if (!NT_STATUS_IS_OK(status
)) {
328 if (memcmp(&hash
[0], &hash_tmp
[0], XATTR_SD_HASH_SIZE
) == 0) {
329 /* Hash matches, return blob sd. */
333 /* Hash doesn't match, return underlying sd. */
339 if (psd
!= pdesc_next
) {
340 /* We're returning the blob, throw
341 * away the filesystem SD. */
342 TALLOC_FREE(pdesc_next
);
344 SMB_STRUCT_STAT sbuf
;
345 SMB_STRUCT_STAT
*psbuf
= &sbuf
;
346 bool is_directory
= false;
348 * We're returning the underlying ACL from the
349 * filesystem. If it's a directory, and has no
350 * inheritable ACE entries we have to fake them.
353 is_directory
= fsp
->is_directory
;
354 psbuf
= &fsp
->fsp_name
->st
;
356 if (vfs_stat_smb_fname(handle
->conn
,
359 is_directory
= S_ISDIR(sbuf
.st_ex_mode
);
363 !sd_has_inheritable_components(psd
,
365 add_directory_inheritable_components(handle
,
372 if (!(security_info
& OWNER_SECURITY_INFORMATION
)) {
373 psd
->owner_sid
= NULL
;
375 if (!(security_info
& GROUP_SECURITY_INFORMATION
)) {
376 psd
->group_sid
= NULL
;
378 if (!(security_info
& DACL_SECURITY_INFORMATION
)) {
381 if (!(security_info
& SACL_SECURITY_INFORMATION
)) {
385 TALLOC_FREE(blob
.data
);
390 /*********************************************************************
391 Create a default ACL by inheriting from the parent. If no inheritance
392 from the parent available, don't set anything. This will leave the actual
393 permissions the new file or directory already got from the filesystem
394 as the NT ACL when read.
395 *********************************************************************/
397 static NTSTATUS
inherit_new_acl(vfs_handle_struct
*handle
,
399 struct security_descriptor
*parent_desc
,
402 TALLOC_CTX
*ctx
= talloc_tos();
403 NTSTATUS status
= NT_STATUS_OK
;
404 struct security_descriptor
*psd
= NULL
;
407 if (!sd_has_inheritable_components(parent_desc
, is_directory
)) {
411 /* Create an inherited descriptor from the parent. */
413 if (DEBUGLEVEL
>= 10) {
414 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
416 NDR_PRINT_DEBUG(security_descriptor
, parent_desc
);
419 status
= se_create_child_secdesc(ctx
,
423 &handle
->conn
->server_info
->ptok
->user_sids
[PRIMARY_USER_SID_INDEX
],
424 &handle
->conn
->server_info
->ptok
->user_sids
[PRIMARY_GROUP_SID_INDEX
],
426 if (!NT_STATUS_IS_OK(status
)) {
430 if (DEBUGLEVEL
>= 10) {
431 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
433 NDR_PRINT_DEBUG(security_descriptor
, parent_desc
);
436 return SMB_VFS_FSET_NT_ACL(fsp
,
437 (OWNER_SECURITY_INFORMATION
|
438 GROUP_SECURITY_INFORMATION
|
439 DACL_SECURITY_INFORMATION
),
443 static NTSTATUS
check_parent_acl_common(vfs_handle_struct
*handle
,
445 uint32_t access_mask
,
446 struct security_descriptor
**pp_parent_desc
)
448 char *parent_name
= NULL
;
449 struct security_descriptor
*parent_desc
= NULL
;
450 uint32_t access_granted
= 0;
453 if (!parent_dirname(talloc_tos(), path
, &parent_name
, NULL
)) {
454 return NT_STATUS_NO_MEMORY
;
457 status
= get_nt_acl_internal(handle
,
460 (OWNER_SECURITY_INFORMATION
|
461 GROUP_SECURITY_INFORMATION
|
462 DACL_SECURITY_INFORMATION
),
465 if (!NT_STATUS_IS_OK(status
)) {
466 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
467 "on directory %s for "
468 "path %s returned %s\n",
471 nt_errstr(status
) ));
474 if (pp_parent_desc
) {
475 *pp_parent_desc
= parent_desc
;
477 status
= smb1_file_se_access_check(handle
->conn
,
479 get_current_nttok(handle
->conn
),
482 if(!NT_STATUS_IS_OK(status
)) {
483 DEBUG(10,("check_parent_acl_common: access check "
484 "on directory %s for "
485 "path %s for mask 0x%x returned %s\n",
489 nt_errstr(status
) ));
495 static void free_sd_common(void **ptr
)
500 /*********************************************************************
501 Check ACL on open. For new files inherit from parent directory.
502 *********************************************************************/
504 static int open_acl_common(vfs_handle_struct
*handle
,
505 struct smb_filename
*smb_fname
,
510 uint32_t access_granted
= 0;
511 struct security_descriptor
*pdesc
= NULL
;
512 struct security_descriptor
*parent_desc
= NULL
;
513 bool file_existed
= true;
518 /* Stream open. Base filename open already did the ACL check. */
519 DEBUG(10,("open_acl_common: stream open on %s\n",
521 return SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
524 status
= get_full_smb_filename(talloc_tos(), smb_fname
,
526 if (!NT_STATUS_IS_OK(status
)) {
530 status
= get_nt_acl_internal(handle
,
533 (OWNER_SECURITY_INFORMATION
|
534 GROUP_SECURITY_INFORMATION
|
535 DACL_SECURITY_INFORMATION
),
537 if (NT_STATUS_IS_OK(status
)) {
538 /* See if we can access it. */
539 status
= smb1_file_se_access_check(handle
->conn
,
541 get_current_nttok(handle
->conn
),
544 if (!NT_STATUS_IS_OK(status
)) {
545 DEBUG(10,("open_acl_xattr: %s open "
546 "refused with error %s\n",
548 nt_errstr(status
) ));
551 } else if (NT_STATUS_EQUAL(status
,NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
552 file_existed
= false;
554 * If O_CREAT is true then we're trying to create a file.
555 * Check the parent directory ACL will allow this.
557 if (flags
& O_CREAT
) {
558 struct security_descriptor
*psd
= NULL
;
560 status
= check_parent_acl_common(handle
, fname
,
561 SEC_DIR_ADD_FILE
, &parent_desc
);
562 if (!NT_STATUS_IS_OK(status
)) {
565 /* Cache the parent security descriptor for
566 * later use. We do have an fsp here, but to
567 * keep the code consistent with the directory
568 * case which doesn't, use the handle. */
570 /* Attach this to the conn, move from talloc_tos(). */
571 psd
= (struct security_descriptor
*)talloc_move(handle
->conn
,
575 status
= NT_STATUS_NO_MEMORY
;
578 status
= NT_STATUS_NO_MEMORY
;
579 SMB_VFS_HANDLE_SET_DATA(handle
, psd
, free_sd_common
,
580 struct security_descriptor
*, goto err
);
581 status
= NT_STATUS_OK
;
585 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
588 nt_errstr(status
) ));
590 fsp
->fh
->fd
= SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
595 errno
= map_errno_from_nt_status(status
);
599 static int mkdir_acl_common(vfs_handle_struct
*handle
, const char *path
, mode_t mode
)
603 SMB_STRUCT_STAT sbuf
;
605 ret
= vfs_stat_smb_fname(handle
->conn
, path
, &sbuf
);
606 if (ret
== -1 && errno
== ENOENT
) {
607 struct security_descriptor
*parent_desc
= NULL
;
608 struct security_descriptor
*psd
= NULL
;
610 /* We're creating a new directory. */
611 status
= check_parent_acl_common(handle
, path
,
612 SEC_DIR_ADD_SUBDIR
, &parent_desc
);
613 if (!NT_STATUS_IS_OK(status
)) {
614 errno
= map_errno_from_nt_status(status
);
618 /* Cache the parent security descriptor for
619 * later use. We don't have an fsp here so
622 /* Attach this to the conn, move from talloc_tos(). */
623 psd
= (struct security_descriptor
*)talloc_move(handle
->conn
,
629 SMB_VFS_HANDLE_SET_DATA(handle
, psd
, free_sd_common
,
630 struct security_descriptor
*, return -1);
633 return SMB_VFS_NEXT_MKDIR(handle
, path
, mode
);
636 /*********************************************************************
637 Fetch a security descriptor given an fsp.
638 *********************************************************************/
640 static NTSTATUS
fget_nt_acl_common(vfs_handle_struct
*handle
, files_struct
*fsp
,
641 uint32_t security_info
, struct security_descriptor
**ppdesc
)
643 return get_nt_acl_internal(handle
, fsp
,
644 NULL
, security_info
, ppdesc
);
647 /*********************************************************************
648 Fetch a security descriptor given a pathname.
649 *********************************************************************/
651 static NTSTATUS
get_nt_acl_common(vfs_handle_struct
*handle
,
652 const char *name
, uint32_t security_info
, struct security_descriptor
**ppdesc
)
654 return get_nt_acl_internal(handle
, NULL
,
655 name
, security_info
, ppdesc
);
658 /*********************************************************************
659 Store a security descriptor given an fsp.
660 *********************************************************************/
662 static NTSTATUS
fset_nt_acl_common(vfs_handle_struct
*handle
, files_struct
*fsp
,
663 uint32_t security_info_sent
, const struct security_descriptor
*psd
)
667 struct security_descriptor
*pdesc_next
= NULL
;
668 uint8_t hash
[XATTR_SD_HASH_SIZE
];
670 if (DEBUGLEVEL
>= 10) {
671 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
673 NDR_PRINT_DEBUG(security_descriptor
,
674 CONST_DISCARD(struct security_descriptor
*,psd
));
677 /* Ensure we have OWNER/GROUP/DACL set. */
679 if ((security_info_sent
& (OWNER_SECURITY_INFORMATION
|
680 GROUP_SECURITY_INFORMATION
|
681 DACL_SECURITY_INFORMATION
)) !=
682 (OWNER_SECURITY_INFORMATION
|
683 GROUP_SECURITY_INFORMATION
|
684 DACL_SECURITY_INFORMATION
)) {
685 /* No we don't - read from the existing SD. */
686 struct security_descriptor
*nc_psd
= NULL
;
688 status
= get_nt_acl_internal(handle
, fsp
,
690 (OWNER_SECURITY_INFORMATION
|
691 GROUP_SECURITY_INFORMATION
|
692 DACL_SECURITY_INFORMATION
),
695 if (!NT_STATUS_IS_OK(status
)) {
699 /* This is safe as nc_psd is discarded at fn exit. */
700 if (security_info_sent
& OWNER_SECURITY_INFORMATION
) {
701 nc_psd
->owner_sid
= psd
->owner_sid
;
703 security_info_sent
|= OWNER_SECURITY_INFORMATION
;
705 if (security_info_sent
& GROUP_SECURITY_INFORMATION
) {
706 nc_psd
->group_sid
= psd
->group_sid
;
708 security_info_sent
|= GROUP_SECURITY_INFORMATION
;
710 if (security_info_sent
& DACL_SECURITY_INFORMATION
) {
711 nc_psd
->dacl
= dup_sec_acl(talloc_tos(), psd
->dacl
);
712 if (nc_psd
->dacl
== NULL
) {
713 return NT_STATUS_NO_MEMORY
;
716 security_info_sent
|= DACL_SECURITY_INFORMATION
;
720 status
= SMB_VFS_NEXT_FSET_NT_ACL(handle
, fsp
, security_info_sent
, psd
);
721 if (!NT_STATUS_IS_OK(status
)) {
725 /* Get the full underlying sd, then hash. */
726 status
= SMB_VFS_NEXT_FGET_NT_ACL(handle
,
731 if (!NT_STATUS_IS_OK(status
)) {
735 status
= hash_sd_sha256(pdesc_next
, hash
);
736 if (!NT_STATUS_IS_OK(status
)) {
740 if (DEBUGLEVEL
>= 10) {
741 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
743 NDR_PRINT_DEBUG(security_descriptor
,
744 CONST_DISCARD(struct security_descriptor
*,psd
));
746 create_acl_blob(psd
, &blob
, XATTR_SD_HASH_TYPE_SHA256
, hash
);
747 store_acl_blob_fsp(handle
, fsp
, &blob
);
752 static SMB_STRUCT_DIR
*opendir_acl_common(vfs_handle_struct
*handle
,
753 const char *fname
, const char *mask
, uint32 attr
)
755 NTSTATUS status
= check_parent_acl_common(handle
, fname
,
758 if (!NT_STATUS_IS_OK(status
)) {
759 errno
= map_errno_from_nt_status(status
);
762 return SMB_VFS_NEXT_OPENDIR(handle
, fname
, mask
, attr
);
765 static int acl_common_remove_object(vfs_handle_struct
*handle
,
769 connection_struct
*conn
= handle
->conn
;
771 files_struct
*fsp
= NULL
;
773 char *parent_dir
= NULL
;
774 const char *final_component
= NULL
;
775 struct smb_filename local_fname
;
778 if (!parent_dirname(talloc_tos(), path
,
779 &parent_dir
, &final_component
)) {
780 saved_errno
= ENOMEM
;
784 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
785 is_directory
? "directory" : "file",
786 parent_dir
, final_component
));
788 /* cd into the parent dir to pin it. */
789 ret
= SMB_VFS_CHDIR(conn
, parent_dir
);
795 ZERO_STRUCT(local_fname
);
796 local_fname
.base_name
= CONST_DISCARD(char *,final_component
);
798 /* Must use lstat here. */
799 ret
= SMB_VFS_LSTAT(conn
, &local_fname
);
805 /* Ensure we have this file open with DELETE access. */
806 id
= vfs_file_id_from_sbuf(conn
, &local_fname
.st
);
807 for (fsp
= file_find_di_first(id
); fsp
; file_find_di_next(fsp
)) {
808 if (fsp
->access_mask
& DELETE_ACCESS
&&
809 fsp
->delete_on_close
) {
810 /* We did open this for delete,
811 * allow the delete as root.
818 DEBUG(10,("acl_common_remove_object: %s %s/%s "
819 "not an open file\n",
820 is_directory
? "directory" : "file",
821 parent_dir
, final_component
));
822 saved_errno
= EACCES
;
828 ret
= SMB_VFS_NEXT_RMDIR(handle
, final_component
);
830 ret
= SMB_VFS_NEXT_UNLINK(handle
, &local_fname
);
840 TALLOC_FREE(parent_dir
);
842 vfs_ChDir(conn
, conn
->connectpath
);
849 static int rmdir_acl_common(struct vfs_handle_struct
*handle
,
854 ret
= SMB_VFS_NEXT_RMDIR(handle
, path
);
855 if (!(ret
== -1 && (errno
== EACCES
|| errno
== EPERM
))) {
856 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
862 return acl_common_remove_object(handle
,
867 static NTSTATUS
create_file_acl_common(struct vfs_handle_struct
*handle
,
868 struct smb_request
*req
,
869 uint16_t root_dir_fid
,
870 struct smb_filename
*smb_fname
,
871 uint32_t access_mask
,
872 uint32_t share_access
,
873 uint32_t create_disposition
,
874 uint32_t create_options
,
875 uint32_t file_attributes
,
876 uint32_t oplock_request
,
877 uint64_t allocation_size
,
878 uint32_t private_flags
,
879 struct security_descriptor
*sd
,
880 struct ea_list
*ea_list
,
881 files_struct
**result
,
884 NTSTATUS status
, status1
;
885 files_struct
*fsp
= NULL
;
887 struct security_descriptor
*parent_sd
= NULL
;
889 status
= SMB_VFS_NEXT_CREATE_FILE(handle
,
906 if (info
!= FILE_WAS_CREATED
) {
907 /* File/directory was opened, not created. */
913 if (!NT_STATUS_IS_OK(status
) || fsp
== NULL
) {
914 /* Only handle success. */
919 /* Security descriptor already set. */
929 /* We must have a cached parent sd in this case.
930 * attached to the handle. */
932 SMB_VFS_HANDLE_GET_DATA(handle
, parent_sd
,
933 struct security_descriptor
,
940 /* New directory - inherit from parent. */
941 status1
= inherit_new_acl(handle
, fsp
, parent_sd
, fsp
->is_directory
);
943 if (!NT_STATUS_IS_OK(status1
)) {
944 DEBUG(1,("create_file_acl_common: error setting "
947 nt_errstr(status1
) ));
952 /* Ensure we never leave attached data around. */
953 SMB_VFS_HANDLE_FREE_DATA(handle
);
955 if (NT_STATUS_IS_OK(status
) && pinfo
) {
962 smb_panic("create_file_acl_common: logic error.\n");
967 static int unlink_acl_common(struct vfs_handle_struct
*handle
,
968 const struct smb_filename
*smb_fname
)
972 ret
= SMB_VFS_NEXT_UNLINK(handle
, smb_fname
);
973 if (!(ret
== -1 && (errno
== EACCES
|| errno
== EPERM
))) {
974 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
975 smb_fname
->base_name
,
979 /* Don't do anything fancy for streams. */
980 if (smb_fname
->stream_name
) {
984 return acl_common_remove_object(handle
,
985 smb_fname
->base_name
,