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