This is it ! The mega-merge of the JRA_NMBD_REWRITE branch
[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   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       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 (!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   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   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_NT1) {    
523     sec_mode = SVAL(inbuf,smb_vwv1);
524     max_xmit = SVAL(inbuf,smb_vwv2);
525     sesskey = IVAL(inbuf,smb_vwv6);
526     serverzone = SVALS(inbuf,smb_vwv10)*60;
527     /* this time is converted to GMT by make_unix_date */
528     servertime = make_unix_date(inbuf+smb_vwv8);
529     if (Protocol >= PROTOCOL_COREPLUS) {
530       readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
531       writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
532     }
533     crypt_len = smb_buflen(inbuf);
534     memcpy(cryptkey,smb_buf(inbuf),8);
535     DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
536     max_vcs = SVAL(inbuf,smb_vwv4); 
537     DEBUG(3,("max vcs %d\n",max_vcs)); 
538     DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
539   } else {
540     /* NT protocol */
541     sec_mode = CVAL(inbuf,smb_vwv1);
542     max_xmit = IVAL(inbuf,smb_vwv3+1);
543     sesskey = IVAL(inbuf,smb_vwv7+1);
544     serverzone = SVALS(inbuf,smb_vwv15+1)*60;
545     /* this time arrives in real GMT */
546     servertime = interpret_long_date(inbuf+smb_vwv11+1);
547     crypt_len = CVAL(inbuf,smb_vwv16+1);
548     memcpy(cryptkey,smb_buf(inbuf),8);
549     if (IVAL(inbuf,smb_vwv9+1) & 1)
550       readbraw_supported = writebraw_supported = True;      
551     DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
552     max_vcs = SVAL(inbuf,smb_vwv2+1); 
553     DEBUG(3,("max vcs %d\n",max_vcs));
554     DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
555     DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
556   }
557
558   DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
559   DEBUG(3,("max xmt %d\n",max_xmit));
560   DEBUG(3,("Got %d byte crypt key\n",crypt_len));
561   DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
562
563   doencrypt = ((sec_mode & 2) != 0);
564
565   if (servertime) {
566     static BOOL done_time = False;
567     if (!done_time) {
568       DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
569                asctime(LocalTime(&servertime)),
570                -(double)(serverzone/3600.0)));
571       done_time = True;
572     }
573   }
574
575  get_pass:
576
577   if (got_pass)
578     pass = password;
579   else
580     pass = (char *)getpass("Password: ");
581
582   pstrcpy(smb_login_passwd, pass);
583
584   /* use a blank username for the 2nd try with a blank password */
585   if (tries++ && !*pass)
586     *username = 0;
587
588   if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
589     {
590       fstring pword;
591       int passlen = strlen(pass)+1;
592       strcpy(pword,pass);      
593
594       if (doencrypt && *pass) {
595         DEBUG(3,("Using encrypted passwords\n"));
596         passlen = 24;
597         SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
598       }
599
600       /* if in share level security then don't send a password now */
601       if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} 
602
603       /* send a session setup command */
604       bzero(outbuf,smb_size);
605
606       if (Protocol < PROTOCOL_NT1) {
607         set_message(outbuf,10,1 + strlen(username) + passlen,True);
608         CVAL(outbuf,smb_com) = SMBsesssetupX;
609         cli_setup_pkt(outbuf);
610
611         CVAL(outbuf,smb_vwv0) = 0xFF;
612         SSVAL(outbuf,smb_vwv2,max_xmit);
613         SSVAL(outbuf,smb_vwv3,2);
614         SSVAL(outbuf,smb_vwv4,max_vcs-1);
615         SIVAL(outbuf,smb_vwv5,sesskey);
616         SSVAL(outbuf,smb_vwv7,passlen);
617         p = smb_buf(outbuf);
618         memcpy(p,pword,passlen);
619         p += passlen;
620         strcpy(p,username);
621       } else {
622         if (!doencrypt) passlen--;
623         /* for Win95 */
624         set_message(outbuf,13,0,True);
625         CVAL(outbuf,smb_com) = SMBsesssetupX;
626         cli_setup_pkt(outbuf);
627
628         CVAL(outbuf,smb_vwv0) = 0xFF;
629         SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
630         SSVAL(outbuf,smb_vwv3,2);
631         SSVAL(outbuf,smb_vwv4,getpid());
632         SIVAL(outbuf,smb_vwv5,sesskey);
633         SSVAL(outbuf,smb_vwv7,passlen);
634         SSVAL(outbuf,smb_vwv8,0);
635         p = smb_buf(outbuf);
636         memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
637         strcpy(p,username);p = skip_string(p,1);
638         strcpy(p,workgroup);p = skip_string(p,1);
639         strcpy(p,"Unix");p = skip_string(p,1);
640         strcpy(p,"Samba");p = skip_string(p,1);
641         set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
642       }
643
644       send_smb(Client,outbuf);
645       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
646
647       show_msg(inbuf);
648
649       if (CVAL(inbuf,smb_rcls) != 0)
650         {
651           if (! *pass &&
652               ((CVAL(inbuf,smb_rcls) == ERRDOS && 
653                 SVAL(inbuf,smb_err) == ERRnoaccess) ||
654                (CVAL(inbuf,smb_rcls) == ERRSRV && 
655                 SVAL(inbuf,smb_err) == ERRbadpw)))
656             {
657               got_pass = False;
658               DEBUG(3,("resending login\n"));
659               goto get_pass;
660             }
661               
662           DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s   %s\n",
663                 username,myname,desthost,smb_errstr(inbuf)));
664           DEBUG(0,("You might find the -U, -W or -n options useful\n"));
665           DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
666           DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
667           if (was_null)
668             {
669               free(inbuf);
670               free(outbuf);
671             }
672           return(False);
673         }
674
675       if (Protocol >= PROTOCOL_NT1) {
676         char *domain,*os,*lanman;
677         p = smb_buf(inbuf);
678         os = p;
679         lanman = skip_string(os,1);
680         domain = skip_string(lanman,1);
681         if (*domain || *os || *lanman)
682           DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
683       }
684
685       /* use the returned uid from now on */
686       if (SVAL(inbuf,smb_uid) != uid)
687         DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
688               SVAL(inbuf,smb_uid),uid));
689       uid = SVAL(inbuf,smb_uid);
690     }
691
692   if (sec_mode & 1) {
693           if (SVAL(inbuf, smb_vwv2) & 1)
694                   DEBUG(1,("connected as guest "));
695           DEBUG(1,("security=user\n"));
696   } else {
697           DEBUG(1,("security=share\n"));
698   }
699
700   /* now we've got a connection - send a tcon message */
701   bzero(outbuf,smb_size);
702
703   if (strncmp(service,"\\\\",2) != 0)
704     {
705       DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
706       DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
707     }
708
709
710  again2:
711
712   {
713     int passlen = strlen(pass)+1;
714     fstring pword;
715     strcpy(pword,pass);
716
717     if (doencrypt && *pass) {
718       passlen=24;
719       SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);      
720     }
721
722     /* if in user level security then don't send a password now */
723     if ((sec_mode & 1)) {
724       strcpy(pword, ""); passlen=1; 
725     }
726
727     if (Protocol <= PROTOCOL_COREPLUS) {
728       set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
729       CVAL(outbuf,smb_com) = SMBtcon;
730       cli_setup_pkt(outbuf);
731
732       p = smb_buf(outbuf);
733       *p++ = 0x04;
734       strcpy(p, service);
735       p = skip_string(p,1);
736       *p++ = 0x04;
737       memcpy(p,pword,passlen);
738       p += passlen;
739       *p++ = 0x04;
740       strcpy(p, dev);
741     }
742     else {
743       set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
744       CVAL(outbuf,smb_com) = SMBtconX;
745       cli_setup_pkt(outbuf);
746   
747       SSVAL(outbuf,smb_vwv0,0xFF);
748       SSVAL(outbuf,smb_vwv3,passlen);
749   
750       p = smb_buf(outbuf);
751       memcpy(p,pword,passlen);
752       p += passlen;
753       strcpy(p,service);
754       p = skip_string(p,1);
755       strcpy(p,dev);
756     }
757   }
758
759   send_smb(Client,outbuf);
760   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
761
762   /* trying again with a blank password */
763   if (CVAL(inbuf,smb_rcls) != 0 && 
764       (int)strlen(pass) > 0 && 
765       !doencrypt &&
766       Protocol >= PROTOCOL_LANMAN1)
767     {
768       DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
769       strcpy(pass,"");
770       goto again2;
771     }  
772
773   if (CVAL(inbuf,smb_rcls) != 0)
774     {
775       DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
776       DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
777       DEBUG(0,("Some servers insist that these be in uppercase\n"));
778       if (was_null)
779         {
780           free(inbuf);
781           free(outbuf);
782         }
783       return(False);
784     }
785   
786
787   if (Protocol <= PROTOCOL_COREPLUS) {
788     max_xmit = SVAL(inbuf,smb_vwv0);
789
790     cnum = SVAL(inbuf,smb_vwv1);
791   }
792   else {
793     max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
794     if (max_xmit <= 0)
795       max_xmit = BUFFER_SIZE - 4;
796
797     cnum = SVAL(inbuf,smb_tid);
798   }
799
800   DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
801
802   if (was_null)
803     {
804       free(inbuf);
805       free(outbuf);
806     }
807
808   return True;
809 }
810
811
812 /****************************************************************************
813 send a logout command
814 ****************************************************************************/
815 void cli_send_logout(void )
816 {
817   pstring inbuf,outbuf;
818
819   DEBUG(5,("cli_send_logout\n"));
820
821   bzero(outbuf,smb_size);
822   set_message(outbuf,0,0,True);
823   CVAL(outbuf,smb_com) = SMBtdis;
824   SSVAL(outbuf,smb_tid,cnum);
825   cli_setup_pkt(outbuf);
826
827   send_smb(Client,outbuf);
828   receive_smb(Client,inbuf,SHORT_TIMEOUT);
829
830   if (CVAL(inbuf,smb_rcls) != 0)
831     {
832       DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
833     }
834
835   
836 #ifdef STATS
837   stats_report();
838 #endif
839   exit(0);
840 }
841
842
843 /****************************************************************************
844 open the client sockets
845 ****************************************************************************/
846 BOOL cli_open_sockets(int port )
847 {
848   static int last_port;
849   char *host;
850   pstring service2;
851   extern int Client;
852   BOOL failed = True;
853
854   if (port == 0) port=last_port;
855   last_port=port;
856
857   strupper(service);
858
859   if (*desthost)
860     {
861       host = desthost;
862     }
863   else
864     {
865       strcpy(service2,service);
866       host = strtok(service2,"\\/");
867       if (!host) {
868         DEBUG(0,("Badly formed host name\n"));
869         return(False);
870       }
871       strcpy(desthost,host);
872     }
873
874   if (!(*myname)) {
875       get_myname(myname,NULL);
876   }
877   strupper(myname);
878
879   DEBUG(3,("Opening sockets\n"));
880
881   if (!have_ip)
882     {
883       struct hostent *hp;
884
885       if ((hp = Get_Hostbyname(host)))
886       {
887         putip((char *)&dest_ip,(char *)hp->h_addr);
888         failed = False;
889       }
890       else
891       {
892 #ifdef USENMB
893         /* Try and resolve the name with the netbios server */
894         int             bcast, count;
895         struct in_addr *ip_list;
896
897         if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
898                                     interpret_addr(lp_socket_address()))) != -1) {
899           set_socket_options(bcast, "SO_BROADCAST");
900
901           if ((ip_list = name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
902                                     &count,0)) {
903                   dest_ip = ip_list[0];
904                   free(ip_list);
905                   failed = False;
906           }
907           close (bcast);
908         }
909 #endif
910         if (failed) {
911           DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
912           return False;
913         }
914       }
915     }
916
917   Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
918   if (Client == -1)
919     return False;
920
921   DEBUG(3,("Connected\n"));
922   
923   set_socket_options(Client,user_socket_options);  
924   
925   return True;
926 }
927
928 /****************************************************************************
929 close and open the connection again
930 ****************************************************************************/
931 BOOL cli_reopen_connection(char *inbuf,char *outbuf)
932 {
933   static int open_count=0;
934
935   open_count++;
936
937   if (open_count>5) return(False);
938
939   DEBUG(1,("Trying to re-open connection\n"));
940
941   set_message(outbuf,0,0,True);
942   SCVAL(outbuf,smb_com,SMBtdis);
943   SSVAL(outbuf,smb_tid,cnum);
944   cli_setup_pkt(outbuf);
945
946   send_smb(Client,outbuf);
947   receive_smb(Client,inbuf,SHORT_TIMEOUT);
948
949   close_sockets();
950   if (!cli_open_sockets(0)) return(False);
951
952   return(cli_send_login(inbuf,outbuf,True,True));
953 }
954