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
static NTSTATUS parse_acl_blob ( const DATA_BLOB * pblob ,
const struct timespec cts ,
uint32 security_info ,
struct security_descriptor * * ppdesc )
{
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-10-29 23:27:14 +03:00
#if 0
{
struct timespec ts ;
/* Arg. This doesn't work. Too many activities
* change the ctime . May have to roll back to
* version 1.
*/
/*
* Check that the ctime timestamp is ealier
* than the stored timestamp .
*/
ts = nt_time_to_unix_timespec ( & xacl . info . sd_ts - > last_changed ) ;
if ( timespec_compare ( & cts , & ts ) > 0 ) {
DEBUG ( 5 , ( " parse_acl_blob: stored ACL out of date "
" (%s > %s. \n " ,
timestring ( ctx , cts . tv_sec ) ,
timestring ( ctx , ts . tv_sec ) ) ) ;
return NT_STATUS_EA_CORRUPT_ERROR ;
}
2008-09-17 02:55:06 +04:00
}
2008-10-29 23:27:14 +03:00
# endif
2008-09-17 02:55:06 +04:00
2008-11-06 12:01:01 +03:00
* ppdesc = make_sec_desc ( ctx , SEC_DESC_REVISION , xacl . info . sd_ts - > sd - > type | SEC_DESC_SELF_RELATIVE ,
2008-09-17 02:55:06 +04:00
( security_info & OWNER_SECURITY_INFORMATION )
? xacl . info . sd_ts - > sd - > owner_sid : NULL ,
( security_info & GROUP_SECURITY_INFORMATION )
? xacl . info . sd_ts - > sd - > group_sid : NULL ,
( security_info & SACL_SECURITY_INFORMATION )
? xacl . info . sd_ts - > sd - > sacl : NULL ,
( security_info & DACL_SECURITY_INFORMATION )
? xacl . info . sd_ts - > sd - > dacl : NULL ,
& sd_size ) ;
TALLOC_FREE ( xacl . info . sd ) ;
return ( * ppdesc ! = NULL ) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY ;
}
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-01 04:04:53 +03:00
static NTSTATUS create_acl_blob ( const struct security_descriptor * psd , DATA_BLOB * pblob )
2008-10-29 23:27:14 +03:00
{
struct xattr_NTACL xacl ;
struct security_descriptor_timestamp sd_ts ;
enum ndr_err_code ndr_err ;
TALLOC_CTX * ctx = talloc_tos ( ) ;
struct timespec curr = timespec_current ( ) ;
ZERO_STRUCT ( xacl ) ;
ZERO_STRUCT ( sd_ts ) ;
/* Horrid hack as setting an xattr changes the ctime
* on Linux . This gives a race of 1 second during
* which we would not see a POSIX ACL set .
*/
curr . tv_sec + = 1 ;
xacl . version = 2 ;
xacl . info . sd_ts = & sd_ts ;
2008-11-01 04:04:53 +03:00
xacl . info . sd_ts - > sd = CONST_DISCARD ( struct security_descriptor * , psd ) ;
2008-10-29 23:27:14 +03:00
unix_timespec_to_nt_time ( & xacl . info . sd_ts - > last_changed , curr ) ;
DEBUG ( 10 , ( " create_acl_blob: timestamp stored as %s \n " ,
timestring ( ctx , curr . tv_sec ) ) ) ;
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-10-30 23:51:28 +03:00
static NTSTATUS store_acl_blob_fsp ( 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 " ,
2008-10-29 23:27:14 +03:00
( unsigned int ) pblob - > length , fsp - > fsp_name ) ) ;
become_root ( ) ;
if ( fsp - > fh - > fd ! = - 1 ) {
ret = SMB_VFS_FSETXATTR ( fsp , XATTR_NTACL_NAME ,
pblob - > data , pblob - > length , 0 ) ;
} else {
ret = SMB_VFS_SETXATTR ( fsp - > conn , fsp - > fsp_name ,
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 " ,
fsp - > fsp_name ,
strerror ( errno ) ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
return NT_STATUS_OK ;
}
2008-10-30 23:51:28 +03:00
static NTSTATUS store_acl_blob_pathname ( connection_struct * conn ,
const char * fname ,
DATA_BLOB * pblob )
{
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-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
{
TALLOC_CTX * ctx = talloc_tos ( ) ;
DATA_BLOB blob ;
SMB_STRUCT_STAT sbuf ;
NTSTATUS status ;
if ( fsp & & name = = NULL ) {
name = fsp - > fsp_name ;
}
DEBUG ( 10 , ( " get_nt_acl_xattr_internal: name=%s \n " , name ) ) ;
status = get_acl_blob ( ctx , handle , fsp , name , & blob ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " get_acl_blob returned %s \n " , nt_errstr ( status ) ) ) ;
return status ;
}
if ( fsp & & fsp - > fh - > fd ! = - 1 ) {
if ( SMB_VFS_FSTAT ( fsp , & sbuf ) = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
} else {
if ( SMB_VFS_STAT ( handle - > conn , name , & sbuf ) = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
}
status = parse_acl_blob ( & blob , get_ctimespec ( & sbuf ) ,
security_info , ppdesc ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " parse_acl_blob returned %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
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 ;
uid_to_sid ( & owner_sid , psbuf - > st_uid ) ;
gid_to_sid ( & group_sid , psbuf - > st_gid ) ;
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 ,
const char * 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 ;
2008-10-29 23:27:14 +03:00
DATA_BLOB blob ;
size_t size ;
char * parent_name ;
if ( ! parent_dirname_talloc ( ctx ,
fname ,
& parent_name ,
NULL ) ) {
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
SMB_STRUCT_STAT sbuf ;
int ret ;
TALLOC_FREE ( psd ) ;
if ( fsp & & ! fsp - > is_directory & & fsp - > fh - > fd ! = - 1 ) {
ret = SMB_VFS_FSTAT ( fsp , & sbuf ) ;
} else {
2008-11-06 11:50:56 +03:00
ret = SMB_VFS_STAT ( handle - > conn , fname , & sbuf ) ;
2008-11-01 04:04:53 +03:00
}
if ( ret = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
psd = default_file_sd ( ctx , & sbuf ) ;
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
}
2008-10-29 23:27:14 +03:00
status = create_acl_blob ( psd , & blob ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2008-10-30 23:51:28 +03:00
if ( fsp ) {
return store_acl_blob_fsp ( fsp , & blob ) ;
} else {
return store_acl_blob_pathname ( handle - > conn , fname , & blob ) ;
}
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 ,
const char * fname ,
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 ;
2008-10-08 01:43:42 +04:00
NTSTATUS status = get_nt_acl_xattr_internal ( handle ,
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 " ,
fname ,
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 " ,
fname ,
nt_errstr ( status ) ) ) ;
fsp - > fh - > fd = SMB_VFS_NEXT_OPEN ( handle , fname , fsp , flags , mode ) ;
if ( ! file_existed & & fsp - > fh - > fd ! = - 1 ) {
/* File was created. Inherit from parent directory. */
string_set ( & fsp - > fsp_name , fname ) ;
2008-10-30 23:51:28 +03:00
inherit_new_acl ( handle , 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 )
{
int ret = SMB_VFS_NEXT_MKDIR ( handle , path , mode ) ;
if ( ret = = - 1 ) {
return ret ;
}
/* New directory - inherit from parent. */
inherit_new_acl ( handle , path , NULL , true ) ;
return ret ;
}
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
{
NTSTATUS status = get_nt_acl_xattr_internal ( handle , fsp ,
NULL , security_info , ppdesc ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2008-10-31 02:13:03 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " fget_nt_acl_xattr: returning xattr sd for file %s \n " ,
fsp - > fsp_name ) ) ;
NDR_PRINT_DEBUG ( security_descriptor , * ppdesc ) ;
}
2008-09-17 02:55:06 +04:00
return NT_STATUS_OK ;
}
return SMB_VFS_NEXT_FGET_NT_ACL ( handle , fsp ,
security_info , ppdesc ) ;
}
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
{
NTSTATUS status = get_nt_acl_xattr_internal ( handle , NULL ,
name , security_info , ppdesc ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2008-10-31 02:13:03 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " get_nt_acl_xattr: returning xattr sd for file %s \n " ,
name ) ) ;
NDR_PRINT_DEBUG ( security_descriptor , * ppdesc ) ;
}
2008-09-17 02:55:06 +04:00
return NT_STATUS_OK ;
}
return SMB_VFS_NEXT_GET_NT_ACL ( handle , name ,
security_info , ppdesc ) ;
}
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 ;
2008-10-31 02:13:03 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " fset_nt_acl_xattr: incoming sd for file %s \n " ,
fsp - > fsp_name ) ) ;
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
}
2008-09-17 02:55:06 +04:00
status = SMB_VFS_NEXT_FSET_NT_ACL ( handle , fsp , security_info_sent , psd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2008-10-31 02:13:03 +03:00
/* Ensure owner and group are set. */
if ( ! psd - > owner_sid | | ! psd - > group_sid ) {
int ret ;
SMB_STRUCT_STAT sbuf ;
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 ) {
ret = SMB_VFS_STAT ( fsp - > conn , fsp - > fsp_name , & sbuf ) ;
} else {
ret = SMB_VFS_FSTAT ( fsp , & sbuf ) ;
}
if ( ret = = - 1 ) {
/* Lower level acl set succeeded,
* so still return OK . */
return NT_STATUS_OK ;
}
create_file_sids ( & sbuf , & owner_sid , & group_sid ) ;
/* 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 ;
}
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-10-31 02:13:03 +03:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " fset_nt_acl_xattr: storing xattr sd for file %s \n " ,
fsp - > fsp_name ) ) ;
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
}
2008-09-17 02:55:06 +04:00
create_acl_blob ( psd , & blob ) ;
2008-10-30 23:51:28 +03:00
store_acl_blob_fsp ( fsp , & blob ) ;
2008-09-17 02:55:06 +04:00
return NT_STATUS_OK ;
}
/* 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 } ,
{ SMB_VFS_OP ( NULL ) , SMB_VFS_OP_NOOP , SMB_VFS_LAYER_NOOP }
} ;
NTSTATUS vfs_acl_xattr_init ( void )
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " acl_xattr " , skel_op_tuples ) ;
}