When doing a cli_ulogoff don't invalidate the cnum, invalidate the vuid.
[obnox/samba-ctdb.git] / source / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
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 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22
23 static const struct {
24         int prot;
25         const char *name;
26 } prots[] = {
27         {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
28         {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
29         {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
30         {PROTOCOL_LANMAN1,"LANMAN1.0"},
31         {PROTOCOL_LANMAN2,"LM1.2X002"},
32         {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
33         {PROTOCOL_LANMAN2,"LANMAN2.1"},
34         {PROTOCOL_LANMAN2,"Samba"},
35         {PROTOCOL_NT1,"NT LANMAN 1.0"},
36         {PROTOCOL_NT1,"NT LM 0.12"},
37         {-1,NULL}
38 };
39
40 static const char *star_smbserver_name = "*SMBSERVER";
41
42 /**
43  * Set the user session key for a connection
44  * @param cli The cli structure to add it too
45  * @param session_key The session key used.  (A copy of this is taken for the cli struct)
46  *
47  */
48
49 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key) 
50 {
51         cli->user_session_key = data_blob(session_key.data, session_key.length);
52 }
53
54 /****************************************************************************
55  Do an old lanman2 style session setup.
56 ****************************************************************************/
57
58 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
59                                           const char *user, 
60                                           const char *pass, size_t passlen,
61                                           const char *workgroup)
62 {
63         DATA_BLOB session_key = data_blob_null;
64         DATA_BLOB lm_response = data_blob_null;
65         fstring pword;
66         char *p;
67
68         if (passlen > sizeof(pword)-1) {
69                 return NT_STATUS_INVALID_PARAMETER;
70         }
71
72         /* LANMAN servers predate NT status codes and Unicode and ignore those 
73            smb flags so we must disable the corresponding default capabilities  
74            that would otherwise cause the Unicode and NT Status flags to be
75            set (and even returned by the server) */
76
77         cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
78
79         /* if in share level security then don't send a password now */
80         if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
81                 passlen = 0;
82
83         if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
84                 /* Encrypted mode needed, and non encrypted password supplied. */
85                 lm_response = data_blob(NULL, 24);
86                 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
87                         DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
88                         return NT_STATUS_ACCESS_DENIED;
89                 }
90         } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
91                 /* Encrypted mode needed, and encrypted password supplied. */
92                 lm_response = data_blob(pass, passlen);
93         } else if (passlen > 0) {
94                 /* Plaintext mode needed, assume plaintext supplied. */
95                 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
96                 lm_response = data_blob(pass, passlen);
97         }
98
99         /* send a session setup command */
100         memset(cli->outbuf,'\0',smb_size);
101         cli_set_message(cli->outbuf,10, 0, True);
102         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
103         cli_setup_packet(cli);
104         
105         SCVAL(cli->outbuf,smb_vwv0,0xFF);
106         SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
107         SSVAL(cli->outbuf,smb_vwv3,2);
108         SSVAL(cli->outbuf,smb_vwv4,1);
109         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
110         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
111
112         p = smb_buf(cli->outbuf);
113         memcpy(p,lm_response.data,lm_response.length);
114         p += lm_response.length;
115         p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
116         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
117         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
118         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
119         cli_setup_bcc(cli, p);
120
121         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
122                 return cli_nt_error(cli);
123         }
124
125         show_msg(cli->inbuf);
126
127         if (cli_is_error(cli)) {
128                 return cli_nt_error(cli);
129         }
130         
131         /* use the returned vuid from now on */
132         cli->vuid = SVAL(cli->inbuf,smb_uid);   
133         fstrcpy(cli->user_name, user);
134
135         if (session_key.data) {
136                 /* Have plaintext orginal */
137                 cli_set_session_key(cli, session_key);
138         }
139
140         return NT_STATUS_OK;
141 }
142
143 /****************************************************************************
144  Work out suitable capabilities to offer the server.
145 ****************************************************************************/
146
147 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
148 {
149         uint32 capabilities = CAP_NT_SMBS;
150
151         if (!cli->force_dos_errors)
152                 capabilities |= CAP_STATUS32;
153
154         if (cli->use_level_II_oplocks)
155                 capabilities |= CAP_LEVEL_II_OPLOCKS;
156
157         capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
158         return capabilities;
159 }
160
161 /****************************************************************************
162  Do a NT1 guest session setup.
163 ****************************************************************************/
164
165 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
166 {
167         char *p;
168         uint32 capabilities = cli_session_setup_capabilities(cli);
169
170         memset(cli->outbuf, '\0', smb_size);
171         cli_set_message(cli->outbuf,13,0,True);
172         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
173         cli_setup_packet(cli);
174                         
175         SCVAL(cli->outbuf,smb_vwv0,0xFF);
176         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
177         SSVAL(cli->outbuf,smb_vwv3,2);
178         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
179         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
180         SSVAL(cli->outbuf,smb_vwv7,0);
181         SSVAL(cli->outbuf,smb_vwv8,0);
182         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
183         p = smb_buf(cli->outbuf);
184         p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
185         p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
186         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
187         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
188         cli_setup_bcc(cli, p);
189
190         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
191                 return cli_nt_error(cli);
192         }
193         
194         show_msg(cli->inbuf);
195         
196         if (cli_is_error(cli)) {
197                 return cli_nt_error(cli);
198         }
199
200         cli->vuid = SVAL(cli->inbuf,smb_uid);
201
202         p = smb_buf(cli->inbuf);
203         p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
204         p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
205         p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
206
207         if (strstr(cli->server_type, "Samba")) {
208                 cli->is_samba = True;
209         }
210
211         fstrcpy(cli->user_name, "");
212
213         return NT_STATUS_OK;
214 }
215
216 /****************************************************************************
217  Do a NT1 plaintext session setup.
218 ****************************************************************************/
219
220 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
221                                             const char *user, const char *pass,
222                                             const char *workgroup)
223 {
224         uint32 capabilities = cli_session_setup_capabilities(cli);
225         char *p;
226         fstring lanman;
227         
228         fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
229
230         memset(cli->outbuf, '\0', smb_size);
231         cli_set_message(cli->outbuf,13,0,True);
232         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
233         cli_setup_packet(cli);
234                         
235         SCVAL(cli->outbuf,smb_vwv0,0xFF);
236         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
237         SSVAL(cli->outbuf,smb_vwv3,2);
238         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
239         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
240         SSVAL(cli->outbuf,smb_vwv8,0);
241         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
242         p = smb_buf(cli->outbuf);
243         
244         /* check wether to send the ASCII or UNICODE version of the password */
245         
246         if ( (capabilities & CAP_UNICODE) == 0 ) {
247                 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
248                 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
249         }
250         else {
251                 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
252                  * the space taken by the unicode password to be one byte too
253                  * long (as we're on an odd byte boundary here). Reduce the
254                  * count by 1 to cope with this. Fixes smbclient against NetApp
255                  * servers which can't cope. Fix from
256                  * bryan.kolodziej@allenlund.com in bug #3840.
257                  */
258                 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
259                 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);        
260         }
261         
262         p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
263         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
264         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
265         p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
266         cli_setup_bcc(cli, p);
267
268         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
269                 return cli_nt_error(cli);
270         }
271         
272         show_msg(cli->inbuf);
273         
274         if (cli_is_error(cli)) {
275                 return cli_nt_error(cli);
276         }
277
278         cli->vuid = SVAL(cli->inbuf,smb_uid);
279         p = smb_buf(cli->inbuf);
280         p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
281         p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
282         p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
283         fstrcpy(cli->user_name, user);
284
285         if (strstr(cli->server_type, "Samba")) {
286                 cli->is_samba = True;
287         }
288
289         return NT_STATUS_OK;
290 }
291
292 /****************************************************************************
293    do a NT1 NTLM/LM encrypted session setup - for when extended security
294    is not negotiated.
295    @param cli client state to create do session setup on
296    @param user username
297    @param pass *either* cleartext password (passlen !=24) or LM response.
298    @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
299    @param workgroup The user's domain.
300 ****************************************************************************/
301
302 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user, 
303                                       const char *pass, size_t passlen,
304                                       const char *ntpass, size_t ntpasslen,
305                                       const char *workgroup)
306 {
307         uint32 capabilities = cli_session_setup_capabilities(cli);
308         DATA_BLOB lm_response = data_blob_null;
309         DATA_BLOB nt_response = data_blob_null;
310         DATA_BLOB session_key = data_blob_null;
311         NTSTATUS result;
312         char *p;
313
314         if (passlen == 0) {
315                 /* do nothing - guest login */
316         } else if (passlen != 24) {
317                 if (lp_client_ntlmv2_auth()) {
318                         DATA_BLOB server_chal;
319                         DATA_BLOB names_blob;
320                         server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); 
321
322                         /* note that the 'workgroup' here is a best guess - we don't know
323                            the server's domain at this point.  The 'server name' is also
324                            dodgy... 
325                         */
326                         names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
327
328                         if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal, 
329                                               &names_blob,
330                                               &lm_response, &nt_response, &session_key)) {
331                                 data_blob_free(&names_blob);
332                                 data_blob_free(&server_chal);
333                                 return NT_STATUS_ACCESS_DENIED;
334                         }
335                         data_blob_free(&names_blob);
336                         data_blob_free(&server_chal);
337
338                 } else {
339                         uchar nt_hash[16];
340                         E_md4hash(pass, nt_hash);
341
342 #ifdef LANMAN_ONLY
343                         nt_response = data_blob_null;
344 #else
345                         nt_response = data_blob(NULL, 24);
346                         SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
347 #endif
348                         /* non encrypted password supplied. Ignore ntpass. */
349                         if (lp_client_lanman_auth()) {
350                                 lm_response = data_blob(NULL, 24);
351                                 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
352                                         /* Oops, the LM response is invalid, just put 
353                                            the NT response there instead */
354                                         data_blob_free(&lm_response);
355                                         lm_response = data_blob(nt_response.data, nt_response.length);
356                                 }
357                         } else {
358                                 /* LM disabled, place NT# in LM field instead */
359                                 lm_response = data_blob(nt_response.data, nt_response.length);
360                         }
361
362                         session_key = data_blob(NULL, 16);
363 #ifdef LANMAN_ONLY
364                         E_deshash(pass, session_key.data);
365                         memset(&session_key.data[8], '\0', 8);
366 #else
367                         SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
368 #endif
369                 }
370 #ifdef LANMAN_ONLY
371                 cli_simple_set_signing(cli, session_key, lm_response); 
372 #else
373                 cli_simple_set_signing(cli, session_key, nt_response); 
374 #endif
375         } else {
376                 /* pre-encrypted password supplied.  Only used for 
377                    security=server, can't do
378                    signing because we don't have original key */
379
380                 lm_response = data_blob(pass, passlen);
381                 nt_response = data_blob(ntpass, ntpasslen);
382         }
383
384         /* send a session setup command */
385         memset(cli->outbuf,'\0',smb_size);
386
387         cli_set_message(cli->outbuf,13,0,True);
388         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
389         cli_setup_packet(cli);
390                         
391         SCVAL(cli->outbuf,smb_vwv0,0xFF);
392         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
393         SSVAL(cli->outbuf,smb_vwv3,2);
394         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
395         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
396         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
397         SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
398         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
399         p = smb_buf(cli->outbuf);
400         if (lm_response.length) {
401                 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
402         }
403         if (nt_response.length) {
404                 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
405         }
406         p += clistr_push(cli, p, user, -1, STR_TERMINATE);
407
408         /* Upper case here might help some NTLMv2 implementations */
409         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
410         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
411         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
412         cli_setup_bcc(cli, p);
413
414         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
415                 result = cli_nt_error(cli);
416                 goto end;
417         }
418
419         /* show_msg(cli->inbuf); */
420
421         if (cli_is_error(cli)) {
422                 result = cli_nt_error(cli);
423                 goto end;
424         }
425
426         /* use the returned vuid from now on */
427         cli->vuid = SVAL(cli->inbuf,smb_uid);
428         
429         p = smb_buf(cli->inbuf);
430         p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
431         p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
432         p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
433
434         if (strstr(cli->server_type, "Samba")) {
435                 cli->is_samba = True;
436         }
437
438         fstrcpy(cli->user_name, user);
439
440         if (session_key.data) {
441                 /* Have plaintext orginal */
442                 cli_set_session_key(cli, session_key);
443         }
444
445         result = NT_STATUS_OK;
446 end:    
447         data_blob_free(&lm_response);
448         data_blob_free(&nt_response);
449         data_blob_free(&session_key);
450         return result;
451 }
452
453 /****************************************************************************
454  Send a extended security session setup blob
455 ****************************************************************************/
456
457 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
458 {
459         uint32 capabilities = cli_session_setup_capabilities(cli);
460         char *p;
461
462         capabilities |= CAP_EXTENDED_SECURITY;
463
464         /* send a session setup command */
465         memset(cli->outbuf,'\0',smb_size);
466
467         cli_set_message(cli->outbuf,12,0,True);
468         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
469
470         cli_setup_packet(cli);
471                         
472         SCVAL(cli->outbuf,smb_vwv0,0xFF);
473         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
474         SSVAL(cli->outbuf,smb_vwv3,2);
475         SSVAL(cli->outbuf,smb_vwv4,1);
476         SIVAL(cli->outbuf,smb_vwv5,0);
477         SSVAL(cli->outbuf,smb_vwv7,blob.length);
478         SIVAL(cli->outbuf,smb_vwv10,capabilities); 
479         p = smb_buf(cli->outbuf);
480         memcpy(p, blob.data, blob.length);
481         p += blob.length;
482         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
483         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
484         cli_setup_bcc(cli, p);
485         return cli_send_smb(cli);
486 }
487
488 /****************************************************************************
489  Send a extended security session setup blob, returning a reply blob.
490 ****************************************************************************/
491
492 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
493 {
494         DATA_BLOB blob2 = data_blob_null;
495         char *p;
496         size_t len;
497
498         if (!cli_receive_smb(cli))
499                 return blob2;
500
501         show_msg(cli->inbuf);
502
503         if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
504                                                   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
505                 return blob2;
506         }
507         
508         /* use the returned vuid from now on */
509         cli->vuid = SVAL(cli->inbuf,smb_uid);
510         
511         p = smb_buf(cli->inbuf);
512
513         blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
514
515         p += blob2.length;
516         p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
517
518         /* w2k with kerberos doesn't properly null terminate this field */
519         len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
520         p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
521
522         return blob2;
523 }
524
525 #ifdef HAVE_KRB5
526 /****************************************************************************
527  Send a extended security session setup blob, returning a reply blob.
528 ****************************************************************************/
529
530 /* The following is calculated from :
531  * (smb_size-4) = 35
532  * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
533  * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
534  * end of packet.
535  */
536
537 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
538
539 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
540 {
541         int32 remaining = blob.length;
542         int32 cur = 0;
543         DATA_BLOB send_blob = data_blob_null;
544         int32 max_blob_size = 0;
545         DATA_BLOB receive_blob = data_blob_null;
546
547         if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
548                 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
549                         "(was %u, need minimum %u)\n",
550                         (unsigned int)cli->max_xmit,
551                         BASE_SESSSETUP_BLOB_PACKET_SIZE));
552                 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
553                 return False;
554         }
555
556         max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
557
558         while ( remaining > 0) {
559                 if (remaining >= max_blob_size) {
560                         send_blob.length = max_blob_size;
561                         remaining -= max_blob_size;
562                 } else {
563                         send_blob.length = remaining; 
564                         remaining = 0;
565                 }
566
567                 send_blob.data =  &blob.data[cur];
568                 cur += send_blob.length;
569
570                 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n", 
571                         (unsigned int)remaining,
572                         (unsigned int)send_blob.length,
573                         (unsigned int)cur ));
574
575                 if (!cli_session_setup_blob_send(cli, send_blob)) {
576                         DEBUG(0, ("cli_session_setup_blob: send failed\n"));
577                         return False;
578                 }
579
580                 receive_blob = cli_session_setup_blob_receive(cli);
581                 data_blob_free(&receive_blob);
582
583                 if (cli_is_error(cli) &&
584                                 !NT_STATUS_EQUAL( cli_get_nt_error(cli), 
585                                         NT_STATUS_MORE_PROCESSING_REQUIRED)) {
586                         DEBUG(0, ("cli_session_setup_blob: receive failed "
587                                   "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
588                         cli->vuid = 0;
589                         return False;
590                 }
591         }
592
593         return True;
594 }
595
596 /****************************************************************************
597  Use in-memory credentials cache
598 ****************************************************************************/
599
600 static void use_in_memory_ccache(void) {
601         setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
602 }
603
604 /****************************************************************************
605  Do a spnego/kerberos encrypted session setup.
606 ****************************************************************************/
607
608 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
609 {
610         DATA_BLOB negTokenTarg;
611         DATA_BLOB session_key_krb5;
612         NTSTATUS nt_status;
613         int rc;
614
615         cli_temp_set_signing(cli);
616
617         DEBUG(2,("Doing kerberos session setup\n"));
618
619         /* generate the encapsulated kerberos5 ticket */
620         rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
621
622         if (rc) {
623                 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
624                         error_message(rc)));
625                 return ADS_ERROR_KRB5(rc);
626         }
627
628 #if 0
629         file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
630 #endif
631
632         if (!cli_session_setup_blob(cli, negTokenTarg)) {
633                 nt_status = cli_nt_error(cli);
634                 goto nt_error;
635         }
636
637         if (cli_is_error(cli)) {
638                 nt_status = cli_nt_error(cli);
639                 if (NT_STATUS_IS_OK(nt_status)) {
640                         nt_status = NT_STATUS_UNSUCCESSFUL;
641                 }
642                 goto nt_error;
643         }
644
645         cli_set_session_key(cli, session_key_krb5);
646
647         if (cli_simple_set_signing(
648                     cli, session_key_krb5, data_blob_null)) {
649
650                 /* 'resign' the last message, so we get the right sequence numbers
651                    for checking the first reply from the server */
652                 cli_calculate_sign_mac(cli, cli->outbuf);
653
654                 if (!cli_check_sign_mac(cli, cli->inbuf)) {
655                         nt_status = NT_STATUS_ACCESS_DENIED;
656                         goto nt_error;
657                 }
658         }
659
660         data_blob_free(&negTokenTarg);
661         data_blob_free(&session_key_krb5);
662
663         return ADS_ERROR_NT(NT_STATUS_OK);
664
665 nt_error:
666         data_blob_free(&negTokenTarg);
667         data_blob_free(&session_key_krb5);
668         cli->vuid = 0;
669         return ADS_ERROR_NT(nt_status);
670 }
671 #endif  /* HAVE_KRB5 */
672
673
674 /****************************************************************************
675  Do a spnego/NTLMSSP encrypted session setup.
676 ****************************************************************************/
677
678 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, 
679                                           const char *pass, const char *domain)
680 {
681         struct ntlmssp_state *ntlmssp_state;
682         NTSTATUS nt_status;
683         int turn = 1;
684         DATA_BLOB msg1;
685         DATA_BLOB blob = data_blob_null;
686         DATA_BLOB blob_in = data_blob_null;
687         DATA_BLOB blob_out = data_blob_null;
688
689         cli_temp_set_signing(cli);
690
691         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
692                 return nt_status;
693         }
694         ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
695
696         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
697                 return nt_status;
698         }
699         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
700                 return nt_status;
701         }
702         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
703                 return nt_status;
704         }
705
706         do {
707                 nt_status = ntlmssp_update(ntlmssp_state, 
708                                                   blob_in, &blob_out);
709                 data_blob_free(&blob_in);
710                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
711                         if (turn == 1) {
712                                 /* and wrap it in a SPNEGO wrapper */
713                                 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
714                         } else {
715                                 /* wrap it in SPNEGO */
716                                 msg1 = spnego_gen_auth(blob_out);
717                         }
718                 
719                         /* now send that blob on its way */
720                         if (!cli_session_setup_blob_send(cli, msg1)) {
721                                 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
722                                 nt_status = NT_STATUS_UNSUCCESSFUL;
723                         } else {
724                                 blob = cli_session_setup_blob_receive(cli);
725                                 
726                                 nt_status = cli_nt_error(cli);
727                                 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
728                                         if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
729                                                 nt_status = NT_STATUS_ACCESS_DENIED;
730                                         } else {
731                                                 nt_status = NT_STATUS_UNSUCCESSFUL;
732                                         }
733                                 }
734                         }
735                         data_blob_free(&msg1);
736                 }
737                 
738                 if (!blob.length) {
739                         if (NT_STATUS_IS_OK(nt_status)) {
740                                 nt_status = NT_STATUS_UNSUCCESSFUL;
741                         }
742                 } else if ((turn == 1) && 
743                            NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
744                         DATA_BLOB tmp_blob = data_blob_null;
745                         /* the server might give us back two challenges */
746                         if (!spnego_parse_challenge(blob, &blob_in, 
747                                                     &tmp_blob)) {
748                                 DEBUG(3,("Failed to parse challenges\n"));
749                                 nt_status = NT_STATUS_INVALID_PARAMETER;
750                         }
751                         data_blob_free(&tmp_blob);
752                 } else {
753                         if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP, 
754                                                         &blob_in)) {
755                                 DEBUG(3,("Failed to parse auth response\n"));
756                                 if (NT_STATUS_IS_OK(nt_status) 
757                                     || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) 
758                                         nt_status = NT_STATUS_INVALID_PARAMETER;
759                         }
760                 }
761                 data_blob_free(&blob);
762                 data_blob_free(&blob_out);
763                 turn++;
764         } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
765
766         data_blob_free(&blob_in);
767
768         if (NT_STATUS_IS_OK(nt_status)) {
769
770                 DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
771                                           ntlmssp_state->session_key.length);
772                 DATA_BLOB null_blob = data_blob_null;
773                 bool res;
774
775                 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
776                 cli_set_session_key(cli, ntlmssp_state->session_key);
777
778                 res = cli_simple_set_signing(cli, key, null_blob);
779
780                 data_blob_free(&key);
781
782                 if (res) {
783                         
784                         /* 'resign' the last message, so we get the right sequence numbers
785                            for checking the first reply from the server */
786                         cli_calculate_sign_mac(cli, cli->outbuf);
787                         
788                         if (!cli_check_sign_mac(cli, cli->inbuf)) {
789                                 nt_status = NT_STATUS_ACCESS_DENIED;
790                         }
791                 }
792         }
793
794         /* we have a reference conter on ntlmssp_state, if we are signing
795            then the state will be kept by the signing engine */
796
797         ntlmssp_end(&ntlmssp_state);
798
799         if (!NT_STATUS_IS_OK(nt_status)) {
800                 cli->vuid = 0;
801         }
802         return nt_status;
803 }
804
805 /****************************************************************************
806  Do a spnego encrypted session setup.
807
808  user_domain: The shortname of the domain the user/machine is a member of.
809  dest_realm: The realm we're connecting to, if NULL we use our default realm.
810 ****************************************************************************/
811
812 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
813                               const char *pass, const char *user_domain,
814                               const char * dest_realm)
815 {
816         char *principal = NULL;
817         char *OIDs[ASN1_MAX_OIDS];
818         int i;
819         DATA_BLOB blob;
820         const char *p = NULL;
821         char *account = NULL;
822
823         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
824
825         /* the server might not even do spnego */
826         if (cli->secblob.length <= 16) {
827                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
828                 goto ntlmssp;
829         }
830
831 #if 0
832         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
833 #endif
834
835         /* there is 16 bytes of GUID before the real spnego packet starts */
836         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
837
838         /* The server sent us the first part of the SPNEGO exchange in the
839          * negprot reply. It is WRONG to depend on the principal sent in the
840          * negprot reply, but right now we do it. If we don't receive one,
841          * we try to best guess, then fall back to NTLM.  */
842         if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
843                 data_blob_free(&blob);
844                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
845         }
846         data_blob_free(&blob);
847
848         /* make sure the server understands kerberos */
849         for (i=0;OIDs[i];i++) {
850                 DEBUG(3,("got OID=%s\n", OIDs[i]));
851                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
852                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
853                         cli->got_kerberos_mechanism = True;
854                 }
855                 free(OIDs[i]);
856         }
857
858         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
859
860         fstrcpy(cli->user_name, user);
861
862 #ifdef HAVE_KRB5
863         /* If password is set we reauthenticate to kerberos server
864          * and do not store results */
865
866         if (cli->got_kerberos_mechanism && cli->use_kerberos) {
867                 ADS_STATUS rc;
868
869                 if (pass && *pass) {
870                         int ret;
871                         
872                         use_in_memory_ccache();
873                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
874                         
875                         if (ret){
876                                 SAFE_FREE(principal);
877                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
878                                 if (cli->fallback_after_kerberos)
879                                         goto ntlmssp;
880                                 return ADS_ERROR_KRB5(ret);
881                         }
882                 }
883                 
884                 /* If we get a bad principal, try to guess it if
885                    we have a valid host NetBIOS name.
886                  */
887                 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
888                         SAFE_FREE(principal);
889                 }
890
891                 if (principal == NULL &&
892                         !is_ipaddress(cli->desthost) &&
893                         !strequal(star_smbserver_name,
894                                 cli->desthost)) {
895                         char *realm = NULL;
896                         char *machine = NULL;
897                         char *host = NULL;
898                         DEBUG(3,("cli_session_setup_spnego: got a "
899                                 "bad server principal, trying to guess ...\n"));
900
901                         host = strchr_m(cli->desthost, '.');
902                         if (host) {
903                                 machine = SMB_STRNDUP(cli->desthost,
904                                         host - cli->desthost);
905                         } else {
906                                 machine = SMB_STRDUP(cli->desthost);
907                         }
908                         if (machine == NULL) {
909                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
910                         }
911
912                         if (dest_realm) {
913                                 realm = SMB_STRDUP(dest_realm);
914                                 strupper_m(realm);
915                         } else {
916                                 realm = kerberos_get_default_realm_from_ccache();
917                         }
918                         if (realm && *realm) {
919                                 if (asprintf(&principal, "%s$@%s",
920                                                 machine, realm) < 0) {
921                                         SAFE_FREE(machine);
922                                         SAFE_FREE(realm);
923                                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
924                                 }
925                                 DEBUG(3,("cli_session_setup_spnego: guessed "
926                                         "server principal=%s\n",
927                                         principal ? principal : "<null>"));
928                         }
929                         SAFE_FREE(machine);
930                         SAFE_FREE(realm);
931                 }
932
933                 if (principal) {
934                         rc = cli_session_setup_kerberos(cli, principal,
935                                 dest_realm);
936                         if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
937                                 SAFE_FREE(principal);
938                                 return rc;
939                         }
940                 }
941         }
942 #endif
943
944         SAFE_FREE(principal);
945
946 ntlmssp:
947
948         account = talloc_strdup(talloc_tos(), user);
949         if (!account) {
950                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
951         }
952
953         /* when falling back to ntlmssp while authenticating with a machine
954          * account strip off the realm - gd */
955
956         if ((p = strchr_m(user, '@')) != NULL) {
957                 account[PTR_DIFF(p,user)] = '\0';
958         }
959
960         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
961 }
962
963 /****************************************************************************
964  Send a session setup. The username and workgroup is in UNIX character
965  format and must be converted to DOS codepage format before sending. If the
966  password is in plaintext, the same should be done.
967 ****************************************************************************/
968
969 NTSTATUS cli_session_setup(struct cli_state *cli,
970                            const char *user,
971                            const char *pass, int passlen,
972                            const char *ntpass, int ntpasslen,
973                            const char *workgroup)
974 {
975         char *p;
976         fstring user2;
977
978         if (user) {
979                 fstrcpy(user2, user);
980         } else {
981                 user2[0] ='\0';
982         }
983
984         if (!workgroup) {
985                 workgroup = "";
986         }
987
988         /* allow for workgroups as part of the username */
989         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
990             (p=strchr_m(user2,*lp_winbind_separator()))) {
991                 *p = 0;
992                 user = p+1;
993                 workgroup = user2;
994         }
995
996         if (cli->protocol < PROTOCOL_LANMAN1) {
997                 return NT_STATUS_OK;
998         }
999
1000         /* now work out what sort of session setup we are going to
1001            do. I have split this into separate functions to make the
1002            flow a bit easier to understand (tridge) */
1003
1004         /* if its an older server then we have to use the older request format */
1005
1006         if (cli->protocol < PROTOCOL_NT1) {
1007                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1008                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1009                                   " is disabled\n"));
1010                         return NT_STATUS_ACCESS_DENIED;
1011                 }
1012
1013                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1014                     !lp_client_plaintext_auth() && (*pass)) {
1015                         DEBUG(1, ("Server requested plaintext password but "
1016                                   "'client plaintext auth' is disabled\n"));
1017                         return NT_STATUS_ACCESS_DENIED;
1018                 }
1019
1020                 return cli_session_setup_lanman2(cli, user, pass, passlen,
1021                                                  workgroup);
1022         }
1023
1024         /* if no user is supplied then we have to do an anonymous connection.
1025            passwords are ignored */
1026
1027         if (!user || !*user)
1028                 return cli_session_setup_guest(cli);
1029
1030         /* if the server is share level then send a plaintext null
1031            password at this point. The password is sent in the tree
1032            connect */
1033
1034         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
1035                 return cli_session_setup_plaintext(cli, user, "", workgroup);
1036
1037         /* if the server doesn't support encryption then we have to use 
1038            plaintext. The second password is ignored */
1039
1040         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1041                 if (!lp_client_plaintext_auth() && (*pass)) {
1042                         DEBUG(1, ("Server requested plaintext password but "
1043                                   "'client plaintext auth' is disabled\n"));
1044                         return NT_STATUS_ACCESS_DENIED;
1045                 }
1046                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1047         }
1048
1049         /* if the server supports extended security then use SPNEGO */
1050
1051         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1052                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1053                                                              workgroup, NULL);
1054                 if (!ADS_ERR_OK(status)) {
1055                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1056                         return ads_ntstatus(status);
1057                 }
1058         } else {
1059                 NTSTATUS status;
1060
1061                 /* otherwise do a NT1 style session setup */
1062                 status = cli_session_setup_nt1(cli, user, pass, passlen,
1063                                                ntpass, ntpasslen, workgroup);
1064                 if (!NT_STATUS_IS_OK(status)) {
1065                         DEBUG(3,("cli_session_setup: NT1 session setup "
1066                                  "failed: %s\n", nt_errstr(status)));
1067                         return status;
1068                 }
1069         }
1070
1071         if (strstr(cli->server_type, "Samba")) {
1072                 cli->is_samba = True;
1073         }
1074
1075         return NT_STATUS_OK;
1076 }
1077
1078 /****************************************************************************
1079  Send a uloggoff.
1080 *****************************************************************************/
1081
1082 bool cli_ulogoff(struct cli_state *cli)
1083 {
1084         memset(cli->outbuf,'\0',smb_size);
1085         cli_set_message(cli->outbuf,2,0,True);
1086         SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1087         cli_setup_packet(cli);
1088         SSVAL(cli->outbuf,smb_vwv0,0xFF);
1089         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
1090
1091         cli_send_smb(cli);
1092         if (!cli_receive_smb(cli))
1093                 return False;
1094
1095         if (cli_is_error(cli)) {
1096                 return False;
1097         }
1098
1099         cli->vuid = -1;
1100         return True;
1101 }
1102
1103 /****************************************************************************
1104  Send a tconX.
1105 ****************************************************************************/
1106
1107 bool cli_send_tconX(struct cli_state *cli, 
1108                     const char *share, const char *dev, const char *pass, int passlen)
1109 {
1110         fstring fullshare, pword;
1111         char *p;
1112         memset(cli->outbuf,'\0',smb_size);
1113         memset(cli->inbuf,'\0',smb_size);
1114
1115         fstrcpy(cli->share, share);
1116
1117         /* in user level security don't send a password now */
1118         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1119                 passlen = 1;
1120                 pass = "";
1121         } else if (!pass) {
1122                 DEBUG(1, ("Server not using user level security and no password supplied.\n"));
1123                 return False;
1124         }
1125
1126         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1127             *pass && passlen != 24) {
1128                 if (!lp_client_lanman_auth()) {
1129                         DEBUG(1, ("Server requested LANMAN password "
1130                                   "(share-level security) but "
1131                                   "'client lanman auth' is disabled\n"));
1132                         return False;
1133                 }
1134
1135                 /*
1136                  * Non-encrypted passwords - convert to DOS codepage before encryption.
1137                  */
1138                 passlen = 24;
1139                 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
1140         } else {
1141                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
1142                         if (!lp_client_plaintext_auth() && (*pass)) {
1143                                 DEBUG(1, ("Server requested plaintext "
1144                                           "password but 'client plaintext "
1145                                           "auth' is disabled\n"));
1146                                 return False;
1147                         }
1148
1149                         /*
1150                          * Non-encrypted passwords - convert to DOS codepage before using.
1151                          */
1152                         passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
1153                         
1154                 } else {
1155                         if (passlen) {
1156                                 memcpy(pword, pass, passlen);
1157                         }
1158                 }
1159         }
1160
1161         slprintf(fullshare, sizeof(fullshare)-1,
1162                  "\\\\%s\\%s", cli->desthost, share);
1163
1164         cli_set_message(cli->outbuf,4, 0, True);
1165         SCVAL(cli->outbuf,smb_com,SMBtconX);
1166         cli_setup_packet(cli);
1167
1168         SSVAL(cli->outbuf,smb_vwv0,0xFF);
1169         SSVAL(cli->outbuf,smb_vwv2,TCONX_FLAG_EXTENDED_RESPONSE);
1170         SSVAL(cli->outbuf,smb_vwv3,passlen);
1171
1172         p = smb_buf(cli->outbuf);
1173         if (passlen) {
1174                 memcpy(p,pword,passlen);
1175         }
1176         p += passlen;
1177         p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
1178         p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
1179
1180         cli_setup_bcc(cli, p);
1181
1182         cli_send_smb(cli);
1183         if (!cli_receive_smb(cli))
1184                 return False;
1185
1186         if (cli_is_error(cli))
1187                 return False;
1188
1189         clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
1190
1191         if (cli->protocol >= PROTOCOL_NT1 &&
1192             smb_buflen(cli->inbuf) == 3) {
1193                 /* almost certainly win95 - enable bug fixes */
1194                 cli->win95 = True;
1195         }
1196         
1197         /* Make sure that we have the optional support 16-bit field.  WCT > 2 */
1198         /* Avoids issues when connecting to Win9x boxes sharing files */
1199
1200         cli->dfsroot = False;
1201         if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 )
1202                 cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False;
1203
1204         cli->cnum = SVAL(cli->inbuf,smb_tid);
1205         return True;
1206 }
1207
1208 /****************************************************************************
1209  Send a tree disconnect.
1210 ****************************************************************************/
1211
1212 bool cli_tdis(struct cli_state *cli)
1213 {
1214         memset(cli->outbuf,'\0',smb_size);
1215         cli_set_message(cli->outbuf,0,0,True);
1216         SCVAL(cli->outbuf,smb_com,SMBtdis);
1217         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1218         cli_setup_packet(cli);
1219         
1220         cli_send_smb(cli);
1221         if (!cli_receive_smb(cli))
1222                 return False;
1223         
1224         if (cli_is_error(cli)) {
1225                 return False;
1226         }
1227
1228         cli->cnum = -1;
1229         return True;
1230 }
1231
1232 /****************************************************************************
1233  Send a negprot command.
1234 ****************************************************************************/
1235
1236 void cli_negprot_send(struct cli_state *cli)
1237 {
1238         char *p;
1239         int numprots;
1240
1241         if (cli->protocol < PROTOCOL_NT1)
1242                 cli->use_spnego = False;
1243
1244         memset(cli->outbuf,'\0',smb_size);
1245
1246         /* setup the protocol strings */
1247         cli_set_message(cli->outbuf,0,0,True);
1248
1249         p = smb_buf(cli->outbuf);
1250         for (numprots=0;
1251              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1252              numprots++) {
1253                 *p++ = 2;
1254                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1255         }
1256
1257         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1258         cli_setup_bcc(cli, p);
1259         cli_setup_packet(cli);
1260
1261         SCVAL(smb_buf(cli->outbuf),0,2);
1262
1263         cli_send_smb(cli);
1264 }
1265
1266 /****************************************************************************
1267  Send a negprot command.
1268 ****************************************************************************/
1269
1270 bool cli_negprot(struct cli_state *cli)
1271 {
1272         char *p;
1273         int numprots;
1274         int plength;
1275
1276         if (cli->protocol < PROTOCOL_NT1)
1277                 cli->use_spnego = False;
1278
1279         memset(cli->outbuf,'\0',smb_size);
1280
1281         /* setup the protocol strings */
1282         for (plength=0,numprots=0;
1283              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1284              numprots++)
1285                 plength += strlen(prots[numprots].name)+2;
1286     
1287         cli_set_message(cli->outbuf,0,plength,True);
1288
1289         p = smb_buf(cli->outbuf);
1290         for (numprots=0;
1291              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1292              numprots++) {
1293                 *p++ = 2;
1294                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1295         }
1296
1297         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1298         cli_setup_packet(cli);
1299
1300         SCVAL(smb_buf(cli->outbuf),0,2);
1301
1302         cli_send_smb(cli);
1303         if (!cli_receive_smb(cli))
1304                 return False;
1305
1306         show_msg(cli->inbuf);
1307
1308         if (cli_is_error(cli) ||
1309             ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1310                 return(False);
1311         }
1312
1313         cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;  
1314
1315         if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1316                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1317                 return False;
1318         }
1319
1320         if (cli->protocol >= PROTOCOL_NT1) {    
1321                 struct timespec ts;
1322                 /* NT protocol */
1323                 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1324                 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1325                 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1326                 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1327                 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1328                 cli->serverzone *= 60;
1329                 /* this time arrives in real GMT */
1330                 ts = interpret_long_date(cli->inbuf+smb_vwv11+1);
1331                 cli->servertime = ts.tv_sec;
1332                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1333                 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1334                 if (cli->capabilities & CAP_RAW_MODE) {
1335                         cli->readbraw_supported = True;
1336                         cli->writebraw_supported = True;      
1337                 }
1338                 /* work out if they sent us a workgroup */
1339                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1340                     smb_buflen(cli->inbuf) > 8) {
1341                         clistr_pull(cli, cli->server_domain, 
1342                                     smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1343                                     smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1344                 }
1345
1346                 /*
1347                  * As signing is slow we only turn it on if either the client or
1348                  * the server require it. JRA.
1349                  */
1350
1351                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1352                         /* Fail if server says signing is mandatory and we don't want to support it. */
1353                         if (!cli->sign_info.allow_smb_signing) {
1354                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1355                                 return False;
1356                         }
1357                         cli->sign_info.negotiated_smb_signing = True;
1358                         cli->sign_info.mandatory_signing = True;
1359                 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1360                         /* Fail if client says signing is mandatory and the server doesn't support it. */
1361                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1362                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1363                                 return False;
1364                         }
1365                         cli->sign_info.negotiated_smb_signing = True;
1366                         cli->sign_info.mandatory_signing = True;
1367                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1368                         cli->sign_info.negotiated_smb_signing = True;
1369                 }
1370
1371                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1372                         SAFE_FREE(cli->outbuf);
1373                         SAFE_FREE(cli->inbuf);
1374                         cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1375                         cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1376                         cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1377                 }
1378
1379         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1380                 cli->use_spnego = False;
1381                 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1382                 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1383                 cli->max_mux = SVAL(cli->inbuf, smb_vwv3); 
1384                 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1385                 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1386                 cli->serverzone *= 60;
1387                 /* this time is converted to GMT by make_unix_date */
1388                 cli->servertime = cli_make_unix_date(cli,cli->inbuf+smb_vwv8);
1389                 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1390                 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1391                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1392         } else {
1393                 /* the old core protocol */
1394                 cli->use_spnego = False;
1395                 cli->sec_mode = 0;
1396                 cli->serverzone = get_time_zone(time(NULL));
1397         }
1398
1399         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1400
1401         /* a way to force ascii SMB */
1402         if (getenv("CLI_FORCE_ASCII"))
1403                 cli->capabilities &= ~CAP_UNICODE;
1404
1405         return True;
1406 }
1407
1408 /****************************************************************************
1409  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1410 ****************************************************************************/
1411
1412 bool cli_session_request(struct cli_state *cli,
1413                          struct nmb_name *calling, struct nmb_name *called)
1414 {
1415         char *p;
1416         int len = 4;
1417
1418         memcpy(&(cli->calling), calling, sizeof(*calling));
1419         memcpy(&(cli->called ), called , sizeof(*called ));
1420   
1421         /* put in the destination name */
1422         p = cli->outbuf+len;
1423         name_mangle(cli->called .name, p, cli->called .name_type);
1424         len += name_len(p);
1425
1426         /* and my name */
1427         p = cli->outbuf+len;
1428         name_mangle(cli->calling.name, p, cli->calling.name_type);
1429         len += name_len(p);
1430
1431         /* 445 doesn't have session request */
1432         if (cli->port == 445)
1433                 return True;
1434
1435         /* send a session request (RFC 1002) */
1436         /* setup the packet length
1437          * Remove four bytes from the length count, since the length
1438          * field in the NBT Session Service header counts the number
1439          * of bytes which follow.  The cli_send_smb() function knows
1440          * about this and accounts for those four bytes.
1441          * CRH.
1442          */
1443         len -= 4;
1444         _smb_setlen(cli->outbuf,len);
1445         SCVAL(cli->outbuf,0,0x81);
1446
1447         cli_send_smb(cli);
1448         DEBUG(5,("Sent session request\n"));
1449
1450         if (!cli_receive_smb(cli))
1451                 return False;
1452
1453         if (CVAL(cli->inbuf,0) == 0x84) {
1454                 /* C. Hoch  9/14/95 Start */
1455                 /* For information, here is the response structure.
1456                  * We do the byte-twiddling to for portability.
1457                 struct RetargetResponse{
1458                 unsigned char type;
1459                 unsigned char flags;
1460                 int16 length;
1461                 int32 ip_addr;
1462                 int16 port;
1463                 };
1464                 */
1465                 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1466                 struct in_addr dest_ip;
1467
1468                 /* SESSION RETARGET */
1469                 putip((char *)&dest_ip,cli->inbuf+4);
1470                 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1471
1472                 cli->fd = open_socket_out(SOCK_STREAM,
1473                                 &cli->dest_ss,
1474                                 port,
1475                                 LONG_CONNECT_TIMEOUT);
1476                 if (cli->fd == -1)
1477                         return False;
1478
1479                 DEBUG(3,("Retargeted\n"));
1480
1481                 set_socket_options(cli->fd, lp_socket_options());
1482
1483                 /* Try again */
1484                 {
1485                         static int depth;
1486                         bool ret;
1487                         if (depth > 4) {
1488                                 DEBUG(0,("Retarget recursion - failing\n"));
1489                                 return False;
1490                         }
1491                         depth++;
1492                         ret = cli_session_request(cli, calling, called);
1493                         depth--;
1494                         return ret;
1495                 }
1496         } /* C. Hoch 9/14/95 End */
1497
1498         if (CVAL(cli->inbuf,0) != 0x82) {
1499                 /* This is the wrong place to put the error... JRA. */
1500                 cli->rap_error = CVAL(cli->inbuf,4);
1501                 return False;
1502         }
1503         return(True);
1504 }
1505
1506 /****************************************************************************
1507  Open the client sockets.
1508 ****************************************************************************/
1509
1510 NTSTATUS cli_connect(struct cli_state *cli,
1511                 const char *host,
1512                 struct sockaddr_storage *dest_ss)
1513
1514 {
1515         int name_type = 0x20;
1516         TALLOC_CTX *frame = talloc_stackframe();
1517         unsigned int num_addrs = 0;
1518         unsigned int i = 0;
1519         struct sockaddr_storage *ss_arr = NULL;
1520         char *p = NULL;
1521
1522         /* reasonable default hostname */
1523         if (!host) {
1524                 host = star_smbserver_name;
1525         }
1526
1527         fstrcpy(cli->desthost, host);
1528         fstr_sprintf(cli->srv_name_slash, "\\\\%s", cli->desthost);
1529         strupper_m(cli->srv_name_slash);
1530
1531         /* allow hostnames of the form NAME#xx and do a netbios lookup */
1532         if ((p = strchr(cli->desthost, '#'))) {
1533                 name_type = strtol(p+1, NULL, 16);
1534                 *p = 0;
1535         }
1536
1537         if (!dest_ss || is_zero_addr(dest_ss)) {
1538                 NTSTATUS status =resolve_name_list(frame,
1539                                         cli->desthost,
1540                                         name_type,
1541                                         &ss_arr,
1542                                         &num_addrs);
1543                 if (!NT_STATUS_IS_OK(status)) {
1544                         TALLOC_FREE(frame);
1545                         return NT_STATUS_BAD_NETWORK_NAME;
1546                 }
1547         } else {
1548                 num_addrs = 1;
1549                 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1550                 if (!ss_arr) {
1551                         TALLOC_FREE(frame);
1552                         return NT_STATUS_NO_MEMORY;
1553                 }
1554                 *ss_arr = *dest_ss;
1555         }
1556
1557         for (i = 0; i < num_addrs; i++) {
1558                 cli->dest_ss = ss_arr[i];
1559                 if (getenv("LIBSMB_PROG")) {
1560                         cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1561                 } else {
1562                         /* try 445 first, then 139 */
1563                         uint16_t port = cli->port?cli->port:445;
1564                         cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss,
1565                                                   port, cli->timeout);
1566                         if (cli->fd == -1 && cli->port == 0) {
1567                                 port = 139;
1568                                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss,
1569                                                           port, cli->timeout);
1570                         }
1571                         if (cli->fd != -1) {
1572                                 cli->port = port;
1573                         }
1574                 }
1575                 if (cli->fd == -1) {
1576                         char addr[INET6_ADDRSTRLEN];
1577                         print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
1578                         DEBUG(2,("Error connecting to %s (%s)\n",
1579                                  dest_ss?addr:host,strerror(errno)));
1580                 } else {
1581                         /* Exit from loop on first connection. */
1582                         break;
1583                 }
1584         }
1585
1586         if (cli->fd == -1) {
1587                 TALLOC_FREE(frame);
1588                 return map_nt_error_from_unix(errno);
1589         }
1590
1591         if (dest_ss) {
1592                 *dest_ss = cli->dest_ss;
1593         }
1594
1595         set_socket_options(cli->fd, lp_socket_options());
1596
1597         TALLOC_FREE(frame);
1598         return NT_STATUS_OK;
1599 }
1600
1601 /**
1602    establishes a connection to after the negprot. 
1603    @param output_cli A fully initialised cli structure, non-null only on success
1604    @param dest_host The netbios name of the remote host
1605    @param dest_ss (optional) The the destination IP, NULL for name based lookup
1606    @param port (optional) The destination port (0 for default)
1607    @param retry bool. Did this connection fail with a retryable error ?
1608
1609 */
1610 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
1611                               const char *my_name, 
1612                               const char *dest_host, 
1613                               struct sockaddr_storage *dest_ss, int port,
1614                               int signing_state, int flags,
1615                               bool *retry) 
1616 {
1617         NTSTATUS nt_status;
1618         struct nmb_name calling;
1619         struct nmb_name called;
1620         struct cli_state *cli;
1621         struct sockaddr_storage ss;
1622
1623         if (retry)
1624                 *retry = False;
1625
1626         if (!my_name) 
1627                 my_name = global_myname();
1628         
1629         if (!(cli = cli_initialise())) {
1630                 return NT_STATUS_NO_MEMORY;
1631         }
1632         
1633         make_nmb_name(&calling, my_name, 0x0);
1634         make_nmb_name(&called , dest_host, 0x20);
1635
1636         if (cli_set_port(cli, port) != port) {
1637                 cli_shutdown(cli);
1638                 return NT_STATUS_UNSUCCESSFUL;
1639         }
1640
1641         cli_set_timeout(cli, 10000); /* 10 seconds. */
1642
1643         if (dest_ss) {
1644                 ss = *dest_ss;
1645         } else {
1646                 zero_sockaddr(&ss);
1647         }
1648
1649 again:
1650
1651         DEBUG(3,("Connecting to host=%s\n", dest_host));
1652
1653         nt_status = cli_connect(cli, dest_host, &ss);
1654         if (!NT_STATUS_IS_OK(nt_status)) {
1655                 char addr[INET6_ADDRSTRLEN];
1656                 print_sockaddr(addr, sizeof(addr), &ss);
1657                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1658                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
1659                 cli_shutdown(cli);
1660                 return nt_status;
1661         }
1662
1663         if (retry)
1664                 *retry = True;
1665
1666         if (!cli_session_request(cli, &calling, &called)) {
1667                 char *p;
1668                 DEBUG(1,("session request to %s failed (%s)\n",
1669                          called.name, cli_errstr(cli)));
1670                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1671                         *p = 0;
1672                         goto again;
1673                 }
1674                 if (strcmp(called.name, star_smbserver_name)) {
1675                         make_nmb_name(&called , star_smbserver_name, 0x20);
1676                         goto again;
1677                 }
1678                 return NT_STATUS_BAD_NETWORK_NAME;
1679         }
1680
1681         cli_setup_signing_state(cli, signing_state);
1682
1683         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1684                 cli->use_spnego = False;
1685         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1686                 cli->use_kerberos = True;
1687
1688         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
1689              cli->use_kerberos) {
1690                 cli->fallback_after_kerberos = true;
1691         }
1692
1693         if (!cli_negprot(cli)) {
1694                 DEBUG(1,("failed negprot\n"));
1695                 nt_status = cli_nt_error(cli);
1696                 if (NT_STATUS_IS_OK(nt_status)) {
1697                         nt_status = NT_STATUS_UNSUCCESSFUL;
1698                 }
1699                 cli_shutdown(cli);
1700                 return nt_status;
1701         }
1702
1703         *output_cli = cli;
1704         return NT_STATUS_OK;
1705 }
1706
1707
1708 /**
1709    establishes a connection right up to doing tconX, password specified.
1710    @param output_cli A fully initialised cli structure, non-null only on success
1711    @param dest_host The netbios name of the remote host
1712    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1713    @param port (optional) The destination port (0 for default)
1714    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
1715    @param service_type The 'type' of serivice. 
1716    @param user Username, unix string
1717    @param domain User's domain
1718    @param password User's password, unencrypted unix string.
1719    @param retry bool. Did this connection fail with a retryable error ?
1720 */
1721
1722 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
1723                              const char *my_name, 
1724                              const char *dest_host, 
1725                              struct sockaddr_storage *dest_ss, int port,
1726                              const char *service, const char *service_type,
1727                              const char *user, const char *domain, 
1728                              const char *password, int flags,
1729                              int signing_state,
1730                              bool *retry) 
1731 {
1732         NTSTATUS nt_status;
1733         struct cli_state *cli = NULL;
1734         int pw_len = password ? strlen(password)+1 : 0;
1735
1736         *output_cli = NULL;
1737
1738         if (password == NULL) {
1739                 password = "";
1740         }
1741
1742         nt_status = cli_start_connection(&cli, my_name, dest_host,
1743                                          dest_ss, port, signing_state,
1744                                          flags, retry);
1745
1746         if (!NT_STATUS_IS_OK(nt_status)) {
1747                 return nt_status;
1748         }
1749
1750         nt_status = cli_session_setup(cli, user, password, pw_len, password,
1751                                       pw_len, domain);
1752         if (!NT_STATUS_IS_OK(nt_status)) {
1753
1754                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
1755                         DEBUG(1,("failed session setup with %s\n",
1756                                  nt_errstr(nt_status)));
1757                         cli_shutdown(cli);
1758                         return nt_status;
1759                 }
1760
1761                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
1762                 if (!NT_STATUS_IS_OK(nt_status)) {
1763                         DEBUG(1,("anonymous failed session setup with %s\n",
1764                                  nt_errstr(nt_status)));
1765                         cli_shutdown(cli);
1766                         return nt_status;
1767                 }
1768         }
1769
1770         if (service) {
1771                 if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
1772                         nt_status = cli_nt_error(cli);
1773                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1774                         cli_shutdown(cli);
1775                         if (NT_STATUS_IS_OK(nt_status)) {
1776                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1777                         }
1778                         return nt_status;
1779                 }
1780         }
1781
1782         cli_init_creds(cli, user, domain, password);
1783
1784         *output_cli = cli;
1785         return NT_STATUS_OK;
1786 }
1787
1788 /****************************************************************************
1789  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1790 ****************************************************************************/
1791
1792 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
1793                                      struct sockaddr_storage *pdest_ss)
1794 {
1795         struct nmb_name calling, called;
1796
1797         make_nmb_name(&calling, srchost, 0x0);
1798
1799         /*
1800          * If the called name is an IP address
1801          * then use *SMBSERVER immediately.
1802          */
1803
1804         if(is_ipaddress(desthost)) {
1805                 make_nmb_name(&called, star_smbserver_name, 0x20);
1806         } else {
1807                 make_nmb_name(&called, desthost, 0x20);
1808         }
1809
1810         if (!cli_session_request(*ppcli, &calling, &called)) {
1811                 NTSTATUS status;
1812                 struct nmb_name smbservername;
1813
1814                 make_nmb_name(&smbservername, star_smbserver_name, 0x20);
1815
1816                 /*
1817                  * If the name wasn't *SMBSERVER then
1818                  * try with *SMBSERVER if the first name fails.
1819                  */
1820
1821                 if (nmb_name_equal(&called, &smbservername)) {
1822
1823                         /*
1824                          * The name used was *SMBSERVER, don't bother with another name.
1825                          */
1826
1827                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1828 with error %s.\n", desthost, cli_errstr(*ppcli) ));
1829                         return False;
1830                 }
1831
1832                 /* Try again... */
1833                 cli_shutdown(*ppcli);
1834
1835                 *ppcli = cli_initialise();
1836                 if (!*ppcli) {
1837                         /* Out of memory... */
1838                         return False;
1839                 }
1840
1841                 status = cli_connect(*ppcli, desthost, pdest_ss);
1842                 if (!NT_STATUS_IS_OK(status) ||
1843                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
1844                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1845 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
1846                         return False;
1847                 }
1848         }
1849
1850         return True;
1851 }
1852
1853 /****************************************************************************
1854  Send an old style tcon.
1855 ****************************************************************************/
1856 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
1857                       const char *service, const char *pass, const char *dev,
1858                       uint16 *max_xmit, uint16 *tid)
1859 {
1860         char *p;
1861
1862         if (!lp_client_plaintext_auth() && (*pass)) {
1863                 DEBUG(1, ("Server requested plaintext password but 'client "
1864                           "plaintext auth' is disabled\n"));
1865                 return NT_STATUS_ACCESS_DENIED;
1866         }
1867
1868         memset(cli->outbuf,'\0',smb_size);
1869         memset(cli->inbuf,'\0',smb_size);
1870
1871         cli_set_message(cli->outbuf, 0, 0, True);
1872         SCVAL(cli->outbuf,smb_com,SMBtcon);
1873         cli_setup_packet(cli);
1874
1875         p = smb_buf(cli->outbuf);
1876         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1877         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1878         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1879
1880         cli_setup_bcc(cli, p);
1881
1882         cli_send_smb(cli);
1883         if (!cli_receive_smb(cli)) {
1884                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1885         }
1886
1887         if (cli_is_error(cli)) {
1888                 return cli_nt_error(cli);
1889         }
1890
1891         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1892         *tid = SVAL(cli->inbuf, smb_vwv1);
1893
1894         return NT_STATUS_OK;
1895 }
1896
1897 /* Return a cli_state pointing at the IPC$ share for the given server */
1898
1899 struct cli_state *get_ipc_connect(char *server,
1900                                 struct sockaddr_storage *server_ss,
1901                                 const struct user_auth_info *user_info)
1902 {
1903         struct cli_state *cli;
1904         NTSTATUS nt_status;
1905         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
1906
1907         if (user_info->use_kerberos) {
1908                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
1909         }
1910
1911         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
1912                                         user_info->username ? user_info->username : "",
1913                                         lp_workgroup(),
1914                                         user_info->password ? user_info->password : "",
1915                                         flags,
1916                                         Undefined, NULL);
1917
1918         if (NT_STATUS_IS_OK(nt_status)) {
1919                 return cli;
1920         } else if (is_ipaddress(server)) {
1921             /* windows 9* needs a correct NMB name for connections */
1922             fstring remote_name;
1923
1924             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
1925                 cli = get_ipc_connect(remote_name, server_ss, user_info);
1926                 if (cli)
1927                     return cli;
1928             }
1929         }
1930         return NULL;
1931 }
1932
1933 /*
1934  * Given the IP address of a master browser on the network, return its
1935  * workgroup and connect to it.
1936  *
1937  * This function is provided to allow additional processing beyond what
1938  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
1939  * browsers and obtain each master browsers' list of domains (in case the
1940  * first master browser is recently on the network and has not yet
1941  * synchronized with other master browsers and therefore does not yet have the
1942  * entire network browse list)
1943  */
1944
1945 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
1946                                 struct ip_service *mb_ip,
1947                                 const struct user_auth_info *user_info,
1948                                 char **pp_workgroup_out)
1949 {
1950         char addr[INET6_ADDRSTRLEN];
1951         fstring name;
1952         struct cli_state *cli;
1953         struct sockaddr_storage server_ss;
1954
1955         *pp_workgroup_out = NULL;
1956
1957         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
1958         DEBUG(99, ("Looking up name of master browser %s\n",
1959                    addr));
1960
1961         /*
1962          * Do a name status query to find out the name of the master browser.
1963          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
1964          * master browser will not respond to a wildcard query (or, at least,
1965          * an NT4 server acting as the domain master browser will not).
1966          *
1967          * We might be able to use ONLY the query on MSBROWSE, but that's not
1968          * yet been tested with all Windows versions, so until it is, leave
1969          * the original wildcard query as the first choice and fall back to
1970          * MSBROWSE if the wildcard query fails.
1971          */
1972         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
1973             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
1974
1975                 DEBUG(99, ("Could not retrieve name status for %s\n",
1976                            addr));
1977                 return NULL;
1978         }
1979
1980         if (!find_master_ip(name, &server_ss)) {
1981                 DEBUG(99, ("Could not find master ip for %s\n", name));
1982                 return NULL;
1983         }
1984
1985         *pp_workgroup_out = talloc_strdup(ctx, name);
1986
1987         DEBUG(4, ("found master browser %s, %s\n", name, addr));
1988
1989         print_sockaddr(addr, sizeof(addr), &server_ss);
1990         cli = get_ipc_connect(addr, &server_ss, user_info);
1991
1992         return cli;
1993 }
1994
1995 /*
1996  * Return the IP address and workgroup of a master browser on the network, and
1997  * connect to it.
1998  */
1999
2000 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2001                                         const struct user_auth_info *user_info,
2002                                         char **pp_workgroup_out)
2003 {
2004         struct ip_service *ip_list;
2005         struct cli_state *cli;
2006         int i, count;
2007
2008         *pp_workgroup_out = NULL;
2009
2010         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2011
2012         /* Go looking for workgroups by broadcasting on the local network */
2013
2014         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2015                                                 &count))) {
2016                 DEBUG(99, ("No master browsers responded\n"));
2017                 return False;
2018         }
2019
2020         for (i = 0; i < count; i++) {
2021                 char addr[INET6_ADDRSTRLEN];
2022                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2023                 DEBUG(99, ("Found master browser %s\n", addr));
2024
2025                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2026                                 user_info, pp_workgroup_out);
2027                 if (cli)
2028                         return(cli);
2029         }
2030
2031         return NULL;
2032 }