pidl/NDR/Parser: also do range checks on the array size
[Samba.git] / source3 / libsmb / cliconnect.c
blobf03219bb0be34dc18317bdc235b1209a2b3d638f
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
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.
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.
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/>.
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"
36 static const struct {
37 int prot;
38 const char name[24];
39 } prots[10] = {
40 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
41 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
42 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
43 {PROTOCOL_LANMAN1, "LANMAN1.0"},
44 {PROTOCOL_LANMAN2, "LM1.2X002"},
45 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
46 {PROTOCOL_LANMAN2, "LANMAN2.1"},
47 {PROTOCOL_LANMAN2, "Samba"},
48 {PROTOCOL_NT1, "NT LANMAN 1.0"},
49 {PROTOCOL_NT1, "NT LM 0.12"},
52 #define STAR_SMBSERVER "*SMBSERVER"
54 /********************************************************
55 Utility function to ensure we always return at least
56 a valid char * pointer to an empty string for the
57 cli->server_os, cli->server_type and cli->server_domain
58 strings.
59 *******************************************************/
61 static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
62 char *inbuf,
63 char **dest,
64 uint8_t *src,
65 size_t srclen,
66 ssize_t *destlen)
68 *destlen = clistr_pull_talloc(cli,
69 inbuf,
70 SVAL(inbuf, smb_flg2),
71 dest,
72 (char *)src,
73 srclen,
74 STR_TERMINATE);
75 if (*destlen == -1) {
76 return NT_STATUS_NO_MEMORY;
79 if (*dest == NULL) {
80 *dest = talloc_strdup(cli, "");
81 if (*dest == NULL) {
82 return NT_STATUS_NO_MEMORY;
85 return NT_STATUS_OK;
88 /**
89 * Set the user session key for a connection
90 * @param cli The cli structure to add it too
91 * @param session_key The session key used. (A copy of this is taken for the cli struct)
95 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
97 cli->user_session_key = data_blob(session_key.data, session_key.length);
100 /****************************************************************************
101 Do an old lanman2 style session setup.
102 ****************************************************************************/
104 struct cli_session_setup_lanman2_state {
105 struct cli_state *cli;
106 uint16_t vwv[10];
107 const char *user;
110 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
112 static struct tevent_req *cli_session_setup_lanman2_send(
113 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
114 struct cli_state *cli, const char *user,
115 const char *pass, size_t passlen,
116 const char *workgroup)
118 struct tevent_req *req, *subreq;
119 struct cli_session_setup_lanman2_state *state;
120 DATA_BLOB lm_response = data_blob_null;
121 uint16_t *vwv;
122 uint8_t *bytes;
123 char *tmp;
125 req = tevent_req_create(mem_ctx, &state,
126 struct cli_session_setup_lanman2_state);
127 if (req == NULL) {
128 return NULL;
130 state->cli = cli;
131 state->user = user;
132 vwv = state->vwv;
135 * LANMAN servers predate NT status codes and Unicode and
136 * ignore those smb flags so we must disable the corresponding
137 * default capabilities that would otherwise cause the Unicode
138 * and NT Status flags to be set (and even returned by the
139 * server)
142 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
145 * if in share level security then don't send a password now
147 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
148 passlen = 0;
151 if (passlen > 0
152 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
153 && passlen != 24) {
155 * Encrypted mode needed, and non encrypted password
156 * supplied.
158 lm_response = data_blob(NULL, 24);
159 if (tevent_req_nomem(lm_response.data, req)) {
160 return tevent_req_post(req, ev);
163 if (!SMBencrypt(pass, cli->secblob.data,
164 (uint8_t *)lm_response.data)) {
165 DEBUG(1, ("Password is > 14 chars in length, and is "
166 "therefore incompatible with Lanman "
167 "authentication\n"));
168 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
169 return tevent_req_post(req, ev);
171 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
172 && passlen == 24) {
174 * Encrypted mode needed, and encrypted password
175 * supplied.
177 lm_response = data_blob(pass, passlen);
178 if (tevent_req_nomem(lm_response.data, req)) {
179 return tevent_req_post(req, ev);
181 } else if (passlen > 0) {
182 uint8_t *buf;
183 size_t converted_size;
185 * Plaintext mode needed, assume plaintext supplied.
187 buf = talloc_array(talloc_tos(), uint8_t, 0);
188 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
189 &converted_size);
190 if (tevent_req_nomem(buf, req)) {
191 return tevent_req_post(req, ev);
193 lm_response = data_blob(pass, passlen);
194 TALLOC_FREE(buf);
195 if (tevent_req_nomem(lm_response.data, req)) {
196 return tevent_req_post(req, ev);
200 SCVAL(vwv+0, 0, 0xff);
201 SCVAL(vwv+0, 1, 0);
202 SSVAL(vwv+1, 0, 0);
203 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
204 SSVAL(vwv+3, 0, 2);
205 SSVAL(vwv+4, 0, 1);
206 SIVAL(vwv+5, 0, cli->sesskey);
207 SSVAL(vwv+7, 0, lm_response.length);
209 bytes = talloc_array(state, uint8_t, lm_response.length);
210 if (tevent_req_nomem(bytes, req)) {
211 return tevent_req_post(req, ev);
213 if (lm_response.length != 0) {
214 memcpy(bytes, lm_response.data, lm_response.length);
216 data_blob_free(&lm_response);
218 tmp = talloc_strdup_upper(talloc_tos(), user);
219 if (tevent_req_nomem(tmp, req)) {
220 return tevent_req_post(req, ev);
222 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
223 NULL);
224 TALLOC_FREE(tmp);
226 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
227 if (tevent_req_nomem(tmp, req)) {
228 return tevent_req_post(req, ev);
230 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
231 NULL);
232 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
233 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
235 if (tevent_req_nomem(bytes, req)) {
236 return tevent_req_post(req, ev);
239 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
240 talloc_get_size(bytes), bytes);
241 if (tevent_req_nomem(subreq, req)) {
242 return tevent_req_post(req, ev);
244 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
245 return req;
248 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
250 struct tevent_req *req = tevent_req_callback_data(
251 subreq, struct tevent_req);
252 struct cli_session_setup_lanman2_state *state = tevent_req_data(
253 req, struct cli_session_setup_lanman2_state);
254 struct cli_state *cli = state->cli;
255 uint32_t num_bytes;
256 uint8_t *in;
257 char *inbuf;
258 uint8_t *bytes;
259 uint8_t *p;
260 NTSTATUS status;
261 ssize_t ret;
262 uint8_t wct;
263 uint16_t *vwv;
265 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
266 &num_bytes, &bytes);
267 TALLOC_FREE(subreq);
268 if (!NT_STATUS_IS_OK(status)) {
269 tevent_req_nterror(req, status);
270 return;
273 inbuf = (char *)in;
274 p = bytes;
276 cli->vuid = SVAL(inbuf, smb_uid);
277 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
279 status = smb_bytes_talloc_string(cli,
280 inbuf,
281 &cli->server_os,
283 bytes+num_bytes-p,
284 &ret);
286 if (!NT_STATUS_IS_OK(status)) {
287 tevent_req_nterror(req, status);
288 return;
290 p += ret;
292 status = smb_bytes_talloc_string(cli,
293 inbuf,
294 &cli->server_type,
296 bytes+num_bytes-p,
297 &ret);
299 if (!NT_STATUS_IS_OK(status)) {
300 tevent_req_nterror(req, status);
301 return;
303 p += ret;
305 status = smb_bytes_talloc_string(cli,
306 inbuf,
307 &cli->server_domain,
309 bytes+num_bytes-p,
310 &ret);
312 if (!NT_STATUS_IS_OK(status)) {
313 tevent_req_nterror(req, status);
314 return;
316 p += ret;
318 if (strstr(cli->server_type, "Samba")) {
319 cli->is_samba = True;
321 status = cli_set_username(cli, state->user);
322 if (tevent_req_nterror(req, status)) {
323 return;
325 tevent_req_done(req);
328 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
330 return tevent_req_simple_recv_ntstatus(req);
333 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
334 const char *pass, size_t passlen,
335 const char *workgroup)
337 TALLOC_CTX *frame = talloc_stackframe();
338 struct event_context *ev;
339 struct tevent_req *req;
340 NTSTATUS status = NT_STATUS_NO_MEMORY;
342 if (cli_has_async_calls(cli)) {
344 * Can't use sync call while an async call is in flight
346 status = NT_STATUS_INVALID_PARAMETER;
347 goto fail;
349 ev = event_context_init(frame);
350 if (ev == NULL) {
351 goto fail;
353 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
354 workgroup);
355 if (req == NULL) {
356 goto fail;
358 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
359 goto fail;
361 status = cli_session_setup_lanman2_recv(req);
362 fail:
363 TALLOC_FREE(frame);
364 return status;
367 /****************************************************************************
368 Work out suitable capabilities to offer the server.
369 ****************************************************************************/
371 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
373 uint32 capabilities = CAP_NT_SMBS;
375 if (!cli->force_dos_errors)
376 capabilities |= CAP_STATUS32;
378 if (cli->use_level_II_oplocks)
379 capabilities |= CAP_LEVEL_II_OPLOCKS;
381 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
382 return capabilities;
385 /****************************************************************************
386 Do a NT1 guest session setup.
387 ****************************************************************************/
389 struct cli_session_setup_guest_state {
390 struct cli_state *cli;
391 uint16_t vwv[13];
392 struct iovec bytes;
395 static void cli_session_setup_guest_done(struct tevent_req *subreq);
397 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
398 struct event_context *ev,
399 struct cli_state *cli,
400 struct tevent_req **psmbreq)
402 struct tevent_req *req, *subreq;
403 struct cli_session_setup_guest_state *state;
404 uint16_t *vwv;
405 uint8_t *bytes;
407 req = tevent_req_create(mem_ctx, &state,
408 struct cli_session_setup_guest_state);
409 if (req == NULL) {
410 return NULL;
412 state->cli = cli;
413 vwv = state->vwv;
415 SCVAL(vwv+0, 0, 0xFF);
416 SCVAL(vwv+0, 1, 0);
417 SSVAL(vwv+1, 0, 0);
418 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
419 SSVAL(vwv+3, 0, 2);
420 SSVAL(vwv+4, 0, cli->pid);
421 SIVAL(vwv+5, 0, cli->sesskey);
422 SSVAL(vwv+7, 0, 0);
423 SSVAL(vwv+8, 0, 0);
424 SSVAL(vwv+9, 0, 0);
425 SSVAL(vwv+10, 0, 0);
426 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
428 bytes = talloc_array(state, uint8_t, 0);
430 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
431 NULL);
432 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
433 NULL);
434 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
435 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
437 if (bytes == NULL) {
438 TALLOC_FREE(req);
439 return NULL;
442 state->bytes.iov_base = (void *)bytes;
443 state->bytes.iov_len = talloc_get_size(bytes);
445 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
446 1, &state->bytes);
447 if (subreq == NULL) {
448 TALLOC_FREE(req);
449 return NULL;
451 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
452 *psmbreq = subreq;
453 return req;
456 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
457 struct event_context *ev,
458 struct cli_state *cli)
460 struct tevent_req *req, *subreq;
461 NTSTATUS status;
463 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
464 if (req == NULL) {
465 return NULL;
468 status = cli_smb_req_send(subreq);
469 if (NT_STATUS_IS_OK(status)) {
470 tevent_req_nterror(req, status);
471 return tevent_req_post(req, ev);
473 return req;
476 static void cli_session_setup_guest_done(struct tevent_req *subreq)
478 struct tevent_req *req = tevent_req_callback_data(
479 subreq, struct tevent_req);
480 struct cli_session_setup_guest_state *state = tevent_req_data(
481 req, struct cli_session_setup_guest_state);
482 struct cli_state *cli = state->cli;
483 uint32_t num_bytes;
484 uint8_t *in;
485 char *inbuf;
486 uint8_t *bytes;
487 uint8_t *p;
488 NTSTATUS status;
489 ssize_t ret;
490 uint8_t wct;
491 uint16_t *vwv;
493 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
494 &num_bytes, &bytes);
495 TALLOC_FREE(subreq);
496 if (!NT_STATUS_IS_OK(status)) {
497 tevent_req_nterror(req, status);
498 return;
501 inbuf = (char *)in;
502 p = bytes;
504 cli->vuid = SVAL(inbuf, smb_uid);
505 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
507 status = smb_bytes_talloc_string(cli,
508 inbuf,
509 &cli->server_os,
511 bytes+num_bytes-p,
512 &ret);
514 if (!NT_STATUS_IS_OK(status)) {
515 tevent_req_nterror(req, status);
516 return;
518 p += ret;
520 status = smb_bytes_talloc_string(cli,
521 inbuf,
522 &cli->server_type,
524 bytes+num_bytes-p,
525 &ret);
527 if (!NT_STATUS_IS_OK(status)) {
528 tevent_req_nterror(req, status);
529 return;
531 p += ret;
533 status = smb_bytes_talloc_string(cli,
534 inbuf,
535 &cli->server_domain,
537 bytes+num_bytes-p,
538 &ret);
540 if (!NT_STATUS_IS_OK(status)) {
541 tevent_req_nterror(req, status);
542 return;
544 p += ret;
546 if (strstr(cli->server_type, "Samba")) {
547 cli->is_samba = True;
550 status = cli_set_username(cli, "");
551 if (!NT_STATUS_IS_OK(status)) {
552 tevent_req_nterror(req, status);
553 return;
555 tevent_req_done(req);
558 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
560 return tevent_req_simple_recv_ntstatus(req);
563 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
565 TALLOC_CTX *frame = talloc_stackframe();
566 struct event_context *ev;
567 struct tevent_req *req;
568 NTSTATUS status = NT_STATUS_OK;
570 if (cli_has_async_calls(cli)) {
572 * Can't use sync call while an async call is in flight
574 status = NT_STATUS_INVALID_PARAMETER;
575 goto fail;
578 ev = event_context_init(frame);
579 if (ev == NULL) {
580 status = NT_STATUS_NO_MEMORY;
581 goto fail;
584 req = cli_session_setup_guest_send(frame, ev, cli);
585 if (req == NULL) {
586 status = NT_STATUS_NO_MEMORY;
587 goto fail;
590 if (!tevent_req_poll(req, ev)) {
591 status = map_nt_error_from_unix(errno);
592 goto fail;
595 status = cli_session_setup_guest_recv(req);
596 fail:
597 TALLOC_FREE(frame);
598 return status;
601 /****************************************************************************
602 Do a NT1 plaintext session setup.
603 ****************************************************************************/
605 struct cli_session_setup_plain_state {
606 struct cli_state *cli;
607 uint16_t vwv[13];
608 const char *user;
611 static void cli_session_setup_plain_done(struct tevent_req *subreq);
613 static struct tevent_req *cli_session_setup_plain_send(
614 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
615 struct cli_state *cli,
616 const char *user, const char *pass, const char *workgroup)
618 struct tevent_req *req, *subreq;
619 struct cli_session_setup_plain_state *state;
620 uint16_t *vwv;
621 uint8_t *bytes;
622 size_t passlen;
623 char *version;
625 req = tevent_req_create(mem_ctx, &state,
626 struct cli_session_setup_plain_state);
627 if (req == NULL) {
628 return NULL;
630 state->cli = cli;
631 state->user = user;
632 vwv = state->vwv;
634 SCVAL(vwv+0, 0, 0xff);
635 SCVAL(vwv+0, 1, 0);
636 SSVAL(vwv+1, 0, 0);
637 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
638 SSVAL(vwv+3, 0, 2);
639 SSVAL(vwv+4, 0, cli->pid);
640 SIVAL(vwv+5, 0, cli->sesskey);
641 SSVAL(vwv+7, 0, 0);
642 SSVAL(vwv+8, 0, 0);
643 SSVAL(vwv+9, 0, 0);
644 SSVAL(vwv+10, 0, 0);
645 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
647 bytes = talloc_array(state, uint8_t, 0);
648 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
649 &passlen);
650 if (tevent_req_nomem(bytes, req)) {
651 return tevent_req_post(req, ev);
653 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
655 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
656 user, strlen(user)+1, NULL);
657 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
658 workgroup, strlen(workgroup)+1, NULL);
659 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
660 "Unix", 5, NULL);
662 version = talloc_asprintf(talloc_tos(), "Samba %s",
663 samba_version_string());
664 if (tevent_req_nomem(version, req)){
665 return tevent_req_post(req, ev);
667 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
668 version, strlen(version)+1, NULL);
669 TALLOC_FREE(version);
671 if (tevent_req_nomem(bytes, req)) {
672 return tevent_req_post(req, ev);
675 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
676 talloc_get_size(bytes), bytes);
677 if (tevent_req_nomem(subreq, req)) {
678 return tevent_req_post(req, ev);
680 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
681 return req;
684 static void cli_session_setup_plain_done(struct tevent_req *subreq)
686 struct tevent_req *req = tevent_req_callback_data(
687 subreq, struct tevent_req);
688 struct cli_session_setup_plain_state *state = tevent_req_data(
689 req, struct cli_session_setup_plain_state);
690 struct cli_state *cli = state->cli;
691 uint32_t num_bytes;
692 uint8_t *in;
693 char *inbuf;
694 uint8_t *bytes;
695 uint8_t *p;
696 NTSTATUS status;
697 ssize_t ret;
698 uint8_t wct;
699 uint16_t *vwv;
701 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
702 &num_bytes, &bytes);
703 TALLOC_FREE(subreq);
704 if (tevent_req_nterror(req, status)) {
705 return;
708 inbuf = (char *)in;
709 p = bytes;
711 cli->vuid = SVAL(inbuf, smb_uid);
712 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
714 status = smb_bytes_talloc_string(cli,
715 inbuf,
716 &cli->server_os,
718 bytes+num_bytes-p,
719 &ret);
721 if (!NT_STATUS_IS_OK(status)) {
722 tevent_req_nterror(req, status);
723 return;
725 p += ret;
727 status = smb_bytes_talloc_string(cli,
728 inbuf,
729 &cli->server_type,
731 bytes+num_bytes-p,
732 &ret);
734 if (!NT_STATUS_IS_OK(status)) {
735 tevent_req_nterror(req, status);
736 return;
738 p += ret;
740 status = smb_bytes_talloc_string(cli,
741 inbuf,
742 &cli->server_domain,
744 bytes+num_bytes-p,
745 &ret);
747 if (!NT_STATUS_IS_OK(status)) {
748 tevent_req_nterror(req, status);
749 return;
751 p += ret;
753 status = cli_set_username(cli, state->user);
754 if (tevent_req_nterror(req, status)) {
755 return;
757 if (strstr(cli->server_type, "Samba")) {
758 cli->is_samba = True;
760 tevent_req_done(req);
763 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
765 return tevent_req_simple_recv_ntstatus(req);
768 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
769 const char *user, const char *pass,
770 const char *workgroup)
772 TALLOC_CTX *frame = talloc_stackframe();
773 struct event_context *ev;
774 struct tevent_req *req;
775 NTSTATUS status = NT_STATUS_NO_MEMORY;
777 if (cli_has_async_calls(cli)) {
779 * Can't use sync call while an async call is in flight
781 status = NT_STATUS_INVALID_PARAMETER;
782 goto fail;
784 ev = event_context_init(frame);
785 if (ev == NULL) {
786 goto fail;
788 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
789 workgroup);
790 if (req == NULL) {
791 goto fail;
793 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
794 goto fail;
796 status = cli_session_setup_plain_recv(req);
797 fail:
798 TALLOC_FREE(frame);
799 return status;
802 /****************************************************************************
803 do a NT1 NTLM/LM encrypted session setup - for when extended security
804 is not negotiated.
805 @param cli client state to create do session setup on
806 @param user username
807 @param pass *either* cleartext password (passlen !=24) or LM response.
808 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
809 @param workgroup The user's domain.
810 ****************************************************************************/
812 struct cli_session_setup_nt1_state {
813 struct cli_state *cli;
814 uint16_t vwv[13];
815 DATA_BLOB response;
816 DATA_BLOB session_key;
817 const char *user;
820 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
822 static struct tevent_req *cli_session_setup_nt1_send(
823 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
824 struct cli_state *cli, const char *user,
825 const char *pass, size_t passlen,
826 const char *ntpass, size_t ntpasslen,
827 const char *workgroup)
829 struct tevent_req *req, *subreq;
830 struct cli_session_setup_nt1_state *state;
831 DATA_BLOB lm_response = data_blob_null;
832 DATA_BLOB nt_response = data_blob_null;
833 DATA_BLOB session_key = data_blob_null;
834 uint16_t *vwv;
835 uint8_t *bytes;
836 char *workgroup_upper;
838 req = tevent_req_create(mem_ctx, &state,
839 struct cli_session_setup_nt1_state);
840 if (req == NULL) {
841 return NULL;
843 state->cli = cli;
844 state->user = user;
845 vwv = state->vwv;
847 if (passlen == 0) {
848 /* do nothing - guest login */
849 } else if (passlen != 24) {
850 if (lp_client_ntlmv2_auth()) {
851 DATA_BLOB server_chal;
852 DATA_BLOB names_blob;
854 server_chal = data_blob(cli->secblob.data,
855 MIN(cli->secblob.length, 8));
856 if (tevent_req_nomem(server_chal.data, req)) {
857 return tevent_req_post(req, ev);
861 * note that the 'workgroup' here is a best
862 * guess - we don't know the server's domain
863 * at this point. The 'server name' is also
864 * dodgy...
866 names_blob = NTLMv2_generate_names_blob(
867 NULL, cli->called.name, workgroup);
869 if (tevent_req_nomem(names_blob.data, req)) {
870 return tevent_req_post(req, ev);
873 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
874 &server_chal, &names_blob,
875 &lm_response, &nt_response,
876 NULL, &session_key)) {
877 data_blob_free(&names_blob);
878 data_blob_free(&server_chal);
879 tevent_req_nterror(
880 req, NT_STATUS_ACCESS_DENIED);
881 return tevent_req_post(req, ev);
883 data_blob_free(&names_blob);
884 data_blob_free(&server_chal);
886 } else {
887 uchar nt_hash[16];
888 E_md4hash(pass, nt_hash);
890 #ifdef LANMAN_ONLY
891 nt_response = data_blob_null;
892 #else
893 nt_response = data_blob(NULL, 24);
894 if (tevent_req_nomem(nt_response.data, req)) {
895 return tevent_req_post(req, ev);
898 SMBNTencrypt(pass, cli->secblob.data,
899 nt_response.data);
900 #endif
901 /* non encrypted password supplied. Ignore ntpass. */
902 if (lp_client_lanman_auth()) {
904 lm_response = data_blob(NULL, 24);
905 if (tevent_req_nomem(lm_response.data, req)) {
906 return tevent_req_post(req, ev);
909 if (!SMBencrypt(pass,cli->secblob.data,
910 lm_response.data)) {
912 * Oops, the LM response is
913 * invalid, just put the NT
914 * response there instead
916 data_blob_free(&lm_response);
917 lm_response = data_blob(
918 nt_response.data,
919 nt_response.length);
921 } else {
923 * LM disabled, place NT# in LM field
924 * instead
926 lm_response = data_blob(
927 nt_response.data, nt_response.length);
930 if (tevent_req_nomem(lm_response.data, req)) {
931 return tevent_req_post(req, ev);
934 session_key = data_blob(NULL, 16);
935 if (tevent_req_nomem(session_key.data, req)) {
936 return tevent_req_post(req, ev);
938 #ifdef LANMAN_ONLY
939 E_deshash(pass, session_key.data);
940 memset(&session_key.data[8], '\0', 8);
941 #else
942 SMBsesskeygen_ntv1(nt_hash, session_key.data);
943 #endif
945 cli_temp_set_signing(cli);
946 } else {
947 /* pre-encrypted password supplied. Only used for
948 security=server, can't do
949 signing because we don't have original key */
951 lm_response = data_blob(pass, passlen);
952 if (tevent_req_nomem(lm_response.data, req)) {
953 return tevent_req_post(req, ev);
956 nt_response = data_blob(ntpass, ntpasslen);
957 if (tevent_req_nomem(nt_response.data, req)) {
958 return tevent_req_post(req, ev);
962 #ifdef LANMAN_ONLY
963 state->response = data_blob_talloc(
964 state, lm_response.data, lm_response.length);
965 #else
966 state->response = data_blob_talloc(
967 state, nt_response.data, nt_response.length);
968 #endif
969 if (tevent_req_nomem(state->response.data, req)) {
970 return tevent_req_post(req, ev);
973 if (session_key.data) {
974 state->session_key = data_blob_talloc(
975 state, session_key.data, session_key.length);
976 if (tevent_req_nomem(state->session_key.data, req)) {
977 return tevent_req_post(req, ev);
980 data_blob_free(&session_key);
982 SCVAL(vwv+0, 0, 0xff);
983 SCVAL(vwv+0, 1, 0);
984 SSVAL(vwv+1, 0, 0);
985 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
986 SSVAL(vwv+3, 0, 2);
987 SSVAL(vwv+4, 0, cli->pid);
988 SIVAL(vwv+5, 0, cli->sesskey);
989 SSVAL(vwv+7, 0, lm_response.length);
990 SSVAL(vwv+8, 0, nt_response.length);
991 SSVAL(vwv+9, 0, 0);
992 SSVAL(vwv+10, 0, 0);
993 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
995 bytes = talloc_array(state, uint8_t,
996 lm_response.length + nt_response.length);
997 if (tevent_req_nomem(bytes, req)) {
998 return tevent_req_post(req, ev);
1000 if (lm_response.length != 0) {
1001 memcpy(bytes, lm_response.data, lm_response.length);
1003 if (nt_response.length != 0) {
1004 memcpy(bytes + lm_response.length,
1005 nt_response.data, nt_response.length);
1007 data_blob_free(&lm_response);
1008 data_blob_free(&nt_response);
1010 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1011 user, strlen(user)+1, NULL);
1014 * Upper case here might help some NTLMv2 implementations
1016 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1017 if (tevent_req_nomem(workgroup_upper, req)) {
1018 return tevent_req_post(req, ev);
1020 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1021 workgroup_upper, strlen(workgroup_upper)+1,
1022 NULL);
1023 TALLOC_FREE(workgroup_upper);
1025 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1026 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1027 if (tevent_req_nomem(bytes, req)) {
1028 return tevent_req_post(req, ev);
1031 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1032 talloc_get_size(bytes), bytes);
1033 if (tevent_req_nomem(subreq, req)) {
1034 return tevent_req_post(req, ev);
1036 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1037 return req;
1040 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1042 struct tevent_req *req = tevent_req_callback_data(
1043 subreq, struct tevent_req);
1044 struct cli_session_setup_nt1_state *state = tevent_req_data(
1045 req, struct cli_session_setup_nt1_state);
1046 struct cli_state *cli = state->cli;
1047 uint32_t num_bytes;
1048 uint8_t *in;
1049 char *inbuf;
1050 uint8_t *bytes;
1051 uint8_t *p;
1052 NTSTATUS status;
1053 ssize_t ret;
1054 uint8_t wct;
1055 uint16_t *vwv;
1057 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1058 &num_bytes, &bytes);
1059 TALLOC_FREE(subreq);
1060 if (!NT_STATUS_IS_OK(status)) {
1061 tevent_req_nterror(req, status);
1062 return;
1065 inbuf = (char *)in;
1066 p = bytes;
1068 cli->vuid = SVAL(inbuf, smb_uid);
1069 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1071 status = smb_bytes_talloc_string(cli,
1072 inbuf,
1073 &cli->server_os,
1075 bytes+num_bytes-p,
1076 &ret);
1077 if (!NT_STATUS_IS_OK(status)) {
1078 tevent_req_nterror(req, status);
1079 return;
1081 p += ret;
1083 status = smb_bytes_talloc_string(cli,
1084 inbuf,
1085 &cli->server_type,
1087 bytes+num_bytes-p,
1088 &ret);
1089 if (!NT_STATUS_IS_OK(status)) {
1090 tevent_req_nterror(req, status);
1091 return;
1093 p += ret;
1095 status = smb_bytes_talloc_string(cli,
1096 inbuf,
1097 &cli->server_domain,
1099 bytes+num_bytes-p,
1100 &ret);
1101 if (!NT_STATUS_IS_OK(status)) {
1102 tevent_req_nterror(req, status);
1103 return;
1105 p += ret;
1107 if (strstr(cli->server_type, "Samba")) {
1108 cli->is_samba = True;
1111 status = cli_set_username(cli, state->user);
1112 if (tevent_req_nterror(req, status)) {
1113 return;
1115 if (cli_simple_set_signing(cli, state->session_key, state->response)
1116 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1117 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1118 return;
1120 if (state->session_key.data) {
1121 /* Have plaintext orginal */
1122 cli_set_session_key(cli, state->session_key);
1124 tevent_req_done(req);
1127 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1129 return tevent_req_simple_recv_ntstatus(req);
1132 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1133 const char *pass, size_t passlen,
1134 const char *ntpass, size_t ntpasslen,
1135 const char *workgroup)
1137 TALLOC_CTX *frame = talloc_stackframe();
1138 struct event_context *ev;
1139 struct tevent_req *req;
1140 NTSTATUS status = NT_STATUS_NO_MEMORY;
1142 if (cli_has_async_calls(cli)) {
1144 * Can't use sync call while an async call is in flight
1146 status = NT_STATUS_INVALID_PARAMETER;
1147 goto fail;
1149 ev = event_context_init(frame);
1150 if (ev == NULL) {
1151 goto fail;
1153 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1154 ntpass, ntpasslen, workgroup);
1155 if (req == NULL) {
1156 goto fail;
1158 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1159 goto fail;
1161 status = cli_session_setup_nt1_recv(req);
1162 fail:
1163 TALLOC_FREE(frame);
1164 return status;
1167 /* The following is calculated from :
1168 * (smb_size-4) = 35
1169 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1170 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1171 * end of packet.
1174 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1176 struct cli_sesssetup_blob_state {
1177 struct tevent_context *ev;
1178 struct cli_state *cli;
1179 DATA_BLOB blob;
1180 uint16_t max_blob_size;
1181 uint16_t vwv[12];
1182 uint8_t *buf;
1184 NTSTATUS status;
1185 char *inbuf;
1186 DATA_BLOB ret_blob;
1189 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1190 struct tevent_req **psubreq);
1191 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1193 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1194 struct tevent_context *ev,
1195 struct cli_state *cli,
1196 DATA_BLOB blob)
1198 struct tevent_req *req, *subreq;
1199 struct cli_sesssetup_blob_state *state;
1201 req = tevent_req_create(mem_ctx, &state,
1202 struct cli_sesssetup_blob_state);
1203 if (req == NULL) {
1204 return NULL;
1206 state->ev = ev;
1207 state->blob = blob;
1208 state->cli = cli;
1210 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1211 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1212 "(was %u, need minimum %u)\n",
1213 (unsigned int)cli->max_xmit,
1214 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1215 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1216 return tevent_req_post(req, ev);
1218 state->max_blob_size =
1219 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1221 if (!cli_sesssetup_blob_next(state, &subreq)) {
1222 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1223 return tevent_req_post(req, ev);
1225 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1226 return req;
1229 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1230 struct tevent_req **psubreq)
1232 struct tevent_req *subreq;
1233 uint16_t thistime;
1235 SCVAL(state->vwv+0, 0, 0xFF);
1236 SCVAL(state->vwv+0, 1, 0);
1237 SSVAL(state->vwv+1, 0, 0);
1238 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1239 SSVAL(state->vwv+3, 0, 2);
1240 SSVAL(state->vwv+4, 0, 1);
1241 SIVAL(state->vwv+5, 0, 0);
1243 thistime = MIN(state->blob.length, state->max_blob_size);
1244 SSVAL(state->vwv+7, 0, thistime);
1246 SSVAL(state->vwv+8, 0, 0);
1247 SSVAL(state->vwv+9, 0, 0);
1248 SIVAL(state->vwv+10, 0,
1249 cli_session_setup_capabilities(state->cli)
1250 | CAP_EXTENDED_SECURITY);
1252 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1253 thistime);
1254 if (state->buf == NULL) {
1255 return false;
1257 state->blob.data += thistime;
1258 state->blob.length -= thistime;
1260 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1261 "Unix", 5, NULL);
1262 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1263 "Samba", 6, NULL);
1264 if (state->buf == NULL) {
1265 return false;
1267 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1268 12, state->vwv,
1269 talloc_get_size(state->buf), state->buf);
1270 if (subreq == NULL) {
1271 return false;
1273 *psubreq = subreq;
1274 return true;
1277 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1279 struct tevent_req *req = tevent_req_callback_data(
1280 subreq, struct tevent_req);
1281 struct cli_sesssetup_blob_state *state = tevent_req_data(
1282 req, struct cli_sesssetup_blob_state);
1283 struct cli_state *cli = state->cli;
1284 uint8_t wct;
1285 uint16_t *vwv;
1286 uint32_t num_bytes;
1287 uint8_t *bytes;
1288 NTSTATUS status;
1289 uint8_t *p;
1290 uint16_t blob_length;
1291 uint8_t *inbuf;
1292 ssize_t ret;
1294 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1295 &num_bytes, &bytes);
1296 TALLOC_FREE(subreq);
1297 if (!NT_STATUS_IS_OK(status)
1298 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1299 tevent_req_nterror(req, status);
1300 return;
1303 state->status = status;
1304 TALLOC_FREE(state->buf);
1306 state->inbuf = (char *)inbuf;
1307 cli->vuid = SVAL(state->inbuf, smb_uid);
1308 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1310 blob_length = SVAL(vwv+3, 0);
1311 if (blob_length > num_bytes) {
1312 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1313 return;
1315 state->ret_blob = data_blob_const(bytes, blob_length);
1317 p = bytes + blob_length;
1319 status = smb_bytes_talloc_string(cli,
1320 (char *)inbuf,
1321 &cli->server_os,
1323 bytes+num_bytes-p,
1324 &ret);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 tevent_req_nterror(req, status);
1328 return;
1330 p += ret;
1332 status = smb_bytes_talloc_string(cli,
1333 (char *)inbuf,
1334 &cli->server_type,
1336 bytes+num_bytes-p,
1337 &ret);
1339 if (!NT_STATUS_IS_OK(status)) {
1340 tevent_req_nterror(req, status);
1341 return;
1343 p += ret;
1345 status = smb_bytes_talloc_string(cli,
1346 (char *)inbuf,
1347 &cli->server_domain,
1349 bytes+num_bytes-p,
1350 &ret);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 tevent_req_nterror(req, status);
1354 return;
1356 p += ret;
1358 if (strstr(cli->server_type, "Samba")) {
1359 cli->is_samba = True;
1362 if (state->blob.length != 0) {
1364 * More to send
1366 if (!cli_sesssetup_blob_next(state, &subreq)) {
1367 tevent_req_nomem(NULL, req);
1368 return;
1370 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1371 return;
1373 tevent_req_done(req);
1376 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1377 TALLOC_CTX *mem_ctx,
1378 DATA_BLOB *pblob,
1379 char **pinbuf)
1381 struct cli_sesssetup_blob_state *state = tevent_req_data(
1382 req, struct cli_sesssetup_blob_state);
1383 NTSTATUS status;
1384 char *inbuf;
1386 if (tevent_req_is_nterror(req, &status)) {
1387 state->cli->vuid = 0;
1388 return status;
1391 inbuf = talloc_move(mem_ctx, &state->inbuf);
1392 if (pblob != NULL) {
1393 *pblob = state->ret_blob;
1395 if (pinbuf != NULL) {
1396 *pinbuf = inbuf;
1398 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1399 return state->status;
1402 #ifdef HAVE_KRB5
1404 /****************************************************************************
1405 Use in-memory credentials cache
1406 ****************************************************************************/
1408 static void use_in_memory_ccache(void) {
1409 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1412 /****************************************************************************
1413 Do a spnego/kerberos encrypted session setup.
1414 ****************************************************************************/
1416 struct cli_session_setup_kerberos_state {
1417 struct cli_state *cli;
1418 DATA_BLOB negTokenTarg;
1419 DATA_BLOB session_key_krb5;
1420 ADS_STATUS ads_status;
1423 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1425 static struct tevent_req *cli_session_setup_kerberos_send(
1426 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1427 const char *principal, const char *workgroup)
1429 struct tevent_req *req, *subreq;
1430 struct cli_session_setup_kerberos_state *state;
1431 int rc;
1433 DEBUG(2,("Doing kerberos session setup\n"));
1435 req = tevent_req_create(mem_ctx, &state,
1436 struct cli_session_setup_kerberos_state);
1437 if (req == NULL) {
1438 return NULL;
1440 state->cli = cli;
1441 state->ads_status = ADS_SUCCESS;
1443 cli_temp_set_signing(cli);
1446 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1447 * we have to acquire a ticket. To be fixed later :-)
1449 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1450 &state->session_key_krb5, 0, NULL);
1451 if (rc) {
1452 DEBUG(1, ("cli_session_setup_kerberos: "
1453 "spnego_gen_krb5_negTokenInit failed: %s\n",
1454 error_message(rc)));
1455 state->ads_status = ADS_ERROR_KRB5(rc);
1456 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1457 return tevent_req_post(req, ev);
1460 #if 0
1461 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1462 state->negTokenTarg.length);
1463 #endif
1465 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1466 if (tevent_req_nomem(subreq, req)) {
1467 return tevent_req_post(req, ev);
1469 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1470 return req;
1473 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1475 struct tevent_req *req = tevent_req_callback_data(
1476 subreq, struct tevent_req);
1477 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1478 req, struct cli_session_setup_kerberos_state);
1479 char *inbuf = NULL;
1480 NTSTATUS status;
1482 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 TALLOC_FREE(subreq);
1485 tevent_req_nterror(req, status);
1486 return;
1489 cli_set_session_key(state->cli, state->session_key_krb5);
1491 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1492 data_blob_null)
1493 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1494 TALLOC_FREE(subreq);
1495 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1496 return;
1498 TALLOC_FREE(subreq);
1499 tevent_req_done(req);
1502 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1504 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1505 req, struct cli_session_setup_kerberos_state);
1506 NTSTATUS status;
1508 if (tevent_req_is_nterror(req, &status)) {
1509 return ADS_ERROR_NT(status);
1511 return state->ads_status;
1514 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1515 const char *principal,
1516 const char *workgroup)
1518 struct tevent_context *ev;
1519 struct tevent_req *req;
1520 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1522 if (cli_has_async_calls(cli)) {
1523 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1525 ev = tevent_context_init(talloc_tos());
1526 if (ev == NULL) {
1527 goto fail;
1529 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1530 workgroup);
1531 if (req == NULL) {
1532 goto fail;
1534 if (!tevent_req_poll(req, ev)) {
1535 status = ADS_ERROR_SYSTEM(errno);
1536 goto fail;
1538 status = cli_session_setup_kerberos_recv(req);
1539 fail:
1540 TALLOC_FREE(ev);
1541 return status;
1543 #endif /* HAVE_KRB5 */
1545 /****************************************************************************
1546 Do a spnego/NTLMSSP encrypted session setup.
1547 ****************************************************************************/
1549 struct cli_session_setup_ntlmssp_state {
1550 struct tevent_context *ev;
1551 struct cli_state *cli;
1552 struct ntlmssp_state *ntlmssp_state;
1553 int turn;
1554 DATA_BLOB blob_out;
1557 static int cli_session_setup_ntlmssp_state_destructor(
1558 struct cli_session_setup_ntlmssp_state *state)
1560 if (state->ntlmssp_state != NULL) {
1561 TALLOC_FREE(state->ntlmssp_state);
1563 return 0;
1566 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1568 static struct tevent_req *cli_session_setup_ntlmssp_send(
1569 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1570 const char *user, const char *pass, const char *domain)
1572 struct tevent_req *req, *subreq;
1573 struct cli_session_setup_ntlmssp_state *state;
1574 NTSTATUS status;
1575 DATA_BLOB blob_out;
1576 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1578 req = tevent_req_create(mem_ctx, &state,
1579 struct cli_session_setup_ntlmssp_state);
1580 if (req == NULL) {
1581 return NULL;
1583 state->ev = ev;
1584 state->cli = cli;
1585 state->turn = 1;
1587 state->ntlmssp_state = NULL;
1588 talloc_set_destructor(
1589 state, cli_session_setup_ntlmssp_state_destructor);
1591 cli_temp_set_signing(cli);
1593 status = ntlmssp_client_start(state,
1594 global_myname(),
1595 lp_workgroup(),
1596 lp_client_ntlmv2_auth(),
1597 &state->ntlmssp_state);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 goto fail;
1601 ntlmssp_want_feature(state->ntlmssp_state,
1602 NTLMSSP_FEATURE_SESSION_KEY);
1603 if (cli->use_ccache) {
1604 ntlmssp_want_feature(state->ntlmssp_state,
1605 NTLMSSP_FEATURE_CCACHE);
1607 status = ntlmssp_set_username(state->ntlmssp_state, user);
1608 if (!NT_STATUS_IS_OK(status)) {
1609 goto fail;
1611 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1612 if (!NT_STATUS_IS_OK(status)) {
1613 goto fail;
1615 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 goto fail;
1619 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1620 &blob_out);
1621 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1622 goto fail;
1625 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1626 data_blob_free(&blob_out);
1628 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1629 if (tevent_req_nomem(subreq, req)) {
1630 return tevent_req_post(req, ev);
1632 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1633 return req;
1634 fail:
1635 tevent_req_nterror(req, status);
1636 return tevent_req_post(req, ev);
1639 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1641 struct tevent_req *req = tevent_req_callback_data(
1642 subreq, struct tevent_req);
1643 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1644 req, struct cli_session_setup_ntlmssp_state);
1645 DATA_BLOB blob_in, msg_in, blob_out;
1646 char *inbuf = NULL;
1647 bool parse_ret;
1648 NTSTATUS status;
1650 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1651 &inbuf);
1652 TALLOC_FREE(subreq);
1653 data_blob_free(&state->blob_out);
1655 if (NT_STATUS_IS_OK(status)) {
1656 if (state->cli->server_domain[0] == '\0') {
1657 TALLOC_FREE(state->cli->server_domain);
1658 state->cli->server_domain = talloc_strdup(state->cli,
1659 state->ntlmssp_state->server.netbios_domain);
1660 if (state->cli->server_domain == NULL) {
1661 TALLOC_FREE(subreq);
1662 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1663 return;
1666 cli_set_session_key(
1667 state->cli, state->ntlmssp_state->session_key);
1669 if (cli_simple_set_signing(
1670 state->cli, state->ntlmssp_state->session_key,
1671 data_blob_null)
1672 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1673 TALLOC_FREE(subreq);
1674 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1675 return;
1677 TALLOC_FREE(subreq);
1678 TALLOC_FREE(state->ntlmssp_state);
1679 tevent_req_done(req);
1680 return;
1682 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1683 tevent_req_nterror(req, status);
1684 return;
1687 if (blob_in.length == 0) {
1688 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1689 return;
1692 if ((state->turn == 1)
1693 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1694 DATA_BLOB tmp_blob = data_blob_null;
1695 /* the server might give us back two challenges */
1696 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1697 &tmp_blob);
1698 data_blob_free(&tmp_blob);
1699 } else {
1700 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1701 OID_NTLMSSP, &msg_in);
1703 state->turn += 1;
1705 if (!parse_ret) {
1706 DEBUG(3,("Failed to parse auth response\n"));
1707 if (NT_STATUS_IS_OK(status)
1708 || NT_STATUS_EQUAL(status,
1709 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1710 tevent_req_nterror(
1711 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1712 return;
1716 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1718 if (!NT_STATUS_IS_OK(status)
1719 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1720 TALLOC_FREE(subreq);
1721 TALLOC_FREE(state->ntlmssp_state);
1722 tevent_req_nterror(req, status);
1723 return;
1726 state->blob_out = spnego_gen_auth(state, blob_out);
1727 TALLOC_FREE(subreq);
1728 if (tevent_req_nomem(state->blob_out.data, req)) {
1729 return;
1732 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1733 state->blob_out);
1734 if (tevent_req_nomem(subreq, req)) {
1735 return;
1737 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1740 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1742 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1743 req, struct cli_session_setup_ntlmssp_state);
1744 NTSTATUS status;
1746 if (tevent_req_is_nterror(req, &status)) {
1747 state->cli->vuid = 0;
1748 return status;
1750 return NT_STATUS_OK;
1753 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1754 const char *user,
1755 const char *pass,
1756 const char *domain)
1758 struct tevent_context *ev;
1759 struct tevent_req *req;
1760 NTSTATUS status = NT_STATUS_NO_MEMORY;
1762 if (cli_has_async_calls(cli)) {
1763 return NT_STATUS_INVALID_PARAMETER;
1765 ev = tevent_context_init(talloc_tos());
1766 if (ev == NULL) {
1767 goto fail;
1769 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1770 if (req == NULL) {
1771 goto fail;
1773 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1774 goto fail;
1776 status = cli_session_setup_ntlmssp_recv(req);
1777 fail:
1778 TALLOC_FREE(ev);
1779 return status;
1782 /****************************************************************************
1783 Do a spnego encrypted session setup.
1785 user_domain: The shortname of the domain the user/machine is a member of.
1786 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1787 ****************************************************************************/
1789 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1790 const char *pass, const char *user_domain,
1791 const char * dest_realm)
1793 char *principal = NULL;
1794 char *OIDs[ASN1_MAX_OIDS];
1795 int i;
1796 DATA_BLOB blob;
1797 const char *p = NULL;
1798 char *account = NULL;
1799 NTSTATUS status;
1801 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1803 /* the server might not even do spnego */
1804 if (cli->secblob.length <= 16) {
1805 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1806 goto ntlmssp;
1809 #if 0
1810 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1811 #endif
1813 /* there is 16 bytes of GUID before the real spnego packet starts */
1814 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1816 /* The server sent us the first part of the SPNEGO exchange in the
1817 * negprot reply. It is WRONG to depend on the principal sent in the
1818 * negprot reply, but right now we do it. If we don't receive one,
1819 * we try to best guess, then fall back to NTLM. */
1820 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1821 OIDs[0] == NULL) {
1822 data_blob_free(&blob);
1823 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1825 data_blob_free(&blob);
1827 /* make sure the server understands kerberos */
1828 for (i=0;OIDs[i];i++) {
1829 if (i == 0)
1830 DEBUG(3,("got OID=%s\n", OIDs[i]));
1831 else
1832 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1833 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1834 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1835 cli->got_kerberos_mechanism = True;
1837 talloc_free(OIDs[i]);
1840 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1842 status = cli_set_username(cli, user);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 TALLOC_FREE(principal);
1845 return ADS_ERROR_NT(status);
1848 #ifdef HAVE_KRB5
1849 /* If password is set we reauthenticate to kerberos server
1850 * and do not store results */
1852 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1853 ADS_STATUS rc;
1855 if (pass && *pass) {
1856 int ret;
1858 use_in_memory_ccache();
1859 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1861 if (ret){
1862 TALLOC_FREE(principal);
1863 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1864 if (cli->fallback_after_kerberos)
1865 goto ntlmssp;
1866 return ADS_ERROR_KRB5(ret);
1870 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1872 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1873 TALLOC_FREE(principal);
1876 if (principal == NULL &&
1877 !is_ipaddress(cli->desthost) &&
1878 !strequal(STAR_SMBSERVER,
1879 cli->desthost)) {
1880 char *realm = NULL;
1881 char *host = NULL;
1882 DEBUG(3,("cli_session_setup_spnego: using target "
1883 "hostname not SPNEGO principal\n"));
1885 host = strchr_m(cli->desthost, '.');
1886 if (dest_realm) {
1887 realm = SMB_STRDUP(dest_realm);
1888 if (!realm) {
1889 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1891 strupper_m(realm);
1892 } else {
1893 if (host) {
1894 /* DNS name. */
1895 realm = kerberos_get_realm_from_hostname(cli->desthost);
1896 } else {
1897 /* NetBIOS name - use our realm. */
1898 realm = kerberos_get_default_realm_from_ccache();
1902 if (realm == NULL || *realm == '\0') {
1903 realm = SMB_STRDUP(lp_realm());
1904 if (!realm) {
1905 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1907 strupper_m(realm);
1908 DEBUG(3,("cli_session_setup_spnego: cannot "
1909 "get realm from dest_realm %s, "
1910 "desthost %s. Using default "
1911 "smb.conf realm %s\n",
1912 dest_realm ? dest_realm : "<null>",
1913 cli->desthost,
1914 realm));
1917 principal = talloc_asprintf(talloc_tos(),
1918 "cifs/%s@%s",
1919 cli->desthost,
1920 realm);
1921 if (!principal) {
1922 SAFE_FREE(realm);
1923 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1925 DEBUG(3,("cli_session_setup_spnego: guessed "
1926 "server principal=%s\n",
1927 principal ? principal : "<null>"));
1929 SAFE_FREE(realm);
1932 if (principal) {
1933 rc = cli_session_setup_kerberos(cli, principal,
1934 dest_realm);
1935 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1936 TALLOC_FREE(principal);
1937 return rc;
1941 #endif
1943 TALLOC_FREE(principal);
1945 ntlmssp:
1947 account = talloc_strdup(talloc_tos(), user);
1948 if (!account) {
1949 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1952 /* when falling back to ntlmssp while authenticating with a machine
1953 * account strip off the realm - gd */
1955 if ((p = strchr_m(user, '@')) != NULL) {
1956 account[PTR_DIFF(p,user)] = '\0';
1959 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1962 /****************************************************************************
1963 Send a session setup. The username and workgroup is in UNIX character
1964 format and must be converted to DOS codepage format before sending. If the
1965 password is in plaintext, the same should be done.
1966 ****************************************************************************/
1968 NTSTATUS cli_session_setup(struct cli_state *cli,
1969 const char *user,
1970 const char *pass, int passlen,
1971 const char *ntpass, int ntpasslen,
1972 const char *workgroup)
1974 char *p;
1975 char *user2;
1977 if (user) {
1978 user2 = talloc_strdup(talloc_tos(), user);
1979 } else {
1980 user2 = talloc_strdup(talloc_tos(), "");
1982 if (user2 == NULL) {
1983 return NT_STATUS_NO_MEMORY;
1986 if (!workgroup) {
1987 workgroup = "";
1990 /* allow for workgroups as part of the username */
1991 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1992 (p=strchr_m(user2,*lp_winbind_separator()))) {
1993 *p = 0;
1994 user = p+1;
1995 strupper_m(user2);
1996 workgroup = user2;
1999 if (cli->protocol < PROTOCOL_LANMAN1) {
2001 * Ensure cli->server_domain,
2002 * cli->server_os and cli->server_type
2003 * are valid pointers.
2005 cli->server_domain = talloc_strdup(cli, "");
2006 cli->server_os = talloc_strdup(cli, "");
2007 cli->server_type = talloc_strdup(cli, "");
2008 if (cli->server_domain == NULL ||
2009 cli->server_os == NULL ||
2010 cli->server_type == NULL) {
2011 return NT_STATUS_NO_MEMORY;
2013 return NT_STATUS_OK;
2016 /* now work out what sort of session setup we are going to
2017 do. I have split this into separate functions to make the
2018 flow a bit easier to understand (tridge) */
2020 /* if its an older server then we have to use the older request format */
2022 if (cli->protocol < PROTOCOL_NT1) {
2023 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2024 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2025 " or 'client ntlmv2 auth = yes'\n"));
2026 return NT_STATUS_ACCESS_DENIED;
2029 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2030 !lp_client_plaintext_auth() && (*pass)) {
2031 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2032 " or 'client ntlmv2 auth = yes'\n"));
2033 return NT_STATUS_ACCESS_DENIED;
2036 return cli_session_setup_lanman2(cli, user, pass, passlen,
2037 workgroup);
2040 /* if no user is supplied then we have to do an anonymous connection.
2041 passwords are ignored */
2043 if (!user || !*user)
2044 return cli_session_setup_guest(cli);
2046 /* if the server is share level then send a plaintext null
2047 password at this point. The password is sent in the tree
2048 connect */
2050 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2051 return cli_session_setup_plain(cli, user, "", workgroup);
2053 /* if the server doesn't support encryption then we have to use
2054 plaintext. The second password is ignored */
2056 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2057 if (!lp_client_plaintext_auth() && (*pass)) {
2058 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2059 " or 'client ntlmv2 auth = yes'\n"));
2060 return NT_STATUS_ACCESS_DENIED;
2062 return cli_session_setup_plain(cli, user, pass, workgroup);
2065 /* if the server supports extended security then use SPNEGO */
2067 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2068 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2069 workgroup, NULL);
2070 if (!ADS_ERR_OK(status)) {
2071 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2072 return ads_ntstatus(status);
2074 } else {
2075 NTSTATUS status;
2077 /* otherwise do a NT1 style session setup */
2078 status = cli_session_setup_nt1(cli, user, pass, passlen,
2079 ntpass, ntpasslen, workgroup);
2080 if (!NT_STATUS_IS_OK(status)) {
2081 DEBUG(3,("cli_session_setup: NT1 session setup "
2082 "failed: %s\n", nt_errstr(status)));
2083 return status;
2087 if (strstr(cli->server_type, "Samba")) {
2088 cli->is_samba = True;
2091 return NT_STATUS_OK;
2094 /****************************************************************************
2095 Send a uloggoff.
2096 *****************************************************************************/
2098 struct cli_ulogoff_state {
2099 struct cli_state *cli;
2100 uint16_t vwv[3];
2103 static void cli_ulogoff_done(struct tevent_req *subreq);
2105 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2106 struct tevent_context *ev,
2107 struct cli_state *cli)
2109 struct tevent_req *req, *subreq;
2110 struct cli_ulogoff_state *state;
2112 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2113 if (req == NULL) {
2114 return NULL;
2116 state->cli = cli;
2118 SCVAL(state->vwv+0, 0, 0xFF);
2119 SCVAL(state->vwv+1, 0, 0);
2120 SSVAL(state->vwv+2, 0, 0);
2122 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2123 0, NULL);
2124 if (tevent_req_nomem(subreq, req)) {
2125 return tevent_req_post(req, ev);
2127 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2128 return req;
2131 static void cli_ulogoff_done(struct tevent_req *subreq)
2133 struct tevent_req *req = tevent_req_callback_data(
2134 subreq, struct tevent_req);
2135 struct cli_ulogoff_state *state = tevent_req_data(
2136 req, struct cli_ulogoff_state);
2137 NTSTATUS status;
2139 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2140 if (!NT_STATUS_IS_OK(status)) {
2141 tevent_req_nterror(req, status);
2142 return;
2144 state->cli->vuid = -1;
2145 tevent_req_done(req);
2148 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2150 return tevent_req_simple_recv_ntstatus(req);
2153 NTSTATUS cli_ulogoff(struct cli_state *cli)
2155 struct tevent_context *ev;
2156 struct tevent_req *req;
2157 NTSTATUS status = NT_STATUS_NO_MEMORY;
2159 if (cli_has_async_calls(cli)) {
2160 return NT_STATUS_INVALID_PARAMETER;
2162 ev = tevent_context_init(talloc_tos());
2163 if (ev == NULL) {
2164 goto fail;
2166 req = cli_ulogoff_send(ev, ev, cli);
2167 if (req == NULL) {
2168 goto fail;
2170 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2171 goto fail;
2173 status = cli_ulogoff_recv(req);
2174 fail:
2175 TALLOC_FREE(ev);
2176 return status;
2179 /****************************************************************************
2180 Send a tconX.
2181 ****************************************************************************/
2183 struct cli_tcon_andx_state {
2184 struct cli_state *cli;
2185 uint16_t vwv[4];
2186 struct iovec bytes;
2189 static void cli_tcon_andx_done(struct tevent_req *subreq);
2191 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2192 struct event_context *ev,
2193 struct cli_state *cli,
2194 const char *share, const char *dev,
2195 const char *pass, int passlen,
2196 struct tevent_req **psmbreq)
2198 struct tevent_req *req, *subreq;
2199 struct cli_tcon_andx_state *state;
2200 uint8_t p24[24];
2201 uint16_t *vwv;
2202 char *tmp = NULL;
2203 uint8_t *bytes;
2205 *psmbreq = NULL;
2207 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2208 if (req == NULL) {
2209 return NULL;
2211 state->cli = cli;
2212 vwv = state->vwv;
2214 cli->share = talloc_strdup(cli, share);
2215 if (!cli->share) {
2216 return NULL;
2219 /* in user level security don't send a password now */
2220 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2221 passlen = 1;
2222 pass = "";
2223 } else if (pass == NULL) {
2224 DEBUG(1, ("Server not using user level security and no "
2225 "password supplied.\n"));
2226 goto access_denied;
2229 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2230 *pass && passlen != 24) {
2231 if (!lp_client_lanman_auth()) {
2232 DEBUG(1, ("Server requested LANMAN password "
2233 "(share-level security) but "
2234 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2235 goto access_denied;
2239 * Non-encrypted passwords - convert to DOS codepage before
2240 * encryption.
2242 SMBencrypt(pass, cli->secblob.data, p24);
2243 passlen = 24;
2244 pass = (const char *)p24;
2245 } else {
2246 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2247 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2248 == 0) {
2249 char *tmp_pass;
2251 if (!lp_client_plaintext_auth() && (*pass)) {
2252 DEBUG(1, ("Server requested plaintext "
2253 "password but "
2254 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2255 goto access_denied;
2259 * Non-encrypted passwords - convert to DOS codepage
2260 * before using.
2262 tmp_pass = talloc_array(talloc_tos(), char, 128);
2263 if (tmp_pass == NULL) {
2264 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2265 return tevent_req_post(req, ev);
2267 passlen = clistr_push(cli,
2268 tmp_pass,
2269 pass,
2270 talloc_get_size(tmp_pass),
2271 STR_TERMINATE);
2272 if (passlen == -1) {
2273 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2274 return tevent_req_post(req, ev);
2276 pass = tmp_pass;
2280 SCVAL(vwv+0, 0, 0xFF);
2281 SCVAL(vwv+0, 1, 0);
2282 SSVAL(vwv+1, 0, 0);
2283 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2284 SSVAL(vwv+3, 0, passlen);
2286 if (passlen && pass) {
2287 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2288 } else {
2289 bytes = talloc_array(state, uint8_t, 0);
2293 * Add the sharename
2295 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2296 cli->desthost, share);
2297 if (tmp == NULL) {
2298 TALLOC_FREE(req);
2299 return NULL;
2301 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2302 NULL);
2303 TALLOC_FREE(tmp);
2306 * Add the devicetype
2308 tmp = talloc_strdup_upper(talloc_tos(), dev);
2309 if (tmp == NULL) {
2310 TALLOC_FREE(req);
2311 return NULL;
2313 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2314 TALLOC_FREE(tmp);
2316 if (bytes == NULL) {
2317 TALLOC_FREE(req);
2318 return NULL;
2321 state->bytes.iov_base = (void *)bytes;
2322 state->bytes.iov_len = talloc_get_size(bytes);
2324 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2325 1, &state->bytes);
2326 if (subreq == NULL) {
2327 TALLOC_FREE(req);
2328 return NULL;
2330 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2331 *psmbreq = subreq;
2332 return req;
2334 access_denied:
2335 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2336 return tevent_req_post(req, ev);
2339 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2340 struct event_context *ev,
2341 struct cli_state *cli,
2342 const char *share, const char *dev,
2343 const char *pass, int passlen)
2345 struct tevent_req *req, *subreq;
2346 NTSTATUS status;
2348 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2349 &subreq);
2350 if (req == NULL) {
2351 return NULL;
2353 if (subreq == NULL) {
2354 return req;
2356 status = cli_smb_req_send(subreq);
2357 if (!NT_STATUS_IS_OK(status)) {
2358 tevent_req_nterror(req, status);
2359 return tevent_req_post(req, ev);
2361 return req;
2364 static void cli_tcon_andx_done(struct tevent_req *subreq)
2366 struct tevent_req *req = tevent_req_callback_data(
2367 subreq, struct tevent_req);
2368 struct cli_tcon_andx_state *state = tevent_req_data(
2369 req, struct cli_tcon_andx_state);
2370 struct cli_state *cli = state->cli;
2371 uint8_t *in;
2372 char *inbuf;
2373 uint8_t wct;
2374 uint16_t *vwv;
2375 uint32_t num_bytes;
2376 uint8_t *bytes;
2377 NTSTATUS status;
2379 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2380 &num_bytes, &bytes);
2381 TALLOC_FREE(subreq);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 tevent_req_nterror(req, status);
2384 return;
2387 inbuf = (char *)in;
2389 if (num_bytes) {
2390 if (clistr_pull_talloc(cli,
2391 inbuf,
2392 SVAL(inbuf, smb_flg2),
2393 &cli->dev,
2394 bytes,
2395 num_bytes,
2396 STR_TERMINATE|STR_ASCII) == -1) {
2397 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2398 return;
2400 } else {
2401 cli->dev = talloc_strdup(cli, "");
2402 if (cli->dev == NULL) {
2403 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2404 return;
2408 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2409 /* almost certainly win95 - enable bug fixes */
2410 cli->win95 = True;
2414 * Make sure that we have the optional support 16-bit field. WCT > 2.
2415 * Avoids issues when connecting to Win9x boxes sharing files
2418 cli->dfsroot = false;
2420 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2421 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2424 cli->cnum = SVAL(inbuf,smb_tid);
2425 tevent_req_done(req);
2428 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2430 return tevent_req_simple_recv_ntstatus(req);
2433 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2434 const char *dev, const char *pass, int passlen)
2436 TALLOC_CTX *frame = talloc_stackframe();
2437 struct event_context *ev;
2438 struct tevent_req *req;
2439 NTSTATUS status = NT_STATUS_OK;
2441 if (cli_has_async_calls(cli)) {
2443 * Can't use sync call while an async call is in flight
2445 status = NT_STATUS_INVALID_PARAMETER;
2446 goto fail;
2449 ev = event_context_init(frame);
2450 if (ev == NULL) {
2451 status = NT_STATUS_NO_MEMORY;
2452 goto fail;
2455 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2456 if (req == NULL) {
2457 status = NT_STATUS_NO_MEMORY;
2458 goto fail;
2461 if (!tevent_req_poll(req, ev)) {
2462 status = map_nt_error_from_unix(errno);
2463 goto fail;
2466 status = cli_tcon_andx_recv(req);
2467 fail:
2468 TALLOC_FREE(frame);
2469 return status;
2472 /****************************************************************************
2473 Send a tree disconnect.
2474 ****************************************************************************/
2476 struct cli_tdis_state {
2477 struct cli_state *cli;
2480 static void cli_tdis_done(struct tevent_req *subreq);
2482 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2483 struct tevent_context *ev,
2484 struct cli_state *cli)
2486 struct tevent_req *req, *subreq;
2487 struct cli_tdis_state *state;
2489 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2490 if (req == NULL) {
2491 return NULL;
2493 state->cli = cli;
2495 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2496 if (tevent_req_nomem(subreq, req)) {
2497 return tevent_req_post(req, ev);
2499 tevent_req_set_callback(subreq, cli_tdis_done, req);
2500 return req;
2503 static void cli_tdis_done(struct tevent_req *subreq)
2505 struct tevent_req *req = tevent_req_callback_data(
2506 subreq, struct tevent_req);
2507 struct cli_tdis_state *state = tevent_req_data(
2508 req, struct cli_tdis_state);
2509 NTSTATUS status;
2511 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2512 TALLOC_FREE(subreq);
2513 if (!NT_STATUS_IS_OK(status)) {
2514 tevent_req_nterror(req, status);
2515 return;
2517 state->cli->cnum = -1;
2518 tevent_req_done(req);
2521 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2523 return tevent_req_simple_recv_ntstatus(req);
2526 NTSTATUS cli_tdis(struct cli_state *cli)
2528 struct tevent_context *ev;
2529 struct tevent_req *req;
2530 NTSTATUS status = NT_STATUS_NO_MEMORY;
2532 if (cli_has_async_calls(cli)) {
2533 return NT_STATUS_INVALID_PARAMETER;
2535 ev = tevent_context_init(talloc_tos());
2536 if (ev == NULL) {
2537 goto fail;
2539 req = cli_tdis_send(ev, ev, cli);
2540 if (req == NULL) {
2541 goto fail;
2543 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2544 goto fail;
2546 status = cli_tdis_recv(req);
2547 fail:
2548 TALLOC_FREE(ev);
2549 return status;
2552 /****************************************************************************
2553 Send a negprot command.
2554 ****************************************************************************/
2556 struct cli_negprot_state {
2557 struct cli_state *cli;
2560 static void cli_negprot_done(struct tevent_req *subreq);
2562 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2563 struct event_context *ev,
2564 struct cli_state *cli)
2566 struct tevent_req *req, *subreq;
2567 struct cli_negprot_state *state;
2568 uint8_t *bytes = NULL;
2569 int numprots;
2570 uint16_t cnum;
2572 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2573 if (req == NULL) {
2574 return NULL;
2576 state->cli = cli;
2578 if (cli->protocol < PROTOCOL_NT1)
2579 cli->use_spnego = False;
2581 /* setup the protocol strings */
2582 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2583 uint8_t c = 2;
2584 if (prots[numprots].prot > cli->protocol) {
2585 break;
2587 bytes = (uint8_t *)talloc_append_blob(
2588 state, bytes, data_blob_const(&c, sizeof(c)));
2589 if (tevent_req_nomem(bytes, req)) {
2590 return tevent_req_post(req, ev);
2592 bytes = smb_bytes_push_str(bytes, false,
2593 prots[numprots].name,
2594 strlen(prots[numprots].name)+1,
2595 NULL);
2596 if (tevent_req_nomem(bytes, req)) {
2597 return tevent_req_post(req, ev);
2601 cnum = cli->cnum;
2603 cli->cnum = 0;
2604 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2605 talloc_get_size(bytes), bytes);
2606 cli->cnum = cnum;
2608 if (tevent_req_nomem(subreq, req)) {
2609 return tevent_req_post(req, ev);
2611 tevent_req_set_callback(subreq, cli_negprot_done, req);
2612 return req;
2615 static void cli_negprot_done(struct tevent_req *subreq)
2617 struct tevent_req *req = tevent_req_callback_data(
2618 subreq, struct tevent_req);
2619 struct cli_negprot_state *state = tevent_req_data(
2620 req, struct cli_negprot_state);
2621 struct cli_state *cli = state->cli;
2622 uint8_t wct;
2623 uint16_t *vwv;
2624 uint32_t num_bytes;
2625 uint8_t *bytes;
2626 NTSTATUS status;
2627 uint16_t protnum;
2628 uint8_t *inbuf;
2630 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2631 &num_bytes, &bytes);
2632 TALLOC_FREE(subreq);
2633 if (!NT_STATUS_IS_OK(status)) {
2634 tevent_req_nterror(req, status);
2635 return;
2638 protnum = SVAL(vwv, 0);
2640 if ((protnum >= ARRAY_SIZE(prots))
2641 || (prots[protnum].prot > cli->protocol)) {
2642 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2643 return;
2646 cli->protocol = prots[protnum].prot;
2648 if ((cli->protocol < PROTOCOL_NT1) &&
2649 client_is_signing_mandatory(cli)) {
2650 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2651 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2652 return;
2655 if (cli->protocol >= PROTOCOL_NT1) {
2656 struct timespec ts;
2657 bool negotiated_smb_signing = false;
2658 DATA_BLOB blob = data_blob_null;
2660 if (wct != 0x11) {
2661 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2662 return;
2665 /* NT protocol */
2666 cli->sec_mode = CVAL(vwv + 1, 0);
2667 cli->max_mux = SVAL(vwv + 1, 1);
2668 cli->max_xmit = IVAL(vwv + 3, 1);
2669 cli->sesskey = IVAL(vwv + 7, 1);
2670 cli->serverzone = SVALS(vwv + 15, 1);
2671 cli->serverzone *= 60;
2672 /* this time arrives in real GMT */
2673 ts = interpret_long_date(((char *)(vwv+11))+1);
2674 cli->servertime = ts.tv_sec;
2675 cli->secblob = data_blob(bytes, num_bytes);
2676 cli->capabilities = IVAL(vwv + 9, 1);
2677 if (cli->capabilities & CAP_RAW_MODE) {
2678 cli->readbraw_supported = True;
2679 cli->writebraw_supported = True;
2681 /* work out if they sent us a workgroup */
2682 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2683 smb_buflen(inbuf) > 8) {
2684 blob = data_blob_const(bytes + 8, num_bytes - 8);
2687 if (blob.length > 0) {
2688 ssize_t ret;
2689 char *server_domain = NULL;
2691 ret = clistr_pull_talloc(cli,
2692 (const char *)inbuf,
2693 SVAL(inbuf, smb_flg2),
2694 &server_domain,
2695 (char *)blob.data,
2696 blob.length,
2697 STR_TERMINATE|
2698 STR_UNICODE|
2699 STR_NOALIGN);
2700 if (ret == -1) {
2701 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2702 return;
2704 if (server_domain) {
2705 cli->server_domain = server_domain;
2710 * As signing is slow we only turn it on if either the client or
2711 * the server require it. JRA.
2714 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2715 /* Fail if server says signing is mandatory and we don't want to support it. */
2716 if (!client_is_signing_allowed(cli)) {
2717 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2718 tevent_req_nterror(req,
2719 NT_STATUS_ACCESS_DENIED);
2720 return;
2722 negotiated_smb_signing = true;
2723 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2724 /* Fail if client says signing is mandatory and the server doesn't support it. */
2725 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2726 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2727 tevent_req_nterror(req,
2728 NT_STATUS_ACCESS_DENIED);
2729 return;
2731 negotiated_smb_signing = true;
2732 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2733 negotiated_smb_signing = true;
2736 if (negotiated_smb_signing) {
2737 cli_set_signing_negotiated(cli);
2740 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2741 SAFE_FREE(cli->outbuf);
2742 SAFE_FREE(cli->inbuf);
2743 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2744 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2745 if (!cli->outbuf || !cli->inbuf) {
2746 tevent_req_nterror(req,
2747 NT_STATUS_NO_MEMORY);
2748 return;
2750 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2753 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2754 if (wct != 0x0D) {
2755 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2756 return;
2759 cli->use_spnego = False;
2760 cli->sec_mode = SVAL(vwv + 1, 0);
2761 cli->max_xmit = SVAL(vwv + 2, 0);
2762 cli->max_mux = SVAL(vwv + 3, 0);
2763 cli->sesskey = IVAL(vwv + 6, 0);
2764 cli->serverzone = SVALS(vwv + 10, 0);
2765 cli->serverzone *= 60;
2766 /* this time is converted to GMT by make_unix_date */
2767 cli->servertime = make_unix_date(
2768 (char *)(vwv + 8), cli->serverzone);
2769 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2770 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2771 cli->secblob = data_blob(bytes, num_bytes);
2772 } else {
2773 /* the old core protocol */
2774 cli->use_spnego = False;
2775 cli->sec_mode = 0;
2776 cli->serverzone = get_time_zone(time(NULL));
2779 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2781 /* a way to force ascii SMB */
2782 if (getenv("CLI_FORCE_ASCII"))
2783 cli->capabilities &= ~CAP_UNICODE;
2785 tevent_req_done(req);
2788 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2790 return tevent_req_simple_recv_ntstatus(req);
2793 NTSTATUS cli_negprot(struct cli_state *cli)
2795 TALLOC_CTX *frame = talloc_stackframe();
2796 struct event_context *ev;
2797 struct tevent_req *req;
2798 NTSTATUS status = NT_STATUS_OK;
2800 if (cli_has_async_calls(cli)) {
2802 * Can't use sync call while an async call is in flight
2804 status = NT_STATUS_INVALID_PARAMETER;
2805 goto fail;
2808 ev = event_context_init(frame);
2809 if (ev == NULL) {
2810 status = NT_STATUS_NO_MEMORY;
2811 goto fail;
2814 req = cli_negprot_send(frame, ev, cli);
2815 if (req == NULL) {
2816 status = NT_STATUS_NO_MEMORY;
2817 goto fail;
2820 if (!tevent_req_poll(req, ev)) {
2821 status = map_nt_error_from_unix(errno);
2822 goto fail;
2825 status = cli_negprot_recv(req);
2826 fail:
2827 TALLOC_FREE(frame);
2828 return status;
2831 /****************************************************************************
2832 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2833 ****************************************************************************/
2835 bool cli_session_request(struct cli_state *cli,
2836 struct nmb_name *calling, struct nmb_name *called)
2838 char *p;
2839 int len = 4;
2840 int namelen = 0;
2841 char *tmp;
2843 /* 445 doesn't have session request */
2844 if (cli->port == 445)
2845 return True;
2847 memcpy(&(cli->calling), calling, sizeof(*calling));
2848 memcpy(&(cli->called ), called , sizeof(*called ));
2850 /* put in the destination name */
2852 tmp = name_mangle(talloc_tos(), cli->called.name,
2853 cli->called.name_type);
2854 if (tmp == NULL) {
2855 return false;
2858 p = cli->outbuf+len;
2859 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2860 if (namelen > 0) {
2861 memcpy(p, tmp, namelen);
2862 len += namelen;
2864 TALLOC_FREE(tmp);
2866 /* and my name */
2868 tmp = name_mangle(talloc_tos(), cli->calling.name,
2869 cli->calling.name_type);
2870 if (tmp == NULL) {
2871 return false;
2874 p = cli->outbuf+len;
2875 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2876 if (namelen > 0) {
2877 memcpy(p, tmp, namelen);
2878 len += namelen;
2880 TALLOC_FREE(tmp);
2882 /* send a session request (RFC 1002) */
2883 /* setup the packet length
2884 * Remove four bytes from the length count, since the length
2885 * field in the NBT Session Service header counts the number
2886 * of bytes which follow. The cli_send_smb() function knows
2887 * about this and accounts for those four bytes.
2888 * CRH.
2890 len -= 4;
2891 _smb_setlen(cli->outbuf,len);
2892 SCVAL(cli->outbuf,0,0x81);
2894 cli_send_smb(cli);
2895 DEBUG(5,("Sent session request\n"));
2897 if (!cli_receive_smb(cli))
2898 return False;
2900 if (CVAL(cli->inbuf,0) == 0x84) {
2901 /* C. Hoch 9/14/95 Start */
2902 /* For information, here is the response structure.
2903 * We do the byte-twiddling to for portability.
2904 struct RetargetResponse{
2905 unsigned char type;
2906 unsigned char flags;
2907 int16 length;
2908 int32 ip_addr;
2909 int16 port;
2912 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2913 struct in_addr dest_ip;
2914 NTSTATUS status;
2916 /* SESSION RETARGET */
2917 putip((char *)&dest_ip,cli->inbuf+4);
2918 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2920 status = open_socket_out(&cli->dest_ss, port,
2921 LONG_CONNECT_TIMEOUT, &cli->fd);
2922 if (!NT_STATUS_IS_OK(status)) {
2923 return False;
2926 DEBUG(3,("Retargeted\n"));
2928 set_socket_options(cli->fd, lp_socket_options());
2930 /* Try again */
2932 static int depth;
2933 bool ret;
2934 if (depth > 4) {
2935 DEBUG(0,("Retarget recursion - failing\n"));
2936 return False;
2938 depth++;
2939 ret = cli_session_request(cli, calling, called);
2940 depth--;
2941 return ret;
2943 } /* C. Hoch 9/14/95 End */
2945 if (CVAL(cli->inbuf,0) != 0x82) {
2946 /* This is the wrong place to put the error... JRA. */
2947 cli->rap_error = CVAL(cli->inbuf,4);
2948 return False;
2950 return(True);
2953 struct fd_struct {
2954 int fd;
2957 static void smb_sock_connected(struct tevent_req *req)
2959 struct fd_struct *pfd = tevent_req_callback_data(
2960 req, struct fd_struct);
2961 int fd;
2962 NTSTATUS status;
2964 status = open_socket_out_defer_recv(req, &fd);
2965 if (NT_STATUS_IS_OK(status)) {
2966 pfd->fd = fd;
2970 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2971 uint16_t *port, int timeout, int *pfd)
2973 struct event_context *ev;
2974 struct tevent_req *r139, *r445;
2975 struct fd_struct *fd139, *fd445;
2976 NTSTATUS status = NT_STATUS_NO_MEMORY;
2978 if (*port != 0) {
2979 return open_socket_out(pss, *port, timeout, pfd);
2982 ev = event_context_init(talloc_tos());
2983 if (ev == NULL) {
2984 return NT_STATUS_NO_MEMORY;
2987 fd139 = talloc(ev, struct fd_struct);
2988 if (fd139 == NULL) {
2989 goto done;
2991 fd139->fd = -1;
2993 fd445 = talloc(ev, struct fd_struct);
2994 if (fd445 == NULL) {
2995 goto done;
2997 fd445->fd = -1;
2999 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
3000 pss, 445, timeout);
3001 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
3002 pss, 139, timeout);
3003 if ((r445 == NULL) || (r139 == NULL)) {
3004 goto done;
3006 tevent_req_set_callback(r445, smb_sock_connected, fd445);
3007 tevent_req_set_callback(r139, smb_sock_connected, fd139);
3009 while ((fd445->fd == -1) && (fd139->fd == -1)
3010 && (tevent_req_is_in_progress(r139)
3011 || tevent_req_is_in_progress(r445))) {
3012 event_loop_once(ev);
3015 if ((fd139->fd != -1) && (fd445->fd != -1)) {
3016 close(fd139->fd);
3017 fd139->fd = -1;
3020 if (fd445->fd != -1) {
3021 *port = 445;
3022 *pfd = fd445->fd;
3023 status = NT_STATUS_OK;
3024 goto done;
3026 if (fd139->fd != -1) {
3027 *port = 139;
3028 *pfd = fd139->fd;
3029 status = NT_STATUS_OK;
3030 goto done;
3033 status = open_socket_out_defer_recv(r445, &fd445->fd);
3034 done:
3035 TALLOC_FREE(ev);
3036 return status;
3039 /****************************************************************************
3040 Open the client sockets.
3041 ****************************************************************************/
3043 NTSTATUS cli_connect(struct cli_state *cli,
3044 const char *host,
3045 struct sockaddr_storage *dest_ss)
3048 int name_type = 0x20;
3049 TALLOC_CTX *frame = talloc_stackframe();
3050 unsigned int num_addrs = 0;
3051 unsigned int i = 0;
3052 struct sockaddr_storage *ss_arr = NULL;
3053 char *p = NULL;
3055 /* reasonable default hostname */
3056 if (!host) {
3057 host = STAR_SMBSERVER;
3060 cli->desthost = talloc_strdup(cli, host);
3061 if (cli->desthost == NULL) {
3062 return NT_STATUS_NO_MEMORY;
3065 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3066 if ((p = strchr(cli->desthost, '#'))) {
3067 name_type = strtol(p+1, NULL, 16);
3068 *p = 0;
3071 if (!dest_ss || is_zero_addr(dest_ss)) {
3072 NTSTATUS status =resolve_name_list(frame,
3073 cli->desthost,
3074 name_type,
3075 &ss_arr,
3076 &num_addrs);
3077 if (!NT_STATUS_IS_OK(status)) {
3078 TALLOC_FREE(frame);
3079 return NT_STATUS_BAD_NETWORK_NAME;
3081 } else {
3082 num_addrs = 1;
3083 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
3084 if (!ss_arr) {
3085 TALLOC_FREE(frame);
3086 return NT_STATUS_NO_MEMORY;
3088 *ss_arr = *dest_ss;
3091 for (i = 0; i < num_addrs; i++) {
3092 cli->dest_ss = ss_arr[i];
3093 if (getenv("LIBSMB_PROG")) {
3094 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
3095 } else {
3096 uint16_t port = cli->port;
3097 NTSTATUS status;
3098 status = open_smb_socket(&cli->dest_ss, &port,
3099 cli->timeout, &cli->fd);
3100 if (NT_STATUS_IS_OK(status)) {
3101 cli->port = port;
3104 if (cli->fd == -1) {
3105 char addr[INET6_ADDRSTRLEN];
3106 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
3107 DEBUG(2,("Error connecting to %s (%s)\n",
3108 dest_ss?addr:host,strerror(errno)));
3109 } else {
3110 /* Exit from loop on first connection. */
3111 break;
3115 if (cli->fd == -1) {
3116 TALLOC_FREE(frame);
3117 return map_nt_error_from_unix(errno);
3120 if (dest_ss) {
3121 *dest_ss = cli->dest_ss;
3124 set_socket_options(cli->fd, lp_socket_options());
3126 TALLOC_FREE(frame);
3127 return NT_STATUS_OK;
3131 establishes a connection to after the negprot.
3132 @param output_cli A fully initialised cli structure, non-null only on success
3133 @param dest_host The netbios name of the remote host
3134 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3135 @param port (optional) The destination port (0 for default)
3137 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3138 const char *my_name,
3139 const char *dest_host,
3140 struct sockaddr_storage *dest_ss, int port,
3141 int signing_state, int flags)
3143 NTSTATUS nt_status;
3144 struct nmb_name calling;
3145 struct nmb_name called;
3146 struct cli_state *cli;
3147 struct sockaddr_storage ss;
3149 if (!my_name)
3150 my_name = global_myname();
3152 if (!(cli = cli_initialise_ex(signing_state))) {
3153 return NT_STATUS_NO_MEMORY;
3156 make_nmb_name(&calling, my_name, 0x0);
3157 make_nmb_name(&called , dest_host, 0x20);
3159 cli_set_port(cli, port);
3160 cli_set_timeout(cli, 10000); /* 10 seconds. */
3162 if (dest_ss) {
3163 ss = *dest_ss;
3164 } else {
3165 zero_sockaddr(&ss);
3168 again:
3170 DEBUG(3,("Connecting to host=%s\n", dest_host));
3172 nt_status = cli_connect(cli, dest_host, &ss);
3173 if (!NT_STATUS_IS_OK(nt_status)) {
3174 char addr[INET6_ADDRSTRLEN];
3175 print_sockaddr(addr, sizeof(addr), &ss);
3176 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3177 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
3178 cli_shutdown(cli);
3179 return nt_status;
3182 if (!cli_session_request(cli, &calling, &called)) {
3183 char *p;
3184 DEBUG(1,("session request to %s failed (%s)\n",
3185 called.name, cli_errstr(cli)));
3186 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
3187 *p = 0;
3188 goto again;
3190 if (strcmp(called.name, STAR_SMBSERVER)) {
3191 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
3192 goto again;
3194 return NT_STATUS_BAD_NETWORK_NAME;
3197 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
3198 cli->use_spnego = False;
3199 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
3200 cli->use_kerberos = True;
3202 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
3203 cli->use_kerberos) {
3204 cli->fallback_after_kerberos = true;
3206 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3207 cli->use_ccache = true;
3210 nt_status = cli_negprot(cli);
3211 if (!NT_STATUS_IS_OK(nt_status)) {
3212 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3213 cli_shutdown(cli);
3214 return nt_status;
3217 *output_cli = cli;
3218 return NT_STATUS_OK;
3223 establishes a connection right up to doing tconX, password specified.
3224 @param output_cli A fully initialised cli structure, non-null only on success
3225 @param dest_host The netbios name of the remote host
3226 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3227 @param port (optional) The destination port (0 for default)
3228 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3229 @param service_type The 'type' of serivice.
3230 @param user Username, unix string
3231 @param domain User's domain
3232 @param password User's password, unencrypted unix string.
3235 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3236 const char *my_name,
3237 const char *dest_host,
3238 struct sockaddr_storage *dest_ss, int port,
3239 const char *service, const char *service_type,
3240 const char *user, const char *domain,
3241 const char *password, int flags,
3242 int signing_state)
3244 NTSTATUS nt_status;
3245 struct cli_state *cli = NULL;
3246 int pw_len = password ? strlen(password)+1 : 0;
3248 *output_cli = NULL;
3250 if (password == NULL) {
3251 password = "";
3254 nt_status = cli_start_connection(&cli, my_name, dest_host,
3255 dest_ss, port, signing_state,
3256 flags);
3258 if (!NT_STATUS_IS_OK(nt_status)) {
3259 return nt_status;
3262 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3263 cli->use_level_II_oplocks =
3264 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3266 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3267 pw_len, domain);
3268 if (!NT_STATUS_IS_OK(nt_status)) {
3270 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3271 DEBUG(1,("failed session setup with %s\n",
3272 nt_errstr(nt_status)));
3273 cli_shutdown(cli);
3274 return nt_status;
3277 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3278 if (!NT_STATUS_IS_OK(nt_status)) {
3279 DEBUG(1,("anonymous failed session setup with %s\n",
3280 nt_errstr(nt_status)));
3281 cli_shutdown(cli);
3282 return nt_status;
3286 if (service) {
3287 nt_status = cli_tcon_andx(cli, service, service_type, password,
3288 pw_len);
3289 if (!NT_STATUS_IS_OK(nt_status)) {
3290 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3291 cli_shutdown(cli);
3292 if (NT_STATUS_IS_OK(nt_status)) {
3293 nt_status = NT_STATUS_UNSUCCESSFUL;
3295 return nt_status;
3299 nt_status = cli_init_creds(cli, user, domain, password);
3300 if (!NT_STATUS_IS_OK(nt_status)) {
3301 cli_shutdown(cli);
3302 return nt_status;
3305 *output_cli = cli;
3306 return NT_STATUS_OK;
3309 /****************************************************************************
3310 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3311 ****************************************************************************/
3313 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
3314 struct sockaddr_storage *pdest_ss)
3316 struct nmb_name calling, called;
3318 make_nmb_name(&calling, srchost, 0x0);
3321 * If the called name is an IP address
3322 * then use *SMBSERVER immediately.
3325 if(is_ipaddress(desthost)) {
3326 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
3327 } else {
3328 make_nmb_name(&called, desthost, 0x20);
3331 if (!cli_session_request(*ppcli, &calling, &called)) {
3332 NTSTATUS status;
3333 struct nmb_name smbservername;
3335 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
3338 * If the name wasn't *SMBSERVER then
3339 * try with *SMBSERVER if the first name fails.
3342 if (nmb_name_equal(&called, &smbservername)) {
3345 * The name used was *SMBSERVER, don't bother with another name.
3348 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3349 with error %s.\n", desthost, cli_errstr(*ppcli) ));
3350 return False;
3353 /* Try again... */
3354 cli_shutdown(*ppcli);
3356 *ppcli = cli_initialise();
3357 if (!*ppcli) {
3358 /* Out of memory... */
3359 return False;
3362 status = cli_connect(*ppcli, desthost, pdest_ss);
3363 if (!NT_STATUS_IS_OK(status) ||
3364 !cli_session_request(*ppcli, &calling, &smbservername)) {
3365 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3366 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
3367 return False;
3371 return True;
3374 /****************************************************************************
3375 Send an old style tcon.
3376 ****************************************************************************/
3377 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3378 const char *service, const char *pass, const char *dev,
3379 uint16 *max_xmit, uint16 *tid)
3381 struct tevent_req *req;
3382 uint16_t *ret_vwv;
3383 uint8_t *bytes;
3384 NTSTATUS status;
3386 if (!lp_client_plaintext_auth() && (*pass)) {
3387 DEBUG(1, ("Server requested plaintext password but 'client "
3388 "plaintext auth' is disabled\n"));
3389 return NT_STATUS_ACCESS_DENIED;
3392 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3393 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3394 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3395 service, strlen(service)+1, NULL);
3396 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3397 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3398 pass, strlen(pass)+1, NULL);
3399 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3400 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3401 dev, strlen(dev)+1, NULL);
3403 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3404 talloc_get_size(bytes), bytes, &req,
3405 2, NULL, &ret_vwv, NULL, NULL);
3406 if (!NT_STATUS_IS_OK(status)) {
3407 return status;
3410 *max_xmit = SVAL(ret_vwv + 0, 0);
3411 *tid = SVAL(ret_vwv + 1, 0);
3413 return NT_STATUS_OK;
3416 /* Return a cli_state pointing at the IPC$ share for the given server */
3418 struct cli_state *get_ipc_connect(char *server,
3419 struct sockaddr_storage *server_ss,
3420 const struct user_auth_info *user_info)
3422 struct cli_state *cli;
3423 NTSTATUS nt_status;
3424 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3426 if (user_info->use_kerberos) {
3427 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3430 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3431 user_info->username ? user_info->username : "",
3432 lp_workgroup(),
3433 user_info->password ? user_info->password : "",
3434 flags,
3435 Undefined);
3437 if (NT_STATUS_IS_OK(nt_status)) {
3438 return cli;
3439 } else if (is_ipaddress(server)) {
3440 /* windows 9* needs a correct NMB name for connections */
3441 fstring remote_name;
3443 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3444 cli = get_ipc_connect(remote_name, server_ss, user_info);
3445 if (cli)
3446 return cli;
3449 return NULL;
3453 * Given the IP address of a master browser on the network, return its
3454 * workgroup and connect to it.
3456 * This function is provided to allow additional processing beyond what
3457 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3458 * browsers and obtain each master browsers' list of domains (in case the
3459 * first master browser is recently on the network and has not yet
3460 * synchronized with other master browsers and therefore does not yet have the
3461 * entire network browse list)
3464 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3465 struct sockaddr_storage *mb_ip,
3466 const struct user_auth_info *user_info,
3467 char **pp_workgroup_out)
3469 char addr[INET6_ADDRSTRLEN];
3470 fstring name;
3471 struct cli_state *cli;
3472 struct sockaddr_storage server_ss;
3474 *pp_workgroup_out = NULL;
3476 print_sockaddr(addr, sizeof(addr), mb_ip);
3477 DEBUG(99, ("Looking up name of master browser %s\n",
3478 addr));
3481 * Do a name status query to find out the name of the master browser.
3482 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3483 * master browser will not respond to a wildcard query (or, at least,
3484 * an NT4 server acting as the domain master browser will not).
3486 * We might be able to use ONLY the query on MSBROWSE, but that's not
3487 * yet been tested with all Windows versions, so until it is, leave
3488 * the original wildcard query as the first choice and fall back to
3489 * MSBROWSE if the wildcard query fails.
3491 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3492 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3494 DEBUG(99, ("Could not retrieve name status for %s\n",
3495 addr));
3496 return NULL;
3499 if (!find_master_ip(name, &server_ss)) {
3500 DEBUG(99, ("Could not find master ip for %s\n", name));
3501 return NULL;
3504 *pp_workgroup_out = talloc_strdup(ctx, name);
3506 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3508 print_sockaddr(addr, sizeof(addr), &server_ss);
3509 cli = get_ipc_connect(addr, &server_ss, user_info);
3511 return cli;
3515 * Return the IP address and workgroup of a master browser on the network, and
3516 * connect to it.
3519 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3520 const struct user_auth_info *user_info,
3521 char **pp_workgroup_out)
3523 struct sockaddr_storage *ip_list;
3524 struct cli_state *cli;
3525 int i, count;
3526 NTSTATUS status;
3528 *pp_workgroup_out = NULL;
3530 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3532 /* Go looking for workgroups by broadcasting on the local network */
3534 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3535 &ip_list, &count);
3536 if (!NT_STATUS_IS_OK(status)) {
3537 DEBUG(99, ("No master browsers responded: %s\n",
3538 nt_errstr(status)));
3539 return False;
3542 for (i = 0; i < count; i++) {
3543 char addr[INET6_ADDRSTRLEN];
3544 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3545 DEBUG(99, ("Found master browser %s\n", addr));
3547 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3548 user_info, pp_workgroup_out);
3549 if (cli)
3550 return(cli);
3553 return NULL;