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