/* Unix SMB/CIFS implementation. SMB torture tester Copyright (C) Andrew Tridgell 1997-1998 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 2 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define NO_SYSLOG #include "includes.h" static fstring host, workgroup, share, password, username, myname; static int max_protocol = PROTOCOL_NT1; static const char *sockops="TCP_NODELAY"; static int nprocs=1; int torture_numops=100; static int procnum; /* records process count number when forking */ static struct cli_state current_cli; static fstring randomfname; static BOOL use_oplocks; static BOOL use_level_II_oplocks; static const char *client_txt = "client_oplocks.txt"; static BOOL use_kerberos; BOOL torture_showall = False; static double create_procs(BOOL (*fn)(int), BOOL *result); static struct timeval tp1,tp2; void start_timer(void) { gettimeofday(&tp1,NULL); } double end_timer(void) { gettimeofday(&tp2,NULL); return((tp2.tv_sec - tp1.tv_sec) + (tp2.tv_usec - tp1.tv_usec)*1.0e-6); } /* return a pointer to a anonymous shared memory segment of size "size" which will persist across fork() but will disappear when all processes exit The memory is not zeroed This function uses system5 shared memory. It takes advantage of a property that the memory is not destroyed if it is attached when the id is removed */ void *shm_setup(int size) { int shmid; void *ret; shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W); if (shmid == -1) { printf("can't get shared memory\n"); exit(1); } ret = (void *)shmat(shmid, 0, 0); if (!ret || ret == (void *)-1) { printf("can't attach to shared memory\n"); return NULL; } /* the following releases the ipc, but note that this process and all its children will still have access to the memory, its just that the shmid is no longer valid for other shm calls. This means we don't leave behind lots of shm segments after we exit See Stevens "advanced programming in unix env" for details */ shmctl(shmid, IPC_RMID, 0); return ret; } static BOOL open_nbt_connection(struct cli_state *c) { struct nmb_name called, calling; struct in_addr ip; ZERO_STRUCTP(c); make_nmb_name(&calling, myname, 0x0); make_nmb_name(&called , host, 0x20); zero_ip(&ip); if (!cli_initialise(c) || !cli_connect(c, host, &ip)) { printf("Failed to connect with %s\n", host); return False; } c->use_kerberos = use_kerberos; c->timeout = 120000; /* set a really long timeout (2 minutes) */ if (use_oplocks) c->use_oplocks = True; if (use_level_II_oplocks) c->use_level_II_oplocks = True; if (!cli_session_request(c, &calling, &called)) { printf("%s rejected the session\n",host); cli_shutdown(c); return False; } return True; } BOOL torture_open_connection(struct cli_state *c) { ZERO_STRUCTP(c); if (!open_nbt_connection(c)) { return False; } if (!cli_negprot(c)) { printf("%s rejected the negprot (%s)\n",host, cli_errstr(c)); cli_shutdown(c); return False; } if (!cli_session_setup(c, username, password, strlen(password), password, strlen(password), workgroup)) { printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c)); cli_shutdown(c); return False; } if (!cli_send_tconX(c, share, "?????", password, strlen(password)+1)) { printf("%s refused tree connect (%s)\n", host, cli_errstr(c)); cli_shutdown(c); return False; } return True; } BOOL torture_close_connection(struct cli_state *c) { BOOL ret = True; if (!cli_tdis(c)) { printf("tdis failed (%s)\n", cli_errstr(c)); ret = False; } cli_shutdown(c); return ret; } /* check if the server produced the expected error code */ static BOOL check_error(int line, struct cli_state *c, uint8 eclass, uint32 ecode, NTSTATUS nterr) { if (cli_is_dos_error(c)) { uint8 class; uint32 num; /* Check DOS error */ cli_dos_error(c, &class, &num); if (eclass != class || ecode != num) { printf("unexpected error code class=%d code=%d\n", (int)class, (int)num); printf(" expected %d/%d %s (line=%d)\n", (int)eclass, (int)ecode, nt_errstr(nterr), line); return False; } } else { NTSTATUS status; /* Check NT error */ status = cli_nt_error(c); if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) { printf("unexpected error code %s\n", nt_errstr(status)); printf(" expected %s (line=%d)\n", nt_errstr(nterr), line); return False; } } return True; } static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len) { while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) { if (!check_error(__LINE__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False; } return True; } static BOOL rw_torture(struct cli_state *c) { const char *lockfname = "\\torture.lck"; fstring fname; int fnum; int fnum2; pid_t pid2, pid = getpid(); int i, j; char buf[1024]; BOOL correct = True; fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE); if (fnum2 == -1) fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE); if (fnum2 == -1) { printf("open of %s failed (%s)\n", lockfname, cli_errstr(c)); return False; } for (i=0;i= countprev) { printf("%d %8d\r", i, count); fflush(stdout); i++; countprev += (sizeof(buf) / 20); } if (procnum == 0) { sent = ((unsigned)sys_random()%(20))+ 1; if (sent > sizeof(buf) - count) { sent = sizeof(buf) - count; } if (cli_write(c, fnum, 0, buf+count, count, (size_t)sent) != sent) { printf("write failed (%s)\n", cli_errstr(c)); correct = False; } } else { sent = cli_read(c, fnum, buf_rd+count, count, sizeof(buf)-count); if (sent < 0) { printf("read failed offset:%d size:%d (%s)\n", count, sizeof(buf)-count, cli_errstr(c)); correct = False; sent = 0; } if (sent > 0) { if (memcmp(buf_rd+count, buf+count, sent) != 0) { printf("read/write compare failed\n"); printf("offset: %d req %d recvd %d\n", count, sizeof(buf)-count, sent); correct = False; break; } } } } if (!cli_close(c, fnum)) { printf("close failed (%s)\n", cli_errstr(c)); correct = False; } return correct; } static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2) { const char *lockfname = "\\torture2.lck"; int fnum1; int fnum2; int i; uchar buf[131072]; uchar buf_rd[131072]; BOOL correct = True; ssize_t bytes_read; if (!cli_unlink(c1, lockfname)) { printf("unlink failed (%s) (normal, this file should not exist)\n", cli_errstr(c1)); } fnum1 = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE); if (fnum1 == -1) { printf("first open read/write of %s failed (%s)\n", lockfname, cli_errstr(c1)); return False; } fnum2 = cli_open(c2, lockfname, O_RDONLY, DENY_NONE); if (fnum2 == -1) { printf("second open read-only of %s failed (%s)\n", lockfname, cli_errstr(c2)); cli_close(c1, fnum1); return False; } for (i=0;i=0;i--) { slprintf(fname,sizeof(fname)-1,template, i,(int)getpid()); cli_close(&cli, fnums[i]); if (!cli_unlink(&cli, fname)) { printf("unlink of %s failed (%s)\n", fname, cli_errstr(&cli)); correct = False; } printf("%6d\r", i); } printf("%6d\n", 0); printf("maxfid test finished\n"); if (!torture_close_connection(&cli)) { correct = False; } return correct; } /* generate a random buffer */ static void rand_buf(char *buf, int len) { while (len--) { *buf = (char)sys_random(); buf++; } } /* send smb negprot commands, not reading the response */ static BOOL run_negprot_nowait(int dummy) { int i; static struct cli_state cli; BOOL correct = True; printf("starting negprot nowait test\n"); if (!open_nbt_connection(&cli)) { return False; } for (i=0;i<50000;i++) { cli_negprot_send(&cli); } if (!torture_close_connection(&cli)) { correct = False; } printf("finished negprot nowait test\n"); return correct; } /* send random IPC commands */ static BOOL run_randomipc(int dummy) { char *rparam = NULL; char *rdata = NULL; int rdrcnt,rprcnt; pstring param; int api, param_len, i; static struct cli_state cli; BOOL correct = True; int count = 50000; printf("starting random ipc test\n"); if (!torture_open_connection(&cli)) { return False; } for (i=0;i 60*60*24*10) { printf("ERROR: SMBgetatr bug. time is %s", ctime(&t)); t = time(NULL); correct = True; } t2 = t-60*60*24; /* 1 day ago */ if (!cli_setatr(&cli, fname, 0, t2)) { printf("setatr failed (%s)\n", cli_errstr(&cli)); correct = True; } if (!cli_getatr(&cli, fname, NULL, NULL, &t)) { printf("getatr failed (%s)\n", cli_errstr(&cli)); correct = True; } if (t != t2) { printf("ERROR: getatr/setatr bug. times are\n%s", ctime(&t)); printf("%s", ctime(&t2)); correct = True; } cli_unlink(&cli, fname); if (!torture_close_connection(&cli)) { correct = False; } printf("attrib test finished\n"); return correct; } /* This checks a couple of trans2 calls */ static BOOL run_trans2test(int dummy) { static struct cli_state cli; int fnum; size_t size; time_t c_time, a_time, m_time, w_time, m_time2; const char *fname = "\\trans2.tst"; const char *dname = "\\trans2"; const char *fname2 = "\\trans2\\trans2.tst"; pstring pname; BOOL correct = True; printf("starting trans2 test\n"); if (!torture_open_connection(&cli)) { return False; } cli_unlink(&cli, fname); fnum = cli_open(&cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE); if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time, NULL, NULL)) { printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli)); correct = False; } if (!cli_qfilename(&cli, fnum, pname)) { printf("ERROR: qfilename failed (%s)\n", cli_errstr(&cli)); correct = False; } if (strcmp(pname, fname)) { printf("qfilename gave different name? [%s] [%s]\n", fname, pname); correct = False; } cli_close(&cli, fnum); sleep(2); cli_unlink(&cli, fname); fnum = cli_open(&cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE); if (fnum == -1) { printf("open of %s failed (%s)\n", fname, cli_errstr(&cli)); return False; } cli_close(&cli, fnum); if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) { printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli)); correct = False; } else { if (c_time != m_time) { printf("create time=%s", ctime(&c_time)); printf("modify time=%s", ctime(&m_time)); printf("This system appears to have sticky create times\n"); correct = False; } if (a_time % (60*60) == 0) { printf("access time=%s", ctime(&a_time)); printf("This system appears to set a midnight access time\n"); correct = False; } if (abs(m_time - time(NULL)) > 60*60*24*7) { printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time)); correct = False; } } cli_unlink(&cli, fname); fnum = cli_open(&cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE); cli_close(&cli, fnum); if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL)) { printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli)); correct = False; } else { if (w_time < 60*60*24*2) { printf("write time=%s", ctime(&w_time)); printf("This system appears to set a initial 0 write time\n"); correct = False; } } cli_unlink(&cli, fname); /* check if the server updates the directory modification time when creating a new file */ if (!cli_mkdir(&cli, dname)) { printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli)); correct = False; } sleep(3); if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL)) { printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli)); correct = False; } fnum = cli_open(&cli, fname2, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE); cli_write(&cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum)); cli_close(&cli, fnum); if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL)) { printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli)); correct = False; } else { if (m_time2 == m_time) { printf("This system does not update directory modification times\n"); correct = False; } } cli_unlink(&cli, fname2); cli_rmdir(&cli, dname); if (!torture_close_connection(&cli)) { correct = False; } printf("trans2 test finished\n"); return correct; } /* This checks new W2K calls. */ static BOOL new_trans(struct cli_state *pcli, int fnum, int level) { char buf[4096]; BOOL correct = True; memset(buf, 0xff, sizeof(buf)); if (!cli_qfileinfo_test(pcli, fnum, level, buf)) { printf("ERROR: qfileinfo (%d) failed (%s)\n", level, cli_errstr(pcli)); correct = False; } else { printf("qfileinfo: level %d\n", level); dump_data(0, buf, 256); printf("\n"); } return correct; } static BOOL run_w2ktest(int dummy) { static struct cli_state cli; int fnum; const char *fname = "\\w2ktest\\w2k.tst"; int level; BOOL correct = True; printf("starting w2k test\n"); if (!torture_open_connection(&cli)) { return False; } fnum = cli_open(&cli, fname, O_RDWR | O_CREAT , DENY_NONE); for (level = 1004; level < 1040; level++) { new_trans(&cli, fnum, level); } cli_close(&cli, fnum); if (!torture_close_connection(&cli)) { correct = False; } printf("w2k test finished\n"); return correct; } /* this is a harness for some oplock tests */ static BOOL run_oplock1(int dummy) { static struct cli_state cli1; const char *fname = "\\lockt1.lck"; int fnum1; BOOL correct = True; printf("starting oplock test 1\n"); if (!torture_open_connection(&cli1)) { return False; } cli_unlink(&cli1, fname); cli_sockopt(&cli1, sockops); cli1.use_oplocks = True; fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); if (fnum1 == -1) { printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } cli1.use_oplocks = False; cli_unlink(&cli1, fname); cli_unlink(&cli1, fname); if (!cli_close(&cli1, fnum1)) { printf("close2 failed (%s)\n", cli_errstr(&cli1)); return False; } if (!cli_unlink(&cli1, fname)) { printf("unlink failed (%s)\n", cli_errstr(&cli1)); return False; } if (!torture_close_connection(&cli1)) { correct = False; } printf("finished oplock test 1\n"); return correct; } static BOOL run_oplock2(int dummy) { static struct cli_state cli1, cli2; const char *fname = "\\lockt2.lck"; int fnum1, fnum2; int saved_use_oplocks = use_oplocks; char buf[4]; BOOL correct = True; volatile BOOL *shared_correct; shared_correct = (volatile BOOL *)shm_setup(sizeof(BOOL)); *shared_correct = True; use_level_II_oplocks = True; use_oplocks = True; printf("starting oplock test 2\n"); if (!torture_open_connection(&cli1)) { use_level_II_oplocks = False; use_oplocks = saved_use_oplocks; return False; } cli1.use_oplocks = True; cli1.use_level_II_oplocks = True; if (!torture_open_connection(&cli2)) { use_level_II_oplocks = False; use_oplocks = saved_use_oplocks; return False; } cli2.use_oplocks = True; cli2.use_level_II_oplocks = True; cli_unlink(&cli1, fname); cli_sockopt(&cli1, sockops); cli_sockopt(&cli2, sockops); fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); if (fnum1 == -1) { printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } /* Don't need the globals any more. */ use_level_II_oplocks = False; use_oplocks = saved_use_oplocks; if (fork() == 0) { /* Child code */ fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE); if (fnum2 == -1) { printf("second open of %s failed (%s)\n", fname, cli_errstr(&cli1)); *shared_correct = False; exit(0); } sleep(2); if (!cli_close(&cli2, fnum2)) { printf("close2 failed (%s)\n", cli_errstr(&cli1)); *shared_correct = False; } exit(0); } sleep(2); /* Ensure cli1 processes the break. */ if (cli_read(&cli1, fnum1, buf, 0, 4) != 4) { printf("read on fnum1 failed (%s)\n", cli_errstr(&cli1)); correct = False; } /* Should now be at level II. */ /* Test if sending a write locks causes a break to none. */ if (!cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK)) { printf("lock failed (%s)\n", cli_errstr(&cli1)); correct = False; } cli_unlock(&cli1, fnum1, 0, 4); sleep(2); if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) { printf("lock failed (%s)\n", cli_errstr(&cli1)); correct = False; } cli_unlock(&cli1, fnum1, 0, 4); sleep(2); cli_read(&cli1, fnum1, buf, 0, 4); #if 0 if (cli_write(&cli1, fnum1, 0, buf, 0, 4) != 4) { printf("write on fnum1 failed (%s)\n", cli_errstr(&cli1)); correct = False; } #endif if (!cli_close(&cli1, fnum1)) { printf("close1 failed (%s)\n", cli_errstr(&cli1)); correct = False; } sleep(4); if (!cli_unlink(&cli1, fname)) { printf("unlink failed (%s)\n", cli_errstr(&cli1)); correct = False; } if (!torture_close_connection(&cli1)) { correct = False; } if (!*shared_correct) { correct = False; } printf("finished oplock test 2\n"); return correct; } /* handler for oplock 3 tests */ static BOOL oplock3_handler(struct cli_state *cli, int fnum, unsigned char level) { printf("got oplock break fnum=%d level=%d\n", fnum, level); return cli_oplock_ack(cli, fnum, level); } static BOOL run_oplock3(int dummy) { static struct cli_state cli; const char *fname = "\\oplockt3.dat"; int fnum; char buf[4] = "abcd"; BOOL correct = True; volatile BOOL *shared_correct; shared_correct = (volatile BOOL *)shm_setup(sizeof(BOOL)); *shared_correct = True; printf("starting oplock test 3\n"); if (fork() == 0) { /* Child code */ use_oplocks = True; use_level_II_oplocks = True; if (!torture_open_connection(&cli)) { *shared_correct = False; exit(0); } sleep(2); /* try to trigger a oplock break in parent */ fnum = cli_open(&cli, fname, O_RDWR, DENY_NONE); cli_write(&cli, fnum, 0, buf, 0, 4); exit(0); } /* parent code */ use_oplocks = True; use_level_II_oplocks = True; if (!torture_open_connection(&cli)) { return False; } cli_oplock_handler(&cli, oplock3_handler); fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE); cli_write(&cli, fnum, 0, buf, 0, 4); cli_close(&cli, fnum); fnum = cli_open(&cli, fname, O_RDWR, DENY_NONE); cli.timeout = 20000; cli_receive_smb(&cli); printf("finished oplock test 3\n"); return (correct && *shared_correct); /* What are we looking for here? What's sucess and what's FAILURE? */ } /* Test delete on close semantics. */ static BOOL run_deletetest(int dummy) { static struct cli_state cli1; static struct cli_state cli2; const char *fname = "\\delete.file"; int fnum1 = -1; int fnum2 = -1; BOOL correct = True; printf("starting delete test\n"); ZERO_STRUCT(cli1); ZERO_STRUCT(cli2); if (!torture_open_connection(&cli1)) { return False; } cli_sockopt(&cli1, sockops); /* Test 1 - this should *NOT* delete the file on close. */ cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE, FILE_OVERWRITE_IF, DELETE_ON_CLOSE_FLAG); if (fnum1 == -1) { printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[1] close failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE); if (fnum1 == -1) { printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[1] close failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } printf("first delete on close test succeeded.\n"); /* Test 2 - this should delete the file on close. */ cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("[2] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_nt_delete_on_close(&cli1, fnum1, True)) { printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[2] close failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE); if (fnum1 != -1) { printf("[2] open of %s succeeded should have been deleted on close !\n", fname); if (!cli_close(&cli1, fnum1)) { printf("[2] close failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } cli_unlink(&cli1, fname); } else printf("second delete on close test succeeded.\n"); /* Test 3 - ... */ cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } /* This should fail with a sharing violation - open for delete is only compatible with SHARE_DELETE. */ fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0); if (fnum2 != -1) { printf("[3] open - 2 of %s succeeded - should have failed.\n", fname); correct = False; goto fail; } /* This should succeed. */ fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0); if (fnum2 == -1) { printf("[3] open - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_nt_delete_on_close(&cli1, fnum1, True)) { printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[3] close 1 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_close(&cli1, fnum2)) { printf("[3] close 2 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } /* This should fail - file should no longer be there. */ fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE); if (fnum1 != -1) { printf("[3] open of %s succeeded should have been deleted on close !\n", fname); if (!cli_close(&cli1, fnum1)) { printf("[3] close failed (%s)\n", cli_errstr(&cli1)); } cli_unlink(&cli1, fname); correct = False; goto fail; } else printf("third delete on close test succeeded.\n"); /* Test 4 ... */ cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("[4] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } /* This should succeed. */ fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0); if (fnum2 == -1) { printf("[4] open - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_close(&cli1, fnum2)) { printf("[4] close - 1 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_nt_delete_on_close(&cli1, fnum1, True)) { printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } /* This should fail - no more opens once delete on close set. */ fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0); if (fnum2 != -1) { printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname ); correct = False; goto fail; } else printf("fourth delete on close test succeeded.\n"); if (!cli_close(&cli1, fnum1)) { printf("[4] close - 2 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } /* Test 5 ... */ cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum1 == -1) { printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } /* This should fail - only allowed on NT opens with DELETE access. */ if (cli_nt_delete_on_close(&cli1, fnum1, True)) { printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n"); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[5] close - 2 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } printf("fifth delete on close test succeeded.\n"); /* Test 6 ... */ cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("[6] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } /* This should fail - only allowed on NT opens with DELETE access. */ if (cli_nt_delete_on_close(&cli1, fnum1, True)) { printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n"); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[6] close - 2 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } printf("sixth delete on close test succeeded.\n"); /* Test 7 ... */ cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("[7] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_nt_delete_on_close(&cli1, fnum1, True)) { printf("[7] setting delete_on_close on file failed !\n"); correct = False; goto fail; } if (!cli_nt_delete_on_close(&cli1, fnum1, False)) { printf("[7] unsetting delete_on_close on file failed !\n"); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } /* This next open should succeed - we reset the flag. */ fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE); if (fnum1 == -1) { printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } printf("seventh delete on close test succeeded.\n"); /* Test 7 ... */ cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); if (!torture_open_connection(&cli2)) { printf("[8] failed to open second connection.\n"); correct = False; goto fail; } cli_sockopt(&cli1, sockops); fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } fnum2 = cli_nt_create_full(&cli2, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0); if (fnum2 == -1) { printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_nt_delete_on_close(&cli1, fnum1, True)) { printf("[8] setting delete_on_close on file failed !\n"); correct = False; goto fail; } if (!cli_close(&cli1, fnum1)) { printf("[8] close - 1 failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } if (!cli_close(&cli2, fnum2)) { printf("[8] close - 2 failed (%s)\n", cli_errstr(&cli2)); correct = False; goto fail; } /* This should fail.. */ fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE); if (fnum1 != -1) { printf("[8] open of %s succeeded should have been deleted on close !\n", fname); goto fail; correct = False; } else printf("eighth delete on close test succeeded.\n"); /* This should fail - we need to set DELETE_ACCESS. */ fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE); if (fnum1 != -1) { printf("[9] open of %s succeeded should have failed!\n", fname); correct = False; goto fail; } printf("ninth delete on close test succeeded.\n"); fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE); if (fnum1 == -1) { printf("[10] open of %s failed (%s)\n", fname, cli_errstr(&cli1)); correct = False; goto fail; } /* This should delete the file. */ if (!cli_close(&cli1, fnum1)) { printf("[10] close failed (%s)\n", cli_errstr(&cli1)); correct = False; goto fail; } /* This should fail.. */ fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE); if (fnum1 != -1) { printf("[10] open of %s succeeded should have been deleted on close !\n", fname); goto fail; correct = False; } else printf("tenth delete on close test succeeded.\n"); printf("finished delete test\n"); fail: cli_close(&cli1, fnum1); cli_close(&cli1, fnum2); cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); if (!torture_close_connection(&cli1)) { correct = False; } if (!torture_close_connection(&cli2)) { correct = False; } return correct; } /* print out server properties */ static BOOL run_properties(int dummy) { static struct cli_state cli; BOOL correct = True; printf("starting properties test\n"); ZERO_STRUCT(cli); if (!torture_open_connection(&cli)) { return False; } cli_sockopt(&cli, sockops); d_printf("Capabilities 0x%08x\n", cli.capabilities); if (!torture_close_connection(&cli)) { correct = False; } return correct; } /* FIRST_DESIRED_ACCESS 0xf019f */ #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\ FILE_READ_EA| /* 0xf */ \ FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \ FILE_WRITE_ATTRIBUTES| /* 0x100 */ \ DELETE_ACCESS|READ_CONTROL_ACCESS|\ WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */ /* SECOND_DESIRED_ACCESS 0xe0080 */ #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \ READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\ WRITE_OWNER_ACCESS /* 0xe0000 */ #if 0 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \ READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\ FILE_READ_DATA|\ WRITE_OWNER_ACCESS /* */ #endif /* Test ntcreate calls made by xcopy */ static BOOL run_xcopy(int dummy) { static struct cli_state cli1; const char *fname = "\\test.txt"; BOOL correct = True; int fnum1, fnum2; printf("starting xcopy test\n"); if (!torture_open_connection(&cli1)) { return False; } fnum1 = cli_nt_create_full(&cli1, fname, FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0x4044); if (fnum1 == -1) { printf("First open failed - %s\n", cli_errstr(&cli1)); return False; } fnum2 = cli_nt_create_full(&cli1, fname, SECOND_DESIRED_ACCESS, 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0x200000); if (fnum2 == -1) { printf("second open failed - %s\n", cli_errstr(&cli1)); return False; } if (!torture_close_connection(&cli1)) { correct = False; } return correct; } /* Test rename on files open with share delete and no share delete. */ static BOOL run_rename(int dummy) { static struct cli_state cli1; const char *fname = "\\test.txt"; const char *fname1 = "\\test1.txt"; BOOL correct = True; int fnum1; printf("starting rename test\n"); if (!torture_open_connection(&cli1)) { return False; } cli_unlink(&cli1, fname); cli_unlink(&cli1, fname1); fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("First open failed - %s\n", cli_errstr(&cli1)); return False; } if (!cli_rename(&cli1, fname, fname1)) { printf("First rename failed (this is correct) - %s\n", cli_errstr(&cli1)); } else { printf("First rename succeeded - this should have failed !\n"); correct = False; } if (!cli_close(&cli1, fnum1)) { printf("close - 1 failed (%s)\n", cli_errstr(&cli1)); return False; } cli_unlink(&cli1, fname); cli_unlink(&cli1, fname1); fnum1 = cli_nt_create_full(&cli1, fname,GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL, #if 0 FILE_SHARE_DELETE|FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); #else FILE_SHARE_DELETE|FILE_SHARE_READ, FILE_OVERWRITE_IF, 0); #endif if (fnum1 == -1) { printf("Second open failed - %s\n", cli_errstr(&cli1)); return False; } if (!cli_rename(&cli1, fname, fname1)) { printf("Second rename failed - this should have succeeded - %s\n", cli_errstr(&cli1)); correct = False; } else { printf("Second rename succeeded\n"); } if (!cli_close(&cli1, fnum1)) { printf("close - 2 failed (%s)\n", cli_errstr(&cli1)); return False; } cli_unlink(&cli1, fname); cli_unlink(&cli1, fname1); fnum1 = cli_nt_create_full(&cli1, fname,READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("Third open failed - %s\n", cli_errstr(&cli1)); return False; } #if 0 { int fnum2; fnum2 = cli_nt_create_full(&cli1, fname,DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum2 == -1) { printf("Fourth open failed - %s\n", cli_errstr(&cli1)); return False; } if (!cli_nt_delete_on_close(&cli1, fnum2, True)) { printf("[8] setting delete_on_close on file failed !\n"); return False; } if (!cli_close(&cli1, fnum2)) { printf("close - 4 failed (%s)\n", cli_errstr(&cli1)); return False; } } #endif if (!cli_rename(&cli1, fname, fname1)) { printf("Third rename failed - this should have succeeded - %s\n", cli_errstr(&cli1)); correct = False; } else { printf("Third rename succeeded\n"); } if (!cli_close(&cli1, fnum1)) { printf("close - 3 failed (%s)\n", cli_errstr(&cli1)); return False; } cli_unlink(&cli1, fname); cli_unlink(&cli1, fname1); if (!torture_close_connection(&cli1)) { correct = False; } return correct; } static BOOL run_pipe_number(int dummy) { static struct cli_state cli1; const char *pipe_name = "\\SPOOLSS"; int fnum; int num_pipes = 0; printf("starting pipenumber test\n"); if (!torture_open_connection(&cli1)) { return False; } cli_sockopt(&cli1, sockops); while(1) { fnum = cli_nt_create_full(&cli1, pipe_name,FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0); if (fnum == -1) { printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(&cli1)); break; } num_pipes++; } printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name ); torture_close_connection(&cli1); return True; } /* Test open mode returns on read-only files. */ static BOOL run_opentest(int dummy) { static struct cli_state cli1; static struct cli_state cli2; const char *fname = "\\readonly.file"; int fnum1, fnum2; char buf[20]; size_t fsize; BOOL correct = True; char *tmp_path; uint16 attr; printf("starting open test\n"); if (!torture_open_connection(&cli1)) { return False; } cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); cli_sockopt(&cli1, sockops); fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); if (fnum1 == -1) { printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli1, fnum1)) { printf("close2 failed (%s)\n", cli_errstr(&cli1)); return False; } if (!cli_setatr(&cli1, fname, aRONLY, 0)) { printf("cli_setatr failed (%s)\n", cli_errstr(&cli1)); return False; } fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE); if (fnum1 == -1) { printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */ fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL); if (check_error(__LINE__, &cli1, ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED)) { printf("correct error code ERRDOS/ERRnoaccess returned\n"); } printf("finished open test 1\n"); cli_close(&cli1, fnum1); /* Now try not readonly and ensure ERRbadshare is returned. */ cli_setatr(&cli1, fname, 0, 0); fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE); if (fnum1 == -1) { printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } /* This will fail - but the error should be ERRshare. */ fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL); if (check_error(__LINE__, &cli1, ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION)) { printf("correct error code ERRDOS/ERRbadshare returned\n"); } if (!cli_close(&cli1, fnum1)) { printf("close2 failed (%s)\n", cli_errstr(&cli1)); return False; } cli_unlink(&cli1, fname); printf("finished open test 2\n"); /* Test truncate open disposition on file opened for read. */ fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); if (fnum1 == -1) { printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } /* write 20 bytes. */ memset(buf, '\0', 20); if (cli_write(&cli1, fnum1, 0, buf, 0, 20) != 20) { printf("write failed (%s)\n", cli_errstr(&cli1)); correct = False; } if (!cli_close(&cli1, fnum1)) { printf("(3) close1 failed (%s)\n", cli_errstr(&cli1)); return False; } /* Ensure size == 20. */ if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) { printf("(3) getatr failed (%s)\n", cli_errstr(&cli1)); return False; } if (fsize != 20) { printf("(3) file size != 20\n"); return False; } /* Now test if we can truncate a file opened for readonly. */ fnum1 = cli_open(&cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE); if (fnum1 == -1) { printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli1, fnum1)) { printf("close2 failed (%s)\n", cli_errstr(&cli1)); return False; } /* Ensure size == 0. */ if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) { printf("(3) getatr failed (%s)\n", cli_errstr(&cli1)); return False; } if (fsize != 0) { printf("(3) file size != 0\n"); return False; } printf("finished open test 3\n"); cli_unlink(&cli1, fname); printf("testing ctemp\n"); fnum1 = cli_ctemp(&cli1, "\\", &tmp_path); if (fnum1 == -1) { printf("ctemp failed (%s)\n", cli_errstr(&cli1)); return False; } printf("ctemp gave path %s\n", tmp_path); if (!cli_close(&cli1, fnum1)) { printf("close of temp failed (%s)\n", cli_errstr(&cli1)); } if (!cli_unlink(&cli1, tmp_path)) { printf("unlink of temp failed (%s)\n", cli_errstr(&cli1)); } /* Test the non-io opens... */ if (!torture_open_connection(&cli2)) { return False; } cli_setatr(&cli2, fname, 0, 0); cli_unlink(&cli2, fname); cli_sockopt(&cli2, sockops); printf("TEST #1 testing 2 non-io opens (no delete)\n"); fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 1 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } fnum2 = cli_nt_create_full(&cli2, fname,FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OPEN_IF, 0); if (fnum2 == -1) { printf("test 1 open 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli2, fnum2)) { printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } printf("non-io open test #1 passed.\n"); cli_unlink(&cli1, fname); printf("TEST #2 testing 2 non-io opens (first with delete)\n"); fnum1 = cli_nt_create_full(&cli1, fname,DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 2 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } fnum2 = cli_nt_create_full(&cli2, fname,FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OPEN_IF, 0); if (fnum2 == -1) { printf("test 2 open 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli2, fnum2)) { printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } printf("non-io open test #2 passed.\n"); cli_unlink(&cli1, fname); printf("TEST #3 testing 2 non-io opens (second with delete)\n"); fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 3 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } fnum2 = cli_nt_create_full(&cli2, fname,DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OPEN_IF, 0); if (fnum2 == -1) { printf("test 3 open 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 3 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli2, fnum2)) { printf("test 3 close 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } printf("non-io open test #3 passed.\n"); cli_unlink(&cli1, fname); printf("TEST #4 testing 2 non-io opens (both with delete)\n"); fnum1 = cli_nt_create_full(&cli1, fname,DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 4 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } fnum2 = cli_nt_create_full(&cli2, fname,DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OPEN_IF, 0); if (fnum2 != -1) { printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(&cli2)); return False; } printf("test 3 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(&cli2), "sharing violation"); if (!cli_close(&cli1, fnum1)) { printf("test 4 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } printf("non-io open test #4 passed.\n"); cli_unlink(&cli1, fname); printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n"); fnum1 = cli_nt_create_full(&cli1, fname,DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 5 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } fnum2 = cli_nt_create_full(&cli2, fname,DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE, FILE_OPEN_IF, 0); if (fnum2 == -1) { printf("test 5 open 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 5 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli2, fnum2)) { printf("test 5 close 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } printf("non-io open test #5 passed.\n"); printf("TEST #6 testing 1 non-io open, one io open\n"); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 6 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } fnum2 = cli_nt_create_full(&cli2, fname,FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, 0); if (fnum2 == -1) { printf("test 6 open 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 6 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli2, fnum2)) { printf("test 6 close 2 of %s failed (%s)\n", fname, cli_errstr(&cli2)); return False; } printf("non-io open test #6 passed.\n"); printf("TEST #7 testing 1 non-io open, one io open with delete\n"); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 7 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } fnum2 = cli_nt_create_full(&cli2, fname,DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_OPEN_IF, 0); if (fnum2 != -1) { printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(&cli2)); return False; } printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(&cli2), "sharing violation"); if (!cli_close(&cli1, fnum1)) { printf("test 7 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } printf("non-io open test #7 passed.\n"); cli_unlink(&cli1, fname); /* Test 8 - attributes test #1... */ fnum1 = cli_nt_create_full(&cli1, fname,FILE_WRITE_DATA, FILE_ATTRIBUTE_HIDDEN, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 8 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 8 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } /* FILE_SUPERSEDE && FILE_OVERWRITE_IF have the same effect here. */ fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_DATA, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 8 open 2 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 8 close 2 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } /* This open should fail with ACCESS_DENIED for FILE_SUPERSEDE, FILE_OVERWRITE and FILE_OVERWRITE_IF. */ fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE, 0); if (fnum1 != -1) { printf("test 8 open 3 of %s succeeded - should have failed with (NT_STATUS_ACCESS_DENIED)\n", fname); correct = False; cli_close(&cli1, fnum1); } else { if (check_error(__LINE__, &cli1, ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED)) { printf("correct error code NT_STATUS_ACCESS_DENIED/ERRDOS:ERRnoaccess returned\n"); } } printf("Attribute open test #8 %s.\n", correct ? "passed" : "failed"); cli_unlink(&cli1, fname); /* * Test #9. Open with NORMAL, close, then re-open with attribute * HIDDEN and request to truncate. */ fnum1 = cli_nt_create_full(&cli1, fname,FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("test 9 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 9 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_DATA|FILE_WRITE_DATA, FILE_ATTRIBUTE_HIDDEN, FILE_SHARE_NONE, FILE_OVERWRITE, 0); if (fnum1 == -1) { printf("test 9 open 2 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli1, fnum1)) { printf("test 9 close 2 of %s failed (%s)\n", fname, cli_errstr(&cli1)); return False; } /* Ensure we have attr hidden. */ if (!cli_getatr(&cli1, fname, &attr, NULL, NULL)) { printf("test 9 getatr(2) failed (%s)\n", cli_errstr(&cli1)); return False; } if (!(attr & FILE_ATTRIBUTE_HIDDEN)) { printf("test 9 getatr didn't have HIDDEN attribute\n"); cli_unlink(&cli1, fname); return False; } printf("Attribute open test #9 %s.\n", correct ? "passed" : "failed"); cli_unlink(&cli1, fname); if (!torture_close_connection(&cli1)) { correct = False; } if (!torture_close_connection(&cli2)) { correct = False; } return correct; } static uint32 initial_open_attrs[] = { FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_SYSTEM }; static uint32 trunc_open_attrs[] = { FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM }; struct trunc_open_results { uint32 nt_error_code; uint32 trunc_result_attr; }; #if 0 statuc struct trunc_open_results attr_results[] = { {NT_STATUS_OK, FILE_ATTRIBUTE_NORMAL}, } #endif static BOOL run_openattrtest(int dummy) { static struct cli_state cli1; const char *fname = "\\openattr.file"; int fnum1; BOOL correct = True; uint16 attr; int i, j; printf("starting open attr test\n"); if (!torture_open_connection(&cli1)) { return False; } cli_sockopt(&cli1, sockops); for (i = 0; i < sizeof(initial_open_attrs)/sizeof(uint32); i++) { cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); fnum1 = cli_nt_create_full(&cli1, fname,FILE_WRITE_DATA, initial_open_attrs[i], FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0); if (fnum1 == -1) { printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(&cli1)); return False; } if (!cli_close(&cli1, fnum1)) { printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(&cli1)); return False; } for (j = 0; j < sizeof(trunc_open_attrs)/sizeof(uint32); j++) { fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_DATA|FILE_WRITE_DATA, trunc_open_attrs[j], FILE_SHARE_NONE, FILE_OVERWRITE, 0); if (fnum1 == -1) { printf("open %d (2) of %s failed (%u:%s)\n", j, fname, 0, cli_errstr(&cli1)); continue; } if (!cli_close(&cli1, fnum1)) { printf("close %d (2) of %s failed (%s)\n", j, fname, cli_errstr(&cli1)); return False; } if (!cli_getatr(&cli1, fname, &attr, NULL, NULL)) { printf("test 9 getatr(2) failed (%s)\n", cli_errstr(&cli1)); return False; } printf("getatr [%x] trunc [%x] got attribute %x\n", initial_open_attrs[i], trunc_open_attrs[j], (unsigned int)attr); } } cli_setatr(&cli1, fname, 0, 0); cli_unlink(&cli1, fname); printf("open attr test %s.\n", correct ? "passed" : "failed"); if (!torture_close_connection(&cli1)) { correct = False; } return correct; } static void list_fn(file_info *finfo, const char *name, void *state) { } /* test directory listing speed */ static BOOL run_dirtest(int dummy) { int i; static struct cli_state cli; int fnum; double t1; BOOL correct = True; printf("starting directory test\n"); if (!torture_open_connection(&cli)) { return False; } cli_sockopt(&cli, sockops); srandom(0); for (i=0;iname); if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0) return; if (finfo->mode & aDIR) { if (!cli_rmdir(pcli, fname)) printf("del_fn: failed to rmdir %s\n,", fname ); } else { if (!cli_unlink(pcli, fname)) printf("del_fn: failed to unlink %s\n,", fname ); } } static BOOL run_dirtest1(int dummy) { int i; static struct cli_state cli; int fnum, num_seen; BOOL correct = True; printf("starting directory test\n"); if (!torture_open_connection(&cli)) { return False; } cli_sockopt(&cli, sockops); cli_list(&cli, "\\LISTDIR\\*", 0, del_fn, &cli); cli_list(&cli, "\\LISTDIR\\*", aDIR, del_fn, &cli); cli_rmdir(&cli, "\\LISTDIR"); cli_mkdir(&cli, "\\LISTDIR"); /* Create 1000 files and 1000 directories. */ for (i=0;i<1000;i++) { fstring fname; slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i); fnum = cli_nt_create_full(&cli, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0); if (fnum == -1) { fprintf(stderr,"Failed to open %s\n", fname); return False; } cli_close(&cli, fnum); } for (i=0;i<1000;i++) { fstring fname; slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i); if (!cli_mkdir(&cli, fname)) { fprintf(stderr,"Failed to open %s\n", fname); return False; } } /* Now ensure that doing an old list sees both files and directories. */ num_seen = cli_list_old(&cli, "\\LISTDIR\\*", aDIR, list_fn, NULL); printf("num_seen = %d\n", num_seen ); /* We should see 100 files + 1000 directories + . and .. */ if (num_seen != 2002) correct = False; /* Ensure if we have the "must have" bits we only see the * relevent entries. */ num_seen = cli_list_old(&cli, "\\LISTDIR\\*", (aDIR<<8)|aDIR, list_fn, NULL); printf("num_seen = %d\n", num_seen ); if (num_seen != 1002) correct = False; num_seen = cli_list_old(&cli, "\\LISTDIR\\*", (aARCH<<8)|aDIR, list_fn, NULL); printf("num_seen = %d\n", num_seen ); if (num_seen != 1000) correct = False; /* Delete everything. */ cli_list(&cli, "\\LISTDIR\\*", 0, del_fn, &cli); cli_list(&cli, "\\LISTDIR\\*", aDIR, del_fn, &cli); cli_rmdir(&cli, "\\LISTDIR"); #if 0 printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn, NULL)); printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn, NULL)); printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn, NULL)); #endif if (!torture_close_connection(&cli)) { correct = False; } printf("finished dirtest1\n"); return correct; } static BOOL run_error_map_extract(int dummy) { static struct cli_state c_dos; static struct cli_state c_nt; uint32 error; uint32 flgs2, errnum; uint8 errclass; NTSTATUS nt_status; fstring user; /* NT-Error connection */ if (!open_nbt_connection(&c_nt)) { return False; } c_nt.use_spnego = False; if (!cli_negprot(&c_nt)) { printf("%s rejected the NT-error negprot (%s)\n",host, cli_errstr(&c_nt)); cli_shutdown(&c_nt); return False; } if (!cli_session_setup(&c_nt, "", "", 0, "", 0, workgroup)) { printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(&c_nt)); return False; } /* DOS-Error connection */ if (!open_nbt_connection(&c_dos)) { return False; } c_dos.use_spnego = False; c_dos.force_dos_errors = True; if (!cli_negprot(&c_dos)) { printf("%s rejected the DOS-error negprot (%s)\n",host, cli_errstr(&c_dos)); cli_shutdown(&c_dos); return False; } if (!cli_session_setup(&c_dos, "", "", 0, "", 0, workgroup)) { printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(&c_dos)); return False; } for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) { snprintf(user, sizeof(user), "%X", error); if (cli_session_setup(&c_nt, user, password, strlen(password), password, strlen(password), workgroup)) { printf("/** Session setup succeeded. This shouldn't happen...*/\n"); } flgs2 = SVAL(c_nt.inbuf,smb_flg2); /* Case #1: 32-bit NT errors */ if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) { nt_status = NT_STATUS(IVAL(c_nt.inbuf,smb_rcls)); } else { printf("/** Dos error on NT connection! (%s) */\n", cli_errstr(&c_nt)); nt_status = NT_STATUS(0xc0000000); } if (cli_session_setup(&c_dos, user, password, strlen(password), password, strlen(password), workgroup)) { printf("/** Session setup succeeded. This shouldn't happen...*/\n"); } flgs2 = SVAL(c_dos.inbuf,smb_flg2), errnum; /* Case #1: 32-bit NT errors */ if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) { printf("/** NT error on DOS connection! (%s) */\n", cli_errstr(&c_nt)); errnum = errclass = 0; } else { cli_dos_error(&c_dos, &errclass, &errnum); } if (NT_STATUS_V(nt_status) != error) { printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", get_nt_error_c_code(NT_STATUS(error)), get_nt_error_c_code(nt_status)); } printf("\t{%s,\t%s,\t%s},\n", smb_dos_err_class(errclass), smb_dos_err_name(errclass, errnum), get_nt_error_c_code(NT_STATUS(error))); } return True; } static double create_procs(BOOL (*fn)(int), BOOL *result) { int i, status; volatile pid_t *child_status; volatile BOOL *child_status_out; int synccount; int tries = 8; synccount = 0; child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs); if (!child_status) { printf("Failed to setup shared memory\n"); return -1; } child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*nprocs); if (!child_status_out) { printf("Failed to setup result status shared memory\n"); return -1; } for (i = 0; i < nprocs; i++) { child_status[i] = 0; child_status_out[i] = True; } start_timer(); for (i=0;i TEST1 TEST2 ...\n"); printf("\t-d debuglevel\n"); printf("\t-U user%%pass\n"); printf("\t-k use kerberos\n"); printf("\t-N numprocs\n"); printf("\t-n my_netbios_name\n"); printf("\t-W workgroup\n"); printf("\t-o num_operations\n"); printf("\t-O socket_options\n"); printf("\t-m maximum protocol\n"); printf("\t-L use oplocks\n"); printf("\t-c CLIENT.TXT specify client load file for NBENCH\n"); printf("\t-A showall\n"); printf("\t-s seed\n"); printf("\n\n"); printf("tests are:"); for (i=0;torture_ops[i].name;i++) { printf(" %s", torture_ops[i].name); } printf("\n"); printf("default test is ALL\n"); exit(1); } /**************************************************************************** main program ****************************************************************************/ int main(int argc,char *argv[]) { int opt, i; char *p; int gotpass = 0; extern char *optarg; extern int optind; BOOL correct = True; dbf = x_stdout; #ifdef HAVE_SETBUFFER setbuffer(stdout, NULL, 0); #endif lp_load(dyn_CONFIGFILE,True,False,False); load_interfaces(); if (argc < 2) { usage(); } for(p = argv[1]; *p; p++) if(*p == '\\') *p = '/'; if (strncmp(argv[1], "//", 2)) { usage(); } fstrcpy(host, &argv[1][2]); p = strchr_m(&host[2],'/'); if (!p) { usage(); } *p = 0; fstrcpy(share, p+1); get_myname(myname); if (*username == 0 && getenv("LOGNAME")) { fstrcpy(username,getenv("LOGNAME")); } argc--; argv++; srandom(time(NULL)); fstrcpy(workgroup, lp_workgroup()); while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:Ld:Ac:ks:")) != EOF) { switch (opt) { case 's': srandom(atoi(optarg)); break; case 'W': fstrcpy(workgroup,optarg); break; case 'm': max_protocol = interpret_protocol(optarg, max_protocol); break; case 'N': nprocs = atoi(optarg); break; case 'o': torture_numops = atoi(optarg); break; case 'd': DEBUGLEVEL = atoi(optarg); break; case 'O': sockops = optarg; break; case 'L': use_oplocks = True; break; case 'A': torture_showall = True; break; case 'n': fstrcpy(myname, optarg); break; case 'c': client_txt = optarg; break; case 'k': #ifdef HAVE_KRB5 use_kerberos = True; gotpass = True; #else d_printf("No kerberos support compiled in\n"); exit(1); #endif break; case 'U': fstrcpy(username,optarg); p = strchr_m(username,'%'); if (p) { *p = 0; fstrcpy(password, p+1); gotpass = 1; } break; default: printf("Unknown option %c (%d)\n", (char)opt, opt); usage(); } } while (!gotpass) { p = getpass("Password:"); if (p) { fstrcpy(password, p); gotpass = 1; } } printf("host=%s share=%s user=%s myname=%s\n", host, share, username, myname); if (argc == 1) { correct = run_test("ALL"); } else { for (i=1;i