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