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