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