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