2007-10-26 21:50:55 +04:00
/*
Unix SMB / CIFS implementation .
Check access to files based on security descriptors .
Copyright ( C ) Jeremy Allison 2005 - 2006.
Copyright ( C ) Michael Adam 2007.
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2010-05-28 04:19:32 +04:00
# include "../librpc/gen_ndr/ndr_security.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2007-10-26 21:50:55 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ACLS
/****************************************************************************
Actually emulate the in - kernel access checking for delete access . We need
this to successfully return ACCESS_DENIED on a file open for delete access .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-06-16 01:14:31 +04:00
bool can_delete_file_in_directory ( connection_struct * conn ,
2020-05-01 01:28:32 +03:00
struct files_struct * dirfsp ,
2020-05-01 01:20:34 +03:00
const struct smb_filename * smb_fname )
2007-10-26 21:50:55 +04:00
{
2020-04-28 16:21:37 +03:00
struct smb_filename * smb_fname_parent = NULL ;
2009-06-23 02:26:56 +04:00
bool ret ;
2021-05-26 21:10:53 +03:00
NTSTATUS status ;
2007-10-26 21:50:55 +04:00
if ( ! CAN_WRITE ( conn ) ) {
return False ;
}
2011-06-24 02:06:16 +04:00
if ( ! lp_acl_check_permissions ( SNUM ( conn ) ) ) {
/* This option means don't check. */
return true ;
}
2021-06-08 21:03:24 +03:00
if ( get_current_uid ( conn ) = = ( uid_t ) 0 ) {
/* I'm sorry sir, I didn't know you were root... */
return true ;
}
2021-06-08 21:08:06 +03:00
if ( dirfsp ! = conn - > cwd_fsp ) {
smb_fname_parent = dirfsp - > fsp_name ;
} else {
2021-06-08 21:14:29 +03:00
struct smb_filename * atname = NULL ;
/*
* Get a pathref on the parent .
*/
status = parent_pathref ( talloc_tos ( ) ,
conn - > cwd_fsp ,
smb_fname ,
& smb_fname_parent ,
& atname ) ;
2021-06-08 21:08:06 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
2009-06-23 02:26:56 +04:00
}
2021-06-08 21:15:59 +03:00
SMB_ASSERT ( VALID_STAT ( smb_fname_parent - > st ) ) ;
2007-10-26 21:50:55 +04:00
/* fast paths first */
2009-06-23 02:26:56 +04:00
if ( ! S_ISDIR ( smb_fname_parent - > st . st_ex_mode ) ) {
ret = false ;
goto out ;
2007-10-26 21:50:55 +04:00
}
# ifdef S_ISVTX
2009-06-11 23:51:45 +04:00
/* sticky bit means delete only by owner of file or by root or
* by owner of directory . */
2009-06-23 02:26:56 +04:00
if ( smb_fname_parent - > st . st_ex_mode & S_ISVTX ) {
2011-11-05 02:39:55 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) ) {
/* If the file doesn't already exist then
* yes we ' ll be able to delete it . */
ret = true ;
2009-06-23 02:26:56 +04:00
goto out ;
2007-10-26 21:50:55 +04:00
}
2009-06-16 01:14:31 +04:00
2007-10-26 21:50:55 +04:00
/*
* Patch from SATOH Fumiyasu < fumiyas @ miraclelinux . com >
* for bug # 3348. Don ' t assume owning sticky bit
* directory means write access allowed .
2009-06-11 23:51:45 +04:00
* Fail to delete if we ' re not the owner of the file ,
* or the owner of the directory as we have no possible
* chance of deleting . Otherwise , go on and check the ACL .
2007-10-26 21:50:55 +04:00
*/
2010-03-15 22:13:30 +03:00
if ( ( get_current_uid ( conn ) ! =
2009-06-23 02:26:56 +04:00
smb_fname_parent - > st . st_ex_uid ) & &
2010-03-15 22:13:30 +03:00
( get_current_uid ( conn ) ! = smb_fname - > st . st_ex_uid ) ) {
2009-06-11 23:51:45 +04:00
DEBUG ( 10 , ( " can_delete_file_in_directory: not "
2009-06-16 01:14:31 +04:00
" owner of file %s or directory %s " ,
2009-06-23 02:26:56 +04:00
smb_fname_str_dbg ( smb_fname ) ,
smb_fname_str_dbg ( smb_fname_parent ) ) ) ;
ret = false ;
goto out ;
2007-10-26 21:50:55 +04:00
}
}
# endif
/* now for ACL checks */
2008-06-19 16:53:46 +04:00
/*
* There ' s two ways to get the permission to delete a file : First by
* having the DELETE bit on the file itself and second if that does
* not help , by the DELETE_CHILD bit on the containing directory .
*
2009-02-03 04:10:27 +03:00
* Here we only check the directory permissions , we will
* check the file DELETE permission separately .
2008-06-19 16:53:46 +04:00
*/
2021-06-08 21:18:34 +03:00
ret = NT_STATUS_IS_OK ( smbd_check_access_rights_fsp (
2021-06-08 22:24:17 +03:00
conn - > cwd_fsp ,
2021-06-08 21:18:34 +03:00
smb_fname_parent - > fsp ,
2012-09-14 03:11:31 +04:00
false ,
2011-11-05 02:55:11 +04:00
FILE_DELETE_CHILD ) ) ;
2009-06-23 02:26:56 +04:00
out :
2021-06-08 21:08:06 +03:00
if ( smb_fname_parent ! = dirfsp - > fsp_name ) {
TALLOC_FREE ( smb_fname_parent ) ;
}
2009-06-23 02:26:56 +04:00
return ret ;
2007-10-26 21:50:55 +04:00
}
2021-06-02 21:36:59 +03:00
/****************************************************************************
Userspace check for write access to fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool can_write_to_fsp ( struct files_struct * fsp )
{
2021-06-08 22:24:17 +03:00
return NT_STATUS_IS_OK ( smbd_check_access_rights_fsp (
fsp - > conn - > cwd_fsp ,
fsp ,
2021-06-02 21:36:59 +03:00
false ,
FILE_WRITE_DATA ) ) ;
}
2021-05-25 02:58:12 +03:00
/****************************************************************************
Check for an existing default Windows ACL on a directory fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool directory_has_default_acl_fsp ( struct files_struct * fsp )
{
struct security_descriptor * secdesc = NULL ;
unsigned int i ;
NTSTATUS status ;
2022-07-29 15:49:56 +03:00
status = SMB_VFS_FGET_NT_ACL ( metadata_fsp ( fsp ) ,
2021-05-25 02:58:12 +03:00
SECINFO_DACL ,
talloc_tos ( ) ,
& secdesc ) ;
if ( ! NT_STATUS_IS_OK ( status ) | |
secdesc = = NULL | |
secdesc - > dacl = = NULL )
{
TALLOC_FREE ( secdesc ) ;
return false ;
}
for ( i = 0 ; i < secdesc - > dacl - > num_aces ; i + + ) {
struct security_ace * psa = & secdesc - > dacl - > aces [ i ] ;
if ( psa - > flags & ( SEC_ACE_FLAG_OBJECT_INHERIT |
SEC_ACE_FLAG_CONTAINER_INHERIT ) )
{
TALLOC_FREE ( secdesc ) ;
return true ;
}
}
TALLOC_FREE ( secdesc ) ;
return false ;
}
2011-12-13 19:01:59 +04:00
/****************************************************************************
Check if setting delete on close is allowed on this fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-05-03 07:01:14 +03:00
NTSTATUS can_set_delete_on_close ( files_struct * fsp , uint32_t dosmode )
2011-12-13 19:01:59 +04:00
{
/*
* Only allow delete on close for writable files .
*/
if ( ( dosmode & FILE_ATTRIBUTE_READONLY ) & &
! lp_delete_readonly ( SNUM ( fsp - > conn ) ) ) {
DEBUG ( 10 , ( " can_set_delete_on_close: file %s delete on close "
" flag set but file attribute is readonly. \n " ,
fsp_str_dbg ( fsp ) ) ) ;
return NT_STATUS_CANNOT_DELETE ;
}
/*
* Only allow delete on close for writable shares .
*/
if ( ! CAN_WRITE ( fsp - > conn ) ) {
DEBUG ( 10 , ( " can_set_delete_on_close: file %s delete on "
" close flag set but write access denied on share. \n " ,
fsp_str_dbg ( fsp ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
/*
* Only allow delete on close for files / directories opened with delete
* intent .
*/
if ( ! ( fsp - > access_mask & DELETE_ACCESS ) ) {
DEBUG ( 10 , ( " can_set_delete_on_close: file %s delete on "
" close flag set but delete access denied. \n " ,
fsp_str_dbg ( fsp ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
/* Don't allow delete on close for non-empty directories. */
2020-04-02 19:21:11 +03:00
if ( fsp - > fsp_flags . is_directory ) {
2022-02-11 11:59:16 +03:00
SMB_ASSERT ( ! fsp_is_alternate_stream ( fsp ) ) ;
2011-12-13 19:01:59 +04:00
/* Or the root of a share. */
if ( ISDOT ( fsp - > fsp_name - > base_name ) ) {
DEBUG ( 10 , ( " can_set_delete_on_close: can't set delete on "
" close for the root of a share. \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2012-11-15 02:40:51 +04:00
return can_delete_directory_fsp ( fsp ) ;
2011-12-13 19:01:59 +04:00
}
return NT_STATUS_OK ;
}