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