a4bbf9a6ec3de63197035a48189a9a2392089db2
[metze/old/v3-2-winbind-ndr.git] / source / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22
23 extern pstring user_socket_options;
24
25 static const struct {
26         int prot;
27         const char *name;
28 } prots[] = {
29         {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
30         {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
31         {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
32         {PROTOCOL_LANMAN1,"LANMAN1.0"},
33         {PROTOCOL_LANMAN2,"LM1.2X002"},
34         {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
35         {PROTOCOL_LANMAN2,"LANMAN2.1"},
36         {PROTOCOL_LANMAN2,"Samba"},
37         {PROTOCOL_NT1,"NT LANMAN 1.0"},
38         {PROTOCOL_NT1,"NT LM 0.12"},
39         {-1,NULL}
40 };
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         set_message(NULL,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         set_message(NULL,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         set_message(NULL,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         set_message(NULL,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         set_message(NULL,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 == 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 counter 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
826         if (got_kerberos_mechanism && (principal == NULL)) {
827                 fstring dns_name;
828                 fstring nb_name;
829
830                 /*
831                  * We didn't get a valid principal in the negTokenInit.  Fake
832                  * it, or fall back on NTLM. We prefer to fake it, and hit the
833                  * translate_name cache to get a REAL realm name.
834                  */ 
835                 if (!(cli->desthost && translate_name(domain, dns_name,
836                             nb_name) && 
837                     asprintf(&principal, "host/%s@%s", cli->desthost, 
838                         dns_name))) {
839
840                         /*
841                          * It is WRONG to depend on the principal sent in the
842                          * negprot reply, but right now we do it. So for safety
843                          * (don't segfault later) disable Kerberos when no 
844                          * principal was sent. -- VL
845                          */
846                         DEBUG(1, ("Kerberos mech was offered, but no principal was "
847                                 "sent, disabling Kerberos\n"));
848                         cli->use_kerberos = False;
849                 }
850
851         }
852
853         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
854
855         fstrcpy(cli->user_name, user);
856
857 #ifdef HAVE_KRB5
858         /* If password is set we reauthenticate to kerberos server
859          * and do not store results */
860
861         if (got_kerberos_mechanism && cli->use_kerberos) {
862                 ADS_STATUS rc;
863
864                 if (pass && *pass) {
865                         int ret;
866                         
867                         use_in_memory_ccache();
868                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
869                         
870                         if (ret){
871                                 SAFE_FREE(principal);
872                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
873                                 if (cli->fallback_after_kerberos)
874                                         goto ntlmssp;
875                                 return ADS_ERROR_KRB5(ret);
876                         }
877                 }
878                 
879                 rc = cli_session_setup_kerberos(cli, principal, domain);
880                 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
881                         SAFE_FREE(principal);
882                         return rc;
883                 }
884         }
885 #endif
886
887         SAFE_FREE(principal);
888
889 ntlmssp:
890
891         /* NTLM is sensitive to adding a domain with a UPN */
892         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass,
893                 (strchr(user, '@') ? NULL : domain)));
894 }
895
896 /****************************************************************************
897  Send a session setup. The username and workgroup is in UNIX character
898  format and must be converted to DOS codepage format before sending. If the
899  password is in plaintext, the same should be done.
900 ****************************************************************************/
901
902 NTSTATUS cli_session_setup(struct cli_state *cli, 
903                            const char *user, 
904                            const char *pass, int passlen,
905                            const char *ntpass, int ntpasslen,
906                            const char *workgroup)
907 {
908         char *p;
909         fstring user2;
910
911         /* allow for workgroups as part of the username */
912         fstrcpy(user2, user);
913         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
914             (p=strchr_m(user2,*lp_winbind_separator()))) {
915                 *p = 0;
916                 user = p+1;
917                 workgroup = user2;
918         }
919
920         if (cli->protocol < PROTOCOL_LANMAN1) {
921                 return NT_STATUS_OK;
922         }
923
924         /* now work out what sort of session setup we are going to
925            do. I have split this into separate functions to make the
926            flow a bit easier to understand (tridge) */
927
928         /* if its an older server then we have to use the older request format */
929
930         if (cli->protocol < PROTOCOL_NT1) {
931                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
932                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
933                                   " is disabled\n"));
934                         return NT_STATUS_ACCESS_DENIED;
935                 }
936
937                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
938                     !lp_client_plaintext_auth() && (*pass)) {
939                         DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
940                                   " is disabled\n"));
941                         return NT_STATUS_ACCESS_DENIED;
942                 }
943
944                 return cli_session_setup_lanman2(cli, user, pass, passlen,
945                                                  workgroup);
946         }
947
948         /* if no user is supplied then we have to do an anonymous connection.
949            passwords are ignored */
950
951         if (!user || !*user)
952                 return cli_session_setup_guest(cli);
953
954         /* if the server is share level then send a plaintext null
955            password at this point. The password is sent in the tree
956            connect */
957
958         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
959                 return cli_session_setup_plaintext(cli, user, "", workgroup);
960
961         /* if the server doesn't support encryption then we have to use 
962            plaintext. The second password is ignored */
963
964         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
965                 if (!lp_client_plaintext_auth() && (*pass)) {
966                         DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
967                                   " is disabled\n"));
968                         return NT_STATUS_ACCESS_DENIED;
969                 }
970                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
971         }
972
973         /* if the server supports extended security then use SPNEGO */
974
975         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
976                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
977                 if (!ADS_ERR_OK(status)) {
978                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
979                         return ads_ntstatus(status);
980                 }
981         } else {
982                 NTSTATUS status;
983
984                 /* otherwise do a NT1 style session setup */
985                 status = cli_session_setup_nt1(cli, user, pass, passlen,
986                                                ntpass, ntpasslen, workgroup);
987                 if (!NT_STATUS_IS_OK(status)) {
988                         DEBUG(3,("cli_session_setup: NT1 session setup "
989                                  "failed: %s\n", nt_errstr(status)));
990                         return status;
991                 }
992         }
993
994         if (strstr(cli->server_type, "Samba")) {
995                 cli->is_samba = True;
996         }
997
998         return NT_STATUS_OK;
999 }
1000
1001 /****************************************************************************
1002  Send a uloggoff.
1003 *****************************************************************************/
1004
1005 BOOL cli_ulogoff(struct cli_state *cli)
1006 {
1007         memset(cli->outbuf,'\0',smb_size);
1008         set_message(NULL,cli->outbuf,2,0,True);
1009         SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1010         cli_setup_packet(cli);
1011         SSVAL(cli->outbuf,smb_vwv0,0xFF);
1012         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
1013
1014         cli_send_smb(cli);
1015         if (!cli_receive_smb(cli))
1016                 return False;
1017
1018         if (cli_is_error(cli)) {
1019                 return False;
1020         }
1021
1022         cli->cnum = -1;
1023         return True;
1024 }
1025
1026 /****************************************************************************
1027  Send a tconX.
1028 ****************************************************************************/
1029
1030 BOOL cli_send_tconX(struct cli_state *cli, 
1031                     const char *share, const char *dev, const char *pass, int passlen)
1032 {
1033         fstring fullshare, pword;
1034         char *p;
1035         memset(cli->outbuf,'\0',smb_size);
1036         memset(cli->inbuf,'\0',smb_size);
1037
1038         fstrcpy(cli->share, share);
1039
1040         /* in user level security don't send a password now */
1041         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1042                 passlen = 1;
1043                 pass = "";
1044         } else if (!pass) {
1045                 DEBUG(1, ("Server not using user level security and no password supplied.\n"));
1046                 return False;
1047         }
1048
1049         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1050             *pass && passlen != 24) {
1051                 if (!lp_client_lanman_auth()) {
1052                         DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
1053                                   " is disabled\n"));
1054                         return False;
1055                 }
1056
1057                 /*
1058                  * Non-encrypted passwords - convert to DOS codepage before encryption.
1059                  */
1060                 passlen = 24;
1061                 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
1062         } else {
1063                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
1064                         if (!lp_client_plaintext_auth() && (*pass)) {
1065                                 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1066                                           " is disabled\n"));
1067                                 return False;
1068                         }
1069
1070                         /*
1071                          * Non-encrypted passwords - convert to DOS codepage before using.
1072                          */
1073                         passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
1074                         
1075                 } else {
1076                         if (passlen) {
1077                                 memcpy(pword, pass, passlen);
1078                         }
1079                 }
1080         }
1081
1082         slprintf(fullshare, sizeof(fullshare)-1,
1083                  "\\\\%s\\%s", cli->desthost, share);
1084
1085         set_message(NULL,cli->outbuf,4, 0, True);
1086         SCVAL(cli->outbuf,smb_com,SMBtconX);
1087         cli_setup_packet(cli);
1088
1089         SSVAL(cli->outbuf,smb_vwv0,0xFF);
1090         SSVAL(cli->outbuf,smb_vwv2,TCONX_FLAG_EXTENDED_RESPONSE);
1091         SSVAL(cli->outbuf,smb_vwv3,passlen);
1092
1093         p = smb_buf(cli->outbuf);
1094         if (passlen) {
1095                 memcpy(p,pword,passlen);
1096         }
1097         p += passlen;
1098         p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
1099         p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
1100
1101         cli_setup_bcc(cli, p);
1102
1103         cli_send_smb(cli);
1104         if (!cli_receive_smb(cli))
1105                 return False;
1106
1107         if (cli_is_error(cli))
1108                 return False;
1109
1110         clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
1111
1112         if (cli->protocol >= PROTOCOL_NT1 &&
1113             smb_buflen(cli->inbuf) == 3) {
1114                 /* almost certainly win95 - enable bug fixes */
1115                 cli->win95 = True;
1116         }
1117         
1118         /* Make sure that we have the optional support 16-bit field.  WCT > 2 */
1119         /* Avoids issues when connecting to Win9x boxes sharing files */
1120
1121         cli->dfsroot = False;
1122         if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 )
1123                 cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False;
1124
1125         cli->cnum = SVAL(cli->inbuf,smb_tid);
1126         return True;
1127 }
1128
1129 /****************************************************************************
1130  Send a tree disconnect.
1131 ****************************************************************************/
1132
1133 BOOL cli_tdis(struct cli_state *cli)
1134 {
1135         memset(cli->outbuf,'\0',smb_size);
1136         set_message(NULL,cli->outbuf,0,0,True);
1137         SCVAL(cli->outbuf,smb_com,SMBtdis);
1138         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1139         cli_setup_packet(cli);
1140         
1141         cli_send_smb(cli);
1142         if (!cli_receive_smb(cli))
1143                 return False;
1144         
1145         if (cli_is_error(cli)) {
1146                 return False;
1147         }
1148
1149         cli->cnum = -1;
1150         return True;
1151 }
1152
1153 /****************************************************************************
1154  Send a negprot command.
1155 ****************************************************************************/
1156
1157 void cli_negprot_send(struct cli_state *cli)
1158 {
1159         char *p;
1160         int numprots;
1161
1162         if (cli->protocol < PROTOCOL_NT1)
1163                 cli->use_spnego = False;
1164
1165         memset(cli->outbuf,'\0',smb_size);
1166
1167         /* setup the protocol strings */
1168         set_message(NULL,cli->outbuf,0,0,True);
1169
1170         p = smb_buf(cli->outbuf);
1171         for (numprots=0;
1172              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1173              numprots++) {
1174                 *p++ = 2;
1175                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1176         }
1177
1178         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1179         cli_setup_bcc(cli, p);
1180         cli_setup_packet(cli);
1181
1182         SCVAL(smb_buf(cli->outbuf),0,2);
1183
1184         cli_send_smb(cli);
1185 }
1186
1187 /****************************************************************************
1188  Send a negprot command.
1189 ****************************************************************************/
1190
1191 BOOL cli_negprot(struct cli_state *cli)
1192 {
1193         char *p;
1194         int numprots;
1195         int plength;
1196
1197         if (cli->protocol < PROTOCOL_NT1)
1198                 cli->use_spnego = False;
1199
1200         memset(cli->outbuf,'\0',smb_size);
1201
1202         /* setup the protocol strings */
1203         for (plength=0,numprots=0;
1204              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1205              numprots++)
1206                 plength += strlen(prots[numprots].name)+2;
1207     
1208         set_message(NULL,cli->outbuf,0,plength,True);
1209
1210         p = smb_buf(cli->outbuf);
1211         for (numprots=0;
1212              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1213              numprots++) {
1214                 *p++ = 2;
1215                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1216         }
1217
1218         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1219         cli_setup_packet(cli);
1220
1221         SCVAL(smb_buf(cli->outbuf),0,2);
1222
1223         cli_send_smb(cli);
1224         if (!cli_receive_smb(cli))
1225                 return False;
1226
1227         show_msg(cli->inbuf);
1228
1229         if (cli_is_error(cli) ||
1230             ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1231                 return(False);
1232         }
1233
1234         cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;  
1235
1236         if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1237                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1238                 return False;
1239         }
1240
1241         if (cli->protocol >= PROTOCOL_NT1) {    
1242                 struct timespec ts;
1243                 /* NT protocol */
1244                 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1245                 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1246                 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1247                 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1248                 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1249                 cli->serverzone *= 60;
1250                 /* this time arrives in real GMT */
1251                 ts = interpret_long_date(cli->inbuf+smb_vwv11+1);
1252                 cli->servertime = ts.tv_sec;
1253                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1254                 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1255                 if (cli->capabilities & CAP_RAW_MODE) {
1256                         cli->readbraw_supported = True;
1257                         cli->writebraw_supported = True;      
1258                 }
1259                 /* work out if they sent us a workgroup */
1260                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1261                     smb_buflen(cli->inbuf) > 8) {
1262                         clistr_pull(cli, cli->server_domain, 
1263                                     smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1264                                     smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1265                 }
1266
1267                 /*
1268                  * As signing is slow we only turn it on if either the client or
1269                  * the server require it. JRA.
1270                  */
1271
1272                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1273                         /* Fail if server says signing is mandatory and we don't want to support it. */
1274                         if (!cli->sign_info.allow_smb_signing) {
1275                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1276                                 return False;
1277                         }
1278                         cli->sign_info.negotiated_smb_signing = True;
1279                         cli->sign_info.mandatory_signing = True;
1280                 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1281                         /* Fail if client says signing is mandatory and the server doesn't support it. */
1282                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1283                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1284                                 return False;
1285                         }
1286                         cli->sign_info.negotiated_smb_signing = True;
1287                         cli->sign_info.mandatory_signing = True;
1288                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1289                         cli->sign_info.negotiated_smb_signing = True;
1290                 }
1291
1292                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1293                         SAFE_FREE(cli->outbuf);
1294                         SAFE_FREE(cli->inbuf);
1295                         cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+SAFETY_MARGIN);
1296                         cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+SAFETY_MARGIN);
1297                         cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE;
1298                 }
1299
1300         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1301                 cli->use_spnego = False;
1302                 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1303                 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1304                 cli->max_mux = SVAL(cli->inbuf, smb_vwv3); 
1305                 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1306                 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1307                 cli->serverzone *= 60;
1308                 /* this time is converted to GMT by make_unix_date */
1309                 cli->servertime = cli_make_unix_date(cli,cli->inbuf+smb_vwv8);
1310                 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1311                 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1312                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1313         } else {
1314                 /* the old core protocol */
1315                 cli->use_spnego = False;
1316                 cli->sec_mode = 0;
1317                 cli->serverzone = get_time_zone(time(NULL));
1318         }
1319
1320         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1321
1322         /* a way to force ascii SMB */
1323         if (getenv("CLI_FORCE_ASCII"))
1324                 cli->capabilities &= ~CAP_UNICODE;
1325
1326         return True;
1327 }
1328
1329 /****************************************************************************
1330  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1331 ****************************************************************************/
1332
1333 BOOL cli_session_request(struct cli_state *cli,
1334                          struct nmb_name *calling, struct nmb_name *called)
1335 {
1336         char *p;
1337         int len = 4;
1338
1339         memcpy(&(cli->calling), calling, sizeof(*calling));
1340         memcpy(&(cli->called ), called , sizeof(*called ));
1341   
1342         /* put in the destination name */
1343         p = cli->outbuf+len;
1344         name_mangle(cli->called .name, p, cli->called .name_type);
1345         len += name_len(p);
1346
1347         /* and my name */
1348         p = cli->outbuf+len;
1349         name_mangle(cli->calling.name, p, cli->calling.name_type);
1350         len += name_len(p);
1351
1352         /* 445 doesn't have session request */
1353         if (cli->port == 445)
1354                 return True;
1355
1356         /* send a session request (RFC 1002) */
1357         /* setup the packet length
1358          * Remove four bytes from the length count, since the length
1359          * field in the NBT Session Service header counts the number
1360          * of bytes which follow.  The cli_send_smb() function knows
1361          * about this and accounts for those four bytes.
1362          * CRH.
1363          */
1364         len -= 4;
1365         _smb_setlen(cli->outbuf,len);
1366         SCVAL(cli->outbuf,0,0x81);
1367
1368         cli_send_smb(cli);
1369         DEBUG(5,("Sent session request\n"));
1370
1371         if (!cli_receive_smb(cli))
1372                 return False;
1373
1374         if (CVAL(cli->inbuf,0) == 0x84) {
1375                 /* C. Hoch  9/14/95 Start */
1376                 /* For information, here is the response structure.
1377                  * We do the byte-twiddling to for portability.
1378                 struct RetargetResponse{
1379                 unsigned char type;
1380                 unsigned char flags;
1381                 int16 length;
1382                 int32 ip_addr;
1383                 int16 port;
1384                 };
1385                 */
1386                 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1387                 /* SESSION RETARGET */
1388                 putip((char *)&cli->dest_ip,cli->inbuf+4);
1389
1390                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1391                 if (cli->fd == -1)
1392                         return False;
1393
1394                 DEBUG(3,("Retargeted\n"));
1395
1396                 set_socket_options(cli->fd,user_socket_options);
1397
1398                 /* Try again */
1399                 {
1400                         static int depth;
1401                         BOOL ret;
1402                         if (depth > 4) {
1403                                 DEBUG(0,("Retarget recursion - failing\n"));
1404                                 return False;
1405                         }
1406                         depth++;
1407                         ret = cli_session_request(cli, calling, called);
1408                         depth--;
1409                         return ret;
1410                 }
1411         } /* C. Hoch 9/14/95 End */
1412
1413         if (CVAL(cli->inbuf,0) != 0x82) {
1414                 /* This is the wrong place to put the error... JRA. */
1415                 cli->rap_error = CVAL(cli->inbuf,4);
1416                 return False;
1417         }
1418         return(True);
1419 }
1420
1421 /****************************************************************************
1422  Open the client sockets.
1423 ****************************************************************************/
1424
1425 NTSTATUS cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1426 {
1427         int name_type = 0x20;
1428         char *p;
1429
1430         /* reasonable default hostname */
1431         if (!host) host = "*SMBSERVER";
1432
1433         fstrcpy(cli->desthost, host);
1434
1435         /* allow hostnames of the form NAME#xx and do a netbios lookup */
1436         if ((p = strchr(cli->desthost, '#'))) {
1437                 name_type = strtol(p+1, NULL, 16);              
1438                 *p = 0;
1439         }
1440         
1441         if (!ip || is_zero_ip(*ip)) {
1442                 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1443                         return NT_STATUS_BAD_NETWORK_NAME;
1444                 }
1445                 if (ip) *ip = cli->dest_ip;
1446         } else {
1447                 cli->dest_ip = *ip;
1448         }
1449
1450         if (getenv("LIBSMB_PROG")) {
1451                 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1452         } else {
1453                 /* try 445 first, then 139 */
1454                 int port = cli->port?cli->port:445;
1455                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
1456                                           port, cli->timeout);
1457                 if (cli->fd == -1 && cli->port == 0) {
1458                         port = 139;
1459                         cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
1460                                                   port, cli->timeout);
1461                 }
1462                 if (cli->fd != -1)
1463                         cli->port = port;
1464         }
1465         if (cli->fd == -1) {
1466                 DEBUG(1,("Error connecting to %s (%s)\n",
1467                          ip?inet_ntoa(*ip):host,strerror(errno)));
1468                 return map_nt_error_from_unix(errno);
1469         }
1470
1471         set_socket_options(cli->fd,user_socket_options);
1472
1473         return NT_STATUS_OK;
1474 }
1475
1476 /**
1477    establishes a connection to after the negprot. 
1478    @param output_cli A fully initialised cli structure, non-null only on success
1479    @param dest_host The netbios name of the remote host
1480    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1481    @param port (optional) The destination port (0 for default)
1482    @param retry BOOL. Did this connection fail with a retryable error ?
1483
1484 */
1485 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
1486                               const char *my_name, 
1487                               const char *dest_host, 
1488                               struct in_addr *dest_ip, int port,
1489                               int signing_state, int flags,
1490                               BOOL *retry) 
1491 {
1492         NTSTATUS nt_status;
1493         struct nmb_name calling;
1494         struct nmb_name called;
1495         struct cli_state *cli;
1496         struct in_addr ip;
1497
1498         if (retry)
1499                 *retry = False;
1500
1501         if (!my_name) 
1502                 my_name = global_myname();
1503         
1504         if (!(cli = cli_initialise())) {
1505                 return NT_STATUS_NO_MEMORY;
1506         }
1507         
1508         make_nmb_name(&calling, my_name, 0x0);
1509         make_nmb_name(&called , dest_host, 0x20);
1510
1511         if (cli_set_port(cli, port) != port) {
1512                 cli_shutdown(cli);
1513                 return NT_STATUS_UNSUCCESSFUL;
1514         }
1515
1516         cli_set_timeout(cli, 10000); /* 10 seconds. */
1517
1518         if (dest_ip)
1519                 ip = *dest_ip;
1520         else
1521                 ZERO_STRUCT(ip);
1522
1523 again:
1524
1525         DEBUG(3,("Connecting to host=%s\n", dest_host));
1526         
1527         nt_status = cli_connect(cli, dest_host, &ip);
1528         if (!NT_STATUS_IS_OK(nt_status)) {
1529                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1530                          nmb_namestr(&called), inet_ntoa(ip), nt_errstr(nt_status) ));
1531                 cli_shutdown(cli);
1532                 return nt_status;
1533         }
1534
1535         if (retry)
1536                 *retry = True;
1537
1538         if (!cli_session_request(cli, &calling, &called)) {
1539                 char *p;
1540                 DEBUG(1,("session request to %s failed (%s)\n", 
1541                          called.name, cli_errstr(cli)));
1542                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1543                         *p = 0;
1544                         goto again;
1545                 }
1546                 if (strcmp(called.name, "*SMBSERVER")) {
1547                         make_nmb_name(&called , "*SMBSERVER", 0x20);
1548                         goto again;
1549                 }
1550                 return NT_STATUS_BAD_NETWORK_NAME;
1551         }
1552
1553         cli_setup_signing_state(cli, signing_state);
1554
1555         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1556                 cli->use_spnego = False;
1557         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1558                 cli->use_kerberos = True;
1559
1560         if (!cli_negprot(cli)) {
1561                 DEBUG(1,("failed negprot\n"));
1562                 nt_status = cli_nt_error(cli);
1563                 if (NT_STATUS_IS_OK(nt_status)) {
1564                         nt_status = NT_STATUS_UNSUCCESSFUL;
1565                 }
1566                 cli_shutdown(cli);
1567                 return nt_status;
1568         }
1569
1570         *output_cli = cli;
1571         return NT_STATUS_OK;
1572 }
1573
1574
1575 /**
1576    establishes a connection right up to doing tconX, password specified.
1577    @param output_cli A fully initialised cli structure, non-null only on success
1578    @param dest_host The netbios name of the remote host
1579    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1580    @param port (optional) The destination port (0 for default)
1581    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
1582    @param service_type The 'type' of serivice. 
1583    @param user Username, unix string
1584    @param domain User's domain
1585    @param password User's password, unencrypted unix string.
1586    @param retry BOOL. Did this connection fail with a retryable error ?
1587 */
1588
1589 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
1590                              const char *my_name, 
1591                              const char *dest_host, 
1592                              struct in_addr *dest_ip, int port,
1593                              const char *service, const char *service_type,
1594                              const char *user, const char *domain, 
1595                              const char *password, int flags,
1596                              int signing_state,
1597                              BOOL *retry) 
1598 {
1599         NTSTATUS nt_status;
1600         struct cli_state *cli = NULL;
1601         int pw_len = password ? strlen(password)+1 : 0;
1602
1603         *output_cli = NULL;
1604
1605         if (password == NULL) {
1606                 password = "";
1607         }
1608
1609         nt_status = cli_start_connection(&cli, my_name, dest_host, 
1610                                          dest_ip, port, signing_state, flags, retry);
1611         
1612         if (!NT_STATUS_IS_OK(nt_status)) {
1613                 return nt_status;
1614         }
1615
1616         nt_status = cli_session_setup(cli, user, password, pw_len, password,
1617                                       pw_len, domain);
1618         if (!NT_STATUS_IS_OK(nt_status)) {
1619
1620                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
1621                         DEBUG(1,("failed session setup with %s\n",
1622                                  nt_errstr(nt_status)));
1623                         cli_shutdown(cli);
1624                         return nt_status;
1625                 }
1626
1627                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
1628                 if (!NT_STATUS_IS_OK(nt_status)) {
1629                         DEBUG(1,("anonymous failed session setup with %s\n",
1630                                  nt_errstr(nt_status)));
1631                         cli_shutdown(cli);
1632                         return nt_status;
1633                 }
1634         }
1635         
1636         if (service) {
1637                 if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
1638                         nt_status = cli_nt_error(cli);
1639                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1640                         cli_shutdown(cli);
1641                         if (NT_STATUS_IS_OK(nt_status)) {
1642                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1643                         }
1644                         return nt_status;
1645                 }
1646         }
1647
1648         cli_init_creds(cli, user, domain, password);
1649
1650         *output_cli = cli;
1651         return NT_STATUS_OK;
1652 }
1653
1654 /****************************************************************************
1655  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1656 ****************************************************************************/
1657
1658 BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
1659                                      struct in_addr *pdest_ip)
1660 {
1661         struct nmb_name calling, called;
1662
1663         make_nmb_name(&calling, srchost, 0x0);
1664
1665         /*
1666          * If the called name is an IP address
1667          * then use *SMBSERVER immediately.
1668          */
1669
1670         if(is_ipaddress(desthost)) {
1671                 make_nmb_name(&called, "*SMBSERVER", 0x20);
1672         } else {
1673                 make_nmb_name(&called, desthost, 0x20);
1674         }
1675
1676         if (!cli_session_request(*ppcli, &calling, &called)) {
1677                 NTSTATUS status;
1678                 struct nmb_name smbservername;
1679
1680                 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1681
1682                 /*
1683                  * If the name wasn't *SMBSERVER then
1684                  * try with *SMBSERVER if the first name fails.
1685                  */
1686
1687                 if (nmb_name_equal(&called, &smbservername)) {
1688
1689                         /*
1690                          * The name used was *SMBSERVER, don't bother with another name.
1691                          */
1692
1693                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1694 with error %s.\n", desthost, cli_errstr(*ppcli) ));
1695                         return False;
1696                 }
1697
1698                 /* Try again... */
1699                 cli_shutdown(*ppcli);
1700
1701                 *ppcli = cli_initialise();
1702                 if (!*ppcli) {
1703                         /* Out of memory... */
1704                         return False;
1705                 }
1706
1707                 status = cli_connect(*ppcli, desthost, pdest_ip);
1708                 if (!NT_STATUS_IS_OK(status) ||
1709                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
1710                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1711 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
1712                         return False;
1713                 }
1714         }
1715
1716         return True;
1717 }
1718
1719
1720
1721
1722
1723 /****************************************************************************
1724  Send an old style tcon.
1725 ****************************************************************************/
1726 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
1727                       const char *service, const char *pass, const char *dev,
1728                       uint16 *max_xmit, uint16 *tid)
1729 {
1730         char *p;
1731
1732         if (!lp_client_plaintext_auth() && (*pass)) {
1733                 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1734                           " is disabled\n"));
1735                 return NT_STATUS_ACCESS_DENIED;
1736         }
1737
1738         memset(cli->outbuf,'\0',smb_size);
1739         memset(cli->inbuf,'\0',smb_size);
1740
1741         set_message(NULL,cli->outbuf, 0, 0, True);
1742         SCVAL(cli->outbuf,smb_com,SMBtcon);
1743         cli_setup_packet(cli);
1744
1745         p = smb_buf(cli->outbuf);
1746         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1747         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1748         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1749
1750         cli_setup_bcc(cli, p);
1751
1752         cli_send_smb(cli);
1753         if (!cli_receive_smb(cli)) {
1754                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1755         }
1756
1757         if (cli_is_error(cli)) {
1758                 return cli_nt_error(cli);
1759         }
1760
1761         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1762         *tid = SVAL(cli->inbuf, smb_vwv1);
1763
1764         return NT_STATUS_OK;
1765 }
1766
1767 /* Return a cli_state pointing at the IPC$ share for the given server */
1768
1769 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1770                                          struct user_auth_info *user_info)
1771 {
1772         struct cli_state *cli;
1773         pstring myname;
1774         NTSTATUS nt_status;
1775
1776         get_myname(myname);
1777         
1778         nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC", 
1779                                         user_info->username, lp_workgroup(), user_info->password, 
1780                                         CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK, Undefined, NULL);
1781
1782         if (NT_STATUS_IS_OK(nt_status)) {
1783                 return cli;
1784         } else if (is_ipaddress(server)) {
1785             /* windows 9* needs a correct NMB name for connections */
1786             fstring remote_name;
1787
1788             if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1789                 cli = get_ipc_connect(remote_name, server_ip, user_info);
1790                 if (cli)
1791                     return cli;
1792             }
1793         }
1794         return NULL;
1795 }
1796
1797 /*
1798  * Given the IP address of a master browser on the network, return its
1799  * workgroup and connect to it.
1800  *
1801  * This function is provided to allow additional processing beyond what
1802  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
1803  * browsers and obtain each master browsers' list of domains (in case the
1804  * first master browser is recently on the network and has not yet
1805  * synchronized with other master browsers and therefore does not yet have the
1806  * entire network browse list)
1807  */
1808
1809 struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info)
1810 {
1811         static fstring name;
1812         struct cli_state *cli;
1813         struct in_addr server_ip; 
1814
1815         DEBUG(99, ("Looking up name of master browser %s\n",
1816                    inet_ntoa(mb_ip->ip)));
1817
1818         /*
1819          * Do a name status query to find out the name of the master browser.
1820          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
1821          * master browser will not respond to a wildcard query (or, at least,
1822          * an NT4 server acting as the domain master browser will not).
1823          *
1824          * We might be able to use ONLY the query on MSBROWSE, but that's not
1825          * yet been tested with all Windows versions, so until it is, leave
1826          * the original wildcard query as the first choice and fall back to
1827          * MSBROWSE if the wildcard query fails.
1828          */
1829         if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) &&
1830             !name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) {
1831
1832                 DEBUG(99, ("Could not retrieve name status for %s\n",
1833                            inet_ntoa(mb_ip->ip)));
1834                 return NULL;
1835         }
1836
1837         if (!find_master_ip(name, &server_ip)) {
1838                 DEBUG(99, ("Could not find master ip for %s\n", name));
1839                 return NULL;
1840         }
1841
1842                 pstrcpy(workgroup, name);
1843
1844                 DEBUG(4, ("found master browser %s, %s\n", 
1845                   name, inet_ntoa(mb_ip->ip)));
1846
1847                 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
1848
1849                 return cli;
1850     
1851 }
1852
1853 /*
1854  * Return the IP address and workgroup of a master browser on the network, and
1855  * connect to it.
1856  */
1857
1858 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1859 {
1860         struct ip_service *ip_list;
1861         struct cli_state *cli;
1862         int i, count;
1863
1864         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
1865
1866         /* Go looking for workgroups by broadcasting on the local network */ 
1867
1868         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
1869                                                 &count))) {
1870                 DEBUG(99, ("No master browsers responded\n"));
1871                 return False;
1872         }
1873
1874         for (i = 0; i < count; i++) {
1875             DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
1876
1877             cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info);
1878             if (cli)
1879                     return(cli);
1880         }
1881
1882         return NULL;
1883 }