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