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