home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Networking / SambaManager / samba-1.9.17p4 / source / clientutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-30  |  29.4 KB  |  1,040 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    SMB client
  5.    Copyright (C) Andrew Tridgell 1994-1997
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #ifdef SYSLOG
  23. #undef SYSLOG
  24. #endif
  25.  
  26. #include "includes.h"
  27.  
  28. #ifndef REGISTER
  29. #define REGISTER 0
  30. #endif
  31.  
  32. pstring service="";
  33. pstring desthost="";
  34. extern pstring myname;
  35. pstring password = "";
  36. pstring username="";
  37. pstring workgroup=WORKGROUP;
  38. BOOL got_pass = False;
  39. BOOL connect_as_printer = False;
  40. BOOL connect_as_ipc = False;
  41.  
  42. char cryptkey[8];
  43. BOOL doencrypt=False;
  44.  
  45. extern pstring user_socket_options;
  46.  
  47. /* 30 second timeout on most commands */
  48. #define CLIENT_TIMEOUT (30*1000)
  49. #define SHORT_TIMEOUT (5*1000)
  50.  
  51. int name_type = 0x20;
  52.  
  53. int max_protocol = PROTOCOL_NT1;
  54.  
  55. BOOL readbraw_supported = False;
  56. BOOL writebraw_supported = False;
  57.  
  58. extern int DEBUGLEVEL;
  59.  
  60. int cnum = 0;
  61. int pid = 0;
  62. int gid = 0;
  63. int uid = 0;
  64. int mid = 0;
  65.  
  66. int max_xmit = BUFFER_SIZE;
  67.  
  68. BOOL have_ip = False;
  69.  
  70. struct in_addr dest_ip;
  71.  
  72. extern int Protocol;
  73.  
  74. extern int Client;
  75.  
  76.  
  77. /****************************************************************************
  78. setup basics in a outgoing packet
  79. ****************************************************************************/
  80. static void cli_setup_pkt(char *outbuf)
  81. {
  82.   SSVAL(outbuf,smb_pid,pid);
  83.   SSVAL(outbuf,smb_uid,uid);
  84.   SSVAL(outbuf,smb_mid,mid);
  85.   if (Protocol > PROTOCOL_CORE)
  86.     {
  87.       SCVAL(outbuf,smb_flg,0x8);
  88.       SSVAL(outbuf,smb_flg2,0x1);
  89.     }
  90. }
  91.  
  92.  
  93.  
  94. /****************************************************************************
  95.   receive a SMB trans or trans2 response allocating the necessary memory
  96.   ****************************************************************************/
  97. static BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len,
  98.                        int *param_len, char **data,
  99.                        char **param)
  100. {
  101.   int total_data=0;
  102.   int total_param=0;
  103.   int this_data,this_param;
  104.  
  105.   *data_len = *param_len = 0;
  106.  
  107.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  108.   show_msg(inbuf);
  109.  
  110.   /* sanity check */
  111.   if (CVAL(inbuf,smb_com) != trans)
  112.     {
  113.       DEBUG(0,("Expected %s response, got command 0x%02x\n",
  114.            trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
  115.       return(False);
  116.     }
  117.   if (CVAL(inbuf,smb_rcls) != 0)
  118.     return(False);
  119.  
  120.   /* parse out the lengths */
  121.   total_data = SVAL(inbuf,smb_tdrcnt);
  122.   total_param = SVAL(inbuf,smb_tprcnt);
  123.  
  124.   /* allocate it */
  125.   *data = Realloc(*data,total_data);
  126.   *param = Realloc(*param,total_param);
  127.  
  128.   while (1)
  129.     {
  130.       this_data = SVAL(inbuf,smb_drcnt);
  131.       this_param = SVAL(inbuf,smb_prcnt);
  132.       if (this_data)
  133.     memcpy(*data + SVAL(inbuf,smb_drdisp),
  134.            smb_base(inbuf) + SVAL(inbuf,smb_droff),
  135.            this_data);
  136.       if (this_param)
  137.     memcpy(*param + SVAL(inbuf,smb_prdisp),
  138.            smb_base(inbuf) + SVAL(inbuf,smb_proff),
  139.            this_param);
  140.       *data_len += this_data;
  141.       *param_len += this_param;
  142.  
  143.       /* parse out the total lengths again - they can shrink! */
  144.       total_data = SVAL(inbuf,smb_tdrcnt);
  145.       total_param = SVAL(inbuf,smb_tprcnt);
  146.  
  147.       if (total_data <= *data_len && total_param <= *param_len)
  148.     break;
  149.  
  150.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  151.       show_msg(inbuf);
  152.  
  153.       /* sanity check */
  154.       if (CVAL(inbuf,smb_com) != trans)
  155.     {
  156.       DEBUG(0,("Expected %s response, got command 0x%02x\n",
  157.            trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
  158.       return(False);
  159.     }
  160.       if (CVAL(inbuf,smb_rcls) != 0)
  161.       return(False);
  162.     }
  163.   
  164.   return(True);
  165. }
  166.  
  167. /****************************************************************************
  168. send a session request
  169. ****************************************************************************/
  170. static BOOL cli_send_session_request(char *inbuf, char *outbuf)
  171. {
  172.   fstring dest;
  173.   char *p;
  174.   int len = 4;
  175.   /* send a session request (RFC 8002) */
  176.  
  177.   fstrcpy(dest,desthost);
  178.   
  179.   p = strchr(dest,'.');
  180.   if (p) *p = 0;
  181.  
  182.   /* put in the destination name */
  183.   p = outbuf+len;
  184.   name_mangle(dest,p,name_type);
  185.   len += name_len(p);
  186.  
  187.   /* and my name */
  188.   p = outbuf+len;
  189.   name_mangle(myname,p,0);
  190.   len += name_len(p);
  191.  
  192.   /* setup the packet length */
  193.   _smb_setlen(outbuf,len);
  194.   CVAL(outbuf,0) = 0x81;
  195.  
  196.   send_smb(Client,outbuf);
  197.   DEBUG(5,("Sent session request\n"));
  198.  
  199.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  200.  
  201.   if (CVAL(inbuf,0) == 0x84) /* C. Hoch  9/14/95 Start */
  202.     {
  203.       /* For information, here is the response structure.
  204.        * We do the byte-twiddling to for portability.
  205.        struct RetargetResponse{
  206.        unsigned char type;
  207.        unsigned char flags;
  208.        int16 length;
  209.        int32 ip_addr;
  210.        int16 port;
  211.        };
  212.        */
  213.       extern int Client;
  214.       int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
  215.       /* SESSION RETARGET */
  216.       putip((char *)&dest_ip,inbuf+4);
  217.  
  218.       close_sockets();
  219.       Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
  220.       if (Client == -1)
  221.         return False;
  222.  
  223.       DEBUG(5,("Retargeted\n"));
  224.  
  225.       set_socket_options(Client,user_socket_options);
  226.  
  227.       /* Try again */
  228.       return cli_send_session_request(inbuf,outbuf);
  229.     } /* C. Hoch 9/14/95 End */
  230.  
  231.  
  232.   if (CVAL(inbuf,0) != 0x82)
  233.     {
  234.       int ecode = CVAL(inbuf,4);
  235.       DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
  236.            CVAL(inbuf,0),ecode,myname,desthost));
  237.       switch (ecode)
  238.     {
  239.     case 0x80: 
  240.       DEBUG(0,("Not listening on called name\n")); 
  241.       DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
  242.       DEBUG(0,("You may find the -I option useful for this\n"));
  243.       break;
  244.     case 0x81: 
  245.       DEBUG(0,("Not listening for calling name\n")); 
  246.       DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
  247.       DEBUG(0,("You may find the -n option useful for this\n"));
  248.       break;
  249.     case 0x82: 
  250.       DEBUG(0,("Called name not present\n")); 
  251.       DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
  252.       DEBUG(0,("You may find the -I option useful for this\n"));
  253.       break;
  254.     case 0x83: 
  255.       DEBUG(0,("Called name present, but insufficient resources\n")); 
  256.       DEBUG(0,("Perhaps you should try again later?\n")); 
  257.       break;
  258.     default:
  259.       DEBUG(0,("Unspecified error 0x%X\n",ecode)); 
  260.       DEBUG(0,("Your server software is being unfriendly\n"));
  261.       break;      
  262.     }
  263.       return(False);
  264.     }
  265.   return(True);
  266. }
  267.  
  268.  
  269. static  struct {
  270.     int prot;
  271.     char *name;
  272.   }
  273. prots[] = 
  274.     {
  275.       {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
  276.       {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
  277.       {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
  278.       {PROTOCOL_LANMAN1,"LANMAN1.0"},
  279.       {PROTOCOL_LANMAN2,"LM1.2X002"},
  280.       {PROTOCOL_LANMAN2,"Samba"},
  281.       {PROTOCOL_NT1,"NT LM 0.12"},
  282.       {PROTOCOL_NT1,"NT LANMAN 1.0"},
  283.       {-1,NULL}
  284.     };
  285.  
  286. /****************************************************************************
  287. send a login command
  288. ****************************************************************************/
  289. BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setup)
  290. {
  291.   BOOL was_null = (!inbuf && !outbuf);
  292.   int sesskey=0;
  293.   time_t servertime = 0;
  294.   extern int serverzone;
  295.   int sec_mode=0;
  296.   int crypt_len;
  297.   int max_vcs=0;
  298.   char *pass = NULL;  
  299.   pstring dev;
  300.   char *p;
  301.   int numprots;
  302.  
  303.   if (was_null)
  304.     {
  305.       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  306.       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  307.     }
  308.  
  309.   pstrcpy(dev,"A:");
  310.   if (connect_as_printer)
  311.     pstrcpy(dev,"LPT1:");
  312.   if (connect_as_ipc)
  313.     pstrcpy(dev,"IPC");
  314.  
  315.  
  316.   if (start_session && !cli_send_session_request(inbuf,outbuf))
  317.     {
  318.       if (was_null)
  319.     {
  320.       free(inbuf);
  321.       free(outbuf);
  322.     }      
  323.       return(False);
  324.     }
  325.  
  326.   bzero(outbuf,smb_size);
  327.  
  328.   /* setup the protocol strings */
  329.   {
  330.     int plength;
  331.  
  332.     for (plength=0,numprots=0;
  333.      prots[numprots].name && prots[numprots].prot<=max_protocol;
  334.      numprots++)
  335.       plength += strlen(prots[numprots].name)+2;
  336.     
  337.     set_message(outbuf,0,plength,True);
  338.  
  339.     p = smb_buf(outbuf);
  340.     for (numprots=0;
  341.      prots[numprots].name && prots[numprots].prot<=max_protocol;
  342.      numprots++)
  343.       {
  344.     *p++ = 2;
  345.     strcpy(p,prots[numprots].name);
  346.     p += strlen(p) + 1;
  347.       }
  348.   }
  349.  
  350.   CVAL(outbuf,smb_com) = SMBnegprot;
  351.   cli_setup_pkt(outbuf);
  352.  
  353.   CVAL(smb_buf(outbuf),0) = 2;
  354.  
  355.   send_smb(Client,outbuf);
  356.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  357.  
  358.   show_msg(inbuf);
  359.  
  360.   if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
  361.     {
  362.       DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
  363.         myname,desthost,smb_errstr(inbuf)));
  364.       if (was_null)
  365.     {
  366.       free(inbuf);
  367.       free(outbuf);
  368.     }
  369.       return(False);
  370.     }
  371.  
  372.   Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
  373.  
  374.  
  375.   if (Protocol < PROTOCOL_NT1) {    
  376.     sec_mode = SVAL(inbuf,smb_vwv1);
  377.     max_xmit = SVAL(inbuf,smb_vwv2);
  378.     sesskey = IVAL(inbuf,smb_vwv6);
  379.     serverzone = SVALS(inbuf,smb_vwv10)*60;
  380.     /* this time is converted to GMT by make_unix_date */
  381.     servertime = make_unix_date(inbuf+smb_vwv8);
  382.     if (Protocol >= PROTOCOL_COREPLUS) {
  383.       readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
  384.       writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
  385.     }
  386.     crypt_len = smb_buflen(inbuf);
  387.     memcpy(cryptkey,smb_buf(inbuf),8);
  388.     DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
  389.     max_vcs = SVAL(inbuf,smb_vwv4); 
  390.     DEBUG(5,("max vcs %d\n",max_vcs)); 
  391.     DEBUG(5,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
  392.   } else {
  393.     /* NT protocol */
  394.     sec_mode = CVAL(inbuf,smb_vwv1);
  395.     max_xmit = IVAL(inbuf,smb_vwv3+1);
  396.     sesskey = IVAL(inbuf,smb_vwv7+1);
  397.     serverzone = SVALS(inbuf,smb_vwv15+1)*60;
  398.     /* this time arrives in real GMT */
  399.     servertime = interpret_long_date(inbuf+smb_vwv11+1);
  400.     crypt_len = CVAL(inbuf,smb_vwv16+1);
  401.     memcpy(cryptkey,smb_buf(inbuf),8);
  402.     if (IVAL(inbuf,smb_vwv9+1) & 1)
  403.       readbraw_supported = writebraw_supported = True;      
  404.     DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
  405.     max_vcs = SVAL(inbuf,smb_vwv2+1); 
  406.     DEBUG(5,("max vcs %d\n",max_vcs));
  407.     DEBUG(5,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
  408.     DEBUG(5,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
  409.   }
  410.  
  411.   DEBUG(5,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
  412.   DEBUG(5,("max xmt %d\n",max_xmit));
  413.   DEBUG(5,("Got %d byte crypt key\n",crypt_len));
  414.   DEBUG(5,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
  415.  
  416.   doencrypt = ((sec_mode & 2) != 0);
  417.  
  418.   if (servertime) {
  419.     static BOOL done_time = False;
  420.     if (!done_time) {
  421.       DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
  422.            asctime(LocalTime(&servertime)),
  423.            -(double)(serverzone/3600.0)));
  424.       done_time = True;
  425.     }
  426.   }
  427.  
  428.  get_pass:
  429.  
  430.   if (got_pass)
  431.     pass = password;
  432.   else
  433.     pass = (char *)getpass("Password: ");
  434.  
  435.   if(pass == NULL)
  436.   {
  437.     DEBUG(0, ("cli_send_login : no password available - logon failed.\n"));
  438.     return False;
  439.   }
  440.  
  441.   if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
  442.     {
  443.       fstring pword;
  444.       int passlen = strlen(pass)+1;
  445.       fstrcpy(pword,pass);      
  446.  
  447. #ifdef SMB_PASSWD
  448.       if (doencrypt && *pass) {
  449.     DEBUG(5,("Using encrypted passwords\n"));
  450.     passlen = 24;
  451.     SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
  452.       }
  453. #else
  454.       doencrypt = False;
  455. #endif
  456.  
  457.       /* if in share level security then don't send a password now */
  458.       if (!(sec_mode & 1)) {fstrcpy(pword, "");passlen=1;} 
  459.  
  460.       /* send a session setup command */
  461.       bzero(outbuf,smb_size);
  462.  
  463.       if (Protocol < PROTOCOL_NT1) {
  464.     set_message(outbuf,10,1 + strlen(username) + passlen,True);
  465.     CVAL(outbuf,smb_com) = SMBsesssetupX;
  466.     cli_setup_pkt(outbuf);
  467.  
  468.     CVAL(outbuf,smb_vwv0) = 0xFF;
  469.     SSVAL(outbuf,smb_vwv2,max_xmit);
  470.     SSVAL(outbuf,smb_vwv3,2);
  471.     SSVAL(outbuf,smb_vwv4,max_vcs-1);
  472.     SIVAL(outbuf,smb_vwv5,sesskey);
  473.     SSVAL(outbuf,smb_vwv7,passlen);
  474.     p = smb_buf(outbuf);
  475.     memcpy(p,pword,passlen);
  476.     p += passlen;
  477.     strcpy(p,username);
  478.       } else {
  479.     if (!doencrypt) passlen--;
  480.     /* for Win95 */
  481.     set_message(outbuf,13,0,True);
  482.     CVAL(outbuf,smb_com) = SMBsesssetupX;
  483.     cli_setup_pkt(outbuf);
  484.  
  485.     CVAL(outbuf,smb_vwv0) = 0xFF;
  486.     SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
  487.     SSVAL(outbuf,smb_vwv3,2);
  488.     SSVAL(outbuf,smb_vwv4,getpid());
  489.     SIVAL(outbuf,smb_vwv5,sesskey);
  490.     SSVAL(outbuf,smb_vwv7,passlen);
  491.     SSVAL(outbuf,smb_vwv8,0);
  492.     p = smb_buf(outbuf);
  493.     memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
  494.     strcpy(p,username);p = skip_string(p,1);
  495.     strcpy(p,workgroup);p = skip_string(p,1);
  496.     strcpy(p,"Unix");p = skip_string(p,1);
  497.     strcpy(p,"Samba");p = skip_string(p,1);
  498.     set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
  499.       }
  500.  
  501.       send_smb(Client,outbuf);
  502.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  503.  
  504.       show_msg(inbuf);
  505.  
  506.       if (CVAL(inbuf,smb_rcls) != 0)
  507.     {
  508.       if (! *pass &&
  509.           ((CVAL(inbuf,smb_rcls) == ERRDOS && 
  510.         SVAL(inbuf,smb_err) == ERRnoaccess) ||
  511.            (CVAL(inbuf,smb_rcls) == ERRSRV && 
  512.         SVAL(inbuf,smb_err) == ERRbadpw)))
  513.         {
  514.           got_pass = False;
  515.           DEBUG(5,("resending login\n"));
  516.           goto get_pass;
  517.         }
  518.           
  519.       DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s   %s\n",
  520.         username,myname,desthost,smb_errstr(inbuf)));
  521.       DEBUG(0,("You might find the -U or -n options useful\n"));
  522.       DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
  523.       DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
  524.       if (was_null)
  525.         {
  526.           free(inbuf);
  527.           free(outbuf);
  528.         }
  529.       return(False);
  530.     }
  531.  
  532.       if (Protocol >= PROTOCOL_NT1) {
  533.     char *domain,*os,*lanman;
  534.     p = smb_buf(inbuf);
  535.     os = p;
  536.     lanman = skip_string(os,1);
  537.     domain = skip_string(lanman,1);
  538.     if (*domain || *os || *lanman)
  539.       DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
  540.       }
  541.  
  542.       /* use the returned uid from now on */
  543.       if (SVAL(inbuf,smb_uid) != uid)
  544.     DEBUG(5,("Server gave us a UID of %d. We gave %d\n",
  545.           SVAL(inbuf,smb_uid),uid));
  546.       uid = SVAL(inbuf,smb_uid);
  547.     }
  548.  
  549.   /* now we've got a connection - send a tcon message */
  550.   bzero(outbuf,smb_size);
  551.  
  552.   if (strncmp(service,"\\\\",2) != 0)
  553.     {
  554.       DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
  555.       DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
  556.     }
  557.  
  558.  
  559.  again2:
  560.  
  561.   {
  562.     int passlen = strlen(pass)+1;
  563.     fstring pword;
  564.     fstrcpy(pword,pass);
  565.  
  566. #ifdef SMB_PASSWD
  567.     if (doencrypt && *pass) {
  568.       passlen=24;
  569.       SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);      
  570.     }
  571. #endif
  572.  
  573.     /* if in user level security then don't send a password now */
  574.     if ((sec_mode & 1)) {
  575.       fstrcpy(pword, ""); passlen=1; 
  576.     }
  577.  
  578.     set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
  579.     CVAL(outbuf,smb_com) = SMBtconX;
  580.     cli_setup_pkt(outbuf);
  581.  
  582.     SSVAL(outbuf,smb_vwv0,0xFF);
  583.     SSVAL(outbuf,smb_vwv3,passlen);
  584.  
  585.     p = smb_buf(outbuf);
  586.     memcpy(p,pword,passlen);
  587.     p += passlen;
  588.     strcpy(p,service);
  589.     p = skip_string(p,1);
  590.     strcpy(p,dev);
  591.   }
  592.  
  593.   send_smb(Client,outbuf);
  594.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  595.  
  596.   /* trying again with a blank password */
  597.   if (CVAL(inbuf,smb_rcls) != 0 && 
  598.       (int)strlen(pass) > 0 && 
  599.       !doencrypt &&
  600.       Protocol >= PROTOCOL_LANMAN1)
  601.     {
  602.       DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
  603.       strcpy(pass,"");
  604.       goto again2;
  605.     }  
  606.  
  607.   if (CVAL(inbuf,smb_rcls) != 0)
  608.     {
  609.       DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
  610.       DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
  611.       DEBUG(0,("Some servers insist that these be in uppercase\n"));
  612.       if (was_null)
  613.     {
  614.       free(inbuf);
  615.       free(outbuf);
  616.     }
  617.       return(False);
  618.     }
  619.   
  620.  
  621.   max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
  622.   if (max_xmit <= 0)
  623.     max_xmit = BUFFER_SIZE - 4;
  624.  
  625.   cnum = SVAL(inbuf,smb_tid);
  626.  
  627.   DEBUG(5,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
  628.  
  629.   if (was_null)
  630.     {
  631.       free(inbuf);
  632.       free(outbuf);
  633.     }
  634.   return True;
  635. }
  636.  
  637.  
  638. /****************************************************************************
  639. send a logout command
  640. ****************************************************************************/
  641. void cli_send_logout(void)
  642. {
  643.   pstring inbuf,outbuf;
  644.  
  645.   bzero(outbuf,smb_size);
  646.   set_message(outbuf,0,0,True);
  647.   CVAL(outbuf,smb_com) = SMBtdis;
  648.   SSVAL(outbuf,smb_tid,cnum);
  649.   cli_setup_pkt(outbuf);
  650.  
  651.   send_smb(Client,outbuf);
  652.   receive_smb(Client,inbuf,SHORT_TIMEOUT);
  653.  
  654.   if (CVAL(inbuf,smb_rcls) != 0)
  655.     {
  656.       DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
  657.     }
  658.  
  659.   
  660. #ifdef STATS
  661.   stats_report();
  662. #endif
  663.   exit(0);
  664. }
  665.  
  666.  
  667. /****************************************************************************
  668.   send a SMB trans or trans2 request
  669.   ****************************************************************************/
  670. static BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags,
  671.                    char *data,char *param,uint16 *setup, int ldata,int lparam,
  672.                    int lsetup,int mdata,int mparam,int msetup)
  673. {
  674.   int i;
  675.   int this_ldata,this_lparam;
  676.   int tot_data=0,tot_param=0;
  677.   char *outdata,*outparam;
  678.   pstring inbuf;
  679.   char *p;
  680.  
  681.   this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
  682.   this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
  683.  
  684.   bzero(outbuf,smb_size);
  685.   set_message(outbuf,14+lsetup,0,True);
  686.   CVAL(outbuf,smb_com) = trans;
  687.   SSVAL(outbuf,smb_tid,cnum);
  688.   cli_setup_pkt(outbuf);
  689.  
  690.   outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
  691.   outdata = outparam+this_lparam;
  692.  
  693.   /* primary request */
  694.   SSVAL(outbuf,smb_tpscnt,lparam);    /* tpscnt */
  695.   SSVAL(outbuf,smb_tdscnt,ldata);    /* tdscnt */
  696.   SSVAL(outbuf,smb_mprcnt,mparam);    /* mprcnt */
  697.   SSVAL(outbuf,smb_mdrcnt,mdata);    /* mdrcnt */
  698.   SCVAL(outbuf,smb_msrcnt,msetup);    /* msrcnt */
  699.   SSVAL(outbuf,smb_flags,flags);    /* flags */
  700.   SIVAL(outbuf,smb_timeout,0);        /* timeout */
  701.   SSVAL(outbuf,smb_pscnt,this_lparam);    /* pscnt */
  702.   SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
  703.   SSVAL(outbuf,smb_dscnt,this_ldata);    /* dscnt */
  704.   SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
  705.   SCVAL(outbuf,smb_suwcnt,lsetup);    /* suwcnt */
  706.   for (i=0;i<lsetup;i++)        /* setup[] */
  707.     SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
  708.   p = smb_buf(outbuf);
  709.   if (trans==SMBtrans)
  710.     strcpy(p,name);            /* name[] */
  711.   else
  712.     {
  713.       *p++ = 0;                /* put in a null smb_name */
  714.       *p++ = 'D'; *p++ = ' ';        /* this was added because OS/2 does it */
  715.     }
  716.   if (this_lparam)            /* param[] */
  717.     memcpy(outparam,param,this_lparam);
  718.   if (this_ldata)            /* data[] */
  719.     memcpy(outdata,data,this_ldata);
  720.   set_message(outbuf,14+lsetup,        /* wcnt, bcc */
  721.           PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
  722.  
  723.   show_msg(outbuf);
  724.   send_smb(Client,outbuf);
  725.  
  726.   if (this_ldata < ldata || this_lparam < lparam)
  727.     {
  728.       /* receive interim response */
  729.       if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  730.     {
  731.       DEBUG(0,("%s request failed (%s)\n",
  732.                trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
  733.       return(False);
  734.     }      
  735.  
  736.       tot_data = this_ldata;
  737.       tot_param = this_lparam;
  738.  
  739.       while (tot_data < ldata || tot_param < lparam)
  740.     {
  741.       this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
  742.       this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
  743.  
  744.       set_message(outbuf,trans==SMBtrans?8:9,0,True);
  745.       CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
  746.  
  747.       outparam = smb_buf(outbuf);
  748.       outdata = outparam+this_lparam;
  749.  
  750.       /* secondary request */
  751.       SSVAL(outbuf,smb_tpscnt,lparam);    /* tpscnt */
  752.       SSVAL(outbuf,smb_tdscnt,ldata);    /* tdscnt */
  753.       SSVAL(outbuf,smb_spscnt,this_lparam);    /* pscnt */
  754.       SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
  755.       SSVAL(outbuf,smb_spsdisp,tot_param);    /* psdisp */
  756.       SSVAL(outbuf,smb_sdscnt,this_ldata);    /* dscnt */
  757.       SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
  758.       SSVAL(outbuf,smb_sdsdisp,tot_data);    /* dsdisp */
  759.       if (trans==SMBtrans2)
  760.         SSVAL(outbuf,smb_sfid,fid);        /* fid */
  761.       if (this_lparam)            /* param[] */
  762.         memcpy(outparam,param,this_lparam);
  763.       if (this_ldata)            /* data[] */
  764.         memcpy(outdata,data,this_ldata);
  765.       set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
  766.               PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
  767.  
  768.       show_msg(outbuf);
  769.       send_smb(Client,outbuf);
  770.  
  771.       tot_data += this_ldata;
  772.       tot_param += this_lparam;
  773.     }
  774.     }
  775.  
  776.     return(True);
  777. }
  778.  
  779.  
  780.  
  781. /****************************************************************************
  782. call a remote api
  783. ****************************************************************************/
  784. BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt,
  785.           int *rdrcnt, char *param,char *data, 
  786.           char **rparam, char **rdata)
  787. {
  788.   static char *inbuf=NULL;
  789.   static char *outbuf=NULL;
  790.  
  791.   if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  792.   if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  793.  
  794.   cli_send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
  795.              data,param,NULL,
  796.              drcnt,prcnt,0,
  797.              mdrcnt,mprcnt,0);
  798.  
  799.   return (cli_receive_trans_response(inbuf,SMBtrans,
  800.                      rdrcnt,rprcnt,
  801.                      rdata,rparam));
  802. }
  803.  
  804.  
  805. /****************************************************************************
  806. open the client sockets
  807. ****************************************************************************/
  808. BOOL cli_open_sockets(int port)
  809. {
  810.   static int last_port;
  811.   char *host;
  812.   pstring service2;
  813.   extern int Client;
  814.  
  815.   if (port == 0) port=last_port;
  816.   last_port=port;
  817.  
  818.   strupper(service);
  819.  
  820.   if (*desthost)
  821.     {
  822.       host = desthost;
  823.     }
  824.   else
  825.     {
  826.       pstrcpy(service2,service);
  827.       host = strtok(service2,"\\/");
  828.       pstrcpy(desthost,host);
  829.     }
  830.  
  831.   DEBUG(5,("Opening sockets\n"));
  832.  
  833.   if (*myname == 0)
  834.     get_myname(myname,NULL);
  835.   strupper(myname);
  836.  
  837.   if (!have_ip)
  838.     {
  839.       struct hostent *hp;
  840.  
  841.       if ((hp = Get_Hostbyname(host)) == 0) 
  842.     {
  843.       DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
  844.       return False;
  845.     }
  846.  
  847.       putip((char *)&dest_ip,(char *)hp->h_addr);
  848.     }
  849.  
  850.   Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
  851.   if (Client == -1)
  852.     return False;
  853.  
  854.   DEBUG(5,("Connected\n"));
  855.  
  856.   set_socket_options(Client,user_socket_options);  
  857.  
  858.   return True;
  859. }
  860.  
  861. /****************************************************************************
  862. close and open the connection again
  863. ****************************************************************************/
  864. BOOL cli_reopen_connection(char *inbuf,char *outbuf)
  865. {
  866.   static int open_count=0;
  867.  
  868.   open_count++;
  869.  
  870.   if (open_count>5) return(False);
  871.  
  872.   DEBUG(1,("Trying to re-open connection\n"));
  873.  
  874.   set_message(outbuf,0,0,True);
  875.   SCVAL(outbuf,smb_com,SMBtdis);
  876.   SSVAL(outbuf,smb_tid,cnum);
  877.   cli_setup_pkt(outbuf);
  878.  
  879.   send_smb(Client,outbuf);
  880.   receive_smb(Client,inbuf,SHORT_TIMEOUT);
  881.  
  882.   close_sockets();
  883.   if (!cli_open_sockets(0)) return(False);
  884.  
  885.   return(cli_send_login(inbuf,outbuf,True,True));
  886. }
  887.  
  888. /* error code stuff - put together by Merik Karman
  889.    merik@blackadder.dsh.oz.au */
  890.  
  891. typedef struct
  892. {
  893.   char *name;
  894.   int code;
  895.   char *message;
  896. } err_code_struct;
  897.  
  898. /* Dos Error Messages */
  899. err_code_struct dos_msgs[] = {
  900.   {"ERRbadfunc",1,"Invalid function."},
  901.   {"ERRbadfile",2,"File not found."},
  902.   {"ERRbadpath",3,"Directory invalid."},
  903.   {"ERRnofids",4,"No file descriptors available"},
  904.   {"ERRnoaccess",5,"Access denied."},
  905.   {"ERRbadfid",6,"Invalid file handle."},
  906.   {"ERRbadmcb",7,"Memory control blocks destroyed."},
  907.   {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
  908.   {"ERRbadmem",9,"Invalid memory block address."},
  909.   {"ERRbadenv",10,"Invalid environment."},
  910.   {"ERRbadformat",11,"Invalid format."},
  911.   {"ERRbadaccess",12,"Invalid open mode."},
  912.   {"ERRbaddata",13,"Invalid data."},
  913.   {"ERR",14,"reserved."},
  914.   {"ERRbaddrive",15,"Invalid drive specified."},
  915.   {"ERRremcd",16,"A Delete Directory request attempted  to  remove  the  server's  current directory."},
  916.   {"ERRdiffdevice",17,"Not same device."},
  917.   {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
  918.   {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing  FIDs  on the file."},
  919.   {"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."},
  920.   {"ERRfilexists",80,"The file named in a Create Directory, Make  New  File  or  Link  request already exists."},
  921.   {"ERRbadpipe",230,"Pipe invalid."},
  922.   {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
  923.   {"ERRpipeclosing",232,"Pipe close in progress."},
  924.   {"ERRnotconnected",233,"No process on other end of pipe."},
  925.   {"ERRmoredata",234,"There is more data to be returned."},
  926.   {NULL,-1,NULL}};
  927.  
  928. /* Server Error Messages */
  929. err_code_struct server_msgs[] = {
  930.   {"ERRerror",1,"Non-specific error code."},
  931.   {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
  932.   {"ERRbadtype",3,"reserved."},
  933.   {"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."},
  934.   {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
  935.   {"ERRinvnetname",6,"Invalid network name in tree connect."},
  936.   {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."},
  937.   {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
  938.   {"ERRqtoobig",50,"Print queue full -- no space."},
  939.   {"ERRqeof",51,"EOF on print queue dump."},
  940.   {"ERRinvpfid",52,"Invalid print file FID."},
  941.   {"ERRsmbcmd",64,"The server did not recognize the command received."},
  942.   {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
  943.   {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid  combination of values."},
  944.   {"ERRreserved",68,"reserved."},
  945.   {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."},
  946.   {"ERRreserved",70,"reserved."},
  947.   {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
  948.   {"ERRpaused",81,"Server is paused."},
  949.   {"ERRmsgoff",82,"Not receiving messages."},
  950.   {"ERRnoroom",83,"No room to buffer message."},
  951.   {"ERRrmuns",87,"Too many remote user names."},
  952.   {"ERRtimeout",88,"Operation timed out."},
  953.   {"ERRnoresource",89,"No resources currently available for request."},
  954.   {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
  955.   {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
  956.   {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
  957.   {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
  958.   {"ERRcontmpx",252,"Continue in MPX mode."},
  959.   {"ERRreserved",253,"reserved."},
  960.   {"ERRreserved",254,"reserved."},
  961.   {"ERRnosupport",0xFFFF,"Function not supported."},
  962.   {NULL,-1,NULL}};
  963.  
  964. /* Hard Error Messages */
  965. err_code_struct hard_msgs[] = {
  966.   {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
  967.   {"ERRbadunit",20,"Unknown unit."},
  968.   {"ERRnotready",21,"Drive not ready."},
  969.   {"ERRbadcmd",22,"Unknown command."},
  970.   {"ERRdata",23,"Data error (CRC)."},
  971.   {"ERRbadreq",24,"Bad request structure length."},
  972.   {"ERRseek",25 ,"Seek error."},
  973.   {"ERRbadmedia",26,"Unknown media type."},
  974.   {"ERRbadsector",27,"Sector not found."},
  975.   {"ERRnopaper",28,"Printer out of paper."},
  976.   {"ERRwrite",29,"Write fault."},
  977.   {"ERRread",30,"Read fault."},
  978.   {"ERRgeneral",31,"General failure."},
  979.   {"ERRbadshare",32,"A open conflicts with an existing open."},
  980.   {"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."},
  981.   {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
  982.   {"ERRFCBUnavail",35,"No FCBs are available to process request."},
  983.   {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
  984.   {NULL,-1,NULL}};
  985.  
  986.  
  987. struct
  988. {
  989.   int code;
  990.   char *class;
  991.   err_code_struct *err_msgs;
  992. } err_classes[] = { 
  993.   {0,"SUCCESS",NULL},
  994.   {0x01,"ERRDOS",dos_msgs},
  995.   {0x02,"ERRSRV",server_msgs},
  996.   {0x03,"ERRHRD",hard_msgs},
  997.   {0x04,"ERRXOS",NULL},
  998.   {0xE1,"ERRRMX1",NULL},
  999.   {0xE2,"ERRRMX2",NULL},
  1000.   {0xE3,"ERRRMX3",NULL},
  1001.   {0xFF,"ERRCMD",NULL},
  1002.   {-1,NULL,NULL}};
  1003.  
  1004.  
  1005. /****************************************************************************
  1006. return a SMB error string from a SMB buffer
  1007. ****************************************************************************/
  1008. char *smb_errstr(char *inbuf)
  1009. {
  1010.   static pstring ret;
  1011.   int class = CVAL(inbuf,smb_rcls);
  1012.   int num = SVAL(inbuf,smb_err);
  1013.   int i,j;
  1014.  
  1015.   for (i=0;err_classes[i].class;i++)
  1016.     if (err_classes[i].code == class)
  1017.       {
  1018.     if (err_classes[i].err_msgs)
  1019.       {
  1020.         err_code_struct *err = err_classes[i].err_msgs;
  1021.         for (j=0;err[j].name;j++)
  1022.           if (num == err[j].code)
  1023.         {
  1024.           if (DEBUGLEVEL > 0)
  1025.             sprintf(ret,"%s - %s (%s)",err_classes[i].class,
  1026.                 err[j].name,err[j].message);
  1027.           else
  1028.             sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
  1029.           return ret;
  1030.         }
  1031.       }
  1032.  
  1033.     sprintf(ret,"%s - %d",err_classes[i].class,num);
  1034.     return ret;
  1035.       }
  1036.   
  1037.   sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num);
  1038.   return(ret);
  1039. }
  1040.