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