s3:libsmb: pass CLI_FULL_CONNECTION_* flags via cli_connect_nb()
[metze/samba/wip.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(TALLOC_CTX *mem_ctx,
63                                         char *inbuf,
64                                         char **dest,
65                                         uint8_t *src,
66                                         size_t srclen,
67                                         ssize_t *destlen)
68 {
69         *destlen = clistr_pull_talloc(mem_ctx,
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(mem_ctx, "");
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_state_set_uid(state->cli, 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_state_capabilities(cli) & (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_state_get_vc_num(cli));
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_state_set_uid(state->cli, 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_state_get_vc_num(cli));
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_state_set_uid(state->cli, 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. Windows clients also don't
865                          * use hostname...
866                          */
867                         names_blob = NTLMv2_generate_names_blob(
868                                 NULL, NULL, 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_state_get_vc_num(cli));
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_state_set_uid(state->cli, 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_state_set_uid(state->cli, SVAL(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                 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
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                 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
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 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1789                               const char *user,
1790                               const char *pass,
1791                               const char *user_domain,
1792                               const char * dest_realm)
1793 {
1794         char *principal = NULL;
1795         char *OIDs[ASN1_MAX_OIDS];
1796         int i;
1797         DATA_BLOB blob;
1798         const char *p = NULL;
1799         char *account = NULL;
1800         NTSTATUS status;
1801
1802         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1803
1804         /* the server might not even do spnego */
1805         if (cli->secblob.length <= 16) {
1806                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1807                 goto ntlmssp;
1808         }
1809
1810 #if 0
1811         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1812 #endif
1813
1814         /* there is 16 bytes of GUID before the real spnego packet starts */
1815         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1816
1817         /* The server sent us the first part of the SPNEGO exchange in the
1818          * negprot reply. It is WRONG to depend on the principal sent in the
1819          * negprot reply, but right now we do it. If we don't receive one,
1820          * we try to best guess, then fall back to NTLM.  */
1821         if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1822                         OIDs[0] == NULL) {
1823                 data_blob_free(&blob);
1824                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1825         }
1826         data_blob_free(&blob);
1827
1828         /* make sure the server understands kerberos */
1829         for (i=0;OIDs[i];i++) {
1830                 if (i == 0)
1831                         DEBUG(3,("got OID=%s\n", OIDs[i]));
1832                 else
1833                         DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1834                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1835                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1836                         cli->got_kerberos_mechanism = True;
1837                 }
1838                 talloc_free(OIDs[i]);
1839         }
1840
1841         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1842
1843         status = cli_set_username(cli, user);
1844         if (!NT_STATUS_IS_OK(status)) {
1845                 TALLOC_FREE(principal);
1846                 return ADS_ERROR_NT(status);
1847         }
1848
1849 #ifdef HAVE_KRB5
1850         /* If password is set we reauthenticate to kerberos server
1851          * and do not store results */
1852
1853         if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1854                 ADS_STATUS rc;
1855                 const char *remote_name = cli_state_remote_name(cli);
1856
1857                 if (pass && *pass) {
1858                         int ret;
1859
1860                         use_in_memory_ccache();
1861                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1862
1863                         if (ret){
1864                                 TALLOC_FREE(principal);
1865                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1866                                 if (cli->fallback_after_kerberos)
1867                                         goto ntlmssp;
1868                                 return ADS_ERROR_KRB5(ret);
1869                         }
1870                 }
1871
1872                 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1873                  */
1874                 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1875                         TALLOC_FREE(principal);
1876                 }
1877
1878                 if (principal == NULL &&
1879                         !is_ipaddress(remote_name) &&
1880                         !strequal(STAR_SMBSERVER,
1881                                   remote_name)) {
1882                         char *realm = NULL;
1883                         char *host = NULL;
1884                         DEBUG(3,("cli_session_setup_spnego: using target "
1885                                  "hostname not SPNEGO principal\n"));
1886
1887                         host = strchr_m(remote_name, '.');
1888                         if (dest_realm) {
1889                                 realm = SMB_STRDUP(dest_realm);
1890                                 if (!realm) {
1891                                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1892                                 }
1893                                 strupper_m(realm);
1894                         } else {
1895                                 if (host) {
1896                                         /* DNS name. */
1897                                         realm = kerberos_get_realm_from_hostname(remote_name);
1898                                 } else {
1899                                         /* NetBIOS name - use our realm. */
1900                                         realm = kerberos_get_default_realm_from_ccache();
1901                                 }
1902                         }
1903
1904                         if (realm == NULL || *realm == '\0') {
1905                                 realm = SMB_STRDUP(lp_realm());
1906                                 if (!realm) {
1907                                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1908                                 }
1909                                 strupper_m(realm);
1910                                 DEBUG(3,("cli_session_setup_spnego: cannot "
1911                                         "get realm from dest_realm %s, "
1912                                         "desthost %s. Using default "
1913                                         "smb.conf realm %s\n",
1914                                         dest_realm ? dest_realm : "<null>",
1915                                         remote_name,
1916                                         realm));
1917                         }
1918
1919                         principal = talloc_asprintf(talloc_tos(),
1920                                                     "cifs/%s@%s",
1921                                                     remote_name,
1922                                                     realm);
1923                         if (!principal) {
1924                                 SAFE_FREE(realm);
1925                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1926                         }
1927                         DEBUG(3,("cli_session_setup_spnego: guessed "
1928                                 "server principal=%s\n",
1929                                 principal ? principal : "<null>"));
1930
1931                         SAFE_FREE(realm);
1932                 }
1933
1934                 if (principal) {
1935                         rc = cli_session_setup_kerberos(cli, principal);
1936                         if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1937                                 TALLOC_FREE(principal);
1938                                 return rc;
1939                         }
1940                 }
1941         }
1942 #endif
1943
1944         TALLOC_FREE(principal);
1945
1946 ntlmssp:
1947
1948         account = talloc_strdup(talloc_tos(), user);
1949         if (!account) {
1950                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1951         }
1952
1953         /* when falling back to ntlmssp while authenticating with a machine
1954          * account strip off the realm - gd */
1955
1956         if ((p = strchr_m(user, '@')) != NULL) {
1957                 account[PTR_DIFF(p,user)] = '\0';
1958         }
1959
1960         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1961 }
1962
1963 /****************************************************************************
1964  Send a session setup. The username and workgroup is in UNIX character
1965  format and must be converted to DOS codepage format before sending. If the
1966  password is in plaintext, the same should be done.
1967 ****************************************************************************/
1968
1969 NTSTATUS cli_session_setup(struct cli_state *cli,
1970                            const char *user,
1971                            const char *pass, int passlen,
1972                            const char *ntpass, int ntpasslen,
1973                            const char *workgroup)
1974 {
1975         char *p;
1976         char *user2;
1977
1978         if (user) {
1979                 user2 = talloc_strdup(talloc_tos(), user);
1980         } else {
1981                 user2 = talloc_strdup(talloc_tos(), "");
1982         }
1983         if (user2 == NULL) {
1984                 return NT_STATUS_NO_MEMORY;
1985         }
1986
1987         if (!workgroup) {
1988                 workgroup = "";
1989         }
1990
1991         /* allow for workgroups as part of the username */
1992         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1993             (p=strchr_m(user2,*lp_winbind_separator()))) {
1994                 *p = 0;
1995                 user = p+1;
1996                 strupper_m(user2);
1997                 workgroup = user2;
1998         }
1999
2000         if (cli_state_protocol(cli) < PROTOCOL_LANMAN1) {
2001                 return NT_STATUS_OK;
2002         }
2003
2004         /* now work out what sort of session setup we are going to
2005            do. I have split this into separate functions to make the
2006            flow a bit easier to understand (tridge) */
2007
2008         /* if its an older server then we have to use the older request format */
2009
2010         if (cli_state_protocol(cli) < PROTOCOL_NT1) {
2011                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2012                         DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2013                                   " or 'client ntlmv2 auth = yes'\n"));
2014                         return NT_STATUS_ACCESS_DENIED;
2015                 }
2016
2017                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2018                     !lp_client_plaintext_auth() && (*pass)) {
2019                         DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2020                                   " or 'client ntlmv2 auth = yes'\n"));
2021                         return NT_STATUS_ACCESS_DENIED;
2022                 }
2023
2024                 return cli_session_setup_lanman2(cli, user, pass, passlen,
2025                                                  workgroup);
2026         }
2027
2028         /* if no user is supplied then we have to do an anonymous connection.
2029            passwords are ignored */
2030
2031         if (!user || !*user)
2032                 return cli_session_setup_guest(cli);
2033
2034         /* if the server is share level then send a plaintext null
2035            password at this point. The password is sent in the tree
2036            connect */
2037
2038         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
2039                 return cli_session_setup_plain(cli, user, "", workgroup);
2040
2041         /* if the server doesn't support encryption then we have to use 
2042            plaintext. The second password is ignored */
2043
2044         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2045                 if (!lp_client_plaintext_auth() && (*pass)) {
2046                         DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2047                                   " or 'client ntlmv2 auth = yes'\n"));
2048                         return NT_STATUS_ACCESS_DENIED;
2049                 }
2050                 return cli_session_setup_plain(cli, user, pass, workgroup);
2051         }
2052
2053         /* if the server supports extended security then use SPNEGO */
2054
2055         if (cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) {
2056                 const char *remote_realm = cli_state_remote_realm(cli);
2057                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2058                                                              workgroup,
2059                                                              remote_realm);
2060                 if (!ADS_ERR_OK(status)) {
2061                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2062                         return ads_ntstatus(status);
2063                 }
2064         } else {
2065                 NTSTATUS status;
2066
2067                 /* otherwise do a NT1 style session setup */
2068                 status = cli_session_setup_nt1(cli, user, pass, passlen,
2069                                                ntpass, ntpasslen, workgroup);
2070                 if (!NT_STATUS_IS_OK(status)) {
2071                         DEBUG(3,("cli_session_setup: NT1 session setup "
2072                                  "failed: %s\n", nt_errstr(status)));
2073                         return status;
2074                 }
2075         }
2076
2077         if (strstr(cli->server_type, "Samba")) {
2078                 cli->is_samba = True;
2079         }
2080
2081         return NT_STATUS_OK;
2082 }
2083
2084 /****************************************************************************
2085  Send a uloggoff.
2086 *****************************************************************************/
2087
2088 struct cli_ulogoff_state {
2089         struct cli_state *cli;
2090         uint16_t vwv[3];
2091 };
2092
2093 static void cli_ulogoff_done(struct tevent_req *subreq);
2094
2095 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2096                                     struct tevent_context *ev,
2097                                     struct cli_state *cli)
2098 {
2099         struct tevent_req *req, *subreq;
2100         struct cli_ulogoff_state *state;
2101
2102         req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2103         if (req == NULL) {
2104                 return NULL;
2105         }
2106         state->cli = cli;
2107
2108         SCVAL(state->vwv+0, 0, 0xFF);
2109         SCVAL(state->vwv+1, 0, 0);
2110         SSVAL(state->vwv+2, 0, 0);
2111
2112         subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2113                               0, NULL);
2114         if (tevent_req_nomem(subreq, req)) {
2115                 return tevent_req_post(req, ev);
2116         }
2117         tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2118         return req;
2119 }
2120
2121 static void cli_ulogoff_done(struct tevent_req *subreq)
2122 {
2123         struct tevent_req *req = tevent_req_callback_data(
2124                 subreq, struct tevent_req);
2125         struct cli_ulogoff_state *state = tevent_req_data(
2126                 req, struct cli_ulogoff_state);
2127         NTSTATUS status;
2128
2129         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2130         if (!NT_STATUS_IS_OK(status)) {
2131                 tevent_req_nterror(req, status);
2132                 return;
2133         }
2134         cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2135         tevent_req_done(req);
2136 }
2137
2138 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2139 {
2140         return tevent_req_simple_recv_ntstatus(req);
2141 }
2142
2143 NTSTATUS cli_ulogoff(struct cli_state *cli)
2144 {
2145         struct tevent_context *ev;
2146         struct tevent_req *req;
2147         NTSTATUS status = NT_STATUS_NO_MEMORY;
2148
2149         if (cli_has_async_calls(cli)) {
2150                 return NT_STATUS_INVALID_PARAMETER;
2151         }
2152         ev = tevent_context_init(talloc_tos());
2153         if (ev == NULL) {
2154                 goto fail;
2155         }
2156         req = cli_ulogoff_send(ev, ev, cli);
2157         if (req == NULL) {
2158                 goto fail;
2159         }
2160         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2161                 goto fail;
2162         }
2163         status = cli_ulogoff_recv(req);
2164 fail:
2165         TALLOC_FREE(ev);
2166         return status;
2167 }
2168
2169 /****************************************************************************
2170  Send a tconX.
2171 ****************************************************************************/
2172
2173 struct cli_tcon_andx_state {
2174         struct cli_state *cli;
2175         uint16_t vwv[4];
2176         struct iovec bytes;
2177 };
2178
2179 static void cli_tcon_andx_done(struct tevent_req *subreq);
2180
2181 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2182                                         struct event_context *ev,
2183                                         struct cli_state *cli,
2184                                         const char *share, const char *dev,
2185                                         const char *pass, int passlen,
2186                                         struct tevent_req **psmbreq)
2187 {
2188         struct tevent_req *req, *subreq;
2189         struct cli_tcon_andx_state *state;
2190         uint8_t p24[24];
2191         uint16_t *vwv;
2192         char *tmp = NULL;
2193         uint8_t *bytes;
2194
2195         *psmbreq = NULL;
2196
2197         req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2198         if (req == NULL) {
2199                 return NULL;
2200         }
2201         state->cli = cli;
2202         vwv = state->vwv;
2203
2204         cli->share = talloc_strdup(cli, share);
2205         if (!cli->share) {
2206                 return NULL;
2207         }
2208
2209         /* in user level security don't send a password now */
2210         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2211                 passlen = 1;
2212                 pass = "";
2213         } else if (pass == NULL) {
2214                 DEBUG(1, ("Server not using user level security and no "
2215                           "password supplied.\n"));
2216                 goto access_denied;
2217         }
2218
2219         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2220             *pass && passlen != 24) {
2221                 if (!lp_client_lanman_auth()) {
2222                         DEBUG(1, ("Server requested LANMAN password "
2223                                   "(share-level security) but "
2224                                   "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2225                         goto access_denied;
2226                 }
2227
2228                 /*
2229                  * Non-encrypted passwords - convert to DOS codepage before
2230                  * encryption.
2231                  */
2232                 SMBencrypt(pass, cli->secblob.data, p24);
2233                 passlen = 24;
2234                 pass = (const char *)p24;
2235         } else {
2236                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2237                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2238                    == 0) {
2239                         uint8_t *tmp_pass;
2240
2241                         if (!lp_client_plaintext_auth() && (*pass)) {
2242                                 DEBUG(1, ("Server requested plaintext "
2243                                           "password but "
2244                                           "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2245                                 goto access_denied;
2246                         }
2247
2248                         /*
2249                          * Non-encrypted passwords - convert to DOS codepage
2250                          * before using.
2251                          */
2252                         tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2253                         if (tevent_req_nomem(tmp_pass, req)) {
2254                                 return tevent_req_post(req, ev);
2255                         }
2256                         tmp_pass = trans2_bytes_push_str(tmp_pass,
2257                                                          false, /* always DOS */
2258                                                          pass,
2259                                                          passlen,
2260                                                          NULL);
2261                         if (tevent_req_nomem(tmp_pass, req)) {
2262                                 return tevent_req_post(req, ev);
2263                         }
2264                         pass = (const char *)tmp_pass;
2265                         passlen = talloc_get_size(tmp_pass);
2266                 }
2267         }
2268
2269         SCVAL(vwv+0, 0, 0xFF);
2270         SCVAL(vwv+0, 1, 0);
2271         SSVAL(vwv+1, 0, 0);
2272         SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2273         SSVAL(vwv+3, 0, passlen);
2274
2275         if (passlen && pass) {
2276                 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2277         } else {
2278                 bytes = talloc_array(state, uint8_t, 0);
2279         }
2280
2281         /*
2282          * Add the sharename
2283          */
2284         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2285                                          cli_state_remote_name(cli), share);
2286         if (tmp == NULL) {
2287                 TALLOC_FREE(req);
2288                 return NULL;
2289         }
2290         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2291                                    NULL);
2292         TALLOC_FREE(tmp);
2293
2294         /*
2295          * Add the devicetype
2296          */
2297         tmp = talloc_strdup_upper(talloc_tos(), dev);
2298         if (tmp == NULL) {
2299                 TALLOC_FREE(req);
2300                 return NULL;
2301         }
2302         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2303         TALLOC_FREE(tmp);
2304
2305         if (bytes == NULL) {
2306                 TALLOC_FREE(req);
2307                 return NULL;
2308         }
2309
2310         state->bytes.iov_base = (void *)bytes;
2311         state->bytes.iov_len = talloc_get_size(bytes);
2312
2313         subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2314                                     1, &state->bytes);
2315         if (subreq == NULL) {
2316                 TALLOC_FREE(req);
2317                 return NULL;
2318         }
2319         tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2320         *psmbreq = subreq;
2321         return req;
2322
2323  access_denied:
2324         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2325         return tevent_req_post(req, ev);
2326 }
2327
2328 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2329                                       struct event_context *ev,
2330                                       struct cli_state *cli,
2331                                       const char *share, const char *dev,
2332                                       const char *pass, int passlen)
2333 {
2334         struct tevent_req *req, *subreq;
2335         NTSTATUS status;
2336
2337         req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2338                                    &subreq);
2339         if (req == NULL) {
2340                 return NULL;
2341         }
2342         if (subreq == NULL) {
2343                 return req;
2344         }
2345         status = cli_smb_req_send(subreq);
2346         if (!NT_STATUS_IS_OK(status)) {
2347                 tevent_req_nterror(req, status);
2348                 return tevent_req_post(req, ev);
2349         }
2350         return req;
2351 }
2352
2353 static void cli_tcon_andx_done(struct tevent_req *subreq)
2354 {
2355         struct tevent_req *req = tevent_req_callback_data(
2356                 subreq, struct tevent_req);
2357         struct cli_tcon_andx_state *state = tevent_req_data(
2358                 req, struct cli_tcon_andx_state);
2359         struct cli_state *cli = state->cli;
2360         uint8_t *in;
2361         char *inbuf;
2362         uint8_t wct;
2363         uint16_t *vwv;
2364         uint32_t num_bytes;
2365         uint8_t *bytes;
2366         NTSTATUS status;
2367
2368         status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2369                               &num_bytes, &bytes);
2370         TALLOC_FREE(subreq);
2371         if (!NT_STATUS_IS_OK(status)) {
2372                 tevent_req_nterror(req, status);
2373                 return;
2374         }
2375
2376         inbuf = (char *)in;
2377
2378         if (num_bytes) {
2379                 if (clistr_pull_talloc(cli,
2380                                 inbuf,
2381                                 SVAL(inbuf, smb_flg2),
2382                                 &cli->dev,
2383                                 bytes,
2384                                 num_bytes,
2385                                 STR_TERMINATE|STR_ASCII) == -1) {
2386                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2387                         return;
2388                 }
2389         } else {
2390                 cli->dev = talloc_strdup(cli, "");
2391                 if (cli->dev == NULL) {
2392                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2393                         return;
2394                 }
2395         }
2396
2397         if ((cli_state_protocol(cli) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2398                 /* almost certainly win95 - enable bug fixes */
2399                 cli->win95 = True;
2400         }
2401
2402         /*
2403          * Make sure that we have the optional support 16-bit field. WCT > 2.
2404          * Avoids issues when connecting to Win9x boxes sharing files
2405          */
2406
2407         cli->dfsroot = false;
2408
2409         if ((wct > 2) && (cli_state_protocol(cli) >= PROTOCOL_LANMAN2)) {
2410                 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2411         }
2412
2413         cli->smb1.tid = SVAL(inbuf,smb_tid);
2414         tevent_req_done(req);
2415 }
2416
2417 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2418 {
2419         return tevent_req_simple_recv_ntstatus(req);
2420 }
2421
2422 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2423                        const char *dev, const char *pass, int passlen)
2424 {
2425         TALLOC_CTX *frame = talloc_stackframe();
2426         struct event_context *ev;
2427         struct tevent_req *req;
2428         NTSTATUS status = NT_STATUS_OK;
2429
2430         if (cli_has_async_calls(cli)) {
2431                 /*
2432                  * Can't use sync call while an async call is in flight
2433                  */
2434                 status = NT_STATUS_INVALID_PARAMETER;
2435                 goto fail;
2436         }
2437
2438         ev = event_context_init(frame);
2439         if (ev == NULL) {
2440                 status = NT_STATUS_NO_MEMORY;
2441                 goto fail;
2442         }
2443
2444         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2445         if (req == NULL) {
2446                 status = NT_STATUS_NO_MEMORY;
2447                 goto fail;
2448         }
2449
2450         if (!tevent_req_poll(req, ev)) {
2451                 status = map_nt_error_from_unix(errno);
2452                 goto fail;
2453         }
2454
2455         status = cli_tcon_andx_recv(req);
2456  fail:
2457         TALLOC_FREE(frame);
2458         return status;
2459 }
2460
2461 /****************************************************************************
2462  Send a tree disconnect.
2463 ****************************************************************************/
2464
2465 struct cli_tdis_state {
2466         struct cli_state *cli;
2467 };
2468
2469 static void cli_tdis_done(struct tevent_req *subreq);
2470
2471 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2472                                  struct tevent_context *ev,
2473                                  struct cli_state *cli)
2474 {
2475         struct tevent_req *req, *subreq;
2476         struct cli_tdis_state *state;
2477
2478         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2479         if (req == NULL) {
2480                 return NULL;
2481         }
2482         state->cli = cli;
2483
2484         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2485         if (tevent_req_nomem(subreq, req)) {
2486                 return tevent_req_post(req, ev);
2487         }
2488         tevent_req_set_callback(subreq, cli_tdis_done, req);
2489         return req;
2490 }
2491
2492 static void cli_tdis_done(struct tevent_req *subreq)
2493 {
2494         struct tevent_req *req = tevent_req_callback_data(
2495                 subreq, struct tevent_req);
2496         struct cli_tdis_state *state = tevent_req_data(
2497                 req, struct cli_tdis_state);
2498         NTSTATUS status;
2499
2500         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2501         TALLOC_FREE(subreq);
2502         if (!NT_STATUS_IS_OK(status)) {
2503                 tevent_req_nterror(req, status);
2504                 return;
2505         }
2506         state->cli->smb1.tid = UINT16_MAX;
2507         tevent_req_done(req);
2508 }
2509
2510 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2511 {
2512         return tevent_req_simple_recv_ntstatus(req);
2513 }
2514
2515 NTSTATUS cli_tdis(struct cli_state *cli)
2516 {
2517         struct tevent_context *ev;
2518         struct tevent_req *req;
2519         NTSTATUS status = NT_STATUS_NO_MEMORY;
2520
2521         if (cli_has_async_calls(cli)) {
2522                 return NT_STATUS_INVALID_PARAMETER;
2523         }
2524         ev = tevent_context_init(talloc_tos());
2525         if (ev == NULL) {
2526                 goto fail;
2527         }
2528         req = cli_tdis_send(ev, ev, cli);
2529         if (req == NULL) {
2530                 goto fail;
2531         }
2532         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2533                 goto fail;
2534         }
2535         status = cli_tdis_recv(req);
2536 fail:
2537         TALLOC_FREE(ev);
2538         return status;
2539 }
2540
2541 /****************************************************************************
2542  Send a negprot command.
2543 ****************************************************************************/
2544
2545 struct cli_negprot_state {
2546         struct cli_state *cli;
2547 };
2548
2549 static void cli_negprot_done(struct tevent_req *subreq);
2550
2551 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2552                                     struct event_context *ev,
2553                                     struct cli_state *cli)
2554 {
2555         struct tevent_req *req, *subreq;
2556         struct cli_negprot_state *state;
2557         uint8_t *bytes = NULL;
2558         int numprots;
2559
2560         req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2561         if (req == NULL) {
2562                 return NULL;
2563         }
2564         state->cli = cli;
2565
2566         if (cli_state_protocol(cli) < PROTOCOL_NT1)
2567                 cli->use_spnego = False;
2568
2569         /* setup the protocol strings */
2570         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2571                 uint8_t c = 2;
2572                 if (prots[numprots].prot > cli_state_protocol(cli)) {
2573                         break;
2574                 }
2575                 bytes = (uint8_t *)talloc_append_blob(
2576                         state, bytes, data_blob_const(&c, sizeof(c)));
2577                 if (tevent_req_nomem(bytes, req)) {
2578                         return tevent_req_post(req, ev);
2579                 }
2580                 bytes = smb_bytes_push_str(bytes, false,
2581                                            prots[numprots].name,
2582                                            strlen(prots[numprots].name)+1,
2583                                            NULL);
2584                 if (tevent_req_nomem(bytes, req)) {
2585                         return tevent_req_post(req, ev);
2586                 }
2587         }
2588
2589         subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2590                               talloc_get_size(bytes), bytes);
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_state_protocol(cli))) {
2626                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2627                 return;
2628         }
2629
2630         cli->protocol = prots[protnum].prot;
2631
2632         if ((cli_state_protocol(cli) < 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_state_protocol(cli) >= 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_state_capabilities(cli) & 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_state_capabilities(cli) & 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_state_protocol(cli) >= 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, const struct sockaddr_storage *dest_ss,
2848                         uint16_t port, int name_type, const char *myname,
2849                         int signing_state, int flags, 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
2858         desthost = talloc_strdup(talloc_tos(), host);
2859         if (desthost == NULL) {
2860                 goto fail;
2861         }
2862
2863         p = strchr(host, '#');
2864         if (p != NULL) {
2865                 name_type = strtol(p+1, NULL, 16);
2866                 host = talloc_strndup(talloc_tos(), host, p - host);
2867                 if (host == NULL) {
2868                         goto fail;
2869                 }
2870         }
2871
2872         status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2873                                   20, &fd, &port);
2874         if (!NT_STATUS_IS_OK(status)) {
2875                 goto fail;
2876         }
2877
2878         cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2879         if (cli == NULL) {
2880                 goto fail;
2881         }
2882
2883         *pcli = cli;
2884         status = NT_STATUS_OK;
2885 fail:
2886         TALLOC_FREE(frame);
2887         return status;
2888 }
2889
2890 /**
2891    establishes a connection to after the negprot. 
2892    @param output_cli A fully initialised cli structure, non-null only on success
2893    @param dest_host The netbios name of the remote host
2894    @param dest_ss (optional) The the destination IP, NULL for name based lookup
2895    @param port (optional) The destination port (0 for default)
2896 */
2897 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
2898                               const char *my_name, 
2899                               const char *dest_host, 
2900                               const struct sockaddr_storage *dest_ss, int port,
2901                               int signing_state, int flags)
2902 {
2903         NTSTATUS nt_status;
2904         struct cli_state *cli;
2905
2906         nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2907                                    signing_state, flags, &cli);
2908         if (!NT_STATUS_IS_OK(nt_status)) {
2909                 DEBUG(10, ("cli_connect_nb failed: %s\n",
2910                            nt_errstr(nt_status)));
2911                 return nt_status;
2912         }
2913
2914         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2915                 cli->use_spnego = False;
2916         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2917                 cli->use_kerberos = True;
2918
2919         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2920              cli->use_kerberos) {
2921                 cli->fallback_after_kerberos = true;
2922         }
2923         if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2924                 cli->use_ccache = true;
2925         }
2926
2927         nt_status = cli_negprot(cli);
2928         if (!NT_STATUS_IS_OK(nt_status)) {
2929                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2930                 cli_shutdown(cli);
2931                 return nt_status;
2932         }
2933
2934         *output_cli = cli;
2935         return NT_STATUS_OK;
2936 }
2937
2938
2939 /**
2940    establishes a connection right up to doing tconX, password specified.
2941    @param output_cli A fully initialised cli structure, non-null only on success
2942    @param dest_host The netbios name of the remote host
2943    @param dest_ip (optional) The the destination IP, NULL for name based lookup
2944    @param port (optional) The destination port (0 for default)
2945    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
2946    @param service_type The 'type' of serivice. 
2947    @param user Username, unix string
2948    @param domain User's domain
2949    @param password User's password, unencrypted unix string.
2950 */
2951
2952 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
2953                              const char *my_name, 
2954                              const char *dest_host, 
2955                              const struct sockaddr_storage *dest_ss, int port,
2956                              const char *service, const char *service_type,
2957                              const char *user, const char *domain, 
2958                              const char *password, int flags,
2959                              int signing_state)
2960 {
2961         NTSTATUS nt_status;
2962         struct cli_state *cli = NULL;
2963         int pw_len = password ? strlen(password)+1 : 0;
2964
2965         *output_cli = NULL;
2966
2967         if (password == NULL) {
2968                 password = "";
2969         }
2970
2971         nt_status = cli_start_connection(&cli, my_name, dest_host,
2972                                          dest_ss, port, signing_state,
2973                                          flags);
2974
2975         if (!NT_STATUS_IS_OK(nt_status)) {
2976                 return nt_status;
2977         }
2978
2979         cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2980         cli->use_level_II_oplocks =
2981                 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2982
2983         nt_status = cli_session_setup(cli, user, password, pw_len, password,
2984                                       pw_len, domain);
2985         if (!NT_STATUS_IS_OK(nt_status)) {
2986
2987                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2988                         DEBUG(1,("failed session setup with %s\n",
2989                                  nt_errstr(nt_status)));
2990                         cli_shutdown(cli);
2991                         return nt_status;
2992                 }
2993
2994                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2995                 if (!NT_STATUS_IS_OK(nt_status)) {
2996                         DEBUG(1,("anonymous failed session setup with %s\n",
2997                                  nt_errstr(nt_status)));
2998                         cli_shutdown(cli);
2999                         return nt_status;
3000                 }
3001         }
3002
3003         if (service) {
3004                 nt_status = cli_tcon_andx(cli, service, service_type, password,
3005                                           pw_len);
3006                 if (!NT_STATUS_IS_OK(nt_status)) {
3007                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3008                         cli_shutdown(cli);
3009                         if (NT_STATUS_IS_OK(nt_status)) {
3010                                 nt_status = NT_STATUS_UNSUCCESSFUL;
3011                         }
3012                         return nt_status;
3013                 }
3014         }
3015
3016         nt_status = cli_init_creds(cli, user, domain, password);
3017         if (!NT_STATUS_IS_OK(nt_status)) {
3018                 cli_shutdown(cli);
3019                 return nt_status;
3020         }
3021
3022         *output_cli = cli;
3023         return NT_STATUS_OK;
3024 }
3025
3026 /****************************************************************************
3027  Send an old style tcon.
3028 ****************************************************************************/
3029 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
3030                       const char *service, const char *pass, const char *dev,
3031                       uint16 *max_xmit, uint16 *tid)
3032 {
3033         struct tevent_req *req;
3034         uint16_t *ret_vwv;
3035         uint8_t *bytes;
3036         NTSTATUS status;
3037
3038         if (!lp_client_plaintext_auth() && (*pass)) {
3039                 DEBUG(1, ("Server requested plaintext password but 'client "
3040                           "plaintext auth' is disabled\n"));
3041                 return NT_STATUS_ACCESS_DENIED;
3042         }
3043
3044         bytes = talloc_array(talloc_tos(), uint8_t, 0);
3045         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3046         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3047                                    service, strlen(service)+1, NULL);
3048         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3049         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3050                                    pass, strlen(pass)+1, NULL);
3051         bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3052         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3053                                    dev, strlen(dev)+1, NULL);
3054
3055         status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3056                          talloc_get_size(bytes), bytes, &req,
3057                          2, NULL, &ret_vwv, NULL, NULL);
3058         if (!NT_STATUS_IS_OK(status)) {
3059                 return status;
3060         }
3061
3062         *max_xmit = SVAL(ret_vwv + 0, 0);
3063         *tid = SVAL(ret_vwv + 1, 0);
3064
3065         return NT_STATUS_OK;
3066 }
3067
3068 /* Return a cli_state pointing at the IPC$ share for the given server */
3069
3070 struct cli_state *get_ipc_connect(char *server,
3071                                 struct sockaddr_storage *server_ss,
3072                                 const struct user_auth_info *user_info)
3073 {
3074         struct cli_state *cli;
3075         NTSTATUS nt_status;
3076         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3077
3078         if (user_info->use_kerberos) {
3079                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3080         }
3081
3082         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
3083                                         user_info->username ? user_info->username : "",
3084                                         lp_workgroup(),
3085                                         user_info->password ? user_info->password : "",
3086                                         flags,
3087                                         Undefined);
3088
3089         if (NT_STATUS_IS_OK(nt_status)) {
3090                 return cli;
3091         } else if (is_ipaddress(server)) {
3092             /* windows 9* needs a correct NMB name for connections */
3093             fstring remote_name;
3094
3095             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3096                 cli = get_ipc_connect(remote_name, server_ss, user_info);
3097                 if (cli)
3098                     return cli;
3099             }
3100         }
3101         return NULL;
3102 }
3103
3104 /*
3105  * Given the IP address of a master browser on the network, return its
3106  * workgroup and connect to it.
3107  *
3108  * This function is provided to allow additional processing beyond what
3109  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3110  * browsers and obtain each master browsers' list of domains (in case the
3111  * first master browser is recently on the network and has not yet
3112  * synchronized with other master browsers and therefore does not yet have the
3113  * entire network browse list)
3114  */
3115
3116 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3117                                 struct sockaddr_storage *mb_ip,
3118                                 const struct user_auth_info *user_info,
3119                                 char **pp_workgroup_out)
3120 {
3121         char addr[INET6_ADDRSTRLEN];
3122         fstring name;
3123         struct cli_state *cli;
3124         struct sockaddr_storage server_ss;
3125
3126         *pp_workgroup_out = NULL;
3127
3128         print_sockaddr(addr, sizeof(addr), mb_ip);
3129         DEBUG(99, ("Looking up name of master browser %s\n",
3130                    addr));
3131
3132         /*
3133          * Do a name status query to find out the name of the master browser.
3134          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3135          * master browser will not respond to a wildcard query (or, at least,
3136          * an NT4 server acting as the domain master browser will not).
3137          *
3138          * We might be able to use ONLY the query on MSBROWSE, but that's not
3139          * yet been tested with all Windows versions, so until it is, leave
3140          * the original wildcard query as the first choice and fall back to
3141          * MSBROWSE if the wildcard query fails.
3142          */
3143         if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3144             !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3145
3146                 DEBUG(99, ("Could not retrieve name status for %s\n",
3147                            addr));
3148                 return NULL;
3149         }
3150
3151         if (!find_master_ip(name, &server_ss)) {
3152                 DEBUG(99, ("Could not find master ip for %s\n", name));
3153                 return NULL;
3154         }
3155
3156         *pp_workgroup_out = talloc_strdup(ctx, name);
3157
3158         DEBUG(4, ("found master browser %s, %s\n", name, addr));
3159
3160         print_sockaddr(addr, sizeof(addr), &server_ss);
3161         cli = get_ipc_connect(addr, &server_ss, user_info);
3162
3163         return cli;
3164 }
3165
3166 /*
3167  * Return the IP address and workgroup of a master browser on the network, and
3168  * connect to it.
3169  */
3170
3171 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3172                                         const struct user_auth_info *user_info,
3173                                         char **pp_workgroup_out)
3174 {
3175         struct sockaddr_storage *ip_list;
3176         struct cli_state *cli;
3177         int i, count;
3178         NTSTATUS status;
3179
3180         *pp_workgroup_out = NULL;
3181
3182         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3183
3184         /* Go looking for workgroups by broadcasting on the local network */
3185
3186         status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3187                                     &ip_list, &count);
3188         if (!NT_STATUS_IS_OK(status)) {
3189                 DEBUG(99, ("No master browsers responded: %s\n",
3190                            nt_errstr(status)));
3191                 return False;
3192         }
3193
3194         for (i = 0; i < count; i++) {
3195                 char addr[INET6_ADDRSTRLEN];
3196                 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3197                 DEBUG(99, ("Found master browser %s\n", addr));
3198
3199                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3200                                 user_info, pp_workgroup_out);
3201                 if (cli)
3202                         return(cli);
3203         }
3204
3205         return NULL;
3206 }