Unix SMB/Netbios implementation.
Version 1.9.
SMB client
- Copyright (C) Andrew Tridgell 1994-1997
+ Copyright (C) Andrew Tridgell 1994-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
#define REGISTER 0
#endif
+#define USENMB
+
pstring service="";
pstring desthost="";
extern pstring myname;
pstring password = "";
+pstring smb_login_passwd = "";
pstring username="";
pstring workgroup=WORKGROUP;
BOOL got_pass = False;
+BOOL no_pass = False;
BOOL connect_as_printer = False;
BOOL connect_as_ipc = False;
/****************************************************************************
call a remote api
****************************************************************************/
-BOOL cli_call_api(char *pipe_name, int prcnt,int drcnt, int srcnt,
+BOOL cli_call_api(char *pipe_name, int pipe_name_len,
+ int prcnt,int drcnt, int srcnt,
int mprcnt,int mdrcnt,
int *rprcnt,int *rdrcnt,
char *param,char *data, uint16 *setup,
if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
- cli_send_trans_request(outbuf,SMBtrans,pipe_name, 0,0,
+ if (pipe_name_len == 0) pipe_name_len = strlen(pipe_name);
+
+ cli_send_trans_request(outbuf,SMBtrans,pipe_name, pipe_name_len, 0,0,
data, param, setup,
drcnt, prcnt, srcnt,
mdrcnt, mprcnt, 0);
*data_len = *param_len = 0;
- receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+ client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
show_msg(inbuf);
/* sanity check */
if (total_data <= *data_len && total_param <= *param_len)
break;
- receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+ client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
show_msg(inbuf);
/* sanity check */
send a SMB trans or trans2 request
****************************************************************************/
BOOL cli_send_trans_request(char *outbuf,int trans,
- char *name,int fid,int flags,
+ char *name,int namelen, int fid,int flags,
char *data,char *param,uint16 *setup,
int ldata,int lparam,int lsetup,
int mdata,int mparam,int msetup)
SSVAL(outbuf,smb_tid,cnum);
cli_setup_pkt(outbuf);
- outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
+ outparam = smb_buf(outbuf)+(trans==SMBtrans ? namelen+1 : 3);
outdata = outparam+this_lparam;
/* primary request */
SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
p = smb_buf(outbuf);
if (trans==SMBtrans)
- strcpy(p,name); /* name[] */
+ memcpy(p,name, namelen+1); /* name[] */
else
{
*p++ = 0; /* put in a null smb_name */
if (this_ldata < ldata || this_lparam < lparam)
{
/* receive interim response */
- if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
+ if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
{
DEBUG(0,("%s request failed (%s)\n",
trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
send_smb(Client,outbuf);
DEBUG(5,("Sent session request\n"));
- receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+ client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */
{
/****************************************************************************
-send a login command
+send a login command.
****************************************************************************/
-BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
+BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup, struct connection_options *options)
{
BOOL was_null = (!inbuf && !outbuf);
- int sesskey=0;
time_t servertime = 0;
extern int serverzone;
- int sec_mode=0;
- int crypt_len;
- int max_vcs=0;
+ int crypt_len=0;
char *pass = NULL;
pstring dev;
char *p;
int numprots;
int tries=0;
+ struct connection_options opt;
+
+ bzero(&opt, sizeof(opt));
if (was_null)
{
CVAL(smb_buf(outbuf),0) = 2;
send_smb(Client,outbuf);
- receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+ client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
show_msg(inbuf);
return(False);
}
- Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
+ opt.protocol = Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
- if (Protocol < PROTOCOL_NT1) {
- sec_mode = SVAL(inbuf,smb_vwv1);
- max_xmit = SVAL(inbuf,smb_vwv2);
- sesskey = IVAL(inbuf,smb_vwv6);
- serverzone = SVALS(inbuf,smb_vwv10)*60;
+ if (Protocol < PROTOCOL_LANMAN1) {
+ /* no extra params */
+ } else if (Protocol < PROTOCOL_NT1) {
+ opt.sec_mode = SVAL(inbuf,smb_vwv1);
+ opt.max_xmit = max_xmit = SVAL(inbuf,smb_vwv2);
+ opt.sesskey = IVAL(inbuf,smb_vwv6);
+ opt.serverzone = serverzone = SVALS(inbuf,smb_vwv10)*60;
/* this time is converted to GMT by make_unix_date */
servertime = make_unix_date(inbuf+smb_vwv8);
if (Protocol >= PROTOCOL_COREPLUS) {
+ opt.rawmode = SVAL(inbuf,smb_vwv5);
readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
}
crypt_len = smb_buflen(inbuf);
memcpy(cryptkey,smb_buf(inbuf),8);
DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
- max_vcs = SVAL(inbuf,smb_vwv4);
- DEBUG(3,("max vcs %d\n",max_vcs));
+ opt.max_vcs = SVAL(inbuf,smb_vwv4);
+ DEBUG(3,("max vcs %d\n",opt.max_vcs));
DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
} else {
/* NT protocol */
- sec_mode = CVAL(inbuf,smb_vwv1);
- max_xmit = IVAL(inbuf,smb_vwv3+1);
- sesskey = IVAL(inbuf,smb_vwv7+1);
- serverzone = SVALS(inbuf,smb_vwv15+1)*60;
+ opt.sec_mode = CVAL(inbuf,smb_vwv1);
+ opt.max_xmit = max_xmit = IVAL(inbuf,smb_vwv3+1);
+ opt.sesskey = IVAL(inbuf,smb_vwv7+1);
+ opt.serverzone = SVALS(inbuf,smb_vwv15+1)*60;
/* this time arrives in real GMT */
servertime = interpret_long_date(inbuf+smb_vwv11+1);
crypt_len = CVAL(inbuf,smb_vwv16+1);
if (IVAL(inbuf,smb_vwv9+1) & 1)
readbraw_supported = writebraw_supported = True;
DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
- max_vcs = SVAL(inbuf,smb_vwv2+1);
- DEBUG(3,("max vcs %d\n",max_vcs));
+ opt.max_vcs = SVAL(inbuf,smb_vwv2+1);
+ DEBUG(3,("max vcs %d\n",opt.max_vcs));
DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
}
DEBUG(3,("Got %d byte crypt key\n",crypt_len));
DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
- doencrypt = ((sec_mode & 2) != 0);
+ doencrypt = ((opt.sec_mode & 2) != 0);
if (servertime) {
static BOOL done_time = False;
else
pass = (char *)getpass("Password: ");
+ pstrcpy(smb_login_passwd, pass);
+
/* use a blank username for the 2nd try with a blank password */
if (tries++ && !*pass)
*username = 0;
}
/* if in share level security then don't send a password now */
- if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;}
+ if (!(opt.sec_mode & 1)) {strcpy(pword, "");passlen=1;}
/* send a session setup command */
bzero(outbuf,smb_size);
CVAL(outbuf,smb_vwv0) = 0xFF;
SSVAL(outbuf,smb_vwv2,max_xmit);
SSVAL(outbuf,smb_vwv3,2);
- SSVAL(outbuf,smb_vwv4,max_vcs-1);
- SIVAL(outbuf,smb_vwv5,sesskey);
+ SSVAL(outbuf,smb_vwv4,opt.max_vcs-1);
+ SIVAL(outbuf,smb_vwv5,opt.sesskey);
SSVAL(outbuf,smb_vwv7,passlen);
p = smb_buf(outbuf);
memcpy(p,pword,passlen);
SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
SSVAL(outbuf,smb_vwv3,2);
SSVAL(outbuf,smb_vwv4,getpid());
- SIVAL(outbuf,smb_vwv5,sesskey);
+ SIVAL(outbuf,smb_vwv5,opt.sesskey);
SSVAL(outbuf,smb_vwv7,passlen);
SSVAL(outbuf,smb_vwv8,0);
p = smb_buf(outbuf);
}
send_smb(Client,outbuf);
- receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+ client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
show_msg(inbuf);
{
got_pass = False;
DEBUG(3,("resending login\n"));
- goto get_pass;
+ if (! no_pass)
+ goto get_pass;
}
DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
if (SVAL(inbuf,smb_uid) != uid)
DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
SVAL(inbuf,smb_uid),uid));
- uid = SVAL(inbuf,smb_uid);
+ opt.server_uid = uid = SVAL(inbuf,smb_uid);
}
- if (sec_mode & 1) {
+ if (opt.sec_mode & 1) {
if (SVAL(inbuf, smb_vwv2) & 1)
DEBUG(1,("connected as guest "));
DEBUG(1,("security=user\n"));
}
/* if in user level security then don't send a password now */
- if ((sec_mode & 1)) {
+ if ((opt.sec_mode & 1)) {
strcpy(pword, ""); passlen=1;
}
}
send_smb(Client,outbuf);
- receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+ client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
/* trying again with a blank password */
if (CVAL(inbuf,smb_rcls) != 0 &&
cnum = SVAL(inbuf,smb_tid);
}
+ opt.max_xmit = max_xmit;
+ opt.tid = cnum;
DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
free(outbuf);
}
+ if (options != NULL)
+ {
+ *options = opt;
+ }
+
return True;
}
cli_setup_pkt(outbuf);
send_smb(Client,outbuf);
- receive_smb(Client,inbuf,SHORT_TIMEOUT);
+ client_receive_smb(Client,inbuf,SHORT_TIMEOUT);
if (CVAL(inbuf,smb_rcls) != 0)
{
{
#ifdef USENMB
/* Try and resolve the name with the netbios server */
- int bcast;
+ int bcast, count;
+ struct in_addr *ip_list;
if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
interpret_addr(lp_socket_address()))) != -1) {
set_socket_options(bcast, "SO_BROADCAST");
- if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
- &dest_ip,0)) {
- failed = False;
+ if ((ip_list = name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
+ &count,0)) != NULL) {
+ dest_ip = ip_list[0];
+ free(ip_list);
+ failed = False;
}
close (bcast);
}
cli_setup_pkt(outbuf);
send_smb(Client,outbuf);
- receive_smb(Client,inbuf,SHORT_TIMEOUT);
+ client_receive_smb(Client,inbuf,SHORT_TIMEOUT);
close_sockets();
if (!cli_open_sockets(0)) return(False);
- return(cli_send_login(inbuf,outbuf,True,True));
+ return(cli_send_login(inbuf,outbuf,True,True,NULL));
}
-/* 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);
-}