s3:libsmb: add cli_session_setup_anon()
[bbaumbach/samba-autobuild/.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6    Copyright (C) Volker Lendecke 2011
7    Copyright (C) Jeremy Allison 2011
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
34 #include "krb5_env.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
40 #include "lib/param/param.h"
41
42 #define STAR_SMBSERVER "*SMBSERVER"
43
44 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
45                                            const char *principal);
46
47 static struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
48                                                       const char *username,
49                                                       const char *domain,
50                                                       const char *realm,
51                                                       const char *password,
52                                                       bool use_kerberos,
53                                                       bool fallback_after_kerberos,
54                                                       bool use_ccache,
55                                                       bool password_is_nt_hash)
56 {
57         struct loadparm_context *lp_ctx = NULL;
58         struct cli_credentials *creds = NULL;
59         const char *principal = NULL;
60         char *tmp = NULL;
61         char *p = NULL;
62         bool ok;
63
64         creds = cli_credentials_init(mem_ctx);
65         if (creds == NULL) {
66                 return NULL;
67         }
68
69         lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
70         if (lp_ctx == NULL) {
71                 goto fail;
72         }
73         cli_credentials_set_conf(creds, lp_ctx);
74
75         if (domain == NULL) {
76                 domain = "";
77         }
78
79         if (username == NULL) {
80                 username = "";
81         }
82
83         if (strlen(username) == 0) {
84                 if (password != NULL && strlen(password) == 0) {
85                         /*
86                          * some callers pass "" as no password
87                          *
88                          * gensec only handles NULL as no password.
89                          */
90                         password = NULL;
91                 }
92                 if (password == NULL) {
93                         cli_credentials_set_anonymous(creds);
94                         return creds;
95                 }
96         }
97
98         tmp = talloc_strdup(creds, username);
99         if (tmp == NULL) {
100                 goto fail;
101         }
102         username = tmp;
103
104         /* allow for workgroups as part of the username */
105         if ((p = strchr_m(tmp, '\\')) ||
106             (p = strchr_m(tmp, '/')) ||
107             (p = strchr_m(tmp, *lp_winbind_separator()))) {
108                 *p = 0;
109                 username = p + 1;
110                 domain = tmp;
111         }
112
113         principal = username;
114         username = cli_session_setup_get_account(creds, principal);
115         if (username == NULL) {
116                 goto fail;
117         }
118         ok = strequal(username, principal);
119         if (ok) {
120                 /*
121                  * Ok still the same, so it's not a principal
122                  */
123                 principal = NULL;
124         }
125
126         if (use_kerberos && fallback_after_kerberos) {
127                 cli_credentials_set_kerberos_state(creds,
128                                                    CRED_AUTO_USE_KERBEROS);
129         } else if (use_kerberos) {
130                 cli_credentials_set_kerberos_state(creds,
131                                                    CRED_MUST_USE_KERBEROS);
132         } else {
133                 cli_credentials_set_kerberos_state(creds,
134                                                    CRED_DONT_USE_KERBEROS);
135         }
136
137         if (use_ccache) {
138                 uint32_t features;
139
140                 features = cli_credentials_get_gensec_features(creds);
141                 features |= GENSEC_FEATURE_NTLM_CCACHE;
142                 cli_credentials_set_gensec_features(creds, features);
143
144                 if (password != NULL && strlen(password) == 0) {
145                         /*
146                          * some callers pass "" as no password
147                          *
148                          * GENSEC_FEATURE_NTLM_CCACHE only handles
149                          * NULL as no password.
150                          */
151                         password = NULL;
152                 }
153         }
154
155         ok = cli_credentials_set_username(creds,
156                                           username,
157                                           CRED_SPECIFIED);
158         if (!ok) {
159                 goto fail;
160         }
161
162         ok = cli_credentials_set_domain(creds,
163                                         domain,
164                                         CRED_SPECIFIED);
165         if (!ok) {
166                 goto fail;
167         }
168
169         if (principal != NULL) {
170                 ok = cli_credentials_set_principal(creds,
171                                                    principal,
172                                                    CRED_SPECIFIED);
173                 if (!ok) {
174                         goto fail;
175                 }
176         }
177
178         if (realm != NULL) {
179                 ok = cli_credentials_set_realm(creds,
180                                                realm,
181                                                CRED_SPECIFIED);
182                 if (!ok) {
183                         goto fail;
184                 }
185         }
186
187         if (password != NULL && strlen(password) > 0) {
188                 if (password_is_nt_hash) {
189                         struct samr_Password nt_hash;
190                         size_t converted;
191
192                         converted = strhex_to_str((char *)nt_hash.hash,
193                                                   sizeof(nt_hash.hash),
194                                                   password,
195                                                   strlen(password));
196                         if (converted != sizeof(nt_hash.hash)) {
197                                 goto fail;
198                         }
199
200                         ok = cli_credentials_set_nt_hash(creds,
201                                                          &nt_hash,
202                                                          CRED_SPECIFIED);
203                         if (!ok) {
204                                 goto fail;
205                         }
206                 } else {
207                         ok = cli_credentials_set_password(creds,
208                                                           password,
209                                                           CRED_SPECIFIED);
210                         if (!ok) {
211                                 goto fail;
212                         }
213                 }
214         }
215
216         return creds;
217 fail:
218         TALLOC_FREE(creds);
219         return NULL;
220 }
221
222 /********************************************************
223  Utility function to ensure we always return at least
224  a valid char * pointer to an empty string for the
225  cli->server_os, cli->server_type and cli->server_domain
226  strings.
227 *******************************************************/
228
229 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
230                                         const uint8_t *hdr,
231                                         char **dest,
232                                         uint8_t *src,
233                                         size_t srclen,
234                                         ssize_t *destlen)
235 {
236         *destlen = clistr_pull_talloc(mem_ctx,
237                                 (const char *)hdr,
238                                 SVAL(hdr, HDR_FLG2),
239                                 dest,
240                                 (char *)src,
241                                 srclen,
242                                 STR_TERMINATE);
243         if (*destlen == -1) {
244                 return NT_STATUS_NO_MEMORY;
245         }
246
247         if (*dest == NULL) {
248                 *dest = talloc_strdup(mem_ctx, "");
249                 if (*dest == NULL) {
250                         return NT_STATUS_NO_MEMORY;
251                 }
252         }
253         return NT_STATUS_OK;
254 }
255
256 /****************************************************************************
257  Work out suitable capabilities to offer the server.
258 ****************************************************************************/
259
260 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
261                                                uint32_t sesssetup_capabilities)
262 {
263         uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
264
265         /*
266          * We only send capabilities based on the mask for:
267          * - client only flags
268          * - flags used in both directions
269          *
270          * We do not echo the server only flags, except some legacy flags.
271          *
272          * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
273          * CAP_LARGE_WRITEX in order to allow us to do large reads
274          * against old Samba releases (<= 3.6.x).
275          */
276         client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
277
278         /*
279          * Session Setup specific flags CAP_DYNAMIC_REAUTH
280          * and CAP_EXTENDED_SECURITY are passed by the caller.
281          * We need that in order to do guest logins even if
282          * CAP_EXTENDED_SECURITY is negotiated.
283          */
284         client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
285         sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
286         client_capabilities |= sesssetup_capabilities;
287
288         return client_capabilities;
289 }
290
291 /****************************************************************************
292  Do a NT1 guest session setup.
293 ****************************************************************************/
294
295 struct cli_session_setup_guest_state {
296         struct cli_state *cli;
297         uint16_t vwv[13];
298         struct iovec bytes;
299 };
300
301 static void cli_session_setup_guest_done(struct tevent_req *subreq);
302
303 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
304                                                   struct tevent_context *ev,
305                                                   struct cli_state *cli,
306                                                   struct tevent_req **psmbreq)
307 {
308         struct tevent_req *req, *subreq;
309         struct cli_session_setup_guest_state *state;
310         uint16_t *vwv;
311         uint8_t *bytes;
312
313         req = tevent_req_create(mem_ctx, &state,
314                                 struct cli_session_setup_guest_state);
315         if (req == NULL) {
316                 return NULL;
317         }
318         state->cli = cli;
319         vwv = state->vwv;
320
321         SCVAL(vwv+0, 0, 0xFF);
322         SCVAL(vwv+0, 1, 0);
323         SSVAL(vwv+1, 0, 0);
324         SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
325         SSVAL(vwv+3, 0, 2);
326         SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
327         SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
328         SSVAL(vwv+7, 0, 0);
329         SSVAL(vwv+8, 0, 0);
330         SSVAL(vwv+9, 0, 0);
331         SSVAL(vwv+10, 0, 0);
332         SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
333
334         bytes = talloc_array(state, uint8_t, 0);
335
336         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "",  1, /* username */
337                                    NULL);
338         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
339                                    NULL);
340         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
341         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
342
343         if (bytes == NULL) {
344                 TALLOC_FREE(req);
345                 return NULL;
346         }
347
348         state->bytes.iov_base = (void *)bytes;
349         state->bytes.iov_len = talloc_get_size(bytes);
350
351         subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
352                         vwv, 1, &state->bytes);
353         if (subreq == NULL) {
354                 TALLOC_FREE(req);
355                 return NULL;
356         }
357         tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
358         *psmbreq = subreq;
359         return req;
360 }
361
362 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
363                                                 struct tevent_context *ev,
364                                                 struct cli_state *cli)
365 {
366         struct tevent_req *req, *subreq;
367         NTSTATUS status;
368
369         req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
370         if (req == NULL) {
371                 return NULL;
372         }
373
374         status = smb1cli_req_chain_submit(&subreq, 1);
375         if (!NT_STATUS_IS_OK(status)) {
376                 tevent_req_nterror(req, status);
377                 return tevent_req_post(req, ev);
378         }
379         return req;
380 }
381
382 static void cli_session_setup_guest_done(struct tevent_req *subreq)
383 {
384         struct tevent_req *req = tevent_req_callback_data(
385                 subreq, struct tevent_req);
386         struct cli_session_setup_guest_state *state = tevent_req_data(
387                 req, struct cli_session_setup_guest_state);
388         struct cli_state *cli = state->cli;
389         uint32_t num_bytes;
390         uint8_t *in;
391         uint8_t *inhdr;
392         uint8_t *bytes;
393         uint8_t *p;
394         NTSTATUS status;
395         ssize_t ret;
396         uint8_t wct;
397         uint16_t *vwv;
398
399         status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
400                               &num_bytes, &bytes);
401         TALLOC_FREE(subreq);
402         if (!NT_STATUS_IS_OK(status)) {
403                 tevent_req_nterror(req, status);
404                 return;
405         }
406
407         inhdr = in + NBT_HDR_SIZE;
408         p = bytes;
409
410         cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
411         smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
412
413         status = smb_bytes_talloc_string(cli,
414                                         inhdr,
415                                         &cli->server_os,
416                                         p,
417                                         bytes+num_bytes-p,
418                                         &ret);
419
420         if (!NT_STATUS_IS_OK(status)) {
421                 tevent_req_nterror(req, status);
422                 return;
423         }
424         p += ret;
425
426         status = smb_bytes_talloc_string(cli,
427                                         inhdr,
428                                         &cli->server_type,
429                                         p,
430                                         bytes+num_bytes-p,
431                                         &ret);
432
433         if (!NT_STATUS_IS_OK(status)) {
434                 tevent_req_nterror(req, status);
435                 return;
436         }
437         p += ret;
438
439         status = smb_bytes_talloc_string(cli,
440                                         inhdr,
441                                         &cli->server_domain,
442                                         p,
443                                         bytes+num_bytes-p,
444                                         &ret);
445
446         if (!NT_STATUS_IS_OK(status)) {
447                 tevent_req_nterror(req, status);
448                 return;
449         }
450         p += ret;
451
452         tevent_req_done(req);
453 }
454
455 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
456 {
457         return tevent_req_simple_recv_ntstatus(req);
458 }
459
460 /* The following is calculated from :
461  * (smb_size-4) = 35
462  * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
463  * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
464  * end of packet.
465  */
466
467 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
468
469 struct cli_sesssetup_blob_state {
470         struct tevent_context *ev;
471         struct cli_state *cli;
472         DATA_BLOB blob;
473         uint16_t max_blob_size;
474
475         DATA_BLOB this_blob;
476         struct iovec *recv_iov;
477
478         NTSTATUS status;
479         const uint8_t *inbuf;
480         DATA_BLOB ret_blob;
481
482         char *out_native_os;
483         char *out_native_lm;
484 };
485
486 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
487                                     struct tevent_req **psubreq);
488 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
489
490 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
491                                                   struct tevent_context *ev,
492                                                   struct cli_state *cli,
493                                                   DATA_BLOB blob)
494 {
495         struct tevent_req *req, *subreq;
496         struct cli_sesssetup_blob_state *state;
497         uint32_t usable_space;
498
499         req = tevent_req_create(mem_ctx, &state,
500                                 struct cli_sesssetup_blob_state);
501         if (req == NULL) {
502                 return NULL;
503         }
504         state->ev = ev;
505         state->blob = blob;
506         state->cli = cli;
507
508         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
509                 usable_space = UINT16_MAX;
510         } else {
511                 usable_space = cli_state_available_size(cli,
512                                 BASE_SESSSETUP_BLOB_PACKET_SIZE);
513         }
514
515         if (usable_space == 0) {
516                 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
517                           "(not possible to send %u bytes)\n",
518                           BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
519                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
520                 return tevent_req_post(req, ev);
521         }
522         state->max_blob_size = MIN(usable_space, 0xFFFF);
523
524         if (!cli_sesssetup_blob_next(state, &subreq)) {
525                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
526                 return tevent_req_post(req, ev);
527         }
528         tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
529         return req;
530 }
531
532 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
533                                     struct tevent_req **psubreq)
534 {
535         struct tevent_req *subreq;
536         uint16_t thistime;
537
538         thistime = MIN(state->blob.length, state->max_blob_size);
539
540         state->this_blob.data = state->blob.data;
541         state->this_blob.length = thistime;
542
543         state->blob.data += thistime;
544         state->blob.length -= thistime;
545
546         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
547                 subreq = smb2cli_session_setup_send(state, state->ev,
548                                                     state->cli->conn,
549                                                     state->cli->timeout,
550                                                     state->cli->smb2.session,
551                                                     0, /* in_flags */
552                                                     SMB2_CAP_DFS, /* in_capabilities */
553                                                     0, /* in_channel */
554                                                     0, /* in_previous_session_id */
555                                                     &state->this_blob);
556                 if (subreq == NULL) {
557                         return false;
558                 }
559         } else {
560                 uint16_t in_buf_size = 0;
561                 uint16_t in_mpx_max = 0;
562                 uint16_t in_vc_num = 0;
563                 uint32_t in_sess_key = 0;
564                 uint32_t in_capabilities = 0;
565                 const char *in_native_os = NULL;
566                 const char *in_native_lm = NULL;
567
568                 in_buf_size = CLI_BUFFER_SIZE;
569                 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
570                 in_vc_num = cli_state_get_vc_num(state->cli);
571                 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
572                 in_capabilities = cli_session_setup_capabilities(state->cli,
573                                                                 CAP_EXTENDED_SECURITY);
574                 in_native_os = "Unix";
575                 in_native_lm = "Samba";
576
577                 /*
578                  * For now we keep the same values as before,
579                  * we may remove these in a separate commit later.
580                  */
581                 in_mpx_max = 2;
582                 in_vc_num = 1;
583                 in_sess_key = 0;
584
585                 subreq = smb1cli_session_setup_ext_send(state, state->ev,
586                                                         state->cli->conn,
587                                                         state->cli->timeout,
588                                                         state->cli->smb1.pid,
589                                                         state->cli->smb1.session,
590                                                         in_buf_size,
591                                                         in_mpx_max,
592                                                         in_vc_num,
593                                                         in_sess_key,
594                                                         state->this_blob,
595                                                         in_capabilities,
596                                                         in_native_os,
597                                                         in_native_lm);
598                 if (subreq == NULL) {
599                         return false;
600                 }
601         }
602         *psubreq = subreq;
603         return true;
604 }
605
606 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
607 {
608         struct tevent_req *req = tevent_req_callback_data(
609                 subreq, struct tevent_req);
610         struct cli_sesssetup_blob_state *state = tevent_req_data(
611                 req, struct cli_sesssetup_blob_state);
612         struct cli_state *cli = state->cli;
613         NTSTATUS status;
614
615         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
616                 status = smb2cli_session_setup_recv(subreq, state,
617                                                     &state->recv_iov,
618                                                     &state->ret_blob);
619         } else {
620                 status = smb1cli_session_setup_ext_recv(subreq, state,
621                                                         &state->recv_iov,
622                                                         &state->inbuf,
623                                                         &state->ret_blob,
624                                                         &state->out_native_os,
625                                                         &state->out_native_lm);
626         }
627         TALLOC_FREE(subreq);
628         if (!NT_STATUS_IS_OK(status)
629             && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
630                 tevent_req_nterror(req, status);
631                 return;
632         }
633
634         if (cli->server_os == NULL) {
635                 cli->server_os = talloc_move(cli, &state->out_native_os);
636         }
637         if (cli->server_type == NULL) {
638                 cli->server_type = talloc_move(cli, &state->out_native_lm);
639         }
640
641         state->status = status;
642
643         if (state->blob.length != 0) {
644                 /*
645                  * More to send
646                  */
647                 if (!cli_sesssetup_blob_next(state, &subreq)) {
648                         tevent_req_oom(req);
649                         return;
650                 }
651                 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
652                 return;
653         }
654         tevent_req_done(req);
655 }
656
657 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
658                                         TALLOC_CTX *mem_ctx,
659                                         DATA_BLOB *pblob,
660                                         const uint8_t **pinbuf,
661                                         struct iovec **precv_iov)
662 {
663         struct cli_sesssetup_blob_state *state = tevent_req_data(
664                 req, struct cli_sesssetup_blob_state);
665         NTSTATUS status;
666         struct iovec *recv_iov;
667
668         if (tevent_req_is_nterror(req, &status)) {
669                 TALLOC_FREE(state->cli->smb2.session);
670                 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
671                 tevent_req_received(req);
672                 return status;
673         }
674
675         recv_iov = talloc_move(mem_ctx, &state->recv_iov);
676         if (pblob != NULL) {
677                 *pblob = state->ret_blob;
678         }
679         if (pinbuf != NULL) {
680                 *pinbuf = state->inbuf;
681         }
682         if (precv_iov != NULL) {
683                 *precv_iov = recv_iov;
684         }
685         /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
686         status = state->status;
687         tevent_req_received(req);
688         return status;
689 }
690
691 /****************************************************************************
692  Use in-memory credentials cache
693 ****************************************************************************/
694
695 static void use_in_memory_ccache(void) {
696         setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
697 }
698
699 /****************************************************************************
700  Do a spnego/NTLMSSP encrypted session setup.
701 ****************************************************************************/
702
703 struct cli_session_setup_gensec_state {
704         struct tevent_context *ev;
705         struct cli_state *cli;
706         struct auth_generic_state *auth_generic;
707         bool is_anonymous;
708         DATA_BLOB blob_in;
709         const uint8_t *inbuf;
710         struct iovec *recv_iov;
711         DATA_BLOB blob_out;
712         bool local_ready;
713         bool remote_ready;
714         DATA_BLOB session_key;
715 };
716
717 static int cli_session_setup_gensec_state_destructor(
718         struct cli_session_setup_gensec_state *state)
719 {
720         TALLOC_FREE(state->auth_generic);
721         data_blob_clear_free(&state->session_key);
722         return 0;
723 }
724
725 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
726 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
727 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
728 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
729 static void cli_session_setup_gensec_ready(struct tevent_req *req);
730
731 static struct tevent_req *cli_session_setup_gensec_send(
732         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
733         struct cli_credentials *creds,
734         const char *target_service,
735         const char *target_hostname)
736 {
737         struct tevent_req *req;
738         struct cli_session_setup_gensec_state *state;
739         NTSTATUS status;
740         const DATA_BLOB *b = NULL;
741
742         req = tevent_req_create(mem_ctx, &state,
743                                 struct cli_session_setup_gensec_state);
744         if (req == NULL) {
745                 return NULL;
746         }
747         state->ev = ev;
748         state->cli = cli;
749
750         talloc_set_destructor(
751                 state, cli_session_setup_gensec_state_destructor);
752
753         status = auth_generic_client_prepare(state, &state->auth_generic);
754         if (tevent_req_nterror(req, status)) {
755                 return tevent_req_post(req, ev);
756         }
757
758         status = auth_generic_set_creds(state->auth_generic, creds);
759         if (tevent_req_nterror(req, status)) {
760                 return tevent_req_post(req, ev);
761         }
762
763         gensec_want_feature(state->auth_generic->gensec_security,
764                             GENSEC_FEATURE_SESSION_KEY);
765
766         if (target_service != NULL) {
767                 status = gensec_set_target_service(
768                                 state->auth_generic->gensec_security,
769                                 target_service);
770                 if (tevent_req_nterror(req, status)) {
771                         return tevent_req_post(req, ev);
772                 }
773         }
774
775         if (target_hostname != NULL) {
776                 status = gensec_set_target_hostname(
777                                 state->auth_generic->gensec_security,
778                                 target_hostname);
779                 if (tevent_req_nterror(req, status)) {
780                         return tevent_req_post(req, ev);
781                 }
782         }
783
784         b = smbXcli_conn_server_gss_blob(cli->conn);
785         if (b != NULL) {
786                 state->blob_in = *b;
787         }
788
789         state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
790
791         status = auth_generic_client_start(state->auth_generic,
792                                            GENSEC_OID_SPNEGO);
793         if (tevent_req_nterror(req, status)) {
794                 return tevent_req_post(req, ev);
795         }
796
797         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
798                 state->cli->smb2.session = smbXcli_session_create(cli,
799                                                                   cli->conn);
800                 if (tevent_req_nomem(state->cli->smb2.session, req)) {
801                         return tevent_req_post(req, ev);
802                 }
803         }
804
805         cli_session_setup_gensec_local_next(req);
806         if (!tevent_req_is_in_progress(req)) {
807                 return tevent_req_post(req, ev);
808         }
809
810         return req;
811 }
812
813 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
814 {
815         struct cli_session_setup_gensec_state *state =
816                 tevent_req_data(req,
817                 struct cli_session_setup_gensec_state);
818         struct tevent_req *subreq = NULL;
819
820         if (state->local_ready) {
821                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
822                 return;
823         }
824
825         subreq = gensec_update_send(state, state->ev,
826                         state->auth_generic->gensec_security,
827                         state->blob_in);
828         if (tevent_req_nomem(subreq, req)) {
829                 return;
830         }
831         tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
832 }
833
834 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
835 {
836         struct tevent_req *req =
837                 tevent_req_callback_data(subreq,
838                 struct tevent_req);
839         struct cli_session_setup_gensec_state *state =
840                 tevent_req_data(req,
841                 struct cli_session_setup_gensec_state);
842         NTSTATUS status;
843
844         status = gensec_update_recv(subreq, state, &state->blob_out);
845         TALLOC_FREE(subreq);
846         state->blob_in = data_blob_null;
847         if (!NT_STATUS_IS_OK(status) &&
848             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
849         {
850                 tevent_req_nterror(req, status);
851                 return;
852         }
853
854         if (NT_STATUS_IS_OK(status)) {
855                 state->local_ready = true;
856         }
857
858         if (state->local_ready && state->remote_ready) {
859                 cli_session_setup_gensec_ready(req);
860                 return;
861         }
862
863         cli_session_setup_gensec_remote_next(req);
864 }
865
866 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
867 {
868         struct cli_session_setup_gensec_state *state =
869                 tevent_req_data(req,
870                 struct cli_session_setup_gensec_state);
871         struct tevent_req *subreq = NULL;
872
873         if (state->remote_ready) {
874                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
875                 return;
876         }
877
878         subreq = cli_sesssetup_blob_send(state, state->ev,
879                                          state->cli, state->blob_out);
880         if (tevent_req_nomem(subreq, req)) {
881                 return;
882         }
883         tevent_req_set_callback(subreq,
884                                 cli_session_setup_gensec_remote_done,
885                                 req);
886 }
887
888 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
889 {
890         struct tevent_req *req =
891                 tevent_req_callback_data(subreq,
892                 struct tevent_req);
893         struct cli_session_setup_gensec_state *state =
894                 tevent_req_data(req,
895                 struct cli_session_setup_gensec_state);
896         NTSTATUS status;
897
898         state->inbuf = NULL;
899         TALLOC_FREE(state->recv_iov);
900
901         status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
902                                          &state->inbuf, &state->recv_iov);
903         TALLOC_FREE(subreq);
904         data_blob_free(&state->blob_out);
905         if (!NT_STATUS_IS_OK(status) &&
906             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
907         {
908                 tevent_req_nterror(req, status);
909                 return;
910         }
911
912         if (NT_STATUS_IS_OK(status)) {
913                 struct smbXcli_session *session = NULL;
914                 bool is_guest = false;
915
916                 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
917                         session = state->cli->smb2.session;
918                 } else {
919                         session = state->cli->smb1.session;
920                 }
921
922                 is_guest = smbXcli_session_is_guest(session);
923                 if (is_guest) {
924                         /*
925                          * We can't finish the gensec handshake, we don't
926                          * have a negotiated session key.
927                          *
928                          * So just pretend we are completely done.
929                          *
930                          * Note that smbXcli_session_is_guest()
931                          * always returns false if we require signing.
932                          */
933                         state->blob_in = data_blob_null;
934                         state->local_ready = true;
935                 }
936
937                 state->remote_ready = true;
938         }
939
940         if (state->local_ready && state->remote_ready) {
941                 cli_session_setup_gensec_ready(req);
942                 return;
943         }
944
945         cli_session_setup_gensec_local_next(req);
946 }
947
948 static void cli_session_setup_gensec_ready(struct tevent_req *req)
949 {
950         struct cli_session_setup_gensec_state *state =
951                 tevent_req_data(req,
952                 struct cli_session_setup_gensec_state);
953         const char *server_domain = NULL;
954         NTSTATUS status;
955
956         if (state->blob_in.length != 0) {
957                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
958                 return;
959         }
960
961         if (state->blob_out.length != 0) {
962                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
963                 return;
964         }
965
966         /*
967          * gensec_ntlmssp_server_domain() returns NULL
968          * if NTLMSSP is not used.
969          *
970          * We can remove this later
971          * and leave the server domain empty for SMB2 and above
972          * in future releases.
973          */
974         server_domain = gensec_ntlmssp_server_domain(
975                                 state->auth_generic->gensec_security);
976
977         if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
978                 TALLOC_FREE(state->cli->server_domain);
979                 state->cli->server_domain = talloc_strdup(state->cli,
980                                         server_domain);
981                 if (state->cli->server_domain == NULL) {
982                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
983                         return;
984                 }
985         }
986
987         if (state->is_anonymous) {
988                 /*
989                  * Windows server does not set the
990                  * SMB2_SESSION_FLAG_IS_NULL flag.
991                  *
992                  * This fix makes sure we do not try
993                  * to verify a signature on the final
994                  * session setup response.
995                  */
996                 tevent_req_done(req);
997                 return;
998         }
999
1000         status = gensec_session_key(state->auth_generic->gensec_security,
1001                                     state, &state->session_key);
1002         if (tevent_req_nterror(req, status)) {
1003                 return;
1004         }
1005
1006         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1007                 struct smbXcli_session *session = state->cli->smb2.session;
1008
1009                 status = smb2cli_session_set_session_key(session,
1010                                                          state->session_key,
1011                                                          state->recv_iov);
1012                 if (tevent_req_nterror(req, status)) {
1013                         return;
1014                 }
1015         } else {
1016                 struct smbXcli_session *session = state->cli->smb1.session;
1017                 bool active;
1018
1019                 status = smb1cli_session_set_session_key(session,
1020                                                          state->session_key);
1021                 if (tevent_req_nterror(req, status)) {
1022                         return;
1023                 }
1024
1025                 active = smb1cli_conn_activate_signing(state->cli->conn,
1026                                                        state->session_key,
1027                                                        data_blob_null);
1028                 if (active) {
1029                         bool ok;
1030
1031                         ok = smb1cli_conn_check_signing(state->cli->conn,
1032                                                         state->inbuf, 1);
1033                         if (!ok) {
1034                                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1035                                 return;
1036                         }
1037                 }
1038         }
1039
1040         tevent_req_done(req);
1041 }
1042
1043 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1044 {
1045         struct cli_session_setup_gensec_state *state =
1046                 tevent_req_data(req,
1047                 struct cli_session_setup_gensec_state);
1048         NTSTATUS status;
1049
1050         if (tevent_req_is_nterror(req, &status)) {
1051                 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1052                 return status;
1053         }
1054         return NT_STATUS_OK;
1055 }
1056
1057 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1058                                            const char *principal)
1059 {
1060         char *account, *p;
1061
1062         account = talloc_strdup(mem_ctx, principal);
1063         if (account == NULL) {
1064                 return NULL;
1065         }
1066         p = strchr_m(account, '@');
1067         if (p != NULL) {
1068                 *p = '\0';
1069         }
1070         return account;
1071 }
1072
1073 /****************************************************************************
1074  Do a spnego encrypted session setup.
1075
1076  user_domain: The shortname of the domain the user/machine is a member of.
1077  dest_realm: The realm we're connecting to, if NULL we use our default realm.
1078 ****************************************************************************/
1079
1080 struct cli_session_setup_spnego_state {
1081         ADS_STATUS result;
1082 };
1083
1084 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1085
1086 static struct tevent_req *cli_session_setup_spnego_send(
1087         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1088         struct cli_credentials *creds)
1089 {
1090         struct tevent_req *req, *subreq;
1091         struct cli_session_setup_spnego_state *state;
1092         const char *user_principal = NULL;
1093         const char *user_account = NULL;
1094         const char *user_domain = NULL;
1095         const char *pass = NULL;
1096         const char *target_hostname = NULL;
1097         const DATA_BLOB *server_blob = NULL;
1098         enum credentials_use_kerberos krb5_state;
1099         bool try_kerberos = false;
1100         bool need_kinit = false;
1101         bool auth_requested = true;
1102
1103         req = tevent_req_create(mem_ctx, &state,
1104                                 struct cli_session_setup_spnego_state);
1105         if (req == NULL) {
1106                 return NULL;
1107         }
1108
1109         target_hostname = smbXcli_conn_remote_name(cli->conn);
1110         server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1111
1112         /* the server might not even do spnego */
1113         if (server_blob != NULL && server_blob->length != 0) {
1114                 char *principal = NULL;
1115                 char *OIDs[ASN1_MAX_OIDS];
1116                 int i;
1117
1118                 /* The server sent us the first part of the SPNEGO exchange in the
1119                  * negprot reply. It is WRONG to depend on the principal sent in the
1120                  * negprot reply, but right now we do it. If we don't receive one,
1121                  * we try to best guess, then fall back to NTLM.  */
1122                 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1123                                                &principal, NULL) ||
1124                                 OIDs[0] == NULL) {
1125                         state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1126                         tevent_req_done(req);
1127                         return tevent_req_post(req, ev);
1128                 }
1129                 TALLOC_FREE(principal);
1130
1131                 /* make sure the server understands kerberos */
1132                 for (i = 0; OIDs[i] != NULL; i++) {
1133                         if (i == 0) {
1134                                 DEBUG(3,("got OID=%s\n", OIDs[i]));
1135                         } else {
1136                                 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1137                         }
1138
1139                         if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1140                             strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1141                                 cli->got_kerberos_mechanism = True;
1142                         }
1143                         talloc_free(OIDs[i]);
1144                 }
1145         }
1146
1147         auth_requested = cli_credentials_authentication_requested(creds);
1148         if (auth_requested) {
1149                 user_principal = cli_credentials_get_principal(creds, state);
1150                 if (tevent_req_nomem(user_principal, req)) {
1151                         return tevent_req_post(req, ev);
1152                 }
1153         }
1154         user_account = cli_credentials_get_username(creds);
1155         user_domain = cli_credentials_get_domain(creds);
1156         pass = cli_credentials_get_password(creds);
1157
1158         krb5_state = cli_credentials_get_kerberos_state(creds);
1159
1160         if (krb5_state != CRED_DONT_USE_KERBEROS) {
1161                 try_kerberos = true;
1162         }
1163
1164         if (target_hostname == NULL) {
1165                 try_kerberos = false;
1166         } else if (is_ipaddress(target_hostname)) {
1167                 try_kerberos = false;
1168         } else if (strequal(target_hostname, "localhost")) {
1169                 try_kerberos = false;
1170         } else if (strequal(target_hostname, STAR_SMBSERVER)) {
1171                 try_kerberos = false;
1172         } else if (!auth_requested) {
1173                 try_kerberos = false;
1174         }
1175
1176         if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
1177                 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
1178                           "'%s' not possible\n",
1179                           user_principal, user_domain, user_account,
1180                           target_hostname));
1181                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1182                 return tevent_req_post(req, ev);
1183         }
1184
1185         if (pass == NULL || strlen(pass) == 0) {
1186                 need_kinit = false;
1187         } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
1188                 need_kinit = try_kerberos;
1189         } else if (!cli->got_kerberos_mechanism) {
1190                 /*
1191                  * Most likely the server doesn't support
1192                  * Kerberos, don't waste time doing a kinit
1193                  */
1194                 need_kinit = false;
1195         } else {
1196                 need_kinit = try_kerberos;
1197         }
1198
1199         if (need_kinit) {
1200                 int ret;
1201
1202                 use_in_memory_ccache();
1203                 ret = kerberos_kinit_password(user_principal, pass,
1204                                         0 /* no time correction for now */,
1205                                         NULL);
1206
1207                 if (ret != 0) {
1208                         DEBUG(0, ("Kinit for %s to access %s failed: %s\n",
1209                                   user_principal, target_hostname,
1210                                   error_message(ret)));
1211                         if (krb5_state == CRED_MUST_USE_KERBEROS) {
1212                                 state->result = ADS_ERROR_KRB5(ret);
1213                                 tevent_req_done(req);
1214                                 return tevent_req_post(req, ev);
1215                         }
1216
1217                         /*
1218                          * Ignore the error and hope that NTLM will work
1219                          */
1220                         ret = 0;
1221                 }
1222         }
1223
1224         subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1225                                                "cifs", target_hostname);
1226         if (tevent_req_nomem(subreq, req)) {
1227                 return tevent_req_post(req, ev);
1228         }
1229         tevent_req_set_callback(
1230                 subreq, cli_session_setup_spnego_done, req);
1231         return req;
1232 }
1233
1234 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1235 {
1236         struct tevent_req *req = tevent_req_callback_data(
1237                 subreq, struct tevent_req);
1238         NTSTATUS status;
1239
1240         status = cli_session_setup_gensec_recv(subreq);
1241         TALLOC_FREE(subreq);
1242         if (tevent_req_nterror(req, status)) {
1243                 return;
1244         }
1245
1246         tevent_req_done(req);
1247 }
1248
1249 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1250 {
1251         struct cli_session_setup_spnego_state *state = tevent_req_data(
1252                 req, struct cli_session_setup_spnego_state);
1253         NTSTATUS status;
1254
1255         if (tevent_req_is_nterror(req, &status)) {
1256                 state->result = ADS_ERROR_NT(status);
1257         }
1258
1259         return state->result;
1260 }
1261
1262 struct cli_session_setup_creds_state {
1263         struct cli_state *cli;
1264         DATA_BLOB apassword_blob;
1265         DATA_BLOB upassword_blob;
1266         DATA_BLOB lm_session_key;
1267         DATA_BLOB session_key;
1268         char *out_native_os;
1269         char *out_native_lm;
1270         char *out_primary_domain;
1271 };
1272
1273 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1274                                             enum tevent_req_state req_state)
1275 {
1276         struct cli_session_setup_creds_state *state = tevent_req_data(
1277                 req, struct cli_session_setup_creds_state);
1278
1279         if (req_state != TEVENT_REQ_RECEIVED) {
1280                 return;
1281         }
1282
1283         /*
1284          * We only call data_blob_clear() as
1285          * some of the blobs point to the same memory.
1286          *
1287          * We let the talloc hierachy free the memory.
1288          */
1289         data_blob_clear(&state->apassword_blob);
1290         data_blob_clear(&state->upassword_blob);
1291         data_blob_clear(&state->lm_session_key);
1292         data_blob_clear(&state->session_key);
1293         ZERO_STRUCTP(state);
1294 }
1295
1296 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1297 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1298 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1299
1300 /****************************************************************************
1301  Send a session setup. The username and workgroup is in UNIX character
1302  format and must be converted to DOS codepage format before sending. If the
1303  password is in plaintext, the same should be done.
1304 ****************************************************************************/
1305
1306 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1307                                         struct tevent_context *ev,
1308                                         struct cli_state *cli,
1309                                         struct cli_credentials *creds)
1310 {
1311         struct tevent_req *req, *subreq;
1312         struct cli_session_setup_creds_state *state;
1313         uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1314         bool use_spnego = false;
1315         int flags = 0;
1316         enum credentials_use_kerberos krb5_state;
1317         uint32_t gensec_features;
1318         const char *username = "";
1319         const char *domain = "";
1320         DATA_BLOB target_info = data_blob_null;
1321         DATA_BLOB challenge = data_blob_null;
1322         uint16_t in_buf_size = 0;
1323         uint16_t in_mpx_max = 0;
1324         uint16_t in_vc_num = 0;
1325         uint32_t in_sess_key = 0;
1326         const char *in_native_os = NULL;
1327         const char *in_native_lm = NULL;
1328         NTSTATUS status;
1329
1330         req = tevent_req_create(mem_ctx, &state,
1331                                 struct cli_session_setup_creds_state);
1332         if (req == NULL) {
1333                 return NULL;
1334         }
1335         state->cli = cli;
1336
1337         tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1338
1339         krb5_state = cli_credentials_get_kerberos_state(creds);
1340         gensec_features = cli_credentials_get_gensec_features(creds);
1341
1342         switch (krb5_state) {
1343         case CRED_MUST_USE_KERBEROS:
1344                 cli->use_kerberos = true;
1345                 cli->fallback_after_kerberos = false;
1346                 break;
1347         case CRED_AUTO_USE_KERBEROS:
1348                 cli->use_kerberos = true;
1349                 cli->fallback_after_kerberos = true;
1350                 break;
1351         case CRED_DONT_USE_KERBEROS:
1352                 cli->use_kerberos = false;
1353                 cli->fallback_after_kerberos = false;
1354                 break;
1355         }
1356
1357         if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1358                 cli->use_ccache = true;
1359         } else {
1360                 cli->use_ccache = false;
1361         }
1362
1363         /*
1364          * Now work out what sort of session setup we are going to
1365          * do. I have split this into separate functions to make the flow a bit
1366          * easier to understand (tridge).
1367          */
1368         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1369                 use_spnego = false;
1370         } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1371                 use_spnego = true;
1372         } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1373                 /*
1374                  * if the server supports extended security then use SPNEGO
1375                  * even for anonymous connections.
1376                  */
1377                 use_spnego = true;
1378         } else {
1379                 use_spnego = false;
1380         }
1381
1382         if (use_spnego) {
1383                 subreq = cli_session_setup_spnego_send(
1384                         state, ev, cli, creds);
1385                 if (tevent_req_nomem(subreq, req)) {
1386                         return tevent_req_post(req, ev);
1387                 }
1388                 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1389                                         req);
1390                 return req;
1391         }
1392
1393         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1394                 /*
1395                  * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1396                  * this step against older servers.
1397                  */
1398                 tevent_req_done(req);
1399                 return tevent_req_post(req, ev);
1400         }
1401
1402         if (cli_credentials_is_anonymous(creds)) {
1403                 /*
1404                  * Do an anonymous session setup
1405                  */
1406                 goto non_spnego_creds_done;
1407         }
1408
1409         if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1410                 /*
1411                  * Do an anonymous session setup,
1412                  * the password is passed via the tree connect.
1413                  */
1414                 goto non_spnego_creds_done;
1415         }
1416
1417         cli_credentials_get_ntlm_username_domain(creds, state,
1418                                                  &username,
1419                                                  &domain);
1420         if (tevent_req_nomem(username, req)) {
1421                 return tevent_req_post(req, ev);
1422         }
1423         if (tevent_req_nomem(domain, req)) {
1424                 return tevent_req_post(req, ev);
1425         }
1426
1427         if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1428                 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1429                 uint8_t *bytes = NULL;
1430                 size_t bytes_len = 0;
1431                 const char *pw = cli_credentials_get_password(creds);
1432                 size_t pw_len = 0;
1433
1434                 if (pw == NULL) {
1435                         pw = "";
1436                 }
1437                 pw_len = strlen(pw) + 1;
1438
1439                 if (!lp_client_plaintext_auth()) {
1440                         DEBUG(1, ("Server requested PLAINTEXT password but "
1441                                   "'client plaintext auth = no'\n"));
1442                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1443                         return tevent_req_post(req, ev);
1444                 }
1445
1446                 bytes = talloc_array(state, uint8_t, 0);
1447                 bytes = trans2_bytes_push_str(bytes, use_unicode,
1448                                               pw, pw_len, &bytes_len);
1449                 if (tevent_req_nomem(bytes, req)) {
1450                         return tevent_req_post(req, ev);
1451                 }
1452
1453                 if (use_unicode) {
1454                         /*
1455                          * CAP_UNICODE, can only be negotiated by NT1.
1456                          */
1457                         state->upassword_blob = data_blob_const(bytes,
1458                                                                 bytes_len);
1459                 } else {
1460                         state->apassword_blob = data_blob_const(bytes,
1461                                                                 bytes_len);
1462                 }
1463
1464                 goto non_spnego_creds_done;
1465         }
1466
1467         challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1468
1469         if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1470                 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1471                         /*
1472                          * Don't send an NTLMv2 response without NTLMSSP if we
1473                          * want to use spnego support.
1474                          */
1475                         DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1476                                   " but 'client use spnego = yes'"
1477                                   " and 'client ntlmv2 auth = yes' is set\n"));
1478                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1479                         return tevent_req_post(req, ev);
1480                 }
1481
1482                 if (lp_client_ntlmv2_auth()) {
1483                         flags |= CLI_CRED_NTLMv2_AUTH;
1484
1485                         /*
1486                          * note that the 'domain' here is a best
1487                          * guess - we don't know the server's domain
1488                          * at this point. Windows clients also don't
1489                          * use hostname...
1490                          */
1491                         target_info = NTLMv2_generate_names_blob(state,
1492                                                                  NULL,
1493                                                                  domain);
1494                         if (tevent_req_nomem(target_info.data, req)) {
1495                                 return tevent_req_post(req, ev);
1496                         }
1497                 } else {
1498                         flags |= CLI_CRED_NTLM_AUTH;
1499                         if (lp_client_lanman_auth()) {
1500                                 flags |= CLI_CRED_LANMAN_AUTH;
1501                         }
1502                 }
1503         } else {
1504                 if (!lp_client_lanman_auth()) {
1505                         DEBUG(1, ("Server requested LM password but "
1506                                   "'client lanman auth = no' "
1507                                   "or 'client ntlmv2 auth = yes' is set\n"));
1508                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1509                         return tevent_req_post(req, ev);
1510                 }
1511
1512                 flags |= CLI_CRED_LANMAN_AUTH;
1513         }
1514
1515         status = cli_credentials_get_ntlm_response(creds, state, &flags,
1516                                                    challenge, NULL,
1517                                                    target_info,
1518                                                    &state->apassword_blob,
1519                                                    &state->upassword_blob,
1520                                                    &state->lm_session_key,
1521                                                    &state->session_key);
1522         if (tevent_req_nterror(req, status)) {
1523                 return tevent_req_post(req, ev);
1524         }
1525
1526 non_spnego_creds_done:
1527
1528         in_buf_size = CLI_BUFFER_SIZE;
1529         in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1530         in_vc_num = cli_state_get_vc_num(cli);
1531         in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1532         in_native_os = "Unix";
1533         in_native_lm = "Samba";
1534
1535         if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1536                 uint32_t in_capabilities = 0;
1537
1538                 in_capabilities = cli_session_setup_capabilities(cli, 0);
1539
1540                 /*
1541                  * For now we keep the same values as before,
1542                  * we may remove these in a separate commit later.
1543                  */
1544                 in_mpx_max = 2;
1545
1546                 subreq = smb1cli_session_setup_nt1_send(state, ev,
1547                                                         cli->conn,
1548                                                         cli->timeout,
1549                                                         cli->smb1.pid,
1550                                                         cli->smb1.session,
1551                                                         in_buf_size,
1552                                                         in_mpx_max,
1553                                                         in_vc_num,
1554                                                         in_sess_key,
1555                                                         username,
1556                                                         domain,
1557                                                         state->apassword_blob,
1558                                                         state->upassword_blob,
1559                                                         in_capabilities,
1560                                                         in_native_os,
1561                                                         in_native_lm);
1562                 if (tevent_req_nomem(subreq, req)) {
1563                         return tevent_req_post(req, ev);
1564                 }
1565                 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1566                                         req);
1567                 return req;
1568         }
1569
1570         /*
1571          * For now we keep the same values as before,
1572          * we may remove these in a separate commit later.
1573          */
1574         in_mpx_max = 2;
1575         in_vc_num = 1;
1576
1577         subreq = smb1cli_session_setup_lm21_send(state, ev,
1578                                                  cli->conn,
1579                                                  cli->timeout,
1580                                                  cli->smb1.pid,
1581                                                  cli->smb1.session,
1582                                                  in_buf_size,
1583                                                  in_mpx_max,
1584                                                  in_vc_num,
1585                                                  in_sess_key,
1586                                                  username,
1587                                                  domain,
1588                                                  state->apassword_blob,
1589                                                  in_native_os,
1590                                                  in_native_lm);
1591         if (tevent_req_nomem(subreq, req)) {
1592                 return tevent_req_post(req, ev);
1593         }
1594         tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1595                                 req);
1596         return req;
1597 }
1598
1599 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1600 {
1601         struct tevent_req *req = tevent_req_callback_data(
1602                 subreq, struct tevent_req);
1603         ADS_STATUS status;
1604
1605         status = cli_session_setup_spnego_recv(subreq);
1606         TALLOC_FREE(subreq);
1607         if (!ADS_ERR_OK(status)) {
1608                 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1609                 tevent_req_nterror(req, ads_ntstatus(status));
1610                 return;
1611         }
1612         tevent_req_done(req);
1613 }
1614
1615 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1616 {
1617         struct tevent_req *req = tevent_req_callback_data(
1618                 subreq, struct tevent_req);
1619         struct cli_session_setup_creds_state *state = tevent_req_data(
1620                 req, struct cli_session_setup_creds_state);
1621         struct cli_state *cli = state->cli;
1622         NTSTATUS status;
1623         struct iovec *recv_iov = NULL;
1624         const uint8_t *inbuf = NULL;
1625         bool ok;
1626
1627         status = smb1cli_session_setup_nt1_recv(subreq, state,
1628                                                 &recv_iov,
1629                                                 &inbuf,
1630                                                 &state->out_native_os,
1631                                                 &state->out_native_lm,
1632                                                 &state->out_primary_domain);
1633         TALLOC_FREE(subreq);
1634         if (!NT_STATUS_IS_OK(status)) {
1635                 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1636                 tevent_req_nterror(req, status);
1637                 return;
1638         }
1639
1640         if (cli->server_os == NULL) {
1641                 cli->server_os = talloc_move(cli, &state->out_native_os);
1642         }
1643         if (cli->server_type == NULL) {
1644                 cli->server_type = talloc_move(cli, &state->out_native_lm);
1645         }
1646         if (cli->server_domain == NULL) {
1647                 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1648         }
1649
1650         ok = smb1cli_conn_activate_signing(cli->conn,
1651                                            state->session_key,
1652                                            state->upassword_blob);
1653         if (ok) {
1654                 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1655                 if (!ok) {
1656                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1657                         return;
1658                 }
1659         }
1660
1661         if (state->session_key.data) {
1662                 struct smbXcli_session *session = cli->smb1.session;
1663
1664                 status = smb1cli_session_set_session_key(session,
1665                                                          state->session_key);
1666                 if (tevent_req_nterror(req, status)) {
1667                         return;
1668                 }
1669         }
1670
1671         tevent_req_done(req);
1672 }
1673
1674 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1675 {
1676         struct tevent_req *req = tevent_req_callback_data(
1677                 subreq, struct tevent_req);
1678         struct cli_session_setup_creds_state *state = tevent_req_data(
1679                 req, struct cli_session_setup_creds_state);
1680         struct cli_state *cli = state->cli;
1681         NTSTATUS status;
1682
1683         status = smb1cli_session_setup_lm21_recv(subreq, state,
1684                                                  &state->out_native_os,
1685                                                  &state->out_native_lm);
1686         TALLOC_FREE(subreq);
1687         if (!NT_STATUS_IS_OK(status)) {
1688                 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1689                 tevent_req_nterror(req, status);
1690                 return;
1691         }
1692
1693         if (cli->server_os == NULL) {
1694                 cli->server_os = talloc_move(cli, &state->out_native_os);
1695         }
1696         if (cli->server_type == NULL) {
1697                 cli->server_type = talloc_move(cli, &state->out_native_lm);
1698         }
1699
1700         tevent_req_done(req);
1701 }
1702
1703 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1704 {
1705         return tevent_req_simple_recv_ntstatus(req);
1706 }
1707
1708 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1709                                  struct cli_credentials *creds)
1710 {
1711         struct tevent_context *ev;
1712         struct tevent_req *req;
1713         NTSTATUS status = NT_STATUS_NO_MEMORY;
1714
1715         if (smbXcli_conn_has_async_calls(cli->conn)) {
1716                 return NT_STATUS_INVALID_PARAMETER;
1717         }
1718         ev = samba_tevent_context_init(talloc_tos());
1719         if (ev == NULL) {
1720                 goto fail;
1721         }
1722         req = cli_session_setup_creds_send(ev, ev, cli, creds);
1723         if (req == NULL) {
1724                 goto fail;
1725         }
1726         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1727                 goto fail;
1728         }
1729         status = cli_session_setup_creds_recv(req);
1730  fail:
1731         TALLOC_FREE(ev);
1732         return status;
1733 }
1734
1735 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1736 {
1737         NTSTATUS status = NT_STATUS_NO_MEMORY;
1738         struct cli_credentials *creds = NULL;
1739
1740         creds = cli_credentials_init_anon(cli);
1741         if (creds == NULL) {
1742                 return NT_STATUS_NO_MEMORY;
1743         }
1744
1745         status = cli_session_setup_creds(cli, creds);
1746         TALLOC_FREE(creds);
1747         if (!NT_STATUS_IS_OK(status)) {
1748                 return status;
1749         }
1750
1751         return NT_STATUS_OK;
1752 }
1753
1754 NTSTATUS cli_session_setup(struct cli_state *cli,
1755                            const char *user,
1756                            const char *pass,
1757                            const char *workgroup)
1758 {
1759         NTSTATUS status = NT_STATUS_NO_MEMORY;
1760         const char *dest_realm = NULL;
1761         struct cli_credentials *creds = NULL;
1762
1763         /*
1764          * dest_realm is only valid in the winbindd use case,
1765          * where we also have the account in that realm.
1766          */
1767         dest_realm = cli_state_remote_realm(cli);
1768
1769         creds = cli_session_creds_init(cli,
1770                                        user,
1771                                        workgroup,
1772                                        dest_realm,
1773                                        pass,
1774                                        cli->use_kerberos,
1775                                        cli->fallback_after_kerberos,
1776                                        cli->use_ccache,
1777                                        cli->pw_nt_hash);
1778         if (creds == NULL) {
1779                 return NT_STATUS_NO_MEMORY;
1780         }
1781
1782         status = cli_session_setup_creds(cli, creds);
1783         TALLOC_FREE(creds);
1784         if (!NT_STATUS_IS_OK(status)) {
1785                 return status;
1786         }
1787
1788         return NT_STATUS_OK;
1789 }
1790
1791 /****************************************************************************
1792  Send a uloggoff.
1793 *****************************************************************************/
1794
1795 struct cli_ulogoff_state {
1796         struct cli_state *cli;
1797         uint16_t vwv[3];
1798 };
1799
1800 static void cli_ulogoff_done(struct tevent_req *subreq);
1801
1802 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1803                                     struct tevent_context *ev,
1804                                     struct cli_state *cli)
1805 {
1806         struct tevent_req *req, *subreq;
1807         struct cli_ulogoff_state *state;
1808
1809         req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1810         if (req == NULL) {
1811                 return NULL;
1812         }
1813         state->cli = cli;
1814
1815         SCVAL(state->vwv+0, 0, 0xFF);
1816         SCVAL(state->vwv+1, 0, 0);
1817         SSVAL(state->vwv+2, 0, 0);
1818
1819         subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1820                               0, NULL);
1821         if (tevent_req_nomem(subreq, req)) {
1822                 return tevent_req_post(req, ev);
1823         }
1824         tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1825         return req;
1826 }
1827
1828 static void cli_ulogoff_done(struct tevent_req *subreq)
1829 {
1830         struct tevent_req *req = tevent_req_callback_data(
1831                 subreq, struct tevent_req);
1832         struct cli_ulogoff_state *state = tevent_req_data(
1833                 req, struct cli_ulogoff_state);
1834         NTSTATUS status;
1835
1836         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1837         if (!NT_STATUS_IS_OK(status)) {
1838                 tevent_req_nterror(req, status);
1839                 return;
1840         }
1841         cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1842         tevent_req_done(req);
1843 }
1844
1845 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1846 {
1847         return tevent_req_simple_recv_ntstatus(req);
1848 }
1849
1850 NTSTATUS cli_ulogoff(struct cli_state *cli)
1851 {
1852         struct tevent_context *ev;
1853         struct tevent_req *req;
1854         NTSTATUS status = NT_STATUS_NO_MEMORY;
1855
1856         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1857                 status = smb2cli_logoff(cli->conn,
1858                                         cli->timeout,
1859                                         cli->smb2.session);
1860                 if (!NT_STATUS_IS_OK(status)) {
1861                         return status;
1862                 }
1863                 smb2cli_session_set_id_and_flags(cli->smb2.session,
1864                                                  UINT64_MAX, 0);
1865                 return NT_STATUS_OK;
1866         }
1867
1868         if (smbXcli_conn_has_async_calls(cli->conn)) {
1869                 return NT_STATUS_INVALID_PARAMETER;
1870         }
1871         ev = samba_tevent_context_init(talloc_tos());
1872         if (ev == NULL) {
1873                 goto fail;
1874         }
1875         req = cli_ulogoff_send(ev, ev, cli);
1876         if (req == NULL) {
1877                 goto fail;
1878         }
1879         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1880                 goto fail;
1881         }
1882         status = cli_ulogoff_recv(req);
1883 fail:
1884         TALLOC_FREE(ev);
1885         return status;
1886 }
1887
1888 /****************************************************************************
1889  Send a tconX.
1890 ****************************************************************************/
1891
1892 struct cli_tcon_andx_state {
1893         struct cli_state *cli;
1894         uint16_t vwv[4];
1895         struct iovec bytes;
1896 };
1897
1898 static void cli_tcon_andx_done(struct tevent_req *subreq);
1899
1900 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1901                                         struct tevent_context *ev,
1902                                         struct cli_state *cli,
1903                                         const char *share, const char *dev,
1904                                         const char *pass, int passlen,
1905                                         struct tevent_req **psmbreq)
1906 {
1907         struct tevent_req *req, *subreq;
1908         struct cli_tcon_andx_state *state;
1909         uint8_t p24[24];
1910         uint16_t *vwv;
1911         char *tmp = NULL;
1912         uint8_t *bytes;
1913         uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1914         uint16_t tcon_flags = 0;
1915
1916         *psmbreq = NULL;
1917
1918         req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1919         if (req == NULL) {
1920                 return NULL;
1921         }
1922         state->cli = cli;
1923         vwv = state->vwv;
1924
1925         cli->share = talloc_strdup(cli, share);
1926         if (!cli->share) {
1927                 return NULL;
1928         }
1929
1930         /* in user level security don't send a password now */
1931         if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1932                 passlen = 1;
1933                 pass = "";
1934         } else if (pass == NULL) {
1935                 DEBUG(1, ("Server not using user level security and no "
1936                           "password supplied.\n"));
1937                 goto access_denied;
1938         }
1939
1940         if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1941             *pass && passlen != 24) {
1942                 if (!lp_client_lanman_auth()) {
1943                         DEBUG(1, ("Server requested LANMAN password "
1944                                   "(share-level security) but "
1945                                   "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1946                         goto access_denied;
1947                 }
1948
1949                 /*
1950                  * Non-encrypted passwords - convert to DOS codepage before
1951                  * encryption.
1952                  */
1953                 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1954                 passlen = 24;
1955                 pass = (const char *)p24;
1956         } else {
1957                 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1958                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1959                    == 0) {
1960                         uint8_t *tmp_pass;
1961
1962                         if (!lp_client_plaintext_auth() && (*pass)) {
1963                                 DEBUG(1, ("Server requested PLAINTEXT "
1964                                           "password but "
1965                                           "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1966                                 goto access_denied;
1967                         }
1968
1969                         /*
1970                          * Non-encrypted passwords - convert to DOS codepage
1971                          * before using.
1972                          */
1973                         tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1974                         if (tevent_req_nomem(tmp_pass, req)) {
1975                                 return tevent_req_post(req, ev);
1976                         }
1977                         tmp_pass = trans2_bytes_push_str(tmp_pass,
1978                                                          false, /* always DOS */
1979                                                          pass,
1980                                                          passlen,
1981                                                          NULL);
1982                         if (tevent_req_nomem(tmp_pass, req)) {
1983                                 return tevent_req_post(req, ev);
1984                         }
1985                         pass = (const char *)tmp_pass;
1986                         passlen = talloc_get_size(tmp_pass);
1987                 }
1988         }
1989
1990         tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1991         tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1992
1993         SCVAL(vwv+0, 0, 0xFF);
1994         SCVAL(vwv+0, 1, 0);
1995         SSVAL(vwv+1, 0, 0);
1996         SSVAL(vwv+2, 0, tcon_flags);
1997         SSVAL(vwv+3, 0, passlen);
1998
1999         if (passlen && pass) {
2000                 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2001         } else {
2002                 bytes = talloc_array(state, uint8_t, 0);
2003         }
2004
2005         /*
2006          * Add the sharename
2007          */
2008         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2009                                          smbXcli_conn_remote_name(cli->conn), share);
2010         if (tmp == NULL) {
2011                 TALLOC_FREE(req);
2012                 return NULL;
2013         }
2014         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2015                                    NULL);
2016         TALLOC_FREE(tmp);
2017
2018         /*
2019          * Add the devicetype
2020          */
2021         tmp = talloc_strdup_upper(talloc_tos(), dev);
2022         if (tmp == NULL) {
2023                 TALLOC_FREE(req);
2024                 return NULL;
2025         }
2026         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2027         TALLOC_FREE(tmp);
2028
2029         if (bytes == NULL) {
2030                 TALLOC_FREE(req);
2031                 return NULL;
2032         }
2033
2034         state->bytes.iov_base = (void *)bytes;
2035         state->bytes.iov_len = talloc_get_size(bytes);
2036
2037         subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2038                                     1, &state->bytes);
2039         if (subreq == NULL) {
2040                 TALLOC_FREE(req);
2041                 return NULL;
2042         }
2043         tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2044         *psmbreq = subreq;
2045         return req;
2046
2047  access_denied:
2048         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2049         return tevent_req_post(req, ev);
2050 }
2051
2052 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2053                                       struct tevent_context *ev,
2054                                       struct cli_state *cli,
2055                                       const char *share, const char *dev,
2056                                       const char *pass, int passlen)
2057 {
2058         struct tevent_req *req, *subreq;
2059         NTSTATUS status;
2060
2061         req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2062                                    &subreq);
2063         if (req == NULL) {
2064                 return NULL;
2065         }
2066         if (subreq == NULL) {
2067                 return req;
2068         }
2069         status = smb1cli_req_chain_submit(&subreq, 1);
2070         if (!NT_STATUS_IS_OK(status)) {
2071                 tevent_req_nterror(req, status);
2072                 return tevent_req_post(req, ev);
2073         }
2074         return req;
2075 }
2076
2077 static void cli_tcon_andx_done(struct tevent_req *subreq)
2078 {
2079         struct tevent_req *req = tevent_req_callback_data(
2080                 subreq, struct tevent_req);
2081         struct cli_tcon_andx_state *state = tevent_req_data(
2082                 req, struct cli_tcon_andx_state);
2083         struct cli_state *cli = state->cli;
2084         uint8_t *in;
2085         uint8_t *inhdr;
2086         uint8_t wct;
2087         uint16_t *vwv;
2088         uint32_t num_bytes;
2089         uint8_t *bytes;
2090         NTSTATUS status;
2091         uint16_t optional_support = 0;
2092
2093         status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2094                               &num_bytes, &bytes);
2095         TALLOC_FREE(subreq);
2096         if (!NT_STATUS_IS_OK(status)) {
2097                 tevent_req_nterror(req, status);
2098                 return;
2099         }
2100
2101         inhdr = in + NBT_HDR_SIZE;
2102
2103         if (num_bytes) {
2104                 if (clistr_pull_talloc(cli,
2105                                 (const char *)inhdr,
2106                                 SVAL(inhdr, HDR_FLG2),
2107                                 &cli->dev,
2108                                 bytes,
2109                                 num_bytes,
2110                                 STR_TERMINATE|STR_ASCII) == -1) {
2111                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2112                         return;
2113                 }
2114         } else {
2115                 cli->dev = talloc_strdup(cli, "");
2116                 if (cli->dev == NULL) {
2117                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2118                         return;
2119                 }
2120         }
2121
2122         if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2123                 /* almost certainly win95 - enable bug fixes */
2124                 cli->win95 = True;
2125         }
2126
2127         /*
2128          * Make sure that we have the optional support 16-bit field. WCT > 2.
2129          * Avoids issues when connecting to Win9x boxes sharing files
2130          */
2131
2132         if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2133                 optional_support = SVAL(vwv+2, 0);
2134         }
2135
2136         if (optional_support & SMB_EXTENDED_SIGNATURES) {
2137                 smb1cli_session_protect_session_key(cli->smb1.session);
2138         }
2139
2140         smb1cli_tcon_set_values(state->cli->smb1.tcon,
2141                                 SVAL(inhdr, HDR_TID),
2142                                 optional_support,
2143                                 0, /* maximal_access */
2144                                 0, /* guest_maximal_access */
2145                                 NULL, /* service */
2146                                 NULL); /* fs_type */
2147
2148         tevent_req_done(req);
2149 }
2150
2151 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2152 {
2153         return tevent_req_simple_recv_ntstatus(req);
2154 }
2155
2156 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2157                        const char *dev, const char *pass, int passlen)
2158 {
2159         TALLOC_CTX *frame = talloc_stackframe();
2160         struct tevent_context *ev;
2161         struct tevent_req *req;
2162         NTSTATUS status = NT_STATUS_NO_MEMORY;
2163
2164         if (smbXcli_conn_has_async_calls(cli->conn)) {
2165                 /*
2166                  * Can't use sync call while an async call is in flight
2167                  */
2168                 status = NT_STATUS_INVALID_PARAMETER;
2169                 goto fail;
2170         }
2171
2172         ev = samba_tevent_context_init(frame);
2173         if (ev == NULL) {
2174                 goto fail;
2175         }
2176
2177         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2178         if (req == NULL) {
2179                 goto fail;
2180         }
2181
2182         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2183                 goto fail;
2184         }
2185
2186         status = cli_tcon_andx_recv(req);
2187  fail:
2188         TALLOC_FREE(frame);
2189         return status;
2190 }
2191
2192 struct cli_tree_connect_state {
2193         struct cli_state *cli;
2194 };
2195
2196 static struct tevent_req *cli_raw_tcon_send(
2197         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2198         const char *service, const char *pass, const char *dev);
2199 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2200                                   uint16_t *max_xmit, uint16_t *tid);
2201
2202 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2203 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2204 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2205
2206 static struct tevent_req *cli_tree_connect_send(
2207         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2208         const char *share, const char *dev, const char *pass, int passlen)
2209 {
2210         struct tevent_req *req, *subreq;
2211         struct cli_tree_connect_state *state;
2212
2213         req = tevent_req_create(mem_ctx, &state,
2214                                 struct cli_tree_connect_state);
2215         if (req == NULL) {
2216                 return NULL;
2217         }
2218         state->cli = cli;
2219
2220         cli->share = talloc_strdup(cli, share);
2221         if (tevent_req_nomem(cli->share, req)) {
2222                 return tevent_req_post(req, ev);
2223         }
2224
2225         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2226                 char *unc;
2227
2228                 cli->smb2.tcon = smbXcli_tcon_create(cli);
2229                 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2230                         return tevent_req_post(req, ev);
2231                 }
2232
2233                 unc = talloc_asprintf(state, "\\\\%s\\%s",
2234                                       smbXcli_conn_remote_name(cli->conn),
2235                                       share);
2236                 if (tevent_req_nomem(unc, req)) {
2237                         return tevent_req_post(req, ev);
2238                 }
2239
2240                 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2241                                            cli->smb2.session, cli->smb2.tcon,
2242                                            0, /* flags */
2243                                            unc);
2244                 if (tevent_req_nomem(subreq, req)) {
2245                         return tevent_req_post(req, ev);
2246                 }
2247                 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2248                                         req);
2249                 return req;
2250         }
2251
2252         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2253                 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2254                                             pass, passlen);
2255                 if (tevent_req_nomem(subreq, req)) {
2256                         return tevent_req_post(req, ev);
2257                 }
2258                 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2259                                         req);
2260                 return req;
2261         }
2262
2263         subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2264         if (tevent_req_nomem(subreq, req)) {
2265                 return tevent_req_post(req, ev);
2266         }
2267         tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2268
2269         return req;
2270 }
2271
2272 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2273 {
2274         tevent_req_simple_finish_ntstatus(
2275                 subreq, smb2cli_tcon_recv(subreq));
2276 }
2277
2278 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2279 {
2280         tevent_req_simple_finish_ntstatus(
2281                 subreq, cli_tcon_andx_recv(subreq));
2282 }
2283
2284 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2285 {
2286         struct tevent_req *req = tevent_req_callback_data(
2287                 subreq, struct tevent_req);
2288         struct cli_tree_connect_state *state = tevent_req_data(
2289                 req, struct cli_tree_connect_state);
2290         NTSTATUS status;
2291         uint16_t max_xmit = 0;
2292         uint16_t tid = 0;
2293
2294         status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2295         if (tevent_req_nterror(req, status)) {
2296                 return;
2297         }
2298
2299         smb1cli_tcon_set_values(state->cli->smb1.tcon,
2300                                 tid,
2301                                 0, /* optional_support */
2302                                 0, /* maximal_access */
2303                                 0, /* guest_maximal_access */
2304                                 NULL, /* service */
2305                                 NULL); /* fs_type */
2306
2307         tevent_req_done(req);
2308 }
2309
2310 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2311 {
2312         return tevent_req_simple_recv_ntstatus(req);
2313 }
2314
2315 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2316                           const char *dev, const char *pass, int passlen)
2317 {
2318         struct tevent_context *ev;
2319         struct tevent_req *req;
2320         NTSTATUS status = NT_STATUS_NO_MEMORY;
2321
2322         if (smbXcli_conn_has_async_calls(cli->conn)) {
2323                 return NT_STATUS_INVALID_PARAMETER;
2324         }
2325         ev = samba_tevent_context_init(talloc_tos());
2326         if (ev == NULL) {
2327                 goto fail;
2328         }
2329         req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2330         if (req == NULL) {
2331                 goto fail;
2332         }
2333         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2334                 goto fail;
2335         }
2336         status = cli_tree_connect_recv(req);
2337 fail:
2338         TALLOC_FREE(ev);
2339         return status;
2340 }
2341
2342 /****************************************************************************
2343  Send a tree disconnect.
2344 ****************************************************************************/
2345
2346 struct cli_tdis_state {
2347         struct cli_state *cli;
2348 };
2349
2350 static void cli_tdis_done(struct tevent_req *subreq);
2351
2352 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2353                                  struct tevent_context *ev,
2354                                  struct cli_state *cli)
2355 {
2356         struct tevent_req *req, *subreq;
2357         struct cli_tdis_state *state;
2358
2359         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2360         if (req == NULL) {
2361                 return NULL;
2362         }
2363         state->cli = cli;
2364
2365         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2366         if (tevent_req_nomem(subreq, req)) {
2367                 return tevent_req_post(req, ev);
2368         }
2369         tevent_req_set_callback(subreq, cli_tdis_done, req);
2370         return req;
2371 }
2372
2373 static void cli_tdis_done(struct tevent_req *subreq)
2374 {
2375         struct tevent_req *req = tevent_req_callback_data(
2376                 subreq, struct tevent_req);
2377         struct cli_tdis_state *state = tevent_req_data(
2378                 req, struct cli_tdis_state);
2379         NTSTATUS status;
2380
2381         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2382         TALLOC_FREE(subreq);
2383         if (!NT_STATUS_IS_OK(status)) {
2384                 tevent_req_nterror(req, status);
2385                 return;
2386         }
2387         cli_state_set_tid(state->cli, UINT16_MAX);
2388         tevent_req_done(req);
2389 }
2390
2391 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2392 {
2393         return tevent_req_simple_recv_ntstatus(req);
2394 }
2395
2396 NTSTATUS cli_tdis(struct cli_state *cli)
2397 {
2398         struct tevent_context *ev;
2399         struct tevent_req *req;
2400         NTSTATUS status = NT_STATUS_NO_MEMORY;
2401
2402         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2403                 return smb2cli_tdis(cli->conn,
2404                                     cli->timeout,
2405                                     cli->smb2.session,
2406                                     cli->smb2.tcon);
2407         }
2408
2409         if (smbXcli_conn_has_async_calls(cli->conn)) {
2410                 return NT_STATUS_INVALID_PARAMETER;
2411         }
2412         ev = samba_tevent_context_init(talloc_tos());
2413         if (ev == NULL) {
2414                 goto fail;
2415         }
2416         req = cli_tdis_send(ev, ev, cli);
2417         if (req == NULL) {
2418                 goto fail;
2419         }
2420         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2421                 goto fail;
2422         }
2423         status = cli_tdis_recv(req);
2424 fail:
2425         TALLOC_FREE(ev);
2426         return status;
2427 }
2428
2429 struct cli_connect_sock_state {
2430         const char **called_names;
2431         const char **calling_names;
2432         int *called_types;
2433         int fd;
2434         uint16_t port;
2435 };
2436
2437 static void cli_connect_sock_done(struct tevent_req *subreq);
2438
2439 /*
2440  * Async only if we don't have to look up the name, i.e. "pss" is set with a
2441  * nonzero address.
2442  */
2443
2444 static struct tevent_req *cli_connect_sock_send(
2445         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2446         const char *host, int name_type, const struct sockaddr_storage *pss,
2447         const char *myname, uint16_t port)
2448 {
2449         struct tevent_req *req, *subreq;
2450         struct cli_connect_sock_state *state;
2451         const char *prog;
2452         struct sockaddr_storage *addrs;
2453         unsigned i, num_addrs;
2454         NTSTATUS status;
2455
2456         req = tevent_req_create(mem_ctx, &state,
2457                                 struct cli_connect_sock_state);
2458         if (req == NULL) {
2459                 return NULL;
2460         }
2461
2462         prog = getenv("LIBSMB_PROG");
2463         if (prog != NULL) {
2464                 state->fd = sock_exec(prog);
2465                 if (state->fd == -1) {
2466                         status = map_nt_error_from_unix(errno);
2467                         tevent_req_nterror(req, status);
2468                 } else {
2469                         state->port = 0;
2470                         tevent_req_done(req);
2471                 }
2472                 return tevent_req_post(req, ev);
2473         }
2474
2475         if ((pss == NULL) || is_zero_addr(pss)) {
2476
2477                 /*
2478                  * Here we cheat. resolve_name_list is not async at all. So
2479                  * this call will only be really async if the name lookup has
2480                  * been done externally.
2481                  */
2482
2483                 status = resolve_name_list(state, host, name_type,
2484                                            &addrs, &num_addrs);
2485                 if (!NT_STATUS_IS_OK(status)) {
2486                         tevent_req_nterror(req, status);
2487                         return tevent_req_post(req, ev);
2488                 }
2489         } else {
2490                 addrs = talloc_array(state, struct sockaddr_storage, 1);
2491                 if (tevent_req_nomem(addrs, req)) {
2492                         return tevent_req_post(req, ev);
2493                 }
2494                 addrs[0] = *pss;
2495                 num_addrs = 1;
2496         }
2497
2498         state->called_names = talloc_array(state, const char *, num_addrs);
2499         if (tevent_req_nomem(state->called_names, req)) {
2500                 return tevent_req_post(req, ev);
2501         }
2502         state->called_types = talloc_array(state, int, num_addrs);
2503         if (tevent_req_nomem(state->called_types, req)) {
2504                 return tevent_req_post(req, ev);
2505         }
2506         state->calling_names = talloc_array(state, const char *, num_addrs);
2507         if (tevent_req_nomem(state->calling_names, req)) {
2508                 return tevent_req_post(req, ev);
2509         }
2510         for (i=0; i<num_addrs; i++) {
2511                 state->called_names[i] = host;
2512                 state->called_types[i] = name_type;
2513                 state->calling_names[i] = myname;
2514         }
2515
2516         subreq = smbsock_any_connect_send(
2517                 state, ev, addrs, state->called_names, state->called_types,
2518                 state->calling_names, NULL, num_addrs, port);
2519         if (tevent_req_nomem(subreq, req)) {
2520                 return tevent_req_post(req, ev);
2521         }
2522         tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2523         return req;
2524 }
2525
2526 static void cli_connect_sock_done(struct tevent_req *subreq)
2527 {
2528         struct tevent_req *req = tevent_req_callback_data(
2529                 subreq, struct tevent_req);
2530         struct cli_connect_sock_state *state = tevent_req_data(
2531                 req, struct cli_connect_sock_state);
2532         NTSTATUS status;
2533
2534         status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2535                                           &state->port);
2536         TALLOC_FREE(subreq);
2537         if (tevent_req_nterror(req, status)) {
2538                 return;
2539         }
2540         set_socket_options(state->fd, lp_socket_options());
2541         tevent_req_done(req);
2542 }
2543
2544 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2545                                       int *pfd, uint16_t *pport)
2546 {
2547         struct cli_connect_sock_state *state = tevent_req_data(
2548                 req, struct cli_connect_sock_state);
2549         NTSTATUS status;
2550
2551         if (tevent_req_is_nterror(req, &status)) {
2552                 return status;
2553         }
2554         *pfd = state->fd;
2555         *pport = state->port;
2556         return NT_STATUS_OK;
2557 }
2558
2559 struct cli_connect_nb_state {
2560         const char *desthost;
2561         int signing_state;
2562         int flags;
2563         struct cli_state *cli;
2564 };
2565
2566 static void cli_connect_nb_done(struct tevent_req *subreq);
2567
2568 static struct tevent_req *cli_connect_nb_send(
2569         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2570         const char *host, const struct sockaddr_storage *dest_ss,
2571         uint16_t port, int name_type, const char *myname,
2572         int signing_state, int flags)
2573 {
2574         struct tevent_req *req, *subreq;
2575         struct cli_connect_nb_state *state;
2576
2577         req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2578         if (req == NULL) {
2579                 return NULL;
2580         }
2581         state->signing_state = signing_state;
2582         state->flags = flags;
2583
2584         if (host != NULL) {
2585                 char *p = strchr(host, '#');
2586
2587                 if (p != NULL) {
2588                         name_type = strtol(p+1, NULL, 16);
2589                         host = talloc_strndup(state, host, p - host);
2590                         if (tevent_req_nomem(host, req)) {
2591                                 return tevent_req_post(req, ev);
2592                         }
2593                 }
2594
2595                 state->desthost = host;
2596         } else if (dest_ss != NULL) {
2597                 state->desthost = print_canonical_sockaddr(state, dest_ss);
2598                 if (tevent_req_nomem(state->desthost, req)) {
2599                         return tevent_req_post(req, ev);
2600                 }
2601         } else {
2602                 /* No host or dest_ss given. Error out. */
2603                 tevent_req_error(req, EINVAL);
2604                 return tevent_req_post(req, ev);
2605         }
2606
2607         subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2608                                        myname, port);
2609         if (tevent_req_nomem(subreq, req)) {
2610                 return tevent_req_post(req, ev);
2611         }
2612         tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2613         return req;
2614 }
2615
2616 static void cli_connect_nb_done(struct tevent_req *subreq)
2617 {
2618         struct tevent_req *req = tevent_req_callback_data(
2619                 subreq, struct tevent_req);
2620         struct cli_connect_nb_state *state = tevent_req_data(
2621                 req, struct cli_connect_nb_state);
2622         NTSTATUS status;
2623         int fd = 0;
2624         uint16_t port;
2625
2626         status = cli_connect_sock_recv(subreq, &fd, &port);
2627         TALLOC_FREE(subreq);
2628         if (tevent_req_nterror(req, status)) {
2629                 return;
2630         }
2631
2632         state->cli = cli_state_create(state, fd, state->desthost, NULL,
2633                                       state->signing_state, state->flags);
2634         if (tevent_req_nomem(state->cli, req)) {
2635                 close(fd);
2636                 return;
2637         }
2638         tevent_req_done(req);
2639 }
2640
2641 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2642                                     struct cli_state **pcli)
2643 {
2644         struct cli_connect_nb_state *state = tevent_req_data(
2645                 req, struct cli_connect_nb_state);
2646         NTSTATUS status;
2647
2648         if (tevent_req_is_nterror(req, &status)) {
2649                 return status;
2650         }
2651         *pcli = talloc_move(NULL, &state->cli);
2652         return NT_STATUS_OK;
2653 }
2654
2655 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2656                         uint16_t port, int name_type, const char *myname,
2657                         int signing_state, int flags, struct cli_state **pcli)
2658 {
2659         struct tevent_context *ev;
2660         struct tevent_req *req;
2661         NTSTATUS status = NT_STATUS_NO_MEMORY;
2662
2663         ev = samba_tevent_context_init(talloc_tos());
2664         if (ev == NULL) {
2665                 goto fail;
2666         }
2667         req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2668                                   myname, signing_state, flags);
2669         if (req == NULL) {
2670                 goto fail;
2671         }
2672         if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2673                 goto fail;
2674         }
2675         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2676                 goto fail;
2677         }
2678         status = cli_connect_nb_recv(req, pcli);
2679 fail:
2680         TALLOC_FREE(ev);
2681         return status;
2682 }
2683
2684 struct cli_start_connection_state {
2685         struct tevent_context *ev;
2686         struct cli_state *cli;
2687         int min_protocol;
2688         int max_protocol;
2689 };
2690
2691 static void cli_start_connection_connected(struct tevent_req *subreq);
2692 static void cli_start_connection_done(struct tevent_req *subreq);
2693
2694 /**
2695    establishes a connection to after the negprot. 
2696    @param output_cli A fully initialised cli structure, non-null only on success
2697    @param dest_host The netbios name of the remote host
2698    @param dest_ss (optional) The the destination IP, NULL for name based lookup
2699    @param port (optional) The destination port (0 for default)
2700 */
2701
2702 static struct tevent_req *cli_start_connection_send(
2703         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2704         const char *my_name, const char *dest_host,
2705         const struct sockaddr_storage *dest_ss, int port,
2706         int signing_state, int flags)
2707 {
2708         struct tevent_req *req, *subreq;
2709         struct cli_start_connection_state *state;
2710
2711         req = tevent_req_create(mem_ctx, &state,
2712                                 struct cli_start_connection_state);
2713         if (req == NULL) {
2714                 return NULL;
2715         }
2716         state->ev = ev;
2717
2718         if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2719                 state->min_protocol = lp_client_ipc_min_protocol();
2720                 state->max_protocol = lp_client_ipc_max_protocol();
2721         } else {
2722                 state->min_protocol = lp_client_min_protocol();
2723                 state->max_protocol = lp_client_max_protocol();
2724         }
2725
2726         subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2727                                      0x20, my_name, signing_state, flags);
2728         if (tevent_req_nomem(subreq, req)) {
2729                 return tevent_req_post(req, ev);
2730         }
2731         tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2732         return req;
2733 }
2734
2735 static void cli_start_connection_connected(struct tevent_req *subreq)
2736 {
2737         struct tevent_req *req = tevent_req_callback_data(
2738                 subreq, struct tevent_req);
2739         struct cli_start_connection_state *state = tevent_req_data(
2740                 req, struct cli_start_connection_state);
2741         NTSTATUS status;
2742
2743         status = cli_connect_nb_recv(subreq, &state->cli);
2744         TALLOC_FREE(subreq);
2745         if (tevent_req_nterror(req, status)) {
2746                 return;
2747         }
2748
2749         subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2750                                       state->cli->timeout,
2751                                       state->min_protocol,
2752                                       state->max_protocol);
2753         if (tevent_req_nomem(subreq, req)) {
2754                 return;
2755         }
2756         tevent_req_set_callback(subreq, cli_start_connection_done, req);
2757 }
2758
2759 static void cli_start_connection_done(struct tevent_req *subreq)
2760 {
2761         struct tevent_req *req = tevent_req_callback_data(
2762                 subreq, struct tevent_req);
2763         struct cli_start_connection_state *state = tevent_req_data(
2764                 req, struct cli_start_connection_state);
2765         NTSTATUS status;
2766
2767         status = smbXcli_negprot_recv(subreq);
2768         TALLOC_FREE(subreq);
2769         if (tevent_req_nterror(req, status)) {
2770                 return;
2771         }
2772
2773         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2774                 /* Ensure we ask for some initial credits. */
2775                 smb2cli_conn_set_max_credits(state->cli->conn,
2776                                              DEFAULT_SMB2_MAX_CREDITS);
2777         }
2778
2779         tevent_req_done(req);
2780 }
2781
2782 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2783                                           struct cli_state **output_cli)
2784 {
2785         struct cli_start_connection_state *state = tevent_req_data(
2786                 req, struct cli_start_connection_state);
2787         NTSTATUS status;
2788
2789         if (tevent_req_is_nterror(req, &status)) {
2790                 return status;
2791         }
2792         *output_cli = state->cli;
2793
2794         return NT_STATUS_OK;
2795 }
2796
2797 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
2798                               const char *my_name, 
2799                               const char *dest_host, 
2800                               const struct sockaddr_storage *dest_ss, int port,
2801                               int signing_state, int flags)
2802 {
2803         struct tevent_context *ev;
2804         struct tevent_req *req;
2805         NTSTATUS status = NT_STATUS_NO_MEMORY;
2806
2807         ev = samba_tevent_context_init(talloc_tos());
2808         if (ev == NULL) {
2809                 goto fail;
2810         }
2811         req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2812                                         port, signing_state, flags);
2813         if (req == NULL) {
2814                 goto fail;
2815         }
2816         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2817                 goto fail;
2818         }
2819         status = cli_start_connection_recv(req, output_cli);
2820 fail:
2821         TALLOC_FREE(ev);
2822         return status;
2823 }
2824
2825 /**
2826    establishes a connection right up to doing tconX, password specified.
2827    @param output_cli A fully initialised cli structure, non-null only on success
2828    @param dest_host The netbios name of the remote host
2829    @param dest_ip (optional) The the destination IP, NULL for name based lookup
2830    @param port (optional) The destination port (0 for default)
2831    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
2832    @param service_type The 'type' of serivice. 
2833    @param user Username, unix string
2834    @param domain User's domain
2835    @param password User's password, unencrypted unix string.
2836 */
2837
2838 struct cli_full_connection_state {
2839         struct tevent_context *ev;
2840         const char *service;
2841         const char *service_type;
2842         const char *user;
2843         const char *domain;
2844         const char *password;
2845         int pw_len;
2846         int flags;
2847         struct cli_state *cli;
2848 };
2849
2850 static int cli_full_connection_state_destructor(
2851         struct cli_full_connection_state *s);
2852 static void cli_full_connection_started(struct tevent_req *subreq);
2853 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
2854 static void cli_full_connection_done(struct tevent_req *subreq);
2855
2856 struct tevent_req *cli_full_connection_send(
2857         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2858         const char *my_name, const char *dest_host,
2859         const struct sockaddr_storage *dest_ss, int port,
2860         const char *service, const char *service_type,
2861         const char *user, const char *domain,
2862         const char *password, int flags, int signing_state)
2863 {
2864         struct tevent_req *req, *subreq;
2865         struct cli_full_connection_state *state;
2866
2867         req = tevent_req_create(mem_ctx, &state,
2868                                 struct cli_full_connection_state);
2869         if (req == NULL) {
2870                 return NULL;
2871         }
2872         talloc_set_destructor(state, cli_full_connection_state_destructor);
2873
2874         state->ev = ev;
2875         state->service = service;
2876         state->service_type = service_type;
2877         state->user = user;
2878         state->domain = domain;
2879         state->password = password;
2880         state->flags = flags;
2881
2882         state->pw_len = state->password ? strlen(state->password)+1 : 0;
2883         if (state->password == NULL) {
2884                 state->password = "";
2885         }
2886
2887         subreq = cli_start_connection_send(
2888                 state, ev, my_name, dest_host, dest_ss, port,
2889                 signing_state, flags);
2890         if (tevent_req_nomem(subreq, req)) {
2891                 return tevent_req_post(req, ev);
2892         }
2893         tevent_req_set_callback(subreq, cli_full_connection_started, req);
2894         return req;
2895 }
2896
2897 static int cli_full_connection_state_destructor(
2898         struct cli_full_connection_state *s)
2899 {
2900         if (s->cli != NULL) {
2901                 cli_shutdown(s->cli);
2902                 s->cli = NULL;
2903         }
2904         return 0;
2905 }
2906
2907 static void cli_full_connection_started(struct tevent_req *subreq)
2908 {
2909         struct tevent_req *req = tevent_req_callback_data(
2910                 subreq, struct tevent_req);
2911         struct cli_full_connection_state *state = tevent_req_data(
2912                 req, struct cli_full_connection_state);
2913         NTSTATUS status;
2914         struct cli_credentials *creds = NULL;
2915
2916         status = cli_start_connection_recv(subreq, &state->cli);
2917         TALLOC_FREE(subreq);
2918         if (tevent_req_nterror(req, status)) {
2919                 return;
2920         }
2921
2922         creds = cli_session_creds_init(state,
2923                                        state->user,
2924                                        state->domain,
2925                                        NULL, /* realm (use default) */
2926                                        state->password,
2927                                        state->cli->use_kerberos,
2928                                        state->cli->fallback_after_kerberos,
2929                                        state->cli->use_ccache,
2930                                        state->cli->pw_nt_hash);
2931         if (tevent_req_nomem(creds, req)) {
2932                 return;
2933         }
2934
2935         subreq = cli_session_setup_creds_send(
2936                 state, state->ev, state->cli, creds);
2937         if (tevent_req_nomem(subreq, req)) {
2938                 return;
2939         }
2940         tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
2941 }
2942
2943 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
2944 {
2945         struct tevent_req *req = tevent_req_callback_data(
2946                 subreq, struct tevent_req);
2947         struct cli_full_connection_state *state = tevent_req_data(
2948                 req, struct cli_full_connection_state);
2949         NTSTATUS status;
2950
2951         status = cli_session_setup_creds_recv(subreq);
2952         TALLOC_FREE(subreq);
2953
2954         if (!NT_STATUS_IS_OK(status) &&
2955             (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2956                 struct cli_credentials *creds = NULL;
2957
2958                 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2959
2960                 creds = cli_credentials_init_anon(state);
2961                 if (tevent_req_nomem(creds, req)) {
2962                         return;
2963                 }
2964
2965                 subreq = cli_session_setup_creds_send(
2966                         state, state->ev, state->cli, creds);
2967                 if (tevent_req_nomem(subreq, req)) {
2968                         return;
2969                 }
2970                 tevent_req_set_callback(
2971                         subreq, cli_full_connection_sess_set_up, req);
2972                 return;
2973         }
2974
2975         if (tevent_req_nterror(req, status)) {
2976                 return;
2977         }
2978
2979         if (state->service != NULL) {
2980                 subreq = cli_tree_connect_send(
2981                         state, state->ev, state->cli,
2982                         state->service, state->service_type,
2983                         state->password, state->pw_len);
2984                 if (tevent_req_nomem(subreq, req)) {
2985                         return;
2986                 }
2987                 tevent_req_set_callback(subreq, cli_full_connection_done, req);
2988                 return;
2989         }
2990
2991         tevent_req_done(req);
2992 }
2993
2994 static void cli_full_connection_done(struct tevent_req *subreq)
2995 {
2996         struct tevent_req *req = tevent_req_callback_data(
2997                 subreq, struct tevent_req);
2998         NTSTATUS status;
2999
3000         status = cli_tree_connect_recv(subreq);
3001         TALLOC_FREE(subreq);
3002         if (tevent_req_nterror(req, status)) {
3003                 return;
3004         }
3005
3006         tevent_req_done(req);
3007 }
3008
3009 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3010                                   struct cli_state **output_cli)
3011 {
3012         struct cli_full_connection_state *state = tevent_req_data(
3013                 req, struct cli_full_connection_state);
3014         NTSTATUS status;
3015
3016         if (tevent_req_is_nterror(req, &status)) {
3017                 return status;
3018         }
3019         *output_cli = state->cli;
3020         talloc_set_destructor(state, NULL);
3021         return NT_STATUS_OK;
3022 }
3023
3024 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3025                              const char *my_name,
3026                              const char *dest_host,
3027                              const struct sockaddr_storage *dest_ss, int port,
3028                              const char *service, const char *service_type,
3029                              const char *user, const char *domain,
3030                              const char *password, int flags,
3031                              int signing_state)
3032 {
3033         struct tevent_context *ev;
3034         struct tevent_req *req;
3035         NTSTATUS status = NT_STATUS_NO_MEMORY;
3036
3037         ev = samba_tevent_context_init(talloc_tos());
3038         if (ev == NULL) {
3039                 goto fail;
3040         }
3041         req = cli_full_connection_send(
3042                 ev, ev, my_name, dest_host, dest_ss, port, service,
3043                 service_type, user, domain, password, flags, signing_state);
3044         if (req == NULL) {
3045                 goto fail;
3046         }
3047         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3048                 goto fail;
3049         }
3050         status = cli_full_connection_recv(req, output_cli);
3051  fail:
3052         TALLOC_FREE(ev);
3053         return status;
3054 }
3055
3056 /****************************************************************************
3057  Send an old style tcon.
3058 ****************************************************************************/
3059 struct cli_raw_tcon_state {
3060         uint16_t *ret_vwv;
3061 };
3062
3063 static void cli_raw_tcon_done(struct tevent_req *subreq);
3064
3065 static struct tevent_req *cli_raw_tcon_send(
3066         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3067         const char *service, const char *pass, const char *dev)
3068 {
3069         struct tevent_req *req, *subreq;
3070         struct cli_raw_tcon_state *state;
3071         uint8_t *bytes;
3072
3073         req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3074         if (req == NULL) {
3075                 return NULL;
3076         }
3077
3078         if (!lp_client_plaintext_auth() && (*pass)) {
3079                 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3080                           " or 'client ntlmv2 auth = yes'\n"));
3081                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3082                 return tevent_req_post(req, ev);
3083         }
3084
3085         bytes = talloc_array(state, uint8_t, 0);
3086         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3087         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3088                                    service, strlen(service)+1, NULL);
3089         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3090         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3091                                    pass, strlen(pass)+1, NULL);
3092         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3093         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3094                                    dev, strlen(dev)+1, NULL);
3095
3096         if (tevent_req_nomem(bytes, req)) {
3097                 return tevent_req_post(req, ev);
3098         }
3099
3100         subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3101                               talloc_get_size(bytes), bytes);
3102         if (tevent_req_nomem(subreq, req)) {
3103                 return tevent_req_post(req, ev);
3104         }
3105         tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3106         return req;
3107 }
3108
3109 static void cli_raw_tcon_done(struct tevent_req *subreq)
3110 {
3111         struct tevent_req *req = tevent_req_callback_data(
3112                 subreq, struct tevent_req);
3113         struct cli_raw_tcon_state *state = tevent_req_data(
3114                 req, struct cli_raw_tcon_state);
3115         NTSTATUS status;
3116
3117         status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3118                               NULL, NULL);
3119         TALLOC_FREE(subreq);
3120         if (tevent_req_nterror(req, status)) {
3121                 return;
3122         }
3123         tevent_req_done(req);
3124 }
3125
3126 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3127                                   uint16_t *max_xmit, uint16_t *tid)
3128 {
3129         struct cli_raw_tcon_state *state = tevent_req_data(
3130                 req, struct cli_raw_tcon_state);
3131         NTSTATUS status;
3132
3133         if (tevent_req_is_nterror(req, &status)) {
3134                 return status;
3135         }
3136         *max_xmit = SVAL(state->ret_vwv + 0, 0);
3137         *tid = SVAL(state->ret_vwv + 1, 0);
3138         return NT_STATUS_OK;
3139 }
3140
3141 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3142                       const char *service, const char *pass, const char *dev,
3143                       uint16_t *max_xmit, uint16_t *tid)
3144 {
3145         struct tevent_context *ev;
3146         struct tevent_req *req;
3147         NTSTATUS status = NT_STATUS_NO_MEMORY;
3148
3149         ev = samba_tevent_context_init(talloc_tos());
3150         if (ev == NULL) {
3151                 goto fail;
3152         }
3153         req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3154         if (req == NULL) {
3155                 goto fail;
3156         }
3157         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3158                 goto fail;
3159         }
3160         status = cli_raw_tcon_recv(req, max_xmit, tid);
3161 fail:
3162         TALLOC_FREE(ev);
3163         return status;
3164 }
3165
3166 /* Return a cli_state pointing at the IPC$ share for the given server */
3167
3168 struct cli_state *get_ipc_connect(char *server,
3169                                 struct sockaddr_storage *server_ss,
3170                                 const struct user_auth_info *user_info)
3171 {
3172         struct cli_state *cli;
3173         NTSTATUS nt_status;
3174         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3175
3176         if (get_cmdline_auth_info_use_kerberos(user_info)) {
3177                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3178         }
3179
3180         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
3181                                         get_cmdline_auth_info_username(user_info),
3182                                         lp_workgroup(),
3183                                         get_cmdline_auth_info_password(user_info),
3184                                         flags,
3185                                         SMB_SIGNING_DEFAULT);
3186
3187         if (NT_STATUS_IS_OK(nt_status)) {
3188                 return cli;
3189         } else if (is_ipaddress(server)) {
3190             /* windows 9* needs a correct NMB name for connections */
3191             fstring remote_name;
3192
3193             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3194                 cli = get_ipc_connect(remote_name, server_ss, user_info);
3195                 if (cli)
3196                     return cli;
3197             }
3198         }
3199         return NULL;
3200 }
3201
3202 /*
3203  * Given the IP address of a master browser on the network, return its
3204  * workgroup and connect to it.
3205  *
3206  * This function is provided to allow additional processing beyond what
3207  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3208  * browsers and obtain each master browsers' list of domains (in case the
3209  * first master browser is recently on the network and has not yet
3210  * synchronized with other master browsers and therefore does not yet have the
3211  * entire network browse list)
3212  */
3213
3214 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3215                                 struct sockaddr_storage *mb_ip,
3216                                 const struct user_auth_info *user_info,
3217                                 char **pp_workgroup_out)
3218 {
3219         char addr[INET6_ADDRSTRLEN];
3220         fstring name;
3221         struct cli_state *cli;
3222         struct sockaddr_storage server_ss;
3223
3224         *pp_workgroup_out = NULL;
3225
3226         print_sockaddr(addr, sizeof(addr), mb_ip);
3227         DEBUG(99, ("Looking up name of master browser %s\n",
3228                    addr));
3229
3230         /*
3231          * Do a name status query to find out the name of the master browser.
3232          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3233          * master browser will not respond to a wildcard query (or, at least,
3234          * an NT4 server acting as the domain master browser will not).
3235          *
3236          * We might be able to use ONLY the query on MSBROWSE, but that's not
3237          * yet been tested with all Windows versions, so until it is, leave
3238          * the original wildcard query as the first choice and fall back to
3239          * MSBROWSE if the wildcard query fails.
3240          */
3241         if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3242             !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3243
3244                 DEBUG(99, ("Could not retrieve name status for %s\n",
3245                            addr));
3246                 return NULL;
3247         }
3248
3249         if (!find_master_ip(name, &server_ss)) {
3250                 DEBUG(99, ("Could not find master ip for %s\n", name));
3251                 return NULL;
3252         }
3253
3254         *pp_workgroup_out = talloc_strdup(ctx, name);
3255
3256         DEBUG(4, ("found master browser %s, %s\n", name, addr));
3257
3258         print_sockaddr(addr, sizeof(addr), &server_ss);
3259         cli = get_ipc_connect(addr, &server_ss, user_info);
3260
3261         return cli;
3262 }
3263
3264 /*
3265  * Return the IP address and workgroup of a master browser on the network, and
3266  * connect to it.
3267  */
3268
3269 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3270                                         const struct user_auth_info *user_info,
3271                                         char **pp_workgroup_out)
3272 {
3273         struct sockaddr_storage *ip_list;
3274         struct cli_state *cli;
3275         int i, count;
3276         NTSTATUS status;
3277
3278         *pp_workgroup_out = NULL;
3279
3280         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3281
3282         /* Go looking for workgroups by broadcasting on the local network */
3283
3284         status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3285                                     &ip_list, &count);
3286         if (!NT_STATUS_IS_OK(status)) {
3287                 DEBUG(99, ("No master browsers responded: %s\n",
3288                            nt_errstr(status)));
3289                 return NULL;
3290         }
3291
3292         for (i = 0; i < count; i++) {
3293                 char addr[INET6_ADDRSTRLEN];
3294                 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3295                 DEBUG(99, ("Found master browser %s\n", addr));
3296
3297                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3298                                 user_info, pp_workgroup_out);
3299                 if (cli)
3300                         return(cli);
3301         }
3302
3303         return NULL;
3304 }