2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
SMB torture tester - mangling test
Copyright ( C ) Andrew Tridgell 2002
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
2003-08-13 05:53:07 +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/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2006-04-24 04:16:51 +04:00
# include "system/dir.h"
2011-06-20 13:10:25 +04:00
# include "../lib/tdb_compat/tdb_compat.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/util_tdb.h"
2006-01-03 18:40:05 +03:00
# include "libcli/libcli.h"
2006-03-17 20:59:58 +03:00
# include "torture/util.h"
2011-03-19 02:42:52 +03:00
# include "torture/basic/proto.h"
2003-08-13 05:53:07 +04:00
static TDB_CONTEXT * tdb ;
# define NAME_LENGTH 20
2010-01-05 20:42:54 +03:00
static unsigned int total , collisions , failures ;
2003-08-13 05:53:07 +04:00
2007-09-07 21:59:53 +04:00
static bool test_one ( struct torture_context * tctx , struct smbcli_state * cli ,
const char * name )
2003-08-13 05:53:07 +04:00
{
int fnum ;
2003-11-28 12:05:44 +03:00
const char * shortname ;
2007-09-07 21:59:53 +04:00
const char * name2 ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
TDB_DATA data ;
total + + ;
2004-08-04 17:23:35 +04:00
fnum = smbcli_open ( cli - > tree , name , O_RDWR | O_CREAT | O_EXCL , DENY_NONE ) ;
2003-08-13 05:53:07 +04:00
if ( fnum = = - 1 ) {
2004-08-04 17:23:35 +04:00
printf ( " open of %s failed (%s) \n " , name , smbcli_errstr ( cli - > tree ) ) ;
2007-09-07 21:59:53 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_close ( cli - > tree , fnum ) ) ) {
printf ( " close of %s failed (%s) \n " , name , smbcli_errstr ( cli - > tree ) ) ;
2007-09-07 21:59:53 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
/* get the short name */
2004-08-04 17:23:35 +04:00
status = smbcli_qpathinfo_alt_name ( cli - > tree , name , & shortname ) ;
2003-08-13 05:53:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-08-04 17:23:35 +04:00
printf ( " query altname of %s failed (%s) \n " , name , smbcli_errstr ( cli - > tree ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
2007-09-07 21:59:53 +04:00
name2 = talloc_asprintf ( tctx , " \\ mangle_test \\ %s " , shortname ) ;
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_unlink ( cli - > tree , name2 ) ) ) {
2003-08-13 05:53:07 +04:00
printf ( " unlink of %s (%s) failed (%s) \n " ,
2004-08-04 17:23:35 +04:00
name2 , name , smbcli_errstr ( cli - > tree ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
/* recreate by short name */
2004-08-04 17:23:35 +04:00
fnum = smbcli_open ( cli - > tree , name2 , O_RDWR | O_CREAT | O_EXCL , DENY_NONE ) ;
2003-08-13 05:53:07 +04:00
if ( fnum = = - 1 ) {
2004-08-04 17:23:35 +04:00
printf ( " open2 of %s failed (%s) \n " , name2 , smbcli_errstr ( cli - > tree ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_close ( cli - > tree , fnum ) ) ) {
printf ( " close of %s failed (%s) \n " , name , smbcli_errstr ( cli - > tree ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
/* and unlink by long name */
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_unlink ( cli - > tree , name ) ) ) {
2003-08-13 05:53:07 +04:00
printf ( " unlink2 of %s (%s) failed (%s) \n " ,
2004-08-04 17:23:35 +04:00
name , name2 , smbcli_errstr ( cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
failures + + ;
2004-08-04 17:23:35 +04:00
smbcli_unlink ( cli - > tree , name2 ) ;
2007-10-07 02:28:14 +04:00
return true ;
2003-08-13 05:53:07 +04:00
}
/* see if the short name is already in the tdb */
2003-12-10 06:02:12 +03:00
data = tdb_fetch_bystring ( tdb , shortname ) ;
2003-08-13 05:53:07 +04:00
if ( data . dptr ) {
/* maybe its a duplicate long name? */
2006-01-18 19:20:33 +03:00
if ( strcasecmp ( name , ( const char * ) data . dptr ) ! = 0 ) {
2003-08-13 05:53:07 +04:00
/* we have a collision */
collisions + + ;
printf ( " Collision between %s and %s -> %s "
" (coll/tot: %u/%u) \n " ,
name , data . dptr , shortname , collisions , total ) ;
}
free ( data . dptr ) ;
} else {
TDB_DATA namedata ;
/* store it for later */
2006-01-18 19:20:33 +03:00
namedata . dptr = discard_const_p ( uint8_t , name ) ;
2003-08-13 05:53:07 +04:00
namedata . dsize = strlen ( name ) + 1 ;
2003-12-10 06:02:12 +03:00
tdb_store_bystring ( tdb , shortname , namedata , TDB_REPLACE ) ;
2003-08-13 05:53:07 +04:00
}
2007-10-07 02:28:14 +04:00
return true ;
2003-08-13 05:53:07 +04:00
}
2007-09-07 21:59:53 +04:00
static char * gen_name ( TALLOC_CTX * mem_ctx )
2003-08-13 05:53:07 +04:00
{
const char * chars = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._-$~... " ;
2010-01-05 20:42:54 +03:00
unsigned int max_idx = strlen ( chars ) ;
unsigned int len ;
2003-08-13 05:53:07 +04:00
int i ;
char * p ;
2007-09-07 21:59:53 +04:00
char * name ;
2003-08-13 05:53:07 +04:00
2007-09-07 21:59:53 +04:00
name = talloc_strdup ( mem_ctx , " \\ mangle_test \\ " ) ;
2003-08-13 05:53:07 +04:00
len = 1 + random ( ) % NAME_LENGTH ;
2007-09-07 21:59:53 +04:00
name = talloc_realloc ( mem_ctx , name , char , strlen ( name ) + len + 6 ) ;
p = name + strlen ( name ) ;
2003-08-13 05:53:07 +04:00
for ( i = 0 ; i < len ; i + + ) {
p [ i ] = chars [ random ( ) % max_idx ] ;
}
p [ i ] = 0 ;
2006-04-24 04:16:51 +04:00
if ( ISDOT ( p ) | | ISDOTDOT ( p ) ) {
2003-08-13 05:53:07 +04:00
p [ 0 ] = ' _ ' ;
}
/* have a high probability of a common lead char */
if ( random ( ) % 2 = = 0 ) {
p [ 0 ] = ' A ' ;
}
/* and a medium probability of a common lead string */
2007-09-16 14:30:31 +04:00
if ( ( len > 5 ) & & ( random ( ) % 10 = = 0 ) ) {
2003-08-13 05:53:07 +04:00
strncpy ( p , " ABCDE " , 5 ) ;
}
/* and a high probability of a good extension length */
if ( random ( ) % 2 = = 0 ) {
char * s = strrchr ( p , ' . ' ) ;
if ( s ) {
s [ 4 ] = 0 ;
}
}
2007-09-07 21:59:53 +04:00
return name ;
2003-08-13 05:53:07 +04:00
}
2007-09-07 19:08:14 +04:00
bool torture_mangle ( struct torture_context * torture ,
struct smbcli_state * cli )
2003-08-13 05:53:07 +04:00
{
extern int torture_numops ;
int i ;
/* we will use an internal tdb to store the names we have used */
2011-06-20 13:10:32 +04:00
tdb = tdb_open_compat ( NULL , 100000 , TDB_INTERNAL , 0 , 0 , NULL , NULL ) ;
2003-08-13 05:53:07 +04:00
if ( ! tdb ) {
printf ( " ERROR: Failed to open tdb \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
2004-11-12 12:37:59 +03:00
if ( ! torture_setup_dir ( cli , " \\ mangle_test " ) ) {
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
for ( i = 0 ; i < torture_numops ; i + + ) {
2007-09-07 21:59:53 +04:00
char * name ;
2005-08-02 00:41:48 +04:00
2007-09-07 21:59:53 +04:00
name = gen_name ( torture ) ;
2003-08-13 05:53:07 +04:00
2007-09-07 21:59:53 +04:00
if ( ! test_one ( torture , cli , name ) ) {
2003-08-13 05:53:07 +04:00
break ;
}
if ( total & & total % 100 = = 0 ) {
2007-04-30 01:37:29 +04:00
if ( torture_setting_bool ( torture , " progress " , true ) ) {
printf ( " collisions %u/%u - %.2f%% (%u failures) \r " ,
collisions , total , ( 100.0 * collisions ) / total , failures ) ;
}
2003-08-13 05:53:07 +04:00
}
}
2004-08-04 17:23:35 +04:00
smbcli_unlink ( cli - > tree , " \\ mangle_test \\ * " ) ;
if ( NT_STATUS_IS_ERR ( smbcli_rmdir ( cli - > tree , " \\ mangle_test " ) ) ) {
2003-08-13 05:53:07 +04:00
printf ( " ERROR: Failed to remove directory \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
printf ( " \n Total collisions %u/%u - %.2f%% (%u failures) \n " ,
collisions , total , ( 100.0 * collisions ) / total , failures ) ;
return ( failures = = 0 ) ;
}