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