2006-06-12 14:18:15 +04:00
/*
Unix SMB / CIFS implementation .
Test samba3 hide unreadable / unwriteable
Copyright ( C ) Volker Lendecke 2006
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-06-12 14:18:15 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-06-12 14:18:15 +04:00
*/
# include "includes.h"
# include "system/time.h"
# include "system/filesys.h"
# include "libcli/libcli.h"
# include "torture/util.h"
static void init_unixinfo_nochange ( union smb_setfileinfo * info )
{
ZERO_STRUCTP ( info ) ;
info - > unix_basic . level = RAW_SFILEINFO_UNIX_BASIC ;
info - > unix_basic . in . mode = SMB_MODE_NO_CHANGE ;
info - > unix_basic . in . end_of_file = SMB_SIZE_NO_CHANGE_HI ;
info - > unix_basic . in . end_of_file < < = 32 ;
info - > unix_basic . in . end_of_file | = SMB_SIZE_NO_CHANGE_LO ;
info - > unix_basic . in . num_bytes = SMB_SIZE_NO_CHANGE_HI ;
info - > unix_basic . in . num_bytes < < = 32 ;
info - > unix_basic . in . num_bytes | = SMB_SIZE_NO_CHANGE_LO ;
info - > unix_basic . in . status_change_time = SMB_TIME_NO_CHANGE_HI ;
info - > unix_basic . in . status_change_time < < = 32 ;
2007-01-05 18:12:32 +03:00
info - > unix_basic . in . status_change_time | = SMB_TIME_NO_CHANGE_LO ;
2006-06-12 14:18:15 +04:00
info - > unix_basic . in . access_time = SMB_TIME_NO_CHANGE_HI ;
info - > unix_basic . in . access_time < < = 32 ;
2006-06-12 15:45:43 +04:00
info - > unix_basic . in . access_time | = SMB_TIME_NO_CHANGE_LO ;
2006-06-12 14:18:15 +04:00
info - > unix_basic . in . change_time = SMB_TIME_NO_CHANGE_HI ;
info - > unix_basic . in . change_time < < = 32 ;
2006-06-12 15:45:43 +04:00
info - > unix_basic . in . change_time | = SMB_TIME_NO_CHANGE_LO ;
2006-06-12 14:18:15 +04:00
info - > unix_basic . in . uid = SMB_UID_NO_CHANGE ;
info - > unix_basic . in . gid = SMB_GID_NO_CHANGE ;
}
struct list_state {
const char * fname ;
2007-10-07 02:28:14 +04:00
bool visible ;
2006-06-12 14:18:15 +04:00
} ;
static void set_visible ( struct clilist_file_info * i , const char * mask ,
void * priv )
{
2007-01-05 19:02:42 +03:00
struct list_state * state = ( struct list_state * ) priv ;
2006-06-12 14:18:15 +04:00
if ( strcasecmp_m ( state - > fname , i - > name ) = = 0 )
2007-10-07 02:28:14 +04:00
state - > visible = true ;
2006-06-12 14:18:15 +04:00
}
2007-10-07 02:28:14 +04:00
static bool is_visible ( struct smbcli_tree * tree , const char * fname )
2006-06-12 14:18:15 +04:00
{
struct list_state state ;
2007-10-07 02:28:14 +04:00
state . visible = false ;
2006-06-12 14:18:15 +04:00
state . fname = fname ;
if ( smbcli_list ( tree , " *.* " , 0 , set_visible , & state ) < 0 ) {
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
return state . visible ;
}
2007-10-07 02:28:14 +04:00
static bool is_readable ( struct smbcli_tree * tree , const char * fname )
2006-06-12 14:18:15 +04:00
{
int fnum ;
fnum = smbcli_open ( tree , fname , O_RDONLY , DENY_NONE ) ;
if ( fnum < 0 ) {
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
smbcli_close ( tree , fnum ) ;
2007-10-07 02:28:14 +04:00
return true ;
2006-06-12 14:18:15 +04:00
}
2007-10-07 02:28:14 +04:00
static bool is_writeable ( TALLOC_CTX * mem_ctx , struct smbcli_tree * tree ,
2006-06-12 14:18:15 +04:00
const char * fname )
{
int fnum ;
fnum = smbcli_open ( tree , fname , O_WRONLY , DENY_NONE ) ;
if ( fnum < 0 ) {
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
smbcli_close ( tree , fnum ) ;
2007-10-07 02:28:14 +04:00
return true ;
2006-06-12 14:18:15 +04:00
}
/*
* This is not an exact method because there ' s a ton of reasons why a getatr
* might fail . But for our purposes it ' s sufficient .
*/
2007-10-07 02:28:14 +04:00
static bool smbcli_file_exists ( struct smbcli_tree * tree , const char * fname )
2006-06-12 14:18:15 +04:00
{
return NT_STATUS_IS_OK ( smbcli_getatr ( tree , fname , NULL , NULL , NULL ) ) ;
}
static NTSTATUS smbcli_chmod ( struct smbcli_tree * tree , const char * fname ,
uint64_t permissions )
{
union smb_setfileinfo sfinfo ;
init_unixinfo_nochange ( & sfinfo ) ;
sfinfo . unix_basic . in . file . path = fname ;
sfinfo . unix_basic . in . permissions = permissions ;
return smb_raw_setpathinfo ( tree , & sfinfo ) ;
}
2007-09-07 19:08:14 +04:00
bool torture_samba3_hide ( struct torture_context * torture )
2006-06-12 14:18:15 +04:00
{
struct smbcli_state * cli ;
const char * fname = " test.txt " ;
int fnum ;
NTSTATUS status ;
struct smbcli_tree * hideunread ;
struct smbcli_tree * hideunwrite ;
if ( ! torture_open_connection_share (
2007-12-03 17:53:07 +03:00
torture , & cli , torture , torture_setting_string ( torture , " host " , NULL ) ,
2008-04-23 00:37:54 +04:00
torture_setting_string ( torture , " share " , NULL ) , torture - > ev ) ) {
2006-06-12 14:18:15 +04:00
d_printf ( " torture_open_connection_share failed \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
2006-06-29 02:09:03 +04:00
status = torture_second_tcon ( torture , cli - > session , " hideunread " ,
& hideunread ) ;
2006-06-12 14:18:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " second_tcon(hideunread) failed: %s \n " ,
nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
2006-06-29 02:09:03 +04:00
status = torture_second_tcon ( torture , cli - > session , " hideunwrite " ,
& hideunwrite ) ;
2006-06-12 14:18:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " second_tcon(hideunwrite) failed: %s \n " ,
nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
status = smbcli_unlink ( cli - > tree , fname ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_CANNOT_DELETE ) ) {
smbcli_setatr ( cli - > tree , fname , 0 , - 1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
}
fnum = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum = = - 1 ) {
d_printf ( " Failed to create %s - %s \n " , fname ,
smbcli_errstr ( cli - > tree ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
smbcli_close ( cli - > tree , fnum ) ;
if ( ! smbcli_file_exists ( cli - > tree , fname ) ) {
d_printf ( " %s does not exist \n " , fname ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
/* R/W file should be visible everywhere */
status = smbcli_chmod ( cli - > tree , fname , UNIX_R_USR | UNIX_W_USR ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " smbcli_chmod failed: %s \n " , nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
2006-06-13 03:01:51 +04:00
if ( ! is_writeable ( torture , cli - > tree , fname ) ) {
2006-06-12 14:18:15 +04:00
d_printf ( " File not writable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( ! is_readable ( cli - > tree , fname ) ) {
d_printf ( " File not readable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( ! is_visible ( cli - > tree , fname ) ) {
d_printf ( " r/w file not visible via normal share \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( ! is_visible ( hideunread , fname ) ) {
d_printf ( " r/w file not visible via hide unreadable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( ! is_visible ( hideunwrite , fname ) ) {
d_printf ( " r/w file not visible via hide unwriteable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
/* R/O file should not be visible via hide unwriteable files */
status = smbcli_chmod ( cli - > tree , fname , UNIX_R_USR ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " smbcli_chmod failed: %s \n " , nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
2006-06-13 03:01:51 +04:00
if ( is_writeable ( torture , cli - > tree , fname ) ) {
2006-06-12 14:18:15 +04:00
d_printf ( " r/o is writable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( ! is_readable ( cli - > tree , fname ) ) {
d_printf ( " r/o not readable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( ! is_visible ( cli - > tree , fname ) ) {
d_printf ( " r/o file not visible via normal share \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( ! is_visible ( hideunread , fname ) ) {
d_printf ( " r/o file not visible via hide unreadable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( is_visible ( hideunwrite , fname ) ) {
d_printf ( " r/o file visible via hide unwriteable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
/* inaccessible file should be only visible on normal share */
status = smbcli_chmod ( cli - > tree , fname , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " smbcli_chmod failed: %s \n " , nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
2006-06-13 03:01:51 +04:00
if ( is_writeable ( torture , cli - > tree , fname ) ) {
2006-06-12 14:18:15 +04:00
d_printf ( " inaccessible file is writable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( is_readable ( cli - > tree , fname ) ) {
d_printf ( " inaccessible file is readable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( ! is_visible ( cli - > tree , fname ) ) {
d_printf ( " inaccessible file not visible via normal share \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( is_visible ( hideunread , fname ) ) {
d_printf ( " inaccessible file visible via hide unreadable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
if ( is_visible ( hideunwrite , fname ) ) {
d_printf ( " inaccessible file visible via hide unwriteable \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-06-12 14:18:15 +04:00
}
2007-01-08 19:11:44 +03:00
smbcli_chmod ( cli - > tree , fname , UNIX_R_USR | UNIX_W_USR ) ;
smbcli_unlink ( cli - > tree , fname ) ;
2007-10-07 02:28:14 +04:00
return true ;
2006-06-12 14:18:15 +04:00
}
2007-01-05 19:02:42 +03:00
/*
* Try to force smb_close to return an error . The only way I can think of is
* to open a file with delete on close , chmod the parent dir to 000 and then
* close . smb_close should return NT_STATUS_ACCESS_DENIED .
*/
2007-09-07 19:08:14 +04:00
bool torture_samba3_closeerr ( struct torture_context * tctx )
2007-01-05 19:02:42 +03:00
{
struct smbcli_state * cli = NULL ;
2007-10-07 02:28:14 +04:00
bool result = false ;
2007-01-05 19:02:42 +03:00
NTSTATUS status ;
const char * dname = " closeerr.dir " ;
const char * fname = " closeerr.dir \\ closerr.txt " ;
int fnum ;
2007-12-03 17:53:07 +03:00
if ( ! torture_open_connection ( & cli , tctx , 0 ) ) {
2007-01-05 19:02:42 +03:00
goto fail ;
}
smbcli_deltree ( cli - > tree , dname ) ;
torture_assert_ntstatus_ok (
tctx , smbcli_mkdir ( cli - > tree , dname ) ,
talloc_asprintf ( tctx , " smbcli_mdir failed: (%s) \n " ,
smbcli_errstr ( cli - > tree ) ) ) ;
fnum = smbcli_open ( cli - > tree , fname , O_CREAT | O_RDWR ,
DENY_NONE ) ;
torture_assert ( tctx , fnum ! = - 1 ,
talloc_asprintf ( tctx , " smbcli_open failed: %s \n " ,
smbcli_errstr ( cli - > tree ) ) ) ;
smbcli_close ( cli - > tree , fnum ) ;
fnum = smbcli_nt_create_full ( cli - > tree , fname , 0 ,
SEC_RIGHTS_FILE_ALL ,
FILE_ATTRIBUTE_NORMAL ,
NTCREATEX_SHARE_ACCESS_DELETE ,
NTCREATEX_DISP_OPEN , 0 , 0 ) ;
torture_assert ( tctx , fnum ! = - 1 ,
talloc_asprintf ( tctx , " smbcli_open failed: %s \n " ,
smbcli_errstr ( cli - > tree ) ) ) ;
2007-10-07 02:28:14 +04:00
status = smbcli_nt_delete_on_close ( cli - > tree , fnum , true ) ;
2007-01-05 19:02:42 +03:00
torture_assert_ntstatus_ok ( tctx , status ,
" setting delete_on_close on file failed ! " ) ;
status = smbcli_chmod ( cli - > tree , dname , 0 ) ;
torture_assert_ntstatus_ok ( tctx , status ,
" smbcli_chmod on file failed ! " ) ;
status = smbcli_close ( cli - > tree , fnum ) ;
smbcli_chmod ( cli - > tree , dname , UNIX_R_USR | UNIX_W_USR | UNIX_X_USR ) ;
smbcli_deltree ( cli - > tree , dname ) ;
torture_assert_ntstatus_equal ( tctx , status , NT_STATUS_ACCESS_DENIED ,
" smbcli_close " ) ;
2007-10-07 02:28:14 +04:00
result = true ;
2007-01-05 19:02:42 +03:00
fail :
if ( cli ) {
torture_close_connection ( cli ) ;
}
return result ;
}