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