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