Remove fstrings from client struct. Properly talloc strings (ensuring we never end...
[Samba.git] / source3 / libsmb / cliconnect.c
blob3678ec80c339abb8e4cb479d4a91c17d4185294e
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
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "popt_common.h"
23 #include "../libcli/auth/libcli_auth.h"
24 #include "../libcli/auth/spnego.h"
25 #include "smb_krb5.h"
26 #include "../libcli/auth/ntlmssp.h"
27 #include "libads/kerberos_proto.h"
28 #include "krb5_env.h"
29 #include "async_smb.h"
30 #include "libsmb/nmblib.h"
32 static const struct {
33 int prot;
34 const char name[24];
35 } prots[10] = {
36 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
37 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
38 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
39 {PROTOCOL_LANMAN1, "LANMAN1.0"},
40 {PROTOCOL_LANMAN2, "LM1.2X002"},
41 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
42 {PROTOCOL_LANMAN2, "LANMAN2.1"},
43 {PROTOCOL_LANMAN2, "Samba"},
44 {PROTOCOL_NT1, "NT LANMAN 1.0"},
45 {PROTOCOL_NT1, "NT LM 0.12"},
48 #define STAR_SMBSERVER "*SMBSERVER"
50 /********************************************************
51 Utility function to ensure we always return at least
52 a valid char * pointer to an empty string for the
53 cli->server_os, cli->server_type and cli->server_domain
54 strings.
55 *******************************************************/
57 static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
58 char *inbuf,
59 char **dest,
60 uint8_t *src,
61 size_t srclen,
62 ssize_t *destlen)
64 *destlen = clistr_pull_talloc(cli,
65 inbuf,
66 SVAL(inbuf, smb_flg2),
67 dest,
68 (char *)src,
69 srclen,
70 STR_TERMINATE);
71 if (*destlen == -1) {
72 return NT_STATUS_NO_MEMORY;
75 if (*dest == NULL) {
76 *dest = talloc_strdup(cli, "");
77 if (*dest == NULL) {
78 return NT_STATUS_NO_MEMORY;
81 return NT_STATUS_OK;
84 /**
85 * Set the user session key for a connection
86 * @param cli The cli structure to add it too
87 * @param session_key The session key used. (A copy of this is taken for the cli struct)
91 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
93 cli->user_session_key = data_blob(session_key.data, session_key.length);
96 /****************************************************************************
97 Do an old lanman2 style session setup.
98 ****************************************************************************/
100 struct cli_session_setup_lanman2_state {
101 struct cli_state *cli;
102 uint16_t vwv[10];
103 const char *user;
106 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
108 static struct tevent_req *cli_session_setup_lanman2_send(
109 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
110 struct cli_state *cli, const char *user,
111 const char *pass, size_t passlen,
112 const char *workgroup)
114 struct tevent_req *req, *subreq;
115 struct cli_session_setup_lanman2_state *state;
116 DATA_BLOB lm_response = data_blob_null;
117 uint16_t *vwv;
118 uint8_t *bytes;
119 char *tmp;
121 req = tevent_req_create(mem_ctx, &state,
122 struct cli_session_setup_lanman2_state);
123 if (req == NULL) {
124 return NULL;
126 state->cli = cli;
127 state->user = user;
128 vwv = state->vwv;
131 * LANMAN servers predate NT status codes and Unicode and
132 * ignore those smb flags so we must disable the corresponding
133 * default capabilities that would otherwise cause the Unicode
134 * and NT Status flags to be set (and even returned by the
135 * server)
138 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
141 * if in share level security then don't send a password now
143 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
144 passlen = 0;
147 if (passlen > 0
148 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
149 && passlen != 24) {
151 * Encrypted mode needed, and non encrypted password
152 * supplied.
154 lm_response = data_blob(NULL, 24);
155 if (tevent_req_nomem(lm_response.data, req)) {
156 return tevent_req_post(req, ev);
159 if (!SMBencrypt(pass, cli->secblob.data,
160 (uint8_t *)lm_response.data)) {
161 DEBUG(1, ("Password is > 14 chars in length, and is "
162 "therefore incompatible with Lanman "
163 "authentication\n"));
164 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
165 return tevent_req_post(req, ev);
167 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
168 && passlen == 24) {
170 * Encrypted mode needed, and encrypted password
171 * supplied.
173 lm_response = data_blob(pass, passlen);
174 if (tevent_req_nomem(lm_response.data, req)) {
175 return tevent_req_post(req, ev);
177 } else if (passlen > 0) {
178 uint8_t *buf;
179 size_t converted_size;
181 * Plaintext mode needed, assume plaintext supplied.
183 buf = talloc_array(talloc_tos(), uint8_t, 0);
184 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
185 &converted_size);
186 if (tevent_req_nomem(buf, req)) {
187 return tevent_req_post(req, ev);
189 lm_response = data_blob(pass, passlen);
190 TALLOC_FREE(buf);
191 if (tevent_req_nomem(lm_response.data, req)) {
192 return tevent_req_post(req, ev);
196 SCVAL(vwv+0, 0, 0xff);
197 SCVAL(vwv+0, 1, 0);
198 SSVAL(vwv+1, 0, 0);
199 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
200 SSVAL(vwv+3, 0, 2);
201 SSVAL(vwv+4, 0, 1);
202 SIVAL(vwv+5, 0, cli->sesskey);
203 SSVAL(vwv+7, 0, lm_response.length);
205 bytes = talloc_array(state, uint8_t, lm_response.length);
206 if (tevent_req_nomem(bytes, req)) {
207 return tevent_req_post(req, ev);
209 if (lm_response.length != 0) {
210 memcpy(bytes, lm_response.data, lm_response.length);
212 data_blob_free(&lm_response);
214 tmp = talloc_strdup_upper(talloc_tos(), user);
215 if (tevent_req_nomem(tmp, req)) {
216 return tevent_req_post(req, ev);
218 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
219 NULL);
220 TALLOC_FREE(tmp);
222 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
223 if (tevent_req_nomem(tmp, req)) {
224 return tevent_req_post(req, ev);
226 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
227 NULL);
228 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
229 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
231 if (tevent_req_nomem(bytes, req)) {
232 return tevent_req_post(req, ev);
235 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
236 talloc_get_size(bytes), bytes);
237 if (tevent_req_nomem(subreq, req)) {
238 return tevent_req_post(req, ev);
240 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
241 return req;
244 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
246 struct tevent_req *req = tevent_req_callback_data(
247 subreq, struct tevent_req);
248 struct cli_session_setup_lanman2_state *state = tevent_req_data(
249 req, struct cli_session_setup_lanman2_state);
250 struct cli_state *cli = state->cli;
251 uint32_t num_bytes;
252 uint8_t *in;
253 char *inbuf;
254 uint8_t *bytes;
255 uint8_t *p;
256 NTSTATUS status;
257 ssize_t ret;
259 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
260 &num_bytes, &bytes);
261 TALLOC_FREE(subreq);
262 if (!NT_STATUS_IS_OK(status)) {
263 tevent_req_nterror(req, status);
264 return;
267 inbuf = (char *)in;
268 p = bytes;
270 cli->vuid = SVAL(inbuf, smb_uid);
272 status = smb_bytes_talloc_string(cli,
273 inbuf,
274 &cli->server_os,
276 bytes+num_bytes-p,
277 &ret);
279 if (!NT_STATUS_IS_OK(status)) {
280 tevent_req_nterror(req, status);
281 return;
283 p += ret;
285 status = smb_bytes_talloc_string(cli,
286 inbuf,
287 &cli->server_type,
289 bytes+num_bytes-p,
290 &ret);
292 if (!NT_STATUS_IS_OK(status)) {
293 tevent_req_nterror(req, status);
294 return;
296 p += ret;
298 status = smb_bytes_talloc_string(cli,
299 inbuf,
300 &cli->server_domain,
302 bytes+num_bytes-p,
303 &ret);
305 if (!NT_STATUS_IS_OK(status)) {
306 tevent_req_nterror(req, status);
307 return;
309 p += ret;
311 if (strstr(cli->server_type, "Samba")) {
312 cli->is_samba = True;
314 status = cli_set_username(cli, state->user);
315 if (tevent_req_nterror(req, status)) {
316 return;
318 tevent_req_done(req);
321 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
323 return tevent_req_simple_recv_ntstatus(req);
326 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
327 const char *pass, size_t passlen,
328 const char *workgroup)
330 TALLOC_CTX *frame = talloc_stackframe();
331 struct event_context *ev;
332 struct tevent_req *req;
333 NTSTATUS status = NT_STATUS_NO_MEMORY;
335 if (cli_has_async_calls(cli)) {
337 * Can't use sync call while an async call is in flight
339 status = NT_STATUS_INVALID_PARAMETER;
340 goto fail;
342 ev = event_context_init(frame);
343 if (ev == NULL) {
344 goto fail;
346 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
347 workgroup);
348 if (req == NULL) {
349 goto fail;
351 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
352 goto fail;
354 status = cli_session_setup_lanman2_recv(req);
355 fail:
356 TALLOC_FREE(frame);
357 if (!NT_STATUS_IS_OK(status)) {
358 cli_set_error(cli, status);
360 return status;
363 /****************************************************************************
364 Work out suitable capabilities to offer the server.
365 ****************************************************************************/
367 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
369 uint32 capabilities = CAP_NT_SMBS;
371 if (!cli->force_dos_errors)
372 capabilities |= CAP_STATUS32;
374 if (cli->use_level_II_oplocks)
375 capabilities |= CAP_LEVEL_II_OPLOCKS;
377 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
378 return capabilities;
381 /****************************************************************************
382 Do a NT1 guest session setup.
383 ****************************************************************************/
385 struct cli_session_setup_guest_state {
386 struct cli_state *cli;
387 uint16_t vwv[13];
388 struct iovec bytes;
391 static void cli_session_setup_guest_done(struct tevent_req *subreq);
393 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
394 struct event_context *ev,
395 struct cli_state *cli,
396 struct tevent_req **psmbreq)
398 struct tevent_req *req, *subreq;
399 struct cli_session_setup_guest_state *state;
400 uint16_t *vwv;
401 uint8_t *bytes;
403 req = tevent_req_create(mem_ctx, &state,
404 struct cli_session_setup_guest_state);
405 if (req == NULL) {
406 return NULL;
408 state->cli = cli;
409 vwv = state->vwv;
411 SCVAL(vwv+0, 0, 0xFF);
412 SCVAL(vwv+0, 1, 0);
413 SSVAL(vwv+1, 0, 0);
414 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
415 SSVAL(vwv+3, 0, 2);
416 SSVAL(vwv+4, 0, cli->pid);
417 SIVAL(vwv+5, 0, cli->sesskey);
418 SSVAL(vwv+7, 0, 0);
419 SSVAL(vwv+8, 0, 0);
420 SSVAL(vwv+9, 0, 0);
421 SSVAL(vwv+10, 0, 0);
422 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
424 bytes = talloc_array(state, uint8_t, 0);
426 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
427 NULL);
428 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
429 NULL);
430 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
431 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
433 if (bytes == NULL) {
434 TALLOC_FREE(req);
435 return NULL;
438 state->bytes.iov_base = (void *)bytes;
439 state->bytes.iov_len = talloc_get_size(bytes);
441 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
442 1, &state->bytes);
443 if (subreq == NULL) {
444 TALLOC_FREE(req);
445 return NULL;
447 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
448 *psmbreq = subreq;
449 return req;
452 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
453 struct event_context *ev,
454 struct cli_state *cli)
456 struct tevent_req *req, *subreq;
457 NTSTATUS status;
459 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
460 if (req == NULL) {
461 return NULL;
464 status = cli_smb_req_send(subreq);
465 if (NT_STATUS_IS_OK(status)) {
466 tevent_req_nterror(req, status);
467 return tevent_req_post(req, ev);
469 return req;
472 static void cli_session_setup_guest_done(struct tevent_req *subreq)
474 struct tevent_req *req = tevent_req_callback_data(
475 subreq, struct tevent_req);
476 struct cli_session_setup_guest_state *state = tevent_req_data(
477 req, struct cli_session_setup_guest_state);
478 struct cli_state *cli = state->cli;
479 uint32_t num_bytes;
480 uint8_t *in;
481 char *inbuf;
482 uint8_t *bytes;
483 uint8_t *p;
484 NTSTATUS status;
485 ssize_t ret;
487 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
488 &num_bytes, &bytes);
489 TALLOC_FREE(subreq);
490 if (!NT_STATUS_IS_OK(status)) {
491 tevent_req_nterror(req, status);
492 return;
495 inbuf = (char *)in;
496 p = bytes;
498 cli->vuid = SVAL(inbuf, smb_uid);
500 status = smb_bytes_talloc_string(cli,
501 inbuf,
502 &cli->server_os,
504 bytes+num_bytes-p,
505 &ret);
507 if (!NT_STATUS_IS_OK(status)) {
508 tevent_req_nterror(req, status);
509 return;
511 p += ret;
513 status = smb_bytes_talloc_string(cli,
514 inbuf,
515 &cli->server_type,
517 bytes+num_bytes-p,
518 &ret);
520 if (!NT_STATUS_IS_OK(status)) {
521 tevent_req_nterror(req, status);
522 return;
524 p += ret;
526 status = smb_bytes_talloc_string(cli,
527 inbuf,
528 &cli->server_domain,
530 bytes+num_bytes-p,
531 &ret);
533 if (!NT_STATUS_IS_OK(status)) {
534 tevent_req_nterror(req, status);
535 return;
537 p += ret;
539 if (strstr(cli->server_type, "Samba")) {
540 cli->is_samba = True;
543 status = cli_set_username(cli, "");
544 if (!NT_STATUS_IS_OK(status)) {
545 tevent_req_nterror(req, status);
546 return;
548 tevent_req_done(req);
551 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
553 return tevent_req_simple_recv_ntstatus(req);
556 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
558 TALLOC_CTX *frame = talloc_stackframe();
559 struct event_context *ev;
560 struct tevent_req *req;
561 NTSTATUS status = NT_STATUS_OK;
563 if (cli_has_async_calls(cli)) {
565 * Can't use sync call while an async call is in flight
567 status = NT_STATUS_INVALID_PARAMETER;
568 goto fail;
571 ev = event_context_init(frame);
572 if (ev == NULL) {
573 status = NT_STATUS_NO_MEMORY;
574 goto fail;
577 req = cli_session_setup_guest_send(frame, ev, cli);
578 if (req == NULL) {
579 status = NT_STATUS_NO_MEMORY;
580 goto fail;
583 if (!tevent_req_poll(req, ev)) {
584 status = map_nt_error_from_unix(errno);
585 goto fail;
588 status = cli_session_setup_guest_recv(req);
589 fail:
590 TALLOC_FREE(frame);
591 if (!NT_STATUS_IS_OK(status)) {
592 cli_set_error(cli, status);
594 return status;
597 /****************************************************************************
598 Do a NT1 plaintext session setup.
599 ****************************************************************************/
601 struct cli_session_setup_plain_state {
602 struct cli_state *cli;
603 uint16_t vwv[13];
604 const char *user;
607 static void cli_session_setup_plain_done(struct tevent_req *subreq);
609 static struct tevent_req *cli_session_setup_plain_send(
610 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
611 struct cli_state *cli,
612 const char *user, const char *pass, const char *workgroup)
614 struct tevent_req *req, *subreq;
615 struct cli_session_setup_plain_state *state;
616 uint16_t *vwv;
617 uint8_t *bytes;
618 size_t passlen;
619 char *version;
621 req = tevent_req_create(mem_ctx, &state,
622 struct cli_session_setup_plain_state);
623 if (req == NULL) {
624 return NULL;
626 state->cli = cli;
627 state->user = user;
628 vwv = state->vwv;
630 SCVAL(vwv+0, 0, 0xff);
631 SCVAL(vwv+0, 1, 0);
632 SSVAL(vwv+1, 0, 0);
633 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
634 SSVAL(vwv+3, 0, 2);
635 SSVAL(vwv+4, 0, cli->pid);
636 SIVAL(vwv+5, 0, cli->sesskey);
637 SSVAL(vwv+7, 0, 0);
638 SSVAL(vwv+8, 0, 0);
639 SSVAL(vwv+9, 0, 0);
640 SSVAL(vwv+10, 0, 0);
641 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
643 bytes = talloc_array(state, uint8_t, 0);
644 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
645 &passlen);
646 if (tevent_req_nomem(bytes, req)) {
647 return tevent_req_post(req, ev);
649 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
651 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
652 user, strlen(user)+1, NULL);
653 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
654 workgroup, strlen(workgroup)+1, NULL);
655 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
656 "Unix", 5, NULL);
658 version = talloc_asprintf(talloc_tos(), "Samba %s",
659 samba_version_string());
660 if (tevent_req_nomem(version, req)){
661 return tevent_req_post(req, ev);
663 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
664 version, strlen(version)+1, NULL);
665 TALLOC_FREE(version);
667 if (tevent_req_nomem(bytes, req)) {
668 return tevent_req_post(req, ev);
671 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
672 talloc_get_size(bytes), bytes);
673 if (tevent_req_nomem(subreq, req)) {
674 return tevent_req_post(req, ev);
676 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
677 return req;
680 static void cli_session_setup_plain_done(struct tevent_req *subreq)
682 struct tevent_req *req = tevent_req_callback_data(
683 subreq, struct tevent_req);
684 struct cli_session_setup_plain_state *state = tevent_req_data(
685 req, struct cli_session_setup_plain_state);
686 struct cli_state *cli = state->cli;
687 uint32_t num_bytes;
688 uint8_t *in;
689 char *inbuf;
690 uint8_t *bytes;
691 uint8_t *p;
692 NTSTATUS status;
693 ssize_t ret;
695 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
696 &num_bytes, &bytes);
697 TALLOC_FREE(subreq);
698 if (tevent_req_nterror(req, status)) {
699 return;
702 inbuf = (char *)in;
703 p = bytes;
705 cli->vuid = SVAL(inbuf, smb_uid);
707 status = smb_bytes_talloc_string(cli,
708 inbuf,
709 &cli->server_os,
711 bytes+num_bytes-p,
712 &ret);
714 if (!NT_STATUS_IS_OK(status)) {
715 tevent_req_nterror(req, status);
716 return;
718 p += ret;
720 status = smb_bytes_talloc_string(cli,
721 inbuf,
722 &cli->server_type,
724 bytes+num_bytes-p,
725 &ret);
727 if (!NT_STATUS_IS_OK(status)) {
728 tevent_req_nterror(req, status);
729 return;
731 p += ret;
733 status = smb_bytes_talloc_string(cli,
734 inbuf,
735 &cli->server_domain,
737 bytes+num_bytes-p,
738 &ret);
740 if (!NT_STATUS_IS_OK(status)) {
741 tevent_req_nterror(req, status);
742 return;
744 p += ret;
746 status = cli_set_username(cli, state->user);
747 if (tevent_req_nterror(req, status)) {
748 return;
750 if (strstr(cli->server_type, "Samba")) {
751 cli->is_samba = True;
753 tevent_req_done(req);
756 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
758 return tevent_req_simple_recv_ntstatus(req);
761 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
762 const char *user, const char *pass,
763 const char *workgroup)
765 TALLOC_CTX *frame = talloc_stackframe();
766 struct event_context *ev;
767 struct tevent_req *req;
768 NTSTATUS status = NT_STATUS_NO_MEMORY;
770 if (cli_has_async_calls(cli)) {
772 * Can't use sync call while an async call is in flight
774 status = NT_STATUS_INVALID_PARAMETER;
775 goto fail;
777 ev = event_context_init(frame);
778 if (ev == NULL) {
779 goto fail;
781 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
782 workgroup);
783 if (req == NULL) {
784 goto fail;
786 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
787 goto fail;
789 status = cli_session_setup_plain_recv(req);
790 fail:
791 TALLOC_FREE(frame);
792 if (!NT_STATUS_IS_OK(status)) {
793 cli_set_error(cli, status);
795 return status;
798 /****************************************************************************
799 do a NT1 NTLM/LM encrypted session setup - for when extended security
800 is not negotiated.
801 @param cli client state to create do session setup on
802 @param user username
803 @param pass *either* cleartext password (passlen !=24) or LM response.
804 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
805 @param workgroup The user's domain.
806 ****************************************************************************/
808 struct cli_session_setup_nt1_state {
809 struct cli_state *cli;
810 uint16_t vwv[13];
811 DATA_BLOB response;
812 DATA_BLOB session_key;
813 const char *user;
816 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
818 static struct tevent_req *cli_session_setup_nt1_send(
819 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
820 struct cli_state *cli, const char *user,
821 const char *pass, size_t passlen,
822 const char *ntpass, size_t ntpasslen,
823 const char *workgroup)
825 struct tevent_req *req, *subreq;
826 struct cli_session_setup_nt1_state *state;
827 DATA_BLOB lm_response = data_blob_null;
828 DATA_BLOB nt_response = data_blob_null;
829 DATA_BLOB session_key = data_blob_null;
830 uint16_t *vwv;
831 uint8_t *bytes;
832 char *workgroup_upper;
834 req = tevent_req_create(mem_ctx, &state,
835 struct cli_session_setup_nt1_state);
836 if (req == NULL) {
837 return NULL;
839 state->cli = cli;
840 state->user = user;
841 vwv = state->vwv;
843 if (passlen == 0) {
844 /* do nothing - guest login */
845 } else if (passlen != 24) {
846 if (lp_client_ntlmv2_auth()) {
847 DATA_BLOB server_chal;
848 DATA_BLOB names_blob;
850 server_chal = data_blob(cli->secblob.data,
851 MIN(cli->secblob.length, 8));
852 if (tevent_req_nomem(server_chal.data, req)) {
853 return tevent_req_post(req, ev);
857 * note that the 'workgroup' here is a best
858 * guess - we don't know the server's domain
859 * at this point. The 'server name' is also
860 * dodgy...
862 names_blob = NTLMv2_generate_names_blob(
863 NULL, cli->called.name, workgroup);
865 if (tevent_req_nomem(names_blob.data, req)) {
866 return tevent_req_post(req, ev);
869 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
870 &server_chal, &names_blob,
871 &lm_response, &nt_response,
872 NULL, &session_key)) {
873 data_blob_free(&names_blob);
874 data_blob_free(&server_chal);
875 tevent_req_nterror(
876 req, NT_STATUS_ACCESS_DENIED);
877 return tevent_req_post(req, ev);
879 data_blob_free(&names_blob);
880 data_blob_free(&server_chal);
882 } else {
883 uchar nt_hash[16];
884 E_md4hash(pass, nt_hash);
886 #ifdef LANMAN_ONLY
887 nt_response = data_blob_null;
888 #else
889 nt_response = data_blob(NULL, 24);
890 if (tevent_req_nomem(nt_response.data, req)) {
891 return tevent_req_post(req, ev);
894 SMBNTencrypt(pass, cli->secblob.data,
895 nt_response.data);
896 #endif
897 /* non encrypted password supplied. Ignore ntpass. */
898 if (lp_client_lanman_auth()) {
900 lm_response = data_blob(NULL, 24);
901 if (tevent_req_nomem(lm_response.data, req)) {
902 return tevent_req_post(req, ev);
905 if (!SMBencrypt(pass,cli->secblob.data,
906 lm_response.data)) {
908 * Oops, the LM response is
909 * invalid, just put the NT
910 * response there instead
912 data_blob_free(&lm_response);
913 lm_response = data_blob(
914 nt_response.data,
915 nt_response.length);
917 } else {
919 * LM disabled, place NT# in LM field
920 * instead
922 lm_response = data_blob(
923 nt_response.data, nt_response.length);
926 if (tevent_req_nomem(lm_response.data, req)) {
927 return tevent_req_post(req, ev);
930 session_key = data_blob(NULL, 16);
931 if (tevent_req_nomem(session_key.data, req)) {
932 return tevent_req_post(req, ev);
934 #ifdef LANMAN_ONLY
935 E_deshash(pass, session_key.data);
936 memset(&session_key.data[8], '\0', 8);
937 #else
938 SMBsesskeygen_ntv1(nt_hash, session_key.data);
939 #endif
941 cli_temp_set_signing(cli);
942 } else {
943 /* pre-encrypted password supplied. Only used for
944 security=server, can't do
945 signing because we don't have original key */
947 lm_response = data_blob(pass, passlen);
948 if (tevent_req_nomem(lm_response.data, req)) {
949 return tevent_req_post(req, ev);
952 nt_response = data_blob(ntpass, ntpasslen);
953 if (tevent_req_nomem(nt_response.data, req)) {
954 return tevent_req_post(req, ev);
958 #ifdef LANMAN_ONLY
959 state->response = data_blob_talloc(
960 state, lm_response.data, lm_response.length);
961 #else
962 state->response = data_blob_talloc(
963 state, nt_response.data, nt_response.length);
964 #endif
965 if (tevent_req_nomem(state->response.data, req)) {
966 return tevent_req_post(req, ev);
969 if (session_key.data) {
970 state->session_key = data_blob_talloc(
971 state, session_key.data, session_key.length);
972 if (tevent_req_nomem(state->session_key.data, req)) {
973 return tevent_req_post(req, ev);
976 data_blob_free(&session_key);
978 SCVAL(vwv+0, 0, 0xff);
979 SCVAL(vwv+0, 1, 0);
980 SSVAL(vwv+1, 0, 0);
981 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
982 SSVAL(vwv+3, 0, 2);
983 SSVAL(vwv+4, 0, cli->pid);
984 SIVAL(vwv+5, 0, cli->sesskey);
985 SSVAL(vwv+7, 0, lm_response.length);
986 SSVAL(vwv+8, 0, nt_response.length);
987 SSVAL(vwv+9, 0, 0);
988 SSVAL(vwv+10, 0, 0);
989 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
991 bytes = talloc_array(state, uint8_t,
992 lm_response.length + nt_response.length);
993 if (tevent_req_nomem(bytes, req)) {
994 return tevent_req_post(req, ev);
996 if (lm_response.length != 0) {
997 memcpy(bytes, lm_response.data, lm_response.length);
999 if (nt_response.length != 0) {
1000 memcpy(bytes + lm_response.length,
1001 nt_response.data, nt_response.length);
1003 data_blob_free(&lm_response);
1004 data_blob_free(&nt_response);
1006 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1007 user, strlen(user)+1, NULL);
1010 * Upper case here might help some NTLMv2 implementations
1012 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1013 if (tevent_req_nomem(workgroup_upper, req)) {
1014 return tevent_req_post(req, ev);
1016 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1017 workgroup_upper, strlen(workgroup_upper)+1,
1018 NULL);
1019 TALLOC_FREE(workgroup_upper);
1021 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1022 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1023 if (tevent_req_nomem(bytes, req)) {
1024 return tevent_req_post(req, ev);
1027 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1028 talloc_get_size(bytes), bytes);
1029 if (tevent_req_nomem(subreq, req)) {
1030 return tevent_req_post(req, ev);
1032 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1033 return req;
1036 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1038 struct tevent_req *req = tevent_req_callback_data(
1039 subreq, struct tevent_req);
1040 struct cli_session_setup_nt1_state *state = tevent_req_data(
1041 req, struct cli_session_setup_nt1_state);
1042 struct cli_state *cli = state->cli;
1043 uint32_t num_bytes;
1044 uint8_t *in;
1045 char *inbuf;
1046 uint8_t *bytes;
1047 uint8_t *p;
1048 NTSTATUS status;
1049 ssize_t ret;
1051 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
1052 &num_bytes, &bytes);
1053 TALLOC_FREE(subreq);
1054 if (!NT_STATUS_IS_OK(status)) {
1055 tevent_req_nterror(req, status);
1056 return;
1059 inbuf = (char *)in;
1060 p = bytes;
1062 cli->vuid = SVAL(inbuf, smb_uid);
1064 status = smb_bytes_talloc_string(cli,
1065 inbuf,
1066 &cli->server_os,
1068 bytes+num_bytes-p,
1069 &ret);
1070 if (!NT_STATUS_IS_OK(status)) {
1071 tevent_req_nterror(req, status);
1072 return;
1074 p += ret;
1076 status = smb_bytes_talloc_string(cli,
1077 inbuf,
1078 &cli->server_type,
1080 bytes+num_bytes-p,
1081 &ret);
1082 if (!NT_STATUS_IS_OK(status)) {
1083 tevent_req_nterror(req, status);
1084 return;
1086 p += ret;
1088 status = smb_bytes_talloc_string(cli,
1089 inbuf,
1090 &cli->server_domain,
1092 bytes+num_bytes-p,
1093 &ret);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 tevent_req_nterror(req, status);
1096 return;
1098 p += ret;
1100 if (strstr(cli->server_type, "Samba")) {
1101 cli->is_samba = True;
1104 status = cli_set_username(cli, state->user);
1105 if (tevent_req_nterror(req, status)) {
1106 return;
1108 if (cli_simple_set_signing(cli, state->session_key, state->response)
1109 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1110 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1111 return;
1113 if (state->session_key.data) {
1114 /* Have plaintext orginal */
1115 cli_set_session_key(cli, state->session_key);
1117 tevent_req_done(req);
1120 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1122 return tevent_req_simple_recv_ntstatus(req);
1125 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1126 const char *pass, size_t passlen,
1127 const char *ntpass, size_t ntpasslen,
1128 const char *workgroup)
1130 TALLOC_CTX *frame = talloc_stackframe();
1131 struct event_context *ev;
1132 struct tevent_req *req;
1133 NTSTATUS status = NT_STATUS_NO_MEMORY;
1135 if (cli_has_async_calls(cli)) {
1137 * Can't use sync call while an async call is in flight
1139 status = NT_STATUS_INVALID_PARAMETER;
1140 goto fail;
1142 ev = event_context_init(frame);
1143 if (ev == NULL) {
1144 goto fail;
1146 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1147 ntpass, ntpasslen, workgroup);
1148 if (req == NULL) {
1149 goto fail;
1151 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1152 goto fail;
1154 status = cli_session_setup_nt1_recv(req);
1155 fail:
1156 TALLOC_FREE(frame);
1157 if (!NT_STATUS_IS_OK(status)) {
1158 cli_set_error(cli, status);
1160 return status;
1163 /* The following is calculated from :
1164 * (smb_size-4) = 35
1165 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1166 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1167 * end of packet.
1170 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1172 struct cli_sesssetup_blob_state {
1173 struct tevent_context *ev;
1174 struct cli_state *cli;
1175 DATA_BLOB blob;
1176 uint16_t max_blob_size;
1177 uint16_t vwv[12];
1178 uint8_t *buf;
1180 NTSTATUS status;
1181 char *inbuf;
1182 DATA_BLOB ret_blob;
1185 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1186 struct tevent_req **psubreq);
1187 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1189 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1190 struct tevent_context *ev,
1191 struct cli_state *cli,
1192 DATA_BLOB blob)
1194 struct tevent_req *req, *subreq;
1195 struct cli_sesssetup_blob_state *state;
1197 req = tevent_req_create(mem_ctx, &state,
1198 struct cli_sesssetup_blob_state);
1199 if (req == NULL) {
1200 return NULL;
1202 state->ev = ev;
1203 state->blob = blob;
1204 state->cli = cli;
1206 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1207 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1208 "(was %u, need minimum %u)\n",
1209 (unsigned int)cli->max_xmit,
1210 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1211 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1212 return tevent_req_post(req, ev);
1214 state->max_blob_size =
1215 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1217 if (!cli_sesssetup_blob_next(state, &subreq)) {
1218 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1219 return tevent_req_post(req, ev);
1221 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1222 return req;
1225 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1226 struct tevent_req **psubreq)
1228 struct tevent_req *subreq;
1229 uint16_t thistime;
1231 SCVAL(state->vwv+0, 0, 0xFF);
1232 SCVAL(state->vwv+0, 1, 0);
1233 SSVAL(state->vwv+1, 0, 0);
1234 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1235 SSVAL(state->vwv+3, 0, 2);
1236 SSVAL(state->vwv+4, 0, 1);
1237 SIVAL(state->vwv+5, 0, 0);
1239 thistime = MIN(state->blob.length, state->max_blob_size);
1240 SSVAL(state->vwv+7, 0, thistime);
1242 SSVAL(state->vwv+8, 0, 0);
1243 SSVAL(state->vwv+9, 0, 0);
1244 SIVAL(state->vwv+10, 0,
1245 cli_session_setup_capabilities(state->cli)
1246 | CAP_EXTENDED_SECURITY);
1248 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1249 thistime);
1250 if (state->buf == NULL) {
1251 return false;
1253 state->blob.data += thistime;
1254 state->blob.length -= thistime;
1256 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1257 "Unix", 5, NULL);
1258 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1259 "Samba", 6, NULL);
1260 if (state->buf == NULL) {
1261 return false;
1263 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1264 12, state->vwv,
1265 talloc_get_size(state->buf), state->buf);
1266 if (subreq == NULL) {
1267 return false;
1269 *psubreq = subreq;
1270 return true;
1273 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1275 struct tevent_req *req = tevent_req_callback_data(
1276 subreq, struct tevent_req);
1277 struct cli_sesssetup_blob_state *state = tevent_req_data(
1278 req, struct cli_sesssetup_blob_state);
1279 struct cli_state *cli = state->cli;
1280 uint8_t wct;
1281 uint16_t *vwv;
1282 uint32_t num_bytes;
1283 uint8_t *bytes;
1284 NTSTATUS status;
1285 uint8_t *p;
1286 uint16_t blob_length;
1287 uint8_t *inbuf;
1288 ssize_t ret;
1290 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
1291 &num_bytes, &bytes);
1292 TALLOC_FREE(subreq);
1293 if (!NT_STATUS_IS_OK(status)
1294 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1295 tevent_req_nterror(req, status);
1296 return;
1299 state->status = status;
1300 TALLOC_FREE(state->buf);
1302 state->inbuf = (char *)inbuf;
1303 cli->vuid = SVAL(state->inbuf, smb_uid);
1305 blob_length = SVAL(vwv+3, 0);
1306 if (blob_length > num_bytes) {
1307 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1308 return;
1310 state->ret_blob = data_blob_const(bytes, blob_length);
1312 p = bytes + blob_length;
1314 status = smb_bytes_talloc_string(cli,
1315 (char *)inbuf,
1316 &cli->server_os,
1318 bytes+num_bytes-p,
1319 &ret);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 tevent_req_nterror(req, status);
1323 return;
1325 p += ret;
1327 status = smb_bytes_talloc_string(cli,
1328 (char *)inbuf,
1329 &cli->server_type,
1331 bytes+num_bytes-p,
1332 &ret);
1334 if (!NT_STATUS_IS_OK(status)) {
1335 tevent_req_nterror(req, status);
1336 return;
1338 p += ret;
1340 status = smb_bytes_talloc_string(cli,
1341 (char *)inbuf,
1342 &cli->server_domain,
1344 bytes+num_bytes-p,
1345 &ret);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 tevent_req_nterror(req, status);
1349 return;
1351 p += ret;
1353 if (strstr(cli->server_type, "Samba")) {
1354 cli->is_samba = True;
1357 if (state->blob.length != 0) {
1359 * More to send
1361 if (!cli_sesssetup_blob_next(state, &subreq)) {
1362 tevent_req_nomem(NULL, req);
1363 return;
1365 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1366 return;
1368 tevent_req_done(req);
1371 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1372 TALLOC_CTX *mem_ctx,
1373 DATA_BLOB *pblob,
1374 char **pinbuf)
1376 struct cli_sesssetup_blob_state *state = tevent_req_data(
1377 req, struct cli_sesssetup_blob_state);
1378 NTSTATUS status;
1379 char *inbuf;
1381 if (tevent_req_is_nterror(req, &status)) {
1382 state->cli->vuid = 0;
1383 return status;
1386 inbuf = talloc_move(mem_ctx, &state->inbuf);
1387 if (pblob != NULL) {
1388 *pblob = state->ret_blob;
1390 if (pinbuf != NULL) {
1391 *pinbuf = inbuf;
1393 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1394 return state->status;
1397 #ifdef HAVE_KRB5
1399 /****************************************************************************
1400 Use in-memory credentials cache
1401 ****************************************************************************/
1403 static void use_in_memory_ccache(void) {
1404 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1407 /****************************************************************************
1408 Do a spnego/kerberos encrypted session setup.
1409 ****************************************************************************/
1411 struct cli_session_setup_kerberos_state {
1412 struct cli_state *cli;
1413 DATA_BLOB negTokenTarg;
1414 DATA_BLOB session_key_krb5;
1415 ADS_STATUS ads_status;
1418 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1420 static struct tevent_req *cli_session_setup_kerberos_send(
1421 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1422 const char *principal, const char *workgroup)
1424 struct tevent_req *req, *subreq;
1425 struct cli_session_setup_kerberos_state *state;
1426 int rc;
1428 DEBUG(2,("Doing kerberos session setup\n"));
1430 req = tevent_req_create(mem_ctx, &state,
1431 struct cli_session_setup_kerberos_state);
1432 if (req == NULL) {
1433 return NULL;
1435 state->cli = cli;
1436 state->ads_status = ADS_SUCCESS;
1438 cli_temp_set_signing(cli);
1441 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1442 * we have to acquire a ticket. To be fixed later :-)
1444 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1445 &state->session_key_krb5, 0, NULL);
1446 if (rc) {
1447 DEBUG(1, ("cli_session_setup_kerberos: "
1448 "spnego_gen_krb5_negTokenInit failed: %s\n",
1449 error_message(rc)));
1450 state->ads_status = ADS_ERROR_KRB5(rc);
1451 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1452 return tevent_req_post(req, ev);
1455 #if 0
1456 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1457 state->negTokenTarg.length);
1458 #endif
1460 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1461 if (tevent_req_nomem(subreq, req)) {
1462 return tevent_req_post(req, ev);
1464 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1465 return req;
1468 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1470 struct tevent_req *req = tevent_req_callback_data(
1471 subreq, struct tevent_req);
1472 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1473 req, struct cli_session_setup_kerberos_state);
1474 char *inbuf = NULL;
1475 NTSTATUS status;
1477 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1478 if (!NT_STATUS_IS_OK(status)) {
1479 TALLOC_FREE(subreq);
1480 tevent_req_nterror(req, status);
1481 return;
1484 cli_set_session_key(state->cli, state->session_key_krb5);
1486 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1487 data_blob_null)
1488 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1489 TALLOC_FREE(subreq);
1490 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1491 return;
1493 TALLOC_FREE(subreq);
1494 tevent_req_done(req);
1497 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1499 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1500 req, struct cli_session_setup_kerberos_state);
1501 NTSTATUS status;
1503 if (tevent_req_is_nterror(req, &status)) {
1504 return ADS_ERROR_NT(status);
1506 return state->ads_status;
1509 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1510 const char *principal,
1511 const char *workgroup)
1513 struct tevent_context *ev;
1514 struct tevent_req *req;
1515 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1517 if (cli_has_async_calls(cli)) {
1518 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1520 ev = tevent_context_init(talloc_tos());
1521 if (ev == NULL) {
1522 goto fail;
1524 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1525 workgroup);
1526 if (req == NULL) {
1527 goto fail;
1529 if (!tevent_req_poll(req, ev)) {
1530 status = ADS_ERROR_SYSTEM(errno);
1531 goto fail;
1533 status = cli_session_setup_kerberos_recv(req);
1534 fail:
1535 TALLOC_FREE(ev);
1536 return status;
1538 #endif /* HAVE_KRB5 */
1540 /****************************************************************************
1541 Do a spnego/NTLMSSP encrypted session setup.
1542 ****************************************************************************/
1544 struct cli_session_setup_ntlmssp_state {
1545 struct tevent_context *ev;
1546 struct cli_state *cli;
1547 struct ntlmssp_state *ntlmssp_state;
1548 int turn;
1549 DATA_BLOB blob_out;
1552 static int cli_session_setup_ntlmssp_state_destructor(
1553 struct cli_session_setup_ntlmssp_state *state)
1555 if (state->ntlmssp_state != NULL) {
1556 TALLOC_FREE(state->ntlmssp_state);
1558 return 0;
1561 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1563 static struct tevent_req *cli_session_setup_ntlmssp_send(
1564 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1565 const char *user, const char *pass, const char *domain)
1567 struct tevent_req *req, *subreq;
1568 struct cli_session_setup_ntlmssp_state *state;
1569 NTSTATUS status;
1570 DATA_BLOB blob_out;
1571 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1573 req = tevent_req_create(mem_ctx, &state,
1574 struct cli_session_setup_ntlmssp_state);
1575 if (req == NULL) {
1576 return NULL;
1578 state->ev = ev;
1579 state->cli = cli;
1580 state->turn = 1;
1582 state->ntlmssp_state = NULL;
1583 talloc_set_destructor(
1584 state, cli_session_setup_ntlmssp_state_destructor);
1586 cli_temp_set_signing(cli);
1588 status = ntlmssp_client_start(state,
1589 global_myname(),
1590 lp_workgroup(),
1591 lp_client_ntlmv2_auth(),
1592 &state->ntlmssp_state);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 goto fail;
1596 ntlmssp_want_feature(state->ntlmssp_state,
1597 NTLMSSP_FEATURE_SESSION_KEY);
1598 if (cli->use_ccache) {
1599 ntlmssp_want_feature(state->ntlmssp_state,
1600 NTLMSSP_FEATURE_CCACHE);
1602 status = ntlmssp_set_username(state->ntlmssp_state, user);
1603 if (!NT_STATUS_IS_OK(status)) {
1604 goto fail;
1606 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 goto fail;
1610 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1611 if (!NT_STATUS_IS_OK(status)) {
1612 goto fail;
1614 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1615 &blob_out);
1616 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1617 goto fail;
1620 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1621 data_blob_free(&blob_out);
1623 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1624 if (tevent_req_nomem(subreq, req)) {
1625 return tevent_req_post(req, ev);
1627 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1628 return req;
1629 fail:
1630 tevent_req_nterror(req, status);
1631 return tevent_req_post(req, ev);
1634 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1636 struct tevent_req *req = tevent_req_callback_data(
1637 subreq, struct tevent_req);
1638 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1639 req, struct cli_session_setup_ntlmssp_state);
1640 DATA_BLOB blob_in, msg_in, blob_out;
1641 char *inbuf = NULL;
1642 bool parse_ret;
1643 NTSTATUS status;
1645 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1646 &inbuf);
1647 TALLOC_FREE(subreq);
1648 data_blob_free(&state->blob_out);
1650 if (NT_STATUS_IS_OK(status)) {
1651 if (state->cli->server_domain[0] == '\0') {
1652 TALLOC_FREE(state->cli->server_domain);
1653 state->cli->server_domain = talloc_strdup(state->cli,
1654 state->ntlmssp_state->server.netbios_domain);
1655 if (state->cli->server_domain == NULL) {
1656 TALLOC_FREE(subreq);
1657 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1658 return;
1661 cli_set_session_key(
1662 state->cli, state->ntlmssp_state->session_key);
1664 if (cli_simple_set_signing(
1665 state->cli, state->ntlmssp_state->session_key,
1666 data_blob_null)
1667 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1668 TALLOC_FREE(subreq);
1669 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1670 return;
1672 TALLOC_FREE(subreq);
1673 TALLOC_FREE(state->ntlmssp_state);
1674 tevent_req_done(req);
1675 return;
1677 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1678 tevent_req_nterror(req, status);
1679 return;
1682 if (blob_in.length == 0) {
1683 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1684 return;
1687 if ((state->turn == 1)
1688 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1689 DATA_BLOB tmp_blob = data_blob_null;
1690 /* the server might give us back two challenges */
1691 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1692 &tmp_blob);
1693 data_blob_free(&tmp_blob);
1694 } else {
1695 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1696 OID_NTLMSSP, &msg_in);
1698 state->turn += 1;
1700 if (!parse_ret) {
1701 DEBUG(3,("Failed to parse auth response\n"));
1702 if (NT_STATUS_IS_OK(status)
1703 || NT_STATUS_EQUAL(status,
1704 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1705 tevent_req_nterror(
1706 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1707 return;
1711 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1713 if (!NT_STATUS_IS_OK(status)
1714 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1715 TALLOC_FREE(subreq);
1716 TALLOC_FREE(state->ntlmssp_state);
1717 tevent_req_nterror(req, status);
1718 return;
1721 state->blob_out = spnego_gen_auth(state, blob_out);
1722 TALLOC_FREE(subreq);
1723 if (tevent_req_nomem(state->blob_out.data, req)) {
1724 return;
1727 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1728 state->blob_out);
1729 if (tevent_req_nomem(subreq, req)) {
1730 return;
1732 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1735 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1737 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1738 req, struct cli_session_setup_ntlmssp_state);
1739 NTSTATUS status;
1741 if (tevent_req_is_nterror(req, &status)) {
1742 state->cli->vuid = 0;
1743 return status;
1745 return NT_STATUS_OK;
1748 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1749 const char *user,
1750 const char *pass,
1751 const char *domain)
1753 struct tevent_context *ev;
1754 struct tevent_req *req;
1755 NTSTATUS status = NT_STATUS_NO_MEMORY;
1757 if (cli_has_async_calls(cli)) {
1758 return NT_STATUS_INVALID_PARAMETER;
1760 ev = tevent_context_init(talloc_tos());
1761 if (ev == NULL) {
1762 goto fail;
1764 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1765 if (req == NULL) {
1766 goto fail;
1768 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1769 goto fail;
1771 status = cli_session_setup_ntlmssp_recv(req);
1772 fail:
1773 TALLOC_FREE(ev);
1774 if (!NT_STATUS_IS_OK(status)) {
1775 cli_set_error(cli, status);
1777 return status;
1780 /****************************************************************************
1781 Do a spnego encrypted session setup.
1783 user_domain: The shortname of the domain the user/machine is a member of.
1784 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1785 ****************************************************************************/
1787 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1788 const char *pass, const char *user_domain,
1789 const char * dest_realm)
1791 char *principal = NULL;
1792 char *OIDs[ASN1_MAX_OIDS];
1793 int i;
1794 DATA_BLOB blob;
1795 const char *p = NULL;
1796 char *account = NULL;
1797 NTSTATUS status;
1799 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1801 /* the server might not even do spnego */
1802 if (cli->secblob.length <= 16) {
1803 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1804 goto ntlmssp;
1807 #if 0
1808 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1809 #endif
1811 /* there is 16 bytes of GUID before the real spnego packet starts */
1812 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1814 /* The server sent us the first part of the SPNEGO exchange in the
1815 * negprot reply. It is WRONG to depend on the principal sent in the
1816 * negprot reply, but right now we do it. If we don't receive one,
1817 * we try to best guess, then fall back to NTLM. */
1818 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1819 OIDs[0] == NULL) {
1820 data_blob_free(&blob);
1821 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1823 data_blob_free(&blob);
1825 /* make sure the server understands kerberos */
1826 for (i=0;OIDs[i];i++) {
1827 if (i == 0)
1828 DEBUG(3,("got OID=%s\n", OIDs[i]));
1829 else
1830 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1831 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1832 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1833 cli->got_kerberos_mechanism = True;
1835 talloc_free(OIDs[i]);
1838 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1840 status = cli_set_username(cli, user);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 TALLOC_FREE(principal);
1843 return ADS_ERROR_NT(status);
1846 #ifdef HAVE_KRB5
1847 /* If password is set we reauthenticate to kerberos server
1848 * and do not store results */
1850 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1851 ADS_STATUS rc;
1853 if (pass && *pass) {
1854 int ret;
1856 use_in_memory_ccache();
1857 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1859 if (ret){
1860 TALLOC_FREE(principal);
1861 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1862 if (cli->fallback_after_kerberos)
1863 goto ntlmssp;
1864 return ADS_ERROR_KRB5(ret);
1868 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1870 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1871 TALLOC_FREE(principal);
1874 if (principal == NULL &&
1875 !is_ipaddress(cli->desthost) &&
1876 !strequal(STAR_SMBSERVER,
1877 cli->desthost)) {
1878 char *realm = NULL;
1879 char *host = NULL;
1880 DEBUG(3,("cli_session_setup_spnego: using target "
1881 "hostname not SPNEGO principal\n"));
1883 host = strchr_m(cli->desthost, '.');
1884 if (dest_realm) {
1885 realm = SMB_STRDUP(dest_realm);
1886 strupper_m(realm);
1887 } else {
1888 if (host) {
1889 /* DNS name. */
1890 realm = kerberos_get_realm_from_hostname(cli->desthost);
1891 } else {
1892 /* NetBIOS name - use our realm. */
1893 realm = kerberos_get_default_realm_from_ccache();
1897 if (realm && *realm) {
1898 principal = talloc_asprintf(talloc_tos(),
1899 "cifs/%s@%s",
1900 cli->desthost,
1901 realm);
1902 if (!principal) {
1903 SAFE_FREE(realm);
1904 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1906 DEBUG(3,("cli_session_setup_spnego: guessed "
1907 "server principal=%s\n",
1908 principal ? principal : "<null>"));
1910 SAFE_FREE(realm);
1913 if (principal) {
1914 rc = cli_session_setup_kerberos(cli, principal,
1915 dest_realm);
1916 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1917 TALLOC_FREE(principal);
1918 return rc;
1922 #endif
1924 TALLOC_FREE(principal);
1926 ntlmssp:
1928 account = talloc_strdup(talloc_tos(), user);
1929 if (!account) {
1930 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1933 /* when falling back to ntlmssp while authenticating with a machine
1934 * account strip off the realm - gd */
1936 if ((p = strchr_m(user, '@')) != NULL) {
1937 account[PTR_DIFF(p,user)] = '\0';
1940 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1943 /****************************************************************************
1944 Send a session setup. The username and workgroup is in UNIX character
1945 format and must be converted to DOS codepage format before sending. If the
1946 password is in plaintext, the same should be done.
1947 ****************************************************************************/
1949 NTSTATUS cli_session_setup(struct cli_state *cli,
1950 const char *user,
1951 const char *pass, int passlen,
1952 const char *ntpass, int ntpasslen,
1953 const char *workgroup)
1955 char *p;
1956 char *user2;
1958 if (user) {
1959 user2 = talloc_strdup(talloc_tos(), user);
1960 } else {
1961 user2 = talloc_strdup(talloc_tos(), "");
1963 if (user2 == NULL) {
1964 return NT_STATUS_NO_MEMORY;
1967 if (!workgroup) {
1968 workgroup = "";
1971 /* allow for workgroups as part of the username */
1972 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1973 (p=strchr_m(user2,*lp_winbind_separator()))) {
1974 *p = 0;
1975 user = p+1;
1976 workgroup = user2;
1979 if (cli->protocol < PROTOCOL_LANMAN1) {
1980 return NT_STATUS_OK;
1983 /* now work out what sort of session setup we are going to
1984 do. I have split this into separate functions to make the
1985 flow a bit easier to understand (tridge) */
1987 /* if its an older server then we have to use the older request format */
1989 if (cli->protocol < PROTOCOL_NT1) {
1990 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1991 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1992 " or 'client ntlmv2 auth = yes'\n"));
1993 return NT_STATUS_ACCESS_DENIED;
1996 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1997 !lp_client_plaintext_auth() && (*pass)) {
1998 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1999 " or 'client ntlmv2 auth = yes'\n"));
2000 return NT_STATUS_ACCESS_DENIED;
2003 return cli_session_setup_lanman2(cli, user, pass, passlen,
2004 workgroup);
2007 /* if no user is supplied then we have to do an anonymous connection.
2008 passwords are ignored */
2010 if (!user || !*user)
2011 return cli_session_setup_guest(cli);
2013 /* if the server is share level then send a plaintext null
2014 password at this point. The password is sent in the tree
2015 connect */
2017 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2018 return cli_session_setup_plain(cli, user, "", workgroup);
2020 /* if the server doesn't support encryption then we have to use
2021 plaintext. The second password is ignored */
2023 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2024 if (!lp_client_plaintext_auth() && (*pass)) {
2025 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2026 " or 'client ntlmv2 auth = yes'\n"));
2027 return NT_STATUS_ACCESS_DENIED;
2029 return cli_session_setup_plain(cli, user, pass, workgroup);
2032 /* if the server supports extended security then use SPNEGO */
2034 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2035 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2036 workgroup, NULL);
2037 if (!ADS_ERR_OK(status)) {
2038 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2039 return ads_ntstatus(status);
2041 } else {
2042 NTSTATUS status;
2044 /* otherwise do a NT1 style session setup */
2045 status = cli_session_setup_nt1(cli, user, pass, passlen,
2046 ntpass, ntpasslen, workgroup);
2047 if (!NT_STATUS_IS_OK(status)) {
2048 DEBUG(3,("cli_session_setup: NT1 session setup "
2049 "failed: %s\n", nt_errstr(status)));
2050 return status;
2054 if (strstr(cli->server_type, "Samba")) {
2055 cli->is_samba = True;
2058 return NT_STATUS_OK;
2061 /****************************************************************************
2062 Send a uloggoff.
2063 *****************************************************************************/
2065 struct cli_ulogoff_state {
2066 struct cli_state *cli;
2067 uint16_t vwv[3];
2070 static void cli_ulogoff_done(struct tevent_req *subreq);
2072 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2073 struct tevent_context *ev,
2074 struct cli_state *cli)
2076 struct tevent_req *req, *subreq;
2077 struct cli_ulogoff_state *state;
2079 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2080 if (req == NULL) {
2081 return NULL;
2083 state->cli = cli;
2085 SCVAL(state->vwv+0, 0, 0xFF);
2086 SCVAL(state->vwv+1, 0, 0);
2087 SSVAL(state->vwv+2, 0, 0);
2089 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2090 0, NULL);
2091 if (tevent_req_nomem(subreq, req)) {
2092 return tevent_req_post(req, ev);
2094 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2095 return req;
2098 static void cli_ulogoff_done(struct tevent_req *subreq)
2100 struct tevent_req *req = tevent_req_callback_data(
2101 subreq, struct tevent_req);
2102 struct cli_ulogoff_state *state = tevent_req_data(
2103 req, struct cli_ulogoff_state);
2104 NTSTATUS status;
2106 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2107 if (!NT_STATUS_IS_OK(status)) {
2108 tevent_req_nterror(req, status);
2109 return;
2111 state->cli->vuid = -1;
2112 tevent_req_done(req);
2115 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2117 return tevent_req_simple_recv_ntstatus(req);
2120 NTSTATUS cli_ulogoff(struct cli_state *cli)
2122 struct tevent_context *ev;
2123 struct tevent_req *req;
2124 NTSTATUS status = NT_STATUS_NO_MEMORY;
2126 if (cli_has_async_calls(cli)) {
2127 return NT_STATUS_INVALID_PARAMETER;
2129 ev = tevent_context_init(talloc_tos());
2130 if (ev == NULL) {
2131 goto fail;
2133 req = cli_ulogoff_send(ev, ev, cli);
2134 if (req == NULL) {
2135 goto fail;
2137 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2138 goto fail;
2140 status = cli_ulogoff_recv(req);
2141 fail:
2142 TALLOC_FREE(ev);
2143 if (!NT_STATUS_IS_OK(status)) {
2144 cli_set_error(cli, status);
2146 return status;
2149 /****************************************************************************
2150 Send a tconX.
2151 ****************************************************************************/
2153 struct cli_tcon_andx_state {
2154 struct cli_state *cli;
2155 uint16_t vwv[4];
2156 struct iovec bytes;
2159 static void cli_tcon_andx_done(struct tevent_req *subreq);
2161 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2162 struct event_context *ev,
2163 struct cli_state *cli,
2164 const char *share, const char *dev,
2165 const char *pass, int passlen,
2166 struct tevent_req **psmbreq)
2168 struct tevent_req *req, *subreq;
2169 struct cli_tcon_andx_state *state;
2170 fstring pword;
2171 uint16_t *vwv;
2172 char *tmp = NULL;
2173 uint8_t *bytes;
2175 *psmbreq = NULL;
2177 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2178 if (req == NULL) {
2179 return NULL;
2181 state->cli = cli;
2182 vwv = state->vwv;
2184 cli->share = talloc_strdup(cli, share);
2185 if (!cli->share) {
2186 return NULL;
2189 /* in user level security don't send a password now */
2190 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2191 passlen = 1;
2192 pass = "";
2193 } else if (pass == NULL) {
2194 DEBUG(1, ("Server not using user level security and no "
2195 "password supplied.\n"));
2196 goto access_denied;
2199 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2200 *pass && passlen != 24) {
2201 if (!lp_client_lanman_auth()) {
2202 DEBUG(1, ("Server requested LANMAN password "
2203 "(share-level security) but "
2204 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2205 goto access_denied;
2209 * Non-encrypted passwords - convert to DOS codepage before
2210 * encryption.
2212 passlen = 24;
2213 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
2214 } else {
2215 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2216 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2217 == 0) {
2218 if (!lp_client_plaintext_auth() && (*pass)) {
2219 DEBUG(1, ("Server requested plaintext "
2220 "password but "
2221 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2222 goto access_denied;
2226 * Non-encrypted passwords - convert to DOS codepage
2227 * before using.
2229 passlen = clistr_push(cli, pword, pass, sizeof(pword),
2230 STR_TERMINATE);
2231 if (passlen == -1) {
2232 DEBUG(1, ("clistr_push(pword) failed\n"));
2233 goto access_denied;
2235 } else {
2236 if (passlen) {
2237 memcpy(pword, pass, passlen);
2242 SCVAL(vwv+0, 0, 0xFF);
2243 SCVAL(vwv+0, 1, 0);
2244 SSVAL(vwv+1, 0, 0);
2245 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2246 SSVAL(vwv+3, 0, passlen);
2248 if (passlen) {
2249 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
2250 } else {
2251 bytes = talloc_array(state, uint8_t, 0);
2255 * Add the sharename
2257 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2258 cli->desthost, share);
2259 if (tmp == NULL) {
2260 TALLOC_FREE(req);
2261 return NULL;
2263 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2264 NULL);
2265 TALLOC_FREE(tmp);
2268 * Add the devicetype
2270 tmp = talloc_strdup_upper(talloc_tos(), dev);
2271 if (tmp == NULL) {
2272 TALLOC_FREE(req);
2273 return NULL;
2275 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2276 TALLOC_FREE(tmp);
2278 if (bytes == NULL) {
2279 TALLOC_FREE(req);
2280 return NULL;
2283 state->bytes.iov_base = (void *)bytes;
2284 state->bytes.iov_len = talloc_get_size(bytes);
2286 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2287 1, &state->bytes);
2288 if (subreq == NULL) {
2289 TALLOC_FREE(req);
2290 return NULL;
2292 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2293 *psmbreq = subreq;
2294 return req;
2296 access_denied:
2297 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2298 return tevent_req_post(req, ev);
2301 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2302 struct event_context *ev,
2303 struct cli_state *cli,
2304 const char *share, const char *dev,
2305 const char *pass, int passlen)
2307 struct tevent_req *req, *subreq;
2308 NTSTATUS status;
2310 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2311 &subreq);
2312 if (req == NULL) {
2313 return NULL;
2315 if (subreq == NULL) {
2316 return req;
2318 status = cli_smb_req_send(subreq);
2319 if (!NT_STATUS_IS_OK(status)) {
2320 tevent_req_nterror(req, status);
2321 return tevent_req_post(req, ev);
2323 return req;
2326 static void cli_tcon_andx_done(struct tevent_req *subreq)
2328 struct tevent_req *req = tevent_req_callback_data(
2329 subreq, struct tevent_req);
2330 struct cli_tcon_andx_state *state = tevent_req_data(
2331 req, struct cli_tcon_andx_state);
2332 struct cli_state *cli = state->cli;
2333 uint8_t *in;
2334 char *inbuf;
2335 uint8_t wct;
2336 uint16_t *vwv;
2337 uint32_t num_bytes;
2338 uint8_t *bytes;
2339 NTSTATUS status;
2341 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2342 &num_bytes, &bytes);
2343 TALLOC_FREE(subreq);
2344 if (!NT_STATUS_IS_OK(status)) {
2345 tevent_req_nterror(req, status);
2346 return;
2349 inbuf = (char *)in;
2351 if (num_bytes) {
2352 if (clistr_pull_talloc(cli,
2353 inbuf,
2354 SVAL(inbuf, smb_flg2),
2355 &cli->dev,
2356 bytes,
2357 num_bytes,
2358 STR_TERMINATE|STR_ASCII) == -1) {
2359 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2360 return;
2362 } else {
2363 cli->dev = talloc_strdup(cli, "");
2364 if (cli->dev == NULL) {
2365 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2366 return;
2370 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2371 /* almost certainly win95 - enable bug fixes */
2372 cli->win95 = True;
2376 * Make sure that we have the optional support 16-bit field. WCT > 2.
2377 * Avoids issues when connecting to Win9x boxes sharing files
2380 cli->dfsroot = false;
2382 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2383 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2386 cli->cnum = SVAL(inbuf,smb_tid);
2387 tevent_req_done(req);
2390 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2392 return tevent_req_simple_recv_ntstatus(req);
2395 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2396 const char *dev, const char *pass, int passlen)
2398 TALLOC_CTX *frame = talloc_stackframe();
2399 struct event_context *ev;
2400 struct tevent_req *req;
2401 NTSTATUS status = NT_STATUS_OK;
2403 if (cli_has_async_calls(cli)) {
2405 * Can't use sync call while an async call is in flight
2407 status = NT_STATUS_INVALID_PARAMETER;
2408 goto fail;
2411 ev = event_context_init(frame);
2412 if (ev == NULL) {
2413 status = NT_STATUS_NO_MEMORY;
2414 goto fail;
2417 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2418 if (req == NULL) {
2419 status = NT_STATUS_NO_MEMORY;
2420 goto fail;
2423 if (!tevent_req_poll(req, ev)) {
2424 status = map_nt_error_from_unix(errno);
2425 goto fail;
2428 status = cli_tcon_andx_recv(req);
2429 fail:
2430 TALLOC_FREE(frame);
2431 if (!NT_STATUS_IS_OK(status)) {
2432 cli_set_error(cli, status);
2434 return status;
2437 /****************************************************************************
2438 Send a tree disconnect.
2439 ****************************************************************************/
2441 struct cli_tdis_state {
2442 struct cli_state *cli;
2445 static void cli_tdis_done(struct tevent_req *subreq);
2447 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2448 struct tevent_context *ev,
2449 struct cli_state *cli)
2451 struct tevent_req *req, *subreq;
2452 struct cli_tdis_state *state;
2454 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2455 if (req == NULL) {
2456 return NULL;
2458 state->cli = cli;
2460 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2461 if (tevent_req_nomem(subreq, req)) {
2462 return tevent_req_post(req, ev);
2464 tevent_req_set_callback(subreq, cli_tdis_done, req);
2465 return req;
2468 static void cli_tdis_done(struct tevent_req *subreq)
2470 struct tevent_req *req = tevent_req_callback_data(
2471 subreq, struct tevent_req);
2472 struct cli_tdis_state *state = tevent_req_data(
2473 req, struct cli_tdis_state);
2474 NTSTATUS status;
2476 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2477 TALLOC_FREE(subreq);
2478 if (!NT_STATUS_IS_OK(status)) {
2479 tevent_req_nterror(req, status);
2480 return;
2482 state->cli->cnum = -1;
2483 tevent_req_done(req);
2486 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2488 return tevent_req_simple_recv_ntstatus(req);
2491 NTSTATUS cli_tdis(struct cli_state *cli)
2493 struct tevent_context *ev;
2494 struct tevent_req *req;
2495 NTSTATUS status = NT_STATUS_NO_MEMORY;
2497 if (cli_has_async_calls(cli)) {
2498 return NT_STATUS_INVALID_PARAMETER;
2500 ev = tevent_context_init(talloc_tos());
2501 if (ev == NULL) {
2502 goto fail;
2504 req = cli_tdis_send(ev, ev, cli);
2505 if (req == NULL) {
2506 goto fail;
2508 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2509 goto fail;
2511 status = cli_tdis_recv(req);
2512 fail:
2513 TALLOC_FREE(ev);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 cli_set_error(cli, status);
2517 return status;
2520 /****************************************************************************
2521 Send a negprot command.
2522 ****************************************************************************/
2524 struct cli_negprot_state {
2525 struct cli_state *cli;
2528 static void cli_negprot_done(struct tevent_req *subreq);
2530 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2531 struct event_context *ev,
2532 struct cli_state *cli)
2534 struct tevent_req *req, *subreq;
2535 struct cli_negprot_state *state;
2536 uint8_t *bytes = NULL;
2537 int numprots;
2538 uint16_t cnum;
2540 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2541 if (req == NULL) {
2542 return NULL;
2544 state->cli = cli;
2546 if (cli->protocol < PROTOCOL_NT1)
2547 cli->use_spnego = False;
2549 /* setup the protocol strings */
2550 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2551 uint8_t c = 2;
2552 if (prots[numprots].prot > cli->protocol) {
2553 break;
2555 bytes = (uint8_t *)talloc_append_blob(
2556 state, bytes, data_blob_const(&c, sizeof(c)));
2557 if (tevent_req_nomem(bytes, req)) {
2558 return tevent_req_post(req, ev);
2560 bytes = smb_bytes_push_str(bytes, false,
2561 prots[numprots].name,
2562 strlen(prots[numprots].name)+1,
2563 NULL);
2564 if (tevent_req_nomem(bytes, req)) {
2565 return tevent_req_post(req, ev);
2569 cnum = cli->cnum;
2571 cli->cnum = 0;
2572 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2573 talloc_get_size(bytes), bytes);
2574 cli->cnum = cnum;
2576 if (tevent_req_nomem(subreq, req)) {
2577 return tevent_req_post(req, ev);
2579 tevent_req_set_callback(subreq, cli_negprot_done, req);
2580 return req;
2583 static void cli_negprot_done(struct tevent_req *subreq)
2585 struct tevent_req *req = tevent_req_callback_data(
2586 subreq, struct tevent_req);
2587 struct cli_negprot_state *state = tevent_req_data(
2588 req, struct cli_negprot_state);
2589 struct cli_state *cli = state->cli;
2590 uint8_t wct;
2591 uint16_t *vwv;
2592 uint32_t num_bytes;
2593 uint8_t *bytes;
2594 NTSTATUS status;
2595 uint16_t protnum;
2596 uint8_t *inbuf;
2598 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2599 &num_bytes, &bytes);
2600 TALLOC_FREE(subreq);
2601 if (!NT_STATUS_IS_OK(status)) {
2602 tevent_req_nterror(req, status);
2603 return;
2606 protnum = SVAL(vwv, 0);
2608 if ((protnum >= ARRAY_SIZE(prots))
2609 || (prots[protnum].prot > cli->protocol)) {
2610 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2611 return;
2614 cli->protocol = prots[protnum].prot;
2616 if ((cli->protocol < PROTOCOL_NT1) &&
2617 client_is_signing_mandatory(cli)) {
2618 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2619 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2620 return;
2623 if (cli->protocol >= PROTOCOL_NT1) {
2624 struct timespec ts;
2625 bool negotiated_smb_signing = false;
2627 /* NT protocol */
2628 cli->sec_mode = CVAL(vwv + 1, 0);
2629 cli->max_mux = SVAL(vwv + 1, 1);
2630 cli->max_xmit = IVAL(vwv + 3, 1);
2631 cli->sesskey = IVAL(vwv + 7, 1);
2632 cli->serverzone = SVALS(vwv + 15, 1);
2633 cli->serverzone *= 60;
2634 /* this time arrives in real GMT */
2635 ts = interpret_long_date(((char *)(vwv+11))+1);
2636 cli->servertime = ts.tv_sec;
2637 cli->secblob = data_blob(bytes, num_bytes);
2638 cli->capabilities = IVAL(vwv + 9, 1);
2639 if (cli->capabilities & CAP_RAW_MODE) {
2640 cli->readbraw_supported = True;
2641 cli->writebraw_supported = True;
2643 /* work out if they sent us a workgroup */
2644 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2645 smb_buflen(cli->inbuf) > 8) {
2646 clistr_pull(cli->inbuf, cli->server_domain,
2647 bytes+8, sizeof(cli->server_domain),
2648 num_bytes-8,
2649 STR_UNICODE|STR_NOALIGN);
2653 * As signing is slow we only turn it on if either the client or
2654 * the server require it. JRA.
2657 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2658 /* Fail if server says signing is mandatory and we don't want to support it. */
2659 if (!client_is_signing_allowed(cli)) {
2660 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2661 tevent_req_nterror(req,
2662 NT_STATUS_ACCESS_DENIED);
2663 return;
2665 negotiated_smb_signing = true;
2666 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2667 /* Fail if client says signing is mandatory and the server doesn't support it. */
2668 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2669 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2670 tevent_req_nterror(req,
2671 NT_STATUS_ACCESS_DENIED);
2672 return;
2674 negotiated_smb_signing = true;
2675 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2676 negotiated_smb_signing = true;
2679 if (negotiated_smb_signing) {
2680 cli_set_signing_negotiated(cli);
2683 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2684 SAFE_FREE(cli->outbuf);
2685 SAFE_FREE(cli->inbuf);
2686 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2687 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2688 if (!cli->outbuf || !cli->inbuf) {
2689 tevent_req_nterror(req,
2690 NT_STATUS_NO_MEMORY);
2691 return;
2693 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2696 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2697 cli->use_spnego = False;
2698 cli->sec_mode = SVAL(vwv + 1, 0);
2699 cli->max_xmit = SVAL(vwv + 2, 0);
2700 cli->max_mux = SVAL(vwv + 3, 0);
2701 cli->sesskey = IVAL(vwv + 6, 0);
2702 cli->serverzone = SVALS(vwv + 10, 0);
2703 cli->serverzone *= 60;
2704 /* this time is converted to GMT by make_unix_date */
2705 cli->servertime = make_unix_date(
2706 (char *)(vwv + 8), cli->serverzone);
2707 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2708 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2709 cli->secblob = data_blob(bytes, num_bytes);
2710 } else {
2711 /* the old core protocol */
2712 cli->use_spnego = False;
2713 cli->sec_mode = 0;
2714 cli->serverzone = get_time_zone(time(NULL));
2717 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2719 /* a way to force ascii SMB */
2720 if (getenv("CLI_FORCE_ASCII"))
2721 cli->capabilities &= ~CAP_UNICODE;
2723 tevent_req_done(req);
2726 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2728 return tevent_req_simple_recv_ntstatus(req);
2731 NTSTATUS cli_negprot(struct cli_state *cli)
2733 TALLOC_CTX *frame = talloc_stackframe();
2734 struct event_context *ev;
2735 struct tevent_req *req;
2736 NTSTATUS status = NT_STATUS_OK;
2738 if (cli_has_async_calls(cli)) {
2740 * Can't use sync call while an async call is in flight
2742 status = NT_STATUS_INVALID_PARAMETER;
2743 goto fail;
2746 ev = event_context_init(frame);
2747 if (ev == NULL) {
2748 status = NT_STATUS_NO_MEMORY;
2749 goto fail;
2752 req = cli_negprot_send(frame, ev, cli);
2753 if (req == NULL) {
2754 status = NT_STATUS_NO_MEMORY;
2755 goto fail;
2758 if (!tevent_req_poll(req, ev)) {
2759 status = map_nt_error_from_unix(errno);
2760 goto fail;
2763 status = cli_negprot_recv(req);
2764 fail:
2765 TALLOC_FREE(frame);
2766 if (!NT_STATUS_IS_OK(status)) {
2767 cli_set_error(cli, status);
2769 return status;
2772 /****************************************************************************
2773 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2774 ****************************************************************************/
2776 bool cli_session_request(struct cli_state *cli,
2777 struct nmb_name *calling, struct nmb_name *called)
2779 char *p;
2780 int len = 4;
2781 int namelen = 0;
2782 char *tmp;
2784 /* 445 doesn't have session request */
2785 if (cli->port == 445)
2786 return True;
2788 memcpy(&(cli->calling), calling, sizeof(*calling));
2789 memcpy(&(cli->called ), called , sizeof(*called ));
2791 /* put in the destination name */
2793 tmp = name_mangle(talloc_tos(), cli->called.name,
2794 cli->called.name_type);
2795 if (tmp == NULL) {
2796 return false;
2799 p = cli->outbuf+len;
2800 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2801 if (namelen > 0) {
2802 memcpy(p, tmp, namelen);
2803 len += namelen;
2805 TALLOC_FREE(tmp);
2807 /* and my name */
2809 tmp = name_mangle(talloc_tos(), cli->calling.name,
2810 cli->calling.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 /* send a session request (RFC 1002) */
2824 /* setup the packet length
2825 * Remove four bytes from the length count, since the length
2826 * field in the NBT Session Service header counts the number
2827 * of bytes which follow. The cli_send_smb() function knows
2828 * about this and accounts for those four bytes.
2829 * CRH.
2831 len -= 4;
2832 _smb_setlen(cli->outbuf,len);
2833 SCVAL(cli->outbuf,0,0x81);
2835 cli_send_smb(cli);
2836 DEBUG(5,("Sent session request\n"));
2838 if (!cli_receive_smb(cli))
2839 return False;
2841 if (CVAL(cli->inbuf,0) == 0x84) {
2842 /* C. Hoch 9/14/95 Start */
2843 /* For information, here is the response structure.
2844 * We do the byte-twiddling to for portability.
2845 struct RetargetResponse{
2846 unsigned char type;
2847 unsigned char flags;
2848 int16 length;
2849 int32 ip_addr;
2850 int16 port;
2853 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2854 struct in_addr dest_ip;
2855 NTSTATUS status;
2857 /* SESSION RETARGET */
2858 putip((char *)&dest_ip,cli->inbuf+4);
2859 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2861 status = open_socket_out(&cli->dest_ss, port,
2862 LONG_CONNECT_TIMEOUT, &cli->fd);
2863 if (!NT_STATUS_IS_OK(status)) {
2864 return False;
2867 DEBUG(3,("Retargeted\n"));
2869 set_socket_options(cli->fd, lp_socket_options());
2871 /* Try again */
2873 static int depth;
2874 bool ret;
2875 if (depth > 4) {
2876 DEBUG(0,("Retarget recursion - failing\n"));
2877 return False;
2879 depth++;
2880 ret = cli_session_request(cli, calling, called);
2881 depth--;
2882 return ret;
2884 } /* C. Hoch 9/14/95 End */
2886 if (CVAL(cli->inbuf,0) != 0x82) {
2887 /* This is the wrong place to put the error... JRA. */
2888 cli->rap_error = CVAL(cli->inbuf,4);
2889 return False;
2891 return(True);
2894 struct fd_struct {
2895 int fd;
2898 static void smb_sock_connected(struct tevent_req *req)
2900 struct fd_struct *pfd = tevent_req_callback_data(
2901 req, struct fd_struct);
2902 int fd;
2903 NTSTATUS status;
2905 status = open_socket_out_defer_recv(req, &fd);
2906 if (NT_STATUS_IS_OK(status)) {
2907 pfd->fd = fd;
2911 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2912 uint16_t *port, int timeout, int *pfd)
2914 struct event_context *ev;
2915 struct tevent_req *r139, *r445;
2916 struct fd_struct *fd139, *fd445;
2917 NTSTATUS status = NT_STATUS_NO_MEMORY;
2919 if (*port != 0) {
2920 return open_socket_out(pss, *port, timeout, pfd);
2923 ev = event_context_init(talloc_tos());
2924 if (ev == NULL) {
2925 return NT_STATUS_NO_MEMORY;
2928 fd139 = talloc(ev, struct fd_struct);
2929 if (fd139 == NULL) {
2930 goto done;
2932 fd139->fd = -1;
2934 fd445 = talloc(ev, struct fd_struct);
2935 if (fd445 == NULL) {
2936 goto done;
2938 fd445->fd = -1;
2940 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2941 pss, 445, timeout);
2942 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2943 pss, 139, timeout);
2944 if ((r445 == NULL) || (r139 == NULL)) {
2945 goto done;
2947 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2948 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2950 while ((fd445->fd == -1) && (fd139->fd == -1)
2951 && (tevent_req_is_in_progress(r139)
2952 || tevent_req_is_in_progress(r445))) {
2953 event_loop_once(ev);
2956 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2957 close(fd139->fd);
2958 fd139->fd = -1;
2961 if (fd445->fd != -1) {
2962 *port = 445;
2963 *pfd = fd445->fd;
2964 status = NT_STATUS_OK;
2965 goto done;
2967 if (fd139->fd != -1) {
2968 *port = 139;
2969 *pfd = fd139->fd;
2970 status = NT_STATUS_OK;
2971 goto done;
2974 status = open_socket_out_defer_recv(r445, &fd445->fd);
2975 done:
2976 TALLOC_FREE(ev);
2977 return status;
2980 /****************************************************************************
2981 Open the client sockets.
2982 ****************************************************************************/
2984 NTSTATUS cli_connect(struct cli_state *cli,
2985 const char *host,
2986 struct sockaddr_storage *dest_ss)
2989 int name_type = 0x20;
2990 TALLOC_CTX *frame = talloc_stackframe();
2991 unsigned int num_addrs = 0;
2992 unsigned int i = 0;
2993 struct sockaddr_storage *ss_arr = NULL;
2994 char *p = NULL;
2996 /* reasonable default hostname */
2997 if (!host) {
2998 host = STAR_SMBSERVER;
3001 cli->desthost = talloc_strdup(cli, host);
3002 if (cli->desthost == NULL) {
3003 return NT_STATUS_NO_MEMORY;
3006 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3007 if ((p = strchr(cli->desthost, '#'))) {
3008 name_type = strtol(p+1, NULL, 16);
3009 *p = 0;
3012 if (!dest_ss || is_zero_addr(dest_ss)) {
3013 NTSTATUS status =resolve_name_list(frame,
3014 cli->desthost,
3015 name_type,
3016 &ss_arr,
3017 &num_addrs);
3018 if (!NT_STATUS_IS_OK(status)) {
3019 TALLOC_FREE(frame);
3020 return NT_STATUS_BAD_NETWORK_NAME;
3022 } else {
3023 num_addrs = 1;
3024 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
3025 if (!ss_arr) {
3026 TALLOC_FREE(frame);
3027 return NT_STATUS_NO_MEMORY;
3029 *ss_arr = *dest_ss;
3032 for (i = 0; i < num_addrs; i++) {
3033 cli->dest_ss = ss_arr[i];
3034 if (getenv("LIBSMB_PROG")) {
3035 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
3036 } else {
3037 uint16_t port = cli->port;
3038 NTSTATUS status;
3039 status = open_smb_socket(&cli->dest_ss, &port,
3040 cli->timeout, &cli->fd);
3041 if (NT_STATUS_IS_OK(status)) {
3042 cli->port = port;
3045 if (cli->fd == -1) {
3046 char addr[INET6_ADDRSTRLEN];
3047 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
3048 DEBUG(2,("Error connecting to %s (%s)\n",
3049 dest_ss?addr:host,strerror(errno)));
3050 } else {
3051 /* Exit from loop on first connection. */
3052 break;
3056 if (cli->fd == -1) {
3057 TALLOC_FREE(frame);
3058 return map_nt_error_from_unix(errno);
3061 if (dest_ss) {
3062 *dest_ss = cli->dest_ss;
3065 set_socket_options(cli->fd, lp_socket_options());
3067 TALLOC_FREE(frame);
3068 return NT_STATUS_OK;
3072 establishes a connection to after the negprot.
3073 @param output_cli A fully initialised cli structure, non-null only on success
3074 @param dest_host The netbios name of the remote host
3075 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3076 @param port (optional) The destination port (0 for default)
3078 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3079 const char *my_name,
3080 const char *dest_host,
3081 struct sockaddr_storage *dest_ss, int port,
3082 int signing_state, int flags)
3084 NTSTATUS nt_status;
3085 struct nmb_name calling;
3086 struct nmb_name called;
3087 struct cli_state *cli;
3088 struct sockaddr_storage ss;
3090 if (!my_name)
3091 my_name = global_myname();
3093 if (!(cli = cli_initialise_ex(signing_state))) {
3094 return NT_STATUS_NO_MEMORY;
3097 make_nmb_name(&calling, my_name, 0x0);
3098 make_nmb_name(&called , dest_host, 0x20);
3100 cli_set_port(cli, port);
3101 cli_set_timeout(cli, 10000); /* 10 seconds. */
3103 if (dest_ss) {
3104 ss = *dest_ss;
3105 } else {
3106 zero_sockaddr(&ss);
3109 again:
3111 DEBUG(3,("Connecting to host=%s\n", dest_host));
3113 nt_status = cli_connect(cli, dest_host, &ss);
3114 if (!NT_STATUS_IS_OK(nt_status)) {
3115 char addr[INET6_ADDRSTRLEN];
3116 print_sockaddr(addr, sizeof(addr), &ss);
3117 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3118 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
3119 cli_shutdown(cli);
3120 return nt_status;
3123 if (!cli_session_request(cli, &calling, &called)) {
3124 char *p;
3125 DEBUG(1,("session request to %s failed (%s)\n",
3126 called.name, cli_errstr(cli)));
3127 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
3128 *p = 0;
3129 goto again;
3131 if (strcmp(called.name, STAR_SMBSERVER)) {
3132 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
3133 goto again;
3135 return NT_STATUS_BAD_NETWORK_NAME;
3138 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
3139 cli->use_spnego = False;
3140 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
3141 cli->use_kerberos = True;
3143 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
3144 cli->use_kerberos) {
3145 cli->fallback_after_kerberos = true;
3147 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3148 cli->use_ccache = true;
3151 nt_status = cli_negprot(cli);
3152 if (!NT_STATUS_IS_OK(nt_status)) {
3153 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3154 cli_shutdown(cli);
3155 return nt_status;
3158 *output_cli = cli;
3159 return NT_STATUS_OK;
3164 establishes a connection right up to doing tconX, password specified.
3165 @param output_cli A fully initialised cli structure, non-null only on success
3166 @param dest_host The netbios name of the remote host
3167 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3168 @param port (optional) The destination port (0 for default)
3169 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3170 @param service_type The 'type' of serivice.
3171 @param user Username, unix string
3172 @param domain User's domain
3173 @param password User's password, unencrypted unix string.
3176 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3177 const char *my_name,
3178 const char *dest_host,
3179 struct sockaddr_storage *dest_ss, int port,
3180 const char *service, const char *service_type,
3181 const char *user, const char *domain,
3182 const char *password, int flags,
3183 int signing_state)
3185 NTSTATUS nt_status;
3186 struct cli_state *cli = NULL;
3187 int pw_len = password ? strlen(password)+1 : 0;
3189 *output_cli = NULL;
3191 if (password == NULL) {
3192 password = "";
3195 nt_status = cli_start_connection(&cli, my_name, dest_host,
3196 dest_ss, port, signing_state,
3197 flags);
3199 if (!NT_STATUS_IS_OK(nt_status)) {
3200 return nt_status;
3203 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3204 cli->use_level_II_oplocks =
3205 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3207 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3208 pw_len, domain);
3209 if (!NT_STATUS_IS_OK(nt_status)) {
3211 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3212 DEBUG(1,("failed session setup with %s\n",
3213 nt_errstr(nt_status)));
3214 cli_shutdown(cli);
3215 return nt_status;
3218 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3219 if (!NT_STATUS_IS_OK(nt_status)) {
3220 DEBUG(1,("anonymous failed session setup with %s\n",
3221 nt_errstr(nt_status)));
3222 cli_shutdown(cli);
3223 return nt_status;
3227 if (service) {
3228 nt_status = cli_tcon_andx(cli, service, service_type, password,
3229 pw_len);
3230 if (!NT_STATUS_IS_OK(nt_status)) {
3231 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3232 cli_shutdown(cli);
3233 if (NT_STATUS_IS_OK(nt_status)) {
3234 nt_status = NT_STATUS_UNSUCCESSFUL;
3236 return nt_status;
3240 nt_status = cli_init_creds(cli, user, domain, password);
3241 if (!NT_STATUS_IS_OK(nt_status)) {
3242 cli_shutdown(cli);
3243 return nt_status;
3246 *output_cli = cli;
3247 return NT_STATUS_OK;
3250 /****************************************************************************
3251 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3252 ****************************************************************************/
3254 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
3255 struct sockaddr_storage *pdest_ss)
3257 struct nmb_name calling, called;
3259 make_nmb_name(&calling, srchost, 0x0);
3262 * If the called name is an IP address
3263 * then use *SMBSERVER immediately.
3266 if(is_ipaddress(desthost)) {
3267 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
3268 } else {
3269 make_nmb_name(&called, desthost, 0x20);
3272 if (!cli_session_request(*ppcli, &calling, &called)) {
3273 NTSTATUS status;
3274 struct nmb_name smbservername;
3276 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
3279 * If the name wasn't *SMBSERVER then
3280 * try with *SMBSERVER if the first name fails.
3283 if (nmb_name_equal(&called, &smbservername)) {
3286 * The name used was *SMBSERVER, don't bother with another name.
3289 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3290 with error %s.\n", desthost, cli_errstr(*ppcli) ));
3291 return False;
3294 /* Try again... */
3295 cli_shutdown(*ppcli);
3297 *ppcli = cli_initialise();
3298 if (!*ppcli) {
3299 /* Out of memory... */
3300 return False;
3303 status = cli_connect(*ppcli, desthost, pdest_ss);
3304 if (!NT_STATUS_IS_OK(status) ||
3305 !cli_session_request(*ppcli, &calling, &smbservername)) {
3306 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3307 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
3308 return False;
3312 return True;
3315 /****************************************************************************
3316 Send an old style tcon.
3317 ****************************************************************************/
3318 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3319 const char *service, const char *pass, const char *dev,
3320 uint16 *max_xmit, uint16 *tid)
3322 struct tevent_req *req;
3323 uint16_t *ret_vwv;
3324 uint8_t *bytes;
3325 NTSTATUS status;
3327 if (!lp_client_plaintext_auth() && (*pass)) {
3328 DEBUG(1, ("Server requested plaintext password but 'client "
3329 "plaintext auth' is disabled\n"));
3330 return NT_STATUS_ACCESS_DENIED;
3333 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3334 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3335 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3336 service, strlen(service)+1, NULL);
3337 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3338 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3339 pass, strlen(pass)+1, NULL);
3340 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3341 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3342 dev, strlen(dev)+1, NULL);
3344 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3345 talloc_get_size(bytes), bytes, &req,
3346 2, NULL, &ret_vwv, NULL, NULL);
3347 if (!NT_STATUS_IS_OK(status)) {
3348 return status;
3351 *max_xmit = SVAL(ret_vwv + 0, 0);
3352 *tid = SVAL(ret_vwv + 1, 0);
3354 return NT_STATUS_OK;
3357 /* Return a cli_state pointing at the IPC$ share for the given server */
3359 struct cli_state *get_ipc_connect(char *server,
3360 struct sockaddr_storage *server_ss,
3361 const struct user_auth_info *user_info)
3363 struct cli_state *cli;
3364 NTSTATUS nt_status;
3365 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3367 if (user_info->use_kerberos) {
3368 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3371 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3372 user_info->username ? user_info->username : "",
3373 lp_workgroup(),
3374 user_info->password ? user_info->password : "",
3375 flags,
3376 Undefined);
3378 if (NT_STATUS_IS_OK(nt_status)) {
3379 return cli;
3380 } else if (is_ipaddress(server)) {
3381 /* windows 9* needs a correct NMB name for connections */
3382 fstring remote_name;
3384 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3385 cli = get_ipc_connect(remote_name, server_ss, user_info);
3386 if (cli)
3387 return cli;
3390 return NULL;
3394 * Given the IP address of a master browser on the network, return its
3395 * workgroup and connect to it.
3397 * This function is provided to allow additional processing beyond what
3398 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3399 * browsers and obtain each master browsers' list of domains (in case the
3400 * first master browser is recently on the network and has not yet
3401 * synchronized with other master browsers and therefore does not yet have the
3402 * entire network browse list)
3405 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3406 struct ip_service *mb_ip,
3407 const struct user_auth_info *user_info,
3408 char **pp_workgroup_out)
3410 char addr[INET6_ADDRSTRLEN];
3411 fstring name;
3412 struct cli_state *cli;
3413 struct sockaddr_storage server_ss;
3415 *pp_workgroup_out = NULL;
3417 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
3418 DEBUG(99, ("Looking up name of master browser %s\n",
3419 addr));
3422 * Do a name status query to find out the name of the master browser.
3423 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3424 * master browser will not respond to a wildcard query (or, at least,
3425 * an NT4 server acting as the domain master browser will not).
3427 * We might be able to use ONLY the query on MSBROWSE, but that's not
3428 * yet been tested with all Windows versions, so until it is, leave
3429 * the original wildcard query as the first choice and fall back to
3430 * MSBROWSE if the wildcard query fails.
3432 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
3433 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
3435 DEBUG(99, ("Could not retrieve name status for %s\n",
3436 addr));
3437 return NULL;
3440 if (!find_master_ip(name, &server_ss)) {
3441 DEBUG(99, ("Could not find master ip for %s\n", name));
3442 return NULL;
3445 *pp_workgroup_out = talloc_strdup(ctx, name);
3447 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3449 print_sockaddr(addr, sizeof(addr), &server_ss);
3450 cli = get_ipc_connect(addr, &server_ss, user_info);
3452 return cli;
3456 * Return the IP address and workgroup of a master browser on the network, and
3457 * connect to it.
3460 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3461 const struct user_auth_info *user_info,
3462 char **pp_workgroup_out)
3464 struct ip_service *ip_list;
3465 struct cli_state *cli;
3466 int i, count;
3468 *pp_workgroup_out = NULL;
3470 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3472 /* Go looking for workgroups by broadcasting on the local network */
3474 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
3475 &count))) {
3476 DEBUG(99, ("No master browsers responded\n"));
3477 return False;
3480 for (i = 0; i < count; i++) {
3481 char addr[INET6_ADDRSTRLEN];
3482 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
3483 DEBUG(99, ("Found master browser %s\n", addr));
3485 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3486 user_info, pp_workgroup_out);
3487 if (cli)
3488 return(cli);
3491 return NULL;