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