Remove smbclient globals that bled into clidfs.c. Now we only have
[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         cli_set_port(cli, port);
1751         cli_set_timeout(cli, 10000); /* 10 seconds. */
1752
1753         if (dest_ss) {
1754                 ss = *dest_ss;
1755         } else {
1756                 zero_sockaddr(&ss);
1757         }
1758
1759 again:
1760
1761         DEBUG(3,("Connecting to host=%s\n", dest_host));
1762
1763         nt_status = cli_connect(cli, dest_host, &ss);
1764         if (!NT_STATUS_IS_OK(nt_status)) {
1765                 char addr[INET6_ADDRSTRLEN];
1766                 print_sockaddr(addr, sizeof(addr), &ss);
1767                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1768                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
1769                 cli_shutdown(cli);
1770                 return nt_status;
1771         }
1772
1773         if (retry)
1774                 *retry = True;
1775
1776         if (!cli_session_request(cli, &calling, &called)) {
1777                 char *p;
1778                 DEBUG(1,("session request to %s failed (%s)\n",
1779                          called.name, cli_errstr(cli)));
1780                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1781                         *p = 0;
1782                         goto again;
1783                 }
1784                 if (strcmp(called.name, STAR_SMBSERVER)) {
1785                         make_nmb_name(&called , STAR_SMBSERVER, 0x20);
1786                         goto again;
1787                 }
1788                 return NT_STATUS_BAD_NETWORK_NAME;
1789         }
1790
1791         cli_setup_signing_state(cli, signing_state);
1792
1793         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1794                 cli->use_spnego = False;
1795         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1796                 cli->use_kerberos = True;
1797
1798         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
1799              cli->use_kerberos) {
1800                 cli->fallback_after_kerberos = true;
1801         }
1802
1803         nt_status = cli_negprot(cli);
1804         if (!NT_STATUS_IS_OK(nt_status)) {
1805                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
1806                 cli_shutdown(cli);
1807                 return nt_status;
1808         }
1809
1810         *output_cli = cli;
1811         return NT_STATUS_OK;
1812 }
1813
1814
1815 /**
1816    establishes a connection right up to doing tconX, password specified.
1817    @param output_cli A fully initialised cli structure, non-null only on success
1818    @param dest_host The netbios name of the remote host
1819    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1820    @param port (optional) The destination port (0 for default)
1821    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
1822    @param service_type The 'type' of serivice. 
1823    @param user Username, unix string
1824    @param domain User's domain
1825    @param password User's password, unencrypted unix string.
1826    @param retry bool. Did this connection fail with a retryable error ?
1827 */
1828
1829 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
1830                              const char *my_name, 
1831                              const char *dest_host, 
1832                              struct sockaddr_storage *dest_ss, int port,
1833                              const char *service, const char *service_type,
1834                              const char *user, const char *domain, 
1835                              const char *password, int flags,
1836                              int signing_state,
1837                              bool *retry) 
1838 {
1839         NTSTATUS nt_status;
1840         struct cli_state *cli = NULL;
1841         int pw_len = password ? strlen(password)+1 : 0;
1842
1843         *output_cli = NULL;
1844
1845         if (password == NULL) {
1846                 password = "";
1847         }
1848
1849         nt_status = cli_start_connection(&cli, my_name, dest_host,
1850                                          dest_ss, port, signing_state,
1851                                          flags, retry);
1852
1853         if (!NT_STATUS_IS_OK(nt_status)) {
1854                 return nt_status;
1855         }
1856
1857         nt_status = cli_session_setup(cli, user, password, pw_len, password,
1858                                       pw_len, domain);
1859         if (!NT_STATUS_IS_OK(nt_status)) {
1860
1861                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
1862                         DEBUG(1,("failed session setup with %s\n",
1863                                  nt_errstr(nt_status)));
1864                         cli_shutdown(cli);
1865                         return nt_status;
1866                 }
1867
1868                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
1869                 if (!NT_STATUS_IS_OK(nt_status)) {
1870                         DEBUG(1,("anonymous failed session setup with %s\n",
1871                                  nt_errstr(nt_status)));
1872                         cli_shutdown(cli);
1873                         return nt_status;
1874                 }
1875         }
1876
1877         if (service) {
1878                 if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
1879                         nt_status = cli_nt_error(cli);
1880                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1881                         cli_shutdown(cli);
1882                         if (NT_STATUS_IS_OK(nt_status)) {
1883                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1884                         }
1885                         return nt_status;
1886                 }
1887         }
1888
1889         cli_init_creds(cli, user, domain, password);
1890
1891         *output_cli = cli;
1892         return NT_STATUS_OK;
1893 }
1894
1895 /****************************************************************************
1896  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1897 ****************************************************************************/
1898
1899 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
1900                                      struct sockaddr_storage *pdest_ss)
1901 {
1902         struct nmb_name calling, called;
1903
1904         make_nmb_name(&calling, srchost, 0x0);
1905
1906         /*
1907          * If the called name is an IP address
1908          * then use *SMBSERVER immediately.
1909          */
1910
1911         if(is_ipaddress(desthost)) {
1912                 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
1913         } else {
1914                 make_nmb_name(&called, desthost, 0x20);
1915         }
1916
1917         if (!cli_session_request(*ppcli, &calling, &called)) {
1918                 NTSTATUS status;
1919                 struct nmb_name smbservername;
1920
1921                 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
1922
1923                 /*
1924                  * If the name wasn't *SMBSERVER then
1925                  * try with *SMBSERVER if the first name fails.
1926                  */
1927
1928                 if (nmb_name_equal(&called, &smbservername)) {
1929
1930                         /*
1931                          * The name used was *SMBSERVER, don't bother with another name.
1932                          */
1933
1934                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1935 with error %s.\n", desthost, cli_errstr(*ppcli) ));
1936                         return False;
1937                 }
1938
1939                 /* Try again... */
1940                 cli_shutdown(*ppcli);
1941
1942                 *ppcli = cli_initialise();
1943                 if (!*ppcli) {
1944                         /* Out of memory... */
1945                         return False;
1946                 }
1947
1948                 status = cli_connect(*ppcli, desthost, pdest_ss);
1949                 if (!NT_STATUS_IS_OK(status) ||
1950                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
1951                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1952 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
1953                         return False;
1954                 }
1955         }
1956
1957         return True;
1958 }
1959
1960 /****************************************************************************
1961  Send an old style tcon.
1962 ****************************************************************************/
1963 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
1964                       const char *service, const char *pass, const char *dev,
1965                       uint16 *max_xmit, uint16 *tid)
1966 {
1967         char *p;
1968
1969         if (!lp_client_plaintext_auth() && (*pass)) {
1970                 DEBUG(1, ("Server requested plaintext password but 'client "
1971                           "plaintext auth' is disabled\n"));
1972                 return NT_STATUS_ACCESS_DENIED;
1973         }
1974
1975         memset(cli->outbuf,'\0',smb_size);
1976         memset(cli->inbuf,'\0',smb_size);
1977
1978         cli_set_message(cli->outbuf, 0, 0, True);
1979         SCVAL(cli->outbuf,smb_com,SMBtcon);
1980         cli_setup_packet(cli);
1981
1982         p = smb_buf(cli->outbuf);
1983         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1984         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1985         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1986
1987         cli_setup_bcc(cli, p);
1988
1989         cli_send_smb(cli);
1990         if (!cli_receive_smb(cli)) {
1991                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1992         }
1993
1994         if (cli_is_error(cli)) {
1995                 return cli_nt_error(cli);
1996         }
1997
1998         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1999         *tid = SVAL(cli->inbuf, smb_vwv1);
2000
2001         return NT_STATUS_OK;
2002 }
2003
2004 /* Return a cli_state pointing at the IPC$ share for the given server */
2005
2006 struct cli_state *get_ipc_connect(char *server,
2007                                 struct sockaddr_storage *server_ss,
2008                                 const struct user_auth_info *user_info)
2009 {
2010         struct cli_state *cli;
2011         NTSTATUS nt_status;
2012         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2013
2014         if (user_info->use_kerberos) {
2015                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2016         }
2017
2018         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
2019                                         user_info->username ? user_info->username : "",
2020                                         lp_workgroup(),
2021                                         user_info->password ? user_info->password : "",
2022                                         flags,
2023                                         Undefined, NULL);
2024
2025         if (NT_STATUS_IS_OK(nt_status)) {
2026                 return cli;
2027         } else if (is_ipaddress(server)) {
2028             /* windows 9* needs a correct NMB name for connections */
2029             fstring remote_name;
2030
2031             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2032                 cli = get_ipc_connect(remote_name, server_ss, user_info);
2033                 if (cli)
2034                     return cli;
2035             }
2036         }
2037         return NULL;
2038 }
2039
2040 /*
2041  * Given the IP address of a master browser on the network, return its
2042  * workgroup and connect to it.
2043  *
2044  * This function is provided to allow additional processing beyond what
2045  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2046  * browsers and obtain each master browsers' list of domains (in case the
2047  * first master browser is recently on the network and has not yet
2048  * synchronized with other master browsers and therefore does not yet have the
2049  * entire network browse list)
2050  */
2051
2052 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2053                                 struct ip_service *mb_ip,
2054                                 const struct user_auth_info *user_info,
2055                                 char **pp_workgroup_out)
2056 {
2057         char addr[INET6_ADDRSTRLEN];
2058         fstring name;
2059         struct cli_state *cli;
2060         struct sockaddr_storage server_ss;
2061
2062         *pp_workgroup_out = NULL;
2063
2064         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2065         DEBUG(99, ("Looking up name of master browser %s\n",
2066                    addr));
2067
2068         /*
2069          * Do a name status query to find out the name of the master browser.
2070          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2071          * master browser will not respond to a wildcard query (or, at least,
2072          * an NT4 server acting as the domain master browser will not).
2073          *
2074          * We might be able to use ONLY the query on MSBROWSE, but that's not
2075          * yet been tested with all Windows versions, so until it is, leave
2076          * the original wildcard query as the first choice and fall back to
2077          * MSBROWSE if the wildcard query fails.
2078          */
2079         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2080             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2081
2082                 DEBUG(99, ("Could not retrieve name status for %s\n",
2083                            addr));
2084                 return NULL;
2085         }
2086
2087         if (!find_master_ip(name, &server_ss)) {
2088                 DEBUG(99, ("Could not find master ip for %s\n", name));
2089                 return NULL;
2090         }
2091
2092         *pp_workgroup_out = talloc_strdup(ctx, name);
2093
2094         DEBUG(4, ("found master browser %s, %s\n", name, addr));
2095
2096         print_sockaddr(addr, sizeof(addr), &server_ss);
2097         cli = get_ipc_connect(addr, &server_ss, user_info);
2098
2099         return cli;
2100 }
2101
2102 /*
2103  * Return the IP address and workgroup of a master browser on the network, and
2104  * connect to it.
2105  */
2106
2107 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2108                                         const struct user_auth_info *user_info,
2109                                         char **pp_workgroup_out)
2110 {
2111         struct ip_service *ip_list;
2112         struct cli_state *cli;
2113         int i, count;
2114
2115         *pp_workgroup_out = NULL;
2116
2117         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2118
2119         /* Go looking for workgroups by broadcasting on the local network */
2120
2121         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2122                                                 &count))) {
2123                 DEBUG(99, ("No master browsers responded\n"));
2124                 return False;
2125         }
2126
2127         for (i = 0; i < count; i++) {
2128                 char addr[INET6_ADDRSTRLEN];
2129                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2130                 DEBUG(99, ("Found master browser %s\n", addr));
2131
2132                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2133                                 user_info, pp_workgroup_out);
2134                 if (cli)
2135                         return(cli);
2136         }
2137
2138         return NULL;
2139 }