s3-build: only include krb5 environment variables where required.
[ira/wip.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "popt_common.h"
23 #include "../libcli/auth/libcli_auth.h"
24 #include "../libcli/auth/spnego.h"
25 #include "smb_krb5.h"
26 #include "../libcli/auth/ntlmssp.h"
27 #include "libads/kerberos_proto.h"
28 #include "krb5_env.h"
29
30 static const struct {
31         int prot;
32         const char name[24];
33 } prots[10] = {
34         {PROTOCOL_CORE,         "PC NETWORK PROGRAM 1.0"},
35         {PROTOCOL_COREPLUS,     "MICROSOFT NETWORKS 1.03"},
36         {PROTOCOL_LANMAN1,      "MICROSOFT NETWORKS 3.0"},
37         {PROTOCOL_LANMAN1,      "LANMAN1.0"},
38         {PROTOCOL_LANMAN2,      "LM1.2X002"},
39         {PROTOCOL_LANMAN2,      "DOS LANMAN2.1"},
40         {PROTOCOL_LANMAN2,      "LANMAN2.1"},
41         {PROTOCOL_LANMAN2,      "Samba"},
42         {PROTOCOL_NT1,          "NT LANMAN 1.0"},
43         {PROTOCOL_NT1,          "NT LM 0.12"},
44 };
45
46 #define STAR_SMBSERVER "*SMBSERVER"
47
48 /**
49  * Set the user session key for a connection
50  * @param cli The cli structure to add it too
51  * @param session_key The session key used.  (A copy of this is taken for the cli struct)
52  *
53  */
54
55 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key) 
56 {
57         cli->user_session_key = data_blob(session_key.data, session_key.length);
58 }
59
60 /****************************************************************************
61  Do an old lanman2 style session setup.
62 ****************************************************************************/
63
64 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
65                                           const char *user, 
66                                           const char *pass, size_t passlen,
67                                           const char *workgroup)
68 {
69         DATA_BLOB session_key = data_blob_null;
70         DATA_BLOB lm_response = data_blob_null;
71         NTSTATUS status;
72         fstring pword;
73         char *p;
74
75         if (passlen > sizeof(pword)-1) {
76                 return NT_STATUS_INVALID_PARAMETER;
77         }
78
79         /* LANMAN servers predate NT status codes and Unicode and ignore those 
80            smb flags so we must disable the corresponding default capabilities  
81            that would otherwise cause the Unicode and NT Status flags to be
82            set (and even returned by the server) */
83
84         cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
85
86         /* if in share level security then don't send a password now */
87         if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
88                 passlen = 0;
89
90         if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
91                 /* Encrypted mode needed, and non encrypted password supplied. */
92                 lm_response = data_blob(NULL, 24);
93                 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
94                         DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
95                         return NT_STATUS_ACCESS_DENIED;
96                 }
97         } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
98                 /* Encrypted mode needed, and encrypted password supplied. */
99                 lm_response = data_blob(pass, passlen);
100         } else if (passlen > 0) {
101                 /* Plaintext mode needed, assume plaintext supplied. */
102                 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
103                 lm_response = data_blob(pass, passlen);
104         }
105
106         /* send a session setup command */
107         memset(cli->outbuf,'\0',smb_size);
108         cli_set_message(cli->outbuf,10, 0, True);
109         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
110         cli_setup_packet(cli);
111
112         SCVAL(cli->outbuf,smb_vwv0,0xFF);
113         SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
114         SSVAL(cli->outbuf,smb_vwv3,2);
115         SSVAL(cli->outbuf,smb_vwv4,1);
116         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
117         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
118
119         p = smb_buf(cli->outbuf);
120         memcpy(p,lm_response.data,lm_response.length);
121         p += lm_response.length;
122         p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
123         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
124         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
125         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
126         cli_setup_bcc(cli, p);
127
128         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
129                 return cli_nt_error(cli);
130         }
131
132         show_msg(cli->inbuf);
133
134         if (cli_is_error(cli)) {
135                 return cli_nt_error(cli);
136         }
137
138         /* use the returned vuid from now on */
139         cli->vuid = SVAL(cli->inbuf,smb_uid);   
140         status = cli_set_username(cli, user);
141         if (!NT_STATUS_IS_OK(status)) {
142                 return status;
143         }
144
145         if (session_key.data) {
146                 /* Have plaintext orginal */
147                 cli_set_session_key(cli, session_key);
148         }
149
150         return NT_STATUS_OK;
151 }
152
153 /****************************************************************************
154  Work out suitable capabilities to offer the server.
155 ****************************************************************************/
156
157 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
158 {
159         uint32 capabilities = CAP_NT_SMBS;
160
161         if (!cli->force_dos_errors)
162                 capabilities |= CAP_STATUS32;
163
164         if (cli->use_level_II_oplocks)
165                 capabilities |= CAP_LEVEL_II_OPLOCKS;
166
167         capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
168         return capabilities;
169 }
170
171 /****************************************************************************
172  Do a NT1 guest session setup.
173 ****************************************************************************/
174
175 struct cli_session_setup_guest_state {
176         struct cli_state *cli;
177         uint16_t vwv[16];
178         struct iovec bytes;
179 };
180
181 static void cli_session_setup_guest_done(struct tevent_req *subreq);
182
183 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
184                                                   struct event_context *ev,
185                                                   struct cli_state *cli,
186                                                   struct tevent_req **psmbreq)
187 {
188         struct tevent_req *req, *subreq;
189         struct cli_session_setup_guest_state *state;
190         uint16_t *vwv;
191         uint8_t *bytes;
192
193         req = tevent_req_create(mem_ctx, &state,
194                                 struct cli_session_setup_guest_state);
195         if (req == NULL) {
196                 return NULL;
197         }
198         state->cli = cli;
199         vwv = state->vwv;
200
201         SCVAL(vwv+0, 0, 0xFF);
202         SCVAL(vwv+0, 1, 0);
203         SSVAL(vwv+1, 0, 0);
204         SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
205         SSVAL(vwv+3, 0, 2);
206         SSVAL(vwv+4, 0, cli->pid);
207         SIVAL(vwv+5, 0, cli->sesskey);
208         SSVAL(vwv+7, 0, 0);
209         SSVAL(vwv+8, 0, 0);
210         SSVAL(vwv+9, 0, 0);
211         SSVAL(vwv+10, 0, 0);
212         SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
213
214         bytes = talloc_array(state, uint8_t, 0);
215
216         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "",  1, /* username */
217                                    NULL);
218         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
219                                    NULL);
220         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
221         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
222
223         if (bytes == NULL) {
224                 TALLOC_FREE(req);
225                 return NULL;
226         }
227
228         state->bytes.iov_base = (void *)bytes;
229         state->bytes.iov_len = talloc_get_size(bytes);
230
231         subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
232                                     1, &state->bytes);
233         if (subreq == NULL) {
234                 TALLOC_FREE(req);
235                 return NULL;
236         }
237         tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
238         *psmbreq = subreq;
239         return req;
240 }
241
242 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
243                                                 struct event_context *ev,
244                                                 struct cli_state *cli)
245 {
246         struct tevent_req *req, *subreq;
247         NTSTATUS status;
248
249         req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
250         if (req == NULL) {
251                 return NULL;
252         }
253
254         status = cli_smb_req_send(subreq);
255         if (NT_STATUS_IS_OK(status)) {
256                 tevent_req_nterror(req, status);
257                 return tevent_req_post(req, ev);
258         }
259         return req;
260 }
261
262 static void cli_session_setup_guest_done(struct tevent_req *subreq)
263 {
264         struct tevent_req *req = tevent_req_callback_data(
265                 subreq, struct tevent_req);
266         struct cli_session_setup_guest_state *state = tevent_req_data(
267                 req, struct cli_session_setup_guest_state);
268         struct cli_state *cli = state->cli;
269         uint32_t num_bytes;
270         uint8_t *in;
271         char *inbuf;
272         uint8_t *bytes;
273         uint8_t *p;
274         NTSTATUS status;
275
276         status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
277                               &num_bytes, &bytes);
278         TALLOC_FREE(subreq);
279         if (!NT_STATUS_IS_OK(status)) {
280                 tevent_req_nterror(req, status);
281                 return;
282         }
283
284         inbuf = (char *)in;
285         p = bytes;
286
287         cli->vuid = SVAL(inbuf, smb_uid);
288
289         p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
290                          bytes+num_bytes-p, STR_TERMINATE);
291         p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
292                          bytes+num_bytes-p, STR_TERMINATE);
293         p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
294                          bytes+num_bytes-p, STR_TERMINATE);
295
296         if (strstr(cli->server_type, "Samba")) {
297                 cli->is_samba = True;
298         }
299
300         status = cli_set_username(cli, "");
301         if (!NT_STATUS_IS_OK(status)) {
302                 tevent_req_nterror(req, status);
303                 return;
304         }
305         tevent_req_done(req);
306 }
307
308 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
309 {
310         return tevent_req_simple_recv_ntstatus(req);
311 }
312
313 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
314 {
315         TALLOC_CTX *frame = talloc_stackframe();
316         struct event_context *ev;
317         struct tevent_req *req;
318         NTSTATUS status = NT_STATUS_OK;
319
320         if (cli_has_async_calls(cli)) {
321                 /*
322                  * Can't use sync call while an async call is in flight
323                  */
324                 status = NT_STATUS_INVALID_PARAMETER;
325                 goto fail;
326         }
327
328         ev = event_context_init(frame);
329         if (ev == NULL) {
330                 status = NT_STATUS_NO_MEMORY;
331                 goto fail;
332         }
333
334         req = cli_session_setup_guest_send(frame, ev, cli);
335         if (req == NULL) {
336                 status = NT_STATUS_NO_MEMORY;
337                 goto fail;
338         }
339
340         if (!tevent_req_poll(req, ev)) {
341                 status = map_nt_error_from_unix(errno);
342                 goto fail;
343         }
344
345         status = cli_session_setup_guest_recv(req);
346  fail:
347         TALLOC_FREE(frame);
348         if (!NT_STATUS_IS_OK(status)) {
349                 cli_set_error(cli, status);
350         }
351         return status;
352 }
353
354 /****************************************************************************
355  Do a NT1 plaintext session setup.
356 ****************************************************************************/
357
358 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
359                                             const char *user, const char *pass,
360                                             const char *workgroup)
361 {
362         uint32 capabilities = cli_session_setup_capabilities(cli);
363         char *p;
364         NTSTATUS status;
365         fstring lanman;
366
367         fstr_sprintf( lanman, "Samba %s", samba_version_string());
368
369         memset(cli->outbuf, '\0', smb_size);
370         cli_set_message(cli->outbuf,13,0,True);
371         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
372         cli_setup_packet(cli);
373
374         SCVAL(cli->outbuf,smb_vwv0,0xFF);
375         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
376         SSVAL(cli->outbuf,smb_vwv3,2);
377         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
378         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
379         SSVAL(cli->outbuf,smb_vwv8,0);
380         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
381         p = smb_buf(cli->outbuf);
382
383         /* check wether to send the ASCII or UNICODE version of the password */
384
385         if ( (capabilities & CAP_UNICODE) == 0 ) {
386                 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
387                 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
388         }
389         else {
390                 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
391                  * the space taken by the unicode password to be one byte too
392                  * long (as we're on an odd byte boundary here). Reduce the
393                  * count by 1 to cope with this. Fixes smbclient against NetApp
394                  * servers which can't cope. Fix from
395                  * bryan.kolodziej@allenlund.com in bug #3840.
396                  */
397                 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
398                 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);        
399         }
400
401         p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
402         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
403         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
404         p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
405         cli_setup_bcc(cli, p);
406
407         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
408                 return cli_nt_error(cli);
409         }
410
411         show_msg(cli->inbuf);
412
413         if (cli_is_error(cli)) {
414                 return cli_nt_error(cli);
415         }
416
417         cli->vuid = SVAL(cli->inbuf,smb_uid);
418         p = smb_buf(cli->inbuf);
419         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
420                          -1, STR_TERMINATE);
421         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
422                          -1, STR_TERMINATE);
423         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
424                          -1, STR_TERMINATE);
425         status = cli_set_username(cli, user);
426         if (!NT_STATUS_IS_OK(status)) {
427                 return status;
428         }
429         if (strstr(cli->server_type, "Samba")) {
430                 cli->is_samba = True;
431         }
432
433         return NT_STATUS_OK;
434 }
435
436 /****************************************************************************
437    do a NT1 NTLM/LM encrypted session setup - for when extended security
438    is not negotiated.
439    @param cli client state to create do session setup on
440    @param user username
441    @param pass *either* cleartext password (passlen !=24) or LM response.
442    @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
443    @param workgroup The user's domain.
444 ****************************************************************************/
445
446 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user, 
447                                       const char *pass, size_t passlen,
448                                       const char *ntpass, size_t ntpasslen,
449                                       const char *workgroup)
450 {
451         uint32 capabilities = cli_session_setup_capabilities(cli);
452         DATA_BLOB lm_response = data_blob_null;
453         DATA_BLOB nt_response = data_blob_null;
454         DATA_BLOB session_key = data_blob_null;
455         NTSTATUS result;
456         char *p;
457         bool ok;
458
459         if (passlen == 0) {
460                 /* do nothing - guest login */
461         } else if (passlen != 24) {
462                 if (lp_client_ntlmv2_auth()) {
463                         DATA_BLOB server_chal;
464                         DATA_BLOB names_blob;
465                         server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); 
466
467                         /* note that the 'workgroup' here is a best guess - we don't know
468                            the server's domain at this point.  The 'server name' is also
469                            dodgy... 
470                         */
471                         names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
472
473                         if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal, 
474                                               &names_blob,
475                                               &lm_response, &nt_response, NULL, &session_key)) {
476                                 data_blob_free(&names_blob);
477                                 data_blob_free(&server_chal);
478                                 return NT_STATUS_ACCESS_DENIED;
479                         }
480                         data_blob_free(&names_blob);
481                         data_blob_free(&server_chal);
482
483                 } else {
484                         uchar nt_hash[16];
485                         E_md4hash(pass, nt_hash);
486
487 #ifdef LANMAN_ONLY
488                         nt_response = data_blob_null;
489 #else
490                         nt_response = data_blob(NULL, 24);
491                         SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
492 #endif
493                         /* non encrypted password supplied. Ignore ntpass. */
494                         if (lp_client_lanman_auth()) {
495                                 lm_response = data_blob(NULL, 24);
496                                 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
497                                         /* Oops, the LM response is invalid, just put 
498                                            the NT response there instead */
499                                         data_blob_free(&lm_response);
500                                         lm_response = data_blob(nt_response.data, nt_response.length);
501                                 }
502                         } else {
503                                 /* LM disabled, place NT# in LM field instead */
504                                 lm_response = data_blob(nt_response.data, nt_response.length);
505                         }
506
507                         session_key = data_blob(NULL, 16);
508 #ifdef LANMAN_ONLY
509                         E_deshash(pass, session_key.data);
510                         memset(&session_key.data[8], '\0', 8);
511 #else
512                         SMBsesskeygen_ntv1(nt_hash, session_key.data);
513 #endif
514                 }
515                 cli_temp_set_signing(cli);
516         } else {
517                 /* pre-encrypted password supplied.  Only used for 
518                    security=server, can't do
519                    signing because we don't have original key */
520
521                 lm_response = data_blob(pass, passlen);
522                 nt_response = data_blob(ntpass, ntpasslen);
523         }
524
525         /* send a session setup command */
526         memset(cli->outbuf,'\0',smb_size);
527
528         cli_set_message(cli->outbuf,13,0,True);
529         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
530         cli_setup_packet(cli);
531
532         SCVAL(cli->outbuf,smb_vwv0,0xFF);
533         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
534         SSVAL(cli->outbuf,smb_vwv3,2);
535         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
536         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
537         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
538         SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
539         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
540         p = smb_buf(cli->outbuf);
541         if (lm_response.length) {
542                 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
543         }
544         if (nt_response.length) {
545                 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
546         }
547         p += clistr_push(cli, p, user, -1, STR_TERMINATE);
548
549         /* Upper case here might help some NTLMv2 implementations */
550         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
551         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
552         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
553         cli_setup_bcc(cli, p);
554
555         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
556                 result = cli_nt_error(cli);
557                 goto end;
558         }
559
560         /* show_msg(cli->inbuf); */
561
562         if (cli_is_error(cli)) {
563                 result = cli_nt_error(cli);
564                 goto end;
565         }
566
567 #ifdef LANMAN_ONLY
568         ok = cli_simple_set_signing(cli, session_key, lm_response);
569 #else
570         ok = cli_simple_set_signing(cli, session_key, nt_response);
571 #endif
572         if (ok) {
573                 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
574                         result = NT_STATUS_ACCESS_DENIED;
575                         goto end;
576                 }
577         }
578
579         /* use the returned vuid from now on */
580         cli->vuid = SVAL(cli->inbuf,smb_uid);
581
582         p = smb_buf(cli->inbuf);
583         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
584                          -1, STR_TERMINATE);
585         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
586                          -1, STR_TERMINATE);
587         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
588                          -1, STR_TERMINATE);
589
590         if (strstr(cli->server_type, "Samba")) {
591                 cli->is_samba = True;
592         }
593
594         result = cli_set_username(cli, user);
595         if (!NT_STATUS_IS_OK(result)) {
596                 goto end;
597         }
598
599         if (session_key.data) {
600                 /* Have plaintext orginal */
601                 cli_set_session_key(cli, session_key);
602         }
603
604         result = NT_STATUS_OK;
605 end:    
606         data_blob_free(&lm_response);
607         data_blob_free(&nt_response);
608         data_blob_free(&session_key);
609         return result;
610 }
611
612 /* The following is calculated from :
613  * (smb_size-4) = 35
614  * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
615  * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
616  * end of packet.
617  */
618
619 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
620
621 struct cli_sesssetup_blob_state {
622         struct tevent_context *ev;
623         struct cli_state *cli;
624         DATA_BLOB blob;
625         uint16_t max_blob_size;
626         uint16_t vwv[12];
627         uint8_t *buf;
628
629         NTSTATUS status;
630         char *inbuf;
631         DATA_BLOB ret_blob;
632 };
633
634 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
635                                     struct tevent_req **psubreq);
636 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
637
638 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
639                                                   struct tevent_context *ev,
640                                                   struct cli_state *cli,
641                                                   DATA_BLOB blob)
642 {
643         struct tevent_req *req, *subreq;
644         struct cli_sesssetup_blob_state *state;
645
646         req = tevent_req_create(mem_ctx, &state,
647                                 struct cli_sesssetup_blob_state);
648         if (req == NULL) {
649                 return NULL;
650         }
651         state->ev = ev;
652         state->blob = blob;
653         state->cli = cli;
654
655         if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
656                 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
657                           "(was %u, need minimum %u)\n",
658                           (unsigned int)cli->max_xmit,
659                           BASE_SESSSETUP_BLOB_PACKET_SIZE));
660                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
661                 return tevent_req_post(req, ev);
662         }
663         state->max_blob_size =
664                 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
665
666         if (!cli_sesssetup_blob_next(state, &subreq)) {
667                 tevent_req_nomem(NULL, req);
668                 return tevent_req_post(req, ev);
669         }
670         tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
671         return req;
672 }
673
674 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
675                                     struct tevent_req **psubreq)
676 {
677         struct tevent_req *subreq;
678         uint16_t thistime;
679
680         SCVAL(state->vwv+0, 0, 0xFF);
681         SCVAL(state->vwv+0, 1, 0);
682         SSVAL(state->vwv+1, 0, 0);
683         SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
684         SSVAL(state->vwv+3, 0, 2);
685         SSVAL(state->vwv+4, 0, 1);
686         SIVAL(state->vwv+5, 0, 0);
687
688         thistime = MIN(state->blob.length, state->max_blob_size);
689         SSVAL(state->vwv+7, 0, thistime);
690
691         SSVAL(state->vwv+8, 0, 0);
692         SSVAL(state->vwv+9, 0, 0);
693         SIVAL(state->vwv+10, 0,
694               cli_session_setup_capabilities(state->cli)
695               | CAP_EXTENDED_SECURITY);
696
697         state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
698                                               thistime);
699         if (state->buf == NULL) {
700                 return false;
701         }
702         state->blob.data += thistime;
703         state->blob.length -= thistime;
704
705         state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
706                                         "Unix", 5, NULL);
707         state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
708                                         "Samba", 6, NULL);
709         if (state->buf == NULL) {
710                 return false;
711         }
712         subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
713                               12, state->vwv,
714                               talloc_get_size(state->buf), state->buf);
715         if (subreq == NULL) {
716                 return false;
717         }
718         *psubreq = subreq;
719         return true;
720 }
721
722 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
723 {
724         struct tevent_req *req = tevent_req_callback_data(
725                 subreq, struct tevent_req);
726         struct cli_sesssetup_blob_state *state = tevent_req_data(
727                 req, struct cli_sesssetup_blob_state);
728         struct cli_state *cli = state->cli;
729         uint8_t wct;
730         uint16_t *vwv;
731         uint32_t num_bytes;
732         uint8_t *bytes;
733         NTSTATUS status;
734         uint8_t *p;
735         uint16_t blob_length;
736         uint8_t *inbuf;
737
738         status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
739                               &num_bytes, &bytes);
740         TALLOC_FREE(subreq);
741         if (!NT_STATUS_IS_OK(status)
742             && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
743                 tevent_req_nterror(req, status);
744                 return;
745         }
746
747         state->status = status;
748         TALLOC_FREE(state->buf);
749
750         state->inbuf = (char *)inbuf;
751         cli->vuid = SVAL(state->inbuf, smb_uid);
752
753         blob_length = SVAL(vwv+3, 0);
754         if (blob_length > num_bytes) {
755                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
756                 return;
757         }
758         state->ret_blob = data_blob_const(bytes, blob_length);
759
760         p = bytes + blob_length;
761
762         p += clistr_pull(state->inbuf, cli->server_os,
763                          (char *)p, sizeof(fstring),
764                          bytes+num_bytes-p, STR_TERMINATE);
765         p += clistr_pull(state->inbuf, cli->server_type,
766                          (char *)p, sizeof(fstring),
767                          bytes+num_bytes-p, STR_TERMINATE);
768         p += clistr_pull(state->inbuf, cli->server_domain,
769                          (char *)p, sizeof(fstring),
770                          bytes+num_bytes-p, STR_TERMINATE);
771
772         if (strstr(cli->server_type, "Samba")) {
773                 cli->is_samba = True;
774         }
775
776         if (state->blob.length != 0) {
777                 /*
778                  * More to send
779                  */
780                 if (!cli_sesssetup_blob_next(state, &subreq)) {
781                         tevent_req_nomem(NULL, req);
782                         return;
783                 }
784                 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
785                 return;
786         }
787         tevent_req_done(req);
788 }
789
790 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
791                                         TALLOC_CTX *mem_ctx,
792                                         DATA_BLOB *pblob,
793                                         char **pinbuf)
794 {
795         struct cli_sesssetup_blob_state *state = tevent_req_data(
796                 req, struct cli_sesssetup_blob_state);
797         NTSTATUS status;
798         char *inbuf;
799
800         if (tevent_req_is_nterror(req, &status)) {
801                 state->cli->vuid = 0;
802                 return status;
803         }
804
805         inbuf = talloc_move(mem_ctx, &state->inbuf);
806         if (pblob != NULL) {
807                 *pblob = state->ret_blob;
808         }
809         if (pinbuf != NULL) {
810                 *pinbuf = inbuf;
811         }
812         /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
813         return state->status;
814 }
815
816 #ifdef HAVE_KRB5
817
818 /****************************************************************************
819  Use in-memory credentials cache
820 ****************************************************************************/
821
822 static void use_in_memory_ccache(void) {
823         setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
824 }
825
826 /****************************************************************************
827  Do a spnego/kerberos encrypted session setup.
828 ****************************************************************************/
829
830 struct cli_session_setup_kerberos_state {
831         struct cli_state *cli;
832         DATA_BLOB negTokenTarg;
833         DATA_BLOB session_key_krb5;
834         ADS_STATUS ads_status;
835 };
836
837 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
838
839 static struct tevent_req *cli_session_setup_kerberos_send(
840         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
841         const char *principal, const char *workgroup)
842 {
843         struct tevent_req *req, *subreq;
844         struct cli_session_setup_kerberos_state *state;
845         int rc;
846
847         DEBUG(2,("Doing kerberos session setup\n"));
848
849         req = tevent_req_create(mem_ctx, &state,
850                                 struct cli_session_setup_kerberos_state);
851         if (req == NULL) {
852                 return NULL;
853         }
854         state->cli = cli;
855         state->ads_status = ADS_SUCCESS;
856
857         cli_temp_set_signing(cli);
858
859         /*
860          * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
861          * we have to acquire a ticket. To be fixed later :-)
862          */
863         rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
864                                      &state->session_key_krb5, 0, NULL);
865         if (rc) {
866                 DEBUG(1, ("cli_session_setup_kerberos: "
867                           "spnego_gen_krb5_negTokenInit failed: %s\n",
868                           error_message(rc)));
869                 state->ads_status = ADS_ERROR_KRB5(rc);
870                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
871                 return tevent_req_post(req, ev);
872         }
873
874 #if 0
875         file_save("negTokenTarg.dat", state->negTokenTarg.data,
876                   state->negTokenTarg.length);
877 #endif
878
879         subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
880         if (tevent_req_nomem(subreq, req)) {
881                 return tevent_req_post(req, ev);
882         }
883         tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
884         return req;
885 }
886
887 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
888 {
889         struct tevent_req *req = tevent_req_callback_data(
890                 subreq, struct tevent_req);
891         struct cli_session_setup_kerberos_state *state = tevent_req_data(
892                 req, struct cli_session_setup_kerberos_state);
893         char *inbuf = NULL;
894         NTSTATUS status;
895
896         status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
897         if (!NT_STATUS_IS_OK(status)) {
898                 TALLOC_FREE(subreq);
899                 tevent_req_nterror(req, status);
900                 return;
901         }
902
903         cli_set_session_key(state->cli, state->session_key_krb5);
904
905         if (cli_simple_set_signing(state->cli, state->session_key_krb5,
906                                    data_blob_null)
907             && !cli_check_sign_mac(state->cli, inbuf, 1)) {
908                 TALLOC_FREE(subreq);
909                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
910                 return;
911         }
912         TALLOC_FREE(subreq);
913         tevent_req_done(req);
914 }
915
916 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
917 {
918         struct cli_session_setup_kerberos_state *state = tevent_req_data(
919                 req, struct cli_session_setup_kerberos_state);
920         NTSTATUS status;
921
922         if (tevent_req_is_nterror(req, &status)) {
923                 return ADS_ERROR_NT(status);
924         }
925         return state->ads_status;
926 }
927
928 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
929                                              const char *principal,
930                                              const char *workgroup)
931 {
932         struct tevent_context *ev;
933         struct tevent_req *req;
934         ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
935
936         if (cli_has_async_calls(cli)) {
937                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
938         }
939         ev = tevent_context_init(talloc_tos());
940         if (ev == NULL) {
941                 goto fail;
942         }
943         req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
944                                               workgroup);
945         if (req == NULL) {
946                 goto fail;
947         }
948         if (!tevent_req_poll(req, ev)) {
949                 status = ADS_ERROR_SYSTEM(errno);
950                 goto fail;
951         }
952         status = cli_session_setup_kerberos_recv(req);
953 fail:
954         TALLOC_FREE(ev);
955         return status;
956 }
957 #endif  /* HAVE_KRB5 */
958
959 /****************************************************************************
960  Do a spnego/NTLMSSP encrypted session setup.
961 ****************************************************************************/
962
963 struct cli_session_setup_ntlmssp_state {
964         struct tevent_context *ev;
965         struct cli_state *cli;
966         struct ntlmssp_state *ntlmssp_state;
967         int turn;
968         DATA_BLOB blob_out;
969 };
970
971 static int cli_session_setup_ntlmssp_state_destructor(
972         struct cli_session_setup_ntlmssp_state *state)
973 {
974         if (state->ntlmssp_state != NULL) {
975                 TALLOC_FREE(state->ntlmssp_state);
976         }
977         return 0;
978 }
979
980 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
981
982 static struct tevent_req *cli_session_setup_ntlmssp_send(
983         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
984         const char *user, const char *pass, const char *domain)
985 {
986         struct tevent_req *req, *subreq;
987         struct cli_session_setup_ntlmssp_state *state;
988         NTSTATUS status;
989         DATA_BLOB blob_out;
990         const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
991
992         req = tevent_req_create(mem_ctx, &state,
993                                 struct cli_session_setup_ntlmssp_state);
994         if (req == NULL) {
995                 return NULL;
996         }
997         state->ev = ev;
998         state->cli = cli;
999         state->turn = 1;
1000
1001         state->ntlmssp_state = NULL;
1002         talloc_set_destructor(
1003                 state, cli_session_setup_ntlmssp_state_destructor);
1004
1005         cli_temp_set_signing(cli);
1006
1007         status = ntlmssp_client_start(state,
1008                                       global_myname(),
1009                                       lp_workgroup(),
1010                                       lp_client_ntlmv2_auth(),
1011                                       &state->ntlmssp_state);
1012         if (!NT_STATUS_IS_OK(status)) {
1013                 goto fail;
1014         }
1015         ntlmssp_want_feature(state->ntlmssp_state,
1016                              NTLMSSP_FEATURE_SESSION_KEY);
1017         if (cli->use_ccache) {
1018                 ntlmssp_want_feature(state->ntlmssp_state,
1019                                      NTLMSSP_FEATURE_CCACHE);
1020         }
1021         status = ntlmssp_set_username(state->ntlmssp_state, user);
1022         if (!NT_STATUS_IS_OK(status)) {
1023                 goto fail;
1024         }
1025         status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1026         if (!NT_STATUS_IS_OK(status)) {
1027                 goto fail;
1028         }
1029         status = ntlmssp_set_password(state->ntlmssp_state, pass);
1030         if (!NT_STATUS_IS_OK(status)) {
1031                 goto fail;
1032         }
1033         status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1034                                 &blob_out);
1035         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1036                 goto fail;
1037         }
1038
1039         state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1040         data_blob_free(&blob_out);
1041
1042         subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1043         if (tevent_req_nomem(subreq, req)) {
1044                 return tevent_req_post(req, ev);
1045         }
1046         tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1047         return req;
1048 fail:
1049         tevent_req_nterror(req, status);
1050         return tevent_req_post(req, ev);
1051 }
1052
1053 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1054 {
1055         struct tevent_req *req = tevent_req_callback_data(
1056                 subreq, struct tevent_req);
1057         struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1058                 req, struct cli_session_setup_ntlmssp_state);
1059         DATA_BLOB blob_in, msg_in, blob_out;
1060         char *inbuf = NULL;
1061         bool parse_ret;
1062         NTSTATUS status;
1063
1064         status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1065                                          &inbuf);
1066         TALLOC_FREE(subreq);
1067         data_blob_free(&state->blob_out);
1068
1069         if (NT_STATUS_IS_OK(status)) {
1070                 if (state->cli->server_domain[0] == '\0') {
1071                         fstrcpy(state->cli->server_domain,
1072                                 state->ntlmssp_state->server.netbios_domain);
1073                 }
1074                 cli_set_session_key(
1075                         state->cli, state->ntlmssp_state->session_key);
1076
1077                 if (cli_simple_set_signing(
1078                             state->cli, state->ntlmssp_state->session_key,
1079                             data_blob_null)
1080                     && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1081                         TALLOC_FREE(subreq);
1082                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1083                         return;
1084                 }
1085                 TALLOC_FREE(subreq);
1086                 TALLOC_FREE(state->ntlmssp_state);
1087                 tevent_req_done(req);
1088                 return;
1089         }
1090         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1091                 tevent_req_nterror(req, status);
1092                 return;
1093         }
1094
1095         if (blob_in.length == 0) {
1096                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1097                 return;
1098         }
1099
1100         if ((state->turn == 1)
1101             && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1102                 DATA_BLOB tmp_blob = data_blob_null;
1103                 /* the server might give us back two challenges */
1104                 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1105                                                    &tmp_blob);
1106                 data_blob_free(&tmp_blob);
1107         } else {
1108                 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1109                                                        OID_NTLMSSP, &msg_in);
1110         }
1111         state->turn += 1;
1112
1113         if (!parse_ret) {
1114                 DEBUG(3,("Failed to parse auth response\n"));
1115                 if (NT_STATUS_IS_OK(status)
1116                     || NT_STATUS_EQUAL(status,
1117                                        NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1118                         tevent_req_nterror(
1119                                 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1120                         return;
1121                 }
1122         }
1123
1124         status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1125
1126         if (!NT_STATUS_IS_OK(status)
1127             && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1128                 TALLOC_FREE(subreq);
1129                 TALLOC_FREE(state->ntlmssp_state);
1130                 tevent_req_nterror(req, status);
1131                 return;
1132         }
1133
1134         state->blob_out = spnego_gen_auth(state, blob_out);
1135         TALLOC_FREE(subreq);
1136         if (tevent_req_nomem(state->blob_out.data, req)) {
1137                 return;
1138         }
1139
1140         subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1141                                          state->blob_out);
1142         if (tevent_req_nomem(subreq, req)) {
1143                 return;
1144         }
1145         tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1146 }
1147
1148 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1149 {
1150         struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1151                 req, struct cli_session_setup_ntlmssp_state);
1152         NTSTATUS status;
1153
1154         if (tevent_req_is_nterror(req, &status)) {
1155                 state->cli->vuid = 0;
1156                 return status;
1157         }
1158         return NT_STATUS_OK;
1159 }
1160
1161 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1162                                           const char *user,
1163                                           const char *pass,
1164                                           const char *domain)
1165 {
1166         struct tevent_context *ev;
1167         struct tevent_req *req;
1168         NTSTATUS status = NT_STATUS_NO_MEMORY;
1169
1170         if (cli_has_async_calls(cli)) {
1171                 return NT_STATUS_INVALID_PARAMETER;
1172         }
1173         ev = tevent_context_init(talloc_tos());
1174         if (ev == NULL) {
1175                 goto fail;
1176         }
1177         req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1178         if (req == NULL) {
1179                 goto fail;
1180         }
1181         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1182                 goto fail;
1183         }
1184         status = cli_session_setup_ntlmssp_recv(req);
1185 fail:
1186         TALLOC_FREE(ev);
1187         if (!NT_STATUS_IS_OK(status)) {
1188                 cli_set_error(cli, status);
1189         }
1190         return status;
1191 }
1192
1193 /****************************************************************************
1194  Do a spnego encrypted session setup.
1195
1196  user_domain: The shortname of the domain the user/machine is a member of.
1197  dest_realm: The realm we're connecting to, if NULL we use our default realm.
1198 ****************************************************************************/
1199
1200 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
1201                               const char *pass, const char *user_domain,
1202                               const char * dest_realm)
1203 {
1204         char *principal = NULL;
1205         char *OIDs[ASN1_MAX_OIDS];
1206         int i;
1207         DATA_BLOB blob;
1208         const char *p = NULL;
1209         char *account = NULL;
1210         NTSTATUS status;
1211
1212         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1213
1214         /* the server might not even do spnego */
1215         if (cli->secblob.length <= 16) {
1216                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1217                 goto ntlmssp;
1218         }
1219
1220 #if 0
1221         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1222 #endif
1223
1224         /* there is 16 bytes of GUID before the real spnego packet starts */
1225         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1226
1227         /* The server sent us the first part of the SPNEGO exchange in the
1228          * negprot reply. It is WRONG to depend on the principal sent in the
1229          * negprot reply, but right now we do it. If we don't receive one,
1230          * we try to best guess, then fall back to NTLM.  */
1231         if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL)) {
1232                 data_blob_free(&blob);
1233                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1234         }
1235         data_blob_free(&blob);
1236
1237         /* make sure the server understands kerberos */
1238         for (i=0;OIDs[i];i++) {
1239                 if (i == 0)
1240                         DEBUG(3,("got OID=%s\n", OIDs[i]));
1241                 else
1242                         DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1243                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1244                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1245                         cli->got_kerberos_mechanism = True;
1246                 }
1247                 talloc_free(OIDs[i]);
1248         }
1249
1250         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1251
1252         status = cli_set_username(cli, user);
1253         if (!NT_STATUS_IS_OK(status)) {
1254                 TALLOC_FREE(principal);
1255                 return ADS_ERROR_NT(status);
1256         }
1257
1258 #ifdef HAVE_KRB5
1259         /* If password is set we reauthenticate to kerberos server
1260          * and do not store results */
1261
1262         if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1263                 ADS_STATUS rc;
1264
1265                 if (pass && *pass) {
1266                         int ret;
1267
1268                         use_in_memory_ccache();
1269                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1270
1271                         if (ret){
1272                                 TALLOC_FREE(principal);
1273                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1274                                 if (cli->fallback_after_kerberos)
1275                                         goto ntlmssp;
1276                                 return ADS_ERROR_KRB5(ret);
1277                         }
1278                 }
1279
1280                 /* If we get a bad principal, try to guess it if
1281                    we have a valid host NetBIOS name.
1282                  */
1283                 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1284                         TALLOC_FREE(principal);
1285                 }
1286
1287                 if (principal == NULL &&
1288                         !is_ipaddress(cli->desthost) &&
1289                         !strequal(STAR_SMBSERVER,
1290                                 cli->desthost)) {
1291                         char *realm = NULL;
1292                         char *machine = NULL;
1293                         char *host = NULL;
1294                         DEBUG(3,("cli_session_setup_spnego: got a "
1295                                 "bad server principal, trying to guess ...\n"));
1296
1297                         host = strchr_m(cli->desthost, '.');
1298                         if (host) {
1299                                 /* We had a '.' in the name. */
1300                                 machine = SMB_STRNDUP(cli->desthost,
1301                                         host - cli->desthost);
1302                         } else {
1303                                 machine = SMB_STRDUP(cli->desthost);
1304                         }
1305                         if (machine == NULL) {
1306                                 TALLOC_FREE(principal);
1307                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1308                         }
1309
1310                         if (dest_realm) {
1311                                 realm = SMB_STRDUP(dest_realm);
1312                                 strupper_m(realm);
1313                         } else {
1314                                 if (host) {
1315                                         /* DNS name. */
1316                                         realm = kerberos_get_realm_from_hostname(cli->desthost);
1317                                 } else {
1318                                         /* NetBIOS name - use our realm. */
1319                                         realm = kerberos_get_default_realm_from_ccache();
1320                                 }
1321                         }
1322
1323                         if (realm && *realm) {
1324                                 if (host) {
1325                                         /* DNS name. */
1326                                         principal = talloc_asprintf(talloc_tos(),
1327                                                         "cifs/%s@%s",
1328                                                         cli->desthost,
1329                                                         realm);
1330                                 } else {
1331                                         /* NetBIOS name, use machine account. */
1332                                         principal = talloc_asprintf(talloc_tos(),
1333                                                         "%s$@%s",
1334                                                         machine,
1335                                                         realm);
1336                                 }
1337                                 if (!principal) {
1338                                         SAFE_FREE(machine);
1339                                         SAFE_FREE(realm);
1340                                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1341                                 }
1342                                 DEBUG(3,("cli_session_setup_spnego: guessed "
1343                                         "server principal=%s\n",
1344                                         principal ? principal : "<null>"));
1345                         }
1346                         SAFE_FREE(machine);
1347                         SAFE_FREE(realm);
1348                 }
1349
1350                 if (principal) {
1351                         rc = cli_session_setup_kerberos(cli, principal,
1352                                 dest_realm);
1353                         if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1354                                 TALLOC_FREE(principal);
1355                                 return rc;
1356                         }
1357                 }
1358         }
1359 #endif
1360
1361         TALLOC_FREE(principal);
1362
1363 ntlmssp:
1364
1365         account = talloc_strdup(talloc_tos(), user);
1366         if (!account) {
1367                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1368         }
1369
1370         /* when falling back to ntlmssp while authenticating with a machine
1371          * account strip off the realm - gd */
1372
1373         if ((p = strchr_m(user, '@')) != NULL) {
1374                 account[PTR_DIFF(p,user)] = '\0';
1375         }
1376
1377         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1378 }
1379
1380 /****************************************************************************
1381  Send a session setup. The username and workgroup is in UNIX character
1382  format and must be converted to DOS codepage format before sending. If the
1383  password is in plaintext, the same should be done.
1384 ****************************************************************************/
1385
1386 NTSTATUS cli_session_setup(struct cli_state *cli,
1387                            const char *user,
1388                            const char *pass, int passlen,
1389                            const char *ntpass, int ntpasslen,
1390                            const char *workgroup)
1391 {
1392         char *p;
1393         fstring user2;
1394
1395         if (user) {
1396                 fstrcpy(user2, user);
1397         } else {
1398                 user2[0] ='\0';
1399         }
1400
1401         if (!workgroup) {
1402                 workgroup = "";
1403         }
1404
1405         /* allow for workgroups as part of the username */
1406         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1407             (p=strchr_m(user2,*lp_winbind_separator()))) {
1408                 *p = 0;
1409                 user = p+1;
1410                 workgroup = user2;
1411         }
1412
1413         if (cli->protocol < PROTOCOL_LANMAN1) {
1414                 return NT_STATUS_OK;
1415         }
1416
1417         /* now work out what sort of session setup we are going to
1418            do. I have split this into separate functions to make the
1419            flow a bit easier to understand (tridge) */
1420
1421         /* if its an older server then we have to use the older request format */
1422
1423         if (cli->protocol < PROTOCOL_NT1) {
1424                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1425                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1426                                   " is disabled\n"));
1427                         return NT_STATUS_ACCESS_DENIED;
1428                 }
1429
1430                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1431                     !lp_client_plaintext_auth() && (*pass)) {
1432                         DEBUG(1, ("Server requested plaintext password but "
1433                                   "'client plaintext auth' is disabled\n"));
1434                         return NT_STATUS_ACCESS_DENIED;
1435                 }
1436
1437                 return cli_session_setup_lanman2(cli, user, pass, passlen,
1438                                                  workgroup);
1439         }
1440
1441         /* if no user is supplied then we have to do an anonymous connection.
1442            passwords are ignored */
1443
1444         if (!user || !*user)
1445                 return cli_session_setup_guest(cli);
1446
1447         /* if the server is share level then send a plaintext null
1448            password at this point. The password is sent in the tree
1449            connect */
1450
1451         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
1452                 return cli_session_setup_plaintext(cli, user, "", workgroup);
1453
1454         /* if the server doesn't support encryption then we have to use 
1455            plaintext. The second password is ignored */
1456
1457         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1458                 if (!lp_client_plaintext_auth() && (*pass)) {
1459                         DEBUG(1, ("Server requested plaintext password but "
1460                                   "'client plaintext auth' is disabled\n"));
1461                         return NT_STATUS_ACCESS_DENIED;
1462                 }
1463                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1464         }
1465
1466         /* if the server supports extended security then use SPNEGO */
1467
1468         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1469                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1470                                                              workgroup, NULL);
1471                 if (!ADS_ERR_OK(status)) {
1472                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1473                         return ads_ntstatus(status);
1474                 }
1475         } else {
1476                 NTSTATUS status;
1477
1478                 /* otherwise do a NT1 style session setup */
1479                 status = cli_session_setup_nt1(cli, user, pass, passlen,
1480                                                ntpass, ntpasslen, workgroup);
1481                 if (!NT_STATUS_IS_OK(status)) {
1482                         DEBUG(3,("cli_session_setup: NT1 session setup "
1483                                  "failed: %s\n", nt_errstr(status)));
1484                         return status;
1485                 }
1486         }
1487
1488         if (strstr(cli->server_type, "Samba")) {
1489                 cli->is_samba = True;
1490         }
1491
1492         return NT_STATUS_OK;
1493 }
1494
1495 /****************************************************************************
1496  Send a uloggoff.
1497 *****************************************************************************/
1498
1499 struct cli_ulogoff_state {
1500         struct cli_state *cli;
1501         uint16_t vwv[2];
1502 };
1503
1504 static void cli_ulogoff_done(struct tevent_req *subreq);
1505
1506 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1507                                     struct tevent_context *ev,
1508                                     struct cli_state *cli)
1509 {
1510         struct tevent_req *req, *subreq;
1511         struct cli_ulogoff_state *state;
1512
1513         req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1514         if (req == NULL) {
1515                 return NULL;
1516         }
1517         state->cli = cli;
1518
1519         SCVAL(state->vwv+0, 0, 0xFF);
1520         SCVAL(state->vwv+1, 0, 0);
1521         SSVAL(state->vwv+2, 0, 0);
1522
1523         subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
1524                               0, NULL);
1525         if (tevent_req_nomem(subreq, req)) {
1526                 return tevent_req_post(req, ev);
1527         }
1528         tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1529         return req;
1530 }
1531
1532 static void cli_ulogoff_done(struct tevent_req *subreq)
1533 {
1534         struct tevent_req *req = tevent_req_callback_data(
1535                 subreq, struct tevent_req);
1536         struct cli_ulogoff_state *state = tevent_req_data(
1537                 req, struct cli_ulogoff_state);
1538         NTSTATUS status;
1539
1540         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1541         if (!NT_STATUS_IS_OK(status)) {
1542                 tevent_req_nterror(req, status);
1543                 return;
1544         }
1545         state->cli->vuid = -1;
1546         tevent_req_done(req);
1547 }
1548
1549 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1550 {
1551         return tevent_req_simple_recv_ntstatus(req);
1552 }
1553
1554 NTSTATUS cli_ulogoff(struct cli_state *cli)
1555 {
1556         struct tevent_context *ev;
1557         struct tevent_req *req;
1558         NTSTATUS status = NT_STATUS_NO_MEMORY;
1559
1560         if (cli_has_async_calls(cli)) {
1561                 return NT_STATUS_INVALID_PARAMETER;
1562         }
1563         ev = tevent_context_init(talloc_tos());
1564         if (ev == NULL) {
1565                 goto fail;
1566         }
1567         req = cli_ulogoff_send(ev, ev, cli);
1568         if (req == NULL) {
1569                 goto fail;
1570         }
1571         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1572                 goto fail;
1573         }
1574         status = cli_ulogoff_recv(req);
1575 fail:
1576         TALLOC_FREE(ev);
1577         if (!NT_STATUS_IS_OK(status)) {
1578                 cli_set_error(cli, status);
1579         }
1580         return status;
1581 }
1582
1583 /****************************************************************************
1584  Send a tconX.
1585 ****************************************************************************/
1586
1587 struct cli_tcon_andx_state {
1588         struct cli_state *cli;
1589         uint16_t vwv[4];
1590         struct iovec bytes;
1591 };
1592
1593 static void cli_tcon_andx_done(struct tevent_req *subreq);
1594
1595 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1596                                         struct event_context *ev,
1597                                         struct cli_state *cli,
1598                                         const char *share, const char *dev,
1599                                         const char *pass, int passlen,
1600                                         struct tevent_req **psmbreq)
1601 {
1602         struct tevent_req *req, *subreq;
1603         struct cli_tcon_andx_state *state;
1604         fstring pword;
1605         uint16_t *vwv;
1606         char *tmp = NULL;
1607         uint8_t *bytes;
1608
1609         *psmbreq = NULL;
1610
1611         req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1612         if (req == NULL) {
1613                 return NULL;
1614         }
1615         state->cli = cli;
1616         vwv = state->vwv;
1617
1618         fstrcpy(cli->share, share);
1619
1620         /* in user level security don't send a password now */
1621         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1622                 passlen = 1;
1623                 pass = "";
1624         } else if (pass == NULL) {
1625                 DEBUG(1, ("Server not using user level security and no "
1626                           "password supplied.\n"));
1627                 goto access_denied;
1628         }
1629
1630         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1631             *pass && passlen != 24) {
1632                 if (!lp_client_lanman_auth()) {
1633                         DEBUG(1, ("Server requested LANMAN password "
1634                                   "(share-level security) but "
1635                                   "'client lanman auth' is disabled\n"));
1636                         goto access_denied;
1637                 }
1638
1639                 /*
1640                  * Non-encrypted passwords - convert to DOS codepage before
1641                  * encryption.
1642                  */
1643                 passlen = 24;
1644                 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1645         } else {
1646                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1647                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1648                    == 0) {
1649                         if (!lp_client_plaintext_auth() && (*pass)) {
1650                                 DEBUG(1, ("Server requested plaintext "
1651                                           "password but 'client plaintext "
1652                                           "auth' is disabled\n"));
1653                                 goto access_denied;
1654                         }
1655
1656                         /*
1657                          * Non-encrypted passwords - convert to DOS codepage
1658                          * before using.
1659                          */
1660                         passlen = clistr_push(cli, pword, pass, sizeof(pword),
1661                                               STR_TERMINATE);
1662                         if (passlen == -1) {
1663                                 DEBUG(1, ("clistr_push(pword) failed\n"));
1664                                 goto access_denied;
1665                         }
1666                 } else {
1667                         if (passlen) {
1668                                 memcpy(pword, pass, passlen);
1669                         }
1670                 }
1671         }
1672
1673         SCVAL(vwv+0, 0, 0xFF);
1674         SCVAL(vwv+0, 1, 0);
1675         SSVAL(vwv+1, 0, 0);
1676         SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1677         SSVAL(vwv+3, 0, passlen);
1678
1679         if (passlen) {
1680                 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1681         } else {
1682                 bytes = talloc_array(state, uint8_t, 0);
1683         }
1684
1685         /*
1686          * Add the sharename
1687          */
1688         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1689                                          cli->desthost, share);
1690         if (tmp == NULL) {
1691                 TALLOC_FREE(req);
1692                 return NULL;
1693         }
1694         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1695                                    NULL);
1696         TALLOC_FREE(tmp);
1697
1698         /*
1699          * Add the devicetype
1700          */
1701         tmp = talloc_strdup_upper(talloc_tos(), dev);
1702         if (tmp == NULL) {
1703                 TALLOC_FREE(req);
1704                 return NULL;
1705         }
1706         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1707         TALLOC_FREE(tmp);
1708
1709         if (bytes == NULL) {
1710                 TALLOC_FREE(req);
1711                 return NULL;
1712         }
1713
1714         state->bytes.iov_base = (void *)bytes;
1715         state->bytes.iov_len = talloc_get_size(bytes);
1716
1717         subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1718                                     1, &state->bytes);
1719         if (subreq == NULL) {
1720                 TALLOC_FREE(req);
1721                 return NULL;
1722         }
1723         tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1724         *psmbreq = subreq;
1725         return req;
1726
1727  access_denied:
1728         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1729         return tevent_req_post(req, ev);
1730 }
1731
1732 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1733                                       struct event_context *ev,
1734                                       struct cli_state *cli,
1735                                       const char *share, const char *dev,
1736                                       const char *pass, int passlen)
1737 {
1738         struct tevent_req *req, *subreq;
1739         NTSTATUS status;
1740
1741         req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1742                                    &subreq);
1743         if (req == NULL) {
1744                 return NULL;
1745         }
1746         if (subreq == NULL) {
1747                 return req;
1748         }
1749         status = cli_smb_req_send(subreq);
1750         if (!NT_STATUS_IS_OK(status)) {
1751                 tevent_req_nterror(req, status);
1752                 return tevent_req_post(req, ev);
1753         }
1754         return req;
1755 }
1756
1757 static void cli_tcon_andx_done(struct tevent_req *subreq)
1758 {
1759         struct tevent_req *req = tevent_req_callback_data(
1760                 subreq, struct tevent_req);
1761         struct cli_tcon_andx_state *state = tevent_req_data(
1762                 req, struct cli_tcon_andx_state);
1763         struct cli_state *cli = state->cli;
1764         uint8_t *in;
1765         char *inbuf;
1766         uint8_t wct;
1767         uint16_t *vwv;
1768         uint32_t num_bytes;
1769         uint8_t *bytes;
1770         NTSTATUS status;
1771
1772         status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
1773                               &num_bytes, &bytes);
1774         TALLOC_FREE(subreq);
1775         if (!NT_STATUS_IS_OK(status)) {
1776                 tevent_req_nterror(req, status);
1777                 return;
1778         }
1779
1780         inbuf = (char *)in;
1781
1782         clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1783                     STR_TERMINATE|STR_ASCII);
1784
1785         if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1786                 /* almost certainly win95 - enable bug fixes */
1787                 cli->win95 = True;
1788         }
1789
1790         /*
1791          * Make sure that we have the optional support 16-bit field. WCT > 2.
1792          * Avoids issues when connecting to Win9x boxes sharing files
1793          */
1794
1795         cli->dfsroot = false;
1796
1797         if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1798                 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1799         }
1800
1801         cli->cnum = SVAL(inbuf,smb_tid);
1802         tevent_req_done(req);
1803 }
1804
1805 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1806 {
1807         return tevent_req_simple_recv_ntstatus(req);
1808 }
1809
1810 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1811                        const char *dev, const char *pass, int passlen)
1812 {
1813         TALLOC_CTX *frame = talloc_stackframe();
1814         struct event_context *ev;
1815         struct tevent_req *req;
1816         NTSTATUS status = NT_STATUS_OK;
1817
1818         if (cli_has_async_calls(cli)) {
1819                 /*
1820                  * Can't use sync call while an async call is in flight
1821                  */
1822                 status = NT_STATUS_INVALID_PARAMETER;
1823                 goto fail;
1824         }
1825
1826         ev = event_context_init(frame);
1827         if (ev == NULL) {
1828                 status = NT_STATUS_NO_MEMORY;
1829                 goto fail;
1830         }
1831
1832         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1833         if (req == NULL) {
1834                 status = NT_STATUS_NO_MEMORY;
1835                 goto fail;
1836         }
1837
1838         if (!tevent_req_poll(req, ev)) {
1839                 status = map_nt_error_from_unix(errno);
1840                 goto fail;
1841         }
1842
1843         status = cli_tcon_andx_recv(req);
1844  fail:
1845         TALLOC_FREE(frame);
1846         if (!NT_STATUS_IS_OK(status)) {
1847                 cli_set_error(cli, status);
1848         }
1849         return status;
1850 }
1851
1852 /****************************************************************************
1853  Send a tree disconnect.
1854 ****************************************************************************/
1855
1856 struct cli_tdis_state {
1857         struct cli_state *cli;
1858 };
1859
1860 static void cli_tdis_done(struct tevent_req *subreq);
1861
1862 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
1863                                  struct tevent_context *ev,
1864                                  struct cli_state *cli)
1865 {
1866         struct tevent_req *req, *subreq;
1867         struct cli_tdis_state *state;
1868
1869         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
1870         if (req == NULL) {
1871                 return NULL;
1872         }
1873         state->cli = cli;
1874
1875         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
1876         if (tevent_req_nomem(subreq, req)) {
1877                 return tevent_req_post(req, ev);
1878         }
1879         tevent_req_set_callback(subreq, cli_tdis_done, req);
1880         return req;
1881 }
1882
1883 static void cli_tdis_done(struct tevent_req *subreq)
1884 {
1885         struct tevent_req *req = tevent_req_callback_data(
1886                 subreq, struct tevent_req);
1887         struct cli_tdis_state *state = tevent_req_data(
1888                 req, struct cli_tdis_state);
1889         NTSTATUS status;
1890
1891         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1892         TALLOC_FREE(subreq);
1893         if (!NT_STATUS_IS_OK(status)) {
1894                 tevent_req_nterror(req, status);
1895                 return;
1896         }
1897         state->cli->cnum = -1;
1898         tevent_req_done(req);
1899 }
1900
1901 NTSTATUS cli_tdis_recv(struct tevent_req *req)
1902 {
1903         return tevent_req_simple_recv_ntstatus(req);
1904 }
1905
1906 NTSTATUS cli_tdis(struct cli_state *cli)
1907 {
1908         struct tevent_context *ev;
1909         struct tevent_req *req;
1910         NTSTATUS status = NT_STATUS_NO_MEMORY;
1911
1912         if (cli_has_async_calls(cli)) {
1913                 return NT_STATUS_INVALID_PARAMETER;
1914         }
1915         ev = tevent_context_init(talloc_tos());
1916         if (ev == NULL) {
1917                 goto fail;
1918         }
1919         req = cli_tdis_send(ev, ev, cli);
1920         if (req == NULL) {
1921                 goto fail;
1922         }
1923         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1924                 goto fail;
1925         }
1926         status = cli_tdis_recv(req);
1927 fail:
1928         TALLOC_FREE(ev);
1929         if (!NT_STATUS_IS_OK(status)) {
1930                 cli_set_error(cli, status);
1931         }
1932         return status;
1933 }
1934
1935 /****************************************************************************
1936  Send a negprot command.
1937 ****************************************************************************/
1938
1939 void cli_negprot_sendsync(struct cli_state *cli)
1940 {
1941         char *p;
1942         int numprots;
1943
1944         if (cli->protocol < PROTOCOL_NT1)
1945                 cli->use_spnego = False;
1946
1947         memset(cli->outbuf,'\0',smb_size);
1948
1949         /* setup the protocol strings */
1950         cli_set_message(cli->outbuf,0,0,True);
1951
1952         p = smb_buf(cli->outbuf);
1953         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1954                 if (prots[numprots].prot > cli->protocol) {
1955                         break;
1956                 }
1957                 *p++ = 2;
1958                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1959         }
1960
1961         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1962         cli_setup_bcc(cli, p);
1963         cli_setup_packet(cli);
1964
1965         SCVAL(smb_buf(cli->outbuf),0,2);
1966
1967         cli_send_smb(cli);
1968 }
1969
1970 /****************************************************************************
1971  Send a negprot command.
1972 ****************************************************************************/
1973
1974 struct cli_negprot_state {
1975         struct cli_state *cli;
1976 };
1977
1978 static void cli_negprot_done(struct tevent_req *subreq);
1979
1980 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1981                                     struct event_context *ev,
1982                                     struct cli_state *cli)
1983 {
1984         struct tevent_req *req, *subreq;
1985         struct cli_negprot_state *state;
1986         uint8_t *bytes = NULL;
1987         int numprots;
1988         uint16_t cnum;
1989
1990         req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1991         if (req == NULL) {
1992                 return NULL;
1993         }
1994         state->cli = cli;
1995
1996         if (cli->protocol < PROTOCOL_NT1)
1997                 cli->use_spnego = False;
1998
1999         /* setup the protocol strings */
2000         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2001                 uint8_t c = 2;
2002                 if (prots[numprots].prot > cli->protocol) {
2003                         break;
2004                 }
2005                 bytes = (uint8_t *)talloc_append_blob(
2006                         state, bytes, data_blob_const(&c, sizeof(c)));
2007                 if (tevent_req_nomem(bytes, req)) {
2008                         return tevent_req_post(req, ev);
2009                 }
2010                 bytes = smb_bytes_push_str(bytes, false,
2011                                            prots[numprots].name,
2012                                            strlen(prots[numprots].name)+1,
2013                                            NULL);
2014                 if (tevent_req_nomem(bytes, req)) {
2015                         return tevent_req_post(req, ev);
2016                 }
2017         }
2018
2019         cnum = cli->cnum;
2020
2021         cli->cnum = 0;
2022         subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2023                               talloc_get_size(bytes), bytes);
2024         cli->cnum = cnum;
2025
2026         if (tevent_req_nomem(subreq, req)) {
2027                 return tevent_req_post(req, ev);
2028         }
2029         tevent_req_set_callback(subreq, cli_negprot_done, req);
2030         return req;
2031 }
2032
2033 static void cli_negprot_done(struct tevent_req *subreq)
2034 {
2035         struct tevent_req *req = tevent_req_callback_data(
2036                 subreq, struct tevent_req);
2037         struct cli_negprot_state *state = tevent_req_data(
2038                 req, struct cli_negprot_state);
2039         struct cli_state *cli = state->cli;
2040         uint8_t wct;
2041         uint16_t *vwv;
2042         uint32_t num_bytes;
2043         uint8_t *bytes;
2044         NTSTATUS status;
2045         uint16_t protnum;
2046         uint8_t *inbuf;
2047
2048         status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2049                               &num_bytes, &bytes);
2050         TALLOC_FREE(subreq);
2051         if (!NT_STATUS_IS_OK(status)) {
2052                 tevent_req_nterror(req, status);
2053                 return;
2054         }
2055
2056         protnum = SVAL(vwv, 0);
2057
2058         if ((protnum >= ARRAY_SIZE(prots))
2059             || (prots[protnum].prot > cli->protocol)) {
2060                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2061                 return;
2062         }
2063
2064         cli->protocol = prots[protnum].prot;
2065
2066         if ((cli->protocol < PROTOCOL_NT1) &&
2067             client_is_signing_mandatory(cli)) {
2068                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2069                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2070                 return;
2071         }
2072
2073         if (cli->protocol >= PROTOCOL_NT1) {    
2074                 struct timespec ts;
2075                 bool negotiated_smb_signing = false;
2076
2077                 /* NT protocol */
2078                 cli->sec_mode = CVAL(vwv + 1, 0);
2079                 cli->max_mux = SVAL(vwv + 1, 1);
2080                 cli->max_xmit = IVAL(vwv + 3, 1);
2081                 cli->sesskey = IVAL(vwv + 7, 1);
2082                 cli->serverzone = SVALS(vwv + 15, 1);
2083                 cli->serverzone *= 60;
2084                 /* this time arrives in real GMT */
2085                 ts = interpret_long_date(((char *)(vwv+11))+1);
2086                 cli->servertime = ts.tv_sec;
2087                 cli->secblob = data_blob(bytes, num_bytes);
2088                 cli->capabilities = IVAL(vwv + 9, 1);
2089                 if (cli->capabilities & CAP_RAW_MODE) {
2090                         cli->readbraw_supported = True;
2091                         cli->writebraw_supported = True;      
2092                 }
2093                 /* work out if they sent us a workgroup */
2094                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2095                     smb_buflen(cli->inbuf) > 8) {
2096                         clistr_pull(cli->inbuf, cli->server_domain,
2097                                     bytes+8, sizeof(cli->server_domain),
2098                                     num_bytes-8,
2099                                     STR_UNICODE|STR_NOALIGN);
2100                 }
2101
2102                 /*
2103                  * As signing is slow we only turn it on if either the client or
2104                  * the server require it. JRA.
2105                  */
2106
2107                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2108                         /* Fail if server says signing is mandatory and we don't want to support it. */
2109                         if (!client_is_signing_allowed(cli)) {
2110                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2111                                 tevent_req_nterror(req,
2112                                                    NT_STATUS_ACCESS_DENIED);
2113                                 return;
2114                         }
2115                         negotiated_smb_signing = true;
2116                 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2117                         /* Fail if client says signing is mandatory and the server doesn't support it. */
2118                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2119                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2120                                 tevent_req_nterror(req,
2121                                                    NT_STATUS_ACCESS_DENIED);
2122                                 return;
2123                         }
2124                         negotiated_smb_signing = true;
2125                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2126                         negotiated_smb_signing = true;
2127                 }
2128
2129                 if (negotiated_smb_signing) {
2130                         cli_set_signing_negotiated(cli);
2131                 }
2132
2133                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2134                         SAFE_FREE(cli->outbuf);
2135                         SAFE_FREE(cli->inbuf);
2136                         cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2137                         cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2138                         cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2139                 }
2140
2141         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2142                 cli->use_spnego = False;
2143                 cli->sec_mode = SVAL(vwv + 1, 0);
2144                 cli->max_xmit = SVAL(vwv + 2, 0);
2145                 cli->max_mux = SVAL(vwv + 3, 0);
2146                 cli->sesskey = IVAL(vwv + 6, 0);
2147                 cli->serverzone = SVALS(vwv + 10, 0);
2148                 cli->serverzone *= 60;
2149                 /* this time is converted to GMT by make_unix_date */
2150                 cli->servertime = make_unix_date(
2151                         (char *)(vwv + 8), cli->serverzone);
2152                 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2153                 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2154                 cli->secblob = data_blob(bytes, num_bytes);
2155         } else {
2156                 /* the old core protocol */
2157                 cli->use_spnego = False;
2158                 cli->sec_mode = 0;
2159                 cli->serverzone = get_time_zone(time(NULL));
2160         }
2161
2162         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2163
2164         /* a way to force ascii SMB */
2165         if (getenv("CLI_FORCE_ASCII"))
2166                 cli->capabilities &= ~CAP_UNICODE;
2167
2168         tevent_req_done(req);
2169 }
2170
2171 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2172 {
2173         return tevent_req_simple_recv_ntstatus(req);
2174 }
2175
2176 NTSTATUS cli_negprot(struct cli_state *cli)
2177 {
2178         TALLOC_CTX *frame = talloc_stackframe();
2179         struct event_context *ev;
2180         struct tevent_req *req;
2181         NTSTATUS status = NT_STATUS_OK;
2182
2183         if (cli_has_async_calls(cli)) {
2184                 /*
2185                  * Can't use sync call while an async call is in flight
2186                  */
2187                 status = NT_STATUS_INVALID_PARAMETER;
2188                 goto fail;
2189         }
2190
2191         ev = event_context_init(frame);
2192         if (ev == NULL) {
2193                 status = NT_STATUS_NO_MEMORY;
2194                 goto fail;
2195         }
2196
2197         req = cli_negprot_send(frame, ev, cli);
2198         if (req == NULL) {
2199                 status = NT_STATUS_NO_MEMORY;
2200                 goto fail;
2201         }
2202
2203         if (!tevent_req_poll(req, ev)) {
2204                 status = map_nt_error_from_unix(errno);
2205                 goto fail;
2206         }
2207
2208         status = cli_negprot_recv(req);
2209  fail:
2210         TALLOC_FREE(frame);
2211         if (!NT_STATUS_IS_OK(status)) {
2212                 cli_set_error(cli, status);
2213         }
2214         return status;
2215 }
2216
2217 /****************************************************************************
2218  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2219 ****************************************************************************/
2220
2221 bool cli_session_request(struct cli_state *cli,
2222                          struct nmb_name *calling, struct nmb_name *called)
2223 {
2224         char *p;
2225         int len = 4;
2226         char *tmp;
2227
2228         /* 445 doesn't have session request */
2229         if (cli->port == 445)
2230                 return True;
2231
2232         memcpy(&(cli->calling), calling, sizeof(*calling));
2233         memcpy(&(cli->called ), called , sizeof(*called ));
2234
2235         /* put in the destination name */
2236
2237         tmp = name_mangle(talloc_tos(), cli->called.name,
2238                           cli->called.name_type);
2239         if (tmp == NULL) {
2240                 return false;
2241         }
2242
2243         p = cli->outbuf+len;
2244         memcpy(p, tmp, name_len(tmp));
2245         len += name_len(tmp);
2246         TALLOC_FREE(tmp);
2247
2248         /* and my name */
2249
2250         tmp = name_mangle(talloc_tos(), cli->calling.name,
2251                           cli->calling.name_type);
2252         if (tmp == NULL) {
2253                 return false;
2254         }
2255
2256         p = cli->outbuf+len;
2257         memcpy(p, tmp, name_len(tmp));
2258         len += name_len(tmp);
2259         TALLOC_FREE(tmp);
2260
2261         /* send a session request (RFC 1002) */
2262         /* setup the packet length
2263          * Remove four bytes from the length count, since the length
2264          * field in the NBT Session Service header counts the number
2265          * of bytes which follow.  The cli_send_smb() function knows
2266          * about this and accounts for those four bytes.
2267          * CRH.
2268          */
2269         len -= 4;
2270         _smb_setlen(cli->outbuf,len);
2271         SCVAL(cli->outbuf,0,0x81);
2272
2273         cli_send_smb(cli);
2274         DEBUG(5,("Sent session request\n"));
2275
2276         if (!cli_receive_smb(cli))
2277                 return False;
2278
2279         if (CVAL(cli->inbuf,0) == 0x84) {
2280                 /* C. Hoch  9/14/95 Start */
2281                 /* For information, here is the response structure.
2282                  * We do the byte-twiddling to for portability.
2283                 struct RetargetResponse{
2284                 unsigned char type;
2285                 unsigned char flags;
2286                 int16 length;
2287                 int32 ip_addr;
2288                 int16 port;
2289                 };
2290                 */
2291                 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2292                 struct in_addr dest_ip;
2293                 NTSTATUS status;
2294
2295                 /* SESSION RETARGET */
2296                 putip((char *)&dest_ip,cli->inbuf+4);
2297                 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2298
2299                 status = open_socket_out(&cli->dest_ss, port,
2300                                          LONG_CONNECT_TIMEOUT, &cli->fd);
2301                 if (!NT_STATUS_IS_OK(status)) {
2302                         return False;
2303                 }
2304
2305                 DEBUG(3,("Retargeted\n"));
2306
2307                 set_socket_options(cli->fd, lp_socket_options());
2308
2309                 /* Try again */
2310                 {
2311                         static int depth;
2312                         bool ret;
2313                         if (depth > 4) {
2314                                 DEBUG(0,("Retarget recursion - failing\n"));
2315                                 return False;
2316                         }
2317                         depth++;
2318                         ret = cli_session_request(cli, calling, called);
2319                         depth--;
2320                         return ret;
2321                 }
2322         } /* C. Hoch 9/14/95 End */
2323
2324         if (CVAL(cli->inbuf,0) != 0x82) {
2325                 /* This is the wrong place to put the error... JRA. */
2326                 cli->rap_error = CVAL(cli->inbuf,4);
2327                 return False;
2328         }
2329         return(True);
2330 }
2331
2332 struct fd_struct {
2333         int fd;
2334 };
2335
2336 static void smb_sock_connected(struct tevent_req *req)
2337 {
2338         struct fd_struct *pfd = tevent_req_callback_data(
2339                 req, struct fd_struct);
2340         int fd;
2341         NTSTATUS status;
2342
2343         status = open_socket_out_defer_recv(req, &fd);
2344         if (NT_STATUS_IS_OK(status)) {
2345                 pfd->fd = fd;
2346         }
2347 }
2348
2349 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2350                                 uint16_t *port, int timeout, int *pfd)
2351 {
2352         struct event_context *ev;
2353         struct tevent_req *r139, *r445;
2354         struct fd_struct *fd139, *fd445;
2355         NTSTATUS status = NT_STATUS_NO_MEMORY;
2356
2357         if (*port != 0) {
2358                 return open_socket_out(pss, *port, timeout, pfd);
2359         }
2360
2361         ev = event_context_init(talloc_tos());
2362         if (ev == NULL) {
2363                 return NT_STATUS_NO_MEMORY;
2364         }
2365
2366         fd139 = talloc(ev, struct fd_struct);
2367         if (fd139 == NULL) {
2368                 goto done;
2369         }
2370         fd139->fd = -1;
2371
2372         fd445 = talloc(ev, struct fd_struct);
2373         if (fd445 == NULL) {
2374                 goto done;
2375         }
2376         fd445->fd = -1;
2377
2378         r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2379                                           pss, 445, timeout);
2380         r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2381                                           pss, 139, timeout);
2382         if ((r445 == NULL) || (r139 == NULL)) {
2383                 goto done;
2384         }
2385         tevent_req_set_callback(r445, smb_sock_connected, fd445);
2386         tevent_req_set_callback(r139, smb_sock_connected, fd139);
2387
2388         while ((fd445->fd == -1) && (fd139->fd == -1)
2389                && (tevent_req_is_in_progress(r139)
2390                    || tevent_req_is_in_progress(r445))) {
2391                 event_loop_once(ev);
2392         }
2393
2394         if ((fd139->fd != -1) && (fd445->fd != -1)) {
2395                 close(fd139->fd);
2396                 fd139->fd = -1;
2397         }
2398
2399         if (fd445->fd != -1) {
2400                 *port = 445;
2401                 *pfd = fd445->fd;
2402                 status = NT_STATUS_OK;
2403                 goto done;
2404         }
2405         if (fd139->fd != -1) {
2406                 *port = 139;
2407                 *pfd = fd139->fd;
2408                 status = NT_STATUS_OK;
2409                 goto done;
2410         }
2411
2412         status = open_socket_out_defer_recv(r445, &fd445->fd);
2413  done:
2414         TALLOC_FREE(ev);
2415         return status;
2416 }
2417
2418 /****************************************************************************
2419  Open the client sockets.
2420 ****************************************************************************/
2421
2422 NTSTATUS cli_connect(struct cli_state *cli,
2423                 const char *host,
2424                 struct sockaddr_storage *dest_ss)
2425
2426 {
2427         int name_type = 0x20;
2428         TALLOC_CTX *frame = talloc_stackframe();
2429         unsigned int num_addrs = 0;
2430         unsigned int i = 0;
2431         struct sockaddr_storage *ss_arr = NULL;
2432         char *p = NULL;
2433
2434         /* reasonable default hostname */
2435         if (!host) {
2436                 host = STAR_SMBSERVER;
2437         }
2438
2439         fstrcpy(cli->desthost, host);
2440
2441         /* allow hostnames of the form NAME#xx and do a netbios lookup */
2442         if ((p = strchr(cli->desthost, '#'))) {
2443                 name_type = strtol(p+1, NULL, 16);
2444                 *p = 0;
2445         }
2446
2447         if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2448                 NTSTATUS status =resolve_name_list(frame,
2449                                         cli->desthost,
2450                                         name_type,
2451                                         &ss_arr,
2452                                         &num_addrs);
2453                 if (!NT_STATUS_IS_OK(status)) {
2454                         TALLOC_FREE(frame);
2455                         return NT_STATUS_BAD_NETWORK_NAME;
2456                 }
2457         } else {
2458                 num_addrs = 1;
2459                 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2460                 if (!ss_arr) {
2461                         TALLOC_FREE(frame);
2462                         return NT_STATUS_NO_MEMORY;
2463                 }
2464                 *ss_arr = *dest_ss;
2465         }
2466
2467         for (i = 0; i < num_addrs; i++) {
2468                 cli->dest_ss = ss_arr[i];
2469                 if (getenv("LIBSMB_PROG")) {
2470                         cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2471                 } else {
2472                         uint16_t port = cli->port;
2473                         NTSTATUS status;
2474                         status = open_smb_socket(&cli->dest_ss, &port,
2475                                                  cli->timeout, &cli->fd);
2476                         if (NT_STATUS_IS_OK(status)) {
2477                                 cli->port = port;
2478                         }
2479                 }
2480                 if (cli->fd == -1) {
2481                         char addr[INET6_ADDRSTRLEN];
2482                         print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2483                         DEBUG(2,("Error connecting to %s (%s)\n",
2484                                  dest_ss?addr:host,strerror(errno)));
2485                 } else {
2486                         /* Exit from loop on first connection. */
2487                         break;
2488                 }
2489         }
2490
2491         if (cli->fd == -1) {
2492                 TALLOC_FREE(frame);
2493                 return map_nt_error_from_unix(errno);
2494         }
2495
2496         if (dest_ss) {
2497                 *dest_ss = cli->dest_ss;
2498         }
2499
2500         set_socket_options(cli->fd, lp_socket_options());
2501
2502         TALLOC_FREE(frame);
2503         return NT_STATUS_OK;
2504 }
2505
2506 /**
2507    establishes a connection to after the negprot. 
2508    @param output_cli A fully initialised cli structure, non-null only on success
2509    @param dest_host The netbios name of the remote host
2510    @param dest_ss (optional) The the destination IP, NULL for name based lookup
2511    @param port (optional) The destination port (0 for default)
2512    @param retry bool. Did this connection fail with a retryable error ?
2513
2514 */
2515 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
2516                               const char *my_name, 
2517                               const char *dest_host, 
2518                               struct sockaddr_storage *dest_ss, int port,
2519                               int signing_state, int flags,
2520                               bool *retry) 
2521 {
2522         NTSTATUS nt_status;
2523         struct nmb_name calling;
2524         struct nmb_name called;
2525         struct cli_state *cli;
2526         struct sockaddr_storage ss;
2527
2528         if (retry)
2529                 *retry = False;
2530
2531         if (!my_name) 
2532                 my_name = global_myname();
2533
2534         if (!(cli = cli_initialise_ex(signing_state))) {
2535                 return NT_STATUS_NO_MEMORY;
2536         }
2537
2538         make_nmb_name(&calling, my_name, 0x0);
2539         make_nmb_name(&called , dest_host, 0x20);
2540
2541         cli_set_port(cli, port);
2542         cli_set_timeout(cli, 10000); /* 10 seconds. */
2543
2544         if (dest_ss) {
2545                 ss = *dest_ss;
2546         } else {
2547                 zero_sockaddr(&ss);
2548         }
2549
2550 again:
2551
2552         DEBUG(3,("Connecting to host=%s\n", dest_host));
2553
2554         nt_status = cli_connect(cli, dest_host, &ss);
2555         if (!NT_STATUS_IS_OK(nt_status)) {
2556                 char addr[INET6_ADDRSTRLEN];
2557                 print_sockaddr(addr, sizeof(addr), &ss);
2558                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2559                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2560                 cli_shutdown(cli);
2561                 return nt_status;
2562         }
2563
2564         if (retry)
2565                 *retry = True;
2566
2567         if (!cli_session_request(cli, &calling, &called)) {
2568                 char *p;
2569                 DEBUG(1,("session request to %s failed (%s)\n",
2570                          called.name, cli_errstr(cli)));
2571                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2572                         *p = 0;
2573                         goto again;
2574                 }
2575                 if (strcmp(called.name, STAR_SMBSERVER)) {
2576                         make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2577                         goto again;
2578                 }
2579                 return NT_STATUS_BAD_NETWORK_NAME;
2580         }
2581
2582         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2583                 cli->use_spnego = False;
2584         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2585                 cli->use_kerberos = True;
2586
2587         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2588              cli->use_kerberos) {
2589                 cli->fallback_after_kerberos = true;
2590         }
2591         if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2592                 cli->use_ccache = true;
2593         }
2594
2595         nt_status = cli_negprot(cli);
2596         if (!NT_STATUS_IS_OK(nt_status)) {
2597                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2598                 cli_shutdown(cli);
2599                 return nt_status;
2600         }
2601
2602         *output_cli = cli;
2603         return NT_STATUS_OK;
2604 }
2605
2606
2607 /**
2608    establishes a connection right up to doing tconX, password specified.
2609    @param output_cli A fully initialised cli structure, non-null only on success
2610    @param dest_host The netbios name of the remote host
2611    @param dest_ip (optional) The the destination IP, NULL for name based lookup
2612    @param port (optional) The destination port (0 for default)
2613    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
2614    @param service_type The 'type' of serivice. 
2615    @param user Username, unix string
2616    @param domain User's domain
2617    @param password User's password, unencrypted unix string.
2618    @param retry bool. Did this connection fail with a retryable error ?
2619 */
2620
2621 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
2622                              const char *my_name, 
2623                              const char *dest_host, 
2624                              struct sockaddr_storage *dest_ss, int port,
2625                              const char *service, const char *service_type,
2626                              const char *user, const char *domain, 
2627                              const char *password, int flags,
2628                              int signing_state,
2629                              bool *retry) 
2630 {
2631         NTSTATUS nt_status;
2632         struct cli_state *cli = NULL;
2633         int pw_len = password ? strlen(password)+1 : 0;
2634
2635         *output_cli = NULL;
2636
2637         if (password == NULL) {
2638                 password = "";
2639         }
2640
2641         nt_status = cli_start_connection(&cli, my_name, dest_host,
2642                                          dest_ss, port, signing_state,
2643                                          flags, retry);
2644
2645         if (!NT_STATUS_IS_OK(nt_status)) {
2646                 return nt_status;
2647         }
2648
2649         cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2650         cli->use_level_II_oplocks =
2651                 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2652
2653         nt_status = cli_session_setup(cli, user, password, pw_len, password,
2654                                       pw_len, domain);
2655         if (!NT_STATUS_IS_OK(nt_status)) {
2656
2657                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2658                         DEBUG(1,("failed session setup with %s\n",
2659                                  nt_errstr(nt_status)));
2660                         cli_shutdown(cli);
2661                         return nt_status;
2662                 }
2663
2664                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2665                 if (!NT_STATUS_IS_OK(nt_status)) {
2666                         DEBUG(1,("anonymous failed session setup with %s\n",
2667                                  nt_errstr(nt_status)));
2668                         cli_shutdown(cli);
2669                         return nt_status;
2670                 }
2671         }
2672
2673         if (service) {
2674                 nt_status = cli_tcon_andx(cli, service, service_type, password,
2675                                           pw_len);
2676                 if (!NT_STATUS_IS_OK(nt_status)) {
2677                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2678                         cli_shutdown(cli);
2679                         if (NT_STATUS_IS_OK(nt_status)) {
2680                                 nt_status = NT_STATUS_UNSUCCESSFUL;
2681                         }
2682                         return nt_status;
2683                 }
2684         }
2685
2686         nt_status = cli_init_creds(cli, user, domain, password);
2687         if (!NT_STATUS_IS_OK(nt_status)) {
2688                 cli_shutdown(cli);
2689                 return nt_status;
2690         }
2691
2692         *output_cli = cli;
2693         return NT_STATUS_OK;
2694 }
2695
2696 /****************************************************************************
2697  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2698 ****************************************************************************/
2699
2700 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2701                                      struct sockaddr_storage *pdest_ss)
2702 {
2703         struct nmb_name calling, called;
2704
2705         make_nmb_name(&calling, srchost, 0x0);
2706
2707         /*
2708          * If the called name is an IP address
2709          * then use *SMBSERVER immediately.
2710          */
2711
2712         if(is_ipaddress(desthost)) {
2713                 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2714         } else {
2715                 make_nmb_name(&called, desthost, 0x20);
2716         }
2717
2718         if (!cli_session_request(*ppcli, &calling, &called)) {
2719                 NTSTATUS status;
2720                 struct nmb_name smbservername;
2721
2722                 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2723
2724                 /*
2725                  * If the name wasn't *SMBSERVER then
2726                  * try with *SMBSERVER if the first name fails.
2727                  */
2728
2729                 if (nmb_name_equal(&called, &smbservername)) {
2730
2731                         /*
2732                          * The name used was *SMBSERVER, don't bother with another name.
2733                          */
2734
2735                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2736 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2737                         return False;
2738                 }
2739
2740                 /* Try again... */
2741                 cli_shutdown(*ppcli);
2742
2743                 *ppcli = cli_initialise();
2744                 if (!*ppcli) {
2745                         /* Out of memory... */
2746                         return False;
2747                 }
2748
2749                 status = cli_connect(*ppcli, desthost, pdest_ss);
2750                 if (!NT_STATUS_IS_OK(status) ||
2751                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
2752                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2753 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2754                         return False;
2755                 }
2756         }
2757
2758         return True;
2759 }
2760
2761 /****************************************************************************
2762  Send an old style tcon.
2763 ****************************************************************************/
2764 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
2765                       const char *service, const char *pass, const char *dev,
2766                       uint16 *max_xmit, uint16 *tid)
2767 {
2768         char *p;
2769
2770         if (!lp_client_plaintext_auth() && (*pass)) {
2771                 DEBUG(1, ("Server requested plaintext password but 'client "
2772                           "plaintext auth' is disabled\n"));
2773                 return NT_STATUS_ACCESS_DENIED;
2774         }
2775
2776         memset(cli->outbuf,'\0',smb_size);
2777         memset(cli->inbuf,'\0',smb_size);
2778
2779         cli_set_message(cli->outbuf, 0, 0, True);
2780         SCVAL(cli->outbuf,smb_com,SMBtcon);
2781         cli_setup_packet(cli);
2782
2783         p = smb_buf(cli->outbuf);
2784         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2785         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2786         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2787
2788         cli_setup_bcc(cli, p);
2789
2790         cli_send_smb(cli);
2791         if (!cli_receive_smb(cli)) {
2792                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2793         }
2794
2795         if (cli_is_error(cli)) {
2796                 return cli_nt_error(cli);
2797         }
2798
2799         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2800         *tid = SVAL(cli->inbuf, smb_vwv1);
2801
2802         return NT_STATUS_OK;
2803 }
2804
2805 /* Return a cli_state pointing at the IPC$ share for the given server */
2806
2807 struct cli_state *get_ipc_connect(char *server,
2808                                 struct sockaddr_storage *server_ss,
2809                                 const struct user_auth_info *user_info)
2810 {
2811         struct cli_state *cli;
2812         NTSTATUS nt_status;
2813         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2814
2815         if (user_info->use_kerberos) {
2816                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2817         }
2818
2819         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
2820                                         user_info->username ? user_info->username : "",
2821                                         lp_workgroup(),
2822                                         user_info->password ? user_info->password : "",
2823                                         flags,
2824                                         Undefined, NULL);
2825
2826         if (NT_STATUS_IS_OK(nt_status)) {
2827                 return cli;
2828         } else if (is_ipaddress(server)) {
2829             /* windows 9* needs a correct NMB name for connections */
2830             fstring remote_name;
2831
2832             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2833                 cli = get_ipc_connect(remote_name, server_ss, user_info);
2834                 if (cli)
2835                     return cli;
2836             }
2837         }
2838         return NULL;
2839 }
2840
2841 /*
2842  * Given the IP address of a master browser on the network, return its
2843  * workgroup and connect to it.
2844  *
2845  * This function is provided to allow additional processing beyond what
2846  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2847  * browsers and obtain each master browsers' list of domains (in case the
2848  * first master browser is recently on the network and has not yet
2849  * synchronized with other master browsers and therefore does not yet have the
2850  * entire network browse list)
2851  */
2852
2853 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2854                                 struct ip_service *mb_ip,
2855                                 const struct user_auth_info *user_info,
2856                                 char **pp_workgroup_out)
2857 {
2858         char addr[INET6_ADDRSTRLEN];
2859         fstring name;
2860         struct cli_state *cli;
2861         struct sockaddr_storage server_ss;
2862
2863         *pp_workgroup_out = NULL;
2864
2865         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2866         DEBUG(99, ("Looking up name of master browser %s\n",
2867                    addr));
2868
2869         /*
2870          * Do a name status query to find out the name of the master browser.
2871          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2872          * master browser will not respond to a wildcard query (or, at least,
2873          * an NT4 server acting as the domain master browser will not).
2874          *
2875          * We might be able to use ONLY the query on MSBROWSE, but that's not
2876          * yet been tested with all Windows versions, so until it is, leave
2877          * the original wildcard query as the first choice and fall back to
2878          * MSBROWSE if the wildcard query fails.
2879          */
2880         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2881             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2882
2883                 DEBUG(99, ("Could not retrieve name status for %s\n",
2884                            addr));
2885                 return NULL;
2886         }
2887
2888         if (!find_master_ip(name, &server_ss)) {
2889                 DEBUG(99, ("Could not find master ip for %s\n", name));
2890                 return NULL;
2891         }
2892
2893         *pp_workgroup_out = talloc_strdup(ctx, name);
2894
2895         DEBUG(4, ("found master browser %s, %s\n", name, addr));
2896
2897         print_sockaddr(addr, sizeof(addr), &server_ss);
2898         cli = get_ipc_connect(addr, &server_ss, user_info);
2899
2900         return cli;
2901 }
2902
2903 /*
2904  * Return the IP address and workgroup of a master browser on the network, and
2905  * connect to it.
2906  */
2907
2908 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2909                                         const struct user_auth_info *user_info,
2910                                         char **pp_workgroup_out)
2911 {
2912         struct ip_service *ip_list;
2913         struct cli_state *cli;
2914         int i, count;
2915
2916         *pp_workgroup_out = NULL;
2917
2918         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2919
2920         /* Go looking for workgroups by broadcasting on the local network */
2921
2922         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2923                                                 &count))) {
2924                 DEBUG(99, ("No master browsers responded\n"));
2925                 return False;
2926         }
2927
2928         for (i = 0; i < count; i++) {
2929                 char addr[INET6_ADDRSTRLEN];
2930                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2931                 DEBUG(99, ("Found master browser %s\n", addr));
2932
2933                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2934                                 user_info, pp_workgroup_out);
2935                 if (cli)
2936                         return(cli);
2937         }
2938
2939         return NULL;
2940 }