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