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