2006-09-18 06:27:48 +04:00
/*
* NFS4 ACL handling
*
* Copyright ( C ) Jim McDonough , 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"
# include "nfs4_acls.h"
2008-01-16 12:18:57 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ACLS
2006-09-18 06:27:48 +04:00
# define SMBACL4_PARAM_TYPE_NAME "nfs4"
2008-09-08 18:42:06 +04:00
extern const struct generic_mapping file_generic_mapping ;
2006-09-18 06:27:48 +04:00
# define SMB_ACE4_INT_MAGIC 0x76F8A967
typedef struct _SMB_ACE4_INT_T
{
uint32 magic ;
SMB_ACE4PROP_T prop ;
void * next ;
} SMB_ACE4_INT_T ;
# define SMB_ACL4_INT_MAGIC 0x29A3E792
typedef struct _SMB_ACL4_INT_T
{
uint32 magic ;
uint32 naces ;
SMB_ACE4_INT_T * first ;
SMB_ACE4_INT_T * last ;
} SMB_ACL4_INT_T ;
2009-02-24 02:03:29 +03:00
static SMB_ACL4_INT_T * get_validated_aclint ( SMB4ACL_T * theacl )
2006-09-18 06:27:48 +04:00
{
2009-02-24 02:03:29 +03:00
SMB_ACL4_INT_T * aclint = ( SMB_ACL4_INT_T * ) theacl ;
if ( theacl = = NULL )
2006-09-18 06:27:48 +04:00
{
DEBUG ( 2 , ( " acl is NULL \n " ) ) ;
errno = EINVAL ;
return NULL ;
}
if ( aclint - > magic ! = SMB_ACL4_INT_MAGIC )
{
DEBUG ( 2 , ( " aclint bad magic 0x%x \n " , aclint - > magic ) ) ;
errno = EINVAL ;
return NULL ;
}
return aclint ;
}
static SMB_ACE4_INT_T * get_validated_aceint ( SMB4ACE_T * ace )
{
SMB_ACE4_INT_T * aceint = ( SMB_ACE4_INT_T * ) ace ;
if ( ace = = NULL )
{
DEBUG ( 2 , ( " ace is NULL \n " ) ) ;
errno = EINVAL ;
return NULL ;
}
if ( aceint - > magic ! = SMB_ACE4_INT_MAGIC )
{
DEBUG ( 2 , ( " aceint bad magic 0x%x \n " , aceint - > magic ) ) ;
errno = EINVAL ;
return NULL ;
}
return aceint ;
}
SMB4ACL_T * smb_create_smb4acl ( void )
{
2007-08-30 23:48:31 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2009-02-24 02:03:29 +03:00
SMB_ACL4_INT_T * theacl = ( SMB_ACL4_INT_T * ) TALLOC_ZERO_SIZE ( mem_ctx , sizeof ( SMB_ACL4_INT_T ) ) ;
if ( theacl = = NULL )
2006-09-18 06:27:48 +04:00
{
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 NULL ;
}
2009-02-24 02:03:29 +03:00
theacl - > magic = SMB_ACL4_INT_MAGIC ;
/* theacl->first, last = NULL not needed */
return ( SMB4ACL_T * ) theacl ;
2006-09-18 06:27:48 +04:00
}
2009-02-24 02:03:29 +03:00
SMB4ACE_T * smb_add_ace4 ( SMB4ACL_T * theacl , SMB_ACE4PROP_T * prop )
2006-09-18 06:27:48 +04:00
{
2009-02-24 02:03:29 +03:00
SMB_ACL4_INT_T * aclint = get_validated_aclint ( theacl ) ;
2007-08-30 23:48:31 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2006-09-18 06:27:48 +04:00
SMB_ACE4_INT_T * ace ;
2007-06-02 10:28:38 +04:00
ace = ( SMB_ACE4_INT_T * ) TALLOC_ZERO_SIZE ( mem_ctx , sizeof ( SMB_ACE4_INT_T ) ) ;
2006-09-18 06:27:48 +04:00
if ( ace = = 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 NULL ;
}
ace - > magic = SMB_ACE4_INT_MAGIC ;
/* ace->next = NULL not needed */
memcpy ( & ace - > prop , prop , sizeof ( SMB_ACE4PROP_T ) ) ;
if ( aclint - > first = = NULL )
{
aclint - > first = ace ;
aclint - > last = ace ;
} else {
aclint - > last - > next = ( void * ) ace ;
aclint - > last = ace ;
}
aclint - > naces + + ;
return ( SMB4ACE_T * ) ace ;
}
SMB_ACE4PROP_T * smb_get_ace4 ( SMB4ACE_T * ace )
{
SMB_ACE4_INT_T * aceint = get_validated_aceint ( ace ) ;
if ( aceint = = NULL )
return NULL ;
return & aceint - > prop ;
}
SMB4ACE_T * smb_next_ace4 ( SMB4ACE_T * ace )
{
SMB_ACE4_INT_T * aceint = get_validated_aceint ( ace ) ;
if ( aceint = = NULL )
return NULL ;
return ( SMB4ACE_T * ) aceint - > next ;
}
2009-02-24 02:03:29 +03:00
SMB4ACE_T * smb_first_ace4 ( SMB4ACL_T * theacl )
2006-09-18 06:27:48 +04:00
{
2009-02-24 02:03:29 +03:00
SMB_ACL4_INT_T * aclint = get_validated_aclint ( theacl ) ;
2006-09-18 06:27:48 +04:00
if ( aclint = = NULL )
return NULL ;
return ( SMB4ACE_T * ) aclint - > first ;
}
2009-02-24 02:03:29 +03:00
uint32 smb_get_naces ( SMB4ACL_T * theacl )
2006-09-18 06:27:48 +04:00
{
2009-02-24 02:03:29 +03:00
SMB_ACL4_INT_T * aclint = get_validated_aclint ( theacl ) ;
2006-09-18 06:27:48 +04:00
if ( aclint = = NULL )
return 0 ;
return aclint - > naces ;
}
2007-11-09 03:01:55 +03:00
static int smbacl4_GetFileOwner ( struct connection_struct * conn ,
const char * filename ,
SMB_STRUCT_STAT * psbuf )
2006-09-18 06:27:48 +04:00
{
memset ( psbuf , 0 , sizeof ( SMB_STRUCT_STAT ) ) ;
2007-11-09 03:01:55 +03:00
/* Get the stat struct for the owner info. */
2009-06-23 02:26:56 +04:00
if ( vfs_stat_smb_fname ( conn , filename , psbuf ) ! = 0 )
2007-11-09 03:01:55 +03:00
{
2009-10-02 22:05:03 +04:00
DEBUG ( 8 , ( " vfs_stat_smb_fname failed with error %s \n " ,
2007-11-09 03:01:55 +03:00
strerror ( errno ) ) ) ;
return - 1 ;
}
return 0 ;
}
static int smbacl4_fGetFileOwner ( files_struct * fsp , SMB_STRUCT_STAT * psbuf )
{
memset ( psbuf , 0 , sizeof ( SMB_STRUCT_STAT ) ) ;
2006-09-18 06:27:48 +04:00
if ( fsp - > is_directory | | fsp - > fh - > fd = = - 1 ) {
2009-07-11 05:11:32 +04:00
return smbacl4_GetFileOwner ( fsp - > conn ,
fsp - > fsp_name - > base_name , psbuf ) ;
2007-11-09 03:01:55 +03:00
}
2008-01-07 15:21:26 +03:00
if ( SMB_VFS_FSTAT ( fsp , psbuf ) ! = 0 )
2007-11-09 03:01:55 +03:00
{
DEBUG ( 8 , ( " SMB_VFS_FSTAT failed with error %s \n " ,
strerror ( errno ) ) ) ;
return - 1 ;
2006-09-18 06:27:48 +04:00
}
return 0 ;
}
2009-02-24 02:03:29 +03:00
static bool smbacl4_nfs42win ( TALLOC_CTX * mem_ctx , SMB4ACL_T * theacl , /* in */
2006-09-18 06:27:48 +04:00
DOM_SID * psid_owner , /* in */
DOM_SID * psid_group , /* in */
2009-02-20 19:23:52 +03:00
bool is_directory , /* in */
2006-09-18 06:27:48 +04:00
SEC_ACE * * ppnt_ace_list , /* out */
int * pgood_aces /* out */
)
{
2009-02-24 02:03:29 +03:00
SMB_ACL4_INT_T * aclint = ( SMB_ACL4_INT_T * ) theacl ;
2006-09-18 06:27:48 +04:00
SMB_ACE4_INT_T * aceint ;
SEC_ACE * nt_ace_list = NULL ;
int good_aces = 0 ;
2009-06-25 16:46:17 +04:00
DEBUG ( 10 , ( " smbacl_nfs42win entered \n " ) ) ;
2006-09-18 06:27:48 +04:00
2009-02-24 02:03:29 +03:00
aclint = get_validated_aclint ( theacl ) ;
/* We do not check for naces being 0 or theacl being NULL here because it is done upstream */
2007-06-02 10:28:38 +04:00
/* in smb_get_nt_acl_nfs4(). */
nt_ace_list = ( SEC_ACE * ) TALLOC_ZERO_SIZE ( mem_ctx , aclint - > naces * sizeof ( SEC_ACE ) ) ;
if ( nt_ace_list = = NULL )
{
DEBUG ( 10 , ( " talloc error " ) ) ;
errno = ENOMEM ;
2006-09-18 06:27:48 +04:00
return False ;
}
for ( aceint = aclint - > first ; aceint ! = NULL ; aceint = ( SMB_ACE4_INT_T * ) aceint - > next ) {
2008-10-09 20:49:03 +04:00
uint32_t mask ;
2006-09-18 06:27:48 +04:00
DOM_SID sid ;
SMB_ACE4PROP_T * ace = & aceint - > prop ;
2009-08-10 20:18:19 +04:00
uint32_t mapped_ace_flags ;
2006-09-18 06:27:48 +04:00
DEBUG ( 10 , ( " magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, "
" who: %d \n " , aceint - > magic , ace - > aceType , ace - > flags ,
ace - > aceFlags , ace - > aceMask , ace - > who . id ) ) ;
SMB_ASSERT ( aceint - > magic = = SMB_ACE4_INT_MAGIC ) ;
if ( ace - > flags & SMB_ACE4_ID_SPECIAL ) {
switch ( ace - > who . special_id ) {
case SMB_ACE4_WHO_OWNER :
sid_copy ( & sid , psid_owner ) ;
break ;
case SMB_ACE4_WHO_GROUP :
sid_copy ( & sid , psid_group ) ;
break ;
case SMB_ACE4_WHO_EVERYONE :
sid_copy ( & sid , & global_sid_World ) ;
break ;
default :
DEBUG ( 8 , ( " invalid special who id %d "
" ignored \n " , ace - > who . special_id ) ) ;
}
} else {
if ( ace - > aceFlags & SMB_ACE4_IDENTIFIER_GROUP ) {
gid_to_sid ( & sid , ace - > who . gid ) ;
} else {
uid_to_sid ( & sid , ace - > who . uid ) ;
}
}
DEBUG ( 10 , ( " mapped %d to %s \n " , ace - > who . id ,
2007-12-15 23:11:36 +03:00
sid_string_dbg ( & sid ) ) ) ;
2006-09-18 06:27:48 +04:00
2009-02-20 19:23:52 +03:00
if ( is_directory & & ( ace - > aceMask & SMB_ACE4_ADD_FILE ) ) {
ace - > aceMask | = SMB_ACE4_DELETE_CHILD ;
}
2009-08-10 20:18:19 +04:00
mapped_ace_flags = ace - > aceFlags & 0xf ;
2009-08-15 02:06:11 +04:00
if ( ! is_directory & & ( mapped_ace_flags & ( SMB_ACE4_FILE_INHERIT_ACE | SMB_ACE4_DIRECTORY_INHERIT_ACE ) ) ) {
2009-08-10 20:18:19 +04:00
/*
* GPFS sets inherits dir_inhert and file_inherit flags
* to files , too , which confuses windows , and seems to
* be wrong anyways . = = > Map these bits away for files .
*/
DEBUG ( 10 , ( " removing inherit flags from nfs4 ace \n " ) ) ;
2009-08-15 02:06:11 +04:00
mapped_ace_flags & = ~ ( SMB_ACE4_FILE_INHERIT_ACE | SMB_ACE4_DIRECTORY_INHERIT_ACE ) ;
2009-08-10 20:18:19 +04:00
}
DEBUG ( 10 , ( " mapped ace flags: 0x%x => 0x%x \n " ,
ace - > aceFlags , mapped_ace_flags ) ) ;
2008-10-09 20:49:03 +04:00
mask = ace - > aceMask ;
2006-09-18 06:27:48 +04:00
init_sec_ace ( & nt_ace_list [ good_aces + + ] , & sid ,
ace - > aceType , mask ,
2009-08-10 20:18:19 +04:00
mapped_ace_flags ) ;
2006-09-18 06:27:48 +04:00
}
* ppnt_ace_list = nt_ace_list ;
* pgood_aces = good_aces ;
return True ;
}
2007-11-15 02:46:20 +03:00
static NTSTATUS smb_get_nt_acl_nfs4_common ( const SMB_STRUCT_STAT * sbuf ,
2006-09-18 06:27:48 +04:00
uint32 security_info ,
2009-02-24 02:03:29 +03:00
SEC_DESC * * ppdesc , SMB4ACL_T * theacl )
2006-09-18 06:27:48 +04:00
{
int good_aces = 0 ;
DOM_SID sid_owner , sid_group ;
size_t sd_size = 0 ;
SEC_ACE * nt_ace_list = NULL ;
SEC_ACL * psa = NULL ;
2007-08-30 23:48:31 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2006-09-18 06:27:48 +04:00
2009-02-24 02:03:29 +03:00
if ( theacl = = NULL | | smb_get_naces ( theacl ) = = 0 )
2007-10-13 23:06:49 +04:00
return NT_STATUS_ACCESS_DENIED ; /* special because we
* shouldn ' t alloc 0 for
* win */
2006-09-18 06:27:48 +04:00
2009-05-14 17:34:42 +04:00
uid_to_sid ( & sid_owner , sbuf - > st_ex_uid ) ;
gid_to_sid ( & sid_group , sbuf - > st_ex_gid ) ;
2006-09-18 06:27:48 +04:00
2009-05-14 17:34:42 +04:00
if ( smbacl4_nfs42win ( mem_ctx , theacl , & sid_owner , & sid_group ,
S_ISDIR ( sbuf - > st_ex_mode ) ,
2009-02-20 19:23:52 +03:00
& nt_ace_list , & good_aces ) = = False ) {
2006-09-18 06:27:48 +04:00
DEBUG ( 8 , ( " smbacl4_nfs42win failed \n " ) ) ;
2007-10-13 23:06:49 +04:00
return map_nt_error_from_unix ( errno ) ;
2006-09-18 06:27:48 +04:00
}
2007-06-02 10:28:38 +04:00
psa = make_sec_acl ( mem_ctx , NT4_ACL_REVISION , good_aces , nt_ace_list ) ;
2006-09-18 06:27:48 +04:00
if ( psa = = NULL ) {
DEBUG ( 2 , ( " make_sec_acl failed \n " ) ) ;
2007-10-13 23:06:49 +04:00
return NT_STATUS_NO_MEMORY ;
2006-09-18 06:27:48 +04:00
}
DEBUG ( 10 , ( " after make sec_acl \n " ) ) ;
2007-06-02 10:28:38 +04:00
* ppdesc = make_sec_desc ( mem_ctx , SEC_DESC_REVISION , SEC_DESC_SELF_RELATIVE ,
( security_info & OWNER_SECURITY_INFORMATION ) ? & sid_owner : NULL ,
( security_info & GROUP_SECURITY_INFORMATION ) ? & sid_group : NULL ,
NULL , psa , & sd_size ) ;
2006-09-18 06:27:48 +04:00
if ( * ppdesc = = NULL ) {
DEBUG ( 2 , ( " make_sec_desc failed \n " ) ) ;
2007-10-13 23:06:49 +04:00
return NT_STATUS_NO_MEMORY ;
2006-09-18 06:27:48 +04:00
}
2007-11-15 02:46:20 +03:00
DEBUG ( 10 , ( " smb_get_nt_acl_nfs4_common successfully exited with sd_size %d \n " ,
2009-05-25 00:16:34 +04:00
( int ) ndr_size_security_descriptor ( * ppdesc , NULL , 0 ) ) ) ;
2007-10-13 23:06:49 +04:00
return NT_STATUS_OK ;
2006-09-18 06:27:48 +04:00
}
2007-11-15 02:46:20 +03:00
NTSTATUS smb_fget_nt_acl_nfs4 ( files_struct * fsp ,
uint32 security_info ,
2009-02-24 02:03:29 +03:00
SEC_DESC * * ppdesc , SMB4ACL_T * theacl )
2007-11-15 02:46:20 +03:00
{
SMB_STRUCT_STAT sbuf ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " smb_fget_nt_acl_nfs4 invoked for %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2007-11-15 02:46:20 +03:00
if ( smbacl4_fGetFileOwner ( fsp , & sbuf ) ) {
return map_nt_error_from_unix ( errno ) ;
}
2009-02-24 02:03:29 +03:00
return smb_get_nt_acl_nfs4_common ( & sbuf , security_info , ppdesc , theacl ) ;
2007-11-15 02:46:20 +03:00
}
NTSTATUS smb_get_nt_acl_nfs4 ( struct connection_struct * conn ,
const char * name ,
uint32 security_info ,
2009-02-24 02:03:29 +03:00
SEC_DESC * * ppdesc , SMB4ACL_T * theacl )
2007-11-15 02:46:20 +03:00
{
SMB_STRUCT_STAT sbuf ;
DEBUG ( 10 , ( " smb_get_nt_acl_nfs4 invoked for %s \n " , name ) ) ;
if ( smbacl4_GetFileOwner ( conn , name , & sbuf ) ) {
return map_nt_error_from_unix ( errno ) ;
}
2009-02-24 02:03:29 +03:00
return smb_get_nt_acl_nfs4_common ( & sbuf , security_info , ppdesc , theacl ) ;
2007-11-15 02:46:20 +03:00
}
2006-09-18 06:27:48 +04:00
enum smbacl4_mode_enum { e_simple = 0 , e_special = 1 } ;
enum smbacl4_acedup_enum { e_dontcare = 0 , e_reject = 1 , e_ignore = 2 , e_merge = 3 } ;
typedef struct _smbacl4_vfs_params {
enum smbacl4_mode_enum mode ;
2007-10-19 04:40:25 +04:00
bool do_chown ;
2006-09-18 06:27:48 +04:00
enum smbacl4_acedup_enum acedup ;
2008-01-16 12:18:57 +03:00
struct db_context * sid_mapping_table ;
2006-09-18 06:27:48 +04:00
} smbacl4_vfs_params ;
/*
* Gather special parameters for NFS4 ACL handling
*/
static int smbacl4_get_vfs_params (
const char * type_name ,
files_struct * fsp ,
smbacl4_vfs_params * params
)
{
static const struct enum_list enum_smbacl4_modes [ ] = {
{ e_simple , " simple " } ,
{ e_special , " special " }
} ;
static const struct enum_list enum_smbacl4_acedups [ ] = {
{ e_dontcare , " dontcare " } ,
{ e_reject , " reject " } ,
{ e_ignore , " ignore " } ,
{ e_merge , " merge " } ,
} ;
memset ( params , 0 , sizeof ( smbacl4_vfs_params ) ) ;
params - > mode = ( enum smbacl4_mode_enum ) lp_parm_enum (
SNUM ( fsp - > conn ) , type_name ,
" mode " , enum_smbacl4_modes , e_simple ) ;
params - > do_chown = lp_parm_bool ( SNUM ( fsp - > conn ) , type_name ,
" chown " , True ) ;
params - > acedup = ( enum smbacl4_acedup_enum ) lp_parm_enum (
SNUM ( fsp - > conn ) , type_name ,
" acedup " , enum_smbacl4_acedups , e_dontcare ) ;
DEBUG ( 10 , ( " mode:%s, do_chown:%s, acedup: %s \n " ,
enum_smbacl4_modes [ params - > mode ] . name ,
params - > do_chown ? " true " : " false " ,
enum_smbacl4_acedups [ params - > acedup ] . name ) ) ;
return 0 ;
}
2009-02-24 02:03:29 +03:00
static void smbacl4_dump_nfs4acl ( int level , SMB4ACL_T * theacl )
2006-09-18 06:27:48 +04:00
{
2009-02-24 02:03:29 +03:00
SMB_ACL4_INT_T * aclint = get_validated_aclint ( theacl ) ;
2006-09-18 06:27:48 +04:00
SMB_ACE4_INT_T * aceint ;
DEBUG ( level , ( " NFS4ACL: size=%d \n " , aclint - > naces ) ) ;
for ( aceint = aclint - > first ; aceint ! = NULL ; aceint = ( SMB_ACE4_INT_T * ) aceint - > next ) {
SMB_ACE4PROP_T * ace = & aceint - > prop ;
DEBUG ( level , ( " \t ACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d \n " ,
ace - > aceType ,
ace - > aceFlags , ace - > flags ,
ace - > aceMask ,
ace - > who . id ) ) ;
}
}
/*
* Find 2 NFS4 who - special ACE property ( non - copy ! ! ! )
* match nonzero if " special " and who is equal
* return ace if found matching ; otherwise NULL
*/
static SMB_ACE4PROP_T * smbacl4_find_equal_special (
2009-02-24 02:03:29 +03:00
SMB4ACL_T * theacl ,
2006-09-18 06:27:48 +04:00
SMB_ACE4PROP_T * aceNew )
{
2009-02-24 02:03:29 +03:00
SMB_ACL4_INT_T * aclint = get_validated_aclint ( theacl ) ;
2006-09-18 06:27:48 +04:00
SMB_ACE4_INT_T * aceint ;
for ( aceint = aclint - > first ; aceint ! = NULL ; aceint = ( SMB_ACE4_INT_T * ) aceint - > next ) {
SMB_ACE4PROP_T * ace = & aceint - > prop ;
2009-07-05 18:03:15 +04:00
DEBUG ( 10 , ( " ace type:0x%x flags:0x%x aceFlags:0x%x "
" new type:0x%x flags:0x%x aceFlags:0x%x \n " ,
ace - > aceType , ace - > flags , ace - > aceFlags ,
aceNew - > aceType , aceNew - > flags , aceNew - > aceFlags ) ) ;
2006-09-18 06:27:48 +04:00
if ( ace - > flags = = aceNew - > flags & &
ace - > aceType = = aceNew - > aceType & &
2009-07-05 18:03:15 +04:00
( ( ace - > aceFlags & SMB_ACE4_INHERIT_ONLY_ACE ) = =
( aceNew - > aceFlags & SMB_ACE4_INHERIT_ONLY_ACE ) ) & &
2006-09-18 06:27:48 +04:00
( ace - > aceFlags & SMB_ACE4_IDENTIFIER_GROUP ) = =
( aceNew - > aceFlags & SMB_ACE4_IDENTIFIER_GROUP )
) {
/* keep type safety; e.g. gid is an u.short */
if ( ace - > flags & SMB_ACE4_ID_SPECIAL )
{
if ( ace - > who . special_id = = aceNew - > who . special_id )
return ace ;
} else {
if ( ace - > aceFlags & SMB_ACE4_IDENTIFIER_GROUP )
{
if ( ace - > who . gid = = aceNew - > who . gid )
return ace ;
} else {
if ( ace - > who . uid = = aceNew - > who . uid )
return ace ;
}
}
}
}
return NULL ;
}
2008-01-16 12:18:57 +03:00
static bool nfs4_map_sid ( smbacl4_vfs_params * params , const DOM_SID * src ,
DOM_SID * dst )
{
static struct db_context * mapping_db = NULL ;
TDB_DATA data ;
if ( mapping_db = = NULL ) {
const char * dbname = lp_parm_const_string (
- 1 , SMBACL4_PARAM_TYPE_NAME , " sidmap " , NULL ) ;
if ( dbname = = NULL ) {
DEBUG ( 10 , ( " %s:sidmap not defined \n " ,
SMBACL4_PARAM_TYPE_NAME ) ) ;
return False ;
}
become_root ( ) ;
mapping_db = db_open ( NULL , dbname , 0 , TDB_DEFAULT ,
O_RDONLY , 0600 ) ;
unbecome_root ( ) ;
if ( mapping_db = = NULL ) {
DEBUG ( 1 , ( " could not open sidmap: %s \n " ,
strerror ( errno ) ) ) ;
return False ;
}
}
if ( mapping_db - > fetch ( mapping_db , NULL ,
string_term_tdb_data ( sid_string_tos ( src ) ) ,
& data ) = = - 1 ) {
DEBUG ( 10 , ( " could not find mapping for SID %s \n " ,
sid_string_dbg ( src ) ) ) ;
return False ;
}
if ( ( data . dptr = = NULL ) | | ( data . dsize < = 0 )
| | ( data . dptr [ data . dsize - 1 ] ! = ' \0 ' ) ) {
DEBUG ( 5 , ( " invalid mapping for SID %s \n " ,
sid_string_dbg ( src ) ) ) ;
TALLOC_FREE ( data . dptr ) ;
return False ;
}
if ( ! string_to_sid ( dst , ( char * ) data . dptr ) ) {
DEBUG ( 1 , ( " invalid mapping %s for SID %s \n " ,
( char * ) data . dptr , sid_string_dbg ( src ) ) ) ;
TALLOC_FREE ( data . dptr ) ;
return False ;
}
TALLOC_FREE ( data . dptr ) ;
return True ;
}
static bool smbacl4_fill_ace4 (
2006-09-18 06:27:48 +04:00
TALLOC_CTX * mem_ctx ,
2008-01-16 12:18:57 +03:00
const char * filename ,
2006-09-18 06:27:48 +04:00
smbacl4_vfs_params * params ,
uid_t ownerUID ,
gid_t ownerGID ,
2008-10-08 04:50:01 +04:00
const SEC_ACE * ace_nt , /* input */
2006-09-18 06:27:48 +04:00
SMB_ACE4PROP_T * ace_v4 /* output */
)
{
2007-12-15 23:11:36 +03:00
DEBUG ( 10 , ( " got ace for %s \n " , sid_string_dbg ( & ace_nt - > trustee ) ) ) ;
2006-09-18 06:27:48 +04:00
memset ( ace_v4 , 0 , sizeof ( SMB_ACE4PROP_T ) ) ;
2007-06-02 10:28:38 +04:00
ace_v4 - > aceType = ace_nt - > type ; /* only ACCESS|DENY supported right now */
2006-09-18 06:27:48 +04:00
ace_v4 - > aceFlags = ace_nt - > flags & SEC_ACE_FLAG_VALID_INHERIT ;
2006-09-21 18:17:00 +04:00
ace_v4 - > aceMask = ace_nt - > access_mask &
2006-09-18 06:27:48 +04:00
( STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS ) ;
2008-09-08 18:42:06 +04:00
se_map_generic ( & ace_v4 - > aceMask , & file_generic_mapping ) ;
2006-09-18 06:27:48 +04:00
if ( ace_v4 - > aceFlags ! = ace_nt - > flags )
DEBUG ( 9 , ( " ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x) \n " ,
ace_v4 - > aceFlags , ace_nt - > flags ) ) ;
2006-09-21 18:17:00 +04:00
if ( ace_v4 - > aceMask ! = ace_nt - > access_mask )
DEBUG ( 9 , ( " ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x) \n " ,
ace_v4 - > aceMask , ace_nt - > access_mask ) ) ;
2006-09-18 06:27:48 +04:00
if ( sid_equal ( & ace_nt - > trustee , & global_sid_World ) ) {
ace_v4 - > who . special_id = SMB_ACE4_WHO_EVERYONE ;
ace_v4 - > flags | = SMB_ACE4_ID_SPECIAL ;
} else {
2008-01-16 12:18:57 +03:00
const char * dom , * name ;
enum lsa_SidType type ;
uid_t uid ;
gid_t gid ;
DOM_SID sid ;
sid_copy ( & sid , & ace_nt - > trustee ) ;
if ( ! lookup_sid ( mem_ctx , & sid , & dom , & name , & type ) ) {
DOM_SID mapped ;
if ( ! nfs4_map_sid ( params , & sid , & mapped ) ) {
DEBUG ( 1 , ( " nfs4_acls.c: file [%s]: SID %s "
" unknown \n " , filename , sid_string_dbg ( & sid ) ) ) ;
errno = EINVAL ;
return False ;
}
DEBUG ( 2 , ( " nfs4_acls.c: file [%s]: mapped SID %s "
" to %s \n " , filename , sid_string_dbg ( & sid ) , sid_string_dbg ( & mapped ) ) ) ;
if ( ! lookup_sid ( mem_ctx , & mapped , & dom ,
& name , & type ) ) {
DEBUG ( 1 , ( " nfs4_acls.c: file [%s]: SID %s "
" mapped from %s is unknown \n " ,
filename , sid_string_dbg ( & mapped ) , sid_string_dbg ( & sid ) ) ) ;
errno = EINVAL ;
return False ;
}
sid_copy ( & sid , & mapped ) ;
2006-09-18 06:27:48 +04:00
}
2008-01-16 12:18:57 +03:00
2006-09-18 06:27:48 +04:00
if ( type = = SID_NAME_USER ) {
2008-01-16 12:18:57 +03:00
if ( ! sid_to_uid ( & sid , & uid ) ) {
DEBUG ( 1 , ( " nfs4_acls.c: file [%s]: could not "
" convert %s to uid \n " , filename ,
sid_string_dbg ( & sid ) ) ) ;
return False ;
2006-09-18 06:27:48 +04:00
}
if ( params - > mode = = e_special & & uid = = ownerUID ) {
ace_v4 - > flags | = SMB_ACE4_ID_SPECIAL ;
ace_v4 - > who . special_id = SMB_ACE4_WHO_OWNER ;
} else {
ace_v4 - > who . uid = uid ;
}
} else { /* else group? - TODO check it... */
2008-01-16 12:18:57 +03:00
if ( ! sid_to_gid ( & sid , & gid ) ) {
DEBUG ( 1 , ( " nfs4_acls.c: file [%s]: could not "
" convert %s to gid \n " , filename ,
sid_string_dbg ( & sid ) ) ) ;
return False ;
2006-09-18 06:27:48 +04:00
}
2008-01-16 12:18:57 +03:00
2006-09-18 06:27:48 +04:00
ace_v4 - > aceFlags | = SMB_ACE4_IDENTIFIER_GROUP ;
if ( params - > mode = = e_special & & gid = = ownerGID ) {
ace_v4 - > flags | = SMB_ACE4_ID_SPECIAL ;
ace_v4 - > who . special_id = SMB_ACE4_WHO_GROUP ;
} else {
ace_v4 - > who . gid = gid ;
}
}
}
2008-01-16 12:18:57 +03:00
return True ; /* OK */
2006-09-18 06:27:48 +04:00
}
static int smbacl4_MergeIgnoreReject (
enum smbacl4_acedup_enum acedup ,
2009-02-24 02:03:29 +03:00
SMB4ACL_T * theacl , /* may modify it */
2006-09-18 06:27:48 +04:00
SMB_ACE4PROP_T * ace , /* the "new" ACE */
2007-10-19 04:40:25 +04:00
bool * paddNewACE ,
2006-09-18 06:27:48 +04:00
int i
)
{
int result = 0 ;
2009-02-24 02:03:29 +03:00
SMB_ACE4PROP_T * ace4found = smbacl4_find_equal_special ( theacl , ace ) ;
2006-09-18 06:27:48 +04:00
if ( ace4found )
{
switch ( acedup )
{
case e_merge : /* "merge" flags */
* paddNewACE = False ;
ace4found - > aceFlags | = ace - > aceFlags ;
ace4found - > aceMask | = ace - > aceMask ;
break ;
case e_ignore : /* leave out this record */
* paddNewACE = False ;
break ;
case e_reject : /* do an error */
DEBUG ( 8 , ( " ACL rejected by duplicate nt ace#%d \n " , i ) ) ;
errno = EINVAL ; /* SHOULD be set on any _real_ error */
result = - 1 ;
break ;
default :
break ;
}
}
return result ;
}
static SMB4ACL_T * smbacl4_win2nfs4 (
2008-01-16 12:18:57 +03:00
const char * filename ,
2008-10-08 04:50:01 +04:00
const SEC_ACL * dacl ,
2006-09-18 06:27:48 +04:00
smbacl4_vfs_params * pparams ,
uid_t ownerUID ,
gid_t ownerGID
)
{
2009-02-24 02:03:29 +03:00
SMB4ACL_T * theacl ;
2006-09-18 06:27:48 +04:00
uint32 i ;
2007-08-30 23:48:31 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2006-09-18 06:27:48 +04:00
DEBUG ( 10 , ( " smbacl4_win2nfs4 invoked \n " ) ) ;
2009-02-24 02:03:29 +03:00
theacl = smb_create_smb4acl ( ) ;
if ( theacl = = NULL )
2006-09-18 06:27:48 +04:00
return NULL ;
for ( i = 0 ; i < dacl - > num_aces ; i + + ) {
SMB_ACE4PROP_T ace_v4 ;
2007-10-19 04:40:25 +04:00
bool addNewACE = True ;
2006-09-18 06:27:48 +04:00
2008-01-16 12:18:57 +03:00
if ( ! smbacl4_fill_ace4 ( mem_ctx , filename , pparams ,
ownerUID , ownerGID ,
dacl - > aces + i , & ace_v4 ) ) {
DEBUG ( 3 , ( " Could not fill ace for file %s, SID %s \n " ,
filename ,
sid_string_dbg ( & ( ( dacl - > aces + i ) - > trustee ) ) ) ) ;
continue ;
}
2006-09-18 06:27:48 +04:00
if ( pparams - > acedup ! = e_dontcare ) {
2009-02-24 02:03:29 +03:00
if ( smbacl4_MergeIgnoreReject ( pparams - > acedup , theacl ,
2006-09-18 06:27:48 +04:00
& ace_v4 , & addNewACE , i ) )
return NULL ;
}
if ( addNewACE )
2009-02-24 02:03:29 +03:00
smb_add_ace4 ( theacl , & ace_v4 ) ;
2006-09-18 06:27:48 +04:00
}
2009-02-24 02:03:29 +03:00
return theacl ;
2006-09-18 06:27:48 +04:00
}
2007-06-27 02:49:10 +04:00
NTSTATUS smb_set_nt_acl_nfs4 ( files_struct * fsp ,
2006-09-18 06:27:48 +04:00
uint32 security_info_sent ,
2008-10-08 04:50:01 +04:00
const SEC_DESC * psd ,
2006-09-18 06:27:48 +04:00
set_nfs4acl_native_fn_t set_nfs4_native )
{
smbacl4_vfs_params params ;
2009-02-24 02:03:29 +03:00
SMB4ACL_T * theacl = NULL ;
2007-10-19 04:40:25 +04:00
bool result ;
2006-09-18 06:27:48 +04:00
SMB_STRUCT_STAT sbuf ;
2009-01-23 03:21:02 +03:00
bool set_acl_as_root = false ;
2006-09-18 06:27:48 +04:00
uid_t newUID = ( uid_t ) - 1 ;
gid_t newGID = ( gid_t ) - 1 ;
2009-01-23 03:21:02 +03:00
int saved_errno ;
2006-09-18 06:27:48 +04:00
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " smb_set_nt_acl_nfs4 invoked for %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2006-09-18 06:27:48 +04:00
if ( ( security_info_sent & ( DACL_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION ) ) = = 0 )
{
DEBUG ( 9 , ( " security_info_sent (0x%x) ignored \n " ,
security_info_sent ) ) ;
2007-06-27 02:49:10 +04:00
return NT_STATUS_OK ; /* won't show error - later to be refined... */
2006-09-18 06:27:48 +04:00
}
/* Special behaviours */
if ( smbacl4_get_vfs_params ( SMBACL4_PARAM_TYPE_NAME , fsp , & params ) )
2007-06-27 02:49:10 +04:00
return NT_STATUS_NO_MEMORY ;
2006-09-18 06:27:48 +04:00
2007-11-09 03:01:55 +03:00
if ( smbacl4_fGetFileOwner ( fsp , & sbuf ) )
2007-06-27 02:49:10 +04:00
return map_nt_error_from_unix ( errno ) ;
2006-09-18 06:27:48 +04:00
2007-03-20 11:17:27 +03:00
if ( params . do_chown ) {
/* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
2010-03-15 20:33:09 +03:00
NTSTATUS status = unpack_nt_owners ( SNUM ( fsp - > conn ) , & newUID , & newGID , security_info_sent , psd ) ;
2007-06-27 02:49:10 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-20 11:17:27 +03:00
DEBUG ( 8 , ( " unpack_nt_owners failed " ) ) ;
2007-06-27 02:49:10 +04:00
return status ;
2007-03-20 11:17:27 +03:00
}
2009-05-14 17:34:42 +04:00
if ( ( ( newUID ! = ( uid_t ) - 1 ) & & ( sbuf . st_ex_uid ! = newUID ) ) | |
( ( newGID ! = ( gid_t ) - 1 ) & & ( sbuf . st_ex_gid ! = newGID ) ) ) {
2009-07-08 23:24:03 +04:00
2009-07-11 05:11:32 +04:00
if ( try_chown ( fsp - > conn , fsp - > fsp_name , newUID ,
newGID ) ) {
DEBUG ( 3 , ( " chown %s, %u, %u failed. Error = "
" %s. \n " , fsp_str_dbg ( fsp ) ,
( unsigned int ) newUID ,
( unsigned int ) newGID ,
2009-01-23 03:21:02 +03:00
strerror ( errno ) ) ) ;
return map_nt_error_from_unix ( errno ) ;
2006-09-18 06:27:48 +04:00
}
2009-01-23 03:21:02 +03:00
DEBUG ( 10 , ( " chown %s, %u, %u succeeded. \n " ,
2009-07-11 05:11:32 +04:00
fsp_str_dbg ( fsp ) , ( unsigned int ) newUID ,
( unsigned int ) newGID ) ) ;
if ( smbacl4_GetFileOwner ( fsp - > conn ,
fsp - > fsp_name - > base_name ,
& sbuf ) )
2009-01-23 03:21:02 +03:00
return map_nt_error_from_unix ( errno ) ;
/* If we successfully chowned, we know we must
* be able to set the acl , so do it as root .
*/
set_acl_as_root = true ;
2006-09-18 06:27:48 +04:00
}
}
2009-01-23 03:21:02 +03:00
if ( ! ( security_info_sent & DACL_SECURITY_INFORMATION ) | | psd - > dacl = = NULL ) {
DEBUG ( 10 , ( " no dacl found; security_info_sent = 0x%x \n " , security_info_sent ) ) ;
return NT_STATUS_OK ;
}
2006-09-18 06:27:48 +04:00
2009-07-11 05:11:32 +04:00
theacl = smbacl4_win2nfs4 ( fsp - > fsp_name - > base_name , psd - > dacl , & params ,
2009-05-25 00:17:58 +04:00
sbuf . st_ex_uid , sbuf . st_ex_gid ) ;
2009-02-24 02:03:29 +03:00
if ( ! theacl )
2009-01-23 03:21:02 +03:00
return map_nt_error_from_unix ( errno ) ;
2006-09-18 06:27:48 +04:00
2009-02-24 02:03:29 +03:00
smbacl4_dump_nfs4acl ( 10 , theacl ) ;
2006-09-18 06:27:48 +04:00
2009-01-23 03:21:02 +03:00
if ( set_acl_as_root ) {
become_root ( ) ;
}
2009-02-24 02:03:29 +03:00
result = set_nfs4_native ( fsp , theacl ) ;
2009-01-23 03:21:02 +03:00
saved_errno = errno ;
if ( set_acl_as_root ) {
unbecome_root ( ) ;
}
if ( result ! = True ) {
errno = saved_errno ;
DEBUG ( 10 , ( " set_nfs4_native failed with %s \n " , strerror ( errno ) ) ) ;
return map_nt_error_from_unix ( errno ) ;
2008-01-16 12:18:57 +03:00
}
2006-09-18 06:27:48 +04:00
DEBUG ( 10 , ( " smb_set_nt_acl_nfs4 succeeded \n " ) ) ;
2007-06-27 02:49:10 +04:00
return NT_STATUS_OK ;
2006-09-18 06:27:48 +04:00
}