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