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