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