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