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
*
* 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"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
static struct nfs4acl * nfs4acl_blob2acl ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx )
{
enum ndr_err_code ndr_err ;
struct nfs4acl * acl = talloc ( mem_ctx , struct nfs4acl ) ;
if ( ! acl ) {
errno = ENOMEM ;
return NULL ;
}
ndr_err = ndr_pull_struct_blob ( blob , acl , acl ,
( ndr_pull_flags_fn_t ) ndr_pull_nfs4acl ) ;
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 nfs4acl_acl2blob ( TALLOC_CTX * mem_ctx , struct nfs4acl * 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_nfs4acl ) ;
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 ;
}
static NTSTATUS nfs4_get_nfs4_acl_common ( TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob ,
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * * ppacl )
2013-04-14 14:06:57 +04:00
{
int i ;
struct nfs4acl * nfs4acl = NULL ;
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl = NULL ;
2013-04-14 14:06:57 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
nfs4acl = nfs4acl_blob2acl ( blob , frame ) ;
/* create SMB4ACL data */
if ( ( pacl = smb_create_smb4acl ( mem_ctx ) ) = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < nfs4acl - > a_count ; i + + ) {
SMB_ACE4PROP_T aceprop ;
2015-05-03 06:11:02 +03:00
aceprop . aceType = ( uint32_t ) nfs4acl - > ace [ i ] . e_type ;
aceprop . aceFlags = ( uint32_t ) nfs4acl - > ace [ i ] . e_flags ;
aceprop . aceMask = ( uint32_t ) nfs4acl - > ace [ i ] . e_mask ;
aceprop . who . id = ( uint32_t ) nfs4acl - > ace [ i ] . e_id ;
2013-04-14 14:06:57 +04:00
if ( ! strcmp ( nfs4acl - > ace [ i ] . e_who ,
NFS4ACL_XATTR_OWNER_WHO ) ) {
aceprop . flags = SMB_ACE4_ID_SPECIAL ;
aceprop . who . special_id = SMB_ACE4_WHO_OWNER ;
} else if ( ! strcmp ( nfs4acl - > ace [ i ] . e_who ,
NFS4ACL_XATTR_GROUP_WHO ) ) {
aceprop . flags = SMB_ACE4_ID_SPECIAL ;
aceprop . who . special_id = SMB_ACE4_WHO_GROUP ;
} else if ( ! strcmp ( nfs4acl - > ace [ i ] . e_who ,
NFS4ACL_XATTR_EVERYONE_WHO ) ) {
aceprop . flags = SMB_ACE4_ID_SPECIAL ;
aceprop . who . special_id = SMB_ACE4_WHO_EVERYONE ;
} else {
aceprop . flags = 0 ;
}
if ( smb_add_ace4 ( pacl , & aceprop ) = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
}
* ppacl = pacl ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
}
/* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
static NTSTATUS nfs4_fget_nfs4_acl ( vfs_handle_struct * handle , TALLOC_CTX * mem_ctx ,
2015-08-11 13:35:20 +03:00
files_struct * fsp , struct SMB4ACL_T * * ppacl )
2013-04-14 14:06:57 +04:00
{
NTSTATUS status ;
DATA_BLOB blob = data_blob_null ;
ssize_t length ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
do {
blob . length + = 1000 ;
blob . data = talloc_realloc ( frame , blob . data , uint8_t , blob . length ) ;
if ( ! blob . data ) {
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return NT_STATUS_NO_MEMORY ;
}
length = SMB_VFS_NEXT_FGETXATTR ( handle , fsp , NFS4ACL_XATTR_NAME , blob . data , blob . length ) ;
blob . length = length ;
} while ( length = = - 1 & & errno = = ERANGE ) ;
if ( length = = - 1 ) {
TALLOC_FREE ( frame ) ;
return map_nt_error_from_unix ( errno ) ;
}
status = nfs4_get_nfs4_acl_common ( mem_ctx , & blob , ppacl ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
/* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
2017-05-26 02:42:04 +03:00
static NTSTATUS nfs4_get_nfs4_acl ( vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
const struct smb_filename * smb_fname ,
struct SMB4ACL_T * * ppacl )
2013-04-14 14:06:57 +04:00
{
NTSTATUS status ;
DATA_BLOB blob = data_blob_null ;
ssize_t length ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
do {
blob . length + = 1000 ;
blob . data = talloc_realloc ( frame , blob . data , uint8_t , blob . length ) ;
if ( ! blob . data ) {
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return NT_STATUS_NO_MEMORY ;
}
2017-05-26 02:42:04 +03:00
length = SMB_VFS_NEXT_GETXATTR ( handle , smb_fname ,
NFS4ACL_XATTR_NAME , blob . data , blob . length ) ;
2013-04-14 14:06:57 +04:00
blob . length = length ;
} while ( length = = - 1 & & errno = = ERANGE ) ;
if ( length = = - 1 ) {
TALLOC_FREE ( frame ) ;
return map_nt_error_from_unix ( errno ) ;
}
status = nfs4_get_nfs4_acl_common ( mem_ctx , & blob , ppacl ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
2013-04-16 16:11:27 +04:00
static bool nfs4acl_smb4acl2nfs4acl ( TALLOC_CTX * mem_ctx ,
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * smbacl ,
2013-04-16 16:11:27 +04:00
struct nfs4acl * * pnfs4acl ,
bool denymissingspecial )
2013-04-14 14:06:57 +04:00
{
struct nfs4acl * nfs4acl ;
2015-08-11 13:35:20 +03:00
struct SMB4ACE_T * smbace ;
2013-04-14 14:06:57 +04:00
bool have_special_id = false ;
2013-04-16 16:11:27 +04:00
int i ;
2013-04-14 14:06:57 +04:00
/* allocate the field of NFS4 aces */
2013-04-16 16:11:27 +04:00
nfs4acl = talloc_zero ( mem_ctx , struct nfs4acl ) ;
2013-04-14 14:06:57 +04:00
if ( nfs4acl = = NULL ) {
errno = ENOMEM ;
return false ;
}
nfs4acl - > a_count = smb_get_naces ( smbacl ) ;
2013-04-16 16:11:27 +04:00
nfs4acl - > ace = talloc_zero_array ( nfs4acl , struct nfs4ace ,
nfs4acl - > a_count ) ;
2013-04-14 14:06:57 +04:00
if ( nfs4acl - > ace = = NULL ) {
2013-04-16 16:11:27 +04:00
TALLOC_FREE ( nfs4acl ) ;
2013-04-14 14:06:57 +04:00
errno = ENOMEM ;
return false ;
}
/* handle all aces */
for ( smbace = smb_first_ace4 ( smbacl ) , i = 0 ;
smbace ! = NULL ;
smbace = smb_next_ace4 ( smbace ) , i + + ) {
SMB_ACE4PROP_T * aceprop = smb_get_ace4 ( smbace ) ;
nfs4acl - > ace [ i ] . e_type = aceprop - > aceType ;
nfs4acl - > ace [ i ] . e_flags = aceprop - > aceFlags ;
nfs4acl - > ace [ i ] . e_mask = aceprop - > aceMask ;
nfs4acl - > ace [ i ] . e_id = aceprop - > who . id ;
if ( aceprop - > flags & SMB_ACE4_ID_SPECIAL ) {
switch ( aceprop - > who . special_id ) {
case SMB_ACE4_WHO_EVERYONE :
nfs4acl - > ace [ i ] . e_who =
NFS4ACL_XATTR_EVERYONE_WHO ;
break ;
case SMB_ACE4_WHO_OWNER :
nfs4acl - > ace [ i ] . e_who =
NFS4ACL_XATTR_OWNER_WHO ;
break ;
case SMB_ACE4_WHO_GROUP :
nfs4acl - > ace [ i ] . e_who =
NFS4ACL_XATTR_GROUP_WHO ;
break ;
default :
DEBUG ( 8 , ( " unsupported special_id %d \n " , \
aceprop - > who . special_id ) ) ;
continue ; /* don't add it !!! */
}
have_special_id = true ;
} else {
nfs4acl - > ace [ i ] . e_who = " " ;
}
}
2013-04-16 16:11:27 +04:00
if ( ! have_special_id & & denymissingspecial ) {
TALLOC_FREE ( nfs4acl ) ;
2013-04-14 14:06:57 +04:00
errno = EACCES ;
return false ;
}
SMB_ASSERT ( i = = nfs4acl - > a_count ) ;
2013-04-16 16:11:27 +04:00
* pnfs4acl = nfs4acl ;
return true ;
}
static bool nfs4acl_xattr_set_smb4acl ( vfs_handle_struct * handle ,
2017-05-25 22:41:31 +03:00
const struct smb_filename * smb_fname ,
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * smbacl )
2013-04-16 16:11:27 +04:00
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct nfs4acl * nfs4acl ;
int ret ;
bool denymissingspecial ;
DATA_BLOB blob ;
denymissingspecial = lp_parm_bool ( handle - > conn - > params - > service ,
" nfs4acl_xattr " ,
" denymissingspecial " , false ) ;
if ( ! nfs4acl_smb4acl2nfs4acl ( frame , smbacl , & nfs4acl ,
denymissingspecial ) ) {
DEBUG ( 0 , ( " Failed to convert smb ACL to nfs4 ACL. \n " ) ) ;
TALLOC_FREE ( frame ) ;
return false ;
}
2013-04-14 14:06:57 +04:00
blob = nfs4acl_acl2blob ( frame , nfs4acl ) ;
if ( ! blob . data ) {
2013-04-16 16:11:27 +04:00
DEBUG ( 0 , ( " Failed to convert ACL to linear blob for xattr \n " ) ) ;
2013-04-14 14:06:57 +04:00
TALLOC_FREE ( frame ) ;
errno = EINVAL ;
return false ;
}
2017-05-25 22:41:31 +03:00
ret = SMB_VFS_NEXT_SETXATTR ( handle , smb_fname , NFS4ACL_XATTR_NAME ,
2013-04-16 16:11:27 +04:00
blob . data , blob . length , 0 ) ;
if ( ret ! = 0 ) {
DEBUG ( 0 , ( " can't store acl in xattr: %s \n " , strerror ( errno ) ) ) ;
}
2013-04-14 14:06:57 +04:00
TALLOC_FREE ( frame ) ;
2013-04-16 16:11:27 +04:00
return ret = = 0 ;
}
2013-04-14 14:06:57 +04:00
2013-04-16 16:11:27 +04:00
/* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */
static bool nfs4acl_xattr_fset_smb4acl ( vfs_handle_struct * handle ,
files_struct * fsp ,
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * smbacl )
2013-04-16 16:11:27 +04:00
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct nfs4acl * nfs4acl ;
int ret ;
bool denymissingspecial ;
DATA_BLOB blob ;
denymissingspecial = lp_parm_bool ( fsp - > conn - > params - > service ,
" nfs4acl_xattr " ,
" denymissingspecial " , false ) ;
if ( ! nfs4acl_smb4acl2nfs4acl ( frame , smbacl , & nfs4acl ,
denymissingspecial ) ) {
DEBUG ( 0 , ( " Failed to convert smb ACL to nfs4 ACL. \n " ) ) ;
TALLOC_FREE ( frame ) ;
return false ;
}
blob = nfs4acl_acl2blob ( frame , nfs4acl ) ;
if ( ! blob . data ) {
DEBUG ( 0 , ( " Failed to convert ACL to linear blob for xattr \n " ) ) ;
TALLOC_FREE ( frame ) ;
errno = EINVAL ;
return false ;
}
if ( fsp - > fh - > fd = = - 1 ) {
DEBUG ( 0 , ( " Error: fsp->fh->fd == -1 \n " ) ) ;
}
ret = SMB_VFS_NEXT_FSETXATTR ( handle , fsp , NFS4ACL_XATTR_NAME ,
blob . data , blob . length , 0 ) ;
if ( ret ! = 0 ) {
DEBUG ( 0 , ( " can't store acl in xattr: %s \n " , strerror ( errno ) ) ) ;
}
TALLOC_FREE ( frame ) ;
2013-04-14 14:06:57 +04:00
return ret = = 0 ;
}
/* nfs4_set_nt_acl()
* set the local file ' s acls obtaining it in NT form
* using the NFSv4 format conversion
*/
static NTSTATUS nfs4_set_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 )
{
2016-08-09 12:07:38 +03:00
return smb_set_nt_acl_nfs4 ( handle , fsp , NULL , security_info_sent , psd ,
2013-04-16 16:11:27 +04:00
nfs4acl_xattr_fset_smb4acl ) ;
}
2015-08-11 13:35:20 +03:00
static struct SMB4ACL_T * nfs4acls_defaultacl ( TALLOC_CTX * mem_ctx )
2013-04-16 16:11:27 +04:00
{
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl = NULL ;
2015-08-11 13:35:20 +03:00
struct SMB4ACE_T * pace ;
2015-04-10 12:29:59 +03:00
SMB_ACE4PROP_T ace = {
. flags = SMB_ACE4_ID_SPECIAL ,
. who = {
. id = SMB_ACE4_WHO_EVERYONE ,
} ,
. aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE ,
. aceFlags = 0 ,
. aceMask = SMB_ACE4_ALL_MASKS ,
} ;
2013-04-16 16:11:27 +04:00
DEBUG ( 10 , ( " Building default full access acl \n " ) ) ;
pacl = smb_create_smb4acl ( mem_ctx ) ;
if ( pacl = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
errno = ENOMEM ;
return NULL ;
}
pace = smb_add_ace4 ( pacl , & ace ) ;
if ( pace = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( pacl ) ;
errno = ENOMEM ;
return NULL ;
}
return pacl ;
}
/*
* Because there is no good way to guarantee that a new xattr will be
* created on file creation there might be no acl xattr on a file when
* trying to read the acl . In this case the acl xattr will get
* constructed at that time from the parent acl .
* If the parent ACL doesn ' t have an xattr either the call will
* recurse to the next parent directory until the share root is
* reached . If the share root doesn ' t contain an ACL xattr either a
* default ACL will be used .
* Also a default ACL will be set if a non inheriting ACL is encountered .
*
* Basic algorithm :
* read acl xattr blob
* if acl xattr blob doesn ' t exist
* stat current directory to know if it ' s a file or directory
* read acl xattr blob from parent dir
* acl xattr blob to smb nfs4 acl
* calculate inherited smb nfs4 acl
* without inheritance use default smb nfs4 acl
* smb nfs4 acl to acl xattr blob
* set acl xattr blob
* return smb nfs4 acl
* else
* acl xattr blob to smb nfs4 acl
*
* Todo : Really use mem_ctx after fixing interface of nfs4_acls
*/
2015-08-11 13:35:20 +03:00
static struct SMB4ACL_T * nfs4acls_inheritacl ( vfs_handle_struct * handle ,
2017-05-26 02:42:04 +03:00
const struct smb_filename * smb_fname_in ,
2013-04-16 16:11:27 +04:00
TALLOC_CTX * mem_ctx )
{
char * parent_dir = NULL ;
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pparentacl = NULL ;
struct SMB4ACL_T * pchildacl = NULL ;
2015-08-11 13:35:20 +03:00
struct SMB4ACE_T * pace ;
2013-04-16 16:11:27 +04:00
SMB_ACE4PROP_T ace ;
bool isdir ;
struct smb_filename * smb_fname = NULL ;
2017-05-26 02:42:04 +03:00
struct smb_filename * smb_fname_parent = NULL ;
2013-04-16 16:11:27 +04:00
NTSTATUS status ;
int ret ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2017-05-26 02:42:04 +03:00
DEBUG ( 10 , ( " nfs4acls_inheritacl invoked for %s \n " ,
smb_fname_in - > base_name ) ) ;
smb_fname = cp_smb_filename_nostream ( frame , smb_fname_in ) ;
2013-04-16 16:11:27 +04:00
if ( smb_fname = = NULL ) {
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return NULL ;
}
ret = SMB_VFS_STAT ( handle - > conn , smb_fname ) ;
if ( ret = = - 1 ) {
DEBUG ( 0 , ( " nfs4acls_inheritacl: failed to stat "
" directory %s. Error was %s \n " ,
smb_fname_str_dbg ( smb_fname ) ,
strerror ( errno ) ) ) ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
isdir = S_ISDIR ( smb_fname - > st . st_ex_mode ) ;
if ( ! parent_dirname ( talloc_tos ( ) ,
2017-05-26 02:42:04 +03:00
smb_fname - > base_name ,
2013-04-16 16:11:27 +04:00
& parent_dir ,
NULL ) ) {
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return NULL ;
}
2017-05-26 02:42:04 +03:00
smb_fname_parent = synthetic_smb_fname ( talloc_tos ( ) ,
parent_dir ,
NULL ,
NULL ,
0 ) ;
if ( smb_fname_parent = = NULL ) {
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return NULL ;
}
status = nfs4_get_nfs4_acl ( handle , frame , smb_fname_parent ,
& pparentacl ) ;
2013-04-16 16:11:27 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND )
& & strncmp ( parent_dir , " . " , 2 ) ! = 0 ) {
2017-05-26 02:42:04 +03:00
pparentacl = nfs4acls_inheritacl ( handle ,
smb_fname_parent ,
frame ) ;
2013-04-16 16:11:27 +04:00
}
else if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
pparentacl = nfs4acls_defaultacl ( frame ) ;
}
else if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return NULL ;
}
pchildacl = smb_create_smb4acl ( mem_ctx ) ;
if ( pchildacl = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return NULL ;
}
for ( pace = smb_first_ace4 ( pparentacl ) ; pace ! = NULL ;
pace = smb_next_ace4 ( pace ) ) {
2015-08-11 13:35:20 +03:00
struct SMB4ACE_T * pchildace ;
2013-04-16 16:11:27 +04:00
ace = * smb_get_ace4 ( pace ) ;
2015-04-10 12:29:59 +03:00
if ( ( isdir & & ! ( ace . aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE ) ) | |
( ! isdir & & ! ( ace . aceFlags & SMB_ACE4_FILE_INHERIT_ACE ) ) ) {
2013-04-16 16:11:27 +04:00
DEBUG ( 10 , ( " non inheriting ace type: %d, iflags: %x, "
" flags: %x, mask: %x, who: %d \n " ,
ace . aceType , ace . flags , ace . aceFlags ,
ace . aceMask , ace . who . id ) ) ;
continue ;
}
DEBUG ( 10 , ( " inheriting ace type: %d, iflags: %x, "
" flags: %x, mask: %x, who: %d \n " ,
ace . aceType , ace . flags , ace . aceFlags ,
ace . aceMask , ace . who . id ) ) ;
ace . aceFlags | = SMB_ACE4_INHERITED_ACE ;
2015-04-10 12:29:59 +03:00
if ( ace . aceFlags & SMB_ACE4_INHERIT_ONLY_ACE ) {
2013-04-16 16:11:27 +04:00
ace . aceFlags & = ~ SMB_ACE4_INHERIT_ONLY_ACE ;
}
if ( ace . aceFlags & SMB_ACE4_NO_PROPAGATE_INHERIT_ACE ) {
ace . aceFlags & = ~ SMB_ACE4_FILE_INHERIT_ACE ;
ace . aceFlags & = ~ SMB_ACE4_DIRECTORY_INHERIT_ACE ;
ace . aceFlags & = ~ SMB_ACE4_NO_PROPAGATE_INHERIT_ACE ;
}
pchildace = smb_add_ace4 ( pchildacl , & ace ) ;
if ( pchildace = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return NULL ;
}
}
/* Set a default ACL if we didn't inherit anything. */
if ( smb_first_ace4 ( pchildacl ) = = NULL ) {
TALLOC_FREE ( pchildacl ) ;
pchildacl = nfs4acls_defaultacl ( mem_ctx ) ;
}
/* store the returned ACL to get it directly in the
future and avoid dynamic inheritance behavior . */
2017-05-25 22:41:31 +03:00
nfs4acl_xattr_set_smb4acl ( handle , smb_fname , pchildacl ) ;
2013-04-16 16:11:27 +04:00
TALLOC_FREE ( frame ) ;
return pchildacl ;
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 ,
struct security_descriptor * * ppdesc )
{
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl ;
2013-04-14 14:06:57 +04:00
NTSTATUS status ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
status = nfs4_fget_nfs4_acl ( handle , frame , fsp , & pacl ) ;
2013-04-16 16:11:27 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
2017-05-26 02:42:04 +03:00
pacl = nfs4acls_inheritacl ( handle , fsp - > fsp_name ,
2013-04-16 16:11:27 +04:00
frame ) ;
}
else if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-04-14 14:06:57 +04:00
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 ,
ppdesc , pacl ) ;
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 ,
struct security_descriptor * * ppdesc )
{
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl ;
2013-04-14 14:06:57 +04:00
NTSTATUS status ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2017-05-26 02:42:04 +03:00
status = nfs4_get_nfs4_acl ( handle , frame , smb_fname , & pacl ) ;
2013-04-14 14:06:57 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
2017-05-26 02:42:04 +03:00
pacl = nfs4acls_inheritacl ( handle , smb_fname , frame ) ;
2013-04-14 14:06:57 +04:00
}
2013-04-16 16:11:27 +04:00
else if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-04-14 14:06:57 +04:00
TALLOC_FREE ( frame ) ;
return status ;
}
2016-08-09 12:07:38 +03:00
status = smb_get_nt_acl_nfs4 ( handle - > conn , smb_fname , NULL ,
security_info , mem_ctx , ppdesc ,
2013-04-14 14:06:57 +04:00
pacl ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
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 )
{
return nfs4_set_nt_acl ( handle , fsp , security_info_sent , psd ) ;
}
/*
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 = {
. 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 ,
. 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 ,
} ;
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 ) ;
}