Ensure the output cli can't have spurious values if the connection fails...
[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 const 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 do an old lanman2 style session setup
47 ****************************************************************************/
48 static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user, 
49                                       char *pass, int passlen)
50 {
51         fstring pword;
52         char *p;
53
54         if (passlen > sizeof(pword)-1) {
55                 return False;
56         }
57
58         /* if in share level security then don't send a password now */
59         if (!(cli->sec_mode & 1)) {
60                 passlen = 0;
61         }
62
63         if (passlen > 0 && (cli->sec_mode & 2) && passlen != 24) {
64                 /* Encrypted mode needed, and non encrypted password supplied. */
65                 passlen = 24;
66                 clistr_push(cli, pword, pass, -1, STR_TERMINATE);
67                 SMBencrypt((uchar *)pword,cli->secblob.data,(uchar *)pword);
68         } else if ((cli->sec_mode & 2) && passlen == 24) {
69                 /* Encrypted mode needed, and encrypted password supplied. */
70                 memcpy(pword, pass, passlen);
71         } else if (passlen > 0) {
72                 /* Plaintext mode needed, assume plaintext supplied. */
73                 passlen = clistr_push(cli, pword, pass, -1, STR_TERMINATE);
74         }
75
76         /* send a session setup command */
77         memset(cli->outbuf,'\0',smb_size);
78         set_message(cli->outbuf,10, 0, True);
79         CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
80         cli_setup_packet(cli);
81         
82         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
83         SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
84         SSVAL(cli->outbuf,smb_vwv3,2);
85         SSVAL(cli->outbuf,smb_vwv4,1);
86         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
87         SSVAL(cli->outbuf,smb_vwv7,passlen);
88
89         p = smb_buf(cli->outbuf);
90         memcpy(p,pword,passlen);
91         p += passlen;
92         p += clistr_push(cli, p, user, -1, STR_TERMINATE);
93         cli_setup_bcc(cli, p);
94
95         cli_send_smb(cli);
96         if (!cli_receive_smb(cli))
97                 return False;
98
99         show_msg(cli->inbuf);
100
101         if (cli_is_error(cli)) {
102                 return False;
103         }
104         
105         /* use the returned vuid from now on */
106         cli->vuid = SVAL(cli->inbuf,smb_uid);   
107         fstrcpy(cli->user_name, user);
108
109         return True;
110 }
111
112
113 /****************************************************************************
114 work out suitable capabilities to offer the server
115 ****************************************************************************/
116 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
117 {
118         uint32 capabilities = CAP_NT_SMBS;
119
120         if (!cli->force_dos_errors) {
121                 capabilities |= CAP_STATUS32;
122         }
123
124         if (cli->use_level_II_oplocks) {
125                 capabilities |= CAP_LEVEL_II_OPLOCKS;
126         }
127
128         if (cli->capabilities & CAP_UNICODE) {
129                 capabilities |= CAP_UNICODE;
130         }
131
132         return capabilities;
133 }
134
135
136 /****************************************************************************
137 do a NT1 guest session setup
138 ****************************************************************************/
139 static BOOL cli_session_setup_guest(struct cli_state *cli)
140 {
141         char *p;
142         uint32 capabilities = cli_session_setup_capabilities(cli);
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,0);
154         SSVAL(cli->outbuf,smb_vwv8,0);
155         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
156         p = smb_buf(cli->outbuf);
157         p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
158         p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
159         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
160         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
161         cli_setup_bcc(cli, p);
162
163         cli_send_smb(cli);
164         if (!cli_receive_smb(cli))
165               return False;
166         
167         show_msg(cli->inbuf);
168         
169         if (cli_is_error(cli)) {
170                 return False;
171         }
172
173         cli->vuid = SVAL(cli->inbuf,smb_uid);
174
175         p = smb_buf(cli->inbuf);
176         p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
177         p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
178         p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
179
180         fstrcpy(cli->user_name, "");
181
182         return True;
183 }
184
185
186 /****************************************************************************
187 do a NT1 plaintext session setup
188 ****************************************************************************/
189 static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user, 
190                                         char *pass, char *workgroup)
191 {
192         uint32 capabilities = cli_session_setup_capabilities(cli);
193         fstring pword;
194         int passlen;
195         char *p;
196
197         passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE|STR_ASCII);
198
199         set_message(cli->outbuf,13,0,True);
200         CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
201         cli_setup_packet(cli);
202                         
203         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
204         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
205         SSVAL(cli->outbuf,smb_vwv3,2);
206         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
207         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
208         SSVAL(cli->outbuf,smb_vwv7,passlen);
209         SSVAL(cli->outbuf,smb_vwv8,0);
210         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
211         p = smb_buf(cli->outbuf);
212         memcpy(p, pword, passlen);
213         p += passlen;
214         p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
215         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
216         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
217         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
218         cli_setup_bcc(cli, p);
219
220         cli_send_smb(cli);
221         if (!cli_receive_smb(cli))
222               return False;
223         
224         show_msg(cli->inbuf);
225         
226         if (cli_is_error(cli)) {
227                 return False;
228         }
229
230         cli->vuid = SVAL(cli->inbuf,smb_uid);
231         p = smb_buf(cli->inbuf);
232         p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
233         p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
234         p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
235         fstrcpy(cli->user_name, user);
236
237         return True;
238 }
239
240
241 /****************************************************************************
242 do a NT1 NTLM/LM encrypted session setup
243 ****************************************************************************/
244 static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user, 
245                                   char *pass, int passlen,
246                                   char *ntpass, int ntpasslen,
247                                   char *workgroup)
248 {
249         uint32 capabilities = cli_session_setup_capabilities(cli);
250         fstring pword, ntpword;
251         char *p;
252
253         if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
254                 return False;
255         }
256
257         if (passlen != 24) {
258                 /* non encrypted password supplied. Ignore ntpass. */
259                 passlen = 24;
260                 ntpasslen = 24;
261                 clistr_push(cli, pword, 
262                             pass?pass:"", sizeof(pword), STR_TERMINATE|STR_ASCII);
263                 clistr_push(cli, ntpword, 
264                             pass?pass:"", sizeof(ntpword), STR_TERMINATE|STR_ASCII);
265                 SMBencrypt((uchar *)pword,cli->secblob.data,(uchar *)pword);
266                 SMBNTencrypt((uchar *)ntpword,cli->secblob.data,(uchar *)ntpword);
267         } else {
268                 memcpy(pword, pass, passlen);
269                 memcpy(ntpword, ntpass, ntpasslen);
270         }
271
272         /* send a session setup command */
273         memset(cli->outbuf,'\0',smb_size);
274
275         set_message(cli->outbuf,13,0,True);
276         CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
277         cli_setup_packet(cli);
278                         
279         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
280         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
281         SSVAL(cli->outbuf,smb_vwv3,2);
282         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
283         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
284         SSVAL(cli->outbuf,smb_vwv7,passlen);
285         SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
286         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
287         p = smb_buf(cli->outbuf);
288         memcpy(p,pword,passlen); p += passlen;
289         memcpy(p,ntpword,ntpasslen); p += ntpasslen;
290         p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
291         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
292         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
293         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
294         cli_setup_bcc(cli, p);
295
296         cli_send_smb(cli);
297         if (!cli_receive_smb(cli))
298                 return False;
299
300         show_msg(cli->inbuf);
301
302         if (cli_is_error(cli)) {
303                 return False;
304         }
305         
306         /* use the returned vuid from now on */
307         cli->vuid = SVAL(cli->inbuf,smb_uid);
308         
309         p = smb_buf(cli->inbuf);
310         p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
311         p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
312         p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
313
314         fstrcpy(cli->user_name, user);
315
316         return True;
317 }
318
319
320 /****************************************************************************
321 send a extended security session setup blob, returning a reply blob
322 ****************************************************************************/
323 static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
324 {
325         uint32 capabilities = cli_session_setup_capabilities(cli);
326         char *p;
327         DATA_BLOB blob2;
328         uint32 len;
329
330         blob2 = data_blob(NULL, 0);
331
332         capabilities |= CAP_EXTENDED_SECURITY;
333
334         /* send a session setup command */
335         memset(cli->outbuf,'\0',smb_size);
336
337         set_message(cli->outbuf,12,0,True);
338         CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
339         cli_setup_packet(cli);
340                         
341         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
342         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
343         SSVAL(cli->outbuf,smb_vwv3,2);
344         SSVAL(cli->outbuf,smb_vwv4,1);
345         SIVAL(cli->outbuf,smb_vwv5,0);
346         SSVAL(cli->outbuf,smb_vwv7,blob.length);
347         SIVAL(cli->outbuf,smb_vwv10,capabilities); 
348         p = smb_buf(cli->outbuf);
349         memcpy(p, blob.data, blob.length);
350         p += blob.length;
351         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
352         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
353         cli_setup_bcc(cli, p);
354
355         cli_send_smb(cli);
356         if (!cli_receive_smb(cli))
357                 return blob2;
358
359         show_msg(cli->inbuf);
360
361         if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
362                                                   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
363                 return blob2;
364         }
365         
366         /* use the returned vuid from now on */
367         cli->vuid = SVAL(cli->inbuf,smb_uid);
368         
369         p = smb_buf(cli->inbuf);
370
371         blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
372
373         p += blob2.length;
374         p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
375
376         /* w2k with kerberos doesn't properly null terminate this field */
377         len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
378         p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
379
380         return blob2;
381 }
382
383
384 #ifdef HAVE_KRB5
385 /****************************************************************************
386 do a spnego/kerberos encrypted session setup
387 ****************************************************************************/
388 static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principal, char *workgroup)
389 {
390         DATA_BLOB blob2, negTokenTarg;
391
392         DEBUG(2,("Doing kerberos session setup\n"));
393
394         /* generate the encapsulated kerberos5 ticket */
395         negTokenTarg = spnego_gen_negTokenTarg(cli, principal);
396
397         if (!negTokenTarg.data) return False;
398
399 #if 0
400         file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
401 #endif
402
403         blob2 = cli_session_setup_blob(cli, negTokenTarg);
404
405         /* we don't need this blob for kerberos */
406         data_blob_free(&blob2);
407
408         data_blob_free(&negTokenTarg);
409
410         return !cli_is_error(cli);
411 }
412 #endif
413
414 /****************************************************************************
415 do a spnego/NTLMSSP encrypted session setup
416 ****************************************************************************/
417 static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user, 
418                                       char *pass, char *workgroup)
419 {
420         const char *mechs[] = {OID_NTLMSSP, NULL};
421         DATA_BLOB msg1;
422         DATA_BLOB blob, chal1, chal2, auth;
423         uint8 challenge[8];
424         uint8 nthash[24], lmhash[24], sess_key[16];
425         uint32 neg_flags;
426
427         neg_flags = NTLMSSP_NEGOTIATE_UNICODE | 
428                 NTLMSSP_NEGOTIATE_LM_KEY | 
429                 NTLMSSP_NEGOTIATE_NTLM;
430
431         memset(sess_key, 0, 16);
432
433         /* generate the ntlmssp negotiate packet */
434         msrpc_gen(&blob, "CddB",
435                   "NTLMSSP",
436                   NTLMSSP_NEGOTIATE,
437                   neg_flags,
438                   sess_key, 16);
439
440         /* and wrap it in a SPNEGO wrapper */
441         msg1 = gen_negTokenTarg(mechs, blob);
442         data_blob_free(&blob);
443
444         /* now send that blob on its way */
445         blob = cli_session_setup_blob(cli, msg1);
446
447         data_blob_free(&msg1);
448
449         if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED)) {
450                 return False;
451         }
452
453 #if 0
454         file_save("chal.dat", blob.data, blob.length);
455 #endif
456
457         /* the server gives us back two challenges */
458         if (!spnego_parse_challenge(blob, &chal1, &chal2)) {
459                 DEBUG(3,("Failed to parse challenges\n"));
460                 return False;
461         }
462
463         data_blob_free(&blob);
464
465         /* encrypt the password with the challenge */
466         memcpy(challenge, chal1.data + 24, 8);
467         SMBencrypt((unsigned char *)pass, challenge,lmhash);
468         SMBNTencrypt((unsigned char *)pass, challenge,nthash);
469
470 #if 0
471         file_save("nthash.dat", nthash, 24);
472         file_save("lmhash.dat", lmhash, 24);
473         file_save("chal1.dat", chal1.data, chal1.length);
474 #endif
475
476         data_blob_free(&chal1);
477         data_blob_free(&chal2);
478
479         /* this generates the actual auth packet */
480         msrpc_gen(&blob, "CdBBUUUBd", 
481                   "NTLMSSP", 
482                   NTLMSSP_AUTH, 
483                   lmhash, 24,
484                   nthash, 24,
485                   workgroup, 
486                   user, 
487                   cli->calling.name,
488                   sess_key, 16,
489                   neg_flags);
490
491         /* wrap it in SPNEGO */
492         auth = spnego_gen_auth(blob);
493
494         data_blob_free(&blob);
495
496         /* now send the auth packet and we should be done */
497         blob = cli_session_setup_blob(cli, auth);
498
499         data_blob_free(&auth);
500         data_blob_free(&blob);
501
502         return !cli_is_error(cli);
503 }
504
505
506 /****************************************************************************
507 do a spnego encrypted session setup
508 ****************************************************************************/
509 static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user, 
510                                      char *pass, char *workgroup)
511 {
512         char *principal;
513         char *OIDs[ASN1_MAX_OIDS];
514         uint8 guid[16];
515         int i;
516         BOOL got_kerberos_mechanism = False;
517
518         DEBUG(2,("Doing spnego session setup (blob length=%d)\n", cli->secblob.length));
519
520         /* the server might not even do spnego */
521         if (cli->secblob.length == 16) {
522                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
523                 goto ntlmssp;
524         }
525
526 #if 0
527         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
528 #endif
529
530         /* the server sent us the first part of the SPNEGO exchange in the negprot 
531            reply */
532         if (!spnego_parse_negTokenInit(cli->secblob, guid, OIDs, &principal)) {
533                 return False;
534         }
535
536         /* make sure the server understands kerberos */
537         for (i=0;OIDs[i];i++) {
538                 DEBUG(3,("got OID=%s\n", OIDs[i]));
539                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
540                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
541                         got_kerberos_mechanism = True;
542                 }
543                 free(OIDs[i]);
544         }
545         DEBUG(3,("got principal=%s\n", principal));
546
547         fstrcpy(cli->user_name, user);
548
549 #ifdef HAVE_KRB5
550         if (got_kerberos_mechanism && cli->use_kerberos) {
551                 return cli_session_setup_kerberos(cli, principal, workgroup);
552         }
553 #endif
554
555         free(principal);
556
557 ntlmssp:
558
559         return cli_session_setup_ntlmssp(cli, user, pass, workgroup);
560 }
561
562
563 /****************************************************************************
564  Send a session setup. The username and workgroup is in UNIX character
565  format and must be converted to DOS codepage format before sending. If the
566  password is in plaintext, the same should be done.
567 ****************************************************************************/
568 BOOL cli_session_setup(struct cli_state *cli, 
569                        char *user, 
570                        char *pass, int passlen,
571                        char *ntpass, int ntpasslen,
572                        char *workgroup)
573 {
574         char *p;
575         fstring user2;
576
577         /* allow for workgroups as part of the username */
578         fstrcpy(user2, user);
579         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/'))) {
580                 *p = 0;
581                 user = p+1;
582                 workgroup = user2;
583         }
584
585         if (cli->protocol < PROTOCOL_LANMAN1)
586                 return True;
587
588         /* now work out what sort of session setup we are going to
589            do. I have split this into separate functions to make the
590            flow a bit easier to understand (tridge) */
591
592         /* if its an older server then we have to use the older request format */
593         if (cli->protocol < PROTOCOL_NT1) {
594                 return cli_session_setup_lanman2(cli, user, pass, passlen);
595         }
596
597         /* if no user is supplied then we have to do an anonymous connection.
598            passwords are ignored */
599         if (!user || !*user) {
600                 return cli_session_setup_guest(cli);
601         }
602
603         /* if the server is share level then send a plaintext null
604            password at this point. The password is sent in the tree
605            connect */
606         if ((cli->sec_mode & 1) == 0) {
607                 return cli_session_setup_plaintext(cli, user, "", workgroup);
608         }
609
610         /* if the server doesn't support encryption then we have to use plaintext. The 
611            second password is ignored */
612         if ((cli->sec_mode & 2) == 0) {
613                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
614         }
615
616         /* if the server supports extended security then use SPNEGO */
617         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
618                 return cli_session_setup_spnego(cli, user, pass, workgroup);
619         }
620
621         /* otherwise do a NT1 style session setup */
622         return cli_session_setup_nt1(cli, user, 
623                                      pass, passlen, ntpass, ntpasslen,
624                                      workgroup);        
625 }
626
627 /****************************************************************************
628  Send a uloggoff.
629 *****************************************************************************/
630
631 BOOL cli_ulogoff(struct cli_state *cli)
632 {
633         memset(cli->outbuf,'\0',smb_size);
634         set_message(cli->outbuf,2,0,True);
635         CVAL(cli->outbuf,smb_com) = SMBulogoffX;
636         cli_setup_packet(cli);
637         SSVAL(cli->outbuf,smb_vwv0,0xFF);
638         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
639
640         cli_send_smb(cli);
641         if (!cli_receive_smb(cli))
642                 return False;
643
644         return !cli_is_error(cli);
645 }
646
647 /****************************************************************************
648 send a tconX
649 ****************************************************************************/
650 BOOL cli_send_tconX(struct cli_state *cli, 
651                     const char *share, const char *dev, const char *pass, int passlen)
652 {
653         fstring fullshare, pword, dos_pword;
654         char *p;
655         memset(cli->outbuf,'\0',smb_size);
656         memset(cli->inbuf,'\0',smb_size);
657
658         fstrcpy(cli->share, share);
659
660         /* in user level security don't send a password now */
661         if (cli->sec_mode & 1) {
662                 passlen = 1;
663                 pass = "";
664         }
665
666         if ((cli->sec_mode & 2) && *pass && passlen != 24) {
667                 /*
668                  * Non-encrypted passwords - convert to DOS codepage before encryption.
669                  */
670                 passlen = 24;
671                 clistr_push(cli, dos_pword, pass, -1, STR_TERMINATE);
672                 SMBencrypt((uchar *)dos_pword,cli->secblob.data,(uchar *)pword);
673         } else {
674                 if((cli->sec_mode & 3) == 0) {
675                         /*
676                          * Non-encrypted passwords - convert to DOS codepage before using.
677                          */
678                         passlen = clistr_push(cli, pword, pass, -1, STR_TERMINATE);
679                 } else {
680                         memcpy(pword, pass, passlen);
681                 }
682         }
683
684         if (cli->port == 445) {
685                 slprintf(fullshare, sizeof(fullshare)-1,
686                          "%s", share);
687         } else {
688                 slprintf(fullshare, sizeof(fullshare)-1,
689                          "\\\\%s\\%s", cli->desthost, share);
690         }
691
692         set_message(cli->outbuf,4, 0, True);
693         CVAL(cli->outbuf,smb_com) = SMBtconX;
694         cli_setup_packet(cli);
695
696         SSVAL(cli->outbuf,smb_vwv0,0xFF);
697         SSVAL(cli->outbuf,smb_vwv3,passlen);
698
699         p = smb_buf(cli->outbuf);
700         memcpy(p,pword,passlen);
701         p += passlen;
702         p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
703         fstrcpy(p, dev); p += strlen(dev)+1;
704
705         cli_setup_bcc(cli, p);
706
707         cli_send_smb(cli);
708         if (!cli_receive_smb(cli))
709                 return False;
710
711         if (cli_is_error(cli)) {
712                 return False;
713         }
714
715         clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
716
717         if (strcasecmp(share,"IPC$")==0) {
718                 fstrcpy(cli->dev, "IPC");
719         }
720
721         if (cli->protocol >= PROTOCOL_NT1 &&
722             smb_buflen(cli->inbuf) == 3) {
723                 /* almost certainly win95 - enable bug fixes */
724                 cli->win95 = True;
725         }
726
727         cli->cnum = SVAL(cli->inbuf,smb_tid);
728         return True;
729 }
730
731
732 /****************************************************************************
733 send a tree disconnect
734 ****************************************************************************/
735 BOOL cli_tdis(struct cli_state *cli)
736 {
737         memset(cli->outbuf,'\0',smb_size);
738         set_message(cli->outbuf,0,0,True);
739         CVAL(cli->outbuf,smb_com) = SMBtdis;
740         SSVAL(cli->outbuf,smb_tid,cli->cnum);
741         cli_setup_packet(cli);
742         
743         cli_send_smb(cli);
744         if (!cli_receive_smb(cli))
745                 return False;
746         
747         return !cli_is_error(cli);
748 }
749
750
751 /****************************************************************************
752 send a negprot command
753 ****************************************************************************/
754 void cli_negprot_send(struct cli_state *cli)
755 {
756         char *p;
757         int numprots;
758
759         memset(cli->outbuf,'\0',smb_size);
760
761         /* setup the protocol strings */
762         set_message(cli->outbuf,0,0,True);
763
764         p = smb_buf(cli->outbuf);
765         for (numprots=0;
766              prots[numprots].name && prots[numprots].prot<=cli->protocol;
767              numprots++) {
768                 *p++ = 2;
769                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
770         }
771
772         CVAL(cli->outbuf,smb_com) = SMBnegprot;
773         cli_setup_bcc(cli, p);
774         cli_setup_packet(cli);
775
776         CVAL(smb_buf(cli->outbuf),0) = 2;
777
778         cli_send_smb(cli);
779 }
780
781
782 /****************************************************************************
783 send a negprot command
784 ****************************************************************************/
785 BOOL cli_negprot(struct cli_state *cli)
786 {
787         char *p;
788         int numprots;
789         int plength;
790
791         memset(cli->outbuf,'\0',smb_size);
792
793         /* setup the protocol strings */
794         for (plength=0,numprots=0;
795              prots[numprots].name && prots[numprots].prot<=cli->protocol;
796              numprots++)
797                 plength += strlen(prots[numprots].name)+2;
798     
799         set_message(cli->outbuf,0,plength,True);
800
801         p = smb_buf(cli->outbuf);
802         for (numprots=0;
803              prots[numprots].name && prots[numprots].prot<=cli->protocol;
804              numprots++) {
805                 *p++ = 2;
806                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
807         }
808
809         CVAL(cli->outbuf,smb_com) = SMBnegprot;
810         cli_setup_packet(cli);
811
812         CVAL(smb_buf(cli->outbuf),0) = 2;
813
814         cli_send_smb(cli);
815         if (!cli_receive_smb(cli))
816                 return False;
817
818         show_msg(cli->inbuf);
819
820         if (cli_is_error(cli) ||
821             ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
822                 return(False);
823         }
824
825         cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
826
827         if (cli->protocol >= PROTOCOL_NT1) {    
828                 /* NT protocol */
829                 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
830                 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
831                 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
832                 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
833                 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
834                 cli->serverzone *= 60;
835                 /* this time arrives in real GMT */
836                 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
837                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
838                 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
839                 if (cli->capabilities & CAP_RAW_MODE) {
840                         cli->readbraw_supported = True;
841                         cli->writebraw_supported = True;      
842                 }
843                 /* work out if they sent us a workgroup */
844                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
845                     smb_buflen(cli->inbuf) > 8) {
846                         clistr_pull(cli, cli->server_domain, 
847                                     smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
848                                     smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
849                 }
850         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
851                 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
852                 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
853                 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
854                 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
855                 cli->serverzone *= 60;
856                 /* this time is converted to GMT by make_unix_date */
857                 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
858                 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
859                 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
860                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
861         } else {
862                 /* the old core protocol */
863                 cli->sec_mode = 0;
864                 cli->serverzone = TimeDiff(time(NULL));
865         }
866
867         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
868
869         /* a way to force ascii SMB */
870         if (getenv("CLI_FORCE_ASCII")) {
871                 cli->capabilities &= ~CAP_UNICODE;
872         }
873
874         return True;
875 }
876
877
878 /****************************************************************************
879   send a session request.  see rfc1002.txt 4.3 and 4.3.2
880 ****************************************************************************/
881 BOOL cli_session_request(struct cli_state *cli,
882                          struct nmb_name *calling, struct nmb_name *called)
883 {
884         char *p;
885         int len = 4;
886         extern pstring user_socket_options;
887
888         /* 445 doesn't have session request */
889         if (cli->port == 445) return True;
890
891         /* send a session request (RFC 1002) */
892         memcpy(&(cli->calling), calling, sizeof(*calling));
893         memcpy(&(cli->called ), called , sizeof(*called ));
894   
895         /* put in the destination name */
896         p = cli->outbuf+len;
897         name_mangle(cli->called .name, p, cli->called .name_type);
898         len += name_len(p);
899
900         /* and my name */
901         p = cli->outbuf+len;
902         name_mangle(cli->calling.name, p, cli->calling.name_type);
903         len += name_len(p);
904
905         /* setup the packet length */
906         _smb_setlen(cli->outbuf,len);
907         CVAL(cli->outbuf,0) = 0x81;
908
909 #ifdef WITH_SSL
910 retry:
911 #endif /* WITH_SSL */
912
913         cli_send_smb(cli);
914         DEBUG(5,("Sent session request\n"));
915
916         if (!cli_receive_smb(cli))
917                 return False;
918
919         if (CVAL(cli->inbuf,0) == 0x84) {
920                 /* C. Hoch  9/14/95 Start */
921                 /* For information, here is the response structure.
922                  * We do the byte-twiddling to for portability.
923                 struct RetargetResponse{
924                 unsigned char type;
925                 unsigned char flags;
926                 int16 length;
927                 int32 ip_addr;
928                 int16 port;
929                 };
930                 */
931                 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
932                 /* SESSION RETARGET */
933                 putip((char *)&cli->dest_ip,cli->inbuf+4);
934
935                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
936                 if (cli->fd == -1)
937                         return False;
938
939                 DEBUG(3,("Retargeted\n"));
940
941                 set_socket_options(cli->fd,user_socket_options);
942
943                 /* Try again */
944                 {
945                         static int depth;
946                         BOOL ret;
947                         if (depth > 4) {
948                                 DEBUG(0,("Retarget recursion - failing\n"));
949                                 return False;
950                         }
951                         depth++;
952                         ret = cli_session_request(cli, calling, called);
953                         depth--;
954                         return ret;
955                 }
956         } /* C. Hoch 9/14/95 End */
957
958 #ifdef WITH_SSL
959     if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
960         if (!sslutil_fd_is_ssl(cli->fd)){
961             if (sslutil_connect(cli->fd) == 0)
962                 goto retry;
963         }
964     }
965 #endif /* WITH_SSL */
966
967         if (CVAL(cli->inbuf,0) != 0x82) {
968                 /* This is the wrong place to put the error... JRA. */
969                 cli->rap_error = CVAL(cli->inbuf,4);
970                 return False;
971         }
972         return(True);
973 }
974
975 /****************************************************************************
976 open the client sockets
977 ****************************************************************************/
978 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
979 {
980         extern pstring user_socket_options;
981         int name_type = 0x20;
982         char *p;
983
984         /* reasonable default hostname */
985         if (!host) host = "*SMBSERVER";
986
987         fstrcpy(cli->desthost, host);
988
989         /* allow hostnames of the form NAME#xx and do a netbios lookup */
990         if ((p = strchr(cli->desthost, '#'))) {
991                 name_type = strtol(p+1, NULL, 16);              
992                 *p = 0;
993         }
994         
995         if (!ip || is_zero_ip(*ip)) {
996                 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
997                         return False;
998                 }
999                 if (ip) *ip = cli->dest_ip;
1000         } else {
1001                 cli->dest_ip = *ip;
1002         }
1003
1004         if (getenv("LIBSMB_PROG")) {
1005                 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1006         } else {
1007                 /* try 445 first, then 139 */
1008                 int port = cli->port?cli->port:445;
1009                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
1010                                           port, cli->timeout);
1011                 if (cli->fd == -1 && cli->port == 0) {
1012                         port = 139;
1013                         cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
1014                                                   port, cli->timeout);
1015                 }
1016                 if (cli->fd != -1) cli->port = port;
1017         }
1018         if (cli->fd == -1) {
1019                 DEBUG(1,("Error connecting to %s (%s)\n",
1020                          inet_ntoa(*ip),strerror(errno)));
1021                 return False;
1022         }
1023
1024         set_socket_options(cli->fd,user_socket_options);
1025
1026         return True;
1027 }
1028
1029 /****************************************************************************
1030 establishes a connection right up to doing tconX, password in cache.
1031 ****************************************************************************/
1032 BOOL cli_establish_connection(struct cli_state *cli, 
1033                                 char *dest_host, struct in_addr *dest_ip,
1034                                 struct nmb_name *calling, struct nmb_name *called,
1035                                 char *service, char *service_type,
1036                                 BOOL do_shutdown, BOOL do_tcon)
1037 {
1038         DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
1039                           nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
1040                       cli->user_name, cli->domain));
1041
1042         /* establish connection */
1043
1044         if ((!cli->initialised))
1045         {
1046                 return False;
1047         }
1048
1049         /* cli_establish_connection() can't handle spnego yet. Once we get rid of
1050            pwd_cache and other horrors we can get rid of this */
1051         cli->use_spnego = False;
1052
1053         if (cli->fd == -1)
1054         {
1055                 if (!cli_connect(cli, dest_host, dest_ip))
1056                 {
1057                         DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
1058                                           nmb_namestr(called), inet_ntoa(*dest_ip)));
1059                         return False;
1060                 }
1061         }
1062
1063         if (!cli_session_request(cli, calling, called))
1064         {
1065                 DEBUG(1,("failed session request\n"));
1066                 if (do_shutdown)
1067                         cli_shutdown(cli);
1068                 return False;
1069         }
1070
1071         if (!cli_negprot(cli))
1072         {
1073                 DEBUG(1,("failed negprot\n"));
1074                 if (do_shutdown)
1075                         cli_shutdown(cli);
1076                 return False;
1077         }
1078
1079         if (cli->pwd.cleartext || cli->pwd.null_pwd)
1080         {
1081                 fstring passwd;
1082                 int pass_len;
1083
1084                 if (cli->pwd.null_pwd)
1085                 {
1086                         /* attempt null session */
1087                         passwd[0] = 0;
1088                         pass_len = 1;
1089                 }
1090                 else
1091                 {
1092                         /* attempt clear-text session */
1093                         pwd_get_cleartext(&(cli->pwd), passwd);
1094                         pass_len = strlen(passwd);
1095                 }
1096
1097                 /* attempt clear-text session */
1098                 if (!cli_session_setup(cli, cli->user_name,
1099                                passwd, pass_len,
1100                                NULL, 0,
1101                                cli->domain))
1102                 {
1103                         DEBUG(1,("failed session setup\n"));
1104                         if (do_shutdown)
1105                         {
1106                                 cli_shutdown(cli);
1107                         }
1108                         return False;
1109                 }
1110                 if (do_tcon)
1111                 {
1112                         if (!cli_send_tconX(cli, service, service_type,
1113                                             (char*)passwd, strlen(passwd)))
1114                         {
1115                                 DEBUG(1,("failed tcon_X\n"));
1116                                 if (do_shutdown)
1117                                 {
1118                                         cli_shutdown(cli);
1119                                 }
1120                                 return False;
1121                         }
1122                 }
1123         }
1124         else
1125         {
1126                 /* attempt encrypted session */
1127                 unsigned char nt_sess_pwd[24];
1128                 unsigned char lm_sess_pwd[24];
1129
1130                 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
1131                 pwd_make_lm_nt_owf(&(cli->pwd), cli->secblob.data);
1132                 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
1133
1134                 /* attempt encrypted session */
1135                 if (!cli_session_setup(cli, cli->user_name,
1136                                (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
1137                                (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
1138                                cli->domain))
1139                 {
1140                         DEBUG(1,("failed session setup\n"));
1141                         if (do_shutdown)
1142                               cli_shutdown(cli);
1143                         return False;
1144                 }
1145
1146                 DEBUG(1,("session setup ok\n"));
1147     
1148                 if (*cli->server_domain || *cli->server_os || *cli->server_type)
1149                 {
1150                         DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
1151                                  cli->server_domain,
1152                                  cli->server_os,
1153                                  cli->server_type));
1154                 }
1155                 
1156                 if (do_tcon)
1157                 {
1158                         if (!cli_send_tconX(cli, service, service_type,
1159                                             (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
1160                         {
1161                                 DEBUG(1,("failed tcon_X\n"));
1162                                 if (do_shutdown)
1163                                         cli_shutdown(cli);
1164                                 return False;
1165                         }
1166                 }
1167         }
1168
1169         if (do_shutdown)
1170                 cli_shutdown(cli);
1171
1172         return True;
1173 }
1174
1175 /* Initialise client credentials for authenticated pipe access */
1176
1177 static void init_creds(struct ntuser_creds *creds, char* username,
1178                        char* domain, char* password, int pass_len)
1179 {
1180         ZERO_STRUCTP(creds);
1181
1182         pwd_set_cleartext(&creds->pwd, password);
1183
1184         fstrcpy(creds->user_name, username);
1185         fstrcpy(creds->domain, domain);
1186
1187         if (!*username) {
1188                 creds->pwd.null_pwd = True;
1189         }
1190 }
1191
1192 /****************************************************************************
1193 establishes a connection right up to doing tconX, password specified.
1194 ****************************************************************************/
1195 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
1196                              const char *my_name, const char *dest_host, 
1197                              struct in_addr *dest_ip, int port,
1198                              char *service, char *service_type,
1199                              char *user, char *domain, 
1200                              char *password, int pass_len) 
1201 {
1202         struct ntuser_creds creds;
1203         NTSTATUS nt_status;
1204         struct nmb_name calling;
1205         struct nmb_name called;
1206         struct cli_state *cli;
1207         struct in_addr ip;
1208         
1209         if (!output_cli) {
1210                 DEBUG(0, ("output_cli is NULL!?!"));
1211         }
1212
1213         *output_cli = NULL;
1214         
1215         make_nmb_name(&calling, my_name, 0x0);
1216         make_nmb_name(&called , dest_host, 0x20);
1217
1218 again:
1219
1220         if (!(cli = cli_initialise(NULL))) {
1221                 return NT_STATUS_NO_MEMORY;
1222         }
1223         
1224         if (cli_set_port(cli, port) != port) {
1225                 return NT_STATUS_UNSUCCESSFUL;
1226         }
1227
1228         ip = *dest_ip;
1229         
1230         DEBUG(3,("Connecting to host=%s share=%s\n\n", 
1231                  dest_host, service));
1232         
1233         if (!cli_connect(cli, dest_host, &ip))
1234         {
1235                 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
1236                          nmb_namestr(&called), inet_ntoa(*dest_ip)));
1237                 return NT_STATUS_UNSUCCESSFUL;
1238         }
1239
1240         if (!cli_session_request(cli, &calling, &called)) {
1241                 char *p;
1242                 DEBUG(1,("session request to %s failed (%s)\n", 
1243                          called.name, cli_errstr(cli)));
1244                 cli_shutdown(cli);
1245                 if ((p=strchr(called.name, '.'))) {
1246                         *p = 0;
1247                         goto again;
1248                 }
1249                 if (strcmp(called.name, "*SMBSERVER")) {
1250                         make_nmb_name(&called , "*SMBSERVER", 0x20);
1251                         goto again;
1252                 }
1253                 return NT_STATUS_UNSUCCESSFUL;
1254         }
1255
1256         if (!cli_negprot(cli))
1257         {
1258                 DEBUG(1,("failed negprot\n"));
1259                 nt_status = cli_nt_error(cli);
1260                 cli_shutdown(cli);
1261                 return nt_status;
1262         }
1263
1264         if (!cli_session_setup(cli, user,
1265                                password, pass_len,
1266                                NULL, 0,
1267                                domain))
1268         {
1269                 DEBUG(1,("failed session setup\n"));
1270                 nt_status = cli_nt_error(cli);
1271                 cli_shutdown(cli);
1272                 return nt_status;
1273         } 
1274
1275         if (service)
1276         {
1277                 if (!cli_send_tconX(cli, service, service_type,
1278                                     (char*)password, pass_len))
1279                 {
1280                         DEBUG(1,("failed tcon_X\n"));
1281                         nt_status = cli_nt_error(cli);
1282                         cli_shutdown(cli);
1283                         return nt_status;
1284                 }
1285         }
1286
1287         init_creds(&creds, user, domain, password, pass_len);
1288         cli_init_creds(cli, &creds);
1289
1290         *output_cli = cli;
1291         return NT_STATUS_OK;
1292 }
1293
1294 /****************************************************************************
1295  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1296 ****************************************************************************/
1297
1298 BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char *desthost,
1299                                      struct in_addr *pdest_ip)
1300 {
1301   struct nmb_name calling, called;
1302
1303   make_nmb_name(&calling, srchost, 0x0);
1304
1305   /*
1306    * If the called name is an IP address
1307    * then use *SMBSERVER immediately.
1308    */
1309
1310   if(is_ipaddress(desthost))
1311     make_nmb_name(&called, "*SMBSERVER", 0x20);
1312   else
1313     make_nmb_name(&called, desthost, 0x20);
1314
1315   if (!cli_session_request(cli, &calling, &called)) {
1316     struct nmb_name smbservername;
1317
1318     make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1319
1320     /*
1321      * If the name wasn't *SMBSERVER then
1322      * try with *SMBSERVER if the first name fails.
1323      */
1324
1325     if (nmb_name_equal(&called, &smbservername)) {
1326
1327         /*
1328          * The name used was *SMBSERVER, don't bother with another name.
1329          */
1330
1331         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1332 with error %s.\n", desthost, cli_errstr(cli) ));
1333         cli_shutdown(cli);
1334         return False;
1335     }
1336
1337     cli_shutdown(cli);
1338
1339     if (!cli_initialise(cli) ||
1340         !cli_connect(cli, desthost, pdest_ip) ||
1341         !cli_session_request(cli, &calling, &smbservername)) {
1342           DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1343 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
1344           cli_shutdown(cli);
1345           return False;
1346     }
1347   }
1348
1349   return True;
1350 }
1351
1352