s3: Make is_executable() available in lib/
[Samba.git] / source3 / libsmb / cliconnect.c
blobb8125818d71d02f1bff19a33eaf15bf1923a09c8
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 if (!NT_STATUS_IS_OK(status)) {
365 cli_set_error(cli, status);
367 return status;
370 /****************************************************************************
371 Work out suitable capabilities to offer the server.
372 ****************************************************************************/
374 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
376 uint32 capabilities = CAP_NT_SMBS;
378 if (!cli->force_dos_errors)
379 capabilities |= CAP_STATUS32;
381 if (cli->use_level_II_oplocks)
382 capabilities |= CAP_LEVEL_II_OPLOCKS;
384 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
385 return capabilities;
388 /****************************************************************************
389 Do a NT1 guest session setup.
390 ****************************************************************************/
392 struct cli_session_setup_guest_state {
393 struct cli_state *cli;
394 uint16_t vwv[13];
395 struct iovec bytes;
398 static void cli_session_setup_guest_done(struct tevent_req *subreq);
400 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
401 struct event_context *ev,
402 struct cli_state *cli,
403 struct tevent_req **psmbreq)
405 struct tevent_req *req, *subreq;
406 struct cli_session_setup_guest_state *state;
407 uint16_t *vwv;
408 uint8_t *bytes;
410 req = tevent_req_create(mem_ctx, &state,
411 struct cli_session_setup_guest_state);
412 if (req == NULL) {
413 return NULL;
415 state->cli = cli;
416 vwv = state->vwv;
418 SCVAL(vwv+0, 0, 0xFF);
419 SCVAL(vwv+0, 1, 0);
420 SSVAL(vwv+1, 0, 0);
421 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
422 SSVAL(vwv+3, 0, 2);
423 SSVAL(vwv+4, 0, cli->pid);
424 SIVAL(vwv+5, 0, cli->sesskey);
425 SSVAL(vwv+7, 0, 0);
426 SSVAL(vwv+8, 0, 0);
427 SSVAL(vwv+9, 0, 0);
428 SSVAL(vwv+10, 0, 0);
429 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
431 bytes = talloc_array(state, uint8_t, 0);
433 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
434 NULL);
435 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
436 NULL);
437 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
438 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
440 if (bytes == NULL) {
441 TALLOC_FREE(req);
442 return NULL;
445 state->bytes.iov_base = (void *)bytes;
446 state->bytes.iov_len = talloc_get_size(bytes);
448 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
449 1, &state->bytes);
450 if (subreq == NULL) {
451 TALLOC_FREE(req);
452 return NULL;
454 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
455 *psmbreq = subreq;
456 return req;
459 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
460 struct event_context *ev,
461 struct cli_state *cli)
463 struct tevent_req *req, *subreq;
464 NTSTATUS status;
466 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
467 if (req == NULL) {
468 return NULL;
471 status = cli_smb_req_send(subreq);
472 if (NT_STATUS_IS_OK(status)) {
473 tevent_req_nterror(req, status);
474 return tevent_req_post(req, ev);
476 return req;
479 static void cli_session_setup_guest_done(struct tevent_req *subreq)
481 struct tevent_req *req = tevent_req_callback_data(
482 subreq, struct tevent_req);
483 struct cli_session_setup_guest_state *state = tevent_req_data(
484 req, struct cli_session_setup_guest_state);
485 struct cli_state *cli = state->cli;
486 uint32_t num_bytes;
487 uint8_t *in;
488 char *inbuf;
489 uint8_t *bytes;
490 uint8_t *p;
491 NTSTATUS status;
492 ssize_t ret;
493 uint8_t wct;
494 uint16_t *vwv;
496 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
497 &num_bytes, &bytes);
498 TALLOC_FREE(subreq);
499 if (!NT_STATUS_IS_OK(status)) {
500 tevent_req_nterror(req, status);
501 return;
504 inbuf = (char *)in;
505 p = bytes;
507 cli->vuid = SVAL(inbuf, smb_uid);
508 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
510 status = smb_bytes_talloc_string(cli,
511 inbuf,
512 &cli->server_os,
514 bytes+num_bytes-p,
515 &ret);
517 if (!NT_STATUS_IS_OK(status)) {
518 tevent_req_nterror(req, status);
519 return;
521 p += ret;
523 status = smb_bytes_talloc_string(cli,
524 inbuf,
525 &cli->server_type,
527 bytes+num_bytes-p,
528 &ret);
530 if (!NT_STATUS_IS_OK(status)) {
531 tevent_req_nterror(req, status);
532 return;
534 p += ret;
536 status = smb_bytes_talloc_string(cli,
537 inbuf,
538 &cli->server_domain,
540 bytes+num_bytes-p,
541 &ret);
543 if (!NT_STATUS_IS_OK(status)) {
544 tevent_req_nterror(req, status);
545 return;
547 p += ret;
549 if (strstr(cli->server_type, "Samba")) {
550 cli->is_samba = True;
553 status = cli_set_username(cli, "");
554 if (!NT_STATUS_IS_OK(status)) {
555 tevent_req_nterror(req, status);
556 return;
558 tevent_req_done(req);
561 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
563 return tevent_req_simple_recv_ntstatus(req);
566 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
568 TALLOC_CTX *frame = talloc_stackframe();
569 struct event_context *ev;
570 struct tevent_req *req;
571 NTSTATUS status = NT_STATUS_OK;
573 if (cli_has_async_calls(cli)) {
575 * Can't use sync call while an async call is in flight
577 status = NT_STATUS_INVALID_PARAMETER;
578 goto fail;
581 ev = event_context_init(frame);
582 if (ev == NULL) {
583 status = NT_STATUS_NO_MEMORY;
584 goto fail;
587 req = cli_session_setup_guest_send(frame, ev, cli);
588 if (req == NULL) {
589 status = NT_STATUS_NO_MEMORY;
590 goto fail;
593 if (!tevent_req_poll(req, ev)) {
594 status = map_nt_error_from_unix(errno);
595 goto fail;
598 status = cli_session_setup_guest_recv(req);
599 fail:
600 TALLOC_FREE(frame);
601 if (!NT_STATUS_IS_OK(status)) {
602 cli_set_error(cli, status);
604 return status;
607 /****************************************************************************
608 Do a NT1 plaintext session setup.
609 ****************************************************************************/
611 struct cli_session_setup_plain_state {
612 struct cli_state *cli;
613 uint16_t vwv[13];
614 const char *user;
617 static void cli_session_setup_plain_done(struct tevent_req *subreq);
619 static struct tevent_req *cli_session_setup_plain_send(
620 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
621 struct cli_state *cli,
622 const char *user, const char *pass, const char *workgroup)
624 struct tevent_req *req, *subreq;
625 struct cli_session_setup_plain_state *state;
626 uint16_t *vwv;
627 uint8_t *bytes;
628 size_t passlen;
629 char *version;
631 req = tevent_req_create(mem_ctx, &state,
632 struct cli_session_setup_plain_state);
633 if (req == NULL) {
634 return NULL;
636 state->cli = cli;
637 state->user = user;
638 vwv = state->vwv;
640 SCVAL(vwv+0, 0, 0xff);
641 SCVAL(vwv+0, 1, 0);
642 SSVAL(vwv+1, 0, 0);
643 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
644 SSVAL(vwv+3, 0, 2);
645 SSVAL(vwv+4, 0, cli->pid);
646 SIVAL(vwv+5, 0, cli->sesskey);
647 SSVAL(vwv+7, 0, 0);
648 SSVAL(vwv+8, 0, 0);
649 SSVAL(vwv+9, 0, 0);
650 SSVAL(vwv+10, 0, 0);
651 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
653 bytes = talloc_array(state, uint8_t, 0);
654 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
655 &passlen);
656 if (tevent_req_nomem(bytes, req)) {
657 return tevent_req_post(req, ev);
659 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
661 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
662 user, strlen(user)+1, NULL);
663 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
664 workgroup, strlen(workgroup)+1, NULL);
665 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
666 "Unix", 5, NULL);
668 version = talloc_asprintf(talloc_tos(), "Samba %s",
669 samba_version_string());
670 if (tevent_req_nomem(version, req)){
671 return tevent_req_post(req, ev);
673 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
674 version, strlen(version)+1, NULL);
675 TALLOC_FREE(version);
677 if (tevent_req_nomem(bytes, req)) {
678 return tevent_req_post(req, ev);
681 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
682 talloc_get_size(bytes), bytes);
683 if (tevent_req_nomem(subreq, req)) {
684 return tevent_req_post(req, ev);
686 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
687 return req;
690 static void cli_session_setup_plain_done(struct tevent_req *subreq)
692 struct tevent_req *req = tevent_req_callback_data(
693 subreq, struct tevent_req);
694 struct cli_session_setup_plain_state *state = tevent_req_data(
695 req, struct cli_session_setup_plain_state);
696 struct cli_state *cli = state->cli;
697 uint32_t num_bytes;
698 uint8_t *in;
699 char *inbuf;
700 uint8_t *bytes;
701 uint8_t *p;
702 NTSTATUS status;
703 ssize_t ret;
704 uint8_t wct;
705 uint16_t *vwv;
707 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
708 &num_bytes, &bytes);
709 TALLOC_FREE(subreq);
710 if (tevent_req_nterror(req, status)) {
711 return;
714 inbuf = (char *)in;
715 p = bytes;
717 cli->vuid = SVAL(inbuf, smb_uid);
718 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
720 status = smb_bytes_talloc_string(cli,
721 inbuf,
722 &cli->server_os,
724 bytes+num_bytes-p,
725 &ret);
727 if (!NT_STATUS_IS_OK(status)) {
728 tevent_req_nterror(req, status);
729 return;
731 p += ret;
733 status = smb_bytes_talloc_string(cli,
734 inbuf,
735 &cli->server_type,
737 bytes+num_bytes-p,
738 &ret);
740 if (!NT_STATUS_IS_OK(status)) {
741 tevent_req_nterror(req, status);
742 return;
744 p += ret;
746 status = smb_bytes_talloc_string(cli,
747 inbuf,
748 &cli->server_domain,
750 bytes+num_bytes-p,
751 &ret);
753 if (!NT_STATUS_IS_OK(status)) {
754 tevent_req_nterror(req, status);
755 return;
757 p += ret;
759 status = cli_set_username(cli, state->user);
760 if (tevent_req_nterror(req, status)) {
761 return;
763 if (strstr(cli->server_type, "Samba")) {
764 cli->is_samba = True;
766 tevent_req_done(req);
769 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
771 return tevent_req_simple_recv_ntstatus(req);
774 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
775 const char *user, const char *pass,
776 const char *workgroup)
778 TALLOC_CTX *frame = talloc_stackframe();
779 struct event_context *ev;
780 struct tevent_req *req;
781 NTSTATUS status = NT_STATUS_NO_MEMORY;
783 if (cli_has_async_calls(cli)) {
785 * Can't use sync call while an async call is in flight
787 status = NT_STATUS_INVALID_PARAMETER;
788 goto fail;
790 ev = event_context_init(frame);
791 if (ev == NULL) {
792 goto fail;
794 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
795 workgroup);
796 if (req == NULL) {
797 goto fail;
799 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
800 goto fail;
802 status = cli_session_setup_plain_recv(req);
803 fail:
804 TALLOC_FREE(frame);
805 if (!NT_STATUS_IS_OK(status)) {
806 cli_set_error(cli, status);
808 return status;
811 /****************************************************************************
812 do a NT1 NTLM/LM encrypted session setup - for when extended security
813 is not negotiated.
814 @param cli client state to create do session setup on
815 @param user username
816 @param pass *either* cleartext password (passlen !=24) or LM response.
817 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
818 @param workgroup The user's domain.
819 ****************************************************************************/
821 struct cli_session_setup_nt1_state {
822 struct cli_state *cli;
823 uint16_t vwv[13];
824 DATA_BLOB response;
825 DATA_BLOB session_key;
826 const char *user;
829 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
831 static struct tevent_req *cli_session_setup_nt1_send(
832 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
833 struct cli_state *cli, const char *user,
834 const char *pass, size_t passlen,
835 const char *ntpass, size_t ntpasslen,
836 const char *workgroup)
838 struct tevent_req *req, *subreq;
839 struct cli_session_setup_nt1_state *state;
840 DATA_BLOB lm_response = data_blob_null;
841 DATA_BLOB nt_response = data_blob_null;
842 DATA_BLOB session_key = data_blob_null;
843 uint16_t *vwv;
844 uint8_t *bytes;
845 char *workgroup_upper;
847 req = tevent_req_create(mem_ctx, &state,
848 struct cli_session_setup_nt1_state);
849 if (req == NULL) {
850 return NULL;
852 state->cli = cli;
853 state->user = user;
854 vwv = state->vwv;
856 if (passlen == 0) {
857 /* do nothing - guest login */
858 } else if (passlen != 24) {
859 if (lp_client_ntlmv2_auth()) {
860 DATA_BLOB server_chal;
861 DATA_BLOB names_blob;
863 server_chal = data_blob(cli->secblob.data,
864 MIN(cli->secblob.length, 8));
865 if (tevent_req_nomem(server_chal.data, req)) {
866 return tevent_req_post(req, ev);
870 * note that the 'workgroup' here is a best
871 * guess - we don't know the server's domain
872 * at this point. The 'server name' is also
873 * dodgy...
875 names_blob = NTLMv2_generate_names_blob(
876 NULL, cli->called.name, workgroup);
878 if (tevent_req_nomem(names_blob.data, req)) {
879 return tevent_req_post(req, ev);
882 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
883 &server_chal, &names_blob,
884 &lm_response, &nt_response,
885 NULL, &session_key)) {
886 data_blob_free(&names_blob);
887 data_blob_free(&server_chal);
888 tevent_req_nterror(
889 req, NT_STATUS_ACCESS_DENIED);
890 return tevent_req_post(req, ev);
892 data_blob_free(&names_blob);
893 data_blob_free(&server_chal);
895 } else {
896 uchar nt_hash[16];
897 E_md4hash(pass, nt_hash);
899 #ifdef LANMAN_ONLY
900 nt_response = data_blob_null;
901 #else
902 nt_response = data_blob(NULL, 24);
903 if (tevent_req_nomem(nt_response.data, req)) {
904 return tevent_req_post(req, ev);
907 SMBNTencrypt(pass, cli->secblob.data,
908 nt_response.data);
909 #endif
910 /* non encrypted password supplied. Ignore ntpass. */
911 if (lp_client_lanman_auth()) {
913 lm_response = data_blob(NULL, 24);
914 if (tevent_req_nomem(lm_response.data, req)) {
915 return tevent_req_post(req, ev);
918 if (!SMBencrypt(pass,cli->secblob.data,
919 lm_response.data)) {
921 * Oops, the LM response is
922 * invalid, just put the NT
923 * response there instead
925 data_blob_free(&lm_response);
926 lm_response = data_blob(
927 nt_response.data,
928 nt_response.length);
930 } else {
932 * LM disabled, place NT# in LM field
933 * instead
935 lm_response = data_blob(
936 nt_response.data, nt_response.length);
939 if (tevent_req_nomem(lm_response.data, req)) {
940 return tevent_req_post(req, ev);
943 session_key = data_blob(NULL, 16);
944 if (tevent_req_nomem(session_key.data, req)) {
945 return tevent_req_post(req, ev);
947 #ifdef LANMAN_ONLY
948 E_deshash(pass, session_key.data);
949 memset(&session_key.data[8], '\0', 8);
950 #else
951 SMBsesskeygen_ntv1(nt_hash, session_key.data);
952 #endif
954 cli_temp_set_signing(cli);
955 } else {
956 /* pre-encrypted password supplied. Only used for
957 security=server, can't do
958 signing because we don't have original key */
960 lm_response = data_blob(pass, passlen);
961 if (tevent_req_nomem(lm_response.data, req)) {
962 return tevent_req_post(req, ev);
965 nt_response = data_blob(ntpass, ntpasslen);
966 if (tevent_req_nomem(nt_response.data, req)) {
967 return tevent_req_post(req, ev);
971 #ifdef LANMAN_ONLY
972 state->response = data_blob_talloc(
973 state, lm_response.data, lm_response.length);
974 #else
975 state->response = data_blob_talloc(
976 state, nt_response.data, nt_response.length);
977 #endif
978 if (tevent_req_nomem(state->response.data, req)) {
979 return tevent_req_post(req, ev);
982 if (session_key.data) {
983 state->session_key = data_blob_talloc(
984 state, session_key.data, session_key.length);
985 if (tevent_req_nomem(state->session_key.data, req)) {
986 return tevent_req_post(req, ev);
989 data_blob_free(&session_key);
991 SCVAL(vwv+0, 0, 0xff);
992 SCVAL(vwv+0, 1, 0);
993 SSVAL(vwv+1, 0, 0);
994 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
995 SSVAL(vwv+3, 0, 2);
996 SSVAL(vwv+4, 0, cli->pid);
997 SIVAL(vwv+5, 0, cli->sesskey);
998 SSVAL(vwv+7, 0, lm_response.length);
999 SSVAL(vwv+8, 0, nt_response.length);
1000 SSVAL(vwv+9, 0, 0);
1001 SSVAL(vwv+10, 0, 0);
1002 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
1004 bytes = talloc_array(state, uint8_t,
1005 lm_response.length + nt_response.length);
1006 if (tevent_req_nomem(bytes, req)) {
1007 return tevent_req_post(req, ev);
1009 if (lm_response.length != 0) {
1010 memcpy(bytes, lm_response.data, lm_response.length);
1012 if (nt_response.length != 0) {
1013 memcpy(bytes + lm_response.length,
1014 nt_response.data, nt_response.length);
1016 data_blob_free(&lm_response);
1017 data_blob_free(&nt_response);
1019 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1020 user, strlen(user)+1, NULL);
1023 * Upper case here might help some NTLMv2 implementations
1025 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1026 if (tevent_req_nomem(workgroup_upper, req)) {
1027 return tevent_req_post(req, ev);
1029 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1030 workgroup_upper, strlen(workgroup_upper)+1,
1031 NULL);
1032 TALLOC_FREE(workgroup_upper);
1034 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1035 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1036 if (tevent_req_nomem(bytes, req)) {
1037 return tevent_req_post(req, ev);
1040 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1041 talloc_get_size(bytes), bytes);
1042 if (tevent_req_nomem(subreq, req)) {
1043 return tevent_req_post(req, ev);
1045 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1046 return req;
1049 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1051 struct tevent_req *req = tevent_req_callback_data(
1052 subreq, struct tevent_req);
1053 struct cli_session_setup_nt1_state *state = tevent_req_data(
1054 req, struct cli_session_setup_nt1_state);
1055 struct cli_state *cli = state->cli;
1056 uint32_t num_bytes;
1057 uint8_t *in;
1058 char *inbuf;
1059 uint8_t *bytes;
1060 uint8_t *p;
1061 NTSTATUS status;
1062 ssize_t ret;
1063 uint8_t wct;
1064 uint16_t *vwv;
1066 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1067 &num_bytes, &bytes);
1068 TALLOC_FREE(subreq);
1069 if (!NT_STATUS_IS_OK(status)) {
1070 tevent_req_nterror(req, status);
1071 return;
1074 inbuf = (char *)in;
1075 p = bytes;
1077 cli->vuid = SVAL(inbuf, smb_uid);
1078 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1080 status = smb_bytes_talloc_string(cli,
1081 inbuf,
1082 &cli->server_os,
1084 bytes+num_bytes-p,
1085 &ret);
1086 if (!NT_STATUS_IS_OK(status)) {
1087 tevent_req_nterror(req, status);
1088 return;
1090 p += ret;
1092 status = smb_bytes_talloc_string(cli,
1093 inbuf,
1094 &cli->server_type,
1096 bytes+num_bytes-p,
1097 &ret);
1098 if (!NT_STATUS_IS_OK(status)) {
1099 tevent_req_nterror(req, status);
1100 return;
1102 p += ret;
1104 status = smb_bytes_talloc_string(cli,
1105 inbuf,
1106 &cli->server_domain,
1108 bytes+num_bytes-p,
1109 &ret);
1110 if (!NT_STATUS_IS_OK(status)) {
1111 tevent_req_nterror(req, status);
1112 return;
1114 p += ret;
1116 if (strstr(cli->server_type, "Samba")) {
1117 cli->is_samba = True;
1120 status = cli_set_username(cli, state->user);
1121 if (tevent_req_nterror(req, status)) {
1122 return;
1124 if (cli_simple_set_signing(cli, state->session_key, state->response)
1125 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1126 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1127 return;
1129 if (state->session_key.data) {
1130 /* Have plaintext orginal */
1131 cli_set_session_key(cli, state->session_key);
1133 tevent_req_done(req);
1136 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1138 return tevent_req_simple_recv_ntstatus(req);
1141 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1142 const char *pass, size_t passlen,
1143 const char *ntpass, size_t ntpasslen,
1144 const char *workgroup)
1146 TALLOC_CTX *frame = talloc_stackframe();
1147 struct event_context *ev;
1148 struct tevent_req *req;
1149 NTSTATUS status = NT_STATUS_NO_MEMORY;
1151 if (cli_has_async_calls(cli)) {
1153 * Can't use sync call while an async call is in flight
1155 status = NT_STATUS_INVALID_PARAMETER;
1156 goto fail;
1158 ev = event_context_init(frame);
1159 if (ev == NULL) {
1160 goto fail;
1162 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1163 ntpass, ntpasslen, workgroup);
1164 if (req == NULL) {
1165 goto fail;
1167 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1168 goto fail;
1170 status = cli_session_setup_nt1_recv(req);
1171 fail:
1172 TALLOC_FREE(frame);
1173 if (!NT_STATUS_IS_OK(status)) {
1174 cli_set_error(cli, status);
1176 return status;
1179 /* The following is calculated from :
1180 * (smb_size-4) = 35
1181 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1182 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1183 * end of packet.
1186 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1188 struct cli_sesssetup_blob_state {
1189 struct tevent_context *ev;
1190 struct cli_state *cli;
1191 DATA_BLOB blob;
1192 uint16_t max_blob_size;
1193 uint16_t vwv[12];
1194 uint8_t *buf;
1196 NTSTATUS status;
1197 char *inbuf;
1198 DATA_BLOB ret_blob;
1201 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1202 struct tevent_req **psubreq);
1203 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1205 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1206 struct tevent_context *ev,
1207 struct cli_state *cli,
1208 DATA_BLOB blob)
1210 struct tevent_req *req, *subreq;
1211 struct cli_sesssetup_blob_state *state;
1213 req = tevent_req_create(mem_ctx, &state,
1214 struct cli_sesssetup_blob_state);
1215 if (req == NULL) {
1216 return NULL;
1218 state->ev = ev;
1219 state->blob = blob;
1220 state->cli = cli;
1222 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1223 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1224 "(was %u, need minimum %u)\n",
1225 (unsigned int)cli->max_xmit,
1226 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1227 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1228 return tevent_req_post(req, ev);
1230 state->max_blob_size =
1231 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1233 if (!cli_sesssetup_blob_next(state, &subreq)) {
1234 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1235 return tevent_req_post(req, ev);
1237 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1238 return req;
1241 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1242 struct tevent_req **psubreq)
1244 struct tevent_req *subreq;
1245 uint16_t thistime;
1247 SCVAL(state->vwv+0, 0, 0xFF);
1248 SCVAL(state->vwv+0, 1, 0);
1249 SSVAL(state->vwv+1, 0, 0);
1250 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1251 SSVAL(state->vwv+3, 0, 2);
1252 SSVAL(state->vwv+4, 0, 1);
1253 SIVAL(state->vwv+5, 0, 0);
1255 thistime = MIN(state->blob.length, state->max_blob_size);
1256 SSVAL(state->vwv+7, 0, thistime);
1258 SSVAL(state->vwv+8, 0, 0);
1259 SSVAL(state->vwv+9, 0, 0);
1260 SIVAL(state->vwv+10, 0,
1261 cli_session_setup_capabilities(state->cli)
1262 | CAP_EXTENDED_SECURITY);
1264 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1265 thistime);
1266 if (state->buf == NULL) {
1267 return false;
1269 state->blob.data += thistime;
1270 state->blob.length -= thistime;
1272 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1273 "Unix", 5, NULL);
1274 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1275 "Samba", 6, NULL);
1276 if (state->buf == NULL) {
1277 return false;
1279 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1280 12, state->vwv,
1281 talloc_get_size(state->buf), state->buf);
1282 if (subreq == NULL) {
1283 return false;
1285 *psubreq = subreq;
1286 return true;
1289 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1291 struct tevent_req *req = tevent_req_callback_data(
1292 subreq, struct tevent_req);
1293 struct cli_sesssetup_blob_state *state = tevent_req_data(
1294 req, struct cli_sesssetup_blob_state);
1295 struct cli_state *cli = state->cli;
1296 uint8_t wct;
1297 uint16_t *vwv;
1298 uint32_t num_bytes;
1299 uint8_t *bytes;
1300 NTSTATUS status;
1301 uint8_t *p;
1302 uint16_t blob_length;
1303 uint8_t *inbuf;
1304 ssize_t ret;
1306 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1307 &num_bytes, &bytes);
1308 TALLOC_FREE(subreq);
1309 if (!NT_STATUS_IS_OK(status)
1310 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1311 tevent_req_nterror(req, status);
1312 return;
1315 state->status = status;
1316 TALLOC_FREE(state->buf);
1318 state->inbuf = (char *)inbuf;
1319 cli->vuid = SVAL(state->inbuf, smb_uid);
1320 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1322 blob_length = SVAL(vwv+3, 0);
1323 if (blob_length > num_bytes) {
1324 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1325 return;
1327 state->ret_blob = data_blob_const(bytes, blob_length);
1329 p = bytes + blob_length;
1331 status = smb_bytes_talloc_string(cli,
1332 (char *)inbuf,
1333 &cli->server_os,
1335 bytes+num_bytes-p,
1336 &ret);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 tevent_req_nterror(req, status);
1340 return;
1342 p += ret;
1344 status = smb_bytes_talloc_string(cli,
1345 (char *)inbuf,
1346 &cli->server_type,
1348 bytes+num_bytes-p,
1349 &ret);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 tevent_req_nterror(req, status);
1353 return;
1355 p += ret;
1357 status = smb_bytes_talloc_string(cli,
1358 (char *)inbuf,
1359 &cli->server_domain,
1361 bytes+num_bytes-p,
1362 &ret);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 tevent_req_nterror(req, status);
1366 return;
1368 p += ret;
1370 if (strstr(cli->server_type, "Samba")) {
1371 cli->is_samba = True;
1374 if (state->blob.length != 0) {
1376 * More to send
1378 if (!cli_sesssetup_blob_next(state, &subreq)) {
1379 tevent_req_nomem(NULL, req);
1380 return;
1382 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1383 return;
1385 tevent_req_done(req);
1388 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1389 TALLOC_CTX *mem_ctx,
1390 DATA_BLOB *pblob,
1391 char **pinbuf)
1393 struct cli_sesssetup_blob_state *state = tevent_req_data(
1394 req, struct cli_sesssetup_blob_state);
1395 NTSTATUS status;
1396 char *inbuf;
1398 if (tevent_req_is_nterror(req, &status)) {
1399 state->cli->vuid = 0;
1400 return status;
1403 inbuf = talloc_move(mem_ctx, &state->inbuf);
1404 if (pblob != NULL) {
1405 *pblob = state->ret_blob;
1407 if (pinbuf != NULL) {
1408 *pinbuf = inbuf;
1410 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1411 return state->status;
1414 #ifdef HAVE_KRB5
1416 /****************************************************************************
1417 Use in-memory credentials cache
1418 ****************************************************************************/
1420 static void use_in_memory_ccache(void) {
1421 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1424 /****************************************************************************
1425 Do a spnego/kerberos encrypted session setup.
1426 ****************************************************************************/
1428 struct cli_session_setup_kerberos_state {
1429 struct cli_state *cli;
1430 DATA_BLOB negTokenTarg;
1431 DATA_BLOB session_key_krb5;
1432 ADS_STATUS ads_status;
1435 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1437 static struct tevent_req *cli_session_setup_kerberos_send(
1438 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1439 const char *principal, const char *workgroup)
1441 struct tevent_req *req, *subreq;
1442 struct cli_session_setup_kerberos_state *state;
1443 int rc;
1445 DEBUG(2,("Doing kerberos session setup\n"));
1447 req = tevent_req_create(mem_ctx, &state,
1448 struct cli_session_setup_kerberos_state);
1449 if (req == NULL) {
1450 return NULL;
1452 state->cli = cli;
1453 state->ads_status = ADS_SUCCESS;
1455 cli_temp_set_signing(cli);
1458 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1459 * we have to acquire a ticket. To be fixed later :-)
1461 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1462 &state->session_key_krb5, 0, NULL);
1463 if (rc) {
1464 DEBUG(1, ("cli_session_setup_kerberos: "
1465 "spnego_gen_krb5_negTokenInit failed: %s\n",
1466 error_message(rc)));
1467 state->ads_status = ADS_ERROR_KRB5(rc);
1468 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1469 return tevent_req_post(req, ev);
1472 #if 0
1473 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1474 state->negTokenTarg.length);
1475 #endif
1477 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1478 if (tevent_req_nomem(subreq, req)) {
1479 return tevent_req_post(req, ev);
1481 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1482 return req;
1485 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1487 struct tevent_req *req = tevent_req_callback_data(
1488 subreq, struct tevent_req);
1489 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1490 req, struct cli_session_setup_kerberos_state);
1491 char *inbuf = NULL;
1492 NTSTATUS status;
1494 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 TALLOC_FREE(subreq);
1497 tevent_req_nterror(req, status);
1498 return;
1501 cli_set_session_key(state->cli, state->session_key_krb5);
1503 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1504 data_blob_null)
1505 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1506 TALLOC_FREE(subreq);
1507 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1508 return;
1510 TALLOC_FREE(subreq);
1511 tevent_req_done(req);
1514 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1516 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1517 req, struct cli_session_setup_kerberos_state);
1518 NTSTATUS status;
1520 if (tevent_req_is_nterror(req, &status)) {
1521 return ADS_ERROR_NT(status);
1523 return state->ads_status;
1526 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1527 const char *principal,
1528 const char *workgroup)
1530 struct tevent_context *ev;
1531 struct tevent_req *req;
1532 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1534 if (cli_has_async_calls(cli)) {
1535 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1537 ev = tevent_context_init(talloc_tos());
1538 if (ev == NULL) {
1539 goto fail;
1541 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1542 workgroup);
1543 if (req == NULL) {
1544 goto fail;
1546 if (!tevent_req_poll(req, ev)) {
1547 status = ADS_ERROR_SYSTEM(errno);
1548 goto fail;
1550 status = cli_session_setup_kerberos_recv(req);
1551 fail:
1552 TALLOC_FREE(ev);
1553 return status;
1555 #endif /* HAVE_KRB5 */
1557 /****************************************************************************
1558 Do a spnego/NTLMSSP encrypted session setup.
1559 ****************************************************************************/
1561 struct cli_session_setup_ntlmssp_state {
1562 struct tevent_context *ev;
1563 struct cli_state *cli;
1564 struct ntlmssp_state *ntlmssp_state;
1565 int turn;
1566 DATA_BLOB blob_out;
1569 static int cli_session_setup_ntlmssp_state_destructor(
1570 struct cli_session_setup_ntlmssp_state *state)
1572 if (state->ntlmssp_state != NULL) {
1573 TALLOC_FREE(state->ntlmssp_state);
1575 return 0;
1578 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1580 static struct tevent_req *cli_session_setup_ntlmssp_send(
1581 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1582 const char *user, const char *pass, const char *domain)
1584 struct tevent_req *req, *subreq;
1585 struct cli_session_setup_ntlmssp_state *state;
1586 NTSTATUS status;
1587 DATA_BLOB blob_out;
1588 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1590 req = tevent_req_create(mem_ctx, &state,
1591 struct cli_session_setup_ntlmssp_state);
1592 if (req == NULL) {
1593 return NULL;
1595 state->ev = ev;
1596 state->cli = cli;
1597 state->turn = 1;
1599 state->ntlmssp_state = NULL;
1600 talloc_set_destructor(
1601 state, cli_session_setup_ntlmssp_state_destructor);
1603 cli_temp_set_signing(cli);
1605 status = ntlmssp_client_start(state,
1606 global_myname(),
1607 lp_workgroup(),
1608 lp_client_ntlmv2_auth(),
1609 &state->ntlmssp_state);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 goto fail;
1613 ntlmssp_want_feature(state->ntlmssp_state,
1614 NTLMSSP_FEATURE_SESSION_KEY);
1615 if (cli->use_ccache) {
1616 ntlmssp_want_feature(state->ntlmssp_state,
1617 NTLMSSP_FEATURE_CCACHE);
1619 status = ntlmssp_set_username(state->ntlmssp_state, user);
1620 if (!NT_STATUS_IS_OK(status)) {
1621 goto fail;
1623 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1624 if (!NT_STATUS_IS_OK(status)) {
1625 goto fail;
1627 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1628 if (!NT_STATUS_IS_OK(status)) {
1629 goto fail;
1631 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1632 &blob_out);
1633 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1634 goto fail;
1637 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1638 data_blob_free(&blob_out);
1640 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1641 if (tevent_req_nomem(subreq, req)) {
1642 return tevent_req_post(req, ev);
1644 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1645 return req;
1646 fail:
1647 tevent_req_nterror(req, status);
1648 return tevent_req_post(req, ev);
1651 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1653 struct tevent_req *req = tevent_req_callback_data(
1654 subreq, struct tevent_req);
1655 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1656 req, struct cli_session_setup_ntlmssp_state);
1657 DATA_BLOB blob_in, msg_in, blob_out;
1658 char *inbuf = NULL;
1659 bool parse_ret;
1660 NTSTATUS status;
1662 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1663 &inbuf);
1664 TALLOC_FREE(subreq);
1665 data_blob_free(&state->blob_out);
1667 if (NT_STATUS_IS_OK(status)) {
1668 if (state->cli->server_domain[0] == '\0') {
1669 TALLOC_FREE(state->cli->server_domain);
1670 state->cli->server_domain = talloc_strdup(state->cli,
1671 state->ntlmssp_state->server.netbios_domain);
1672 if (state->cli->server_domain == NULL) {
1673 TALLOC_FREE(subreq);
1674 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1675 return;
1678 cli_set_session_key(
1679 state->cli, state->ntlmssp_state->session_key);
1681 if (cli_simple_set_signing(
1682 state->cli, state->ntlmssp_state->session_key,
1683 data_blob_null)
1684 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1685 TALLOC_FREE(subreq);
1686 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1687 return;
1689 TALLOC_FREE(subreq);
1690 TALLOC_FREE(state->ntlmssp_state);
1691 tevent_req_done(req);
1692 return;
1694 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1695 tevent_req_nterror(req, status);
1696 return;
1699 if (blob_in.length == 0) {
1700 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1701 return;
1704 if ((state->turn == 1)
1705 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1706 DATA_BLOB tmp_blob = data_blob_null;
1707 /* the server might give us back two challenges */
1708 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1709 &tmp_blob);
1710 data_blob_free(&tmp_blob);
1711 } else {
1712 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1713 OID_NTLMSSP, &msg_in);
1715 state->turn += 1;
1717 if (!parse_ret) {
1718 DEBUG(3,("Failed to parse auth response\n"));
1719 if (NT_STATUS_IS_OK(status)
1720 || NT_STATUS_EQUAL(status,
1721 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1722 tevent_req_nterror(
1723 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1724 return;
1728 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1730 if (!NT_STATUS_IS_OK(status)
1731 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1732 TALLOC_FREE(subreq);
1733 TALLOC_FREE(state->ntlmssp_state);
1734 tevent_req_nterror(req, status);
1735 return;
1738 state->blob_out = spnego_gen_auth(state, blob_out);
1739 TALLOC_FREE(subreq);
1740 if (tevent_req_nomem(state->blob_out.data, req)) {
1741 return;
1744 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1745 state->blob_out);
1746 if (tevent_req_nomem(subreq, req)) {
1747 return;
1749 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1752 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1754 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1755 req, struct cli_session_setup_ntlmssp_state);
1756 NTSTATUS status;
1758 if (tevent_req_is_nterror(req, &status)) {
1759 state->cli->vuid = 0;
1760 return status;
1762 return NT_STATUS_OK;
1765 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1766 const char *user,
1767 const char *pass,
1768 const char *domain)
1770 struct tevent_context *ev;
1771 struct tevent_req *req;
1772 NTSTATUS status = NT_STATUS_NO_MEMORY;
1774 if (cli_has_async_calls(cli)) {
1775 return NT_STATUS_INVALID_PARAMETER;
1777 ev = tevent_context_init(talloc_tos());
1778 if (ev == NULL) {
1779 goto fail;
1781 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1782 if (req == NULL) {
1783 goto fail;
1785 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1786 goto fail;
1788 status = cli_session_setup_ntlmssp_recv(req);
1789 fail:
1790 TALLOC_FREE(ev);
1791 if (!NT_STATUS_IS_OK(status)) {
1792 cli_set_error(cli, status);
1794 return status;
1797 /****************************************************************************
1798 Do a spnego encrypted session setup.
1800 user_domain: The shortname of the domain the user/machine is a member of.
1801 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1802 ****************************************************************************/
1804 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1805 const char *pass, const char *user_domain,
1806 const char * dest_realm)
1808 char *principal = NULL;
1809 char *OIDs[ASN1_MAX_OIDS];
1810 int i;
1811 DATA_BLOB blob;
1812 const char *p = NULL;
1813 char *account = NULL;
1814 NTSTATUS status;
1816 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1818 /* the server might not even do spnego */
1819 if (cli->secblob.length <= 16) {
1820 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1821 goto ntlmssp;
1824 #if 0
1825 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1826 #endif
1828 /* there is 16 bytes of GUID before the real spnego packet starts */
1829 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1831 /* The server sent us the first part of the SPNEGO exchange in the
1832 * negprot reply. It is WRONG to depend on the principal sent in the
1833 * negprot reply, but right now we do it. If we don't receive one,
1834 * we try to best guess, then fall back to NTLM. */
1835 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1836 OIDs[0] == NULL) {
1837 data_blob_free(&blob);
1838 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1840 data_blob_free(&blob);
1842 /* make sure the server understands kerberos */
1843 for (i=0;OIDs[i];i++) {
1844 if (i == 0)
1845 DEBUG(3,("got OID=%s\n", OIDs[i]));
1846 else
1847 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1848 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1849 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1850 cli->got_kerberos_mechanism = True;
1852 talloc_free(OIDs[i]);
1855 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1857 status = cli_set_username(cli, user);
1858 if (!NT_STATUS_IS_OK(status)) {
1859 TALLOC_FREE(principal);
1860 return ADS_ERROR_NT(status);
1863 #ifdef HAVE_KRB5
1864 /* If password is set we reauthenticate to kerberos server
1865 * and do not store results */
1867 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1868 ADS_STATUS rc;
1870 if (pass && *pass) {
1871 int ret;
1873 use_in_memory_ccache();
1874 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1876 if (ret){
1877 TALLOC_FREE(principal);
1878 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1879 if (cli->fallback_after_kerberos)
1880 goto ntlmssp;
1881 return ADS_ERROR_KRB5(ret);
1885 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1887 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1888 TALLOC_FREE(principal);
1891 if (principal == NULL &&
1892 !is_ipaddress(cli->desthost) &&
1893 !strequal(STAR_SMBSERVER,
1894 cli->desthost)) {
1895 char *realm = NULL;
1896 char *host = NULL;
1897 DEBUG(3,("cli_session_setup_spnego: using target "
1898 "hostname not SPNEGO principal\n"));
1900 host = strchr_m(cli->desthost, '.');
1901 if (dest_realm) {
1902 realm = SMB_STRDUP(dest_realm);
1903 if (!realm) {
1904 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1906 strupper_m(realm);
1907 } else {
1908 if (host) {
1909 /* DNS name. */
1910 realm = kerberos_get_realm_from_hostname(cli->desthost);
1911 } else {
1912 /* NetBIOS name - use our realm. */
1913 realm = kerberos_get_default_realm_from_ccache();
1917 if (realm == NULL || *realm == '\0') {
1918 realm = SMB_STRDUP(lp_realm());
1919 if (!realm) {
1920 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1922 strupper_m(realm);
1923 DEBUG(3,("cli_session_setup_spnego: cannot "
1924 "get realm from dest_realm %s, "
1925 "desthost %s. Using default "
1926 "smb.conf realm %s\n",
1927 dest_realm ? dest_realm : "<null>",
1928 cli->desthost,
1929 realm));
1932 principal = talloc_asprintf(talloc_tos(),
1933 "cifs/%s@%s",
1934 cli->desthost,
1935 realm);
1936 if (!principal) {
1937 SAFE_FREE(realm);
1938 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1940 DEBUG(3,("cli_session_setup_spnego: guessed "
1941 "server principal=%s\n",
1942 principal ? principal : "<null>"));
1944 SAFE_FREE(realm);
1947 if (principal) {
1948 rc = cli_session_setup_kerberos(cli, principal,
1949 dest_realm);
1950 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1951 TALLOC_FREE(principal);
1952 return rc;
1956 #endif
1958 TALLOC_FREE(principal);
1960 ntlmssp:
1962 account = talloc_strdup(talloc_tos(), user);
1963 if (!account) {
1964 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1967 /* when falling back to ntlmssp while authenticating with a machine
1968 * account strip off the realm - gd */
1970 if ((p = strchr_m(user, '@')) != NULL) {
1971 account[PTR_DIFF(p,user)] = '\0';
1974 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1977 /****************************************************************************
1978 Send a session setup. The username and workgroup is in UNIX character
1979 format and must be converted to DOS codepage format before sending. If the
1980 password is in plaintext, the same should be done.
1981 ****************************************************************************/
1983 NTSTATUS cli_session_setup(struct cli_state *cli,
1984 const char *user,
1985 const char *pass, int passlen,
1986 const char *ntpass, int ntpasslen,
1987 const char *workgroup)
1989 char *p;
1990 char *user2;
1992 if (user) {
1993 user2 = talloc_strdup(talloc_tos(), user);
1994 } else {
1995 user2 = talloc_strdup(talloc_tos(), "");
1997 if (user2 == NULL) {
1998 return NT_STATUS_NO_MEMORY;
2001 if (!workgroup) {
2002 workgroup = "";
2005 /* allow for workgroups as part of the username */
2006 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2007 (p=strchr_m(user2,*lp_winbind_separator()))) {
2008 *p = 0;
2009 user = p+1;
2010 strupper_m(user2);
2011 workgroup = user2;
2014 if (cli->protocol < PROTOCOL_LANMAN1) {
2015 return NT_STATUS_OK;
2018 /* now work out what sort of session setup we are going to
2019 do. I have split this into separate functions to make the
2020 flow a bit easier to understand (tridge) */
2022 /* if its an older server then we have to use the older request format */
2024 if (cli->protocol < PROTOCOL_NT1) {
2025 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2026 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2027 " or 'client ntlmv2 auth = yes'\n"));
2028 return NT_STATUS_ACCESS_DENIED;
2031 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2032 !lp_client_plaintext_auth() && (*pass)) {
2033 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2034 " or 'client ntlmv2 auth = yes'\n"));
2035 return NT_STATUS_ACCESS_DENIED;
2038 return cli_session_setup_lanman2(cli, user, pass, passlen,
2039 workgroup);
2042 /* if no user is supplied then we have to do an anonymous connection.
2043 passwords are ignored */
2045 if (!user || !*user)
2046 return cli_session_setup_guest(cli);
2048 /* if the server is share level then send a plaintext null
2049 password at this point. The password is sent in the tree
2050 connect */
2052 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2053 return cli_session_setup_plain(cli, user, "", workgroup);
2055 /* if the server doesn't support encryption then we have to use
2056 plaintext. The second password is ignored */
2058 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2059 if (!lp_client_plaintext_auth() && (*pass)) {
2060 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2061 " or 'client ntlmv2 auth = yes'\n"));
2062 return NT_STATUS_ACCESS_DENIED;
2064 return cli_session_setup_plain(cli, user, pass, workgroup);
2067 /* if the server supports extended security then use SPNEGO */
2069 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2070 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2071 workgroup, NULL);
2072 if (!ADS_ERR_OK(status)) {
2073 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2074 return ads_ntstatus(status);
2076 } else {
2077 NTSTATUS status;
2079 /* otherwise do a NT1 style session setup */
2080 status = cli_session_setup_nt1(cli, user, pass, passlen,
2081 ntpass, ntpasslen, workgroup);
2082 if (!NT_STATUS_IS_OK(status)) {
2083 DEBUG(3,("cli_session_setup: NT1 session setup "
2084 "failed: %s\n", nt_errstr(status)));
2085 return status;
2089 if (strstr(cli->server_type, "Samba")) {
2090 cli->is_samba = True;
2093 return NT_STATUS_OK;
2096 /****************************************************************************
2097 Send a uloggoff.
2098 *****************************************************************************/
2100 struct cli_ulogoff_state {
2101 struct cli_state *cli;
2102 uint16_t vwv[3];
2105 static void cli_ulogoff_done(struct tevent_req *subreq);
2107 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2108 struct tevent_context *ev,
2109 struct cli_state *cli)
2111 struct tevent_req *req, *subreq;
2112 struct cli_ulogoff_state *state;
2114 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2115 if (req == NULL) {
2116 return NULL;
2118 state->cli = cli;
2120 SCVAL(state->vwv+0, 0, 0xFF);
2121 SCVAL(state->vwv+1, 0, 0);
2122 SSVAL(state->vwv+2, 0, 0);
2124 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2125 0, NULL);
2126 if (tevent_req_nomem(subreq, req)) {
2127 return tevent_req_post(req, ev);
2129 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2130 return req;
2133 static void cli_ulogoff_done(struct tevent_req *subreq)
2135 struct tevent_req *req = tevent_req_callback_data(
2136 subreq, struct tevent_req);
2137 struct cli_ulogoff_state *state = tevent_req_data(
2138 req, struct cli_ulogoff_state);
2139 NTSTATUS status;
2141 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2142 if (!NT_STATUS_IS_OK(status)) {
2143 tevent_req_nterror(req, status);
2144 return;
2146 state->cli->vuid = -1;
2147 tevent_req_done(req);
2150 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2152 return tevent_req_simple_recv_ntstatus(req);
2155 NTSTATUS cli_ulogoff(struct cli_state *cli)
2157 struct tevent_context *ev;
2158 struct tevent_req *req;
2159 NTSTATUS status = NT_STATUS_NO_MEMORY;
2161 if (cli_has_async_calls(cli)) {
2162 return NT_STATUS_INVALID_PARAMETER;
2164 ev = tevent_context_init(talloc_tos());
2165 if (ev == NULL) {
2166 goto fail;
2168 req = cli_ulogoff_send(ev, ev, cli);
2169 if (req == NULL) {
2170 goto fail;
2172 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2173 goto fail;
2175 status = cli_ulogoff_recv(req);
2176 fail:
2177 TALLOC_FREE(ev);
2178 if (!NT_STATUS_IS_OK(status)) {
2179 cli_set_error(cli, status);
2181 return status;
2184 /****************************************************************************
2185 Send a tconX.
2186 ****************************************************************************/
2188 struct cli_tcon_andx_state {
2189 struct cli_state *cli;
2190 uint16_t vwv[4];
2191 struct iovec bytes;
2194 static void cli_tcon_andx_done(struct tevent_req *subreq);
2196 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2197 struct event_context *ev,
2198 struct cli_state *cli,
2199 const char *share, const char *dev,
2200 const char *pass, int passlen,
2201 struct tevent_req **psmbreq)
2203 struct tevent_req *req, *subreq;
2204 struct cli_tcon_andx_state *state;
2205 uint8_t p24[24];
2206 uint16_t *vwv;
2207 char *tmp = NULL;
2208 uint8_t *bytes;
2210 *psmbreq = NULL;
2212 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2213 if (req == NULL) {
2214 return NULL;
2216 state->cli = cli;
2217 vwv = state->vwv;
2219 cli->share = talloc_strdup(cli, share);
2220 if (!cli->share) {
2221 return NULL;
2224 /* in user level security don't send a password now */
2225 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2226 passlen = 1;
2227 pass = "";
2228 } else if (pass == NULL) {
2229 DEBUG(1, ("Server not using user level security and no "
2230 "password supplied.\n"));
2231 goto access_denied;
2234 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2235 *pass && passlen != 24) {
2236 if (!lp_client_lanman_auth()) {
2237 DEBUG(1, ("Server requested LANMAN password "
2238 "(share-level security) but "
2239 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2240 goto access_denied;
2244 * Non-encrypted passwords - convert to DOS codepage before
2245 * encryption.
2247 SMBencrypt(pass, cli->secblob.data, p24);
2248 passlen = 24;
2249 pass = (const char *)p24;
2250 } else {
2251 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2252 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2253 == 0) {
2254 char *tmp_pass;
2256 if (!lp_client_plaintext_auth() && (*pass)) {
2257 DEBUG(1, ("Server requested plaintext "
2258 "password but "
2259 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2260 goto access_denied;
2264 * Non-encrypted passwords - convert to DOS codepage
2265 * before using.
2267 tmp_pass = talloc_array(talloc_tos(), char, 128);
2268 if (tmp_pass == NULL) {
2269 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2270 return tevent_req_post(req, ev);
2272 passlen = clistr_push(cli,
2273 tmp_pass,
2274 pass,
2275 talloc_get_size(tmp_pass),
2276 STR_TERMINATE);
2277 if (passlen == -1) {
2278 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2279 return tevent_req_post(req, ev);
2281 pass = tmp_pass;
2285 SCVAL(vwv+0, 0, 0xFF);
2286 SCVAL(vwv+0, 1, 0);
2287 SSVAL(vwv+1, 0, 0);
2288 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2289 SSVAL(vwv+3, 0, passlen);
2291 if (passlen && pass) {
2292 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2293 } else {
2294 bytes = talloc_array(state, uint8_t, 0);
2298 * Add the sharename
2300 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2301 cli->desthost, share);
2302 if (tmp == NULL) {
2303 TALLOC_FREE(req);
2304 return NULL;
2306 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2307 NULL);
2308 TALLOC_FREE(tmp);
2311 * Add the devicetype
2313 tmp = talloc_strdup_upper(talloc_tos(), dev);
2314 if (tmp == NULL) {
2315 TALLOC_FREE(req);
2316 return NULL;
2318 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2319 TALLOC_FREE(tmp);
2321 if (bytes == NULL) {
2322 TALLOC_FREE(req);
2323 return NULL;
2326 state->bytes.iov_base = (void *)bytes;
2327 state->bytes.iov_len = talloc_get_size(bytes);
2329 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2330 1, &state->bytes);
2331 if (subreq == NULL) {
2332 TALLOC_FREE(req);
2333 return NULL;
2335 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2336 *psmbreq = subreq;
2337 return req;
2339 access_denied:
2340 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2341 return tevent_req_post(req, ev);
2344 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2345 struct event_context *ev,
2346 struct cli_state *cli,
2347 const char *share, const char *dev,
2348 const char *pass, int passlen)
2350 struct tevent_req *req, *subreq;
2351 NTSTATUS status;
2353 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2354 &subreq);
2355 if (req == NULL) {
2356 return NULL;
2358 if (subreq == NULL) {
2359 return req;
2361 status = cli_smb_req_send(subreq);
2362 if (!NT_STATUS_IS_OK(status)) {
2363 tevent_req_nterror(req, status);
2364 return tevent_req_post(req, ev);
2366 return req;
2369 static void cli_tcon_andx_done(struct tevent_req *subreq)
2371 struct tevent_req *req = tevent_req_callback_data(
2372 subreq, struct tevent_req);
2373 struct cli_tcon_andx_state *state = tevent_req_data(
2374 req, struct cli_tcon_andx_state);
2375 struct cli_state *cli = state->cli;
2376 uint8_t *in;
2377 char *inbuf;
2378 uint8_t wct;
2379 uint16_t *vwv;
2380 uint32_t num_bytes;
2381 uint8_t *bytes;
2382 NTSTATUS status;
2384 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2385 &num_bytes, &bytes);
2386 TALLOC_FREE(subreq);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 tevent_req_nterror(req, status);
2389 return;
2392 inbuf = (char *)in;
2394 if (num_bytes) {
2395 if (clistr_pull_talloc(cli,
2396 inbuf,
2397 SVAL(inbuf, smb_flg2),
2398 &cli->dev,
2399 bytes,
2400 num_bytes,
2401 STR_TERMINATE|STR_ASCII) == -1) {
2402 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2403 return;
2405 } else {
2406 cli->dev = talloc_strdup(cli, "");
2407 if (cli->dev == NULL) {
2408 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2409 return;
2413 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2414 /* almost certainly win95 - enable bug fixes */
2415 cli->win95 = True;
2419 * Make sure that we have the optional support 16-bit field. WCT > 2.
2420 * Avoids issues when connecting to Win9x boxes sharing files
2423 cli->dfsroot = false;
2425 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2426 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2429 cli->cnum = SVAL(inbuf,smb_tid);
2430 tevent_req_done(req);
2433 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2435 return tevent_req_simple_recv_ntstatus(req);
2438 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2439 const char *dev, const char *pass, int passlen)
2441 TALLOC_CTX *frame = talloc_stackframe();
2442 struct event_context *ev;
2443 struct tevent_req *req;
2444 NTSTATUS status = NT_STATUS_OK;
2446 if (cli_has_async_calls(cli)) {
2448 * Can't use sync call while an async call is in flight
2450 status = NT_STATUS_INVALID_PARAMETER;
2451 goto fail;
2454 ev = event_context_init(frame);
2455 if (ev == NULL) {
2456 status = NT_STATUS_NO_MEMORY;
2457 goto fail;
2460 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2461 if (req == NULL) {
2462 status = NT_STATUS_NO_MEMORY;
2463 goto fail;
2466 if (!tevent_req_poll(req, ev)) {
2467 status = map_nt_error_from_unix(errno);
2468 goto fail;
2471 status = cli_tcon_andx_recv(req);
2472 fail:
2473 TALLOC_FREE(frame);
2474 if (!NT_STATUS_IS_OK(status)) {
2475 cli_set_error(cli, status);
2477 return status;
2480 /****************************************************************************
2481 Send a tree disconnect.
2482 ****************************************************************************/
2484 struct cli_tdis_state {
2485 struct cli_state *cli;
2488 static void cli_tdis_done(struct tevent_req *subreq);
2490 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2491 struct tevent_context *ev,
2492 struct cli_state *cli)
2494 struct tevent_req *req, *subreq;
2495 struct cli_tdis_state *state;
2497 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2498 if (req == NULL) {
2499 return NULL;
2501 state->cli = cli;
2503 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2504 if (tevent_req_nomem(subreq, req)) {
2505 return tevent_req_post(req, ev);
2507 tevent_req_set_callback(subreq, cli_tdis_done, req);
2508 return req;
2511 static void cli_tdis_done(struct tevent_req *subreq)
2513 struct tevent_req *req = tevent_req_callback_data(
2514 subreq, struct tevent_req);
2515 struct cli_tdis_state *state = tevent_req_data(
2516 req, struct cli_tdis_state);
2517 NTSTATUS status;
2519 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2520 TALLOC_FREE(subreq);
2521 if (!NT_STATUS_IS_OK(status)) {
2522 tevent_req_nterror(req, status);
2523 return;
2525 state->cli->cnum = -1;
2526 tevent_req_done(req);
2529 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2531 return tevent_req_simple_recv_ntstatus(req);
2534 NTSTATUS cli_tdis(struct cli_state *cli)
2536 struct tevent_context *ev;
2537 struct tevent_req *req;
2538 NTSTATUS status = NT_STATUS_NO_MEMORY;
2540 if (cli_has_async_calls(cli)) {
2541 return NT_STATUS_INVALID_PARAMETER;
2543 ev = tevent_context_init(talloc_tos());
2544 if (ev == NULL) {
2545 goto fail;
2547 req = cli_tdis_send(ev, ev, cli);
2548 if (req == NULL) {
2549 goto fail;
2551 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2552 goto fail;
2554 status = cli_tdis_recv(req);
2555 fail:
2556 TALLOC_FREE(ev);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 cli_set_error(cli, status);
2560 return status;
2563 /****************************************************************************
2564 Send a negprot command.
2565 ****************************************************************************/
2567 struct cli_negprot_state {
2568 struct cli_state *cli;
2571 static void cli_negprot_done(struct tevent_req *subreq);
2573 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2574 struct event_context *ev,
2575 struct cli_state *cli)
2577 struct tevent_req *req, *subreq;
2578 struct cli_negprot_state *state;
2579 uint8_t *bytes = NULL;
2580 int numprots;
2581 uint16_t cnum;
2583 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2584 if (req == NULL) {
2585 return NULL;
2587 state->cli = cli;
2589 if (cli->protocol < PROTOCOL_NT1)
2590 cli->use_spnego = False;
2592 /* setup the protocol strings */
2593 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2594 uint8_t c = 2;
2595 if (prots[numprots].prot > cli->protocol) {
2596 break;
2598 bytes = (uint8_t *)talloc_append_blob(
2599 state, bytes, data_blob_const(&c, sizeof(c)));
2600 if (tevent_req_nomem(bytes, req)) {
2601 return tevent_req_post(req, ev);
2603 bytes = smb_bytes_push_str(bytes, false,
2604 prots[numprots].name,
2605 strlen(prots[numprots].name)+1,
2606 NULL);
2607 if (tevent_req_nomem(bytes, req)) {
2608 return tevent_req_post(req, ev);
2612 cnum = cli->cnum;
2614 cli->cnum = 0;
2615 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2616 talloc_get_size(bytes), bytes);
2617 cli->cnum = cnum;
2619 if (tevent_req_nomem(subreq, req)) {
2620 return tevent_req_post(req, ev);
2622 tevent_req_set_callback(subreq, cli_negprot_done, req);
2623 return req;
2626 static void cli_negprot_done(struct tevent_req *subreq)
2628 struct tevent_req *req = tevent_req_callback_data(
2629 subreq, struct tevent_req);
2630 struct cli_negprot_state *state = tevent_req_data(
2631 req, struct cli_negprot_state);
2632 struct cli_state *cli = state->cli;
2633 uint8_t wct;
2634 uint16_t *vwv;
2635 uint32_t num_bytes;
2636 uint8_t *bytes;
2637 NTSTATUS status;
2638 uint16_t protnum;
2639 uint8_t *inbuf;
2641 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2642 &num_bytes, &bytes);
2643 TALLOC_FREE(subreq);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 tevent_req_nterror(req, status);
2646 return;
2649 protnum = SVAL(vwv, 0);
2651 if ((protnum >= ARRAY_SIZE(prots))
2652 || (prots[protnum].prot > cli->protocol)) {
2653 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2654 return;
2657 cli->protocol = prots[protnum].prot;
2659 if ((cli->protocol < PROTOCOL_NT1) &&
2660 client_is_signing_mandatory(cli)) {
2661 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2662 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2663 return;
2666 if (cli->protocol >= PROTOCOL_NT1) {
2667 struct timespec ts;
2668 bool negotiated_smb_signing = false;
2670 /* NT protocol */
2671 cli->sec_mode = CVAL(vwv + 1, 0);
2672 cli->max_mux = SVAL(vwv + 1, 1);
2673 cli->max_xmit = IVAL(vwv + 3, 1);
2674 cli->sesskey = IVAL(vwv + 7, 1);
2675 cli->serverzone = SVALS(vwv + 15, 1);
2676 cli->serverzone *= 60;
2677 /* this time arrives in real GMT */
2678 ts = interpret_long_date(((char *)(vwv+11))+1);
2679 cli->servertime = ts.tv_sec;
2680 cli->secblob = data_blob(bytes, num_bytes);
2681 cli->capabilities = IVAL(vwv + 9, 1);
2682 if (cli->capabilities & CAP_RAW_MODE) {
2683 cli->readbraw_supported = True;
2684 cli->writebraw_supported = True;
2686 /* work out if they sent us a workgroup */
2687 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2688 smb_buflen(inbuf) > 8) {
2689 ssize_t ret;
2690 status = smb_bytes_talloc_string(
2691 cli, (char *)inbuf, &cli->server_domain,
2692 bytes + 8, num_bytes - 8, &ret);
2693 if (tevent_req_nterror(req, status)) {
2694 return;
2699 * As signing is slow we only turn it on if either the client or
2700 * the server require it. JRA.
2703 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2704 /* Fail if server says signing is mandatory and we don't want to support it. */
2705 if (!client_is_signing_allowed(cli)) {
2706 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2707 tevent_req_nterror(req,
2708 NT_STATUS_ACCESS_DENIED);
2709 return;
2711 negotiated_smb_signing = true;
2712 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2713 /* Fail if client says signing is mandatory and the server doesn't support it. */
2714 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2715 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2716 tevent_req_nterror(req,
2717 NT_STATUS_ACCESS_DENIED);
2718 return;
2720 negotiated_smb_signing = true;
2721 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2722 negotiated_smb_signing = true;
2725 if (negotiated_smb_signing) {
2726 cli_set_signing_negotiated(cli);
2729 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2730 SAFE_FREE(cli->outbuf);
2731 SAFE_FREE(cli->inbuf);
2732 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2733 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2734 if (!cli->outbuf || !cli->inbuf) {
2735 tevent_req_nterror(req,
2736 NT_STATUS_NO_MEMORY);
2737 return;
2739 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2742 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2743 cli->use_spnego = False;
2744 cli->sec_mode = SVAL(vwv + 1, 0);
2745 cli->max_xmit = SVAL(vwv + 2, 0);
2746 cli->max_mux = SVAL(vwv + 3, 0);
2747 cli->sesskey = IVAL(vwv + 6, 0);
2748 cli->serverzone = SVALS(vwv + 10, 0);
2749 cli->serverzone *= 60;
2750 /* this time is converted to GMT by make_unix_date */
2751 cli->servertime = make_unix_date(
2752 (char *)(vwv + 8), cli->serverzone);
2753 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2754 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2755 cli->secblob = data_blob(bytes, num_bytes);
2756 } else {
2757 /* the old core protocol */
2758 cli->use_spnego = False;
2759 cli->sec_mode = 0;
2760 cli->serverzone = get_time_zone(time(NULL));
2763 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2765 /* a way to force ascii SMB */
2766 if (getenv("CLI_FORCE_ASCII"))
2767 cli->capabilities &= ~CAP_UNICODE;
2769 tevent_req_done(req);
2772 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2774 return tevent_req_simple_recv_ntstatus(req);
2777 NTSTATUS cli_negprot(struct cli_state *cli)
2779 TALLOC_CTX *frame = talloc_stackframe();
2780 struct event_context *ev;
2781 struct tevent_req *req;
2782 NTSTATUS status = NT_STATUS_OK;
2784 if (cli_has_async_calls(cli)) {
2786 * Can't use sync call while an async call is in flight
2788 status = NT_STATUS_INVALID_PARAMETER;
2789 goto fail;
2792 ev = event_context_init(frame);
2793 if (ev == NULL) {
2794 status = NT_STATUS_NO_MEMORY;
2795 goto fail;
2798 req = cli_negprot_send(frame, ev, cli);
2799 if (req == NULL) {
2800 status = NT_STATUS_NO_MEMORY;
2801 goto fail;
2804 if (!tevent_req_poll(req, ev)) {
2805 status = map_nt_error_from_unix(errno);
2806 goto fail;
2809 status = cli_negprot_recv(req);
2810 fail:
2811 TALLOC_FREE(frame);
2812 if (!NT_STATUS_IS_OK(status)) {
2813 cli_set_error(cli, status);
2815 return status;
2818 /****************************************************************************
2819 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2820 ****************************************************************************/
2822 bool cli_session_request(struct cli_state *cli,
2823 struct nmb_name *calling, struct nmb_name *called)
2825 char *p;
2826 int len = 4;
2827 int namelen = 0;
2828 char *tmp;
2830 /* 445 doesn't have session request */
2831 if (cli->port == 445)
2832 return True;
2834 memcpy(&(cli->calling), calling, sizeof(*calling));
2835 memcpy(&(cli->called ), called , sizeof(*called ));
2837 /* put in the destination name */
2839 tmp = name_mangle(talloc_tos(), cli->called.name,
2840 cli->called.name_type);
2841 if (tmp == NULL) {
2842 return false;
2845 p = cli->outbuf+len;
2846 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2847 if (namelen > 0) {
2848 memcpy(p, tmp, namelen);
2849 len += namelen;
2851 TALLOC_FREE(tmp);
2853 /* and my name */
2855 tmp = name_mangle(talloc_tos(), cli->calling.name,
2856 cli->calling.name_type);
2857 if (tmp == NULL) {
2858 return false;
2861 p = cli->outbuf+len;
2862 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2863 if (namelen > 0) {
2864 memcpy(p, tmp, namelen);
2865 len += namelen;
2867 TALLOC_FREE(tmp);
2869 /* send a session request (RFC 1002) */
2870 /* setup the packet length
2871 * Remove four bytes from the length count, since the length
2872 * field in the NBT Session Service header counts the number
2873 * of bytes which follow. The cli_send_smb() function knows
2874 * about this and accounts for those four bytes.
2875 * CRH.
2877 len -= 4;
2878 _smb_setlen(cli->outbuf,len);
2879 SCVAL(cli->outbuf,0,0x81);
2881 cli_send_smb(cli);
2882 DEBUG(5,("Sent session request\n"));
2884 if (!cli_receive_smb(cli))
2885 return False;
2887 if (CVAL(cli->inbuf,0) == 0x84) {
2888 /* C. Hoch 9/14/95 Start */
2889 /* For information, here is the response structure.
2890 * We do the byte-twiddling to for portability.
2891 struct RetargetResponse{
2892 unsigned char type;
2893 unsigned char flags;
2894 int16 length;
2895 int32 ip_addr;
2896 int16 port;
2899 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2900 struct in_addr dest_ip;
2901 NTSTATUS status;
2903 /* SESSION RETARGET */
2904 putip((char *)&dest_ip,cli->inbuf+4);
2905 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2907 status = open_socket_out(&cli->dest_ss, port,
2908 LONG_CONNECT_TIMEOUT, &cli->fd);
2909 if (!NT_STATUS_IS_OK(status)) {
2910 return False;
2913 DEBUG(3,("Retargeted\n"));
2915 set_socket_options(cli->fd, lp_socket_options());
2917 /* Try again */
2919 static int depth;
2920 bool ret;
2921 if (depth > 4) {
2922 DEBUG(0,("Retarget recursion - failing\n"));
2923 return False;
2925 depth++;
2926 ret = cli_session_request(cli, calling, called);
2927 depth--;
2928 return ret;
2930 } /* C. Hoch 9/14/95 End */
2932 if (CVAL(cli->inbuf,0) != 0x82) {
2933 /* This is the wrong place to put the error... JRA. */
2934 cli->rap_error = CVAL(cli->inbuf,4);
2935 return False;
2937 return(True);
2940 struct fd_struct {
2941 int fd;
2944 static void smb_sock_connected(struct tevent_req *req)
2946 struct fd_struct *pfd = tevent_req_callback_data(
2947 req, struct fd_struct);
2948 int fd;
2949 NTSTATUS status;
2951 status = open_socket_out_defer_recv(req, &fd);
2952 if (NT_STATUS_IS_OK(status)) {
2953 pfd->fd = fd;
2957 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2958 uint16_t *port, int timeout, int *pfd)
2960 struct event_context *ev;
2961 struct tevent_req *r139, *r445;
2962 struct fd_struct *fd139, *fd445;
2963 NTSTATUS status = NT_STATUS_NO_MEMORY;
2965 if (*port != 0) {
2966 return open_socket_out(pss, *port, timeout, pfd);
2969 ev = event_context_init(talloc_tos());
2970 if (ev == NULL) {
2971 return NT_STATUS_NO_MEMORY;
2974 fd139 = talloc(ev, struct fd_struct);
2975 if (fd139 == NULL) {
2976 goto done;
2978 fd139->fd = -1;
2980 fd445 = talloc(ev, struct fd_struct);
2981 if (fd445 == NULL) {
2982 goto done;
2984 fd445->fd = -1;
2986 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2987 pss, 445, timeout);
2988 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2989 pss, 139, timeout);
2990 if ((r445 == NULL) || (r139 == NULL)) {
2991 goto done;
2993 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2994 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2996 while ((fd445->fd == -1) && (fd139->fd == -1)
2997 && (tevent_req_is_in_progress(r139)
2998 || tevent_req_is_in_progress(r445))) {
2999 event_loop_once(ev);
3002 if ((fd139->fd != -1) && (fd445->fd != -1)) {
3003 close(fd139->fd);
3004 fd139->fd = -1;
3007 if (fd445->fd != -1) {
3008 *port = 445;
3009 *pfd = fd445->fd;
3010 status = NT_STATUS_OK;
3011 goto done;
3013 if (fd139->fd != -1) {
3014 *port = 139;
3015 *pfd = fd139->fd;
3016 status = NT_STATUS_OK;
3017 goto done;
3020 status = open_socket_out_defer_recv(r445, &fd445->fd);
3021 done:
3022 TALLOC_FREE(ev);
3023 return status;
3026 /****************************************************************************
3027 Open the client sockets.
3028 ****************************************************************************/
3030 NTSTATUS cli_connect(struct cli_state *cli,
3031 const char *host,
3032 struct sockaddr_storage *dest_ss)
3035 int name_type = 0x20;
3036 TALLOC_CTX *frame = talloc_stackframe();
3037 unsigned int num_addrs = 0;
3038 unsigned int i = 0;
3039 struct sockaddr_storage *ss_arr = NULL;
3040 char *p = NULL;
3042 /* reasonable default hostname */
3043 if (!host) {
3044 host = STAR_SMBSERVER;
3047 cli->desthost = talloc_strdup(cli, host);
3048 if (cli->desthost == NULL) {
3049 return NT_STATUS_NO_MEMORY;
3052 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3053 if ((p = strchr(cli->desthost, '#'))) {
3054 name_type = strtol(p+1, NULL, 16);
3055 *p = 0;
3058 if (!dest_ss || is_zero_addr(dest_ss)) {
3059 NTSTATUS status =resolve_name_list(frame,
3060 cli->desthost,
3061 name_type,
3062 &ss_arr,
3063 &num_addrs);
3064 if (!NT_STATUS_IS_OK(status)) {
3065 TALLOC_FREE(frame);
3066 return NT_STATUS_BAD_NETWORK_NAME;
3068 } else {
3069 num_addrs = 1;
3070 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
3071 if (!ss_arr) {
3072 TALLOC_FREE(frame);
3073 return NT_STATUS_NO_MEMORY;
3075 *ss_arr = *dest_ss;
3078 for (i = 0; i < num_addrs; i++) {
3079 cli->dest_ss = ss_arr[i];
3080 if (getenv("LIBSMB_PROG")) {
3081 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
3082 } else {
3083 uint16_t port = cli->port;
3084 NTSTATUS status;
3085 status = open_smb_socket(&cli->dest_ss, &port,
3086 cli->timeout, &cli->fd);
3087 if (NT_STATUS_IS_OK(status)) {
3088 cli->port = port;
3091 if (cli->fd == -1) {
3092 char addr[INET6_ADDRSTRLEN];
3093 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
3094 DEBUG(2,("Error connecting to %s (%s)\n",
3095 dest_ss?addr:host,strerror(errno)));
3096 } else {
3097 /* Exit from loop on first connection. */
3098 break;
3102 if (cli->fd == -1) {
3103 TALLOC_FREE(frame);
3104 return map_nt_error_from_unix(errno);
3107 if (dest_ss) {
3108 *dest_ss = cli->dest_ss;
3111 set_socket_options(cli->fd, lp_socket_options());
3113 TALLOC_FREE(frame);
3114 return NT_STATUS_OK;
3118 establishes a connection to after the negprot.
3119 @param output_cli A fully initialised cli structure, non-null only on success
3120 @param dest_host The netbios name of the remote host
3121 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3122 @param port (optional) The destination port (0 for default)
3124 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3125 const char *my_name,
3126 const char *dest_host,
3127 struct sockaddr_storage *dest_ss, int port,
3128 int signing_state, int flags)
3130 NTSTATUS nt_status;
3131 struct nmb_name calling;
3132 struct nmb_name called;
3133 struct cli_state *cli;
3134 struct sockaddr_storage ss;
3136 if (!my_name)
3137 my_name = global_myname();
3139 if (!(cli = cli_initialise_ex(signing_state))) {
3140 return NT_STATUS_NO_MEMORY;
3143 make_nmb_name(&calling, my_name, 0x0);
3144 make_nmb_name(&called , dest_host, 0x20);
3146 cli_set_port(cli, port);
3147 cli_set_timeout(cli, 10000); /* 10 seconds. */
3149 if (dest_ss) {
3150 ss = *dest_ss;
3151 } else {
3152 zero_sockaddr(&ss);
3155 again:
3157 DEBUG(3,("Connecting to host=%s\n", dest_host));
3159 nt_status = cli_connect(cli, dest_host, &ss);
3160 if (!NT_STATUS_IS_OK(nt_status)) {
3161 char addr[INET6_ADDRSTRLEN];
3162 print_sockaddr(addr, sizeof(addr), &ss);
3163 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3164 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
3165 cli_shutdown(cli);
3166 return nt_status;
3169 if (!cli_session_request(cli, &calling, &called)) {
3170 char *p;
3171 DEBUG(1,("session request to %s failed (%s)\n",
3172 called.name, cli_errstr(cli)));
3173 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
3174 *p = 0;
3175 goto again;
3177 if (strcmp(called.name, STAR_SMBSERVER)) {
3178 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
3179 goto again;
3181 return NT_STATUS_BAD_NETWORK_NAME;
3184 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
3185 cli->use_spnego = False;
3186 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
3187 cli->use_kerberos = True;
3189 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
3190 cli->use_kerberos) {
3191 cli->fallback_after_kerberos = true;
3193 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3194 cli->use_ccache = true;
3197 nt_status = cli_negprot(cli);
3198 if (!NT_STATUS_IS_OK(nt_status)) {
3199 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3200 cli_shutdown(cli);
3201 return nt_status;
3204 *output_cli = cli;
3205 return NT_STATUS_OK;
3210 establishes a connection right up to doing tconX, password specified.
3211 @param output_cli A fully initialised cli structure, non-null only on success
3212 @param dest_host The netbios name of the remote host
3213 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3214 @param port (optional) The destination port (0 for default)
3215 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3216 @param service_type The 'type' of serivice.
3217 @param user Username, unix string
3218 @param domain User's domain
3219 @param password User's password, unencrypted unix string.
3222 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3223 const char *my_name,
3224 const char *dest_host,
3225 struct sockaddr_storage *dest_ss, int port,
3226 const char *service, const char *service_type,
3227 const char *user, const char *domain,
3228 const char *password, int flags,
3229 int signing_state)
3231 NTSTATUS nt_status;
3232 struct cli_state *cli = NULL;
3233 int pw_len = password ? strlen(password)+1 : 0;
3235 *output_cli = NULL;
3237 if (password == NULL) {
3238 password = "";
3241 nt_status = cli_start_connection(&cli, my_name, dest_host,
3242 dest_ss, port, signing_state,
3243 flags);
3245 if (!NT_STATUS_IS_OK(nt_status)) {
3246 return nt_status;
3249 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3250 cli->use_level_II_oplocks =
3251 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3253 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3254 pw_len, domain);
3255 if (!NT_STATUS_IS_OK(nt_status)) {
3257 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3258 DEBUG(1,("failed session setup with %s\n",
3259 nt_errstr(nt_status)));
3260 cli_shutdown(cli);
3261 return nt_status;
3264 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3265 if (!NT_STATUS_IS_OK(nt_status)) {
3266 DEBUG(1,("anonymous failed session setup with %s\n",
3267 nt_errstr(nt_status)));
3268 cli_shutdown(cli);
3269 return nt_status;
3273 if (service) {
3274 nt_status = cli_tcon_andx(cli, service, service_type, password,
3275 pw_len);
3276 if (!NT_STATUS_IS_OK(nt_status)) {
3277 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3278 cli_shutdown(cli);
3279 if (NT_STATUS_IS_OK(nt_status)) {
3280 nt_status = NT_STATUS_UNSUCCESSFUL;
3282 return nt_status;
3286 nt_status = cli_init_creds(cli, user, domain, password);
3287 if (!NT_STATUS_IS_OK(nt_status)) {
3288 cli_shutdown(cli);
3289 return nt_status;
3292 *output_cli = cli;
3293 return NT_STATUS_OK;
3296 /****************************************************************************
3297 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3298 ****************************************************************************/
3300 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
3301 struct sockaddr_storage *pdest_ss)
3303 struct nmb_name calling, called;
3305 make_nmb_name(&calling, srchost, 0x0);
3308 * If the called name is an IP address
3309 * then use *SMBSERVER immediately.
3312 if(is_ipaddress(desthost)) {
3313 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
3314 } else {
3315 make_nmb_name(&called, desthost, 0x20);
3318 if (!cli_session_request(*ppcli, &calling, &called)) {
3319 NTSTATUS status;
3320 struct nmb_name smbservername;
3322 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
3325 * If the name wasn't *SMBSERVER then
3326 * try with *SMBSERVER if the first name fails.
3329 if (nmb_name_equal(&called, &smbservername)) {
3332 * The name used was *SMBSERVER, don't bother with another name.
3335 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3336 with error %s.\n", desthost, cli_errstr(*ppcli) ));
3337 return False;
3340 /* Try again... */
3341 cli_shutdown(*ppcli);
3343 *ppcli = cli_initialise();
3344 if (!*ppcli) {
3345 /* Out of memory... */
3346 return False;
3349 status = cli_connect(*ppcli, desthost, pdest_ss);
3350 if (!NT_STATUS_IS_OK(status) ||
3351 !cli_session_request(*ppcli, &calling, &smbservername)) {
3352 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3353 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
3354 return False;
3358 return True;
3361 /****************************************************************************
3362 Send an old style tcon.
3363 ****************************************************************************/
3364 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3365 const char *service, const char *pass, const char *dev,
3366 uint16 *max_xmit, uint16 *tid)
3368 struct tevent_req *req;
3369 uint16_t *ret_vwv;
3370 uint8_t *bytes;
3371 NTSTATUS status;
3373 if (!lp_client_plaintext_auth() && (*pass)) {
3374 DEBUG(1, ("Server requested plaintext password but 'client "
3375 "plaintext auth' is disabled\n"));
3376 return NT_STATUS_ACCESS_DENIED;
3379 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3380 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3381 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3382 service, strlen(service)+1, NULL);
3383 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3384 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3385 pass, strlen(pass)+1, NULL);
3386 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3387 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3388 dev, strlen(dev)+1, NULL);
3390 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3391 talloc_get_size(bytes), bytes, &req,
3392 2, NULL, &ret_vwv, NULL, NULL);
3393 if (!NT_STATUS_IS_OK(status)) {
3394 return status;
3397 *max_xmit = SVAL(ret_vwv + 0, 0);
3398 *tid = SVAL(ret_vwv + 1, 0);
3400 return NT_STATUS_OK;
3403 /* Return a cli_state pointing at the IPC$ share for the given server */
3405 struct cli_state *get_ipc_connect(char *server,
3406 struct sockaddr_storage *server_ss,
3407 const struct user_auth_info *user_info)
3409 struct cli_state *cli;
3410 NTSTATUS nt_status;
3411 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3413 if (user_info->use_kerberos) {
3414 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3417 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3418 user_info->username ? user_info->username : "",
3419 lp_workgroup(),
3420 user_info->password ? user_info->password : "",
3421 flags,
3422 Undefined);
3424 if (NT_STATUS_IS_OK(nt_status)) {
3425 return cli;
3426 } else if (is_ipaddress(server)) {
3427 /* windows 9* needs a correct NMB name for connections */
3428 fstring remote_name;
3430 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3431 cli = get_ipc_connect(remote_name, server_ss, user_info);
3432 if (cli)
3433 return cli;
3436 return NULL;
3440 * Given the IP address of a master browser on the network, return its
3441 * workgroup and connect to it.
3443 * This function is provided to allow additional processing beyond what
3444 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3445 * browsers and obtain each master browsers' list of domains (in case the
3446 * first master browser is recently on the network and has not yet
3447 * synchronized with other master browsers and therefore does not yet have the
3448 * entire network browse list)
3451 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3452 struct sockaddr_storage *mb_ip,
3453 const struct user_auth_info *user_info,
3454 char **pp_workgroup_out)
3456 char addr[INET6_ADDRSTRLEN];
3457 fstring name;
3458 struct cli_state *cli;
3459 struct sockaddr_storage server_ss;
3461 *pp_workgroup_out = NULL;
3463 print_sockaddr(addr, sizeof(addr), mb_ip);
3464 DEBUG(99, ("Looking up name of master browser %s\n",
3465 addr));
3468 * Do a name status query to find out the name of the master browser.
3469 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3470 * master browser will not respond to a wildcard query (or, at least,
3471 * an NT4 server acting as the domain master browser will not).
3473 * We might be able to use ONLY the query on MSBROWSE, but that's not
3474 * yet been tested with all Windows versions, so until it is, leave
3475 * the original wildcard query as the first choice and fall back to
3476 * MSBROWSE if the wildcard query fails.
3478 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3479 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3481 DEBUG(99, ("Could not retrieve name status for %s\n",
3482 addr));
3483 return NULL;
3486 if (!find_master_ip(name, &server_ss)) {
3487 DEBUG(99, ("Could not find master ip for %s\n", name));
3488 return NULL;
3491 *pp_workgroup_out = talloc_strdup(ctx, name);
3493 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3495 print_sockaddr(addr, sizeof(addr), &server_ss);
3496 cli = get_ipc_connect(addr, &server_ss, user_info);
3498 return cli;
3502 * Return the IP address and workgroup of a master browser on the network, and
3503 * connect to it.
3506 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3507 const struct user_auth_info *user_info,
3508 char **pp_workgroup_out)
3510 struct sockaddr_storage *ip_list;
3511 struct cli_state *cli;
3512 int i, count;
3513 NTSTATUS status;
3515 *pp_workgroup_out = NULL;
3517 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3519 /* Go looking for workgroups by broadcasting on the local network */
3521 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3522 &ip_list, &count);
3523 if (!NT_STATUS_IS_OK(status)) {
3524 DEBUG(99, ("No master browsers responded: %s\n",
3525 nt_errstr(status)));
3526 return False;
3529 for (i = 0; i < count; i++) {
3530 char addr[INET6_ADDRSTRLEN];
3531 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3532 DEBUG(99, ("Found master browser %s\n", addr));
3534 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3535 user_info, pp_workgroup_out);
3536 if (cli)
3537 return(cli);
3540 return NULL;