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
static int fake_acls_uid ( vfs_handle_struct * handle ,
2017-05-26 02:42:04 +03:00
struct smb_filename * smb_fname ,
2012-08-15 14:34:41 +04:00
uid_t * uid )
{
ssize_t size ;
uint8_t uid_buf [ 4 ] ;
2017-05-26 02:42:04 +03:00
size = SMB_VFS_NEXT_GETXATTR ( handle , smb_fname ,
FAKE_UID , uid_buf , sizeof ( uid_buf ) ) ;
2012-08-15 14:34:41 +04:00
if ( size = = - 1 & & errno = = ENOATTR ) {
return 0 ;
}
if ( size ! = 4 ) {
return - 1 ;
}
* uid = IVAL ( uid_buf , 0 ) ;
return 0 ;
}
static int fake_acls_gid ( vfs_handle_struct * handle ,
2017-05-26 02:42:04 +03:00
struct smb_filename * smb_fname ,
2012-08-15 14:34:41 +04:00
uid_t * gid )
{
ssize_t size ;
uint8_t gid_buf [ 4 ] ;
2017-05-26 02:42:04 +03:00
size = SMB_VFS_NEXT_GETXATTR ( handle , smb_fname ,
FAKE_GID , gid_buf , sizeof ( gid_buf ) ) ;
2012-08-15 14:34:41 +04:00
if ( size = = - 1 & & errno = = ENOATTR ) {
return 0 ;
}
if ( size ! = 4 ) {
return - 1 ;
}
* gid = IVAL ( gid_buf , 0 ) ;
return 0 ;
}
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 ) ) ;
if ( size = = - 1 & & errno = = ENOATTR ) {
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 ) ) ;
if ( size = = - 1 & & errno = = ENOATTR ) {
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 ;
ret = SMB_VFS_NEXT_STAT ( handle , smb_fname ) ;
if ( ret = = 0 ) {
TALLOC_CTX * frame = talloc_stackframe ( ) ;
char * path ;
2015-05-05 05:56:39 +03:00
struct smb_filename smb_fname_base = {
. base_name = smb_fname - > base_name
} ;
2012-08-15 14:34:41 +04:00
NTSTATUS status ;
2015-05-05 05:56:39 +03:00
/*
* As we ' re calling getxattr directly here
* we need to use only the base_name , not
* the full name containing any stream name .
*/
status = get_full_smb_filename ( frame , & smb_fname_base , & path ) ;
2012-08-15 14:34:41 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2017-05-26 02:42:04 +03:00
ret = fake_acls_uid ( handle , & smb_fname_base ,
& smb_fname - > st . st_ex_uid ) ;
2012-08-15 14:34:41 +04:00
if ( ret ! = 0 ) {
TALLOC_FREE ( frame ) ;
return ret ;
}
2017-05-26 02:42:04 +03:00
ret = fake_acls_gid ( handle , & smb_fname_base ,
& smb_fname - > st . st_ex_gid ) ;
2012-08-15 14:34:41 +04:00
if ( ret ! = 0 ) {
TALLOC_FREE ( frame ) ;
return ret ;
}
TALLOC_FREE ( frame ) ;
}
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 ;
ret = SMB_VFS_NEXT_LSTAT ( handle , smb_fname ) ;
if ( ret = = 0 ) {
TALLOC_CTX * frame = talloc_stackframe ( ) ;
char * path ;
2015-05-05 05:56:39 +03:00
struct smb_filename smb_fname_base = {
. base_name = smb_fname - > base_name
} ;
2012-08-20 15:28:57 +04:00
NTSTATUS status ;
2015-05-05 05:56:39 +03:00
/*
* As we ' re calling getxattr directly here
* we need to use only the base_name , not
* the full name containing any stream name .
*/
status = get_full_smb_filename ( frame , & smb_fname_base , & path ) ;
2012-08-20 15:28:57 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
/* This isn't quite right (calling getxattr 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 */
2017-05-26 02:42:04 +03:00
fake_acls_uid ( handle , & smb_fname_base ,
& smb_fname - > st . st_ex_uid ) ;
fake_acls_gid ( handle , & smb_fname_base ,
& smb_fname - > st . st_ex_gid ) ;
2012-08-20 15:28:57 +04:00
TALLOC_FREE ( frame ) ;
}
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_file ( struct vfs_handle_struct * handle ,
2017-05-24 03:11:18 +03:00
const struct smb_filename * smb_fname ,
SMB_ACL_TYPE_T type ,
TALLOC_CTX * mem_ctx )
2012-08-15 14:34:41 +04:00
{
DATA_BLOB blob = data_blob_null ;
ssize_t length ;
const char * name = NULL ;
struct smb_acl_t * acl = NULL ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
switch ( type ) {
case SMB_ACL_TYPE_ACCESS :
name = FAKE_ACL_ACCESS_XATTR ;
break ;
case SMB_ACL_TYPE_DEFAULT :
name = FAKE_ACL_DEFAULT_XATTR ;
break ;
}
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 ;
}
2017-05-26 02:42:04 +03:00
length = SMB_VFS_NEXT_GETXATTR ( handle , smb_fname ,
name , blob . data , blob . length ) ;
2012-08-15 14:34:41 +04:00
blob . length = length ;
} while ( length = = - 1 & & errno = = ERANGE ) ;
if ( length = = - 1 & & errno = = ENOATTR ) {
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 ;
}
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 ,
TALLOC_CTX * mem_ctx )
2012-08-15 14:34:41 +04:00
{
DATA_BLOB blob = data_blob_null ;
ssize_t length ;
const char * name = FAKE_ACL_ACCESS_XATTR ;
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 ( ) ;
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 ) ;
if ( length = = - 1 & & errno = = ENOATTR ) {
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 ;
}
2012-09-10 06:44:01 +04:00
2017-05-24 20:47:46 +03:00
static int fake_acls_sys_acl_set_file ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
SMB_ACL_TYPE_T acltype ,
SMB_ACL_T theacl )
2012-08-15 14:34:41 +04:00
{
int ret ;
const char * name = NULL ;
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 ;
}
switch ( acltype ) {
case SMB_ACL_TYPE_ACCESS :
name = FAKE_ACL_ACCESS_XATTR ;
break ;
case SMB_ACL_TYPE_DEFAULT :
name = FAKE_ACL_DEFAULT_XATTR ;
break ;
}
2017-05-25 22:41:31 +03:00
ret = SMB_VFS_NEXT_SETXATTR ( handle , smb_fname ,
2017-05-24 20:47:46 +03:00
name , blob . data , blob . length , 0 ) ;
2012-08-15 14:34:41 +04:00
TALLOC_FREE ( frame ) ;
return ret ;
}
static int fake_acls_sys_acl_set_fd ( vfs_handle_struct * handle , files_struct * fsp , SMB_ACL_T theacl )
{
int ret ;
const char * name = FAKE_ACL_ACCESS_XATTR ;
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 ;
}
ret = SMB_VFS_NEXT_FSETXATTR ( handle , fsp , name , blob . data , blob . length , 0 ) ;
TALLOC_FREE ( frame ) ;
return ret ;
}
2017-05-24 01:33:31 +03:00
static int fake_acls_sys_acl_delete_def_file ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname_in )
2012-08-15 14:34:41 +04:00
{
2012-08-18 18:01:57 +04:00
int ret ;
2012-08-15 14:34:41 +04:00
const char * name = FAKE_ACL_DEFAULT_XATTR ;
2012-08-18 18:01:57 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2017-05-24 01:33:31 +03:00
struct smb_filename * smb_fname = cp_smb_filename_nostream ( talloc_tos ( ) ,
smb_fname_in ) ;
2013-04-12 13:22:23 +04:00
if ( smb_fname = = NULL ) {
2012-08-18 18:01:57 +04:00
TALLOC_FREE ( frame ) ;
2013-04-12 13:22:23 +04:00
errno = ENOMEM ;
2012-08-18 18:01:57 +04:00
return - 1 ;
}
ret = SMB_VFS_NEXT_STAT ( handle , smb_fname ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( frame ) ;
return - 1 ;
}
if ( ! S_ISDIR ( smb_fname - > st . st_ex_mode ) ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2017-05-24 21:35:50 +03:00
ret = SMB_VFS_NEXT_REMOVEXATTR ( handle , smb_fname , name ) ;
2012-08-18 18:01:57 +04:00
if ( ret = = - 1 & & errno = = ENOATTR ) {
ret = 0 ;
errno = 0 ;
}
TALLOC_FREE ( frame ) ;
return ret ;
2012-08-15 14:34:41 +04:00
}
2016-03-03 22:54:23 +03:00
static int fake_acls_chown ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uid_t uid ,
gid_t gid )
2012-08-15 14:34:41 +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-15 14:34:41 +04:00
SIVAL ( id_buf , 0 , uid ) ;
2016-03-03 22:54:23 +03:00
ret = SMB_VFS_NEXT_SETXATTR ( handle ,
2017-05-25 22:41:31 +03:00
smb_fname ,
2016-03-03 22:54:23 +03:00
FAKE_UID ,
id_buf ,
sizeof ( id_buf ) ,
0 ) ;
2012-08-15 14:34:41 +04:00
if ( ret ! = 0 ) {
return ret ;
}
}
if ( gid ! = - 1 ) {
SIVAL ( id_buf , 0 , gid ) ;
2016-03-03 22:54:23 +03:00
ret = SMB_VFS_NEXT_SETXATTR ( handle ,
2017-05-25 22:41:31 +03:00
smb_fname ,
2016-03-03 22:54:23 +03:00
FAKE_GID ,
id_buf ,
sizeof ( id_buf ) ,
0 ) ;
2012-08-15 14:34:41 +04:00
if ( ret ! = 0 ) {
return ret ;
}
}
return 0 ;
}
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 ) ;
2016-03-04 01:34:57 +03:00
ret = SMB_VFS_NEXT_SETXATTR ( handle ,
2017-05-25 22:41:31 +03:00
smb_fname ,
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 ) ;
2016-03-04 01:34:57 +03:00
ret = SMB_VFS_NEXT_SETXATTR ( handle ,
2017-05-25 22:41:31 +03:00
smb_fname ,
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 ;
SMB_ACL_PERMSET_T mask_permset ;
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_chmod ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname_in ,
mode_t mode )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
int ret = - 1 ;
SMB_ACL_T the_acl = NULL ;
struct smb_filename * smb_fname = cp_smb_filename_nostream ( talloc_tos ( ) ,
smb_fname_in ) ;
if ( smb_fname = = NULL ) {
TALLOC_FREE ( frame ) ;
return - 1 ;
}
/*
* Passthrough first to preserve the
* S_ISUID | S_ISGID | S_ISVTX
* bits .
*/
ret = SMB_VFS_NEXT_CHMOD ( handle ,
smb_fname ,
mode ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( frame ) ;
return - 1 ;
}
the_acl = fake_acls_sys_acl_get_file ( handle ,
smb_fname ,
SMB_ACL_TYPE_ACCESS ,
talloc_tos ( ) ) ;
if ( the_acl = = NULL ) {
TALLOC_FREE ( frame ) ;
if ( errno = = ENOATTR ) {
/* No ACL on this file. Just passthrough. */
return 0 ;
}
return - 1 ;
}
ret = fake_acl_process_chmod ( & the_acl ,
smb_fname - > st . st_ex_uid ,
mode ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( frame ) ;
return - 1 ;
}
ret = fake_acls_sys_acl_set_file ( handle ,
smb_fname ,
SMB_ACL_TYPE_ACCESS ,
the_acl ) ;
TALLOC_FREE ( frame ) ;
return ret ;
}
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 ,
talloc_tos ( ) ) ;
if ( the_acl = = NULL ) {
TALLOC_FREE ( frame ) ;
if ( errno = = ENOATTR ) {
/* 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 ,
the_acl ) ;
TALLOC_FREE ( frame ) ;
return ret ;
}
2012-08-15 14:34:41 +04:00
static struct vfs_fn_pointers vfs_fake_acls_fns = {
. 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
. chmod_fn = fake_acls_chmod ,
. fchmod_fn = fake_acls_fchmod ,
2012-08-15 14:34:41 +04:00
. sys_acl_get_file_fn = fake_acls_sys_acl_get_file ,
. sys_acl_get_fd_fn = fake_acls_sys_acl_get_fd ,
2012-10-10 09:53:43 +04:00
. sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file ,
. sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd ,
2012-08-15 14:34:41 +04:00
. sys_acl_set_file_fn = fake_acls_sys_acl_set_file ,
. sys_acl_set_fd_fn = fake_acls_sys_acl_set_fd ,
. sys_acl_delete_def_file_fn = fake_acls_sys_acl_delete_def_file ,
. chown_fn = fake_acls_chown ,
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 ) ;
}