2006-09-18 06:27:48 +04:00
/*
* Convert JFS2 NFS4 / AIXC acls to NT acls and vice versa .
*
* Copyright ( C ) Volker Lendecke , 2006
*
* 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
2007-07-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2006-09-18 06:27:48 +04:00
* ( 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
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2006-09-18 06:27:48 +04:00
*/
# include "includes.h"
2011-08-22 08:48:40 +04:00
# include "system/filesys.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2006-11-21 23:44:09 +03:00
# include "nfs4_acls.h"
2012-11-28 14:21:51 +04:00
# include "vfs_aixacl_util.h"
2006-09-18 06:27:48 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
# define AIXACL2_MODULE_NAME "aixacl2"
typedef union aixjfs2_acl_t {
nfs4_acl_int_t jfs2_acl [ 1 ] ;
aixc_acl_t aixc_acl [ 1 ] ;
} AIXJFS2_ACL_T ;
static int32_t aixacl2_getlen ( AIXJFS2_ACL_T * acl , acl_type_t * type )
{
int32_t len ;
if ( type - > u64 = = ACL_NFS4 ) {
len = acl - > jfs2_acl [ 0 ] . aclLength ;
}
else {
if ( type - > u64 = = ACL_AIXC ) {
len = acl - > aixc_acl [ 0 ] . acl_len ;
} else {
DEBUG ( 0 , ( " aixacl2_getlen:unknown type:%d \n " , type - > u64 ) ) ;
return False ;
}
}
DEBUG ( 10 , ( " aixacl2_getlen:%d \n " , len ) ) ;
return len ;
}
static AIXJFS2_ACL_T * aixjfs2_getacl_alloc ( const char * fname , acl_type_t * type )
{
AIXJFS2_ACL_T * acl ;
size_t len = 200 ;
mode_t mode ;
int ret ;
uint64_t ctl_flag = 0 ;
TALLOC_CTX * mem_ctx ;
2007-08-30 23:48:31 +04:00
mem_ctx = talloc_tos ( ) ;
2007-04-28 03:18:41 +04:00
acl = ( AIXJFS2_ACL_T * ) TALLOC_SIZE ( mem_ctx , len ) ;
2006-09-18 06:27:48 +04:00
if ( acl = = NULL ) {
errno = ENOMEM ;
return NULL ;
}
if ( type - > u64 = = ACL_ANY ) {
ctl_flag = ctl_flag | GET_ACLINFO_ONLY ;
}
ret = aclx_get ( ( char * ) fname , ctl_flag , type , acl , & len , & mode ) ;
if ( ( ret ! = 0 ) & & ( errno = = ENOSPC ) ) {
len = aixacl2_getlen ( acl , type ) + sizeof ( AIXJFS2_ACL_T ) ;
DEBUG ( 10 , ( " aixjfs2_getacl_alloc - acl_len:%d \n " , len ) ) ;
2007-04-28 03:18:41 +04:00
acl = ( AIXJFS2_ACL_T * ) TALLOC_SIZE ( mem_ctx , len ) ;
2006-09-18 06:27:48 +04:00
if ( acl = = NULL ) {
errno = ENOMEM ;
return NULL ;
}
ret = aclx_get ( ( char * ) fname , ctl_flag , type , acl , & len , & mode ) ;
}
if ( ret ! = 0 ) {
DEBUG ( 8 , ( " aclx_get failed with %s \n " , strerror ( errno ) ) ) ;
return NULL ;
}
return acl ;
}
2013-05-06 20:56:09 +04:00
static bool aixjfs2_get_nfs4_acl ( TALLOC_CTX * mem_ctx , const char * name ,
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * * ppacl , bool * pretryPosix )
2006-09-18 06:27:48 +04:00
{
int32_t i ;
AIXJFS2_ACL_T * pacl = NULL ;
nfs4_acl_int_t * jfs2_acl = NULL ;
nfs4_ace_int_t * jfs2_ace = NULL ;
acl_type_t type ;
2007-12-03 20:24:56 +03:00
DEBUG ( 10 , ( " jfs2 get_nt_acl invoked for %s \n " , name ) ) ;
2006-09-18 06:27:48 +04:00
memset ( & type , 0 , sizeof ( acl_type_t ) ) ;
type . u64 = ACL_NFS4 ;
2007-12-03 20:24:56 +03:00
pacl = aixjfs2_getacl_alloc ( name , & type ) ;
2006-09-18 06:27:48 +04:00
if ( pacl = = NULL ) {
DEBUG ( 9 , ( " aixjfs2_getacl_alloc failed for %s with %s \n " ,
2007-12-03 20:24:56 +03:00
name , strerror ( errno ) ) ) ;
2006-09-18 06:27:48 +04:00
if ( errno = = ENOSYS )
* pretryPosix = True ;
return False ;
}
jfs2_acl = & pacl - > jfs2_acl [ 0 ] ;
DEBUG ( 10 , ( " len: %d, version: %d, nace: %d, type: 0x%x \n " ,
jfs2_acl - > aclLength , jfs2_acl - > aclVersion , jfs2_acl - > aclEntryN , type . u64 ) ) ;
2013-04-14 12:13:42 +04:00
* ppacl = smb_create_smb4acl ( mem_ctx ) ;
2006-09-18 06:27:48 +04:00
if ( * ppacl = = NULL )
return False ;
jfs2_ace = & jfs2_acl - > aclEntry [ 0 ] ;
for ( i = 0 ; i < jfs2_acl - > aclEntryN ; i + + ) {
SMB_ACE4PROP_T aceprop ;
DEBUG ( 10 , ( " type: %d, iflags: %x, flags: %x, mask: %x, "
" who: %d, aclLen: %d \n " , jfs2_ace - > aceType , jfs2_ace - > flags ,
jfs2_ace - > aceFlags , jfs2_ace - > aceMask , jfs2_ace - > aceWho . id , jfs2_ace - > entryLen ) ) ;
aceprop . aceType = jfs2_ace - > aceType ;
aceprop . aceFlags = jfs2_ace - > aceFlags ;
aceprop . aceMask = jfs2_ace - > aceMask ;
aceprop . flags = ( jfs2_ace - > flags & ACE4_ID_SPECIAL ) ? SMB_ACE4_ID_SPECIAL : 0 ;
/* don't care it's real content is only 16 or 32 bit */
aceprop . who . id = jfs2_ace - > aceWho . id ;
if ( smb_add_ace4 ( * ppacl , & aceprop ) = = NULL )
return False ;
/* iterate to the next jfs2 ace */
jfs2_ace = ( nfs4_ace_int_t * ) ( ( ( char * ) jfs2_ace ) + jfs2_ace - > entryLen ) ;
}
DEBUG ( 10 , ( " jfs2 get_nt_acl finished successfully \n " ) ) ;
return True ;
}
2007-12-03 20:31:03 +03:00
static NTSTATUS aixjfs2_fget_nt_acl ( vfs_handle_struct * handle ,
2015-05-03 06:11:02 +03:00
files_struct * fsp , uint32_t security_info ,
2012-10-10 04:50:27 +04:00
TALLOC_CTX * mem_ctx ,
2010-05-18 12:29:34 +04:00
struct security_descriptor * * ppdesc )
2006-09-18 06:27:48 +04:00
{
2013-04-14 12:13:42 +04:00
NTSTATUS status ;
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl = NULL ;
2007-10-19 04:40:25 +04:00
bool result ;
bool retryPosix = False ;
2013-04-14 12:13:42 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2006-09-18 06:27:48 +04:00
* ppdesc = NULL ;
2013-04-14 12:13:42 +04:00
result = aixjfs2_get_nfs4_acl ( frame , fsp - > fsp_name - > base_name , & pacl ,
2009-07-11 05:11:32 +04:00
& retryPosix ) ;
2006-09-18 06:27:48 +04:00
if ( retryPosix )
{
2013-04-14 12:13:42 +04:00
TALLOC_FREE ( frame ) ;
2006-09-18 06:27:48 +04:00
DEBUG ( 10 , ( " retrying with posix acl... \n " ) ) ;
2012-10-10 04:50:27 +04:00
return posix_fget_nt_acl ( fsp , security_info ,
mem_ctx , ppdesc ) ;
2006-09-18 06:27:48 +04:00
}
2013-05-08 01:04:24 +04:00
if ( result = = False ) {
TALLOC_FREE ( frame ) ;
2007-10-13 23:06:49 +04:00
return NT_STATUS_ACCESS_DENIED ;
2013-05-08 01:04:24 +04:00
}
2006-09-18 06:27:48 +04:00
2021-03-03 13:20:51 +03:00
status = smb_fget_nt_acl_nfs4 (
fsp , NULL , security_info , mem_ctx , ppdesc , pacl ) ;
2013-04-14 12:13:42 +04:00
TALLOC_FREE ( frame ) ;
return status ;
2006-09-18 06:27:48 +04:00
}
2012-10-10 09:52:17 +04:00
static int aixjfs2_sys_acl_blob_get_fd ( vfs_handle_struct * handle , files_struct * fsp , TALLOC_CTX * mem_ctx , char * * blob_description , DATA_BLOB * blob )
{
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl = NULL ;
2012-10-10 09:52:17 +04:00
bool result ;
bool retryPosix = False ;
2013-05-06 20:56:09 +04:00
result = aixjfs2_get_nfs4_acl ( mem_ctx , fsp - > fsp_name - > base_name , & pacl ,
2012-10-10 09:52:17 +04:00
& retryPosix ) ;
if ( retryPosix )
{
return posix_sys_acl_blob_get_fd ( handle , fsp , mem_ctx , blob_description , blob ) ;
}
/* Now way to linarlise NFS4 ACLs at the moment, but the NT ACL is pretty close in this case */
errno = ENOSYS ;
return - 1 ;
}
2012-10-10 03:18:32 +04:00
static SMB_ACL_T aixjfs2_get_posix_acl ( const char * path , acl_type_t type , TALLOC_CTX * mem_ctx )
2006-09-18 06:27:48 +04:00
{
aixc_acl_t * pacl ;
AIXJFS2_ACL_T * acl ;
SMB_ACL_T result = NULL ;
int ret ;
acl = aixjfs2_getacl_alloc ( path , & type ) ;
if ( acl = = NULL ) {
DEBUG ( 10 , ( " aixjfs2_getacl failed for %s with %s \n " ,
path , strerror ( errno ) ) ) ;
if ( errno = = 0 ) {
errno = EINVAL ;
}
goto done ;
}
pacl = & acl - > aixc_acl [ 0 ] ;
DEBUG ( 10 , ( " len: %d, mode: %d \n " ,
pacl - > acl_len , pacl - > acl_mode ) ) ;
2012-10-10 03:18:32 +04:00
result = aixacl_to_smbacl ( pacl , mem_ctx ) ;
2006-09-18 06:27:48 +04:00
if ( result = = NULL ) {
goto done ;
}
done :
if ( errno ! = 0 ) {
2012-08-12 14:41:35 +04:00
TALLOC_FREE ( result ) ;
2006-09-18 06:27:48 +04:00
}
return result ;
}
SMB_ACL_T aixjfs2_sys_acl_get_fd ( vfs_handle_struct * handle ,
2021-05-14 17:26:46 +03:00
files_struct * fsp ,
SMB_ACL_TYPE_T type ,
TALLOC_CTX * mem_ctx )
2006-09-18 06:27:48 +04:00
{
acl_type_t aixjfs2_type ;
2021-05-14 17:26:46 +03:00
switch ( type ) {
case SMB_ACL_TYPE_ACCESS :
aixjfs2_type . u64 = ACL_AIXC ;
break ;
case SMB_ACL_TYPE_DEFAULT :
DEBUG ( 0 , ( " Got AIX JFS2 unsupported type: %d \n " , type ) ) ;
return NULL ;
default :
DEBUG ( 0 , ( " Got invalid type: %d \n " , type ) ) ;
smb_panic ( " exiting " ) ;
}
2006-09-18 06:27:48 +04:00
2013-05-06 20:56:09 +04:00
return aixjfs2_get_posix_acl ( fsp - > fsp_name - > base_name ,
aixjfs2_type , mem_ctx ) ;
2006-09-18 06:27:48 +04:00
}
/*
* Test whether we have that aclType support on the given path
*/
static int aixjfs2_query_acl_support (
char * filepath ,
uint64_t aclType ,
acl_type_t * pacl_type_info
)
{
2015-05-03 06:11:02 +03:00
acl_types_list_t acl_type_list ;
size_t acl_type_list_len = sizeof ( acl_types_list_t ) ;
uint32_t i ;
2006-09-18 06:27:48 +04:00
memset ( & acl_type_list , 0 , sizeof ( acl_type_list ) ) ;
if ( aclx_gettypes ( filepath , & acl_type_list , & acl_type_list_len ) ) {
DEBUG ( 2 , ( " aclx_gettypes failed with error %s for %s \n " ,
strerror ( errno ) , filepath ) ) ;
return - 1 ;
}
for ( i = 0 ; i < acl_type_list . num_entries ; i + + ) {
if ( acl_type_list . entries [ i ] . u64 = = aclType ) {
memcpy ( pacl_type_info , acl_type_list . entries + i , sizeof ( acl_type_t ) ) ;
DEBUG ( 10 , ( " found %s ACL support for %s \n " ,
pacl_type_info - > acl_type , filepath ) ) ;
return 0 ;
}
}
return 1 ; /* haven't found that ACL type. */
}
2015-08-11 13:35:20 +03:00
static bool aixjfs2_process_smbacl ( vfs_handle_struct * handle ,
files_struct * fsp ,
struct SMB4ACL_T * smbacl )
2006-09-18 06:27:48 +04:00
{
2015-08-11 13:35:20 +03:00
struct SMB4ACE_T * smbace ;
2006-09-18 06:27:48 +04:00
TALLOC_CTX * mem_ctx ;
nfs4_acl_int_t * jfs2acl ;
2015-05-03 06:11:02 +03:00
int32_t entryLen ;
uint32_t aclLen , naces ;
int rc ;
2006-09-18 06:27:48 +04:00
acl_type_t acltype ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " jfs2_process_smbacl invoked on %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2006-09-18 06:27:48 +04:00
/* no need to be freed which is alloced with mem_ctx */
2007-08-30 23:48:31 +04:00
mem_ctx = talloc_tos ( ) ;
2006-09-18 06:27:48 +04:00
entryLen = sizeof ( nfs4_ace_int_t ) ;
if ( entryLen & 0x03 )
entryLen = entryLen + 4 - ( entryLen % 4 ) ;
naces = smb_get_naces ( smbacl ) ;
aclLen = ACL_V4_SIZ + naces * entryLen ;
2007-04-28 03:18:41 +04:00
jfs2acl = ( nfs4_acl_int_t * ) TALLOC_SIZE ( mem_ctx , aclLen ) ;
2006-09-18 06:27:48 +04:00
if ( jfs2acl = = NULL ) {
2007-04-28 03:18:41 +04:00
DEBUG ( 0 , ( " TALLOC_SIZE failed \n " ) ) ;
2006-09-18 06:27:48 +04:00
errno = ENOMEM ;
return False ;
}
jfs2acl - > aclLength = ACL_V4_SIZ ;
jfs2acl - > aclVersion = NFS4_ACL_INT_STRUCT_VERSION ;
jfs2acl - > aclEntryN = 0 ;
for ( smbace = smb_first_ace4 ( smbacl ) ; smbace ! = NULL ; smbace = smb_next_ace4 ( smbace ) )
{
SMB_ACE4PROP_T * aceprop = smb_get_ace4 ( smbace ) ;
nfs4_ace_int_t * jfs2_ace = ( nfs4_ace_int_t * ) ( ( ( char * ) jfs2acl ) + jfs2acl - > aclLength ) ;
memset ( jfs2_ace , 0 , entryLen ) ;
jfs2_ace - > entryLen = entryLen ; /* won't store textual "who" */
jfs2_ace - > aceType = aceprop - > aceType ; /* only ACCES|DENY supported by jfs2 */
jfs2_ace - > aceFlags = aceprop - > aceFlags ;
jfs2_ace - > aceMask = aceprop - > aceMask ;
jfs2_ace - > flags = ( aceprop - > flags & SMB_ACE4_ID_SPECIAL ) ? ACE4_ID_SPECIAL : 0 ;
/* don't care it's real content is only 16 or 32 bit */
jfs2_ace - > aceWho . id = aceprop - > who . id ;
/* iterate to the next jfs2 ace */
jfs2acl - > aclLength + = jfs2_ace - > entryLen ;
jfs2acl - > aclEntryN + + ;
}
SMB_ASSERT ( jfs2acl - > aclEntryN = = naces ) ;
/* Don't query it (again) */
memset ( & acltype , 0 , sizeof ( acl_type_t ) ) ;
acltype . u64 = ACL_NFS4 ;
/* won't set S_ISUID - the only one JFS2/NFS4 accepts */
rc = aclx_put (
2009-07-11 05:11:32 +04:00
fsp - > fsp_name - > base_name ,
2006-09-18 06:27:48 +04:00
SET_ACL , /* set only the ACL, not mode bits */
acltype , /* not a pointer !!! */
jfs2acl ,
jfs2acl - > aclLength ,
0 /* don't set here mode bits */
) ;
if ( rc ) {
DEBUG ( 8 , ( " aclx_put failed with %s \n " , strerror ( errno ) ) ) ;
return False ;
}
DEBUG ( 10 , ( " jfs2_process_smbacl succeeded. \n " ) ) ;
return True ;
}
2015-05-03 06:11:02 +03:00
static NTSTATUS aixjfs2_set_nt_acl_common ( vfs_handle_struct * handle , files_struct * fsp , uint32_t security_info_sent , const struct security_descriptor * psd )
2006-09-18 06:27:48 +04:00
{
acl_type_t acl_type_info ;
2007-06-27 02:49:10 +04:00
NTSTATUS result = NT_STATUS_ACCESS_DENIED ;
2006-09-18 06:27:48 +04:00
int rc ;
rc = aixjfs2_query_acl_support (
2013-05-06 20:56:09 +04:00
fsp - > fsp_name - > base_name ,
2006-09-18 06:27:48 +04:00
ACL_NFS4 ,
& acl_type_info ) ;
if ( rc = = 0 )
{
2013-04-14 11:31:42 +04:00
result = smb_set_nt_acl_nfs4 ( handle ,
2016-08-09 12:07:38 +03:00
fsp , NULL , security_info_sent , psd ,
2006-09-18 06:27:48 +04:00
aixjfs2_process_smbacl ) ;
} else if ( rc = = 1 ) { /* assume POSIX ACL - by default... */
result = set_nt_acl ( fsp , security_info_sent , psd ) ;
} else
2007-06-27 02:49:10 +04:00
result = map_nt_error_from_unix ( errno ) ; /* query failed */
2006-09-18 06:27:48 +04:00
return result ;
}
2015-05-03 06:11:02 +03:00
NTSTATUS aixjfs2_fset_nt_acl ( vfs_handle_struct * handle , files_struct * fsp , uint32_t security_info_sent , const struct security_descriptor * psd )
2006-09-18 06:27:48 +04:00
{
2013-04-14 11:31:42 +04:00
return aixjfs2_set_nt_acl_common ( handle , fsp , security_info_sent , psd ) ;
2006-09-18 06:27:48 +04:00
}
int aixjfs2_sys_acl_set_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
2020-12-14 18:28:26 +03:00
SMB_ACL_TYPE_T type ,
2008-01-08 03:54:19 +03:00
SMB_ACL_T theacl )
2006-09-18 06:27:48 +04:00
{
struct acl * acl_aixc ;
acl_type_t acl_type_info ;
int rc ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " aixjfs2_sys_acl_set_fd invoked for %s " , fsp_str_dbg ( fsp ) ) ) ;
2006-09-18 06:27:48 +04:00
2009-07-11 05:11:32 +04:00
rc = aixjfs2_query_acl_support ( fsp - > fsp_name - > base_name , ACL_AIXC ,
& acl_type_info ) ;
2006-09-18 06:27:48 +04:00
if ( rc ) {
DEBUG ( 8 , ( " jfs2_set_nt_acl: AIXC support not found \n " ) ) ;
return - 1 ;
}
2020-12-13 11:07:51 +03:00
acl_aixc = aixacl_smb_to_aixacl ( type , theacl ) ;
2006-09-18 06:27:48 +04:00
if ( ! acl_aixc )
return - 1 ;
2020-12-14 12:07:04 +03:00
if ( fsp - > fsp_flags . is_pathref ) {
/*
* This is no longer a handle based call .
*/
return aclx_put ( fsp - > fsp_name - > base_name ,
SET_ACL ,
acl_type_info ,
acl_aixc ,
acl_aixc - > acl_len ,
0 ) ;
}
2006-09-18 06:27:48 +04:00
rc = aclx_fput (
2020-09-26 22:52:52 +03:00
fsp_get_io_fd ( fsp ) ,
2006-09-18 06:27:48 +04:00
SET_ACL , /* set only the ACL, not mode bits */
acl_type_info ,
acl_aixc ,
acl_aixc - > acl_len ,
0
) ;
if ( rc ) {
DEBUG ( 2 , ( " aclx_fput failed with %s for %s \n " ,
2009-07-11 05:11:32 +04:00
strerror ( errno ) , fsp_str_dbg ( fsp ) ) ) ;
2006-09-18 06:27:48 +04:00
return - 1 ;
}
return 0 ;
}
2021-05-15 00:30:29 +03:00
int aixjfs2_sys_acl_delete_def_fd ( vfs_handle_struct * handle ,
files_struct * fsp )
{
/* Not available under AIXC ACL */
/* Don't report here any error otherwise */
/* upper layer will break the normal execution */
return 0 ;
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_aixacl2_fns = {
2011-12-04 08:45:04 +04:00
. fget_nt_acl_fn = aixjfs2_fget_nt_acl ,
. fset_nt_acl_fn = aixjfs2_fset_nt_acl ,
. sys_acl_get_fd_fn = aixjfs2_sys_acl_get_fd ,
2012-10-10 09:52:17 +04:00
. sys_acl_blob_get_fd_fn = aixjfs2_sys_acl_blob_get_fd ,
2011-12-04 08:45:04 +04:00
. sys_acl_set_fd_fn = aixjfs2_sys_acl_set_fd ,
2021-05-15 00:30:29 +03:00
. sys_acl_delete_def_fd_fn = aixjfs2_sys_acl_delete_def_fd
2010-03-02 15:00:19 +03:00
} ;
2006-09-18 06:27:48 +04:00
2017-12-16 01:32:12 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_aixacl2_init ( TALLOC_CTX * ctx )
2006-09-18 06:27:48 +04:00
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , AIXACL2_MODULE_NAME ,
2009-07-24 04:28:58 +04:00
& vfs_aixacl2_fns ) ;
2006-09-18 06:27:48 +04:00
}