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