s3:libsmb: make use of smb1cli_tcon_set_values()
[mat/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         cli->dfsroot = false;
2574
2575         if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2576                 optional_support = SVAL(vwv+2, 0);
2577         }
2578
2579         if (optional_support & SMB_SHARE_IN_DFS) {
2580                 cli->dfsroot = true;
2581         }
2582
2583         if (optional_support & SMB_EXTENDED_SIGNATURES) {
2584                 smb1cli_session_protect_session_key(cli->smb1.session);
2585         }
2586
2587         smb1cli_tcon_set_values(state->cli->smb1.tcon,
2588                                 SVAL(inhdr, HDR_TID),
2589                                 optional_support,
2590                                 0, /* maximal_access */
2591                                 0, /* guest_maximal_access */
2592                                 NULL, /* service */
2593                                 NULL); /* fs_type */
2594
2595         tevent_req_done(req);
2596 }
2597
2598 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2599 {
2600         return tevent_req_simple_recv_ntstatus(req);
2601 }
2602
2603 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2604                        const char *dev, const char *pass, int passlen)
2605 {
2606         TALLOC_CTX *frame = talloc_stackframe();
2607         struct tevent_context *ev;
2608         struct tevent_req *req;
2609         NTSTATUS status = NT_STATUS_NO_MEMORY;
2610
2611         if (smbXcli_conn_has_async_calls(cli->conn)) {
2612                 /*
2613                  * Can't use sync call while an async call is in flight
2614                  */
2615                 status = NT_STATUS_INVALID_PARAMETER;
2616                 goto fail;
2617         }
2618
2619         ev = samba_tevent_context_init(frame);
2620         if (ev == NULL) {
2621                 goto fail;
2622         }
2623
2624         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2625         if (req == NULL) {
2626                 goto fail;
2627         }
2628
2629         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2630                 goto fail;
2631         }
2632
2633         status = cli_tcon_andx_recv(req);
2634  fail:
2635         TALLOC_FREE(frame);
2636         return status;
2637 }
2638
2639 struct cli_tree_connect_state {
2640         struct cli_state *cli;
2641 };
2642
2643 static struct tevent_req *cli_raw_tcon_send(
2644         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2645         const char *service, const char *pass, const char *dev);
2646 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2647                                   uint16 *max_xmit, uint16 *tid);
2648
2649 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2650 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2651 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2652
2653 static struct tevent_req *cli_tree_connect_send(
2654         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2655         const char *share, const char *dev, const char *pass, int passlen)
2656 {
2657         struct tevent_req *req, *subreq;
2658         struct cli_tree_connect_state *state;
2659
2660         req = tevent_req_create(mem_ctx, &state,
2661                                 struct cli_tree_connect_state);
2662         if (req == NULL) {
2663                 return NULL;
2664         }
2665         state->cli = cli;
2666
2667         cli->share = talloc_strdup(cli, share);
2668         if (tevent_req_nomem(cli->share, req)) {
2669                 return tevent_req_post(req, ev);
2670         }
2671
2672         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2673                 subreq = smb2cli_tcon_send(state, ev, cli, share);
2674                 if (tevent_req_nomem(subreq, req)) {
2675                         return tevent_req_post(req, ev);
2676                 }
2677                 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2678                                         req);
2679                 return req;
2680         }
2681
2682         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2683                 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2684                                             pass, passlen);
2685                 if (tevent_req_nomem(subreq, req)) {
2686                         return tevent_req_post(req, ev);
2687                 }
2688                 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2689                                         req);
2690                 return req;
2691         }
2692
2693         subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2694         if (tevent_req_nomem(subreq, req)) {
2695                 return tevent_req_post(req, ev);
2696         }
2697         tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2698
2699         return req;
2700 }
2701
2702 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2703 {
2704         tevent_req_simple_finish_ntstatus(
2705                 subreq, smb2cli_tcon_recv(subreq));
2706 }
2707
2708 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2709 {
2710         tevent_req_simple_finish_ntstatus(
2711                 subreq, cli_tcon_andx_recv(subreq));
2712 }
2713
2714 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2715 {
2716         struct tevent_req *req = tevent_req_callback_data(
2717                 subreq, struct tevent_req);
2718         struct cli_tree_connect_state *state = tevent_req_data(
2719                 req, struct cli_tree_connect_state);
2720         NTSTATUS status;
2721         uint16_t max_xmit = 0;
2722         uint16_t tid = 0;
2723
2724         status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2725         if (tevent_req_nterror(req, status)) {
2726                 return;
2727         }
2728
2729         smb1cli_tcon_set_values(state->cli->smb1.tcon,
2730                                 tid,
2731                                 0, /* optional_support */
2732                                 0, /* maximal_access */
2733                                 0, /* guest_maximal_access */
2734                                 NULL, /* service */
2735                                 NULL); /* fs_type */
2736
2737         tevent_req_done(req);
2738 }
2739
2740 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2741 {
2742         return tevent_req_simple_recv_ntstatus(req);
2743 }
2744
2745 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2746                           const char *dev, const char *pass, int passlen)
2747 {
2748         struct tevent_context *ev;
2749         struct tevent_req *req;
2750         NTSTATUS status = NT_STATUS_NO_MEMORY;
2751
2752         if (smbXcli_conn_has_async_calls(cli->conn)) {
2753                 return NT_STATUS_INVALID_PARAMETER;
2754         }
2755         ev = samba_tevent_context_init(talloc_tos());
2756         if (ev == NULL) {
2757                 goto fail;
2758         }
2759         req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2760         if (req == NULL) {
2761                 goto fail;
2762         }
2763         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2764                 goto fail;
2765         }
2766         status = cli_tree_connect_recv(req);
2767 fail:
2768         TALLOC_FREE(ev);
2769         return status;
2770 }
2771
2772 /****************************************************************************
2773  Send a tree disconnect.
2774 ****************************************************************************/
2775
2776 struct cli_tdis_state {
2777         struct cli_state *cli;
2778 };
2779
2780 static void cli_tdis_done(struct tevent_req *subreq);
2781
2782 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2783                                  struct tevent_context *ev,
2784                                  struct cli_state *cli)
2785 {
2786         struct tevent_req *req, *subreq;
2787         struct cli_tdis_state *state;
2788
2789         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2790         if (req == NULL) {
2791                 return NULL;
2792         }
2793         state->cli = cli;
2794
2795         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2796         if (tevent_req_nomem(subreq, req)) {
2797                 return tevent_req_post(req, ev);
2798         }
2799         tevent_req_set_callback(subreq, cli_tdis_done, req);
2800         return req;
2801 }
2802
2803 static void cli_tdis_done(struct tevent_req *subreq)
2804 {
2805         struct tevent_req *req = tevent_req_callback_data(
2806                 subreq, struct tevent_req);
2807         struct cli_tdis_state *state = tevent_req_data(
2808                 req, struct cli_tdis_state);
2809         NTSTATUS status;
2810
2811         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2812         TALLOC_FREE(subreq);
2813         if (!NT_STATUS_IS_OK(status)) {
2814                 tevent_req_nterror(req, status);
2815                 return;
2816         }
2817         cli_state_set_tid(state->cli, UINT16_MAX);
2818         tevent_req_done(req);
2819 }
2820
2821 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2822 {
2823         return tevent_req_simple_recv_ntstatus(req);
2824 }
2825
2826 NTSTATUS cli_tdis(struct cli_state *cli)
2827 {
2828         struct tevent_context *ev;
2829         struct tevent_req *req;
2830         NTSTATUS status = NT_STATUS_NO_MEMORY;
2831
2832         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2833                 return smb2cli_tdis(cli);
2834         }
2835
2836         if (smbXcli_conn_has_async_calls(cli->conn)) {
2837                 return NT_STATUS_INVALID_PARAMETER;
2838         }
2839         ev = samba_tevent_context_init(talloc_tos());
2840         if (ev == NULL) {
2841                 goto fail;
2842         }
2843         req = cli_tdis_send(ev, ev, cli);
2844         if (req == NULL) {
2845                 goto fail;
2846         }
2847         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2848                 goto fail;
2849         }
2850         status = cli_tdis_recv(req);
2851 fail:
2852         TALLOC_FREE(ev);
2853         return status;
2854 }
2855
2856 struct cli_connect_sock_state {
2857         const char **called_names;
2858         const char **calling_names;
2859         int *called_types;
2860         int fd;
2861         uint16_t port;
2862 };
2863
2864 static void cli_connect_sock_done(struct tevent_req *subreq);
2865
2866 /*
2867  * Async only if we don't have to look up the name, i.e. "pss" is set with a
2868  * nonzero address.
2869  */
2870
2871 static struct tevent_req *cli_connect_sock_send(
2872         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2873         const char *host, int name_type, const struct sockaddr_storage *pss,
2874         const char *myname, uint16_t port)
2875 {
2876         struct tevent_req *req, *subreq;
2877         struct cli_connect_sock_state *state;
2878         const char *prog;
2879         unsigned i, num_addrs;
2880         NTSTATUS status;
2881
2882         req = tevent_req_create(mem_ctx, &state,
2883                                 struct cli_connect_sock_state);
2884         if (req == NULL) {
2885                 return NULL;
2886         }
2887
2888         prog = getenv("LIBSMB_PROG");
2889         if (prog != NULL) {
2890                 state->fd = sock_exec(prog);
2891                 if (state->fd == -1) {
2892                         status = map_nt_error_from_unix(errno);
2893                         tevent_req_nterror(req, status);
2894                 } else {
2895                         state->port = 0;
2896                         tevent_req_done(req);
2897                 }
2898                 return tevent_req_post(req, ev);
2899         }
2900
2901         if ((pss == NULL) || is_zero_addr(pss)) {
2902                 struct sockaddr_storage *addrs;
2903
2904                 /*
2905                  * Here we cheat. resolve_name_list is not async at all. So
2906                  * this call will only be really async if the name lookup has
2907                  * been done externally.
2908                  */
2909
2910                 status = resolve_name_list(state, host, name_type,
2911                                            &addrs, &num_addrs);
2912                 if (!NT_STATUS_IS_OK(status)) {
2913                         tevent_req_nterror(req, status);
2914                         return tevent_req_post(req, ev);
2915                 }
2916                 pss = addrs;
2917         } else {
2918                 num_addrs = 1;
2919         }
2920
2921         state->called_names = talloc_array(state, const char *, num_addrs);
2922         if (tevent_req_nomem(state->called_names, req)) {
2923                 return tevent_req_post(req, ev);
2924         }
2925         state->called_types = talloc_array(state, int, num_addrs);
2926         if (tevent_req_nomem(state->called_types, req)) {
2927                 return tevent_req_post(req, ev);
2928         }
2929         state->calling_names = talloc_array(state, const char *, num_addrs);
2930         if (tevent_req_nomem(state->calling_names, req)) {
2931                 return tevent_req_post(req, ev);
2932         }
2933         for (i=0; i<num_addrs; i++) {
2934                 state->called_names[i] = host;
2935                 state->called_types[i] = name_type;
2936                 state->calling_names[i] = myname;
2937         }
2938
2939         subreq = smbsock_any_connect_send(
2940                 state, ev, pss, state->called_names, state->called_types,
2941                 state->calling_names, NULL, num_addrs, port);
2942         if (tevent_req_nomem(subreq, req)) {
2943                 return tevent_req_post(req, ev);
2944         }
2945         tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2946         return req;
2947 }
2948
2949 static void cli_connect_sock_done(struct tevent_req *subreq)
2950 {
2951         struct tevent_req *req = tevent_req_callback_data(
2952                 subreq, struct tevent_req);
2953         struct cli_connect_sock_state *state = tevent_req_data(
2954                 req, struct cli_connect_sock_state);
2955         NTSTATUS status;
2956
2957         status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2958                                           &state->port);
2959         TALLOC_FREE(subreq);
2960         if (tevent_req_nterror(req, status)) {
2961                 return;
2962         }
2963         set_socket_options(state->fd, lp_socket_options());
2964         tevent_req_done(req);
2965 }
2966
2967 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2968                                       int *pfd, uint16_t *pport)
2969 {
2970         struct cli_connect_sock_state *state = tevent_req_data(
2971                 req, struct cli_connect_sock_state);
2972         NTSTATUS status;
2973
2974         if (tevent_req_is_nterror(req, &status)) {
2975                 return status;
2976         }
2977         *pfd = state->fd;
2978         *pport = state->port;
2979         return NT_STATUS_OK;
2980 }
2981
2982 struct cli_connect_nb_state {
2983         const char *desthost;
2984         int signing_state;
2985         int flags;
2986         struct cli_state *cli;
2987 };
2988
2989 static void cli_connect_nb_done(struct tevent_req *subreq);
2990
2991 static struct tevent_req *cli_connect_nb_send(
2992         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2993         const char *host, const struct sockaddr_storage *dest_ss,
2994         uint16_t port, int name_type, const char *myname,
2995         int signing_state, int flags)
2996 {
2997         struct tevent_req *req, *subreq;
2998         struct cli_connect_nb_state *state;
2999         char *p;
3000
3001         req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3002         if (req == NULL) {
3003                 return NULL;
3004         }
3005         state->desthost = host;
3006         state->signing_state = signing_state;
3007         state->flags = flags;
3008
3009         p = strchr(host, '#');
3010         if (p != NULL) {
3011                 name_type = strtol(p+1, NULL, 16);
3012                 host = talloc_strndup(state, host, p - host);
3013                 if (tevent_req_nomem(host, req)) {
3014                         return tevent_req_post(req, ev);
3015                 }
3016         }
3017
3018         subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3019                                        myname, port);
3020         if (tevent_req_nomem(subreq, req)) {
3021                 return tevent_req_post(req, ev);
3022         }
3023         tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3024         return req;
3025 }
3026
3027 static void cli_connect_nb_done(struct tevent_req *subreq)
3028 {
3029         struct tevent_req *req = tevent_req_callback_data(
3030                 subreq, struct tevent_req);
3031         struct cli_connect_nb_state *state = tevent_req_data(
3032                 req, struct cli_connect_nb_state);
3033         NTSTATUS status;
3034         int fd;
3035         uint16_t port;
3036
3037         status = cli_connect_sock_recv(subreq, &fd, &port);
3038         TALLOC_FREE(subreq);
3039         if (tevent_req_nterror(req, status)) {
3040                 return;
3041         }
3042
3043         state->cli = cli_state_create(state, fd, state->desthost, NULL,
3044                                       state->signing_state, state->flags);
3045         if (tevent_req_nomem(state->cli, req)) {
3046                 close(fd);
3047                 return;
3048         }
3049         tevent_req_done(req);
3050 }
3051
3052 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3053                                     struct cli_state **pcli)
3054 {
3055         struct cli_connect_nb_state *state = tevent_req_data(
3056                 req, struct cli_connect_nb_state);
3057         NTSTATUS status;
3058
3059         if (tevent_req_is_nterror(req, &status)) {
3060                 return status;
3061         }
3062         *pcli = talloc_move(NULL, &state->cli);
3063         return NT_STATUS_OK;
3064 }
3065
3066 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3067                         uint16_t port, int name_type, const char *myname,
3068                         int signing_state, int flags, struct cli_state **pcli)
3069 {
3070         struct tevent_context *ev;
3071         struct tevent_req *req;
3072         NTSTATUS status = NT_STATUS_NO_MEMORY;
3073
3074         ev = samba_tevent_context_init(talloc_tos());
3075         if (ev == NULL) {
3076                 goto fail;
3077         }
3078         req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3079                                   myname, signing_state, flags);
3080         if (req == NULL) {
3081                 goto fail;
3082         }
3083         if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3084                 goto fail;
3085         }
3086         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3087                 goto fail;
3088         }
3089         status = cli_connect_nb_recv(req, pcli);
3090 fail:
3091         TALLOC_FREE(ev);
3092         return status;
3093 }
3094
3095 struct cli_start_connection_state {
3096         struct tevent_context *ev;
3097         struct cli_state *cli;
3098 };
3099
3100 static void cli_start_connection_connected(struct tevent_req *subreq);
3101 static void cli_start_connection_done(struct tevent_req *subreq);
3102
3103 /**
3104    establishes a connection to after the negprot. 
3105    @param output_cli A fully initialised cli structure, non-null only on success
3106    @param dest_host The netbios name of the remote host
3107    @param dest_ss (optional) The the destination IP, NULL for name based lookup
3108    @param port (optional) The destination port (0 for default)
3109 */
3110
3111 static struct tevent_req *cli_start_connection_send(
3112         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3113         const char *my_name, const char *dest_host,
3114         const struct sockaddr_storage *dest_ss, int port,
3115         int signing_state, int flags)
3116 {
3117         struct tevent_req *req, *subreq;
3118         struct cli_start_connection_state *state;
3119
3120         req = tevent_req_create(mem_ctx, &state,
3121                                 struct cli_start_connection_state);
3122         if (req == NULL) {
3123                 return NULL;
3124         }
3125         state->ev = ev;
3126
3127         subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3128                                      0x20, my_name, signing_state, flags);
3129         if (tevent_req_nomem(subreq, req)) {
3130                 return tevent_req_post(req, ev);
3131         }
3132         tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3133         return req;
3134 }
3135
3136 static void cli_start_connection_connected(struct tevent_req *subreq)
3137 {
3138         struct tevent_req *req = tevent_req_callback_data(
3139                 subreq, struct tevent_req);
3140         struct cli_start_connection_state *state = tevent_req_data(
3141                 req, struct cli_start_connection_state);
3142         NTSTATUS status;
3143
3144         status = cli_connect_nb_recv(subreq, &state->cli);
3145         TALLOC_FREE(subreq);
3146         if (tevent_req_nterror(req, status)) {
3147                 return;
3148         }
3149
3150         subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3151                                       state->cli->timeout,
3152                                       lp_cli_minprotocol(),
3153                                       lp_cli_maxprotocol());
3154         if (tevent_req_nomem(subreq, req)) {
3155                 return;
3156         }
3157         tevent_req_set_callback(subreq, cli_start_connection_done, req);
3158 }
3159
3160 static void cli_start_connection_done(struct tevent_req *subreq)
3161 {
3162         struct tevent_req *req = tevent_req_callback_data(
3163                 subreq, struct tevent_req);
3164         struct cli_start_connection_state *state = tevent_req_data(
3165                 req, struct cli_start_connection_state);
3166         NTSTATUS status;
3167
3168         status = smbXcli_negprot_recv(subreq);
3169         TALLOC_FREE(subreq);
3170         if (tevent_req_nterror(req, status)) {
3171                 return;
3172         }
3173
3174         if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3175                 /* Ensure we ask for some initial credits. */
3176                 smb2cli_conn_set_max_credits(state->cli->conn,
3177                                              DEFAULT_SMB2_MAX_CREDITS);
3178         }
3179
3180         tevent_req_done(req);
3181 }
3182
3183 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3184                                           struct cli_state **output_cli)
3185 {
3186         struct cli_start_connection_state *state = tevent_req_data(
3187                 req, struct cli_start_connection_state);
3188         NTSTATUS status;
3189
3190         if (tevent_req_is_nterror(req, &status)) {
3191                 return status;
3192         }
3193         *output_cli = state->cli;
3194
3195         return NT_STATUS_OK;
3196 }
3197
3198 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
3199                               const char *my_name, 
3200                               const char *dest_host, 
3201                               const struct sockaddr_storage *dest_ss, int port,
3202                               int signing_state, int flags)
3203 {
3204         struct tevent_context *ev;
3205         struct tevent_req *req;
3206         NTSTATUS status = NT_STATUS_NO_MEMORY;
3207
3208         ev = samba_tevent_context_init(talloc_tos());
3209         if (ev == NULL) {
3210                 goto fail;
3211         }
3212         req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3213                                         port, signing_state, flags);
3214         if (req == NULL) {
3215                 goto fail;
3216         }
3217         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3218                 goto fail;
3219         }
3220         status = cli_start_connection_recv(req, output_cli);
3221 fail:
3222         TALLOC_FREE(ev);
3223         return status;
3224 }
3225
3226 /**
3227    establishes a connection right up to doing tconX, password specified.
3228    @param output_cli A fully initialised cli structure, non-null only on success
3229    @param dest_host The netbios name of the remote host
3230    @param dest_ip (optional) The the destination IP, NULL for name based lookup
3231    @param port (optional) The destination port (0 for default)
3232    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
3233    @param service_type The 'type' of serivice. 
3234    @param user Username, unix string
3235    @param domain User's domain
3236    @param password User's password, unencrypted unix string.
3237 */
3238
3239 struct cli_full_connection_state {
3240         struct tevent_context *ev;
3241         const char *service;
3242         const char *service_type;
3243         const char *user;
3244         const char *domain;
3245         const char *password;
3246         int pw_len;
3247         int flags;
3248         struct cli_state *cli;
3249 };
3250
3251 static int cli_full_connection_state_destructor(
3252         struct cli_full_connection_state *s);
3253 static void cli_full_connection_started(struct tevent_req *subreq);
3254 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3255 static void cli_full_connection_done(struct tevent_req *subreq);
3256
3257 struct tevent_req *cli_full_connection_send(
3258         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3259         const char *my_name, const char *dest_host,
3260         const struct sockaddr_storage *dest_ss, int port,
3261         const char *service, const char *service_type,
3262         const char *user, const char *domain,
3263         const char *password, int flags, int signing_state)
3264 {
3265         struct tevent_req *req, *subreq;
3266         struct cli_full_connection_state *state;
3267
3268         req = tevent_req_create(mem_ctx, &state,
3269                                 struct cli_full_connection_state);
3270         if (req == NULL) {
3271                 return NULL;
3272         }
3273         talloc_set_destructor(state, cli_full_connection_state_destructor);
3274
3275         state->ev = ev;
3276         state->service = service;
3277         state->service_type = service_type;
3278         state->user = user;
3279         state->domain = domain;
3280         state->password = password;
3281         state->flags = flags;
3282
3283         state->pw_len = state->password ? strlen(state->password)+1 : 0;
3284         if (state->password == NULL) {
3285                 state->password = "";
3286         }
3287
3288         subreq = cli_start_connection_send(
3289                 state, ev, my_name, dest_host, dest_ss, port,
3290                 signing_state, flags);
3291         if (tevent_req_nomem(subreq, req)) {
3292                 return tevent_req_post(req, ev);
3293         }
3294         tevent_req_set_callback(subreq, cli_full_connection_started, req);
3295         return req;
3296 }
3297
3298 static int cli_full_connection_state_destructor(
3299         struct cli_full_connection_state *s)
3300 {
3301         if (s->cli != NULL) {
3302                 cli_shutdown(s->cli);
3303                 s->cli = NULL;
3304         }
3305         return 0;
3306 }
3307
3308 static void cli_full_connection_started(struct tevent_req *subreq)
3309 {
3310         struct tevent_req *req = tevent_req_callback_data(
3311                 subreq, struct tevent_req);
3312         struct cli_full_connection_state *state = tevent_req_data(
3313                 req, struct cli_full_connection_state);
3314         NTSTATUS status;
3315
3316         status = cli_start_connection_recv(subreq, &state->cli);
3317         TALLOC_FREE(subreq);
3318         if (tevent_req_nterror(req, status)) {
3319                 return;
3320         }
3321         subreq = cli_session_setup_send(
3322                 state, state->ev, state->cli, state->user,
3323                 state->password, state->pw_len, state->password, state->pw_len,
3324                 state->domain);
3325         if (tevent_req_nomem(subreq, req)) {
3326                 return;
3327         }
3328         tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3329 }
3330
3331 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3332 {
3333         struct tevent_req *req = tevent_req_callback_data(
3334                 subreq, struct tevent_req);
3335         struct cli_full_connection_state *state = tevent_req_data(
3336                 req, struct cli_full_connection_state);
3337         NTSTATUS status;
3338
3339         status = cli_session_setup_recv(subreq);
3340         TALLOC_FREE(subreq);
3341
3342         if (!NT_STATUS_IS_OK(status) &&
3343             (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3344
3345                 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3346
3347                 subreq = cli_session_setup_send(
3348                         state, state->ev, state->cli, "", "", 0, "", 0,
3349                         state->domain);
3350                 if (tevent_req_nomem(subreq, req)) {
3351                         return;
3352                 }
3353                 tevent_req_set_callback(
3354                         subreq, cli_full_connection_sess_set_up, req);
3355                 return;
3356         }
3357
3358         if (tevent_req_nterror(req, status)) {
3359                 return;
3360         }
3361
3362         if (state->service != NULL) {
3363                 subreq = cli_tree_connect_send(
3364                         state, state->ev, state->cli,
3365                         state->service, state->service_type,
3366                         state->password, state->pw_len);
3367                 if (tevent_req_nomem(subreq, req)) {
3368                         return;
3369                 }
3370                 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3371                 return;
3372         }
3373
3374         status = cli_init_creds(state->cli, state->user, state->domain,
3375                                 state->password);
3376         if (tevent_req_nterror(req, status)) {
3377                 return;
3378         }
3379         tevent_req_done(req);
3380 }
3381
3382 static void cli_full_connection_done(struct tevent_req *subreq)
3383 {
3384         struct tevent_req *req = tevent_req_callback_data(
3385                 subreq, struct tevent_req);
3386         struct cli_full_connection_state *state = tevent_req_data(
3387                 req, struct cli_full_connection_state);
3388         NTSTATUS status;
3389
3390         status = cli_tree_connect_recv(subreq);
3391         TALLOC_FREE(subreq);
3392         if (tevent_req_nterror(req, status)) {
3393                 return;
3394         }
3395         status = cli_init_creds(state->cli, state->user, state->domain,
3396                                 state->password);
3397         if (tevent_req_nterror(req, status)) {
3398                 return;
3399         }
3400         tevent_req_done(req);
3401 }
3402
3403 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3404                                   struct cli_state **output_cli)
3405 {
3406         struct cli_full_connection_state *state = tevent_req_data(
3407                 req, struct cli_full_connection_state);
3408         NTSTATUS status;
3409
3410         if (tevent_req_is_nterror(req, &status)) {
3411                 return status;
3412         }
3413         *output_cli = state->cli;
3414         talloc_set_destructor(state, NULL);
3415         return NT_STATUS_OK;
3416 }
3417
3418 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3419                              const char *my_name,
3420                              const char *dest_host,
3421                              const struct sockaddr_storage *dest_ss, int port,
3422                              const char *service, const char *service_type,
3423                              const char *user, const char *domain,
3424                              const char *password, int flags,
3425                              int signing_state)
3426 {
3427         struct tevent_context *ev;
3428         struct tevent_req *req;
3429         NTSTATUS status = NT_STATUS_NO_MEMORY;
3430
3431         ev = samba_tevent_context_init(talloc_tos());
3432         if (ev == NULL) {
3433                 goto fail;
3434         }
3435         req = cli_full_connection_send(
3436                 ev, ev, my_name, dest_host, dest_ss, port, service,
3437                 service_type, user, domain, password, flags, signing_state);
3438         if (req == NULL) {
3439                 goto fail;
3440         }
3441         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3442                 goto fail;
3443         }
3444         status = cli_full_connection_recv(req, output_cli);
3445  fail:
3446         TALLOC_FREE(ev);
3447         return status;
3448 }
3449
3450 /****************************************************************************
3451  Send an old style tcon.
3452 ****************************************************************************/
3453 struct cli_raw_tcon_state {
3454         uint16_t *ret_vwv;
3455 };
3456
3457 static void cli_raw_tcon_done(struct tevent_req *subreq);
3458
3459 static struct tevent_req *cli_raw_tcon_send(
3460         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3461         const char *service, const char *pass, const char *dev)
3462 {
3463         struct tevent_req *req, *subreq;
3464         struct cli_raw_tcon_state *state;
3465         uint8_t *bytes;
3466
3467         req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3468         if (req == NULL) {
3469                 return NULL;
3470         }
3471
3472         if (!lp_client_plaintext_auth() && (*pass)) {
3473                 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3474                           " or 'client ntlmv2 auth = yes'\n"));
3475                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3476                 return tevent_req_post(req, ev);
3477         }
3478
3479         bytes = talloc_array(state, uint8_t, 0);
3480         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3481         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3482                                    service, strlen(service)+1, NULL);
3483         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3484         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3485                                    pass, strlen(pass)+1, NULL);
3486         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3487         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3488                                    dev, strlen(dev)+1, NULL);
3489
3490         if (tevent_req_nomem(bytes, req)) {
3491                 return tevent_req_post(req, ev);
3492         }
3493
3494         subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3495                               talloc_get_size(bytes), bytes);
3496         if (tevent_req_nomem(subreq, req)) {
3497                 return tevent_req_post(req, ev);
3498         }
3499         tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3500         return req;
3501 }
3502
3503 static void cli_raw_tcon_done(struct tevent_req *subreq)
3504 {
3505         struct tevent_req *req = tevent_req_callback_data(
3506                 subreq, struct tevent_req);
3507         struct cli_raw_tcon_state *state = tevent_req_data(
3508                 req, struct cli_raw_tcon_state);
3509         NTSTATUS status;
3510
3511         status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3512                               NULL, NULL);
3513         TALLOC_FREE(subreq);
3514         if (tevent_req_nterror(req, status)) {
3515                 return;
3516         }
3517         tevent_req_done(req);
3518 }
3519
3520 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3521                                   uint16 *max_xmit, uint16 *tid)
3522 {
3523         struct cli_raw_tcon_state *state = tevent_req_data(
3524                 req, struct cli_raw_tcon_state);
3525         NTSTATUS status;
3526
3527         if (tevent_req_is_nterror(req, &status)) {
3528                 return status;
3529         }
3530         *max_xmit = SVAL(state->ret_vwv + 0, 0);
3531         *tid = SVAL(state->ret_vwv + 1, 0);
3532         return NT_STATUS_OK;
3533 }
3534
3535 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3536                       const char *service, const char *pass, const char *dev,
3537                       uint16 *max_xmit, uint16 *tid)
3538 {
3539         struct tevent_context *ev;
3540         struct tevent_req *req;
3541         NTSTATUS status = NT_STATUS_NO_MEMORY;
3542
3543         ev = samba_tevent_context_init(talloc_tos());
3544         if (ev == NULL) {
3545                 goto fail;
3546         }
3547         req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3548         if (req == NULL) {
3549                 goto fail;
3550         }
3551         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3552                 goto fail;
3553         }
3554         status = cli_raw_tcon_recv(req, max_xmit, tid);
3555 fail:
3556         TALLOC_FREE(ev);
3557         return status;
3558 }
3559
3560 /* Return a cli_state pointing at the IPC$ share for the given server */
3561
3562 struct cli_state *get_ipc_connect(char *server,
3563                                 struct sockaddr_storage *server_ss,
3564                                 const struct user_auth_info *user_info)
3565 {
3566         struct cli_state *cli;
3567         NTSTATUS nt_status;
3568         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3569
3570         if (user_info->use_kerberos) {
3571                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3572         }
3573
3574         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
3575                                         user_info->username ? user_info->username : "",
3576                                         lp_workgroup(),
3577                                         user_info->password ? user_info->password : "",
3578                                         flags,
3579                                         SMB_SIGNING_DEFAULT);
3580
3581         if (NT_STATUS_IS_OK(nt_status)) {
3582                 return cli;
3583         } else if (is_ipaddress(server)) {
3584             /* windows 9* needs a correct NMB name for connections */
3585             fstring remote_name;
3586
3587             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3588                 cli = get_ipc_connect(remote_name, server_ss, user_info);
3589                 if (cli)
3590                     return cli;
3591             }
3592         }
3593         return NULL;
3594 }
3595
3596 /*
3597  * Given the IP address of a master browser on the network, return its
3598  * workgroup and connect to it.
3599  *
3600  * This function is provided to allow additional processing beyond what
3601  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3602  * browsers and obtain each master browsers' list of domains (in case the
3603  * first master browser is recently on the network and has not yet
3604  * synchronized with other master browsers and therefore does not yet have the
3605  * entire network browse list)
3606  */
3607
3608 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3609                                 struct sockaddr_storage *mb_ip,
3610                                 const struct user_auth_info *user_info,
3611                                 char **pp_workgroup_out)
3612 {
3613         char addr[INET6_ADDRSTRLEN];
3614         fstring name;
3615         struct cli_state *cli;
3616         struct sockaddr_storage server_ss;
3617
3618         *pp_workgroup_out = NULL;
3619
3620         print_sockaddr(addr, sizeof(addr), mb_ip);
3621         DEBUG(99, ("Looking up name of master browser %s\n",
3622                    addr));
3623
3624         /*
3625          * Do a name status query to find out the name of the master browser.
3626          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3627          * master browser will not respond to a wildcard query (or, at least,
3628          * an NT4 server acting as the domain master browser will not).
3629          *
3630          * We might be able to use ONLY the query on MSBROWSE, but that's not
3631          * yet been tested with all Windows versions, so until it is, leave
3632          * the original wildcard query as the first choice and fall back to
3633          * MSBROWSE if the wildcard query fails.
3634          */
3635         if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3636             !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3637
3638                 DEBUG(99, ("Could not retrieve name status for %s\n",
3639                            addr));
3640                 return NULL;
3641         }
3642
3643         if (!find_master_ip(name, &server_ss)) {
3644                 DEBUG(99, ("Could not find master ip for %s\n", name));
3645                 return NULL;
3646         }
3647
3648         *pp_workgroup_out = talloc_strdup(ctx, name);
3649
3650         DEBUG(4, ("found master browser %s, %s\n", name, addr));
3651
3652         print_sockaddr(addr, sizeof(addr), &server_ss);
3653         cli = get_ipc_connect(addr, &server_ss, user_info);
3654
3655         return cli;
3656 }
3657
3658 /*
3659  * Return the IP address and workgroup of a master browser on the network, and
3660  * connect to it.
3661  */
3662
3663 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3664                                         const struct user_auth_info *user_info,
3665                                         char **pp_workgroup_out)
3666 {
3667         struct sockaddr_storage *ip_list;
3668         struct cli_state *cli;
3669         int i, count;
3670         NTSTATUS status;
3671
3672         *pp_workgroup_out = NULL;
3673
3674         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3675
3676         /* Go looking for workgroups by broadcasting on the local network */
3677
3678         status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3679                                     &ip_list, &count);
3680         if (!NT_STATUS_IS_OK(status)) {
3681                 DEBUG(99, ("No master browsers responded: %s\n",
3682                            nt_errstr(status)));
3683                 return NULL;
3684         }
3685
3686         for (i = 0; i < count; i++) {
3687                 char addr[INET6_ADDRSTRLEN];
3688                 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3689                 DEBUG(99, ("Found master browser %s\n", addr));
3690
3691                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3692                                 user_info, pp_workgroup_out);
3693                 if (cli)
3694                         return(cli);
3695         }
3696
3697         return NULL;
3698 }