Make it clearer that the domain here is the domain of the user for
[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 #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, 0); 
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, 0); 
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 *domain)
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, domain))) {
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                         if (turn == 1) {
579                                 /* and wrap it in a SPNEGO wrapper */
580                                 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
581                         } else {
582                                 /* wrap it in SPNEGO */
583                                 msg1 = spnego_gen_auth(blob_out);
584                         }
585                 
586                         /* now send that blob on its way */
587                         if (!cli_session_setup_blob_send(cli, msg1)) {
588                                 DEBUG(3, ("Failed to send NTLMSSP/SPENGO blob to server!\n"));
589                                 nt_status = NT_STATUS_UNSUCCESSFUL;
590                         } else {
591                                 data_blob_free(&msg1);
592                                 
593                                 blob = cli_session_setup_blob_receive(cli);
594                                 
595                                 nt_status = cli_nt_error(cli);
596                                 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
597                                         if (cli->smb_rw_error == READ_BAD_SIG) {
598                                                 nt_status = NT_STATUS_ACCESS_DENIED;
599                                         } else {
600                                                 nt_status = NT_STATUS_UNSUCCESSFUL;
601                                         }
602                                 }
603                         }
604                 }
605                 
606                 if (!blob.length) {
607                         if (NT_STATUS_IS_OK(nt_status)) {
608                                 nt_status = NT_STATUS_UNSUCCESSFUL;
609                         }
610                 } else if ((turn == 1) && 
611                            NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
612                         DATA_BLOB tmp_blob = data_blob(NULL, 0);
613                         /* the server might give us back two challenges */
614                         if (!spnego_parse_challenge(blob, &blob_in, 
615                                                     &tmp_blob)) {
616                                 DEBUG(3,("Failed to parse challenges\n"));
617                                 nt_status = NT_STATUS_INVALID_PARAMETER;
618                         }
619                         data_blob_free(&tmp_blob);
620                 } else {
621                         if (!spnego_parse_auth_response(blob, nt_status, 
622                                                         &blob_in)) {
623                                 DEBUG(3,("Failed to parse auth response\n"));
624                                 if (NT_STATUS_IS_OK(nt_status) 
625                                     || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) 
626                                         nt_status = NT_STATUS_INVALID_PARAMETER;
627                         }
628                 }
629                 data_blob_free(&blob);
630                 data_blob_free(&blob_out);
631                 turn++;
632         } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
633
634         if (NT_STATUS_IS_OK(nt_status)) {
635
636                 DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
637                                           ntlmssp_state->session_key.length);
638                 DATA_BLOB null_blob = data_blob(NULL, 0);
639
640                 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
641                 cli_set_session_key(cli, ntlmssp_state->session_key);
642
643                 /* Using NTLMSSP session setup, signing on the net only starts
644                  * after a successful authentication and the session key has
645                  * been determined, but with a sequence number of 2. This
646                  * assumes that NTLMSSP needs exactly 2 roundtrips, for any
647                  * other SPNEGO mechanism it needs adapting. */
648
649                 cli_simple_set_signing(cli, key, null_blob, 2);
650         }
651
652         /* we have a reference conter on ntlmssp_state, if we are signing
653            then the state will be kept by the signing engine */
654
655         ntlmssp_end(&ntlmssp_state);
656
657         return nt_status;
658 }
659
660 /****************************************************************************
661  Do a spnego encrypted session setup.
662 ****************************************************************************/
663
664 NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
665                               const char *pass, const char *domain)
666 {
667         char *principal;
668         char *OIDs[ASN1_MAX_OIDS];
669         int i;
670         BOOL got_kerberos_mechanism = False;
671         DATA_BLOB blob;
672
673         DEBUG(2,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
674
675         /* the server might not even do spnego */
676         if (cli->secblob.length <= 16) {
677                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
678                 goto ntlmssp;
679         }
680
681 #if 0
682         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
683 #endif
684
685         /* there is 16 bytes of GUID before the real spnego packet starts */
686         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
687
688         /* the server sent us the first part of the SPNEGO exchange in the negprot 
689            reply */
690         if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
691                 data_blob_free(&blob);
692                 return NT_STATUS_INVALID_PARAMETER;
693         }
694         data_blob_free(&blob);
695
696         /* make sure the server understands kerberos */
697         for (i=0;OIDs[i];i++) {
698                 DEBUG(3,("got OID=%s\n", OIDs[i]));
699                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
700                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
701                         got_kerberos_mechanism = True;
702                 }
703                 free(OIDs[i]);
704         }
705         DEBUG(3,("got principal=%s\n", principal));
706
707         fstrcpy(cli->user_name, user);
708
709 #ifdef HAVE_KRB5
710         /* If password is set we reauthenticate to kerberos server
711          * and do not store results */
712
713         if (got_kerberos_mechanism && cli->use_kerberos) {
714                 if (pass && *pass) {
715                         int ret;
716                         
717                         use_in_memory_ccache();
718                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */);
719                         
720                         if (ret){
721                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
722                                 return NT_STATUS_LOGON_FAILURE;
723                         }
724                 }
725                 
726                 return cli_session_setup_kerberos(cli, principal, domain);
727         }
728 #endif
729
730         free(principal);
731
732 ntlmssp:
733
734         return cli_session_setup_ntlmssp(cli, user, pass, domain);
735 }
736
737 /****************************************************************************
738  Send a session setup. The username and workgroup is in UNIX character
739  format and must be converted to DOS codepage format before sending. If the
740  password is in plaintext, the same should be done.
741 ****************************************************************************/
742
743 BOOL cli_session_setup(struct cli_state *cli, 
744                        const char *user, 
745                        const char *pass, int passlen,
746                        const char *ntpass, int ntpasslen,
747                        const char *workgroup)
748 {
749         char *p;
750         fstring user2;
751
752         /* allow for workgroups as part of the username */
753         fstrcpy(user2, user);
754         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
755             (p=strchr_m(user2,*lp_winbind_separator()))) {
756                 *p = 0;
757                 user = p+1;
758                 workgroup = user2;
759         }
760
761         if (cli->protocol < PROTOCOL_LANMAN1)
762                 return True;
763
764         /* now work out what sort of session setup we are going to
765            do. I have split this into separate functions to make the
766            flow a bit easier to understand (tridge) */
767
768         /* if its an older server then we have to use the older request format */
769
770         if (cli->protocol < PROTOCOL_NT1) {
771                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
772                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
773                                   " is disabled\n"));
774                         return False;
775                 }
776
777                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
778                     !lp_client_plaintext_auth() && (*pass)) {
779                         DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
780                                   " is disabled\n"));
781                         return False;
782                 }
783
784                 return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
785         }
786
787         /* if no user is supplied then we have to do an anonymous connection.
788            passwords are ignored */
789
790         if (!user || !*user)
791                 return cli_session_setup_guest(cli);
792
793         /* if the server is share level then send a plaintext null
794            password at this point. The password is sent in the tree
795            connect */
796
797         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
798                 return cli_session_setup_plaintext(cli, user, "", workgroup);
799
800         /* if the server doesn't support encryption then we have to use 
801            plaintext. The second password is ignored */
802
803         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
804                 if (!lp_client_plaintext_auth() && (*pass)) {
805                         DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
806                                   " is disabled\n"));
807                         return False;
808                 }
809                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
810         }
811
812         /* if the server supports extended security then use SPNEGO */
813
814         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
815                 NTSTATUS nt_status;
816                 if (!NT_STATUS_IS_OK(nt_status = cli_session_setup_spnego(cli, user, pass, workgroup))) {
817                         DEBUG(3, ("SPENGO login failed: %s\n", get_friendly_nt_error_msg(nt_status)));
818                         return False;
819                 }
820                 return True;
821         }
822
823         /* otherwise do a NT1 style session setup */
824
825         return cli_session_setup_nt1(cli, user, 
826                                      pass, passlen, ntpass, ntpasslen,
827                                      workgroup);        
828 }
829
830 /****************************************************************************
831  Send a uloggoff.
832 *****************************************************************************/
833
834 BOOL cli_ulogoff(struct cli_state *cli)
835 {
836         memset(cli->outbuf,'\0',smb_size);
837         set_message(cli->outbuf,2,0,True);
838         SCVAL(cli->outbuf,smb_com,SMBulogoffX);
839         cli_setup_packet(cli);
840         SSVAL(cli->outbuf,smb_vwv0,0xFF);
841         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
842
843         cli_send_smb(cli);
844         if (!cli_receive_smb(cli))
845                 return False;
846
847         return !cli_is_error(cli);
848 }
849
850 /****************************************************************************
851  Send a tconX.
852 ****************************************************************************/
853 BOOL cli_send_tconX(struct cli_state *cli, 
854                     const char *share, const char *dev, const char *pass, int passlen)
855 {
856         fstring fullshare, pword;
857         char *p;
858         memset(cli->outbuf,'\0',smb_size);
859         memset(cli->inbuf,'\0',smb_size);
860
861         fstrcpy(cli->share, share);
862
863         /* in user level security don't send a password now */
864         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
865                 passlen = 1;
866                 pass = "";
867         }
868
869         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
870                 if (!lp_client_lanman_auth()) {
871                         DEBUG(1, ("Server requested LANMAN password but 'client use lanman auth'"
872                                   " is disabled\n"));
873                         return False;
874                 }
875
876                 /*
877                  * Non-encrypted passwords - convert to DOS codepage before encryption.
878                  */
879                 passlen = 24;
880                 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
881         } else {
882                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
883                         if (!lp_client_plaintext_auth() && (*pass)) {
884                                 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
885                                           " is disabled\n"));
886                                 return False;
887                         }
888
889                         /*
890                          * Non-encrypted passwords - convert to DOS codepage before using.
891                          */
892                         passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
893                         
894                 } else {
895                         memcpy(pword, pass, passlen);
896                 }
897         }
898
899         slprintf(fullshare, sizeof(fullshare)-1,
900                  "\\\\%s\\%s", cli->desthost, share);
901
902         set_message(cli->outbuf,4, 0, True);
903         SCVAL(cli->outbuf,smb_com,SMBtconX);
904         cli_setup_packet(cli);
905
906         SSVAL(cli->outbuf,smb_vwv0,0xFF);
907         SSVAL(cli->outbuf,smb_vwv3,passlen);
908
909         p = smb_buf(cli->outbuf);
910         memcpy(p,pword,passlen);
911         p += passlen;
912         p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
913         p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
914
915         cli_setup_bcc(cli, p);
916
917         cli_send_smb(cli);
918         if (!cli_receive_smb(cli))
919                 return False;
920
921         if (cli_is_error(cli))
922                 return False;
923
924         clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
925
926         if (cli->protocol >= PROTOCOL_NT1 &&
927             smb_buflen(cli->inbuf) == 3) {
928                 /* almost certainly win95 - enable bug fixes */
929                 cli->win95 = True;
930         }
931
932         cli->cnum = SVAL(cli->inbuf,smb_tid);
933         return True;
934 }
935
936 /****************************************************************************
937  Send a tree disconnect.
938 ****************************************************************************/
939
940 BOOL cli_tdis(struct cli_state *cli)
941 {
942         memset(cli->outbuf,'\0',smb_size);
943         set_message(cli->outbuf,0,0,True);
944         SCVAL(cli->outbuf,smb_com,SMBtdis);
945         SSVAL(cli->outbuf,smb_tid,cli->cnum);
946         cli_setup_packet(cli);
947         
948         cli_send_smb(cli);
949         if (!cli_receive_smb(cli))
950                 return False;
951         
952         return !cli_is_error(cli);
953 }
954
955 /****************************************************************************
956  Send a negprot command.
957 ****************************************************************************/
958
959 void cli_negprot_send(struct cli_state *cli)
960 {
961         char *p;
962         int numprots;
963
964         if (cli->protocol < PROTOCOL_NT1)
965                 cli->use_spnego = False;
966
967         memset(cli->outbuf,'\0',smb_size);
968
969         /* setup the protocol strings */
970         set_message(cli->outbuf,0,0,True);
971
972         p = smb_buf(cli->outbuf);
973         for (numprots=0;
974              prots[numprots].name && prots[numprots].prot<=cli->protocol;
975              numprots++) {
976                 *p++ = 2;
977                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
978         }
979
980         SCVAL(cli->outbuf,smb_com,SMBnegprot);
981         cli_setup_bcc(cli, p);
982         cli_setup_packet(cli);
983
984         SCVAL(smb_buf(cli->outbuf),0,2);
985
986         cli_send_smb(cli);
987 }
988
989 /****************************************************************************
990  Send a negprot command.
991 ****************************************************************************/
992
993 BOOL cli_negprot(struct cli_state *cli)
994 {
995         char *p;
996         int numprots;
997         int plength;
998
999         if (cli->protocol < PROTOCOL_NT1)
1000                 cli->use_spnego = False;
1001
1002         memset(cli->outbuf,'\0',smb_size);
1003
1004         /* setup the protocol strings */
1005         for (plength=0,numprots=0;
1006              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1007              numprots++)
1008                 plength += strlen(prots[numprots].name)+2;
1009     
1010         set_message(cli->outbuf,0,plength,True);
1011
1012         p = smb_buf(cli->outbuf);
1013         for (numprots=0;
1014              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1015              numprots++) {
1016                 *p++ = 2;
1017                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1018         }
1019
1020         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1021         cli_setup_packet(cli);
1022
1023         SCVAL(smb_buf(cli->outbuf),0,2);
1024
1025         cli_send_smb(cli);
1026         if (!cli_receive_smb(cli))
1027                 return False;
1028
1029         show_msg(cli->inbuf);
1030
1031         if (cli_is_error(cli) ||
1032             ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1033                 return(False);
1034         }
1035
1036         cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;  
1037
1038         if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1039                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1040                 return False;
1041         }
1042
1043         if (cli->protocol >= PROTOCOL_NT1) {    
1044                 /* NT protocol */
1045                 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1046                 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1047                 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1048                 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1049                 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1050                 cli->serverzone *= 60;
1051                 /* this time arrives in real GMT */
1052                 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1053                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1054                 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1055                 if (cli->capabilities & CAP_RAW_MODE) {
1056                         cli->readbraw_supported = True;
1057                         cli->writebraw_supported = True;      
1058                 }
1059                 /* work out if they sent us a workgroup */
1060                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1061                     smb_buflen(cli->inbuf) > 8) {
1062                         clistr_pull(cli, cli->server_domain, 
1063                                     smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1064                                     smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1065                 }
1066
1067                 /*
1068                  * As signing is slow we only turn it on if either the client or
1069                  * the server require it. JRA.
1070                  */
1071
1072                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1073                         /* Fail if server says signing is mandatory and we don't want to support it. */
1074                         if (!cli->sign_info.allow_smb_signing) {
1075                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1076                                 return False;
1077                         }
1078                         cli->sign_info.negotiated_smb_signing = True;
1079                         cli->sign_info.mandatory_signing = True;
1080                 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1081                         /* Fail if client says signing is mandatory and the server doesn't support it. */
1082                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1083                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1084                                 return False;
1085                         }
1086                         cli->sign_info.negotiated_smb_signing = True;
1087                         cli->sign_info.mandatory_signing = True;
1088                 }
1089
1090         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1091                 cli->use_spnego = False;
1092                 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1093                 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1094                 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1095                 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1096                 cli->serverzone *= 60;
1097                 /* this time is converted to GMT by make_unix_date */
1098                 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
1099                 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1100                 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1101                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1102         } else {
1103                 /* the old core protocol */
1104                 cli->use_spnego = False;
1105                 cli->sec_mode = 0;
1106                 cli->serverzone = TimeDiff(time(NULL));
1107         }
1108
1109         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1110
1111         /* a way to force ascii SMB */
1112         if (getenv("CLI_FORCE_ASCII"))
1113                 cli->capabilities &= ~CAP_UNICODE;
1114
1115         return True;
1116 }
1117
1118 /****************************************************************************
1119  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1120 ****************************************************************************/
1121
1122 BOOL cli_session_request(struct cli_state *cli,
1123                          struct nmb_name *calling, struct nmb_name *called)
1124 {
1125         char *p;
1126         int len = 4;
1127         extern pstring user_socket_options;
1128
1129         memcpy(&(cli->calling), calling, sizeof(*calling));
1130         memcpy(&(cli->called ), called , sizeof(*called ));
1131   
1132         /* put in the destination name */
1133         p = cli->outbuf+len;
1134         name_mangle(cli->called .name, p, cli->called .name_type);
1135         len += name_len(p);
1136
1137         /* and my name */
1138         p = cli->outbuf+len;
1139         name_mangle(cli->calling.name, p, cli->calling.name_type);
1140         len += name_len(p);
1141
1142         /* 445 doesn't have session request */
1143         if (cli->port == 445)
1144                 return True;
1145
1146         /* send a session request (RFC 1002) */
1147         /* setup the packet length
1148          * Remove four bytes from the length count, since the length
1149          * field in the NBT Session Service header counts the number
1150          * of bytes which follow.  The cli_send_smb() function knows
1151          * about this and accounts for those four bytes.
1152          * CRH.
1153          */
1154         len -= 4;
1155         _smb_setlen(cli->outbuf,len);
1156         SCVAL(cli->outbuf,0,0x81);
1157
1158         cli_send_smb(cli);
1159         DEBUG(5,("Sent session request\n"));
1160
1161         if (!cli_receive_smb(cli))
1162                 return False;
1163
1164         if (CVAL(cli->inbuf,0) == 0x84) {
1165                 /* C. Hoch  9/14/95 Start */
1166                 /* For information, here is the response structure.
1167                  * We do the byte-twiddling to for portability.
1168                 struct RetargetResponse{
1169                 unsigned char type;
1170                 unsigned char flags;
1171                 int16 length;
1172                 int32 ip_addr;
1173                 int16 port;
1174                 };
1175                 */
1176                 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1177                 /* SESSION RETARGET */
1178                 putip((char *)&cli->dest_ip,cli->inbuf+4);
1179
1180                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1181                 if (cli->fd == -1)
1182                         return False;
1183
1184                 DEBUG(3,("Retargeted\n"));
1185
1186                 set_socket_options(cli->fd,user_socket_options);
1187
1188                 /* Try again */
1189                 {
1190                         static int depth;
1191                         BOOL ret;
1192                         if (depth > 4) {
1193                                 DEBUG(0,("Retarget recursion - failing\n"));
1194                                 return False;
1195                         }
1196                         depth++;
1197                         ret = cli_session_request(cli, calling, called);
1198                         depth--;
1199                         return ret;
1200                 }
1201         } /* C. Hoch 9/14/95 End */
1202
1203         if (CVAL(cli->inbuf,0) != 0x82) {
1204                 /* This is the wrong place to put the error... JRA. */
1205                 cli->rap_error = CVAL(cli->inbuf,4);
1206                 return False;
1207         }
1208         return(True);
1209 }
1210
1211 /****************************************************************************
1212  Open the client sockets.
1213 ****************************************************************************/
1214
1215 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1216 {
1217         extern pstring user_socket_options;
1218         int name_type = 0x20;
1219         char *p;
1220
1221         /* reasonable default hostname */
1222         if (!host) host = "*SMBSERVER";
1223
1224         fstrcpy(cli->desthost, host);
1225
1226         /* allow hostnames of the form NAME#xx and do a netbios lookup */
1227         if ((p = strchr(cli->desthost, '#'))) {
1228                 name_type = strtol(p+1, NULL, 16);              
1229                 *p = 0;
1230         }
1231         
1232         if (!ip || is_zero_ip(*ip)) {
1233                 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1234                         return False;
1235                 }
1236                 if (ip) *ip = cli->dest_ip;
1237         } else {
1238                 cli->dest_ip = *ip;
1239         }
1240
1241         if (getenv("LIBSMB_PROG")) {
1242                 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1243         } else {
1244                 /* try 445 first, then 139 */
1245                 int port = cli->port?cli->port:445;
1246                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
1247                                           port, cli->timeout);
1248                 if (cli->fd == -1 && cli->port == 0) {
1249                         port = 139;
1250                         cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
1251                                                   port, cli->timeout);
1252                 }
1253                 if (cli->fd != -1)
1254                         cli->port = port;
1255         }
1256         if (cli->fd == -1) {
1257                 DEBUG(1,("Error connecting to %s (%s)\n",
1258                          ip?inet_ntoa(*ip):host,strerror(errno)));
1259                 return False;
1260         }
1261
1262         set_socket_options(cli->fd,user_socket_options);
1263
1264         return True;
1265 }
1266
1267 /****************************************************************************
1268  Initialise client credentials for authenticated pipe access.
1269 ****************************************************************************/
1270
1271 void init_creds(struct ntuser_creds *creds, const char* username,
1272                        const char* domain, const char* password)
1273 {
1274         ZERO_STRUCTP(creds);
1275
1276         pwd_set_cleartext(&creds->pwd, password);
1277
1278         fstrcpy(creds->user_name, username);
1279         fstrcpy(creds->domain, domain);
1280
1281         if (!*username) {
1282                 creds->pwd.null_pwd = True;
1283         }
1284 }
1285
1286 /**
1287    establishes a connection to after the negprot. 
1288    @param output_cli A fully initialised cli structure, non-null only on success
1289    @param dest_host The netbios name of the remote host
1290    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1291    @param port (optional) The destination port (0 for default)
1292    @param retry BOOL. Did this connection fail with a retryable error ?
1293
1294 */
1295 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
1296                               const char *my_name, 
1297                               const char *dest_host, 
1298                               struct in_addr *dest_ip, int port,
1299                               int signing_state, int flags,
1300                               BOOL *retry) 
1301 {
1302         NTSTATUS nt_status;
1303         struct nmb_name calling;
1304         struct nmb_name called;
1305         struct cli_state *cli;
1306         struct in_addr ip;
1307
1308         if (retry)
1309                 *retry = False;
1310
1311         if (!my_name) 
1312                 my_name = global_myname();
1313         
1314         if (!(cli = cli_initialise(NULL)))
1315                 return NT_STATUS_NO_MEMORY;
1316         
1317         make_nmb_name(&calling, my_name, 0x0);
1318         make_nmb_name(&called , dest_host, 0x20);
1319
1320         if (cli_set_port(cli, port) != port) {
1321                 cli_shutdown(cli);
1322                 return NT_STATUS_UNSUCCESSFUL;
1323         }
1324
1325         cli_set_timeout(cli, 10000); /* 10 seconds. */
1326
1327         if (dest_ip)
1328                 ip = *dest_ip;
1329         else
1330                 ZERO_STRUCT(ip);
1331
1332 again:
1333
1334         DEBUG(3,("Connecting to host=%s\n", dest_host));
1335         
1336         if (!cli_connect(cli, dest_host, &ip)) {
1337                 DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
1338                          nmb_namestr(&called), inet_ntoa(ip)));
1339                 cli_shutdown(cli);
1340                 return NT_STATUS_UNSUCCESSFUL;
1341         }
1342
1343         if (retry)
1344                 *retry = True;
1345
1346         if (!cli_session_request(cli, &calling, &called)) {
1347                 char *p;
1348                 DEBUG(1,("session request to %s failed (%s)\n", 
1349                          called.name, cli_errstr(cli)));
1350                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1351                         *p = 0;
1352                         goto again;
1353                 }
1354                 if (strcmp(called.name, "*SMBSERVER")) {
1355                         make_nmb_name(&called , "*SMBSERVER", 0x20);
1356                         goto again;
1357                 }
1358                 return NT_STATUS_UNSUCCESSFUL;
1359         }
1360
1361         cli_setup_signing_state(cli, signing_state);
1362
1363         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1364                 cli->use_spnego = False;
1365         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1366                 cli->use_kerberos = True;
1367
1368         if (!cli_negprot(cli)) {
1369                 DEBUG(1,("failed negprot\n"));
1370                 nt_status = NT_STATUS_UNSUCCESSFUL;
1371                 cli_shutdown(cli);
1372                 return nt_status;
1373         }
1374
1375         *output_cli = cli;
1376         return NT_STATUS_OK;
1377 }
1378
1379
1380 /**
1381    establishes a connection right up to doing tconX, password specified.
1382    @param output_cli A fully initialised cli structure, non-null only on success
1383    @param dest_host The netbios name of the remote host
1384    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1385    @param port (optional) The destination port (0 for default)
1386    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
1387    @param service_type The 'type' of serivice. 
1388    @param user Username, unix string
1389    @param domain User's domain
1390    @param password User's password, unencrypted unix string.
1391    @param retry BOOL. Did this connection fail with a retryable error ?
1392 */
1393
1394 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
1395                              const char *my_name, 
1396                              const char *dest_host, 
1397                              struct in_addr *dest_ip, int port,
1398                              const char *service, const char *service_type,
1399                              const char *user, const char *domain, 
1400                              const char *password, int flags,
1401                              int signing_state,
1402                              BOOL *retry) 
1403 {
1404         struct ntuser_creds creds;
1405         NTSTATUS nt_status;
1406         struct cli_state *cli = NULL;
1407
1408         nt_status = cli_start_connection(&cli, my_name, dest_host, 
1409                                          dest_ip, port, signing_state, flags, retry);
1410         
1411         if (!NT_STATUS_IS_OK(nt_status)) {
1412                 return nt_status;
1413         }
1414
1415         if (!cli_session_setup(cli, user, password, strlen(password)+1, 
1416                                password, strlen(password)+1, 
1417                                domain)) {
1418                 if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
1419                     && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
1420                 } else {
1421                         nt_status = cli_nt_error(cli);
1422                         DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
1423                         cli_shutdown(cli);
1424                         if (NT_STATUS_IS_OK(nt_status)) 
1425                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1426                         return nt_status;
1427                 }
1428         } 
1429
1430         if (service) {
1431                 if (!cli_send_tconX(cli, service, service_type,
1432                                     password, strlen(password)+1)) {
1433                         nt_status = cli_nt_error(cli);
1434                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1435                         cli_shutdown(cli);
1436                         if (NT_STATUS_IS_OK(nt_status)) {
1437                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1438                         }
1439                         return nt_status;
1440                 }
1441         }
1442
1443         init_creds(&creds, user, domain, password);
1444         cli_init_creds(cli, &creds);
1445
1446         *output_cli = cli;
1447         return NT_STATUS_OK;
1448 }
1449
1450 /****************************************************************************
1451  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1452 ****************************************************************************/
1453
1454 BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
1455                                      struct in_addr *pdest_ip)
1456 {
1457         struct nmb_name calling, called;
1458
1459         make_nmb_name(&calling, srchost, 0x0);
1460
1461         /*
1462          * If the called name is an IP address
1463          * then use *SMBSERVER immediately.
1464          */
1465
1466         if(is_ipaddress(desthost))
1467                 make_nmb_name(&called, "*SMBSERVER", 0x20);
1468         else
1469                 make_nmb_name(&called, desthost, 0x20);
1470
1471         if (!cli_session_request(cli, &calling, &called)) {
1472                 struct nmb_name smbservername;
1473
1474                 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1475
1476                 /*
1477                  * If the name wasn't *SMBSERVER then
1478                  * try with *SMBSERVER if the first name fails.
1479                  */
1480
1481                 if (nmb_name_equal(&called, &smbservername)) {
1482
1483                         /*
1484                          * The name used was *SMBSERVER, don't bother with another name.
1485                          */
1486
1487                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1488 with error %s.\n", desthost, cli_errstr(cli) ));
1489                         return False;
1490                 }
1491
1492                 /*
1493                  * We need to close the connection here but can't call cli_shutdown as
1494                  * will free an allocated cli struct. cli_close_connection was invented
1495                  * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1496                  */
1497
1498                 cli_close_connection(cli);
1499
1500                 if (!cli_initialise(cli) ||
1501                                 !cli_connect(cli, desthost, pdest_ip) ||
1502                                 !cli_session_request(cli, &calling, &smbservername)) {
1503                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1504 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
1505                         return False;
1506                 }
1507         }
1508
1509         return True;
1510 }
1511
1512
1513
1514
1515
1516 /****************************************************************************
1517  Send an old style tcon.
1518 ****************************************************************************/
1519 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
1520                       const char *service, const char *pass, const char *dev,
1521                       uint16 *max_xmit, uint16 *tid)
1522 {
1523         char *p;
1524
1525         if (!lp_client_plaintext_auth() && (*pass)) {
1526                 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1527                           " is disabled\n"));
1528                 return NT_STATUS_ACCESS_DENIED;
1529         }
1530
1531         memset(cli->outbuf,'\0',smb_size);
1532         memset(cli->inbuf,'\0',smb_size);
1533
1534         set_message(cli->outbuf, 0, 0, True);
1535         SCVAL(cli->outbuf,smb_com,SMBtcon);
1536         cli_setup_packet(cli);
1537
1538         p = smb_buf(cli->outbuf);
1539         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1540         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1541         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1542
1543         cli_setup_bcc(cli, p);
1544
1545         cli_send_smb(cli);
1546         if (!cli_receive_smb(cli)) {
1547                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1548         }
1549
1550         if (cli_is_error(cli)) {
1551                 return cli_nt_error(cli);
1552         }
1553
1554         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1555         *tid = SVAL(cli->inbuf, smb_vwv1);
1556
1557         return NT_STATUS_OK;
1558 }
1559
1560 /* Return a cli_state pointing at the IPC$ share for the given server */
1561
1562 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1563                                          struct user_auth_info *user_info)
1564 {
1565         struct cli_state *cli;
1566         pstring myname;
1567         NTSTATUS nt_status;
1568
1569         get_myname(myname);
1570         
1571         nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC", 
1572                                         user_info->username, lp_workgroup(), user_info->password, 
1573                                         CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL);
1574
1575         if (NT_STATUS_IS_OK(nt_status)) {
1576                 return cli;
1577         } else if (is_ipaddress(server)) {
1578             /* windows 9* needs a correct NMB name for connections */
1579             fstring remote_name;
1580
1581             if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1582                 cli = get_ipc_connect(remote_name, server_ip, user_info);
1583                 if (cli)
1584                     return cli;
1585             }
1586         }
1587         return NULL;
1588 }
1589
1590 /* Return the IP address and workgroup of a master browser on the 
1591    network. */
1592
1593 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1594 {
1595         struct ip_service *ip_list;
1596         struct cli_state *cli;
1597         int i, count;
1598         struct in_addr server_ip; 
1599
1600         /* Go looking for workgroups by broadcasting on the local network */ 
1601
1602         if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
1603                 return False;
1604         }
1605
1606         for (i = 0; i < count; i++) {
1607                 static fstring name;
1608
1609                 if (!name_status_find("*", 0, 0x1d, ip_list[i].ip, name))
1610                         continue;
1611
1612                 if (!find_master_ip(name, &server_ip))
1613                         continue;
1614
1615                 pstrcpy(workgroup, name);
1616
1617                 DEBUG(4, ("found master browser %s, %s\n", 
1618                           name, inet_ntoa(ip_list[i].ip)));
1619
1620                 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
1621
1622                 if (!cli)
1623                     continue;
1624                 
1625                 return cli;
1626         }
1627
1628         return NULL;
1629 }