-N option still prompted for password in smbclient -L usage
[samba.git] / source3 / client / clientutil.c
index 9dd1dc040e43aa00026ca44952f833a453aa505d..8d5e11e4d8c2ce955dbbed15296fd19af7f5d510 100644 (file)
@@ -2,7 +2,7 @@
    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;
 
@@ -67,7 +71,7 @@ int max_xmit = BUFFER_SIZE;
 
 BOOL have_ip = False;
 
-struct in_addr dest_ip;
+extern struct in_addr dest_ip;
 
 extern int Protocol;
 
@@ -77,26 +81,53 @@ extern int Client;
 /****************************************************************************
 setup basics in a outgoing packet
 ****************************************************************************/
-static void cli_setup_pkt(char *outbuf)
+void cli_setup_pkt(char *outbuf)
 {
   SSVAL(outbuf,smb_pid,pid);
   SSVAL(outbuf,smb_uid,uid);
   SSVAL(outbuf,smb_mid,mid);
-  if (Protocol > PROTOCOL_CORE)
+  if (Protocol > PROTOCOL_COREPLUS)
     {
       SCVAL(outbuf,smb_flg,0x8);
       SSVAL(outbuf,smb_flg2,0x1);
     }
 }
 
+/****************************************************************************
+call a remote api
+****************************************************************************/
+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,
+                    char **rparam,char **rdata)
+{
+  static char *inbuf=NULL;
+  static char *outbuf=NULL;
+
+  if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+  if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+
+  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);
+
+  return (cli_receive_trans_response(inbuf,SMBtrans,
+                                 rdrcnt,rprcnt,
+                                 rdata,rparam));
+}
 
 
 /****************************************************************************
   receive a SMB trans or trans2 response allocating the necessary memory
   ****************************************************************************/
-static BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len,
-                                      int *param_len, char **data,
-                                      char **param)
+BOOL cli_receive_trans_response(char *inbuf,int trans,
+                                   int *data_len,int *param_len,
+                                  char **data,char **param)
 {
   int total_data=0;
   int total_param=0;
@@ -104,7 +135,7 @@ static BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len,
 
   *data_len = *param_len = 0;
 
-  receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+  client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
   show_msg(inbuf);
 
   /* sanity check */
@@ -129,13 +160,6 @@ static BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len,
     {
       this_data = SVAL(inbuf,smb_drcnt);
       this_param = SVAL(inbuf,smb_prcnt);
-
-      if (this_data + *data_len > total_data ||
-         this_param + *param_len > total_param) {
-             DEBUG(1,("Data overflow in cli_receive_trans_response\n"));
-             return False;
-      }
-
       if (this_data)
        memcpy(*data + SVAL(inbuf,smb_drdisp),
               smb_base(inbuf) + SVAL(inbuf,smb_droff),
@@ -154,7 +178,7 @@ static BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len,
       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 */
@@ -171,24 +195,140 @@ static BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len,
   return(True);
 }
 
+
+
+/****************************************************************************
+  send a SMB trans or trans2 request
+  ****************************************************************************/
+BOOL cli_send_trans_request(char *outbuf,int trans,
+                              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)
+{
+  int i;
+  int this_ldata,this_lparam;
+  int tot_data=0,tot_param=0;
+  char *outdata,*outparam;
+  pstring inbuf;
+  char *p;
+
+  this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
+  this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
+
+  bzero(outbuf,smb_size);
+  set_message(outbuf,14+lsetup,0,True);
+  CVAL(outbuf,smb_com) = trans;
+  SSVAL(outbuf,smb_tid,cnum);
+  cli_setup_pkt(outbuf);
+
+  outparam = smb_buf(outbuf)+(trans==SMBtrans ? namelen+1 : 3);
+  outdata = outparam+this_lparam;
+
+  /* primary request */
+  SSVAL(outbuf,smb_tpscnt,lparam);     /* tpscnt */
+  SSVAL(outbuf,smb_tdscnt,ldata);      /* tdscnt */
+  SSVAL(outbuf,smb_mprcnt,mparam);     /* mprcnt */
+  SSVAL(outbuf,smb_mdrcnt,mdata);      /* mdrcnt */
+  SCVAL(outbuf,smb_msrcnt,msetup);     /* msrcnt */
+  SSVAL(outbuf,smb_flags,flags);       /* flags */
+  SIVAL(outbuf,smb_timeout,0);         /* timeout */
+  SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
+  SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
+  SSVAL(outbuf,smb_dscnt,this_ldata);  /* dscnt */
+  SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
+  SCVAL(outbuf,smb_suwcnt,lsetup);     /* suwcnt */
+  for (i=0;i<lsetup;i++)               /* setup[] */
+    SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
+  p = smb_buf(outbuf);
+  if (trans==SMBtrans)
+    memcpy(p,name, namelen+1);                 /* name[] */
+  else
+    {
+      *p++ = 0;                                /* put in a null smb_name */
+      *p++ = 'D'; *p++ = ' ';          /* this was added because OS/2 does it */
+    }
+  if (this_lparam)                     /* param[] */
+    memcpy(outparam,param,this_lparam);
+  if (this_ldata)                      /* data[] */
+    memcpy(outdata,data,this_ldata);
+  set_message(outbuf,14+lsetup,                /* wcnt, bcc */
+             PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
+
+  show_msg(outbuf);
+  send_smb(Client,outbuf);
+
+  if (this_ldata < ldata || this_lparam < lparam)
+    {
+      /* receive interim response */
+      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)));
+         return(False);
+       }      
+
+      tot_data = this_ldata;
+      tot_param = this_lparam;
+
+      while (tot_data < ldata || tot_param < lparam)
+    {
+         this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
+         this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
+
+         set_message(outbuf,trans==SMBtrans?8:9,0,True);
+         CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
+
+         outparam = smb_buf(outbuf);
+         outdata = outparam+this_lparam;
+
+         /* secondary request */
+         SSVAL(outbuf,smb_tpscnt,lparam);      /* tpscnt */
+         SSVAL(outbuf,smb_tdscnt,ldata);       /* tdscnt */
+         SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
+         SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
+         SSVAL(outbuf,smb_spsdisp,tot_param);  /* psdisp */
+         SSVAL(outbuf,smb_sdscnt,this_ldata);  /* dscnt */
+         SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
+         SSVAL(outbuf,smb_sdsdisp,tot_data);   /* dsdisp */
+         if (trans==SMBtrans2)
+           SSVAL(outbuf,smb_sfid,fid);         /* fid */
+         if (this_lparam)                      /* param[] */
+           memcpy(outparam,param,this_lparam);
+         if (this_ldata)                       /* data[] */
+           memcpy(outdata,data,this_ldata);
+         set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
+                     PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
+
+         show_msg(outbuf);
+         send_smb(Client,outbuf);
+
+         tot_data += this_ldata;
+         tot_param += this_lparam;
+       }
+    }
+
+    return(True);
+}
+
+
 /****************************************************************************
 send a session request
 ****************************************************************************/
-static BOOL cli_send_session_request(char *inbuf, char *outbuf)
+BOOL cli_send_session_request(char *inbuf,char *outbuf)
 {
   fstring dest;
   char *p;
   int len = 4;
   /* send a session request (RFC 8002) */
 
-  fstrcpy(dest,desthost);
-  
+  strcpy(dest,desthost);
   p = strchr(dest,'.');
   if (p) *p = 0;
 
   /* put in the destination name */
   p = outbuf+len;
-  name_mangle(dest,p,name_type);
+  name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
   len += name_len(p);
 
   /* and my name */
@@ -203,7 +343,7 @@ static BOOL cli_send_session_request(char *inbuf, char *outbuf)
   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 */
     {
@@ -223,11 +363,11 @@ static BOOL cli_send_session_request(char *inbuf, char *outbuf)
       putip((char *)&dest_ip,inbuf+4);
 
       close_sockets();
-      Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
+      Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
       if (Client == -1)
         return False;
 
-      DEBUG(5,("Retargeted\n"));
+      DEBUG(3,("Retargeted\n"));
 
       set_socket_options(Client,user_socket_options);
 
@@ -272,40 +412,39 @@ static BOOL cli_send_session_request(char *inbuf, char *outbuf)
   return(True);
 }
 
+static struct {
+  int prot;
+  char *name;
+} prots[] = {
+  {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
+  {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
+  {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
+  {PROTOCOL_LANMAN1,"LANMAN1.0"},
+  {PROTOCOL_LANMAN2,"LM1.2X002"},
+  {PROTOCOL_LANMAN2,"Samba"},
+  {PROTOCOL_NT1,"NT LM 0.12"},
+  {PROTOCOL_NT1,"NT LANMAN 1.0"},
+  {-1,NULL}
+};
 
-static  struct {
-    int prot;
-    char *name;
-  }
-prots[] = 
-    {
-      {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
-      {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
-      {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
-      {PROTOCOL_LANMAN1,"LANMAN1.0"},
-      {PROTOCOL_LANMAN2,"LM1.2X002"},
-      {PROTOCOL_LANMAN2,"Samba"},
-      {PROTOCOL_NT1,"NT LM 0.12"},
-      {PROTOCOL_NT1,"NT LANMAN 1.0"},
-      {-1,NULL}
-    };
 
 /****************************************************************************
-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)
     {
@@ -313,11 +452,15 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
     }
 
-  pstrcpy(dev,"A:");
+#if AJT
+  if (strstr(service,"IPC$")) connect_as_ipc = True;
+#endif
+
+  strcpy(dev,"A:");
   if (connect_as_printer)
-    pstrcpy(dev,"LPT1:");
+    strcpy(dev,"LPT1:");
   if (connect_as_ipc)
-    pstrcpy(dev,"IPC");
+    strcpy(dev,"IPC");
 
 
   if (start_session && !cli_send_session_request(inbuf,outbuf))
@@ -360,7 +503,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
   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);
 
@@ -376,51 +519,54 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
       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(5,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
-    max_vcs = SVAL(inbuf,smb_vwv4); 
-    DEBUG(5,("max vcs %d\n",max_vcs)); 
-    DEBUG(5,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
+    DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
+    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);
     memcpy(cryptkey,smb_buf(inbuf),8);
     if (IVAL(inbuf,smb_vwv9+1) & 1)
       readbraw_supported = writebraw_supported = True;      
-    DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
-    max_vcs = SVAL(inbuf,smb_vwv2+1); 
-    DEBUG(5,("max vcs %d\n",max_vcs));
-    DEBUG(5,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
-    DEBUG(5,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
+    DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
+    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(5,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
-  DEBUG(5,("max xmt %d\n",max_xmit));
-  DEBUG(5,("Got %d byte crypt key\n",crypt_len));
-  DEBUG(5,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
+  DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
+  DEBUG(3,("max xmt %d\n",max_xmit));
+  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;
@@ -439,35 +585,30 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
   else
     pass = (char *)getpass("Password: ");
 
-  if(pass == NULL)
-  {
-    DEBUG(0, ("cli_send_login : no password available - logon failed.\n"));
-    return False;
-  }
+  pstrcpy(smb_login_passwd, pass);
+
+  /* use a blank username for the 2nd try with a blank password */
+  if (tries++ && !*pass)
+    *username = 0;
 
   if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
     {
       fstring pword;
       int passlen = strlen(pass)+1;
-      fstrcpy(pword,pass);      
+      strcpy(pword,pass);      
 
       if (doencrypt && *pass) {
-       DEBUG(5,("Using encrypted passwords\n"));
+       DEBUG(3,("Using encrypted passwords\n"));
        passlen = 24;
        SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
       }
 
       /* if in share level security then don't send a password now */
-      if (!(sec_mode & 1)) {fstrcpy(pword, "");passlen=1;} 
+      if (!(opt.sec_mode & 1)) {strcpy(pword, "");passlen=1;} 
 
       /* send a session setup command */
       bzero(outbuf,smb_size);
 
-      if (passlen > MAX_PASS_LEN) {
-             DEBUG(1,("password too long %d\n", passlen));
-             return False;
-      }
-
       if (Protocol < PROTOCOL_NT1) {
        set_message(outbuf,10,1 + strlen(username) + passlen,True);
        CVAL(outbuf,smb_com) = SMBsesssetupX;
@@ -476,8 +617,8 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
        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);
@@ -494,7 +635,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
        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);
@@ -507,7 +648,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
       }
 
       send_smb(Client,outbuf);
-      receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+      client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
 
       show_msg(inbuf);
 
@@ -520,13 +661,14 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
                SVAL(inbuf,smb_err) == ERRbadpw)))
            {
              got_pass = False;
-             DEBUG(5,("resending login\n"));
-             goto get_pass;
+             DEBUG(3,("resending login\n"));
+             if (! no_pass)
+                 goto get_pass;
            }
              
          DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s   %s\n",
                username,myname,desthost,smb_errstr(inbuf)));
-         DEBUG(0,("You might find the -U or -n options useful\n"));
+         DEBUG(0,("You might find the -U, -W or -n options useful\n"));
          DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
          DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
          if (was_null)
@@ -549,11 +691,19 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
 
       /* use the returned uid from now on */
       if (SVAL(inbuf,smb_uid) != uid)
-       DEBUG(5,("Server gave us a UID of %d. We gave %d\n",
+       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 (opt.sec_mode & 1) {
+         if (SVAL(inbuf, smb_vwv2) & 1)
+                 DEBUG(1,("connected as guest "));
+         DEBUG(1,("security=user\n"));
+  } else {
+         DEBUG(1,("security=share\n"));
+  }
+
   /* now we've got a connection - send a tcon message */
   bzero(outbuf,smb_size);
 
@@ -569,7 +719,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
   {
     int passlen = strlen(pass)+1;
     fstring pword;
-    fstrcpy(pword,pass);
+    strcpy(pword,pass);
 
     if (doencrypt && *pass) {
       passlen=24;
@@ -577,27 +727,44 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
     }
 
     /* if in user level security then don't send a password now */
-    if ((sec_mode & 1)) {
-      fstrcpy(pword, ""); passlen=1; 
+    if ((opt.sec_mode & 1)) {
+      strcpy(pword, ""); passlen=1; 
     }
 
-    set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
-    CVAL(outbuf,smb_com) = SMBtconX;
-    cli_setup_pkt(outbuf);
-
-    SSVAL(outbuf,smb_vwv0,0xFF);
-    SSVAL(outbuf,smb_vwv3,passlen);
-
-    p = smb_buf(outbuf);
-    memcpy(p,pword,passlen);
-    p += passlen;
-    strcpy(p,service);
-    p = skip_string(p,1);
-    strcpy(p,dev);
+    if (Protocol <= PROTOCOL_COREPLUS) {
+      set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
+      CVAL(outbuf,smb_com) = SMBtcon;
+      cli_setup_pkt(outbuf);
+
+      p = smb_buf(outbuf);
+      *p++ = 0x04;
+      strcpy(p, service);
+      p = skip_string(p,1);
+      *p++ = 0x04;
+      memcpy(p,pword,passlen);
+      p += passlen;
+      *p++ = 0x04;
+      strcpy(p, dev);
+    }
+    else {
+      set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
+      CVAL(outbuf,smb_com) = SMBtconX;
+      cli_setup_pkt(outbuf);
+  
+      SSVAL(outbuf,smb_vwv0,0xFF);
+      SSVAL(outbuf,smb_vwv3,passlen);
+  
+      p = smb_buf(outbuf);
+      memcpy(p,pword,passlen);
+      p += passlen;
+      strcpy(p,service);
+      p = skip_string(p,1);
+      strcpy(p,dev);
+    }
   }
 
   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 && 
@@ -624,19 +791,34 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
     }
   
 
-  max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
-  if (max_xmit <= 0)
-    max_xmit = BUFFER_SIZE - 4;
+  if (Protocol <= PROTOCOL_COREPLUS) {
+    max_xmit = SVAL(inbuf,smb_vwv0);
 
-  cnum = SVAL(inbuf,smb_tid);
+    cnum = SVAL(inbuf,smb_vwv1);
+  }
+  else {
+    max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
+    if (max_xmit <= 0)
+      max_xmit = BUFFER_SIZE - 4;
+
+    cnum = SVAL(inbuf,smb_tid);
+  }
+  opt.max_xmit = max_xmit;
+  opt.tid = cnum;
 
-  DEBUG(5,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
+  DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
 
   if (was_null)
     {
       free(inbuf);
       free(outbuf);
     }
+
+  if (options != NULL)
+    {
+      *options = opt;
+    }
+
   return True;
 }
 
@@ -644,10 +826,12 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu
 /****************************************************************************
 send a logout command
 ****************************************************************************/
-void cli_send_logout(void)
+void cli_send_logout(void )
 {
   pstring inbuf,outbuf;
 
+  DEBUG(5,("cli_send_logout\n"));
+
   bzero(outbuf,smb_size);
   set_message(outbuf,0,0,True);
   CVAL(outbuf,smb_com) = SMBtdis;
@@ -655,7 +839,7 @@ void cli_send_logout(void)
   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)
     {
@@ -670,153 +854,16 @@ void cli_send_logout(void)
 }
 
 
-/****************************************************************************
-  send a SMB trans or trans2 request
-  ****************************************************************************/
-static BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags,
-                                  char *data,char *param,uint16 *setup, int ldata,int lparam,
-                                  int lsetup,int mdata,int mparam,int msetup)
-{
-  int i;
-  int this_ldata,this_lparam;
-  int tot_data=0,tot_param=0;
-  char *outdata,*outparam;
-  pstring inbuf;
-  char *p;
-
-  this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
-  this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
-
-  bzero(outbuf,smb_size);
-  set_message(outbuf,14+lsetup,0,True);
-  CVAL(outbuf,smb_com) = trans;
-  SSVAL(outbuf,smb_tid,cnum);
-  cli_setup_pkt(outbuf);
-
-  outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
-  outdata = outparam+this_lparam;
-
-  /* primary request */
-  SSVAL(outbuf,smb_tpscnt,lparam);     /* tpscnt */
-  SSVAL(outbuf,smb_tdscnt,ldata);      /* tdscnt */
-  SSVAL(outbuf,smb_mprcnt,mparam);     /* mprcnt */
-  SSVAL(outbuf,smb_mdrcnt,mdata);      /* mdrcnt */
-  SCVAL(outbuf,smb_msrcnt,msetup);     /* msrcnt */
-  SSVAL(outbuf,smb_flags,flags);       /* flags */
-  SIVAL(outbuf,smb_timeout,0);         /* timeout */
-  SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
-  SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
-  SSVAL(outbuf,smb_dscnt,this_ldata);  /* dscnt */
-  SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
-  SCVAL(outbuf,smb_suwcnt,lsetup);     /* suwcnt */
-  for (i=0;i<lsetup;i++)               /* setup[] */
-    SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
-  p = smb_buf(outbuf);
-  if (trans==SMBtrans)
-    strcpy(p,name);                    /* name[] */
-  else
-    {
-      *p++ = 0;                                /* put in a null smb_name */
-      *p++ = 'D'; *p++ = ' ';          /* this was added because OS/2 does it */
-    }
-  if (this_lparam)                     /* param[] */
-    memcpy(outparam,param,this_lparam);
-  if (this_ldata)                      /* data[] */
-    memcpy(outdata,data,this_ldata);
-  set_message(outbuf,14+lsetup,                /* wcnt, bcc */
-             PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
-
-  show_msg(outbuf);
-  send_smb(Client,outbuf);
-
-  if (this_ldata < ldata || this_lparam < lparam)
-    {
-      /* receive interim response */
-      if (!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)));
-         return(False);
-       }      
-
-      tot_data = this_ldata;
-      tot_param = this_lparam;
-
-      while (tot_data < ldata || tot_param < lparam)
-    {
-         this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
-         this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
-
-         set_message(outbuf,trans==SMBtrans?8:9,0,True);
-         CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
-
-         outparam = smb_buf(outbuf);
-         outdata = outparam+this_lparam;
-
-         /* secondary request */
-         SSVAL(outbuf,smb_tpscnt,lparam);      /* tpscnt */
-         SSVAL(outbuf,smb_tdscnt,ldata);       /* tdscnt */
-         SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
-         SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
-         SSVAL(outbuf,smb_spsdisp,tot_param);  /* psdisp */
-         SSVAL(outbuf,smb_sdscnt,this_ldata);  /* dscnt */
-         SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
-         SSVAL(outbuf,smb_sdsdisp,tot_data);   /* dsdisp */
-         if (trans==SMBtrans2)
-           SSVAL(outbuf,smb_sfid,fid);         /* fid */
-         if (this_lparam)                      /* param[] */
-           memcpy(outparam,param,this_lparam);
-         if (this_ldata)                       /* data[] */
-           memcpy(outdata,data,this_ldata);
-         set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
-                     PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
-
-         show_msg(outbuf);
-         send_smb(Client,outbuf);
-
-         tot_data += this_ldata;
-         tot_param += this_lparam;
-       }
-    }
-
-    return(True);
-}
-
-
-
-/****************************************************************************
-call a remote api
-****************************************************************************/
-BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt,
-                 int *rdrcnt, char *param,char *data, 
-                 char **rparam, char **rdata)
-{
-  static char *inbuf=NULL;
-  static char *outbuf=NULL;
-
-  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\\LANMAN",0,0,
-                        data,param,NULL,
-                        drcnt,prcnt,0,
-                        mdrcnt,mprcnt,0);
-
-  return (cli_receive_trans_response(inbuf,SMBtrans,
-                                    rdrcnt,rprcnt,
-                                    rdata,rparam));
-}
-
-
 /****************************************************************************
 open the client sockets
 ****************************************************************************/
-BOOL cli_open_sockets(int port)
+BOOL cli_open_sockets(int port )
 {
   static int last_port;
   char *host;
   pstring service2;
   extern int Client;
+  BOOL failed = True;
 
   if (port == 0) port=last_port;
   last_port=port;
@@ -829,38 +876,66 @@ BOOL cli_open_sockets(int port)
     }
   else
     {
-      pstrcpy(service2,service);
+      strcpy(service2,service);
       host = strtok(service2,"\\/");
-      pstrcpy(desthost,host);
+      if (!host) {
+       DEBUG(0,("Badly formed host name\n"));
+       return(False);
+      }
+      strcpy(desthost,host);
     }
 
-  DEBUG(5,("Opening sockets\n"));
-
-  if (*myname == 0)
-    get_myname(myname,NULL);
+  if (!(*myname)) {
+      get_myname(myname,NULL);
+  }
   strupper(myname);
 
+  DEBUG(3,("Opening sockets\n"));
+
   if (!have_ip)
     {
       struct hostent *hp;
 
-      if ((hp = Get_Hostbyname(host)) == 0) 
-       {
+      if ((hp = Get_Hostbyname(host)))
+      {
+       putip((char *)&dest_ip,(char *)hp->h_addr);
+       failed = False;
+      }
+      else
+      {
+#ifdef USENMB
+       /* Try and resolve the name with the netbios server */
+       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 ((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);
+       }
+#endif
+       if (failed) {
          DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
          return False;
        }
-
-      putip((char *)&dest_ip,(char *)hp->h_addr);
+      }
     }
 
-  Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
+  Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
   if (Client == -1)
     return False;
 
-  DEBUG(5,("Connected\n"));
-
+  DEBUG(3,("Connected\n"));
+  
   set_socket_options(Client,user_socket_options);  
-
+  
   return True;
 }
 
@@ -883,163 +958,11 @@ BOOL cli_reopen_connection(char *inbuf,char *outbuf)
   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."},
-  {"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."},
-  {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,"A 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);
-}