to use the same macros in the client and server rename the CLISTR_
[samba.git] / source / 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, STR_CONVERT|STR_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, STR_CONVERT|STR_UPPER|STR_TERMINATE);
140                 cli_setup_bcc(cli, p);
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                 }
150                 if (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, STR_CONVERT|STR_TERMINATE|STR_UPPER);
171                 p += clistr_push(cli, p, workgroup, -1, STR_CONVERT|STR_TERMINATE|STR_UPPER);
172                 p += clistr_push(cli, p, "Unix", -1, STR_CONVERT|STR_TERMINATE);
173                 p += clistr_push(cli, p, "Samba", -1, STR_CONVERT|STR_TERMINATE);
174                 cli_setup_bcc(cli, p);
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 *q = smb_buf(cli->inbuf);
196               q += clistr_pull(cli, cli->server_os, q, sizeof(fstring), -1, STR_TERMINATE|STR_CONVERT);
197               q += clistr_pull(cli, cli->server_type, q, sizeof(fstring), -1, STR_TERMINATE|STR_CONVERT);
198               q += clistr_pull(cli, cli->server_domain, q, sizeof(fstring), -1, STR_TERMINATE|STR_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, STR_CONVERT|STR_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, STR_CONVERT | STR_TERMINATE);
280         fstrcpy(p, dev); p += strlen(dev)+1;
281
282         cli_setup_bcc(cli, p);
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, STR_TERMINATE | STR_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
343         memset(cli->outbuf,'\0',smb_size);
344
345         /* setup the protocol strings */
346         set_message(cli->outbuf,0,0,True);
347
348         p = smb_buf(cli->outbuf);
349         for (numprots=0;
350              prots[numprots].name && prots[numprots].prot<=cli->protocol;
351              numprots++) {
352                 *p++ = 2;
353                 pstrcpy(p,prots[numprots].name);
354                 unix_to_dos(p,True);
355                 p += strlen(p) + 1;
356         }
357
358         CVAL(cli->outbuf,smb_com) = SMBnegprot;
359         cli_setup_bcc(cli, p);
360         cli_setup_packet(cli);
361
362         CVAL(smb_buf(cli->outbuf),0) = 2;
363
364         cli_send_smb(cli);
365 }
366
367
368 /****************************************************************************
369 send a negprot command
370 ****************************************************************************/
371 BOOL cli_negprot(struct cli_state *cli)
372 {
373         char *p;
374         int numprots;
375         int plength;
376
377         memset(cli->outbuf,'\0',smb_size);
378
379         /* setup the protocol strings */
380         for (plength=0,numprots=0;
381              prots[numprots].name && prots[numprots].prot<=cli->protocol;
382              numprots++)
383                 plength += strlen(prots[numprots].name)+2;
384     
385         set_message(cli->outbuf,0,plength,True);
386
387         p = smb_buf(cli->outbuf);
388         for (numprots=0;
389              prots[numprots].name && prots[numprots].prot<=cli->protocol;
390              numprots++) {
391                 *p++ = 2;
392                 pstrcpy(p,prots[numprots].name);
393                 unix_to_dos(p,True);
394                 p += strlen(p) + 1;
395         }
396
397         CVAL(cli->outbuf,smb_com) = SMBnegprot;
398         cli_setup_packet(cli);
399
400         CVAL(smb_buf(cli->outbuf),0) = 2;
401
402         cli_send_smb(cli);
403         if (!cli_receive_smb(cli))
404                 return False;
405
406         show_msg(cli->inbuf);
407
408         if (CVAL(cli->inbuf,smb_rcls) != 0 || 
409             ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
410                 return(False);
411         }
412
413         cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
414
415
416         if (cli->protocol >= PROTOCOL_NT1) {    
417                 /* NT protocol */
418                 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
419                 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
420                 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
421                 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
422                 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
423                 cli->serverzone *= 60;
424                 /* this time arrives in real GMT */
425                 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
426                 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
427                 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
428                 if (cli->capabilities & CAP_RAW_MODE) {
429                         cli->readbraw_supported = True;
430                         cli->writebraw_supported = True;      
431                 }
432         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
433                 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
434                 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
435                 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
436                 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
437                 cli->serverzone *= 60;
438                 /* this time is converted to GMT by make_unix_date */
439                 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
440                 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
441                 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
442                 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
443         } else {
444                 /* the old core protocol */
445                 cli->sec_mode = 0;
446                 cli->serverzone = TimeDiff(time(NULL));
447         }
448
449         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
450
451         /* a way to force ascii SMB */
452         if (getenv("CLI_FORCE_ASCII")) {
453                 cli->capabilities &= ~CAP_UNICODE;
454         }
455
456         return True;
457 }
458
459
460 /****************************************************************************
461   send a session request.  see rfc1002.txt 4.3 and 4.3.2
462 ****************************************************************************/
463 BOOL cli_session_request(struct cli_state *cli,
464                          struct nmb_name *calling, struct nmb_name *called)
465 {
466         char *p;
467         int len = 4;
468         extern pstring user_socket_options;
469
470         /* send a session request (RFC 1002) */
471
472         memcpy(&(cli->calling), calling, sizeof(*calling));
473         memcpy(&(cli->called ), called , sizeof(*called ));
474   
475         /* put in the destination name */
476         p = cli->outbuf+len;
477         name_mangle(cli->called .name, p, cli->called .name_type);
478         len += name_len(p);
479
480         /* and my name */
481         p = cli->outbuf+len;
482         name_mangle(cli->calling.name, p, cli->calling.name_type);
483         len += name_len(p);
484
485         /* setup the packet length */
486         _smb_setlen(cli->outbuf,len);
487         CVAL(cli->outbuf,0) = 0x81;
488
489 #ifdef WITH_SSL
490 retry:
491 #endif /* WITH_SSL */
492
493         cli_send_smb(cli);
494         DEBUG(5,("Sent session request\n"));
495
496         if (!cli_receive_smb(cli))
497                 return False;
498
499         if (CVAL(cli->inbuf,0) == 0x84) {
500                 /* C. Hoch  9/14/95 Start */
501                 /* For information, here is the response structure.
502                  * We do the byte-twiddling to for portability.
503                 struct RetargetResponse{
504                 unsigned char type;
505                 unsigned char flags;
506                 int16 length;
507                 int32 ip_addr;
508                 int16 port;
509                 };
510                 */
511                 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
512                 /* SESSION RETARGET */
513                 putip((char *)&cli->dest_ip,cli->inbuf+4);
514
515                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
516                 if (cli->fd == -1)
517                         return False;
518
519                 DEBUG(3,("Retargeted\n"));
520
521                 set_socket_options(cli->fd,user_socket_options);
522
523                 /* Try again */
524                 {
525                         static int depth;
526                         BOOL ret;
527                         if (depth > 4) {
528                                 DEBUG(0,("Retarget recursion - failing\n"));
529                                 return False;
530                         }
531                         depth++;
532                         ret = cli_session_request(cli, calling, called);
533                         depth--;
534                         return ret;
535                 }
536         } /* C. Hoch 9/14/95 End */
537
538 #ifdef WITH_SSL
539     if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
540         if (!sslutil_fd_is_ssl(cli->fd)){
541             if (sslutil_connect(cli->fd) == 0)
542                 goto retry;
543         }
544     }
545 #endif /* WITH_SSL */
546
547         if (CVAL(cli->inbuf,0) != 0x82) {
548                 /* This is the wrong place to put the error... JRA. */
549                 cli->rap_error = CVAL(cli->inbuf,4);
550                 return False;
551         }
552         return(True);
553 }
554
555
556 /****************************************************************************
557 open the client sockets
558 ****************************************************************************/
559 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
560 {
561         extern struct in_addr ipzero;
562         extern pstring user_socket_options;
563
564         fstrcpy(cli->desthost, host);
565         
566         if (!ip || ip_equal(*ip, ipzero)) {
567                 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
568                         return False;
569                 }
570                 if (ip) *ip = cli->dest_ip;
571         } else {
572                 cli->dest_ip = *ip;
573         }
574
575         if (cli->port == 0) cli->port = 139;  /* Set to default */
576
577         cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
578                                   cli->port, cli->timeout);
579         if (cli->fd == -1)
580                 return False;
581
582         set_socket_options(cli->fd,user_socket_options);
583
584         return True;
585 }
586
587 /****************************************************************************
588 re-establishes a connection
589 ****************************************************************************/
590 BOOL cli_reestablish_connection(struct cli_state *cli)
591 {
592         struct nmb_name calling;
593         struct nmb_name called;
594         fstring dest_host;
595         fstring share;
596         fstring dev;
597         BOOL do_tcon = False;
598         int oldfd = cli->fd;
599
600         if (!cli->initialised || cli->fd == -1)
601         {
602                 DEBUG(3,("cli_reestablish_connection: not connected\n"));
603                 return False;
604         }
605
606         /* copy the parameters necessary to re-establish the connection */
607
608         if (cli->cnum != 0)
609         {
610                 fstrcpy(share, cli->share);
611                 fstrcpy(dev  , cli->dev);
612                 do_tcon = True;
613         }
614
615         memcpy(&called , &(cli->called ), sizeof(called ));
616         memcpy(&calling, &(cli->calling), sizeof(calling));
617         fstrcpy(dest_host, cli->full_dest_host_name);
618
619         DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
620                  nmb_namestr(&calling), nmb_namestr(&called), 
621                  inet_ntoa(cli->dest_ip),
622                  cli->user_name, cli->domain));
623
624         cli->fd = -1;
625
626         if (cli_establish_connection(cli,
627                                      dest_host, &cli->dest_ip,
628                                      &calling, &called,
629                                      share, dev, False, do_tcon)) {
630                 if ((cli->fd != oldfd) && (oldfd != -1)) {
631                         close( oldfd );
632                 }
633                 return True;
634         }
635         return False;
636 }
637
638 /****************************************************************************
639 establishes a connection right up to doing tconX, reading in a password.
640 ****************************************************************************/
641 BOOL cli_establish_connection(struct cli_state *cli, 
642                                 char *dest_host, struct in_addr *dest_ip,
643                                 struct nmb_name *calling, struct nmb_name *called,
644                                 char *service, char *service_type,
645                                 BOOL do_shutdown, BOOL do_tcon)
646 {
647         DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
648                           nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
649                       cli->user_name, cli->domain));
650
651         /* establish connection */
652
653         if ((!cli->initialised))
654         {
655                 return False;
656         }
657
658         if (cli->fd == -1)
659         {
660                 if (!cli_connect(cli, dest_host, dest_ip))
661                 {
662                         DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
663                                           nmb_namestr(calling), inet_ntoa(*dest_ip)));
664                         return False;
665                 }
666         }
667
668         if (!cli_session_request(cli, calling, called))
669         {
670                 DEBUG(1,("failed session request\n"));
671                 if (do_shutdown)
672           cli_shutdown(cli);
673                 return False;
674         }
675
676         if (!cli_negprot(cli))
677         {
678                 DEBUG(1,("failed negprot\n"));
679                 if (do_shutdown)
680                         cli_shutdown(cli);
681                 return False;
682         }
683
684         if (cli->pwd.cleartext || cli->pwd.null_pwd)
685         {
686                 fstring passwd;
687                 int pass_len;
688
689                 if (cli->pwd.null_pwd)
690                 {
691                         /* attempt null session */
692                         passwd[0] = 0;
693                         pass_len = 1;
694                 }
695                 else
696                 {
697                         /* attempt clear-text session */
698                         pwd_get_cleartext(&(cli->pwd), passwd);
699                         pass_len = strlen(passwd);
700                 }
701
702                 /* attempt clear-text session */
703                 if (!cli_session_setup(cli, cli->user_name,
704                                passwd, pass_len,
705                                NULL, 0,
706                                cli->domain))
707                 {
708                         DEBUG(1,("failed session setup\n"));
709                         if (do_shutdown)
710                         {
711                                 cli_shutdown(cli);
712                         }
713                         return False;
714                 }
715                 if (do_tcon)
716                 {
717                         if (!cli_send_tconX(cli, service, service_type,
718                                             (char*)passwd, strlen(passwd)))
719                         {
720                                 DEBUG(1,("failed tcon_X\n"));
721                                 if (do_shutdown)
722                                 {
723                                         cli_shutdown(cli);
724                                 }
725                                 return False;
726                         }
727                 }
728         }
729         else
730         {
731                 /* attempt encrypted session */
732                 unsigned char nt_sess_pwd[24];
733                 unsigned char lm_sess_pwd[24];
734
735                 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
736                 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
737                 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
738
739                 /* attempt encrypted session */
740                 if (!cli_session_setup(cli, cli->user_name,
741                                (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
742                                (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
743                                cli->domain))
744                 {
745                         DEBUG(1,("failed session setup\n"));
746                         if (do_shutdown)
747                               cli_shutdown(cli);
748                         return False;
749                 }
750
751                 DEBUG(1,("session setup ok\n"));
752     
753                 if (*cli->server_domain || *cli->server_os || *cli->server_type)
754                 {
755                         DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
756                              cli->server_domain,
757                              cli->server_os,
758                              cli->server_type));
759                 }
760                 
761                 if (do_tcon)
762                 {
763                         if (!cli_send_tconX(cli, service, service_type,
764                                             (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
765                         {
766                                 DEBUG(1,("failed tcon_X\n"));
767                                 if (do_shutdown)
768                   cli_shutdown(cli);
769                                 return False;
770                         }
771                 }
772         }
773
774         if (do_shutdown)
775       cli_shutdown(cli);
776
777         return True;
778 }
779
780
781 /****************************************************************************
782  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
783 ****************************************************************************/
784
785 BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char *desthost,
786                                      struct in_addr *pdest_ip)
787 {
788   struct nmb_name calling, called;
789
790   make_nmb_name(&calling, srchost, 0x0);
791
792   /*
793    * If the called name is an IP address
794    * then use *SMBSERVER immediately.
795    */
796
797   if(is_ipaddress(desthost))
798     make_nmb_name(&called, "*SMBSERVER", 0x20);
799   else
800     make_nmb_name(&called, desthost, 0x20);
801
802   if (!cli_session_request(cli, &calling, &called)) {
803     struct nmb_name smbservername;
804
805     make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
806
807     /*
808      * If the name wasn't *SMBSERVER then
809      * try with *SMBSERVER if the first name fails.
810      */
811
812     if (nmb_name_equal(&called, &smbservername)) {
813
814         /*
815          * The name used was *SMBSERVER, don't bother with another name.
816          */
817
818         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
819 with error %s.\n", desthost, cli_errstr(cli) ));
820             cli_shutdown(cli);
821                 return False;
822         }
823
824     cli_shutdown(cli);
825
826     if (!cli_initialise(cli) ||
827         !cli_connect(cli, desthost, pdest_ip) ||
828         !cli_session_request(cli, &calling, &smbservername)) {
829           DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
830 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
831           cli_shutdown(cli);
832           return False;
833     }
834   }
835
836   return True;
837 }