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