2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
29 #include "../auth/ntlmssp/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "librpc/ndr/libndr.h"
36 #include "../libcli/smb/smbXcli_base.h"
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /********************************************************
42 Utility function to ensure we always return at least
43 a valid char * pointer to an empty string for the
44 cli->server_os, cli->server_type and cli->server_domain
46 *******************************************************/
48 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
55 *destlen = clistr_pull_talloc(mem_ctx,
63 return NT_STATUS_NO_MEMORY;
67 *dest = talloc_strdup(mem_ctx, "");
69 return NT_STATUS_NO_MEMORY;
75 /****************************************************************************
76 Do an old lanman2 style session setup.
77 ****************************************************************************/
79 struct cli_session_setup_lanman2_state {
80 struct cli_state *cli;
85 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
87 static struct tevent_req *cli_session_setup_lanman2_send(
88 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
89 struct cli_state *cli, const char *user,
90 const char *pass, size_t passlen,
91 const char *workgroup)
93 struct tevent_req *req, *subreq;
94 struct cli_session_setup_lanman2_state *state;
95 DATA_BLOB lm_response = data_blob_null;
99 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
101 req = tevent_req_create(mem_ctx, &state,
102 struct cli_session_setup_lanman2_state);
111 * if in share level security then don't send a password now
113 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
118 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
121 * Encrypted mode needed, and non encrypted password
124 lm_response = data_blob(NULL, 24);
125 if (tevent_req_nomem(lm_response.data, req)) {
126 return tevent_req_post(req, ev);
129 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
130 (uint8_t *)lm_response.data)) {
131 DEBUG(1, ("Password is > 14 chars in length, and is "
132 "therefore incompatible with Lanman "
133 "authentication\n"));
134 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
135 return tevent_req_post(req, ev);
137 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
140 * Encrypted mode needed, and encrypted password
143 lm_response = data_blob(pass, passlen);
144 if (tevent_req_nomem(lm_response.data, req)) {
145 return tevent_req_post(req, ev);
147 } else if (passlen > 0) {
149 size_t converted_size;
151 * Plaintext mode needed, assume plaintext supplied.
153 buf = talloc_array(talloc_tos(), uint8_t, 0);
154 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
156 if (tevent_req_nomem(buf, req)) {
157 return tevent_req_post(req, ev);
159 lm_response = data_blob(pass, passlen);
161 if (tevent_req_nomem(lm_response.data, req)) {
162 return tevent_req_post(req, ev);
166 SCVAL(vwv+0, 0, 0xff);
169 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
172 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
173 SSVAL(vwv+7, 0, lm_response.length);
175 bytes = talloc_array(state, uint8_t, lm_response.length);
176 if (tevent_req_nomem(bytes, req)) {
177 return tevent_req_post(req, ev);
179 if (lm_response.length != 0) {
180 memcpy(bytes, lm_response.data, lm_response.length);
182 data_blob_free(&lm_response);
184 tmp = talloc_strdup_upper(talloc_tos(), user);
185 if (tevent_req_nomem(tmp, req)) {
186 return tevent_req_post(req, ev);
188 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
192 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
193 if (tevent_req_nomem(tmp, req)) {
194 return tevent_req_post(req, ev);
196 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
199 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
201 if (tevent_req_nomem(bytes, req)) {
202 return tevent_req_post(req, ev);
205 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
206 talloc_get_size(bytes), bytes);
207 if (tevent_req_nomem(subreq, req)) {
208 return tevent_req_post(req, ev);
210 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
214 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
216 struct tevent_req *req = tevent_req_callback_data(
217 subreq, struct tevent_req);
218 struct cli_session_setup_lanman2_state *state = tevent_req_data(
219 req, struct cli_session_setup_lanman2_state);
220 struct cli_state *cli = state->cli;
231 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
234 if (!NT_STATUS_IS_OK(status)) {
235 tevent_req_nterror(req, status);
239 inhdr = in + NBT_HDR_SIZE;
242 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
244 status = smb_bytes_talloc_string(cli,
251 if (!NT_STATUS_IS_OK(status)) {
252 tevent_req_nterror(req, status);
257 status = smb_bytes_talloc_string(cli,
264 if (!NT_STATUS_IS_OK(status)) {
265 tevent_req_nterror(req, status);
270 status = smb_bytes_talloc_string(cli,
277 if (!NT_STATUS_IS_OK(status)) {
278 tevent_req_nterror(req, status);
283 status = cli_set_username(cli, state->user);
284 if (tevent_req_nterror(req, status)) {
287 tevent_req_done(req);
290 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
292 return tevent_req_simple_recv_ntstatus(req);
295 /****************************************************************************
296 Work out suitable capabilities to offer the server.
297 ****************************************************************************/
299 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
300 uint32_t sesssetup_capabilities)
302 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
305 * We only send capabilities based on the mask for:
306 * - client only flags
307 * - flags used in both directions
309 * We do not echo the server only flags, except some legacy flags.
311 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
312 * CAP_LARGE_WRITEX in order to allow us to do large reads
313 * against old Samba releases (<= 3.6.x).
315 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
318 * Session Setup specific flags CAP_DYNAMIC_REAUTH
319 * and CAP_EXTENDED_SECURITY are passed by the caller.
320 * We need that in order to do guest logins even if
321 * CAP_EXTENDED_SECURITY is negotiated.
323 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
324 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
325 client_capabilities |= sesssetup_capabilities;
327 return client_capabilities;
330 /****************************************************************************
331 Do a NT1 guest session setup.
332 ****************************************************************************/
334 struct cli_session_setup_guest_state {
335 struct cli_state *cli;
340 static void cli_session_setup_guest_done(struct tevent_req *subreq);
342 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
343 struct tevent_context *ev,
344 struct cli_state *cli,
345 struct tevent_req **psmbreq)
347 struct tevent_req *req, *subreq;
348 struct cli_session_setup_guest_state *state;
352 req = tevent_req_create(mem_ctx, &state,
353 struct cli_session_setup_guest_state);
360 SCVAL(vwv+0, 0, 0xFF);
363 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
365 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
366 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
371 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
373 bytes = talloc_array(state, uint8_t, 0);
375 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
377 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
379 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
380 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
387 state->bytes.iov_base = (void *)bytes;
388 state->bytes.iov_len = talloc_get_size(bytes);
390 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
392 if (subreq == NULL) {
396 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
401 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
402 struct tevent_context *ev,
403 struct cli_state *cli)
405 struct tevent_req *req, *subreq;
408 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
413 status = smb1cli_req_chain_submit(&subreq, 1);
414 if (!NT_STATUS_IS_OK(status)) {
415 tevent_req_nterror(req, status);
416 return tevent_req_post(req, ev);
421 static void cli_session_setup_guest_done(struct tevent_req *subreq)
423 struct tevent_req *req = tevent_req_callback_data(
424 subreq, struct tevent_req);
425 struct cli_session_setup_guest_state *state = tevent_req_data(
426 req, struct cli_session_setup_guest_state);
427 struct cli_state *cli = state->cli;
438 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
441 if (!NT_STATUS_IS_OK(status)) {
442 tevent_req_nterror(req, status);
446 inhdr = in + NBT_HDR_SIZE;
449 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
451 status = smb_bytes_talloc_string(cli,
458 if (!NT_STATUS_IS_OK(status)) {
459 tevent_req_nterror(req, status);
464 status = smb_bytes_talloc_string(cli,
471 if (!NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
477 status = smb_bytes_talloc_string(cli,
484 if (!NT_STATUS_IS_OK(status)) {
485 tevent_req_nterror(req, status);
490 status = cli_set_username(cli, "");
491 if (!NT_STATUS_IS_OK(status)) {
492 tevent_req_nterror(req, status);
495 tevent_req_done(req);
498 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
500 return tevent_req_simple_recv_ntstatus(req);
503 /****************************************************************************
504 Do a NT1 plaintext session setup.
505 ****************************************************************************/
507 struct cli_session_setup_plain_state {
508 struct cli_state *cli;
513 static void cli_session_setup_plain_done(struct tevent_req *subreq);
515 static struct tevent_req *cli_session_setup_plain_send(
516 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
517 struct cli_state *cli,
518 const char *user, const char *pass, const char *workgroup)
520 struct tevent_req *req, *subreq;
521 struct cli_session_setup_plain_state *state;
527 req = tevent_req_create(mem_ctx, &state,
528 struct cli_session_setup_plain_state);
536 SCVAL(vwv+0, 0, 0xff);
539 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
541 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
542 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
547 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
549 bytes = talloc_array(state, uint8_t, 0);
550 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
552 if (tevent_req_nomem(bytes, req)) {
553 return tevent_req_post(req, ev);
555 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
557 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
558 user, strlen(user)+1, NULL);
559 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
560 workgroup, strlen(workgroup)+1, NULL);
561 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
564 version = talloc_asprintf(talloc_tos(), "Samba %s",
565 samba_version_string());
566 if (tevent_req_nomem(version, req)){
567 return tevent_req_post(req, ev);
569 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
570 version, strlen(version)+1, NULL);
571 TALLOC_FREE(version);
573 if (tevent_req_nomem(bytes, req)) {
574 return tevent_req_post(req, ev);
577 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
578 talloc_get_size(bytes), bytes);
579 if (tevent_req_nomem(subreq, req)) {
580 return tevent_req_post(req, ev);
582 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
586 static void cli_session_setup_plain_done(struct tevent_req *subreq)
588 struct tevent_req *req = tevent_req_callback_data(
589 subreq, struct tevent_req);
590 struct cli_session_setup_plain_state *state = tevent_req_data(
591 req, struct cli_session_setup_plain_state);
592 struct cli_state *cli = state->cli;
603 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
606 if (tevent_req_nterror(req, status)) {
610 inhdr = in + NBT_HDR_SIZE;
613 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
615 status = smb_bytes_talloc_string(cli,
622 if (!NT_STATUS_IS_OK(status)) {
623 tevent_req_nterror(req, status);
628 status = smb_bytes_talloc_string(cli,
635 if (!NT_STATUS_IS_OK(status)) {
636 tevent_req_nterror(req, status);
641 status = smb_bytes_talloc_string(cli,
648 if (!NT_STATUS_IS_OK(status)) {
649 tevent_req_nterror(req, status);
654 status = cli_set_username(cli, state->user);
655 if (tevent_req_nterror(req, status)) {
659 tevent_req_done(req);
662 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
664 return tevent_req_simple_recv_ntstatus(req);
667 /****************************************************************************
668 do a NT1 NTLM/LM encrypted session setup - for when extended security
670 @param cli client state to create do session setup on
672 @param pass *either* cleartext password (passlen !=24) or LM response.
673 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
674 @param workgroup The user's domain.
675 ****************************************************************************/
677 struct cli_session_setup_nt1_state {
678 struct cli_state *cli;
681 DATA_BLOB session_key;
685 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
687 static struct tevent_req *cli_session_setup_nt1_send(
688 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
689 struct cli_state *cli, const char *user,
690 const char *pass, size_t passlen,
691 const char *ntpass, size_t ntpasslen,
692 const char *workgroup)
694 struct tevent_req *req, *subreq;
695 struct cli_session_setup_nt1_state *state;
696 DATA_BLOB lm_response = data_blob_null;
697 DATA_BLOB nt_response = data_blob_null;
698 DATA_BLOB session_key = data_blob_null;
701 char *workgroup_upper;
703 req = tevent_req_create(mem_ctx, &state,
704 struct cli_session_setup_nt1_state);
713 /* do nothing - guest login */
714 } else if (passlen != 24) {
715 if (lp_client_ntlmv2_auth()) {
716 DATA_BLOB server_chal;
717 DATA_BLOB names_blob;
720 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
724 * note that the 'workgroup' here is a best
725 * guess - we don't know the server's domain
726 * at this point. Windows clients also don't
729 names_blob = NTLMv2_generate_names_blob(
730 NULL, NULL, workgroup);
732 if (tevent_req_nomem(names_blob.data, req)) {
733 return tevent_req_post(req, ev);
736 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
737 &server_chal, &names_blob,
738 &lm_response, &nt_response,
739 NULL, &session_key)) {
740 data_blob_free(&names_blob);
742 req, NT_STATUS_ACCESS_DENIED);
743 return tevent_req_post(req, ev);
745 data_blob_free(&names_blob);
749 E_md4hash(pass, nt_hash);
752 nt_response = data_blob_null;
754 nt_response = data_blob(NULL, 24);
755 if (tevent_req_nomem(nt_response.data, req)) {
756 return tevent_req_post(req, ev);
759 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
762 /* non encrypted password supplied. Ignore ntpass. */
763 if (lp_client_lanman_auth()) {
765 lm_response = data_blob(NULL, 24);
766 if (tevent_req_nomem(lm_response.data, req)) {
767 return tevent_req_post(req, ev);
770 if (!SMBencrypt(pass,
771 smb1cli_conn_server_challenge(cli->conn),
774 * Oops, the LM response is
775 * invalid, just put the NT
776 * response there instead
778 data_blob_free(&lm_response);
779 lm_response = data_blob(
785 * LM disabled, place NT# in LM field
788 lm_response = data_blob(
789 nt_response.data, nt_response.length);
792 if (tevent_req_nomem(lm_response.data, req)) {
793 return tevent_req_post(req, ev);
796 session_key = data_blob(NULL, 16);
797 if (tevent_req_nomem(session_key.data, req)) {
798 return tevent_req_post(req, ev);
801 E_deshash(pass, session_key.data);
802 memset(&session_key.data[8], '\0', 8);
804 SMBsesskeygen_ntv1(nt_hash, session_key.data);
808 /* pre-encrypted password supplied. Only used for
809 security=server, can't do
810 signing because we don't have original key */
812 lm_response = data_blob(pass, passlen);
813 if (tevent_req_nomem(lm_response.data, req)) {
814 return tevent_req_post(req, ev);
817 nt_response = data_blob(ntpass, ntpasslen);
818 if (tevent_req_nomem(nt_response.data, req)) {
819 return tevent_req_post(req, ev);
824 state->response = data_blob_talloc(
825 state, lm_response.data, lm_response.length);
827 state->response = data_blob_talloc(
828 state, nt_response.data, nt_response.length);
830 if (tevent_req_nomem(state->response.data, req)) {
831 return tevent_req_post(req, ev);
834 if (session_key.data) {
835 state->session_key = data_blob_talloc(
836 state, session_key.data, session_key.length);
837 if (tevent_req_nomem(state->session_key.data, req)) {
838 return tevent_req_post(req, ev);
841 data_blob_free(&session_key);
843 SCVAL(vwv+0, 0, 0xff);
846 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
848 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
849 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
850 SSVAL(vwv+7, 0, lm_response.length);
851 SSVAL(vwv+8, 0, nt_response.length);
854 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
856 bytes = talloc_array(state, uint8_t,
857 lm_response.length + nt_response.length);
858 if (tevent_req_nomem(bytes, req)) {
859 return tevent_req_post(req, ev);
861 if (lm_response.length != 0) {
862 memcpy(bytes, lm_response.data, lm_response.length);
864 if (nt_response.length != 0) {
865 memcpy(bytes + lm_response.length,
866 nt_response.data, nt_response.length);
868 data_blob_free(&lm_response);
869 data_blob_free(&nt_response);
871 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
872 user, strlen(user)+1, NULL);
875 * Upper case here might help some NTLMv2 implementations
877 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
878 if (tevent_req_nomem(workgroup_upper, req)) {
879 return tevent_req_post(req, ev);
881 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
882 workgroup_upper, strlen(workgroup_upper)+1,
884 TALLOC_FREE(workgroup_upper);
886 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
887 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
888 if (tevent_req_nomem(bytes, req)) {
889 return tevent_req_post(req, ev);
892 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
893 talloc_get_size(bytes), bytes);
894 if (tevent_req_nomem(subreq, req)) {
895 return tevent_req_post(req, ev);
897 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
901 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
903 struct tevent_req *req = tevent_req_callback_data(
904 subreq, struct tevent_req);
905 struct cli_session_setup_nt1_state *state = tevent_req_data(
906 req, struct cli_session_setup_nt1_state);
907 struct cli_state *cli = state->cli;
918 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
921 if (!NT_STATUS_IS_OK(status)) {
922 tevent_req_nterror(req, status);
926 inhdr = in + NBT_HDR_SIZE;
929 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
931 status = smb_bytes_talloc_string(cli,
937 if (!NT_STATUS_IS_OK(status)) {
938 tevent_req_nterror(req, status);
943 status = smb_bytes_talloc_string(cli,
949 if (!NT_STATUS_IS_OK(status)) {
950 tevent_req_nterror(req, status);
955 status = smb_bytes_talloc_string(cli,
961 if (!NT_STATUS_IS_OK(status)) {
962 tevent_req_nterror(req, status);
967 status = cli_set_username(cli, state->user);
968 if (tevent_req_nterror(req, status)) {
971 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
972 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
973 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
976 if (state->session_key.data) {
977 struct smbXcli_session *session = state->cli->smb1.session;
979 status = smb1cli_session_set_session_key(session,
981 if (tevent_req_nterror(req, status)) {
985 tevent_req_done(req);
988 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
990 return tevent_req_simple_recv_ntstatus(req);
993 /* The following is calculated from :
995 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
996 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1000 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1002 struct cli_sesssetup_blob_state {
1003 struct tevent_context *ev;
1004 struct cli_state *cli;
1006 uint16_t max_blob_size;
1010 DATA_BLOB smb2_blob;
1011 struct iovec *recv_iov;
1018 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1019 struct tevent_req **psubreq);
1020 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1022 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1023 struct tevent_context *ev,
1024 struct cli_state *cli,
1027 struct tevent_req *req, *subreq;
1028 struct cli_sesssetup_blob_state *state;
1029 uint32_t usable_space;
1031 req = tevent_req_create(mem_ctx, &state,
1032 struct cli_sesssetup_blob_state);
1040 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1041 usable_space = UINT16_MAX;
1043 usable_space = cli_state_available_size(cli,
1044 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1047 if (usable_space == 0) {
1048 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1049 "(not possible to send %u bytes)\n",
1050 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1051 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1052 return tevent_req_post(req, ev);
1054 state->max_blob_size = MIN(usable_space, 0xFFFF);
1056 if (!cli_sesssetup_blob_next(state, &subreq)) {
1057 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1058 return tevent_req_post(req, ev);
1060 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1064 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1065 struct tevent_req **psubreq)
1067 struct tevent_req *subreq;
1070 thistime = MIN(state->blob.length, state->max_blob_size);
1072 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1074 state->smb2_blob.data = state->blob.data;
1075 state->smb2_blob.length = thistime;
1077 state->blob.data += thistime;
1078 state->blob.length -= thistime;
1080 subreq = smb2cli_session_setup_send(state, state->ev,
1082 state->cli->timeout,
1083 state->cli->smb2.session,
1085 SMB2_CAP_DFS, /* in_capabilities */
1087 0, /* in_previous_session_id */
1089 if (subreq == NULL) {
1096 SCVAL(state->vwv+0, 0, 0xFF);
1097 SCVAL(state->vwv+0, 1, 0);
1098 SSVAL(state->vwv+1, 0, 0);
1099 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1100 SSVAL(state->vwv+3, 0, 2);
1101 SSVAL(state->vwv+4, 0, 1);
1102 SIVAL(state->vwv+5, 0, 0);
1104 SSVAL(state->vwv+7, 0, thistime);
1106 SSVAL(state->vwv+8, 0, 0);
1107 SSVAL(state->vwv+9, 0, 0);
1108 SIVAL(state->vwv+10, 0,
1109 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1111 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1113 if (state->buf == NULL) {
1116 state->blob.data += thistime;
1117 state->blob.length -= thistime;
1119 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1121 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1123 if (state->buf == NULL) {
1126 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1128 talloc_get_size(state->buf), state->buf);
1129 if (subreq == NULL) {
1136 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1138 struct tevent_req *req = tevent_req_callback_data(
1139 subreq, struct tevent_req);
1140 struct cli_sesssetup_blob_state *state = tevent_req_data(
1141 req, struct cli_sesssetup_blob_state);
1142 struct cli_state *cli = state->cli;
1149 uint16_t blob_length;
1154 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1155 status = smb2cli_session_setup_recv(subreq, state,
1159 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1160 &num_bytes, &bytes);
1161 TALLOC_FREE(state->buf);
1163 TALLOC_FREE(subreq);
1164 if (!NT_STATUS_IS_OK(status)
1165 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1166 tevent_req_nterror(req, status);
1170 state->status = status;
1172 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1177 inhdr = in + NBT_HDR_SIZE;
1178 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1180 blob_length = SVAL(vwv+3, 0);
1181 if (blob_length > num_bytes) {
1182 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1185 state->ret_blob = data_blob_const(bytes, blob_length);
1187 p = bytes + blob_length;
1189 status = smb_bytes_talloc_string(cli,
1196 if (!NT_STATUS_IS_OK(status)) {
1197 tevent_req_nterror(req, status);
1202 status = smb_bytes_talloc_string(cli,
1209 if (!NT_STATUS_IS_OK(status)) {
1210 tevent_req_nterror(req, status);
1215 status = smb_bytes_talloc_string(cli,
1217 &cli->server_domain,
1222 if (!NT_STATUS_IS_OK(status)) {
1223 tevent_req_nterror(req, status);
1229 if (state->blob.length != 0) {
1233 if (!cli_sesssetup_blob_next(state, &subreq)) {
1234 tevent_req_oom(req);
1237 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1240 tevent_req_done(req);
1243 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1244 TALLOC_CTX *mem_ctx,
1247 struct iovec **precv_iov)
1249 struct cli_sesssetup_blob_state *state = tevent_req_data(
1250 req, struct cli_sesssetup_blob_state);
1253 struct iovec *recv_iov;
1255 if (tevent_req_is_nterror(req, &status)) {
1256 TALLOC_FREE(state->cli->smb2.session);
1257 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1261 inbuf = talloc_move(mem_ctx, &state->inbuf);
1262 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1263 if (pblob != NULL) {
1264 *pblob = state->ret_blob;
1266 if (pinbuf != NULL) {
1269 if (precv_iov != NULL) {
1270 *precv_iov = recv_iov;
1272 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1273 return state->status;
1278 /****************************************************************************
1279 Use in-memory credentials cache
1280 ****************************************************************************/
1282 static void use_in_memory_ccache(void) {
1283 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1286 /****************************************************************************
1287 Do a spnego/kerberos encrypted session setup.
1288 ****************************************************************************/
1290 struct cli_session_setup_kerberos_state {
1291 struct cli_state *cli;
1292 DATA_BLOB negTokenTarg;
1293 DATA_BLOB session_key_krb5;
1294 ADS_STATUS ads_status;
1297 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1299 static struct tevent_req *cli_session_setup_kerberos_send(
1300 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1301 const char *principal)
1303 struct tevent_req *req, *subreq;
1304 struct cli_session_setup_kerberos_state *state;
1307 DEBUG(2,("Doing kerberos session setup\n"));
1309 req = tevent_req_create(mem_ctx, &state,
1310 struct cli_session_setup_kerberos_state);
1315 state->ads_status = ADS_SUCCESS;
1318 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1319 * we have to acquire a ticket. To be fixed later :-)
1321 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1322 &state->session_key_krb5, 0, NULL, NULL);
1324 DEBUG(1, ("cli_session_setup_kerberos: "
1325 "spnego_gen_krb5_negTokenInit failed: %s\n",
1326 error_message(rc)));
1327 state->ads_status = ADS_ERROR_KRB5(rc);
1328 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1329 return tevent_req_post(req, ev);
1333 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1334 state->negTokenTarg.length);
1337 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1338 state->cli->smb2.session = smbXcli_session_create(cli,
1340 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1341 return tevent_req_post(req, ev);
1345 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1346 if (tevent_req_nomem(subreq, req)) {
1347 return tevent_req_post(req, ev);
1349 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1353 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1355 struct tevent_req *req = tevent_req_callback_data(
1356 subreq, struct tevent_req);
1357 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1358 req, struct cli_session_setup_kerberos_state);
1359 uint8_t *inbuf = NULL;
1360 struct iovec *recv_iov = NULL;
1363 status = cli_sesssetup_blob_recv(subreq, state,
1364 NULL, &inbuf, &recv_iov);
1365 TALLOC_FREE(subreq);
1366 if (!NT_STATUS_IS_OK(status)) {
1367 tevent_req_nterror(req, status);
1371 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1372 struct smbXcli_session *session = state->cli->smb2.session;
1373 status = smb2cli_session_set_session_key(session,
1374 state->session_key_krb5,
1376 if (tevent_req_nterror(req, status)) {
1380 struct smbXcli_session *session = state->cli->smb1.session;
1382 status = smb1cli_session_set_session_key(session,
1383 state->session_key_krb5);
1384 if (tevent_req_nterror(req, status)) {
1388 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1390 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1391 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1396 tevent_req_done(req);
1399 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1401 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1402 req, struct cli_session_setup_kerberos_state);
1405 if (tevent_req_is_nterror(req, &status)) {
1406 return ADS_ERROR_NT(status);
1408 return state->ads_status;
1411 #endif /* HAVE_KRB5 */
1413 /****************************************************************************
1414 Do a spnego/NTLMSSP encrypted session setup.
1415 ****************************************************************************/
1417 struct cli_session_setup_ntlmssp_state {
1418 struct tevent_context *ev;
1419 struct cli_state *cli;
1420 struct ntlmssp_state *ntlmssp_state;
1425 static int cli_session_setup_ntlmssp_state_destructor(
1426 struct cli_session_setup_ntlmssp_state *state)
1428 if (state->ntlmssp_state != NULL) {
1429 TALLOC_FREE(state->ntlmssp_state);
1434 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1436 static struct tevent_req *cli_session_setup_ntlmssp_send(
1437 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1438 const char *user, const char *pass, const char *domain)
1440 struct tevent_req *req, *subreq;
1441 struct cli_session_setup_ntlmssp_state *state;
1444 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1446 req = tevent_req_create(mem_ctx, &state,
1447 struct cli_session_setup_ntlmssp_state);
1455 state->ntlmssp_state = NULL;
1456 talloc_set_destructor(
1457 state, cli_session_setup_ntlmssp_state_destructor);
1459 status = ntlmssp_client_start(state,
1462 lp_client_ntlmv2_auth(),
1463 &state->ntlmssp_state);
1464 if (!NT_STATUS_IS_OK(status)) {
1467 ntlmssp_want_feature(state->ntlmssp_state,
1468 NTLMSSP_FEATURE_SESSION_KEY);
1469 if (cli->use_ccache) {
1470 ntlmssp_want_feature(state->ntlmssp_state,
1471 NTLMSSP_FEATURE_CCACHE);
1473 status = ntlmssp_set_username(state->ntlmssp_state, user);
1474 if (!NT_STATUS_IS_OK(status)) {
1477 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1478 if (!NT_STATUS_IS_OK(status)) {
1481 if (cli->pw_nt_hash) {
1482 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1484 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1486 if (!NT_STATUS_IS_OK(status)) {
1489 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1491 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1495 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1496 data_blob_free(&blob_out);
1498 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1499 state->cli->smb2.session = smbXcli_session_create(cli,
1501 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1502 return tevent_req_post(req, ev);
1506 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1507 if (tevent_req_nomem(subreq, req)) {
1508 return tevent_req_post(req, ev);
1510 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1513 tevent_req_nterror(req, status);
1514 return tevent_req_post(req, ev);
1517 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1519 struct tevent_req *req = tevent_req_callback_data(
1520 subreq, struct tevent_req);
1521 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1522 req, struct cli_session_setup_ntlmssp_state);
1523 DATA_BLOB blob_in, msg_in, blob_out;
1524 uint8_t *inbuf = NULL;
1525 struct iovec *recv_iov = NULL;
1529 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1531 TALLOC_FREE(subreq);
1532 data_blob_free(&state->blob_out);
1534 if (NT_STATUS_IS_OK(status)) {
1535 if (state->cli->server_domain[0] == '\0') {
1536 TALLOC_FREE(state->cli->server_domain);
1537 state->cli->server_domain = talloc_strdup(state->cli,
1538 state->ntlmssp_state->server.netbios_domain);
1539 if (state->cli->server_domain == NULL) {
1540 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1545 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1546 struct smbXcli_session *session = state->cli->smb2.session;
1548 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1550 * Windows server does not set the
1551 * SMB2_SESSION_FLAG_IS_GUEST nor
1552 * SMB2_SESSION_FLAG_IS_NULL flag.
1554 * This fix makes sure we do not try
1555 * to verify a signature on the final
1556 * session setup response.
1558 TALLOC_FREE(state->ntlmssp_state);
1559 tevent_req_done(req);
1563 status = smb2cli_session_set_session_key(session,
1564 state->ntlmssp_state->session_key,
1566 if (tevent_req_nterror(req, status)) {
1570 struct smbXcli_session *session = state->cli->smb1.session;
1572 status = smb1cli_session_set_session_key(session,
1573 state->ntlmssp_state->session_key);
1574 if (tevent_req_nterror(req, status)) {
1578 if (smb1cli_conn_activate_signing(
1579 state->cli->conn, state->ntlmssp_state->session_key,
1581 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1582 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1586 TALLOC_FREE(state->ntlmssp_state);
1587 tevent_req_done(req);
1590 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1591 tevent_req_nterror(req, status);
1595 if (blob_in.length == 0) {
1596 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1600 if ((state->turn == 1)
1601 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1602 DATA_BLOB tmp_blob = data_blob_null;
1603 /* the server might give us back two challenges */
1604 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1606 data_blob_free(&tmp_blob);
1608 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1609 OID_NTLMSSP, &msg_in);
1614 DEBUG(3,("Failed to parse auth response\n"));
1615 if (NT_STATUS_IS_OK(status)
1616 || NT_STATUS_EQUAL(status,
1617 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1619 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1624 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1626 if (!NT_STATUS_IS_OK(status)
1627 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1628 TALLOC_FREE(state->ntlmssp_state);
1629 tevent_req_nterror(req, status);
1633 state->blob_out = spnego_gen_auth(state, blob_out);
1634 if (tevent_req_nomem(state->blob_out.data, req)) {
1638 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1640 if (tevent_req_nomem(subreq, req)) {
1643 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1646 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1648 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1649 req, struct cli_session_setup_ntlmssp_state);
1652 if (tevent_req_is_nterror(req, &status)) {
1653 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1656 return NT_STATUS_OK;
1661 static char *cli_session_setup_get_principal(
1662 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1663 const char *remote_name, const char *dest_realm)
1665 char *principal = NULL;
1667 if (!lp_client_use_spnego_principal() ||
1668 strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1669 spnego_principal = NULL;
1671 if (spnego_principal != NULL) {
1672 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1673 "principal %s\n", spnego_principal));
1674 return talloc_strdup(mem_ctx, spnego_principal);
1676 if (is_ipaddress(remote_name) ||
1677 strequal(remote_name, STAR_SMBSERVER)) {
1681 DEBUG(3, ("cli_session_setup_spnego: using target "
1682 "hostname not SPNEGO principal\n"));
1685 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1686 if (realm == NULL) {
1689 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1690 remote_name, realm);
1693 principal = kerberos_get_principal_from_service_hostname(
1694 talloc_tos(), "cifs", remote_name, lp_realm());
1696 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1697 principal ? principal : "<null>"));
1703 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1704 const char *principal)
1708 account = talloc_strdup(mem_ctx, principal);
1709 if (account == NULL) {
1712 p = strchr_m(account, '@');
1719 /****************************************************************************
1720 Do a spnego encrypted session setup.
1722 user_domain: The shortname of the domain the user/machine is a member of.
1723 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1724 ****************************************************************************/
1726 struct cli_session_setup_spnego_state {
1727 struct tevent_context *ev;
1728 struct cli_state *cli;
1730 const char *account;
1732 const char *user_domain;
1733 const char *dest_realm;
1738 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1741 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1743 static struct tevent_req *cli_session_setup_spnego_send(
1744 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1745 const char *user, const char *pass, const char *user_domain,
1746 const char *dest_realm)
1748 struct tevent_req *req, *subreq;
1749 struct cli_session_setup_spnego_state *state;
1750 char *principal = NULL;
1751 char *OIDs[ASN1_MAX_OIDS];
1753 const DATA_BLOB *server_blob;
1756 req = tevent_req_create(mem_ctx, &state,
1757 struct cli_session_setup_spnego_state);
1765 state->user_domain = user_domain;
1766 state->dest_realm = dest_realm;
1768 state->account = cli_session_setup_get_account(state, user);
1769 if (tevent_req_nomem(state->account, req)) {
1770 return tevent_req_post(req, ev);
1773 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1775 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1776 (unsigned long)server_blob->length));
1778 /* the server might not even do spnego */
1779 if (server_blob->length == 0) {
1780 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1785 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1788 /* The server sent us the first part of the SPNEGO exchange in the
1789 * negprot reply. It is WRONG to depend on the principal sent in the
1790 * negprot reply, but right now we do it. If we don't receive one,
1791 * we try to best guess, then fall back to NTLM. */
1792 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1793 &principal, NULL) ||
1795 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1796 tevent_req_done(req);
1797 return tevent_req_post(req, ev);
1800 /* make sure the server understands kerberos */
1801 for (i=0;OIDs[i];i++) {
1803 DEBUG(3,("got OID=%s\n", OIDs[i]));
1805 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1806 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1807 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1808 cli->got_kerberos_mechanism = True;
1810 talloc_free(OIDs[i]);
1813 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1815 status = cli_set_username(cli, user);
1816 if (!NT_STATUS_IS_OK(status)) {
1817 state->result = ADS_ERROR_NT(status);
1818 tevent_req_done(req);
1819 return tevent_req_post(req, ev);
1823 /* If password is set we reauthenticate to kerberos server
1824 * and do not store results */
1826 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1827 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1830 if (pass && *pass) {
1833 use_in_memory_ccache();
1834 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1837 TALLOC_FREE(principal);
1838 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1839 if (cli->fallback_after_kerberos)
1841 state->result = ADS_ERROR_KRB5(ret);
1842 tevent_req_done(req);
1843 return tevent_req_post(req, ev);
1847 tmp = cli_session_setup_get_principal(
1848 talloc_tos(), principal, remote_name, dest_realm);
1849 TALLOC_FREE(principal);
1853 subreq = cli_session_setup_kerberos_send(
1854 state, ev, cli, principal);
1855 if (tevent_req_nomem(subreq, req)) {
1856 return tevent_req_post(req, ev);
1858 tevent_req_set_callback(
1859 subreq, cli_session_setup_spnego_done_krb,
1867 subreq = cli_session_setup_ntlmssp_send(
1868 state, ev, cli, state->account, pass, user_domain);
1869 if (tevent_req_nomem(subreq, req)) {
1870 return tevent_req_post(req, ev);
1872 tevent_req_set_callback(
1873 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1878 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1880 struct tevent_req *req = tevent_req_callback_data(
1881 subreq, struct tevent_req);
1882 struct cli_session_setup_spnego_state *state = tevent_req_data(
1883 req, struct cli_session_setup_spnego_state);
1885 state->result = cli_session_setup_kerberos_recv(subreq);
1886 TALLOC_FREE(subreq);
1888 if (ADS_ERR_OK(state->result) ||
1889 !state->cli->fallback_after_kerberos) {
1890 tevent_req_done(req);
1894 subreq = cli_session_setup_ntlmssp_send(
1895 state, state->ev, state->cli, state->account, state->pass,
1896 state->user_domain);
1897 if (tevent_req_nomem(subreq, req)) {
1900 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1905 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1907 struct tevent_req *req = tevent_req_callback_data(
1908 subreq, struct tevent_req);
1909 struct cli_session_setup_spnego_state *state = tevent_req_data(
1910 req, struct cli_session_setup_spnego_state);
1913 status = cli_session_setup_ntlmssp_recv(subreq);
1914 TALLOC_FREE(subreq);
1915 state->result = ADS_ERROR_NT(status);
1916 tevent_req_done(req);
1919 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1921 struct cli_session_setup_spnego_state *state = tevent_req_data(
1922 req, struct cli_session_setup_spnego_state);
1924 return state->result;
1927 struct cli_session_setup_state {
1931 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1932 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1933 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1934 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1935 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1937 /****************************************************************************
1938 Send a session setup. The username and workgroup is in UNIX character
1939 format and must be converted to DOS codepage format before sending. If the
1940 password is in plaintext, the same should be done.
1941 ****************************************************************************/
1943 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1944 struct tevent_context *ev,
1945 struct cli_state *cli,
1947 const char *pass, int passlen,
1948 const char *ntpass, int ntpasslen,
1949 const char *workgroup)
1951 struct tevent_req *req, *subreq;
1952 struct cli_session_setup_state *state;
1955 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1957 req = tevent_req_create(mem_ctx, &state,
1958 struct cli_session_setup_state);
1964 user2 = talloc_strdup(state, user);
1966 user2 = talloc_strdup(state, "");
1968 if (user2 == NULL) {
1969 tevent_req_oom(req);
1970 return tevent_req_post(req, ev);
1977 /* allow for workgroups as part of the username */
1978 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1979 (p=strchr_m(user2,*lp_winbind_separator()))) {
1982 if (!strupper_m(user2)) {
1983 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1984 return tevent_req_post(req, ev);
1989 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1990 tevent_req_done(req);
1991 return tevent_req_post(req, ev);
1994 /* now work out what sort of session setup we are going to
1995 do. I have split this into separate functions to make the
1996 flow a bit easier to understand (tridge) */
1998 /* if its an older server then we have to use the older request format */
2000 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2001 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2002 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2003 " or 'client ntlmv2 auth = yes'\n"));
2004 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2005 return tevent_req_post(req, ev);
2008 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2009 !lp_client_plaintext_auth() && (*pass)) {
2010 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2011 " or 'client ntlmv2 auth = yes'\n"));
2012 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2013 return tevent_req_post(req, ev);
2016 subreq = cli_session_setup_lanman2_send(
2017 state, ev, cli, user, pass, passlen, workgroup);
2018 if (tevent_req_nomem(subreq, req)) {
2019 return tevent_req_post(req, ev);
2021 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2026 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2027 const char *remote_realm = cli_state_remote_realm(cli);
2029 subreq = cli_session_setup_spnego_send(
2030 state, ev, cli, user, pass, workgroup, remote_realm);
2031 if (tevent_req_nomem(subreq, req)) {
2032 return tevent_req_post(req, ev);
2034 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2039 /* if no user is supplied then we have to do an anonymous connection.
2040 passwords are ignored */
2042 if (!user || !*user) {
2043 subreq = cli_session_setup_guest_send(state, ev, cli);
2044 if (tevent_req_nomem(subreq, req)) {
2045 return tevent_req_post(req, ev);
2047 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2052 /* if the server is share level then send a plaintext null
2053 password at this point. The password is sent in the tree
2056 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2057 subreq = cli_session_setup_plain_send(
2058 state, ev, cli, user, "", workgroup);
2059 if (tevent_req_nomem(subreq, req)) {
2060 return tevent_req_post(req, ev);
2062 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2067 /* if the server doesn't support encryption then we have to use
2068 plaintext. The second password is ignored */
2070 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2071 if (!lp_client_plaintext_auth() && (*pass)) {
2072 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2073 " or 'client ntlmv2 auth = yes'\n"));
2074 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2075 return tevent_req_post(req, ev);
2077 subreq = cli_session_setup_plain_send(
2078 state, ev, cli, user, pass, workgroup);
2079 if (tevent_req_nomem(subreq, req)) {
2080 return tevent_req_post(req, ev);
2082 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2087 /* if the server supports extended security then use SPNEGO */
2089 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2090 const char *remote_realm = cli_state_remote_realm(cli);
2092 subreq = cli_session_setup_spnego_send(
2093 state, ev, cli, user, pass, workgroup, remote_realm);
2094 if (tevent_req_nomem(subreq, req)) {
2095 return tevent_req_post(req, ev);
2097 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2101 /* otherwise do a NT1 style session setup */
2103 subreq = cli_session_setup_nt1_send(
2104 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2106 if (tevent_req_nomem(subreq, req)) {
2107 return tevent_req_post(req, ev);
2109 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2114 tevent_req_done(req);
2115 return tevent_req_post(req, ev);
2118 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2120 struct tevent_req *req = tevent_req_callback_data(
2121 subreq, struct tevent_req);
2124 status = cli_session_setup_lanman2_recv(subreq);
2125 TALLOC_FREE(subreq);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 tevent_req_nterror(req, status);
2130 tevent_req_done(req);
2133 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2135 struct tevent_req *req = tevent_req_callback_data(
2136 subreq, struct tevent_req);
2139 status = cli_session_setup_spnego_recv(subreq);
2140 TALLOC_FREE(subreq);
2141 if (!ADS_ERR_OK(status)) {
2142 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2143 tevent_req_nterror(req, ads_ntstatus(status));
2146 tevent_req_done(req);
2149 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2151 struct tevent_req *req = tevent_req_callback_data(
2152 subreq, struct tevent_req);
2155 status = cli_session_setup_guest_recv(subreq);
2156 TALLOC_FREE(subreq);
2157 if (!NT_STATUS_IS_OK(status)) {
2158 tevent_req_nterror(req, status);
2161 tevent_req_done(req);
2164 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2166 struct tevent_req *req = tevent_req_callback_data(
2167 subreq, struct tevent_req);
2170 status = cli_session_setup_plain_recv(subreq);
2171 TALLOC_FREE(subreq);
2172 if (!NT_STATUS_IS_OK(status)) {
2173 tevent_req_nterror(req, status);
2176 tevent_req_done(req);
2179 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2181 struct tevent_req *req = tevent_req_callback_data(
2182 subreq, struct tevent_req);
2185 status = cli_session_setup_nt1_recv(subreq);
2186 TALLOC_FREE(subreq);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 DEBUG(3, ("cli_session_setup: NT1 session setup "
2189 "failed: %s\n", nt_errstr(status)));
2190 tevent_req_nterror(req, status);
2193 tevent_req_done(req);
2196 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2198 return tevent_req_simple_recv_ntstatus(req);
2201 NTSTATUS cli_session_setup(struct cli_state *cli,
2203 const char *pass, int passlen,
2204 const char *ntpass, int ntpasslen,
2205 const char *workgroup)
2207 struct tevent_context *ev;
2208 struct tevent_req *req;
2209 NTSTATUS status = NT_STATUS_NO_MEMORY;
2211 if (smbXcli_conn_has_async_calls(cli->conn)) {
2212 return NT_STATUS_INVALID_PARAMETER;
2214 ev = samba_tevent_context_init(talloc_tos());
2218 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2219 ntpass, ntpasslen, workgroup);
2223 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2226 status = cli_session_setup_recv(req);
2232 /****************************************************************************
2234 *****************************************************************************/
2236 struct cli_ulogoff_state {
2237 struct cli_state *cli;
2241 static void cli_ulogoff_done(struct tevent_req *subreq);
2243 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2244 struct tevent_context *ev,
2245 struct cli_state *cli)
2247 struct tevent_req *req, *subreq;
2248 struct cli_ulogoff_state *state;
2250 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2256 SCVAL(state->vwv+0, 0, 0xFF);
2257 SCVAL(state->vwv+1, 0, 0);
2258 SSVAL(state->vwv+2, 0, 0);
2260 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2262 if (tevent_req_nomem(subreq, req)) {
2263 return tevent_req_post(req, ev);
2265 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2269 static void cli_ulogoff_done(struct tevent_req *subreq)
2271 struct tevent_req *req = tevent_req_callback_data(
2272 subreq, struct tevent_req);
2273 struct cli_ulogoff_state *state = tevent_req_data(
2274 req, struct cli_ulogoff_state);
2277 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2278 if (!NT_STATUS_IS_OK(status)) {
2279 tevent_req_nterror(req, status);
2282 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2283 tevent_req_done(req);
2286 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2288 return tevent_req_simple_recv_ntstatus(req);
2291 NTSTATUS cli_ulogoff(struct cli_state *cli)
2293 struct tevent_context *ev;
2294 struct tevent_req *req;
2295 NTSTATUS status = NT_STATUS_NO_MEMORY;
2297 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2298 status = smb2cli_logoff(cli->conn,
2301 if (!NT_STATUS_IS_OK(status)) {
2304 smb2cli_session_set_id_and_flags(cli->smb2.session,
2306 return NT_STATUS_OK;
2309 if (smbXcli_conn_has_async_calls(cli->conn)) {
2310 return NT_STATUS_INVALID_PARAMETER;
2312 ev = samba_tevent_context_init(talloc_tos());
2316 req = cli_ulogoff_send(ev, ev, cli);
2320 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2323 status = cli_ulogoff_recv(req);
2329 /****************************************************************************
2331 ****************************************************************************/
2333 struct cli_tcon_andx_state {
2334 struct cli_state *cli;
2339 static void cli_tcon_andx_done(struct tevent_req *subreq);
2341 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2342 struct tevent_context *ev,
2343 struct cli_state *cli,
2344 const char *share, const char *dev,
2345 const char *pass, int passlen,
2346 struct tevent_req **psmbreq)
2348 struct tevent_req *req, *subreq;
2349 struct cli_tcon_andx_state *state;
2354 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2355 uint16_t tcon_flags = 0;
2359 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2366 cli->share = talloc_strdup(cli, share);
2371 /* in user level security don't send a password now */
2372 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2375 } else if (pass == NULL) {
2376 DEBUG(1, ("Server not using user level security and no "
2377 "password supplied.\n"));
2381 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2382 *pass && passlen != 24) {
2383 if (!lp_client_lanman_auth()) {
2384 DEBUG(1, ("Server requested LANMAN password "
2385 "(share-level security) but "
2386 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2391 * Non-encrypted passwords - convert to DOS codepage before
2394 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2396 pass = (const char *)p24;
2398 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2399 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2403 if (!lp_client_plaintext_auth() && (*pass)) {
2404 DEBUG(1, ("Server requested PLAINTEXT "
2406 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2411 * Non-encrypted passwords - convert to DOS codepage
2414 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2415 if (tevent_req_nomem(tmp_pass, req)) {
2416 return tevent_req_post(req, ev);
2418 tmp_pass = trans2_bytes_push_str(tmp_pass,
2419 false, /* always DOS */
2423 if (tevent_req_nomem(tmp_pass, req)) {
2424 return tevent_req_post(req, ev);
2426 pass = (const char *)tmp_pass;
2427 passlen = talloc_get_size(tmp_pass);
2431 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2432 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2434 SCVAL(vwv+0, 0, 0xFF);
2437 SSVAL(vwv+2, 0, tcon_flags);
2438 SSVAL(vwv+3, 0, passlen);
2440 if (passlen && pass) {
2441 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2443 bytes = talloc_array(state, uint8_t, 0);
2449 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2450 smbXcli_conn_remote_name(cli->conn), share);
2455 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2460 * Add the devicetype
2462 tmp = talloc_strdup_upper(talloc_tos(), dev);
2467 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2470 if (bytes == NULL) {
2475 state->bytes.iov_base = (void *)bytes;
2476 state->bytes.iov_len = talloc_get_size(bytes);
2478 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2480 if (subreq == NULL) {
2484 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2489 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2490 return tevent_req_post(req, ev);
2493 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2494 struct tevent_context *ev,
2495 struct cli_state *cli,
2496 const char *share, const char *dev,
2497 const char *pass, int passlen)
2499 struct tevent_req *req, *subreq;
2502 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2507 if (subreq == NULL) {
2510 status = smb1cli_req_chain_submit(&subreq, 1);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 tevent_req_nterror(req, status);
2513 return tevent_req_post(req, ev);
2518 static void cli_tcon_andx_done(struct tevent_req *subreq)
2520 struct tevent_req *req = tevent_req_callback_data(
2521 subreq, struct tevent_req);
2522 struct cli_tcon_andx_state *state = tevent_req_data(
2523 req, struct cli_tcon_andx_state);
2524 struct cli_state *cli = state->cli;
2532 uint16_t optional_support = 0;
2534 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2535 &num_bytes, &bytes);
2536 TALLOC_FREE(subreq);
2537 if (!NT_STATUS_IS_OK(status)) {
2538 tevent_req_nterror(req, status);
2542 inhdr = in + NBT_HDR_SIZE;
2545 if (clistr_pull_talloc(cli,
2546 (const char *)inhdr,
2547 SVAL(inhdr, HDR_FLG2),
2551 STR_TERMINATE|STR_ASCII) == -1) {
2552 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2556 cli->dev = talloc_strdup(cli, "");
2557 if (cli->dev == NULL) {
2558 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2563 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2564 /* almost certainly win95 - enable bug fixes */
2569 * Make sure that we have the optional support 16-bit field. WCT > 2.
2570 * Avoids issues when connecting to Win9x boxes sharing files
2573 cli->dfsroot = false;
2575 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2576 optional_support = SVAL(vwv+2, 0);
2579 if (optional_support & SMB_SHARE_IN_DFS) {
2580 cli->dfsroot = true;
2583 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2584 smb1cli_session_protect_session_key(cli->smb1.session);
2587 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2588 SVAL(inhdr, HDR_TID),
2590 0, /* maximal_access */
2591 0, /* guest_maximal_access */
2593 NULL); /* fs_type */
2595 tevent_req_done(req);
2598 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2600 return tevent_req_simple_recv_ntstatus(req);
2603 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2604 const char *dev, const char *pass, int passlen)
2606 TALLOC_CTX *frame = talloc_stackframe();
2607 struct tevent_context *ev;
2608 struct tevent_req *req;
2609 NTSTATUS status = NT_STATUS_NO_MEMORY;
2611 if (smbXcli_conn_has_async_calls(cli->conn)) {
2613 * Can't use sync call while an async call is in flight
2615 status = NT_STATUS_INVALID_PARAMETER;
2619 ev = samba_tevent_context_init(frame);
2624 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2629 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2633 status = cli_tcon_andx_recv(req);
2639 struct cli_tree_connect_state {
2640 struct cli_state *cli;
2643 static struct tevent_req *cli_raw_tcon_send(
2644 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2645 const char *service, const char *pass, const char *dev);
2646 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2647 uint16 *max_xmit, uint16 *tid);
2649 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2650 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2651 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2653 static struct tevent_req *cli_tree_connect_send(
2654 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2655 const char *share, const char *dev, const char *pass, int passlen)
2657 struct tevent_req *req, *subreq;
2658 struct cli_tree_connect_state *state;
2660 req = tevent_req_create(mem_ctx, &state,
2661 struct cli_tree_connect_state);
2667 cli->share = talloc_strdup(cli, share);
2668 if (tevent_req_nomem(cli->share, req)) {
2669 return tevent_req_post(req, ev);
2672 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2673 subreq = smb2cli_tcon_send(state, ev, cli, share);
2674 if (tevent_req_nomem(subreq, req)) {
2675 return tevent_req_post(req, ev);
2677 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2682 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2683 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2685 if (tevent_req_nomem(subreq, req)) {
2686 return tevent_req_post(req, ev);
2688 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2693 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2694 if (tevent_req_nomem(subreq, req)) {
2695 return tevent_req_post(req, ev);
2697 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2702 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2704 tevent_req_simple_finish_ntstatus(
2705 subreq, smb2cli_tcon_recv(subreq));
2708 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2710 tevent_req_simple_finish_ntstatus(
2711 subreq, cli_tcon_andx_recv(subreq));
2714 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2716 struct tevent_req *req = tevent_req_callback_data(
2717 subreq, struct tevent_req);
2718 struct cli_tree_connect_state *state = tevent_req_data(
2719 req, struct cli_tree_connect_state);
2721 uint16_t max_xmit = 0;
2724 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2725 if (tevent_req_nterror(req, status)) {
2729 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2731 0, /* optional_support */
2732 0, /* maximal_access */
2733 0, /* guest_maximal_access */
2735 NULL); /* fs_type */
2737 tevent_req_done(req);
2740 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2742 return tevent_req_simple_recv_ntstatus(req);
2745 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2746 const char *dev, const char *pass, int passlen)
2748 struct tevent_context *ev;
2749 struct tevent_req *req;
2750 NTSTATUS status = NT_STATUS_NO_MEMORY;
2752 if (smbXcli_conn_has_async_calls(cli->conn)) {
2753 return NT_STATUS_INVALID_PARAMETER;
2755 ev = samba_tevent_context_init(talloc_tos());
2759 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2763 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2766 status = cli_tree_connect_recv(req);
2772 /****************************************************************************
2773 Send a tree disconnect.
2774 ****************************************************************************/
2776 struct cli_tdis_state {
2777 struct cli_state *cli;
2780 static void cli_tdis_done(struct tevent_req *subreq);
2782 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2783 struct tevent_context *ev,
2784 struct cli_state *cli)
2786 struct tevent_req *req, *subreq;
2787 struct cli_tdis_state *state;
2789 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2795 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2796 if (tevent_req_nomem(subreq, req)) {
2797 return tevent_req_post(req, ev);
2799 tevent_req_set_callback(subreq, cli_tdis_done, req);
2803 static void cli_tdis_done(struct tevent_req *subreq)
2805 struct tevent_req *req = tevent_req_callback_data(
2806 subreq, struct tevent_req);
2807 struct cli_tdis_state *state = tevent_req_data(
2808 req, struct cli_tdis_state);
2811 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2812 TALLOC_FREE(subreq);
2813 if (!NT_STATUS_IS_OK(status)) {
2814 tevent_req_nterror(req, status);
2817 cli_state_set_tid(state->cli, UINT16_MAX);
2818 tevent_req_done(req);
2821 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2823 return tevent_req_simple_recv_ntstatus(req);
2826 NTSTATUS cli_tdis(struct cli_state *cli)
2828 struct tevent_context *ev;
2829 struct tevent_req *req;
2830 NTSTATUS status = NT_STATUS_NO_MEMORY;
2832 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2833 return smb2cli_tdis(cli);
2836 if (smbXcli_conn_has_async_calls(cli->conn)) {
2837 return NT_STATUS_INVALID_PARAMETER;
2839 ev = samba_tevent_context_init(talloc_tos());
2843 req = cli_tdis_send(ev, ev, cli);
2847 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2850 status = cli_tdis_recv(req);
2856 struct cli_connect_sock_state {
2857 const char **called_names;
2858 const char **calling_names;
2864 static void cli_connect_sock_done(struct tevent_req *subreq);
2867 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2871 static struct tevent_req *cli_connect_sock_send(
2872 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2873 const char *host, int name_type, const struct sockaddr_storage *pss,
2874 const char *myname, uint16_t port)
2876 struct tevent_req *req, *subreq;
2877 struct cli_connect_sock_state *state;
2879 unsigned i, num_addrs;
2882 req = tevent_req_create(mem_ctx, &state,
2883 struct cli_connect_sock_state);
2888 prog = getenv("LIBSMB_PROG");
2890 state->fd = sock_exec(prog);
2891 if (state->fd == -1) {
2892 status = map_nt_error_from_unix(errno);
2893 tevent_req_nterror(req, status);
2896 tevent_req_done(req);
2898 return tevent_req_post(req, ev);
2901 if ((pss == NULL) || is_zero_addr(pss)) {
2902 struct sockaddr_storage *addrs;
2905 * Here we cheat. resolve_name_list is not async at all. So
2906 * this call will only be really async if the name lookup has
2907 * been done externally.
2910 status = resolve_name_list(state, host, name_type,
2911 &addrs, &num_addrs);
2912 if (!NT_STATUS_IS_OK(status)) {
2913 tevent_req_nterror(req, status);
2914 return tevent_req_post(req, ev);
2921 state->called_names = talloc_array(state, const char *, num_addrs);
2922 if (tevent_req_nomem(state->called_names, req)) {
2923 return tevent_req_post(req, ev);
2925 state->called_types = talloc_array(state, int, num_addrs);
2926 if (tevent_req_nomem(state->called_types, req)) {
2927 return tevent_req_post(req, ev);
2929 state->calling_names = talloc_array(state, const char *, num_addrs);
2930 if (tevent_req_nomem(state->calling_names, req)) {
2931 return tevent_req_post(req, ev);
2933 for (i=0; i<num_addrs; i++) {
2934 state->called_names[i] = host;
2935 state->called_types[i] = name_type;
2936 state->calling_names[i] = myname;
2939 subreq = smbsock_any_connect_send(
2940 state, ev, pss, state->called_names, state->called_types,
2941 state->calling_names, NULL, num_addrs, port);
2942 if (tevent_req_nomem(subreq, req)) {
2943 return tevent_req_post(req, ev);
2945 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2949 static void cli_connect_sock_done(struct tevent_req *subreq)
2951 struct tevent_req *req = tevent_req_callback_data(
2952 subreq, struct tevent_req);
2953 struct cli_connect_sock_state *state = tevent_req_data(
2954 req, struct cli_connect_sock_state);
2957 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2959 TALLOC_FREE(subreq);
2960 if (tevent_req_nterror(req, status)) {
2963 set_socket_options(state->fd, lp_socket_options());
2964 tevent_req_done(req);
2967 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2968 int *pfd, uint16_t *pport)
2970 struct cli_connect_sock_state *state = tevent_req_data(
2971 req, struct cli_connect_sock_state);
2974 if (tevent_req_is_nterror(req, &status)) {
2978 *pport = state->port;
2979 return NT_STATUS_OK;
2982 struct cli_connect_nb_state {
2983 const char *desthost;
2986 struct cli_state *cli;
2989 static void cli_connect_nb_done(struct tevent_req *subreq);
2991 static struct tevent_req *cli_connect_nb_send(
2992 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2993 const char *host, const struct sockaddr_storage *dest_ss,
2994 uint16_t port, int name_type, const char *myname,
2995 int signing_state, int flags)
2997 struct tevent_req *req, *subreq;
2998 struct cli_connect_nb_state *state;
3001 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3005 state->desthost = host;
3006 state->signing_state = signing_state;
3007 state->flags = flags;
3009 p = strchr(host, '#');
3011 name_type = strtol(p+1, NULL, 16);
3012 host = talloc_strndup(state, host, p - host);
3013 if (tevent_req_nomem(host, req)) {
3014 return tevent_req_post(req, ev);
3018 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3020 if (tevent_req_nomem(subreq, req)) {
3021 return tevent_req_post(req, ev);
3023 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3027 static void cli_connect_nb_done(struct tevent_req *subreq)
3029 struct tevent_req *req = tevent_req_callback_data(
3030 subreq, struct tevent_req);
3031 struct cli_connect_nb_state *state = tevent_req_data(
3032 req, struct cli_connect_nb_state);
3037 status = cli_connect_sock_recv(subreq, &fd, &port);
3038 TALLOC_FREE(subreq);
3039 if (tevent_req_nterror(req, status)) {
3043 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3044 state->signing_state, state->flags);
3045 if (tevent_req_nomem(state->cli, req)) {
3049 tevent_req_done(req);
3052 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3053 struct cli_state **pcli)
3055 struct cli_connect_nb_state *state = tevent_req_data(
3056 req, struct cli_connect_nb_state);
3059 if (tevent_req_is_nterror(req, &status)) {
3062 *pcli = talloc_move(NULL, &state->cli);
3063 return NT_STATUS_OK;
3066 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3067 uint16_t port, int name_type, const char *myname,
3068 int signing_state, int flags, struct cli_state **pcli)
3070 struct tevent_context *ev;
3071 struct tevent_req *req;
3072 NTSTATUS status = NT_STATUS_NO_MEMORY;
3074 ev = samba_tevent_context_init(talloc_tos());
3078 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3079 myname, signing_state, flags);
3083 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3086 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3089 status = cli_connect_nb_recv(req, pcli);
3095 struct cli_start_connection_state {
3096 struct tevent_context *ev;
3097 struct cli_state *cli;
3100 static void cli_start_connection_connected(struct tevent_req *subreq);
3101 static void cli_start_connection_done(struct tevent_req *subreq);
3104 establishes a connection to after the negprot.
3105 @param output_cli A fully initialised cli structure, non-null only on success
3106 @param dest_host The netbios name of the remote host
3107 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3108 @param port (optional) The destination port (0 for default)
3111 static struct tevent_req *cli_start_connection_send(
3112 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3113 const char *my_name, const char *dest_host,
3114 const struct sockaddr_storage *dest_ss, int port,
3115 int signing_state, int flags)
3117 struct tevent_req *req, *subreq;
3118 struct cli_start_connection_state *state;
3120 req = tevent_req_create(mem_ctx, &state,
3121 struct cli_start_connection_state);
3127 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3128 0x20, my_name, signing_state, flags);
3129 if (tevent_req_nomem(subreq, req)) {
3130 return tevent_req_post(req, ev);
3132 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3136 static void cli_start_connection_connected(struct tevent_req *subreq)
3138 struct tevent_req *req = tevent_req_callback_data(
3139 subreq, struct tevent_req);
3140 struct cli_start_connection_state *state = tevent_req_data(
3141 req, struct cli_start_connection_state);
3144 status = cli_connect_nb_recv(subreq, &state->cli);
3145 TALLOC_FREE(subreq);
3146 if (tevent_req_nterror(req, status)) {
3150 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3151 state->cli->timeout,
3152 lp_cli_minprotocol(),
3153 lp_cli_maxprotocol());
3154 if (tevent_req_nomem(subreq, req)) {
3157 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3160 static void cli_start_connection_done(struct tevent_req *subreq)
3162 struct tevent_req *req = tevent_req_callback_data(
3163 subreq, struct tevent_req);
3164 struct cli_start_connection_state *state = tevent_req_data(
3165 req, struct cli_start_connection_state);
3168 status = smbXcli_negprot_recv(subreq);
3169 TALLOC_FREE(subreq);
3170 if (tevent_req_nterror(req, status)) {
3174 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3175 /* Ensure we ask for some initial credits. */
3176 smb2cli_conn_set_max_credits(state->cli->conn,
3177 DEFAULT_SMB2_MAX_CREDITS);
3180 tevent_req_done(req);
3183 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3184 struct cli_state **output_cli)
3186 struct cli_start_connection_state *state = tevent_req_data(
3187 req, struct cli_start_connection_state);
3190 if (tevent_req_is_nterror(req, &status)) {
3193 *output_cli = state->cli;
3195 return NT_STATUS_OK;
3198 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3199 const char *my_name,
3200 const char *dest_host,
3201 const struct sockaddr_storage *dest_ss, int port,
3202 int signing_state, int flags)
3204 struct tevent_context *ev;
3205 struct tevent_req *req;
3206 NTSTATUS status = NT_STATUS_NO_MEMORY;
3208 ev = samba_tevent_context_init(talloc_tos());
3212 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3213 port, signing_state, flags);
3217 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3220 status = cli_start_connection_recv(req, output_cli);
3227 establishes a connection right up to doing tconX, password specified.
3228 @param output_cli A fully initialised cli structure, non-null only on success
3229 @param dest_host The netbios name of the remote host
3230 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3231 @param port (optional) The destination port (0 for default)
3232 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3233 @param service_type The 'type' of serivice.
3234 @param user Username, unix string
3235 @param domain User's domain
3236 @param password User's password, unencrypted unix string.
3239 struct cli_full_connection_state {
3240 struct tevent_context *ev;
3241 const char *service;
3242 const char *service_type;
3245 const char *password;
3248 struct cli_state *cli;
3251 static int cli_full_connection_state_destructor(
3252 struct cli_full_connection_state *s);
3253 static void cli_full_connection_started(struct tevent_req *subreq);
3254 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3255 static void cli_full_connection_done(struct tevent_req *subreq);
3257 struct tevent_req *cli_full_connection_send(
3258 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3259 const char *my_name, const char *dest_host,
3260 const struct sockaddr_storage *dest_ss, int port,
3261 const char *service, const char *service_type,
3262 const char *user, const char *domain,
3263 const char *password, int flags, int signing_state)
3265 struct tevent_req *req, *subreq;
3266 struct cli_full_connection_state *state;
3268 req = tevent_req_create(mem_ctx, &state,
3269 struct cli_full_connection_state);
3273 talloc_set_destructor(state, cli_full_connection_state_destructor);
3276 state->service = service;
3277 state->service_type = service_type;
3279 state->domain = domain;
3280 state->password = password;
3281 state->flags = flags;
3283 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3284 if (state->password == NULL) {
3285 state->password = "";
3288 subreq = cli_start_connection_send(
3289 state, ev, my_name, dest_host, dest_ss, port,
3290 signing_state, flags);
3291 if (tevent_req_nomem(subreq, req)) {
3292 return tevent_req_post(req, ev);
3294 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3298 static int cli_full_connection_state_destructor(
3299 struct cli_full_connection_state *s)
3301 if (s->cli != NULL) {
3302 cli_shutdown(s->cli);
3308 static void cli_full_connection_started(struct tevent_req *subreq)
3310 struct tevent_req *req = tevent_req_callback_data(
3311 subreq, struct tevent_req);
3312 struct cli_full_connection_state *state = tevent_req_data(
3313 req, struct cli_full_connection_state);
3316 status = cli_start_connection_recv(subreq, &state->cli);
3317 TALLOC_FREE(subreq);
3318 if (tevent_req_nterror(req, status)) {
3321 subreq = cli_session_setup_send(
3322 state, state->ev, state->cli, state->user,
3323 state->password, state->pw_len, state->password, state->pw_len,
3325 if (tevent_req_nomem(subreq, req)) {
3328 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3331 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3333 struct tevent_req *req = tevent_req_callback_data(
3334 subreq, struct tevent_req);
3335 struct cli_full_connection_state *state = tevent_req_data(
3336 req, struct cli_full_connection_state);
3339 status = cli_session_setup_recv(subreq);
3340 TALLOC_FREE(subreq);
3342 if (!NT_STATUS_IS_OK(status) &&
3343 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3345 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3347 subreq = cli_session_setup_send(
3348 state, state->ev, state->cli, "", "", 0, "", 0,
3350 if (tevent_req_nomem(subreq, req)) {
3353 tevent_req_set_callback(
3354 subreq, cli_full_connection_sess_set_up, req);
3358 if (tevent_req_nterror(req, status)) {
3362 if (state->service != NULL) {
3363 subreq = cli_tree_connect_send(
3364 state, state->ev, state->cli,
3365 state->service, state->service_type,
3366 state->password, state->pw_len);
3367 if (tevent_req_nomem(subreq, req)) {
3370 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3374 status = cli_init_creds(state->cli, state->user, state->domain,
3376 if (tevent_req_nterror(req, status)) {
3379 tevent_req_done(req);
3382 static void cli_full_connection_done(struct tevent_req *subreq)
3384 struct tevent_req *req = tevent_req_callback_data(
3385 subreq, struct tevent_req);
3386 struct cli_full_connection_state *state = tevent_req_data(
3387 req, struct cli_full_connection_state);
3390 status = cli_tree_connect_recv(subreq);
3391 TALLOC_FREE(subreq);
3392 if (tevent_req_nterror(req, status)) {
3395 status = cli_init_creds(state->cli, state->user, state->domain,
3397 if (tevent_req_nterror(req, status)) {
3400 tevent_req_done(req);
3403 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3404 struct cli_state **output_cli)
3406 struct cli_full_connection_state *state = tevent_req_data(
3407 req, struct cli_full_connection_state);
3410 if (tevent_req_is_nterror(req, &status)) {
3413 *output_cli = state->cli;
3414 talloc_set_destructor(state, NULL);
3415 return NT_STATUS_OK;
3418 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3419 const char *my_name,
3420 const char *dest_host,
3421 const struct sockaddr_storage *dest_ss, int port,
3422 const char *service, const char *service_type,
3423 const char *user, const char *domain,
3424 const char *password, int flags,
3427 struct tevent_context *ev;
3428 struct tevent_req *req;
3429 NTSTATUS status = NT_STATUS_NO_MEMORY;
3431 ev = samba_tevent_context_init(talloc_tos());
3435 req = cli_full_connection_send(
3436 ev, ev, my_name, dest_host, dest_ss, port, service,
3437 service_type, user, domain, password, flags, signing_state);
3441 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3444 status = cli_full_connection_recv(req, output_cli);
3450 /****************************************************************************
3451 Send an old style tcon.
3452 ****************************************************************************/
3453 struct cli_raw_tcon_state {
3457 static void cli_raw_tcon_done(struct tevent_req *subreq);
3459 static struct tevent_req *cli_raw_tcon_send(
3460 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3461 const char *service, const char *pass, const char *dev)
3463 struct tevent_req *req, *subreq;
3464 struct cli_raw_tcon_state *state;
3467 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3472 if (!lp_client_plaintext_auth() && (*pass)) {
3473 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3474 " or 'client ntlmv2 auth = yes'\n"));
3475 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3476 return tevent_req_post(req, ev);
3479 bytes = talloc_array(state, uint8_t, 0);
3480 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3481 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3482 service, strlen(service)+1, NULL);
3483 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3484 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3485 pass, strlen(pass)+1, NULL);
3486 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3487 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3488 dev, strlen(dev)+1, NULL);
3490 if (tevent_req_nomem(bytes, req)) {
3491 return tevent_req_post(req, ev);
3494 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3495 talloc_get_size(bytes), bytes);
3496 if (tevent_req_nomem(subreq, req)) {
3497 return tevent_req_post(req, ev);
3499 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3503 static void cli_raw_tcon_done(struct tevent_req *subreq)
3505 struct tevent_req *req = tevent_req_callback_data(
3506 subreq, struct tevent_req);
3507 struct cli_raw_tcon_state *state = tevent_req_data(
3508 req, struct cli_raw_tcon_state);
3511 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3513 TALLOC_FREE(subreq);
3514 if (tevent_req_nterror(req, status)) {
3517 tevent_req_done(req);
3520 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3521 uint16 *max_xmit, uint16 *tid)
3523 struct cli_raw_tcon_state *state = tevent_req_data(
3524 req, struct cli_raw_tcon_state);
3527 if (tevent_req_is_nterror(req, &status)) {
3530 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3531 *tid = SVAL(state->ret_vwv + 1, 0);
3532 return NT_STATUS_OK;
3535 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3536 const char *service, const char *pass, const char *dev,
3537 uint16 *max_xmit, uint16 *tid)
3539 struct tevent_context *ev;
3540 struct tevent_req *req;
3541 NTSTATUS status = NT_STATUS_NO_MEMORY;
3543 ev = samba_tevent_context_init(talloc_tos());
3547 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3551 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3554 status = cli_raw_tcon_recv(req, max_xmit, tid);
3560 /* Return a cli_state pointing at the IPC$ share for the given server */
3562 struct cli_state *get_ipc_connect(char *server,
3563 struct sockaddr_storage *server_ss,
3564 const struct user_auth_info *user_info)
3566 struct cli_state *cli;
3568 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3570 if (user_info->use_kerberos) {
3571 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3574 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3575 user_info->username ? user_info->username : "",
3577 user_info->password ? user_info->password : "",
3579 SMB_SIGNING_DEFAULT);
3581 if (NT_STATUS_IS_OK(nt_status)) {
3583 } else if (is_ipaddress(server)) {
3584 /* windows 9* needs a correct NMB name for connections */
3585 fstring remote_name;
3587 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3588 cli = get_ipc_connect(remote_name, server_ss, user_info);
3597 * Given the IP address of a master browser on the network, return its
3598 * workgroup and connect to it.
3600 * This function is provided to allow additional processing beyond what
3601 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3602 * browsers and obtain each master browsers' list of domains (in case the
3603 * first master browser is recently on the network and has not yet
3604 * synchronized with other master browsers and therefore does not yet have the
3605 * entire network browse list)
3608 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3609 struct sockaddr_storage *mb_ip,
3610 const struct user_auth_info *user_info,
3611 char **pp_workgroup_out)
3613 char addr[INET6_ADDRSTRLEN];
3615 struct cli_state *cli;
3616 struct sockaddr_storage server_ss;
3618 *pp_workgroup_out = NULL;
3620 print_sockaddr(addr, sizeof(addr), mb_ip);
3621 DEBUG(99, ("Looking up name of master browser %s\n",
3625 * Do a name status query to find out the name of the master browser.
3626 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3627 * master browser will not respond to a wildcard query (or, at least,
3628 * an NT4 server acting as the domain master browser will not).
3630 * We might be able to use ONLY the query on MSBROWSE, but that's not
3631 * yet been tested with all Windows versions, so until it is, leave
3632 * the original wildcard query as the first choice and fall back to
3633 * MSBROWSE if the wildcard query fails.
3635 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3636 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3638 DEBUG(99, ("Could not retrieve name status for %s\n",
3643 if (!find_master_ip(name, &server_ss)) {
3644 DEBUG(99, ("Could not find master ip for %s\n", name));
3648 *pp_workgroup_out = talloc_strdup(ctx, name);
3650 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3652 print_sockaddr(addr, sizeof(addr), &server_ss);
3653 cli = get_ipc_connect(addr, &server_ss, user_info);
3659 * Return the IP address and workgroup of a master browser on the network, and
3663 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3664 const struct user_auth_info *user_info,
3665 char **pp_workgroup_out)
3667 struct sockaddr_storage *ip_list;
3668 struct cli_state *cli;
3672 *pp_workgroup_out = NULL;
3674 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3676 /* Go looking for workgroups by broadcasting on the local network */
3678 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3680 if (!NT_STATUS_IS_OK(status)) {
3681 DEBUG(99, ("No master browsers responded: %s\n",
3682 nt_errstr(status)));
3686 for (i = 0; i < count; i++) {
3687 char addr[INET6_ADDRSTRLEN];
3688 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3689 DEBUG(99, ("Found master browser %s\n", addr));
3691 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3692 user_info, pp_workgroup_out);