summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1997-11-01 13:22:16 +0000
committerAndrew Tridgell <tridge@samba.org>1997-11-01 13:22:16 +0000
commit224c40a52335bf1afc7662183900e143307aa5be (patch)
treec137653f344bf5e3f0e9f78745144c03eb367119
parent00247250052d0f7b76b0478eb08f63844cd13dc5 (diff)
downloadsamba-224c40a52335bf1afc7662183900e143307aa5be.tar.gz
samba-224c40a52335bf1afc7662183900e143307aa5be.tar.bz2
samba-224c40a52335bf1afc7662183900e143307aa5be.zip
a simple SMB torture tester. This will allow us to evaluate locking
techniques more accurately. (This used to be commit 054e3b2ae3a8cfb98fde72becef9b05de34d2ba7)
-rw-r--r--source3/client/client.c2
-rw-r--r--source3/client/clientutil.c154
-rw-r--r--source3/include/proto.h17
-rw-r--r--source3/libsmb/clientgen.c334
-rw-r--r--source3/libsmb/smberr.c182
-rw-r--r--source3/nmbsync.c5
-rw-r--r--source3/smbd/password.c5
-rw-r--r--source3/utils/torture.c316
8 files changed, 847 insertions, 168 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index 6528919051..f1ab4410a9 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -1102,7 +1102,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1)
cli_setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,0xFF);
- SSVAL(outbuf,smb_vwv2,1);
+ SSVAL(outbuf,smb_vwv2,1); /* return additional info */
SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
diff --git a/source3/client/clientutil.c b/source3/client/clientutil.c
index d05be8ae9b..8924e692aa 100644
--- a/source3/client/clientutil.c
+++ b/source3/client/clientutil.c
@@ -943,157 +943,3 @@ BOOL cli_reopen_connection(char *inbuf,char *outbuf)
return(cli_send_login(inbuf,outbuf,True,True));
}
-/* error code stuff - put together by Merik Karman
- merik@blackadder.dsh.oz.au */
-
-typedef struct
-{
- char *name;
- int code;
- char *message;
-} err_code_struct;
-
-/* Dos Error Messages */
-err_code_struct dos_msgs[] = {
- {"ERRbadfunc",1,"Invalid function."},
- {"ERRbadfile",2,"File not found."},
- {"ERRbadpath",3,"Directory invalid."},
- {"ERRnofids",4,"No file descriptors available"},
- {"ERRnoaccess",5,"Access denied."},
- {"ERRbadfid",6,"Invalid file handle."},
- {"ERRbadmcb",7,"Memory control blocks destroyed."},
- {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
- {"ERRbadmem",9,"Invalid memory block address."},
- {"ERRbadenv",10,"Invalid environment."},
- {"ERRbadformat",11,"Invalid format."},
- {"ERRbadaccess",12,"Invalid open mode."},
- {"ERRbaddata",13,"Invalid data."},
- {"ERR",14,"reserved."},
- {"ERRbaddrive",15,"Invalid drive specified."},
- {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
- {"ERRdiffdevice",17,"Not same device."},
- {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
- {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
- {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
- {"ERRnosuchshare", 67, "You specified an invalid share name"},
- {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
- {"ERRbadpipe",230,"Pipe invalid."},
- {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
- {"ERRpipeclosing",232,"Pipe close in progress."},
- {"ERRnotconnected",233,"No process on other end of pipe."},
- {"ERRmoredata",234,"There is more data to be returned."},
- {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
- {NULL,-1,NULL}};
-
-/* Server Error Messages */
-err_code_struct server_msgs[] = {
- {"ERRerror",1,"Non-specific error code."},
- {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
- {"ERRbadtype",3,"reserved."},
- {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
- {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
- {"ERRinvnetname",6,"Invalid network name in tree connect."},
- {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
- {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
- {"ERRqtoobig",50,"Print queue full -- no space."},
- {"ERRqeof",51,"EOF on print queue dump."},
- {"ERRinvpfid",52,"Invalid print file FID."},
- {"ERRsmbcmd",64,"The server did not recognize the command received."},
- {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
- {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
- {"ERRreserved",68,"reserved."},
- {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
- {"ERRreserved",70,"reserved."},
- {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
- {"ERRpaused",81,"Server is paused."},
- {"ERRmsgoff",82,"Not receiving messages."},
- {"ERRnoroom",83,"No room to buffer message."},
- {"ERRrmuns",87,"Too many remote user names."},
- {"ERRtimeout",88,"Operation timed out."},
- {"ERRnoresource",89,"No resources currently available for request."},
- {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
- {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
- {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
- {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
- {"ERRcontmpx",252,"Continue in MPX mode."},
- {"ERRreserved",253,"reserved."},
- {"ERRreserved",254,"reserved."},
- {"ERRnosupport",0xFFFF,"Function not supported."},
- {NULL,-1,NULL}};
-
-/* Hard Error Messages */
-err_code_struct hard_msgs[] = {
- {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
- {"ERRbadunit",20,"Unknown unit."},
- {"ERRnotready",21,"Drive not ready."},
- {"ERRbadcmd",22,"Unknown command."},
- {"ERRdata",23,"Data error (CRC)."},
- {"ERRbadreq",24,"Bad request structure length."},
- {"ERRseek",25 ,"Seek error."},
- {"ERRbadmedia",26,"Unknown media type."},
- {"ERRbadsector",27,"Sector not found."},
- {"ERRnopaper",28,"Printer out of paper."},
- {"ERRwrite",29,"Write fault."},
- {"ERRread",30,"Read fault."},
- {"ERRgeneral",31,"General failure."},
- {"ERRbadshare",32,"An open conflicts with an existing open."},
- {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
- {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
- {"ERRFCBUnavail",35,"No FCBs are available to process request."},
- {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
- {NULL,-1,NULL}};
-
-
-struct
-{
- int code;
- char *class;
- err_code_struct *err_msgs;
-} err_classes[] = {
- {0,"SUCCESS",NULL},
- {0x01,"ERRDOS",dos_msgs},
- {0x02,"ERRSRV",server_msgs},
- {0x03,"ERRHRD",hard_msgs},
- {0x04,"ERRXOS",NULL},
- {0xE1,"ERRRMX1",NULL},
- {0xE2,"ERRRMX2",NULL},
- {0xE3,"ERRRMX3",NULL},
- {0xFF,"ERRCMD",NULL},
- {-1,NULL,NULL}};
-
-
-/****************************************************************************
-return a SMB error string from a SMB buffer
-****************************************************************************/
-char *smb_errstr(char *inbuf)
-{
- static pstring ret;
- int class = CVAL(inbuf,smb_rcls);
- int num = SVAL(inbuf,smb_err);
- int i,j;
-
- for (i=0;err_classes[i].class;i++)
- if (err_classes[i].code == class)
- {
- if (err_classes[i].err_msgs)
- {
- err_code_struct *err = err_classes[i].err_msgs;
- for (j=0;err[j].name;j++)
- if (num == err[j].code)
- {
- if (DEBUGLEVEL > 0)
- sprintf(ret,"%s - %s (%s)",err_classes[i].class,
- err[j].name,err[j].message);
- else
- sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
- return ret;
- }
- }
-
- sprintf(ret,"%s - %d",err_classes[i].class,num);
- return ret;
- }
-
- sprintf(ret,"Error: Unknown error (%d,%d)",class,num);
- return(ret);
-}
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 949d2472a9..7e4ed43aa0 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -51,14 +51,24 @@ BOOL cli_session_setup(struct cli_state *cli,
char *ntpass, int ntpasslen,
char *workgroup);
BOOL cli_send_tconX(struct cli_state *cli,
- char *share, char *dev, char *pword, int passlen);
+ char *share, char *dev, char *pass, int passlen);
BOOL cli_tdis(struct cli_state *cli);
+BOOL cli_unlink(struct cli_state *cli, char *fname);
+int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode);
+BOOL cli_close(struct cli_state *cli, int fnum);
+BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout);
+BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout);
+int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size);
+int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size);
BOOL cli_negprot(struct cli_state *cli);
BOOL cli_session_request(struct cli_state *cli, char *host, int name_type,
char *myname);
BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip);
BOOL cli_initialise(struct cli_state *cli);
void cli_shutdown(struct cli_state *cli);
+char *cli_errstr(struct cli_state *cli);
+void cli_error(struct cli_state *cli, int *eclass, int *num);
+void cli_sockopt(struct cli_state *cli, char *options);
/*The following definitions come from clientutil.c */
@@ -81,7 +91,6 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup);
void cli_send_logout(void );
BOOL cli_open_sockets(int port );
BOOL cli_reopen_connection(char *inbuf,char *outbuf);
-char *smb_errstr(char *inbuf);
/*The following definitions come from clitar.c */
@@ -1030,6 +1039,10 @@ void E_md4hash(uchar *passwd, uchar *p16);
void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24);
void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16);
+/*The following definitions come from smberr.c */
+
+char *smb_errstr(char *inbuf);
+
/*The following definitions come from smbpass.c */
int pw_file_lock(char *name, int type, int secs);
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index b6ad1611ac..b2ecb07ded 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -502,14 +502,29 @@ BOOL cli_session_setup(struct cli_state *cli,
send a tconX
****************************************************************************/
BOOL cli_send_tconX(struct cli_state *cli,
- char *share, char *dev, char *pword, int passlen)
+ char *share, char *dev, char *pass, int passlen)
{
+ fstring fullshare, pword;
char *p;
bzero(cli->outbuf,smb_size);
bzero(cli->inbuf,smb_size);
+ if (cli->sec_mode & 1) {
+ passlen = 1;
+ pass = "";
+ }
+
+ if ((cli->sec_mode & 2) && *pass && passlen != 24) {
+ passlen = 24;
+ SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
+ } else {
+ memcpy(pword, pass, passlen);
+ }
+
+ sprintf(fullshare, "\\\\%s\\%s", cli->desthost, share);
+
set_message(cli->outbuf,4,
- 2 + strlen(share) + passlen + strlen(dev),True);
+ 2 + strlen(fullshare) + passlen + strlen(dev),True);
CVAL(cli->outbuf,smb_com) = SMBtconX;
cli_setup_packet(cli);
@@ -519,7 +534,7 @@ BOOL cli_send_tconX(struct cli_state *cli,
p = smb_buf(cli->outbuf);
memcpy(p,pword,passlen);
p += passlen;
- strcpy(p,share);
+ strcpy(p,fullshare);
p = skip_string(p,1);
strcpy(p,dev);
@@ -556,6 +571,294 @@ BOOL cli_tdis(struct cli_state *cli)
return CVAL(cli->inbuf,smb_rcls) == 0;
}
+/****************************************************************************
+delete a file
+****************************************************************************/
+BOOL cli_unlink(struct cli_state *cli, char *fname)
+{
+ char *p;
+
+ bzero(cli->outbuf,smb_size);
+ bzero(cli->inbuf,smb_size);
+
+ set_message(cli->outbuf,1, 2 + strlen(fname),True);
+
+ CVAL(cli->outbuf,smb_com) = SMBunlink;
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
+
+ p = smb_buf(cli->outbuf);
+ *p++ = 4;
+ strcpy(p,fname);
+ p = skip_string(p,1);
+
+ send_smb(cli->fd,cli->outbuf);
+ if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
+ return False;
+ }
+
+ if (CVAL(cli->inbuf,smb_rcls) != 0) {
+ return False;
+ }
+
+ return True;
+}
+
+
+
+/****************************************************************************
+open a file
+****************************************************************************/
+int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
+{
+ char *p;
+ unsigned openfn=0;
+ unsigned accessmode=0;
+
+ if (flags & O_CREAT)
+ openfn |= (1<<4);
+ if (!(flags & O_EXCL)) {
+ if (flags & O_TRUNC)
+ openfn |= (1<<1);
+ else
+ openfn |= (1<<0);
+ }
+
+ accessmode = (share_mode<<4);
+
+ if ((flags & O_RDWR) == O_RDWR) {
+ accessmode |= 2;
+ } else if ((flags & O_WRONLY) == O_WRONLY) {
+ accessmode |= 1;
+ }
+
+ bzero(cli->outbuf,smb_size);
+ bzero(cli->inbuf,smb_size);
+
+ set_message(cli->outbuf,15,1 + strlen(fname),True);
+
+ CVAL(cli->outbuf,smb_com) = SMBopenX;
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ SSVAL(cli->outbuf,smb_vwv0,0xFF);
+ SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
+ SSVAL(cli->outbuf,smb_vwv3,accessmode);
+ SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
+ SSVAL(cli->outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
+ SSVAL(cli->outbuf,smb_vwv8,openfn);
+
+ p = smb_buf(cli->outbuf);
+ strcpy(p,fname);
+ p = skip_string(p,1);
+
+ send_smb(cli->fd,cli->outbuf);
+ if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
+ return -1;
+ }
+
+ if (CVAL(cli->inbuf,smb_rcls) != 0) {
+ return -1;
+ }
+
+ return SVAL(cli->inbuf,smb_vwv2);
+}
+
+
+
+
+/****************************************************************************
+ close a file
+****************************************************************************/
+BOOL cli_close(struct cli_state *cli, int fnum)
+{
+ bzero(cli->outbuf,smb_size);
+ bzero(cli->inbuf,smb_size);
+
+ set_message(cli->outbuf,3,0,True);
+
+ CVAL(cli->outbuf,smb_com) = SMBclose;
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ SSVAL(cli->outbuf,smb_vwv0,fnum);
+ SSVAL(cli->outbuf,smb_vwv1,0);
+ SSVAL(cli->outbuf,smb_vwv2,0);
+
+ send_smb(cli->fd,cli->outbuf);
+ if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
+ return False;
+ }
+
+ if (CVAL(cli->inbuf,smb_rcls) != 0) {
+ return False;
+ }
+
+ return True;
+}
+
+
+/****************************************************************************
+ lock a file
+****************************************************************************/
+BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
+{
+ char *p;
+
+ bzero(cli->outbuf,smb_size);
+ bzero(cli->inbuf,smb_size);
+
+ set_message(cli->outbuf,8,10,True);
+
+ CVAL(cli->outbuf,smb_com) = SMBlockingX;
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ CVAL(cli->outbuf,smb_vwv0) = 0xFF;
+ SSVAL(cli->outbuf,smb_vwv2,fnum);
+ CVAL(cli->outbuf,smb_vwv3) = 0;
+ SIVALS(cli->outbuf, smb_vwv4, timeout);
+ SSVAL(cli->outbuf,smb_vwv6,0);
+ SSVAL(cli->outbuf,smb_vwv7,1);
+
+ p = smb_buf(cli->outbuf);
+ SSVAL(p, 0, cli->pid);
+ SIVAL(p, 2, offset);
+ SIVAL(p, 6, len);
+
+ send_smb(cli->fd,cli->outbuf);
+ if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
+ return False;
+ }
+
+ if (CVAL(cli->inbuf,smb_rcls) != 0) {
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
+ unlock a file
+****************************************************************************/
+BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
+{
+ char *p;
+
+ bzero(cli->outbuf,smb_size);
+ bzero(cli->inbuf,smb_size);
+
+ set_message(cli->outbuf,8,10,True);
+
+ CVAL(cli->outbuf,smb_com) = SMBlockingX;
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ CVAL(cli->outbuf,smb_vwv0) = 0xFF;
+ SSVAL(cli->outbuf,smb_vwv2,fnum);
+ CVAL(cli->outbuf,smb_vwv3) = 0;
+ SIVALS(cli->outbuf, smb_vwv4, timeout);
+ SSVAL(cli->outbuf,smb_vwv6,1);
+ SSVAL(cli->outbuf,smb_vwv7,0);
+
+ p = smb_buf(cli->outbuf);
+ SSVAL(p, 0, cli->pid);
+ SIVAL(p, 2, offset);
+ SIVAL(p, 6, len);
+
+ send_smb(cli->fd,cli->outbuf);
+ if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
+ return False;
+ }
+
+ if (CVAL(cli->inbuf,smb_rcls) != 0) {
+ return False;
+ }
+
+ return True;
+}
+
+
+/****************************************************************************
+ read from a file
+****************************************************************************/
+int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
+{
+ char *p;
+
+ bzero(cli->outbuf,smb_size);
+ bzero(cli->inbuf,smb_size);
+
+ set_message(cli->outbuf,10,0,True);
+
+ CVAL(cli->outbuf,smb_com) = SMBreadX;
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ CVAL(cli->outbuf,smb_vwv0) = 0xFF;
+ SSVAL(cli->outbuf,smb_vwv2,fnum);
+ SIVAL(cli->outbuf,smb_vwv3,offset);
+ SSVAL(cli->outbuf,smb_vwv5,size);
+ SSVAL(cli->outbuf,smb_vwv6,size);
+
+ send_smb(cli->fd,cli->outbuf);
+ if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
+ return -1;
+ }
+
+ if (CVAL(cli->inbuf,smb_rcls) != 0) {
+ return -1;
+ }
+
+ size = SVAL(cli->inbuf, smb_vwv5);
+ p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
+
+ memcpy(buf, p, size);
+
+ return size;
+}
+
+
+/****************************************************************************
+ write to a file
+****************************************************************************/
+int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
+{
+ char *p;
+
+ bzero(cli->outbuf,smb_size);
+ bzero(cli->inbuf,smb_size);
+
+ set_message(cli->outbuf,12,size,True);
+
+ CVAL(cli->outbuf,smb_com) = SMBwriteX;
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ CVAL(cli->outbuf,smb_vwv0) = 0xFF;
+ SSVAL(cli->outbuf,smb_vwv2,fnum);
+ SIVAL(cli->outbuf,smb_vwv3,offset);
+
+ SSVAL(cli->outbuf,smb_vwv10,size);
+ SSVAL(cli->outbuf,smb_vwv11,smb_buf(cli->outbuf) - smb_base(cli->outbuf));
+
+ p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
+ memcpy(p, buf, size);
+
+ send_smb(cli->fd,cli->outbuf);
+ if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
+ return -1;
+ }
+
+ if (CVAL(cli->inbuf,smb_rcls) != 0) {
+ return -1;
+ }
+
+ return SVAL(cli->inbuf, smb_vwv2);
+}
+
/****************************************************************************
send a negprot command
@@ -744,3 +1047,28 @@ void cli_shutdown(struct cli_state *cli)
if (cli->fd != -1) close(cli->fd);
memset(cli, 0, sizeof(*cli));
}
+
+/****************************************************************************
+ return a description of the error
+****************************************************************************/
+char *cli_errstr(struct cli_state *cli)
+{
+ return smb_errstr(cli->inbuf);
+}
+
+/****************************************************************************
+ return error codes for the last packet
+****************************************************************************/
+void cli_error(struct cli_state *cli, int *eclass, int *num)
+{
+ *eclass = CVAL(cli->inbuf,smb_rcls);
+ *num = SVAL(cli->inbuf,smb_err);
+}
+
+/****************************************************************************
+set socket options on a open connection
+****************************************************************************/
+void cli_sockopt(struct cli_state *cli, char *options)
+{
+ set_socket_options(cli->fd, options);
+}
diff --git a/source3/libsmb/smberr.c b/source3/libsmb/smberr.c
new file mode 100644
index 0000000000..5149568c04
--- /dev/null
+++ b/source3/libsmb/smberr.c
@@ -0,0 +1,182 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Copyright (C) Andrew Tridgell 1997
+
+ 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.
+*/
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/* error code stuff - put together by Merik Karman
+ merik@blackadder.dsh.oz.au */
+
+typedef struct
+{
+ char *name;
+ int code;
+ char *message;
+} err_code_struct;
+
+/* Dos Error Messages */
+err_code_struct dos_msgs[] = {
+ {"ERRbadfunc",1,"Invalid function."},
+ {"ERRbadfile",2,"File not found."},
+ {"ERRbadpath",3,"Directory invalid."},
+ {"ERRnofids",4,"No file descriptors available"},
+ {"ERRnoaccess",5,"Access denied."},
+ {"ERRbadfid",6,"Invalid file handle."},
+ {"ERRbadmcb",7,"Memory control blocks destroyed."},
+ {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
+ {"ERRbadmem",9,"Invalid memory block address."},
+ {"ERRbadenv",10,"Invalid environment."},
+ {"ERRbadformat",11,"Invalid format."},
+ {"ERRbadaccess",12,"Invalid open mode."},
+ {"ERRbaddata",13,"Invalid data."},
+ {"ERR",14,"reserved."},
+ {"ERRbaddrive",15,"Invalid drive specified."},
+ {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
+ {"ERRdiffdevice",17,"Not same device."},
+ {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
+ {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
+ {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRnosuchshare", 67, "You specified an invalid share name"},
+ {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
+ {"ERRbadpipe",230,"Pipe invalid."},
+ {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
+ {"ERRpipeclosing",232,"Pipe close in progress."},
+ {"ERRnotconnected",233,"No process on other end of pipe."},
+ {"ERRmoredata",234,"There is more data to be returned."},
+ {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
+ {NULL,-1,NULL}};
+
+/* Server Error Messages */
+err_code_struct server_msgs[] = {
+ {"ERRerror",1,"Non-specific error code."},
+ {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
+ {"ERRbadtype",3,"reserved."},
+ {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
+ {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
+ {"ERRinvnetname",6,"Invalid network name in tree connect."},
+ {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
+ {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
+ {"ERRqtoobig",50,"Print queue full -- no space."},
+ {"ERRqeof",51,"EOF on print queue dump."},
+ {"ERRinvpfid",52,"Invalid print file FID."},
+ {"ERRsmbcmd",64,"The server did not recognize the command received."},
+ {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
+ {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
+ {"ERRreserved",68,"reserved."},
+ {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
+ {"ERRreserved",70,"reserved."},
+ {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
+ {"ERRpaused",81,"Server is paused."},
+ {"ERRmsgoff",82,"Not receiving messages."},
+ {"ERRnoroom",83,"No room to buffer message."},
+ {"ERRrmuns",87,"Too many remote user names."},
+ {"ERRtimeout",88,"Operation timed out."},
+ {"ERRnoresource",89,"No resources currently available for request."},
+ {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
+ {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
+ {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
+ {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
+ {"ERRcontmpx",252,"Continue in MPX mode."},
+ {"ERRreserved",253,"reserved."},
+ {"ERRreserved",254,"reserved."},
+ {"ERRnosupport",0xFFFF,"Function not supported."},
+ {NULL,-1,NULL}};
+
+/* Hard Error Messages */
+err_code_struct hard_msgs[] = {
+ {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
+ {"ERRbadunit",20,"Unknown unit."},
+ {"ERRnotready",21,"Drive not ready."},
+ {"ERRbadcmd",22,"Unknown command."},
+ {"ERRdata",23,"Data error (CRC)."},
+ {"ERRbadreq",24,"Bad request structure length."},
+ {"ERRseek",25 ,"Seek error."},
+ {"ERRbadmedia",26,"Unknown media type."},
+ {"ERRbadsector",27,"Sector not found."},
+ {"ERRnopaper",28,"Printer out of paper."},
+ {"ERRwrite",29,"Write fault."},
+ {"ERRread",30,"Read fault."},
+ {"ERRgeneral",31,"General failure."},
+ {"ERRbadshare",32,"An open conflicts with an existing open."},
+ {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
+ {"ERRFCBUnavail",35,"No FCBs are available to process request."},
+ {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
+ {NULL,-1,NULL}};
+
+
+struct
+{
+ int code;
+ char *class;
+ err_code_struct *err_msgs;
+} err_classes[] = {
+ {0,"SUCCESS",NULL},
+ {0x01,"ERRDOS",dos_msgs},
+ {0x02,"ERRSRV",server_msgs},
+ {0x03,"ERRHRD",hard_msgs},
+ {0x04,"ERRXOS",NULL},
+ {0xE1,"ERRRMX1",NULL},
+ {0xE2,"ERRRMX2",NULL},
+ {0xE3,"ERRRMX3",NULL},
+ {0xFF,"ERRCMD",NULL},
+ {-1,NULL,NULL}};
+
+
+/****************************************************************************
+return a SMB error string from a SMB buffer
+****************************************************************************/
+char *smb_errstr(char *inbuf)
+{
+ static pstring ret;
+ int class = CVAL(inbuf,smb_rcls);
+ int num = SVAL(inbuf,smb_err);
+ int i,j;
+
+ for (i=0;err_classes[i].class;i++)
+ if (err_classes[i].code == class)
+ {
+ if (err_classes[i].err_msgs)
+ {
+ err_code_struct *err = err_classes[i].err_msgs;
+ for (j=0;err[j].name;j++)
+ if (num == err[j].code)
+ {
+ if (DEBUGLEVEL > 0)
+ sprintf(ret,"%s - %s (%s)",err_classes[i].class,
+ err[j].name,err[j].message);
+ else
+ sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
+ return ret;
+ }
+ }
+
+ sprintf(ret,"%s - %d",err_classes[i].class,num);
+ return ret;
+ }
+
+ sprintf(ret,"Error: Unknown error (%d,%d)",class,num);
+ return(ret);
+}
diff --git a/source3/nmbsync.c b/source3/nmbsync.c
index 5fa41e127a..c1db37ff5c 100644
--- a/source3/nmbsync.c
+++ b/source3/nmbsync.c
@@ -60,7 +60,6 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work,
char *name, int nm_type, struct in_addr ip, BOOL local)
{
extern fstring local_machine;
- fstring share;
static struct cli_state cli;
uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
@@ -97,9 +96,7 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work,
return;
}
- sprintf(share,"\\\\%s\\IPC$", name);
-
- if (!cli_send_tconX(&cli, share, "IPC", "", 1)) {
+ if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
DEBUG(1,("%s refused browse sync IPC$ connect\n", name));
cli_shutdown(&cli);
return;
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 24ee52ed69..b759f68430 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -1560,7 +1560,6 @@ BOOL server_validate(char *user, char *domain,
char *ntpass, int ntpasslen)
{
extern fstring local_machine;
- fstring share;
if (!cli.initialised) {
DEBUG(1,("password server %s is not connected\n", cli.desthost));
@@ -1579,9 +1578,7 @@ BOOL server_validate(char *user, char *domain,
}
- sprintf(share,"\\\\%s\\IPC$", cli.desthost);
-
- if (!cli_send_tconX(&cli, share, "IPC", "", 1)) {
+ if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost));
return False;
}
diff --git a/source3/utils/torture.c b/source3/utils/torture.c
new file mode 100644
index 0000000000..bc7ebfb335
--- /dev/null
+++ b/source3/utils/torture.c
@@ -0,0 +1,316 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ SMB torture tester
+ Copyright (C) Andrew Tridgell 1997
+
+ 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.
+*/
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+static struct cli_state cli;
+static fstring host, workgroup, share, password, username, myname;
+static char *sockops="";
+
+
+static struct timeval tp1,tp2;
+
+static void start_timer()
+{
+ gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+ gettimeofday(&tp2,NULL);
+ return((tp2.tv_sec - tp1.tv_sec) +
+ (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
+}
+
+
+static int open_connection(void)
+{
+ if (!cli_initialise(&cli) || !cli_connect(&cli, host, NULL)) {
+ printf("Failed to connect with %s\n", host);
+ }
+
+ if (!cli_session_request(&cli, host, 0x20, myname)) {
+ printf("%s rejected the session\n",host);
+ cli_shutdown(&cli);
+ return -1;
+ }
+
+ if (!cli_negprot(&cli)) {
+ printf("%s rejected the negprot (%s)\n",host, cli_errstr(&cli));
+ cli_shutdown(&cli);
+ return -1;
+ }
+
+ if (!cli_session_setup(&cli, username, password, strlen(password),
+ "", 0, workgroup)) {
+ printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(&cli));
+ cli_shutdown(&cli);
+ return -1;
+ }
+
+ if (!cli_send_tconX(&cli, share, "A:", password, strlen(password)+1)) {
+ printf("%s refused tree connect (%s)\n", host, cli_errstr(&cli));
+ cli_shutdown(&cli);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+static void close_connection(void)
+{
+ if (!cli_tdis(&cli)) {
+ printf("tdis failed (%s)\n", cli_errstr(&cli));
+ }
+
+ cli_shutdown(&cli);
+}
+
+
+
+
+static BOOL wait_lock(int fnum, uint32 offset, uint32 len)
+{
+ while (!cli_lock(&cli, fnum, offset, len, -1)) {
+ int eclass, num;
+ cli_error(&cli, &eclass, &num);
+ if (eclass != ERRDOS || num != ERRlock) {
+ printf("lock failed (%s)\n",
+ cli_errstr(&cli));
+ return False;
+ }
+ }
+ return True;
+}
+
+
+static int rw_torture(int numops)
+{
+ char *lockfname = "\\torture.lck";
+ fstring fname;
+ int fnum;
+ int fnum2;
+ int pid2, pid = getpid();
+ int i;
+
+ fnum2 = cli_open(&cli, lockfname, O_RDWR | O_EXCL, DENY_NONE);
+ if (fnum2 == -1)
+ fnum2 = cli_open(&cli, lockfname, O_RDWR, DENY_NONE);
+ if (fnum2 == -1) {
+ printf("open of %s failed (%s)\n", lockfname, cli_errstr(&cli));
+ return -1;
+ }
+
+
+ for (i=0;i<numops;i++) {
+ unsigned n = (unsigned)random()%10;
+ printf("%d\r", i); fflush(stdout);
+ sprintf(fname,"\\torture.%u", n);
+
+ if (!wait_lock(fnum2, n*sizeof(int), sizeof(int))) {
+ return -1;
+ }
+
+ fnum = cli_open(&cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
+ if (fnum == -1) {
+ printf("open failed (%s)\n", cli_errstr(&cli));
+ break;
+ }
+
+ if (cli_write(&cli, fnum, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
+ printf("write failed (%s)\n", cli_errstr(&cli));
+ }
+
+ pid2 = 0;
+
+ if (cli_read(&cli, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
+ printf("read failed (%s)\n", cli_errstr(&cli));
+ }
+
+ if (pid2 != pid) {
+ printf("data corruption!\n");
+ }
+
+ if (!cli_close(&cli, fnum)) {
+ printf("close failed (%s)\n", cli_errstr(&cli));
+ }
+
+ if (!cli_unlink(&cli, fname)) {
+ printf("unlink failed (%s)\n", cli_errstr(&cli));
+ }
+
+ if (!cli_unlock(&cli, fnum2, n*sizeof(int), sizeof(int), -1)) {
+ printf("unlock failed (%s)\n", cli_errstr(&cli));
+ }
+ }
+
+ printf("%d\n", i);
+
+ return 0;
+}
+
+static void usage(void)
+{
+ printf("Usage: smbtorture \\\\server\\share <options>\n");
+
+ printf("\t-U user%%pass\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("\n");
+
+ exit(1);
+}
+
+
+
+static void run_torture(int numops)
+{
+ if (open_connection() == 0) {
+ cli_sockopt(&cli, sockops);
+
+ printf("pid %d OK\n", getpid());
+
+ rw_torture(numops);
+
+ close_connection();
+ }
+}
+
+
+static void create_procs(int nprocs, int numops)
+{
+ int i, status;
+
+ for (i=0;i<nprocs;i++) {
+ if (fork() == 0) {
+ int mypid = getpid();
+ srandom(mypid ^ time(NULL));
+ run_torture(numops);
+ _exit(0);
+ }
+ }
+
+ for (i=0;i<nprocs;i++)
+ waitpid(0, &status, 0);
+}
+
+
+
+/****************************************************************************
+ main program
+****************************************************************************/
+ int main(int argc,char *argv[])
+{
+ int nprocs=1, numops=100;
+ int opt;
+ char *p;
+ int gotpass = 0;
+ extern char *optarg;
+ extern int optind;
+ extern FILE *dbf;
+
+ dbf = stdout;
+
+ charset_initialise();
+
+ if (argc < 2) {
+ usage();
+ }
+
+ if (strncmp(argv[1], "\\\\", 2)) {
+ usage();
+ }
+
+ fstrcpy(host, &argv[1][2]);
+ p = strchr(&host[2],'\\');
+ if (!p) {
+ usage();
+ }
+ *p = 0;
+ fstrcpy(share, p+1);
+
+ get_myname(myname,NULL);
+
+ argc--;
+ argv++;
+
+
+ while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:")) != EOF) {
+ switch (opt) {
+ case 'W':
+ fstrcpy(workgroup,optarg);
+ break;
+ case 'N':
+ nprocs = atoi(optarg);
+ break;
+ case 'o':
+ numops = atoi(optarg);
+ break;
+ case 'O':
+ sockops = optarg;
+ break;
+ case 'n':
+ fstrcpy(myname, optarg);
+ break;
+ case 'U':
+ strcpy(username,optarg);
+ p = strchr(username,'%');
+ if (p) {
+ *p = 0;
+ strcpy(password, p+1);
+ gotpass = 1;
+ }
+ break;
+ default:
+ printf("Unknown option %c (%d)\n", (char)opt, opt);
+ usage();
+ }
+ }
+
+
+ while (!gotpass) {
+ p = getpass("Password:");
+ if (p) {
+ strcpy(password, p);
+ gotpass = 1;
+ }
+ }
+
+ printf("host=%s share=%s user=%s myname=%s\n",
+ host, share, username, myname);
+
+ start_timer();
+ create_procs(nprocs, numops);
+ printf("rw_torture: %g secs\n", end_timer());
+
+ return(0);
+}
+
+