2012-08-15 14:34:41 +04:00
/*
* Fake ACLs VFS module . Implements passthrough operation of all VFS
* calls to disk functions , except for file ownership and ACLs , which
* are stored in xattrs .
*
* Copyright ( C ) Tim Potter , 1999 - 2000
* Copyright ( C ) Alexander Bokovoy , 2002
* Copyright ( C ) Andrew Bartlett , 2002 , 2012
*
* 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"
# include "smbd/smbd.h"
# include "system/filesys.h"
# include "auth.h"
# include "librpc/gen_ndr/ndr_smb_acl.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2012-08-20 04:10:27 +04:00
# define FAKE_UID "system.fake_uid"
# define FAKE_GID "system.fake_gid"
# define FAKE_ACL_ACCESS_XATTR "system.fake_access_acl"
# define FAKE_ACL_DEFAULT_XATTR "system.fake_default_acl"
2012-08-15 14:34:41 +04:00
2021-06-29 02:48:51 +03:00
struct in_pathref_data {
bool calling_pathref_fsp ;
} ;
2012-08-15 14:34:41 +04:00
static int fake_acls_fuid ( vfs_handle_struct * handle ,
files_struct * fsp ,
uid_t * uid )
{
ssize_t size ;
uint8_t uid_buf [ 4 ] ;
size = SMB_VFS_NEXT_FGETXATTR ( handle , fsp , FAKE_UID , uid_buf , sizeof ( uid_buf ) ) ;
2024-07-08 20:37:01 +03:00
if ( size = = - 1 & & ( ( errno = = ENOATTR ) | | ( errno = = EBADF ) ) ) {
2012-08-15 14:34:41 +04:00
return 0 ;
}
if ( size ! = 4 ) {
return - 1 ;
}
* uid = IVAL ( uid_buf , 0 ) ;
return 0 ;
}
static int fake_acls_fgid ( vfs_handle_struct * handle ,
files_struct * fsp ,
uid_t * gid )
{
ssize_t size ;
uint8_t gid_buf [ 4 ] ;
size = SMB_VFS_NEXT_FGETXATTR ( handle , fsp , FAKE_GID , gid_buf , sizeof ( gid_buf ) ) ;
2024-07-08 20:37:01 +03:00
if ( size = = - 1 & & ( ( errno = = ENOATTR ) | | ( errno = = EBADF ) ) ) {
2012-08-15 14:34:41 +04:00
return 0 ;
}
if ( size ! = 4 ) {
return - 1 ;
}
* gid = IVAL ( gid_buf , 0 ) ;
return 0 ;
}
static int fake_acls_stat ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
{
int ret = - 1 ;
2021-06-29 02:48:51 +03:00
struct in_pathref_data * prd = NULL ;
2022-01-18 19:55:04 +03:00
struct smb_filename * smb_fname_cp = NULL ;
struct files_struct * fsp = NULL ;
2021-06-29 02:48:51 +03:00
SMB_VFS_HANDLE_GET_DATA ( handle ,
prd ,
struct in_pathref_data ,
return - 1 ) ;
2012-08-15 14:34:41 +04:00
ret = SMB_VFS_NEXT_STAT ( handle , smb_fname ) ;
2022-01-18 19:55:04 +03:00
if ( ret ! = 0 ) {
return ret ;
}
2021-06-29 02:48:51 +03:00
2022-01-18 19:55:04 +03:00
if ( smb_fname - > fsp ! = NULL ) {
2022-02-11 11:45:30 +03:00
fsp = metadata_fsp ( smb_fname - > fsp ) ;
2022-01-18 19:55:04 +03:00
} else {
NTSTATUS status ;
2021-06-29 02:48:51 +03:00
2022-01-18 19:55:04 +03:00
/*
* Ensure openat_pathref_fsp ( )
* can ' t recurse into fake_acls_stat ( ) .
* openat_pathref_fsp ( ) doesn ' t care
* about the uid / gid values , it only
* wants a valid / invalid stat answer
* and we know smb_fname exists as
* the SMB_VFS_NEXT_STAT ( ) returned
* zero above .
*/
if ( prd - > calling_pathref_fsp ) {
return 0 ;
2021-06-23 05:10:37 +03:00
}
2021-06-23 05:05:06 +03:00
2022-01-18 19:55:04 +03:00
/*
* openat_pathref_fsp ( ) expects a talloc ' ed
* smb_filename . stat can be passed a struct
* from the stack . Make a talloc ' ed copy
* so openat_pathref_fsp ( ) can add its
* destructor .
*/
smb_fname_cp = cp_smb_filename ( talloc_tos ( ) ,
smb_fname ) ;
if ( smb_fname_cp = = NULL ) {
errno = ENOMEM ;
return - 1 ;
2012-08-15 14:34:41 +04:00
}
2022-01-18 19:55:04 +03:00
/* Recursion guard. */
prd - > calling_pathref_fsp = true ;
status = openat_pathref_fsp ( handle - > conn - > cwd_fsp ,
smb_fname_cp ) ;
/* End recursion guard. */
prd - > calling_pathref_fsp = false ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/*
* Ignore errors here . We know
* the path exists ( the SMB_VFS_NEXT_STAT ( )
* above succeeded . So being unable to
* open a pathref fsp can be due to a
* range of errors ( startup path beginning
* with ' / ' for example , path = " .. " when
* enumerating a directory . Just treat this
* the same way as the path not having the
* FAKE_UID or FAKE_GID EA ' s present . For the
* test purposes of this module ( fake NT ACLs
* from windows clients ) this is close enough .
* Just report for debugging purposes .
*/
DBG_DEBUG ( " Unable to get pathref fsp on %s. "
" Error %s \n " ,
smb_fname_str_dbg ( smb_fname_cp ) ,
nt_errstr ( status ) ) ;
2021-06-23 20:43:51 +03:00
TALLOC_FREE ( smb_fname_cp ) ;
2022-01-18 19:55:04 +03:00
return 0 ;
2012-08-15 14:34:41 +04:00
}
2022-01-18 19:55:04 +03:00
fsp = smb_fname_cp - > fsp ;
2012-08-15 14:34:41 +04:00
}
2022-01-18 19:55:04 +03:00
ret = fake_acls_fuid ( handle ,
fsp ,
& smb_fname - > st . st_ex_uid ) ;
if ( ret ! = 0 ) {
TALLOC_FREE ( smb_fname_cp ) ;
return ret ;
}
ret = fake_acls_fgid ( handle ,
fsp ,
& smb_fname - > st . st_ex_gid ) ;
if ( ret ! = 0 ) {
TALLOC_FREE ( smb_fname_cp ) ;
return ret ;
}
TALLOC_FREE ( smb_fname_cp ) ;
2012-08-15 14:34:41 +04:00
return ret ;
}
2012-08-20 15:28:57 +04:00
static int fake_acls_lstat ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
{
int ret = - 1 ;
2021-06-29 02:48:51 +03:00
struct in_pathref_data * prd = NULL ;
SMB_VFS_HANDLE_GET_DATA ( handle ,
prd ,
struct in_pathref_data ,
return - 1 ) ;
2012-08-20 15:28:57 +04:00
ret = SMB_VFS_NEXT_LSTAT ( handle , smb_fname ) ;
if ( ret = = 0 ) {
2021-06-23 20:27:13 +03:00
struct smb_filename * smb_fname_base = NULL ;
SMB_STRUCT_STAT sbuf = { 0 } ;
NTSTATUS status ;
2021-06-29 02:48:51 +03:00
/*
* Ensure synthetic_pathref ( )
* can ' t recurse into fake_acls_lstat ( ) .
* synthetic_pathref ( ) doesn ' t care
* about the uid / gid values , it only
* wants a valid / invalid stat answer
* and we know smb_fname exists as
* the SMB_VFS_NEXT_LSTAT ( ) returned
* zero above .
*/
if ( prd - > calling_pathref_fsp ) {
2021-06-23 20:27:13 +03:00
return 0 ;
}
/* Recursion guard. */
2021-06-29 02:48:51 +03:00
prd - > calling_pathref_fsp = true ;
2021-06-23 20:27:13 +03:00
status = synthetic_pathref ( talloc_tos ( ) ,
handle - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
& sbuf ,
smb_fname - > twrp ,
0 , /* we want stat, not lstat. */
& smb_fname_base ) ;
/* End recursion guard. */
2021-06-29 02:48:51 +03:00
prd - > calling_pathref_fsp = false ;
2021-06-23 20:27:13 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
/*
* This isn ' t quite right ( calling fgetxattr not
* lgetxattr ) , but for the test purposes of this
* module ( fake NT ACLs from windows clients ) , it is
* close enough . We removed the l * xattr functions
* because linux doesn ' t support using them , but we
* could fake them in xattr_tdb if we really wanted
* to . We ignore errors because the link might not
* point anywhere */
fake_acls_fuid ( handle ,
smb_fname_base - > fsp ,
& smb_fname - > st . st_ex_uid ) ;
fake_acls_fgid ( handle ,
smb_fname_base - > fsp ,
& smb_fname - > st . st_ex_gid ) ;
}
TALLOC_FREE ( smb_fname_base ) ;
2012-08-20 15:28:57 +04:00
}
return ret ;
}
2012-08-15 14:34:41 +04:00
static int fake_acls_fstat ( vfs_handle_struct * handle , files_struct * fsp , SMB_STRUCT_STAT * sbuf )
{
int ret = - 1 ;
ret = SMB_VFS_NEXT_FSTAT ( handle , fsp , sbuf ) ;
if ( ret = = 0 ) {
ret = fake_acls_fuid ( handle , fsp , & sbuf - > st_ex_uid ) ;
if ( ret ! = 0 ) {
return ret ;
}
ret = fake_acls_fgid ( handle , fsp , & sbuf - > st_ex_gid ) ;
if ( ret ! = 0 ) {
return ret ;
}
}
return ret ;
}
2012-10-10 03:18:32 +04:00
static SMB_ACL_T fake_acls_blob2acl ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx )
2012-08-15 14:34:41 +04:00
{
enum ndr_err_code ndr_err ;
2012-10-10 03:18:32 +04:00
struct smb_acl_t * acl = talloc ( mem_ctx , struct smb_acl_t ) ;
2012-08-15 14:34:41 +04:00
if ( ! acl ) {
errno = ENOMEM ;
return NULL ;
}
ndr_err = ndr_pull_struct_blob ( blob , acl , acl ,
( ndr_pull_flags_fn_t ) ndr_pull_smb_acl_t ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " ndr_pull_acl_t failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ) ;
TALLOC_FREE ( acl ) ;
return NULL ;
}
return acl ;
}
static DATA_BLOB fake_acls_acl2blob ( TALLOC_CTX * mem_ctx , SMB_ACL_T acl )
{
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , acl ,
( ndr_push_flags_fn_t ) ndr_push_smb_acl_t ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " ndr_push_acl_t failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ) ;
return data_blob_null ;
}
return blob ;
}
2012-10-10 03:18:32 +04:00
static SMB_ACL_T fake_acls_sys_acl_get_fd ( struct vfs_handle_struct * handle ,
files_struct * fsp ,
2021-05-14 17:26:46 +03:00
SMB_ACL_TYPE_T type ,
2012-10-10 03:18:32 +04:00
TALLOC_CTX * mem_ctx )
2012-08-15 14:34:41 +04:00
{
DATA_BLOB blob = data_blob_null ;
ssize_t length ;
2021-05-14 17:26:46 +03:00
const char * name = NULL ;
2012-09-23 00:33:02 +04:00
struct smb_acl_t * acl = NULL ;
2012-08-15 14:34:41 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2021-05-14 17:26:46 +03:00
switch ( type ) {
case SMB_ACL_TYPE_ACCESS :
name = FAKE_ACL_ACCESS_XATTR ;
break ;
case SMB_ACL_TYPE_DEFAULT :
name = FAKE_ACL_DEFAULT_XATTR ;
break ;
default :
DBG_ERR ( " Illegal ACL type %d \n " , ( int ) type ) ;
break ;
}
if ( name = = NULL ) {
TALLOC_FREE ( frame ) ;
return NULL ;
}
2012-08-15 14:34:41 +04:00
do {
blob . length + = 1000 ;
blob . data = talloc_realloc ( frame , blob . data , uint8_t , blob . length ) ;
if ( ! blob . data ) {
errno = ENOMEM ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
length = SMB_VFS_NEXT_FGETXATTR ( handle , fsp , name , blob . data , blob . length ) ;
blob . length = length ;
} while ( length = = - 1 & & errno = = ERANGE ) ;
2024-07-08 20:37:01 +03:00
if ( length = = - 1 & & ( ( errno = = ENOATTR ) | | ( errno = = EBADF ) ) ) {
2012-08-15 14:34:41 +04:00
TALLOC_FREE ( frame ) ;
return NULL ;
}
if ( length ! = - 1 ) {
2012-10-10 03:18:32 +04:00
acl = fake_acls_blob2acl ( & blob , mem_ctx ) ;
2012-08-15 14:34:41 +04:00
}
TALLOC_FREE ( frame ) ;
return acl ;
}
2020-12-14 18:28:26 +03:00
static int fake_acls_sys_acl_set_fd ( vfs_handle_struct * handle ,
struct files_struct * fsp ,
SMB_ACL_TYPE_T type ,
SMB_ACL_T theacl )
2012-08-15 14:34:41 +04:00
{
int ret ;
2020-12-13 11:18:00 +03:00
const char * name = NULL ;
2012-08-15 14:34:41 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
DATA_BLOB blob = fake_acls_acl2blob ( frame , theacl ) ;
if ( ! blob . data ) {
DEBUG ( 0 , ( " Failed to convert ACL to linear blob for xattr storage \n " ) ) ;
TALLOC_FREE ( frame ) ;
errno = EINVAL ;
return - 1 ;
}
2020-12-13 11:18:00 +03:00
switch ( type ) {
case SMB_ACL_TYPE_ACCESS :
name = FAKE_ACL_ACCESS_XATTR ;
break ;
case SMB_ACL_TYPE_DEFAULT :
name = FAKE_ACL_DEFAULT_XATTR ;
break ;
default :
errno = EINVAL ;
return - 1 ;
}
2012-08-15 14:34:41 +04:00
ret = SMB_VFS_NEXT_FSETXATTR ( handle , fsp , name , blob . data , blob . length , 0 ) ;
TALLOC_FREE ( frame ) ;
return ret ;
}
2021-05-15 00:39:12 +03:00
static int fake_acls_sys_acl_delete_def_fd ( vfs_handle_struct * handle ,
struct files_struct * fsp )
{
int ret ;
const char * name = FAKE_ACL_DEFAULT_XATTR ;
if ( ! fsp - > fsp_flags . is_directory ) {
errno = EINVAL ;
return - 1 ;
}
ret = SMB_VFS_NEXT_FREMOVEXATTR ( handle , fsp , name ) ;
2024-07-08 20:37:01 +03:00
if ( ret = = - 1 & & ( ( errno = = ENOATTR ) | | ( errno = = EBADF ) ) ) {
2021-05-15 00:39:12 +03:00
ret = 0 ;
errno = 0 ;
}
return ret ;
}
2016-03-04 01:34:57 +03:00
static int fake_acls_lchown ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uid_t uid ,
gid_t gid )
2012-08-20 15:28:57 +04:00
{
int ret ;
uint8_t id_buf [ 4 ] ;
if ( uid ! = - 1 ) {
2017-10-06 16:25:54 +03:00
uid_t current_uid = get_current_uid ( handle - > conn ) ;
if ( current_uid ! = 0 & & current_uid ! = uid ) {
return EACCES ;
}
2012-08-20 15:28:57 +04:00
/* This isn't quite right (calling setxattr not
* lsetxattr ) , but for the test purposes of this
* module ( fake NT ACLs from windows clients ) , it is
* close enough . We removed the l * xattr functions
* because linux doesn ' t support using them , but we
* could fake them in xattr_tdb if we really wanted
* to .
*/
SIVAL ( id_buf , 0 , uid ) ;
2021-02-19 19:21:58 +03:00
ret = SMB_VFS_NEXT_FSETXATTR ( handle ,
smb_fname - > fsp ,
2016-03-04 01:34:57 +03:00
FAKE_UID ,
id_buf ,
sizeof ( id_buf ) ,
0 ) ;
2012-08-20 15:28:57 +04:00
if ( ret ! = 0 ) {
return ret ;
}
}
if ( gid ! = - 1 ) {
SIVAL ( id_buf , 0 , gid ) ;
2021-02-19 19:21:58 +03:00
ret = SMB_VFS_NEXT_FSETXATTR ( handle ,
smb_fname - > fsp ,
2016-03-04 01:34:57 +03:00
FAKE_GID ,
id_buf ,
sizeof ( id_buf ) ,
0 ) ;
2012-08-20 15:28:57 +04:00
if ( ret ! = 0 ) {
return ret ;
}
}
return 0 ;
}
2012-08-15 14:34:41 +04:00
static int fake_acls_fchown ( vfs_handle_struct * handle , files_struct * fsp , uid_t uid , gid_t gid )
{
int ret ;
uint8_t id_buf [ 4 ] ;
if ( uid ! = - 1 ) {
2017-10-06 16:25:54 +03:00
uid_t current_uid = get_current_uid ( handle - > conn ) ;
if ( current_uid ! = 0 & & current_uid ! = uid ) {
return EACCES ;
}
2012-08-15 14:34:41 +04:00
SIVAL ( id_buf , 0 , uid ) ;
ret = SMB_VFS_NEXT_FSETXATTR ( handle , fsp , FAKE_UID , id_buf , sizeof ( id_buf ) , 0 ) ;
if ( ret ! = 0 ) {
return ret ;
}
}
if ( gid ! = - 1 ) {
SIVAL ( id_buf , 0 , gid ) ;
ret = SMB_VFS_NEXT_FSETXATTR ( handle , fsp , FAKE_GID , id_buf , sizeof ( id_buf ) , 0 ) ;
if ( ret ! = 0 ) {
return ret ;
}
}
return 0 ;
}
2018-05-18 21:52:23 +03:00
/*
* Implement the chmod uid / mask / other mode changes on a fake ACL .
*/
static int fake_acl_process_chmod ( SMB_ACL_T * pp_the_acl ,
uid_t owner ,
mode_t mode )
{
bool got_mask = false ;
int entry_id = SMB_ACL_FIRST_ENTRY ;
mode_t umode = 0 ;
mode_t mmode = 0 ;
mode_t omode = 0 ;
int ret = - 1 ;
SMB_ACL_T the_acl = * pp_the_acl ;
/* Split the mode into u/mask/other masks. */
umode = unix_perms_to_acl_perms ( mode , S_IRUSR , S_IWUSR , S_IXUSR ) ;
mmode = unix_perms_to_acl_perms ( mode , S_IRGRP , S_IWGRP , S_IXGRP ) ;
omode = unix_perms_to_acl_perms ( mode , S_IROTH , S_IWOTH , S_IXOTH ) ;
while ( 1 ) {
SMB_ACL_ENTRY_T entry ;
SMB_ACL_TAG_T tagtype ;
SMB_ACL_PERMSET_T permset ;
uid_t * puid = NULL ;
ret = sys_acl_get_entry ( the_acl ,
entry_id ,
& entry ) ;
if ( ret = = 0 ) {
/* End of ACL */
break ;
}
if ( ret = = - 1 ) {
return - 1 ;
}
ret = sys_acl_get_tag_type ( entry , & tagtype ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
ret = sys_acl_get_permset ( entry , & permset ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
switch ( tagtype ) {
case SMB_ACL_USER_OBJ :
2018-11-10 01:13:47 +03:00
ret = map_acl_perms_to_permset ( umode , & permset ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
2018-05-18 21:52:23 +03:00
break ;
case SMB_ACL_USER :
puid = ( uid_t * ) sys_acl_get_qualifier ( entry ) ;
if ( puid = = NULL ) {
return - 1 ;
}
if ( owner ! = * puid ) {
break ;
}
2018-11-10 01:13:47 +03:00
ret = map_acl_perms_to_permset ( umode , & permset ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
2018-05-18 21:52:23 +03:00
break ;
case SMB_ACL_GROUP_OBJ :
case SMB_ACL_GROUP :
/* Ignore all group entries. */
break ;
case SMB_ACL_MASK :
2018-11-10 01:13:47 +03:00
ret = map_acl_perms_to_permset ( mmode , & permset ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
2018-05-18 21:52:23 +03:00
got_mask = true ;
break ;
case SMB_ACL_OTHER :
2018-11-10 01:13:47 +03:00
ret = map_acl_perms_to_permset ( omode , & permset ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
2018-05-18 21:52:23 +03:00
break ;
default :
errno = EINVAL ;
return - 1 ;
}
ret = sys_acl_set_permset ( entry , permset ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
/* Move to next entry. */
entry_id = SMB_ACL_NEXT_ENTRY ;
}
/*
* If we didn ' t see a mask entry , add one .
*/
if ( ! got_mask ) {
SMB_ACL_ENTRY_T mask_entry ;
2023-10-06 04:58:34 +03:00
uint32_t mask_perm = 0 ;
SMB_ACL_PERMSET_T mask_permset = & mask_perm ;
2018-05-18 21:52:23 +03:00
ret = sys_acl_create_entry ( & the_acl , & mask_entry ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
2018-11-10 01:13:47 +03:00
ret = map_acl_perms_to_permset ( mmode , & mask_permset ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
2018-05-18 21:52:23 +03:00
ret = sys_acl_set_permset ( mask_entry , mask_permset ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
ret = sys_acl_set_tag_type ( mask_entry , SMB_ACL_MASK ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
/* In case we were realloced and moved. */
* pp_the_acl = the_acl ;
}
return 0 ;
}
static int fake_acls_fchmod ( vfs_handle_struct * handle ,
files_struct * fsp ,
mode_t mode )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
int ret = - 1 ;
SMB_ACL_T the_acl = NULL ;
/*
* Passthrough first to preserve the
* S_ISUID | S_ISGID | S_ISVTX
* bits .
*/
ret = SMB_VFS_NEXT_FCHMOD ( handle ,
fsp ,
mode ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( frame ) ;
return - 1 ;
}
the_acl = fake_acls_sys_acl_get_fd ( handle ,
fsp ,
2021-05-14 17:26:46 +03:00
SMB_ACL_TYPE_ACCESS ,
2018-05-18 21:52:23 +03:00
talloc_tos ( ) ) ;
if ( the_acl = = NULL ) {
TALLOC_FREE ( frame ) ;
2024-07-08 20:37:01 +03:00
if ( ( ( errno = = ENOATTR ) | | ( errno = = EBADF ) ) ) {
2018-05-18 21:52:23 +03:00
/* No ACL on this file. Just passthrough. */
return 0 ;
}
return - 1 ;
}
ret = fake_acl_process_chmod ( & the_acl ,
fsp - > fsp_name - > st . st_ex_uid ,
mode ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( frame ) ;
return - 1 ;
}
ret = fake_acls_sys_acl_set_fd ( handle ,
fsp ,
2020-12-14 18:28:26 +03:00
SMB_ACL_TYPE_ACCESS ,
2018-05-18 21:52:23 +03:00
the_acl ) ;
TALLOC_FREE ( frame ) ;
return ret ;
}
2012-08-15 14:34:41 +04:00
2021-06-29 02:48:51 +03:00
static int fake_acls_connect ( struct vfs_handle_struct * handle ,
const char * service ,
const char * user )
{
struct in_pathref_data * prd = NULL ;
int ret ;
ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( ret < 0 ) {
return ret ;
}
/*
* Create a struct can tell us if we ' re recursing
2021-11-25 18:52:41 +03:00
* into openat_pathref_fsp ( ) in this module . This will
2021-06-29 02:48:51 +03:00
* go away once we have SMB_VFS_STATX ( ) and we will
* have a way for a caller to as for specific stat
* fields in a granular way . Then we will know exactly
* what fields the caller wants , so we won ' t have to
* fill in everything .
*/
prd = talloc_zero ( handle - > conn , struct in_pathref_data ) ;
if ( prd = = NULL ) {
return - 1 ;
}
SMB_VFS_HANDLE_SET_DATA ( handle ,
prd ,
NULL ,
struct in_pathref_data ,
return - 1 ) ;
return 0 ;
}
2012-08-15 14:34:41 +04:00
static struct vfs_fn_pointers vfs_fake_acls_fns = {
2021-06-29 02:48:51 +03:00
. connect_fn = fake_acls_connect ,
2012-08-15 14:34:41 +04:00
. stat_fn = fake_acls_stat ,
2012-08-20 15:28:57 +04:00
. lstat_fn = fake_acls_lstat ,
2012-08-15 14:34:41 +04:00
. fstat_fn = fake_acls_fstat ,
2018-05-18 21:52:23 +03:00
. fchmod_fn = fake_acls_fchmod ,
2012-08-15 14:34:41 +04:00
. sys_acl_get_fd_fn = fake_acls_sys_acl_get_fd ,
2012-10-10 09:53:43 +04:00
. sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd ,
2012-08-15 14:34:41 +04:00
. sys_acl_set_fd_fn = fake_acls_sys_acl_set_fd ,
2021-05-15 00:39:12 +03:00
. sys_acl_delete_def_fd_fn = fake_acls_sys_acl_delete_def_fd ,
2012-08-20 15:28:57 +04:00
. lchown_fn = fake_acls_lchown ,
2012-08-15 14:34:41 +04:00
. fchown_fn = fake_acls_fchown ,
} ;
2017-12-16 01:32:12 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_fake_acls_init ( TALLOC_CTX * ctx )
2012-08-15 14:34:41 +04:00
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " fake_acls " ,
& vfs_fake_acls_fns ) ;
}