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