s3:libsmb: add cli_tree_connect_creds()
[nivanova/samba-autobuild/.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6    Copyright (C) Volker Lendecke 2011
7    Copyright (C) Jeremy Allison 2011
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
34 #include "krb5_env.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
40 #include "lib/param/param.h"
41
42 #define STAR_SMBSERVER "*SMBSERVER"
43
44 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
45                                            const char *principal);
46
47 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 user level LM password but "
1506                                   "'client lanman auth = no' is set.\n"));
1507                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1508                         return tevent_req_post(req, ev);
1509                 }
1510
1511                 flags |= CLI_CRED_LANMAN_AUTH;
1512         }
1513
1514         status = cli_credentials_get_ntlm_response(creds, state, &flags,
1515                                                    challenge, NULL,
1516                                                    target_info,
1517                                                    &state->apassword_blob,
1518                                                    &state->upassword_blob,
1519                                                    &state->lm_session_key,
1520                                                    &state->session_key);
1521         if (tevent_req_nterror(req, status)) {
1522                 return tevent_req_post(req, ev);
1523         }
1524
1525 non_spnego_creds_done:
1526
1527         in_buf_size = CLI_BUFFER_SIZE;
1528         in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1529         in_vc_num = cli_state_get_vc_num(cli);
1530         in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1531         in_native_os = "Unix";
1532         in_native_lm = "Samba";
1533
1534         if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1535                 uint32_t in_capabilities = 0;
1536
1537                 in_capabilities = cli_session_setup_capabilities(cli, 0);
1538
1539                 /*
1540                  * For now we keep the same values as before,
1541                  * we may remove these in a separate commit later.
1542                  */
1543                 in_mpx_max = 2;
1544
1545                 subreq = smb1cli_session_setup_nt1_send(state, ev,
1546                                                         cli->conn,
1547                                                         cli->timeout,
1548                                                         cli->smb1.pid,
1549                                                         cli->smb1.session,
1550                                                         in_buf_size,
1551                                                         in_mpx_max,
1552                                                         in_vc_num,
1553                                                         in_sess_key,
1554                                                         username,
1555                                                         domain,
1556                                                         state->apassword_blob,
1557                                                         state->upassword_blob,
1558                                                         in_capabilities,
1559                                                         in_native_os,
1560                                                         in_native_lm);
1561                 if (tevent_req_nomem(subreq, req)) {
1562                         return tevent_req_post(req, ev);
1563                 }
1564                 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1565                                         req);
1566                 return req;
1567         }
1568
1569         /*
1570          * For now we keep the same values as before,
1571          * we may remove these in a separate commit later.
1572          */
1573         in_mpx_max = 2;
1574         in_vc_num = 1;
1575
1576         subreq = smb1cli_session_setup_lm21_send(state, ev,
1577                                                  cli->conn,
1578                                                  cli->timeout,
1579                                                  cli->smb1.pid,
1580                                                  cli->smb1.session,
1581                                                  in_buf_size,
1582                                                  in_mpx_max,
1583                                                  in_vc_num,
1584                                                  in_sess_key,
1585                                                  username,
1586                                                  domain,
1587                                                  state->apassword_blob,
1588                                                  in_native_os,
1589                                                  in_native_lm);
1590         if (tevent_req_nomem(subreq, req)) {
1591                 return tevent_req_post(req, ev);
1592         }
1593         tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1594                                 req);
1595         return req;
1596 }
1597
1598 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1599 {
1600         struct tevent_req *req = tevent_req_callback_data(
1601                 subreq, struct tevent_req);
1602         ADS_STATUS status;
1603
1604         status = cli_session_setup_spnego_recv(subreq);
1605         TALLOC_FREE(subreq);
1606         if (!ADS_ERR_OK(status)) {
1607                 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1608                 tevent_req_nterror(req, ads_ntstatus(status));
1609                 return;
1610         }
1611         tevent_req_done(req);
1612 }
1613
1614 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1615 {
1616         struct tevent_req *req = tevent_req_callback_data(
1617                 subreq, struct tevent_req);
1618         struct cli_session_setup_creds_state *state = tevent_req_data(
1619                 req, struct cli_session_setup_creds_state);
1620         struct cli_state *cli = state->cli;
1621         NTSTATUS status;
1622         struct iovec *recv_iov = NULL;
1623         const uint8_t *inbuf = NULL;
1624         bool ok;
1625
1626         status = smb1cli_session_setup_nt1_recv(subreq, state,
1627                                                 &recv_iov,
1628                                                 &inbuf,
1629                                                 &state->out_native_os,
1630                                                 &state->out_native_lm,
1631                                                 &state->out_primary_domain);
1632         TALLOC_FREE(subreq);
1633         if (!NT_STATUS_IS_OK(status)) {
1634                 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1635                 tevent_req_nterror(req, status);
1636                 return;
1637         }
1638
1639         if (cli->server_os == NULL) {
1640                 cli->server_os = talloc_move(cli, &state->out_native_os);
1641         }
1642         if (cli->server_type == NULL) {
1643                 cli->server_type = talloc_move(cli, &state->out_native_lm);
1644         }
1645         if (cli->server_domain == NULL) {
1646                 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1647         }
1648
1649         ok = smb1cli_conn_activate_signing(cli->conn,
1650                                            state->session_key,
1651                                            state->upassword_blob);
1652         if (ok) {
1653                 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1654                 if (!ok) {
1655                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1656                         return;
1657                 }
1658         }
1659
1660         if (state->session_key.data) {
1661                 struct smbXcli_session *session = cli->smb1.session;
1662
1663                 status = smb1cli_session_set_session_key(session,
1664                                                          state->session_key);
1665                 if (tevent_req_nterror(req, status)) {
1666                         return;
1667                 }
1668         }
1669
1670         tevent_req_done(req);
1671 }
1672
1673 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1674 {
1675         struct tevent_req *req = tevent_req_callback_data(
1676                 subreq, struct tevent_req);
1677         struct cli_session_setup_creds_state *state = tevent_req_data(
1678                 req, struct cli_session_setup_creds_state);
1679         struct cli_state *cli = state->cli;
1680         NTSTATUS status;
1681
1682         status = smb1cli_session_setup_lm21_recv(subreq, state,
1683                                                  &state->out_native_os,
1684                                                  &state->out_native_lm);
1685         TALLOC_FREE(subreq);
1686         if (!NT_STATUS_IS_OK(status)) {
1687                 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1688                 tevent_req_nterror(req, status);
1689                 return;
1690         }
1691
1692         if (cli->server_os == NULL) {
1693                 cli->server_os = talloc_move(cli, &state->out_native_os);
1694         }
1695         if (cli->server_type == NULL) {
1696                 cli->server_type = talloc_move(cli, &state->out_native_lm);
1697         }
1698
1699         tevent_req_done(req);
1700 }
1701
1702 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1703 {
1704         return tevent_req_simple_recv_ntstatus(req);
1705 }
1706
1707 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1708                                  struct cli_credentials *creds)
1709 {
1710         struct tevent_context *ev;
1711         struct tevent_req *req;
1712         NTSTATUS status = NT_STATUS_NO_MEMORY;
1713
1714         if (smbXcli_conn_has_async_calls(cli->conn)) {
1715                 return NT_STATUS_INVALID_PARAMETER;
1716         }
1717         ev = samba_tevent_context_init(talloc_tos());
1718         if (ev == NULL) {
1719                 goto fail;
1720         }
1721         req = cli_session_setup_creds_send(ev, ev, cli, creds);
1722         if (req == NULL) {
1723                 goto fail;
1724         }
1725         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1726                 goto fail;
1727         }
1728         status = cli_session_setup_creds_recv(req);
1729  fail:
1730         TALLOC_FREE(ev);
1731         return status;
1732 }
1733
1734 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1735 {
1736         NTSTATUS status = NT_STATUS_NO_MEMORY;
1737         struct cli_credentials *creds = NULL;
1738
1739         creds = cli_credentials_init_anon(cli);
1740         if (creds == NULL) {
1741                 return NT_STATUS_NO_MEMORY;
1742         }
1743
1744         status = cli_session_setup_creds(cli, creds);
1745         TALLOC_FREE(creds);
1746         if (!NT_STATUS_IS_OK(status)) {
1747                 return status;
1748         }
1749
1750         return NT_STATUS_OK;
1751 }
1752
1753 NTSTATUS cli_session_setup(struct cli_state *cli,
1754                            const char *user,
1755                            const char *pass,
1756                            const char *workgroup)
1757 {
1758         NTSTATUS status = NT_STATUS_NO_MEMORY;
1759         const char *dest_realm = NULL;
1760         struct cli_credentials *creds = NULL;
1761
1762         /*
1763          * dest_realm is only valid in the winbindd use case,
1764          * where we also have the account in that realm.
1765          */
1766         dest_realm = cli_state_remote_realm(cli);
1767
1768         creds = cli_session_creds_init(cli,
1769                                        user,
1770                                        workgroup,
1771                                        dest_realm,
1772                                        pass,
1773                                        cli->use_kerberos,
1774                                        cli->fallback_after_kerberos,
1775                                        cli->use_ccache,
1776                                        cli->pw_nt_hash);
1777         if (creds == NULL) {
1778                 return NT_STATUS_NO_MEMORY;
1779         }
1780
1781         status = cli_session_setup_creds(cli, creds);
1782         TALLOC_FREE(creds);
1783         if (!NT_STATUS_IS_OK(status)) {
1784                 return status;
1785         }
1786
1787         return NT_STATUS_OK;
1788 }
1789
1790 /****************************************************************************
1791  Send a uloggoff.
1792 *****************************************************************************/
1793
1794 struct cli_ulogoff_state {
1795         struct cli_state *cli;
1796         uint16_t vwv[3];
1797 };
1798
1799 static void cli_ulogoff_done(struct tevent_req *subreq);
1800
1801 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1802                                     struct tevent_context *ev,
1803                                     struct cli_state *cli)
1804 {
1805         struct tevent_req *req, *subreq;
1806         struct cli_ulogoff_state *state;
1807
1808         req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1809         if (req == NULL) {
1810                 return NULL;
1811         }
1812         state->cli = cli;
1813
1814         SCVAL(state->vwv+0, 0, 0xFF);
1815         SCVAL(state->vwv+1, 0, 0);
1816         SSVAL(state->vwv+2, 0, 0);
1817
1818         subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1819                               0, NULL);
1820         if (tevent_req_nomem(subreq, req)) {
1821                 return tevent_req_post(req, ev);
1822         }
1823         tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1824         return req;
1825 }
1826
1827 static void cli_ulogoff_done(struct tevent_req *subreq)
1828 {
1829         struct tevent_req *req = tevent_req_callback_data(
1830                 subreq, struct tevent_req);
1831         struct cli_ulogoff_state *state = tevent_req_data(
1832                 req, struct cli_ulogoff_state);
1833         NTSTATUS status;
1834
1835         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1836         if (!NT_STATUS_IS_OK(status)) {
1837                 tevent_req_nterror(req, status);
1838                 return;
1839         }
1840         cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1841         tevent_req_done(req);
1842 }
1843
1844 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1845 {
1846         return tevent_req_simple_recv_ntstatus(req);
1847 }
1848
1849 NTSTATUS cli_ulogoff(struct cli_state *cli)
1850 {
1851         struct tevent_context *ev;
1852         struct tevent_req *req;
1853         NTSTATUS status = NT_STATUS_NO_MEMORY;
1854
1855         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1856                 status = smb2cli_logoff(cli->conn,
1857                                         cli->timeout,
1858                                         cli->smb2.session);
1859                 if (!NT_STATUS_IS_OK(status)) {
1860                         return status;
1861                 }
1862                 smb2cli_session_set_id_and_flags(cli->smb2.session,
1863                                                  UINT64_MAX, 0);
1864                 return NT_STATUS_OK;
1865         }
1866
1867         if (smbXcli_conn_has_async_calls(cli->conn)) {
1868                 return NT_STATUS_INVALID_PARAMETER;
1869         }
1870         ev = samba_tevent_context_init(talloc_tos());
1871         if (ev == NULL) {
1872                 goto fail;
1873         }
1874         req = cli_ulogoff_send(ev, ev, cli);
1875         if (req == NULL) {
1876                 goto fail;
1877         }
1878         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1879                 goto fail;
1880         }
1881         status = cli_ulogoff_recv(req);
1882 fail:
1883         TALLOC_FREE(ev);
1884         return status;
1885 }
1886
1887 /****************************************************************************
1888  Send a tconX.
1889 ****************************************************************************/
1890
1891 struct cli_tcon_andx_state {
1892         struct cli_state *cli;
1893         uint16_t vwv[4];
1894         struct iovec bytes;
1895 };
1896
1897 static void cli_tcon_andx_done(struct tevent_req *subreq);
1898
1899 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1900                                         struct tevent_context *ev,
1901                                         struct cli_state *cli,
1902                                         const char *share, const char *dev,
1903                                         const char *pass, int passlen,
1904                                         struct tevent_req **psmbreq)
1905 {
1906         struct tevent_req *req, *subreq;
1907         struct cli_tcon_andx_state *state;
1908         uint8_t p24[24];
1909         uint16_t *vwv;
1910         char *tmp = NULL;
1911         uint8_t *bytes;
1912         uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1913         uint16_t tcon_flags = 0;
1914
1915         *psmbreq = NULL;
1916
1917         req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1918         if (req == NULL) {
1919                 return NULL;
1920         }
1921         state->cli = cli;
1922         vwv = state->vwv;
1923
1924         cli->share = talloc_strdup(cli, share);
1925         if (!cli->share) {
1926                 return NULL;
1927         }
1928
1929         /* in user level security don't send a password now */
1930         if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1931                 passlen = 1;
1932                 pass = "";
1933         } else if (pass == NULL) {
1934                 DEBUG(1, ("Server not using user level security and no "
1935                           "password supplied.\n"));
1936                 goto access_denied;
1937         }
1938
1939         if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1940             *pass && passlen != 24) {
1941                 if (!lp_client_lanman_auth()) {
1942                         DEBUG(1, ("Server requested LANMAN password "
1943                                   "(share-level security) but "
1944                                   "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1945                         goto access_denied;
1946                 }
1947
1948                 /*
1949                  * Non-encrypted passwords - convert to DOS codepage before
1950                  * encryption.
1951                  */
1952                 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1953                 passlen = 24;
1954                 pass = (const char *)p24;
1955         } else {
1956                 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1957                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1958                    == 0) {
1959                         uint8_t *tmp_pass;
1960
1961                         if (!lp_client_plaintext_auth() && (*pass)) {
1962                                 DEBUG(1, ("Server requested PLAINTEXT "
1963                                           "password but "
1964                                           "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1965                                 goto access_denied;
1966                         }
1967
1968                         /*
1969                          * Non-encrypted passwords - convert to DOS codepage
1970                          * before using.
1971                          */
1972                         tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1973                         if (tevent_req_nomem(tmp_pass, req)) {
1974                                 return tevent_req_post(req, ev);
1975                         }
1976                         tmp_pass = trans2_bytes_push_str(tmp_pass,
1977                                                          false, /* always DOS */
1978                                                          pass,
1979                                                          passlen,
1980                                                          NULL);
1981                         if (tevent_req_nomem(tmp_pass, req)) {
1982                                 return tevent_req_post(req, ev);
1983                         }
1984                         pass = (const char *)tmp_pass;
1985                         passlen = talloc_get_size(tmp_pass);
1986                 }
1987         }
1988
1989         tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1990         tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1991
1992         SCVAL(vwv+0, 0, 0xFF);
1993         SCVAL(vwv+0, 1, 0);
1994         SSVAL(vwv+1, 0, 0);
1995         SSVAL(vwv+2, 0, tcon_flags);
1996         SSVAL(vwv+3, 0, passlen);
1997
1998         if (passlen && pass) {
1999                 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2000         } else {
2001                 bytes = talloc_array(state, uint8_t, 0);
2002         }
2003
2004         /*
2005          * Add the sharename
2006          */
2007         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2008                                          smbXcli_conn_remote_name(cli->conn), share);
2009         if (tmp == NULL) {
2010                 TALLOC_FREE(req);
2011                 return NULL;
2012         }
2013         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2014                                    NULL);
2015         TALLOC_FREE(tmp);
2016
2017         /*
2018          * Add the devicetype
2019          */
2020         tmp = talloc_strdup_upper(talloc_tos(), dev);
2021         if (tmp == NULL) {
2022                 TALLOC_FREE(req);
2023                 return NULL;
2024         }
2025         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2026         TALLOC_FREE(tmp);
2027
2028         if (bytes == NULL) {
2029                 TALLOC_FREE(req);
2030                 return NULL;
2031         }
2032
2033         state->bytes.iov_base = (void *)bytes;
2034         state->bytes.iov_len = talloc_get_size(bytes);
2035
2036         subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2037                                     1, &state->bytes);
2038         if (subreq == NULL) {
2039                 TALLOC_FREE(req);
2040                 return NULL;
2041         }
2042         tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2043         *psmbreq = subreq;
2044         return req;
2045
2046  access_denied:
2047         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2048         return tevent_req_post(req, ev);
2049 }
2050
2051 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2052                                       struct tevent_context *ev,
2053                                       struct cli_state *cli,
2054                                       const char *share, const char *dev,
2055                                       const char *pass, int passlen)
2056 {
2057         struct tevent_req *req, *subreq;
2058         NTSTATUS status;
2059
2060         req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2061                                    &subreq);
2062         if (req == NULL) {
2063                 return NULL;
2064         }
2065         if (subreq == NULL) {
2066                 return req;
2067         }
2068         status = smb1cli_req_chain_submit(&subreq, 1);
2069         if (!NT_STATUS_IS_OK(status)) {
2070                 tevent_req_nterror(req, status);
2071                 return tevent_req_post(req, ev);
2072         }
2073         return req;
2074 }
2075
2076 static void cli_tcon_andx_done(struct tevent_req *subreq)
2077 {
2078         struct tevent_req *req = tevent_req_callback_data(
2079                 subreq, struct tevent_req);
2080         struct cli_tcon_andx_state *state = tevent_req_data(
2081                 req, struct cli_tcon_andx_state);
2082         struct cli_state *cli = state->cli;
2083         uint8_t *in;
2084         uint8_t *inhdr;
2085         uint8_t wct;
2086         uint16_t *vwv;
2087         uint32_t num_bytes;
2088         uint8_t *bytes;
2089         NTSTATUS status;
2090         uint16_t optional_support = 0;
2091
2092         status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2093                               &num_bytes, &bytes);
2094         TALLOC_FREE(subreq);
2095         if (!NT_STATUS_IS_OK(status)) {
2096                 tevent_req_nterror(req, status);
2097                 return;
2098         }
2099
2100         inhdr = in + NBT_HDR_SIZE;
2101
2102         if (num_bytes) {
2103                 if (clistr_pull_talloc(cli,
2104                                 (const char *)inhdr,
2105                                 SVAL(inhdr, HDR_FLG2),
2106                                 &cli->dev,
2107                                 bytes,
2108                                 num_bytes,
2109                                 STR_TERMINATE|STR_ASCII) == -1) {
2110                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2111                         return;
2112                 }
2113         } else {
2114                 cli->dev = talloc_strdup(cli, "");
2115                 if (cli->dev == NULL) {
2116                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2117                         return;
2118                 }
2119         }
2120
2121         if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2122                 /* almost certainly win95 - enable bug fixes */
2123                 cli->win95 = True;
2124         }
2125
2126         /*
2127          * Make sure that we have the optional support 16-bit field. WCT > 2.
2128          * Avoids issues when connecting to Win9x boxes sharing files
2129          */
2130
2131         if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2132                 optional_support = SVAL(vwv+2, 0);
2133         }
2134
2135         if (optional_support & SMB_EXTENDED_SIGNATURES) {
2136                 smb1cli_session_protect_session_key(cli->smb1.session);
2137         }
2138
2139         smb1cli_tcon_set_values(state->cli->smb1.tcon,
2140                                 SVAL(inhdr, HDR_TID),
2141                                 optional_support,
2142                                 0, /* maximal_access */
2143                                 0, /* guest_maximal_access */
2144                                 NULL, /* service */
2145                                 NULL); /* fs_type */
2146
2147         tevent_req_done(req);
2148 }
2149
2150 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2151 {
2152         return tevent_req_simple_recv_ntstatus(req);
2153 }
2154
2155 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2156                        const char *dev, const char *pass, int passlen)
2157 {
2158         TALLOC_CTX *frame = talloc_stackframe();
2159         struct tevent_context *ev;
2160         struct tevent_req *req;
2161         NTSTATUS status = NT_STATUS_NO_MEMORY;
2162
2163         if (smbXcli_conn_has_async_calls(cli->conn)) {
2164                 /*
2165                  * Can't use sync call while an async call is in flight
2166                  */
2167                 status = NT_STATUS_INVALID_PARAMETER;
2168                 goto fail;
2169         }
2170
2171         ev = samba_tevent_context_init(frame);
2172         if (ev == NULL) {
2173                 goto fail;
2174         }
2175
2176         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2177         if (req == NULL) {
2178                 goto fail;
2179         }
2180
2181         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2182                 goto fail;
2183         }
2184
2185         status = cli_tcon_andx_recv(req);
2186  fail:
2187         TALLOC_FREE(frame);
2188         return status;
2189 }
2190
2191 struct cli_tree_connect_state {
2192         struct cli_state *cli;
2193 };
2194
2195 static struct tevent_req *cli_raw_tcon_send(
2196         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2197         const char *service, const char *pass, const char *dev);
2198 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2199                                   uint16_t *max_xmit, uint16_t *tid);
2200
2201 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2202 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2203 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2204
2205 static struct tevent_req *cli_tree_connect_send(
2206         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2207         const char *share, const char *dev, const char *pass, int passlen)
2208 {
2209         struct tevent_req *req, *subreq;
2210         struct cli_tree_connect_state *state;
2211
2212         req = tevent_req_create(mem_ctx, &state,
2213                                 struct cli_tree_connect_state);
2214         if (req == NULL) {
2215                 return NULL;
2216         }
2217         state->cli = cli;
2218
2219         cli->share = talloc_strdup(cli, share);
2220         if (tevent_req_nomem(cli->share, req)) {
2221                 return tevent_req_post(req, ev);
2222         }
2223
2224         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2225                 char *unc;
2226
2227                 cli->smb2.tcon = smbXcli_tcon_create(cli);
2228                 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2229                         return tevent_req_post(req, ev);
2230                 }
2231
2232                 unc = talloc_asprintf(state, "\\\\%s\\%s",
2233                                       smbXcli_conn_remote_name(cli->conn),
2234                                       share);
2235                 if (tevent_req_nomem(unc, req)) {
2236                         return tevent_req_post(req, ev);
2237                 }
2238
2239                 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2240                                            cli->smb2.session, cli->smb2.tcon,
2241                                            0, /* flags */
2242                                            unc);
2243                 if (tevent_req_nomem(subreq, req)) {
2244                         return tevent_req_post(req, ev);
2245                 }
2246                 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2247                                         req);
2248                 return req;
2249         }
2250
2251         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2252                 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2253                                             pass, passlen);
2254                 if (tevent_req_nomem(subreq, req)) {
2255                         return tevent_req_post(req, ev);
2256                 }
2257                 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2258                                         req);
2259                 return req;
2260         }
2261
2262         subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2263         if (tevent_req_nomem(subreq, req)) {
2264                 return tevent_req_post(req, ev);
2265         }
2266         tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2267
2268         return req;
2269 }
2270
2271 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2272 {
2273         tevent_req_simple_finish_ntstatus(
2274                 subreq, smb2cli_tcon_recv(subreq));
2275 }
2276
2277 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2278 {
2279         tevent_req_simple_finish_ntstatus(
2280                 subreq, cli_tcon_andx_recv(subreq));
2281 }
2282
2283 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2284 {
2285         struct tevent_req *req = tevent_req_callback_data(
2286                 subreq, struct tevent_req);
2287         struct cli_tree_connect_state *state = tevent_req_data(
2288                 req, struct cli_tree_connect_state);
2289         NTSTATUS status;
2290         uint16_t max_xmit = 0;
2291         uint16_t tid = 0;
2292
2293         status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2294         if (tevent_req_nterror(req, status)) {
2295                 return;
2296         }
2297
2298         smb1cli_tcon_set_values(state->cli->smb1.tcon,
2299                                 tid,
2300                                 0, /* optional_support */
2301                                 0, /* maximal_access */
2302                                 0, /* guest_maximal_access */
2303                                 NULL, /* service */
2304                                 NULL); /* fs_type */
2305
2306         tevent_req_done(req);
2307 }
2308
2309 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2310 {
2311         return tevent_req_simple_recv_ntstatus(req);
2312 }
2313
2314 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2315                           const char *dev, const char *pass, int passlen)
2316 {
2317         struct tevent_context *ev;
2318         struct tevent_req *req;
2319         NTSTATUS status = NT_STATUS_NO_MEMORY;
2320
2321         if (smbXcli_conn_has_async_calls(cli->conn)) {
2322                 return NT_STATUS_INVALID_PARAMETER;
2323         }
2324         ev = samba_tevent_context_init(talloc_tos());
2325         if (ev == NULL) {
2326                 goto fail;
2327         }
2328         req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2329         if (req == NULL) {
2330                 goto fail;
2331         }
2332         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2333                 goto fail;
2334         }
2335         status = cli_tree_connect_recv(req);
2336 fail:
2337         TALLOC_FREE(ev);
2338         return status;
2339 }
2340
2341 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2342                                 const char *share, const char *dev,
2343                                 struct cli_credentials *creds)
2344 {
2345         const char *pw = NULL;
2346         size_t pw_len = 0;
2347
2348         if (creds != NULL) {
2349                 pw = cli_credentials_get_password(creds);
2350         }
2351
2352         if (pw == NULL) {
2353                 pw = "";
2354         }
2355         pw_len = strlen(pw) + 1;
2356
2357         return cli_tree_connect(cli, share, dev, pw, pw_len);
2358 }
2359
2360 /****************************************************************************
2361  Send a tree disconnect.
2362 ****************************************************************************/
2363
2364 struct cli_tdis_state {
2365         struct cli_state *cli;
2366 };
2367
2368 static void cli_tdis_done(struct tevent_req *subreq);
2369
2370 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2371                                  struct tevent_context *ev,
2372                                  struct cli_state *cli)
2373 {
2374         struct tevent_req *req, *subreq;
2375         struct cli_tdis_state *state;
2376
2377         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2378         if (req == NULL) {
2379                 return NULL;
2380         }
2381         state->cli = cli;
2382
2383         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2384         if (tevent_req_nomem(subreq, req)) {
2385                 return tevent_req_post(req, ev);
2386         }
2387         tevent_req_set_callback(subreq, cli_tdis_done, req);
2388         return req;
2389 }
2390
2391 static void cli_tdis_done(struct tevent_req *subreq)
2392 {
2393         struct tevent_req *req = tevent_req_callback_data(
2394                 subreq, struct tevent_req);
2395         struct cli_tdis_state *state = tevent_req_data(
2396                 req, struct cli_tdis_state);
2397         NTSTATUS status;
2398
2399         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2400         TALLOC_FREE(subreq);
2401         if (!NT_STATUS_IS_OK(status)) {
2402                 tevent_req_nterror(req, status);
2403                 return;
2404         }
2405         cli_state_set_tid(state->cli, UINT16_MAX);
2406         tevent_req_done(req);
2407 }
2408
2409 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2410 {
2411         return tevent_req_simple_recv_ntstatus(req);
2412 }
2413
2414 NTSTATUS cli_tdis(struct cli_state *cli)
2415 {
2416         struct tevent_context *ev;
2417         struct tevent_req *req;
2418         NTSTATUS status = NT_STATUS_NO_MEMORY;
2419
2420         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2421                 return smb2cli_tdis(cli->conn,
2422                                     cli->timeout,
2423                                     cli->smb2.session,
2424                                     cli->smb2.tcon);
2425         }
2426
2427         if (smbXcli_conn_has_async_calls(cli->conn)) {
2428                 return NT_STATUS_INVALID_PARAMETER;
2429         }
2430         ev = samba_tevent_context_init(talloc_tos());
2431         if (ev == NULL) {
2432                 goto fail;
2433         }
2434         req = cli_tdis_send(ev, ev, cli);
2435         if (req == NULL) {
2436                 goto fail;
2437         }
2438         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2439                 goto fail;
2440         }
2441         status = cli_tdis_recv(req);
2442 fail:
2443         TALLOC_FREE(ev);
2444         return status;
2445 }
2446
2447 struct cli_connect_sock_state {
2448         const char **called_names;
2449         const char **calling_names;
2450         int *called_types;
2451         int fd;
2452         uint16_t port;
2453 };
2454
2455 static void cli_connect_sock_done(struct tevent_req *subreq);
2456
2457 /*
2458  * Async only if we don't have to look up the name, i.e. "pss" is set with a
2459  * nonzero address.
2460  */
2461
2462 static struct tevent_req *cli_connect_sock_send(
2463         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2464         const char *host, int name_type, const struct sockaddr_storage *pss,
2465         const char *myname, uint16_t port)
2466 {
2467         struct tevent_req *req, *subreq;
2468         struct cli_connect_sock_state *state;
2469         const char *prog;
2470         struct sockaddr_storage *addrs;
2471         unsigned i, num_addrs;
2472         NTSTATUS status;
2473
2474         req = tevent_req_create(mem_ctx, &state,
2475                                 struct cli_connect_sock_state);
2476         if (req == NULL) {
2477                 return NULL;
2478         }
2479
2480         prog = getenv("LIBSMB_PROG");
2481         if (prog != NULL) {
2482                 state->fd = sock_exec(prog);
2483                 if (state->fd == -1) {
2484                         status = map_nt_error_from_unix(errno);
2485                         tevent_req_nterror(req, status);
2486                 } else {
2487                         state->port = 0;
2488                         tevent_req_done(req);
2489                 }
2490                 return tevent_req_post(req, ev);
2491         }
2492
2493         if ((pss == NULL) || is_zero_addr(pss)) {
2494
2495                 /*
2496                  * Here we cheat. resolve_name_list is not async at all. So
2497                  * this call will only be really async if the name lookup has
2498                  * been done externally.
2499                  */
2500
2501                 status = resolve_name_list(state, host, name_type,
2502                                            &addrs, &num_addrs);
2503                 if (!NT_STATUS_IS_OK(status)) {
2504                         tevent_req_nterror(req, status);
2505                         return tevent_req_post(req, ev);
2506                 }
2507         } else {
2508                 addrs = talloc_array(state, struct sockaddr_storage, 1);
2509                 if (tevent_req_nomem(addrs, req)) {
2510                         return tevent_req_post(req, ev);
2511                 }
2512                 addrs[0] = *pss;
2513                 num_addrs = 1;
2514         }
2515
2516         state->called_names = talloc_array(state, const char *, num_addrs);
2517         if (tevent_req_nomem(state->called_names, req)) {
2518                 return tevent_req_post(req, ev);
2519         }
2520         state->called_types = talloc_array(state, int, num_addrs);
2521         if (tevent_req_nomem(state->called_types, req)) {
2522                 return tevent_req_post(req, ev);
2523         }
2524         state->calling_names = talloc_array(state, const char *, num_addrs);
2525         if (tevent_req_nomem(state->calling_names, req)) {
2526                 return tevent_req_post(req, ev);
2527         }
2528         for (i=0; i<num_addrs; i++) {
2529                 state->called_names[i] = host;
2530                 state->called_types[i] = name_type;
2531                 state->calling_names[i] = myname;
2532         }
2533
2534         subreq = smbsock_any_connect_send(
2535                 state, ev, addrs, state->called_names, state->called_types,
2536                 state->calling_names, NULL, num_addrs, port);
2537         if (tevent_req_nomem(subreq, req)) {
2538                 return tevent_req_post(req, ev);
2539         }
2540         tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2541         return req;
2542 }
2543
2544 static void cli_connect_sock_done(struct tevent_req *subreq)
2545 {
2546         struct tevent_req *req = tevent_req_callback_data(
2547                 subreq, struct tevent_req);
2548         struct cli_connect_sock_state *state = tevent_req_data(
2549                 req, struct cli_connect_sock_state);
2550         NTSTATUS status;
2551
2552         status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2553                                           &state->port);
2554         TALLOC_FREE(subreq);
2555         if (tevent_req_nterror(req, status)) {
2556                 return;
2557         }
2558         set_socket_options(state->fd, lp_socket_options());
2559         tevent_req_done(req);
2560 }
2561
2562 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2563                                       int *pfd, uint16_t *pport)
2564 {
2565         struct cli_connect_sock_state *state = tevent_req_data(
2566                 req, struct cli_connect_sock_state);
2567         NTSTATUS status;
2568
2569         if (tevent_req_is_nterror(req, &status)) {
2570                 return status;
2571         }
2572         *pfd = state->fd;
2573         *pport = state->port;
2574         return NT_STATUS_OK;
2575 }
2576
2577 struct cli_connect_nb_state {
2578         const char *desthost;
2579         int signing_state;
2580         int flags;
2581         struct cli_state *cli;
2582 };
2583
2584 static void cli_connect_nb_done(struct tevent_req *subreq);
2585
2586 static struct tevent_req *cli_connect_nb_send(
2587         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2588         const char *host, const struct sockaddr_storage *dest_ss,
2589         uint16_t port, int name_type, const char *myname,
2590         int signing_state, int flags)
2591 {
2592         struct tevent_req *req, *subreq;
2593         struct cli_connect_nb_state *state;
2594
2595         req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2596         if (req == NULL) {
2597                 return NULL;
2598         }
2599         state->signing_state = signing_state;
2600         state->flags = flags;
2601
2602         if (host != NULL) {
2603                 char *p = strchr(host, '#');
2604
2605                 if (p != NULL) {
2606                         name_type = strtol(p+1, NULL, 16);
2607                         host = talloc_strndup(state, host, p - host);
2608                         if (tevent_req_nomem(host, req)) {
2609                                 return tevent_req_post(req, ev);
2610                         }
2611                 }
2612
2613                 state->desthost = host;
2614         } else if (dest_ss != NULL) {
2615                 state->desthost = print_canonical_sockaddr(state, dest_ss);
2616                 if (tevent_req_nomem(state->desthost, req)) {
2617                         return tevent_req_post(req, ev);
2618                 }
2619         } else {
2620                 /* No host or dest_ss given. Error out. */
2621                 tevent_req_error(req, EINVAL);
2622                 return tevent_req_post(req, ev);
2623         }
2624
2625         subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2626                                        myname, port);
2627         if (tevent_req_nomem(subreq, req)) {
2628                 return tevent_req_post(req, ev);
2629         }
2630         tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2631         return req;
2632 }
2633
2634 static void cli_connect_nb_done(struct tevent_req *subreq)
2635 {
2636         struct tevent_req *req = tevent_req_callback_data(
2637                 subreq, struct tevent_req);
2638         struct cli_connect_nb_state *state = tevent_req_data(
2639                 req, struct cli_connect_nb_state);
2640         NTSTATUS status;
2641         int fd = 0;
2642         uint16_t port;
2643
2644         status = cli_connect_sock_recv(subreq, &fd, &port);
2645         TALLOC_FREE(subreq);
2646         if (tevent_req_nterror(req, status)) {
2647                 return;
2648         }
2649
2650         state->cli = cli_state_create(state, fd, state->desthost, NULL,
2651                                       state->signing_state, state->flags);
2652         if (tevent_req_nomem(state->cli, req)) {
2653                 close(fd);
2654                 return;
2655         }
2656         tevent_req_done(req);
2657 }
2658
2659 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2660                                     struct cli_state **pcli)
2661 {
2662         struct cli_connect_nb_state *state = tevent_req_data(
2663                 req, struct cli_connect_nb_state);
2664         NTSTATUS status;
2665
2666         if (tevent_req_is_nterror(req, &status)) {
2667                 return status;
2668         }
2669         *pcli = talloc_move(NULL, &state->cli);
2670         return NT_STATUS_OK;
2671 }
2672
2673 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2674                         uint16_t port, int name_type, const char *myname,
2675                         int signing_state, int flags, struct cli_state **pcli)
2676 {
2677         struct tevent_context *ev;
2678         struct tevent_req *req;
2679         NTSTATUS status = NT_STATUS_NO_MEMORY;
2680
2681         ev = samba_tevent_context_init(talloc_tos());
2682         if (ev == NULL) {
2683                 goto fail;
2684         }
2685         req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2686                                   myname, signing_state, flags);
2687         if (req == NULL) {
2688                 goto fail;
2689         }
2690         if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2691                 goto fail;
2692         }
2693         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2694                 goto fail;
2695         }
2696         status = cli_connect_nb_recv(req, pcli);
2697 fail:
2698         TALLOC_FREE(ev);
2699         return status;
2700 }
2701
2702 struct cli_start_connection_state {
2703         struct tevent_context *ev;
2704         struct cli_state *cli;
2705         int min_protocol;
2706         int max_protocol;
2707 };
2708
2709 static void cli_start_connection_connected(struct tevent_req *subreq);
2710 static void cli_start_connection_done(struct tevent_req *subreq);
2711
2712 /**
2713    establishes a connection to after the negprot. 
2714    @param output_cli A fully initialised cli structure, non-null only on success
2715    @param dest_host The netbios name of the remote host
2716    @param dest_ss (optional) The the destination IP, NULL for name based lookup
2717    @param port (optional) The destination port (0 for default)
2718 */
2719
2720 static struct tevent_req *cli_start_connection_send(
2721         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2722         const char *my_name, const char *dest_host,
2723         const struct sockaddr_storage *dest_ss, int port,
2724         int signing_state, int flags)
2725 {
2726         struct tevent_req *req, *subreq;
2727         struct cli_start_connection_state *state;
2728
2729         req = tevent_req_create(mem_ctx, &state,
2730                                 struct cli_start_connection_state);
2731         if (req == NULL) {
2732                 return NULL;
2733         }
2734         state->ev = ev;
2735
2736         if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2737                 state->min_protocol = lp_client_ipc_min_protocol();
2738                 state->max_protocol = lp_client_ipc_max_protocol();
2739         } else {
2740                 state->min_protocol = lp_client_min_protocol();
2741                 state->max_protocol = lp_client_max_protocol();
2742         }
2743
2744         subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2745                                      0x20, my_name, signing_state, flags);
2746         if (tevent_req_nomem(subreq, req)) {
2747                 return tevent_req_post(req, ev);
2748         }
2749         tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2750         return req;
2751 }
2752
2753 static void cli_start_connection_connected(struct tevent_req *subreq)
2754 {
2755         struct tevent_req *req = tevent_req_callback_data(
2756                 subreq, struct tevent_req);
2757         struct cli_start_connection_state *state = tevent_req_data(
2758                 req, struct cli_start_connection_state);
2759         NTSTATUS status;
2760
2761         status = cli_connect_nb_recv(subreq, &state->cli);
2762         TALLOC_FREE(subreq);
2763         if (tevent_req_nterror(req, status)) {
2764                 return;
2765         }
2766
2767         subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2768                                       state->cli->timeout,
2769                                       state->min_protocol,
2770                                       state->max_protocol);
2771         if (tevent_req_nomem(subreq, req)) {
2772                 return;
2773         }
2774         tevent_req_set_callback(subreq, cli_start_connection_done, req);
2775 }
2776
2777 static void cli_start_connection_done(struct tevent_req *subreq)
2778 {
2779         struct tevent_req *req = tevent_req_callback_data(
2780                 subreq, struct tevent_req);
2781         struct cli_start_connection_state *state = tevent_req_data(
2782                 req, struct cli_start_connection_state);
2783         NTSTATUS status;
2784
2785         status = smbXcli_negprot_recv(subreq);
2786         TALLOC_FREE(subreq);
2787         if (tevent_req_nterror(req, status)) {
2788                 return;
2789         }
2790
2791         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2792                 /* Ensure we ask for some initial credits. */
2793                 smb2cli_conn_set_max_credits(state->cli->conn,
2794                                              DEFAULT_SMB2_MAX_CREDITS);
2795         }
2796
2797         tevent_req_done(req);
2798 }
2799
2800 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2801                                           struct cli_state **output_cli)
2802 {
2803         struct cli_start_connection_state *state = tevent_req_data(
2804                 req, struct cli_start_connection_state);
2805         NTSTATUS status;
2806
2807         if (tevent_req_is_nterror(req, &status)) {
2808                 return status;
2809         }
2810         *output_cli = state->cli;
2811
2812         return NT_STATUS_OK;
2813 }
2814
2815 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
2816                               const char *my_name, 
2817                               const char *dest_host, 
2818                               const struct sockaddr_storage *dest_ss, int port,
2819                               int signing_state, int flags)
2820 {
2821         struct tevent_context *ev;
2822         struct tevent_req *req;
2823         NTSTATUS status = NT_STATUS_NO_MEMORY;
2824
2825         ev = samba_tevent_context_init(talloc_tos());
2826         if (ev == NULL) {
2827                 goto fail;
2828         }
2829         req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2830                                         port, signing_state, flags);
2831         if (req == NULL) {
2832                 goto fail;
2833         }
2834         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2835                 goto fail;
2836         }
2837         status = cli_start_connection_recv(req, output_cli);
2838 fail:
2839         TALLOC_FREE(ev);
2840         return status;
2841 }
2842
2843 /**
2844    establishes a connection right up to doing tconX, password specified.
2845    @param output_cli A fully initialised cli structure, non-null only on success
2846    @param dest_host The netbios name of the remote host
2847    @param dest_ip (optional) The the destination IP, NULL for name based lookup
2848    @param port (optional) The destination port (0 for default)
2849    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
2850    @param service_type The 'type' of serivice. 
2851    @param creds The used user credentials
2852 */
2853
2854 struct cli_full_connection_creds_state {
2855         struct tevent_context *ev;
2856         const char *service;
2857         const char *service_type;
2858         struct cli_credentials *creds;
2859         int flags;
2860         struct cli_state *cli;
2861 };
2862
2863 static int cli_full_connection_creds_state_destructor(
2864         struct cli_full_connection_creds_state *s)
2865 {
2866         if (s->cli != NULL) {
2867                 cli_shutdown(s->cli);
2868                 s->cli = NULL;
2869         }
2870         return 0;
2871 }
2872
2873 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
2874 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
2875 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
2876 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
2877 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
2878
2879 struct tevent_req *cli_full_connection_creds_send(
2880         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2881         const char *my_name, const char *dest_host,
2882         const struct sockaddr_storage *dest_ss, int port,
2883         const char *service, const char *service_type,
2884         struct cli_credentials *creds,
2885         int flags, int signing_state)
2886 {
2887         struct tevent_req *req, *subreq;
2888         struct cli_full_connection_creds_state *state;
2889         enum credentials_use_kerberos krb5_state;
2890         uint32_t gensec_features = 0;
2891
2892         req = tevent_req_create(mem_ctx, &state,
2893                                 struct cli_full_connection_creds_state);
2894         if (req == NULL) {
2895                 return NULL;
2896         }
2897         talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
2898
2899         flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
2900         flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
2901         flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
2902         flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
2903
2904         krb5_state = cli_credentials_get_kerberos_state(creds);
2905         switch (krb5_state) {
2906         case CRED_MUST_USE_KERBEROS:
2907                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2908                 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
2909                 break;
2910         case CRED_AUTO_USE_KERBEROS:
2911                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2912                 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
2913                 break;
2914         case CRED_DONT_USE_KERBEROS:
2915                 break;
2916         }
2917
2918         gensec_features = cli_credentials_get_gensec_features(creds);
2919         if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
2920                 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
2921         }
2922
2923         state->ev = ev;
2924         state->service = service;
2925         state->service_type = service_type;
2926         state->creds = creds;
2927         state->flags = flags;
2928
2929         subreq = cli_start_connection_send(
2930                 state, ev, my_name, dest_host, dest_ss, port,
2931                 signing_state, flags);
2932         if (tevent_req_nomem(subreq, req)) {
2933                 return tevent_req_post(req, ev);
2934         }
2935         tevent_req_set_callback(subreq,
2936                                 cli_full_connection_creds_conn_done,
2937                                 req);
2938         return req;
2939 }
2940
2941 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
2942 {
2943         struct tevent_req *req = tevent_req_callback_data(
2944                 subreq, struct tevent_req);
2945         struct cli_full_connection_creds_state *state = tevent_req_data(
2946                 req, struct cli_full_connection_creds_state);
2947         NTSTATUS status;
2948
2949         status = cli_start_connection_recv(subreq, &state->cli);
2950         TALLOC_FREE(subreq);
2951         if (tevent_req_nterror(req, status)) {
2952                 return;
2953         }
2954
2955         cli_full_connection_creds_sess_start(req);
2956 }
2957
2958 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
2959 {
2960         struct cli_full_connection_creds_state *state = tevent_req_data(
2961                 req, struct cli_full_connection_creds_state);
2962         struct tevent_req *subreq = NULL;
2963
2964         subreq = cli_session_setup_creds_send(
2965                 state, state->ev, state->cli, state->creds);
2966         if (tevent_req_nomem(subreq, req)) {
2967                 return;
2968         }
2969         tevent_req_set_callback(subreq,
2970                                 cli_full_connection_creds_sess_done,
2971                                 req);
2972 }
2973
2974 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
2975 {
2976         struct tevent_req *req = tevent_req_callback_data(
2977                 subreq, struct tevent_req);
2978         struct cli_full_connection_creds_state *state = tevent_req_data(
2979                 req, struct cli_full_connection_creds_state);
2980         NTSTATUS status;
2981
2982         status = cli_session_setup_creds_recv(subreq);
2983         TALLOC_FREE(subreq);
2984
2985         if (!NT_STATUS_IS_OK(status) &&
2986             (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2987
2988                 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2989
2990                 state->creds = cli_credentials_init_anon(state);
2991                 if (tevent_req_nomem(state->creds, req)) {
2992                         return;
2993                 }
2994
2995                 cli_full_connection_creds_sess_start(req);
2996                 return;
2997         }
2998
2999         if (tevent_req_nterror(req, status)) {
3000                 return;
3001         }
3002
3003         cli_full_connection_creds_tcon_start(req);
3004 }
3005
3006 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3007 {
3008         struct cli_full_connection_creds_state *state = tevent_req_data(
3009                 req, struct cli_full_connection_creds_state);
3010         struct tevent_req *subreq = NULL;
3011         const char *password = NULL;
3012         int pw_len = 0;
3013
3014         if (state->service == NULL) {
3015                 tevent_req_done(req);
3016                 return;
3017         }
3018
3019         password = cli_credentials_get_password(state->creds);
3020         if (password == NULL) {
3021                 password = "";
3022                 pw_len = 0;
3023         } else {
3024                 pw_len = strlen(password) + 1;
3025         }
3026
3027         subreq = cli_tree_connect_send(state, state->ev,
3028                                        state->cli,
3029                                        state->service,
3030                                        state->service_type,
3031                                        password, pw_len);
3032         if (tevent_req_nomem(subreq, req)) {
3033                 return;
3034         }
3035         tevent_req_set_callback(subreq,
3036                                 cli_full_connection_creds_tcon_done,
3037                                 req);
3038 }
3039
3040 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3041 {
3042         struct tevent_req *req = tevent_req_callback_data(
3043                 subreq, struct tevent_req);
3044         NTSTATUS status;
3045
3046         status = cli_tree_connect_recv(subreq);
3047         TALLOC_FREE(subreq);
3048         if (tevent_req_nterror(req, status)) {
3049                 return;
3050         }
3051
3052         tevent_req_done(req);
3053 }
3054
3055 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3056                                   struct cli_state **output_cli)
3057 {
3058         struct cli_full_connection_creds_state *state = tevent_req_data(
3059                 req, struct cli_full_connection_creds_state);
3060         NTSTATUS status;
3061
3062         if (tevent_req_is_nterror(req, &status)) {
3063                 return status;
3064         }
3065         *output_cli = state->cli;
3066         talloc_set_destructor(state, NULL);
3067         return NT_STATUS_OK;
3068 }
3069
3070 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3071                                    const char *my_name,
3072                                    const char *dest_host,
3073                                    const struct sockaddr_storage *dest_ss, int port,
3074                                    const char *service, const char *service_type,
3075                                    struct cli_credentials *creds,
3076                                    int flags,
3077                                    int signing_state)
3078 {
3079         struct tevent_context *ev;
3080         struct tevent_req *req;
3081         NTSTATUS status = NT_STATUS_NO_MEMORY;
3082
3083         ev = samba_tevent_context_init(talloc_tos());
3084         if (ev == NULL) {
3085                 goto fail;
3086         }
3087         req = cli_full_connection_creds_send(
3088                 ev, ev, my_name, dest_host, dest_ss, port, service,
3089                 service_type, creds, flags, signing_state);
3090         if (req == NULL) {
3091                 goto fail;
3092         }
3093         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3094                 goto fail;
3095         }
3096         status = cli_full_connection_creds_recv(req, output_cli);
3097  fail:
3098         TALLOC_FREE(ev);
3099         return status;
3100 }
3101
3102 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3103                              const char *my_name,
3104                              const char *dest_host,
3105                              const struct sockaddr_storage *dest_ss, int port,
3106                              const char *service, const char *service_type,
3107                              const char *user, const char *domain,
3108                              const char *password, int flags,
3109                              int signing_state)
3110 {
3111         TALLOC_CTX *frame = talloc_stackframe();
3112         NTSTATUS status;
3113         bool use_kerberos = false;
3114         bool fallback_after_kerberos = false;
3115         bool use_ccache = false;
3116         bool pw_nt_hash = false;
3117         struct cli_credentials *creds = NULL;
3118
3119         if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3120                 use_kerberos = true;
3121         }
3122
3123         if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3124                 fallback_after_kerberos = true;
3125         }
3126
3127         if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3128                 use_ccache = true;
3129         }
3130
3131         if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3132                 pw_nt_hash = true;
3133         }
3134
3135         creds = cli_session_creds_init(frame,
3136                                        user,
3137                                        domain,
3138                                        NULL, /* realm (use default) */
3139                                        password,
3140                                        use_kerberos,
3141                                        fallback_after_kerberos,
3142                                        use_ccache,
3143                                        pw_nt_hash);
3144         if (creds == NULL) {
3145                 TALLOC_FREE(frame);
3146                 return NT_STATUS_NO_MEMORY;
3147         }
3148
3149         status = cli_full_connection_creds(output_cli, my_name,
3150                                            dest_host, dest_ss, port,
3151                                            service, service_type,
3152                                            creds, flags, signing_state);
3153         if (!NT_STATUS_IS_OK(status)) {
3154                 TALLOC_FREE(frame);
3155                 return status;
3156         }
3157
3158         TALLOC_FREE(frame);
3159         return NT_STATUS_OK;
3160 }
3161
3162 /****************************************************************************
3163  Send an old style tcon.
3164 ****************************************************************************/
3165 struct cli_raw_tcon_state {
3166         uint16_t *ret_vwv;
3167 };
3168
3169 static void cli_raw_tcon_done(struct tevent_req *subreq);
3170
3171 static struct tevent_req *cli_raw_tcon_send(
3172         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3173         const char *service, const char *pass, const char *dev)
3174 {
3175         struct tevent_req *req, *subreq;
3176         struct cli_raw_tcon_state *state;
3177         uint8_t *bytes;
3178
3179         req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3180         if (req == NULL) {
3181                 return NULL;
3182         }
3183
3184         if (!lp_client_plaintext_auth() && (*pass)) {
3185                 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3186                           " or 'client ntlmv2 auth = yes'\n"));
3187                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3188                 return tevent_req_post(req, ev);
3189         }
3190
3191         bytes = talloc_array(state, uint8_t, 0);
3192         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3193         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3194                                    service, strlen(service)+1, NULL);
3195         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3196         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3197                                    pass, strlen(pass)+1, NULL);
3198         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3199         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3200                                    dev, strlen(dev)+1, NULL);
3201
3202         if (tevent_req_nomem(bytes, req)) {
3203                 return tevent_req_post(req, ev);
3204         }
3205
3206         subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3207                               talloc_get_size(bytes), bytes);
3208         if (tevent_req_nomem(subreq, req)) {
3209                 return tevent_req_post(req, ev);
3210         }
3211         tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3212         return req;
3213 }
3214
3215 static void cli_raw_tcon_done(struct tevent_req *subreq)
3216 {
3217         struct tevent_req *req = tevent_req_callback_data(
3218                 subreq, struct tevent_req);
3219         struct cli_raw_tcon_state *state = tevent_req_data(
3220                 req, struct cli_raw_tcon_state);
3221         NTSTATUS status;
3222
3223         status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3224                               NULL, NULL);
3225         TALLOC_FREE(subreq);
3226         if (tevent_req_nterror(req, status)) {
3227                 return;
3228         }
3229         tevent_req_done(req);
3230 }
3231
3232 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3233                                   uint16_t *max_xmit, uint16_t *tid)
3234 {
3235         struct cli_raw_tcon_state *state = tevent_req_data(
3236                 req, struct cli_raw_tcon_state);
3237         NTSTATUS status;
3238
3239         if (tevent_req_is_nterror(req, &status)) {
3240                 return status;
3241         }
3242         *max_xmit = SVAL(state->ret_vwv + 0, 0);
3243         *tid = SVAL(state->ret_vwv + 1, 0);
3244         return NT_STATUS_OK;
3245 }
3246
3247 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3248                       const char *service, const char *pass, const char *dev,
3249                       uint16_t *max_xmit, uint16_t *tid)
3250 {
3251         struct tevent_context *ev;
3252         struct tevent_req *req;
3253         NTSTATUS status = NT_STATUS_NO_MEMORY;
3254
3255         ev = samba_tevent_context_init(talloc_tos());
3256         if (ev == NULL) {
3257                 goto fail;
3258         }
3259         req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3260         if (req == NULL) {
3261                 goto fail;
3262         }
3263         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3264                 goto fail;
3265         }
3266         status = cli_raw_tcon_recv(req, max_xmit, tid);
3267 fail:
3268         TALLOC_FREE(ev);
3269         return status;
3270 }
3271
3272 /* Return a cli_state pointing at the IPC$ share for the given server */
3273
3274 struct cli_state *get_ipc_connect(char *server,
3275                                 struct sockaddr_storage *server_ss,
3276                                 const struct user_auth_info *user_info)
3277 {
3278         struct cli_state *cli;
3279         NTSTATUS nt_status;
3280         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3281
3282         if (get_cmdline_auth_info_use_kerberos(user_info)) {
3283                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3284         }
3285
3286         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
3287                                         get_cmdline_auth_info_username(user_info),
3288                                         lp_workgroup(),
3289                                         get_cmdline_auth_info_password(user_info),
3290                                         flags,
3291                                         SMB_SIGNING_DEFAULT);
3292
3293         if (NT_STATUS_IS_OK(nt_status)) {
3294                 return cli;
3295         } else if (is_ipaddress(server)) {
3296             /* windows 9* needs a correct NMB name for connections */
3297             fstring remote_name;
3298
3299             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3300                 cli = get_ipc_connect(remote_name, server_ss, user_info);
3301                 if (cli)
3302                     return cli;
3303             }
3304         }
3305         return NULL;
3306 }
3307
3308 /*
3309  * Given the IP address of a master browser on the network, return its
3310  * workgroup and connect to it.
3311  *
3312  * This function is provided to allow additional processing beyond what
3313  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3314  * browsers and obtain each master browsers' list of domains (in case the
3315  * first master browser is recently on the network and has not yet
3316  * synchronized with other master browsers and therefore does not yet have the
3317  * entire network browse list)
3318  */
3319
3320 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3321                                 struct sockaddr_storage *mb_ip,
3322                                 const struct user_auth_info *user_info,
3323                                 char **pp_workgroup_out)
3324 {
3325         char addr[INET6_ADDRSTRLEN];
3326         fstring name;
3327         struct cli_state *cli;
3328         struct sockaddr_storage server_ss;
3329
3330         *pp_workgroup_out = NULL;
3331
3332         print_sockaddr(addr, sizeof(addr), mb_ip);
3333         DEBUG(99, ("Looking up name of master browser %s\n",
3334                    addr));
3335
3336         /*
3337          * Do a name status query to find out the name of the master browser.
3338          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3339          * master browser will not respond to a wildcard query (or, at least,
3340          * an NT4 server acting as the domain master browser will not).
3341          *
3342          * We might be able to use ONLY the query on MSBROWSE, but that's not
3343          * yet been tested with all Windows versions, so until it is, leave
3344          * the original wildcard query as the first choice and fall back to
3345          * MSBROWSE if the wildcard query fails.
3346          */
3347         if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3348             !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3349
3350                 DEBUG(99, ("Could not retrieve name status for %s\n",
3351                            addr));
3352                 return NULL;
3353         }
3354
3355         if (!find_master_ip(name, &server_ss)) {
3356                 DEBUG(99, ("Could not find master ip for %s\n", name));
3357                 return NULL;
3358         }
3359
3360         *pp_workgroup_out = talloc_strdup(ctx, name);
3361
3362         DEBUG(4, ("found master browser %s, %s\n", name, addr));
3363
3364         print_sockaddr(addr, sizeof(addr), &server_ss);
3365         cli = get_ipc_connect(addr, &server_ss, user_info);
3366
3367         return cli;
3368 }
3369
3370 /*
3371  * Return the IP address and workgroup of a master browser on the network, and
3372  * connect to it.
3373  */
3374
3375 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3376                                         const struct user_auth_info *user_info,
3377                                         char **pp_workgroup_out)
3378 {
3379         struct sockaddr_storage *ip_list;
3380         struct cli_state *cli;
3381         int i, count;
3382         NTSTATUS status;
3383
3384         *pp_workgroup_out = NULL;
3385
3386         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3387
3388         /* Go looking for workgroups by broadcasting on the local network */
3389
3390         status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3391                                     &ip_list, &count);
3392         if (!NT_STATUS_IS_OK(status)) {
3393                 DEBUG(99, ("No master browsers responded: %s\n",
3394                            nt_errstr(status)));
3395                 return NULL;
3396         }
3397
3398         for (i = 0; i < count; i++) {
3399                 char addr[INET6_ADDRSTRLEN];
3400                 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3401                 DEBUG(99, ("Found master browser %s\n", addr));
3402
3403                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3404                                 user_info, pp_workgroup_out);
3405                 if (cli)
3406                         return(cli);
3407         }
3408
3409         return NULL;
3410 }