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