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