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