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/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
41 #define STAR_SMBSERVER "*SMBSERVER"
43 /********************************************************
44 Utility function to ensure we always return at least
45 a valid char * pointer to an empty string for the
46 cli->server_os, cli->server_type and cli->server_domain
48 *******************************************************/
50 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
57 *destlen = clistr_pull_talloc(mem_ctx,
65 return NT_STATUS_NO_MEMORY;
69 *dest = talloc_strdup(mem_ctx, "");
71 return NT_STATUS_NO_MEMORY;
77 /****************************************************************************
78 Do an old lanman2 style session setup.
79 ****************************************************************************/
81 struct cli_session_setup_lanman2_state {
82 struct cli_state *cli;
87 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
89 static struct tevent_req *cli_session_setup_lanman2_send(
90 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
91 struct cli_state *cli, const char *user,
92 const char *pass, size_t passlen,
93 const char *workgroup)
95 struct tevent_req *req, *subreq;
96 struct cli_session_setup_lanman2_state *state;
97 DATA_BLOB lm_response = data_blob_null;
101 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
103 req = tevent_req_create(mem_ctx, &state,
104 struct cli_session_setup_lanman2_state);
113 * if in share level security then don't send a password now
115 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
120 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
123 * Encrypted mode needed, and non encrypted password
126 lm_response = data_blob(NULL, 24);
127 if (tevent_req_nomem(lm_response.data, req)) {
128 return tevent_req_post(req, ev);
131 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
132 (uint8_t *)lm_response.data)) {
133 DEBUG(1, ("Password is > 14 chars in length, and is "
134 "therefore incompatible with Lanman "
135 "authentication\n"));
136 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
137 return tevent_req_post(req, ev);
139 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
142 * Encrypted mode needed, and encrypted password
145 lm_response = data_blob(pass, passlen);
146 if (tevent_req_nomem(lm_response.data, req)) {
147 return tevent_req_post(req, ev);
149 } else if (passlen > 0) {
151 size_t converted_size;
153 * Plaintext mode needed, assume plaintext supplied.
155 buf = talloc_array(talloc_tos(), uint8_t, 0);
156 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
158 if (tevent_req_nomem(buf, req)) {
159 return tevent_req_post(req, ev);
161 lm_response = data_blob(pass, passlen);
163 if (tevent_req_nomem(lm_response.data, req)) {
164 return tevent_req_post(req, ev);
168 SCVAL(vwv+0, 0, 0xff);
171 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
174 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
175 SSVAL(vwv+7, 0, lm_response.length);
177 bytes = talloc_array(state, uint8_t, lm_response.length);
178 if (tevent_req_nomem(bytes, req)) {
179 return tevent_req_post(req, ev);
181 if (lm_response.length != 0) {
182 memcpy(bytes, lm_response.data, lm_response.length);
184 data_blob_free(&lm_response);
186 tmp = talloc_strdup_upper(talloc_tos(), user);
187 if (tevent_req_nomem(tmp, req)) {
188 return tevent_req_post(req, ev);
190 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
194 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
195 if (tevent_req_nomem(tmp, req)) {
196 return tevent_req_post(req, ev);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
200 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
201 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
203 if (tevent_req_nomem(bytes, req)) {
204 return tevent_req_post(req, ev);
207 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
208 talloc_get_size(bytes), bytes);
209 if (tevent_req_nomem(subreq, req)) {
210 return tevent_req_post(req, ev);
212 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
216 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
218 struct tevent_req *req = tevent_req_callback_data(
219 subreq, struct tevent_req);
220 struct cli_session_setup_lanman2_state *state = tevent_req_data(
221 req, struct cli_session_setup_lanman2_state);
222 struct cli_state *cli = state->cli;
233 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
236 if (!NT_STATUS_IS_OK(status)) {
237 tevent_req_nterror(req, status);
241 inhdr = in + NBT_HDR_SIZE;
244 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
245 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
247 status = smb_bytes_talloc_string(cli,
254 if (!NT_STATUS_IS_OK(status)) {
255 tevent_req_nterror(req, status);
260 status = smb_bytes_talloc_string(cli,
267 if (!NT_STATUS_IS_OK(status)) {
268 tevent_req_nterror(req, status);
273 status = smb_bytes_talloc_string(cli,
280 if (!NT_STATUS_IS_OK(status)) {
281 tevent_req_nterror(req, status);
286 status = cli_set_username(cli, state->user);
287 if (tevent_req_nterror(req, status)) {
290 tevent_req_done(req);
293 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
295 return tevent_req_simple_recv_ntstatus(req);
298 /****************************************************************************
299 Work out suitable capabilities to offer the server.
300 ****************************************************************************/
302 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
303 uint32_t sesssetup_capabilities)
305 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
308 * We only send capabilities based on the mask for:
309 * - client only flags
310 * - flags used in both directions
312 * We do not echo the server only flags, except some legacy flags.
314 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
315 * CAP_LARGE_WRITEX in order to allow us to do large reads
316 * against old Samba releases (<= 3.6.x).
318 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
321 * Session Setup specific flags CAP_DYNAMIC_REAUTH
322 * and CAP_EXTENDED_SECURITY are passed by the caller.
323 * We need that in order to do guest logins even if
324 * CAP_EXTENDED_SECURITY is negotiated.
326 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
327 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
328 client_capabilities |= sesssetup_capabilities;
330 return client_capabilities;
333 /****************************************************************************
334 Do a NT1 guest session setup.
335 ****************************************************************************/
337 struct cli_session_setup_guest_state {
338 struct cli_state *cli;
343 static void cli_session_setup_guest_done(struct tevent_req *subreq);
345 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
346 struct tevent_context *ev,
347 struct cli_state *cli,
348 struct tevent_req **psmbreq)
350 struct tevent_req *req, *subreq;
351 struct cli_session_setup_guest_state *state;
355 req = tevent_req_create(mem_ctx, &state,
356 struct cli_session_setup_guest_state);
363 SCVAL(vwv+0, 0, 0xFF);
366 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
368 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
369 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
374 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
376 bytes = talloc_array(state, uint8_t, 0);
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
380 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
382 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
383 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
390 state->bytes.iov_base = (void *)bytes;
391 state->bytes.iov_len = talloc_get_size(bytes);
393 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
395 if (subreq == NULL) {
399 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
404 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
405 struct tevent_context *ev,
406 struct cli_state *cli)
408 struct tevent_req *req, *subreq;
411 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
416 status = smb1cli_req_chain_submit(&subreq, 1);
417 if (!NT_STATUS_IS_OK(status)) {
418 tevent_req_nterror(req, status);
419 return tevent_req_post(req, ev);
424 static void cli_session_setup_guest_done(struct tevent_req *subreq)
426 struct tevent_req *req = tevent_req_callback_data(
427 subreq, struct tevent_req);
428 struct cli_session_setup_guest_state *state = tevent_req_data(
429 req, struct cli_session_setup_guest_state);
430 struct cli_state *cli = state->cli;
441 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
444 if (!NT_STATUS_IS_OK(status)) {
445 tevent_req_nterror(req, status);
449 inhdr = in + NBT_HDR_SIZE;
452 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
453 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
455 status = smb_bytes_talloc_string(cli,
462 if (!NT_STATUS_IS_OK(status)) {
463 tevent_req_nterror(req, status);
468 status = smb_bytes_talloc_string(cli,
475 if (!NT_STATUS_IS_OK(status)) {
476 tevent_req_nterror(req, status);
481 status = smb_bytes_talloc_string(cli,
488 if (!NT_STATUS_IS_OK(status)) {
489 tevent_req_nterror(req, status);
494 status = cli_set_username(cli, "");
495 if (!NT_STATUS_IS_OK(status)) {
496 tevent_req_nterror(req, status);
499 tevent_req_done(req);
502 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
504 return tevent_req_simple_recv_ntstatus(req);
507 /****************************************************************************
508 Do a NT1 plaintext session setup.
509 ****************************************************************************/
511 struct cli_session_setup_plain_state {
512 struct cli_state *cli;
517 static void cli_session_setup_plain_done(struct tevent_req *subreq);
519 static struct tevent_req *cli_session_setup_plain_send(
520 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
521 struct cli_state *cli,
522 const char *user, const char *pass, const char *workgroup)
524 struct tevent_req *req, *subreq;
525 struct cli_session_setup_plain_state *state;
531 req = tevent_req_create(mem_ctx, &state,
532 struct cli_session_setup_plain_state);
540 SCVAL(vwv+0, 0, 0xff);
543 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
545 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
546 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
551 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
553 bytes = talloc_array(state, uint8_t, 0);
554 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
556 if (tevent_req_nomem(bytes, req)) {
557 return tevent_req_post(req, ev);
559 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
561 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
562 user, strlen(user)+1, NULL);
563 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
564 workgroup, strlen(workgroup)+1, NULL);
565 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
568 version = talloc_asprintf(talloc_tos(), "Samba %s",
569 samba_version_string());
570 if (tevent_req_nomem(version, req)){
571 return tevent_req_post(req, ev);
573 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
574 version, strlen(version)+1, NULL);
575 TALLOC_FREE(version);
577 if (tevent_req_nomem(bytes, req)) {
578 return tevent_req_post(req, ev);
581 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
582 talloc_get_size(bytes), bytes);
583 if (tevent_req_nomem(subreq, req)) {
584 return tevent_req_post(req, ev);
586 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
590 static void cli_session_setup_plain_done(struct tevent_req *subreq)
592 struct tevent_req *req = tevent_req_callback_data(
593 subreq, struct tevent_req);
594 struct cli_session_setup_plain_state *state = tevent_req_data(
595 req, struct cli_session_setup_plain_state);
596 struct cli_state *cli = state->cli;
607 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
610 if (tevent_req_nterror(req, status)) {
614 inhdr = in + NBT_HDR_SIZE;
617 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
618 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
620 status = smb_bytes_talloc_string(cli,
627 if (!NT_STATUS_IS_OK(status)) {
628 tevent_req_nterror(req, status);
633 status = smb_bytes_talloc_string(cli,
640 if (!NT_STATUS_IS_OK(status)) {
641 tevent_req_nterror(req, status);
646 status = smb_bytes_talloc_string(cli,
653 if (!NT_STATUS_IS_OK(status)) {
654 tevent_req_nterror(req, status);
659 status = cli_set_username(cli, state->user);
660 if (tevent_req_nterror(req, status)) {
664 tevent_req_done(req);
667 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
669 return tevent_req_simple_recv_ntstatus(req);
672 /****************************************************************************
673 do a NT1 NTLM/LM encrypted session setup - for when extended security
675 @param cli client state to create do session setup on
677 @param pass *either* cleartext password (passlen !=24) or LM response.
678 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
679 @param workgroup The user's domain.
680 ****************************************************************************/
682 struct cli_session_setup_nt1_state {
683 struct cli_state *cli;
686 DATA_BLOB session_key;
690 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
692 static struct tevent_req *cli_session_setup_nt1_send(
693 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
694 struct cli_state *cli, const char *user,
695 const char *pass, size_t passlen,
696 const char *ntpass, size_t ntpasslen,
697 const char *workgroup)
699 struct tevent_req *req, *subreq;
700 struct cli_session_setup_nt1_state *state;
701 DATA_BLOB lm_response = data_blob_null;
702 DATA_BLOB nt_response = data_blob_null;
703 DATA_BLOB session_key = data_blob_null;
706 char *workgroup_upper;
708 req = tevent_req_create(mem_ctx, &state,
709 struct cli_session_setup_nt1_state);
718 /* do nothing - guest login */
719 } else if (passlen != 24) {
720 if (lp_client_ntlmv2_auth()) {
721 DATA_BLOB server_chal;
722 DATA_BLOB names_blob;
725 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
729 * note that the 'workgroup' here is a best
730 * guess - we don't know the server's domain
731 * at this point. Windows clients also don't
734 names_blob = NTLMv2_generate_names_blob(
735 NULL, NULL, workgroup);
737 if (tevent_req_nomem(names_blob.data, req)) {
738 return tevent_req_post(req, ev);
741 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
742 &server_chal, &names_blob,
743 &lm_response, &nt_response,
744 NULL, &session_key)) {
745 data_blob_free(&names_blob);
747 req, NT_STATUS_ACCESS_DENIED);
748 return tevent_req_post(req, ev);
750 data_blob_free(&names_blob);
754 E_md4hash(pass, nt_hash);
757 nt_response = data_blob_null;
759 nt_response = data_blob(NULL, 24);
760 if (tevent_req_nomem(nt_response.data, req)) {
761 return tevent_req_post(req, ev);
764 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
767 /* non encrypted password supplied. Ignore ntpass. */
768 if (lp_client_lanman_auth()) {
770 lm_response = data_blob(NULL, 24);
771 if (tevent_req_nomem(lm_response.data, req)) {
772 return tevent_req_post(req, ev);
775 if (!SMBencrypt(pass,
776 smb1cli_conn_server_challenge(cli->conn),
779 * Oops, the LM response is
780 * invalid, just put the NT
781 * response there instead
783 data_blob_free(&lm_response);
784 lm_response = data_blob(
790 * LM disabled, place NT# in LM field
793 lm_response = data_blob(
794 nt_response.data, nt_response.length);
797 if (tevent_req_nomem(lm_response.data, req)) {
798 return tevent_req_post(req, ev);
801 session_key = data_blob(NULL, 16);
802 if (tevent_req_nomem(session_key.data, req)) {
803 return tevent_req_post(req, ev);
806 E_deshash(pass, session_key.data);
807 memset(&session_key.data[8], '\0', 8);
809 SMBsesskeygen_ntv1(nt_hash, session_key.data);
813 /* pre-encrypted password supplied. Only used for
814 security=server, can't do
815 signing because we don't have original key */
817 lm_response = data_blob(pass, passlen);
818 if (tevent_req_nomem(lm_response.data, req)) {
819 return tevent_req_post(req, ev);
822 nt_response = data_blob(ntpass, ntpasslen);
823 if (tevent_req_nomem(nt_response.data, req)) {
824 return tevent_req_post(req, ev);
829 state->response = data_blob_talloc(
830 state, lm_response.data, lm_response.length);
832 state->response = data_blob_talloc(
833 state, nt_response.data, nt_response.length);
835 if (tevent_req_nomem(state->response.data, req)) {
836 return tevent_req_post(req, ev);
839 if (session_key.data) {
840 state->session_key = data_blob_talloc(
841 state, session_key.data, session_key.length);
842 if (tevent_req_nomem(state->session_key.data, req)) {
843 return tevent_req_post(req, ev);
846 data_blob_free(&session_key);
848 SCVAL(vwv+0, 0, 0xff);
851 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
853 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
854 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
855 SSVAL(vwv+7, 0, lm_response.length);
856 SSVAL(vwv+8, 0, nt_response.length);
859 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
861 bytes = talloc_array(state, uint8_t,
862 lm_response.length + nt_response.length);
863 if (tevent_req_nomem(bytes, req)) {
864 return tevent_req_post(req, ev);
866 if (lm_response.length != 0) {
867 memcpy(bytes, lm_response.data, lm_response.length);
869 if (nt_response.length != 0) {
870 memcpy(bytes + lm_response.length,
871 nt_response.data, nt_response.length);
873 data_blob_free(&lm_response);
874 data_blob_free(&nt_response);
876 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
877 user, strlen(user)+1, NULL);
880 * Upper case here might help some NTLMv2 implementations
882 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
883 if (tevent_req_nomem(workgroup_upper, req)) {
884 return tevent_req_post(req, ev);
886 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
887 workgroup_upper, strlen(workgroup_upper)+1,
889 TALLOC_FREE(workgroup_upper);
891 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
892 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
893 if (tevent_req_nomem(bytes, req)) {
894 return tevent_req_post(req, ev);
897 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
898 talloc_get_size(bytes), bytes);
899 if (tevent_req_nomem(subreq, req)) {
900 return tevent_req_post(req, ev);
902 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
906 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
908 struct tevent_req *req = tevent_req_callback_data(
909 subreq, struct tevent_req);
910 struct cli_session_setup_nt1_state *state = tevent_req_data(
911 req, struct cli_session_setup_nt1_state);
912 struct cli_state *cli = state->cli;
923 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
926 if (!NT_STATUS_IS_OK(status)) {
927 tevent_req_nterror(req, status);
931 inhdr = in + NBT_HDR_SIZE;
934 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
935 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
937 status = smb_bytes_talloc_string(cli,
943 if (!NT_STATUS_IS_OK(status)) {
944 tevent_req_nterror(req, status);
949 status = smb_bytes_talloc_string(cli,
955 if (!NT_STATUS_IS_OK(status)) {
956 tevent_req_nterror(req, status);
961 status = smb_bytes_talloc_string(cli,
967 if (!NT_STATUS_IS_OK(status)) {
968 tevent_req_nterror(req, status);
973 status = cli_set_username(cli, state->user);
974 if (tevent_req_nterror(req, status)) {
977 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
978 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
979 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
982 if (state->session_key.data) {
983 struct smbXcli_session *session = state->cli->smb1.session;
985 status = smb1cli_session_set_session_key(session,
987 if (tevent_req_nterror(req, status)) {
991 tevent_req_done(req);
994 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
996 return tevent_req_simple_recv_ntstatus(req);
999 /* The following is calculated from :
1001 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1002 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1006 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1008 struct cli_sesssetup_blob_state {
1009 struct tevent_context *ev;
1010 struct cli_state *cli;
1012 uint16_t max_blob_size;
1016 DATA_BLOB smb2_blob;
1017 struct iovec *recv_iov;
1024 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1025 struct tevent_req **psubreq);
1026 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1028 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1029 struct tevent_context *ev,
1030 struct cli_state *cli,
1033 struct tevent_req *req, *subreq;
1034 struct cli_sesssetup_blob_state *state;
1035 uint32_t usable_space;
1037 req = tevent_req_create(mem_ctx, &state,
1038 struct cli_sesssetup_blob_state);
1046 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1047 usable_space = UINT16_MAX;
1049 usable_space = cli_state_available_size(cli,
1050 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1053 if (usable_space == 0) {
1054 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1055 "(not possible to send %u bytes)\n",
1056 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1057 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1058 return tevent_req_post(req, ev);
1060 state->max_blob_size = MIN(usable_space, 0xFFFF);
1062 if (!cli_sesssetup_blob_next(state, &subreq)) {
1063 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1064 return tevent_req_post(req, ev);
1066 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1070 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1071 struct tevent_req **psubreq)
1073 struct tevent_req *subreq;
1076 thistime = MIN(state->blob.length, state->max_blob_size);
1078 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1080 state->smb2_blob.data = state->blob.data;
1081 state->smb2_blob.length = thistime;
1083 state->blob.data += thistime;
1084 state->blob.length -= thistime;
1086 subreq = smb2cli_session_setup_send(state, state->ev,
1088 state->cli->timeout,
1089 state->cli->smb2.session,
1091 SMB2_CAP_DFS, /* in_capabilities */
1093 0, /* in_previous_session_id */
1095 if (subreq == NULL) {
1102 SCVAL(state->vwv+0, 0, 0xFF);
1103 SCVAL(state->vwv+0, 1, 0);
1104 SSVAL(state->vwv+1, 0, 0);
1105 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1106 SSVAL(state->vwv+3, 0, 2);
1107 SSVAL(state->vwv+4, 0, 1);
1108 SIVAL(state->vwv+5, 0, 0);
1110 SSVAL(state->vwv+7, 0, thistime);
1112 SSVAL(state->vwv+8, 0, 0);
1113 SSVAL(state->vwv+9, 0, 0);
1114 SIVAL(state->vwv+10, 0,
1115 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1117 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1119 if (state->buf == NULL) {
1122 state->blob.data += thistime;
1123 state->blob.length -= thistime;
1125 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1127 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1129 if (state->buf == NULL) {
1132 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1134 talloc_get_size(state->buf), state->buf);
1135 if (subreq == NULL) {
1142 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1144 struct tevent_req *req = tevent_req_callback_data(
1145 subreq, struct tevent_req);
1146 struct cli_sesssetup_blob_state *state = tevent_req_data(
1147 req, struct cli_sesssetup_blob_state);
1148 struct cli_state *cli = state->cli;
1155 uint16_t blob_length;
1160 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1161 status = smb2cli_session_setup_recv(subreq, state,
1165 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1166 &num_bytes, &bytes);
1167 TALLOC_FREE(state->buf);
1169 TALLOC_FREE(subreq);
1170 if (!NT_STATUS_IS_OK(status)
1171 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1172 tevent_req_nterror(req, status);
1176 state->status = status;
1178 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1183 inhdr = in + NBT_HDR_SIZE;
1184 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1185 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
1187 blob_length = SVAL(vwv+3, 0);
1188 if (blob_length > num_bytes) {
1189 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1192 state->ret_blob = data_blob_const(bytes, blob_length);
1194 p = bytes + blob_length;
1196 status = smb_bytes_talloc_string(cli,
1203 if (!NT_STATUS_IS_OK(status)) {
1204 tevent_req_nterror(req, status);
1209 status = smb_bytes_talloc_string(cli,
1216 if (!NT_STATUS_IS_OK(status)) {
1217 tevent_req_nterror(req, status);
1222 status = smb_bytes_talloc_string(cli,
1224 &cli->server_domain,
1229 if (!NT_STATUS_IS_OK(status)) {
1230 tevent_req_nterror(req, status);
1236 if (state->blob.length != 0) {
1240 if (!cli_sesssetup_blob_next(state, &subreq)) {
1241 tevent_req_oom(req);
1244 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1247 tevent_req_done(req);
1250 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1251 TALLOC_CTX *mem_ctx,
1254 struct iovec **precv_iov)
1256 struct cli_sesssetup_blob_state *state = tevent_req_data(
1257 req, struct cli_sesssetup_blob_state);
1260 struct iovec *recv_iov;
1262 if (tevent_req_is_nterror(req, &status)) {
1263 TALLOC_FREE(state->cli->smb2.session);
1264 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1268 inbuf = talloc_move(mem_ctx, &state->inbuf);
1269 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1270 if (pblob != NULL) {
1271 *pblob = state->ret_blob;
1273 if (pinbuf != NULL) {
1276 if (precv_iov != NULL) {
1277 *precv_iov = recv_iov;
1279 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1280 return state->status;
1285 /****************************************************************************
1286 Use in-memory credentials cache
1287 ****************************************************************************/
1289 static void use_in_memory_ccache(void) {
1290 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1293 #endif /* HAVE_KRB5 */
1295 /****************************************************************************
1296 Do a spnego/NTLMSSP encrypted session setup.
1297 ****************************************************************************/
1299 struct cli_session_setup_gensec_state {
1300 struct tevent_context *ev;
1301 struct cli_state *cli;
1302 struct auth_generic_state *auth_generic;
1306 struct iovec *recv_iov;
1310 DATA_BLOB session_key;
1313 static int cli_session_setup_gensec_state_destructor(
1314 struct cli_session_setup_gensec_state *state)
1316 TALLOC_FREE(state->auth_generic);
1317 data_blob_clear_free(&state->session_key);
1321 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
1322 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
1323 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
1324 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
1325 static void cli_session_setup_gensec_ready(struct tevent_req *req);
1327 static struct tevent_req *cli_session_setup_gensec_send(
1328 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1329 const char *user, const char *pass, const char *domain,
1330 enum credentials_use_kerberos krb5_state,
1331 const char *target_service,
1332 const char *target_hostname,
1333 const char *target_principal)
1335 struct tevent_req *req;
1336 struct cli_session_setup_gensec_state *state;
1338 bool use_spnego_principal = lp_client_use_spnego_principal();
1340 req = tevent_req_create(mem_ctx, &state,
1341 struct cli_session_setup_gensec_state);
1348 talloc_set_destructor(
1349 state, cli_session_setup_gensec_state_destructor);
1351 if (user == NULL || strlen(user) == 0) {
1352 if (pass != NULL && strlen(pass) == 0) {
1354 * some callers pass "" as no password
1356 * gensec only handles NULL as no password.
1362 status = auth_generic_client_prepare(state, &state->auth_generic);
1363 if (tevent_req_nterror(req, status)) {
1364 return tevent_req_post(req, ev);
1367 gensec_want_feature(state->auth_generic->gensec_security,
1368 GENSEC_FEATURE_SESSION_KEY);
1369 if (cli->use_ccache) {
1370 gensec_want_feature(state->auth_generic->gensec_security,
1371 GENSEC_FEATURE_NTLM_CCACHE);
1372 if (pass != NULL && strlen(pass) == 0) {
1374 * some callers pass "" as no password
1376 * GENSEC_FEATURE_NTLM_CCACHE only handles
1377 * NULL as no password.
1383 status = auth_generic_set_username(state->auth_generic, user);
1384 if (tevent_req_nterror(req, status)) {
1385 return tevent_req_post(req, ev);
1388 status = auth_generic_set_domain(state->auth_generic, domain);
1389 if (tevent_req_nterror(req, status)) {
1390 return tevent_req_post(req, ev);
1393 if (cli->pw_nt_hash) {
1394 struct samr_Password nt_hash;
1399 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1400 return tevent_req_post(req, ev);
1403 converted = strhex_to_str((char *)nt_hash.hash,
1404 sizeof(nt_hash.hash),
1405 pass, strlen(pass));
1406 if (converted != sizeof(nt_hash.hash)) {
1407 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1408 return tevent_req_post(req, ev);
1411 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
1412 &nt_hash, CRED_SPECIFIED);
1414 tevent_req_oom(req);
1415 return tevent_req_post(req, ev);
1418 status = auth_generic_set_password(state->auth_generic, pass);
1419 if (tevent_req_nterror(req, status)) {
1420 return tevent_req_post(req, ev);
1424 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
1427 if (krb5_state == CRED_DONT_USE_KERBEROS) {
1428 use_spnego_principal = false;
1431 if (target_service != NULL) {
1432 status = gensec_set_target_service(
1433 state->auth_generic->gensec_security,
1435 if (tevent_req_nterror(req, status)) {
1436 return tevent_req_post(req, ev);
1440 if (target_hostname != NULL) {
1441 status = gensec_set_target_hostname(
1442 state->auth_generic->gensec_security,
1444 if (tevent_req_nterror(req, status)) {
1445 return tevent_req_post(req, ev);
1449 if (target_principal != NULL) {
1450 status = gensec_set_target_principal(
1451 state->auth_generic->gensec_security,
1453 if (tevent_req_nterror(req, status)) {
1454 return tevent_req_post(req, ev);
1456 use_spnego_principal = false;
1457 } else if (target_service != NULL && target_hostname != NULL) {
1458 use_spnego_principal = false;
1461 if (use_spnego_principal) {
1463 b = smbXcli_conn_server_gss_blob(cli->conn);
1465 state->blob_in = *b;
1469 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
1471 status = auth_generic_client_start(state->auth_generic,
1473 if (tevent_req_nterror(req, status)) {
1474 return tevent_req_post(req, ev);
1477 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1478 state->cli->smb2.session = smbXcli_session_create(cli,
1480 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1481 return tevent_req_post(req, ev);
1485 cli_session_setup_gensec_local_next(req);
1486 if (!tevent_req_is_in_progress(req)) {
1487 return tevent_req_post(req, ev);
1493 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
1495 struct cli_session_setup_gensec_state *state =
1496 tevent_req_data(req,
1497 struct cli_session_setup_gensec_state);
1498 struct tevent_req *subreq = NULL;
1500 if (state->local_ready) {
1501 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1505 subreq = gensec_update_send(state, state->ev,
1506 state->auth_generic->gensec_security,
1508 if (tevent_req_nomem(subreq, req)) {
1511 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1514 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1516 struct tevent_req *req =
1517 tevent_req_callback_data(subreq,
1519 struct cli_session_setup_gensec_state *state =
1520 tevent_req_data(req,
1521 struct cli_session_setup_gensec_state);
1524 status = gensec_update_recv(subreq, state, &state->blob_out);
1525 TALLOC_FREE(subreq);
1526 state->blob_in = data_blob_null;
1527 if (!NT_STATUS_IS_OK(status) &&
1528 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1530 tevent_req_nterror(req, status);
1534 if (NT_STATUS_IS_OK(status)) {
1535 state->local_ready = true;
1538 if (state->local_ready && state->remote_ready) {
1539 cli_session_setup_gensec_ready(req);
1543 cli_session_setup_gensec_remote_next(req);
1546 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1548 struct cli_session_setup_gensec_state *state =
1549 tevent_req_data(req,
1550 struct cli_session_setup_gensec_state);
1551 struct tevent_req *subreq = NULL;
1553 if (state->remote_ready) {
1554 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1558 subreq = cli_sesssetup_blob_send(state, state->ev,
1559 state->cli, state->blob_out);
1560 if (tevent_req_nomem(subreq, req)) {
1563 tevent_req_set_callback(subreq,
1564 cli_session_setup_gensec_remote_done,
1568 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1570 struct tevent_req *req =
1571 tevent_req_callback_data(subreq,
1573 struct cli_session_setup_gensec_state *state =
1574 tevent_req_data(req,
1575 struct cli_session_setup_gensec_state);
1578 TALLOC_FREE(state->inbuf);
1579 TALLOC_FREE(state->recv_iov);
1581 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1582 &state->inbuf, &state->recv_iov);
1583 TALLOC_FREE(subreq);
1584 data_blob_free(&state->blob_out);
1585 if (!NT_STATUS_IS_OK(status) &&
1586 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1588 tevent_req_nterror(req, status);
1592 if (NT_STATUS_IS_OK(status)) {
1593 state->remote_ready = true;
1596 if (state->local_ready && state->remote_ready) {
1597 cli_session_setup_gensec_ready(req);
1601 cli_session_setup_gensec_local_next(req);
1604 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1606 struct cli_session_setup_gensec_state *state =
1607 tevent_req_data(req,
1608 struct cli_session_setup_gensec_state);
1609 const char *server_domain = NULL;
1612 if (state->blob_in.length != 0) {
1613 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1617 if (state->blob_out.length != 0) {
1618 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1623 * gensec_ntlmssp_server_domain() returns NULL
1624 * if NTLMSSP is not used.
1626 * We can remove this later
1627 * and leave the server domain empty for SMB2 and above
1628 * in future releases.
1630 server_domain = gensec_ntlmssp_server_domain(
1631 state->auth_generic->gensec_security);
1633 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1634 TALLOC_FREE(state->cli->server_domain);
1635 state->cli->server_domain = talloc_strdup(state->cli,
1637 if (state->cli->server_domain == NULL) {
1638 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1643 status = gensec_session_key(state->auth_generic->gensec_security,
1644 state, &state->session_key);
1645 if (tevent_req_nterror(req, status)) {
1649 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1650 struct smbXcli_session *session = state->cli->smb2.session;
1652 if (state->is_anonymous) {
1654 * Windows server does not set the
1655 * SMB2_SESSION_FLAG_IS_GUEST nor
1656 * SMB2_SESSION_FLAG_IS_NULL flag.
1658 * This fix makes sure we do not try
1659 * to verify a signature on the final
1660 * session setup response.
1662 tevent_req_done(req);
1666 status = smb2cli_session_set_session_key(session,
1669 if (tevent_req_nterror(req, status)) {
1673 struct smbXcli_session *session = state->cli->smb1.session;
1676 status = smb1cli_session_set_session_key(session,
1677 state->session_key);
1678 if (tevent_req_nterror(req, status)) {
1682 active = smb1cli_conn_activate_signing(state->cli->conn,
1688 ok = smb1cli_conn_check_signing(state->cli->conn,
1691 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1697 tevent_req_done(req);
1700 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1702 struct cli_session_setup_gensec_state *state =
1703 tevent_req_data(req,
1704 struct cli_session_setup_gensec_state);
1707 if (tevent_req_is_nterror(req, &status)) {
1708 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1711 return NT_STATUS_OK;
1716 static char *cli_session_setup_get_principal(
1717 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1718 const char *remote_name, const char *dest_realm)
1720 char *principal = NULL;
1722 if (!lp_client_use_spnego_principal() ||
1723 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1724 spnego_principal = NULL;
1726 if (spnego_principal != NULL) {
1727 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1728 "principal %s\n", spnego_principal));
1729 return talloc_strdup(mem_ctx, spnego_principal);
1731 if (is_ipaddress(remote_name) ||
1732 strequal(remote_name, STAR_SMBSERVER)) {
1736 DEBUG(3, ("cli_session_setup_spnego: using target "
1737 "hostname not SPNEGO principal\n"));
1740 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1741 if (realm == NULL) {
1744 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1745 remote_name, realm);
1748 principal = kerberos_get_principal_from_service_hostname(
1749 talloc_tos(), "cifs", remote_name, lp_realm());
1751 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1752 principal ? principal : "<null>"));
1758 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1759 const char *principal)
1763 account = talloc_strdup(mem_ctx, principal);
1764 if (account == NULL) {
1767 p = strchr_m(account, '@');
1774 /****************************************************************************
1775 Do a spnego encrypted session setup.
1777 user_domain: The shortname of the domain the user/machine is a member of.
1778 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1779 ****************************************************************************/
1781 struct cli_session_setup_spnego_state {
1782 struct tevent_context *ev;
1783 struct cli_state *cli;
1784 const char *target_hostname;
1786 const char *account;
1788 const char *user_domain;
1789 const char *dest_realm;
1794 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1797 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1799 static struct tevent_req *cli_session_setup_spnego_send(
1800 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1801 const char *user, const char *pass, const char *user_domain)
1803 struct tevent_req *req, *subreq;
1804 struct cli_session_setup_spnego_state *state;
1805 char *principal = NULL;
1806 char *OIDs[ASN1_MAX_OIDS];
1808 const char *dest_realm = cli_state_remote_realm(cli);
1809 const DATA_BLOB *server_blob;
1812 req = tevent_req_create(mem_ctx, &state,
1813 struct cli_session_setup_spnego_state);
1821 state->user_domain = user_domain;
1822 state->dest_realm = dest_realm;
1824 state->account = cli_session_setup_get_account(state, user);
1825 if (tevent_req_nomem(state->account, req)) {
1826 return tevent_req_post(req, ev);
1829 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1830 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1832 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1833 (unsigned long)server_blob->length));
1835 /* the server might not even do spnego */
1836 if (server_blob->length == 0) {
1837 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1842 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1845 /* The server sent us the first part of the SPNEGO exchange in the
1846 * negprot reply. It is WRONG to depend on the principal sent in the
1847 * negprot reply, but right now we do it. If we don't receive one,
1848 * we try to best guess, then fall back to NTLM. */
1849 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1850 &principal, NULL) ||
1852 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1853 tevent_req_done(req);
1854 return tevent_req_post(req, ev);
1857 /* make sure the server understands kerberos */
1858 for (i=0;OIDs[i];i++) {
1860 DEBUG(3,("got OID=%s\n", OIDs[i]));
1862 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1863 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1864 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1865 cli->got_kerberos_mechanism = True;
1867 talloc_free(OIDs[i]);
1870 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1872 status = cli_set_username(cli, user);
1873 if (!NT_STATUS_IS_OK(status)) {
1874 state->result = ADS_ERROR_NT(status);
1875 tevent_req_done(req);
1876 return tevent_req_post(req, ev);
1880 /* If password is set we reauthenticate to kerberos server
1881 * and do not store results */
1883 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1886 tmp = cli_session_setup_get_principal(
1887 talloc_tos(), principal, state->target_hostname, dest_realm);
1888 TALLOC_FREE(principal);
1891 if (pass && *pass) {
1894 use_in_memory_ccache();
1895 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1898 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1899 TALLOC_FREE(principal);
1900 if (cli->fallback_after_kerberos)
1902 state->result = ADS_ERROR_KRB5(ret);
1903 tevent_req_done(req);
1904 return tevent_req_post(req, ev);
1909 subreq = cli_session_setup_gensec_send(
1911 state->account, pass, user_domain,
1912 CRED_MUST_USE_KERBEROS,
1913 "cifs", state->target_hostname, principal);
1914 if (tevent_req_nomem(subreq, req)) {
1915 return tevent_req_post(req, ev);
1917 tevent_req_set_callback(
1918 subreq, cli_session_setup_spnego_done_krb,
1926 subreq = cli_session_setup_gensec_send(
1927 state, state->ev, state->cli,
1928 state->account, state->pass, state->user_domain,
1929 CRED_DONT_USE_KERBEROS,
1930 "cifs", state->target_hostname, NULL);
1931 if (tevent_req_nomem(subreq, req)) {
1932 return tevent_req_post(req, ev);
1934 tevent_req_set_callback(
1935 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1940 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1942 struct tevent_req *req = tevent_req_callback_data(
1943 subreq, struct tevent_req);
1944 struct cli_session_setup_spnego_state *state = tevent_req_data(
1945 req, struct cli_session_setup_spnego_state);
1948 status = cli_session_setup_gensec_recv(subreq);
1949 TALLOC_FREE(subreq);
1950 state->result = ADS_ERROR_NT(status);
1952 if (ADS_ERR_OK(state->result) ||
1953 !state->cli->fallback_after_kerberos) {
1954 tevent_req_done(req);
1958 subreq = cli_session_setup_gensec_send(
1959 state, state->ev, state->cli,
1960 state->account, state->pass, state->user_domain,
1961 CRED_DONT_USE_KERBEROS,
1962 "cifs", state->target_hostname, NULL);
1963 if (tevent_req_nomem(subreq, req)) {
1966 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1971 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1973 struct tevent_req *req = tevent_req_callback_data(
1974 subreq, struct tevent_req);
1975 struct cli_session_setup_spnego_state *state = tevent_req_data(
1976 req, struct cli_session_setup_spnego_state);
1979 status = cli_session_setup_gensec_recv(subreq);
1980 TALLOC_FREE(subreq);
1981 state->result = ADS_ERROR_NT(status);
1982 tevent_req_done(req);
1985 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1987 struct cli_session_setup_spnego_state *state = tevent_req_data(
1988 req, struct cli_session_setup_spnego_state);
1990 return state->result;
1993 struct cli_session_setup_state {
1997 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1998 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1999 static void cli_session_setup_done_guest(struct tevent_req *subreq);
2000 static void cli_session_setup_done_plain(struct tevent_req *subreq);
2001 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
2003 /****************************************************************************
2004 Send a session setup. The username and workgroup is in UNIX character
2005 format and must be converted to DOS codepage format before sending. If the
2006 password is in plaintext, the same should be done.
2007 ****************************************************************************/
2009 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
2010 struct tevent_context *ev,
2011 struct cli_state *cli,
2013 const char *pass, int passlen,
2014 const char *ntpass, int ntpasslen,
2015 const char *workgroup)
2017 struct tevent_req *req, *subreq;
2018 struct cli_session_setup_state *state;
2021 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2023 req = tevent_req_create(mem_ctx, &state,
2024 struct cli_session_setup_state);
2030 user2 = talloc_strdup(state, user);
2032 user2 = talloc_strdup(state, "");
2034 if (user2 == NULL) {
2035 tevent_req_oom(req);
2036 return tevent_req_post(req, ev);
2043 /* allow for workgroups as part of the username */
2044 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2045 (p=strchr_m(user2,*lp_winbind_separator()))) {
2048 if (!strupper_m(user2)) {
2049 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2050 return tevent_req_post(req, ev);
2055 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2056 tevent_req_done(req);
2057 return tevent_req_post(req, ev);
2060 /* now work out what sort of session setup we are going to
2061 do. I have split this into separate functions to make the
2062 flow a bit easier to understand (tridge) */
2064 /* if its an older server then we have to use the older request format */
2066 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2067 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2068 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2069 " or 'client ntlmv2 auth = yes'\n"));
2070 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2071 return tevent_req_post(req, ev);
2074 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2075 !lp_client_plaintext_auth() && (*pass)) {
2076 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2077 " or 'client ntlmv2 auth = yes'\n"));
2078 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2079 return tevent_req_post(req, ev);
2082 subreq = cli_session_setup_lanman2_send(
2083 state, ev, cli, user, pass, passlen, workgroup);
2084 if (tevent_req_nomem(subreq, req)) {
2085 return tevent_req_post(req, ev);
2087 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2092 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2093 subreq = cli_session_setup_spnego_send(
2094 state, ev, cli, user, pass, workgroup);
2095 if (tevent_req_nomem(subreq, req)) {
2096 return tevent_req_post(req, ev);
2098 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2103 /* if no user is supplied then we have to do an anonymous connection.
2104 passwords are ignored */
2106 if (!user || !*user) {
2107 subreq = cli_session_setup_guest_send(state, ev, cli);
2108 if (tevent_req_nomem(subreq, req)) {
2109 return tevent_req_post(req, ev);
2111 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2116 /* if the server is share level then send a plaintext null
2117 password at this point. The password is sent in the tree
2120 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2121 subreq = cli_session_setup_plain_send(
2122 state, ev, cli, user, "", workgroup);
2123 if (tevent_req_nomem(subreq, req)) {
2124 return tevent_req_post(req, ev);
2126 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2131 /* if the server doesn't support encryption then we have to use
2132 plaintext. The second password is ignored */
2134 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2135 if (!lp_client_plaintext_auth() && (*pass)) {
2136 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2137 " or 'client ntlmv2 auth = yes'\n"));
2138 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2139 return tevent_req_post(req, ev);
2141 subreq = cli_session_setup_plain_send(
2142 state, ev, cli, user, pass, workgroup);
2143 if (tevent_req_nomem(subreq, req)) {
2144 return tevent_req_post(req, ev);
2146 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2151 /* if the server supports extended security then use SPNEGO */
2153 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2154 subreq = cli_session_setup_spnego_send(
2155 state, ev, cli, user, pass, workgroup);
2156 if (tevent_req_nomem(subreq, req)) {
2157 return tevent_req_post(req, ev);
2159 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2163 /* otherwise do a NT1 style session setup */
2164 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2166 * Don't send an NTLMv2 response without NTLMSSP
2167 * if we want to use spnego support
2169 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2170 " but 'client use spnego = yes"
2171 " and 'client ntlmv2 auth = yes'\n"));
2172 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2173 return tevent_req_post(req, ev);
2176 subreq = cli_session_setup_nt1_send(
2177 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2179 if (tevent_req_nomem(subreq, req)) {
2180 return tevent_req_post(req, ev);
2182 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2187 tevent_req_done(req);
2188 return tevent_req_post(req, ev);
2191 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2193 struct tevent_req *req = tevent_req_callback_data(
2194 subreq, struct tevent_req);
2197 status = cli_session_setup_lanman2_recv(subreq);
2198 TALLOC_FREE(subreq);
2199 if (!NT_STATUS_IS_OK(status)) {
2200 tevent_req_nterror(req, status);
2203 tevent_req_done(req);
2206 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2208 struct tevent_req *req = tevent_req_callback_data(
2209 subreq, struct tevent_req);
2212 status = cli_session_setup_spnego_recv(subreq);
2213 TALLOC_FREE(subreq);
2214 if (!ADS_ERR_OK(status)) {
2215 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2216 tevent_req_nterror(req, ads_ntstatus(status));
2219 tevent_req_done(req);
2222 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2224 struct tevent_req *req = tevent_req_callback_data(
2225 subreq, struct tevent_req);
2228 status = cli_session_setup_guest_recv(subreq);
2229 TALLOC_FREE(subreq);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 tevent_req_nterror(req, status);
2234 tevent_req_done(req);
2237 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2239 struct tevent_req *req = tevent_req_callback_data(
2240 subreq, struct tevent_req);
2243 status = cli_session_setup_plain_recv(subreq);
2244 TALLOC_FREE(subreq);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 tevent_req_nterror(req, status);
2249 tevent_req_done(req);
2252 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2254 struct tevent_req *req = tevent_req_callback_data(
2255 subreq, struct tevent_req);
2258 status = cli_session_setup_nt1_recv(subreq);
2259 TALLOC_FREE(subreq);
2260 if (!NT_STATUS_IS_OK(status)) {
2261 DEBUG(3, ("cli_session_setup: NT1 session setup "
2262 "failed: %s\n", nt_errstr(status)));
2263 tevent_req_nterror(req, status);
2266 tevent_req_done(req);
2269 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2271 return tevent_req_simple_recv_ntstatus(req);
2274 NTSTATUS cli_session_setup(struct cli_state *cli,
2276 const char *pass, int passlen,
2277 const char *ntpass, int ntpasslen,
2278 const char *workgroup)
2280 struct tevent_context *ev;
2281 struct tevent_req *req;
2282 NTSTATUS status = NT_STATUS_NO_MEMORY;
2284 if (smbXcli_conn_has_async_calls(cli->conn)) {
2285 return NT_STATUS_INVALID_PARAMETER;
2287 ev = samba_tevent_context_init(talloc_tos());
2291 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2292 ntpass, ntpasslen, workgroup);
2296 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2299 status = cli_session_setup_recv(req);
2305 /****************************************************************************
2307 *****************************************************************************/
2309 struct cli_ulogoff_state {
2310 struct cli_state *cli;
2314 static void cli_ulogoff_done(struct tevent_req *subreq);
2316 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2317 struct tevent_context *ev,
2318 struct cli_state *cli)
2320 struct tevent_req *req, *subreq;
2321 struct cli_ulogoff_state *state;
2323 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2329 SCVAL(state->vwv+0, 0, 0xFF);
2330 SCVAL(state->vwv+1, 0, 0);
2331 SSVAL(state->vwv+2, 0, 0);
2333 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2335 if (tevent_req_nomem(subreq, req)) {
2336 return tevent_req_post(req, ev);
2338 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2342 static void cli_ulogoff_done(struct tevent_req *subreq)
2344 struct tevent_req *req = tevent_req_callback_data(
2345 subreq, struct tevent_req);
2346 struct cli_ulogoff_state *state = tevent_req_data(
2347 req, struct cli_ulogoff_state);
2350 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2351 if (!NT_STATUS_IS_OK(status)) {
2352 tevent_req_nterror(req, status);
2355 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2356 tevent_req_done(req);
2359 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2361 return tevent_req_simple_recv_ntstatus(req);
2364 NTSTATUS cli_ulogoff(struct cli_state *cli)
2366 struct tevent_context *ev;
2367 struct tevent_req *req;
2368 NTSTATUS status = NT_STATUS_NO_MEMORY;
2370 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2371 status = smb2cli_logoff(cli->conn,
2374 if (!NT_STATUS_IS_OK(status)) {
2377 smb2cli_session_set_id_and_flags(cli->smb2.session,
2379 return NT_STATUS_OK;
2382 if (smbXcli_conn_has_async_calls(cli->conn)) {
2383 return NT_STATUS_INVALID_PARAMETER;
2385 ev = samba_tevent_context_init(talloc_tos());
2389 req = cli_ulogoff_send(ev, ev, cli);
2393 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2396 status = cli_ulogoff_recv(req);
2402 /****************************************************************************
2404 ****************************************************************************/
2406 struct cli_tcon_andx_state {
2407 struct cli_state *cli;
2412 static void cli_tcon_andx_done(struct tevent_req *subreq);
2414 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2415 struct tevent_context *ev,
2416 struct cli_state *cli,
2417 const char *share, const char *dev,
2418 const char *pass, int passlen,
2419 struct tevent_req **psmbreq)
2421 struct tevent_req *req, *subreq;
2422 struct cli_tcon_andx_state *state;
2427 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2428 uint16_t tcon_flags = 0;
2432 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2439 cli->share = talloc_strdup(cli, share);
2444 /* in user level security don't send a password now */
2445 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2448 } else if (pass == NULL) {
2449 DEBUG(1, ("Server not using user level security and no "
2450 "password supplied.\n"));
2454 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2455 *pass && passlen != 24) {
2456 if (!lp_client_lanman_auth()) {
2457 DEBUG(1, ("Server requested LANMAN password "
2458 "(share-level security) but "
2459 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2464 * Non-encrypted passwords - convert to DOS codepage before
2467 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2469 pass = (const char *)p24;
2471 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2472 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2476 if (!lp_client_plaintext_auth() && (*pass)) {
2477 DEBUG(1, ("Server requested PLAINTEXT "
2479 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2484 * Non-encrypted passwords - convert to DOS codepage
2487 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2488 if (tevent_req_nomem(tmp_pass, req)) {
2489 return tevent_req_post(req, ev);
2491 tmp_pass = trans2_bytes_push_str(tmp_pass,
2492 false, /* always DOS */
2496 if (tevent_req_nomem(tmp_pass, req)) {
2497 return tevent_req_post(req, ev);
2499 pass = (const char *)tmp_pass;
2500 passlen = talloc_get_size(tmp_pass);
2504 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2505 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2507 SCVAL(vwv+0, 0, 0xFF);
2510 SSVAL(vwv+2, 0, tcon_flags);
2511 SSVAL(vwv+3, 0, passlen);
2513 if (passlen && pass) {
2514 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2516 bytes = talloc_array(state, uint8_t, 0);
2522 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2523 smbXcli_conn_remote_name(cli->conn), share);
2528 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2533 * Add the devicetype
2535 tmp = talloc_strdup_upper(talloc_tos(), dev);
2540 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2543 if (bytes == NULL) {
2548 state->bytes.iov_base = (void *)bytes;
2549 state->bytes.iov_len = talloc_get_size(bytes);
2551 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2553 if (subreq == NULL) {
2557 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2562 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2563 return tevent_req_post(req, ev);
2566 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2567 struct tevent_context *ev,
2568 struct cli_state *cli,
2569 const char *share, const char *dev,
2570 const char *pass, int passlen)
2572 struct tevent_req *req, *subreq;
2575 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2580 if (subreq == NULL) {
2583 status = smb1cli_req_chain_submit(&subreq, 1);
2584 if (!NT_STATUS_IS_OK(status)) {
2585 tevent_req_nterror(req, status);
2586 return tevent_req_post(req, ev);
2591 static void cli_tcon_andx_done(struct tevent_req *subreq)
2593 struct tevent_req *req = tevent_req_callback_data(
2594 subreq, struct tevent_req);
2595 struct cli_tcon_andx_state *state = tevent_req_data(
2596 req, struct cli_tcon_andx_state);
2597 struct cli_state *cli = state->cli;
2605 uint16_t optional_support = 0;
2607 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2608 &num_bytes, &bytes);
2609 TALLOC_FREE(subreq);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 tevent_req_nterror(req, status);
2615 inhdr = in + NBT_HDR_SIZE;
2618 if (clistr_pull_talloc(cli,
2619 (const char *)inhdr,
2620 SVAL(inhdr, HDR_FLG2),
2624 STR_TERMINATE|STR_ASCII) == -1) {
2625 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2629 cli->dev = talloc_strdup(cli, "");
2630 if (cli->dev == NULL) {
2631 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2636 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2637 /* almost certainly win95 - enable bug fixes */
2642 * Make sure that we have the optional support 16-bit field. WCT > 2.
2643 * Avoids issues when connecting to Win9x boxes sharing files
2646 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2647 optional_support = SVAL(vwv+2, 0);
2650 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2651 smb1cli_session_protect_session_key(cli->smb1.session);
2654 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2655 SVAL(inhdr, HDR_TID),
2657 0, /* maximal_access */
2658 0, /* guest_maximal_access */
2660 NULL); /* fs_type */
2662 tevent_req_done(req);
2665 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2667 return tevent_req_simple_recv_ntstatus(req);
2670 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2671 const char *dev, const char *pass, int passlen)
2673 TALLOC_CTX *frame = talloc_stackframe();
2674 struct tevent_context *ev;
2675 struct tevent_req *req;
2676 NTSTATUS status = NT_STATUS_NO_MEMORY;
2678 if (smbXcli_conn_has_async_calls(cli->conn)) {
2680 * Can't use sync call while an async call is in flight
2682 status = NT_STATUS_INVALID_PARAMETER;
2686 ev = samba_tevent_context_init(frame);
2691 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2696 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2700 status = cli_tcon_andx_recv(req);
2706 struct cli_tree_connect_state {
2707 struct cli_state *cli;
2710 static struct tevent_req *cli_raw_tcon_send(
2711 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2712 const char *service, const char *pass, const char *dev);
2713 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2714 uint16_t *max_xmit, uint16_t *tid);
2716 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2717 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2718 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2720 static struct tevent_req *cli_tree_connect_send(
2721 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2722 const char *share, const char *dev, const char *pass, int passlen)
2724 struct tevent_req *req, *subreq;
2725 struct cli_tree_connect_state *state;
2727 req = tevent_req_create(mem_ctx, &state,
2728 struct cli_tree_connect_state);
2734 cli->share = talloc_strdup(cli, share);
2735 if (tevent_req_nomem(cli->share, req)) {
2736 return tevent_req_post(req, ev);
2739 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2742 cli->smb2.tcon = smbXcli_tcon_create(cli);
2743 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2744 return tevent_req_post(req, ev);
2747 unc = talloc_asprintf(state, "\\\\%s\\%s",
2748 smbXcli_conn_remote_name(cli->conn),
2750 if (tevent_req_nomem(unc, req)) {
2751 return tevent_req_post(req, ev);
2754 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2755 cli->smb2.session, cli->smb2.tcon,
2758 if (tevent_req_nomem(subreq, req)) {
2759 return tevent_req_post(req, ev);
2761 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2766 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2767 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2769 if (tevent_req_nomem(subreq, req)) {
2770 return tevent_req_post(req, ev);
2772 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2777 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2778 if (tevent_req_nomem(subreq, req)) {
2779 return tevent_req_post(req, ev);
2781 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2786 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2788 tevent_req_simple_finish_ntstatus(
2789 subreq, smb2cli_tcon_recv(subreq));
2792 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2794 tevent_req_simple_finish_ntstatus(
2795 subreq, cli_tcon_andx_recv(subreq));
2798 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2800 struct tevent_req *req = tevent_req_callback_data(
2801 subreq, struct tevent_req);
2802 struct cli_tree_connect_state *state = tevent_req_data(
2803 req, struct cli_tree_connect_state);
2805 uint16_t max_xmit = 0;
2808 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2809 if (tevent_req_nterror(req, status)) {
2813 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2815 0, /* optional_support */
2816 0, /* maximal_access */
2817 0, /* guest_maximal_access */
2819 NULL); /* fs_type */
2821 tevent_req_done(req);
2824 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2826 return tevent_req_simple_recv_ntstatus(req);
2829 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2830 const char *dev, const char *pass, int passlen)
2832 struct tevent_context *ev;
2833 struct tevent_req *req;
2834 NTSTATUS status = NT_STATUS_NO_MEMORY;
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_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2847 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2850 status = cli_tree_connect_recv(req);
2856 /****************************************************************************
2857 Send a tree disconnect.
2858 ****************************************************************************/
2860 struct cli_tdis_state {
2861 struct cli_state *cli;
2864 static void cli_tdis_done(struct tevent_req *subreq);
2866 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2867 struct tevent_context *ev,
2868 struct cli_state *cli)
2870 struct tevent_req *req, *subreq;
2871 struct cli_tdis_state *state;
2873 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2879 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2880 if (tevent_req_nomem(subreq, req)) {
2881 return tevent_req_post(req, ev);
2883 tevent_req_set_callback(subreq, cli_tdis_done, req);
2887 static void cli_tdis_done(struct tevent_req *subreq)
2889 struct tevent_req *req = tevent_req_callback_data(
2890 subreq, struct tevent_req);
2891 struct cli_tdis_state *state = tevent_req_data(
2892 req, struct cli_tdis_state);
2895 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2896 TALLOC_FREE(subreq);
2897 if (!NT_STATUS_IS_OK(status)) {
2898 tevent_req_nterror(req, status);
2901 cli_state_set_tid(state->cli, UINT16_MAX);
2902 tevent_req_done(req);
2905 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2907 return tevent_req_simple_recv_ntstatus(req);
2910 NTSTATUS cli_tdis(struct cli_state *cli)
2912 struct tevent_context *ev;
2913 struct tevent_req *req;
2914 NTSTATUS status = NT_STATUS_NO_MEMORY;
2916 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2917 return smb2cli_tdis(cli->conn,
2923 if (smbXcli_conn_has_async_calls(cli->conn)) {
2924 return NT_STATUS_INVALID_PARAMETER;
2926 ev = samba_tevent_context_init(talloc_tos());
2930 req = cli_tdis_send(ev, ev, cli);
2934 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2937 status = cli_tdis_recv(req);
2943 struct cli_connect_sock_state {
2944 const char **called_names;
2945 const char **calling_names;
2951 static void cli_connect_sock_done(struct tevent_req *subreq);
2954 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2958 static struct tevent_req *cli_connect_sock_send(
2959 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2960 const char *host, int name_type, const struct sockaddr_storage *pss,
2961 const char *myname, uint16_t port)
2963 struct tevent_req *req, *subreq;
2964 struct cli_connect_sock_state *state;
2966 struct sockaddr_storage *addrs;
2967 unsigned i, num_addrs;
2970 req = tevent_req_create(mem_ctx, &state,
2971 struct cli_connect_sock_state);
2976 prog = getenv("LIBSMB_PROG");
2978 state->fd = sock_exec(prog);
2979 if (state->fd == -1) {
2980 status = map_nt_error_from_unix(errno);
2981 tevent_req_nterror(req, status);
2984 tevent_req_done(req);
2986 return tevent_req_post(req, ev);
2989 if ((pss == NULL) || is_zero_addr(pss)) {
2992 * Here we cheat. resolve_name_list is not async at all. So
2993 * this call will only be really async if the name lookup has
2994 * been done externally.
2997 status = resolve_name_list(state, host, name_type,
2998 &addrs, &num_addrs);
2999 if (!NT_STATUS_IS_OK(status)) {
3000 tevent_req_nterror(req, status);
3001 return tevent_req_post(req, ev);
3004 addrs = talloc_array(state, struct sockaddr_storage, 1);
3005 if (tevent_req_nomem(addrs, req)) {
3006 return tevent_req_post(req, ev);
3012 state->called_names = talloc_array(state, const char *, num_addrs);
3013 if (tevent_req_nomem(state->called_names, req)) {
3014 return tevent_req_post(req, ev);
3016 state->called_types = talloc_array(state, int, num_addrs);
3017 if (tevent_req_nomem(state->called_types, req)) {
3018 return tevent_req_post(req, ev);
3020 state->calling_names = talloc_array(state, const char *, num_addrs);
3021 if (tevent_req_nomem(state->calling_names, req)) {
3022 return tevent_req_post(req, ev);
3024 for (i=0; i<num_addrs; i++) {
3025 state->called_names[i] = host;
3026 state->called_types[i] = name_type;
3027 state->calling_names[i] = myname;
3030 subreq = smbsock_any_connect_send(
3031 state, ev, addrs, state->called_names, state->called_types,
3032 state->calling_names, NULL, num_addrs, port);
3033 if (tevent_req_nomem(subreq, req)) {
3034 return tevent_req_post(req, ev);
3036 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3040 static void cli_connect_sock_done(struct tevent_req *subreq)
3042 struct tevent_req *req = tevent_req_callback_data(
3043 subreq, struct tevent_req);
3044 struct cli_connect_sock_state *state = tevent_req_data(
3045 req, struct cli_connect_sock_state);
3048 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3050 TALLOC_FREE(subreq);
3051 if (tevent_req_nterror(req, status)) {
3054 set_socket_options(state->fd, lp_socket_options());
3055 tevent_req_done(req);
3058 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3059 int *pfd, uint16_t *pport)
3061 struct cli_connect_sock_state *state = tevent_req_data(
3062 req, struct cli_connect_sock_state);
3065 if (tevent_req_is_nterror(req, &status)) {
3069 *pport = state->port;
3070 return NT_STATUS_OK;
3073 struct cli_connect_nb_state {
3074 const char *desthost;
3077 struct cli_state *cli;
3080 static void cli_connect_nb_done(struct tevent_req *subreq);
3082 static struct tevent_req *cli_connect_nb_send(
3083 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3084 const char *host, const struct sockaddr_storage *dest_ss,
3085 uint16_t port, int name_type, const char *myname,
3086 int signing_state, int flags)
3088 struct tevent_req *req, *subreq;
3089 struct cli_connect_nb_state *state;
3091 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3095 state->signing_state = signing_state;
3096 state->flags = flags;
3099 char *p = strchr(host, '#');
3102 name_type = strtol(p+1, NULL, 16);
3103 host = talloc_strndup(state, host, p - host);
3104 if (tevent_req_nomem(host, req)) {
3105 return tevent_req_post(req, ev);
3109 state->desthost = host;
3111 state->desthost = print_canonical_sockaddr(state, dest_ss);
3112 if (tevent_req_nomem(state->desthost, req)) {
3113 return tevent_req_post(req, ev);
3117 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3119 if (tevent_req_nomem(subreq, req)) {
3120 return tevent_req_post(req, ev);
3122 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3126 static void cli_connect_nb_done(struct tevent_req *subreq)
3128 struct tevent_req *req = tevent_req_callback_data(
3129 subreq, struct tevent_req);
3130 struct cli_connect_nb_state *state = tevent_req_data(
3131 req, struct cli_connect_nb_state);
3136 status = cli_connect_sock_recv(subreq, &fd, &port);
3137 TALLOC_FREE(subreq);
3138 if (tevent_req_nterror(req, status)) {
3142 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3143 state->signing_state, state->flags);
3144 if (tevent_req_nomem(state->cli, req)) {
3148 tevent_req_done(req);
3151 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3152 struct cli_state **pcli)
3154 struct cli_connect_nb_state *state = tevent_req_data(
3155 req, struct cli_connect_nb_state);
3158 if (tevent_req_is_nterror(req, &status)) {
3161 *pcli = talloc_move(NULL, &state->cli);
3162 return NT_STATUS_OK;
3165 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3166 uint16_t port, int name_type, const char *myname,
3167 int signing_state, int flags, struct cli_state **pcli)
3169 struct tevent_context *ev;
3170 struct tevent_req *req;
3171 NTSTATUS status = NT_STATUS_NO_MEMORY;
3173 ev = samba_tevent_context_init(talloc_tos());
3177 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3178 myname, signing_state, flags);
3182 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3185 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3188 status = cli_connect_nb_recv(req, pcli);
3194 struct cli_start_connection_state {
3195 struct tevent_context *ev;
3196 struct cli_state *cli;
3201 static void cli_start_connection_connected(struct tevent_req *subreq);
3202 static void cli_start_connection_done(struct tevent_req *subreq);
3205 establishes a connection to after the negprot.
3206 @param output_cli A fully initialised cli structure, non-null only on success
3207 @param dest_host The netbios name of the remote host
3208 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3209 @param port (optional) The destination port (0 for default)
3212 static struct tevent_req *cli_start_connection_send(
3213 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3214 const char *my_name, const char *dest_host,
3215 const struct sockaddr_storage *dest_ss, int port,
3216 int signing_state, int flags)
3218 struct tevent_req *req, *subreq;
3219 struct cli_start_connection_state *state;
3221 req = tevent_req_create(mem_ctx, &state,
3222 struct cli_start_connection_state);
3228 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3229 state->min_protocol = lp_client_ipc_min_protocol();
3230 state->max_protocol = lp_client_ipc_max_protocol();
3232 state->min_protocol = lp_client_min_protocol();
3233 state->max_protocol = lp_client_max_protocol();
3236 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3237 0x20, my_name, signing_state, flags);
3238 if (tevent_req_nomem(subreq, req)) {
3239 return tevent_req_post(req, ev);
3241 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3245 static void cli_start_connection_connected(struct tevent_req *subreq)
3247 struct tevent_req *req = tevent_req_callback_data(
3248 subreq, struct tevent_req);
3249 struct cli_start_connection_state *state = tevent_req_data(
3250 req, struct cli_start_connection_state);
3253 status = cli_connect_nb_recv(subreq, &state->cli);
3254 TALLOC_FREE(subreq);
3255 if (tevent_req_nterror(req, status)) {
3259 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3260 state->cli->timeout,
3261 state->min_protocol,
3262 state->max_protocol);
3263 if (tevent_req_nomem(subreq, req)) {
3266 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3269 static void cli_start_connection_done(struct tevent_req *subreq)
3271 struct tevent_req *req = tevent_req_callback_data(
3272 subreq, struct tevent_req);
3273 struct cli_start_connection_state *state = tevent_req_data(
3274 req, struct cli_start_connection_state);
3277 status = smbXcli_negprot_recv(subreq);
3278 TALLOC_FREE(subreq);
3279 if (tevent_req_nterror(req, status)) {
3283 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3284 /* Ensure we ask for some initial credits. */
3285 smb2cli_conn_set_max_credits(state->cli->conn,
3286 DEFAULT_SMB2_MAX_CREDITS);
3289 tevent_req_done(req);
3292 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3293 struct cli_state **output_cli)
3295 struct cli_start_connection_state *state = tevent_req_data(
3296 req, struct cli_start_connection_state);
3299 if (tevent_req_is_nterror(req, &status)) {
3302 *output_cli = state->cli;
3304 return NT_STATUS_OK;
3307 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3308 const char *my_name,
3309 const char *dest_host,
3310 const struct sockaddr_storage *dest_ss, int port,
3311 int signing_state, int flags)
3313 struct tevent_context *ev;
3314 struct tevent_req *req;
3315 NTSTATUS status = NT_STATUS_NO_MEMORY;
3317 ev = samba_tevent_context_init(talloc_tos());
3321 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3322 port, signing_state, flags);
3326 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3329 status = cli_start_connection_recv(req, output_cli);
3336 establishes a connection right up to doing tconX, password specified.
3337 @param output_cli A fully initialised cli structure, non-null only on success
3338 @param dest_host The netbios name of the remote host
3339 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3340 @param port (optional) The destination port (0 for default)
3341 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3342 @param service_type The 'type' of serivice.
3343 @param user Username, unix string
3344 @param domain User's domain
3345 @param password User's password, unencrypted unix string.
3348 struct cli_full_connection_state {
3349 struct tevent_context *ev;
3350 const char *service;
3351 const char *service_type;
3354 const char *password;
3357 struct cli_state *cli;
3360 static int cli_full_connection_state_destructor(
3361 struct cli_full_connection_state *s);
3362 static void cli_full_connection_started(struct tevent_req *subreq);
3363 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3364 static void cli_full_connection_done(struct tevent_req *subreq);
3366 struct tevent_req *cli_full_connection_send(
3367 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3368 const char *my_name, const char *dest_host,
3369 const struct sockaddr_storage *dest_ss, int port,
3370 const char *service, const char *service_type,
3371 const char *user, const char *domain,
3372 const char *password, int flags, int signing_state)
3374 struct tevent_req *req, *subreq;
3375 struct cli_full_connection_state *state;
3377 req = tevent_req_create(mem_ctx, &state,
3378 struct cli_full_connection_state);
3382 talloc_set_destructor(state, cli_full_connection_state_destructor);
3385 state->service = service;
3386 state->service_type = service_type;
3388 state->domain = domain;
3389 state->password = password;
3390 state->flags = flags;
3392 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3393 if (state->password == NULL) {
3394 state->password = "";
3397 subreq = cli_start_connection_send(
3398 state, ev, my_name, dest_host, dest_ss, port,
3399 signing_state, flags);
3400 if (tevent_req_nomem(subreq, req)) {
3401 return tevent_req_post(req, ev);
3403 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3407 static int cli_full_connection_state_destructor(
3408 struct cli_full_connection_state *s)
3410 if (s->cli != NULL) {
3411 cli_shutdown(s->cli);
3417 static void cli_full_connection_started(struct tevent_req *subreq)
3419 struct tevent_req *req = tevent_req_callback_data(
3420 subreq, struct tevent_req);
3421 struct cli_full_connection_state *state = tevent_req_data(
3422 req, struct cli_full_connection_state);
3425 status = cli_start_connection_recv(subreq, &state->cli);
3426 TALLOC_FREE(subreq);
3427 if (tevent_req_nterror(req, status)) {
3430 subreq = cli_session_setup_send(
3431 state, state->ev, state->cli, state->user,
3432 state->password, state->pw_len, state->password, state->pw_len,
3434 if (tevent_req_nomem(subreq, req)) {
3437 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3440 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3442 struct tevent_req *req = tevent_req_callback_data(
3443 subreq, struct tevent_req);
3444 struct cli_full_connection_state *state = tevent_req_data(
3445 req, struct cli_full_connection_state);
3448 status = cli_session_setup_recv(subreq);
3449 TALLOC_FREE(subreq);
3451 if (!NT_STATUS_IS_OK(status) &&
3452 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3454 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3456 subreq = cli_session_setup_send(
3457 state, state->ev, state->cli, "", "", 0, "", 0,
3459 if (tevent_req_nomem(subreq, req)) {
3462 tevent_req_set_callback(
3463 subreq, cli_full_connection_sess_set_up, req);
3467 if (tevent_req_nterror(req, status)) {
3471 if (state->service != NULL) {
3472 subreq = cli_tree_connect_send(
3473 state, state->ev, state->cli,
3474 state->service, state->service_type,
3475 state->password, state->pw_len);
3476 if (tevent_req_nomem(subreq, req)) {
3479 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3483 status = cli_init_creds(state->cli, state->user, state->domain,
3485 if (tevent_req_nterror(req, status)) {
3488 tevent_req_done(req);
3491 static void cli_full_connection_done(struct tevent_req *subreq)
3493 struct tevent_req *req = tevent_req_callback_data(
3494 subreq, struct tevent_req);
3495 struct cli_full_connection_state *state = tevent_req_data(
3496 req, struct cli_full_connection_state);
3499 status = cli_tree_connect_recv(subreq);
3500 TALLOC_FREE(subreq);
3501 if (tevent_req_nterror(req, status)) {
3504 status = cli_init_creds(state->cli, state->user, state->domain,
3506 if (tevent_req_nterror(req, status)) {
3509 tevent_req_done(req);
3512 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3513 struct cli_state **output_cli)
3515 struct cli_full_connection_state *state = tevent_req_data(
3516 req, struct cli_full_connection_state);
3519 if (tevent_req_is_nterror(req, &status)) {
3522 *output_cli = state->cli;
3523 talloc_set_destructor(state, NULL);
3524 return NT_STATUS_OK;
3527 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3528 const char *my_name,
3529 const char *dest_host,
3530 const struct sockaddr_storage *dest_ss, int port,
3531 const char *service, const char *service_type,
3532 const char *user, const char *domain,
3533 const char *password, int flags,
3536 struct tevent_context *ev;
3537 struct tevent_req *req;
3538 NTSTATUS status = NT_STATUS_NO_MEMORY;
3540 ev = samba_tevent_context_init(talloc_tos());
3544 req = cli_full_connection_send(
3545 ev, ev, my_name, dest_host, dest_ss, port, service,
3546 service_type, user, domain, password, flags, signing_state);
3550 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3553 status = cli_full_connection_recv(req, output_cli);
3559 /****************************************************************************
3560 Send an old style tcon.
3561 ****************************************************************************/
3562 struct cli_raw_tcon_state {
3566 static void cli_raw_tcon_done(struct tevent_req *subreq);
3568 static struct tevent_req *cli_raw_tcon_send(
3569 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3570 const char *service, const char *pass, const char *dev)
3572 struct tevent_req *req, *subreq;
3573 struct cli_raw_tcon_state *state;
3576 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3581 if (!lp_client_plaintext_auth() && (*pass)) {
3582 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3583 " or 'client ntlmv2 auth = yes'\n"));
3584 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3585 return tevent_req_post(req, ev);
3588 bytes = talloc_array(state, uint8_t, 0);
3589 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3590 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3591 service, strlen(service)+1, NULL);
3592 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3593 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3594 pass, strlen(pass)+1, NULL);
3595 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3596 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3597 dev, strlen(dev)+1, NULL);
3599 if (tevent_req_nomem(bytes, req)) {
3600 return tevent_req_post(req, ev);
3603 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3604 talloc_get_size(bytes), bytes);
3605 if (tevent_req_nomem(subreq, req)) {
3606 return tevent_req_post(req, ev);
3608 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3612 static void cli_raw_tcon_done(struct tevent_req *subreq)
3614 struct tevent_req *req = tevent_req_callback_data(
3615 subreq, struct tevent_req);
3616 struct cli_raw_tcon_state *state = tevent_req_data(
3617 req, struct cli_raw_tcon_state);
3620 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3622 TALLOC_FREE(subreq);
3623 if (tevent_req_nterror(req, status)) {
3626 tevent_req_done(req);
3629 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3630 uint16_t *max_xmit, uint16_t *tid)
3632 struct cli_raw_tcon_state *state = tevent_req_data(
3633 req, struct cli_raw_tcon_state);
3636 if (tevent_req_is_nterror(req, &status)) {
3639 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3640 *tid = SVAL(state->ret_vwv + 1, 0);
3641 return NT_STATUS_OK;
3644 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3645 const char *service, const char *pass, const char *dev,
3646 uint16_t *max_xmit, uint16_t *tid)
3648 struct tevent_context *ev;
3649 struct tevent_req *req;
3650 NTSTATUS status = NT_STATUS_NO_MEMORY;
3652 ev = samba_tevent_context_init(talloc_tos());
3656 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3660 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3663 status = cli_raw_tcon_recv(req, max_xmit, tid);
3669 /* Return a cli_state pointing at the IPC$ share for the given server */
3671 struct cli_state *get_ipc_connect(char *server,
3672 struct sockaddr_storage *server_ss,
3673 const struct user_auth_info *user_info)
3675 struct cli_state *cli;
3677 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3679 if (user_info->use_kerberos) {
3680 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3683 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3684 user_info->username ? user_info->username : "",
3686 user_info->password ? user_info->password : "",
3688 SMB_SIGNING_DEFAULT);
3690 if (NT_STATUS_IS_OK(nt_status)) {
3692 } else if (is_ipaddress(server)) {
3693 /* windows 9* needs a correct NMB name for connections */
3694 fstring remote_name;
3696 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3697 cli = get_ipc_connect(remote_name, server_ss, user_info);
3706 * Given the IP address of a master browser on the network, return its
3707 * workgroup and connect to it.
3709 * This function is provided to allow additional processing beyond what
3710 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3711 * browsers and obtain each master browsers' list of domains (in case the
3712 * first master browser is recently on the network and has not yet
3713 * synchronized with other master browsers and therefore does not yet have the
3714 * entire network browse list)
3717 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3718 struct sockaddr_storage *mb_ip,
3719 const struct user_auth_info *user_info,
3720 char **pp_workgroup_out)
3722 char addr[INET6_ADDRSTRLEN];
3724 struct cli_state *cli;
3725 struct sockaddr_storage server_ss;
3727 *pp_workgroup_out = NULL;
3729 print_sockaddr(addr, sizeof(addr), mb_ip);
3730 DEBUG(99, ("Looking up name of master browser %s\n",
3734 * Do a name status query to find out the name of the master browser.
3735 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3736 * master browser will not respond to a wildcard query (or, at least,
3737 * an NT4 server acting as the domain master browser will not).
3739 * We might be able to use ONLY the query on MSBROWSE, but that's not
3740 * yet been tested with all Windows versions, so until it is, leave
3741 * the original wildcard query as the first choice and fall back to
3742 * MSBROWSE if the wildcard query fails.
3744 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3745 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3747 DEBUG(99, ("Could not retrieve name status for %s\n",
3752 if (!find_master_ip(name, &server_ss)) {
3753 DEBUG(99, ("Could not find master ip for %s\n", name));
3757 *pp_workgroup_out = talloc_strdup(ctx, name);
3759 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3761 print_sockaddr(addr, sizeof(addr), &server_ss);
3762 cli = get_ipc_connect(addr, &server_ss, user_info);
3768 * Return the IP address and workgroup of a master browser on the network, and
3772 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3773 const struct user_auth_info *user_info,
3774 char **pp_workgroup_out)
3776 struct sockaddr_storage *ip_list;
3777 struct cli_state *cli;
3781 *pp_workgroup_out = NULL;
3783 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3785 /* Go looking for workgroups by broadcasting on the local network */
3787 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3789 if (!NT_STATUS_IS_OK(status)) {
3790 DEBUG(99, ("No master browsers responded: %s\n",
3791 nt_errstr(status)));
3795 for (i = 0; i < count; i++) {
3796 char addr[INET6_ADDRSTRLEN];
3797 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3798 DEBUG(99, ("Found master browser %s\n", addr));
3800 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3801 user_info, pp_workgroup_out);