2006-07-21 19:51:34 +04:00
/*
Unix SMB / Netbios implementation .
VFS module to get and set Tru64 acls
Copyright ( C ) Michael Adam 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-07-21 19:51:34 +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 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-07-21 19:51:34 +04:00
*/
# include "includes.h"
/* prototypes for private functions first - for clarity */
static struct smb_acl_t * tru64_acl_to_smb_acl ( const struct acl * tru64_acl ) ;
static BOOL tru64_ace_to_smb_ace ( acl_entry_t tru64_ace ,
struct smb_acl_entry * smb_ace ) ;
static acl_t smb_acl_to_tru64_acl ( const SMB_ACL_T smb_acl ) ;
static acl_tag_t smb_tag_to_tru64 ( SMB_ACL_TAG_T smb_tag ) ;
static SMB_ACL_TAG_T tru64_tag_to_smb ( acl_tag_t tru64_tag ) ;
2007-05-16 01:41:02 +04:00
static acl_perm_t smb_permset_to_tru64 ( SMB_ACL_PERM_T smb_permset ) ;
static SMB_ACL_PERM_T tru64_permset_to_smb ( const acl_perm_t tru64_permset ) ;
2006-07-21 19:51:34 +04:00
/* public functions - the api */
SMB_ACL_T tru64acl_sys_acl_get_file ( vfs_handle_struct * handle ,
const char * path_p ,
SMB_ACL_TYPE_T type )
{
struct smb_acl_t * result ;
acl_type_t the_acl_type ;
acl_t tru64_acl ;
DEBUG ( 10 , ( " Hi! This is tru64acl_sys_acl_get_file. \n " ) ) ;
switch ( type ) {
case SMB_ACL_TYPE_ACCESS :
the_acl_type = ACL_TYPE_ACCESS ;
break ;
case SMB_ACL_TYPE_DEFAULT :
the_acl_type = ACL_TYPE_DEFAULT ;
break ;
default :
errno = EINVAL ;
return NULL ;
}
tru64_acl = acl_get_file ( ( char * ) path_p , the_acl_type ) ;
if ( tru64_acl = = NULL ) {
return NULL ;
}
result = tru64_acl_to_smb_acl ( tru64_acl ) ;
acl_free ( tru64_acl ) ;
return result ;
}
SMB_ACL_T tru64acl_sys_acl_get_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
int fd )
{
struct smb_acl_t * result ;
acl_t tru64_acl = acl_get_fd ( fd , ACL_TYPE_ACCESS ) ;
if ( tru64_acl = = NULL ) {
return NULL ;
}
result = tru64_acl_to_smb_acl ( tru64_acl ) ;
acl_free ( tru64_acl ) ;
return result ;
}
int tru64acl_sys_acl_set_file ( vfs_handle_struct * handle ,
const char * name ,
SMB_ACL_TYPE_T type ,
SMB_ACL_T theacl )
{
int res ;
acl_type_t the_acl_type ;
acl_t tru64_acl ;
DEBUG ( 10 , ( " tru64acl_sys_acl_set_file called with name %s, type %d \n " ,
name , type ) ) ;
switch ( type ) {
case SMB_ACL_TYPE_ACCESS :
DEBUGADD ( 10 , ( " got acl type ACL_TYPE_ACCESS \n " ) ) ;
the_acl_type = ACL_TYPE_ACCESS ;
break ;
case SMB_ACL_TYPE_DEFAULT :
DEBUGADD ( 10 , ( " got acl type ACL_TYPE_DEFAULT \n " ) ) ;
the_acl_type = ACL_TYPE_DEFAULT ;
break ;
default :
DEBUGADD ( 10 , ( " invalid acl type \n " ) ) ;
errno = EINVAL ;
goto fail ;
}
tru64_acl = smb_acl_to_tru64_acl ( theacl ) ;
if ( tru64_acl = = NULL ) {
DEBUG ( 10 , ( " smb_acl_to_tru64_acl failed! \n " ) ) ;
goto fail ;
}
DEBUG ( 10 , ( " got tru64 acl... \n " ) ) ;
res = acl_set_file ( ( char * ) name , the_acl_type , tru64_acl ) ;
acl_free ( tru64_acl ) ;
if ( res ! = 0 ) {
DEBUG ( 10 , ( " acl_set_file failed: %s \n " , strerror ( errno ) ) ) ;
goto fail ;
}
return res ;
fail :
DEBUG ( 1 , ( " tru64acl_sys_acl_set_file failed! \n " ) ) ;
return - 1 ;
}
int tru64acl_sys_acl_set_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
int fd , SMB_ACL_T theacl )
{
int res ;
acl_t tru64_acl = smb_acl_to_tru64_acl ( theacl ) ;
if ( tru64_acl = = NULL ) {
return - 1 ;
}
res = acl_set_fd ( fd , ACL_TYPE_ACCESS , tru64_acl ) ;
acl_free ( tru64_acl ) ;
return res ;
}
int tru64acl_sys_acl_delete_def_file ( vfs_handle_struct * handle ,
const char * path )
{
return acl_delete_def_file ( ( char * ) path ) ;
}
/* private functions */
static struct smb_acl_t * tru64_acl_to_smb_acl ( const struct acl * tru64_acl )
{
struct smb_acl_t * result ;
acl_entry_t entry ;
DEBUG ( 10 , ( " Hi! This is tru64_acl_to_smb_acl. \n " ) ) ;
if ( ( result = SMB_MALLOC_P ( struct smb_acl_t ) ) = = NULL ) {
DEBUG ( 0 , ( " SMB_MALLOC_P failed in tru64_acl_to_smb_acl \n " ) ) ;
errno = ENOMEM ;
goto fail ;
}
ZERO_STRUCTP ( result ) ;
if ( acl_first_entry ( ( struct acl * ) tru64_acl ) ! = 0 ) {
DEBUG ( 10 , ( " acl_first_entry failed: %s \n " , strerror ( errno ) ) ) ;
goto fail ;
}
while ( ( entry = acl_get_entry ( ( struct acl * ) tru64_acl ) ) ! = NULL ) {
result = SMB_REALLOC ( result , sizeof ( struct smb_acl_t ) +
( sizeof ( struct smb_acl_entry ) *
( result - > count + 1 ) ) ) ;
if ( result = = NULL ) {
DEBUG ( 0 , ( " SMB_REALLOC failed in tru64_acl_to_smb_acl \n " ) ) ;
errno = ENOMEM ;
goto fail ;
}
/* XYZ */
if ( ! tru64_ace_to_smb_ace ( entry , & result - > acl [ result - > count ] ) ) {
SAFE_FREE ( result ) ;
goto fail ;
}
result - > count + = 1 ;
}
return result ;
fail :
if ( result ! = NULL ) {
SAFE_FREE ( result ) ;
}
DEBUG ( 1 , ( " tru64_acl_to_smb_acl failed! \n " ) ) ;
return NULL ;
}
static BOOL tru64_ace_to_smb_ace ( acl_entry_t tru64_ace ,
struct smb_acl_entry * smb_ace )
{
acl_tag_t tru64_tag ;
acl_permset_t permset ;
SMB_ACL_TAG_T smb_tag_type ;
2007-05-16 01:41:02 +04:00
SMB_ACL_PERM_T smb_permset ;
2006-07-21 19:51:34 +04:00
void * qualifier ;
if ( acl_get_tag_type ( tru64_ace , & tru64_tag ) ! = 0 ) {
DEBUG ( 0 , ( " acl_get_tag_type failed: %s \n " , strerror ( errno ) ) ) ;
return False ;
}
/* On could set the tag type directly to save a function call,
* but I like this better . . . */
smb_tag_type = tru64_tag_to_smb ( tru64_tag ) ;
if ( smb_tag_type = = 0 ) {
DEBUG ( 3 , ( " invalid tag type given: %d \n " , tru64_tag ) ) ;
return False ;
}
if ( sys_acl_set_tag_type ( smb_ace , smb_tag_type ) ! = 0 ) {
DEBUG ( 3 , ( " sys_acl_set_tag_type failed: %s \n " ,
strerror ( errno ) ) ) ;
return False ;
}
qualifier = acl_get_qualifier ( tru64_ace ) ;
if ( qualifier ! = NULL ) {
if ( sys_acl_set_qualifier ( smb_ace , qualifier ) ! = 0 ) {
DEBUG ( 3 , ( " sys_acl_set_qualifier failed \n " ) ) ;
return False ;
}
}
if ( acl_get_permset ( tru64_ace , & permset ) ! = 0 ) {
DEBUG ( 3 , ( " acl_get_permset failed: %s \n " , strerror ( errno ) ) ) ;
return False ;
}
smb_permset = tru64_permset_to_smb ( * permset ) ;
if ( sys_acl_set_permset ( smb_ace , & smb_permset ) ! = 0 ) {
DEBUG ( 3 , ( " sys_acl_set_permset failed: %s \n " , strerror ( errno ) ) ) ;
return False ;
}
return True ;
}
static acl_t smb_acl_to_tru64_acl ( const SMB_ACL_T smb_acl )
{
acl_t result ;
acl_entry_t tru64_entry ;
int i ;
char * acl_text ;
ssize_t acl_text_len ;
/* The tru64 acl_init function takes a size_t value
* instead of a count of entries ( as with posix ) .
* the size parameter " Specifies the size of the working
* storage in bytes " (according to the man page).
* But it is unclear to me , how this size is to be
* calculated .
*
* It should not matter , since acl_create_entry enlarges
* the working storage at need . . . . */
DEBUG ( 10 , ( " Hi! This is smb_acl_to_tru64_acl. \n " ) ) ;
result = acl_init ( 1 ) ;
if ( result = = NULL ) {
DEBUG ( 3 , ( " acl_init failed! \n " ) ) ;
goto fail ;
}
DEBUGADD ( 10 , ( " parsing acl entries... \n " ) ) ;
for ( i = 0 ; i < smb_acl - > count ; i + + ) {
/* XYZ - maybe eliminate this direct access? */
const struct smb_acl_entry * smb_entry = & smb_acl - > acl [ i ] ;
acl_tag_t tru64_tag ;
acl_perm_t tru64_permset ;
tru64_tag = smb_tag_to_tru64 ( smb_entry - > a_type ) ;
if ( tru64_tag = = - 1 ) {
DEBUG ( 3 , ( " smb_tag_to_tru64 failed! \n " ) ) ;
goto fail ;
}
if ( tru64_tag = = ACL_MASK ) {
DEBUGADD ( 10 , ( " - acl type ACL_MASK: not implemented on Tru64 ==> skipping \n " ) ) ;
continue ;
}
tru64_entry = acl_create_entry ( & result ) ;
if ( tru64_entry = = NULL ) {
DEBUG ( 3 , ( " acl_create_entry failed: %s \n " ,
strerror ( errno ) ) ) ;
goto fail ;
}
if ( acl_set_tag_type ( tru64_entry , tru64_tag ) ! = 0 ) {
DEBUG ( 3 , ( " acl_set_tag_type(%d) failed: %s \n " ,
strerror ( errno ) ) ) ;
goto fail ;
}
switch ( smb_entry - > a_type ) {
case SMB_ACL_USER :
if ( acl_set_qualifier ( tru64_entry ,
( int * ) & smb_entry - > uid ) ! = 0 )
{
DEBUG ( 3 , ( " acl_set_qualifier failed: %s \n " ,
strerror ( errno ) ) ) ;
goto fail ;
}
DEBUGADD ( 10 , ( " - setting uid to %d \n " , smb_entry - > uid ) ) ;
break ;
case SMB_ACL_GROUP :
if ( acl_set_qualifier ( tru64_entry ,
( int * ) & smb_entry - > gid ) ! = 0 )
{
DEBUG ( 3 , ( " acl_set_qualifier failed: %s \n " ,
strerror ( errno ) ) ) ;
goto fail ;
}
DEBUGADD ( 10 , ( " - setting gid to %d \n " , smb_entry - > gid ) ) ;
break ;
default :
break ;
}
tru64_permset = smb_permset_to_tru64 ( smb_entry - > a_perm ) ;
if ( tru64_permset = = - 1 ) {
DEBUG ( 3 , ( " smb_permset_to_tru64 failed! \n " ) ) ;
goto fail ;
}
DEBUGADD ( 10 , ( " - setting perms to %0d \n " , tru64_permset ) ) ;
if ( acl_set_permset ( tru64_entry , & tru64_permset ) ! = 0 )
{
DEBUG ( 3 , ( " acl_set_permset failed: %s \n " , strerror ( errno ) ) ) ;
goto fail ;
}
} /* for */
DEBUGADD ( 10 , ( " done parsing acl entries \n " ) ) ;
tru64_entry = NULL ;
if ( acl_valid ( result , & tru64_entry ) ! = 0 ) {
DEBUG ( 1 , ( " smb_acl_to_tru64_acl: ACL is invalid (%s) \n " ,
strerror ( errno ) ) ) ;
if ( tru64_entry ! = NULL ) {
DEBUGADD ( 1 , ( " the acl contains duplicate entries \n " ) ) ;
}
goto fail ;
}
DEBUGADD ( 10 , ( " acl is valid \n " ) ) ;
acl_text = acl_to_text ( result , & acl_text_len ) ;
if ( acl_text = = NULL ) {
DEBUG ( 3 , ( " acl_to_text failed: %s \n " , strerror ( errno ) ) ) ;
goto fail ;
}
DEBUG ( 1 , ( " acl_text: %s \n " , acl_text ) ) ;
free ( acl_text ) ;
return result ;
fail :
if ( result ! = NULL ) {
acl_free ( result ) ;
}
DEBUG ( 1 , ( " smb_acl_to_tru64_acl failed! \n " ) ) ;
return NULL ;
}
static acl_tag_t smb_tag_to_tru64 ( SMB_ACL_TAG_T smb_tag )
{
acl_tag_t result ;
switch ( smb_tag ) {
case SMB_ACL_USER :
result = ACL_USER ;
DEBUGADD ( 10 , ( " got acl type ACL_USER \n " ) ) ;
break ;
case SMB_ACL_USER_OBJ :
result = ACL_USER_OBJ ;
DEBUGADD ( 10 , ( " got acl type ACL_USER_OBJ \n " ) ) ;
break ;
case SMB_ACL_GROUP :
result = ACL_GROUP ;
DEBUGADD ( 10 , ( " got acl type ACL_GROUP \n " ) ) ;
break ;
case SMB_ACL_GROUP_OBJ :
result = ACL_GROUP_OBJ ;
DEBUGADD ( 10 , ( " got acl type ACL_GROUP_OBJ \n " ) ) ;
break ;
case SMB_ACL_OTHER :
result = ACL_OTHER ;
DEBUGADD ( 10 , ( " got acl type ACL_OTHER \n " ) ) ;
break ;
case SMB_ACL_MASK :
result = ACL_MASK ;
DEBUGADD ( 10 , ( " got acl type ACL_MASK \n " ) ) ;
break ;
default :
DEBUG ( 1 , ( " Unknown tag type %d \n " , smb_tag ) ) ;
result = - 1 ;
}
return result ;
}
static SMB_ACL_TAG_T tru64_tag_to_smb ( acl_tag_t tru64_tag )
{
SMB_ACL_TAG_T smb_tag_type ;
switch ( tru64_tag ) {
case ACL_USER :
smb_tag_type = SMB_ACL_USER ;
DEBUGADD ( 10 , ( " got smb acl tag type SMB_ACL_USER \n " ) ) ;
break ;
case ACL_USER_OBJ :
smb_tag_type = SMB_ACL_USER_OBJ ;
DEBUGADD ( 10 , ( " got smb acl tag type SMB_ACL_USER_OBJ \n " ) ) ;
break ;
case ACL_GROUP :
smb_tag_type = SMB_ACL_GROUP ;
DEBUGADD ( 10 , ( " got smb acl tag type SMB_ACL_GROUP \n " ) ) ;
break ;
case ACL_GROUP_OBJ :
smb_tag_type = SMB_ACL_GROUP_OBJ ;
DEBUGADD ( 10 , ( " got smb acl tag type SMB_ACL_GROUP_OBJ \n " ) ) ;
break ;
case ACL_OTHER :
smb_tag_type = SMB_ACL_OTHER ;
DEBUGADD ( 10 , ( " got smb acl tag type SMB_ACL_OTHER \n " ) ) ;
break ;
case ACL_MASK :
smb_tag_type = SMB_ACL_MASK ;
DEBUGADD ( 10 , ( " got smb acl tag type SMB_ACL_MASK \n " ) ) ;
break ;
default :
DEBUG ( 0 , ( " Unknown tag type %d \n " , ( unsigned int ) tru64_tag ) ) ;
smb_tag_type = 0 ;
}
return smb_tag_type ;
}
2007-05-16 01:41:02 +04:00
static acl_perm_t smb_permset_to_tru64 ( SMB_ACL_PERM_T smb_permset )
2006-07-21 19:51:34 +04:00
{
/* originally, I thought that acl_clear_perm was the
* proper way to reset the permset to 0. but without
* initializing it to 0 , acl_clear_perm fails .
* so probably , acl_clear_perm is not necessary here . . . ? ! */
acl_perm_t tru64_permset = 0 ;
if ( acl_clear_perm ( & tru64_permset ) ! = 0 ) {
DEBUG ( 5 , ( " acl_clear_perm failed: %s \n " , strerror ( errno ) ) ) ;
return - 1 ;
}
/* according to original lib/sysacls.c, acl_add_perm is
* broken on tru64 . . . */
tru64_permset | = ( ( smb_permset & SMB_ACL_READ ) ? ACL_READ : 0 ) ;
tru64_permset | = ( ( smb_permset & SMB_ACL_WRITE ) ? ACL_WRITE : 0 ) ;
tru64_permset | = ( ( smb_permset & SMB_ACL_EXECUTE ) ? ACL_EXECUTE : 0 ) ;
return tru64_permset ;
}
2007-05-16 01:41:02 +04:00
static SMB_ACL_PERM_T tru64_permset_to_smb ( const acl_perm_t tru64_permset )
2006-07-21 19:51:34 +04:00
{
2007-05-16 01:41:02 +04:00
SMB_ACL_PERM_T smb_permset = 0 ;
2006-07-21 19:51:34 +04:00
smb_permset | = ( ( tru64_permset & ACL_READ ) ? SMB_ACL_READ : 0 ) ;
smb_permset | = ( ( tru64_permset & ACL_WRITE ) ? SMB_ACL_WRITE : 0 ) ;
smb_permset | = ( ( tru64_permset & ACL_EXECUTE ) ? SMB_ACL_EXECUTE : 0 ) ;
return smb_permset ;
}
/* VFS operations structure */
static vfs_op_tuple tru64acl_op_tuples [ ] = {
/* Disk operations */
{ SMB_VFS_OP ( tru64acl_sys_acl_get_file ) ,
SMB_VFS_OP_SYS_ACL_GET_FILE ,
SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( tru64acl_sys_acl_get_fd ) ,
SMB_VFS_OP_SYS_ACL_GET_FD ,
SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( tru64acl_sys_acl_set_file ) ,
SMB_VFS_OP_SYS_ACL_SET_FILE ,
SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( tru64acl_sys_acl_set_fd ) ,
SMB_VFS_OP_SYS_ACL_SET_FD ,
SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( tru64acl_sys_acl_delete_def_file ) ,
SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE ,
SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( NULL ) ,
SMB_VFS_OP_NOOP ,
SMB_VFS_LAYER_NOOP }
} ;
2006-12-19 23:16:52 +03:00
NTSTATUS vfs_tru64acl_init ( void ) ;
2006-07-21 19:51:34 +04:00
NTSTATUS vfs_tru64acl_init ( void )
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " tru64acl " ,
tru64acl_op_tuples ) ;
}
/* ENTE */