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