2008-09-17 02:55:06 +04:00
/*
* Store Windows ACLs in xattrs .
*
* Copyright ( C ) Volker Lendecke , 2008
* Copyright ( C ) Jeremy Allison , 2008
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
2008-09-17 23:34:09 +04:00
/* NOTE: This is an experimental module, not yet finished. JRA. */
2008-09-17 02:55:06 +04:00
# include "includes.h"
# include "librpc/gen_ndr/xattr.h"
# include "librpc/gen_ndr/ndr_xattr.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2009-07-11 02:50:40 +04:00
static NTSTATUS create_acl_blob ( const struct security_descriptor * psd ,
DATA_BLOB * pblob ,
uint8_t hash [ 16 ] ) ;
# define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
GROUP_SECURITY_INFORMATION | \
DACL_SECURITY_INFORMATION | \
SACL_SECURITY_INFORMATION )
/*******************************************************************
Hash a security descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS hash_sd ( struct security_descriptor * psd ,
uint8_t hash [ 16 ] )
{
DATA_BLOB blob ;
struct MD5Context tctx ;
NTSTATUS status ;
memset ( hash , ' \0 ' , 16 ) ;
status = create_acl_blob ( psd , & blob , hash ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
MD5Init ( & tctx ) ;
MD5Update ( & tctx , blob . data , blob . length ) ;
MD5Final ( hash , & tctx ) ;
return NT_STATUS_OK ;
}
2008-11-11 04:57:22 +03:00
/*******************************************************************
Parse out a struct security_descriptor from a DATA_BLOB .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-17 02:55:06 +04:00
static NTSTATUS parse_acl_blob ( const DATA_BLOB * pblob ,
uint32 security_info ,
2009-07-11 02:50:40 +04:00
struct security_descriptor * * ppdesc ,
uint8_t hash [ 16 ] )
2008-09-17 02:55:06 +04:00
{
TALLOC_CTX * ctx = talloc_tos ( ) ;
struct xattr_NTACL xacl ;
enum ndr_err_code ndr_err ;
size_t sd_size ;
2008-09-23 11:49:56 +04:00
ndr_err = ndr_pull_struct_blob ( pblob , ctx , NULL , & xacl ,
2008-09-17 02:55:06 +04:00
( ndr_pull_flags_fn_t ) ndr_pull_xattr_NTACL ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 5 , ( " parse_acl_blob: ndr_pull_xattr_NTACL failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ) ;
return ndr_map_error2ntstatus ( ndr_err ) ; ;
}
if ( xacl . version ! = 2 ) {
return NT_STATUS_REVISION_MISMATCH ;
}
2008-11-14 04:18:41 +03:00
* ppdesc = make_sec_desc ( ctx , SEC_DESC_REVISION , xacl . info . sd_hs - > sd - > type | SEC_DESC_SELF_RELATIVE ,
2008-09-17 02:55:06 +04:00
( security_info & OWNER_SECURITY_INFORMATION )
2008-11-14 04:18:41 +03:00
? xacl . info . sd_hs - > sd - > owner_sid : NULL ,
2008-09-17 02:55:06 +04:00
( security_info & GROUP_SECURITY_INFORMATION )
2008-11-14 04:18:41 +03:00
? xacl . info . sd_hs - > sd - > group_sid : NULL ,
2008-09-17 02:55:06 +04:00
( security_info & SACL_SECURITY_INFORMATION )
2008-11-14 04:18:41 +03:00
? xacl . info . sd_hs - > sd - > sacl : NULL ,
2008-09-17 02:55:06 +04:00
( security_info & DACL_SECURITY_INFORMATION )
2008-11-14 04:18:41 +03:00
? xacl . info . sd_hs - > sd - > dacl : NULL ,
2008-09-17 02:55:06 +04:00
& sd_size ) ;
2009-07-11 02:50:40 +04:00
memcpy ( hash , xacl . info . sd_hs - > hash , 16 ) ;
2008-09-17 02:55:06 +04:00
TALLOC_FREE ( xacl . info . sd ) ;
return ( * ppdesc ! = NULL ) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY ;
}
2008-11-11 04:57:22 +03:00
/*******************************************************************
Pull a security descriptor into a DATA_BLOB from a xattr .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-17 23:34:09 +04:00
static NTSTATUS get_acl_blob ( TALLOC_CTX * ctx ,
vfs_handle_struct * handle ,
2008-09-17 02:55:06 +04:00
files_struct * fsp ,
const char * name ,
DATA_BLOB * pblob )
{
size_t size = 1024 ;
uint8_t * val = NULL ;
uint8_t * tmp ;
ssize_t sizeret ;
2008-10-08 07:16:04 +04:00
int saved_errno = 0 ;
2008-09-17 02:55:06 +04:00
ZERO_STRUCTP ( pblob ) ;
again :
tmp = TALLOC_REALLOC_ARRAY ( ctx , val , uint8_t , size ) ;
if ( tmp = = NULL ) {
TALLOC_FREE ( val ) ;
return NT_STATUS_NO_MEMORY ;
}
val = tmp ;
become_root ( ) ;
2008-09-18 00:44:29 +04:00
if ( fsp & & fsp - > fh - > fd ! = - 1 ) {
2008-09-17 02:55:06 +04:00
sizeret = SMB_VFS_FGETXATTR ( fsp , XATTR_NTACL_NAME , val , size ) ;
} else {
sizeret = SMB_VFS_GETXATTR ( handle - > conn , name ,
XATTR_NTACL_NAME , val , size ) ;
}
if ( sizeret = = - 1 ) {
saved_errno = errno ;
}
unbecome_root ( ) ;
/* Max ACL size is 65536 bytes. */
if ( sizeret = = - 1 ) {
errno = saved_errno ;
if ( ( errno = = ERANGE ) & & ( size ! = 65536 ) ) {
/* Too small, try again. */
size = 65536 ;
goto again ;
}
/* Real error - exit here. */
TALLOC_FREE ( val ) ;
return map_nt_error_from_unix ( errno ) ;
}
pblob - > data = val ;
pblob - > length = sizeret ;
return NT_STATUS_OK ;
}
2008-11-11 04:57:22 +03:00
/*******************************************************************
Create a DATA_BLOB from a security descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-11 02:50:40 +04:00
static NTSTATUS create_acl_blob ( const struct security_descriptor * psd ,
DATA_BLOB * pblob ,
uint8_t hash [ 16 ] )
2008-10-29 23:27:14 +03:00
{
struct xattr_NTACL xacl ;
2008-11-14 04:18:41 +03:00
struct security_descriptor_hash sd_hs ;
2008-10-29 23:27:14 +03:00
enum ndr_err_code ndr_err ;
TALLOC_CTX * ctx = talloc_tos ( ) ;
ZERO_STRUCT ( xacl ) ;
2008-11-14 04:18:41 +03:00
ZERO_STRUCT ( sd_hs ) ;
2008-10-29 23:27:14 +03:00
xacl . version = 2 ;
2008-11-14 04:18:41 +03:00
xacl . info . sd_hs = & sd_hs ;
xacl . info . sd_hs - > sd = CONST_DISCARD ( struct security_descriptor * , psd ) ;
2009-07-11 02:50:40 +04:00
memcpy ( & xacl . info . sd_hs - > hash [ 0 ] , hash , 16 ) ;
2008-10-29 23:27:14 +03:00
ndr_err = ndr_push_struct_blob (
pblob , ctx , NULL , & xacl ,
( ndr_push_flags_fn_t ) ndr_push_xattr_NTACL ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 5 , ( " create_acl_blob: ndr_push_xattr_NTACL failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ) ;
return ndr_map_error2ntstatus ( ndr_err ) ; ;
}
return NT_STATUS_OK ;
}
2008-11-11 04:57:22 +03:00
/*******************************************************************
Store a DATA_BLOB into an xattr given an fsp pointer .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS store_acl_blob_fsp ( vfs_handle_struct * handle ,
files_struct * fsp ,
2008-10-29 23:27:14 +03:00
DATA_BLOB * pblob )
{
int ret ;
int saved_errno = 0 ;
2008-10-30 23:51:28 +03:00
DEBUG ( 10 , ( " store_acl_blob_fsp: storing blob length %u on file %s \n " ,
2009-07-11 05:11:32 +04:00
( unsigned int ) pblob - > length , fsp_str_dbg ( fsp ) ) ) ;
2008-10-29 23:27:14 +03:00
become_root ( ) ;
if ( fsp - > fh - > fd ! = - 1 ) {
ret = SMB_VFS_FSETXATTR ( fsp , XATTR_NTACL_NAME ,
pblob - > data , pblob - > length , 0 ) ;
} else {
2009-07-11 05:11:32 +04:00
ret = SMB_VFS_SETXATTR ( fsp - > conn , fsp - > fsp_name - > base_name ,
2008-10-29 23:27:14 +03:00
XATTR_NTACL_NAME ,
pblob - > data , pblob - > length , 0 ) ;
}
if ( ret ) {
saved_errno = errno ;
}
unbecome_root ( ) ;
if ( ret ) {
errno = saved_errno ;
2008-10-30 23:51:28 +03:00
DEBUG ( 5 , ( " store_acl_blob_fsp: setting attr failed for file %s "
2008-10-29 23:27:14 +03:00
" with error %s \n " ,
2009-07-11 05:11:32 +04:00
fsp_str_dbg ( fsp ) ,
2008-10-29 23:27:14 +03:00
strerror ( errno ) ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
return NT_STATUS_OK ;
}
2008-11-11 04:57:22 +03:00
/*******************************************************************
Store a DATA_BLOB into an xattr given a pathname .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS store_acl_blob_pathname ( vfs_handle_struct * handle ,
2008-10-30 23:51:28 +03:00
const char * fname ,
DATA_BLOB * pblob )
{
2008-11-11 04:57:22 +03:00
connection_struct * conn = handle - > conn ;
2008-10-30 23:51:28 +03:00
int ret ;
int saved_errno = 0 ;
DEBUG ( 10 , ( " store_acl_blob_pathname: storing blob "
" length %u on file %s \n " ,
( unsigned int ) pblob - > length , fname ) ) ;
become_root ( ) ;
ret = SMB_VFS_SETXATTR ( conn , fname ,
XATTR_NTACL_NAME ,
pblob - > data , pblob - > length , 0 ) ;
if ( ret ) {
saved_errno = errno ;
}
unbecome_root ( ) ;
if ( ret ) {
errno = saved_errno ;
DEBUG ( 5 , ( " store_acl_blob_pathname: setting attr failed "
" for file %s with error %s \n " ,
fname ,
strerror ( errno ) ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
return NT_STATUS_OK ;
}
2008-11-11 04:57:22 +03:00
/*******************************************************************
Store a DATA_BLOB into an xattr given a pathname .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-29 23:27:14 +03:00
2008-09-17 02:55:06 +04:00
static NTSTATUS get_nt_acl_xattr_internal ( vfs_handle_struct * handle ,
files_struct * fsp ,
const char * name ,
uint32 security_info ,
2008-11-01 04:04:53 +03:00
struct security_descriptor * * ppdesc )
2008-09-17 02:55:06 +04:00
{
DATA_BLOB blob ;
NTSTATUS status ;
2009-07-11 02:50:40 +04:00
uint8_t hash [ 16 ] ;
uint8_t hash_tmp [ 16 ] ;
struct security_descriptor * pdesc_next = NULL ;
2008-09-17 02:55:06 +04:00
if ( fsp & & name = = NULL ) {
2009-07-11 05:11:32 +04:00
name = fsp - > fsp_name - > base_name ;
2008-09-17 02:55:06 +04:00
}
DEBUG ( 10 , ( " get_nt_acl_xattr_internal: name=%s \n " , name ) ) ;
2009-07-11 02:50:40 +04:00
status = get_acl_blob ( talloc_tos ( ) , handle , fsp , name , & blob ) ;
2008-09-17 02:55:06 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " get_acl_blob returned %s \n " , nt_errstr ( status ) ) ) ;
return status ;
}
2009-07-11 02:50:40 +04:00
status = parse_acl_blob ( & blob , security_info , ppdesc , & hash [ 0 ] ) ;
2008-09-17 02:55:06 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " parse_acl_blob returned %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
2009-07-11 02:50:40 +04:00
/* If there was no stored hash, don't check. */
memset ( & hash_tmp [ 0 ] , ' \0 ' , 16 ) ;
if ( memcmp ( & hash [ 0 ] , & hash_tmp [ 0 ] , 16 ) = = 0 ) {
/* No hash, goto return blob sd. */
goto out ;
}
/* Get the full underlying sd, then hash. */
if ( fsp ) {
status = SMB_VFS_NEXT_FGET_NT_ACL ( handle ,
fsp ,
HASH_SECURITY_INFO ,
& pdesc_next ) ;
} else {
status = SMB_VFS_NEXT_GET_NT_ACL ( handle ,
name ,
HASH_SECURITY_INFO ,
& pdesc_next ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
status = hash_sd ( pdesc_next , hash_tmp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
if ( memcmp ( & hash [ 0 ] , & hash_tmp [ 0 ] , 16 ) = = 0 ) {
TALLOC_FREE ( pdesc_next ) ;
/* Hash matches, return blob sd. */
goto out ;
}
/* Hash doesn't match, return underlying sd. */
if ( ! ( security_info & OWNER_SECURITY_INFORMATION ) ) {
pdesc_next - > owner_sid = NULL ;
}
if ( ! ( security_info & GROUP_SECURITY_INFORMATION ) ) {
pdesc_next - > group_sid = NULL ;
}
if ( ! ( security_info & DACL_SECURITY_INFORMATION ) ) {
pdesc_next - > dacl = NULL ;
}
if ( ! ( security_info & SACL_SECURITY_INFORMATION ) ) {
pdesc_next - > sacl = NULL ;
}
TALLOC_FREE ( * ppdesc ) ;
* ppdesc = pdesc_next ;
out :
2008-09-17 02:55:06 +04:00
TALLOC_FREE ( blob . data ) ;
return status ;
}
2008-10-08 01:43:42 +04:00
/*********************************************************************
2008-11-01 04:04:53 +03:00
Create a default security descriptor for a file in case no inheritance
exists . All permissions to the owner and SYSTEM .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct security_descriptor * default_file_sd ( TALLOC_CTX * mem_ctx ,
SMB_STRUCT_STAT * psbuf )
{
struct dom_sid owner_sid , group_sid ;
size_t sd_size ;
struct security_ace * pace = NULL ;
struct security_acl * pacl = NULL ;
2009-05-14 17:34:42 +04:00
uid_to_sid ( & owner_sid , psbuf - > st_ex_uid ) ;
gid_to_sid ( & group_sid , psbuf - > st_ex_gid ) ;
2008-11-01 04:04:53 +03:00
pace = TALLOC_ARRAY ( mem_ctx , struct security_ace , 2 ) ;
if ( ! pace ) {
return NULL ;
}
init_sec_ace ( & pace [ 0 ] , & owner_sid , SEC_ACE_TYPE_ACCESS_ALLOWED ,
SEC_RIGHTS_FILE_ALL , 0 ) ;
init_sec_ace ( & pace [ 1 ] , & global_sid_System , SEC_ACE_TYPE_ACCESS_ALLOWED ,
SEC_RIGHTS_FILE_ALL , 0 ) ;
pacl = make_sec_acl ( mem_ctx ,
NT4_ACL_REVISION ,
2 ,
pace ) ;
if ( ! pacl ) {
return NULL ;
}
return make_sec_desc ( mem_ctx ,
SECURITY_DESCRIPTOR_REVISION_1 ,
2008-11-06 12:58:56 +03:00
SEC_DESC_SELF_RELATIVE | SEC_DESC_DACL_PRESENT ,
2008-11-01 04:04:53 +03:00
& owner_sid ,
& group_sid ,
NULL ,
pacl ,
& sd_size ) ;
}
/*********************************************************************
2008-10-08 01:43:42 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-29 23:27:14 +03:00
static NTSTATUS inherit_new_acl ( vfs_handle_struct * handle ,
2009-07-11 05:11:32 +04:00
struct smb_filename * smb_fname ,
2008-10-30 23:51:28 +03:00
files_struct * fsp ,
bool container )
2008-10-29 23:27:14 +03:00
{
TALLOC_CTX * ctx = talloc_tos ( ) ;
NTSTATUS status ;
2008-11-01 04:04:53 +03:00
struct security_descriptor * parent_desc = NULL ;
struct security_descriptor * psd = NULL ;
2009-07-11 02:50:40 +04:00
struct security_descriptor * pdesc_next = NULL ;
2008-10-29 23:27:14 +03:00
DATA_BLOB blob ;
size_t size ;
char * parent_name ;
2009-07-11 02:50:40 +04:00
uint8_t hash [ 16 ] ;
2008-10-29 23:27:14 +03:00
2009-07-11 05:11:32 +04:00
if ( ! parent_dirname ( ctx , smb_fname - > base_name , & parent_name , NULL ) ) {
2008-10-29 23:27:14 +03:00
return NT_STATUS_NO_MEMORY ;
}
DEBUG ( 10 , ( " inherit_new_acl: check directory %s \n " ,
parent_name ) ) ;
status = get_nt_acl_xattr_internal ( handle ,
NULL ,
parent_name ,
2008-11-09 09:57:57 +03:00
( OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION ) ,
2008-10-29 23:27:14 +03:00
& parent_desc ) ;
2008-11-06 11:50:56 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
/* Create an inherited descriptor from the parent. */
2008-11-09 09:57:57 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " inherit_new_acl: parent acl is: \n " ) ) ;
NDR_PRINT_DEBUG ( security_descriptor , parent_desc ) ;
}
2008-11-06 11:50:56 +03:00
status = se_create_child_secdesc ( ctx ,
2008-10-29 23:27:14 +03:00
& psd ,
& size ,
parent_desc ,
& handle - > conn - > server_info - > ptok - > user_sids [ PRIMARY_USER_SID_INDEX ] ,
& handle - > conn - > server_info - > ptok - > user_sids [ PRIMARY_GROUP_SID_INDEX ] ,
2008-10-30 23:51:28 +03:00
container ) ;
2008-11-06 11:50:56 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2008-11-09 09:57:57 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " inherit_new_acl: child acl is: \n " ) ) ;
NDR_PRINT_DEBUG ( security_descriptor , psd ) ;
}
2008-11-06 11:50:56 +03:00
} else {
DEBUG ( 10 , ( " inherit_new_acl: directory %s failed "
" to get acl %s \n " ,
parent_name ,
nt_errstr ( status ) ) ) ;
2008-10-29 23:27:14 +03:00
}
2008-11-06 11:50:56 +03:00
if ( ! psd | | psd - > dacl = = NULL ) {
2008-11-01 04:04:53 +03:00
int ret ;
TALLOC_FREE ( psd ) ;
if ( fsp & & ! fsp - > is_directory & & fsp - > fh - > fd ! = - 1 ) {
2009-07-11 05:11:32 +04:00
ret = SMB_VFS_FSTAT ( fsp , & smb_fname - > st ) ;
2008-11-01 04:04:53 +03:00
} else {
2009-03-05 01:48:33 +03:00
if ( fsp & & fsp - > posix_open ) {
2009-07-11 05:11:32 +04:00
ret = SMB_VFS_LSTAT ( handle - > conn , smb_fname ) ;
2009-02-26 01:12:51 +03:00
} else {
2009-07-11 05:11:32 +04:00
ret = SMB_VFS_STAT ( handle - > conn , smb_fname ) ;
2009-02-26 01:12:51 +03:00
}
2008-11-01 04:04:53 +03:00
}
if ( ret = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
2009-07-11 05:11:32 +04:00
psd = default_file_sd ( ctx , & smb_fname - > st ) ;
2008-11-01 04:04:53 +03:00
if ( ! psd ) {
return NT_STATUS_NO_MEMORY ;
}
2008-11-09 09:57:57 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " inherit_new_acl: default acl is: \n " ) ) ;
NDR_PRINT_DEBUG ( security_descriptor , psd ) ;
}
2008-11-01 04:04:53 +03:00
}
2009-07-11 02:50:40 +04:00
/* Object exists. Read the current SD to get the hash. */
if ( fsp ) {
status = SMB_VFS_NEXT_FGET_NT_ACL ( handle ,
fsp ,
HASH_SECURITY_INFO ,
& pdesc_next ) ;
} else {
status = SMB_VFS_NEXT_GET_NT_ACL ( handle ,
2009-07-11 05:11:32 +04:00
smb_fname - > base_name ,
2009-07-11 02:50:40 +04:00
HASH_SECURITY_INFO ,
& pdesc_next ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
status = hash_sd ( pdesc_next , hash ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
status = create_acl_blob ( psd , & blob , hash ) ;
2008-10-29 23:27:14 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2008-10-30 23:51:28 +03:00
if ( fsp ) {
2008-11-11 04:57:22 +03:00
return store_acl_blob_fsp ( handle , fsp , & blob ) ;
2008-10-30 23:51:28 +03:00
} else {
2009-07-11 05:11:32 +04:00
return store_acl_blob_pathname ( handle , smb_fname - > base_name ,
& blob ) ;
2008-10-30 23:51:28 +03:00
}
2008-10-29 23:27:14 +03:00
}
/*********************************************************************
Check ACL on open . For new files inherit from parent directory .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int open_acl_xattr ( vfs_handle_struct * handle ,
2009-06-16 23:01:13 +04:00
struct smb_filename * smb_fname ,
2008-10-29 23:27:14 +03:00
files_struct * fsp ,
int flags ,
mode_t mode )
2008-10-08 01:43:42 +04:00
{
uint32_t access_granted = 0 ;
2008-11-01 04:04:53 +03:00
struct security_descriptor * pdesc = NULL ;
2008-10-29 23:27:14 +03:00
bool file_existed = true ;
2009-06-16 23:01:13 +04:00
char * fname = NULL ;
NTSTATUS status ;
2009-07-11 02:50:40 +04:00
if ( fsp - > base_fsp ) {
/* Stream open. Base filename open already did the ACL check. */
DEBUG ( 10 , ( " open_acl_xattr: stream open on %s \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
return SMB_VFS_NEXT_OPEN ( handle , smb_fname , fsp , flags , mode ) ;
}
2009-06-16 23:01:13 +04:00
status = get_full_smb_filename ( talloc_tos ( ) , smb_fname ,
& fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
status = get_nt_acl_xattr_internal ( handle ,
2008-10-08 01:43:42 +04:00
NULL ,
fname ,
( OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION ) ,
& pdesc ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
/* See if we can access it. */
2008-11-04 12:34:08 +03:00
status = smb1_file_se_access_check ( pdesc ,
2008-10-08 01:43:42 +04:00
handle - > conn - > server_info - > ptok ,
fsp - > access_mask ,
2008-10-31 20:51:45 +03:00
& access_granted ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-11-04 09:42:53 +03:00
DEBUG ( 10 , ( " open_acl_xattr: file %s open "
" refused with error %s \n " ,
2009-06-16 23:01:13 +04:00
smb_fname_str_dbg ( smb_fname ) ,
2008-11-04 09:42:53 +03:00
nt_errstr ( status ) ) ) ;
2008-10-08 01:43:42 +04:00
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2008-10-29 23:27:14 +03:00
} else if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
file_existed = false ;
}
DEBUG ( 10 , ( " open_acl_xattr: get_nt_acl_attr_internal for "
" file %s returned %s \n " ,
2009-06-16 23:01:13 +04:00
smb_fname_str_dbg ( smb_fname ) ,
2008-10-29 23:27:14 +03:00
nt_errstr ( status ) ) ) ;
2009-06-16 23:01:13 +04:00
fsp - > fh - > fd = SMB_VFS_NEXT_OPEN ( handle , smb_fname , fsp , flags , mode ) ;
2008-10-29 23:27:14 +03:00
if ( ! file_existed & & fsp - > fh - > fd ! = - 1 ) {
/* File was created. Inherit from parent directory. */
2009-07-11 05:11:32 +04:00
status = fsp_set_smb_fname ( fsp , smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
inherit_new_acl ( handle , smb_fname , fsp , false ) ;
2008-10-29 23:27:14 +03:00
}
2008-10-08 01:43:42 +04:00
2008-10-29 23:27:14 +03:00
return fsp - > fh - > fd ;
2008-10-08 01:43:42 +04:00
}
2008-10-30 23:51:28 +03:00
static int mkdir_acl_xattr ( vfs_handle_struct * handle , const char * path , mode_t mode )
{
2009-07-11 05:11:32 +04:00
struct smb_filename * smb_fname = NULL ;
2008-10-30 23:51:28 +03:00
int ret = SMB_VFS_NEXT_MKDIR ( handle , path , mode ) ;
2009-07-11 05:11:32 +04:00
NTSTATUS status ;
2008-10-30 23:51:28 +03:00
if ( ret = = - 1 ) {
return ret ;
}
2009-07-11 05:11:32 +04:00
status = create_synthetic_smb_fname ( talloc_tos ( ) , path , NULL , NULL ,
& smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2008-10-30 23:51:28 +03:00
/* New directory - inherit from parent. */
2009-07-11 05:11:32 +04:00
inherit_new_acl ( handle , smb_fname , NULL , true ) ;
TALLOC_FREE ( smb_fname ) ;
2008-10-30 23:51:28 +03:00
return ret ;
}
2008-11-11 04:57:22 +03:00
/*********************************************************************
Fetch a security descriptor given an fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-17 02:55:06 +04:00
static NTSTATUS fget_nt_acl_xattr ( vfs_handle_struct * handle , files_struct * fsp ,
2008-11-01 04:04:53 +03:00
uint32 security_info , struct security_descriptor * * ppdesc )
2008-09-17 02:55:06 +04:00
{
2009-07-11 02:50:40 +04:00
return get_nt_acl_xattr_internal ( handle , fsp ,
2008-09-17 02:55:06 +04:00
NULL , security_info , ppdesc ) ;
}
2008-11-11 04:57:22 +03:00
/*********************************************************************
Fetch a security descriptor given a pathname .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-17 02:55:06 +04:00
static NTSTATUS get_nt_acl_xattr ( vfs_handle_struct * handle ,
2008-11-01 04:04:53 +03:00
const char * name , uint32 security_info , struct security_descriptor * * ppdesc )
2008-09-17 02:55:06 +04:00
{
2009-07-11 02:50:40 +04:00
return get_nt_acl_xattr_internal ( handle , NULL ,
2008-09-17 02:55:06 +04:00
name , security_info , ppdesc ) ;
}
2008-11-11 04:57:22 +03:00
/*********************************************************************
Store a security descriptor given an fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-17 02:55:06 +04:00
static NTSTATUS fset_nt_acl_xattr ( vfs_handle_struct * handle , files_struct * fsp ,
2008-11-01 04:04:53 +03:00
uint32 security_info_sent , const struct security_descriptor * psd )
2008-09-17 02:55:06 +04:00
{
NTSTATUS status ;
DATA_BLOB blob ;
2009-07-11 02:50:40 +04:00
struct security_descriptor * pdesc_next = NULL ;
uint8_t hash [ 16 ] ;
2008-09-17 02:55:06 +04:00
2008-10-31 02:13:03 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " fset_nt_acl_xattr: incoming sd for file %s \n " ,
2009-07-11 05:11:32 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2008-10-31 02:13:03 +03:00
NDR_PRINT_DEBUG ( security_descriptor ,
2008-11-01 04:04:53 +03:00
CONST_DISCARD ( struct security_descriptor * , psd ) ) ;
2008-10-31 02:13:03 +03:00
}
/* Ensure owner and group are set. */
if ( ! psd - > owner_sid | | ! psd - > group_sid ) {
int ret ;
DOM_SID owner_sid , group_sid ;
2008-11-01 04:04:53 +03:00
struct security_descriptor * nc_psd = dup_sec_desc ( talloc_tos ( ) , psd ) ;
2008-10-31 02:13:03 +03:00
if ( ! nc_psd ) {
return NT_STATUS_OK ;
}
if ( fsp - > is_directory | | fsp - > fh - > fd = = - 1 ) {
2009-02-26 01:50:19 +03:00
if ( fsp - > posix_open ) {
2009-07-11 05:11:32 +04:00
ret = SMB_VFS_LSTAT ( fsp - > conn , fsp - > fsp_name ) ;
2009-02-26 01:12:51 +03:00
} else {
2009-07-11 05:11:32 +04:00
ret = SMB_VFS_STAT ( fsp - > conn , fsp - > fsp_name ) ;
2009-02-26 01:12:51 +03:00
}
2008-10-31 02:13:03 +03:00
} else {
2009-07-11 05:11:32 +04:00
ret = SMB_VFS_FSTAT ( fsp , & fsp - > fsp_name - > st ) ;
2008-10-31 02:13:03 +03:00
}
if ( ret = = - 1 ) {
/* Lower level acl set succeeded,
* so still return OK . */
return NT_STATUS_OK ;
}
2009-07-11 05:11:32 +04:00
create_file_sids ( & fsp - > fsp_name - > st , & owner_sid , & group_sid ) ;
2008-10-31 02:13:03 +03:00
/* This is safe as nc_psd is discarded at fn exit. */
nc_psd - > owner_sid = & owner_sid ;
nc_psd - > group_sid = & group_sid ;
security_info_sent | = ( OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION ) ;
psd = nc_psd ;
}
2009-07-11 02:50:40 +04:00
status = SMB_VFS_NEXT_FSET_NT_ACL ( handle , fsp , security_info_sent , psd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
/* Get the full underlying sd, then hash. */
status = SMB_VFS_NEXT_FGET_NT_ACL ( handle ,
fsp ,
HASH_SECURITY_INFO ,
& pdesc_next ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
status = hash_sd ( pdesc_next , hash ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2008-12-19 02:38:28 +03:00
#if 0
2008-10-09 02:18:25 +04:00
if ( ( security_info_sent & DACL_SECURITY_INFORMATION ) & &
psd - > dacl ! = NULL & &
( psd - > type & ( SE_DESC_DACL_AUTO_INHERITED |
SE_DESC_DACL_AUTO_INHERIT_REQ ) ) = =
( SE_DESC_DACL_AUTO_INHERITED |
SE_DESC_DACL_AUTO_INHERIT_REQ ) ) {
2008-11-01 04:04:53 +03:00
struct security_descriptor * new_psd = NULL ;
2008-10-09 02:18:25 +04:00
status = append_parent_acl ( fsp , psd , & new_psd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* Lower level acl set succeeded,
* so still return OK . */
return NT_STATUS_OK ;
}
psd = new_psd ;
}
2008-12-19 02:38:28 +03:00
# endif
2008-10-09 02:18:25 +04:00
2008-10-31 02:13:03 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " fset_nt_acl_xattr: storing xattr sd for file %s \n " ,
2009-07-11 05:11:32 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2008-10-31 02:13:03 +03:00
NDR_PRINT_DEBUG ( security_descriptor ,
2008-11-01 04:04:53 +03:00
CONST_DISCARD ( struct security_descriptor * , psd ) ) ;
2008-10-31 02:13:03 +03:00
}
2009-07-11 02:50:40 +04:00
create_acl_blob ( psd , & blob , hash ) ;
2008-11-11 04:57:22 +03:00
store_acl_blob_fsp ( handle , fsp , & blob ) ;
2008-09-17 02:55:06 +04:00
return NT_STATUS_OK ;
}
2008-11-19 23:24:53 +03:00
/*********************************************************************
Remove a Windows ACL - we ' re setting the underlying POSIX ACL .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int sys_acl_set_file_xattr ( vfs_handle_struct * handle ,
const char * name ,
SMB_ACL_TYPE_T type ,
SMB_ACL_T theacl )
{
int ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE ( handle ,
name ,
type ,
theacl ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
become_root ( ) ;
SMB_VFS_REMOVEXATTR ( handle - > conn , name , XATTR_NTACL_NAME ) ;
unbecome_root ( ) ;
return ret ;
}
/*********************************************************************
Remove a Windows ACL - we ' re setting the underlying POSIX ACL .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int sys_acl_set_fd_xattr ( vfs_handle_struct * handle ,
files_struct * fsp ,
SMB_ACL_T theacl )
{
int ret = SMB_VFS_NEXT_SYS_ACL_SET_FD ( handle ,
fsp ,
theacl ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
become_root ( ) ;
SMB_VFS_FREMOVEXATTR ( fsp , XATTR_NTACL_NAME ) ;
unbecome_root ( ) ;
return ret ;
}
2008-09-17 02:55:06 +04:00
/* VFS operations structure */
static vfs_op_tuple skel_op_tuples [ ] =
{
{ SMB_VFS_OP ( mkdir_acl_xattr ) , SMB_VFS_OP_MKDIR , SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( open_acl_xattr ) , SMB_VFS_OP_OPEN , SMB_VFS_LAYER_TRANSPARENT } ,
/* NT File ACL operations */
{ SMB_VFS_OP ( fget_nt_acl_xattr ) , SMB_VFS_OP_FGET_NT_ACL , SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( get_nt_acl_xattr ) , SMB_VFS_OP_GET_NT_ACL , SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( fset_nt_acl_xattr ) , SMB_VFS_OP_FSET_NT_ACL , SMB_VFS_LAYER_TRANSPARENT } ,
2008-11-19 23:24:53 +03:00
/* POSIX ACL operations. */
{ SMB_VFS_OP ( sys_acl_set_file_xattr ) , SMB_VFS_OP_SYS_ACL_SET_FILE , SMB_VFS_LAYER_TRANSPARENT } ,
2008-11-20 01:51:55 +03:00
{ SMB_VFS_OP ( sys_acl_set_fd_xattr ) , SMB_VFS_OP_SYS_ACL_SET_FD , SMB_VFS_LAYER_TRANSPARENT } ,
2008-11-19 23:24:53 +03:00
2008-11-11 04:57:22 +03:00
{ SMB_VFS_OP ( NULL ) , SMB_VFS_OP_NOOP , SMB_VFS_LAYER_NOOP }
2008-09-17 02:55:06 +04:00
} ;
NTSTATUS vfs_acl_xattr_init ( void )
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " acl_xattr " , skel_op_tuples ) ;
}