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