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