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