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