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