s3: Fix a leftover from fstring removal in cli_state
[Samba.git] / source3 / libsmb / cliconnect.c
blob9cebab734eb8c4396db52428676b0380a119fcc2
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;
263 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
264 &num_bytes, &bytes);
265 TALLOC_FREE(subreq);
266 if (!NT_STATUS_IS_OK(status)) {
267 tevent_req_nterror(req, status);
268 return;
271 inbuf = (char *)in;
272 p = bytes;
274 cli->vuid = SVAL(inbuf, smb_uid);
276 status = smb_bytes_talloc_string(cli,
277 inbuf,
278 &cli->server_os,
280 bytes+num_bytes-p,
281 &ret);
283 if (!NT_STATUS_IS_OK(status)) {
284 tevent_req_nterror(req, status);
285 return;
287 p += ret;
289 status = smb_bytes_talloc_string(cli,
290 inbuf,
291 &cli->server_type,
293 bytes+num_bytes-p,
294 &ret);
296 if (!NT_STATUS_IS_OK(status)) {
297 tevent_req_nterror(req, status);
298 return;
300 p += ret;
302 status = smb_bytes_talloc_string(cli,
303 inbuf,
304 &cli->server_domain,
306 bytes+num_bytes-p,
307 &ret);
309 if (!NT_STATUS_IS_OK(status)) {
310 tevent_req_nterror(req, status);
311 return;
313 p += ret;
315 if (strstr(cli->server_type, "Samba")) {
316 cli->is_samba = True;
318 status = cli_set_username(cli, state->user);
319 if (tevent_req_nterror(req, status)) {
320 return;
322 tevent_req_done(req);
325 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
327 return tevent_req_simple_recv_ntstatus(req);
330 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
331 const char *pass, size_t passlen,
332 const char *workgroup)
334 TALLOC_CTX *frame = talloc_stackframe();
335 struct event_context *ev;
336 struct tevent_req *req;
337 NTSTATUS status = NT_STATUS_NO_MEMORY;
339 if (cli_has_async_calls(cli)) {
341 * Can't use sync call while an async call is in flight
343 status = NT_STATUS_INVALID_PARAMETER;
344 goto fail;
346 ev = event_context_init(frame);
347 if (ev == NULL) {
348 goto fail;
350 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
351 workgroup);
352 if (req == NULL) {
353 goto fail;
355 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
356 goto fail;
358 status = cli_session_setup_lanman2_recv(req);
359 fail:
360 TALLOC_FREE(frame);
361 if (!NT_STATUS_IS_OK(status)) {
362 cli_set_error(cli, status);
364 return status;
367 /****************************************************************************
368 Work out suitable capabilities to offer the server.
369 ****************************************************************************/
371 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
373 uint32 capabilities = CAP_NT_SMBS;
375 if (!cli->force_dos_errors)
376 capabilities |= CAP_STATUS32;
378 if (cli->use_level_II_oplocks)
379 capabilities |= CAP_LEVEL_II_OPLOCKS;
381 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
382 return capabilities;
385 /****************************************************************************
386 Do a NT1 guest session setup.
387 ****************************************************************************/
389 struct cli_session_setup_guest_state {
390 struct cli_state *cli;
391 uint16_t vwv[13];
392 struct iovec bytes;
395 static void cli_session_setup_guest_done(struct tevent_req *subreq);
397 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
398 struct event_context *ev,
399 struct cli_state *cli,
400 struct tevent_req **psmbreq)
402 struct tevent_req *req, *subreq;
403 struct cli_session_setup_guest_state *state;
404 uint16_t *vwv;
405 uint8_t *bytes;
407 req = tevent_req_create(mem_ctx, &state,
408 struct cli_session_setup_guest_state);
409 if (req == NULL) {
410 return NULL;
412 state->cli = cli;
413 vwv = state->vwv;
415 SCVAL(vwv+0, 0, 0xFF);
416 SCVAL(vwv+0, 1, 0);
417 SSVAL(vwv+1, 0, 0);
418 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
419 SSVAL(vwv+3, 0, 2);
420 SSVAL(vwv+4, 0, cli->pid);
421 SIVAL(vwv+5, 0, cli->sesskey);
422 SSVAL(vwv+7, 0, 0);
423 SSVAL(vwv+8, 0, 0);
424 SSVAL(vwv+9, 0, 0);
425 SSVAL(vwv+10, 0, 0);
426 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
428 bytes = talloc_array(state, uint8_t, 0);
430 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
431 NULL);
432 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
433 NULL);
434 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
435 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
437 if (bytes == NULL) {
438 TALLOC_FREE(req);
439 return NULL;
442 state->bytes.iov_base = (void *)bytes;
443 state->bytes.iov_len = talloc_get_size(bytes);
445 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
446 1, &state->bytes);
447 if (subreq == NULL) {
448 TALLOC_FREE(req);
449 return NULL;
451 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
452 *psmbreq = subreq;
453 return req;
456 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
457 struct event_context *ev,
458 struct cli_state *cli)
460 struct tevent_req *req, *subreq;
461 NTSTATUS status;
463 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
464 if (req == NULL) {
465 return NULL;
468 status = cli_smb_req_send(subreq);
469 if (NT_STATUS_IS_OK(status)) {
470 tevent_req_nterror(req, status);
471 return tevent_req_post(req, ev);
473 return req;
476 static void cli_session_setup_guest_done(struct tevent_req *subreq)
478 struct tevent_req *req = tevent_req_callback_data(
479 subreq, struct tevent_req);
480 struct cli_session_setup_guest_state *state = tevent_req_data(
481 req, struct cli_session_setup_guest_state);
482 struct cli_state *cli = state->cli;
483 uint32_t num_bytes;
484 uint8_t *in;
485 char *inbuf;
486 uint8_t *bytes;
487 uint8_t *p;
488 NTSTATUS status;
489 ssize_t ret;
491 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
492 &num_bytes, &bytes);
493 TALLOC_FREE(subreq);
494 if (!NT_STATUS_IS_OK(status)) {
495 tevent_req_nterror(req, status);
496 return;
499 inbuf = (char *)in;
500 p = bytes;
502 cli->vuid = SVAL(inbuf, smb_uid);
504 status = smb_bytes_talloc_string(cli,
505 inbuf,
506 &cli->server_os,
508 bytes+num_bytes-p,
509 &ret);
511 if (!NT_STATUS_IS_OK(status)) {
512 tevent_req_nterror(req, status);
513 return;
515 p += ret;
517 status = smb_bytes_talloc_string(cli,
518 inbuf,
519 &cli->server_type,
521 bytes+num_bytes-p,
522 &ret);
524 if (!NT_STATUS_IS_OK(status)) {
525 tevent_req_nterror(req, status);
526 return;
528 p += ret;
530 status = smb_bytes_talloc_string(cli,
531 inbuf,
532 &cli->server_domain,
534 bytes+num_bytes-p,
535 &ret);
537 if (!NT_STATUS_IS_OK(status)) {
538 tevent_req_nterror(req, status);
539 return;
541 p += ret;
543 if (strstr(cli->server_type, "Samba")) {
544 cli->is_samba = True;
547 status = cli_set_username(cli, "");
548 if (!NT_STATUS_IS_OK(status)) {
549 tevent_req_nterror(req, status);
550 return;
552 tevent_req_done(req);
555 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
557 return tevent_req_simple_recv_ntstatus(req);
560 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
562 TALLOC_CTX *frame = talloc_stackframe();
563 struct event_context *ev;
564 struct tevent_req *req;
565 NTSTATUS status = NT_STATUS_OK;
567 if (cli_has_async_calls(cli)) {
569 * Can't use sync call while an async call is in flight
571 status = NT_STATUS_INVALID_PARAMETER;
572 goto fail;
575 ev = event_context_init(frame);
576 if (ev == NULL) {
577 status = NT_STATUS_NO_MEMORY;
578 goto fail;
581 req = cli_session_setup_guest_send(frame, ev, cli);
582 if (req == NULL) {
583 status = NT_STATUS_NO_MEMORY;
584 goto fail;
587 if (!tevent_req_poll(req, ev)) {
588 status = map_nt_error_from_unix(errno);
589 goto fail;
592 status = cli_session_setup_guest_recv(req);
593 fail:
594 TALLOC_FREE(frame);
595 if (!NT_STATUS_IS_OK(status)) {
596 cli_set_error(cli, status);
598 return status;
601 /****************************************************************************
602 Do a NT1 plaintext session setup.
603 ****************************************************************************/
605 struct cli_session_setup_plain_state {
606 struct cli_state *cli;
607 uint16_t vwv[13];
608 const char *user;
611 static void cli_session_setup_plain_done(struct tevent_req *subreq);
613 static struct tevent_req *cli_session_setup_plain_send(
614 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
615 struct cli_state *cli,
616 const char *user, const char *pass, const char *workgroup)
618 struct tevent_req *req, *subreq;
619 struct cli_session_setup_plain_state *state;
620 uint16_t *vwv;
621 uint8_t *bytes;
622 size_t passlen;
623 char *version;
625 req = tevent_req_create(mem_ctx, &state,
626 struct cli_session_setup_plain_state);
627 if (req == NULL) {
628 return NULL;
630 state->cli = cli;
631 state->user = user;
632 vwv = state->vwv;
634 SCVAL(vwv+0, 0, 0xff);
635 SCVAL(vwv+0, 1, 0);
636 SSVAL(vwv+1, 0, 0);
637 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
638 SSVAL(vwv+3, 0, 2);
639 SSVAL(vwv+4, 0, cli->pid);
640 SIVAL(vwv+5, 0, cli->sesskey);
641 SSVAL(vwv+7, 0, 0);
642 SSVAL(vwv+8, 0, 0);
643 SSVAL(vwv+9, 0, 0);
644 SSVAL(vwv+10, 0, 0);
645 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
647 bytes = talloc_array(state, uint8_t, 0);
648 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
649 &passlen);
650 if (tevent_req_nomem(bytes, req)) {
651 return tevent_req_post(req, ev);
653 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
655 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
656 user, strlen(user)+1, NULL);
657 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
658 workgroup, strlen(workgroup)+1, NULL);
659 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
660 "Unix", 5, NULL);
662 version = talloc_asprintf(talloc_tos(), "Samba %s",
663 samba_version_string());
664 if (tevent_req_nomem(version, req)){
665 return tevent_req_post(req, ev);
667 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
668 version, strlen(version)+1, NULL);
669 TALLOC_FREE(version);
671 if (tevent_req_nomem(bytes, req)) {
672 return tevent_req_post(req, ev);
675 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
676 talloc_get_size(bytes), bytes);
677 if (tevent_req_nomem(subreq, req)) {
678 return tevent_req_post(req, ev);
680 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
681 return req;
684 static void cli_session_setup_plain_done(struct tevent_req *subreq)
686 struct tevent_req *req = tevent_req_callback_data(
687 subreq, struct tevent_req);
688 struct cli_session_setup_plain_state *state = tevent_req_data(
689 req, struct cli_session_setup_plain_state);
690 struct cli_state *cli = state->cli;
691 uint32_t num_bytes;
692 uint8_t *in;
693 char *inbuf;
694 uint8_t *bytes;
695 uint8_t *p;
696 NTSTATUS status;
697 ssize_t ret;
699 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
700 &num_bytes, &bytes);
701 TALLOC_FREE(subreq);
702 if (tevent_req_nterror(req, status)) {
703 return;
706 inbuf = (char *)in;
707 p = bytes;
709 cli->vuid = SVAL(inbuf, smb_uid);
711 status = smb_bytes_talloc_string(cli,
712 inbuf,
713 &cli->server_os,
715 bytes+num_bytes-p,
716 &ret);
718 if (!NT_STATUS_IS_OK(status)) {
719 tevent_req_nterror(req, status);
720 return;
722 p += ret;
724 status = smb_bytes_talloc_string(cli,
725 inbuf,
726 &cli->server_type,
728 bytes+num_bytes-p,
729 &ret);
731 if (!NT_STATUS_IS_OK(status)) {
732 tevent_req_nterror(req, status);
733 return;
735 p += ret;
737 status = smb_bytes_talloc_string(cli,
738 inbuf,
739 &cli->server_domain,
741 bytes+num_bytes-p,
742 &ret);
744 if (!NT_STATUS_IS_OK(status)) {
745 tevent_req_nterror(req, status);
746 return;
748 p += ret;
750 status = cli_set_username(cli, state->user);
751 if (tevent_req_nterror(req, status)) {
752 return;
754 if (strstr(cli->server_type, "Samba")) {
755 cli->is_samba = True;
757 tevent_req_done(req);
760 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
762 return tevent_req_simple_recv_ntstatus(req);
765 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
766 const char *user, const char *pass,
767 const char *workgroup)
769 TALLOC_CTX *frame = talloc_stackframe();
770 struct event_context *ev;
771 struct tevent_req *req;
772 NTSTATUS status = NT_STATUS_NO_MEMORY;
774 if (cli_has_async_calls(cli)) {
776 * Can't use sync call while an async call is in flight
778 status = NT_STATUS_INVALID_PARAMETER;
779 goto fail;
781 ev = event_context_init(frame);
782 if (ev == NULL) {
783 goto fail;
785 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
786 workgroup);
787 if (req == NULL) {
788 goto fail;
790 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
791 goto fail;
793 status = cli_session_setup_plain_recv(req);
794 fail:
795 TALLOC_FREE(frame);
796 if (!NT_STATUS_IS_OK(status)) {
797 cli_set_error(cli, status);
799 return status;
802 /****************************************************************************
803 do a NT1 NTLM/LM encrypted session setup - for when extended security
804 is not negotiated.
805 @param cli client state to create do session setup on
806 @param user username
807 @param pass *either* cleartext password (passlen !=24) or LM response.
808 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
809 @param workgroup The user's domain.
810 ****************************************************************************/
812 struct cli_session_setup_nt1_state {
813 struct cli_state *cli;
814 uint16_t vwv[13];
815 DATA_BLOB response;
816 DATA_BLOB session_key;
817 const char *user;
820 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
822 static struct tevent_req *cli_session_setup_nt1_send(
823 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
824 struct cli_state *cli, const char *user,
825 const char *pass, size_t passlen,
826 const char *ntpass, size_t ntpasslen,
827 const char *workgroup)
829 struct tevent_req *req, *subreq;
830 struct cli_session_setup_nt1_state *state;
831 DATA_BLOB lm_response = data_blob_null;
832 DATA_BLOB nt_response = data_blob_null;
833 DATA_BLOB session_key = data_blob_null;
834 uint16_t *vwv;
835 uint8_t *bytes;
836 char *workgroup_upper;
838 req = tevent_req_create(mem_ctx, &state,
839 struct cli_session_setup_nt1_state);
840 if (req == NULL) {
841 return NULL;
843 state->cli = cli;
844 state->user = user;
845 vwv = state->vwv;
847 if (passlen == 0) {
848 /* do nothing - guest login */
849 } else if (passlen != 24) {
850 if (lp_client_ntlmv2_auth()) {
851 DATA_BLOB server_chal;
852 DATA_BLOB names_blob;
854 server_chal = data_blob(cli->secblob.data,
855 MIN(cli->secblob.length, 8));
856 if (tevent_req_nomem(server_chal.data, req)) {
857 return tevent_req_post(req, ev);
861 * note that the 'workgroup' here is a best
862 * guess - we don't know the server's domain
863 * at this point. The 'server name' is also
864 * dodgy...
866 names_blob = NTLMv2_generate_names_blob(
867 NULL, cli->called.name, workgroup);
869 if (tevent_req_nomem(names_blob.data, req)) {
870 return tevent_req_post(req, ev);
873 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
874 &server_chal, &names_blob,
875 &lm_response, &nt_response,
876 NULL, &session_key)) {
877 data_blob_free(&names_blob);
878 data_blob_free(&server_chal);
879 tevent_req_nterror(
880 req, NT_STATUS_ACCESS_DENIED);
881 return tevent_req_post(req, ev);
883 data_blob_free(&names_blob);
884 data_blob_free(&server_chal);
886 } else {
887 uchar nt_hash[16];
888 E_md4hash(pass, nt_hash);
890 #ifdef LANMAN_ONLY
891 nt_response = data_blob_null;
892 #else
893 nt_response = data_blob(NULL, 24);
894 if (tevent_req_nomem(nt_response.data, req)) {
895 return tevent_req_post(req, ev);
898 SMBNTencrypt(pass, cli->secblob.data,
899 nt_response.data);
900 #endif
901 /* non encrypted password supplied. Ignore ntpass. */
902 if (lp_client_lanman_auth()) {
904 lm_response = data_blob(NULL, 24);
905 if (tevent_req_nomem(lm_response.data, req)) {
906 return tevent_req_post(req, ev);
909 if (!SMBencrypt(pass,cli->secblob.data,
910 lm_response.data)) {
912 * Oops, the LM response is
913 * invalid, just put the NT
914 * response there instead
916 data_blob_free(&lm_response);
917 lm_response = data_blob(
918 nt_response.data,
919 nt_response.length);
921 } else {
923 * LM disabled, place NT# in LM field
924 * instead
926 lm_response = data_blob(
927 nt_response.data, nt_response.length);
930 if (tevent_req_nomem(lm_response.data, req)) {
931 return tevent_req_post(req, ev);
934 session_key = data_blob(NULL, 16);
935 if (tevent_req_nomem(session_key.data, req)) {
936 return tevent_req_post(req, ev);
938 #ifdef LANMAN_ONLY
939 E_deshash(pass, session_key.data);
940 memset(&session_key.data[8], '\0', 8);
941 #else
942 SMBsesskeygen_ntv1(nt_hash, session_key.data);
943 #endif
945 cli_temp_set_signing(cli);
946 } else {
947 /* pre-encrypted password supplied. Only used for
948 security=server, can't do
949 signing because we don't have original key */
951 lm_response = data_blob(pass, passlen);
952 if (tevent_req_nomem(lm_response.data, req)) {
953 return tevent_req_post(req, ev);
956 nt_response = data_blob(ntpass, ntpasslen);
957 if (tevent_req_nomem(nt_response.data, req)) {
958 return tevent_req_post(req, ev);
962 #ifdef LANMAN_ONLY
963 state->response = data_blob_talloc(
964 state, lm_response.data, lm_response.length);
965 #else
966 state->response = data_blob_talloc(
967 state, nt_response.data, nt_response.length);
968 #endif
969 if (tevent_req_nomem(state->response.data, req)) {
970 return tevent_req_post(req, ev);
973 if (session_key.data) {
974 state->session_key = data_blob_talloc(
975 state, session_key.data, session_key.length);
976 if (tevent_req_nomem(state->session_key.data, req)) {
977 return tevent_req_post(req, ev);
980 data_blob_free(&session_key);
982 SCVAL(vwv+0, 0, 0xff);
983 SCVAL(vwv+0, 1, 0);
984 SSVAL(vwv+1, 0, 0);
985 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
986 SSVAL(vwv+3, 0, 2);
987 SSVAL(vwv+4, 0, cli->pid);
988 SIVAL(vwv+5, 0, cli->sesskey);
989 SSVAL(vwv+7, 0, lm_response.length);
990 SSVAL(vwv+8, 0, nt_response.length);
991 SSVAL(vwv+9, 0, 0);
992 SSVAL(vwv+10, 0, 0);
993 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
995 bytes = talloc_array(state, uint8_t,
996 lm_response.length + nt_response.length);
997 if (tevent_req_nomem(bytes, req)) {
998 return tevent_req_post(req, ev);
1000 if (lm_response.length != 0) {
1001 memcpy(bytes, lm_response.data, lm_response.length);
1003 if (nt_response.length != 0) {
1004 memcpy(bytes + lm_response.length,
1005 nt_response.data, nt_response.length);
1007 data_blob_free(&lm_response);
1008 data_blob_free(&nt_response);
1010 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1011 user, strlen(user)+1, NULL);
1014 * Upper case here might help some NTLMv2 implementations
1016 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1017 if (tevent_req_nomem(workgroup_upper, req)) {
1018 return tevent_req_post(req, ev);
1020 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1021 workgroup_upper, strlen(workgroup_upper)+1,
1022 NULL);
1023 TALLOC_FREE(workgroup_upper);
1025 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1026 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1027 if (tevent_req_nomem(bytes, req)) {
1028 return tevent_req_post(req, ev);
1031 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1032 talloc_get_size(bytes), bytes);
1033 if (tevent_req_nomem(subreq, req)) {
1034 return tevent_req_post(req, ev);
1036 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1037 return req;
1040 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1042 struct tevent_req *req = tevent_req_callback_data(
1043 subreq, struct tevent_req);
1044 struct cli_session_setup_nt1_state *state = tevent_req_data(
1045 req, struct cli_session_setup_nt1_state);
1046 struct cli_state *cli = state->cli;
1047 uint32_t num_bytes;
1048 uint8_t *in;
1049 char *inbuf;
1050 uint8_t *bytes;
1051 uint8_t *p;
1052 NTSTATUS status;
1053 ssize_t ret;
1055 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
1056 &num_bytes, &bytes);
1057 TALLOC_FREE(subreq);
1058 if (!NT_STATUS_IS_OK(status)) {
1059 tevent_req_nterror(req, status);
1060 return;
1063 inbuf = (char *)in;
1064 p = bytes;
1066 cli->vuid = SVAL(inbuf, smb_uid);
1068 status = smb_bytes_talloc_string(cli,
1069 inbuf,
1070 &cli->server_os,
1072 bytes+num_bytes-p,
1073 &ret);
1074 if (!NT_STATUS_IS_OK(status)) {
1075 tevent_req_nterror(req, status);
1076 return;
1078 p += ret;
1080 status = smb_bytes_talloc_string(cli,
1081 inbuf,
1082 &cli->server_type,
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_domain,
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 if (strstr(cli->server_type, "Samba")) {
1105 cli->is_samba = True;
1108 status = cli_set_username(cli, state->user);
1109 if (tevent_req_nterror(req, status)) {
1110 return;
1112 if (cli_simple_set_signing(cli, state->session_key, state->response)
1113 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1114 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1115 return;
1117 if (state->session_key.data) {
1118 /* Have plaintext orginal */
1119 cli_set_session_key(cli, state->session_key);
1121 tevent_req_done(req);
1124 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1126 return tevent_req_simple_recv_ntstatus(req);
1129 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1130 const char *pass, size_t passlen,
1131 const char *ntpass, size_t ntpasslen,
1132 const char *workgroup)
1134 TALLOC_CTX *frame = talloc_stackframe();
1135 struct event_context *ev;
1136 struct tevent_req *req;
1137 NTSTATUS status = NT_STATUS_NO_MEMORY;
1139 if (cli_has_async_calls(cli)) {
1141 * Can't use sync call while an async call is in flight
1143 status = NT_STATUS_INVALID_PARAMETER;
1144 goto fail;
1146 ev = event_context_init(frame);
1147 if (ev == NULL) {
1148 goto fail;
1150 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1151 ntpass, ntpasslen, workgroup);
1152 if (req == NULL) {
1153 goto fail;
1155 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1156 goto fail;
1158 status = cli_session_setup_nt1_recv(req);
1159 fail:
1160 TALLOC_FREE(frame);
1161 if (!NT_STATUS_IS_OK(status)) {
1162 cli_set_error(cli, status);
1164 return status;
1167 /* The following is calculated from :
1168 * (smb_size-4) = 35
1169 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1170 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1171 * end of packet.
1174 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1176 struct cli_sesssetup_blob_state {
1177 struct tevent_context *ev;
1178 struct cli_state *cli;
1179 DATA_BLOB blob;
1180 uint16_t max_blob_size;
1181 uint16_t vwv[12];
1182 uint8_t *buf;
1184 NTSTATUS status;
1185 char *inbuf;
1186 DATA_BLOB ret_blob;
1189 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1190 struct tevent_req **psubreq);
1191 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1193 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1194 struct tevent_context *ev,
1195 struct cli_state *cli,
1196 DATA_BLOB blob)
1198 struct tevent_req *req, *subreq;
1199 struct cli_sesssetup_blob_state *state;
1201 req = tevent_req_create(mem_ctx, &state,
1202 struct cli_sesssetup_blob_state);
1203 if (req == NULL) {
1204 return NULL;
1206 state->ev = ev;
1207 state->blob = blob;
1208 state->cli = cli;
1210 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1211 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1212 "(was %u, need minimum %u)\n",
1213 (unsigned int)cli->max_xmit,
1214 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1215 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1216 return tevent_req_post(req, ev);
1218 state->max_blob_size =
1219 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1221 if (!cli_sesssetup_blob_next(state, &subreq)) {
1222 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1223 return tevent_req_post(req, ev);
1225 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1226 return req;
1229 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1230 struct tevent_req **psubreq)
1232 struct tevent_req *subreq;
1233 uint16_t thistime;
1235 SCVAL(state->vwv+0, 0, 0xFF);
1236 SCVAL(state->vwv+0, 1, 0);
1237 SSVAL(state->vwv+1, 0, 0);
1238 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1239 SSVAL(state->vwv+3, 0, 2);
1240 SSVAL(state->vwv+4, 0, 1);
1241 SIVAL(state->vwv+5, 0, 0);
1243 thistime = MIN(state->blob.length, state->max_blob_size);
1244 SSVAL(state->vwv+7, 0, thistime);
1246 SSVAL(state->vwv+8, 0, 0);
1247 SSVAL(state->vwv+9, 0, 0);
1248 SIVAL(state->vwv+10, 0,
1249 cli_session_setup_capabilities(state->cli)
1250 | CAP_EXTENDED_SECURITY);
1252 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1253 thistime);
1254 if (state->buf == NULL) {
1255 return false;
1257 state->blob.data += thistime;
1258 state->blob.length -= thistime;
1260 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1261 "Unix", 5, NULL);
1262 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1263 "Samba", 6, NULL);
1264 if (state->buf == NULL) {
1265 return false;
1267 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1268 12, state->vwv,
1269 talloc_get_size(state->buf), state->buf);
1270 if (subreq == NULL) {
1271 return false;
1273 *psubreq = subreq;
1274 return true;
1277 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1279 struct tevent_req *req = tevent_req_callback_data(
1280 subreq, struct tevent_req);
1281 struct cli_sesssetup_blob_state *state = tevent_req_data(
1282 req, struct cli_sesssetup_blob_state);
1283 struct cli_state *cli = state->cli;
1284 uint8_t wct;
1285 uint16_t *vwv;
1286 uint32_t num_bytes;
1287 uint8_t *bytes;
1288 NTSTATUS status;
1289 uint8_t *p;
1290 uint16_t blob_length;
1291 uint8_t *inbuf;
1292 ssize_t ret;
1294 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
1295 &num_bytes, &bytes);
1296 TALLOC_FREE(subreq);
1297 if (!NT_STATUS_IS_OK(status)
1298 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1299 tevent_req_nterror(req, status);
1300 return;
1303 state->status = status;
1304 TALLOC_FREE(state->buf);
1306 state->inbuf = (char *)inbuf;
1307 cli->vuid = SVAL(state->inbuf, smb_uid);
1309 blob_length = SVAL(vwv+3, 0);
1310 if (blob_length > num_bytes) {
1311 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1312 return;
1314 state->ret_blob = data_blob_const(bytes, blob_length);
1316 p = bytes + blob_length;
1318 status = smb_bytes_talloc_string(cli,
1319 (char *)inbuf,
1320 &cli->server_os,
1322 bytes+num_bytes-p,
1323 &ret);
1325 if (!NT_STATUS_IS_OK(status)) {
1326 tevent_req_nterror(req, status);
1327 return;
1329 p += ret;
1331 status = smb_bytes_talloc_string(cli,
1332 (char *)inbuf,
1333 &cli->server_type,
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_domain,
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 if (strstr(cli->server_type, "Samba")) {
1358 cli->is_samba = True;
1361 if (state->blob.length != 0) {
1363 * More to send
1365 if (!cli_sesssetup_blob_next(state, &subreq)) {
1366 tevent_req_nomem(NULL, req);
1367 return;
1369 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1370 return;
1372 tevent_req_done(req);
1375 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1376 TALLOC_CTX *mem_ctx,
1377 DATA_BLOB *pblob,
1378 char **pinbuf)
1380 struct cli_sesssetup_blob_state *state = tevent_req_data(
1381 req, struct cli_sesssetup_blob_state);
1382 NTSTATUS status;
1383 char *inbuf;
1385 if (tevent_req_is_nterror(req, &status)) {
1386 state->cli->vuid = 0;
1387 return status;
1390 inbuf = talloc_move(mem_ctx, &state->inbuf);
1391 if (pblob != NULL) {
1392 *pblob = state->ret_blob;
1394 if (pinbuf != NULL) {
1395 *pinbuf = inbuf;
1397 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1398 return state->status;
1401 #ifdef HAVE_KRB5
1403 /****************************************************************************
1404 Use in-memory credentials cache
1405 ****************************************************************************/
1407 static void use_in_memory_ccache(void) {
1408 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1411 /****************************************************************************
1412 Do a spnego/kerberos encrypted session setup.
1413 ****************************************************************************/
1415 struct cli_session_setup_kerberos_state {
1416 struct cli_state *cli;
1417 DATA_BLOB negTokenTarg;
1418 DATA_BLOB session_key_krb5;
1419 ADS_STATUS ads_status;
1422 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1424 static struct tevent_req *cli_session_setup_kerberos_send(
1425 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1426 const char *principal, const char *workgroup)
1428 struct tevent_req *req, *subreq;
1429 struct cli_session_setup_kerberos_state *state;
1430 int rc;
1432 DEBUG(2,("Doing kerberos session setup\n"));
1434 req = tevent_req_create(mem_ctx, &state,
1435 struct cli_session_setup_kerberos_state);
1436 if (req == NULL) {
1437 return NULL;
1439 state->cli = cli;
1440 state->ads_status = ADS_SUCCESS;
1442 cli_temp_set_signing(cli);
1445 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1446 * we have to acquire a ticket. To be fixed later :-)
1448 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1449 &state->session_key_krb5, 0, NULL);
1450 if (rc) {
1451 DEBUG(1, ("cli_session_setup_kerberos: "
1452 "spnego_gen_krb5_negTokenInit failed: %s\n",
1453 error_message(rc)));
1454 state->ads_status = ADS_ERROR_KRB5(rc);
1455 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1456 return tevent_req_post(req, ev);
1459 #if 0
1460 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1461 state->negTokenTarg.length);
1462 #endif
1464 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1465 if (tevent_req_nomem(subreq, req)) {
1466 return tevent_req_post(req, ev);
1468 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1469 return req;
1472 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1474 struct tevent_req *req = tevent_req_callback_data(
1475 subreq, struct tevent_req);
1476 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1477 req, struct cli_session_setup_kerberos_state);
1478 char *inbuf = NULL;
1479 NTSTATUS status;
1481 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 TALLOC_FREE(subreq);
1484 tevent_req_nterror(req, status);
1485 return;
1488 cli_set_session_key(state->cli, state->session_key_krb5);
1490 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1491 data_blob_null)
1492 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1493 TALLOC_FREE(subreq);
1494 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1495 return;
1497 TALLOC_FREE(subreq);
1498 tevent_req_done(req);
1501 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1503 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1504 req, struct cli_session_setup_kerberos_state);
1505 NTSTATUS status;
1507 if (tevent_req_is_nterror(req, &status)) {
1508 return ADS_ERROR_NT(status);
1510 return state->ads_status;
1513 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1514 const char *principal,
1515 const char *workgroup)
1517 struct tevent_context *ev;
1518 struct tevent_req *req;
1519 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1521 if (cli_has_async_calls(cli)) {
1522 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1524 ev = tevent_context_init(talloc_tos());
1525 if (ev == NULL) {
1526 goto fail;
1528 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1529 workgroup);
1530 if (req == NULL) {
1531 goto fail;
1533 if (!tevent_req_poll(req, ev)) {
1534 status = ADS_ERROR_SYSTEM(errno);
1535 goto fail;
1537 status = cli_session_setup_kerberos_recv(req);
1538 fail:
1539 TALLOC_FREE(ev);
1540 return status;
1542 #endif /* HAVE_KRB5 */
1544 /****************************************************************************
1545 Do a spnego/NTLMSSP encrypted session setup.
1546 ****************************************************************************/
1548 struct cli_session_setup_ntlmssp_state {
1549 struct tevent_context *ev;
1550 struct cli_state *cli;
1551 struct ntlmssp_state *ntlmssp_state;
1552 int turn;
1553 DATA_BLOB blob_out;
1556 static int cli_session_setup_ntlmssp_state_destructor(
1557 struct cli_session_setup_ntlmssp_state *state)
1559 if (state->ntlmssp_state != NULL) {
1560 TALLOC_FREE(state->ntlmssp_state);
1562 return 0;
1565 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1567 static struct tevent_req *cli_session_setup_ntlmssp_send(
1568 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1569 const char *user, const char *pass, const char *domain)
1571 struct tevent_req *req, *subreq;
1572 struct cli_session_setup_ntlmssp_state *state;
1573 NTSTATUS status;
1574 DATA_BLOB blob_out;
1575 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1577 req = tevent_req_create(mem_ctx, &state,
1578 struct cli_session_setup_ntlmssp_state);
1579 if (req == NULL) {
1580 return NULL;
1582 state->ev = ev;
1583 state->cli = cli;
1584 state->turn = 1;
1586 state->ntlmssp_state = NULL;
1587 talloc_set_destructor(
1588 state, cli_session_setup_ntlmssp_state_destructor);
1590 cli_temp_set_signing(cli);
1592 status = ntlmssp_client_start(state,
1593 global_myname(),
1594 lp_workgroup(),
1595 lp_client_ntlmv2_auth(),
1596 &state->ntlmssp_state);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 goto fail;
1600 ntlmssp_want_feature(state->ntlmssp_state,
1601 NTLMSSP_FEATURE_SESSION_KEY);
1602 if (cli->use_ccache) {
1603 ntlmssp_want_feature(state->ntlmssp_state,
1604 NTLMSSP_FEATURE_CCACHE);
1606 status = ntlmssp_set_username(state->ntlmssp_state, user);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 goto fail;
1610 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1611 if (!NT_STATUS_IS_OK(status)) {
1612 goto fail;
1614 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 goto fail;
1618 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1619 &blob_out);
1620 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1621 goto fail;
1624 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1625 data_blob_free(&blob_out);
1627 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1628 if (tevent_req_nomem(subreq, req)) {
1629 return tevent_req_post(req, ev);
1631 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1632 return req;
1633 fail:
1634 tevent_req_nterror(req, status);
1635 return tevent_req_post(req, ev);
1638 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1640 struct tevent_req *req = tevent_req_callback_data(
1641 subreq, struct tevent_req);
1642 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1643 req, struct cli_session_setup_ntlmssp_state);
1644 DATA_BLOB blob_in, msg_in, blob_out;
1645 char *inbuf = NULL;
1646 bool parse_ret;
1647 NTSTATUS status;
1649 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1650 &inbuf);
1651 TALLOC_FREE(subreq);
1652 data_blob_free(&state->blob_out);
1654 if (NT_STATUS_IS_OK(status)) {
1655 if (state->cli->server_domain[0] == '\0') {
1656 TALLOC_FREE(state->cli->server_domain);
1657 state->cli->server_domain = talloc_strdup(state->cli,
1658 state->ntlmssp_state->server.netbios_domain);
1659 if (state->cli->server_domain == NULL) {
1660 TALLOC_FREE(subreq);
1661 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1662 return;
1665 cli_set_session_key(
1666 state->cli, state->ntlmssp_state->session_key);
1668 if (cli_simple_set_signing(
1669 state->cli, state->ntlmssp_state->session_key,
1670 data_blob_null)
1671 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1672 TALLOC_FREE(subreq);
1673 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1674 return;
1676 TALLOC_FREE(subreq);
1677 TALLOC_FREE(state->ntlmssp_state);
1678 tevent_req_done(req);
1679 return;
1681 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1682 tevent_req_nterror(req, status);
1683 return;
1686 if (blob_in.length == 0) {
1687 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1688 return;
1691 if ((state->turn == 1)
1692 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1693 DATA_BLOB tmp_blob = data_blob_null;
1694 /* the server might give us back two challenges */
1695 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1696 &tmp_blob);
1697 data_blob_free(&tmp_blob);
1698 } else {
1699 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1700 OID_NTLMSSP, &msg_in);
1702 state->turn += 1;
1704 if (!parse_ret) {
1705 DEBUG(3,("Failed to parse auth response\n"));
1706 if (NT_STATUS_IS_OK(status)
1707 || NT_STATUS_EQUAL(status,
1708 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1709 tevent_req_nterror(
1710 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1711 return;
1715 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1717 if (!NT_STATUS_IS_OK(status)
1718 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1719 TALLOC_FREE(subreq);
1720 TALLOC_FREE(state->ntlmssp_state);
1721 tevent_req_nterror(req, status);
1722 return;
1725 state->blob_out = spnego_gen_auth(state, blob_out);
1726 TALLOC_FREE(subreq);
1727 if (tevent_req_nomem(state->blob_out.data, req)) {
1728 return;
1731 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1732 state->blob_out);
1733 if (tevent_req_nomem(subreq, req)) {
1734 return;
1736 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1739 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1741 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1742 req, struct cli_session_setup_ntlmssp_state);
1743 NTSTATUS status;
1745 if (tevent_req_is_nterror(req, &status)) {
1746 state->cli->vuid = 0;
1747 return status;
1749 return NT_STATUS_OK;
1752 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1753 const char *user,
1754 const char *pass,
1755 const char *domain)
1757 struct tevent_context *ev;
1758 struct tevent_req *req;
1759 NTSTATUS status = NT_STATUS_NO_MEMORY;
1761 if (cli_has_async_calls(cli)) {
1762 return NT_STATUS_INVALID_PARAMETER;
1764 ev = tevent_context_init(talloc_tos());
1765 if (ev == NULL) {
1766 goto fail;
1768 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1769 if (req == NULL) {
1770 goto fail;
1772 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1773 goto fail;
1775 status = cli_session_setup_ntlmssp_recv(req);
1776 fail:
1777 TALLOC_FREE(ev);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 cli_set_error(cli, status);
1781 return status;
1784 /****************************************************************************
1785 Do a spnego encrypted session setup.
1787 user_domain: The shortname of the domain the user/machine is a member of.
1788 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1789 ****************************************************************************/
1791 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1792 const char *pass, const char *user_domain,
1793 const char * dest_realm)
1795 char *principal = NULL;
1796 char *OIDs[ASN1_MAX_OIDS];
1797 int i;
1798 DATA_BLOB blob;
1799 const char *p = NULL;
1800 char *account = NULL;
1801 NTSTATUS status;
1803 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1805 /* the server might not even do spnego */
1806 if (cli->secblob.length <= 16) {
1807 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1808 goto ntlmssp;
1811 #if 0
1812 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1813 #endif
1815 /* there is 16 bytes of GUID before the real spnego packet starts */
1816 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1818 /* The server sent us the first part of the SPNEGO exchange in the
1819 * negprot reply. It is WRONG to depend on the principal sent in the
1820 * negprot reply, but right now we do it. If we don't receive one,
1821 * we try to best guess, then fall back to NTLM. */
1822 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1823 OIDs[0] == NULL) {
1824 data_blob_free(&blob);
1825 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1827 data_blob_free(&blob);
1829 /* make sure the server understands kerberos */
1830 for (i=0;OIDs[i];i++) {
1831 if (i == 0)
1832 DEBUG(3,("got OID=%s\n", OIDs[i]));
1833 else
1834 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1835 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1836 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1837 cli->got_kerberos_mechanism = True;
1839 talloc_free(OIDs[i]);
1842 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1844 status = cli_set_username(cli, user);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 TALLOC_FREE(principal);
1847 return ADS_ERROR_NT(status);
1850 #ifdef HAVE_KRB5
1851 /* If password is set we reauthenticate to kerberos server
1852 * and do not store results */
1854 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1855 ADS_STATUS rc;
1857 if (pass && *pass) {
1858 int ret;
1860 use_in_memory_ccache();
1861 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1863 if (ret){
1864 TALLOC_FREE(principal);
1865 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1866 if (cli->fallback_after_kerberos)
1867 goto ntlmssp;
1868 return ADS_ERROR_KRB5(ret);
1872 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1874 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1875 TALLOC_FREE(principal);
1878 if (principal == NULL &&
1879 !is_ipaddress(cli->desthost) &&
1880 !strequal(STAR_SMBSERVER,
1881 cli->desthost)) {
1882 char *realm = NULL;
1883 char *host = NULL;
1884 DEBUG(3,("cli_session_setup_spnego: using target "
1885 "hostname not SPNEGO principal\n"));
1887 host = strchr_m(cli->desthost, '.');
1888 if (dest_realm) {
1889 realm = SMB_STRDUP(dest_realm);
1890 strupper_m(realm);
1891 } else {
1892 if (host) {
1893 /* DNS name. */
1894 realm = kerberos_get_realm_from_hostname(cli->desthost);
1895 } else {
1896 /* NetBIOS name - use our realm. */
1897 realm = kerberos_get_default_realm_from_ccache();
1901 if (realm && *realm) {
1902 principal = talloc_asprintf(talloc_tos(),
1903 "cifs/%s@%s",
1904 cli->desthost,
1905 realm);
1906 if (!principal) {
1907 SAFE_FREE(realm);
1908 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1910 DEBUG(3,("cli_session_setup_spnego: guessed "
1911 "server principal=%s\n",
1912 principal ? principal : "<null>"));
1914 SAFE_FREE(realm);
1917 if (principal) {
1918 rc = cli_session_setup_kerberos(cli, principal,
1919 dest_realm);
1920 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1921 TALLOC_FREE(principal);
1922 return rc;
1926 #endif
1928 TALLOC_FREE(principal);
1930 ntlmssp:
1932 account = talloc_strdup(talloc_tos(), user);
1933 if (!account) {
1934 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1937 /* when falling back to ntlmssp while authenticating with a machine
1938 * account strip off the realm - gd */
1940 if ((p = strchr_m(user, '@')) != NULL) {
1941 account[PTR_DIFF(p,user)] = '\0';
1944 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1947 /****************************************************************************
1948 Send a session setup. The username and workgroup is in UNIX character
1949 format and must be converted to DOS codepage format before sending. If the
1950 password is in plaintext, the same should be done.
1951 ****************************************************************************/
1953 NTSTATUS cli_session_setup(struct cli_state *cli,
1954 const char *user,
1955 const char *pass, int passlen,
1956 const char *ntpass, int ntpasslen,
1957 const char *workgroup)
1959 char *p;
1960 char *user2;
1962 if (user) {
1963 user2 = talloc_strdup(talloc_tos(), user);
1964 } else {
1965 user2 = talloc_strdup(talloc_tos(), "");
1967 if (user2 == NULL) {
1968 return NT_STATUS_NO_MEMORY;
1971 if (!workgroup) {
1972 workgroup = "";
1975 /* allow for workgroups as part of the username */
1976 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1977 (p=strchr_m(user2,*lp_winbind_separator()))) {
1978 *p = 0;
1979 user = p+1;
1980 strupper_m(user2);
1981 workgroup = user2;
1984 if (cli->protocol < PROTOCOL_LANMAN1) {
1985 return NT_STATUS_OK;
1988 /* now work out what sort of session setup we are going to
1989 do. I have split this into separate functions to make the
1990 flow a bit easier to understand (tridge) */
1992 /* if its an older server then we have to use the older request format */
1994 if (cli->protocol < PROTOCOL_NT1) {
1995 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1996 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1997 " or 'client ntlmv2 auth = yes'\n"));
1998 return NT_STATUS_ACCESS_DENIED;
2001 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2002 !lp_client_plaintext_auth() && (*pass)) {
2003 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2004 " or 'client ntlmv2 auth = yes'\n"));
2005 return NT_STATUS_ACCESS_DENIED;
2008 return cli_session_setup_lanman2(cli, user, pass, passlen,
2009 workgroup);
2012 /* if no user is supplied then we have to do an anonymous connection.
2013 passwords are ignored */
2015 if (!user || !*user)
2016 return cli_session_setup_guest(cli);
2018 /* if the server is share level then send a plaintext null
2019 password at this point. The password is sent in the tree
2020 connect */
2022 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2023 return cli_session_setup_plain(cli, user, "", workgroup);
2025 /* if the server doesn't support encryption then we have to use
2026 plaintext. The second password is ignored */
2028 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2029 if (!lp_client_plaintext_auth() && (*pass)) {
2030 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2031 " or 'client ntlmv2 auth = yes'\n"));
2032 return NT_STATUS_ACCESS_DENIED;
2034 return cli_session_setup_plain(cli, user, pass, workgroup);
2037 /* if the server supports extended security then use SPNEGO */
2039 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2040 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2041 workgroup, NULL);
2042 if (!ADS_ERR_OK(status)) {
2043 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2044 return ads_ntstatus(status);
2046 } else {
2047 NTSTATUS status;
2049 /* otherwise do a NT1 style session setup */
2050 status = cli_session_setup_nt1(cli, user, pass, passlen,
2051 ntpass, ntpasslen, workgroup);
2052 if (!NT_STATUS_IS_OK(status)) {
2053 DEBUG(3,("cli_session_setup: NT1 session setup "
2054 "failed: %s\n", nt_errstr(status)));
2055 return status;
2059 if (strstr(cli->server_type, "Samba")) {
2060 cli->is_samba = True;
2063 return NT_STATUS_OK;
2066 /****************************************************************************
2067 Send a uloggoff.
2068 *****************************************************************************/
2070 struct cli_ulogoff_state {
2071 struct cli_state *cli;
2072 uint16_t vwv[3];
2075 static void cli_ulogoff_done(struct tevent_req *subreq);
2077 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2078 struct tevent_context *ev,
2079 struct cli_state *cli)
2081 struct tevent_req *req, *subreq;
2082 struct cli_ulogoff_state *state;
2084 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2085 if (req == NULL) {
2086 return NULL;
2088 state->cli = cli;
2090 SCVAL(state->vwv+0, 0, 0xFF);
2091 SCVAL(state->vwv+1, 0, 0);
2092 SSVAL(state->vwv+2, 0, 0);
2094 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2095 0, NULL);
2096 if (tevent_req_nomem(subreq, req)) {
2097 return tevent_req_post(req, ev);
2099 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2100 return req;
2103 static void cli_ulogoff_done(struct tevent_req *subreq)
2105 struct tevent_req *req = tevent_req_callback_data(
2106 subreq, struct tevent_req);
2107 struct cli_ulogoff_state *state = tevent_req_data(
2108 req, struct cli_ulogoff_state);
2109 NTSTATUS status;
2111 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2112 if (!NT_STATUS_IS_OK(status)) {
2113 tevent_req_nterror(req, status);
2114 return;
2116 state->cli->vuid = -1;
2117 tevent_req_done(req);
2120 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2122 return tevent_req_simple_recv_ntstatus(req);
2125 NTSTATUS cli_ulogoff(struct cli_state *cli)
2127 struct tevent_context *ev;
2128 struct tevent_req *req;
2129 NTSTATUS status = NT_STATUS_NO_MEMORY;
2131 if (cli_has_async_calls(cli)) {
2132 return NT_STATUS_INVALID_PARAMETER;
2134 ev = tevent_context_init(talloc_tos());
2135 if (ev == NULL) {
2136 goto fail;
2138 req = cli_ulogoff_send(ev, ev, cli);
2139 if (req == NULL) {
2140 goto fail;
2142 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2143 goto fail;
2145 status = cli_ulogoff_recv(req);
2146 fail:
2147 TALLOC_FREE(ev);
2148 if (!NT_STATUS_IS_OK(status)) {
2149 cli_set_error(cli, status);
2151 return status;
2154 /****************************************************************************
2155 Send a tconX.
2156 ****************************************************************************/
2158 struct cli_tcon_andx_state {
2159 struct cli_state *cli;
2160 uint16_t vwv[4];
2161 struct iovec bytes;
2164 static void cli_tcon_andx_done(struct tevent_req *subreq);
2166 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2167 struct event_context *ev,
2168 struct cli_state *cli,
2169 const char *share, const char *dev,
2170 const char *pass, int passlen,
2171 struct tevent_req **psmbreq)
2173 struct tevent_req *req, *subreq;
2174 struct cli_tcon_andx_state *state;
2175 uint8_t p24[24];
2176 uint16_t *vwv;
2177 char *tmp = NULL;
2178 uint8_t *bytes;
2180 *psmbreq = NULL;
2182 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2183 if (req == NULL) {
2184 return NULL;
2186 state->cli = cli;
2187 vwv = state->vwv;
2189 cli->share = talloc_strdup(cli, share);
2190 if (!cli->share) {
2191 return NULL;
2194 /* in user level security don't send a password now */
2195 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2196 passlen = 1;
2197 pass = "";
2198 } else if (pass == NULL) {
2199 DEBUG(1, ("Server not using user level security and no "
2200 "password supplied.\n"));
2201 goto access_denied;
2204 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2205 *pass && passlen != 24) {
2206 if (!lp_client_lanman_auth()) {
2207 DEBUG(1, ("Server requested LANMAN password "
2208 "(share-level security) but "
2209 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2210 goto access_denied;
2214 * Non-encrypted passwords - convert to DOS codepage before
2215 * encryption.
2217 SMBencrypt(pass, cli->secblob.data, p24);
2218 passlen = 24;
2219 pass = (const char *)p24;
2220 } else {
2221 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2222 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2223 == 0) {
2224 char *tmp_pass;
2226 if (!lp_client_plaintext_auth() && (*pass)) {
2227 DEBUG(1, ("Server requested plaintext "
2228 "password but "
2229 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2230 goto access_denied;
2234 * Non-encrypted passwords - convert to DOS codepage
2235 * before using.
2237 tmp_pass = talloc_array(talloc_tos(), char, 128);
2238 if (tmp_pass == NULL) {
2239 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2240 return tevent_req_post(req, ev);
2242 passlen = clistr_push(cli,
2243 tmp_pass,
2244 pass,
2245 talloc_get_size(tmp_pass),
2246 STR_TERMINATE);
2247 if (passlen == -1) {
2248 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2249 return tevent_req_post(req, ev);
2251 pass = tmp_pass;
2255 SCVAL(vwv+0, 0, 0xFF);
2256 SCVAL(vwv+0, 1, 0);
2257 SSVAL(vwv+1, 0, 0);
2258 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2259 SSVAL(vwv+3, 0, passlen);
2261 if (passlen && pass) {
2262 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2263 } else {
2264 bytes = talloc_array(state, uint8_t, 0);
2268 * Add the sharename
2270 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2271 cli->desthost, share);
2272 if (tmp == NULL) {
2273 TALLOC_FREE(req);
2274 return NULL;
2276 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2277 NULL);
2278 TALLOC_FREE(tmp);
2281 * Add the devicetype
2283 tmp = talloc_strdup_upper(talloc_tos(), dev);
2284 if (tmp == NULL) {
2285 TALLOC_FREE(req);
2286 return NULL;
2288 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2289 TALLOC_FREE(tmp);
2291 if (bytes == NULL) {
2292 TALLOC_FREE(req);
2293 return NULL;
2296 state->bytes.iov_base = (void *)bytes;
2297 state->bytes.iov_len = talloc_get_size(bytes);
2299 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2300 1, &state->bytes);
2301 if (subreq == NULL) {
2302 TALLOC_FREE(req);
2303 return NULL;
2305 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2306 *psmbreq = subreq;
2307 return req;
2309 access_denied:
2310 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2311 return tevent_req_post(req, ev);
2314 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2315 struct event_context *ev,
2316 struct cli_state *cli,
2317 const char *share, const char *dev,
2318 const char *pass, int passlen)
2320 struct tevent_req *req, *subreq;
2321 NTSTATUS status;
2323 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2324 &subreq);
2325 if (req == NULL) {
2326 return NULL;
2328 if (subreq == NULL) {
2329 return req;
2331 status = cli_smb_req_send(subreq);
2332 if (!NT_STATUS_IS_OK(status)) {
2333 tevent_req_nterror(req, status);
2334 return tevent_req_post(req, ev);
2336 return req;
2339 static void cli_tcon_andx_done(struct tevent_req *subreq)
2341 struct tevent_req *req = tevent_req_callback_data(
2342 subreq, struct tevent_req);
2343 struct cli_tcon_andx_state *state = tevent_req_data(
2344 req, struct cli_tcon_andx_state);
2345 struct cli_state *cli = state->cli;
2346 uint8_t *in;
2347 char *inbuf;
2348 uint8_t wct;
2349 uint16_t *vwv;
2350 uint32_t num_bytes;
2351 uint8_t *bytes;
2352 NTSTATUS status;
2354 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2355 &num_bytes, &bytes);
2356 TALLOC_FREE(subreq);
2357 if (!NT_STATUS_IS_OK(status)) {
2358 tevent_req_nterror(req, status);
2359 return;
2362 inbuf = (char *)in;
2364 if (num_bytes) {
2365 if (clistr_pull_talloc(cli,
2366 inbuf,
2367 SVAL(inbuf, smb_flg2),
2368 &cli->dev,
2369 bytes,
2370 num_bytes,
2371 STR_TERMINATE|STR_ASCII) == -1) {
2372 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2373 return;
2375 } else {
2376 cli->dev = talloc_strdup(cli, "");
2377 if (cli->dev == NULL) {
2378 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2379 return;
2383 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2384 /* almost certainly win95 - enable bug fixes */
2385 cli->win95 = True;
2389 * Make sure that we have the optional support 16-bit field. WCT > 2.
2390 * Avoids issues when connecting to Win9x boxes sharing files
2393 cli->dfsroot = false;
2395 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2396 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2399 cli->cnum = SVAL(inbuf,smb_tid);
2400 tevent_req_done(req);
2403 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2405 return tevent_req_simple_recv_ntstatus(req);
2408 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2409 const char *dev, const char *pass, int passlen)
2411 TALLOC_CTX *frame = talloc_stackframe();
2412 struct event_context *ev;
2413 struct tevent_req *req;
2414 NTSTATUS status = NT_STATUS_OK;
2416 if (cli_has_async_calls(cli)) {
2418 * Can't use sync call while an async call is in flight
2420 status = NT_STATUS_INVALID_PARAMETER;
2421 goto fail;
2424 ev = event_context_init(frame);
2425 if (ev == NULL) {
2426 status = NT_STATUS_NO_MEMORY;
2427 goto fail;
2430 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2431 if (req == NULL) {
2432 status = NT_STATUS_NO_MEMORY;
2433 goto fail;
2436 if (!tevent_req_poll(req, ev)) {
2437 status = map_nt_error_from_unix(errno);
2438 goto fail;
2441 status = cli_tcon_andx_recv(req);
2442 fail:
2443 TALLOC_FREE(frame);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 cli_set_error(cli, status);
2447 return status;
2450 /****************************************************************************
2451 Send a tree disconnect.
2452 ****************************************************************************/
2454 struct cli_tdis_state {
2455 struct cli_state *cli;
2458 static void cli_tdis_done(struct tevent_req *subreq);
2460 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2461 struct tevent_context *ev,
2462 struct cli_state *cli)
2464 struct tevent_req *req, *subreq;
2465 struct cli_tdis_state *state;
2467 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2468 if (req == NULL) {
2469 return NULL;
2471 state->cli = cli;
2473 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2474 if (tevent_req_nomem(subreq, req)) {
2475 return tevent_req_post(req, ev);
2477 tevent_req_set_callback(subreq, cli_tdis_done, req);
2478 return req;
2481 static void cli_tdis_done(struct tevent_req *subreq)
2483 struct tevent_req *req = tevent_req_callback_data(
2484 subreq, struct tevent_req);
2485 struct cli_tdis_state *state = tevent_req_data(
2486 req, struct cli_tdis_state);
2487 NTSTATUS status;
2489 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2490 TALLOC_FREE(subreq);
2491 if (!NT_STATUS_IS_OK(status)) {
2492 tevent_req_nterror(req, status);
2493 return;
2495 state->cli->cnum = -1;
2496 tevent_req_done(req);
2499 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2501 return tevent_req_simple_recv_ntstatus(req);
2504 NTSTATUS cli_tdis(struct cli_state *cli)
2506 struct tevent_context *ev;
2507 struct tevent_req *req;
2508 NTSTATUS status = NT_STATUS_NO_MEMORY;
2510 if (cli_has_async_calls(cli)) {
2511 return NT_STATUS_INVALID_PARAMETER;
2513 ev = tevent_context_init(talloc_tos());
2514 if (ev == NULL) {
2515 goto fail;
2517 req = cli_tdis_send(ev, ev, cli);
2518 if (req == NULL) {
2519 goto fail;
2521 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2522 goto fail;
2524 status = cli_tdis_recv(req);
2525 fail:
2526 TALLOC_FREE(ev);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 cli_set_error(cli, status);
2530 return status;
2533 /****************************************************************************
2534 Send a negprot command.
2535 ****************************************************************************/
2537 struct cli_negprot_state {
2538 struct cli_state *cli;
2541 static void cli_negprot_done(struct tevent_req *subreq);
2543 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2544 struct event_context *ev,
2545 struct cli_state *cli)
2547 struct tevent_req *req, *subreq;
2548 struct cli_negprot_state *state;
2549 uint8_t *bytes = NULL;
2550 int numprots;
2551 uint16_t cnum;
2553 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2554 if (req == NULL) {
2555 return NULL;
2557 state->cli = cli;
2559 if (cli->protocol < PROTOCOL_NT1)
2560 cli->use_spnego = False;
2562 /* setup the protocol strings */
2563 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2564 uint8_t c = 2;
2565 if (prots[numprots].prot > cli->protocol) {
2566 break;
2568 bytes = (uint8_t *)talloc_append_blob(
2569 state, bytes, data_blob_const(&c, sizeof(c)));
2570 if (tevent_req_nomem(bytes, req)) {
2571 return tevent_req_post(req, ev);
2573 bytes = smb_bytes_push_str(bytes, false,
2574 prots[numprots].name,
2575 strlen(prots[numprots].name)+1,
2576 NULL);
2577 if (tevent_req_nomem(bytes, req)) {
2578 return tevent_req_post(req, ev);
2582 cnum = cli->cnum;
2584 cli->cnum = 0;
2585 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2586 talloc_get_size(bytes), bytes);
2587 cli->cnum = cnum;
2589 if (tevent_req_nomem(subreq, req)) {
2590 return tevent_req_post(req, ev);
2592 tevent_req_set_callback(subreq, cli_negprot_done, req);
2593 return req;
2596 static void cli_negprot_done(struct tevent_req *subreq)
2598 struct tevent_req *req = tevent_req_callback_data(
2599 subreq, struct tevent_req);
2600 struct cli_negprot_state *state = tevent_req_data(
2601 req, struct cli_negprot_state);
2602 struct cli_state *cli = state->cli;
2603 uint8_t wct;
2604 uint16_t *vwv;
2605 uint32_t num_bytes;
2606 uint8_t *bytes;
2607 NTSTATUS status;
2608 uint16_t protnum;
2609 uint8_t *inbuf;
2611 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2612 &num_bytes, &bytes);
2613 TALLOC_FREE(subreq);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 tevent_req_nterror(req, status);
2616 return;
2619 protnum = SVAL(vwv, 0);
2621 if ((protnum >= ARRAY_SIZE(prots))
2622 || (prots[protnum].prot > cli->protocol)) {
2623 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2624 return;
2627 cli->protocol = prots[protnum].prot;
2629 if ((cli->protocol < PROTOCOL_NT1) &&
2630 client_is_signing_mandatory(cli)) {
2631 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2632 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2633 return;
2636 if (cli->protocol >= PROTOCOL_NT1) {
2637 struct timespec ts;
2638 bool negotiated_smb_signing = false;
2640 /* NT protocol */
2641 cli->sec_mode = CVAL(vwv + 1, 0);
2642 cli->max_mux = SVAL(vwv + 1, 1);
2643 cli->max_xmit = IVAL(vwv + 3, 1);
2644 cli->sesskey = IVAL(vwv + 7, 1);
2645 cli->serverzone = SVALS(vwv + 15, 1);
2646 cli->serverzone *= 60;
2647 /* this time arrives in real GMT */
2648 ts = interpret_long_date(((char *)(vwv+11))+1);
2649 cli->servertime = ts.tv_sec;
2650 cli->secblob = data_blob(bytes, num_bytes);
2651 cli->capabilities = IVAL(vwv + 9, 1);
2652 if (cli->capabilities & CAP_RAW_MODE) {
2653 cli->readbraw_supported = True;
2654 cli->writebraw_supported = True;
2656 /* work out if they sent us a workgroup */
2657 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2658 smb_buflen(cli->inbuf) > 8) {
2659 ssize_t ret;
2660 status = smb_bytes_talloc_string(
2661 cli, (char *)cli->inbuf, &cli->server_domain,
2662 bytes + 8, num_bytes - 8, &ret);
2663 if (tevent_req_nterror(req, status)) {
2664 return;
2669 * As signing is slow we only turn it on if either the client or
2670 * the server require it. JRA.
2673 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2674 /* Fail if server says signing is mandatory and we don't want to support it. */
2675 if (!client_is_signing_allowed(cli)) {
2676 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2677 tevent_req_nterror(req,
2678 NT_STATUS_ACCESS_DENIED);
2679 return;
2681 negotiated_smb_signing = true;
2682 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2683 /* Fail if client says signing is mandatory and the server doesn't support it. */
2684 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2685 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2686 tevent_req_nterror(req,
2687 NT_STATUS_ACCESS_DENIED);
2688 return;
2690 negotiated_smb_signing = true;
2691 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2692 negotiated_smb_signing = true;
2695 if (negotiated_smb_signing) {
2696 cli_set_signing_negotiated(cli);
2699 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2700 SAFE_FREE(cli->outbuf);
2701 SAFE_FREE(cli->inbuf);
2702 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2703 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2704 if (!cli->outbuf || !cli->inbuf) {
2705 tevent_req_nterror(req,
2706 NT_STATUS_NO_MEMORY);
2707 return;
2709 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2712 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2713 cli->use_spnego = False;
2714 cli->sec_mode = SVAL(vwv + 1, 0);
2715 cli->max_xmit = SVAL(vwv + 2, 0);
2716 cli->max_mux = SVAL(vwv + 3, 0);
2717 cli->sesskey = IVAL(vwv + 6, 0);
2718 cli->serverzone = SVALS(vwv + 10, 0);
2719 cli->serverzone *= 60;
2720 /* this time is converted to GMT by make_unix_date */
2721 cli->servertime = make_unix_date(
2722 (char *)(vwv + 8), cli->serverzone);
2723 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2724 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2725 cli->secblob = data_blob(bytes, num_bytes);
2726 } else {
2727 /* the old core protocol */
2728 cli->use_spnego = False;
2729 cli->sec_mode = 0;
2730 cli->serverzone = get_time_zone(time(NULL));
2733 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2735 /* a way to force ascii SMB */
2736 if (getenv("CLI_FORCE_ASCII"))
2737 cli->capabilities &= ~CAP_UNICODE;
2739 tevent_req_done(req);
2742 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2744 return tevent_req_simple_recv_ntstatus(req);
2747 NTSTATUS cli_negprot(struct cli_state *cli)
2749 TALLOC_CTX *frame = talloc_stackframe();
2750 struct event_context *ev;
2751 struct tevent_req *req;
2752 NTSTATUS status = NT_STATUS_OK;
2754 if (cli_has_async_calls(cli)) {
2756 * Can't use sync call while an async call is in flight
2758 status = NT_STATUS_INVALID_PARAMETER;
2759 goto fail;
2762 ev = event_context_init(frame);
2763 if (ev == NULL) {
2764 status = NT_STATUS_NO_MEMORY;
2765 goto fail;
2768 req = cli_negprot_send(frame, ev, cli);
2769 if (req == NULL) {
2770 status = NT_STATUS_NO_MEMORY;
2771 goto fail;
2774 if (!tevent_req_poll(req, ev)) {
2775 status = map_nt_error_from_unix(errno);
2776 goto fail;
2779 status = cli_negprot_recv(req);
2780 fail:
2781 TALLOC_FREE(frame);
2782 if (!NT_STATUS_IS_OK(status)) {
2783 cli_set_error(cli, status);
2785 return status;
2788 /****************************************************************************
2789 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2790 ****************************************************************************/
2792 bool cli_session_request(struct cli_state *cli,
2793 struct nmb_name *calling, struct nmb_name *called)
2795 char *p;
2796 int len = 4;
2797 int namelen = 0;
2798 char *tmp;
2800 /* 445 doesn't have session request */
2801 if (cli->port == 445)
2802 return True;
2804 memcpy(&(cli->calling), calling, sizeof(*calling));
2805 memcpy(&(cli->called ), called , sizeof(*called ));
2807 /* put in the destination name */
2809 tmp = name_mangle(talloc_tos(), cli->called.name,
2810 cli->called.name_type);
2811 if (tmp == NULL) {
2812 return false;
2815 p = cli->outbuf+len;
2816 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2817 if (namelen > 0) {
2818 memcpy(p, tmp, namelen);
2819 len += namelen;
2821 TALLOC_FREE(tmp);
2823 /* and my name */
2825 tmp = name_mangle(talloc_tos(), cli->calling.name,
2826 cli->calling.name_type);
2827 if (tmp == NULL) {
2828 return false;
2831 p = cli->outbuf+len;
2832 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2833 if (namelen > 0) {
2834 memcpy(p, tmp, namelen);
2835 len += namelen;
2837 TALLOC_FREE(tmp);
2839 /* send a session request (RFC 1002) */
2840 /* setup the packet length
2841 * Remove four bytes from the length count, since the length
2842 * field in the NBT Session Service header counts the number
2843 * of bytes which follow. The cli_send_smb() function knows
2844 * about this and accounts for those four bytes.
2845 * CRH.
2847 len -= 4;
2848 _smb_setlen(cli->outbuf,len);
2849 SCVAL(cli->outbuf,0,0x81);
2851 cli_send_smb(cli);
2852 DEBUG(5,("Sent session request\n"));
2854 if (!cli_receive_smb(cli))
2855 return False;
2857 if (CVAL(cli->inbuf,0) == 0x84) {
2858 /* C. Hoch 9/14/95 Start */
2859 /* For information, here is the response structure.
2860 * We do the byte-twiddling to for portability.
2861 struct RetargetResponse{
2862 unsigned char type;
2863 unsigned char flags;
2864 int16 length;
2865 int32 ip_addr;
2866 int16 port;
2869 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2870 struct in_addr dest_ip;
2871 NTSTATUS status;
2873 /* SESSION RETARGET */
2874 putip((char *)&dest_ip,cli->inbuf+4);
2875 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2877 status = open_socket_out(&cli->dest_ss, port,
2878 LONG_CONNECT_TIMEOUT, &cli->fd);
2879 if (!NT_STATUS_IS_OK(status)) {
2880 return False;
2883 DEBUG(3,("Retargeted\n"));
2885 set_socket_options(cli->fd, lp_socket_options());
2887 /* Try again */
2889 static int depth;
2890 bool ret;
2891 if (depth > 4) {
2892 DEBUG(0,("Retarget recursion - failing\n"));
2893 return False;
2895 depth++;
2896 ret = cli_session_request(cli, calling, called);
2897 depth--;
2898 return ret;
2900 } /* C. Hoch 9/14/95 End */
2902 if (CVAL(cli->inbuf,0) != 0x82) {
2903 /* This is the wrong place to put the error... JRA. */
2904 cli->rap_error = CVAL(cli->inbuf,4);
2905 return False;
2907 return(True);
2910 struct fd_struct {
2911 int fd;
2914 static void smb_sock_connected(struct tevent_req *req)
2916 struct fd_struct *pfd = tevent_req_callback_data(
2917 req, struct fd_struct);
2918 int fd;
2919 NTSTATUS status;
2921 status = open_socket_out_defer_recv(req, &fd);
2922 if (NT_STATUS_IS_OK(status)) {
2923 pfd->fd = fd;
2927 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2928 uint16_t *port, int timeout, int *pfd)
2930 struct event_context *ev;
2931 struct tevent_req *r139, *r445;
2932 struct fd_struct *fd139, *fd445;
2933 NTSTATUS status = NT_STATUS_NO_MEMORY;
2935 if (*port != 0) {
2936 return open_socket_out(pss, *port, timeout, pfd);
2939 ev = event_context_init(talloc_tos());
2940 if (ev == NULL) {
2941 return NT_STATUS_NO_MEMORY;
2944 fd139 = talloc(ev, struct fd_struct);
2945 if (fd139 == NULL) {
2946 goto done;
2948 fd139->fd = -1;
2950 fd445 = talloc(ev, struct fd_struct);
2951 if (fd445 == NULL) {
2952 goto done;
2954 fd445->fd = -1;
2956 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2957 pss, 445, timeout);
2958 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2959 pss, 139, timeout);
2960 if ((r445 == NULL) || (r139 == NULL)) {
2961 goto done;
2963 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2964 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2966 while ((fd445->fd == -1) && (fd139->fd == -1)
2967 && (tevent_req_is_in_progress(r139)
2968 || tevent_req_is_in_progress(r445))) {
2969 event_loop_once(ev);
2972 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2973 close(fd139->fd);
2974 fd139->fd = -1;
2977 if (fd445->fd != -1) {
2978 *port = 445;
2979 *pfd = fd445->fd;
2980 status = NT_STATUS_OK;
2981 goto done;
2983 if (fd139->fd != -1) {
2984 *port = 139;
2985 *pfd = fd139->fd;
2986 status = NT_STATUS_OK;
2987 goto done;
2990 status = open_socket_out_defer_recv(r445, &fd445->fd);
2991 done:
2992 TALLOC_FREE(ev);
2993 return status;
2996 /****************************************************************************
2997 Open the client sockets.
2998 ****************************************************************************/
3000 NTSTATUS cli_connect(struct cli_state *cli,
3001 const char *host,
3002 struct sockaddr_storage *dest_ss)
3005 int name_type = 0x20;
3006 TALLOC_CTX *frame = talloc_stackframe();
3007 unsigned int num_addrs = 0;
3008 unsigned int i = 0;
3009 struct sockaddr_storage *ss_arr = NULL;
3010 char *p = NULL;
3012 /* reasonable default hostname */
3013 if (!host) {
3014 host = STAR_SMBSERVER;
3017 cli->desthost = talloc_strdup(cli, host);
3018 if (cli->desthost == NULL) {
3019 return NT_STATUS_NO_MEMORY;
3022 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3023 if ((p = strchr(cli->desthost, '#'))) {
3024 name_type = strtol(p+1, NULL, 16);
3025 *p = 0;
3028 if (!dest_ss || is_zero_addr(dest_ss)) {
3029 NTSTATUS status =resolve_name_list(frame,
3030 cli->desthost,
3031 name_type,
3032 &ss_arr,
3033 &num_addrs);
3034 if (!NT_STATUS_IS_OK(status)) {
3035 TALLOC_FREE(frame);
3036 return NT_STATUS_BAD_NETWORK_NAME;
3038 } else {
3039 num_addrs = 1;
3040 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
3041 if (!ss_arr) {
3042 TALLOC_FREE(frame);
3043 return NT_STATUS_NO_MEMORY;
3045 *ss_arr = *dest_ss;
3048 for (i = 0; i < num_addrs; i++) {
3049 cli->dest_ss = ss_arr[i];
3050 if (getenv("LIBSMB_PROG")) {
3051 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
3052 } else {
3053 uint16_t port = cli->port;
3054 NTSTATUS status;
3055 status = open_smb_socket(&cli->dest_ss, &port,
3056 cli->timeout, &cli->fd);
3057 if (NT_STATUS_IS_OK(status)) {
3058 cli->port = port;
3061 if (cli->fd == -1) {
3062 char addr[INET6_ADDRSTRLEN];
3063 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
3064 DEBUG(2,("Error connecting to %s (%s)\n",
3065 dest_ss?addr:host,strerror(errno)));
3066 } else {
3067 /* Exit from loop on first connection. */
3068 break;
3072 if (cli->fd == -1) {
3073 TALLOC_FREE(frame);
3074 return map_nt_error_from_unix(errno);
3077 if (dest_ss) {
3078 *dest_ss = cli->dest_ss;
3081 set_socket_options(cli->fd, lp_socket_options());
3083 TALLOC_FREE(frame);
3084 return NT_STATUS_OK;
3088 establishes a connection to after the negprot.
3089 @param output_cli A fully initialised cli structure, non-null only on success
3090 @param dest_host The netbios name of the remote host
3091 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3092 @param port (optional) The destination port (0 for default)
3094 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3095 const char *my_name,
3096 const char *dest_host,
3097 struct sockaddr_storage *dest_ss, int port,
3098 int signing_state, int flags)
3100 NTSTATUS nt_status;
3101 struct nmb_name calling;
3102 struct nmb_name called;
3103 struct cli_state *cli;
3104 struct sockaddr_storage ss;
3106 if (!my_name)
3107 my_name = global_myname();
3109 if (!(cli = cli_initialise_ex(signing_state))) {
3110 return NT_STATUS_NO_MEMORY;
3113 make_nmb_name(&calling, my_name, 0x0);
3114 make_nmb_name(&called , dest_host, 0x20);
3116 cli_set_port(cli, port);
3117 cli_set_timeout(cli, 10000); /* 10 seconds. */
3119 if (dest_ss) {
3120 ss = *dest_ss;
3121 } else {
3122 zero_sockaddr(&ss);
3125 again:
3127 DEBUG(3,("Connecting to host=%s\n", dest_host));
3129 nt_status = cli_connect(cli, dest_host, &ss);
3130 if (!NT_STATUS_IS_OK(nt_status)) {
3131 char addr[INET6_ADDRSTRLEN];
3132 print_sockaddr(addr, sizeof(addr), &ss);
3133 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3134 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
3135 cli_shutdown(cli);
3136 return nt_status;
3139 if (!cli_session_request(cli, &calling, &called)) {
3140 char *p;
3141 DEBUG(1,("session request to %s failed (%s)\n",
3142 called.name, cli_errstr(cli)));
3143 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
3144 *p = 0;
3145 goto again;
3147 if (strcmp(called.name, STAR_SMBSERVER)) {
3148 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
3149 goto again;
3151 return NT_STATUS_BAD_NETWORK_NAME;
3154 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
3155 cli->use_spnego = False;
3156 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
3157 cli->use_kerberos = True;
3159 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
3160 cli->use_kerberos) {
3161 cli->fallback_after_kerberos = true;
3163 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3164 cli->use_ccache = true;
3167 nt_status = cli_negprot(cli);
3168 if (!NT_STATUS_IS_OK(nt_status)) {
3169 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3170 cli_shutdown(cli);
3171 return nt_status;
3174 *output_cli = cli;
3175 return NT_STATUS_OK;
3180 establishes a connection right up to doing tconX, password specified.
3181 @param output_cli A fully initialised cli structure, non-null only on success
3182 @param dest_host The netbios name of the remote host
3183 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3184 @param port (optional) The destination port (0 for default)
3185 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3186 @param service_type The 'type' of serivice.
3187 @param user Username, unix string
3188 @param domain User's domain
3189 @param password User's password, unencrypted unix string.
3192 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3193 const char *my_name,
3194 const char *dest_host,
3195 struct sockaddr_storage *dest_ss, int port,
3196 const char *service, const char *service_type,
3197 const char *user, const char *domain,
3198 const char *password, int flags,
3199 int signing_state)
3201 NTSTATUS nt_status;
3202 struct cli_state *cli = NULL;
3203 int pw_len = password ? strlen(password)+1 : 0;
3205 *output_cli = NULL;
3207 if (password == NULL) {
3208 password = "";
3211 nt_status = cli_start_connection(&cli, my_name, dest_host,
3212 dest_ss, port, signing_state,
3213 flags);
3215 if (!NT_STATUS_IS_OK(nt_status)) {
3216 return nt_status;
3219 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3220 cli->use_level_II_oplocks =
3221 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3223 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3224 pw_len, domain);
3225 if (!NT_STATUS_IS_OK(nt_status)) {
3227 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3228 DEBUG(1,("failed session setup with %s\n",
3229 nt_errstr(nt_status)));
3230 cli_shutdown(cli);
3231 return nt_status;
3234 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3235 if (!NT_STATUS_IS_OK(nt_status)) {
3236 DEBUG(1,("anonymous failed session setup with %s\n",
3237 nt_errstr(nt_status)));
3238 cli_shutdown(cli);
3239 return nt_status;
3243 if (service) {
3244 nt_status = cli_tcon_andx(cli, service, service_type, password,
3245 pw_len);
3246 if (!NT_STATUS_IS_OK(nt_status)) {
3247 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3248 cli_shutdown(cli);
3249 if (NT_STATUS_IS_OK(nt_status)) {
3250 nt_status = NT_STATUS_UNSUCCESSFUL;
3252 return nt_status;
3256 nt_status = cli_init_creds(cli, user, domain, password);
3257 if (!NT_STATUS_IS_OK(nt_status)) {
3258 cli_shutdown(cli);
3259 return nt_status;
3262 *output_cli = cli;
3263 return NT_STATUS_OK;
3266 /****************************************************************************
3267 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3268 ****************************************************************************/
3270 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
3271 struct sockaddr_storage *pdest_ss)
3273 struct nmb_name calling, called;
3275 make_nmb_name(&calling, srchost, 0x0);
3278 * If the called name is an IP address
3279 * then use *SMBSERVER immediately.
3282 if(is_ipaddress(desthost)) {
3283 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
3284 } else {
3285 make_nmb_name(&called, desthost, 0x20);
3288 if (!cli_session_request(*ppcli, &calling, &called)) {
3289 NTSTATUS status;
3290 struct nmb_name smbservername;
3292 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
3295 * If the name wasn't *SMBSERVER then
3296 * try with *SMBSERVER if the first name fails.
3299 if (nmb_name_equal(&called, &smbservername)) {
3302 * The name used was *SMBSERVER, don't bother with another name.
3305 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3306 with error %s.\n", desthost, cli_errstr(*ppcli) ));
3307 return False;
3310 /* Try again... */
3311 cli_shutdown(*ppcli);
3313 *ppcli = cli_initialise();
3314 if (!*ppcli) {
3315 /* Out of memory... */
3316 return False;
3319 status = cli_connect(*ppcli, desthost, pdest_ss);
3320 if (!NT_STATUS_IS_OK(status) ||
3321 !cli_session_request(*ppcli, &calling, &smbservername)) {
3322 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3323 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
3324 return False;
3328 return True;
3331 /****************************************************************************
3332 Send an old style tcon.
3333 ****************************************************************************/
3334 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3335 const char *service, const char *pass, const char *dev,
3336 uint16 *max_xmit, uint16 *tid)
3338 struct tevent_req *req;
3339 uint16_t *ret_vwv;
3340 uint8_t *bytes;
3341 NTSTATUS status;
3343 if (!lp_client_plaintext_auth() && (*pass)) {
3344 DEBUG(1, ("Server requested plaintext password but 'client "
3345 "plaintext auth' is disabled\n"));
3346 return NT_STATUS_ACCESS_DENIED;
3349 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3350 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3351 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3352 service, strlen(service)+1, NULL);
3353 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3354 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3355 pass, strlen(pass)+1, NULL);
3356 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3357 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3358 dev, strlen(dev)+1, NULL);
3360 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3361 talloc_get_size(bytes), bytes, &req,
3362 2, NULL, &ret_vwv, NULL, NULL);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 return status;
3367 *max_xmit = SVAL(ret_vwv + 0, 0);
3368 *tid = SVAL(ret_vwv + 1, 0);
3370 return NT_STATUS_OK;
3373 /* Return a cli_state pointing at the IPC$ share for the given server */
3375 struct cli_state *get_ipc_connect(char *server,
3376 struct sockaddr_storage *server_ss,
3377 const struct user_auth_info *user_info)
3379 struct cli_state *cli;
3380 NTSTATUS nt_status;
3381 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3383 if (user_info->use_kerberos) {
3384 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3387 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3388 user_info->username ? user_info->username : "",
3389 lp_workgroup(),
3390 user_info->password ? user_info->password : "",
3391 flags,
3392 Undefined);
3394 if (NT_STATUS_IS_OK(nt_status)) {
3395 return cli;
3396 } else if (is_ipaddress(server)) {
3397 /* windows 9* needs a correct NMB name for connections */
3398 fstring remote_name;
3400 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3401 cli = get_ipc_connect(remote_name, server_ss, user_info);
3402 if (cli)
3403 return cli;
3406 return NULL;
3410 * Given the IP address of a master browser on the network, return its
3411 * workgroup and connect to it.
3413 * This function is provided to allow additional processing beyond what
3414 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3415 * browsers and obtain each master browsers' list of domains (in case the
3416 * first master browser is recently on the network and has not yet
3417 * synchronized with other master browsers and therefore does not yet have the
3418 * entire network browse list)
3421 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3422 struct sockaddr_storage *mb_ip,
3423 const struct user_auth_info *user_info,
3424 char **pp_workgroup_out)
3426 char addr[INET6_ADDRSTRLEN];
3427 fstring name;
3428 struct cli_state *cli;
3429 struct sockaddr_storage server_ss;
3431 *pp_workgroup_out = NULL;
3433 print_sockaddr(addr, sizeof(addr), mb_ip);
3434 DEBUG(99, ("Looking up name of master browser %s\n",
3435 addr));
3438 * Do a name status query to find out the name of the master browser.
3439 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3440 * master browser will not respond to a wildcard query (or, at least,
3441 * an NT4 server acting as the domain master browser will not).
3443 * We might be able to use ONLY the query on MSBROWSE, but that's not
3444 * yet been tested with all Windows versions, so until it is, leave
3445 * the original wildcard query as the first choice and fall back to
3446 * MSBROWSE if the wildcard query fails.
3448 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3449 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3451 DEBUG(99, ("Could not retrieve name status for %s\n",
3452 addr));
3453 return NULL;
3456 if (!find_master_ip(name, &server_ss)) {
3457 DEBUG(99, ("Could not find master ip for %s\n", name));
3458 return NULL;
3461 *pp_workgroup_out = talloc_strdup(ctx, name);
3463 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3465 print_sockaddr(addr, sizeof(addr), &server_ss);
3466 cli = get_ipc_connect(addr, &server_ss, user_info);
3468 return cli;
3472 * Return the IP address and workgroup of a master browser on the network, and
3473 * connect to it.
3476 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3477 const struct user_auth_info *user_info,
3478 char **pp_workgroup_out)
3480 struct sockaddr_storage *ip_list;
3481 struct cli_state *cli;
3482 int i, count;
3483 NTSTATUS status;
3485 *pp_workgroup_out = NULL;
3487 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3489 /* Go looking for workgroups by broadcasting on the local network */
3491 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3492 &ip_list, &count);
3493 if (!NT_STATUS_IS_OK(status)) {
3494 DEBUG(99, ("No master browsers responded: %s\n",
3495 nt_errstr(status)));
3496 return False;
3499 for (i = 0; i < count; i++) {
3500 char addr[INET6_ADDRSTRLEN];
3501 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3502 DEBUG(99, ("Found master browser %s\n", addr));
3504 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3505 user_info, pp_workgroup_out);
3506 if (cli)
3507 return(cli);
3510 return NULL;