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