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