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