9ce2c80d844aba15cc07efdcdb21e15ce82e3030
[kai/samba.git] / source3 / client / clientutil.c
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 smb_login_passwd = "";
37 pstring username="";
38 pstring workgroup=WORKGROUP;
39 BOOL got_pass = False;
40 BOOL connect_as_printer = False;
41 BOOL connect_as_ipc = False;
42
43 char cryptkey[8];
44 BOOL doencrypt=False;
45
46 extern pstring user_socket_options;
47
48 /* 30 second timeout on most commands */
49 #define CLIENT_TIMEOUT (30*1000)
50 #define SHORT_TIMEOUT (5*1000)
51
52 int name_type = 0x20;
53
54 int max_protocol = PROTOCOL_NT1;
55
56 BOOL readbraw_supported = False;
57 BOOL writebraw_supported = False;
58
59 extern int DEBUGLEVEL;
60
61 int cnum = 0;
62 int pid = 0;
63 int gid = 0;
64 int uid = 0;
65 int mid = 0;
66
67 int max_xmit = BUFFER_SIZE;
68
69 BOOL have_ip = False;
70
71 extern struct in_addr dest_ip;
72
73 extern int Protocol;
74
75 extern int Client;
76
77
78 /****************************************************************************
79 setup basics in a outgoing packet
80 ****************************************************************************/
81 void cli_setup_pkt(char *outbuf)
82 {
83   SSVAL(outbuf,smb_pid,pid);
84   SSVAL(outbuf,smb_uid,uid);
85   SSVAL(outbuf,smb_mid,mid);
86   if (Protocol > PROTOCOL_COREPLUS)
87     {
88       SCVAL(outbuf,smb_flg,0x8);
89       SSVAL(outbuf,smb_flg2,0x1);
90     }
91 }
92
93 /****************************************************************************
94 call a remote api
95 ****************************************************************************/
96 BOOL cli_call_api(char *pipe_name, int pipe_name_len,
97                         int prcnt,int drcnt, int srcnt,
98                      int mprcnt,int mdrcnt,
99                      int *rprcnt,int *rdrcnt,
100                      char *param,char *data, uint16 *setup,
101                      char **rparam,char **rdata)
102 {
103   static char *inbuf=NULL;
104   static char *outbuf=NULL;
105
106   if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
107   if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
108
109   if (pipe_name_len == 0) pipe_name_len = strlen(pipe_name);
110
111   cli_send_trans_request(outbuf,SMBtrans,pipe_name, pipe_name_len, 0,0,
112                      data, param, setup,
113                      drcnt, prcnt, srcnt,
114                      mdrcnt, mprcnt, 0);
115
116   return (cli_receive_trans_response(inbuf,SMBtrans,
117                                  rdrcnt,rprcnt,
118                                  rdata,rparam));
119 }
120
121
122 /****************************************************************************
123   receive a SMB trans or trans2 response allocating the necessary memory
124   ****************************************************************************/
125 BOOL cli_receive_trans_response(char *inbuf,int trans,
126                                    int *data_len,int *param_len,
127                                    char **data,char **param)
128 {
129   int total_data=0;
130   int total_param=0;
131   int this_data,this_param;
132
133   *data_len = *param_len = 0;
134
135   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
136   show_msg(inbuf);
137
138   /* sanity check */
139   if (CVAL(inbuf,smb_com) != trans)
140     {
141       DEBUG(0,("Expected %s response, got command 0x%02x\n",
142                trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
143       return(False);
144     }
145   if (CVAL(inbuf,smb_rcls) != 0)
146     return(False);
147
148   /* parse out the lengths */
149   total_data = SVAL(inbuf,smb_tdrcnt);
150   total_param = SVAL(inbuf,smb_tprcnt);
151
152   /* allocate it */
153   *data = Realloc(*data,total_data);
154   *param = Realloc(*param,total_param);
155
156   while (1)
157     {
158       this_data = SVAL(inbuf,smb_drcnt);
159       this_param = SVAL(inbuf,smb_prcnt);
160       if (this_data)
161         memcpy(*data + SVAL(inbuf,smb_drdisp),
162                smb_base(inbuf) + SVAL(inbuf,smb_droff),
163                this_data);
164       if (this_param)
165         memcpy(*param + SVAL(inbuf,smb_prdisp),
166                smb_base(inbuf) + SVAL(inbuf,smb_proff),
167                this_param);
168       *data_len += this_data;
169       *param_len += this_param;
170
171       /* parse out the total lengths again - they can shrink! */
172       total_data = SVAL(inbuf,smb_tdrcnt);
173       total_param = SVAL(inbuf,smb_tprcnt);
174
175       if (total_data <= *data_len && total_param <= *param_len)
176         break;
177
178       client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
179       show_msg(inbuf);
180
181       /* sanity check */
182       if (CVAL(inbuf,smb_com) != trans)
183         {
184           DEBUG(0,("Expected %s response, got command 0x%02x\n",
185                    trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
186           return(False);
187         }
188       if (CVAL(inbuf,smb_rcls) != 0)
189           return(False);
190     }
191   
192   return(True);
193 }
194
195
196
197 /****************************************************************************
198   send a SMB trans or trans2 request
199   ****************************************************************************/
200 BOOL cli_send_trans_request(char *outbuf,int trans,
201                                char *name,int namelen, int fid,int flags,
202                                char *data,char *param,uint16 *setup,
203                                int ldata,int lparam,int lsetup,
204                                int mdata,int mparam,int msetup)
205 {
206   int i;
207   int this_ldata,this_lparam;
208   int tot_data=0,tot_param=0;
209   char *outdata,*outparam;
210   pstring inbuf;
211   char *p;
212
213   this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
214   this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
215
216   bzero(outbuf,smb_size);
217   set_message(outbuf,14+lsetup,0,True);
218   CVAL(outbuf,smb_com) = trans;
219   SSVAL(outbuf,smb_tid,cnum);
220   cli_setup_pkt(outbuf);
221
222   outparam = smb_buf(outbuf)+(trans==SMBtrans ? namelen+1 : 3);
223   outdata = outparam+this_lparam;
224
225   /* primary request */
226   SSVAL(outbuf,smb_tpscnt,lparam);      /* tpscnt */
227   SSVAL(outbuf,smb_tdscnt,ldata);       /* tdscnt */
228   SSVAL(outbuf,smb_mprcnt,mparam);      /* mprcnt */
229   SSVAL(outbuf,smb_mdrcnt,mdata);       /* mdrcnt */
230   SCVAL(outbuf,smb_msrcnt,msetup);      /* msrcnt */
231   SSVAL(outbuf,smb_flags,flags);        /* flags */
232   SIVAL(outbuf,smb_timeout,0);          /* timeout */
233   SSVAL(outbuf,smb_pscnt,this_lparam);  /* pscnt */
234   SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
235   SSVAL(outbuf,smb_dscnt,this_ldata);   /* dscnt */
236   SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
237   SCVAL(outbuf,smb_suwcnt,lsetup);      /* suwcnt */
238   for (i=0;i<lsetup;i++)                /* setup[] */
239     SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
240   p = smb_buf(outbuf);
241   if (trans==SMBtrans)
242     memcpy(p,name, namelen+1);                  /* name[] */
243   else
244     {
245       *p++ = 0;                         /* put in a null smb_name */
246       *p++ = 'D'; *p++ = ' ';           /* this was added because OS/2 does it */
247     }
248   if (this_lparam)                      /* param[] */
249     memcpy(outparam,param,this_lparam);
250   if (this_ldata)                       /* data[] */
251     memcpy(outdata,data,this_ldata);
252   set_message(outbuf,14+lsetup,         /* wcnt, bcc */
253               PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
254
255   show_msg(outbuf);
256   send_smb(Client,outbuf);
257
258   if (this_ldata < ldata || this_lparam < lparam)
259     {
260       /* receive interim response */
261       if (!client_receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
262         {
263           DEBUG(0,("%s request failed (%s)\n",
264                    trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
265           return(False);
266         }      
267
268       tot_data = this_ldata;
269       tot_param = this_lparam;
270
271       while (tot_data < ldata || tot_param < lparam)
272     {
273           this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
274           this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
275
276           set_message(outbuf,trans==SMBtrans?8:9,0,True);
277           CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
278
279           outparam = smb_buf(outbuf);
280           outdata = outparam+this_lparam;
281
282           /* secondary request */
283           SSVAL(outbuf,smb_tpscnt,lparam);      /* tpscnt */
284           SSVAL(outbuf,smb_tdscnt,ldata);       /* tdscnt */
285           SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
286           SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
287           SSVAL(outbuf,smb_spsdisp,tot_param);  /* psdisp */
288           SSVAL(outbuf,smb_sdscnt,this_ldata);  /* dscnt */
289           SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
290           SSVAL(outbuf,smb_sdsdisp,tot_data);   /* dsdisp */
291           if (trans==SMBtrans2)
292             SSVAL(outbuf,smb_sfid,fid);         /* fid */
293           if (this_lparam)                      /* param[] */
294             memcpy(outparam,param,this_lparam);
295           if (this_ldata)                       /* data[] */
296             memcpy(outdata,data,this_ldata);
297           set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
298                       PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
299
300           show_msg(outbuf);
301           send_smb(Client,outbuf);
302
303           tot_data += this_ldata;
304           tot_param += this_lparam;
305         }
306     }
307
308     return(True);
309 }
310
311
312 /****************************************************************************
313 send a session request
314 ****************************************************************************/
315 BOOL cli_send_session_request(char *inbuf,char *outbuf)
316 {
317   fstring dest;
318   char *p;
319   int len = 4;
320   /* send a session request (RFC 8002) */
321
322   strcpy(dest,desthost);
323   p = strchr(dest,'.');
324   if (p) *p = 0;
325
326   /* put in the destination name */
327   p = outbuf+len;
328   name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
329   len += name_len(p);
330
331   /* and my name */
332   p = outbuf+len;
333   name_mangle(myname,p,0);
334   len += name_len(p);
335
336   /* setup the packet length */
337   _smb_setlen(outbuf,len);
338   CVAL(outbuf,0) = 0x81;
339
340   send_smb(Client,outbuf);
341   DEBUG(5,("Sent session request\n"));
342
343   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
344
345   if (CVAL(inbuf,0) == 0x84) /* C. Hoch  9/14/95 Start */
346     {
347       /* For information, here is the response structure.
348        * We do the byte-twiddling to for portability.
349        struct RetargetResponse{
350        unsigned char type;
351        unsigned char flags;
352        int16 length;
353        int32 ip_addr;
354        int16 port;
355        };
356        */
357       extern int Client;
358       int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
359       /* SESSION RETARGET */
360       putip((char *)&dest_ip,inbuf+4);
361
362       close_sockets();
363       Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
364       if (Client == -1)
365         return False;
366
367       DEBUG(3,("Retargeted\n"));
368
369       set_socket_options(Client,user_socket_options);
370
371       /* Try again */
372       return cli_send_session_request(inbuf,outbuf);
373     } /* C. Hoch 9/14/95 End */
374
375
376   if (CVAL(inbuf,0) != 0x82)
377     {
378       int ecode = CVAL(inbuf,4);
379       DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
380                CVAL(inbuf,0),ecode,myname,desthost));
381       switch (ecode)
382         {
383         case 0x80: 
384           DEBUG(0,("Not listening on called name\n")); 
385           DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
386           DEBUG(0,("You may find the -I option useful for this\n"));
387           break;
388         case 0x81: 
389           DEBUG(0,("Not listening for calling name\n")); 
390           DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
391           DEBUG(0,("You may find the -n option useful for this\n"));
392           break;
393         case 0x82: 
394           DEBUG(0,("Called name not present\n")); 
395           DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
396           DEBUG(0,("You may find the -I option useful for this\n"));
397           break;
398         case 0x83: 
399           DEBUG(0,("Called name present, but insufficient resources\n")); 
400           DEBUG(0,("Perhaps you should try again later?\n")); 
401           break;
402         default:
403           DEBUG(0,("Unspecified error 0x%X\n",ecode)); 
404           DEBUG(0,("Your server software is being unfriendly\n"));
405           break;          
406         }
407       return(False);
408     }
409   return(True);
410 }
411
412 static struct {
413   int prot;
414   char *name;
415 } prots[] = {
416   {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
417   {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
418   {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
419   {PROTOCOL_LANMAN1,"LANMAN1.0"},
420   {PROTOCOL_LANMAN2,"LM1.2X002"},
421   {PROTOCOL_LANMAN2,"Samba"},
422   {PROTOCOL_NT1,"NT LM 0.12"},
423   {PROTOCOL_NT1,"NT LANMAN 1.0"},
424   {-1,NULL}
425 };
426
427
428 /****************************************************************************
429 send a login command.  
430 ****************************************************************************/
431 BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
432 {
433   BOOL was_null = (!inbuf && !outbuf);
434   int sesskey=0;
435   time_t servertime = 0;
436   extern int serverzone;
437   int sec_mode=0;
438   int crypt_len;
439   int max_vcs=0;
440   char *pass = NULL;  
441   pstring dev;
442   char *p;
443   int numprots;
444   int tries=0;
445
446   if (was_null)
447     {
448       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
449       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
450     }
451
452 #if AJT
453   if (strstr(service,"IPC$")) connect_as_ipc = True;
454 #endif
455
456   strcpy(dev,"A:");
457   if (connect_as_printer)
458     strcpy(dev,"LPT1:");
459   if (connect_as_ipc)
460     strcpy(dev,"IPC");
461
462
463   if (start_session && !cli_send_session_request(inbuf,outbuf))
464     {
465       if (was_null)
466         {
467           free(inbuf);
468           free(outbuf);
469         }      
470       return(False);
471     }
472
473   bzero(outbuf,smb_size);
474
475   /* setup the protocol strings */
476   {
477     int plength;
478
479     for (plength=0,numprots=0;
480          prots[numprots].name && prots[numprots].prot<=max_protocol;
481          numprots++)
482       plength += strlen(prots[numprots].name)+2;
483     
484     set_message(outbuf,0,plength,True);
485
486     p = smb_buf(outbuf);
487     for (numprots=0;
488          prots[numprots].name && prots[numprots].prot<=max_protocol;
489          numprots++)
490       {
491         *p++ = 2;
492         strcpy(p,prots[numprots].name);
493         p += strlen(p) + 1;
494       }
495   }
496
497   CVAL(outbuf,smb_com) = SMBnegprot;
498   cli_setup_pkt(outbuf);
499
500   CVAL(smb_buf(outbuf),0) = 2;
501
502   send_smb(Client,outbuf);
503   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
504
505   show_msg(inbuf);
506
507   if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
508     {
509       DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
510             myname,desthost,smb_errstr(inbuf)));
511       if (was_null)
512         {
513           free(inbuf);
514           free(outbuf);
515         }
516       return(False);
517     }
518
519   Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
520
521
522   if (Protocol < PROTOCOL_LANMAN1) {    
523           /* no extra params */
524   } else if (Protocol < PROTOCOL_NT1) {
525     sec_mode = SVAL(inbuf,smb_vwv1);
526     max_xmit = SVAL(inbuf,smb_vwv2);
527     sesskey = IVAL(inbuf,smb_vwv6);
528     serverzone = SVALS(inbuf,smb_vwv10)*60;
529     /* this time is converted to GMT by make_unix_date */
530     servertime = make_unix_date(inbuf+smb_vwv8);
531     if (Protocol >= PROTOCOL_COREPLUS) {
532       readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
533       writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
534     }
535     crypt_len = smb_buflen(inbuf);
536     memcpy(cryptkey,smb_buf(inbuf),8);
537     DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
538     max_vcs = SVAL(inbuf,smb_vwv4); 
539     DEBUG(3,("max vcs %d\n",max_vcs)); 
540     DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
541   } else {
542     /* NT protocol */
543     sec_mode = CVAL(inbuf,smb_vwv1);
544     max_xmit = IVAL(inbuf,smb_vwv3+1);
545     sesskey = IVAL(inbuf,smb_vwv7+1);
546     serverzone = SVALS(inbuf,smb_vwv15+1)*60;
547     /* this time arrives in real GMT */
548     servertime = interpret_long_date(inbuf+smb_vwv11+1);
549     crypt_len = CVAL(inbuf,smb_vwv16+1);
550     memcpy(cryptkey,smb_buf(inbuf),8);
551     if (IVAL(inbuf,smb_vwv9+1) & 1)
552       readbraw_supported = writebraw_supported = True;      
553     DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
554     max_vcs = SVAL(inbuf,smb_vwv2+1); 
555     DEBUG(3,("max vcs %d\n",max_vcs));
556     DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
557     DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
558   }
559
560   DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
561   DEBUG(3,("max xmt %d\n",max_xmit));
562   DEBUG(3,("Got %d byte crypt key\n",crypt_len));
563   DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
564
565   doencrypt = ((sec_mode & 2) != 0);
566
567   if (servertime) {
568     static BOOL done_time = False;
569     if (!done_time) {
570       DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
571                asctime(LocalTime(&servertime)),
572                -(double)(serverzone/3600.0)));
573       done_time = True;
574     }
575   }
576
577  get_pass:
578
579   if (got_pass)
580     pass = password;
581   else
582     pass = (char *)getpass("Password: ");
583
584   pstrcpy(smb_login_passwd, pass);
585
586   /* use a blank username for the 2nd try with a blank password */
587   if (tries++ && !*pass)
588     *username = 0;
589
590   if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
591     {
592       fstring pword;
593       int passlen = strlen(pass)+1;
594       strcpy(pword,pass);      
595
596       if (doencrypt && *pass) {
597         DEBUG(3,("Using encrypted passwords\n"));
598         passlen = 24;
599         SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
600       }
601
602       /* if in share level security then don't send a password now */
603       if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} 
604
605       /* send a session setup command */
606       bzero(outbuf,smb_size);
607
608       if (Protocol < PROTOCOL_NT1) {
609         set_message(outbuf,10,1 + strlen(username) + passlen,True);
610         CVAL(outbuf,smb_com) = SMBsesssetupX;
611         cli_setup_pkt(outbuf);
612
613         CVAL(outbuf,smb_vwv0) = 0xFF;
614         SSVAL(outbuf,smb_vwv2,max_xmit);
615         SSVAL(outbuf,smb_vwv3,2);
616         SSVAL(outbuf,smb_vwv4,max_vcs-1);
617         SIVAL(outbuf,smb_vwv5,sesskey);
618         SSVAL(outbuf,smb_vwv7,passlen);
619         p = smb_buf(outbuf);
620         memcpy(p,pword,passlen);
621         p += passlen;
622         strcpy(p,username);
623       } else {
624         if (!doencrypt) passlen--;
625         /* for Win95 */
626         set_message(outbuf,13,0,True);
627         CVAL(outbuf,smb_com) = SMBsesssetupX;
628         cli_setup_pkt(outbuf);
629
630         CVAL(outbuf,smb_vwv0) = 0xFF;
631         SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
632         SSVAL(outbuf,smb_vwv3,2);
633         SSVAL(outbuf,smb_vwv4,getpid());
634         SIVAL(outbuf,smb_vwv5,sesskey);
635         SSVAL(outbuf,smb_vwv7,passlen);
636         SSVAL(outbuf,smb_vwv8,0);
637         p = smb_buf(outbuf);
638         memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
639         strcpy(p,username);p = skip_string(p,1);
640         strcpy(p,workgroup);p = skip_string(p,1);
641         strcpy(p,"Unix");p = skip_string(p,1);
642         strcpy(p,"Samba");p = skip_string(p,1);
643         set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
644       }
645
646       send_smb(Client,outbuf);
647       client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
648
649       show_msg(inbuf);
650
651       if (CVAL(inbuf,smb_rcls) != 0)
652         {
653           if (! *pass &&
654               ((CVAL(inbuf,smb_rcls) == ERRDOS && 
655                 SVAL(inbuf,smb_err) == ERRnoaccess) ||
656                (CVAL(inbuf,smb_rcls) == ERRSRV && 
657                 SVAL(inbuf,smb_err) == ERRbadpw)))
658             {
659               got_pass = False;
660               DEBUG(3,("resending login\n"));
661               goto get_pass;
662             }
663               
664           DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s   %s\n",
665                 username,myname,desthost,smb_errstr(inbuf)));
666           DEBUG(0,("You might find the -U, -W or -n options useful\n"));
667           DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
668           DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
669           if (was_null)
670             {
671               free(inbuf);
672               free(outbuf);
673             }
674           return(False);
675         }
676
677       if (Protocol >= PROTOCOL_NT1) {
678         char *domain,*os,*lanman;
679         p = smb_buf(inbuf);
680         os = p;
681         lanman = skip_string(os,1);
682         domain = skip_string(lanman,1);
683         if (*domain || *os || *lanman)
684           DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
685       }
686
687       /* use the returned uid from now on */
688       if (SVAL(inbuf,smb_uid) != uid)
689         DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
690               SVAL(inbuf,smb_uid),uid));
691       uid = SVAL(inbuf,smb_uid);
692     }
693
694   if (sec_mode & 1) {
695           if (SVAL(inbuf, smb_vwv2) & 1)
696                   DEBUG(1,("connected as guest "));
697           DEBUG(1,("security=user\n"));
698   } else {
699           DEBUG(1,("security=share\n"));
700   }
701
702   /* now we've got a connection - send a tcon message */
703   bzero(outbuf,smb_size);
704
705   if (strncmp(service,"\\\\",2) != 0)
706     {
707       DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
708       DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
709     }
710
711
712  again2:
713
714   {
715     int passlen = strlen(pass)+1;
716     fstring pword;
717     strcpy(pword,pass);
718
719     if (doencrypt && *pass) {
720       passlen=24;
721       SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);      
722     }
723
724     /* if in user level security then don't send a password now */
725     if ((sec_mode & 1)) {
726       strcpy(pword, ""); passlen=1; 
727     }
728
729     if (Protocol <= PROTOCOL_COREPLUS) {
730       set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
731       CVAL(outbuf,smb_com) = SMBtcon;
732       cli_setup_pkt(outbuf);
733
734       p = smb_buf(outbuf);
735       *p++ = 0x04;
736       strcpy(p, service);
737       p = skip_string(p,1);
738       *p++ = 0x04;
739       memcpy(p,pword,passlen);
740       p += passlen;
741       *p++ = 0x04;
742       strcpy(p, dev);
743     }
744     else {
745       set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
746       CVAL(outbuf,smb_com) = SMBtconX;
747       cli_setup_pkt(outbuf);
748   
749       SSVAL(outbuf,smb_vwv0,0xFF);
750       SSVAL(outbuf,smb_vwv3,passlen);
751   
752       p = smb_buf(outbuf);
753       memcpy(p,pword,passlen);
754       p += passlen;
755       strcpy(p,service);
756       p = skip_string(p,1);
757       strcpy(p,dev);
758     }
759   }
760
761   send_smb(Client,outbuf);
762   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
763
764   /* trying again with a blank password */
765   if (CVAL(inbuf,smb_rcls) != 0 && 
766       (int)strlen(pass) > 0 && 
767       !doencrypt &&
768       Protocol >= PROTOCOL_LANMAN1)
769     {
770       DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
771       strcpy(pass,"");
772       goto again2;
773     }  
774
775   if (CVAL(inbuf,smb_rcls) != 0)
776     {
777       DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
778       DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
779       DEBUG(0,("Some servers insist that these be in uppercase\n"));
780       if (was_null)
781         {
782           free(inbuf);
783           free(outbuf);
784         }
785       return(False);
786     }
787   
788
789   if (Protocol <= PROTOCOL_COREPLUS) {
790     max_xmit = SVAL(inbuf,smb_vwv0);
791
792     cnum = SVAL(inbuf,smb_vwv1);
793   }
794   else {
795     max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
796     if (max_xmit <= 0)
797       max_xmit = BUFFER_SIZE - 4;
798
799     cnum = SVAL(inbuf,smb_tid);
800   }
801
802   DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
803
804   if (was_null)
805     {
806       free(inbuf);
807       free(outbuf);
808     }
809
810   return True;
811 }
812
813
814 /****************************************************************************
815 send a logout command
816 ****************************************************************************/
817 void cli_send_logout(void )
818 {
819   pstring inbuf,outbuf;
820
821   DEBUG(5,("cli_send_logout\n"));
822
823   bzero(outbuf,smb_size);
824   set_message(outbuf,0,0,True);
825   CVAL(outbuf,smb_com) = SMBtdis;
826   SSVAL(outbuf,smb_tid,cnum);
827   cli_setup_pkt(outbuf);
828
829   send_smb(Client,outbuf);
830   client_receive_smb(Client,inbuf,SHORT_TIMEOUT);
831
832   if (CVAL(inbuf,smb_rcls) != 0)
833     {
834       DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
835     }
836
837   
838 #ifdef STATS
839   stats_report();
840 #endif
841   exit(0);
842 }
843
844
845 /****************************************************************************
846 open the client sockets
847 ****************************************************************************/
848 BOOL cli_open_sockets(int port )
849 {
850   static int last_port;
851   char *host;
852   pstring service2;
853   extern int Client;
854   BOOL failed = True;
855
856   if (port == 0) port=last_port;
857   last_port=port;
858
859   strupper(service);
860
861   if (*desthost)
862     {
863       host = desthost;
864     }
865   else
866     {
867       strcpy(service2,service);
868       host = strtok(service2,"\\/");
869       if (!host) {
870         DEBUG(0,("Badly formed host name\n"));
871         return(False);
872       }
873       strcpy(desthost,host);
874     }
875
876   if (!(*myname)) {
877       get_myname(myname,NULL);
878   }
879   strupper(myname);
880
881   DEBUG(3,("Opening sockets\n"));
882
883   if (!have_ip)
884     {
885       struct hostent *hp;
886
887       if ((hp = Get_Hostbyname(host)))
888       {
889         putip((char *)&dest_ip,(char *)hp->h_addr);
890         failed = False;
891       }
892       else
893       {
894 #ifdef USENMB
895         /* Try and resolve the name with the netbios server */
896         int             bcast, count;
897         struct in_addr *ip_list;
898
899         if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
900                                     interpret_addr(lp_socket_address()))) != -1) {
901           set_socket_options(bcast, "SO_BROADCAST");
902
903           if ((ip_list = name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
904                                     &count,0)) {
905                   dest_ip = ip_list[0];
906                   free(ip_list);
907                   failed = False;
908           }
909           close (bcast);
910         }
911 #endif
912         if (failed) {
913           DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
914           return False;
915         }
916       }
917     }
918
919   Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
920   if (Client == -1)
921     return False;
922
923   DEBUG(3,("Connected\n"));
924   
925   set_socket_options(Client,user_socket_options);  
926   
927   return True;
928 }
929
930 /****************************************************************************
931 close and open the connection again
932 ****************************************************************************/
933 BOOL cli_reopen_connection(char *inbuf,char *outbuf)
934 {
935   static int open_count=0;
936
937   open_count++;
938
939   if (open_count>5) return(False);
940
941   DEBUG(1,("Trying to re-open connection\n"));
942
943   set_message(outbuf,0,0,True);
944   SCVAL(outbuf,smb_com,SMBtdis);
945   SSVAL(outbuf,smb_tid,cnum);
946   cli_setup_pkt(outbuf);
947
948   send_smb(Client,outbuf);
949   client_receive_smb(Client,inbuf,SHORT_TIMEOUT);
950
951   close_sockets();
952   if (!cli_open_sockets(0)) return(False);
953
954   return(cli_send_login(inbuf,outbuf,True,True));
955 }
956