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 "../libcli/security/security.h"
23 #include "../librpc/gen_ndr/ndr_security.h"
25 static NTSTATUS
create_acl_blob(const struct security_descriptor
*psd
,
28 uint8_t hash
[XATTR_SD_HASH_SIZE
]);
30 static NTSTATUS
get_acl_blob(TALLOC_CTX
*ctx
,
31 vfs_handle_struct
*handle
,
36 static NTSTATUS
store_acl_blob_fsp(vfs_handle_struct
*handle
,
40 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
45 /*******************************************************************
46 Hash a security descriptor.
47 *******************************************************************/
49 static NTSTATUS
hash_sd_sha256(struct security_descriptor
*psd
,
56 memset(hash
, '\0', XATTR_SD_HASH_SIZE
);
57 status
= create_acl_blob(psd
, &blob
, XATTR_SD_HASH_TYPE_SHA256
, hash
);
58 if (!NT_STATUS_IS_OK(status
)) {
63 SHA256_Update(&tctx
, blob
.data
, blob
.length
);
64 SHA256_Final(hash
, &tctx
);
69 /*******************************************************************
70 Parse out a struct security_descriptor from a DATA_BLOB.
71 *******************************************************************/
73 static NTSTATUS
parse_acl_blob(const DATA_BLOB
*pblob
,
74 struct security_descriptor
**ppdesc
,
75 uint16_t *p_hash_type
,
76 uint8_t hash
[XATTR_SD_HASH_SIZE
])
78 TALLOC_CTX
*ctx
= talloc_tos();
79 struct xattr_NTACL xacl
;
80 enum ndr_err_code ndr_err
;
83 ndr_err
= ndr_pull_struct_blob(pblob
, ctx
, &xacl
,
84 (ndr_pull_flags_fn_t
)ndr_pull_xattr_NTACL
);
86 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
87 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
88 ndr_errstr(ndr_err
)));
89 return ndr_map_error2ntstatus(ndr_err
);;
92 switch (xacl
.version
) {
94 *ppdesc
= make_sec_desc(ctx
, SD_REVISION
,
95 xacl
.info
.sd_hs2
->sd
->type
| SEC_DESC_SELF_RELATIVE
,
96 xacl
.info
.sd_hs2
->sd
->owner_sid
,
97 xacl
.info
.sd_hs2
->sd
->group_sid
,
98 xacl
.info
.sd_hs2
->sd
->sacl
,
99 xacl
.info
.sd_hs2
->sd
->dacl
,
101 /* No hash - null out. */
102 *p_hash_type
= XATTR_SD_HASH_TYPE_NONE
;
103 memset(hash
, '\0', XATTR_SD_HASH_SIZE
);
106 *ppdesc
= make_sec_desc(ctx
, SD_REVISION
,
107 xacl
.info
.sd_hs3
->sd
->type
| SEC_DESC_SELF_RELATIVE
,
108 xacl
.info
.sd_hs3
->sd
->owner_sid
,
109 xacl
.info
.sd_hs3
->sd
->group_sid
,
110 xacl
.info
.sd_hs3
->sd
->sacl
,
111 xacl
.info
.sd_hs3
->sd
->dacl
,
113 *p_hash_type
= xacl
.info
.sd_hs3
->hash_type
;
114 /* Current version 3. */
115 memcpy(hash
, xacl
.info
.sd_hs3
->hash
, XATTR_SD_HASH_SIZE
);
118 return NT_STATUS_REVISION_MISMATCH
;
121 TALLOC_FREE(xacl
.info
.sd
);
123 return (*ppdesc
!= NULL
) ? NT_STATUS_OK
: NT_STATUS_NO_MEMORY
;
126 /*******************************************************************
127 Create a DATA_BLOB from a security descriptor.
128 *******************************************************************/
130 static NTSTATUS
create_acl_blob(const struct security_descriptor
*psd
,
133 uint8_t hash
[XATTR_SD_HASH_SIZE
])
135 struct xattr_NTACL xacl
;
136 struct security_descriptor_hash_v3 sd_hs3
;
137 enum ndr_err_code ndr_err
;
138 TALLOC_CTX
*ctx
= talloc_tos();
144 xacl
.info
.sd_hs3
= &sd_hs3
;
145 xacl
.info
.sd_hs3
->sd
= CONST_DISCARD(struct security_descriptor
*, psd
);
146 xacl
.info
.sd_hs3
->hash_type
= hash_type
;
147 memcpy(&xacl
.info
.sd_hs3
->hash
[0], hash
, XATTR_SD_HASH_SIZE
);
149 ndr_err
= ndr_push_struct_blob(
151 (ndr_push_flags_fn_t
)ndr_push_xattr_NTACL
);
153 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
154 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
155 ndr_errstr(ndr_err
)));
156 return ndr_map_error2ntstatus(ndr_err
);;
162 /*******************************************************************
163 Add in 3 inheritable components for a non-inheritable directory ACL.
164 CREATOR_OWNER/CREATOR_GROUP/WORLD.
165 *******************************************************************/
167 static void add_directory_inheritable_components(vfs_handle_struct
*handle
,
169 SMB_STRUCT_STAT
*psbuf
,
170 struct security_descriptor
*psd
)
172 struct connection_struct
*conn
= handle
->conn
;
173 int num_aces
= (psd
->dacl
? psd
->dacl
->num_aces
: 0);
174 struct smb_filename smb_fname
;
175 enum security_ace_type acltype
;
176 uint32_t access_mask
;
180 struct security_ace
*new_ace_list
= TALLOC_ZERO_ARRAY(talloc_tos(),
184 if (new_ace_list
== NULL
) {
188 /* Fake a quick smb_filename. */
189 ZERO_STRUCT(smb_fname
);
190 smb_fname
.st
= *psbuf
;
191 smb_fname
.base_name
= CONST_DISCARD(char *, name
);
193 dir_mode
= unix_mode(conn
,
194 FILE_ATTRIBUTE_DIRECTORY
, &smb_fname
, NULL
);
195 file_mode
= unix_mode(conn
,
196 FILE_ATTRIBUTE_ARCHIVE
, &smb_fname
, NULL
);
198 mode
= dir_mode
| file_mode
;
200 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
203 (unsigned int)mode
));
206 memcpy(new_ace_list
, psd
->dacl
->aces
,
207 num_aces
* sizeof(struct security_ace
));
209 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
212 init_sec_ace(&new_ace_list
[num_aces
],
213 &global_sid_Creator_Owner
,
216 SEC_ACE_FLAG_CONTAINER_INHERIT
|
217 SEC_ACE_FLAG_OBJECT_INHERIT
|
218 SEC_ACE_FLAG_INHERIT_ONLY
);
219 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
220 (mode
<< 3) & 0700, false);
221 init_sec_ace(&new_ace_list
[num_aces
+1],
222 &global_sid_Creator_Group
,
225 SEC_ACE_FLAG_CONTAINER_INHERIT
|
226 SEC_ACE_FLAG_OBJECT_INHERIT
|
227 SEC_ACE_FLAG_INHERIT_ONLY
);
228 access_mask
= map_canon_ace_perms(SNUM(conn
), &acltype
,
229 (mode
<< 6) & 0700, false);
230 init_sec_ace(&new_ace_list
[num_aces
+2],
234 SEC_ACE_FLAG_CONTAINER_INHERIT
|
235 SEC_ACE_FLAG_OBJECT_INHERIT
|
236 SEC_ACE_FLAG_INHERIT_ONLY
);
237 psd
->dacl
->aces
= new_ace_list
;
238 psd
->dacl
->num_aces
+= 3;
241 /*******************************************************************
242 Pull a DATA_BLOB from an xattr given a pathname.
243 If the hash doesn't match, or doesn't exist - return the underlying
245 *******************************************************************/
247 static NTSTATUS
get_nt_acl_internal(vfs_handle_struct
*handle
,
250 uint32_t security_info
,
251 struct security_descriptor
**ppdesc
)
255 uint16_t hash_type
= XATTR_SD_HASH_TYPE_NONE
;
256 uint8_t hash
[XATTR_SD_HASH_SIZE
];
257 uint8_t hash_tmp
[XATTR_SD_HASH_SIZE
];
258 struct security_descriptor
*psd
= NULL
;
259 struct security_descriptor
*pdesc_next
= NULL
;
260 bool ignore_file_system_acl
= lp_parm_bool(SNUM(handle
->conn
),
262 "ignore system acls",
265 if (fsp
&& name
== NULL
) {
266 name
= fsp
->fsp_name
->base_name
;
269 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name
));
271 /* Get the full underlying sd for the hash
272 or to return as backup. */
274 status
= SMB_VFS_NEXT_FGET_NT_ACL(handle
,
279 status
= SMB_VFS_NEXT_GET_NT_ACL(handle
,
285 if (!NT_STATUS_IS_OK(status
)) {
286 DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
293 status
= get_acl_blob(talloc_tos(), handle
, fsp
, name
, &blob
);
294 if (!NT_STATUS_IS_OK(status
)) {
295 DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
301 status
= parse_acl_blob(&blob
, &psd
,
302 &hash_type
, &hash
[0]);
303 if (!NT_STATUS_IS_OK(status
)) {
304 DEBUG(10, ("parse_acl_blob returned %s\n",
310 /* Ensure the hash type is one we know. */
312 case XATTR_SD_HASH_TYPE_NONE
:
313 /* No hash, just return blob sd. */
315 case XATTR_SD_HASH_TYPE_SHA256
:
318 DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
319 "mismatch (%u) for file %s\n",
320 (unsigned int)hash_type
,
327 if (ignore_file_system_acl
) {
331 status
= hash_sd_sha256(pdesc_next
, hash_tmp
);
332 if (!NT_STATUS_IS_OK(status
)) {
338 if (memcmp(&hash
[0], &hash_tmp
[0], XATTR_SD_HASH_SIZE
) == 0) {
339 /* Hash matches, return blob sd. */
340 DEBUG(10, ("get_nt_acl_internal: blob hash "
341 "matches for file %s\n",
346 /* Hash doesn't match, return underlying sd. */
352 if (psd
!= pdesc_next
) {
353 /* We're returning the blob, throw
354 * away the filesystem SD. */
355 TALLOC_FREE(pdesc_next
);
357 SMB_STRUCT_STAT sbuf
;
358 SMB_STRUCT_STAT
*psbuf
= &sbuf
;
359 bool is_directory
= false;
361 * We're returning the underlying ACL from the
362 * filesystem. If it's a directory, and has no
363 * inheritable ACE entries we have to fake them.
366 status
= vfs_stat_fsp(fsp
);
367 if (!NT_STATUS_IS_OK(status
)) {
370 psbuf
= &fsp
->fsp_name
->st
;
372 int ret
= vfs_stat_smb_fname(handle
->conn
,
376 return map_nt_error_from_unix(errno
);
379 is_directory
= S_ISDIR(sbuf
.st_ex_mode
);
381 if (ignore_file_system_acl
) {
382 TALLOC_FREE(pdesc_next
);
383 status
= make_default_filesystem_acl(talloc_tos(),
387 if (!NT_STATUS_IS_OK(status
)) {
392 !sd_has_inheritable_components(psd
,
394 add_directory_inheritable_components(handle
,
399 /* The underlying POSIX module always sets
400 the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
401 can't be inherited in this way under POSIX.
402 Remove it for Windows-style ACLs. */
403 psd
->type
&= ~SEC_DESC_DACL_PROTECTED
;
407 if (!(security_info
& SECINFO_OWNER
)) {
408 psd
->owner_sid
= NULL
;
410 if (!(security_info
& SECINFO_GROUP
)) {
411 psd
->group_sid
= NULL
;
413 if (!(security_info
& SECINFO_DACL
)) {
416 if (!(security_info
& SECINFO_SACL
)) {
420 TALLOC_FREE(blob
.data
);
423 if (DEBUGLEVEL
>= 10) {
424 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
426 NDR_PRINT_DEBUG(security_descriptor
, psd
);
432 /*********************************************************************
433 Create a default ACL by inheriting from the parent. If no inheritance
434 from the parent available, don't set anything. This will leave the actual
435 permissions the new file or directory already got from the filesystem
436 as the NT ACL when read.
437 *********************************************************************/
439 static NTSTATUS
inherit_new_acl(vfs_handle_struct
*handle
,
441 struct security_descriptor
*parent_desc
,
444 TALLOC_CTX
*ctx
= talloc_tos();
445 NTSTATUS status
= NT_STATUS_OK
;
446 struct security_descriptor
*psd
= NULL
;
449 if (!sd_has_inheritable_components(parent_desc
, is_directory
)) {
453 /* Create an inherited descriptor from the parent. */
455 if (DEBUGLEVEL
>= 10) {
456 DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
458 NDR_PRINT_DEBUG(security_descriptor
, parent_desc
);
461 status
= se_create_child_secdesc(ctx
,
465 &handle
->conn
->server_info
->ptok
->sids
[PRIMARY_USER_SID_INDEX
],
466 &handle
->conn
->server_info
->ptok
->sids
[PRIMARY_GROUP_SID_INDEX
],
468 if (!NT_STATUS_IS_OK(status
)) {
472 if (DEBUGLEVEL
>= 10) {
473 DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
475 NDR_PRINT_DEBUG(security_descriptor
, parent_desc
);
478 return SMB_VFS_FSET_NT_ACL(fsp
,
485 static NTSTATUS
check_parent_acl_common(vfs_handle_struct
*handle
,
487 uint32_t access_mask
,
488 struct security_descriptor
**pp_parent_desc
)
490 char *parent_name
= NULL
;
491 struct security_descriptor
*parent_desc
= NULL
;
492 uint32_t access_granted
= 0;
495 if (!parent_dirname(talloc_tos(), path
, &parent_name
, NULL
)) {
496 return NT_STATUS_NO_MEMORY
;
499 status
= get_nt_acl_internal(handle
,
507 if (!NT_STATUS_IS_OK(status
)) {
508 DEBUG(10,("check_parent_acl_common: get_nt_acl_internal "
509 "on directory %s for "
510 "path %s returned %s\n",
513 nt_errstr(status
) ));
516 if (pp_parent_desc
) {
517 *pp_parent_desc
= parent_desc
;
519 status
= smb1_file_se_access_check(handle
->conn
,
521 get_current_nttok(handle
->conn
),
524 if(!NT_STATUS_IS_OK(status
)) {
525 DEBUG(10,("check_parent_acl_common: access check "
526 "on directory %s for "
527 "path %s for mask 0x%x returned %s\n",
531 nt_errstr(status
) ));
537 static void free_sd_common(void **ptr
)
542 /*********************************************************************
543 Check ACL on open. For new files inherit from parent directory.
544 *********************************************************************/
546 static int open_acl_common(vfs_handle_struct
*handle
,
547 struct smb_filename
*smb_fname
,
552 uint32_t access_granted
= 0;
553 struct security_descriptor
*pdesc
= NULL
;
554 struct security_descriptor
*parent_desc
= NULL
;
555 bool file_existed
= true;
560 /* Stream open. Base filename open already did the ACL check. */
561 DEBUG(10,("open_acl_common: stream open on %s\n",
563 return SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
566 status
= get_full_smb_filename(talloc_tos(), smb_fname
,
568 if (!NT_STATUS_IS_OK(status
)) {
572 status
= get_nt_acl_internal(handle
,
579 if (NT_STATUS_IS_OK(status
)) {
580 /* See if we can access it. */
581 status
= smb1_file_se_access_check(handle
->conn
,
583 get_current_nttok(handle
->conn
),
586 if (!NT_STATUS_IS_OK(status
)) {
587 DEBUG(10,("open_acl_xattr: %s open "
588 "refused with error %s\n",
590 nt_errstr(status
) ));
593 } else if (NT_STATUS_EQUAL(status
,NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
594 file_existed
= false;
596 * If O_CREAT is true then we're trying to create a file.
597 * Check the parent directory ACL will allow this.
599 if (flags
& O_CREAT
) {
600 struct security_descriptor
*psd
= NULL
;
602 status
= check_parent_acl_common(handle
, fname
,
603 SEC_DIR_ADD_FILE
, &parent_desc
);
604 if (!NT_STATUS_IS_OK(status
)) {
607 /* Cache the parent security descriptor for
608 * later use. We do have an fsp here, but to
609 * keep the code consistent with the directory
610 * case which doesn't, use the handle. */
612 /* Attach this to the conn, move from talloc_tos(). */
613 psd
= (struct security_descriptor
*)talloc_move(handle
->conn
,
617 status
= NT_STATUS_NO_MEMORY
;
620 status
= NT_STATUS_NO_MEMORY
;
621 SMB_VFS_HANDLE_SET_DATA(handle
, psd
, free_sd_common
,
622 struct security_descriptor
*, goto err
);
623 status
= NT_STATUS_OK
;
627 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
630 nt_errstr(status
) ));
632 fsp
->fh
->fd
= SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
637 errno
= map_errno_from_nt_status(status
);
641 static int mkdir_acl_common(vfs_handle_struct
*handle
, const char *path
, mode_t mode
)
645 SMB_STRUCT_STAT sbuf
;
647 ret
= vfs_stat_smb_fname(handle
->conn
, path
, &sbuf
);
648 if (ret
== -1 && errno
== ENOENT
) {
649 struct security_descriptor
*parent_desc
= NULL
;
650 struct security_descriptor
*psd
= NULL
;
652 /* We're creating a new directory. */
653 status
= check_parent_acl_common(handle
, path
,
654 SEC_DIR_ADD_SUBDIR
, &parent_desc
);
655 if (!NT_STATUS_IS_OK(status
)) {
656 errno
= map_errno_from_nt_status(status
);
660 /* Cache the parent security descriptor for
661 * later use. We don't have an fsp here so
664 /* Attach this to the conn, move from talloc_tos(). */
665 psd
= (struct security_descriptor
*)talloc_move(handle
->conn
,
671 SMB_VFS_HANDLE_SET_DATA(handle
, psd
, free_sd_common
,
672 struct security_descriptor
*, return -1);
675 return SMB_VFS_NEXT_MKDIR(handle
, path
, mode
);
678 /*********************************************************************
679 Fetch a security descriptor given an fsp.
680 *********************************************************************/
682 static NTSTATUS
fget_nt_acl_common(vfs_handle_struct
*handle
, files_struct
*fsp
,
683 uint32_t security_info
, struct security_descriptor
**ppdesc
)
685 return get_nt_acl_internal(handle
, fsp
,
686 NULL
, security_info
, ppdesc
);
689 /*********************************************************************
690 Fetch a security descriptor given a pathname.
691 *********************************************************************/
693 static NTSTATUS
get_nt_acl_common(vfs_handle_struct
*handle
,
694 const char *name
, uint32_t security_info
, struct security_descriptor
**ppdesc
)
696 return get_nt_acl_internal(handle
, NULL
,
697 name
, security_info
, ppdesc
);
700 /*********************************************************************
701 Store a security descriptor given an fsp.
702 *********************************************************************/
704 static NTSTATUS
fset_nt_acl_common(vfs_handle_struct
*handle
, files_struct
*fsp
,
705 uint32_t security_info_sent
, const struct security_descriptor
*orig_psd
)
709 struct security_descriptor
*pdesc_next
= NULL
;
710 struct security_descriptor
*psd
= NULL
;
711 uint8_t hash
[XATTR_SD_HASH_SIZE
];
713 if (DEBUGLEVEL
>= 10) {
714 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
716 NDR_PRINT_DEBUG(security_descriptor
,
717 CONST_DISCARD(struct security_descriptor
*,orig_psd
));
720 status
= get_nt_acl_internal(handle
, fsp
,
722 SECINFO_OWNER
|SECINFO_GROUP
|SECINFO_DACL
|SECINFO_SACL
,
725 if (!NT_STATUS_IS_OK(status
)) {
729 psd
->revision
= orig_psd
->revision
;
730 /* All our SD's are self relative. */
731 psd
->type
= orig_psd
->type
| SEC_DESC_SELF_RELATIVE
;
733 if ((security_info_sent
& SECINFO_OWNER
) && (orig_psd
->owner_sid
!= NULL
)) {
734 psd
->owner_sid
= orig_psd
->owner_sid
;
736 if ((security_info_sent
& SECINFO_GROUP
) && (orig_psd
->group_sid
!= NULL
)) {
737 psd
->group_sid
= orig_psd
->group_sid
;
739 if (security_info_sent
& SECINFO_DACL
) {
740 psd
->dacl
= orig_psd
->dacl
;
741 psd
->type
|= SEC_DESC_DACL_PRESENT
;
743 if (security_info_sent
& SECINFO_SACL
) {
744 psd
->sacl
= orig_psd
->sacl
;
745 psd
->type
|= SEC_DESC_SACL_PRESENT
;
748 status
= SMB_VFS_NEXT_FSET_NT_ACL(handle
, fsp
, security_info_sent
, psd
);
749 if (!NT_STATUS_IS_OK(status
)) {
753 /* Get the full underlying sd, then hash. */
754 status
= SMB_VFS_NEXT_FGET_NT_ACL(handle
,
759 if (!NT_STATUS_IS_OK(status
)) {
763 status
= hash_sd_sha256(pdesc_next
, hash
);
764 if (!NT_STATUS_IS_OK(status
)) {
768 if (DEBUGLEVEL
>= 10) {
769 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
771 NDR_PRINT_DEBUG(security_descriptor
,
772 CONST_DISCARD(struct security_descriptor
*,psd
));
774 create_acl_blob(psd
, &blob
, XATTR_SD_HASH_TYPE_SHA256
, hash
);
775 store_acl_blob_fsp(handle
, fsp
, &blob
);
780 static SMB_STRUCT_DIR
*opendir_acl_common(vfs_handle_struct
*handle
,
781 const char *fname
, const char *mask
, uint32 attr
)
783 NTSTATUS status
= check_parent_acl_common(handle
, fname
,
786 if (!NT_STATUS_IS_OK(status
)) {
787 errno
= map_errno_from_nt_status(status
);
790 return SMB_VFS_NEXT_OPENDIR(handle
, fname
, mask
, attr
);
793 static int acl_common_remove_object(vfs_handle_struct
*handle
,
797 connection_struct
*conn
= handle
->conn
;
799 files_struct
*fsp
= NULL
;
801 char *parent_dir
= NULL
;
802 const char *final_component
= NULL
;
803 struct smb_filename local_fname
;
806 if (!parent_dirname(talloc_tos(), path
,
807 &parent_dir
, &final_component
)) {
808 saved_errno
= ENOMEM
;
812 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
813 is_directory
? "directory" : "file",
814 parent_dir
, final_component
));
816 /* cd into the parent dir to pin it. */
817 ret
= SMB_VFS_CHDIR(conn
, parent_dir
);
823 ZERO_STRUCT(local_fname
);
824 local_fname
.base_name
= CONST_DISCARD(char *,final_component
);
826 /* Must use lstat here. */
827 ret
= SMB_VFS_LSTAT(conn
, &local_fname
);
833 /* Ensure we have this file open with DELETE access. */
834 id
= vfs_file_id_from_sbuf(conn
, &local_fname
.st
);
835 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
836 file_find_di_next(fsp
)) {
837 if (fsp
->access_mask
& DELETE_ACCESS
&&
838 fsp
->delete_on_close
) {
839 /* We did open this for delete,
840 * allow the delete as root.
847 DEBUG(10,("acl_common_remove_object: %s %s/%s "
848 "not an open file\n",
849 is_directory
? "directory" : "file",
850 parent_dir
, final_component
));
851 saved_errno
= EACCES
;
857 ret
= SMB_VFS_NEXT_RMDIR(handle
, final_component
);
859 ret
= SMB_VFS_NEXT_UNLINK(handle
, &local_fname
);
869 TALLOC_FREE(parent_dir
);
871 vfs_ChDir(conn
, conn
->connectpath
);
878 static int rmdir_acl_common(struct vfs_handle_struct
*handle
,
883 ret
= SMB_VFS_NEXT_RMDIR(handle
, path
);
884 if (!(ret
== -1 && (errno
== EACCES
|| errno
== EPERM
))) {
885 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
891 return acl_common_remove_object(handle
,
896 static NTSTATUS
create_file_acl_common(struct vfs_handle_struct
*handle
,
897 struct smb_request
*req
,
898 uint16_t root_dir_fid
,
899 struct smb_filename
*smb_fname
,
900 uint32_t access_mask
,
901 uint32_t share_access
,
902 uint32_t create_disposition
,
903 uint32_t create_options
,
904 uint32_t file_attributes
,
905 uint32_t oplock_request
,
906 uint64_t allocation_size
,
907 uint32_t private_flags
,
908 struct security_descriptor
*sd
,
909 struct ea_list
*ea_list
,
910 files_struct
**result
,
913 NTSTATUS status
, status1
;
914 files_struct
*fsp
= NULL
;
916 struct security_descriptor
*parent_sd
= NULL
;
918 status
= SMB_VFS_NEXT_CREATE_FILE(handle
,
935 if (!NT_STATUS_IS_OK(status
)) {
939 if (info
!= FILE_WAS_CREATED
) {
940 /* File/directory was opened, not created. */
947 /* Only handle success. */
952 /* Security descriptor already set. */
962 /* We must have a cached parent sd in this case.
963 * attached to the handle. */
965 SMB_VFS_HANDLE_GET_DATA(handle
, parent_sd
,
966 struct security_descriptor
,
973 /* New directory - inherit from parent. */
974 status1
= inherit_new_acl(handle
, fsp
, parent_sd
, fsp
->is_directory
);
976 if (!NT_STATUS_IS_OK(status1
)) {
977 DEBUG(1,("create_file_acl_common: error setting "
980 nt_errstr(status1
) ));
985 /* Ensure we never leave attached data around. */
986 SMB_VFS_HANDLE_FREE_DATA(handle
);
988 if (NT_STATUS_IS_OK(status
) && pinfo
) {
995 smb_panic("create_file_acl_common: logic error.\n");
1000 static int unlink_acl_common(struct vfs_handle_struct
*handle
,
1001 const struct smb_filename
*smb_fname
)
1005 ret
= SMB_VFS_NEXT_UNLINK(handle
, smb_fname
);
1006 if (!(ret
== -1 && (errno
== EACCES
|| errno
== EPERM
))) {
1007 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1008 smb_fname
->base_name
,
1012 /* Don't do anything fancy for streams. */
1013 if (smb_fname
->stream_name
) {
1017 return acl_common_remove_object(handle
,
1018 smb_fname
->base_name
,