2008-09-17 02:55:06 +04:00
/*
* Store Windows ACLs in xattrs .
*
* Copyright ( C ) Volker Lendecke , 2008
* Copyright ( C ) Jeremy Allison , 2008
*
* 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-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2019-09-12 02:49:38 +03:00
# include "system/filesys.h"
2008-09-17 02:55:06 +04:00
# include "librpc/gen_ndr/xattr.h"
2011-03-24 16:15:54 +03:00
# include "auth.h"
2017-08-18 15:41:57 +03:00
# include "vfs_acl_common.h"
2008-09-17 02:55:06 +04:00
2009-07-27 23:09:40 +04:00
/* Pull in the common functions. */
2010-10-16 02:56:09 +04:00
# define ACL_MODULE_NAME "acl_xattr"
2017-08-18 15:41:57 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2009-07-27 23:09:40 +04:00
2008-11-11 04:57:22 +03:00
/*******************************************************************
Pull a security descriptor into a DATA_BLOB from a xattr .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-04-09 00:40:44 +03:00
static ssize_t getxattr_do ( vfs_handle_struct * handle ,
files_struct * fsp ,
const struct smb_filename * smb_fname ,
const char * xattr_name ,
uint8_t * val ,
size_t size )
{
ssize_t sizeret ;
int saved_errno = 0 ;
become_root ( ) ;
if ( fsp & & fsp - > fh - > fd ! = - 1 ) {
sizeret = SMB_VFS_FGETXATTR ( fsp , xattr_name , val , size ) ;
} else {
2017-05-26 02:42:04 +03:00
sizeret = SMB_VFS_GETXATTR ( handle - > conn , smb_fname ,
2017-04-09 00:40:44 +03:00
XATTR_NTACL_NAME , val , size ) ;
}
if ( sizeret = = - 1 ) {
saved_errno = errno ;
}
unbecome_root ( ) ;
if ( saved_errno ! = 0 ) {
errno = saved_errno ;
}
return sizeret ;
}
2020-04-13 22:24:14 +03:00
static NTSTATUS fget_acl_blob ( TALLOC_CTX * ctx ,
vfs_handle_struct * handle ,
files_struct * fsp ,
DATA_BLOB * pblob )
{
size_t size = 4096 ;
uint8_t * val = NULL ;
uint8_t * tmp ;
ssize_t sizeret ;
ZERO_STRUCTP ( pblob ) ;
again :
tmp = talloc_realloc ( ctx , val , uint8_t , size ) ;
if ( tmp = = NULL ) {
TALLOC_FREE ( val ) ;
return NT_STATUS_NO_MEMORY ;
}
val = tmp ;
sizeret =
getxattr_do ( handle , fsp , NULL , XATTR_NTACL_NAME , val , size ) ;
if ( sizeret > = 0 ) {
pblob - > data = val ;
pblob - > length = sizeret ;
return NT_STATUS_OK ;
}
if ( errno ! = ERANGE ) {
goto err ;
}
/* Too small, try again. */
sizeret =
getxattr_do ( handle , fsp , NULL , XATTR_NTACL_NAME , NULL , 0 ) ;
if ( sizeret < 0 ) {
goto err ;
}
if ( size < sizeret ) {
size = sizeret ;
}
if ( size > 65536 ) {
/* Max ACL size is 65536 bytes. */
errno = ERANGE ;
goto err ;
}
goto again ;
err :
/* Real error - exit here. */
TALLOC_FREE ( val ) ;
return map_nt_error_from_unix ( errno ) ;
}
2020-04-13 23:29:48 +03:00
static NTSTATUS get_acl_blob_at ( TALLOC_CTX * ctx ,
2008-09-17 23:34:09 +04:00
vfs_handle_struct * handle ,
2020-04-13 23:29:48 +03:00
struct files_struct * dirfsp ,
2016-03-12 02:50:57 +03:00
const struct smb_filename * smb_fname ,
2008-09-17 02:55:06 +04:00
DATA_BLOB * pblob )
{
2017-04-13 12:44:58 +03:00
size_t size = 4096 ;
2008-09-17 02:55:06 +04:00
uint8_t * val = NULL ;
uint8_t * tmp ;
ssize_t sizeret ;
ZERO_STRUCTP ( pblob ) ;
again :
2011-06-07 05:10:15 +04:00
tmp = talloc_realloc ( ctx , val , uint8_t , size ) ;
2008-09-17 02:55:06 +04:00
if ( tmp = = NULL ) {
TALLOC_FREE ( val ) ;
return NT_STATUS_NO_MEMORY ;
}
val = tmp ;
2017-04-09 00:40:44 +03:00
sizeret =
2020-04-13 22:53:58 +03:00
getxattr_do ( handle , NULL , smb_fname , XATTR_NTACL_NAME , val , size ) ;
2008-09-17 02:55:06 +04:00
2017-04-13 12:44:58 +03:00
if ( sizeret > = 0 ) {
pblob - > data = val ;
pblob - > length = sizeret ;
return NT_STATUS_OK ;
}
2008-09-17 02:55:06 +04:00
2017-04-13 12:44:58 +03:00
if ( errno ! = ERANGE ) {
goto err ;
}
/* Too small, try again. */
sizeret =
2020-04-13 22:53:58 +03:00
getxattr_do ( handle , NULL , smb_fname , XATTR_NTACL_NAME , NULL , 0 ) ;
2017-04-13 12:44:58 +03:00
if ( sizeret < 0 ) {
goto err ;
}
if ( size < sizeret ) {
size = sizeret ;
}
if ( size > 65536 ) {
/* Max ACL size is 65536 bytes. */
errno = ERANGE ;
goto err ;
2008-09-17 02:55:06 +04:00
}
2017-04-13 12:44:58 +03:00
goto again ;
err :
/* Real error - exit here. */
TALLOC_FREE ( val ) ;
return map_nt_error_from_unix ( errno ) ;
2008-09-17 02:55:06 +04:00
}
2008-11-11 04:57:22 +03:00
/*******************************************************************
Store a DATA_BLOB into an xattr given an fsp pointer .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-27 23:09:40 +04:00
static NTSTATUS store_acl_blob_fsp ( vfs_handle_struct * handle ,
2008-11-11 04:57:22 +03:00
files_struct * fsp ,
2008-10-29 23:27:14 +03:00
DATA_BLOB * pblob )
{
int ret ;
int saved_errno = 0 ;
2008-10-30 23:51:28 +03:00
DEBUG ( 10 , ( " store_acl_blob_fsp: storing blob length %u on file %s \n " ,
2009-07-11 05:11:32 +04:00
( unsigned int ) pblob - > length , fsp_str_dbg ( fsp ) ) ) ;
2008-10-29 23:27:14 +03:00
become_root ( ) ;
if ( fsp - > fh - > fd ! = - 1 ) {
ret = SMB_VFS_FSETXATTR ( fsp , XATTR_NTACL_NAME ,
pblob - > data , pblob - > length , 0 ) ;
} else {
2017-05-25 22:41:31 +03:00
ret = SMB_VFS_SETXATTR ( fsp - > conn , fsp - > fsp_name ,
2008-10-29 23:27:14 +03:00
XATTR_NTACL_NAME ,
pblob - > data , pblob - > length , 0 ) ;
}
if ( ret ) {
saved_errno = errno ;
}
unbecome_root ( ) ;
if ( ret ) {
2008-10-30 23:51:28 +03:00
DEBUG ( 5 , ( " store_acl_blob_fsp: setting attr failed for file %s "
2008-10-29 23:27:14 +03:00
" with error %s \n " ,
2009-07-11 05:11:32 +04:00
fsp_str_dbg ( fsp ) ,
2012-05-15 18:47:14 +04:00
strerror ( saved_errno ) ) ) ;
errno = saved_errno ;
return map_nt_error_from_unix ( saved_errno ) ;
2008-10-29 23:27:14 +03:00
}
return NT_STATUS_OK ;
}
2008-11-19 23:24:53 +03:00
/*********************************************************************
Remove a Windows ACL - we ' re setting the underlying POSIX ACL .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int sys_acl_set_file_xattr ( vfs_handle_struct * handle ,
2017-05-24 20:47:46 +03:00
const struct smb_filename * smb_fname ,
SMB_ACL_TYPE_T type ,
SMB_ACL_T theacl )
2008-11-19 23:24:53 +03:00
{
int ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE ( handle ,
2017-05-24 20:47:46 +03:00
smb_fname ,
2008-11-19 23:24:53 +03:00
type ,
theacl ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
become_root ( ) ;
2017-05-24 21:35:50 +03:00
SMB_VFS_REMOVEXATTR ( handle - > conn , smb_fname ,
2017-05-24 20:47:46 +03:00
XATTR_NTACL_NAME ) ;
2008-11-19 23:24:53 +03:00
unbecome_root ( ) ;
return ret ;
}
/*********************************************************************
Remove a Windows ACL - we ' re setting the underlying POSIX ACL .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int sys_acl_set_fd_xattr ( vfs_handle_struct * handle ,
files_struct * fsp ,
SMB_ACL_T theacl )
{
int ret = SMB_VFS_NEXT_SYS_ACL_SET_FD ( handle ,
fsp ,
theacl ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
become_root ( ) ;
SMB_VFS_FREMOVEXATTR ( fsp , XATTR_NTACL_NAME ) ;
unbecome_root ( ) ;
return ret ;
}
2009-11-07 08:53:07 +03:00
static int connect_acl_xattr ( struct vfs_handle_struct * handle ,
const char * service ,
const char * user )
{
2009-12-01 02:53:04 +03:00
int ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
2016-08-24 11:01:17 +03:00
bool ok ;
2016-08-26 11:04:53 +03:00
struct acl_common_config * config = NULL ;
2009-12-01 02:53:04 +03:00
if ( ret < 0 ) {
return ret ;
}
2017-08-18 15:41:57 +03:00
ok = init_acl_common_config ( handle , ACL_MODULE_NAME ) ;
2016-08-24 11:01:17 +03:00
if ( ! ok ) {
DBG_ERR ( " init_acl_common_config failed \n " ) ;
return - 1 ;
}
2010-10-16 06:54:51 +04:00
/* Ensure we have the parameters correct if we're
2009-11-07 08:53:07 +03:00
* using this module . */
2009-11-12 05:35:18 +03:00
DEBUG ( 2 , ( " connect_acl_xattr: setting 'inherit acls = true' "
2010-10-16 06:54:51 +04:00
" 'dos filemode = true' and "
" 'force unknown acl user = true' for service %s \n " ,
2009-11-07 08:53:07 +03:00
service ) ) ;
2009-11-12 05:35:18 +03:00
lp_do_parameter ( SNUM ( handle - > conn ) , " inherit acls " , " true " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " dos filemode " , " true " ) ;
2010-10-16 06:54:51 +04:00
lp_do_parameter ( SNUM ( handle - > conn ) , " force unknown acl user " , " true " ) ;
2009-11-12 05:35:18 +03:00
2016-08-26 11:04:53 +03:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct acl_common_config ,
return - 1 ) ;
if ( config - > ignore_system_acls ) {
2017-02-06 14:47:41 +03:00
mode_t create_mask = lp_create_mask ( SNUM ( handle - > conn ) ) ;
char * create_mask_str = NULL ;
if ( ( create_mask & 0666 ) ! = 0666 ) {
create_mask | = 0666 ;
create_mask_str = talloc_asprintf ( handle , " 0%o " ,
create_mask ) ;
if ( create_mask_str = = NULL ) {
DBG_ERR ( " talloc_asprintf failed \n " ) ;
return - 1 ;
}
DBG_NOTICE ( " setting 'create mask = %s' \n " , create_mask_str ) ;
lp_do_parameter ( SNUM ( handle - > conn ) ,
" create mask " , create_mask_str ) ;
TALLOC_FREE ( create_mask_str ) ;
}
DBG_NOTICE ( " setting 'directory mask = 0777', "
2016-08-26 11:04:53 +03:00
" 'store dos attributes = yes' and all "
" 'map ...' options to 'no' \n " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " directory mask " , " 0777 " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " map archive " , " no " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " map hidden " , " no " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " map readonly " , " no " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " map system " , " no " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " store dos attributes " ,
" yes " ) ;
}
2009-11-07 08:53:07 +03:00
return 0 ;
}
2008-09-17 02:55:06 +04:00
2019-09-12 02:49:38 +03:00
static int acl_xattr_unlinkat ( vfs_handle_struct * handle ,
struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
int flags )
{
int ret ;
if ( flags & AT_REMOVEDIR ) {
2019-10-05 00:34:41 +03:00
ret = rmdir_acl_common ( handle ,
dirfsp ,
smb_fname ) ;
2019-09-12 02:49:38 +03:00
} else {
2019-09-17 03:50:17 +03:00
ret = unlink_acl_common ( handle ,
dirfsp ,
smb_fname ,
flags ) ;
2019-09-12 02:49:38 +03:00
}
return ret ;
}
2017-08-18 15:41:57 +03:00
static NTSTATUS acl_xattr_fget_nt_acl ( vfs_handle_struct * handle ,
files_struct * fsp ,
uint32_t security_info ,
TALLOC_CTX * mem_ctx ,
struct security_descriptor * * ppdesc )
{
NTSTATUS status ;
2020-04-13 22:42:49 +03:00
status = fget_nt_acl_common ( fget_acl_blob , handle , fsp ,
2017-08-18 15:41:57 +03:00
security_info , mem_ctx , ppdesc ) ;
return status ;
}
static NTSTATUS acl_xattr_get_nt_acl ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uint32_t security_info ,
TALLOC_CTX * mem_ctx ,
struct security_descriptor * * ppdesc )
{
NTSTATUS status ;
2020-04-13 23:29:48 +03:00
status = get_nt_acl_common_at ( get_acl_blob_at ,
handle ,
handle - > conn - > cwd_fsp ,
smb_fname ,
security_info ,
mem_ctx ,
ppdesc ) ;
2017-08-18 15:41:57 +03:00
return status ;
}
static NTSTATUS acl_xattr_fset_nt_acl ( vfs_handle_struct * handle ,
files_struct * fsp ,
uint32_t security_info_sent ,
const struct security_descriptor * psd )
{
NTSTATUS status ;
2020-04-13 22:29:22 +03:00
status = fset_nt_acl_common ( fget_acl_blob , store_acl_blob_fsp ,
2017-08-18 15:41:57 +03:00
ACL_MODULE_NAME ,
handle , fsp , security_info_sent , psd ) ;
return status ;
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_acl_xattr_fns = {
2009-11-07 08:53:07 +03:00
. connect_fn = connect_acl_xattr ,
2019-09-12 02:49:38 +03:00
. unlinkat_fn = acl_xattr_unlinkat ,
2011-12-04 08:45:04 +04:00
. chmod_fn = chmod_acl_module_common ,
. fchmod_fn = fchmod_acl_module_common ,
2017-08-18 15:41:57 +03:00
. fget_nt_acl_fn = acl_xattr_fget_nt_acl ,
. get_nt_acl_fn = acl_xattr_get_nt_acl ,
. fset_nt_acl_fn = acl_xattr_fset_nt_acl ,
2011-12-04 08:45:04 +04:00
. sys_acl_set_file_fn = sys_acl_set_file_xattr ,
. sys_acl_set_fd_fn = sys_acl_set_fd_xattr
2008-09-17 02:55:06 +04:00
} ;
2015-08-13 19:16:20 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_acl_xattr_init ( TALLOC_CTX * ctx )
2008-09-17 02:55:06 +04:00
{
2009-07-24 04:28:58 +04:00
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " acl_xattr " ,
& vfs_acl_xattr_fns ) ;
2008-09-17 02:55:06 +04:00
}