2013-04-14 14:06:57 +04:00
/*
* Convert NFSv4 acls stored per http : //www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
*
* Copyright ( C ) Jiri Sasek , 2007
* based on the foobar . c module which is copyrighted by Volker Lendecke
* based on pvfs_acl_nfs4 . c Copyright ( C ) Andrew Tridgell 2006
*
* based on vfs_fake_acls :
* Copyright ( C ) Tim Potter , 1999 - 2000
* Copyright ( C ) Alexander Bokovoy , 2002
* Copyright ( C ) Andrew Bartlett , 2002 , 2012
2017-10-19 17:34:44 +03:00
* Copyright ( C ) Ralph Boehme 2017
2013-04-14 14:06:57 +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/>.
*
*/
# include "includes.h"
# include "system/filesys.h"
# include "smbd/smbd.h"
# include "nfs4_acls.h"
# include "librpc/gen_ndr/ndr_nfs4acl.h"
2017-10-19 17:34:44 +03:00
# include "nfs4acl_xattr.h"
2017-10-17 13:02:53 +03:00
# include "nfs4acl_xattr_ndr.h"
2013-04-14 14:06:57 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2017-10-19 17:34:44 +03:00
static const struct enum_list nfs4acl_encoding [ ] = {
{ NFS4ACL_ENCODING_NDR , " ndr " } ,
{ NFS4ACL_ENCODING_XDR , " xdr " } ,
} ;
2017-10-23 17:35:52 +03:00
static NTSTATUS nfs4acl_get_blob ( struct vfs_handle_struct * handle ,
files_struct * fsp ,
const struct smb_filename * smb_fname_in ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob )
{
struct nfs4acl_config * config = NULL ;
const struct smb_filename * smb_fname = NULL ;
size_t allocsize = 256 ;
ssize_t length ;
bool ok ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct nfs4acl_config ,
return NT_STATUS_INTERNAL_ERROR ) ;
* blob = data_blob_null ;
if ( fsp = = NULL & & smb_fname_in = = NULL ) {
return NT_STATUS_INTERNAL_ERROR ;
}
smb_fname = smb_fname_in ;
if ( smb_fname = = NULL ) {
smb_fname = fsp - > fsp_name ;
}
if ( smb_fname = = NULL ) {
return NT_STATUS_INTERNAL_ERROR ;
}
do {
allocsize * = 4 ;
ok = data_blob_realloc ( mem_ctx , blob , allocsize ) ;
if ( ! ok ) {
return NT_STATUS_NO_MEMORY ;
}
if ( fsp ! = NULL & & fsp - > fh - > fd ! = - 1 ) {
length = SMB_VFS_NEXT_FGETXATTR ( handle ,
fsp ,
config - > xattr_name ,
blob - > data ,
blob - > length ) ;
} else {
length = SMB_VFS_NEXT_GETXATTR ( handle ,
smb_fname ,
config - > xattr_name ,
blob - > data ,
blob - > length ) ;
}
} while ( length = = - 1 & & errno = = ERANGE & & allocsize < = 65536 ) ;
if ( length = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
return NT_STATUS_OK ;
}
2017-10-16 19:05:51 +03:00
static NTSTATUS nfs4acl_xattr_default_sd (
struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
TALLOC_CTX * mem_ctx ,
struct security_descriptor * * sd )
2013-04-16 16:11:27 +04:00
{
2017-10-16 19:05:51 +03:00
struct nfs4acl_config * config = NULL ;
enum default_acl_style default_acl_style ;
mode_t required_mode ;
SMB_STRUCT_STAT sbuf = smb_fname - > st ;
2013-04-16 16:11:27 +04:00
int ret ;
2017-10-16 19:05:51 +03:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct nfs4acl_config ,
return NT_STATUS_INTERNAL_ERROR ) ;
2013-04-16 16:11:27 +04:00
2017-10-16 19:05:51 +03:00
default_acl_style = config - > default_acl_style ;
2013-04-16 16:11:27 +04:00
2017-10-16 19:05:51 +03:00
if ( ! VALID_STAT ( sbuf ) ) {
ret = vfs_stat_smb_basename ( handle - > conn ,
smb_fname ,
& sbuf ) ;
if ( ret ! = 0 ) {
return map_nt_error_from_unix ( errno ) ;
2013-04-16 16:11:27 +04:00
}
}
2017-10-16 19:05:51 +03:00
if ( S_ISDIR ( sbuf . st_ex_mode ) ) {
required_mode = 0777 ;
} else {
required_mode = 0666 ;
}
if ( ( sbuf . st_ex_mode & required_mode ) ! = required_mode ) {
default_acl_style = DEFAULT_ACL_POSIX ;
2013-04-16 16:11:27 +04:00
}
2017-10-16 19:05:51 +03:00
return make_default_filesystem_acl ( mem_ctx ,
default_acl_style ,
smb_fname - > base_name ,
& sbuf ,
sd ) ;
2013-04-14 14:06:57 +04:00
}
2017-10-23 17:35:52 +03:00
static NTSTATUS nfs4acl_blob_to_smb4 ( struct vfs_handle_struct * handle ,
DATA_BLOB * blob ,
TALLOC_CTX * mem_ctx ,
struct SMB4ACL_T * * smb4acl )
{
struct nfs4acl_config * config = NULL ;
NTSTATUS status ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct nfs4acl_config ,
return NT_STATUS_INTERNAL_ERROR ) ;
switch ( config - > encoding ) {
case NFS4ACL_ENCODING_NDR :
status = nfs4acl_ndr_blob_to_smb4 ( handle , mem_ctx , blob , smb4acl ) ;
break ;
default :
status = NT_STATUS_INTERNAL_ERROR ;
break ;
}
return status ;
}
2013-04-14 14:06:57 +04:00
static NTSTATUS nfs4acl_xattr_fget_nt_acl ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
2015-05-03 06:11:02 +03:00
uint32_t security_info ,
2013-04-14 14:06:57 +04:00
TALLOC_CTX * mem_ctx ,
2017-10-19 22:53:40 +03:00
struct security_descriptor * * sd )
2013-04-14 14:06:57 +04:00
{
2017-10-19 22:53:40 +03:00
struct SMB4ACL_T * smb4acl = NULL ;
2013-04-14 14:06:57 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2017-10-23 17:35:52 +03:00
DATA_BLOB blob ;
2017-10-19 22:53:40 +03:00
NTSTATUS status ;
2013-04-14 14:06:57 +04:00
2017-10-23 17:35:52 +03:00
status = nfs4acl_get_blob ( handle , fsp , NULL , frame , & blob ) ;
2013-04-16 16:11:27 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
2017-10-16 19:05:51 +03:00
TALLOC_FREE ( frame ) ;
return nfs4acl_xattr_default_sd (
2017-10-19 22:53:40 +03:00
handle , fsp - > fsp_name , mem_ctx , sd ) ;
2013-04-16 16:11:27 +04:00
}
2017-10-16 19:05:51 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-04-14 14:06:57 +04:00
TALLOC_FREE ( frame ) ;
return status ;
}
2017-10-23 17:35:52 +03:00
status = nfs4acl_blob_to_smb4 ( handle , & blob , frame , & smb4acl ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
2016-08-09 12:07:38 +03:00
status = smb_fget_nt_acl_nfs4 ( fsp , NULL , security_info , mem_ctx ,
2017-10-19 22:53:40 +03:00
sd , smb4acl ) ;
2013-04-14 14:06:57 +04:00
TALLOC_FREE ( frame ) ;
return status ;
}
static NTSTATUS nfs4acl_xattr_get_nt_acl ( struct vfs_handle_struct * handle ,
2016-02-12 21:30:10 +03:00
const struct smb_filename * smb_fname ,
uint32_t security_info ,
2013-04-14 14:06:57 +04:00
TALLOC_CTX * mem_ctx ,
2017-10-19 22:53:40 +03:00
struct security_descriptor * * sd )
2013-04-14 14:06:57 +04:00
{
2017-10-19 22:53:40 +03:00
struct SMB4ACL_T * smb4acl = NULL ;
2013-04-14 14:06:57 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2017-10-23 17:35:52 +03:00
DATA_BLOB blob ;
2017-10-19 22:53:40 +03:00
NTSTATUS status ;
2013-04-14 14:06:57 +04:00
2017-10-23 17:35:52 +03:00
status = nfs4acl_get_blob ( handle , NULL , smb_fname , frame , & blob ) ;
2013-04-14 14:06:57 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
2017-10-16 19:05:51 +03:00
TALLOC_FREE ( frame ) ;
return nfs4acl_xattr_default_sd (
2017-10-19 22:53:40 +03:00
handle , smb_fname , mem_ctx , sd ) ;
2013-04-14 14:06:57 +04:00
}
2017-10-16 19:05:51 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-04-14 14:06:57 +04:00
TALLOC_FREE ( frame ) ;
return status ;
}
2017-10-23 17:35:52 +03:00
status = nfs4acl_blob_to_smb4 ( handle , & blob , frame , & smb4acl ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
2016-08-09 12:07:38 +03:00
status = smb_get_nt_acl_nfs4 ( handle - > conn , smb_fname , NULL ,
2017-10-19 22:53:40 +03:00
security_info , mem_ctx , sd ,
smb4acl ) ;
2013-04-14 14:06:57 +04:00
TALLOC_FREE ( frame ) ;
return status ;
}
2017-10-23 17:35:52 +03:00
static bool nfs4acl_smb4acl_set_fn ( vfs_handle_struct * handle ,
files_struct * fsp ,
struct SMB4ACL_T * smb4acl )
{
struct nfs4acl_config * config = NULL ;
DATA_BLOB blob ;
NTSTATUS status ;
int ret ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct nfs4acl_config ,
return false ) ;
switch ( config - > encoding ) {
case NFS4ACL_ENCODING_NDR :
status = nfs4acl_smb4acl_to_ndr_blob ( handle , talloc_tos ( ) ,
smb4acl , & blob ) ;
break ;
default :
status = NT_STATUS_INTERNAL_ERROR ;
break ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
2017-10-23 17:38:51 +03:00
if ( fsp - > fh - > fd ! = - 1 ) {
ret = SMB_VFS_NEXT_FSETXATTR ( handle , fsp , config - > xattr_name ,
blob . data , blob . length , 0 ) ;
} else {
ret = SMB_VFS_NEXT_SETXATTR ( handle , fsp - > fsp_name ,
config - > xattr_name ,
blob . data , blob . length , 0 ) ;
}
2017-10-23 17:35:52 +03:00
data_blob_free ( & blob ) ;
if ( ret ! = 0 ) {
DBG_ERR ( " can't store acl in xattr: %s \n " , strerror ( errno ) ) ;
return false ;
}
return true ;
}
2013-04-14 14:06:57 +04:00
static NTSTATUS nfs4acl_xattr_fset_nt_acl ( vfs_handle_struct * handle ,
files_struct * fsp ,
2015-05-03 06:11:02 +03:00
uint32_t security_info_sent ,
2013-04-14 14:06:57 +04:00
const struct security_descriptor * psd )
{
2017-10-23 17:35:52 +03:00
struct nfs4acl_config * config = NULL ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct nfs4acl_config ,
return NT_STATUS_INTERNAL_ERROR ) ;
return smb_set_nt_acl_nfs4 ( handle ,
fsp ,
& config - > nfs4_params ,
security_info_sent ,
psd ,
nfs4acl_smb4acl_set_fn ) ;
2013-04-14 14:06:57 +04:00
}
2017-10-19 17:34:44 +03:00
static int nfs4acl_connect ( struct vfs_handle_struct * handle ,
const char * service ,
const char * user )
{
struct nfs4acl_config * config = NULL ;
const struct enum_list * default_acl_style_list = NULL ;
const char * default_xattr_name = NULL ;
int enumval ;
unsigned nfs_version ;
int ret ;
default_acl_style_list = get_default_acl_style_list ( ) ;
config = talloc_zero ( handle - > conn , struct nfs4acl_config ) ;
if ( config = = NULL ) {
DBG_ERR ( " talloc_zero() failed \n " ) ;
return - 1 ;
}
ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( ret < 0 ) {
TALLOC_FREE ( config ) ;
return ret ;
}
ret = smbacl4_get_vfs_params ( handle - > conn , & config - > nfs4_params ) ;
if ( ret < 0 ) {
TALLOC_FREE ( config ) ;
return ret ;
}
enumval = lp_parm_enum ( SNUM ( handle - > conn ) ,
" nfs4acl_xattr " ,
" encoding " ,
nfs4acl_encoding ,
NFS4ACL_ENCODING_NDR ) ;
if ( enumval = = - 1 ) {
DBG_ERR ( " Invalid \" nfs4acl_xattr:encoding \" parameter \n " ) ;
return - 1 ;
}
config - > encoding = ( enum nfs4acl_encoding ) enumval ;
switch ( config - > encoding ) {
case NFS4ACL_ENCODING_NDR :
default :
default_xattr_name = NFS4ACL_NDR_XATTR_NAME ;
break ;
}
nfs_version = ( unsigned ) lp_parm_int ( SNUM ( handle - > conn ) ,
" nfs4acl_xattr " ,
" version " ,
40 ) ;
switch ( nfs_version ) {
case 40 :
config - > nfs_version = ACL4_XATTR_VERSION_40 ;
break ;
default :
config - > nfs_version = ACL4_XATTR_VERSION_DEFAULT ;
break ;
}
config - > default_acl_style = lp_parm_enum ( SNUM ( handle - > conn ) ,
" nfs4acl_xattr " ,
" default acl style " ,
default_acl_style_list ,
DEFAULT_ACL_EVERYONE ) ;
config - > xattr_name = lp_parm_talloc_string ( config ,
SNUM ( handle - > conn ) ,
" nfs4acl_xattr " ,
" xattr_name " ,
default_xattr_name ) ;
SMB_VFS_HANDLE_SET_DATA ( handle , config , NULL , struct nfs4acl_config ,
return - 1 ) ;
2017-10-16 19:05:51 +03:00
/*
* Ensure we have the parameters correct if we ' re using this module .
*/
DBG_NOTICE ( " Setting 'inherit acls = true', "
" 'dos filemode = true', "
" 'force unknown acl user = true', "
" 'create mask = 0666', "
" 'directory mask = 0777' and "
" 'store dos attributes = yes' "
" for service [%s] \n " , service ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " inherit acls " , " true " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " dos filemode " , " true " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " force unknown acl user " , " true " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " create mask " , " 0666 " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " directory mask " , " 0777 " ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " store dos attributes " , " yes " ) ;
2017-10-19 17:34:44 +03:00
return 0 ;
}
2013-04-14 14:06:57 +04:00
/*
As long as Samba does not support an exiplicit method for a module
to define conflicting vfs methods , we should override all conflicting
methods here . That way , we know we are using the NFSv4 storage
Function declarations taken from vfs_solarisacl
*/
static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_file ( 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 )
2013-04-14 14:06:57 +04:00
{
return ( SMB_ACL_T ) NULL ;
}
static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
TALLOC_CTX * mem_ctx )
{
return ( SMB_ACL_T ) NULL ;
}
static int nfs4acl_xattr_fail__sys_acl_set_file ( vfs_handle_struct * handle ,
2017-05-24 20:47:46 +03:00
const struct smb_filename * smb_fname ,
2013-04-14 14:06:57 +04:00
SMB_ACL_TYPE_T type ,
SMB_ACL_T theacl )
{
return - 1 ;
}
static int nfs4acl_xattr_fail__sys_acl_set_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
SMB_ACL_T theacl )
{
return - 1 ;
}
static int nfs4acl_xattr_fail__sys_acl_delete_def_file ( vfs_handle_struct * handle ,
2017-05-24 01:33:31 +03:00
const struct smb_filename * smb_fname )
2013-04-14 14:06:57 +04:00
{
return - 1 ;
}
2017-05-24 03:35:59 +03:00
static int nfs4acl_xattr_fail__sys_acl_blob_get_file ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
TALLOC_CTX * mem_ctx ,
char * * blob_description ,
DATA_BLOB * blob )
2013-04-14 14:06:57 +04:00
{
return - 1 ;
}
static int nfs4acl_xattr_fail__sys_acl_blob_get_fd ( vfs_handle_struct * handle , files_struct * fsp , TALLOC_CTX * mem_ctx , char * * blob_description , DATA_BLOB * blob )
{
return - 1 ;
}
/* VFS operations structure */
static struct vfs_fn_pointers nfs4acl_xattr_fns = {
2017-10-19 17:34:44 +03:00
. connect_fn = nfs4acl_connect ,
2017-10-19 16:50:07 +03:00
. fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl ,
. get_nt_acl_fn = nfs4acl_xattr_get_nt_acl ,
. fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl ,
2013-04-14 14:06:57 +04:00
. sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file ,
. sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd ,
. sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file ,
. sys_acl_blob_get_fd_fn = nfs4acl_xattr_fail__sys_acl_blob_get_fd ,
. sys_acl_set_file_fn = nfs4acl_xattr_fail__sys_acl_set_file ,
. sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd ,
. sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file ,
} ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_nfs4acl_xattr_init ( TALLOC_CTX * ) ;
NTSTATUS vfs_nfs4acl_xattr_init ( TALLOC_CTX * ctx )
2013-04-14 14:06:57 +04:00
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " nfs4acl_xattr " ,
& nfs4acl_xattr_fns ) ;
}