2000-08-29 04:29:15 +04:00
# define OLD_NTDOMAIN 1
/*
Unix SMB / Netbios implementation .
Version 1.9 .
SMB NT Security Descriptor / Unix permission conversion .
Copyright ( C ) Jeremy Allison 1994 - 2000
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 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2001-01-12 01:37:59 +03:00
enum ace_owner { UID_ACE , GID_ACE , WORLD_ACE } ;
typedef union posix_id {
uid_t uid ;
gid_t gid ;
int world ;
} posix_id ;
2000-11-30 04:00:36 +03:00
typedef struct canon_ace {
struct canon_ace * next , * prev ;
2000-12-06 04:34:16 +03:00
SMB_ACL_TAG_T type ;
2001-01-12 01:37:59 +03:00
mode_t perms ; /* Only use S_I(R|W|X)USR mode bits here. */
2000-11-30 04:00:36 +03:00
DOM_SID sid ;
2001-01-12 01:37:59 +03:00
enum ace_owner owner_type ;
posix_id unix_ug ;
2000-11-30 04:00:36 +03:00
} canon_ace ;
2001-01-12 01:37:59 +03:00
static void free_canon_ace_list ( canon_ace * list_head ) ;
2001-01-23 04:52:30 +03:00
/****************************************************************************
Function to duplicate a canon_ace entry .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static canon_ace * dup_canon_ace ( canon_ace * src_ace )
{
canon_ace * dst_ace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ;
if ( dst_ace = = NULL )
return NULL ;
* dst_ace = * src_ace ;
dst_ace - > prev = dst_ace - > next = NULL ;
return dst_ace ;
}
2001-01-12 01:37:59 +03:00
/****************************************************************************
2001-01-16 01:46:22 +03:00
Function to create owner and group SIDs from a SMB_STRUCT_STAT .
2001-01-12 01:37:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-01-16 01:46:22 +03:00
static void create_file_sids ( SMB_STRUCT_STAT * psbuf , DOM_SID * powner_sid , DOM_SID * pgroup_sid )
2001-01-12 01:37:59 +03:00
{
2001-01-16 01:46:22 +03:00
uid_to_sid ( powner_sid , psbuf - > st_uid ) ;
gid_to_sid ( pgroup_sid , psbuf - > st_gid ) ;
2001-01-12 01:37:59 +03:00
}
2000-08-29 04:29:15 +04:00
/****************************************************************************
2001-01-16 01:46:22 +03:00
Print out a canon ace .
2000-08-29 04:29:15 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-01-16 01:46:22 +03:00
static void print_canon_ace ( canon_ace * ace , int num )
2000-08-29 04:29:15 +04:00
{
2001-01-16 01:46:22 +03:00
fstring str ;
dbgtext ( " canon_ace index %d. " , num ) ;
dbgtext ( " SID = %s " , sid_to_string ( str , & ace - > sid ) ) ;
if ( ace - > owner_type = = UID_ACE ) {
struct passwd * pass = sys_getpwuid ( ace - > unix_ug . uid ) ;
dbgtext ( " uid %u (%s) " , ( unsigned int ) ace - > unix_ug . uid , pass ? pass - > pw_name : " UNKNOWN " ) ;
} else if ( ace - > owner_type = = GID_ACE ) {
struct group * grp = getgrgid ( ace - > unix_ug . gid ) ;
dbgtext ( " gid %u (%s) " , ( unsigned int ) ace - > unix_ug . gid , grp ? grp - > gr_name : " UNKNOWN " ) ;
} else
dbgtext ( " other " ) ;
switch ( ace - > type ) {
case SMB_ACL_USER :
dbgtext ( " SMB_ACL_USER " ) ;
break ;
case SMB_ACL_USER_OBJ :
dbgtext ( " SMB_ACL_USER_OBJ " ) ;
break ;
case SMB_ACL_GROUP :
dbgtext ( " SMB_ACL_GROUP " ) ;
break ;
case SMB_ACL_GROUP_OBJ :
dbgtext ( " SMB_ACL_GROUP_OBJ " ) ;
break ;
case SMB_ACL_OTHER :
dbgtext ( " SMB_ACL_OTHER " ) ;
break ;
}
dbgtext ( " perms " ) ;
dbgtext ( " %c " , ace - > perms & S_IRUSR ? ' r ' : ' - ' ) ;
dbgtext ( " %c " , ace - > perms & S_IWUSR ? ' w ' : ' - ' ) ;
dbgtext ( " %c \n " , ace - > perms & S_IXUSR ? ' x ' : ' - ' ) ;
2000-08-29 04:29:15 +04:00
}
/****************************************************************************
2001-01-12 01:37:59 +03:00
Map canon_ace perms to permission bits NT .
2000-08-29 04:29:15 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-11-30 22:31:04 +03:00
static SEC_ACCESS map_canon_ace_perms ( int * pacl_type , DOM_SID * powner_sid , canon_ace * ace )
2000-08-29 04:29:15 +04:00
{
SEC_ACCESS sa ;
uint32 nt_mask = 0 ;
* pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED ;
2001-01-16 01:46:22 +03:00
if ( ( ace - > perms & ( S_IRUSR | S_IWUSR | S_IXUSR ) ) = = ( S_IRUSR | S_IWUSR | S_IXUSR ) ) {
2000-12-07 08:38:01 +03:00
nt_mask = UNIX_ACCESS_RWX ;
2001-01-16 01:46:22 +03:00
} else if ( ( ace - > perms & ( S_IRUSR | S_IWUSR | S_IXUSR ) ) = = 0 ) {
2000-11-30 22:31:04 +03:00
/*
* Here we differentiate between the owner and any other user .
*/
2000-12-07 02:24:31 +03:00
if ( sid_equal ( powner_sid , & ace - > sid ) ) {
2000-11-30 22:31:04 +03:00
nt_mask = UNIX_ACCESS_NONE ;
} else {
2000-12-07 02:24:31 +03:00
/* Not owner, no access. */
nt_mask = 0 ;
2000-11-30 22:31:04 +03:00
}
2000-08-29 04:29:15 +04:00
} else {
2001-01-16 01:46:22 +03:00
nt_mask | = ( ( ace - > perms & S_IRUSR ) ? UNIX_ACCESS_R : 0 ) ;
2000-12-07 08:38:01 +03:00
nt_mask | = ( ( ace - > perms & S_IWUSR ) ? UNIX_ACCESS_W : 0 ) ;
nt_mask | = ( ( ace - > perms & S_IXUSR ) ? UNIX_ACCESS_X : 0 ) ;
2000-08-29 04:29:15 +04:00
}
2000-12-07 08:38:01 +03:00
DEBUG ( 10 , ( " map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x \n " ,
( unsigned int ) ace - > perms , ( unsigned int ) nt_mask ) ) ;
2000-08-29 04:29:15 +04:00
init_sec_access ( & sa , nt_mask ) ;
return sa ;
}
/****************************************************************************
2001-01-12 01:37:59 +03:00
Map NT perms to a UNIX mode_t .
2000-08-29 04:29:15 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES)
# define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)
# define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
static mode_t map_nt_perms ( SEC_ACCESS sec_access , int type )
{
2001-01-12 01:37:59 +03:00
mode_t mode = 0 ;
switch ( type ) {
case S_IRUSR :
if ( sec_access . mask & GENERIC_ALL_ACCESS )
mode = S_IRUSR | S_IWUSR | S_IXUSR ;
else {
mode | = ( sec_access . mask & ( GENERIC_READ_ACCESS | FILE_SPECIFIC_READ_BITS ) ) ? S_IRUSR : 0 ;
mode | = ( sec_access . mask & ( GENERIC_WRITE_ACCESS | FILE_SPECIFIC_WRITE_BITS ) ) ? S_IWUSR : 0 ;
mode | = ( sec_access . mask & ( GENERIC_EXECUTE_ACCESS | FILE_SPECIFIC_EXECUTE_BITS ) ) ? S_IXUSR : 0 ;
}
break ;
case S_IRGRP :
if ( sec_access . mask & GENERIC_ALL_ACCESS )
mode = S_IRGRP | S_IWGRP | S_IXGRP ;
else {
mode | = ( sec_access . mask & ( GENERIC_READ_ACCESS | FILE_SPECIFIC_READ_BITS ) ) ? S_IRGRP : 0 ;
mode | = ( sec_access . mask & ( GENERIC_WRITE_ACCESS | FILE_SPECIFIC_WRITE_BITS ) ) ? S_IWGRP : 0 ;
mode | = ( sec_access . mask & ( GENERIC_EXECUTE_ACCESS | FILE_SPECIFIC_EXECUTE_BITS ) ) ? S_IXGRP : 0 ;
}
break ;
case S_IROTH :
if ( sec_access . mask & GENERIC_ALL_ACCESS )
mode = S_IROTH | S_IWOTH | S_IXOTH ;
else {
mode | = ( sec_access . mask & ( GENERIC_READ_ACCESS | FILE_SPECIFIC_READ_BITS ) ) ? S_IROTH : 0 ;
mode | = ( sec_access . mask & ( GENERIC_WRITE_ACCESS | FILE_SPECIFIC_WRITE_BITS ) ) ? S_IWOTH : 0 ;
mode | = ( sec_access . mask & ( GENERIC_EXECUTE_ACCESS | FILE_SPECIFIC_EXECUTE_BITS ) ) ? S_IXOTH : 0 ;
}
break ;
}
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
return mode ;
2000-08-29 04:29:15 +04:00
}
/****************************************************************************
2001-01-12 01:37:59 +03:00
Unpack a SEC_DESC into a UNIX owner and group .
2000-08-29 04:29:15 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-12-19 23:00:28 +03:00
static BOOL unpack_nt_owners ( SMB_STRUCT_STAT * psbuf , uid_t * puser , gid_t * pgrp , uint32 security_info_sent , SEC_DESC * psd )
{
DOM_SID owner_sid ;
DOM_SID grp_sid ;
enum SID_NAME_USE sid_type ;
* puser = ( uid_t ) - 1 ;
* pgrp = ( gid_t ) - 1 ;
if ( security_info_sent = = 0 ) {
DEBUG ( 0 , ( " unpack_nt_owners: no security info sent ! \n " ) ) ;
return False ;
}
/*
* Validate the owner and group SID ' s .
*/
memset ( & owner_sid , ' \0 ' , sizeof ( owner_sid ) ) ;
memset ( & grp_sid , ' \0 ' , sizeof ( grp_sid ) ) ;
DEBUG ( 5 , ( " unpack_nt_owners: validating owner_sids. \n " ) ) ;
/*
* Don ' t immediately fail if the owner sid cannot be validated .
* This may be a group chown only set .
*/
if ( security_info_sent & OWNER_SECURITY_INFORMATION ) {
sid_copy ( & owner_sid , psd - > owner_sid ) ;
if ( ! sid_to_uid ( & owner_sid , puser , & sid_type ) )
DEBUG ( 3 , ( " unpack_nt_owners: unable to validate owner sid. \n " ) ) ;
}
/*
* Don ' t immediately fail if the group sid cannot be validated .
* This may be an owner chown only set .
*/
if ( security_info_sent & GROUP_SECURITY_INFORMATION ) {
sid_copy ( & grp_sid , psd - > grp_sid ) ;
if ( ! sid_to_gid ( & grp_sid , pgrp , & sid_type ) )
DEBUG ( 3 , ( " unpack_nt_owners: unable to validate group sid. \n " ) ) ;
}
return True ;
}
2001-01-16 01:46:22 +03:00
/****************************************************************************
Merge aces with a common user .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL merge_aces ( canon_ace * list_head , canon_ace * p_ace )
{
canon_ace * curr_ace ;
for ( curr_ace = list_head ; curr_ace ; curr_ace = curr_ace - > next ) {
if ( curr_ace = = p_ace )
continue ;
if ( curr_ace - > type = = p_ace - > type & & sid_equal ( & curr_ace - > sid , & p_ace - > sid ) ) {
if ( DEBUGLVL ( 10 ) ) {
dbgtext ( " Merging ACE's \n " ) ;
print_canon_ace ( p_ace , 0 ) ;
print_canon_ace ( curr_ace , 0 ) ;
}
p_ace - > perms | = curr_ace - > perms ;
DLIST_REMOVE ( list_head , curr_ace ) ;
free ( curr_ace ) ;
return True ;
}
}
return False ;
}
2001-01-23 04:52:30 +03:00
/****************************************************************************
Create a default mode for a directory default ACE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static mode_t get_default_ace_mode ( files_struct * fsp , int type )
{
mode_t force_mode = lp_force_dir_security_mode ( SNUM ( fsp - > conn ) ) ;
mode_t mode = 0 ;
switch ( type ) {
case S_IRUSR :
mode | = ( force_mode & S_IRUSR ) ? S_IRUSR : 0 ;
mode | = ( force_mode & S_IWUSR ) ? S_IWUSR : 0 ;
mode | = ( force_mode & S_IXUSR ) ? S_IXUSR : 0 ;
break ;
case S_IRGRP :
mode | = ( force_mode & S_IRGRP ) ? S_IRUSR : 0 ;
mode | = ( force_mode & S_IWGRP ) ? S_IWUSR : 0 ;
mode | = ( force_mode & S_IXGRP ) ? S_IXUSR : 0 ;
break ;
case S_IROTH :
mode | = ( force_mode & S_IROTH ) ? S_IRUSR : 0 ;
mode | = ( force_mode & S_IWOTH ) ? S_IWUSR : 0 ;
mode | = ( force_mode & S_IXOTH ) ? S_IXUSR : 0 ;
break ;
}
return mode ;
}
/****************************************************************************
A well formed POSIX file or default ACL has at least 3 entries , a
SMB_ACL_USER_OBJ , SMB_ACL_GROUP_OBJ , SMB_ACL_OTHER_OBJ .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL ensure_canon_entry_valid ( canon_ace * * pp_ace ,
files_struct * fsp ,
DOM_SID * pfile_owner_sid ,
DOM_SID * pfile_grp_sid ,
SMB_STRUCT_STAT * pst ,
BOOL default_acl )
{
extern DOM_SID global_sid_World ;
canon_ace * pace ;
BOOL got_user = False ;
BOOL got_grp = False ;
BOOL got_other = False ;
for ( pace = * pp_ace ; pace ; pace = pace - > next ) {
if ( pace - > type = = SMB_ACL_USER_OBJ )
got_user = True ;
else if ( pace - > type = = SMB_ACL_GROUP_OBJ )
got_grp = True ;
else if ( pace - > type = = SMB_ACL_OTHER )
got_other = True ;
}
if ( ! got_user ) {
if ( ( pace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ) = = NULL ) {
DEBUG ( 0 , ( " ensure_canon_entry_valid: malloc fail. \n " ) ) ;
return False ;
}
ZERO_STRUCTP ( pace ) ;
pace - > type = SMB_ACL_USER_OBJ ;
pace - > owner_type = UID_ACE ;
pace - > unix_ug . uid = pst - > st_uid ;
pace - > sid = * pfile_owner_sid ;
pace - > perms = default_acl ? get_default_ace_mode ( fsp , S_IRUSR ) : 0 ;
DLIST_ADD ( * pp_ace , pace ) ;
}
if ( ! got_grp ) {
if ( ( pace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ) = = NULL ) {
DEBUG ( 0 , ( " ensure_canon_entry_valid: malloc fail. \n " ) ) ;
return False ;
}
ZERO_STRUCTP ( pace ) ;
pace - > type = SMB_ACL_GROUP_OBJ ;
pace - > owner_type = GID_ACE ;
pace - > unix_ug . uid = pst - > st_gid ;
pace - > sid = * pfile_grp_sid ;
pace - > perms = default_acl ? get_default_ace_mode ( fsp , S_IRGRP ) : 0 ;
DLIST_ADD ( * pp_ace , pace ) ;
}
if ( ! got_other ) {
if ( ( pace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ) = = NULL ) {
DEBUG ( 0 , ( " ensure_canon_entry_valid: malloc fail. \n " ) ) ;
return False ;
}
ZERO_STRUCTP ( pace ) ;
pace - > type = SMB_ACL_OTHER ;
pace - > owner_type = WORLD_ACE ;
pace - > unix_ug . world = - 1 ;
pace - > sid = global_sid_World ;
pace - > perms = default_acl ? get_default_ace_mode ( fsp , S_IROTH ) : 0 ;
DLIST_ADD ( * pp_ace , pace ) ;
}
return True ;
}
2000-12-19 23:00:28 +03:00
/****************************************************************************
2001-01-12 01:37:59 +03:00
Unpack a SEC_DESC into two canonical ace lists . We don ' t depend on this
succeeding .
2000-12-19 23:00:28 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-01-12 01:37:59 +03:00
static BOOL unpack_canon_ace ( files_struct * fsp ,
2001-01-23 04:52:30 +03:00
SMB_STRUCT_STAT * pst ,
2001-01-12 01:37:59 +03:00
DOM_SID * pfile_owner_sid ,
DOM_SID * pfile_grp_sid ,
canon_ace * * ppfile_ace , canon_ace * * ppdir_ace ,
uint32 security_info_sent , SEC_DESC * psd )
{
extern DOM_SID global_sid_World ;
SEC_ACL * dacl = psd - > dacl ;
BOOL all_aces_are_inherit_only = ( fsp - > is_directory ? True : False ) ;
canon_ace * file_ace = NULL ;
canon_ace * dir_ace = NULL ;
2001-01-16 01:46:22 +03:00
canon_ace * current_ace = NULL ;
2001-01-12 01:37:59 +03:00
enum SID_NAME_USE sid_type ;
int i ;
* ppfile_ace = NULL ;
* ppdir_ace = NULL ;
if ( security_info_sent = = 0 ) {
DEBUG ( 0 , ( " unpack_canon_ace: no security info sent ! \n " ) ) ;
return False ;
}
/*
* If no DACL then this is a chown only security descriptor .
*/
if ( ! ( security_info_sent & DACL_SECURITY_INFORMATION ) | | ! dacl )
return True ;
/*
* Now go through the DACL and create the canon_ace lists .
*/
for ( i = 0 ; i < dacl - > num_aces ; i + + ) {
SEC_ACE * psa = & dacl - > ace [ i ] ;
if ( ( psa - > type ! = SEC_ACE_TYPE_ACCESS_ALLOWED ) & & ( psa - > type ! = SEC_ACE_TYPE_ACCESS_DENIED ) ) {
DEBUG ( 3 , ( " unpack_canon_ace: unable to set anything but an ALLOW or DENY ACE. \n " ) ) ;
return False ;
}
/*
* The security mask may be UNIX_ACCESS_NONE which should map into
* no permissions ( we overload the WRITE_OWNER bit for this ) or it
* should be one of the ALL / EXECUTE / READ / WRITE bits . Arrange for this
* to be so . Any other bits override the UNIX_ACCESS_NONE bit .
*/
psa - > info . mask & = ( GENERIC_ALL_ACCESS | GENERIC_EXECUTE_ACCESS | GENERIC_WRITE_ACCESS |
GENERIC_READ_ACCESS | UNIX_ACCESS_NONE | FILE_ALL_ATTRIBUTES ) ;
if ( psa - > info . mask ! = UNIX_ACCESS_NONE )
psa - > info . mask & = ~ UNIX_ACCESS_NONE ;
/*
* Create a cannon_ace entry representing this NT DACL ACE .
*/
if ( ( current_ace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ) = = NULL ) {
free_canon_ace_list ( file_ace ) ;
free_canon_ace_list ( dir_ace ) ;
DEBUG ( 0 , ( " unpack_canon_ace: malloc fail. \n " ) ) ;
return False ;
}
ZERO_STRUCTP ( current_ace ) ;
sid_copy ( & current_ace - > sid , & psa - > sid ) ;
/*
* Try and work out if the SID is a user or group
* as we need to flag these differently for POSIX .
*/
if ( sid_equal ( & current_ace - > sid , & global_sid_World ) ) {
current_ace - > owner_type = WORLD_ACE ;
current_ace - > unix_ug . world = - 1 ;
} else if ( sid_to_uid ( & current_ace - > sid , & current_ace - > unix_ug . uid , & sid_type ) ) {
current_ace - > owner_type = UID_ACE ;
} else if ( sid_to_gid ( & current_ace - > sid , & current_ace - > unix_ug . gid , & sid_type ) ) {
current_ace - > owner_type = GID_ACE ;
} else {
fstring str ;
free_canon_ace_list ( file_ace ) ;
free_canon_ace_list ( dir_ace ) ;
free ( current_ace ) ;
DEBUG ( 0 , ( " unpack_canon_ace: unable to map SID %s to uid or gid. \n " ,
sid_to_string ( str , & current_ace - > sid ) ) ) ;
return False ;
}
/*
* Map the given NT permissions into a UNIX mode_t containing only
* S_I ( R | W | X ) USR bits .
*/
if ( psa - > type = = SEC_ACE_TYPE_ACCESS_ALLOWED )
current_ace - > perms | = map_nt_perms ( psa - > info , S_IRUSR ) ;
else
2001-01-16 01:46:22 +03:00
current_ace - > perms = 0 ;
2001-01-12 01:37:59 +03:00
/*
* Now note what kind of a POSIX ACL this should map to .
*/
if ( sid_equal ( & current_ace - > sid , pfile_owner_sid ) ) {
/* Note we should apply the default mode/mask here.... FIXME ! JRA */
current_ace - > type = SMB_ACL_USER_OBJ ;
} else if ( sid_equal ( & current_ace - > sid , pfile_grp_sid ) ) {
/* Note we should apply the default mode/mask here.... FIXME ! JRA */
current_ace - > type = SMB_ACL_GROUP_OBJ ;
} else if ( sid_equal ( & current_ace - > sid , & global_sid_World ) ) {
/* Note we should apply the default mode/mask here.... FIXME ! JRA */
current_ace - > type = SMB_ACL_OTHER ;
} else {
/*
* Could be a SMB_ACL_USER or SMB_ACL_GROUP . Check by
* looking at owner_type .
*/
current_ace - > type = ( current_ace - > owner_type = = UID_ACE ) ? SMB_ACL_USER : SMB_ACL_GROUP ;
}
2001-01-23 04:52:30 +03:00
if ( fsp - > is_directory ) {
2001-01-12 01:37:59 +03:00
/*
* We can only add to the default POSIX ACE list if the ACE is
* designed to be inherited by both files and directories .
*/
if ( ( psa - > flags & ( SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_CONTAINER_INHERIT ) ) = =
( SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_CONTAINER_INHERIT ) ) {
DLIST_ADD ( dir_ace , current_ace ) ;
2001-01-23 04:52:30 +03:00
/*
* If this is not an inherit only ACE we need to add a duplicate
* to the file acl .
*/
if ( ! ( psa - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) ) {
canon_ace * dup_ace = dup_canon_ace ( current_ace ) ;
if ( ! dup_ace ) {
DEBUG ( 0 , ( " unpack_canon_ace: malloc fail ! \n " ) ) ;
free_canon_ace_list ( file_ace ) ;
free_canon_ace_list ( dir_ace ) ;
return False ;
}
current_ace = dup_ace ;
} else {
current_ace = NULL ;
}
2001-01-12 01:37:59 +03:00
}
2001-01-23 04:52:30 +03:00
}
/*
* Only add to the file ACL if not inherit only .
*/
if ( ! ( psa - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) ) {
2001-01-12 01:37:59 +03:00
DLIST_ADD ( file_ace , current_ace ) ;
all_aces_are_inherit_only = False ;
2001-01-23 04:52:30 +03:00
current_ace = NULL ;
2001-01-12 01:37:59 +03:00
}
2001-01-23 04:52:30 +03:00
/*
* Free if ACE was not addedd .
*/
if ( current_ace )
free ( current_ace ) ;
2001-01-12 01:37:59 +03:00
}
if ( fsp - > is_directory & & all_aces_are_inherit_only ) {
/*
* Windows 2000 is doing one of these weird ' inherit acl '
* traverses to conserve NTFS ACL resources . Just pretend
* there was no DACL sent . JRA .
*/
2001-01-16 01:46:22 +03:00
DEBUG ( 10 , ( " unpack_canon_ace: Win2k inherit acl traverse. Ignoring DACL. \n " ) ) ;
2001-01-12 01:37:59 +03:00
free_sec_acl ( & psd - > dacl ) ;
}
2001-01-16 01:46:22 +03:00
/*
* Now go through the canon_ace lists and merge entries
* belonging to identical users .
*/
again_file :
for ( current_ace = file_ace ; current_ace ; current_ace = current_ace - > next ) {
if ( merge_aces ( file_ace , current_ace ) )
goto again_file ;
}
again_dir :
for ( current_ace = dir_ace ; current_ace ; current_ace = current_ace - > next ) {
if ( merge_aces ( dir_ace , current_ace ) )
goto again_dir ;
}
2001-01-23 04:52:30 +03:00
/*
* A well formed POSIX file or default ACL has at least 3 entries , a
* SMB_ACL_USER_OBJ , SMB_ACL_GROUP_OBJ , SMB_ACL_OTHER_OBJ
* and optionally a mask entry . Ensure this is the case .
*/
if ( ! ensure_canon_entry_valid ( & file_ace , fsp , pfile_owner_sid , pfile_grp_sid , pst , False ) ) {
free_canon_ace_list ( file_ace ) ;
free_canon_ace_list ( dir_ace ) ;
return False ;
}
if ( ! ensure_canon_entry_valid ( & dir_ace , fsp , pfile_owner_sid , pfile_grp_sid , pst , True ) ) {
free_canon_ace_list ( file_ace ) ;
free_canon_ace_list ( dir_ace ) ;
return False ;
}
if ( DEBUGLVL ( 10 ) ) {
dbgtext ( " unpack_canon_ace: File ACL: \n " ) ;
for ( i = 0 , current_ace = file_ace ; current_ace ; current_ace = current_ace - > next , i + + ) {
print_canon_ace ( current_ace , i ) ;
}
dbgtext ( " unpack_canon_ace: Directory ACL: \n " ) ;
for ( i = 0 , current_ace = dir_ace ; current_ace ; current_ace = current_ace - > next , i + + ) {
print_canon_ace ( current_ace , i ) ;
}
}
2001-01-12 01:37:59 +03:00
* ppfile_ace = file_ace ;
* ppdir_ace = dir_ace ;
return True ;
}
/****************************************************************************
Unpack a SEC_DESC into a set of standard POSIX permissions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL unpack_posix_permissions ( files_struct * fsp , SMB_STRUCT_STAT * psbuf , mode_t * pmode ,
2001-01-16 01:46:22 +03:00
uint32 security_info_sent , SEC_DESC * psd , BOOL posix_acls )
2000-08-29 04:29:15 +04:00
{
extern DOM_SID global_sid_World ;
2001-01-12 01:37:59 +03:00
connection_struct * conn = fsp - > conn ;
2000-08-29 04:29:15 +04:00
DOM_SID file_owner_sid ;
DOM_SID file_grp_sid ;
SEC_ACL * dacl = psd - > dacl ;
2001-01-12 01:37:59 +03:00
BOOL all_aces_are_inherit_only = ( fsp - > is_directory ? True : False ) ;
2000-08-29 04:29:15 +04:00
int i ;
* pmode = 0 ;
if ( security_info_sent = = 0 ) {
2001-01-12 01:37:59 +03:00
DEBUG ( 0 , ( " unpack_posix_permissions: no security info sent ! \n " ) ) ;
2000-08-29 04:29:15 +04:00
return False ;
}
/*
* Windows 2000 sends the owner and group SIDs as the logged in
* user , not the connected user . But it still sends the file
* owner SIDs on an ACL set . So we need to check for the file
* owner and group SIDs as well as the owner SIDs . JRA .
*/
create_file_sids ( psbuf , & file_owner_sid , & file_grp_sid ) ;
/*
* If no DACL then this is a chown only security descriptor .
*/
if ( ! ( security_info_sent & DACL_SECURITY_INFORMATION ) | | ! dacl ) {
* pmode = 0 ;
return True ;
}
/*
* Now go through the DACL and ensure that
* any owner / group sids match .
*/
for ( i = 0 ; i < dacl - > num_aces ; i + + ) {
DOM_SID ace_sid ;
SEC_ACE * psa = & dacl - > ace [ i ] ;
if ( ( psa - > type ! = SEC_ACE_TYPE_ACCESS_ALLOWED ) & &
( psa - > type ! = SEC_ACE_TYPE_ACCESS_DENIED ) ) {
2001-01-12 01:37:59 +03:00
DEBUG ( 3 , ( " unpack_posix_permissions: unable to set anything but an ALLOW or DENY ACE. \n " ) ) ;
2000-08-29 04:29:15 +04:00
return False ;
}
/*
* Ignore or remove bits we don ' t care about on a directory ACE .
*/
2001-01-12 01:37:59 +03:00
if ( fsp - > is_directory ) {
2000-08-29 04:29:15 +04:00
if ( psa - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) {
2001-01-12 01:37:59 +03:00
DEBUG ( 3 , ( " unpack_posix_permissions: ignoring inherit only ACE. \n " ) ) ;
2000-08-29 04:29:15 +04:00
continue ;
}
/*
* At least one of the ACE entries wasn ' t inherit only .
* Flag this so we know the returned mode is valid .
*/
all_aces_are_inherit_only = False ;
}
/*
* Windows 2000 sets these flags even on * file * ACE ' s . This is wrong
* but we can ignore them for now . Revisit this when we go to POSIX
* ACLs on directories .
*/
psa - > flags & = ~ ( SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_CONTAINER_INHERIT ) ;
if ( psa - > flags ! = 0 ) {
2001-01-12 01:37:59 +03:00
DEBUG ( 1 , ( " unpack_posix_permissions: unable to set ACE flags (%x). \n " ,
2000-08-29 04:29:15 +04:00
( unsigned int ) psa - > flags ) ) ;
return False ;
}
/*
* The security mask may be UNIX_ACCESS_NONE which should map into
* no permissions ( we overload the WRITE_OWNER bit for this ) or it
* should be one of the ALL / EXECUTE / READ / WRITE bits . Arrange for this
* to be so . Any other bits override the UNIX_ACCESS_NONE bit .
*/
psa - > info . mask & = ( GENERIC_ALL_ACCESS | GENERIC_EXECUTE_ACCESS | GENERIC_WRITE_ACCESS |
GENERIC_READ_ACCESS | UNIX_ACCESS_NONE | FILE_ALL_ATTRIBUTES ) ;
if ( psa - > info . mask ! = UNIX_ACCESS_NONE )
psa - > info . mask & = ~ UNIX_ACCESS_NONE ;
sid_copy ( & ace_sid , & psa - > sid ) ;
if ( sid_equal ( & ace_sid , & file_owner_sid ) ) {
/*
* Map the desired permissions into owner perms .
*/
if ( psa - > type = = SEC_ACE_TYPE_ACCESS_ALLOWED )
* pmode | = map_nt_perms ( psa - > info , S_IRUSR ) ;
else
* pmode & = ~ ( map_nt_perms ( psa - > info , S_IRUSR ) ) ;
2001-01-16 01:46:22 +03:00
2000-08-29 04:29:15 +04:00
} else if ( sid_equal ( & ace_sid , & file_grp_sid ) ) {
/*
* Map the desired permissions into group perms .
*/
if ( psa - > type = = SEC_ACE_TYPE_ACCESS_ALLOWED )
* pmode | = map_nt_perms ( psa - > info , S_IRGRP ) ;
else
* pmode & = ~ ( map_nt_perms ( psa - > info , S_IRGRP ) ) ;
} else if ( sid_equal ( & ace_sid , & global_sid_World ) ) {
/*
* Map the desired permissions into other perms .
*/
if ( psa - > type = = SEC_ACE_TYPE_ACCESS_ALLOWED )
* pmode | = map_nt_perms ( psa - > info , S_IROTH ) ;
else
* pmode & = ~ ( map_nt_perms ( psa - > info , S_IROTH ) ) ;
} else {
2001-01-16 01:46:22 +03:00
/*
* Only bother printing the level zero error if we didn ' t get any
* POSIX ACLS .
*/
if ( ! posix_acls )
DEBUG ( 0 , ( " unpack_posix_permissions: unknown SID used in ACL. \n " ) ) ;
2000-08-29 04:29:15 +04:00
return False ;
}
}
2001-01-12 01:37:59 +03:00
if ( fsp - > is_directory & & all_aces_are_inherit_only ) {
2000-08-29 04:29:15 +04:00
/*
* Windows 2000 is doing one of these weird ' inherit acl '
* traverses to conserve NTFS ACL resources . Just pretend
* there was no DACL sent . JRA .
*/
2001-01-12 01:37:59 +03:00
DEBUG ( 10 , ( " unpack_posix_permissions: Win2k inherit acl traverse. Ignoring DACL. \n " ) ) ;
2000-08-29 04:29:15 +04:00
free_sec_acl ( & psd - > dacl ) ;
}
2001-01-12 01:37:59 +03:00
/*
* Check to see if we need to change anything .
* Enforce limits on modified bits * only * . Don ' t enforce masks
* on bits not changed by the user .
*/
if ( fsp - > is_directory ) {
* pmode & = ( lp_dir_security_mask ( SNUM ( conn ) ) | psbuf - > st_mode ) ;
* pmode | = ( lp_force_dir_security_mode ( SNUM ( conn ) ) & ( * pmode ^ psbuf - > st_mode ) ) ;
} else {
* pmode & = ( lp_security_mask ( SNUM ( conn ) ) | psbuf - > st_mode ) ;
* pmode | = ( lp_force_security_mode ( SNUM ( conn ) ) & ( * pmode ^ psbuf - > st_mode ) ) ;
}
/*
* Preserve special bits .
*/
* pmode | = ( psbuf - > st_mode & ~ 0777 ) ;
2000-08-29 04:29:15 +04:00
return True ;
}
2000-12-01 03:32:25 +03:00
/****************************************************************************
2001-01-12 01:37:59 +03:00
Map POSIX ACL perms to canon_ace permissions ( a mode_t containing only S_ ( R | W | X ) USR bits ) .
2000-12-01 03:32:25 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-12-07 08:38:01 +03:00
static mode_t convert_permset_to_mode_t ( SMB_ACL_PERMSET_T permset )
{
mode_t ret = 0 ;
ret | = ( sys_acl_get_perm ( permset , SMB_ACL_READ ) ? S_IRUSR : 0 ) ;
ret | = ( sys_acl_get_perm ( permset , SMB_ACL_WRITE ) ? S_IWUSR : 0 ) ;
ret | = ( sys_acl_get_perm ( permset , SMB_ACL_EXECUTE ) ? S_IXUSR : 0 ) ;
return ret ;
}
/****************************************************************************
2001-01-12 01:37:59 +03:00
Map generic UNIX permissions to canon_ace permissions ( a mode_t containing only S_ ( R | W | X ) USR bits ) .
2000-12-07 08:38:01 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static mode_t unix_perms_to_acl_perms ( mode_t mode , int r_mask , int w_mask , int x_mask )
2000-12-01 03:32:25 +03:00
{
2000-12-07 08:38:01 +03:00
mode_t ret = 0 ;
2000-12-01 03:32:25 +03:00
2000-12-07 08:38:01 +03:00
if ( mode & r_mask )
ret | = S_IRUSR ;
if ( mode & w_mask )
ret | = S_IWUSR ;
if ( mode & x_mask )
ret | = S_IXUSR ;
2000-12-01 03:32:25 +03:00
return ret ;
}
2001-01-12 01:37:59 +03:00
/****************************************************************************
Map canon_ace permissions ( a mode_t containing only S_ ( R | W | X ) USR bits ) to
an SMB_ACL_PERMSET_T .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int map_acl_perms_to_permset ( mode_t mode , SMB_ACL_PERMSET_T * p_permset )
{
if ( sys_acl_clear_perms ( * p_permset ) = = - 1 )
return - 1 ;
if ( mode & S_IRUSR ) {
if ( sys_acl_add_perm ( * p_permset , SMB_ACL_READ ) = = - 1 )
return - 1 ;
}
if ( mode & S_IWUSR ) {
if ( sys_acl_add_perm ( * p_permset , SMB_ACL_WRITE ) = = - 1 )
return - 1 ;
}
if ( mode & S_IXUSR ) {
if ( sys_acl_add_perm ( * p_permset , SMB_ACL_EXECUTE ) = = - 1 )
return - 1 ;
}
return 0 ;
}
2000-11-30 22:31:04 +03:00
/****************************************************************************
Count a linked list of canonical ACE entries .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static size_t count_canon_ace_list ( canon_ace * list_head )
{
size_t count = 0 ;
canon_ace * ace ;
for ( ace = list_head ; ace ; ace = ace - > next )
count + + ;
return count ;
}
/****************************************************************************
Free a linked list of canonical ACE entries .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_canon_ace_list ( canon_ace * list_head )
{
while ( list_head ) {
canon_ace * old_head = list_head ;
DLIST_REMOVE ( list_head , list_head ) ;
free ( old_head ) ;
}
}
2000-12-01 03:32:25 +03:00
/******************************************************************************
Fall back to the generic 3 element UNIX permissions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static canon_ace * unix_canonicalise_acl ( files_struct * fsp , SMB_STRUCT_STAT * psbuf ,
DOM_SID * powner , DOM_SID * pgroup )
{
extern DOM_SID global_sid_World ;
canon_ace * list_head = NULL ;
canon_ace * owner_ace = NULL ;
canon_ace * group_ace = NULL ;
canon_ace * other_ace = NULL ;
/*
* Create 3 linked list entries .
*/
if ( ( owner_ace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ) = = NULL )
goto fail ;
2000-12-07 02:24:31 +03:00
if ( ( group_ace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ) = = NULL )
2000-12-01 03:32:25 +03:00
goto fail ;
if ( ( other_ace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ) = = NULL )
goto fail ;
ZERO_STRUCTP ( owner_ace ) ;
ZERO_STRUCTP ( group_ace ) ;
ZERO_STRUCTP ( other_ace ) ;
2000-12-06 04:34:16 +03:00
owner_ace - > type = SMB_ACL_USER_OBJ ;
2000-12-01 03:32:25 +03:00
owner_ace - > sid = * powner ;
2001-01-12 01:37:59 +03:00
owner_ace - > unix_ug . uid = psbuf - > st_uid ;
owner_ace - > owner_type = UID_ACE ;
2000-12-01 03:32:25 +03:00
2000-12-06 04:34:16 +03:00
group_ace - > type = SMB_ACL_GROUP_OBJ ;
2000-12-01 03:32:25 +03:00
group_ace - > sid = * pgroup ;
2001-01-12 01:37:59 +03:00
owner_ace - > unix_ug . gid = psbuf - > st_gid ;
owner_ace - > owner_type = GID_ACE ;
2000-12-01 03:32:25 +03:00
2000-12-07 08:38:01 +03:00
other_ace - > type = SMB_ACL_OTHER ;
2000-12-01 03:32:25 +03:00
other_ace - > sid = global_sid_World ;
2001-01-12 01:37:59 +03:00
owner_ace - > unix_ug . world = - 1 ;
owner_ace - > owner_type = WORLD_ACE ;
2000-12-01 03:32:25 +03:00
if ( ! fsp - > is_directory ) {
2000-12-07 02:24:31 +03:00
owner_ace - > perms = unix_perms_to_acl_perms ( psbuf - > st_mode , S_IRUSR , S_IWUSR , S_IXUSR ) ;
group_ace - > perms = unix_perms_to_acl_perms ( psbuf - > st_mode , S_IRGRP , S_IWGRP , S_IXGRP ) ;
other_ace - > perms = unix_perms_to_acl_perms ( psbuf - > st_mode , S_IROTH , S_IWOTH , S_IXOTH ) ;
2000-12-01 03:32:25 +03:00
} else {
mode_t mode = unix_mode ( fsp - > conn , FILE_ATTRIBUTE_ARCHIVE , fsp - > fsp_name ) ;
owner_ace - > perms = unix_perms_to_acl_perms ( mode , S_IRUSR , S_IWUSR , S_IXUSR ) ;
group_ace - > perms = unix_perms_to_acl_perms ( mode , S_IRGRP , S_IWGRP , S_IXGRP ) ;
other_ace - > perms = unix_perms_to_acl_perms ( mode , S_IROTH , S_IWOTH , S_IXOTH ) ;
}
DLIST_ADD ( list_head , other_ace ) ;
DLIST_ADD ( list_head , group_ace ) ;
DLIST_ADD ( list_head , owner_ace ) ;
return list_head ;
fail :
safe_free ( owner_ace ) ;
safe_free ( group_ace ) ;
safe_free ( other_ace ) ;
return NULL ;
}
2000-11-30 04:00:36 +03:00
/****************************************************************************
Create a linked list of canonical ACE entries . This is sorted so that DENY
entries are at the front of the list , as NT requires .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-12-06 05:32:48 +03:00
static canon_ace * canonicalise_acl ( SMB_ACL_T posix_acl , SMB_STRUCT_STAT * psbuf )
2000-11-30 04:00:36 +03:00
{
extern DOM_SID global_sid_World ;
2000-12-07 08:38:01 +03:00
mode_t acl_mask = ( S_IRUSR | S_IWUSR | S_IXUSR ) ;
2000-11-30 04:00:36 +03:00
canon_ace * list_head = NULL ;
canon_ace * ace = NULL ;
canon_ace * next_ace = NULL ;
2000-12-06 04:34:16 +03:00
int entry_id = SMB_ACL_FIRST_ENTRY ;
SMB_ACL_ENTRY_T entry ;
2000-11-30 04:00:36 +03:00
2000-12-06 04:34:16 +03:00
while ( sys_acl_get_entry ( posix_acl , entry_id , & entry ) = = 1 ) {
SMB_ACL_TAG_T tagtype ;
SMB_ACL_PERMSET_T permset ;
2000-11-30 04:00:36 +03:00
DOM_SID sid ;
2001-01-12 01:37:59 +03:00
posix_id unix_ug ;
enum ace_owner owner_type ;
2000-11-30 04:00:36 +03:00
/* get_next... */
2000-12-06 04:34:16 +03:00
if ( entry_id = = SMB_ACL_FIRST_ENTRY )
entry_id = SMB_ACL_NEXT_ENTRY ;
2000-11-30 04:00:36 +03:00
/* Is this a MASK entry ? */
2000-12-06 05:32:48 +03:00
if ( sys_acl_get_tag_type ( entry , & tagtype ) = = - 1 )
2000-11-30 04:00:36 +03:00
continue ;
2000-12-06 05:32:48 +03:00
if ( sys_acl_get_permset ( entry , & permset ) = = - 1 )
2000-11-30 04:00:36 +03:00
continue ;
/* Decide which SID to use based on the ACL type. */
switch ( tagtype ) {
2000-12-07 02:24:31 +03:00
case SMB_ACL_USER_OBJ :
2000-11-30 04:00:36 +03:00
/* Get the SID from the owner. */
uid_to_sid ( & sid , psbuf - > st_uid ) ;
2001-01-12 01:37:59 +03:00
unix_ug . uid = psbuf - > st_uid ;
owner_type = UID_ACE ;
2000-11-30 04:00:36 +03:00
break ;
2000-12-07 02:24:31 +03:00
case SMB_ACL_USER :
2000-11-30 04:00:36 +03:00
{
2000-12-06 04:34:16 +03:00
uid_t * puid = ( uid_t * ) sys_acl_get_qualifier ( entry ) ;
2000-11-30 04:00:36 +03:00
if ( puid = = NULL ) {
DEBUG ( 0 , ( " canonicalise_acl: Failed to get uid. \n " ) ) ;
continue ;
}
uid_to_sid ( & sid , * puid ) ;
2001-01-12 01:37:59 +03:00
unix_ug . uid = * puid ;
owner_type = UID_ACE ;
2000-11-30 04:00:36 +03:00
break ;
}
2000-12-07 02:24:31 +03:00
case SMB_ACL_GROUP_OBJ :
2000-11-30 04:00:36 +03:00
/* Get the SID from the owning group. */
gid_to_sid ( & sid , psbuf - > st_gid ) ;
2001-01-12 01:37:59 +03:00
unix_ug . gid = psbuf - > st_gid ;
owner_type = GID_ACE ;
2000-11-30 04:00:36 +03:00
break ;
2000-12-07 02:24:31 +03:00
case SMB_ACL_GROUP :
2000-11-30 04:00:36 +03:00
{
2000-12-06 04:34:16 +03:00
gid_t * pgid = ( gid_t * ) sys_acl_get_qualifier ( entry ) ;
2000-11-30 04:00:36 +03:00
if ( pgid = = NULL ) {
DEBUG ( 0 , ( " canonicalise_acl: Failed to get gid. \n " ) ) ;
continue ;
}
gid_to_sid ( & sid , * pgid ) ;
2001-01-12 01:37:59 +03:00
unix_ug . gid = * pgid ;
owner_type = GID_ACE ;
2000-11-30 04:00:36 +03:00
break ;
}
2000-12-07 02:24:31 +03:00
case SMB_ACL_MASK :
2000-12-07 08:38:01 +03:00
acl_mask = convert_permset_to_mode_t ( permset ) ;
2000-11-30 04:00:36 +03:00
continue ; /* Don't count the mask as an entry. */
2000-12-07 08:38:01 +03:00
case SMB_ACL_OTHER :
2000-11-30 04:00:36 +03:00
/* Use the Everyone SID */
sid = global_sid_World ;
2001-01-12 01:37:59 +03:00
unix_ug . world = - 1 ;
owner_type = WORLD_ACE ;
2000-11-30 04:00:36 +03:00
break ;
default :
DEBUG ( 0 , ( " canonicalise_acl: Unknown tagtype %u \n " , ( unsigned int ) tagtype ) ) ;
continue ;
2000-12-07 08:38:01 +03:00
}
2000-11-30 04:00:36 +03:00
/*
* Add this entry to the list .
*/
if ( ( ace = ( canon_ace * ) malloc ( sizeof ( canon_ace ) ) ) = = NULL )
goto fail ;
ZERO_STRUCTP ( ace ) ;
ace - > type = tagtype ;
2000-12-07 08:38:01 +03:00
ace - > perms = convert_permset_to_mode_t ( permset ) ;
2000-11-30 04:00:36 +03:00
ace - > sid = sid ;
2001-01-12 01:37:59 +03:00
ace - > unix_ug = unix_ug ;
ace - > owner_type = owner_type ;
2000-11-30 04:00:36 +03:00
DLIST_ADD ( list_head , ace ) ;
}
/*
* Now go through the list , masking the permissions with the
2000-12-07 08:38:01 +03:00
* acl_mask . If the permissions are 0 it should be listed
* first .
2000-11-30 04:00:36 +03:00
*/
for ( ace = list_head ; ace ; ace = next_ace ) {
2000-12-07 02:24:31 +03:00
next_ace = ace - > next ;
2000-12-07 08:38:01 +03:00
/* Masks are only applied to entries other than USER_OBJ and OTHER. */
if ( ace - > type ! = SMB_ACL_OTHER & & ace - > type ! = SMB_ACL_USER_OBJ )
ace - > perms & = acl_mask ;
if ( ace - > perms = = 0 )
DLIST_PROMOTE ( list_head , ace ) ;
}
if ( DEBUGLVL ( 10 ) ) {
char * acl_text = sys_acl_to_text ( posix_acl , NULL ) ;
dbgtext ( " canonicalize_acl: processed acl %s \n " , acl_text = = NULL ? " NULL " : acl_text ) ;
if ( acl_text )
2000-12-19 21:41:51 +03:00
sys_acl_free_text ( acl_text ) ;
2000-11-30 04:00:36 +03:00
}
return list_head ;
2000-12-07 02:24:31 +03:00
fail :
free_canon_ace_list ( list_head ) ;
return NULL ;
2000-11-30 04:00:36 +03:00
}
2001-01-12 01:37:59 +03:00
/****************************************************************************
Attempt to apply an ACL to a file or directory .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-01-23 04:52:30 +03:00
static BOOL set_canon_ace_list ( files_struct * fsp , canon_ace * the_ace , BOOL default_ace , BOOL * pacl_set_support )
2001-01-12 01:37:59 +03:00
{
BOOL ret = False ;
2001-01-15 22:02:57 +03:00
SMB_ACL_T the_acl = sys_acl_init ( ( int ) count_canon_ace_list ( the_ace ) + 1 ) ;
2001-01-12 01:37:59 +03:00
canon_ace * p_ace ;
int i ;
2001-01-15 22:02:57 +03:00
SMB_ACL_ENTRY_T mask_entry ;
SMB_ACL_PERMSET_T mask_permset ;
2001-01-12 01:37:59 +03:00
SMB_ACL_TYPE_T the_acl_type = ( default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS ) ;
if ( the_acl = = NULL ) {
# if !defined(HAVE_NO_ACLS)
/*
* Only print this error message if we have some kind of ACL
* support that ' s not working . Otherwise we would always get this .
*/
DEBUG ( 0 , ( " set_canon_ace_list: Unable to init %s ACL. (%s) \n " ,
default_ace ? " default " : " file " , strerror ( errno ) ) ) ;
# endif
2001-01-23 04:52:30 +03:00
* pacl_set_support = False ;
2001-01-12 01:37:59 +03:00
return False ;
}
for ( i = 0 , p_ace = the_ace ; p_ace ; p_ace = p_ace - > next , i + + ) {
SMB_ACL_ENTRY_T the_entry ;
SMB_ACL_PERMSET_T the_permset ;
/*
* Get the entry for this ACE .
*/
if ( sys_acl_create_entry ( & the_acl , & the_entry ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to create entry %d. (%s) \n " ,
i , strerror ( errno ) ) ) ;
goto done ;
}
2001-01-23 04:52:30 +03:00
/*
* Ok - we now know the ACL calls should be working , don ' t
* allow fallback to chmod .
*/
* pacl_set_support = True ;
2001-01-12 01:37:59 +03:00
/*
* Initialise the entry from the canon_ace .
*/
/*
* First tell the entry what type of ACE this is .
*/
if ( sys_acl_set_tag_type ( the_entry , p_ace - > type ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to set tag type on entry %d. (%s) \n " ,
i , strerror ( errno ) ) ) ;
goto done ;
}
/*
* Only set the qualifier ( user or group id ) if the entry is a user
* or group id ACE .
*/
if ( ( p_ace - > type = = SMB_ACL_USER ) | | ( p_ace - > type = = SMB_ACL_GROUP ) ) {
if ( sys_acl_set_qualifier ( the_entry , ( void * ) & p_ace - > unix_ug . uid ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to set qualifier on entry %d. (%s) \n " ,
i , strerror ( errno ) ) ) ;
goto done ;
}
}
/*
* Convert the mode_t perms in the canon_ace to a POSIX permset .
*/
2001-01-15 22:02:57 +03:00
if ( sys_acl_get_permset ( the_entry , & the_permset ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to get permset on entry %d. (%s) \n " ,
2001-01-12 01:37:59 +03:00
i , strerror ( errno ) ) ) ;
goto done ;
}
2001-01-15 22:02:57 +03:00
if ( map_acl_perms_to_permset ( p_ace - > perms , & the_permset ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s) \n " ,
p_ace - > perms , i , strerror ( errno ) ) ) ;
goto done ;
}
2001-01-12 01:37:59 +03:00
/*
* . . and apply them to the entry .
*/
if ( sys_acl_set_permset ( the_entry , the_permset ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to add permset on entry %d. (%s) \n " ,
i , strerror ( errno ) ) ) ;
goto done ;
}
2001-01-16 01:46:22 +03:00
if ( DEBUGLVL ( 10 ) )
print_canon_ace ( p_ace , i ) ;
2001-01-12 01:37:59 +03:00
}
2001-01-15 22:02:57 +03:00
/*
* Add in a mask of rwx .
*/
if ( sys_acl_create_entry ( & the_acl , & mask_entry ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to create mask entry. (%s) \n " , strerror ( errno ) ) ) ;
goto done ;
}
if ( sys_acl_set_tag_type ( mask_entry , SMB_ACL_MASK ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to set tag type on mask entry. (%s) \n " , strerror ( errno ) ) ) ;
goto done ;
}
if ( sys_acl_get_permset ( mask_entry , & mask_permset ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to get mask permset. (%s) \n " , strerror ( errno ) ) ) ;
goto done ;
}
if ( map_acl_perms_to_permset ( S_IRUSR | S_IWUSR | S_IXUSR , & mask_permset ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to create mask permset. (%s) \n " , strerror ( errno ) ) ) ;
goto done ;
}
if ( sys_acl_set_permset ( mask_entry , mask_permset ) = = - 1 ) {
DEBUG ( 0 , ( " set_canon_ace_list: Failed to add mask permset. (%s) \n " , strerror ( errno ) ) ) ;
goto done ;
}
2001-01-12 01:37:59 +03:00
/*
* Check if the ACL is valid .
*/
if ( sys_acl_valid ( the_acl ) = = - 1 ) {
2001-01-23 04:52:30 +03:00
DEBUG ( 0 , ( " set_canon_ace_list: ACL type (%s) is invalid for set (%s). \n " ,
the_acl_type = = SMB_ACL_TYPE_DEFAULT ? " directory default " : " file " ,
strerror ( errno ) ) ) ;
2001-01-12 01:37:59 +03:00
goto done ;
}
/*
* Finally apply it to the file or directory .
*/
2001-01-12 02:41:33 +03:00
if ( default_ace | | fsp - > is_directory | | fsp - > fd = = - 1 ) {
2001-01-12 01:37:59 +03:00
if ( sys_acl_set_file ( fsp - > fsp_name , the_acl_type , the_acl ) = = - 1 ) {
2001-01-23 04:52:30 +03:00
DEBUG ( 0 , ( " set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s). \n " ,
the_acl_type = = SMB_ACL_TYPE_DEFAULT ? " directory default " : " file " ,
2001-01-12 01:37:59 +03:00
fsp - > fsp_name , strerror ( errno ) ) ) ;
goto done ;
}
} else {
2001-01-12 02:41:33 +03:00
if ( sys_acl_set_fd ( fsp - > fd , the_acl ) = = - 1 ) {
2001-01-12 01:37:59 +03:00
DEBUG ( 0 , ( " set_canon_ace_list: sys_acl_set_file failed for file %s (%s). \n " ,
fsp - > fsp_name , strerror ( errno ) ) ) ;
goto done ;
}
}
ret = True ;
done :
if ( the_acl ! = NULL )
sys_acl_free_acl ( the_acl ) ;
return ret ;
}
2000-08-29 04:29:15 +04:00
/****************************************************************************
Reply to query a security descriptor from an fsp . If it succeeds it allocates
the space for the return elements and returns the size needed to return the
security descriptor . This should be the only external function needed for
the UNIX style get ACL .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t get_nt_acl ( files_struct * fsp , SEC_DESC * * ppdesc )
{
SMB_STRUCT_STAT sbuf ;
2000-11-30 22:31:04 +03:00
SEC_ACE * nt_ace_list ;
2000-08-29 04:29:15 +04:00
DOM_SID owner_sid ;
DOM_SID group_sid ;
2000-11-30 22:31:04 +03:00
size_t sd_size = 0 ;
2000-08-29 04:29:15 +04:00
SEC_ACL * psa = NULL ;
2000-10-28 23:38:39 +04:00
size_t num_acls = 0 ;
size_t num_dir_acls = 0 ;
2000-11-30 22:31:04 +03:00
size_t num_aces = 0 ;
2000-12-06 04:34:16 +03:00
SMB_ACL_T posix_acl = NULL ;
SMB_ACL_T dir_acl = NULL ;
2000-11-30 22:31:04 +03:00
canon_ace * file_ace = NULL ;
canon_ace * dir_ace = NULL ;
2000-08-29 04:29:15 +04:00
* ppdesc = NULL ;
2001-01-16 01:46:22 +03:00
DEBUG ( 10 , ( " get_nt_acl: called for file %s \n " , fsp - > fsp_name ) ) ;
2000-08-29 04:29:15 +04:00
if ( fsp - > is_directory | | fsp - > fd = = - 1 ) {
2000-11-30 04:00:36 +03:00
/* Get the stat struct for the owner info. */
2000-12-07 02:24:31 +03:00
if ( vfs_stat ( fsp - > conn , fsp - > fsp_name , & sbuf ) ! = 0 ) {
2000-08-29 04:29:15 +04:00
return 0 ;
}
/*
* Get the ACL from the path .
*/
2000-12-06 04:34:16 +03:00
posix_acl = sys_acl_get_file ( dos_to_unix ( fsp - > fsp_name , False ) , SMB_ACL_TYPE_ACCESS ) ;
2000-08-29 04:29:15 +04:00
2000-10-28 23:38:39 +04:00
/*
* If it ' s a directory get the default POSIX ACL .
*/
2000-11-30 04:00:36 +03:00
if ( fsp - > is_directory )
2000-12-06 04:34:16 +03:00
dir_acl = sys_acl_get_file ( dos_to_unix ( fsp - > fsp_name , False ) , SMB_ACL_TYPE_DEFAULT ) ;
2000-10-28 23:38:39 +04:00
2000-08-29 04:29:15 +04:00
} else {
2000-11-30 04:00:36 +03:00
/* Get the stat struct for the owner info. */
2000-12-07 02:24:31 +03:00
if ( vfs_fstat ( fsp , fsp - > fd , & sbuf ) ! = 0 ) {
2000-08-29 04:29:15 +04:00
return 0 ;
}
/*
* Get the ACL from the fd .
*/
2000-12-06 04:34:16 +03:00
posix_acl = sys_acl_get_fd ( fsp - > fd ) ;
2000-08-29 04:29:15 +04:00
}
2000-12-07 08:38:01 +03:00
DEBUG ( 5 , ( " get_nt_acl : file ACL %s, directory ACL %s \n " ,
posix_acl ? " present " : " absent " ,
dir_acl ? " present " : " absent " ) ) ;
2000-08-29 04:29:15 +04:00
/*
* Get the owner , group and world SIDs .
*/
create_file_sids ( & sbuf , & owner_sid , & group_sid ) ;
2000-11-30 22:31:04 +03:00
/* Create the canon_ace lists. */
2000-12-01 03:32:25 +03:00
if ( posix_acl )
file_ace = canonicalise_acl ( posix_acl , & sbuf ) ;
else
file_ace = unix_canonicalise_acl ( fsp , & sbuf , & owner_sid , & group_sid ) ;
2000-11-30 22:31:04 +03:00
num_acls = count_canon_ace_list ( file_ace ) ;
2000-08-29 04:29:15 +04:00
2000-11-30 22:31:04 +03:00
if ( fsp - > is_directory ) {
2001-01-23 04:52:30 +03:00
if ( dir_acl )
2000-12-01 03:32:25 +03:00
dir_ace = canonicalise_acl ( dir_acl , & sbuf ) ;
else
dir_ace = unix_canonicalise_acl ( fsp , & sbuf , & owner_sid , & group_sid ) ;
2000-11-30 22:31:04 +03:00
num_dir_acls = count_canon_ace_list ( dir_ace ) ;
}
2000-08-29 04:29:15 +04:00
2000-11-30 04:00:36 +03:00
/* Allocate the ace list. */
2000-11-30 22:31:04 +03:00
if ( ( nt_ace_list = ( SEC_ACE * ) malloc ( ( num_acls + num_dir_acls ) * sizeof ( SEC_ACE ) ) ) = = NULL ) {
DEBUG ( 0 , ( " get_nt_acl: Unable to malloc space for nt_ace_list. \n " ) ) ;
2000-12-07 02:24:31 +03:00
goto done ;
2000-11-30 04:00:36 +03:00
}
2000-11-30 22:31:04 +03:00
memset ( nt_ace_list , ' \0 ' , ( num_acls + num_dir_acls ) * sizeof ( SEC_ACE ) ) ;
/*
* Create the NT ACE list from the canonical ace lists .
*/
{
canon_ace * ace ;
int nt_acl_type ;
2000-12-07 02:24:31 +03:00
int i ;
2000-11-30 04:00:36 +03:00
2000-11-30 22:31:04 +03:00
ace = file_ace ;
for ( i = 0 ; i < num_acls ; i + + , ace = ace - > next ) {
SEC_ACCESS acc = map_canon_ace_perms ( & nt_acl_type , & owner_sid , ace ) ;
init_sec_ace ( & nt_ace_list [ num_aces + + ] , & ace - > sid , nt_acl_type , acc , 0 ) ;
}
ace = dir_ace ;
for ( i = 0 ; i < num_dir_acls ; i + + , ace = ace - > next ) {
SEC_ACCESS acc = map_canon_ace_perms ( & nt_acl_type , & owner_sid , ace ) ;
init_sec_ace ( & nt_ace_list [ num_aces + + ] , & ace - > sid , nt_acl_type , acc ,
SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_CONTAINER_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY ) ;
}
2000-11-30 04:00:36 +03:00
}
2000-11-30 22:31:04 +03:00
if ( num_acls ) {
2000-12-07 02:24:31 +03:00
if ( ( psa = make_sec_acl ( ACL_REVISION , num_aces , nt_ace_list ) ) = = NULL ) {
2000-11-30 22:31:04 +03:00
DEBUG ( 0 , ( " get_nt_acl: Unable to malloc space for acl. \n " ) ) ;
goto done ;
}
}
* ppdesc = make_standard_sec_desc ( & owner_sid , & group_sid , psa , & sd_size ) ;
if ( ! * ppdesc ) {
DEBUG ( 0 , ( " get_nt_acl: Unable to malloc space for security descriptor. \n " ) ) ;
sd_size = 0 ;
2000-11-30 04:00:36 +03:00
}
done :
if ( posix_acl )
2000-12-19 21:41:51 +03:00
sys_acl_free_acl ( posix_acl ) ;
2000-12-07 02:24:31 +03:00
if ( dir_acl )
2000-12-19 21:41:51 +03:00
sys_acl_free_acl ( dir_acl ) ;
2001-01-12 01:37:59 +03:00
free_canon_ace_list ( file_ace ) ;
free_canon_ace_list ( dir_ace ) ;
2000-11-30 22:31:04 +03:00
if ( nt_ace_list )
free ( nt_ace_list ) ;
if ( psa )
free_sec_acl ( & psa ) ;
return sd_size ;
}
2000-11-30 04:00:36 +03:00
2000-08-29 04:29:15 +04:00
/****************************************************************************
Reply to set a security descriptor on an fsp . security_info_sent is the
description of the following NT ACL .
This should be the only external function needed for the UNIX style set ACL .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL set_nt_acl ( files_struct * fsp , uint32 security_info_sent , SEC_DESC * psd )
{
2000-12-19 23:00:28 +03:00
connection_struct * conn = fsp - > conn ;
uid_t user = ( uid_t ) - 1 ;
gid_t grp = ( gid_t ) - 1 ;
mode_t perms = 0 ;
SMB_STRUCT_STAT sbuf ;
2001-01-12 01:37:59 +03:00
DOM_SID file_owner_sid ;
DOM_SID file_grp_sid ;
canon_ace * file_ace_list = NULL ;
canon_ace * dir_ace_list = NULL ;
BOOL posix_perms ;
BOOL acl_perms ;
2000-08-29 04:29:15 +04:00
2001-01-16 01:46:22 +03:00
DEBUG ( 10 , ( " set_nt_acl: called for file %s \n " , fsp - > fsp_name ) ) ;
2000-12-19 23:00:28 +03:00
/*
* Get the current state of the file .
*/
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
if ( fsp - > is_directory | | fsp - > fd = = - 1 ) {
if ( vfs_stat ( fsp - > conn , fsp - > fsp_name , & sbuf ) ! = 0 )
return False ;
} else {
2001-01-12 01:37:59 +03:00
if ( vfs_fstat ( fsp , fsp - > fd , & sbuf ) ! = 0 )
2000-12-19 23:00:28 +03:00
return False ;
}
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
/*
* Unpack the user / group / world id ' s .
*/
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
if ( ! unpack_nt_owners ( & sbuf , & user , & grp , security_info_sent , psd ) )
return False ;
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
/*
* Do we need to chown ?
*/
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
if ( ( user ! = ( uid_t ) - 1 | | grp ! = ( uid_t ) - 1 ) & & ( sbuf . st_uid ! = user | | sbuf . st_gid ! = grp ) ) {
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
DEBUG ( 3 , ( " set_nt_acl: chown %s. uid = %u, gid = %u. \n " ,
fsp - > fsp_name , ( unsigned int ) user , ( unsigned int ) grp ) ) ;
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
if ( vfs_chown ( fsp - > conn , fsp - > fsp_name , user , grp ) = = - 1 ) {
DEBUG ( 3 , ( " set_nt_acl: chown %s, %u, %u failed. Error = %s. \n " ,
fsp - > fsp_name , ( unsigned int ) user , ( unsigned int ) grp , strerror ( errno ) ) ) ;
return False ;
}
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
/*
* Recheck the current state of the file , which may have changed .
* ( suid / sgid bits , for instance )
*/
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
if ( fsp - > is_directory ) {
if ( vfs_stat ( fsp - > conn , fsp - > fsp_name , & sbuf ) ! = 0 ) {
return False ;
}
} else {
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
int ret ;
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
if ( fsp - > fd = = - 1 )
ret = vfs_stat ( fsp - > conn , fsp - > fsp_name , & sbuf ) ;
else
2001-01-12 01:37:59 +03:00
ret = vfs_fstat ( fsp , fsp - > fd , & sbuf ) ;
2000-08-29 04:29:15 +04:00
2000-12-19 23:00:28 +03:00
if ( ret ! = 0 )
return False ;
}
}
2001-01-12 01:37:59 +03:00
create_file_sids ( & sbuf , & file_owner_sid , & file_grp_sid ) ;
2000-12-19 23:00:28 +03:00
2001-01-23 04:52:30 +03:00
acl_perms = unpack_canon_ace ( fsp , & sbuf , & file_owner_sid , & file_grp_sid ,
2001-01-12 01:37:59 +03:00
& file_ace_list , & dir_ace_list , security_info_sent , psd ) ;
2001-01-16 01:46:22 +03:00
posix_perms = unpack_posix_permissions ( fsp , & sbuf , & perms , security_info_sent , psd , acl_perms ) ;
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
if ( ! posix_perms & & ! acl_perms ) {
/*
* Neither method of setting permissions can work . Fail here .
*/
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
DEBUG ( 3 , ( " set_nt_acl: cannot set normal POSIX permissions or POSIX ACL permissions \n " ) ) ;
free_canon_ace_list ( file_ace_list ) ;
free_canon_ace_list ( dir_ace_list ) ;
return False ;
}
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
/*
* Only change security if we got a DACL .
*/
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
if ( ( security_info_sent & DACL_SECURITY_INFORMATION ) & & ( psd - > dacl ! = NULL ) ) {
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
BOOL acl_set_support = False ;
2001-01-23 04:52:30 +03:00
BOOL ret = False ;
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
/*
* Try using the POSIX ACL set first . All back to chmod if
* we have no ACL support on this filesystem .
*/
2000-08-29 04:29:15 +04:00
2001-01-23 04:52:30 +03:00
if ( acl_perms & & file_ace_list ) {
ret = set_canon_ace_list ( fsp , file_ace_list , False , & acl_set_support ) ;
if ( acl_set_support & & ret = = False ) {
DEBUG ( 3 , ( " set_nt_acl: failed to set file acl on file %s (%s). \n " , fsp - > fsp_name , strerror ( errno ) ) ) ;
free_canon_ace_list ( file_ace_list ) ;
free_canon_ace_list ( dir_ace_list ) ;
return False ;
}
}
2000-08-29 04:29:15 +04:00
2001-01-23 04:52:30 +03:00
if ( acl_perms & & acl_set_support & & fsp - > is_directory & & dir_ace_list ) {
if ( ! set_canon_ace_list ( fsp , dir_ace_list , True , & acl_set_support ) ) {
DEBUG ( 3 , ( " set_nt_acl: failed to set default acl on directory %s (%s). \n " , fsp - > fsp_name , strerror ( errno ) ) ) ;
free_canon_ace_list ( file_ace_list ) ;
free_canon_ace_list ( dir_ace_list ) ;
return False ;
}
}
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
/*
* If we cannot set using POSIX ACLs we fall back to checking if we need to chmod .
*/
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
if ( ! acl_set_support & & ( sbuf . st_mode ! = perms ) ) {
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
free_canon_ace_list ( file_ace_list ) ;
free_canon_ace_list ( dir_ace_list ) ;
file_ace_list = NULL ;
dir_ace_list = NULL ;
2000-08-29 04:29:15 +04:00
2001-01-23 04:52:30 +03:00
DEBUG ( 3 , ( " set_nt_acl: chmod %s. perms = 0%o. \n " ,
2001-01-12 01:37:59 +03:00
fsp - > fsp_name , ( unsigned int ) perms ) ) ;
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
if ( conn - > vfs_ops . chmod ( conn , dos_to_unix ( fsp - > fsp_name , False ) , perms ) = = - 1 ) {
DEBUG ( 3 , ( " set_nt_acl: chmod %s, 0%o failed. Error = %s. \n " ,
fsp - > fsp_name , ( unsigned int ) perms , strerror ( errno ) ) ) ;
return False ;
}
}
}
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
free_canon_ace_list ( file_ace_list ) ;
free_canon_ace_list ( dir_ace_list ) ;
2000-08-29 04:29:15 +04:00
2001-01-12 01:37:59 +03:00
return True ;
2000-08-29 04:29:15 +04:00
}
2001-01-23 04:52:30 +03:00
/****************************************************************************
Do a chmod by setting the ACL USER_OBJ , GROUP_OBJ and OTHER bits in an ACL
and set the mask to rwx . Needed to preserve complex ACLs set by NT .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int chmod_acl_internals ( SMB_ACL_T posix_acl , mode_t mode )
{
int entry_id = SMB_ACL_FIRST_ENTRY ;
SMB_ACL_ENTRY_T entry ;
int num_entries = 0 ;
# if 1
return - 1 ;
# else
while ( sys_acl_get_entry ( posix_acl , entry_id , & entry ) = = 1 ) {
SMB_ACL_TAG_T tagtype ;
SMB_ACL_PERMSET_T permset ;
if ( sys_acl_get_tag_type ( entry , & tagtype ) = = - 1 )
return - 1 ;
if ( sys_acl_get_permset ( entry , & permset ) = = - 1 )
return - 1 ;
num_entries + + ;
switch ( tagtype ) {
case SMB_ACL_USER_OBJ :
break ;
case SMB_ACL_USER :
break ;
case SMB_ACL_GROUP_OBJ :
break ;
case SMB_ACL_GROUP :
break ;
case SMB_ACL_MASK :
break ;
case SMB_ACL_OTHER :
break ;
}
}
# endif
}
/****************************************************************************
Do a chmod by setting the ACL USER_OBJ , GROUP_OBJ and OTHER bits in an ACL
and set the mask to rwx . Needed to preserve complex ACLs set by NT .
Note that name is in UNIX character set .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int chmod_acl ( char * name , mode_t mode )
{
SMB_ACL_T posix_acl = NULL ;
if ( ( posix_acl = sys_acl_get_file ( name , SMB_ACL_TYPE_ACCESS ) ) = = NULL )
return - 1 ;
return chmod_acl_internals ( posix_acl , mode ) ;
}
/****************************************************************************
Do an fchmod by setting the ACL USER_OBJ , GROUP_OBJ and OTHER bits in an ACL
and set the mask to rwx . Needed to preserve complex ACLs set by NT .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int fchmod_acl ( int fd , mode_t mode )
{
SMB_ACL_T posix_acl = NULL ;
if ( ( posix_acl = sys_acl_get_fd ( fd ) ) = = NULL )
return - 1 ;
return chmod_acl_internals ( posix_acl , mode ) ;
}
2000-08-29 04:29:15 +04:00
# undef OLD_NTDOMAIN