2009-07-25 04:06:41 +04:00
/*
* Store Windows ACLs in data store - common functions .
2009-07-27 23:09:40 +04:00
* # included into modules / vfs_acl_xattr . c and modules / vfs_acl_tdb . c
2009-07-25 04:06:41 +04:00
*
* Copyright ( C ) Volker Lendecke , 2008
* Copyright ( C ) Jeremy Allison , 2009
2016-08-30 22:01:00 +03:00
* Copyright ( C ) Ralph Böhme , 2016
2009-07-25 04:06:41 +04:00
*
* 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/>.
*/
2017-08-18 15:41:57 +03:00
# include "includes.h"
# include "vfs_acl_common.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2017-08-18 15:41:57 +03:00
# include "librpc/gen_ndr/ndr_xattr.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-07-07 15:04:31 +04:00
# include "../lib/util/bitmap.h"
2016-07-15 18:48:19 +03:00
# include "passdb/lookup_sid.h"
2010-05-28 04:19:32 +04:00
2018-10-11 15:43:24 +03:00
# include <gnutls/gnutls.h>
# include <gnutls/crypto.h>
2009-07-25 04:06:41 +04:00
static NTSTATUS create_acl_blob ( const struct security_descriptor * psd ,
DATA_BLOB * pblob ,
uint16_t hash_type ,
uint8_t hash [ XATTR_SD_HASH_SIZE ] ) ;
2010-06-03 01:22:12 +04:00
# define HASH_SECURITY_INFO (SECINFO_OWNER | \
2010-06-03 01:25:18 +04:00
SECINFO_GROUP | \
2010-06-03 01:35:44 +04:00
SECINFO_DACL | \
2010-06-03 01:29:16 +04:00
SECINFO_SACL )
2009-07-25 04:06:41 +04:00
2017-08-18 15:41:57 +03:00
bool init_acl_common_config ( vfs_handle_struct * handle ,
const char * module_name )
2016-08-24 11:01:17 +03:00
{
struct acl_common_config * config = NULL ;
2017-09-28 08:53:48 +03:00
const struct enum_list * default_acl_style_list = NULL ;
default_acl_style_list = get_default_acl_style_list ( ) ;
2016-08-24 11:01:17 +03:00
config = talloc_zero ( handle - > conn , struct acl_common_config ) ;
if ( config = = NULL ) {
DBG_ERR ( " talloc_zero() failed \n " ) ;
errno = ENOMEM ;
return false ;
}
config - > ignore_system_acls = lp_parm_bool ( SNUM ( handle - > conn ) ,
2017-08-18 15:41:57 +03:00
module_name ,
2016-08-24 11:01:17 +03:00
" ignore system acls " ,
false ) ;
2016-08-24 21:31:00 +03:00
config - > default_acl_style = lp_parm_enum ( SNUM ( handle - > conn ) ,
2017-08-18 15:41:57 +03:00
module_name ,
2016-08-24 21:31:00 +03:00
" default acl style " ,
2017-09-28 08:53:48 +03:00
default_acl_style_list ,
2016-08-24 21:31:00 +03:00
DEFAULT_ACL_POSIX ) ;
2016-08-24 11:01:17 +03:00
SMB_VFS_HANDLE_SET_DATA ( handle , config , NULL ,
struct acl_common_config ,
return false ) ;
return true ;
}
2009-07-25 04:06:41 +04:00
/*******************************************************************
Hash a security descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-01-21 05:43:00 +04:00
static NTSTATUS hash_blob_sha256 ( DATA_BLOB blob ,
uint8_t * hash )
{
2018-10-11 15:43:24 +03:00
int rc ;
2013-01-21 05:43:00 +04:00
2018-10-11 15:43:24 +03:00
ZERO_ARRAY_LEN ( hash , XATTR_SD_HASH_SIZE ) ;
2013-01-21 05:43:00 +04:00
2018-10-11 15:43:24 +03:00
rc = gnutls_hash_fast ( GNUTLS_DIG_SHA256 ,
blob . data ,
blob . length ,
hash ) ;
if ( rc < 0 ) {
return NT_STATUS_INTERNAL_ERROR ;
}
2013-01-21 05:43:00 +04:00
return NT_STATUS_OK ;
}
/*******************************************************************
Hash a security descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-25 04:06:41 +04:00
static NTSTATUS hash_sd_sha256 ( struct security_descriptor * psd ,
uint8_t * hash )
{
DATA_BLOB blob ;
NTSTATUS status ;
memset ( hash , ' \0 ' , XATTR_SD_HASH_SIZE ) ;
status = create_acl_blob ( psd , & blob , XATTR_SD_HASH_TYPE_SHA256 , hash ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2013-01-21 05:43:00 +04:00
return hash_blob_sha256 ( blob , hash ) ;
2009-07-25 04:06:41 +04:00
}
/*******************************************************************
Parse out a struct security_descriptor from a DATA_BLOB .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS parse_acl_blob ( const DATA_BLOB * pblob ,
2012-10-10 04:50:27 +04:00
TALLOC_CTX * mem_ctx ,
2012-10-10 09:36:47 +04:00
struct security_descriptor * * ppdesc ,
uint16_t * p_hash_type ,
uint16_t * p_version ,
uint8_t hash [ XATTR_SD_HASH_SIZE ] ,
uint8_t sys_acl_hash [ XATTR_SD_HASH_SIZE ] )
2009-07-25 04:06:41 +04:00
{
struct xattr_NTACL xacl ;
enum ndr_err_code ndr_err ;
size_t sd_size ;
2012-10-10 04:50:27 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-07-25 04:06:41 +04:00
2012-10-10 04:50:27 +04:00
ndr_err = ndr_pull_struct_blob ( pblob , frame , & xacl ,
2009-07-25 04:06:41 +04:00
( ndr_pull_flags_fn_t ) ndr_pull_xattr_NTACL ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2016-08-27 11:11:14 +03:00
DBG_INFO ( " ndr_pull_xattr_NTACL failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ;
2012-10-10 04:50:27 +04:00
TALLOC_FREE ( frame ) ;
2011-02-02 14:50:42 +03:00
return ndr_map_error2ntstatus ( ndr_err ) ;
2009-07-25 04:06:41 +04:00
}
2012-10-10 09:36:47 +04:00
* p_version = xacl . version ;
2009-07-25 04:06:41 +04:00
switch ( xacl . version ) {
2011-10-11 14:37:56 +04:00
case 1 :
2012-10-10 04:50:27 +04:00
* ppdesc = make_sec_desc ( mem_ctx , SD_REVISION ,
2011-10-11 14:37:56 +04:00
xacl . info . sd - > type | SEC_DESC_SELF_RELATIVE ,
xacl . info . sd - > owner_sid ,
xacl . info . sd - > group_sid ,
xacl . info . sd - > sacl ,
xacl . info . sd - > dacl ,
& sd_size ) ;
/* No hash - null out. */
* p_hash_type = XATTR_SD_HASH_TYPE_NONE ;
memset ( hash , ' \0 ' , XATTR_SD_HASH_SIZE ) ;
break ;
2009-07-25 04:06:41 +04:00
case 2 :
2012-10-10 04:50:27 +04:00
* ppdesc = make_sec_desc ( mem_ctx , SD_REVISION ,
2009-07-25 04:06:41 +04:00
xacl . info . sd_hs2 - > sd - > type | SEC_DESC_SELF_RELATIVE ,
xacl . info . sd_hs2 - > sd - > owner_sid ,
xacl . info . sd_hs2 - > sd - > group_sid ,
xacl . info . sd_hs2 - > sd - > sacl ,
xacl . info . sd_hs2 - > sd - > dacl ,
& sd_size ) ;
/* No hash - null out. */
* p_hash_type = XATTR_SD_HASH_TYPE_NONE ;
memset ( hash , ' \0 ' , XATTR_SD_HASH_SIZE ) ;
break ;
case 3 :
2012-10-10 04:50:27 +04:00
* ppdesc = make_sec_desc ( mem_ctx , SD_REVISION ,
2009-07-25 04:06:41 +04:00
xacl . info . sd_hs3 - > sd - > type | SEC_DESC_SELF_RELATIVE ,
xacl . info . sd_hs3 - > sd - > owner_sid ,
xacl . info . sd_hs3 - > sd - > group_sid ,
xacl . info . sd_hs3 - > sd - > sacl ,
xacl . info . sd_hs3 - > sd - > dacl ,
& sd_size ) ;
* p_hash_type = xacl . info . sd_hs3 - > hash_type ;
2012-10-10 09:36:47 +04:00
/* Current version 3 (if no sys acl hash available). */
2009-07-25 04:06:41 +04:00
memcpy ( hash , xacl . info . sd_hs3 - > hash , XATTR_SD_HASH_SIZE ) ;
break ;
2012-10-10 09:36:47 +04:00
case 4 :
* ppdesc = make_sec_desc ( mem_ctx , SD_REVISION ,
xacl . info . sd_hs4 - > sd - > type | SEC_DESC_SELF_RELATIVE ,
xacl . info . sd_hs4 - > sd - > owner_sid ,
xacl . info . sd_hs4 - > sd - > group_sid ,
xacl . info . sd_hs4 - > sd - > sacl ,
xacl . info . sd_hs4 - > sd - > dacl ,
& sd_size ) ;
* p_hash_type = xacl . info . sd_hs4 - > hash_type ;
/* Current version 4. */
memcpy ( hash , xacl . info . sd_hs4 - > hash , XATTR_SD_HASH_SIZE ) ;
memcpy ( sys_acl_hash , xacl . info . sd_hs4 - > sys_acl_hash , XATTR_SD_HASH_SIZE ) ;
break ;
2009-07-25 04:06:41 +04:00
default :
2012-10-10 04:50:27 +04:00
TALLOC_FREE ( frame ) ;
2009-07-25 04:06:41 +04:00
return NT_STATUS_REVISION_MISMATCH ;
}
2012-10-10 04:50:27 +04:00
TALLOC_FREE ( frame ) ;
2009-07-25 04:06:41 +04:00
return ( * ppdesc ! = NULL ) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY ;
}
/*******************************************************************
2012-10-10 09:36:47 +04:00
Create a DATA_BLOB from a hash of the security descriptor storead at
the system layer and the NT ACL we wish to preserve
2009-07-25 04:06:41 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS create_acl_blob ( const struct security_descriptor * psd ,
DATA_BLOB * pblob ,
uint16_t hash_type ,
uint8_t hash [ XATTR_SD_HASH_SIZE ] )
{
struct xattr_NTACL xacl ;
struct security_descriptor_hash_v3 sd_hs3 ;
enum ndr_err_code ndr_err ;
TALLOC_CTX * ctx = talloc_tos ( ) ;
ZERO_STRUCT ( xacl ) ;
ZERO_STRUCT ( sd_hs3 ) ;
xacl . version = 3 ;
xacl . info . sd_hs3 = & sd_hs3 ;
2011-05-06 03:19:49 +04:00
xacl . info . sd_hs3 - > sd = discard_const_p ( struct security_descriptor , psd ) ;
2009-07-25 04:06:41 +04:00
xacl . info . sd_hs3 - > hash_type = hash_type ;
memcpy ( & xacl . info . sd_hs3 - > hash [ 0 ] , hash , XATTR_SD_HASH_SIZE ) ;
ndr_err = ndr_push_struct_blob (
2010-05-10 02:42:06 +04:00
pblob , ctx , & xacl ,
2009-07-25 04:06:41 +04:00
( ndr_push_flags_fn_t ) ndr_push_xattr_NTACL ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2016-08-27 11:11:14 +03:00
DBG_INFO ( " ndr_push_xattr_NTACL failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ;
2011-02-02 14:50:42 +03:00
return ndr_map_error2ntstatus ( ndr_err ) ;
2009-07-25 04:06:41 +04:00
}
return NT_STATUS_OK ;
}
2012-10-10 09:36:47 +04:00
/*******************************************************************
Create a DATA_BLOB from a hash of the security descriptors
( system and NT ) stored at the system layer and the NT ACL we wish
to preserve .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS create_sys_acl_blob ( const struct security_descriptor * psd ,
DATA_BLOB * pblob ,
uint16_t hash_type ,
uint8_t hash [ XATTR_SD_HASH_SIZE ] ,
const char * description ,
uint8_t sys_acl_hash [ XATTR_SD_HASH_SIZE ] )
{
struct xattr_NTACL xacl ;
struct security_descriptor_hash_v4 sd_hs4 ;
enum ndr_err_code ndr_err ;
TALLOC_CTX * ctx = talloc_tos ( ) ;
ZERO_STRUCT ( xacl ) ;
ZERO_STRUCT ( sd_hs4 ) ;
xacl . version = 4 ;
xacl . info . sd_hs4 = & sd_hs4 ;
xacl . info . sd_hs4 - > sd = discard_const_p ( struct security_descriptor , psd ) ;
xacl . info . sd_hs4 - > hash_type = hash_type ;
memcpy ( & xacl . info . sd_hs4 - > hash [ 0 ] , hash , XATTR_SD_HASH_SIZE ) ;
xacl . info . sd_hs4 - > description = description ;
memcpy ( & xacl . info . sd_hs4 - > sys_acl_hash [ 0 ] , sys_acl_hash , XATTR_SD_HASH_SIZE ) ;
ndr_err = ndr_push_struct_blob (
pblob , ctx , & xacl ,
( ndr_push_flags_fn_t ) ndr_push_xattr_NTACL ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2016-08-27 11:11:14 +03:00
DBG_INFO ( " ndr_push_xattr_NTACL failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ;
2012-10-10 09:36:47 +04:00
return ndr_map_error2ntstatus ( ndr_err ) ;
}
return NT_STATUS_OK ;
}
2009-12-24 04:19:22 +03:00
/*******************************************************************
Add in 3 inheritable components for a non - inheritable directory ACL .
CREATOR_OWNER / CREATOR_GROUP / WORLD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-03-17 02:26:57 +04:00
static NTSTATUS add_directory_inheritable_components ( vfs_handle_struct * handle ,
2009-12-24 04:19:22 +03:00
const char * name ,
SMB_STRUCT_STAT * psbuf ,
struct security_descriptor * psd )
{
struct connection_struct * conn = handle - > conn ;
int num_aces = ( psd - > dacl ? psd - > dacl - > num_aces : 0 ) ;
struct smb_filename smb_fname ;
2010-02-07 22:10:57 +03:00
enum security_ace_type acltype ;
2009-12-24 04:19:22 +03:00
uint32_t access_mask ;
mode_t dir_mode ;
mode_t file_mode ;
mode_t mode ;
2012-11-01 02:51:28 +04:00
struct security_ace * new_ace_list ;
if ( psd - > dacl ) {
new_ace_list = talloc_zero_array ( psd - > dacl ,
struct security_ace ,
num_aces + 3 ) ;
} else {
/*
* make_sec_acl ( ) at the bottom of this function
2023-07-13 09:52:45 +03:00
* duplicates new_ace_list
2012-11-01 02:51:28 +04:00
*/
new_ace_list = talloc_zero_array ( talloc_tos ( ) ,
struct security_ace ,
num_aces + 3 ) ;
}
2009-12-24 04:19:22 +03:00
if ( new_ace_list = = NULL ) {
2012-03-17 02:26:57 +04:00
return NT_STATUS_NO_MEMORY ;
2009-12-24 04:19:22 +03:00
}
/* Fake a quick smb_filename. */
ZERO_STRUCT ( smb_fname ) ;
smb_fname . st = * psbuf ;
2011-05-06 03:19:49 +04:00
smb_fname . base_name = discard_const_p ( char , name ) ;
2009-12-24 04:19:22 +03:00
dir_mode = unix_mode ( conn ,
FILE_ATTRIBUTE_DIRECTORY , & smb_fname , NULL ) ;
file_mode = unix_mode ( conn ,
FILE_ATTRIBUTE_ARCHIVE , & smb_fname , NULL ) ;
mode = dir_mode | file_mode ;
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " directory %s, mode = 0%o \n " , name , ( unsigned int ) mode ) ;
2009-12-24 04:19:22 +03:00
if ( num_aces ) {
memcpy ( new_ace_list , psd - > dacl - > aces ,
num_aces * sizeof ( struct security_ace ) ) ;
}
2010-02-07 22:10:57 +03:00
access_mask = map_canon_ace_perms ( SNUM ( conn ) , & acltype ,
2009-12-24 04:19:22 +03:00
mode & 0700 , false ) ;
init_sec_ace ( & new_ace_list [ num_aces ] ,
& global_sid_Creator_Owner ,
2010-02-07 22:10:57 +03:00
acltype ,
2009-12-24 04:19:22 +03:00
access_mask ,
SEC_ACE_FLAG_CONTAINER_INHERIT |
SEC_ACE_FLAG_OBJECT_INHERIT |
SEC_ACE_FLAG_INHERIT_ONLY ) ;
2010-02-07 22:10:57 +03:00
access_mask = map_canon_ace_perms ( SNUM ( conn ) , & acltype ,
2009-12-24 04:19:22 +03:00
( mode < < 3 ) & 0700 , false ) ;
init_sec_ace ( & new_ace_list [ num_aces + 1 ] ,
& global_sid_Creator_Group ,
2010-02-07 22:10:57 +03:00
acltype ,
2009-12-24 04:19:22 +03:00
access_mask ,
SEC_ACE_FLAG_CONTAINER_INHERIT |
SEC_ACE_FLAG_OBJECT_INHERIT |
SEC_ACE_FLAG_INHERIT_ONLY ) ;
2010-02-07 22:10:57 +03:00
access_mask = map_canon_ace_perms ( SNUM ( conn ) , & acltype ,
2009-12-24 04:19:22 +03:00
( mode < < 6 ) & 0700 , false ) ;
init_sec_ace ( & new_ace_list [ num_aces + 2 ] ,
& global_sid_World ,
2010-02-07 22:10:57 +03:00
acltype ,
2009-12-24 04:19:22 +03:00
access_mask ,
SEC_ACE_FLAG_CONTAINER_INHERIT |
SEC_ACE_FLAG_OBJECT_INHERIT |
SEC_ACE_FLAG_INHERIT_ONLY ) ;
2012-03-17 02:26:57 +04:00
if ( psd - > dacl ) {
psd - > dacl - > aces = new_ace_list ;
psd - > dacl - > num_aces + = 3 ;
2014-09-08 22:53:44 +04:00
psd - > dacl - > size + = new_ace_list [ num_aces ] . size +
new_ace_list [ num_aces + 1 ] . size +
new_ace_list [ num_aces + 2 ] . size ;
2012-03-17 02:26:57 +04:00
} else {
2012-11-01 02:51:28 +04:00
psd - > dacl = make_sec_acl ( psd ,
2012-03-17 02:26:57 +04:00
NT4_ACL_REVISION ,
3 ,
new_ace_list ) ;
if ( psd - > dacl = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
return NT_STATUS_OK ;
2009-12-24 04:19:22 +03:00
}
2016-08-23 23:32:57 +03:00
/**
* Validate an ACL blob
*
* This validates an ACL blob against the underlying filesystem ACL . If this
* function returns NT_STATUS_OK ppsd can be
*
* 1. the ACL from the blob ( psd_from_fs = false ) , or
* 2. the ACL from the fs ( psd_from_fs = true ) , or
* 3. NULL ( ! )
*
* If the return value is anything else then NT_STATUS_OK , ppsd is set to NULL
* and psd_from_fs set to false .
*
* Returning the underlying filesystem ACL in case no . 2 is really just an
2023-07-13 09:52:45 +03:00
* optimisation , because some validations have to fetch the filesystem ACL as
2016-08-23 23:32:57 +03:00
* part of the validation , so we already have it available and callers might
* need it as well .
* */
static NTSTATUS validate_nt_acl_blob ( TALLOC_CTX * mem_ctx ,
2020-04-14 22:43:51 +03:00
vfs_handle_struct * handle ,
struct files_struct * fsp ,
const struct smb_filename * smb_fname ,
const DATA_BLOB * blob ,
struct security_descriptor * * ppsd ,
bool * psd_is_from_fs )
2009-07-25 04:06:41 +04:00
{
NTSTATUS status ;
2010-08-01 22:15:57 +04:00
uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE ;
2012-10-10 09:36:47 +04:00
uint16_t xattr_version = 0 ;
2009-07-25 04:06:41 +04:00
uint8_t hash [ XATTR_SD_HASH_SIZE ] ;
2012-10-10 09:36:47 +04:00
uint8_t sys_acl_hash [ XATTR_SD_HASH_SIZE ] ;
2009-07-25 04:06:41 +04:00
uint8_t hash_tmp [ XATTR_SD_HASH_SIZE ] ;
2012-10-10 09:36:47 +04:00
uint8_t sys_acl_hash_tmp [ XATTR_SD_HASH_SIZE ] ;
2016-08-23 18:07:20 +03:00
struct security_descriptor * psd = NULL ;
2016-08-23 14:08:12 +03:00
struct security_descriptor * psd_blob = NULL ;
2016-08-23 14:11:24 +03:00
struct security_descriptor * psd_fs = NULL ;
2016-08-23 23:32:57 +03:00
char * sys_acl_blob_description = NULL ;
DATA_BLOB sys_acl_blob = { 0 } ;
2016-08-24 11:01:17 +03:00
struct acl_common_config * config = NULL ;
2009-07-25 04:06:41 +04:00
2016-08-23 23:32:57 +03:00
* ppsd = NULL ;
* psd_is_from_fs = false ;
2009-07-25 04:06:41 +04:00
2016-08-24 11:01:17 +03:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct acl_common_config ,
return NT_STATUS_UNSUCCESSFUL ) ;
2016-08-23 23:32:57 +03:00
status = parse_acl_blob ( blob ,
mem_ctx ,
& psd_blob ,
& hash_type ,
& xattr_version ,
& hash [ 0 ] ,
& sys_acl_hash [ 0 ] ) ;
2009-07-25 04:06:41 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-08-23 23:32:57 +03:00
DBG_DEBUG ( " parse_acl_blob returned %s \n " , nt_errstr ( status ) ) ;
goto fail ;
2009-07-25 04:06:41 +04:00
}
2012-10-10 09:36:47 +04:00
/* determine which type of xattr we got */
switch ( xattr_version ) {
case 1 :
case 2 :
2023-08-31 13:01:13 +03:00
/* These xattr types are unilateral, they do not
2012-10-10 09:36:47 +04:00
* require confirmation of the hash . In particular ,
* the NTVFS file server uses version 1 , but
* ' samba - tool ntacl ' can set these as well */
2016-08-23 23:32:57 +03:00
* ppsd = psd_blob ;
return NT_STATUS_OK ;
2012-10-10 09:36:47 +04:00
case 3 :
case 4 :
2016-08-24 11:01:17 +03:00
if ( config - > ignore_system_acls ) {
2016-08-23 23:32:57 +03:00
* ppsd = psd_blob ;
return NT_STATUS_OK ;
2012-10-10 09:36:47 +04:00
}
2009-07-25 04:06:41 +04:00
2012-10-10 09:36:47 +04:00
break ;
default :
2016-08-23 23:32:57 +03:00
DBG_DEBUG ( " ACL blob revision mismatch (%u) for file %s \n " ,
( unsigned int ) hash_type , smb_fname - > base_name ) ;
2016-08-23 14:08:12 +03:00
TALLOC_FREE ( psd_blob ) ;
2016-08-23 23:32:57 +03:00
return NT_STATUS_OK ;
2010-10-16 02:56:09 +04:00
}
2009-07-25 04:06:41 +04:00
2012-10-10 09:36:47 +04:00
/* determine which type of xattr we got */
if ( hash_type ! = XATTR_SD_HASH_TYPE_SHA256 ) {
2016-08-23 23:32:57 +03:00
DBG_DEBUG ( " ACL blob hash type (%u) unexpected for file %s \n " ,
( unsigned int ) hash_type , smb_fname - > base_name ) ;
2016-08-23 14:08:12 +03:00
TALLOC_FREE ( psd_blob ) ;
2016-08-23 23:32:57 +03:00
return NT_STATUS_OK ;
2009-07-25 04:06:41 +04:00
}
2012-10-10 09:36:47 +04:00
/* determine which type of xattr we got */
switch ( xattr_version ) {
case 4 :
{
int ret ;
2021-06-08 23:01:12 +03:00
/* Get the full underlying sd, then hash. */
ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD ( handle ,
fsp ,
mem_ctx ,
& sys_acl_blob_description ,
& sys_acl_blob ) ;
2012-10-10 09:36:47 +04:00
/* If we fail to get the ACL blob (for some reason) then this
* is not fatal , we just work based on the NT ACL only */
if ( ret = = 0 ) {
status = hash_blob_sha256 ( sys_acl_blob , sys_acl_hash_tmp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-08-23 18:07:20 +03:00
goto fail ;
2012-10-10 09:36:47 +04:00
}
2009-07-25 04:06:41 +04:00
2016-08-23 18:07:20 +03:00
TALLOC_FREE ( sys_acl_blob_description ) ;
TALLOC_FREE ( sys_acl_blob . data ) ;
2012-10-10 09:36:47 +04:00
if ( memcmp ( & sys_acl_hash [ 0 ] , & sys_acl_hash_tmp [ 0 ] ,
XATTR_SD_HASH_SIZE ) = = 0 ) {
/* Hash matches, return blob sd. */
2016-08-23 23:32:57 +03:00
DBG_DEBUG ( " blob hash matches for file %s \n " ,
smb_fname - > base_name ) ;
* ppsd = psd_blob ;
return NT_STATUS_OK ;
2012-10-10 09:36:47 +04:00
}
}
2012-07-17 21:04:03 +04:00
2012-10-10 09:36:47 +04:00
/* Otherwise, fall though and see if the NT ACL hash matches */
2017-07-26 18:53:45 +03:00
FALL_THROUGH ;
2012-09-10 02:43:09 +04:00
}
2012-10-10 09:36:47 +04:00
case 3 :
2012-10-24 10:03:41 +04:00
/* Get the full underlying sd for the hash
or to return as backup . */
2021-06-08 23:01:12 +03:00
status = SMB_VFS_NEXT_FGET_NT_ACL ( handle ,
fsp ,
HASH_SECURITY_INFO ,
mem_ctx ,
& psd_fs ) ;
2012-10-24 10:03:41 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-08-23 23:32:57 +03:00
DBG_DEBUG ( " get_next_acl for file %s returned %s \n " ,
smb_fname - > base_name , nt_errstr ( status ) ) ;
2016-08-23 18:07:20 +03:00
goto fail ;
2012-10-24 10:03:41 +04:00
}
2016-08-23 14:11:24 +03:00
status = hash_sd_sha256 ( psd_fs , hash_tmp ) ;
2012-10-10 09:36:47 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-08-23 14:08:12 +03:00
TALLOC_FREE ( psd_blob ) ;
2016-08-23 23:32:57 +03:00
* ppsd = psd_fs ;
* psd_is_from_fs = true ;
return NT_STATUS_OK ;
2012-10-10 09:36:47 +04:00
}
2012-09-10 02:43:09 +04:00
2012-10-10 09:36:47 +04:00
if ( memcmp ( & hash [ 0 ] , & hash_tmp [ 0 ] , XATTR_SD_HASH_SIZE ) = = 0 ) {
/* Hash matches, return blob sd. */
2016-08-23 23:32:57 +03:00
DBG_DEBUG ( " blob hash matches for file %s \n " ,
smb_fname - > base_name ) ;
* ppsd = psd_blob ;
return NT_STATUS_OK ;
2012-10-10 09:36:47 +04:00
}
2009-07-25 04:06:41 +04:00
2012-10-10 09:36:47 +04:00
/* Hash doesn't match, return underlying sd. */
2016-08-23 23:32:57 +03:00
DBG_DEBUG ( " blob hash does not match for file %s - returning "
" file system SD mapping. \n " ,
smb_fname - > base_name ) ;
2012-10-10 09:36:47 +04:00
if ( DEBUGLEVEL > = 10 ) {
2016-08-23 23:32:57 +03:00
DBG_DEBUG ( " acl for blob hash for %s is: \n " ,
smb_fname - > base_name ) ;
2016-08-23 14:11:24 +03:00
NDR_PRINT_DEBUG ( security_descriptor , psd_fs ) ;
2012-10-10 09:36:47 +04:00
}
2016-08-23 14:08:12 +03:00
TALLOC_FREE ( psd_blob ) ;
2016-08-23 23:32:57 +03:00
* ppsd = psd_fs ;
* psd_is_from_fs = true ;
}
return NT_STATUS_OK ;
fail :
TALLOC_FREE ( psd ) ;
TALLOC_FREE ( psd_blob ) ;
TALLOC_FREE ( psd_fs ) ;
TALLOC_FREE ( sys_acl_blob_description ) ;
TALLOC_FREE ( sys_acl_blob . data ) ;
return status ;
}
2020-04-13 22:09:47 +03:00
/*******************************************************************
Pull a DATA_BLOB from an xattr given an fsp .
If the hash doesn ' t match , or doesn ' t exist - return the underlying
filesystem sd .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS fget_nt_acl_common (
NTSTATUS ( * fget_acl_blob_fn ) ( TALLOC_CTX * ctx ,
vfs_handle_struct * handle ,
files_struct * fsp ,
DATA_BLOB * pblob ) ,
vfs_handle_struct * handle ,
files_struct * fsp ,
uint32_t security_info ,
TALLOC_CTX * mem_ctx ,
struct security_descriptor * * ppdesc )
{
DATA_BLOB blob = data_blob_null ;
NTSTATUS status ;
struct security_descriptor * psd = NULL ;
const struct smb_filename * smb_fname = fsp - > fsp_name ;
bool psd_is_from_fs = false ;
struct acl_common_config * config = NULL ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct acl_common_config ,
return NT_STATUS_UNSUCCESSFUL ) ;
DBG_DEBUG ( " name=%s \n " , smb_fname - > base_name ) ;
status = fget_acl_blob_fn ( mem_ctx , handle , fsp , & blob ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
status = validate_nt_acl_blob ( mem_ctx ,
2020-04-14 22:43:51 +03:00
handle ,
fsp ,
smb_fname ,
& blob ,
& psd ,
& psd_is_from_fs ) ;
2020-04-13 22:09:47 +03:00
TALLOC_FREE ( blob . data ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " ACL validation for [%s] failed \n " ,
smb_fname - > base_name ) ;
goto fail ;
}
}
if ( psd = = NULL ) {
/* Get the full underlying sd, as we failed to get the
* blob for the hash , or the revision / hash type wasn ' t
* known */
if ( config - > ignore_system_acls ) {
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
status = make_default_filesystem_acl (
mem_ctx ,
config - > default_acl_style ,
smb_fname - > base_name ,
& fsp - > fsp_name - > st ,
& psd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
} else {
status = SMB_VFS_NEXT_FGET_NT_ACL ( handle ,
fsp ,
security_info ,
mem_ctx ,
& psd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " get_next_acl for file %s "
" returned %s \n " ,
smb_fname - > base_name ,
nt_errstr ( status ) ) ;
goto fail ;
}
psd_is_from_fs = true ;
}
}
if ( psd_is_from_fs ) {
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
/*
* We ' re returning the underlying ACL from the
* filesystem . If it ' s a directory , and has no
* inheritable ACE entries we have to fake them .
*/
if ( fsp - > fsp_flags . is_directory & &
! sd_has_inheritable_components ( psd , true ) ) {
status = add_directory_inheritable_components (
handle ,
smb_fname - > base_name ,
& fsp - > fsp_name - > st ,
psd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
}
/*
* The underlying POSIX module always sets the
* ~ SEC_DESC_DACL_PROTECTED bit , as ACLs can ' t be inherited in
* this way under POSIX . Remove it for Windows - style ACLs .
*/
psd - > type & = ~ SEC_DESC_DACL_PROTECTED ;
}
if ( ! ( security_info & SECINFO_OWNER ) ) {
psd - > owner_sid = NULL ;
}
if ( ! ( security_info & SECINFO_GROUP ) ) {
psd - > group_sid = NULL ;
}
if ( ! ( security_info & SECINFO_DACL ) ) {
psd - > type & = ~ SEC_DESC_DACL_PRESENT ;
psd - > dacl = NULL ;
}
if ( ! ( security_info & SECINFO_SACL ) ) {
psd - > type & = ~ SEC_DESC_SACL_PRESENT ;
psd - > sacl = NULL ;
}
if ( DEBUGLEVEL > = 10 ) {
DBG_DEBUG ( " returning acl for %s is: \n " ,
smb_fname - > base_name ) ;
NDR_PRINT_DEBUG ( security_descriptor , psd ) ;
}
* ppdesc = psd ;
return NT_STATUS_OK ;
fail :
TALLOC_FREE ( psd ) ;
return status ;
}
2016-03-22 00:04:24 +03:00
/*********************************************************************
Set the underlying ACL ( e . g . POSIX ACLS , POSIX owner , etc )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS set_underlying_acl ( vfs_handle_struct * handle , files_struct * fsp ,
struct security_descriptor * psd ,
uint32_t security_info_sent ,
bool chown_needed )
{
2017-10-04 13:51:29 +03:00
NTSTATUS status ;
2017-10-04 23:27:24 +03:00
const struct security_token * token = NULL ;
2018-12-08 17:37:21 +03:00
struct dom_sid_buf buf ;
2017-10-04 13:51:29 +03:00
status = SMB_VFS_NEXT_FSET_NT_ACL ( handle , fsp , security_info_sent , psd ) ;
2016-03-22 00:04:24 +03:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) ) {
return status ;
}
/* We got access denied here. If we're already root,
or we didn ' t need to do a chown , or the fsp isn ' t
open with WRITE_OWNER access , just return . */
2023-12-20 20:01:57 +03:00
if ( get_current_uid ( handle - > conn ) = = 0 | | ! chown_needed ) {
2016-03-22 00:04:24 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
2023-12-20 20:01:57 +03:00
status = check_any_access_fsp ( fsp , SEC_STD_WRITE_OWNER ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2016-03-22 00:04:24 +03:00
2017-10-04 23:27:24 +03:00
/*
* Only allow take - ownership , not give - ownership . That ' s the way Windows
* implements SEC_STD_WRITE_OWNER . MS - FSA 2.1 .5 .16 just states : If
* InputBuffer . OwnerSid is not a valid owner SID for a file in the
* objectstore , as determined in an implementation specific manner , the
* object store MUST return STATUS_INVALID_OWNER .
*/
token = get_current_nttok ( fsp - > conn ) ;
if ( ! security_token_is_sid ( token , psd - > owner_sid ) ) {
return NT_STATUS_INVALID_OWNER ;
}
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " overriding chown on file %s for sid %s \n " ,
2018-12-08 17:37:21 +03:00
fsp_str_dbg ( fsp ) ,
dom_sid_str_buf ( psd - > owner_sid , & buf ) ) ;
2016-03-22 00:04:24 +03:00
/* Ok, we failed to chown and we have
SEC_STD_WRITE_OWNER access - override . */
2024-03-25 19:04:17 +03:00
become_root ( ) ;
2016-03-22 00:04:24 +03:00
status = SMB_VFS_NEXT_FSET_NT_ACL ( handle , fsp , security_info_sent , psd ) ;
2024-03-25 19:04:17 +03:00
unbecome_root ( ) ;
2016-03-22 00:04:24 +03:00
return status ;
}
/*********************************************************************
Store a v3 security descriptor
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-08-18 14:52:31 +03:00
static NTSTATUS store_v3_blob (
NTSTATUS ( * store_acl_blob_fsp_fn ) ( vfs_handle_struct * handle ,
files_struct * fsp ,
DATA_BLOB * pblob ) ,
vfs_handle_struct * handle , files_struct * fsp ,
struct security_descriptor * psd ,
struct security_descriptor * pdesc_next ,
uint8_t hash [ XATTR_SD_HASH_SIZE ] )
2016-03-22 00:04:24 +03:00
{
NTSTATUS status ;
DATA_BLOB blob ;
if ( DEBUGLEVEL > = 10 ) {
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " storing xattr sd for file %s \n " ,
fsp_str_dbg ( fsp ) ) ;
2016-03-22 00:04:24 +03:00
NDR_PRINT_DEBUG (
security_descriptor ,
discard_const_p ( struct security_descriptor , psd ) ) ;
if ( pdesc_next ! = NULL ) {
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " storing xattr sd based on \n " ) ;
2016-03-22 00:04:24 +03:00
NDR_PRINT_DEBUG (
security_descriptor ,
discard_const_p ( struct security_descriptor ,
pdesc_next ) ) ;
} else {
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " ignoring underlying sd \n " ) ;
2016-03-22 00:04:24 +03:00
}
}
status = create_acl_blob ( psd , & blob , XATTR_SD_HASH_TYPE_SHA256 , hash ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " create_acl_blob failed \n " ) ;
2016-03-22 00:04:24 +03:00
return status ;
}
2017-08-18 14:52:31 +03:00
status = store_acl_blob_fsp_fn ( handle , fsp , & blob ) ;
2016-03-22 00:04:24 +03:00
return status ;
}
2009-07-25 04:06:41 +04:00
/*********************************************************************
Store a security descriptor given an fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-08-18 15:41:57 +03:00
NTSTATUS fset_nt_acl_common (
2020-04-13 22:29:22 +03:00
NTSTATUS ( * fget_acl_blob_fn ) ( TALLOC_CTX * ctx ,
2017-08-18 15:41:57 +03:00
vfs_handle_struct * handle ,
files_struct * fsp ,
DATA_BLOB * pblob ) ,
NTSTATUS ( * store_acl_blob_fsp_fn ) ( vfs_handle_struct * handle ,
files_struct * fsp ,
DATA_BLOB * pblob ) ,
const char * module_name ,
vfs_handle_struct * handle , files_struct * fsp ,
uint32_t security_info_sent ,
const struct security_descriptor * orig_psd )
2009-07-25 04:06:41 +04:00
{
NTSTATUS status ;
2012-10-10 09:36:47 +04:00
int ret ;
DATA_BLOB blob , sys_acl_blob ;
2009-07-25 04:06:41 +04:00
struct security_descriptor * pdesc_next = NULL ;
2010-10-12 04:15:39 +04:00
struct security_descriptor * psd = NULL ;
2009-07-25 04:06:41 +04:00
uint8_t hash [ XATTR_SD_HASH_SIZE ] ;
2012-10-10 09:36:47 +04:00
uint8_t sys_acl_hash [ XATTR_SD_HASH_SIZE ] ;
2012-02-04 02:55:34 +04:00
bool chown_needed = false ;
2012-10-10 09:36:47 +04:00
char * sys_acl_description ;
2012-10-10 04:50:27 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2016-03-22 00:04:24 +03:00
bool ignore_file_system_acl = lp_parm_bool (
2017-08-18 15:41:57 +03:00
SNUM ( handle - > conn ) , module_name , " ignore system acls " , false ) ;
2020-12-16 17:37:02 +03:00
struct acl_common_fsp_ext * ext = NULL ;
2009-07-25 04:06:41 +04:00
if ( DEBUGLEVEL > = 10 ) {
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " incoming sd for file %s \n " , fsp_str_dbg ( fsp ) ) ;
2009-07-25 04:06:41 +04:00
NDR_PRINT_DEBUG ( security_descriptor ,
2011-05-06 03:19:49 +04:00
discard_const_p ( struct security_descriptor , orig_psd ) ) ;
2009-07-25 04:06:41 +04:00
}
2020-04-13 22:29:22 +03:00
status = fget_nt_acl_common ( fget_acl_blob_fn , handle , fsp ,
2010-10-12 04:15:39 +04:00
SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL ,
2012-10-10 04:50:27 +04:00
frame ,
2010-10-12 04:15:39 +04:00
& psd ) ;
2009-11-25 21:20:38 +03:00
2010-10-12 04:15:39 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-10-10 04:50:27 +04:00
TALLOC_FREE ( frame ) ;
2010-10-12 04:15:39 +04:00
return status ;
}
2009-11-25 21:20:38 +03:00
2010-11-24 01:31:43 +03:00
psd - > revision = orig_psd - > revision ;
2018-05-10 13:29:35 +03:00
if ( security_info_sent & SECINFO_DACL ) {
psd - > type = orig_psd - > type ;
/* All our SD's are self relative. */
psd - > type | = SEC_DESC_SELF_RELATIVE ;
}
2010-11-24 01:31:43 +03:00
2010-10-12 04:15:39 +04:00
if ( ( security_info_sent & SECINFO_OWNER ) & & ( orig_psd - > owner_sid ! = NULL ) ) {
2012-02-04 02:55:34 +04:00
if ( ! dom_sid_equal ( orig_psd - > owner_sid , psd - > owner_sid ) ) {
/* We're changing the owner. */
chown_needed = true ;
}
2010-10-12 04:15:39 +04:00
psd - > owner_sid = orig_psd - > owner_sid ;
}
if ( ( security_info_sent & SECINFO_GROUP ) & & ( orig_psd - > group_sid ! = NULL ) ) {
2012-02-04 02:55:34 +04:00
if ( ! dom_sid_equal ( orig_psd - > group_sid , psd - > group_sid ) ) {
/* We're changing the group. */
chown_needed = true ;
}
2010-10-12 04:15:39 +04:00
psd - > group_sid = orig_psd - > group_sid ;
}
if ( security_info_sent & SECINFO_DACL ) {
2014-11-26 20:01:37 +03:00
if ( security_descriptor_with_ms_nfs ( orig_psd ) ) {
/*
* If the sd contains a MS NFS SID , do
* nothing , it ' s a chmod ( ) request from OS X
* with AAPL context .
*/
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
}
2010-10-12 04:15:39 +04:00
psd - > dacl = orig_psd - > dacl ;
2010-11-24 01:31:43 +03:00
psd - > type | = SEC_DESC_DACL_PRESENT ;
2010-10-12 04:15:39 +04:00
}
if ( security_info_sent & SECINFO_SACL ) {
psd - > sacl = orig_psd - > sacl ;
2010-11-24 01:31:43 +03:00
psd - > type | = SEC_DESC_SACL_PRESENT ;
2009-07-25 04:06:41 +04:00
}
2020-12-16 17:37:02 +03:00
ext = VFS_ADD_FSP_EXTENSION ( handle ,
fsp ,
struct acl_common_fsp_ext ,
NULL ) ;
ext - > setting_nt_acl = true ;
2016-03-22 00:04:24 +03:00
if ( ignore_file_system_acl ) {
if ( chown_needed ) {
/* send only ownership stuff to lower layer */
security_info_sent & = ( SECINFO_OWNER | SECINFO_GROUP ) ;
status = set_underlying_acl ( handle , fsp , psd ,
security_info_sent , true ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-12-16 17:32:52 +03:00
goto done ;
2016-03-22 00:04:24 +03:00
}
2012-02-04 02:55:34 +04:00
}
2016-03-22 00:04:24 +03:00
ZERO_ARRAY ( hash ) ;
2017-08-18 15:41:57 +03:00
status = store_v3_blob ( store_acl_blob_fsp_fn , handle , fsp , psd ,
2017-08-18 14:52:31 +03:00
NULL , hash ) ;
2020-12-16 17:32:52 +03:00
goto done ;
2016-03-22 00:04:24 +03:00
}
status = set_underlying_acl ( handle , fsp , psd , security_info_sent ,
chown_needed ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-12-16 17:32:52 +03:00
goto done ;
2009-07-25 04:06:41 +04:00
}
/* Get the full underlying sd, then hash. */
status = SMB_VFS_NEXT_FGET_NT_ACL ( handle ,
2012-10-10 04:50:27 +04:00
fsp ,
HASH_SECURITY_INFO ,
frame ,
& pdesc_next ) ;
2009-07-25 04:06:41 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-12-16 17:32:52 +03:00
goto done ;
2009-07-25 04:06:41 +04:00
}
status = hash_sd_sha256 ( pdesc_next , hash ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-12-16 17:32:52 +03:00
goto done ;
2009-07-25 04:06:41 +04:00
}
2012-10-10 09:36:47 +04:00
/* Get the full underlying sd, then hash. */
ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD ( handle ,
fsp ,
frame ,
& sys_acl_description ,
& sys_acl_blob ) ;
/* If we fail to get the ACL blob (for some reason) then this
* is not fatal , we just work based on the NT ACL only */
if ( ret ! = 0 ) {
2017-08-18 15:41:57 +03:00
status = store_v3_blob ( store_acl_blob_fsp_fn , handle , fsp , psd ,
2017-08-18 14:52:31 +03:00
pdesc_next , hash ) ;
2012-10-10 09:36:47 +04:00
2020-12-16 17:32:52 +03:00
goto done ;
2012-10-10 09:36:47 +04:00
}
status = hash_blob_sha256 ( sys_acl_blob , sys_acl_hash ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-12-16 17:32:52 +03:00
goto done ;
2012-10-10 09:36:47 +04:00
}
2009-07-25 04:06:41 +04:00
if ( DEBUGLEVEL > = 10 ) {
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " storing xattr sd for file %s based on system ACL \n " ,
fsp_str_dbg ( fsp ) ) ;
2009-07-25 04:06:41 +04:00
NDR_PRINT_DEBUG ( security_descriptor ,
2012-10-10 09:36:47 +04:00
discard_const_p ( struct security_descriptor , psd ) ) ;
2012-09-10 02:43:09 +04:00
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " storing hash in xattr sd based on system ACL and: \n " ) ;
2012-09-10 02:43:09 +04:00
NDR_PRINT_DEBUG ( security_descriptor ,
2012-10-10 09:36:47 +04:00
discard_const_p ( struct security_descriptor , pdesc_next ) ) ;
2009-07-25 04:06:41 +04:00
}
2012-10-10 09:36:47 +04:00
/* We store hashes of both the sys ACL blob and the NT
2023-07-13 09:52:45 +03:00
* security descriptor mapped from that ACL so as to improve
* our chances against some inadvertent change breaking the
2012-10-10 09:36:47 +04:00
* hash used */
status = create_sys_acl_blob ( psd , & blob , XATTR_SD_HASH_TYPE_SHA256 , hash ,
sys_acl_description , sys_acl_hash ) ;
2012-05-17 07:21:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " create_sys_acl_blob failed \n " ) ;
2020-12-16 17:32:52 +03:00
goto done ;
2012-05-17 07:21:34 +04:00
}
2017-08-18 15:41:57 +03:00
status = store_acl_blob_fsp_fn ( handle , fsp , & blob ) ;
2009-07-25 04:06:41 +04:00
2020-12-16 17:32:52 +03:00
done :
2020-12-16 17:37:02 +03:00
VFS_REMOVE_FSP_EXTENSION ( handle , fsp ) ;
2012-10-10 04:50:27 +04:00
TALLOC_FREE ( frame ) ;
2012-05-15 18:47:14 +04:00
return status ;
2009-07-25 04:06:41 +04:00
}
2009-12-01 03:50:34 +03:00
2010-01-13 03:04:44 +03:00
static int acl_common_remove_object ( vfs_handle_struct * handle ,
2021-01-20 18:08:58 +03:00
struct files_struct * dirfsp ,
2017-06-29 21:29:33 +03:00
const struct smb_filename * smb_fname ,
2010-01-13 03:04:44 +03:00
bool is_directory )
{
connection_struct * conn = handle - > conn ;
struct file_id id ;
files_struct * fsp = NULL ;
int ret = 0 ;
2021-01-20 18:08:58 +03:00
struct smb_filename * full_fname = NULL ;
2020-04-28 15:15:38 +03:00
struct smb_filename * local_fname = NULL ;
struct smb_filename * parent_dir_fname = NULL ;
2010-01-13 03:04:44 +03:00
int saved_errno = 0 ;
2017-06-30 00:32:47 +03:00
struct smb_filename * saved_dir_fname = NULL ;
2021-05-26 21:00:49 +03:00
NTSTATUS status ;
2011-08-19 01:11:45 +04:00
2017-06-30 00:32:47 +03:00
saved_dir_fname = vfs_GetWd ( talloc_tos ( ) , conn ) ;
if ( saved_dir_fname = = NULL ) {
2011-08-19 01:11:45 +04:00
saved_errno = errno ;
goto out ;
}
2010-01-13 03:04:44 +03:00
2021-01-20 18:08:58 +03:00
full_fname = full_path_from_dirfsp_atname ( talloc_tos ( ) ,
dirfsp ,
smb_fname ) ;
if ( full_fname = = NULL ) {
goto out ;
}
2021-05-26 21:00:49 +03:00
status = SMB_VFS_PARENT_PATHNAME ( conn ,
talloc_tos ( ) ,
full_fname ,
& parent_dir_fname ,
& local_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
saved_errno = map_errno_from_nt_status ( status ) ;
2010-01-13 03:04:44 +03:00
goto out ;
}
2021-01-20 18:08:58 +03:00
DBG_DEBUG ( " removing %s %s \n " , is_directory ? " directory " : " file " ,
smb_fname_str_dbg ( full_fname ) ) ;
2017-06-29 21:29:33 +03:00
2010-01-13 03:04:44 +03:00
/* cd into the parent dir to pin it. */
2020-04-28 15:15:38 +03:00
ret = vfs_ChDir ( conn , parent_dir_fname ) ;
2010-01-13 03:04:44 +03:00
if ( ret = = - 1 ) {
saved_errno = errno ;
goto out ;
}
/* Must use lstat here. */
2020-04-28 15:15:38 +03:00
ret = SMB_VFS_LSTAT ( conn , local_fname ) ;
2010-01-13 03:04:44 +03:00
if ( ret = = - 1 ) {
saved_errno = errno ;
goto out ;
}
/* Ensure we have this file open with DELETE access. */
2020-04-28 15:15:38 +03:00
id = vfs_file_id_from_sbuf ( conn , & local_fname - > st ) ;
2020-11-19 13:35:23 +03:00
for ( fsp = file_find_di_first ( conn - > sconn , id , true ) ; fsp ;
fsp = file_find_di_next ( fsp , true ) ) {
2010-01-13 03:04:44 +03:00
if ( fsp - > access_mask & DELETE_ACCESS & &
2020-04-03 08:48:08 +03:00
fsp - > fsp_flags . delete_on_close )
{
2010-01-13 03:04:44 +03:00
/* We did open this for delete,
* allow the delete as root .
*/
break ;
}
}
if ( ! fsp ) {
2021-01-20 18:08:58 +03:00
DBG_DEBUG ( " %s %s not an open file \n " ,
2016-08-27 11:11:14 +03:00
is_directory ? " directory " : " file " ,
2021-01-20 18:08:58 +03:00
smb_fname_str_dbg ( full_fname ) ) ;
2010-01-13 03:04:44 +03:00
saved_errno = EACCES ;
goto out ;
}
2024-03-25 19:04:17 +03:00
become_root ( ) ;
2010-01-13 03:04:44 +03:00
if ( is_directory ) {
2019-10-05 00:25:00 +03:00
ret = SMB_VFS_NEXT_UNLINKAT ( handle ,
2021-01-20 18:08:58 +03:00
dirfsp ,
smb_fname ,
2019-10-05 00:25:00 +03:00
AT_REMOVEDIR ) ;
2010-01-13 03:04:44 +03:00
} else {
2019-09-17 03:54:00 +03:00
ret = SMB_VFS_NEXT_UNLINKAT ( handle ,
2021-01-20 18:08:58 +03:00
dirfsp ,
smb_fname ,
2019-09-17 03:54:00 +03:00
0 ) ;
2010-01-13 03:04:44 +03:00
}
2024-03-25 19:04:17 +03:00
unbecome_root ( ) ;
2010-01-17 04:03:06 +03:00
2010-01-13 03:04:44 +03:00
if ( ret = = - 1 ) {
saved_errno = errno ;
}
out :
2020-04-28 15:15:38 +03:00
TALLOC_FREE ( parent_dir_fname ) ;
2021-01-20 18:08:58 +03:00
TALLOC_FREE ( full_fname ) ;
2010-01-13 03:04:44 +03:00
2017-06-30 00:32:47 +03:00
if ( saved_dir_fname ) {
vfs_ChDir ( conn , saved_dir_fname ) ;
TALLOC_FREE ( saved_dir_fname ) ;
2011-08-19 01:11:45 +04:00
}
2010-01-13 03:04:44 +03:00
if ( saved_errno ) {
errno = saved_errno ;
}
return ret ;
}
2017-08-18 15:41:57 +03:00
int rmdir_acl_common ( struct vfs_handle_struct * handle ,
2019-10-05 00:34:41 +03:00
struct files_struct * dirfsp ,
const struct smb_filename * smb_fname )
2010-01-13 03:04:44 +03:00
{
int ret ;
2012-01-11 00:52:01 +04:00
/* Try the normal rmdir first. */
2019-10-05 00:37:01 +03:00
ret = SMB_VFS_NEXT_UNLINKAT ( handle ,
dirfsp ,
smb_fname ,
AT_REMOVEDIR ) ;
2012-01-11 00:52:01 +04:00
if ( ret = = 0 ) {
return 0 ;
}
if ( errno = = EACCES | | errno = = EPERM ) {
/* Failed due to access denied,
see if we need to root override . */
return acl_common_remove_object ( handle ,
2021-01-20 18:08:58 +03:00
dirfsp ,
2017-06-29 21:29:33 +03:00
smb_fname ,
2012-01-11 00:52:01 +04:00
true ) ;
2010-01-13 03:04:44 +03:00
}
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " unlink of %s failed %s \n " ,
smb_fname - > base_name ,
strerror ( errno ) ) ;
2012-01-11 00:52:01 +04:00
return - 1 ;
2010-01-13 03:04:44 +03:00
}
2017-08-18 15:41:57 +03:00
int unlink_acl_common ( struct vfs_handle_struct * handle ,
2019-09-17 03:50:17 +03:00
struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
int flags )
2010-01-13 03:04:44 +03:00
{
int ret ;
2012-01-11 00:52:01 +04:00
/* Try the normal unlink first. */
2019-09-17 03:54:00 +03:00
ret = SMB_VFS_NEXT_UNLINKAT ( handle ,
dirfsp ,
smb_fname ,
flags ) ;
2012-01-11 00:52:01 +04:00
if ( ret = = 0 ) {
return 0 ;
2010-01-13 03:04:44 +03:00
}
2012-01-11 00:52:01 +04:00
if ( errno = = EACCES | | errno = = EPERM ) {
/* Failed due to access denied,
see if we need to root override . */
2010-01-13 03:04:44 +03:00
2012-01-11 00:52:01 +04:00
/* Don't do anything fancy for streams. */
if ( smb_fname - > stream_name ) {
return - 1 ;
}
return acl_common_remove_object ( handle ,
2021-01-20 18:08:58 +03:00
dirfsp ,
2017-06-29 21:29:33 +03:00
smb_fname ,
2010-01-13 03:04:44 +03:00
false ) ;
2012-01-11 00:52:01 +04:00
}
2016-08-27 11:11:14 +03:00
DBG_DEBUG ( " unlink of %s failed %s \n " ,
smb_fname - > base_name ,
strerror ( errno ) ) ;
2012-01-11 00:52:01 +04:00
return - 1 ;
2010-01-13 03:04:44 +03:00
}
2011-04-02 03:50:28 +04:00
2017-08-18 15:41:57 +03:00
int fchmod_acl_module_common ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , mode_t mode )
2011-04-02 03:50:28 +04:00
{
2021-04-07 18:02:15 +03:00
if ( fsp - > posix_flags & FSP_POSIX_FLAGS_PATHNAMES
| | fsp - > fsp_name - > flags & SMB_FILENAME_POSIX_PATH ) {
2011-04-02 03:50:28 +04:00
/* Only allow this on POSIX opens. */
return SMB_VFS_NEXT_FCHMOD ( handle , fsp , mode ) ;
}
return 0 ;
}