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