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