s3: libsmb: Protect cli_connect_nb_send() from being passed a NULL hostname and dest_ss.
[samba.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6    Copyright (C) Volker Lendecke 2011
7    Copyright (C) Jeremy Allison 2011
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
34 #include "krb5_env.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
40
41 #define STAR_SMBSERVER "*SMBSERVER"
42
43 /********************************************************
44  Utility function to ensure we always return at least
45  a valid char * pointer to an empty string for the
46  cli->server_os, cli->server_type and cli->server_domain
47  strings.
48 *******************************************************/
49
50 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
51                                         const uint8_t *hdr,
52                                         char **dest,
53                                         uint8_t *src,
54                                         size_t srclen,
55                                         ssize_t *destlen)
56 {
57         *destlen = clistr_pull_talloc(mem_ctx,
58                                 (const char *)hdr,
59                                 SVAL(hdr, HDR_FLG2),
60                                 dest,
61                                 (char *)src,
62                                 srclen,
63                                 STR_TERMINATE);
64         if (*destlen == -1) {
65                 return NT_STATUS_NO_MEMORY;
66         }
67
68         if (*dest == NULL) {
69                 *dest = talloc_strdup(mem_ctx, "");
70                 if (*dest == NULL) {
71                         return NT_STATUS_NO_MEMORY;
72                 }
73         }
74         return NT_STATUS_OK;
75 }
76
77 /****************************************************************************
78  Do an old lanman2 style session setup.
79 ****************************************************************************/
80
81 struct cli_session_setup_lanman2_state {
82         struct cli_state *cli;
83         uint16_t vwv[10];
84         const char *user;
85 };
86
87 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
88
89 static struct tevent_req *cli_session_setup_lanman2_send(
90         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
91         struct cli_state *cli, const char *user,
92         const char *pass, size_t passlen,
93         const char *workgroup)
94 {
95         struct tevent_req *req, *subreq;
96         struct cli_session_setup_lanman2_state *state;
97         DATA_BLOB lm_response = data_blob_null;
98         uint16_t *vwv;
99         uint8_t *bytes;
100         char *tmp;
101         uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
102
103         req = tevent_req_create(mem_ctx, &state,
104                                 struct cli_session_setup_lanman2_state);
105         if (req == NULL) {
106                 return NULL;
107         }
108         state->cli = cli;
109         state->user = user;
110         vwv = state->vwv;
111
112         /*
113          * if in share level security then don't send a password now
114          */
115         if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
116                 passlen = 0;
117         }
118
119         if (passlen > 0
120             && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
121             && passlen != 24) {
122                 /*
123                  * Encrypted mode needed, and non encrypted password
124                  * supplied.
125                  */
126                 lm_response = data_blob(NULL, 24);
127                 if (tevent_req_nomem(lm_response.data, req)) {
128                         return tevent_req_post(req, ev);
129                 }
130
131                 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
132                                 (uint8_t *)lm_response.data)) {
133                         DEBUG(1, ("Password is > 14 chars in length, and is "
134                                   "therefore incompatible with Lanman "
135                                   "authentication\n"));
136                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
137                         return tevent_req_post(req, ev);
138                 }
139         } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
140                    && passlen == 24) {
141                 /*
142                  * Encrypted mode needed, and encrypted password
143                  * supplied.
144                  */
145                 lm_response = data_blob(pass, passlen);
146                 if (tevent_req_nomem(lm_response.data, req)) {
147                         return tevent_req_post(req, ev);
148                 }
149         } else if (passlen > 0) {
150                 uint8_t *buf;
151                 size_t converted_size;
152                 /*
153                  * Plaintext mode needed, assume plaintext supplied.
154                  */
155                 buf = talloc_array(talloc_tos(), uint8_t, 0);
156                 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
157                                          &converted_size);
158                 if (tevent_req_nomem(buf, req)) {
159                         return tevent_req_post(req, ev);
160                 }
161                 lm_response = data_blob(pass, passlen);
162                 TALLOC_FREE(buf);
163                 if (tevent_req_nomem(lm_response.data, req)) {
164                         return tevent_req_post(req, ev);
165                 }
166         }
167
168         SCVAL(vwv+0, 0, 0xff);
169         SCVAL(vwv+0, 1, 0);
170         SSVAL(vwv+1, 0, 0);
171         SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
172         SSVAL(vwv+3, 0, 2);
173         SSVAL(vwv+4, 0, 1);
174         SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
175         SSVAL(vwv+7, 0, lm_response.length);
176
177         bytes = talloc_array(state, uint8_t, lm_response.length);
178         if (tevent_req_nomem(bytes, req)) {
179                 return tevent_req_post(req, ev);
180         }
181         if (lm_response.length != 0) {
182                 memcpy(bytes, lm_response.data, lm_response.length);
183         }
184         data_blob_free(&lm_response);
185
186         tmp = talloc_strdup_upper(talloc_tos(), user);
187         if (tevent_req_nomem(tmp, req)) {
188                 return tevent_req_post(req, ev);
189         }
190         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
191                                    NULL);
192         TALLOC_FREE(tmp);
193
194         tmp = talloc_strdup_upper(talloc_tos(), workgroup);
195         if (tevent_req_nomem(tmp, req)) {
196                 return tevent_req_post(req, ev);
197         }
198         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
199                                    NULL);
200         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
201         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
202
203         if (tevent_req_nomem(bytes, req)) {
204                 return tevent_req_post(req, ev);
205         }
206
207         subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
208                               talloc_get_size(bytes), bytes);
209         if (tevent_req_nomem(subreq, req)) {
210                 return tevent_req_post(req, ev);
211         }
212         tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
213         return req;
214 }
215
216 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
217 {
218         struct tevent_req *req = tevent_req_callback_data(
219                 subreq, struct tevent_req);
220         struct cli_session_setup_lanman2_state *state = tevent_req_data(
221                 req, struct cli_session_setup_lanman2_state);
222         struct cli_state *cli = state->cli;
223         uint32_t num_bytes;
224         uint8_t *in;
225         uint8_t *inhdr;
226         uint8_t *bytes;
227         uint8_t *p;
228         NTSTATUS status;
229         ssize_t ret;
230         uint8_t wct;
231         uint16_t *vwv;
232
233         status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
234                               &num_bytes, &bytes);
235         TALLOC_FREE(subreq);
236         if (!NT_STATUS_IS_OK(status)) {
237                 tevent_req_nterror(req, status);
238                 return;
239         }
240
241         inhdr = in + NBT_HDR_SIZE;
242         p = bytes;
243
244         cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
245         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, 13, vwv,
390                                     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, 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, 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,
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 = kerberos_get_principal_from_service_hostname(
1754                         talloc_tos(), "cifs", remote_name, lp_realm());
1755         }
1756         DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1757                   principal ? principal : "<null>"));
1758
1759         return principal;
1760 }
1761 #endif
1762
1763 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1764                                            const char *principal)
1765 {
1766         char *account, *p;
1767
1768         account = talloc_strdup(mem_ctx, principal);
1769         if (account == NULL) {
1770                 return NULL;
1771         }
1772         p = strchr_m(account, '@');
1773         if (p != NULL) {
1774                 *p = '\0';
1775         }
1776         return account;
1777 }
1778
1779 /****************************************************************************
1780  Do a spnego encrypted session setup.
1781
1782  user_domain: The shortname of the domain the user/machine is a member of.
1783  dest_realm: The realm we're connecting to, if NULL we use our default realm.
1784 ****************************************************************************/
1785
1786 struct cli_session_setup_spnego_state {
1787         struct tevent_context *ev;
1788         struct cli_state *cli;
1789         const char *target_hostname;
1790         const char *user;
1791         const char *account;
1792         const char *pass;
1793         const char *user_domain;
1794         const char *dest_realm;
1795         ADS_STATUS result;
1796 };
1797
1798 #ifdef HAVE_KRB5
1799 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1800 #endif
1801
1802 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1803
1804 static struct tevent_req *cli_session_setup_spnego_send(
1805         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1806         const char *user, const char *pass, const char *user_domain)
1807 {
1808         struct tevent_req *req, *subreq;
1809         struct cli_session_setup_spnego_state *state;
1810         char *principal = NULL;
1811         char *OIDs[ASN1_MAX_OIDS];
1812         int i;
1813         const char *dest_realm = cli_state_remote_realm(cli);
1814         const DATA_BLOB *server_blob;
1815
1816         req = tevent_req_create(mem_ctx, &state,
1817                                 struct cli_session_setup_spnego_state);
1818         if (req == NULL) {
1819                 return NULL;
1820         }
1821         state->ev = ev;
1822         state->cli = cli;
1823         state->user = user;
1824         state->pass = pass;
1825         state->user_domain = user_domain;
1826         state->dest_realm = dest_realm;
1827
1828         state->account = cli_session_setup_get_account(state, user);
1829         if (tevent_req_nomem(state->account, req)) {
1830                 return tevent_req_post(req, ev);
1831         }
1832
1833         state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1834         server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1835
1836         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1837                  (unsigned long)server_blob->length));
1838
1839         /* the server might not even do spnego */
1840         if (server_blob->length == 0) {
1841                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1842                 goto ntlmssp;
1843         }
1844
1845 #if 0
1846         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1847 #endif
1848
1849         /* The server sent us the first part of the SPNEGO exchange in the
1850          * negprot reply. It is WRONG to depend on the principal sent in the
1851          * negprot reply, but right now we do it. If we don't receive one,
1852          * we try to best guess, then fall back to NTLM.  */
1853         if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1854                                        &principal, NULL) ||
1855                         OIDs[0] == NULL) {
1856                 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1857                 tevent_req_done(req);
1858                 return tevent_req_post(req, ev);
1859         }
1860
1861         /* make sure the server understands kerberos */
1862         for (i=0;OIDs[i];i++) {
1863                 if (i == 0)
1864                         DEBUG(3,("got OID=%s\n", OIDs[i]));
1865                 else
1866                         DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1867                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1868                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1869                         cli->got_kerberos_mechanism = True;
1870                 }
1871                 talloc_free(OIDs[i]);
1872         }
1873
1874         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1875
1876 #ifdef HAVE_KRB5
1877         /* If password is set we reauthenticate to kerberos server
1878          * and do not store results */
1879
1880         if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1881                 char *tmp;
1882
1883                 tmp = cli_session_setup_get_principal(
1884                         talloc_tos(), principal, state->target_hostname, dest_realm);
1885                 TALLOC_FREE(principal);
1886                 principal = tmp;
1887
1888                 if (pass && *pass) {
1889                         int ret;
1890
1891                         use_in_memory_ccache();
1892                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1893
1894                         if (ret){
1895                                 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1896                                 TALLOC_FREE(principal);
1897                                 if (cli->fallback_after_kerberos)
1898                                         goto ntlmssp;
1899                                 state->result = ADS_ERROR_KRB5(ret);
1900                                 tevent_req_done(req);
1901                                 return tevent_req_post(req, ev);
1902                         }
1903                 }
1904
1905                 if (principal) {
1906                         subreq = cli_session_setup_gensec_send(
1907                                 state, ev, cli,
1908                                 state->account, pass, user_domain,
1909                                 CRED_MUST_USE_KERBEROS,
1910                                 "cifs", state->target_hostname, principal);
1911                         if (tevent_req_nomem(subreq, req)) {
1912                                 return tevent_req_post(req, ev);
1913                         }
1914                         tevent_req_set_callback(
1915                                 subreq, cli_session_setup_spnego_done_krb,
1916                                 req);
1917                         return req;
1918                 }
1919         }
1920 #endif
1921
1922 ntlmssp:
1923         subreq = cli_session_setup_gensec_send(
1924                 state, state->ev, state->cli,
1925                 state->account, state->pass, state->user_domain,
1926                 CRED_DONT_USE_KERBEROS,
1927                 "cifs", state->target_hostname, NULL);
1928         if (tevent_req_nomem(subreq, req)) {
1929                 return tevent_req_post(req, ev);
1930         }
1931         tevent_req_set_callback(
1932                 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1933         return req;
1934 }
1935
1936 #ifdef HAVE_KRB5
1937 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1938 {
1939         struct tevent_req *req = tevent_req_callback_data(
1940                 subreq, struct tevent_req);
1941         struct cli_session_setup_spnego_state *state = tevent_req_data(
1942                 req, struct cli_session_setup_spnego_state);
1943         NTSTATUS status;
1944
1945         status = cli_session_setup_gensec_recv(subreq);
1946         TALLOC_FREE(subreq);
1947         state->result = ADS_ERROR_NT(status);
1948
1949         if (ADS_ERR_OK(state->result) ||
1950             !state->cli->fallback_after_kerberos) {
1951                 tevent_req_done(req);
1952                 return;
1953         }
1954
1955         subreq = cli_session_setup_gensec_send(
1956                 state, state->ev, state->cli,
1957                 state->account, state->pass, state->user_domain,
1958                 CRED_DONT_USE_KERBEROS,
1959                 "cifs", state->target_hostname, NULL);
1960         if (tevent_req_nomem(subreq, req)) {
1961                 return;
1962         }
1963         tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1964                                 req);
1965 }
1966 #endif
1967
1968 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1969 {
1970         struct tevent_req *req = tevent_req_callback_data(
1971                 subreq, struct tevent_req);
1972         struct cli_session_setup_spnego_state *state = tevent_req_data(
1973                 req, struct cli_session_setup_spnego_state);
1974         NTSTATUS status;
1975
1976         status = cli_session_setup_gensec_recv(subreq);
1977         TALLOC_FREE(subreq);
1978         state->result = ADS_ERROR_NT(status);
1979         tevent_req_done(req);
1980 }
1981
1982 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1983 {
1984         struct cli_session_setup_spnego_state *state = tevent_req_data(
1985                 req, struct cli_session_setup_spnego_state);
1986
1987         return state->result;
1988 }
1989
1990 struct cli_session_setup_state {
1991         uint8_t dummy;
1992 };
1993
1994 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1995 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1996 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1997 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1998 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1999
2000 /****************************************************************************
2001  Send a session setup. The username and workgroup is in UNIX character
2002  format and must be converted to DOS codepage format before sending. If the
2003  password is in plaintext, the same should be done.
2004 ****************************************************************************/
2005
2006 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
2007                                           struct tevent_context *ev,
2008                                           struct cli_state *cli,
2009                                           const char *user,
2010                                           const char *pass, int passlen,
2011                                           const char *ntpass, int ntpasslen,
2012                                           const char *workgroup)
2013 {
2014         struct tevent_req *req, *subreq;
2015         struct cli_session_setup_state *state;
2016         char *p;
2017         char *user2;
2018         uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2019
2020         req = tevent_req_create(mem_ctx, &state,
2021                                 struct cli_session_setup_state);
2022         if (req == NULL) {
2023                 return NULL;
2024         }
2025
2026         if (user) {
2027                 user2 = talloc_strdup(state, user);
2028         } else {
2029                 user2 = talloc_strdup(state, "");
2030         }
2031         if (user2 == NULL) {
2032                 tevent_req_oom(req);
2033                 return tevent_req_post(req, ev);
2034         }
2035
2036         if (!workgroup) {
2037                 workgroup = "";
2038         }
2039
2040         /* allow for workgroups as part of the username */
2041         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2042             (p=strchr_m(user2,*lp_winbind_separator()))) {
2043                 *p = 0;
2044                 user = p+1;
2045                 if (!strupper_m(user2)) {
2046                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2047                         return tevent_req_post(req, ev);
2048                 }
2049                 workgroup = user2;
2050         }
2051
2052         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2053                 tevent_req_done(req);
2054                 return tevent_req_post(req, ev);
2055         }
2056
2057         /* now work out what sort of session setup we are going to
2058            do. I have split this into separate functions to make the
2059            flow a bit easier to understand (tridge) */
2060
2061         /* if its an older server then we have to use the older request format */
2062
2063         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2064                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2065                         DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2066                                   " or 'client ntlmv2 auth = yes'\n"));
2067                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2068                         return tevent_req_post(req, ev);
2069                 }
2070
2071                 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2072                     !lp_client_plaintext_auth() && (*pass)) {
2073                         DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2074                                   " or 'client ntlmv2 auth = yes'\n"));
2075                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2076                         return tevent_req_post(req, ev);
2077                 }
2078
2079                 subreq = cli_session_setup_lanman2_send(
2080                         state, ev, cli, user, pass, passlen, workgroup);
2081                 if (tevent_req_nomem(subreq, req)) {
2082                         return tevent_req_post(req, ev);
2083                 }
2084                 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2085                                         req);
2086                 return req;
2087         }
2088
2089         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2090                 subreq = cli_session_setup_spnego_send(
2091                         state, ev, cli, user, pass, workgroup);
2092                 if (tevent_req_nomem(subreq, req)) {
2093                         return tevent_req_post(req, ev);
2094                 }
2095                 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2096                                         req);
2097                 return req;
2098         }
2099
2100         /*
2101          * if the server supports extended security then use SPNEGO
2102          * even for anonymous connections.
2103          */
2104         if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2105                 subreq = cli_session_setup_spnego_send(
2106                         state, ev, cli, user, pass, workgroup);
2107                 if (tevent_req_nomem(subreq, req)) {
2108                         return tevent_req_post(req, ev);
2109                 }
2110                 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2111                                         req);
2112                 return req;
2113         }
2114
2115         /* if no user is supplied then we have to do an anonymous connection.
2116            passwords are ignored */
2117
2118         if (!user || !*user) {
2119                 subreq = cli_session_setup_guest_send(state, ev, cli);
2120                 if (tevent_req_nomem(subreq, req)) {
2121                         return tevent_req_post(req, ev);
2122                 }
2123                 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2124                                         req);
2125                 return req;
2126         }
2127
2128         /* if the server is share level then send a plaintext null
2129            password at this point. The password is sent in the tree
2130            connect */
2131
2132         if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2133                 subreq = cli_session_setup_plain_send(
2134                         state, ev, cli, user, "", workgroup);
2135                 if (tevent_req_nomem(subreq, req)) {
2136                         return tevent_req_post(req, ev);
2137                 }
2138                 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2139                                         req);
2140                 return req;
2141         }
2142
2143         /* if the server doesn't support encryption then we have to use 
2144            plaintext. The second password is ignored */
2145
2146         if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2147                 if (!lp_client_plaintext_auth() && (*pass)) {
2148                         DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2149                                   " or 'client ntlmv2 auth = yes'\n"));
2150                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2151                         return tevent_req_post(req, ev);
2152                 }
2153                 subreq = cli_session_setup_plain_send(
2154                         state, ev, cli, user, pass, workgroup);
2155                 if (tevent_req_nomem(subreq, req)) {
2156                         return tevent_req_post(req, ev);
2157                 }
2158                 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2159                                         req);
2160                 return req;
2161         }
2162
2163         {
2164                 /* otherwise do a NT1 style session setup */
2165                 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2166                         /*
2167                          * Don't send an NTLMv2 response without NTLMSSP
2168                          * if we want to use spnego support
2169                          */
2170                         DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2171                                   " but 'client use spnego = yes"
2172                                   " and 'client ntlmv2 auth = yes'\n"));
2173                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2174                         return tevent_req_post(req, ev);
2175                 }
2176
2177                 subreq = cli_session_setup_nt1_send(
2178                         state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2179                         workgroup);
2180                 if (tevent_req_nomem(subreq, req)) {
2181                         return tevent_req_post(req, ev);
2182                 }
2183                 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2184                                         req);
2185                 return req;
2186         }
2187
2188         tevent_req_done(req);
2189         return tevent_req_post(req, ev);
2190 }
2191
2192 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2193 {
2194         struct tevent_req *req = tevent_req_callback_data(
2195                 subreq, struct tevent_req);
2196         NTSTATUS status;
2197
2198         status = cli_session_setup_lanman2_recv(subreq);
2199         TALLOC_FREE(subreq);
2200         if (!NT_STATUS_IS_OK(status)) {
2201                 tevent_req_nterror(req, status);
2202                 return;
2203         }
2204         tevent_req_done(req);
2205 }
2206
2207 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2208 {
2209         struct tevent_req *req = tevent_req_callback_data(
2210                 subreq, struct tevent_req);
2211         ADS_STATUS status;
2212
2213         status = cli_session_setup_spnego_recv(subreq);
2214         TALLOC_FREE(subreq);
2215         if (!ADS_ERR_OK(status)) {
2216                 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2217                 tevent_req_nterror(req, ads_ntstatus(status));
2218                 return;
2219         }
2220         tevent_req_done(req);
2221 }
2222
2223 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2224 {
2225         struct tevent_req *req = tevent_req_callback_data(
2226                 subreq, struct tevent_req);
2227         NTSTATUS status;
2228
2229         status = cli_session_setup_guest_recv(subreq);
2230         TALLOC_FREE(subreq);
2231         if (!NT_STATUS_IS_OK(status)) {
2232                 tevent_req_nterror(req, status);
2233                 return;
2234         }
2235         tevent_req_done(req);
2236 }
2237
2238 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2239 {
2240         struct tevent_req *req = tevent_req_callback_data(
2241                 subreq, struct tevent_req);
2242         NTSTATUS status;
2243
2244         status = cli_session_setup_plain_recv(subreq);
2245         TALLOC_FREE(subreq);
2246         if (!NT_STATUS_IS_OK(status)) {
2247                 tevent_req_nterror(req, status);
2248                 return;
2249         }
2250         tevent_req_done(req);
2251 }
2252
2253 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2254 {
2255         struct tevent_req *req = tevent_req_callback_data(
2256                 subreq, struct tevent_req);
2257         NTSTATUS status;
2258
2259         status = cli_session_setup_nt1_recv(subreq);
2260         TALLOC_FREE(subreq);
2261         if (!NT_STATUS_IS_OK(status)) {
2262                 DEBUG(3, ("cli_session_setup: NT1 session setup "
2263                           "failed: %s\n", nt_errstr(status)));
2264                 tevent_req_nterror(req, status);
2265                 return;
2266         }
2267         tevent_req_done(req);
2268 }
2269
2270 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2271 {
2272         return tevent_req_simple_recv_ntstatus(req);
2273 }
2274
2275 NTSTATUS cli_session_setup(struct cli_state *cli,
2276                            const char *user,
2277                            const char *pass, int passlen,
2278                            const char *ntpass, int ntpasslen,
2279                            const char *workgroup)
2280 {
2281         struct tevent_context *ev;
2282         struct tevent_req *req;
2283         NTSTATUS status = NT_STATUS_NO_MEMORY;
2284
2285         if (smbXcli_conn_has_async_calls(cli->conn)) {
2286                 return NT_STATUS_INVALID_PARAMETER;
2287         }
2288         ev = samba_tevent_context_init(talloc_tos());
2289         if (ev == NULL) {
2290                 goto fail;
2291         }
2292         req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2293                                      ntpass, ntpasslen, workgroup);
2294         if (req == NULL) {
2295                 goto fail;
2296         }
2297         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2298                 goto fail;
2299         }
2300         status = cli_session_setup_recv(req);
2301  fail:
2302         TALLOC_FREE(ev);
2303         return status;
2304 }
2305
2306 /****************************************************************************
2307  Send a uloggoff.
2308 *****************************************************************************/
2309
2310 struct cli_ulogoff_state {
2311         struct cli_state *cli;
2312         uint16_t vwv[3];
2313 };
2314
2315 static void cli_ulogoff_done(struct tevent_req *subreq);
2316
2317 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2318                                     struct tevent_context *ev,
2319                                     struct cli_state *cli)
2320 {
2321         struct tevent_req *req, *subreq;
2322         struct cli_ulogoff_state *state;
2323
2324         req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2325         if (req == NULL) {
2326                 return NULL;
2327         }
2328         state->cli = cli;
2329
2330         SCVAL(state->vwv+0, 0, 0xFF);
2331         SCVAL(state->vwv+1, 0, 0);
2332         SSVAL(state->vwv+2, 0, 0);
2333
2334         subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2335                               0, NULL);
2336         if (tevent_req_nomem(subreq, req)) {
2337                 return tevent_req_post(req, ev);
2338         }
2339         tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2340         return req;
2341 }
2342
2343 static void cli_ulogoff_done(struct tevent_req *subreq)
2344 {
2345         struct tevent_req *req = tevent_req_callback_data(
2346                 subreq, struct tevent_req);
2347         struct cli_ulogoff_state *state = tevent_req_data(
2348                 req, struct cli_ulogoff_state);
2349         NTSTATUS status;
2350
2351         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2352         if (!NT_STATUS_IS_OK(status)) {
2353                 tevent_req_nterror(req, status);
2354                 return;
2355         }
2356         cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2357         tevent_req_done(req);
2358 }
2359
2360 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2361 {
2362         return tevent_req_simple_recv_ntstatus(req);
2363 }
2364
2365 NTSTATUS cli_ulogoff(struct cli_state *cli)
2366 {
2367         struct tevent_context *ev;
2368         struct tevent_req *req;
2369         NTSTATUS status = NT_STATUS_NO_MEMORY;
2370
2371         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2372                 status = smb2cli_logoff(cli->conn,
2373                                         cli->timeout,
2374                                         cli->smb2.session);
2375                 if (!NT_STATUS_IS_OK(status)) {
2376                         return status;
2377                 }
2378                 smb2cli_session_set_id_and_flags(cli->smb2.session,
2379                                                  UINT64_MAX, 0);
2380                 return NT_STATUS_OK;
2381         }
2382
2383         if (smbXcli_conn_has_async_calls(cli->conn)) {
2384                 return NT_STATUS_INVALID_PARAMETER;
2385         }
2386         ev = samba_tevent_context_init(talloc_tos());
2387         if (ev == NULL) {
2388                 goto fail;
2389         }
2390         req = cli_ulogoff_send(ev, ev, cli);
2391         if (req == NULL) {
2392                 goto fail;
2393         }
2394         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2395                 goto fail;
2396         }
2397         status = cli_ulogoff_recv(req);
2398 fail:
2399         TALLOC_FREE(ev);
2400         return status;
2401 }
2402
2403 /****************************************************************************
2404  Send a tconX.
2405 ****************************************************************************/
2406
2407 struct cli_tcon_andx_state {
2408         struct cli_state *cli;
2409         uint16_t vwv[4];
2410         struct iovec bytes;
2411 };
2412
2413 static void cli_tcon_andx_done(struct tevent_req *subreq);
2414
2415 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2416                                         struct tevent_context *ev,
2417                                         struct cli_state *cli,
2418                                         const char *share, const char *dev,
2419                                         const char *pass, int passlen,
2420                                         struct tevent_req **psmbreq)
2421 {
2422         struct tevent_req *req, *subreq;
2423         struct cli_tcon_andx_state *state;
2424         uint8_t p24[24];
2425         uint16_t *vwv;
2426         char *tmp = NULL;
2427         uint8_t *bytes;
2428         uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2429         uint16_t tcon_flags = 0;
2430
2431         *psmbreq = NULL;
2432
2433         req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2434         if (req == NULL) {
2435                 return NULL;
2436         }
2437         state->cli = cli;
2438         vwv = state->vwv;
2439
2440         cli->share = talloc_strdup(cli, share);
2441         if (!cli->share) {
2442                 return NULL;
2443         }
2444
2445         /* in user level security don't send a password now */
2446         if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2447                 passlen = 1;
2448                 pass = "";
2449         } else if (pass == NULL) {
2450                 DEBUG(1, ("Server not using user level security and no "
2451                           "password supplied.\n"));
2452                 goto access_denied;
2453         }
2454
2455         if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2456             *pass && passlen != 24) {
2457                 if (!lp_client_lanman_auth()) {
2458                         DEBUG(1, ("Server requested LANMAN password "
2459                                   "(share-level security) but "
2460                                   "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2461                         goto access_denied;
2462                 }
2463
2464                 /*
2465                  * Non-encrypted passwords - convert to DOS codepage before
2466                  * encryption.
2467                  */
2468                 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2469                 passlen = 24;
2470                 pass = (const char *)p24;
2471         } else {
2472                 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2473                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2474                    == 0) {
2475                         uint8_t *tmp_pass;
2476
2477                         if (!lp_client_plaintext_auth() && (*pass)) {
2478                                 DEBUG(1, ("Server requested PLAINTEXT "
2479                                           "password but "
2480                                           "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2481                                 goto access_denied;
2482                         }
2483
2484                         /*
2485                          * Non-encrypted passwords - convert to DOS codepage
2486                          * before using.
2487                          */
2488                         tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2489                         if (tevent_req_nomem(tmp_pass, req)) {
2490                                 return tevent_req_post(req, ev);
2491                         }
2492                         tmp_pass = trans2_bytes_push_str(tmp_pass,
2493                                                          false, /* always DOS */
2494                                                          pass,
2495                                                          passlen,
2496                                                          NULL);
2497                         if (tevent_req_nomem(tmp_pass, req)) {
2498                                 return tevent_req_post(req, ev);
2499                         }
2500                         pass = (const char *)tmp_pass;
2501                         passlen = talloc_get_size(tmp_pass);
2502                 }
2503         }
2504
2505         tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2506         tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2507
2508         SCVAL(vwv+0, 0, 0xFF);
2509         SCVAL(vwv+0, 1, 0);
2510         SSVAL(vwv+1, 0, 0);
2511         SSVAL(vwv+2, 0, tcon_flags);
2512         SSVAL(vwv+3, 0, passlen);
2513
2514         if (passlen && pass) {
2515                 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2516         } else {
2517                 bytes = talloc_array(state, uint8_t, 0);
2518         }
2519
2520         /*
2521          * Add the sharename
2522          */
2523         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2524                                          smbXcli_conn_remote_name(cli->conn), share);
2525         if (tmp == NULL) {
2526                 TALLOC_FREE(req);
2527                 return NULL;
2528         }
2529         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2530                                    NULL);
2531         TALLOC_FREE(tmp);
2532
2533         /*
2534          * Add the devicetype
2535          */
2536         tmp = talloc_strdup_upper(talloc_tos(), dev);
2537         if (tmp == NULL) {
2538                 TALLOC_FREE(req);
2539                 return NULL;
2540         }
2541         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2542         TALLOC_FREE(tmp);
2543
2544         if (bytes == NULL) {
2545                 TALLOC_FREE(req);
2546                 return NULL;
2547         }
2548
2549         state->bytes.iov_base = (void *)bytes;
2550         state->bytes.iov_len = talloc_get_size(bytes);
2551
2552         subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2553                                     1, &state->bytes);
2554         if (subreq == NULL) {
2555                 TALLOC_FREE(req);
2556                 return NULL;
2557         }
2558         tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2559         *psmbreq = subreq;
2560         return req;
2561
2562  access_denied:
2563         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2564         return tevent_req_post(req, ev);
2565 }
2566
2567 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2568                                       struct tevent_context *ev,
2569                                       struct cli_state *cli,
2570                                       const char *share, const char *dev,
2571                                       const char *pass, int passlen)
2572 {
2573         struct tevent_req *req, *subreq;
2574         NTSTATUS status;
2575
2576         req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2577                                    &subreq);
2578         if (req == NULL) {
2579                 return NULL;
2580         }
2581         if (subreq == NULL) {
2582                 return req;
2583         }
2584         status = smb1cli_req_chain_submit(&subreq, 1);
2585         if (!NT_STATUS_IS_OK(status)) {
2586                 tevent_req_nterror(req, status);
2587                 return tevent_req_post(req, ev);
2588         }
2589         return req;
2590 }
2591
2592 static void cli_tcon_andx_done(struct tevent_req *subreq)
2593 {
2594         struct tevent_req *req = tevent_req_callback_data(
2595                 subreq, struct tevent_req);
2596         struct cli_tcon_andx_state *state = tevent_req_data(
2597                 req, struct cli_tcon_andx_state);
2598         struct cli_state *cli = state->cli;
2599         uint8_t *in;
2600         uint8_t *inhdr;
2601         uint8_t wct;
2602         uint16_t *vwv;
2603         uint32_t num_bytes;
2604         uint8_t *bytes;
2605         NTSTATUS status;
2606         uint16_t optional_support = 0;
2607
2608         status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2609                               &num_bytes, &bytes);
2610         TALLOC_FREE(subreq);
2611         if (!NT_STATUS_IS_OK(status)) {
2612                 tevent_req_nterror(req, status);
2613                 return;
2614         }
2615
2616         inhdr = in + NBT_HDR_SIZE;
2617
2618         if (num_bytes) {
2619                 if (clistr_pull_talloc(cli,
2620                                 (const char *)inhdr,
2621                                 SVAL(inhdr, HDR_FLG2),
2622                                 &cli->dev,
2623                                 bytes,
2624                                 num_bytes,
2625                                 STR_TERMINATE|STR_ASCII) == -1) {
2626                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2627                         return;
2628                 }
2629         } else {
2630                 cli->dev = talloc_strdup(cli, "");
2631                 if (cli->dev == NULL) {
2632                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2633                         return;
2634                 }
2635         }
2636
2637         if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2638                 /* almost certainly win95 - enable bug fixes */
2639                 cli->win95 = True;
2640         }
2641
2642         /*
2643          * Make sure that we have the optional support 16-bit field. WCT > 2.
2644          * Avoids issues when connecting to Win9x boxes sharing files
2645          */
2646
2647         if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2648                 optional_support = SVAL(vwv+2, 0);
2649         }
2650
2651         if (optional_support & SMB_EXTENDED_SIGNATURES) {
2652                 smb1cli_session_protect_session_key(cli->smb1.session);
2653         }
2654
2655         smb1cli_tcon_set_values(state->cli->smb1.tcon,
2656                                 SVAL(inhdr, HDR_TID),
2657                                 optional_support,
2658                                 0, /* maximal_access */
2659                                 0, /* guest_maximal_access */
2660                                 NULL, /* service */
2661                                 NULL); /* fs_type */
2662
2663         tevent_req_done(req);
2664 }
2665
2666 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2667 {
2668         return tevent_req_simple_recv_ntstatus(req);
2669 }
2670
2671 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2672                        const char *dev, const char *pass, int passlen)
2673 {
2674         TALLOC_CTX *frame = talloc_stackframe();
2675         struct tevent_context *ev;
2676         struct tevent_req *req;
2677         NTSTATUS status = NT_STATUS_NO_MEMORY;
2678
2679         if (smbXcli_conn_has_async_calls(cli->conn)) {
2680                 /*
2681                  * Can't use sync call while an async call is in flight
2682                  */
2683                 status = NT_STATUS_INVALID_PARAMETER;
2684                 goto fail;
2685         }
2686
2687         ev = samba_tevent_context_init(frame);
2688         if (ev == NULL) {
2689                 goto fail;
2690         }
2691
2692         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2693         if (req == NULL) {
2694                 goto fail;
2695         }
2696
2697         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2698                 goto fail;
2699         }
2700
2701         status = cli_tcon_andx_recv(req);
2702  fail:
2703         TALLOC_FREE(frame);
2704         return status;
2705 }
2706
2707 struct cli_tree_connect_state {
2708         struct cli_state *cli;
2709 };
2710
2711 static struct tevent_req *cli_raw_tcon_send(
2712         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2713         const char *service, const char *pass, const char *dev);
2714 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2715                                   uint16_t *max_xmit, uint16_t *tid);
2716
2717 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2718 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2719 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2720
2721 static struct tevent_req *cli_tree_connect_send(
2722         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2723         const char *share, const char *dev, const char *pass, int passlen)
2724 {
2725         struct tevent_req *req, *subreq;
2726         struct cli_tree_connect_state *state;
2727
2728         req = tevent_req_create(mem_ctx, &state,
2729                                 struct cli_tree_connect_state);
2730         if (req == NULL) {
2731                 return NULL;
2732         }
2733         state->cli = cli;
2734
2735         cli->share = talloc_strdup(cli, share);
2736         if (tevent_req_nomem(cli->share, req)) {
2737                 return tevent_req_post(req, ev);
2738         }
2739
2740         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2741                 char *unc;
2742
2743                 cli->smb2.tcon = smbXcli_tcon_create(cli);
2744                 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2745                         return tevent_req_post(req, ev);
2746                 }
2747
2748                 unc = talloc_asprintf(state, "\\\\%s\\%s",
2749                                       smbXcli_conn_remote_name(cli->conn),
2750                                       share);
2751                 if (tevent_req_nomem(unc, req)) {
2752                         return tevent_req_post(req, ev);
2753                 }
2754
2755                 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2756                                            cli->smb2.session, cli->smb2.tcon,
2757                                            0, /* flags */
2758                                            unc);
2759                 if (tevent_req_nomem(subreq, req)) {
2760                         return tevent_req_post(req, ev);
2761                 }
2762                 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2763                                         req);
2764                 return req;
2765         }
2766
2767         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2768                 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2769                                             pass, passlen);
2770                 if (tevent_req_nomem(subreq, req)) {
2771                         return tevent_req_post(req, ev);
2772                 }
2773                 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2774                                         req);
2775                 return req;
2776         }
2777
2778         subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2779         if (tevent_req_nomem(subreq, req)) {
2780                 return tevent_req_post(req, ev);
2781         }
2782         tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2783
2784         return req;
2785 }
2786
2787 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2788 {
2789         tevent_req_simple_finish_ntstatus(
2790                 subreq, smb2cli_tcon_recv(subreq));
2791 }
2792
2793 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2794 {
2795         tevent_req_simple_finish_ntstatus(
2796                 subreq, cli_tcon_andx_recv(subreq));
2797 }
2798
2799 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2800 {
2801         struct tevent_req *req = tevent_req_callback_data(
2802                 subreq, struct tevent_req);
2803         struct cli_tree_connect_state *state = tevent_req_data(
2804                 req, struct cli_tree_connect_state);
2805         NTSTATUS status;
2806         uint16_t max_xmit = 0;
2807         uint16_t tid = 0;
2808
2809         status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2810         if (tevent_req_nterror(req, status)) {
2811                 return;
2812         }
2813
2814         smb1cli_tcon_set_values(state->cli->smb1.tcon,
2815                                 tid,
2816                                 0, /* optional_support */
2817                                 0, /* maximal_access */
2818                                 0, /* guest_maximal_access */
2819                                 NULL, /* service */
2820                                 NULL); /* fs_type */
2821
2822         tevent_req_done(req);
2823 }
2824
2825 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2826 {
2827         return tevent_req_simple_recv_ntstatus(req);
2828 }
2829
2830 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2831                           const char *dev, const char *pass, int passlen)
2832 {
2833         struct tevent_context *ev;
2834         struct tevent_req *req;
2835         NTSTATUS status = NT_STATUS_NO_MEMORY;
2836
2837         if (smbXcli_conn_has_async_calls(cli->conn)) {
2838                 return NT_STATUS_INVALID_PARAMETER;
2839         }
2840         ev = samba_tevent_context_init(talloc_tos());
2841         if (ev == NULL) {
2842                 goto fail;
2843         }
2844         req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2845         if (req == NULL) {
2846                 goto fail;
2847         }
2848         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2849                 goto fail;
2850         }
2851         status = cli_tree_connect_recv(req);
2852 fail:
2853         TALLOC_FREE(ev);
2854         return status;
2855 }
2856
2857 /****************************************************************************
2858  Send a tree disconnect.
2859 ****************************************************************************/
2860
2861 struct cli_tdis_state {
2862         struct cli_state *cli;
2863 };
2864
2865 static void cli_tdis_done(struct tevent_req *subreq);
2866
2867 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2868                                  struct tevent_context *ev,
2869                                  struct cli_state *cli)
2870 {
2871         struct tevent_req *req, *subreq;
2872         struct cli_tdis_state *state;
2873
2874         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2875         if (req == NULL) {
2876                 return NULL;
2877         }
2878         state->cli = cli;
2879
2880         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2881         if (tevent_req_nomem(subreq, req)) {
2882                 return tevent_req_post(req, ev);
2883         }
2884         tevent_req_set_callback(subreq, cli_tdis_done, req);
2885         return req;
2886 }
2887
2888 static void cli_tdis_done(struct tevent_req *subreq)
2889 {
2890         struct tevent_req *req = tevent_req_callback_data(
2891                 subreq, struct tevent_req);
2892         struct cli_tdis_state *state = tevent_req_data(
2893                 req, struct cli_tdis_state);
2894         NTSTATUS status;
2895
2896         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2897         TALLOC_FREE(subreq);
2898         if (!NT_STATUS_IS_OK(status)) {
2899                 tevent_req_nterror(req, status);
2900                 return;
2901         }
2902         cli_state_set_tid(state->cli, UINT16_MAX);
2903         tevent_req_done(req);
2904 }
2905
2906 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2907 {
2908         return tevent_req_simple_recv_ntstatus(req);
2909 }
2910
2911 NTSTATUS cli_tdis(struct cli_state *cli)
2912 {
2913         struct tevent_context *ev;
2914         struct tevent_req *req;
2915         NTSTATUS status = NT_STATUS_NO_MEMORY;
2916
2917         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2918                 return smb2cli_tdis(cli->conn,
2919                                     cli->timeout,
2920                                     cli->smb2.session,
2921                                     cli->smb2.tcon);
2922         }
2923
2924         if (smbXcli_conn_has_async_calls(cli->conn)) {
2925                 return NT_STATUS_INVALID_PARAMETER;
2926         }
2927         ev = samba_tevent_context_init(talloc_tos());
2928         if (ev == NULL) {
2929                 goto fail;
2930         }
2931         req = cli_tdis_send(ev, ev, cli);
2932         if (req == NULL) {
2933                 goto fail;
2934         }
2935         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2936                 goto fail;
2937         }
2938         status = cli_tdis_recv(req);
2939 fail:
2940         TALLOC_FREE(ev);
2941         return status;
2942 }
2943
2944 struct cli_connect_sock_state {
2945         const char **called_names;
2946         const char **calling_names;
2947         int *called_types;
2948         int fd;
2949         uint16_t port;
2950 };
2951
2952 static void cli_connect_sock_done(struct tevent_req *subreq);
2953
2954 /*
2955  * Async only if we don't have to look up the name, i.e. "pss" is set with a
2956  * nonzero address.
2957  */
2958
2959 static struct tevent_req *cli_connect_sock_send(
2960         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2961         const char *host, int name_type, const struct sockaddr_storage *pss,
2962         const char *myname, uint16_t port)
2963 {
2964         struct tevent_req *req, *subreq;
2965         struct cli_connect_sock_state *state;
2966         const char *prog;
2967         struct sockaddr_storage *addrs;
2968         unsigned i, num_addrs;
2969         NTSTATUS status;
2970
2971         req = tevent_req_create(mem_ctx, &state,
2972                                 struct cli_connect_sock_state);
2973         if (req == NULL) {
2974                 return NULL;
2975         }
2976
2977         prog = getenv("LIBSMB_PROG");
2978         if (prog != NULL) {
2979                 state->fd = sock_exec(prog);
2980                 if (state->fd == -1) {
2981                         status = map_nt_error_from_unix(errno);
2982                         tevent_req_nterror(req, status);
2983                 } else {
2984                         state->port = 0;
2985                         tevent_req_done(req);
2986                 }
2987                 return tevent_req_post(req, ev);
2988         }
2989
2990         if ((pss == NULL) || is_zero_addr(pss)) {
2991
2992                 /*
2993                  * Here we cheat. resolve_name_list is not async at all. So
2994                  * this call will only be really async if the name lookup has
2995                  * been done externally.
2996                  */
2997
2998                 status = resolve_name_list(state, host, name_type,
2999                                            &addrs, &num_addrs);
3000                 if (!NT_STATUS_IS_OK(status)) {
3001                         tevent_req_nterror(req, status);
3002                         return tevent_req_post(req, ev);
3003                 }
3004         } else {
3005                 addrs = talloc_array(state, struct sockaddr_storage, 1);
3006                 if (tevent_req_nomem(addrs, req)) {
3007                         return tevent_req_post(req, ev);
3008                 }
3009                 addrs[0] = *pss;
3010                 num_addrs = 1;
3011         }
3012
3013         state->called_names = talloc_array(state, const char *, num_addrs);
3014         if (tevent_req_nomem(state->called_names, req)) {
3015                 return tevent_req_post(req, ev);
3016         }
3017         state->called_types = talloc_array(state, int, num_addrs);
3018         if (tevent_req_nomem(state->called_types, req)) {
3019                 return tevent_req_post(req, ev);
3020         }
3021         state->calling_names = talloc_array(state, const char *, num_addrs);
3022         if (tevent_req_nomem(state->calling_names, req)) {
3023                 return tevent_req_post(req, ev);
3024         }
3025         for (i=0; i<num_addrs; i++) {
3026                 state->called_names[i] = host;
3027                 state->called_types[i] = name_type;
3028                 state->calling_names[i] = myname;
3029         }
3030
3031         subreq = smbsock_any_connect_send(
3032                 state, ev, addrs, state->called_names, state->called_types,
3033                 state->calling_names, NULL, num_addrs, port);
3034         if (tevent_req_nomem(subreq, req)) {
3035                 return tevent_req_post(req, ev);
3036         }
3037         tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3038         return req;
3039 }
3040
3041 static void cli_connect_sock_done(struct tevent_req *subreq)
3042 {
3043         struct tevent_req *req = tevent_req_callback_data(
3044                 subreq, struct tevent_req);
3045         struct cli_connect_sock_state *state = tevent_req_data(
3046                 req, struct cli_connect_sock_state);
3047         NTSTATUS status;
3048
3049         status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3050                                           &state->port);
3051         TALLOC_FREE(subreq);
3052         if (tevent_req_nterror(req, status)) {
3053                 return;
3054         }
3055         set_socket_options(state->fd, lp_socket_options());
3056         tevent_req_done(req);
3057 }
3058
3059 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3060                                       int *pfd, uint16_t *pport)
3061 {
3062         struct cli_connect_sock_state *state = tevent_req_data(
3063                 req, struct cli_connect_sock_state);
3064         NTSTATUS status;
3065
3066         if (tevent_req_is_nterror(req, &status)) {
3067                 return status;
3068         }
3069         *pfd = state->fd;
3070         *pport = state->port;
3071         return NT_STATUS_OK;
3072 }
3073
3074 struct cli_connect_nb_state {
3075         const char *desthost;
3076         int signing_state;
3077         int flags;
3078         struct cli_state *cli;
3079 };
3080
3081 static void cli_connect_nb_done(struct tevent_req *subreq);
3082
3083 static struct tevent_req *cli_connect_nb_send(
3084         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3085         const char *host, const struct sockaddr_storage *dest_ss,
3086         uint16_t port, int name_type, const char *myname,
3087         int signing_state, int flags)
3088 {
3089         struct tevent_req *req, *subreq;
3090         struct cli_connect_nb_state *state;
3091
3092         req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3093         if (req == NULL) {
3094                 return NULL;
3095         }
3096         state->signing_state = signing_state;
3097         state->flags = flags;
3098
3099         if (host != NULL) {
3100                 char *p = strchr(host, '#');
3101
3102                 if (p != NULL) {
3103                         name_type = strtol(p+1, NULL, 16);
3104                         host = talloc_strndup(state, host, p - host);
3105                         if (tevent_req_nomem(host, req)) {
3106                                 return tevent_req_post(req, ev);
3107                         }
3108                 }
3109
3110                 state->desthost = host;
3111         } else if (dest_ss != NULL) {
3112                 state->desthost = print_canonical_sockaddr(state, dest_ss);
3113                 if (tevent_req_nomem(state->desthost, req)) {
3114                         return tevent_req_post(req, ev);
3115                 }
3116         } else {
3117                 /* No host or dest_ss given. Error out. */
3118                 tevent_req_error(req, EINVAL);
3119                 return tevent_req_post(req, ev);
3120         }
3121
3122         subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3123                                        myname, port);
3124         if (tevent_req_nomem(subreq, req)) {
3125                 return tevent_req_post(req, ev);
3126         }
3127         tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3128         return req;
3129 }
3130
3131 static void cli_connect_nb_done(struct tevent_req *subreq)
3132 {
3133         struct tevent_req *req = tevent_req_callback_data(
3134                 subreq, struct tevent_req);
3135         struct cli_connect_nb_state *state = tevent_req_data(
3136                 req, struct cli_connect_nb_state);
3137         NTSTATUS status;
3138         int fd = 0;
3139         uint16_t port;
3140
3141         status = cli_connect_sock_recv(subreq, &fd, &port);
3142         TALLOC_FREE(subreq);
3143         if (tevent_req_nterror(req, status)) {
3144                 return;
3145         }
3146
3147         state->cli = cli_state_create(state, fd, state->desthost, NULL,
3148                                       state->signing_state, state->flags);
3149         if (tevent_req_nomem(state->cli, req)) {
3150                 close(fd);
3151                 return;
3152         }
3153         tevent_req_done(req);
3154 }
3155
3156 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3157                                     struct cli_state **pcli)
3158 {
3159         struct cli_connect_nb_state *state = tevent_req_data(
3160                 req, struct cli_connect_nb_state);
3161         NTSTATUS status;
3162
3163         if (tevent_req_is_nterror(req, &status)) {
3164                 return status;
3165         }
3166         *pcli = talloc_move(NULL, &state->cli);
3167         return NT_STATUS_OK;
3168 }
3169
3170 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3171                         uint16_t port, int name_type, const char *myname,
3172                         int signing_state, int flags, struct cli_state **pcli)
3173 {
3174         struct tevent_context *ev;
3175         struct tevent_req *req;
3176         NTSTATUS status = NT_STATUS_NO_MEMORY;
3177
3178         ev = samba_tevent_context_init(talloc_tos());
3179         if (ev == NULL) {
3180                 goto fail;
3181         }
3182         req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3183                                   myname, signing_state, flags);
3184         if (req == NULL) {
3185                 goto fail;
3186         }
3187         if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3188                 goto fail;
3189         }
3190         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3191                 goto fail;
3192         }
3193         status = cli_connect_nb_recv(req, pcli);
3194 fail:
3195         TALLOC_FREE(ev);
3196         return status;
3197 }
3198
3199 struct cli_start_connection_state {
3200         struct tevent_context *ev;
3201         struct cli_state *cli;
3202         int min_protocol;
3203         int max_protocol;
3204 };
3205
3206 static void cli_start_connection_connected(struct tevent_req *subreq);
3207 static void cli_start_connection_done(struct tevent_req *subreq);
3208
3209 /**
3210    establishes a connection to after the negprot. 
3211    @param output_cli A fully initialised cli structure, non-null only on success
3212    @param dest_host The netbios name of the remote host
3213    @param dest_ss (optional) The the destination IP, NULL for name based lookup
3214    @param port (optional) The destination port (0 for default)
3215 */
3216
3217 static struct tevent_req *cli_start_connection_send(
3218         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3219         const char *my_name, const char *dest_host,
3220         const struct sockaddr_storage *dest_ss, int port,
3221         int signing_state, int flags)
3222 {
3223         struct tevent_req *req, *subreq;
3224         struct cli_start_connection_state *state;
3225
3226         req = tevent_req_create(mem_ctx, &state,
3227                                 struct cli_start_connection_state);
3228         if (req == NULL) {
3229                 return NULL;
3230         }
3231         state->ev = ev;
3232
3233         if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3234                 state->min_protocol = lp_client_ipc_min_protocol();
3235                 state->max_protocol = lp_client_ipc_max_protocol();
3236         } else {
3237                 state->min_protocol = lp_client_min_protocol();
3238                 state->max_protocol = lp_client_max_protocol();
3239         }
3240
3241         subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3242                                      0x20, my_name, signing_state, flags);
3243         if (tevent_req_nomem(subreq, req)) {
3244                 return tevent_req_post(req, ev);
3245         }
3246         tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3247         return req;
3248 }
3249
3250 static void cli_start_connection_connected(struct tevent_req *subreq)
3251 {
3252         struct tevent_req *req = tevent_req_callback_data(
3253                 subreq, struct tevent_req);
3254         struct cli_start_connection_state *state = tevent_req_data(
3255                 req, struct cli_start_connection_state);
3256         NTSTATUS status;
3257
3258         status = cli_connect_nb_recv(subreq, &state->cli);
3259         TALLOC_FREE(subreq);
3260         if (tevent_req_nterror(req, status)) {
3261                 return;
3262         }
3263
3264         subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3265                                       state->cli->timeout,
3266                                       state->min_protocol,
3267                                       state->max_protocol);
3268         if (tevent_req_nomem(subreq, req)) {
3269                 return;
3270         }
3271         tevent_req_set_callback(subreq, cli_start_connection_done, req);
3272 }
3273
3274 static void cli_start_connection_done(struct tevent_req *subreq)
3275 {
3276         struct tevent_req *req = tevent_req_callback_data(
3277                 subreq, struct tevent_req);
3278         struct cli_start_connection_state *state = tevent_req_data(
3279                 req, struct cli_start_connection_state);
3280         NTSTATUS status;
3281
3282         status = smbXcli_negprot_recv(subreq);
3283         TALLOC_FREE(subreq);
3284         if (tevent_req_nterror(req, status)) {
3285                 return;
3286         }
3287
3288         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3289                 /* Ensure we ask for some initial credits. */
3290                 smb2cli_conn_set_max_credits(state->cli->conn,
3291                                              DEFAULT_SMB2_MAX_CREDITS);
3292         }
3293
3294         tevent_req_done(req);
3295 }
3296
3297 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3298                                           struct cli_state **output_cli)
3299 {
3300         struct cli_start_connection_state *state = tevent_req_data(
3301                 req, struct cli_start_connection_state);
3302         NTSTATUS status;
3303
3304         if (tevent_req_is_nterror(req, &status)) {
3305                 return status;
3306         }
3307         *output_cli = state->cli;
3308
3309         return NT_STATUS_OK;
3310 }
3311
3312 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
3313                               const char *my_name, 
3314                               const char *dest_host, 
3315                               const struct sockaddr_storage *dest_ss, int port,
3316                               int signing_state, int flags)
3317 {
3318         struct tevent_context *ev;
3319         struct tevent_req *req;
3320         NTSTATUS status = NT_STATUS_NO_MEMORY;
3321
3322         ev = samba_tevent_context_init(talloc_tos());
3323         if (ev == NULL) {
3324                 goto fail;
3325         }
3326         req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3327                                         port, signing_state, flags);
3328         if (req == NULL) {
3329                 goto fail;
3330         }
3331         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3332                 goto fail;
3333         }
3334         status = cli_start_connection_recv(req, output_cli);
3335 fail:
3336         TALLOC_FREE(ev);
3337         return status;
3338 }
3339
3340 /**
3341    establishes a connection right up to doing tconX, password specified.
3342    @param output_cli A fully initialised cli structure, non-null only on success
3343    @param dest_host The netbios name of the remote host
3344    @param dest_ip (optional) The the destination IP, NULL for name based lookup
3345    @param port (optional) The destination port (0 for default)
3346    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
3347    @param service_type The 'type' of serivice. 
3348    @param user Username, unix string
3349    @param domain User's domain
3350    @param password User's password, unencrypted unix string.
3351 */
3352
3353 struct cli_full_connection_state {
3354         struct tevent_context *ev;
3355         const char *service;
3356         const char *service_type;
3357         const char *user;
3358         const char *domain;
3359         const char *password;
3360         int pw_len;
3361         int flags;
3362         struct cli_state *cli;
3363 };
3364
3365 static int cli_full_connection_state_destructor(
3366         struct cli_full_connection_state *s);
3367 static void cli_full_connection_started(struct tevent_req *subreq);
3368 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3369 static void cli_full_connection_done(struct tevent_req *subreq);
3370
3371 struct tevent_req *cli_full_connection_send(
3372         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3373         const char *my_name, const char *dest_host,
3374         const struct sockaddr_storage *dest_ss, int port,
3375         const char *service, const char *service_type,
3376         const char *user, const char *domain,
3377         const char *password, int flags, int signing_state)
3378 {
3379         struct tevent_req *req, *subreq;
3380         struct cli_full_connection_state *state;
3381
3382         req = tevent_req_create(mem_ctx, &state,
3383                                 struct cli_full_connection_state);
3384         if (req == NULL) {
3385                 return NULL;
3386         }
3387         talloc_set_destructor(state, cli_full_connection_state_destructor);
3388
3389         state->ev = ev;
3390         state->service = service;
3391         state->service_type = service_type;
3392         state->user = user;
3393         state->domain = domain;
3394         state->password = password;
3395         state->flags = flags;
3396
3397         state->pw_len = state->password ? strlen(state->password)+1 : 0;
3398         if (state->password == NULL) {
3399                 state->password = "";
3400         }
3401
3402         subreq = cli_start_connection_send(
3403                 state, ev, my_name, dest_host, dest_ss, port,
3404                 signing_state, flags);
3405         if (tevent_req_nomem(subreq, req)) {
3406                 return tevent_req_post(req, ev);
3407         }
3408         tevent_req_set_callback(subreq, cli_full_connection_started, req);
3409         return req;
3410 }
3411
3412 static int cli_full_connection_state_destructor(
3413         struct cli_full_connection_state *s)
3414 {
3415         if (s->cli != NULL) {
3416                 cli_shutdown(s->cli);
3417                 s->cli = NULL;
3418         }
3419         return 0;
3420 }
3421
3422 static void cli_full_connection_started(struct tevent_req *subreq)
3423 {
3424         struct tevent_req *req = tevent_req_callback_data(
3425                 subreq, struct tevent_req);
3426         struct cli_full_connection_state *state = tevent_req_data(
3427                 req, struct cli_full_connection_state);
3428         NTSTATUS status;
3429
3430         status = cli_start_connection_recv(subreq, &state->cli);
3431         TALLOC_FREE(subreq);
3432         if (tevent_req_nterror(req, status)) {
3433                 return;
3434         }
3435         subreq = cli_session_setup_send(
3436                 state, state->ev, state->cli, state->user,
3437                 state->password, state->pw_len, state->password, state->pw_len,
3438                 state->domain);
3439         if (tevent_req_nomem(subreq, req)) {
3440                 return;
3441         }
3442         tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3443 }
3444
3445 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3446 {
3447         struct tevent_req *req = tevent_req_callback_data(
3448                 subreq, struct tevent_req);
3449         struct cli_full_connection_state *state = tevent_req_data(
3450                 req, struct cli_full_connection_state);
3451         NTSTATUS status;
3452
3453         status = cli_session_setup_recv(subreq);
3454         TALLOC_FREE(subreq);
3455
3456         if (!NT_STATUS_IS_OK(status) &&
3457             (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3458
3459                 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3460
3461                 subreq = cli_session_setup_send(
3462                         state, state->ev, state->cli, "", "", 0, "", 0,
3463                         state->domain);
3464                 if (tevent_req_nomem(subreq, req)) {
3465                         return;
3466                 }
3467                 tevent_req_set_callback(
3468                         subreq, cli_full_connection_sess_set_up, req);
3469                 return;
3470         }
3471
3472         if (tevent_req_nterror(req, status)) {
3473                 return;
3474         }
3475
3476         if (state->service != NULL) {
3477                 subreq = cli_tree_connect_send(
3478                         state, state->ev, state->cli,
3479                         state->service, state->service_type,
3480                         state->password, state->pw_len);
3481                 if (tevent_req_nomem(subreq, req)) {
3482                         return;
3483                 }
3484                 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3485                 return;
3486         }
3487
3488         tevent_req_done(req);
3489 }
3490
3491 static void cli_full_connection_done(struct tevent_req *subreq)
3492 {
3493         struct tevent_req *req = tevent_req_callback_data(
3494                 subreq, struct tevent_req);
3495         NTSTATUS status;
3496
3497         status = cli_tree_connect_recv(subreq);
3498         TALLOC_FREE(subreq);
3499         if (tevent_req_nterror(req, status)) {
3500                 return;
3501         }
3502
3503         tevent_req_done(req);
3504 }
3505
3506 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3507                                   struct cli_state **output_cli)
3508 {
3509         struct cli_full_connection_state *state = tevent_req_data(
3510                 req, struct cli_full_connection_state);
3511         NTSTATUS status;
3512
3513         if (tevent_req_is_nterror(req, &status)) {
3514                 return status;
3515         }
3516         *output_cli = state->cli;
3517         talloc_set_destructor(state, NULL);
3518         return NT_STATUS_OK;
3519 }
3520
3521 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3522                              const char *my_name,
3523                              const char *dest_host,
3524                              const struct sockaddr_storage *dest_ss, int port,
3525                              const char *service, const char *service_type,
3526                              const char *user, const char *domain,
3527                              const char *password, int flags,
3528                              int signing_state)
3529 {
3530         struct tevent_context *ev;
3531         struct tevent_req *req;
3532         NTSTATUS status = NT_STATUS_NO_MEMORY;
3533
3534         ev = samba_tevent_context_init(talloc_tos());
3535         if (ev == NULL) {
3536                 goto fail;
3537         }
3538         req = cli_full_connection_send(
3539                 ev, ev, my_name, dest_host, dest_ss, port, service,
3540                 service_type, user, domain, password, flags, signing_state);
3541         if (req == NULL) {
3542                 goto fail;
3543         }
3544         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3545                 goto fail;
3546         }
3547         status = cli_full_connection_recv(req, output_cli);
3548  fail:
3549         TALLOC_FREE(ev);
3550         return status;
3551 }
3552
3553 /****************************************************************************
3554  Send an old style tcon.
3555 ****************************************************************************/
3556 struct cli_raw_tcon_state {
3557         uint16_t *ret_vwv;
3558 };
3559
3560 static void cli_raw_tcon_done(struct tevent_req *subreq);
3561
3562 static struct tevent_req *cli_raw_tcon_send(
3563         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3564         const char *service, const char *pass, const char *dev)
3565 {
3566         struct tevent_req *req, *subreq;
3567         struct cli_raw_tcon_state *state;
3568         uint8_t *bytes;
3569
3570         req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3571         if (req == NULL) {
3572                 return NULL;
3573         }
3574
3575         if (!lp_client_plaintext_auth() && (*pass)) {
3576                 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3577                           " or 'client ntlmv2 auth = yes'\n"));
3578                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3579                 return tevent_req_post(req, ev);
3580         }
3581
3582         bytes = talloc_array(state, uint8_t, 0);
3583         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3584         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3585                                    service, strlen(service)+1, NULL);
3586         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3587         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3588                                    pass, strlen(pass)+1, NULL);
3589         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3590         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3591                                    dev, strlen(dev)+1, NULL);
3592
3593         if (tevent_req_nomem(bytes, req)) {
3594                 return tevent_req_post(req, ev);
3595         }
3596
3597         subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3598                               talloc_get_size(bytes), bytes);
3599         if (tevent_req_nomem(subreq, req)) {
3600                 return tevent_req_post(req, ev);
3601         }
3602         tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3603         return req;
3604 }
3605
3606 static void cli_raw_tcon_done(struct tevent_req *subreq)
3607 {
3608         struct tevent_req *req = tevent_req_callback_data(
3609                 subreq, struct tevent_req);
3610         struct cli_raw_tcon_state *state = tevent_req_data(
3611                 req, struct cli_raw_tcon_state);
3612         NTSTATUS status;
3613
3614         status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3615                               NULL, NULL);
3616         TALLOC_FREE(subreq);
3617         if (tevent_req_nterror(req, status)) {
3618                 return;
3619         }
3620         tevent_req_done(req);
3621 }
3622
3623 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3624                                   uint16_t *max_xmit, uint16_t *tid)
3625 {
3626         struct cli_raw_tcon_state *state = tevent_req_data(
3627                 req, struct cli_raw_tcon_state);
3628         NTSTATUS status;
3629
3630         if (tevent_req_is_nterror(req, &status)) {
3631                 return status;
3632         }
3633         *max_xmit = SVAL(state->ret_vwv + 0, 0);
3634         *tid = SVAL(state->ret_vwv + 1, 0);
3635         return NT_STATUS_OK;
3636 }
3637
3638 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3639                       const char *service, const char *pass, const char *dev,
3640                       uint16_t *max_xmit, uint16_t *tid)
3641 {
3642         struct tevent_context *ev;
3643         struct tevent_req *req;
3644         NTSTATUS status = NT_STATUS_NO_MEMORY;
3645
3646         ev = samba_tevent_context_init(talloc_tos());
3647         if (ev == NULL) {
3648                 goto fail;
3649         }
3650         req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3651         if (req == NULL) {
3652                 goto fail;
3653         }
3654         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3655                 goto fail;
3656         }
3657         status = cli_raw_tcon_recv(req, max_xmit, tid);
3658 fail:
3659         TALLOC_FREE(ev);
3660         return status;
3661 }
3662
3663 /* Return a cli_state pointing at the IPC$ share for the given server */
3664
3665 struct cli_state *get_ipc_connect(char *server,
3666                                 struct sockaddr_storage *server_ss,
3667                                 const struct user_auth_info *user_info)
3668 {
3669         struct cli_state *cli;
3670         NTSTATUS nt_status;
3671         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3672
3673         if (user_info->use_kerberos) {
3674                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3675         }
3676
3677         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
3678                                         user_info->username ? user_info->username : "",
3679                                         lp_workgroup(),
3680                                         user_info->password ? user_info->password : "",
3681                                         flags,
3682                                         SMB_SIGNING_DEFAULT);
3683
3684         if (NT_STATUS_IS_OK(nt_status)) {
3685                 return cli;
3686         } else if (is_ipaddress(server)) {
3687             /* windows 9* needs a correct NMB name for connections */
3688             fstring remote_name;
3689
3690             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3691                 cli = get_ipc_connect(remote_name, server_ss, user_info);
3692                 if (cli)
3693                     return cli;
3694             }
3695         }
3696         return NULL;
3697 }
3698
3699 /*
3700  * Given the IP address of a master browser on the network, return its
3701  * workgroup and connect to it.
3702  *
3703  * This function is provided to allow additional processing beyond what
3704  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3705  * browsers and obtain each master browsers' list of domains (in case the
3706  * first master browser is recently on the network and has not yet
3707  * synchronized with other master browsers and therefore does not yet have the
3708  * entire network browse list)
3709  */
3710
3711 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3712                                 struct sockaddr_storage *mb_ip,
3713                                 const struct user_auth_info *user_info,
3714                                 char **pp_workgroup_out)
3715 {
3716         char addr[INET6_ADDRSTRLEN];
3717         fstring name;
3718         struct cli_state *cli;
3719         struct sockaddr_storage server_ss;
3720
3721         *pp_workgroup_out = NULL;
3722
3723         print_sockaddr(addr, sizeof(addr), mb_ip);
3724         DEBUG(99, ("Looking up name of master browser %s\n",
3725                    addr));
3726
3727         /*
3728          * Do a name status query to find out the name of the master browser.
3729          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3730          * master browser will not respond to a wildcard query (or, at least,
3731          * an NT4 server acting as the domain master browser will not).
3732          *
3733          * We might be able to use ONLY the query on MSBROWSE, but that's not
3734          * yet been tested with all Windows versions, so until it is, leave
3735          * the original wildcard query as the first choice and fall back to
3736          * MSBROWSE if the wildcard query fails.
3737          */
3738         if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3739             !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3740
3741                 DEBUG(99, ("Could not retrieve name status for %s\n",
3742                            addr));
3743                 return NULL;
3744         }
3745
3746         if (!find_master_ip(name, &server_ss)) {
3747                 DEBUG(99, ("Could not find master ip for %s\n", name));
3748                 return NULL;
3749         }
3750
3751         *pp_workgroup_out = talloc_strdup(ctx, name);
3752
3753         DEBUG(4, ("found master browser %s, %s\n", name, addr));
3754
3755         print_sockaddr(addr, sizeof(addr), &server_ss);
3756         cli = get_ipc_connect(addr, &server_ss, user_info);
3757
3758         return cli;
3759 }
3760
3761 /*
3762  * Return the IP address and workgroup of a master browser on the network, and
3763  * connect to it.
3764  */
3765
3766 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3767                                         const struct user_auth_info *user_info,
3768                                         char **pp_workgroup_out)
3769 {
3770         struct sockaddr_storage *ip_list;
3771         struct cli_state *cli;
3772         int i, count;
3773         NTSTATUS status;
3774
3775         *pp_workgroup_out = NULL;
3776
3777         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3778
3779         /* Go looking for workgroups by broadcasting on the local network */
3780
3781         status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3782                                     &ip_list, &count);
3783         if (!NT_STATUS_IS_OK(status)) {
3784                 DEBUG(99, ("No master browsers responded: %s\n",
3785                            nt_errstr(status)));
3786                 return NULL;
3787         }
3788
3789         for (i = 0; i < count; i++) {
3790                 char addr[INET6_ADDRSTRLEN];
3791                 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3792                 DEBUG(99, ("Found master browser %s\n", addr));
3793
3794                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3795                                 user_info, pp_workgroup_out);
3796                 if (cli)
3797                         return(cli);
3798         }
3799
3800         return NULL;
3801 }