2019-12-10 17:47:12 +03:00
/*
Unix SMB / CIFS implementation .
openattr tester
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) David Mulder 2019
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/>.
*/
# include "includes.h"
# include "libcli/smb2/smb2.h"
# include "libcli/smb2/smb2_calls.h"
# include "torture/torture.h"
# include "libcli/security/security_descriptor.h"
# include "torture/smb2/proto.h"
static const uint32_t open_attrs_table [ ] = {
FILE_ATTRIBUTE_NORMAL ,
FILE_ATTRIBUTE_ARCHIVE ,
FILE_ATTRIBUTE_READONLY ,
FILE_ATTRIBUTE_HIDDEN ,
FILE_ATTRIBUTE_SYSTEM ,
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY ,
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN ,
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM ,
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN ,
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM ,
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ,
FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN ,
FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM ,
FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ,
FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_SYSTEM ,
} ;
struct trunc_open_results {
unsigned int num ;
uint32_t init_attr ;
uint32_t trunc_attr ;
uint32_t result_attr ;
} ;
static const struct trunc_open_results attr_results [ ] = {
{ 0 , FILE_ATTRIBUTE_NORMAL , FILE_ATTRIBUTE_NORMAL , FILE_ATTRIBUTE_ARCHIVE } ,
{ 1 , FILE_ATTRIBUTE_NORMAL , FILE_ATTRIBUTE_ARCHIVE , FILE_ATTRIBUTE_ARCHIVE } ,
{ 2 , FILE_ATTRIBUTE_NORMAL , FILE_ATTRIBUTE_READONLY , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY } ,
{ 16 , FILE_ATTRIBUTE_ARCHIVE , FILE_ATTRIBUTE_NORMAL , FILE_ATTRIBUTE_ARCHIVE } ,
{ 17 , FILE_ATTRIBUTE_ARCHIVE , FILE_ATTRIBUTE_ARCHIVE , FILE_ATTRIBUTE_ARCHIVE } ,
{ 18 , FILE_ATTRIBUTE_ARCHIVE , FILE_ATTRIBUTE_READONLY , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY } ,
{ 51 , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN } ,
{ 54 , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN } ,
{ 56 , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN } ,
{ 68 , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM } ,
{ 71 , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM } ,
{ 73 , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM } ,
{ 99 , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN } ,
{ 102 , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN } ,
{ 104 , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN } ,
{ 116 , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM } ,
{ 119 , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM } ,
{ 121 , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM } ,
{ 170 , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN } ,
{ 173 , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM } ,
{ 227 , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN } ,
{ 230 , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN } ,
{ 232 , FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN } ,
{ 244 , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM } ,
{ 247 , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM } ,
{ 249 , FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM }
} ;
static NTSTATUS smb2_setatr ( struct smb2_tree * tree , const char * name ,
uint32_t attrib )
{
NTSTATUS status ;
struct smb2_create create_io = { 0 } ;
union smb_setfileinfo io ;
create_io . in . desired_access = SEC_FILE_READ_DATA |
SEC_FILE_WRITE_ATTRIBUTE ;
create_io . in . file_attributes = FILE_ATTRIBUTE_NORMAL ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = NTCREATEX_DISP_OPEN ;
create_io . in . fname = name ;
status = smb2_create ( tree , tree , & create_io ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
ZERO_STRUCT ( io ) ;
io . basic_info . level = RAW_SFILEINFO_BASIC_INFORMATION ;
io . basic_info . in . file . handle = create_io . out . file . handle ;
io . basic_info . in . attrib = attrib ;
status = smb2_setinfo_file ( tree , & io ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return status ;
}
bool torture_smb2_openattrtest ( struct torture_context * tctx ,
struct smb2_tree * tree )
{
NTSTATUS status ;
const char * fname = " openattr.file " ;
uint16_t attr ;
unsigned int i , j , k , l ;
int ret = true ;
for ( k = 0 , i = 0 ; i < sizeof ( open_attrs_table ) / sizeof ( uint32_t ) ; i + + ) {
struct smb2_create create_io = { 0 } ;
smb2_setatr ( tree , fname , FILE_ATTRIBUTE_NORMAL ) ;
smb2_util_unlink ( tree , fname ) ;
create_io . in . create_flags = 0 ;
create_io . in . desired_access = SEC_FILE_WRITE_DATA ;
create_io . in . file_attributes = open_attrs_table [ i ] ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = NTCREATEX_DISP_OVERWRITE_IF ;
create_io . in . create_options = 0 ;
create_io . in . security_flags = 0 ;
create_io . in . fname = fname ;
status = smb2_create ( tree , tctx , & create_io ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " open %d (1) of %s failed (%s) " ,
i , fname , nt_errstr ( status ) ) ) ;
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " close %d (1) of %s failed (%s) " ,
i , fname , nt_errstr ( status ) ) ) ;
for ( j = 0 ; j < ARRAY_SIZE ( open_attrs_table ) ; j + + ) {
create_io = ( struct smb2_create ) { 0 } ;
create_io . in . create_flags = 0 ;
create_io . in . desired_access = SEC_FILE_READ_DATA |
SEC_FILE_WRITE_DATA ;
create_io . in . file_attributes = open_attrs_table [ j ] ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = NTCREATEX_DISP_OVERWRITE ;
create_io . in . create_options = 0 ;
create_io . in . security_flags = 0 ;
create_io . in . fname = fname ;
status = smb2_create ( tree , tctx , & create_io ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
for ( l = 0 ; l < ARRAY_SIZE ( attr_results ) ; l + + ) {
torture_assert_goto ( tctx ,
attr_results [ l ] . num ! = k ,
ret , error_exit ,
talloc_asprintf ( tctx ,
" [%d] trunc open 0x%x "
" -> 0x%x of %s failed "
" - should have "
" succeeded !(%s) " ,
k , open_attrs_table [ i ] ,
open_attrs_table [ j ] ,
fname ,
nt_errstr ( status ) ) ) ;
}
torture_assert_ntstatus_equal_goto ( tctx ,
status , NT_STATUS_ACCESS_DENIED ,
ret , error_exit ,
talloc_asprintf ( tctx ,
" [%d] trunc open 0x%x "
" -> 0x%x failed with "
" wrong error code %s " ,
k , open_attrs_table [ i ] ,
open_attrs_table [ j ] ,
nt_errstr ( status ) ) ) ;
k + + ;
continue ;
}
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret ,
error_exit , talloc_asprintf ( tctx ,
" close %d (2) of %s failed (%s) " , j ,
fname , nt_errstr ( status ) ) ) ;
status = smb2_util_getatr ( tree , fname , & attr , NULL , NULL ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret ,
error_exit , talloc_asprintf ( tctx ,
" getatr(2) failed (%s) " ,
nt_errstr ( status ) ) ) ;
for ( l = 0 ; l < ARRAY_SIZE ( attr_results ) ; l + + ) {
if ( attr_results [ l ] . num = = k ) {
if ( attr ! = attr_results [ l ] . result_attr | |
open_attrs_table [ i ] ! = attr_results [ l ] . init_attr | |
open_attrs_table [ j ] ! = attr_results [ l ] . trunc_attr ) {
ret = false ;
torture_fail_goto ( tctx , error_exit ,
talloc_asprintf ( tctx ,
" [%d] getatr check "
" failed. [0x%x] trunc "
" [0x%x] got attr 0x%x, "
" should be 0x%x " ,
k , open_attrs_table [ i ] ,
open_attrs_table [ j ] ,
( unsigned int ) attr ,
attr_results [ l ] . result_attr ) ) ;
}
break ;
}
}
k + + ;
}
}
error_exit :
smb2_setatr ( tree , fname , FILE_ATTRIBUTE_NORMAL ) ;
smb2_util_unlink ( tree , fname ) ;
return ret ;
}
bool torture_smb2_winattrtest ( struct torture_context * tctx ,
struct smb2_tree * tree )
{
const char * fname = " winattr1.file " ;
const char * dname = " winattr1.dir " ;
uint16_t attr ;
uint16_t j ;
uint32_t aceno ;
bool ret = true ;
union smb_fileinfo query , query_org ;
NTSTATUS status ;
struct security_descriptor * sd1 = NULL , * sd2 = NULL ;
struct smb2_create create_io = { 0 } ;
ZERO_STRUCT ( query ) ;
ZERO_STRUCT ( query_org ) ;
/* Test winattrs for file */
smb2_util_unlink ( tree , fname ) ;
/* Open a file*/
create_io . in . create_flags = 0 ;
2020-04-15 22:07:57 +03:00
create_io . in . desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA |
SEC_STD_READ_CONTROL ;
2019-12-10 17:47:12 +03:00
create_io . in . file_attributes = 0 ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = FILE_SUPERSEDE ;
create_io . in . create_options = 0 ;
create_io . in . security_flags = 0 ;
create_io . in . fname = fname ;
status = smb2_create ( tree , tctx , & create_io ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " open(1) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
/* Get security descriptor and store it*/
query_org . generic . level = RAW_FILEINFO_SEC_DESC ;
query_org . generic . in . file . handle = create_io . out . file . handle ;
2020-04-15 22:07:57 +03:00
query_org . query_secdesc . in . secinfo_flags = SECINFO_OWNER |
SECINFO_GROUP |
SECINFO_DACL ;
status = smb2_getinfo_file ( tree , tctx , & query_org ) ;
2019-12-10 17:47:12 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
NTSTATUS s = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , s , ret , error_exit ,
talloc_asprintf ( tctx ,
" close(1) of %s failed (%s) \n " ,
fname , nt_errstr ( s ) ) ) ;
ret = false ;
torture_fail_goto ( tctx , error_exit , talloc_asprintf ( tctx ,
" smb2_getinfo_file(1) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
}
sd1 = query_org . query_secdesc . out . sd ;
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " close(1) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
/*Set and get attributes*/
for ( j = 0 ; j < ARRAY_SIZE ( open_attrs_table ) ; j + + ) {
status = smb2_setatr ( tree , fname , open_attrs_table [ j ] ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret ,
error_exit ,
talloc_asprintf ( tctx , " setatr(2) failed (%s) " ,
nt_errstr ( status ) ) ) ;
status = smb2_util_getatr ( tree , fname , & attr , NULL , NULL ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret ,
error_exit ,
talloc_asprintf ( tctx , " getatr(2) failed (%s) " ,
nt_errstr ( status ) ) ) ;
/* Check the result */
torture_assert_goto ( tctx , attr = = open_attrs_table [ j ] , ret ,
error_exit , talloc_asprintf ( tctx ,
" getatr check failed. \
Attr applied [ 0 x % x ] , got attr 0 x % x , \
should be 0 x % x " , open_attrs_table[j],
( uint16_t ) attr , open_attrs_table [ j ] ) ) ;
create_io = ( struct smb2_create ) { 0 } ;
create_io . in . create_flags = 0 ;
2020-04-15 22:07:57 +03:00
create_io . in . desired_access = SEC_FILE_READ_ATTRIBUTE |
SEC_STD_READ_CONTROL ;
2019-12-10 17:47:12 +03:00
create_io . in . file_attributes = 0 ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = FILE_OPEN_IF ;
create_io . in . create_options = 0 ;
create_io . in . security_flags = 0 ;
create_io . in . fname = fname ;
status = smb2_create ( tree , tctx , & create_io ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret ,
error_exit ,
talloc_asprintf ( tctx , " open(2) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
/*Get security descriptor */
query . query_secdesc . level = RAW_FILEINFO_SEC_DESC ;
query . query_secdesc . in . file . handle = create_io . out . file . handle ;
2020-04-15 22:07:57 +03:00
query . query_secdesc . in . secinfo_flags = SECINFO_OWNER |
SECINFO_GROUP |
SECINFO_DACL ;
2019-12-10 17:47:12 +03:00
status = smb2_getinfo_file ( tree , tctx , & query ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
NTSTATUS s = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , s , ret ,
error_exit ,
talloc_asprintf ( tctx ,
" close(2) of %s failed (%s) \n " ,
fname , nt_errstr ( s ) ) ) ;
ret = false ;
torture_fail_goto ( tctx , error_exit ,
talloc_asprintf ( tctx ,
" smb2_getinfo_file(2) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
}
sd2 = query . query_secdesc . out . sd ;
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " close(2) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
/*Compare security descriptors -- Must be same*/
for ( aceno = 0 ; ( sd1 - > dacl & & aceno < sd1 - > dacl - > num_aces ) ; aceno + + ) {
struct security_ace * ace1 = & sd1 - > dacl - > aces [ aceno ] ;
struct security_ace * ace2 = & sd2 - > dacl - > aces [ aceno ] ;
torture_assert_goto ( tctx , security_ace_equal ( ace1 , ace2 ) ,
ret , error_exit ,
" ACLs changed! Not expected! \n " ) ;
}
torture_comment ( tctx , " [%d] setattr = [0x%x] got attr 0x%x \n " ,
j , open_attrs_table [ j ] , attr ) ;
}
/* Check for Directory. */
smb2_deltree ( tree , dname ) ;
smb2_util_rmdir ( tree , dname ) ;
/* Open a directory */
create_io = ( struct smb2_create ) { 0 } ;
create_io . in . create_flags = 0 ;
create_io . in . desired_access = SEC_RIGHTS_DIR_ALL ;
create_io . in . file_attributes = FILE_ATTRIBUTE_DIRECTORY ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = NTCREATEX_DISP_OPEN_IF ;
create_io . in . create_options = NTCREATEX_OPTIONS_DIRECTORY ;
create_io . in . security_flags = 0 ;
create_io . in . fname = dname ;
status = smb2_create ( tree , tctx , & create_io ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx ,
" open (1) of %s failed (%s) " ,
dname , nt_errstr ( status ) ) ) ;
/* Get Security Descriptor */
query_org . generic . level = RAW_FILEINFO_SEC_DESC ;
query_org . generic . in . file . handle = create_io . out . file . handle ;
status = smb2_getinfo_file ( tree , tctx , & query_org ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
NTSTATUS s = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , s , ret , error_exit ,
talloc_asprintf ( tctx ,
" close(1) of %s failed (%s) \n " ,
dname , nt_errstr ( s ) ) ) ;
ret = false ;
torture_fail_goto ( tctx , error_exit , talloc_asprintf ( tctx ,
" smb2_getinfo_file(1) of %s failed (%s) \n " , dname ,
nt_errstr ( status ) ) ) ;
}
sd1 = query_org . query_secdesc . out . sd ;
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx ,
" close (1) of %s failed (%s) " , dname ,
nt_errstr ( status ) ) ) ;
/* Set and get win attributes*/
for ( j = 1 ; j < ARRAY_SIZE ( open_attrs_table ) ; j + + ) {
status = smb2_setatr ( tree , dname , open_attrs_table [ j ] ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " setatr(2) failed (%s) " ,
nt_errstr ( status ) ) ) ;
status = smb2_util_getatr ( tree , dname , & attr , NULL , NULL ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " getatr(2) failed (%s) " ,
nt_errstr ( status ) ) ) ;
torture_comment ( tctx , " [%d] setatt = [0x%x] got attr 0x%x \n " ,
j , open_attrs_table [ j ] , attr ) ;
/* Check the result */
torture_assert_goto ( tctx ,
attr = = ( open_attrs_table [ j ] | FILE_ATTRIBUTE_DIRECTORY ) ,
ret , error_exit , talloc_asprintf ( tctx ,
" getatr check failed. set attr "
" [0x%x], got attr 0x%x, should be 0x%x \n " ,
open_attrs_table [ j ] , ( uint16_t ) attr ,
( unsigned int ) ( open_attrs_table [ j ] | FILE_ATTRIBUTE_DIRECTORY ) ) ) ;
create_io = ( struct smb2_create ) { 0 } ;
create_io . in . create_flags = 0 ;
create_io . in . desired_access = SEC_RIGHTS_DIR_READ ;
create_io . in . file_attributes = FILE_ATTRIBUTE_DIRECTORY ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = NTCREATEX_DISP_OPEN ;
create_io . in . create_options = 0 ;
create_io . in . security_flags = 0 ;
create_io . in . fname = dname ;
status = smb2_create ( tree , tctx , & create_io ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx ,
" open (2) of %s failed (%s) " ,
dname , nt_errstr ( status ) ) ) ;
/* Get security descriptor */
query . generic . level = RAW_FILEINFO_SEC_DESC ;
query . generic . in . file . handle = create_io . out . file . handle ;
status = smb2_getinfo_file ( tree , tctx , & query ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
NTSTATUS s = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , s , ret , error_exit ,
talloc_asprintf ( tctx ,
" close (2) of %s failed (%s) " , dname ,
nt_errstr ( s ) ) ) ;
ret = false ;
torture_fail_goto ( tctx , error_exit ,
talloc_asprintf ( tctx ,
" smb2_getinfo_file(2) of %s failed(%s) \n " ,
dname , nt_errstr ( status ) ) ) ;
}
sd2 = query . query_secdesc . out . sd ;
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx ,
" close (2) of %s failed (%s) " , dname ,
nt_errstr ( status ) ) ) ;
/* Security descriptor must be same*/
for ( aceno = 0 ; ( sd1 - > dacl & & aceno < sd1 - > dacl - > num_aces ) ; aceno + + ) {
struct security_ace * ace1 = & sd1 - > dacl - > aces [ aceno ] ;
struct security_ace * ace2 = & sd2 - > dacl - > aces [ aceno ] ;
torture_assert_goto ( tctx , security_ace_equal ( ace1 , ace2 ) ,
ret , error_exit ,
" ACLs changed! Not expected! \n " ) ;
}
}
error_exit :
smb2_setatr ( tree , fname , FILE_ATTRIBUTE_NORMAL ) ;
smb2_util_unlink ( tree , fname ) ;
smb2_deltree ( tree , dname ) ;
smb2_util_rmdir ( tree , dname ) ;
return ret ;
}
2020-04-15 21:59:17 +03:00
2022-11-25 18:02:27 +03:00
bool torture_smb2_winattr2 ( struct torture_context * tctx ,
struct smb2_tree * tree )
{
const char * fname = " winattr2.file " ;
struct smb2_create c = { 0 } ;
NTSTATUS status ;
bool ret = true ;
smb2_util_unlink ( tree , fname ) ;
/* Create a file with FILE_ATTRIBUTE_ARCHIVE */
c = ( struct smb2_create ) {
. in . desired_access = SEC_FILE_READ_DATA ,
. in . file_attributes = FILE_ATTRIBUTE_ARCHIVE ,
. in . share_access = NTCREATEX_SHARE_ACCESS_NONE ,
. in . create_disposition = NTCREATEX_DISP_OPEN_IF ,
. in . fname = fname ,
} ;
status = smb2_create ( tree , tctx , & c ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , done ,
" smb2_create failed \n " ) ;
status = smb2_util_close ( tree , c . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , done ,
" smb2_util_close failed \n " ) ;
/* Reopen file with different attributes */
c = ( struct smb2_create ) {
. in . desired_access = SEC_FILE_READ_DATA ,
. in . file_attributes = FILE_ATTRIBUTE_ARCHIVE |
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_READONLY ,
. in . share_access = NTCREATEX_SHARE_ACCESS_NONE ,
. in . create_disposition = NTCREATEX_DISP_OPEN_IF ,
. in . fname = fname ,
} ;
status = smb2_create ( tree , tctx , & c ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , done ,
" smb2_create failed \n " ) ;
status = smb2_util_close ( tree , c . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , done ,
" smb2_util_close failed \n " ) ;
torture_assert_int_equal_goto ( tctx ,
c . out . file_attr ,
FILE_ATTRIBUTE_ARCHIVE ,
ret , done ,
" Wrong attributes \n " ) ;
done :
smb2_util_unlink ( tree , fname ) ;
return ret ;
}
2020-04-15 21:59:17 +03:00
bool torture_smb2_sdreadtest ( struct torture_context * tctx ,
struct smb2_tree * tree )
{
const char * fname = " sdread.file " ;
bool ret = true ;
union smb_fileinfo query ;
NTSTATUS status ;
struct security_descriptor * sd = NULL ;
struct smb2_create create_io = { 0 } ;
uint32_t sd_bits [ ] = { SECINFO_OWNER ,
SECINFO_GROUP ,
SECINFO_DACL } ;
size_t i ;
ZERO_STRUCT ( query ) ;
smb2_util_unlink ( tree , fname ) ;
/* Create then close a file*/
create_io . in . create_flags = 0 ;
create_io . in . desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA ;
create_io . in . file_attributes = 0 ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = FILE_SUPERSEDE ;
create_io . in . create_options = 0 ;
create_io . in . security_flags = 0 ;
create_io . in . fname = fname ;
status = smb2_create ( tree , tctx , & create_io ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " open(1) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret , error_exit ,
talloc_asprintf ( tctx , " close(1) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
/*
* Open the file with READ_ATTRIBUTES * only * ,
* no READ_CONTROL .
*
* This should deny access for any attempt to
* get a security descriptor if we ask for
* any of OWNER | GROUP | DACL , but if
* we ask for * NO * info but still ask for
* the security descriptor , then Windows
* returns an ACL but with zero entries
* for OWNER | GROUP | DACL .
*/
create_io = ( struct smb2_create ) { 0 } ;
create_io . in . create_flags = 0 ;
create_io . in . desired_access = SEC_FILE_READ_ATTRIBUTE ;
create_io . in . file_attributes = 0 ;
create_io . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
create_io . in . create_disposition = FILE_OPEN ;
create_io . in . create_options = 0 ;
create_io . in . security_flags = 0 ;
create_io . in . fname = fname ;
status = smb2_create ( tree , tctx , & create_io ) ;
torture_assert_ntstatus_ok_goto ( tctx , status , ret ,
error_exit ,
talloc_asprintf ( tctx , " open(2) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
/* Check asking for SD fails ACCESS_DENIED with actual bits set. */
for ( i = 0 ; i < ARRAY_SIZE ( sd_bits ) ; i + + ) {
query . query_secdesc . level = RAW_FILEINFO_SEC_DESC ;
query . query_secdesc . in . file . handle = create_io . out . file . handle ;
query . query_secdesc . in . secinfo_flags = sd_bits [ i ] ;
status = smb2_getinfo_file ( tree , tctx , & query ) ;
/* Must return ACESS_DENIED. */
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) ) {
NTSTATUS s = smb2_util_close ( tree ,
create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , s , ret ,
error_exit ,
talloc_asprintf ( tctx ,
" close(2) of %s failed (%s) \n " ,
fname , nt_errstr ( s ) ) ) ;
ret = false ;
torture_fail_goto ( tctx , error_exit ,
talloc_asprintf ( tctx ,
" smb2_getinfo_file(2) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
}
}
/*
* Get security descriptor whilst asking for * NO * bits .
* This succeeds even though we don ' t have READ_CONTROL
* access but returns an SD with zero data .
*/
query . query_secdesc . level = RAW_FILEINFO_SEC_DESC ;
query . query_secdesc . in . file . handle = create_io . out . file . handle ;
query . query_secdesc . in . secinfo_flags = 0 ;
status = smb2_getinfo_file ( tree , tctx , & query ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
NTSTATUS s = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx , s , ret , error_exit ,
talloc_asprintf ( tctx ,
" close(3) of %s failed (%s) \n " ,
fname , nt_errstr ( s ) ) ) ;
ret = false ;
torture_fail_goto ( tctx , error_exit , talloc_asprintf ( tctx ,
" smb2_getinfo_file(3) of %s failed (%s) \n " ,
fname , nt_errstr ( status ) ) ) ;
}
sd = query . query_secdesc . out . sd ;
/* Check it's empty. */
torture_assert_goto ( tctx ,
( sd - > owner_sid = = NULL ) ,
ret ,
error_exit ,
" sd->owner_sid != NULL \n " ) ;
torture_assert_goto ( tctx ,
( sd - > group_sid = = NULL ) ,
ret ,
error_exit ,
" sd->group_sid != NULL \n " ) ;
torture_assert_goto ( tctx ,
( sd - > dacl = = NULL ) ,
ret ,
error_exit ,
" sd->dacl != NULL \n " ) ;
status = smb2_util_close ( tree , create_io . out . file . handle ) ;
torture_assert_ntstatus_ok_goto ( tctx ,
status ,
ret ,
error_exit ,
talloc_asprintf ( tctx , " close(4) of %s failed (%s) \n " ,
fname ,
nt_errstr ( status ) ) ) ;
error_exit :
smb2_setatr ( tree , fname , FILE_ATTRIBUTE_NORMAL ) ;
smb2_util_unlink ( tree , fname ) ;
return ret ;
}