48885f19d8413af26cbbc0422d9d067731677c6d
[ira/wip.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern pstring user_socket_options;
25
26 static const struct {
27         int prot;
28         const char *name;
29 } prots[] = {
30         {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
31         {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
32         {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
33         {PROTOCOL_LANMAN1,"LANMAN1.0"},
34         {PROTOCOL_LANMAN2,"LM1.2X002"},
35         {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
36         {PROTOCOL_LANMAN2,"Samba"},
37         {PROTOCOL_NT1,"NT LANMAN 1.0"},
38         {PROTOCOL_NT1,"NT LM 0.12"},
39         {-1,NULL}
40 };
41
42 /**
43  * Set the user session key for a connection
44  * @param cli The cli structure to add it too
45  * @param session_key The session key used.  (A copy of this is taken for the cli struct)
46  *
47  */
48
49 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key) 
50 {
51         cli->user_session_key = data_blob(session_key.data, session_key.length);
52 }
53
54 /****************************************************************************
55  Do an old lanman2 style session setup.
56 ****************************************************************************/
57
58 static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user, 
59                                       const char *pass, size_t passlen, const char *workgroup)
60 {
61         DATA_BLOB session_key = data_blob(NULL, 0);
62         DATA_BLOB lm_response = data_blob(NULL, 0);
63         fstring pword;
64         char *p;
65
66         if (passlen > sizeof(pword)-1)
67                 return False;
68
69         /* LANMAN servers predate NT status codes and Unicode and ignore those 
70            smb flags so we must disable the corresponding default capabilities  
71            that would otherwise cause the Unicode and NT Status flags to be
72            set (and even returned by the server) */
73
74         cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
75
76         /* if in share level security then don't send a password now */
77         if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
78                 passlen = 0;
79
80         if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
81                 /* Encrypted mode needed, and non encrypted password supplied. */
82                 lm_response = data_blob(NULL, 24);
83                 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
84                         DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
85                         return False;
86                 }
87         } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
88                 /* Encrypted mode needed, and encrypted password supplied. */
89                 lm_response = data_blob(pass, passlen);
90         } else if (passlen > 0) {
91                 /* Plaintext mode needed, assume plaintext supplied. */
92                 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
93                 lm_response = data_blob(pass, passlen);
94         }
95
96         /* send a session setup command */
97         memset(cli->outbuf,'\0',smb_size);
98         set_message(cli->outbuf,10, 0, True);
99         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
100         cli_setup_packet(cli);
101         
102         SCVAL(cli->outbuf,smb_vwv0,0xFF);
103         SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
104         SSVAL(cli->outbuf,smb_vwv3,2);
105         SSVAL(cli->outbuf,smb_vwv4,1);
106         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
107         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
108
109         p = smb_buf(cli->outbuf);
110         memcpy(p,lm_response.data,lm_response.length);
111         p += lm_response.length;
112         p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
113         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
114         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
115         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
116         cli_setup_bcc(cli, p);
117
118         cli_send_smb(cli);
119         if (!cli_receive_smb(cli))
120                 return False;
121
122         show_msg(cli->inbuf);
123
124         if (cli_is_error(cli))
125                 return False;
126         
127         /* use the returned vuid from now on */
128         cli->vuid = SVAL(cli->inbuf,smb_uid);   
129         fstrcpy(cli->user_name, user);
130
131         if (session_key.data) {
132                 /* Have plaintext orginal */
133                 cli_set_session_key(cli, session_key);
134         }
135
136         return True;
137 }
138
139 /****************************************************************************
140  Work out suitable capabilities to offer the server.
141 ****************************************************************************/
142
143 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
144 {
145         uint32 capabilities = CAP_NT_SMBS;
146
147         if (!cli->force_dos_errors)
148                 capabilities |= CAP_STATUS32;
149
150         if (cli->use_level_II_oplocks)
151                 capabilities |= CAP_LEVEL_II_OPLOCKS;
152
153         capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
154         return capabilities;
155 }
156
157 /****************************************************************************
158  Do a NT1 guest session setup.
159 ****************************************************************************/
160
161 static BOOL cli_session_setup_guest(struct cli_state *cli)
162 {
163         char *p;
164         uint32 capabilities = cli_session_setup_capabilities(cli);
165
166         memset(cli->outbuf, '\0', smb_size);
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, 0);
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) || NT_STATUS_IS_OK(nt_status)) {
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 #ifdef HAVE_KRB5
706         BOOL got_kerberos_mechanism = False;
707 #endif
708         DATA_BLOB blob;
709
710         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
711
712         /* the server might not even do spnego */
713         if (cli->secblob.length <= 16) {
714                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
715                 goto ntlmssp;
716         }
717
718 #if 0
719         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
720 #endif
721
722         /* there is 16 bytes of GUID before the real spnego packet starts */
723         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
724
725         /* the server sent us the first part of the SPNEGO exchange in the negprot 
726            reply */
727         if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
728                 data_blob_free(&blob);
729                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
730         }
731         data_blob_free(&blob);
732
733         /* make sure the server understands kerberos */
734         for (i=0;OIDs[i];i++) {
735                 DEBUG(3,("got OID=%s\n", OIDs[i]));
736 #ifdef HAVE_KRB5
737                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
738                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
739                         got_kerberos_mechanism = True;
740                 }
741 #endif
742                 free(OIDs[i]);
743         }
744         DEBUG(3,("got principal=%s\n", principal));
745
746         fstrcpy(cli->user_name, user);
747
748 #ifdef HAVE_KRB5
749         /* If password is set we reauthenticate to kerberos server
750          * and do not store results */
751
752         if (got_kerberos_mechanism && cli->use_kerberos) {
753                 ADS_STATUS rc;
754
755                 if (pass && *pass) {
756                         int ret;
757                         
758                         use_in_memory_ccache();
759                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
760                         
761                         if (ret){
762                                 SAFE_FREE(principal);
763                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
764                                 if (cli->fallback_after_kerberos)
765                                         goto ntlmssp;
766                                 return ADS_ERROR_KRB5(ret);
767                         }
768                 }
769                 
770                 rc = cli_session_setup_kerberos(cli, principal, domain);
771                 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
772                         SAFE_FREE(principal);
773                         return rc;
774                 }
775         }
776 #endif
777
778         SAFE_FREE(principal);
779
780 ntlmssp:
781
782         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain));
783 }
784
785 /****************************************************************************
786  Send a session setup. The username and workgroup is in UNIX character
787  format and must be converted to DOS codepage format before sending. If the
788  password is in plaintext, the same should be done.
789 ****************************************************************************/
790
791 BOOL cli_session_setup(struct cli_state *cli, 
792                        const char *user, 
793                        const char *pass, int passlen,
794                        const char *ntpass, int ntpasslen,
795                        const char *workgroup)
796 {
797         char *p;
798         fstring user2;
799
800         /* allow for workgroups as part of the username */
801         fstrcpy(user2, user);
802         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
803             (p=strchr_m(user2,*lp_winbind_separator()))) {
804                 *p = 0;
805                 user = p+1;
806                 workgroup = user2;
807         }
808
809         if (cli->protocol < PROTOCOL_LANMAN1)
810                 return True;
811
812         /* now work out what sort of session setup we are going to
813            do. I have split this into separate functions to make the
814            flow a bit easier to understand (tridge) */
815
816         /* if its an older server then we have to use the older request format */
817
818         if (cli->protocol < PROTOCOL_NT1) {
819                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
820                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
821                                   " is disabled\n"));
822                         return False;
823                 }
824
825                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
826                     !lp_client_plaintext_auth() && (*pass)) {
827                         DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
828                                   " is disabled\n"));
829                         return False;
830                 }
831
832                 return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
833         }
834
835         /* if no user is supplied then we have to do an anonymous connection.
836            passwords are ignored */
837
838         if (!user || !*user)
839                 return cli_session_setup_guest(cli);
840
841         /* if the server is share level then send a plaintext null
842            password at this point. The password is sent in the tree
843            connect */
844
845         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
846                 return cli_session_setup_plaintext(cli, user, "", workgroup);
847
848         /* if the server doesn't support encryption then we have to use 
849            plaintext. The second password is ignored */
850
851         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
852                 if (!lp_client_plaintext_auth() && (*pass)) {
853                         DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
854                                   " is disabled\n"));
855                         return False;
856                 }
857                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
858         }
859
860         /* if the server supports extended security then use SPNEGO */
861
862         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
863                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
864                 if (!ADS_ERR_OK(status)) {
865                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
866                         return False;
867                 }
868         } else {
869                 /* otherwise do a NT1 style session setup */
870                 if ( !cli_session_setup_nt1(cli, user, pass, passlen, ntpass, ntpasslen, workgroup) ) {
871                         DEBUG(3,("cli_session_setup: NT1 session setup failed!\n"));
872                         return False;
873                 }
874         }
875
876         return True;
877
878 }
879
880 /****************************************************************************
881  Send a uloggoff.
882 *****************************************************************************/
883
884 BOOL cli_ulogoff(struct cli_state *cli)
885 {
886         memset(cli->outbuf,'\0',smb_size);
887         set_message(cli->outbuf,2,0,True);
888         SCVAL(cli->outbuf,smb_com,SMBulogoffX);
889         cli_setup_packet(cli);
890         SSVAL(cli->outbuf,smb_vwv0,0xFF);
891         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
892
893         cli_send_smb(cli);
894         if (!cli_receive_smb(cli))
895                 return False;
896
897         if (cli_is_error(cli)) {
898                 return False;
899         }
900
901         cli->cnum = -1;
902         return True;
903 }
904
905 /****************************************************************************
906  Send a tconX.
907 ****************************************************************************/
908 BOOL cli_send_tconX(struct cli_state *cli, 
909                     const char *share, const char *dev, const char *pass, int passlen)
910 {
911         fstring fullshare, pword;
912         char *p;
913         memset(cli->outbuf,'\0',smb_size);
914         memset(cli->inbuf,'\0',smb_size);
915
916         fstrcpy(cli->share, share);
917
918         /* in user level security don't send a password now */
919         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
920                 passlen = 1;
921                 pass = "";
922         }
923
924         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
925                 if (!lp_client_lanman_auth()) {
926                         DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
927                                   " is disabled\n"));
928                         return False;
929                 }
930
931                 /*
932                  * Non-encrypted passwords - convert to DOS codepage before encryption.
933                  */
934                 passlen = 24;
935                 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
936         } else {
937                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
938                         if (!lp_client_plaintext_auth() && (*pass)) {
939                                 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
940                                           " is disabled\n"));
941                                 return False;
942                         }
943
944                         /*
945                          * Non-encrypted passwords - convert to DOS codepage before using.
946                          */
947                         passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
948                         
949                 } else {
950                         memcpy(pword, pass, passlen);
951                 }
952         }
953
954         slprintf(fullshare, sizeof(fullshare)-1,
955                  "\\\\%s\\%s", cli->desthost, share);
956
957         set_message(cli->outbuf,4, 0, True);
958         SCVAL(cli->outbuf,smb_com,SMBtconX);
959         cli_setup_packet(cli);
960
961         SSVAL(cli->outbuf,smb_vwv0,0xFF);
962         SSVAL(cli->outbuf,smb_vwv3,passlen);
963
964         p = smb_buf(cli->outbuf);
965         memcpy(p,pword,passlen);
966         p += passlen;
967         p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
968         p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
969
970         cli_setup_bcc(cli, p);
971
972         cli_send_smb(cli);
973         if (!cli_receive_smb(cli))
974                 return False;
975
976         if (cli_is_error(cli))
977                 return False;
978
979         clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
980
981         if (cli->protocol >= PROTOCOL_NT1 &&
982             smb_buflen(cli->inbuf) == 3) {
983                 /* almost certainly win95 - enable bug fixes */
984                 cli->win95 = True;
985         }
986         
987         /* Make sure that we have the optional support 16-bit field.  WCT > 2 */
988         /* Avoids issues when connecting to Win9x boxes sharing files */
989
990         cli->dfsroot = False;
991         if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 )
992                 cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False;
993
994         cli->cnum = SVAL(cli->inbuf,smb_tid);
995         return True;
996 }
997
998 /****************************************************************************
999  Send a tree disconnect.
1000 ****************************************************************************/
1001
1002 BOOL cli_tdis(struct cli_state *cli)
1003 {
1004         memset(cli->outbuf,'\0',smb_size);
1005         set_message(cli->outbuf,0,0,True);
1006         SCVAL(cli->outbuf,smb_com,SMBtdis);
1007         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1008         cli_setup_packet(cli);
1009         
1010         cli_send_smb(cli);
1011         if (!cli_receive_smb(cli))
1012                 return False;
1013         
1014         if (cli_is_error(cli)) {
1015                 return False;
1016         }
1017
1018         cli->cnum = -1;
1019         return True;
1020 }
1021
1022 /****************************************************************************
1023  Send a negprot command.
1024 ****************************************************************************/
1025
1026 void cli_negprot_send(struct cli_state *cli)
1027 {
1028         char *p;
1029         int numprots;
1030
1031         if (cli->protocol < PROTOCOL_NT1)
1032                 cli->use_spnego = False;
1033
1034         memset(cli->outbuf,'\0',smb_size);
1035
1036         /* setup the protocol strings */
1037         set_message(cli->outbuf,0,0,True);
1038
1039         p = smb_buf(cli->outbuf);
1040         for (numprots=0;
1041              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1042              numprots++) {
1043                 *p++ = 2;
1044                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1045         }
1046
1047         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1048         cli_setup_bcc(cli, p);
1049         cli_setup_packet(cli);
1050
1051         SCVAL(smb_buf(cli->outbuf),0,2);
1052
1053         cli_send_smb(cli);
1054 }
1055
1056 /****************************************************************************
1057  Send a negprot command.
1058 ****************************************************************************/
1059
1060 BOOL cli_negprot(struct cli_state *cli)
1061 {
1062         char *p;
1063         int numprots;
1064         int plength;
1065
1066         if (cli->protocol < PROTOCOL_NT1)
1067                 cli->use_spnego = False;
1068
1069         memset(cli->outbuf,'\0',smb_size);
1070
1071         /* setup the protocol strings */
1072         for (plength=0,numprots=0;
1073              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1074              numprots++)
1075                 plength += strlen(prots[numprots].name)+2;
1076     
1077         set_message(cli->outbuf,0,plength,True);
1078
1079         p = smb_buf(cli->outbuf);
1080         for (numprots=0;
1081              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1082              numprots++) {
1083                 *p++ = 2;
1084                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1085         }
1086
1087         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1088         cli_setup_packet(cli);
1089
1090         SCVAL(smb_buf(cli->outbuf),0,2);
1091
1092         cli_send_smb(cli);
1093         if (!cli_receive_smb(cli))
1094                 return False;
1095
1096         show_msg(cli->inbuf);
1097
1098         if (cli_is_error(cli) ||
1099             ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1100                 return(False);
1101         }
1102
1103         cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;  
1104
1105         if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1106                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1107                 return False;
1108         }
1109
1110         if (cli->protocol >= PROTOCOL_NT1) {    
1111                 /* NT protocol */
1112                 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1113                 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1114                 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1115                 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1116                 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1117                 cli->serverzone *= 60;
1118                 /* this time arrives in real GMT */
1119                 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1120                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1121                 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1122                 if (cli->capabilities & CAP_RAW_MODE) {
1123                         cli->readbraw_supported = True;
1124                         cli->writebraw_supported = True;      
1125                 }
1126                 /* work out if they sent us a workgroup */
1127                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1128                     smb_buflen(cli->inbuf) > 8) {
1129                         clistr_pull(cli, cli->server_domain, 
1130                                     smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1131                                     smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1132                 }
1133
1134                 /*
1135                  * As signing is slow we only turn it on if either the client or
1136                  * the server require it. JRA.
1137                  */
1138
1139                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1140                         /* Fail if server says signing is mandatory and we don't want to support it. */
1141                         if (!cli->sign_info.allow_smb_signing) {
1142                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1143                                 return False;
1144                         }
1145                         cli->sign_info.negotiated_smb_signing = True;
1146                         cli->sign_info.mandatory_signing = True;
1147                 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1148                         /* Fail if client says signing is mandatory and the server doesn't support it. */
1149                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1150                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1151                                 return False;
1152                         }
1153                         cli->sign_info.negotiated_smb_signing = True;
1154                         cli->sign_info.mandatory_signing = True;
1155                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1156                         cli->sign_info.negotiated_smb_signing = True;
1157                 }
1158
1159                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1160                         SAFE_FREE(cli->outbuf);
1161                         SAFE_FREE(cli->inbuf);
1162                         cli->outbuf = (char *)SMB_MALLOC(CLI_MAX_LARGE_READX_SIZE+SAFETY_MARGIN);
1163                         cli->inbuf = (char *)SMB_MALLOC(CLI_MAX_LARGE_READX_SIZE+SAFETY_MARGIN);
1164                         cli->bufsize = CLI_MAX_LARGE_READX_SIZE;
1165                 }
1166
1167         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1168                 cli->use_spnego = False;
1169                 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1170                 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1171                 cli->max_mux = SVAL(cli->inbuf, smb_vwv3); 
1172                 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1173                 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1174                 cli->serverzone *= 60;
1175                 /* this time is converted to GMT by make_unix_date */
1176                 cli->servertime = cli_make_unix_date(cli,cli->inbuf+smb_vwv8);
1177                 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1178                 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1179                 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1180         } else {
1181                 /* the old core protocol */
1182                 cli->use_spnego = False;
1183                 cli->sec_mode = 0;
1184                 cli->serverzone = get_time_zone(time(NULL));
1185         }
1186
1187         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1188
1189         /* a way to force ascii SMB */
1190         if (getenv("CLI_FORCE_ASCII"))
1191                 cli->capabilities &= ~CAP_UNICODE;
1192
1193         return True;
1194 }
1195
1196 /****************************************************************************
1197  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1198 ****************************************************************************/
1199
1200 BOOL cli_session_request(struct cli_state *cli,
1201                          struct nmb_name *calling, struct nmb_name *called)
1202 {
1203         char *p;
1204         int len = 4;
1205
1206         memcpy(&(cli->calling), calling, sizeof(*calling));
1207         memcpy(&(cli->called ), called , sizeof(*called ));
1208   
1209         /* put in the destination name */
1210         p = cli->outbuf+len;
1211         name_mangle(cli->called .name, p, cli->called .name_type);
1212         len += name_len(p);
1213
1214         /* and my name */
1215         p = cli->outbuf+len;
1216         name_mangle(cli->calling.name, p, cli->calling.name_type);
1217         len += name_len(p);
1218
1219         /* 445 doesn't have session request */
1220         if (cli->port == 445)
1221                 return True;
1222
1223         /* send a session request (RFC 1002) */
1224         /* setup the packet length
1225          * Remove four bytes from the length count, since the length
1226          * field in the NBT Session Service header counts the number
1227          * of bytes which follow.  The cli_send_smb() function knows
1228          * about this and accounts for those four bytes.
1229          * CRH.
1230          */
1231         len -= 4;
1232         _smb_setlen(cli->outbuf,len);
1233         SCVAL(cli->outbuf,0,0x81);
1234
1235         cli_send_smb(cli);
1236         DEBUG(5,("Sent session request\n"));
1237
1238         if (!cli_receive_smb(cli))
1239                 return False;
1240
1241         if (CVAL(cli->inbuf,0) == 0x84) {
1242                 /* C. Hoch  9/14/95 Start */
1243                 /* For information, here is the response structure.
1244                  * We do the byte-twiddling to for portability.
1245                 struct RetargetResponse{
1246                 unsigned char type;
1247                 unsigned char flags;
1248                 int16 length;
1249                 int32 ip_addr;
1250                 int16 port;
1251                 };
1252                 */
1253                 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1254                 /* SESSION RETARGET */
1255                 putip((char *)&cli->dest_ip,cli->inbuf+4);
1256
1257                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1258                 if (cli->fd == -1)
1259                         return False;
1260
1261                 DEBUG(3,("Retargeted\n"));
1262
1263                 set_socket_options(cli->fd,user_socket_options);
1264
1265                 /* Try again */
1266                 {
1267                         static int depth;
1268                         BOOL ret;
1269                         if (depth > 4) {
1270                                 DEBUG(0,("Retarget recursion - failing\n"));
1271                                 return False;
1272                         }
1273                         depth++;
1274                         ret = cli_session_request(cli, calling, called);
1275                         depth--;
1276                         return ret;
1277                 }
1278         } /* C. Hoch 9/14/95 End */
1279
1280         if (CVAL(cli->inbuf,0) != 0x82) {
1281                 /* This is the wrong place to put the error... JRA. */
1282                 cli->rap_error = CVAL(cli->inbuf,4);
1283                 return False;
1284         }
1285         return(True);
1286 }
1287
1288 /****************************************************************************
1289  Open the client sockets.
1290 ****************************************************************************/
1291
1292 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1293 {
1294         int name_type = 0x20;
1295         char *p;
1296
1297         /* reasonable default hostname */
1298         if (!host) host = "*SMBSERVER";
1299
1300         fstrcpy(cli->desthost, host);
1301
1302         /* allow hostnames of the form NAME#xx and do a netbios lookup */
1303         if ((p = strchr(cli->desthost, '#'))) {
1304                 name_type = strtol(p+1, NULL, 16);              
1305                 *p = 0;
1306         }
1307         
1308         if (!ip || is_zero_ip(*ip)) {
1309                 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1310                         return False;
1311                 }
1312                 if (ip) *ip = cli->dest_ip;
1313         } else {
1314                 cli->dest_ip = *ip;
1315         }
1316
1317         if (getenv("LIBSMB_PROG")) {
1318                 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1319         } else {
1320                 /* try 445 first, then 139 */
1321                 int port = cli->port?cli->port:445;
1322                 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
1323                                           port, cli->timeout);
1324                 if (cli->fd == -1 && cli->port == 0) {
1325                         port = 139;
1326                         cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
1327                                                   port, cli->timeout);
1328                 }
1329                 if (cli->fd != -1)
1330                         cli->port = port;
1331         }
1332         if (cli->fd == -1) {
1333                 DEBUG(1,("Error connecting to %s (%s)\n",
1334                          ip?inet_ntoa(*ip):host,strerror(errno)));
1335                 return False;
1336         }
1337
1338         set_socket_options(cli->fd,user_socket_options);
1339
1340         return True;
1341 }
1342
1343 /**
1344    establishes a connection to after the negprot. 
1345    @param output_cli A fully initialised cli structure, non-null only on success
1346    @param dest_host The netbios name of the remote host
1347    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1348    @param port (optional) The destination port (0 for default)
1349    @param retry BOOL. Did this connection fail with a retryable error ?
1350
1351 */
1352 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
1353                               const char *my_name, 
1354                               const char *dest_host, 
1355                               struct in_addr *dest_ip, int port,
1356                               int signing_state, int flags,
1357                               BOOL *retry) 
1358 {
1359         NTSTATUS nt_status;
1360         struct nmb_name calling;
1361         struct nmb_name called;
1362         struct cli_state *cli;
1363         struct in_addr ip;
1364
1365         if (retry)
1366                 *retry = False;
1367
1368         if (!my_name) 
1369                 my_name = global_myname();
1370         
1371         if (!(cli = cli_initialise(NULL)))
1372                 return NT_STATUS_NO_MEMORY;
1373         
1374         make_nmb_name(&calling, my_name, 0x0);
1375         make_nmb_name(&called , dest_host, 0x20);
1376
1377         if (cli_set_port(cli, port) != port) {
1378                 cli_shutdown(cli);
1379                 return NT_STATUS_UNSUCCESSFUL;
1380         }
1381
1382         cli_set_timeout(cli, 10000); /* 10 seconds. */
1383
1384         if (dest_ip)
1385                 ip = *dest_ip;
1386         else
1387                 ZERO_STRUCT(ip);
1388
1389 again:
1390
1391         DEBUG(3,("Connecting to host=%s\n", dest_host));
1392         
1393         if (!cli_connect(cli, dest_host, &ip)) {
1394                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s)\n",
1395                          nmb_namestr(&called), inet_ntoa(ip)));
1396                 cli_shutdown(cli);
1397                 if (is_zero_ip(ip)) {
1398                         return NT_STATUS_BAD_NETWORK_NAME;
1399                 } else {
1400                         return NT_STATUS_CONNECTION_REFUSED;
1401                 }
1402         }
1403
1404         if (retry)
1405                 *retry = True;
1406
1407         if (!cli_session_request(cli, &calling, &called)) {
1408                 char *p;
1409                 DEBUG(1,("session request to %s failed (%s)\n", 
1410                          called.name, cli_errstr(cli)));
1411                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1412                         *p = 0;
1413                         goto again;
1414                 }
1415                 if (strcmp(called.name, "*SMBSERVER")) {
1416                         make_nmb_name(&called , "*SMBSERVER", 0x20);
1417                         goto again;
1418                 }
1419                 return NT_STATUS_BAD_NETWORK_NAME;
1420         }
1421
1422         cli_setup_signing_state(cli, signing_state);
1423
1424         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1425                 cli->use_spnego = False;
1426         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1427                 cli->use_kerberos = True;
1428
1429         if (!cli_negprot(cli)) {
1430                 DEBUG(1,("failed negprot\n"));
1431                 nt_status = cli_nt_error(cli);
1432                 if (NT_STATUS_IS_OK(nt_status)) {
1433                         nt_status = NT_STATUS_UNSUCCESSFUL;
1434                 }
1435                 cli_shutdown(cli);
1436                 return nt_status;
1437         }
1438
1439         *output_cli = cli;
1440         return NT_STATUS_OK;
1441 }
1442
1443
1444 /**
1445    establishes a connection right up to doing tconX, password specified.
1446    @param output_cli A fully initialised cli structure, non-null only on success
1447    @param dest_host The netbios name of the remote host
1448    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1449    @param port (optional) The destination port (0 for default)
1450    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
1451    @param service_type The 'type' of serivice. 
1452    @param user Username, unix string
1453    @param domain User's domain
1454    @param password User's password, unencrypted unix string.
1455    @param retry BOOL. Did this connection fail with a retryable error ?
1456 */
1457
1458 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
1459                              const char *my_name, 
1460                              const char *dest_host, 
1461                              struct in_addr *dest_ip, int port,
1462                              const char *service, const char *service_type,
1463                              const char *user, const char *domain, 
1464                              const char *password, int flags,
1465                              int signing_state,
1466                              BOOL *retry) 
1467 {
1468         NTSTATUS nt_status;
1469         struct cli_state *cli = NULL;
1470
1471         nt_status = cli_start_connection(&cli, my_name, dest_host, 
1472                                          dest_ip, port, signing_state, flags, retry);
1473         
1474         if (!NT_STATUS_IS_OK(nt_status)) {
1475                 return nt_status;
1476         }
1477
1478         if (!cli_session_setup(cli, user, password, strlen(password)+1, 
1479                                password, strlen(password)+1, 
1480                                domain)) {
1481                 if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
1482                     && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
1483                 } else {
1484                         nt_status = cli_nt_error(cli);
1485                         DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
1486                         cli_shutdown(cli);
1487                         if (NT_STATUS_IS_OK(nt_status)) 
1488                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1489                         return nt_status;
1490                 }
1491         } 
1492
1493         if (service) {
1494                 if (!cli_send_tconX(cli, service, service_type,
1495                                     password, strlen(password)+1)) {
1496                         nt_status = cli_nt_error(cli);
1497                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1498                         cli_shutdown(cli);
1499                         if (NT_STATUS_IS_OK(nt_status)) {
1500                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1501                         }
1502                         return nt_status;
1503                 }
1504         }
1505
1506         cli_init_creds(cli, user, domain, password);
1507
1508         *output_cli = cli;
1509         return NT_STATUS_OK;
1510 }
1511
1512 /****************************************************************************
1513  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1514 ****************************************************************************/
1515
1516 BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
1517                                      struct in_addr *pdest_ip)
1518 {
1519         struct nmb_name calling, called;
1520
1521         make_nmb_name(&calling, srchost, 0x0);
1522
1523         /*
1524          * If the called name is an IP address
1525          * then use *SMBSERVER immediately.
1526          */
1527
1528         if(is_ipaddress(desthost))
1529                 make_nmb_name(&called, "*SMBSERVER", 0x20);
1530         else
1531                 make_nmb_name(&called, desthost, 0x20);
1532
1533         if (!cli_session_request(cli, &calling, &called)) {
1534                 struct nmb_name smbservername;
1535
1536                 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1537
1538                 /*
1539                  * If the name wasn't *SMBSERVER then
1540                  * try with *SMBSERVER if the first name fails.
1541                  */
1542
1543                 if (nmb_name_equal(&called, &smbservername)) {
1544
1545                         /*
1546                          * The name used was *SMBSERVER, don't bother with another name.
1547                          */
1548
1549                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1550 with error %s.\n", desthost, cli_errstr(cli) ));
1551                         return False;
1552                 }
1553
1554                 /*
1555                  * We need to close the connection here but can't call cli_shutdown as
1556                  * will free an allocated cli struct. cli_close_connection was invented
1557                  * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1558                  */
1559
1560                 cli_close_connection(cli);
1561
1562                 if (!cli_initialise(cli) ||
1563                                 !cli_connect(cli, desthost, pdest_ip) ||
1564                                 !cli_session_request(cli, &calling, &smbservername)) {
1565                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1566 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
1567                         return False;
1568                 }
1569         }
1570
1571         return True;
1572 }
1573
1574
1575
1576
1577
1578 /****************************************************************************
1579  Send an old style tcon.
1580 ****************************************************************************/
1581 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
1582                       const char *service, const char *pass, const char *dev,
1583                       uint16 *max_xmit, uint16 *tid)
1584 {
1585         char *p;
1586
1587         if (!lp_client_plaintext_auth() && (*pass)) {
1588                 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1589                           " is disabled\n"));
1590                 return NT_STATUS_ACCESS_DENIED;
1591         }
1592
1593         memset(cli->outbuf,'\0',smb_size);
1594         memset(cli->inbuf,'\0',smb_size);
1595
1596         set_message(cli->outbuf, 0, 0, True);
1597         SCVAL(cli->outbuf,smb_com,SMBtcon);
1598         cli_setup_packet(cli);
1599
1600         p = smb_buf(cli->outbuf);
1601         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1602         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1603         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1604
1605         cli_setup_bcc(cli, p);
1606
1607         cli_send_smb(cli);
1608         if (!cli_receive_smb(cli)) {
1609                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1610         }
1611
1612         if (cli_is_error(cli)) {
1613                 return cli_nt_error(cli);
1614         }
1615
1616         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1617         *tid = SVAL(cli->inbuf, smb_vwv1);
1618
1619         return NT_STATUS_OK;
1620 }
1621
1622 /* Return a cli_state pointing at the IPC$ share for the given server */
1623
1624 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1625                                          struct user_auth_info *user_info)
1626 {
1627         struct cli_state *cli;
1628         pstring myname;
1629         NTSTATUS nt_status;
1630
1631         get_myname(myname);
1632         
1633         nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC", 
1634                                         user_info->username, lp_workgroup(), user_info->password, 
1635                                         CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL);
1636
1637         if (NT_STATUS_IS_OK(nt_status)) {
1638                 return cli;
1639         } else if (is_ipaddress(server)) {
1640             /* windows 9* needs a correct NMB name for connections */
1641             fstring remote_name;
1642
1643             if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1644                 cli = get_ipc_connect(remote_name, server_ip, user_info);
1645                 if (cli)
1646                     return cli;
1647             }
1648         }
1649         return NULL;
1650 }
1651
1652 /*
1653  * Given the IP address of a master browser on the network, return its
1654  * workgroup and connect to it.
1655  *
1656  * This function is provided to allow additional processing beyond what
1657  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
1658  * browsers and obtain each master browsers' list of domains (in case the
1659  * first master browser is recently on the network and has not yet
1660  * synchronized with other master browsers and therefore does not yet have the
1661  * entire network browse list)
1662  */
1663
1664 struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info)
1665 {
1666         static fstring name;
1667         struct cli_state *cli;
1668         struct in_addr server_ip; 
1669
1670         DEBUG(99, ("Looking up name of master browser %s\n",
1671                    inet_ntoa(mb_ip->ip)));
1672
1673         /*
1674          * Do a name status query to find out the name of the master browser.
1675          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
1676          * master browser will not respond to a wildcard query (or, at least,
1677          * an NT4 server acting as the domain master browser will not).
1678          *
1679          * We might be able to use ONLY the query on MSBROWSE, but that's not
1680          * yet been tested with all Windows versions, so until it is, leave
1681          * the original wildcard query as the first choice and fall back to
1682          * MSBROWSE if the wildcard query fails.
1683          */
1684         if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) &&
1685             !name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) {
1686
1687                 DEBUG(99, ("Could not retrieve name status for %s\n",
1688                            inet_ntoa(mb_ip->ip)));
1689                 return NULL;
1690         }
1691
1692         if (!find_master_ip(name, &server_ip)) {
1693                 DEBUG(99, ("Could not find master ip for %s\n", name));
1694                 return NULL;
1695         }
1696
1697                 pstrcpy(workgroup, name);
1698
1699                 DEBUG(4, ("found master browser %s, %s\n", 
1700                   name, inet_ntoa(mb_ip->ip)));
1701
1702                 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
1703
1704                 return cli;
1705     
1706 }
1707
1708 /*
1709  * Return the IP address and workgroup of a master browser on the network, and
1710  * connect to it.
1711  */
1712
1713 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1714 {
1715         struct ip_service *ip_list;
1716         struct cli_state *cli;
1717         int i, count;
1718
1719         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
1720
1721         /* Go looking for workgroups by broadcasting on the local network */ 
1722
1723         if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
1724                 DEBUG(99, ("No master browsers responded\n"));
1725                 return False;
1726         }
1727
1728         for (i = 0; i < count; i++) {
1729             DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
1730
1731             cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info);
1732             if (cli)
1733                     return(cli);
1734         }
1735
1736         return NULL;
1737 }