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