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