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