converted cli_list()
[kai/samba.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    client connect/disconnect routines
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 #define NO_SYSLOG
23
24 #include "includes.h"
25
26
27 static  struct {
28     int prot;
29     char *name;
30   }
31 prots[] = 
32     {
33       {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
34       {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
35       {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
36       {PROTOCOL_LANMAN1,"LANMAN1.0"},
37       {PROTOCOL_LANMAN2,"LM1.2X002"},
38       {PROTOCOL_LANMAN2,"Samba"},
39       {PROTOCOL_NT1,"NT LANMAN 1.0"},
40       {PROTOCOL_NT1,"NT LM 0.12"},
41       {-1,NULL}
42     };
43
44
45 /****************************************************************************
46  Send a session setup. The username and workgroup is in UNIX character
47  format and must be converted to DOS codepage format before sending. If the
48  password is in plaintext, the same should be done.
49 ****************************************************************************/
50
51 BOOL cli_session_setup(struct cli_state *cli, 
52                        char *user, 
53                        char *pass, int passlen,
54                        char *ntpass, int ntpasslen,
55                        char *workgroup)
56 {
57         char *p;
58         fstring pword, ntpword;
59         fstring user2;
60
61         /* allow for workgroups as part of the username */
62         fstrcpy(user2, user);
63         if ((p=strchr(user2,'\\')) || (p=strchr(user2,'/'))) {
64                 *p = 0;
65                 user = p+1;
66                 workgroup = user2;
67         }
68
69         if (cli->protocol < PROTOCOL_LANMAN1)
70                 return True;
71
72         if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
73                 return False;
74         }
75
76         if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
77                 /* Null session connect. */
78                 pword[0] = '\0';
79                 ntpword[0] = '\0';
80         } else {
81                 if ((cli->sec_mode & 2) && passlen != 24) {
82                         /*
83                          * Encrypted mode needed, and non encrypted password supplied.
84                          */
85                         passlen = 24;
86                         ntpasslen = 24;
87                         fstrcpy(pword, pass);
88                         unix_to_dos(pword,True);
89                         fstrcpy(ntpword, ntpass);;
90                         SMBencrypt((uchar *)pword,(uchar *)cli->cryptkey,(uchar *)pword);
91                         SMBNTencrypt((uchar *)ntpword,(uchar *)cli->cryptkey,(uchar *)ntpword);
92                 } else if ((cli->sec_mode & 2) && passlen == 24) {
93                         /*
94                          * Encrypted mode needed, and encrypted password supplied.
95                          */
96                         memcpy(pword, pass, passlen);
97                         if(ntpasslen == 24) {
98                                 memcpy(ntpword, ntpass, ntpasslen);
99                         } else {
100                                 fstrcpy(ntpword, "");
101                                 ntpasslen = 0;
102                         }
103                 } else {
104                         /*
105                          * Plaintext mode needed, assume plaintext supplied.
106                          */
107                         passlen = clistr_push(cli, pword, pass, -1, CLISTR_CONVERT|CLISTR_TERMINATE);
108                         fstrcpy(ntpword, "");
109                         ntpasslen = 0;
110                 }
111         }
112
113         /* if in share level security then don't send a password now */
114         if (!(cli->sec_mode & 1)) {
115                 fstrcpy(pword, "");
116                 passlen=1;
117                 fstrcpy(ntpword, "");
118                 ntpasslen=1;
119         } 
120
121         /* send a session setup command */
122         memset(cli->outbuf,'\0',smb_size);
123
124         if (cli->protocol < PROTOCOL_NT1)
125         {
126                 set_message(cli->outbuf,10, 0, True);
127                 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
128                 cli_setup_packet(cli);
129
130                 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
131                 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
132                 SSVAL(cli->outbuf,smb_vwv3,2);
133                 SSVAL(cli->outbuf,smb_vwv4,1);
134                 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
135                 SSVAL(cli->outbuf,smb_vwv7,passlen);
136                 p = smb_buf(cli->outbuf);
137                 memcpy(p,pword,passlen);
138                 p += passlen;
139                 p += clistr_push(cli, p, user, -1, CLISTR_CONVERT|CLISTR_UPPER|CLISTR_TERMINATE);
140                 set_message(cli->outbuf,10,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
141         }
142         else
143         {
144                 uint32 capabilities;
145
146                 capabilities = CAP_NT_SMBS;
147                 if (cli->use_level_II_oplocks) 
148                         capabilities |= CAP_LEVEL_II_OPLOCKS;
149                 if (getenv("USE_UNICODE") && 
150                     (cli->capabilities & CAP_UNICODE)) {
151                         capabilities |= CAP_UNICODE;
152                 }
153                 set_message(cli->outbuf,13,0,True);
154                 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
155                 cli_setup_packet(cli);
156                 
157                 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
158                 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
159                 SSVAL(cli->outbuf,smb_vwv3,2);
160                 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
161                 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
162                 SSVAL(cli->outbuf,smb_vwv7,passlen);
163                 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
164                 SIVAL(cli->outbuf,smb_vwv11,capabilities);
165                 p = smb_buf(cli->outbuf);
166                 memcpy(p,pword,passlen); 
167                 p += SVAL(cli->outbuf,smb_vwv7);
168                 memcpy(p,ntpword,ntpasslen); 
169                 p += SVAL(cli->outbuf,smb_vwv8);
170                 p += clistr_push(cli, p, user, -1, CLISTR_CONVERT|CLISTR_TERMINATE|CLISTR_UPPER);
171                 p += clistr_push(cli, p, workgroup, -1, CLISTR_CONVERT|CLISTR_TERMINATE|CLISTR_UPPER);
172                 p += clistr_push(cli, p, "Unix", -1, CLISTR_CONVERT|CLISTR_TERMINATE);
173                 p += clistr_push(cli, p, "Samba", -1, CLISTR_CONVERT|CLISTR_TERMINATE);
174                 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
175         }
176
177       cli_send_smb(cli);
178       if (!cli_receive_smb(cli))
179               return False;
180
181       show_msg(cli->inbuf);
182
183       if (CVAL(cli->inbuf,smb_rcls) != 0) {
184               return False;
185       }
186
187       /* use the returned vuid from now on */
188       cli->vuid = SVAL(cli->inbuf,smb_uid);
189
190       if (cli->protocol >= PROTOCOL_NT1) {
191               /*
192                * Save off some of the connected server
193                * info.
194                */
195               char *p = smb_buf(cli->inbuf);
196               p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT);
197               p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT);
198               p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT);
199       }
200
201       fstrcpy(cli->user_name, user);
202
203       return True;
204 }
205
206 /****************************************************************************
207  Send a uloggoff.
208 *****************************************************************************/
209
210 BOOL cli_ulogoff(struct cli_state *cli)
211 {
212         memset(cli->outbuf,'\0',smb_size);
213         set_message(cli->outbuf,2,0,True);
214         CVAL(cli->outbuf,smb_com) = SMBulogoffX;
215         cli_setup_packet(cli);
216         SSVAL(cli->outbuf,smb_vwv0,0xFF);
217         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
218
219         cli_send_smb(cli);
220         if (!cli_receive_smb(cli))
221                 return False;
222
223         return CVAL(cli->inbuf,smb_rcls) == 0;
224 }
225
226 /****************************************************************************
227 send a tconX
228 ****************************************************************************/
229 BOOL cli_send_tconX(struct cli_state *cli, 
230                     char *share, char *dev, char *pass, int passlen)
231 {
232         fstring fullshare, pword, dos_pword;
233         char *p;
234         memset(cli->outbuf,'\0',smb_size);
235         memset(cli->inbuf,'\0',smb_size);
236
237         fstrcpy(cli->share, share);
238
239         /* in user level security don't send a password now */
240         if (cli->sec_mode & 1) {
241                 passlen = 1;
242                 pass = "";
243         }
244
245         if ((cli->sec_mode & 2) && *pass && passlen != 24) {
246                 /*
247                  * Non-encrypted passwords - convert to DOS codepage before encryption.
248                  */
249                 passlen = 24;
250                 fstrcpy(dos_pword,pass);
251                 unix_to_dos(dos_pword,True);
252                 SMBencrypt((uchar *)dos_pword,(uchar *)cli->cryptkey,(uchar *)pword);
253         } else {
254                 if((cli->sec_mode & 3) == 0) {
255                         /*
256                          * Non-encrypted passwords - convert to DOS codepage before using.
257                          */
258                         passlen = clistr_push(cli, pword, pass, -1, CLISTR_CONVERT|CLISTR_TERMINATE);
259                 } else {
260                         memcpy(pword, pass, passlen);
261                 }
262         }
263
264         slprintf(fullshare, sizeof(fullshare)-1,
265                  "\\\\%s\\%s", cli->desthost, share);
266         unix_to_dos(fullshare, True);
267         strupper(fullshare);
268
269         set_message(cli->outbuf,4, 0, True);
270         CVAL(cli->outbuf,smb_com) = SMBtconX;
271         cli_setup_packet(cli);
272
273         SSVAL(cli->outbuf,smb_vwv0,0xFF);
274         SSVAL(cli->outbuf,smb_vwv3,passlen);
275
276         p = smb_buf(cli->outbuf);
277         memcpy(p,pword,passlen);
278         p += passlen;
279         p += clistr_push(cli, p, fullshare, -1, CLISTR_CONVERT | CLISTR_TERMINATE);
280         fstrcpy(p, dev); p += strlen(dev)+1;
281
282         set_message(cli->outbuf,4,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
283
284         SCVAL(cli->inbuf,smb_rcls, 1);
285
286         cli_send_smb(cli);
287         if (!cli_receive_smb(cli))
288                 return False;
289
290         if (CVAL(cli->inbuf,smb_rcls) != 0) {
291                 return False;
292         }
293
294         fstrcpy(cli->dev, "A:");
295
296         if (cli->protocol >= PROTOCOL_NT1) {
297                 clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, CLISTR_TERMINATE | CLISTR_CONVERT);
298         }
299
300         if (strcasecmp(share,"IPC$")==0) {
301                 fstrcpy(cli->dev, "IPC");
302         }
303
304         /* only grab the device if we have a recent protocol level */
305         if (cli->protocol >= PROTOCOL_NT1 &&
306             smb_buflen(cli->inbuf) == 3) {
307                 /* almost certainly win95 - enable bug fixes */
308                 cli->win95 = True;
309         }
310
311         cli->cnum = SVAL(cli->inbuf,smb_tid);
312         return True;
313 }
314
315
316 /****************************************************************************
317 send a tree disconnect
318 ****************************************************************************/
319 BOOL cli_tdis(struct cli_state *cli)
320 {
321         memset(cli->outbuf,'\0',smb_size);
322         set_message(cli->outbuf,0,0,True);
323         CVAL(cli->outbuf,smb_com) = SMBtdis;
324         SSVAL(cli->outbuf,smb_tid,cli->cnum);
325         cli_setup_packet(cli);
326         
327         cli_send_smb(cli);
328         if (!cli_receive_smb(cli))
329                 return False;
330         
331         return CVAL(cli->inbuf,smb_rcls) == 0;
332 }
333
334
335 /****************************************************************************
336 send a negprot command
337 ****************************************************************************/
338 void cli_negprot_send(struct cli_state *cli)
339 {
340         char *p;
341         int numprots;
342         int plength;
343
344         memset(cli->outbuf,'\0',smb_size);
345
346         /* setup the protocol strings */
347         for (plength=0,numprots=0;
348              prots[numprots].name && prots[numprots].prot<=cli->protocol;
349              numprots++)
350                 plength += strlen(prots[numprots].name)+2;
351     
352         set_message(cli->outbuf,0,plength,True);
353
354         p = smb_buf(cli->outbuf);
355         for (numprots=0;
356              prots[numprots].name && prots[numprots].prot<=cli->protocol;
357              numprots++) {
358                 *p++ = 2;
359                 pstrcpy(p,prots[numprots].name);
360                 unix_to_dos(p,True);
361                 p += strlen(p) + 1;
362         }
363
364         CVAL(cli->outbuf,smb_com) = SMBnegprot;
365         cli_setup_packet(cli);
366
367         CVAL(smb_buf(cli->outbuf),0) = 2;
368
369         cli_send_smb(cli);
370 }
371
372
373 /****************************************************************************
374 send a negprot command
375 ****************************************************************************/
376 BOOL cli_negprot(struct cli_state *cli)
377 {
378         char *p;
379         int numprots;
380         int plength;
381
382         memset(cli->outbuf,'\0',smb_size);
383
384         /* setup the protocol strings */
385         for (plength=0,numprots=0;
386              prots[numprots].name && prots[numprots].prot<=cli->protocol;
387              numprots++)
388                 plength += strlen(prots[numprots].name)+2;
389     
390         set_message(cli->outbuf,0,plength,True);
391
392         p = smb_buf(cli->outbuf);
393         for (numprots=0;
394              prots[numprots].name && prots[numprots].prot<=cli->protocol;
395              numprots++) {
396                 *p++ = 2;
397                 pstrcpy(p,prots[numprots].name);
398                 unix_to_dos(p,True);
399                 p += strlen(p) + 1;
400         }
401
402         CVAL(cli->outbuf,smb_com) = SMBnegprot;
403         cli_setup_packet(cli);
404
405         CVAL(smb_buf(cli->outbuf),0) = 2;
406
407         cli_send_smb(cli);
408         if (!cli_receive_smb(cli))
409                 return False;
410
411         show_msg(cli->inbuf);
412
413         if (CVAL(cli->inbuf,smb_rcls) != 0 || 
414             ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
415                 return(False);
416         }
417
418         cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
419
420
421         if (cli->protocol >= PROTOCOL_NT1) {    
422                 /* NT protocol */
423                 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
424                 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
425                 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
426                 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
427                 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
428                 cli->serverzone *= 60;
429                 /* this time arrives in real GMT */
430                 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
431                 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
432                 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
433                 if (cli->capabilities & CAP_RAW_MODE) {
434                         cli->readbraw_supported = True;
435                         cli->writebraw_supported = True;      
436                 }
437         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
438                 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
439                 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
440                 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
441                 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
442                 cli->serverzone *= 60;
443                 /* this time is converted to GMT by make_unix_date */
444                 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
445                 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
446                 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
447                 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
448         } else {
449                 /* the old core protocol */
450                 cli->sec_mode = 0;
451                 cli->serverzone = TimeDiff(time(NULL));
452         }
453
454         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
455
456         /* this ensures cli_use_unicode is setup - delete this call later (tridge) */
457         cli_setup_packet(cli);
458
459         return True;
460 }
461
462
463 /****************************************************************************
464   send a session request.  see rfc1002.txt 4.3 and 4.3.2
465 ****************************************************************************/
466 BOOL cli_session_request(struct cli_state *cli,
467                          struct nmb_name *calling, struct nmb_name *called)
468 {
469         char *p;
470         int len = 4;
471         extern pstring user_socket_options;
472
473         /* send a session request (RFC 1002) */
474
475         memcpy(&(cli->calling), calling, sizeof(*calling));
476         memcpy(&(cli->called ), called , sizeof(*called ));
477   
478         /* put in the destination name */
479         p = cli->outbuf+len;
480         name_mangle(cli->called .name, p, cli->called .name_type);
481         len += name_len(p);
482
483         /* and my name */
484         p = cli->outbuf+len;
485         name_mangle(cli->calling.name, p, cli->calling.name_type);
486         len += name_len(p);
487
488         /* setup the packet length */
489         _smb_setlen(cli->outbuf,len);
490         CVAL(cli->outbuf,0) = 0x81;
491
492 #ifdef WITH_SSL
493 retry:
494 #endif /* WITH_SSL */
495
496         cli_send_smb(cli);
497         DEBUG(5,("Sent session request\n"));
498
499         if (!cli_receive_smb(cli))
500                 return False;
501
502         if (CVAL(cli->inbuf,0) == 0x84) {
503                 /* C. Hoch  9/14/95 Start */
504                 /* For information, here is the response structure.
505                  * We do the byte-twiddling to for portability.
506                 struct RetargetResponse{
507                 unsigned char type;
508                 unsigned char flags;
509                 int16 length;
510                 int32 ip_addr;
511                 int16 port;
512                 };
513                 */
514                 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
515                 /* SESSION RETARGET */
516                 putip((char *)&cli->dest_ip,cli->inbuf+4);
517
518                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
519                 if (cli->fd == -1)
520                         return False;
521
522                 DEBUG(3,("Retargeted\n"));
523
524                 set_socket_options(cli->fd,user_socket_options);
525
526                 /* Try again */
527                 {
528                         static int depth;
529                         BOOL ret;
530                         if (depth > 4) {
531                                 DEBUG(0,("Retarget recursion - failing\n"));
532                                 return False;
533                         }
534                         depth++;
535                         ret = cli_session_request(cli, calling, called);
536                         depth--;
537                         return ret;
538                 }
539         } /* C. Hoch 9/14/95 End */
540
541 #ifdef WITH_SSL
542     if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
543         if (!sslutil_fd_is_ssl(cli->fd)){
544             if (sslutil_connect(cli->fd) == 0)
545                 goto retry;
546         }
547     }
548 #endif /* WITH_SSL */
549
550         if (CVAL(cli->inbuf,0) != 0x82) {
551                 /* This is the wrong place to put the error... JRA. */
552                 cli->rap_error = CVAL(cli->inbuf,4);
553                 return False;
554         }
555         return(True);
556 }
557
558
559 /****************************************************************************
560 open the client sockets
561 ****************************************************************************/
562 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
563 {
564         extern struct in_addr ipzero;
565         extern pstring user_socket_options;
566
567         fstrcpy(cli->desthost, host);
568         
569         if (!ip || ip_equal(*ip, ipzero)) {
570                 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
571                         return False;
572                 }
573                 if (ip) *ip = cli->dest_ip;
574         } else {
575                 cli->dest_ip = *ip;
576         }
577
578         if (cli->port == 0) cli->port = 139;  /* Set to default */
579
580         cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
581                                   cli->port, cli->timeout);
582         if (cli->fd == -1)
583                 return False;
584
585         set_socket_options(cli->fd,user_socket_options);
586
587         return True;
588 }
589
590 /****************************************************************************
591 re-establishes a connection
592 ****************************************************************************/
593 BOOL cli_reestablish_connection(struct cli_state *cli)
594 {
595         struct nmb_name calling;
596         struct nmb_name called;
597         fstring dest_host;
598         fstring share;
599         fstring dev;
600         BOOL do_tcon = False;
601         int oldfd = cli->fd;
602
603         if (!cli->initialised || cli->fd == -1)
604         {
605                 DEBUG(3,("cli_reestablish_connection: not connected\n"));
606                 return False;
607         }
608
609         /* copy the parameters necessary to re-establish the connection */
610
611         if (cli->cnum != 0)
612         {
613                 fstrcpy(share, cli->share);
614                 fstrcpy(dev  , cli->dev);
615                 do_tcon = True;
616         }
617
618         memcpy(&called , &(cli->called ), sizeof(called ));
619         memcpy(&calling, &(cli->calling), sizeof(calling));
620         fstrcpy(dest_host, cli->full_dest_host_name);
621
622         DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
623                  nmb_namestr(&calling), nmb_namestr(&called), 
624                  inet_ntoa(cli->dest_ip),
625                  cli->user_name, cli->domain));
626
627         cli->fd = -1;
628
629         if (cli_establish_connection(cli,
630                                      dest_host, &cli->dest_ip,
631                                      &calling, &called,
632                                      share, dev, False, do_tcon)) {
633                 if ((cli->fd != oldfd) && (oldfd != -1)) {
634                         close( oldfd );
635                 }
636                 return True;
637         }
638         return False;
639 }
640
641 /****************************************************************************
642 establishes a connection right up to doing tconX, reading in a password.
643 ****************************************************************************/
644 BOOL cli_establish_connection(struct cli_state *cli, 
645                                 char *dest_host, struct in_addr *dest_ip,
646                                 struct nmb_name *calling, struct nmb_name *called,
647                                 char *service, char *service_type,
648                                 BOOL do_shutdown, BOOL do_tcon)
649 {
650         DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
651                           nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
652                       cli->user_name, cli->domain));
653
654         /* establish connection */
655
656         if ((!cli->initialised))
657         {
658                 return False;
659         }
660
661         if (cli->fd == -1)
662         {
663                 if (!cli_connect(cli, dest_host, dest_ip))
664                 {
665                         DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
666                                           nmb_namestr(calling), inet_ntoa(*dest_ip)));
667                         return False;
668                 }
669         }
670
671         if (!cli_session_request(cli, calling, called))
672         {
673                 DEBUG(1,("failed session request\n"));
674                 if (do_shutdown)
675           cli_shutdown(cli);
676                 return False;
677         }
678
679         if (!cli_negprot(cli))
680         {
681                 DEBUG(1,("failed negprot\n"));
682                 if (do_shutdown)
683                         cli_shutdown(cli);
684                 return False;
685         }
686
687         if (cli->pwd.cleartext || cli->pwd.null_pwd)
688         {
689                 fstring passwd;
690                 int pass_len;
691
692                 if (cli->pwd.null_pwd)
693                 {
694                         /* attempt null session */
695                         passwd[0] = 0;
696                         pass_len = 1;
697                 }
698                 else
699                 {
700                         /* attempt clear-text session */
701                         pwd_get_cleartext(&(cli->pwd), passwd);
702                         pass_len = strlen(passwd);
703                 }
704
705                 /* attempt clear-text session */
706                 if (!cli_session_setup(cli, cli->user_name,
707                                passwd, pass_len,
708                                NULL, 0,
709                                cli->domain))
710                 {
711                         DEBUG(1,("failed session setup\n"));
712                         if (do_shutdown)
713                         {
714                                 cli_shutdown(cli);
715                         }
716                         return False;
717                 }
718                 if (do_tcon)
719                 {
720                         if (!cli_send_tconX(cli, service, service_type,
721                                             (char*)passwd, strlen(passwd)))
722                         {
723                                 DEBUG(1,("failed tcon_X\n"));
724                                 if (do_shutdown)
725                                 {
726                                         cli_shutdown(cli);
727                                 }
728                                 return False;
729                         }
730                 }
731         }
732         else
733         {
734                 /* attempt encrypted session */
735                 unsigned char nt_sess_pwd[24];
736                 unsigned char lm_sess_pwd[24];
737
738                 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
739                 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
740                 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
741
742                 /* attempt encrypted session */
743                 if (!cli_session_setup(cli, cli->user_name,
744                                (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
745                                (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
746                                cli->domain))
747                 {
748                         DEBUG(1,("failed session setup\n"));
749                         if (do_shutdown)
750                               cli_shutdown(cli);
751                         return False;
752                 }
753
754                 DEBUG(1,("session setup ok\n"));
755     
756                 if (*cli->server_domain || *cli->server_os || *cli->server_type)
757                 {
758                         DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
759                              cli->server_domain,
760                              cli->server_os,
761                              cli->server_type));
762                 }
763                 
764                 if (do_tcon)
765                 {
766                         if (!cli_send_tconX(cli, service, service_type,
767                                             (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
768                         {
769                                 DEBUG(1,("failed tcon_X\n"));
770                                 if (do_shutdown)
771                   cli_shutdown(cli);
772                                 return False;
773                         }
774                 }
775         }
776
777         if (do_shutdown)
778       cli_shutdown(cli);
779
780         return True;
781 }
782
783
784 /****************************************************************************
785  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
786 ****************************************************************************/
787
788 BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char *desthost,
789                                      struct in_addr *pdest_ip)
790 {
791   struct nmb_name calling, called;
792
793   make_nmb_name(&calling, srchost, 0x0);
794
795   /*
796    * If the called name is an IP address
797    * then use *SMBSERVER immediately.
798    */
799
800   if(is_ipaddress(desthost))
801     make_nmb_name(&called, "*SMBSERVER", 0x20);
802   else
803     make_nmb_name(&called, desthost, 0x20);
804
805   if (!cli_session_request(cli, &calling, &called)) {
806     struct nmb_name smbservername;
807
808     make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
809
810     /*
811      * If the name wasn't *SMBSERVER then
812      * try with *SMBSERVER if the first name fails.
813      */
814
815     if (nmb_name_equal(&called, &smbservername)) {
816
817         /*
818          * The name used was *SMBSERVER, don't bother with another name.
819          */
820
821         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
822 with error %s.\n", desthost, cli_errstr(cli) ));
823             cli_shutdown(cli);
824                 return False;
825         }
826
827     cli_shutdown(cli);
828
829     if (!cli_initialise(cli) ||
830         !cli_connect(cli, desthost, pdest_ip) ||
831         !cli_session_request(cli, &calling, &smbservername)) {
832           DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
833 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
834           cli_shutdown(cli);
835           return False;
836     }
837   }
838
839   return True;
840 }