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 struct smbXcli_session *session = NULL;
1594 bool is_guest = false;
1596 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1597 session = state->cli->smb2.session;
1599 session = state->cli->smb1.session;
1602 is_guest = smbXcli_session_is_guest(session);
1605 * We can't finish the gensec handshake, we don't
1606 * have a negotiated session key.
1608 * So just pretend we are completely done.
1610 * Note that smbXcli_session_is_guest()
1611 * always returns false if we require signing.
1613 state->blob_in = data_blob_null;
1614 state->local_ready = true;
1617 state->remote_ready = true;
1620 if (state->local_ready && state->remote_ready) {
1621 cli_session_setup_gensec_ready(req);
1625 cli_session_setup_gensec_local_next(req);
1628 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1630 struct cli_session_setup_gensec_state *state =
1631 tevent_req_data(req,
1632 struct cli_session_setup_gensec_state);
1633 const char *server_domain = NULL;
1636 if (state->blob_in.length != 0) {
1637 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1641 if (state->blob_out.length != 0) {
1642 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1647 * gensec_ntlmssp_server_domain() returns NULL
1648 * if NTLMSSP is not used.
1650 * We can remove this later
1651 * and leave the server domain empty for SMB2 and above
1652 * in future releases.
1654 server_domain = gensec_ntlmssp_server_domain(
1655 state->auth_generic->gensec_security);
1657 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1658 TALLOC_FREE(state->cli->server_domain);
1659 state->cli->server_domain = talloc_strdup(state->cli,
1661 if (state->cli->server_domain == NULL) {
1662 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1667 if (state->is_anonymous) {
1669 * Windows server does not set the
1670 * SMB2_SESSION_FLAG_IS_NULL flag.
1672 * This fix makes sure we do not try
1673 * to verify a signature on the final
1674 * session setup response.
1676 tevent_req_done(req);
1680 status = gensec_session_key(state->auth_generic->gensec_security,
1681 state, &state->session_key);
1682 if (tevent_req_nterror(req, status)) {
1686 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1687 struct smbXcli_session *session = state->cli->smb2.session;
1689 status = smb2cli_session_set_session_key(session,
1692 if (tevent_req_nterror(req, status)) {
1696 struct smbXcli_session *session = state->cli->smb1.session;
1699 status = smb1cli_session_set_session_key(session,
1700 state->session_key);
1701 if (tevent_req_nterror(req, status)) {
1705 active = smb1cli_conn_activate_signing(state->cli->conn,
1711 ok = smb1cli_conn_check_signing(state->cli->conn,
1714 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1720 tevent_req_done(req);
1723 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1725 struct cli_session_setup_gensec_state *state =
1726 tevent_req_data(req,
1727 struct cli_session_setup_gensec_state);
1730 if (tevent_req_is_nterror(req, &status)) {
1731 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1734 return NT_STATUS_OK;
1739 static char *cli_session_setup_get_principal(
1740 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1741 const char *remote_name, const char *dest_realm)
1743 char *principal = NULL;
1745 if (!lp_client_use_spnego_principal() ||
1746 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1747 spnego_principal = NULL;
1749 if (spnego_principal != NULL) {
1750 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1751 "principal %s\n", spnego_principal));
1752 return talloc_strdup(mem_ctx, spnego_principal);
1754 if (is_ipaddress(remote_name) ||
1755 strequal(remote_name, STAR_SMBSERVER)) {
1759 DEBUG(3, ("cli_session_setup_spnego: using target "
1760 "hostname not SPNEGO principal\n"));
1763 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1764 if (realm == NULL) {
1767 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1768 remote_name, realm);
1771 principal = kerberos_get_principal_from_service_hostname(
1772 talloc_tos(), "cifs", remote_name, lp_realm());
1774 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1775 principal ? principal : "<null>"));
1781 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1782 const char *principal)
1786 account = talloc_strdup(mem_ctx, principal);
1787 if (account == NULL) {
1790 p = strchr_m(account, '@');
1797 /****************************************************************************
1798 Do a spnego encrypted session setup.
1800 user_domain: The shortname of the domain the user/machine is a member of.
1801 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1802 ****************************************************************************/
1804 struct cli_session_setup_spnego_state {
1805 struct tevent_context *ev;
1806 struct cli_state *cli;
1807 const char *target_hostname;
1809 const char *account;
1811 const char *user_domain;
1812 const char *dest_realm;
1817 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1820 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1822 static struct tevent_req *cli_session_setup_spnego_send(
1823 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1824 const char *user, const char *pass, const char *user_domain)
1826 struct tevent_req *req, *subreq;
1827 struct cli_session_setup_spnego_state *state;
1828 char *principal = NULL;
1829 char *OIDs[ASN1_MAX_OIDS];
1831 const char *dest_realm = cli_state_remote_realm(cli);
1832 const DATA_BLOB *server_blob;
1835 req = tevent_req_create(mem_ctx, &state,
1836 struct cli_session_setup_spnego_state);
1844 state->user_domain = user_domain;
1845 state->dest_realm = dest_realm;
1847 state->account = cli_session_setup_get_account(state, user);
1848 if (tevent_req_nomem(state->account, req)) {
1849 return tevent_req_post(req, ev);
1852 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1853 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1855 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1856 (unsigned long)server_blob->length));
1858 /* the server might not even do spnego */
1859 if (server_blob->length == 0) {
1860 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1865 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1868 /* The server sent us the first part of the SPNEGO exchange in the
1869 * negprot reply. It is WRONG to depend on the principal sent in the
1870 * negprot reply, but right now we do it. If we don't receive one,
1871 * we try to best guess, then fall back to NTLM. */
1872 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1873 &principal, NULL) ||
1875 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1876 tevent_req_done(req);
1877 return tevent_req_post(req, ev);
1880 /* make sure the server understands kerberos */
1881 for (i=0;OIDs[i];i++) {
1883 DEBUG(3,("got OID=%s\n", OIDs[i]));
1885 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1886 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1887 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1888 cli->got_kerberos_mechanism = True;
1890 talloc_free(OIDs[i]);
1893 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1895 status = cli_set_username(cli, user);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 state->result = ADS_ERROR_NT(status);
1898 tevent_req_done(req);
1899 return tevent_req_post(req, ev);
1903 /* If password is set we reauthenticate to kerberos server
1904 * and do not store results */
1906 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1909 tmp = cli_session_setup_get_principal(
1910 talloc_tos(), principal, state->target_hostname, dest_realm);
1911 TALLOC_FREE(principal);
1914 if (pass && *pass) {
1917 use_in_memory_ccache();
1918 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1921 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1922 TALLOC_FREE(principal);
1923 if (cli->fallback_after_kerberos)
1925 state->result = ADS_ERROR_KRB5(ret);
1926 tevent_req_done(req);
1927 return tevent_req_post(req, ev);
1932 subreq = cli_session_setup_gensec_send(
1934 state->account, pass, user_domain,
1935 CRED_MUST_USE_KERBEROS,
1936 "cifs", state->target_hostname, principal);
1937 if (tevent_req_nomem(subreq, req)) {
1938 return tevent_req_post(req, ev);
1940 tevent_req_set_callback(
1941 subreq, cli_session_setup_spnego_done_krb,
1949 subreq = cli_session_setup_gensec_send(
1950 state, state->ev, state->cli,
1951 state->account, state->pass, state->user_domain,
1952 CRED_DONT_USE_KERBEROS,
1953 "cifs", state->target_hostname, NULL);
1954 if (tevent_req_nomem(subreq, req)) {
1955 return tevent_req_post(req, ev);
1957 tevent_req_set_callback(
1958 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1963 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1965 struct tevent_req *req = tevent_req_callback_data(
1966 subreq, struct tevent_req);
1967 struct cli_session_setup_spnego_state *state = tevent_req_data(
1968 req, struct cli_session_setup_spnego_state);
1971 status = cli_session_setup_gensec_recv(subreq);
1972 TALLOC_FREE(subreq);
1973 state->result = ADS_ERROR_NT(status);
1975 if (ADS_ERR_OK(state->result) ||
1976 !state->cli->fallback_after_kerberos) {
1977 tevent_req_done(req);
1981 subreq = cli_session_setup_gensec_send(
1982 state, state->ev, state->cli,
1983 state->account, state->pass, state->user_domain,
1984 CRED_DONT_USE_KERBEROS,
1985 "cifs", state->target_hostname, NULL);
1986 if (tevent_req_nomem(subreq, req)) {
1989 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1994 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1996 struct tevent_req *req = tevent_req_callback_data(
1997 subreq, struct tevent_req);
1998 struct cli_session_setup_spnego_state *state = tevent_req_data(
1999 req, struct cli_session_setup_spnego_state);
2002 status = cli_session_setup_gensec_recv(subreq);
2003 TALLOC_FREE(subreq);
2004 state->result = ADS_ERROR_NT(status);
2005 tevent_req_done(req);
2008 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
2010 struct cli_session_setup_spnego_state *state = tevent_req_data(
2011 req, struct cli_session_setup_spnego_state);
2013 return state->result;
2016 struct cli_session_setup_state {
2020 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
2021 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
2022 static void cli_session_setup_done_guest(struct tevent_req *subreq);
2023 static void cli_session_setup_done_plain(struct tevent_req *subreq);
2024 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
2026 /****************************************************************************
2027 Send a session setup. The username and workgroup is in UNIX character
2028 format and must be converted to DOS codepage format before sending. If the
2029 password is in plaintext, the same should be done.
2030 ****************************************************************************/
2032 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
2033 struct tevent_context *ev,
2034 struct cli_state *cli,
2036 const char *pass, int passlen,
2037 const char *ntpass, int ntpasslen,
2038 const char *workgroup)
2040 struct tevent_req *req, *subreq;
2041 struct cli_session_setup_state *state;
2044 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2046 req = tevent_req_create(mem_ctx, &state,
2047 struct cli_session_setup_state);
2053 user2 = talloc_strdup(state, user);
2055 user2 = talloc_strdup(state, "");
2057 if (user2 == NULL) {
2058 tevent_req_oom(req);
2059 return tevent_req_post(req, ev);
2066 /* allow for workgroups as part of the username */
2067 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2068 (p=strchr_m(user2,*lp_winbind_separator()))) {
2071 if (!strupper_m(user2)) {
2072 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 return tevent_req_post(req, ev);
2078 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2079 tevent_req_done(req);
2080 return tevent_req_post(req, ev);
2083 /* now work out what sort of session setup we are going to
2084 do. I have split this into separate functions to make the
2085 flow a bit easier to understand (tridge) */
2087 /* if its an older server then we have to use the older request format */
2089 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2090 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2091 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2092 " or 'client ntlmv2 auth = yes'\n"));
2093 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2094 return tevent_req_post(req, ev);
2097 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2098 !lp_client_plaintext_auth() && (*pass)) {
2099 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2100 " or 'client ntlmv2 auth = yes'\n"));
2101 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2102 return tevent_req_post(req, ev);
2105 subreq = cli_session_setup_lanman2_send(
2106 state, ev, cli, user, pass, passlen, workgroup);
2107 if (tevent_req_nomem(subreq, req)) {
2108 return tevent_req_post(req, ev);
2110 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2115 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2116 subreq = cli_session_setup_spnego_send(
2117 state, ev, cli, user, pass, workgroup);
2118 if (tevent_req_nomem(subreq, req)) {
2119 return tevent_req_post(req, ev);
2121 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2127 * if the server supports extended security then use SPNEGO
2128 * even for anonymous connections.
2130 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2131 subreq = cli_session_setup_spnego_send(
2132 state, ev, cli, user, pass, workgroup);
2133 if (tevent_req_nomem(subreq, req)) {
2134 return tevent_req_post(req, ev);
2136 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2141 /* if no user is supplied then we have to do an anonymous connection.
2142 passwords are ignored */
2144 if (!user || !*user) {
2145 subreq = cli_session_setup_guest_send(state, ev, cli);
2146 if (tevent_req_nomem(subreq, req)) {
2147 return tevent_req_post(req, ev);
2149 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2154 /* if the server is share level then send a plaintext null
2155 password at this point. The password is sent in the tree
2158 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2159 subreq = cli_session_setup_plain_send(
2160 state, ev, cli, user, "", workgroup);
2161 if (tevent_req_nomem(subreq, req)) {
2162 return tevent_req_post(req, ev);
2164 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2169 /* if the server doesn't support encryption then we have to use
2170 plaintext. The second password is ignored */
2172 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2173 if (!lp_client_plaintext_auth() && (*pass)) {
2174 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2175 " or 'client ntlmv2 auth = yes'\n"));
2176 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2177 return tevent_req_post(req, ev);
2179 subreq = cli_session_setup_plain_send(
2180 state, ev, cli, user, pass, workgroup);
2181 if (tevent_req_nomem(subreq, req)) {
2182 return tevent_req_post(req, ev);
2184 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2190 /* otherwise do a NT1 style session setup */
2191 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2193 * Don't send an NTLMv2 response without NTLMSSP
2194 * if we want to use spnego support
2196 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2197 " but 'client use spnego = yes"
2198 " and 'client ntlmv2 auth = yes'\n"));
2199 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2200 return tevent_req_post(req, ev);
2203 subreq = cli_session_setup_nt1_send(
2204 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2206 if (tevent_req_nomem(subreq, req)) {
2207 return tevent_req_post(req, ev);
2209 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2214 tevent_req_done(req);
2215 return tevent_req_post(req, ev);
2218 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2220 struct tevent_req *req = tevent_req_callback_data(
2221 subreq, struct tevent_req);
2224 status = cli_session_setup_lanman2_recv(subreq);
2225 TALLOC_FREE(subreq);
2226 if (!NT_STATUS_IS_OK(status)) {
2227 tevent_req_nterror(req, status);
2230 tevent_req_done(req);
2233 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2235 struct tevent_req *req = tevent_req_callback_data(
2236 subreq, struct tevent_req);
2239 status = cli_session_setup_spnego_recv(subreq);
2240 TALLOC_FREE(subreq);
2241 if (!ADS_ERR_OK(status)) {
2242 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2243 tevent_req_nterror(req, ads_ntstatus(status));
2246 tevent_req_done(req);
2249 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2251 struct tevent_req *req = tevent_req_callback_data(
2252 subreq, struct tevent_req);
2255 status = cli_session_setup_guest_recv(subreq);
2256 TALLOC_FREE(subreq);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 tevent_req_nterror(req, status);
2261 tevent_req_done(req);
2264 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2266 struct tevent_req *req = tevent_req_callback_data(
2267 subreq, struct tevent_req);
2270 status = cli_session_setup_plain_recv(subreq);
2271 TALLOC_FREE(subreq);
2272 if (!NT_STATUS_IS_OK(status)) {
2273 tevent_req_nterror(req, status);
2276 tevent_req_done(req);
2279 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2281 struct tevent_req *req = tevent_req_callback_data(
2282 subreq, struct tevent_req);
2285 status = cli_session_setup_nt1_recv(subreq);
2286 TALLOC_FREE(subreq);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 DEBUG(3, ("cli_session_setup: NT1 session setup "
2289 "failed: %s\n", nt_errstr(status)));
2290 tevent_req_nterror(req, status);
2293 tevent_req_done(req);
2296 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2298 return tevent_req_simple_recv_ntstatus(req);
2301 NTSTATUS cli_session_setup(struct cli_state *cli,
2303 const char *pass, int passlen,
2304 const char *ntpass, int ntpasslen,
2305 const char *workgroup)
2307 struct tevent_context *ev;
2308 struct tevent_req *req;
2309 NTSTATUS status = NT_STATUS_NO_MEMORY;
2311 if (smbXcli_conn_has_async_calls(cli->conn)) {
2312 return NT_STATUS_INVALID_PARAMETER;
2314 ev = samba_tevent_context_init(talloc_tos());
2318 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2319 ntpass, ntpasslen, workgroup);
2323 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2326 status = cli_session_setup_recv(req);
2332 /****************************************************************************
2334 *****************************************************************************/
2336 struct cli_ulogoff_state {
2337 struct cli_state *cli;
2341 static void cli_ulogoff_done(struct tevent_req *subreq);
2343 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2344 struct tevent_context *ev,
2345 struct cli_state *cli)
2347 struct tevent_req *req, *subreq;
2348 struct cli_ulogoff_state *state;
2350 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2356 SCVAL(state->vwv+0, 0, 0xFF);
2357 SCVAL(state->vwv+1, 0, 0);
2358 SSVAL(state->vwv+2, 0, 0);
2360 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2362 if (tevent_req_nomem(subreq, req)) {
2363 return tevent_req_post(req, ev);
2365 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2369 static void cli_ulogoff_done(struct tevent_req *subreq)
2371 struct tevent_req *req = tevent_req_callback_data(
2372 subreq, struct tevent_req);
2373 struct cli_ulogoff_state *state = tevent_req_data(
2374 req, struct cli_ulogoff_state);
2377 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 tevent_req_nterror(req, status);
2382 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2383 tevent_req_done(req);
2386 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2388 return tevent_req_simple_recv_ntstatus(req);
2391 NTSTATUS cli_ulogoff(struct cli_state *cli)
2393 struct tevent_context *ev;
2394 struct tevent_req *req;
2395 NTSTATUS status = NT_STATUS_NO_MEMORY;
2397 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2398 status = smb2cli_logoff(cli->conn,
2401 if (!NT_STATUS_IS_OK(status)) {
2404 smb2cli_session_set_id_and_flags(cli->smb2.session,
2406 return NT_STATUS_OK;
2409 if (smbXcli_conn_has_async_calls(cli->conn)) {
2410 return NT_STATUS_INVALID_PARAMETER;
2412 ev = samba_tevent_context_init(talloc_tos());
2416 req = cli_ulogoff_send(ev, ev, cli);
2420 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2423 status = cli_ulogoff_recv(req);
2429 /****************************************************************************
2431 ****************************************************************************/
2433 struct cli_tcon_andx_state {
2434 struct cli_state *cli;
2439 static void cli_tcon_andx_done(struct tevent_req *subreq);
2441 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2442 struct tevent_context *ev,
2443 struct cli_state *cli,
2444 const char *share, const char *dev,
2445 const char *pass, int passlen,
2446 struct tevent_req **psmbreq)
2448 struct tevent_req *req, *subreq;
2449 struct cli_tcon_andx_state *state;
2454 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2455 uint16_t tcon_flags = 0;
2459 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2466 cli->share = talloc_strdup(cli, share);
2471 /* in user level security don't send a password now */
2472 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2475 } else if (pass == NULL) {
2476 DEBUG(1, ("Server not using user level security and no "
2477 "password supplied.\n"));
2481 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2482 *pass && passlen != 24) {
2483 if (!lp_client_lanman_auth()) {
2484 DEBUG(1, ("Server requested LANMAN password "
2485 "(share-level security) but "
2486 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2491 * Non-encrypted passwords - convert to DOS codepage before
2494 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2496 pass = (const char *)p24;
2498 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2499 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2503 if (!lp_client_plaintext_auth() && (*pass)) {
2504 DEBUG(1, ("Server requested PLAINTEXT "
2506 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2511 * Non-encrypted passwords - convert to DOS codepage
2514 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2515 if (tevent_req_nomem(tmp_pass, req)) {
2516 return tevent_req_post(req, ev);
2518 tmp_pass = trans2_bytes_push_str(tmp_pass,
2519 false, /* always DOS */
2523 if (tevent_req_nomem(tmp_pass, req)) {
2524 return tevent_req_post(req, ev);
2526 pass = (const char *)tmp_pass;
2527 passlen = talloc_get_size(tmp_pass);
2531 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2532 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2534 SCVAL(vwv+0, 0, 0xFF);
2537 SSVAL(vwv+2, 0, tcon_flags);
2538 SSVAL(vwv+3, 0, passlen);
2540 if (passlen && pass) {
2541 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2543 bytes = talloc_array(state, uint8_t, 0);
2549 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2550 smbXcli_conn_remote_name(cli->conn), share);
2555 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2560 * Add the devicetype
2562 tmp = talloc_strdup_upper(talloc_tos(), dev);
2567 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2570 if (bytes == NULL) {
2575 state->bytes.iov_base = (void *)bytes;
2576 state->bytes.iov_len = talloc_get_size(bytes);
2578 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2580 if (subreq == NULL) {
2584 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2589 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2590 return tevent_req_post(req, ev);
2593 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2594 struct tevent_context *ev,
2595 struct cli_state *cli,
2596 const char *share, const char *dev,
2597 const char *pass, int passlen)
2599 struct tevent_req *req, *subreq;
2602 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2607 if (subreq == NULL) {
2610 status = smb1cli_req_chain_submit(&subreq, 1);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 tevent_req_nterror(req, status);
2613 return tevent_req_post(req, ev);
2618 static void cli_tcon_andx_done(struct tevent_req *subreq)
2620 struct tevent_req *req = tevent_req_callback_data(
2621 subreq, struct tevent_req);
2622 struct cli_tcon_andx_state *state = tevent_req_data(
2623 req, struct cli_tcon_andx_state);
2624 struct cli_state *cli = state->cli;
2632 uint16_t optional_support = 0;
2634 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2635 &num_bytes, &bytes);
2636 TALLOC_FREE(subreq);
2637 if (!NT_STATUS_IS_OK(status)) {
2638 tevent_req_nterror(req, status);
2642 inhdr = in + NBT_HDR_SIZE;
2645 if (clistr_pull_talloc(cli,
2646 (const char *)inhdr,
2647 SVAL(inhdr, HDR_FLG2),
2651 STR_TERMINATE|STR_ASCII) == -1) {
2652 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2656 cli->dev = talloc_strdup(cli, "");
2657 if (cli->dev == NULL) {
2658 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2663 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2664 /* almost certainly win95 - enable bug fixes */
2669 * Make sure that we have the optional support 16-bit field. WCT > 2.
2670 * Avoids issues when connecting to Win9x boxes sharing files
2673 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2674 optional_support = SVAL(vwv+2, 0);
2677 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2678 smb1cli_session_protect_session_key(cli->smb1.session);
2681 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2682 SVAL(inhdr, HDR_TID),
2684 0, /* maximal_access */
2685 0, /* guest_maximal_access */
2687 NULL); /* fs_type */
2689 tevent_req_done(req);
2692 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2694 return tevent_req_simple_recv_ntstatus(req);
2697 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2698 const char *dev, const char *pass, int passlen)
2700 TALLOC_CTX *frame = talloc_stackframe();
2701 struct tevent_context *ev;
2702 struct tevent_req *req;
2703 NTSTATUS status = NT_STATUS_NO_MEMORY;
2705 if (smbXcli_conn_has_async_calls(cli->conn)) {
2707 * Can't use sync call while an async call is in flight
2709 status = NT_STATUS_INVALID_PARAMETER;
2713 ev = samba_tevent_context_init(frame);
2718 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2723 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2727 status = cli_tcon_andx_recv(req);
2733 struct cli_tree_connect_state {
2734 struct cli_state *cli;
2737 static struct tevent_req *cli_raw_tcon_send(
2738 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2739 const char *service, const char *pass, const char *dev);
2740 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2741 uint16_t *max_xmit, uint16_t *tid);
2743 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2744 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2745 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2747 static struct tevent_req *cli_tree_connect_send(
2748 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2749 const char *share, const char *dev, const char *pass, int passlen)
2751 struct tevent_req *req, *subreq;
2752 struct cli_tree_connect_state *state;
2754 req = tevent_req_create(mem_ctx, &state,
2755 struct cli_tree_connect_state);
2761 cli->share = talloc_strdup(cli, share);
2762 if (tevent_req_nomem(cli->share, req)) {
2763 return tevent_req_post(req, ev);
2766 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2769 cli->smb2.tcon = smbXcli_tcon_create(cli);
2770 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2771 return tevent_req_post(req, ev);
2774 unc = talloc_asprintf(state, "\\\\%s\\%s",
2775 smbXcli_conn_remote_name(cli->conn),
2777 if (tevent_req_nomem(unc, req)) {
2778 return tevent_req_post(req, ev);
2781 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2782 cli->smb2.session, cli->smb2.tcon,
2785 if (tevent_req_nomem(subreq, req)) {
2786 return tevent_req_post(req, ev);
2788 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2793 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2794 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2796 if (tevent_req_nomem(subreq, req)) {
2797 return tevent_req_post(req, ev);
2799 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2804 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2805 if (tevent_req_nomem(subreq, req)) {
2806 return tevent_req_post(req, ev);
2808 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2813 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2815 tevent_req_simple_finish_ntstatus(
2816 subreq, smb2cli_tcon_recv(subreq));
2819 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2821 tevent_req_simple_finish_ntstatus(
2822 subreq, cli_tcon_andx_recv(subreq));
2825 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2827 struct tevent_req *req = tevent_req_callback_data(
2828 subreq, struct tevent_req);
2829 struct cli_tree_connect_state *state = tevent_req_data(
2830 req, struct cli_tree_connect_state);
2832 uint16_t max_xmit = 0;
2835 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2836 if (tevent_req_nterror(req, status)) {
2840 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2842 0, /* optional_support */
2843 0, /* maximal_access */
2844 0, /* guest_maximal_access */
2846 NULL); /* fs_type */
2848 tevent_req_done(req);
2851 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2853 return tevent_req_simple_recv_ntstatus(req);
2856 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2857 const char *dev, const char *pass, int passlen)
2859 struct tevent_context *ev;
2860 struct tevent_req *req;
2861 NTSTATUS status = NT_STATUS_NO_MEMORY;
2863 if (smbXcli_conn_has_async_calls(cli->conn)) {
2864 return NT_STATUS_INVALID_PARAMETER;
2866 ev = samba_tevent_context_init(talloc_tos());
2870 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2874 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2877 status = cli_tree_connect_recv(req);
2883 /****************************************************************************
2884 Send a tree disconnect.
2885 ****************************************************************************/
2887 struct cli_tdis_state {
2888 struct cli_state *cli;
2891 static void cli_tdis_done(struct tevent_req *subreq);
2893 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2894 struct tevent_context *ev,
2895 struct cli_state *cli)
2897 struct tevent_req *req, *subreq;
2898 struct cli_tdis_state *state;
2900 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2906 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2907 if (tevent_req_nomem(subreq, req)) {
2908 return tevent_req_post(req, ev);
2910 tevent_req_set_callback(subreq, cli_tdis_done, req);
2914 static void cli_tdis_done(struct tevent_req *subreq)
2916 struct tevent_req *req = tevent_req_callback_data(
2917 subreq, struct tevent_req);
2918 struct cli_tdis_state *state = tevent_req_data(
2919 req, struct cli_tdis_state);
2922 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2923 TALLOC_FREE(subreq);
2924 if (!NT_STATUS_IS_OK(status)) {
2925 tevent_req_nterror(req, status);
2928 cli_state_set_tid(state->cli, UINT16_MAX);
2929 tevent_req_done(req);
2932 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2934 return tevent_req_simple_recv_ntstatus(req);
2937 NTSTATUS cli_tdis(struct cli_state *cli)
2939 struct tevent_context *ev;
2940 struct tevent_req *req;
2941 NTSTATUS status = NT_STATUS_NO_MEMORY;
2943 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2944 return smb2cli_tdis(cli->conn,
2950 if (smbXcli_conn_has_async_calls(cli->conn)) {
2951 return NT_STATUS_INVALID_PARAMETER;
2953 ev = samba_tevent_context_init(talloc_tos());
2957 req = cli_tdis_send(ev, ev, cli);
2961 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2964 status = cli_tdis_recv(req);
2970 struct cli_connect_sock_state {
2971 const char **called_names;
2972 const char **calling_names;
2978 static void cli_connect_sock_done(struct tevent_req *subreq);
2981 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2985 static struct tevent_req *cli_connect_sock_send(
2986 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2987 const char *host, int name_type, const struct sockaddr_storage *pss,
2988 const char *myname, uint16_t port)
2990 struct tevent_req *req, *subreq;
2991 struct cli_connect_sock_state *state;
2993 struct sockaddr_storage *addrs;
2994 unsigned i, num_addrs;
2997 req = tevent_req_create(mem_ctx, &state,
2998 struct cli_connect_sock_state);
3003 prog = getenv("LIBSMB_PROG");
3005 state->fd = sock_exec(prog);
3006 if (state->fd == -1) {
3007 status = map_nt_error_from_unix(errno);
3008 tevent_req_nterror(req, status);
3011 tevent_req_done(req);
3013 return tevent_req_post(req, ev);
3016 if ((pss == NULL) || is_zero_addr(pss)) {
3019 * Here we cheat. resolve_name_list is not async at all. So
3020 * this call will only be really async if the name lookup has
3021 * been done externally.
3024 status = resolve_name_list(state, host, name_type,
3025 &addrs, &num_addrs);
3026 if (!NT_STATUS_IS_OK(status)) {
3027 tevent_req_nterror(req, status);
3028 return tevent_req_post(req, ev);
3031 addrs = talloc_array(state, struct sockaddr_storage, 1);
3032 if (tevent_req_nomem(addrs, req)) {
3033 return tevent_req_post(req, ev);
3039 state->called_names = talloc_array(state, const char *, num_addrs);
3040 if (tevent_req_nomem(state->called_names, req)) {
3041 return tevent_req_post(req, ev);
3043 state->called_types = talloc_array(state, int, num_addrs);
3044 if (tevent_req_nomem(state->called_types, req)) {
3045 return tevent_req_post(req, ev);
3047 state->calling_names = talloc_array(state, const char *, num_addrs);
3048 if (tevent_req_nomem(state->calling_names, req)) {
3049 return tevent_req_post(req, ev);
3051 for (i=0; i<num_addrs; i++) {
3052 state->called_names[i] = host;
3053 state->called_types[i] = name_type;
3054 state->calling_names[i] = myname;
3057 subreq = smbsock_any_connect_send(
3058 state, ev, addrs, state->called_names, state->called_types,
3059 state->calling_names, NULL, num_addrs, port);
3060 if (tevent_req_nomem(subreq, req)) {
3061 return tevent_req_post(req, ev);
3063 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3067 static void cli_connect_sock_done(struct tevent_req *subreq)
3069 struct tevent_req *req = tevent_req_callback_data(
3070 subreq, struct tevent_req);
3071 struct cli_connect_sock_state *state = tevent_req_data(
3072 req, struct cli_connect_sock_state);
3075 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3077 TALLOC_FREE(subreq);
3078 if (tevent_req_nterror(req, status)) {
3081 set_socket_options(state->fd, lp_socket_options());
3082 tevent_req_done(req);
3085 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3086 int *pfd, uint16_t *pport)
3088 struct cli_connect_sock_state *state = tevent_req_data(
3089 req, struct cli_connect_sock_state);
3092 if (tevent_req_is_nterror(req, &status)) {
3096 *pport = state->port;
3097 return NT_STATUS_OK;
3100 struct cli_connect_nb_state {
3101 const char *desthost;
3104 struct cli_state *cli;
3107 static void cli_connect_nb_done(struct tevent_req *subreq);
3109 static struct tevent_req *cli_connect_nb_send(
3110 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3111 const char *host, const struct sockaddr_storage *dest_ss,
3112 uint16_t port, int name_type, const char *myname,
3113 int signing_state, int flags)
3115 struct tevent_req *req, *subreq;
3116 struct cli_connect_nb_state *state;
3118 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3122 state->signing_state = signing_state;
3123 state->flags = flags;
3126 char *p = strchr(host, '#');
3129 name_type = strtol(p+1, NULL, 16);
3130 host = talloc_strndup(state, host, p - host);
3131 if (tevent_req_nomem(host, req)) {
3132 return tevent_req_post(req, ev);
3136 state->desthost = host;
3138 state->desthost = print_canonical_sockaddr(state, dest_ss);
3139 if (tevent_req_nomem(state->desthost, req)) {
3140 return tevent_req_post(req, ev);
3144 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3146 if (tevent_req_nomem(subreq, req)) {
3147 return tevent_req_post(req, ev);
3149 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3153 static void cli_connect_nb_done(struct tevent_req *subreq)
3155 struct tevent_req *req = tevent_req_callback_data(
3156 subreq, struct tevent_req);
3157 struct cli_connect_nb_state *state = tevent_req_data(
3158 req, struct cli_connect_nb_state);
3163 status = cli_connect_sock_recv(subreq, &fd, &port);
3164 TALLOC_FREE(subreq);
3165 if (tevent_req_nterror(req, status)) {
3169 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3170 state->signing_state, state->flags);
3171 if (tevent_req_nomem(state->cli, req)) {
3175 tevent_req_done(req);
3178 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3179 struct cli_state **pcli)
3181 struct cli_connect_nb_state *state = tevent_req_data(
3182 req, struct cli_connect_nb_state);
3185 if (tevent_req_is_nterror(req, &status)) {
3188 *pcli = talloc_move(NULL, &state->cli);
3189 return NT_STATUS_OK;
3192 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3193 uint16_t port, int name_type, const char *myname,
3194 int signing_state, int flags, struct cli_state **pcli)
3196 struct tevent_context *ev;
3197 struct tevent_req *req;
3198 NTSTATUS status = NT_STATUS_NO_MEMORY;
3200 ev = samba_tevent_context_init(talloc_tos());
3204 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3205 myname, signing_state, flags);
3209 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3212 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3215 status = cli_connect_nb_recv(req, pcli);
3221 struct cli_start_connection_state {
3222 struct tevent_context *ev;
3223 struct cli_state *cli;
3228 static void cli_start_connection_connected(struct tevent_req *subreq);
3229 static void cli_start_connection_done(struct tevent_req *subreq);
3232 establishes a connection to after the negprot.
3233 @param output_cli A fully initialised cli structure, non-null only on success
3234 @param dest_host The netbios name of the remote host
3235 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3236 @param port (optional) The destination port (0 for default)
3239 static struct tevent_req *cli_start_connection_send(
3240 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3241 const char *my_name, const char *dest_host,
3242 const struct sockaddr_storage *dest_ss, int port,
3243 int signing_state, int flags)
3245 struct tevent_req *req, *subreq;
3246 struct cli_start_connection_state *state;
3248 req = tevent_req_create(mem_ctx, &state,
3249 struct cli_start_connection_state);
3255 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3256 state->min_protocol = lp_client_ipc_min_protocol();
3257 state->max_protocol = lp_client_ipc_max_protocol();
3259 state->min_protocol = lp_client_min_protocol();
3260 state->max_protocol = lp_client_max_protocol();
3263 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3264 0x20, my_name, signing_state, flags);
3265 if (tevent_req_nomem(subreq, req)) {
3266 return tevent_req_post(req, ev);
3268 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3272 static void cli_start_connection_connected(struct tevent_req *subreq)
3274 struct tevent_req *req = tevent_req_callback_data(
3275 subreq, struct tevent_req);
3276 struct cli_start_connection_state *state = tevent_req_data(
3277 req, struct cli_start_connection_state);
3280 status = cli_connect_nb_recv(subreq, &state->cli);
3281 TALLOC_FREE(subreq);
3282 if (tevent_req_nterror(req, status)) {
3286 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3287 state->cli->timeout,
3288 state->min_protocol,
3289 state->max_protocol);
3290 if (tevent_req_nomem(subreq, req)) {
3293 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3296 static void cli_start_connection_done(struct tevent_req *subreq)
3298 struct tevent_req *req = tevent_req_callback_data(
3299 subreq, struct tevent_req);
3300 struct cli_start_connection_state *state = tevent_req_data(
3301 req, struct cli_start_connection_state);
3304 status = smbXcli_negprot_recv(subreq);
3305 TALLOC_FREE(subreq);
3306 if (tevent_req_nterror(req, status)) {
3310 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3311 /* Ensure we ask for some initial credits. */
3312 smb2cli_conn_set_max_credits(state->cli->conn,
3313 DEFAULT_SMB2_MAX_CREDITS);
3316 tevent_req_done(req);
3319 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3320 struct cli_state **output_cli)
3322 struct cli_start_connection_state *state = tevent_req_data(
3323 req, struct cli_start_connection_state);
3326 if (tevent_req_is_nterror(req, &status)) {
3329 *output_cli = state->cli;
3331 return NT_STATUS_OK;
3334 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3335 const char *my_name,
3336 const char *dest_host,
3337 const struct sockaddr_storage *dest_ss, int port,
3338 int signing_state, int flags)
3340 struct tevent_context *ev;
3341 struct tevent_req *req;
3342 NTSTATUS status = NT_STATUS_NO_MEMORY;
3344 ev = samba_tevent_context_init(talloc_tos());
3348 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3349 port, signing_state, flags);
3353 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3356 status = cli_start_connection_recv(req, output_cli);
3363 establishes a connection right up to doing tconX, password specified.
3364 @param output_cli A fully initialised cli structure, non-null only on success
3365 @param dest_host The netbios name of the remote host
3366 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3367 @param port (optional) The destination port (0 for default)
3368 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3369 @param service_type The 'type' of serivice.
3370 @param user Username, unix string
3371 @param domain User's domain
3372 @param password User's password, unencrypted unix string.
3375 struct cli_full_connection_state {
3376 struct tevent_context *ev;
3377 const char *service;
3378 const char *service_type;
3381 const char *password;
3384 struct cli_state *cli;
3387 static int cli_full_connection_state_destructor(
3388 struct cli_full_connection_state *s);
3389 static void cli_full_connection_started(struct tevent_req *subreq);
3390 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3391 static void cli_full_connection_done(struct tevent_req *subreq);
3393 struct tevent_req *cli_full_connection_send(
3394 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3395 const char *my_name, const char *dest_host,
3396 const struct sockaddr_storage *dest_ss, int port,
3397 const char *service, const char *service_type,
3398 const char *user, const char *domain,
3399 const char *password, int flags, int signing_state)
3401 struct tevent_req *req, *subreq;
3402 struct cli_full_connection_state *state;
3404 req = tevent_req_create(mem_ctx, &state,
3405 struct cli_full_connection_state);
3409 talloc_set_destructor(state, cli_full_connection_state_destructor);
3412 state->service = service;
3413 state->service_type = service_type;
3415 state->domain = domain;
3416 state->password = password;
3417 state->flags = flags;
3419 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3420 if (state->password == NULL) {
3421 state->password = "";
3424 subreq = cli_start_connection_send(
3425 state, ev, my_name, dest_host, dest_ss, port,
3426 signing_state, flags);
3427 if (tevent_req_nomem(subreq, req)) {
3428 return tevent_req_post(req, ev);
3430 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3434 static int cli_full_connection_state_destructor(
3435 struct cli_full_connection_state *s)
3437 if (s->cli != NULL) {
3438 cli_shutdown(s->cli);
3444 static void cli_full_connection_started(struct tevent_req *subreq)
3446 struct tevent_req *req = tevent_req_callback_data(
3447 subreq, struct tevent_req);
3448 struct cli_full_connection_state *state = tevent_req_data(
3449 req, struct cli_full_connection_state);
3452 status = cli_start_connection_recv(subreq, &state->cli);
3453 TALLOC_FREE(subreq);
3454 if (tevent_req_nterror(req, status)) {
3457 subreq = cli_session_setup_send(
3458 state, state->ev, state->cli, state->user,
3459 state->password, state->pw_len, state->password, state->pw_len,
3461 if (tevent_req_nomem(subreq, req)) {
3464 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3467 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3469 struct tevent_req *req = tevent_req_callback_data(
3470 subreq, struct tevent_req);
3471 struct cli_full_connection_state *state = tevent_req_data(
3472 req, struct cli_full_connection_state);
3475 status = cli_session_setup_recv(subreq);
3476 TALLOC_FREE(subreq);
3478 if (!NT_STATUS_IS_OK(status) &&
3479 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3481 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3483 subreq = cli_session_setup_send(
3484 state, state->ev, state->cli, "", "", 0, "", 0,
3486 if (tevent_req_nomem(subreq, req)) {
3489 tevent_req_set_callback(
3490 subreq, cli_full_connection_sess_set_up, req);
3494 if (tevent_req_nterror(req, status)) {
3498 if (state->service != NULL) {
3499 subreq = cli_tree_connect_send(
3500 state, state->ev, state->cli,
3501 state->service, state->service_type,
3502 state->password, state->pw_len);
3503 if (tevent_req_nomem(subreq, req)) {
3506 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3510 status = cli_init_creds(state->cli, state->user, state->domain,
3512 if (tevent_req_nterror(req, status)) {
3515 tevent_req_done(req);
3518 static void cli_full_connection_done(struct tevent_req *subreq)
3520 struct tevent_req *req = tevent_req_callback_data(
3521 subreq, struct tevent_req);
3522 struct cli_full_connection_state *state = tevent_req_data(
3523 req, struct cli_full_connection_state);
3526 status = cli_tree_connect_recv(subreq);
3527 TALLOC_FREE(subreq);
3528 if (tevent_req_nterror(req, status)) {
3531 status = cli_init_creds(state->cli, state->user, state->domain,
3533 if (tevent_req_nterror(req, status)) {
3536 tevent_req_done(req);
3539 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3540 struct cli_state **output_cli)
3542 struct cli_full_connection_state *state = tevent_req_data(
3543 req, struct cli_full_connection_state);
3546 if (tevent_req_is_nterror(req, &status)) {
3549 *output_cli = state->cli;
3550 talloc_set_destructor(state, NULL);
3551 return NT_STATUS_OK;
3554 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3555 const char *my_name,
3556 const char *dest_host,
3557 const struct sockaddr_storage *dest_ss, int port,
3558 const char *service, const char *service_type,
3559 const char *user, const char *domain,
3560 const char *password, int flags,
3563 struct tevent_context *ev;
3564 struct tevent_req *req;
3565 NTSTATUS status = NT_STATUS_NO_MEMORY;
3567 ev = samba_tevent_context_init(talloc_tos());
3571 req = cli_full_connection_send(
3572 ev, ev, my_name, dest_host, dest_ss, port, service,
3573 service_type, user, domain, password, flags, signing_state);
3577 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3580 status = cli_full_connection_recv(req, output_cli);
3586 /****************************************************************************
3587 Send an old style tcon.
3588 ****************************************************************************/
3589 struct cli_raw_tcon_state {
3593 static void cli_raw_tcon_done(struct tevent_req *subreq);
3595 static struct tevent_req *cli_raw_tcon_send(
3596 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3597 const char *service, const char *pass, const char *dev)
3599 struct tevent_req *req, *subreq;
3600 struct cli_raw_tcon_state *state;
3603 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3608 if (!lp_client_plaintext_auth() && (*pass)) {
3609 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3610 " or 'client ntlmv2 auth = yes'\n"));
3611 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3612 return tevent_req_post(req, ev);
3615 bytes = talloc_array(state, uint8_t, 0);
3616 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3617 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3618 service, strlen(service)+1, NULL);
3619 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3620 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3621 pass, strlen(pass)+1, NULL);
3622 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3623 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3624 dev, strlen(dev)+1, NULL);
3626 if (tevent_req_nomem(bytes, req)) {
3627 return tevent_req_post(req, ev);
3630 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3631 talloc_get_size(bytes), bytes);
3632 if (tevent_req_nomem(subreq, req)) {
3633 return tevent_req_post(req, ev);
3635 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3639 static void cli_raw_tcon_done(struct tevent_req *subreq)
3641 struct tevent_req *req = tevent_req_callback_data(
3642 subreq, struct tevent_req);
3643 struct cli_raw_tcon_state *state = tevent_req_data(
3644 req, struct cli_raw_tcon_state);
3647 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3649 TALLOC_FREE(subreq);
3650 if (tevent_req_nterror(req, status)) {
3653 tevent_req_done(req);
3656 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3657 uint16_t *max_xmit, uint16_t *tid)
3659 struct cli_raw_tcon_state *state = tevent_req_data(
3660 req, struct cli_raw_tcon_state);
3663 if (tevent_req_is_nterror(req, &status)) {
3666 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3667 *tid = SVAL(state->ret_vwv + 1, 0);
3668 return NT_STATUS_OK;
3671 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3672 const char *service, const char *pass, const char *dev,
3673 uint16_t *max_xmit, uint16_t *tid)
3675 struct tevent_context *ev;
3676 struct tevent_req *req;
3677 NTSTATUS status = NT_STATUS_NO_MEMORY;
3679 ev = samba_tevent_context_init(talloc_tos());
3683 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3687 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3690 status = cli_raw_tcon_recv(req, max_xmit, tid);
3696 /* Return a cli_state pointing at the IPC$ share for the given server */
3698 struct cli_state *get_ipc_connect(char *server,
3699 struct sockaddr_storage *server_ss,
3700 const struct user_auth_info *user_info)
3702 struct cli_state *cli;
3704 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3706 if (user_info->use_kerberos) {
3707 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3710 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3711 user_info->username ? user_info->username : "",
3713 user_info->password ? user_info->password : "",
3715 SMB_SIGNING_DEFAULT);
3717 if (NT_STATUS_IS_OK(nt_status)) {
3719 } else if (is_ipaddress(server)) {
3720 /* windows 9* needs a correct NMB name for connections */
3721 fstring remote_name;
3723 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3724 cli = get_ipc_connect(remote_name, server_ss, user_info);
3733 * Given the IP address of a master browser on the network, return its
3734 * workgroup and connect to it.
3736 * This function is provided to allow additional processing beyond what
3737 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3738 * browsers and obtain each master browsers' list of domains (in case the
3739 * first master browser is recently on the network and has not yet
3740 * synchronized with other master browsers and therefore does not yet have the
3741 * entire network browse list)
3744 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3745 struct sockaddr_storage *mb_ip,
3746 const struct user_auth_info *user_info,
3747 char **pp_workgroup_out)
3749 char addr[INET6_ADDRSTRLEN];
3751 struct cli_state *cli;
3752 struct sockaddr_storage server_ss;
3754 *pp_workgroup_out = NULL;
3756 print_sockaddr(addr, sizeof(addr), mb_ip);
3757 DEBUG(99, ("Looking up name of master browser %s\n",
3761 * Do a name status query to find out the name of the master browser.
3762 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3763 * master browser will not respond to a wildcard query (or, at least,
3764 * an NT4 server acting as the domain master browser will not).
3766 * We might be able to use ONLY the query on MSBROWSE, but that's not
3767 * yet been tested with all Windows versions, so until it is, leave
3768 * the original wildcard query as the first choice and fall back to
3769 * MSBROWSE if the wildcard query fails.
3771 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3772 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3774 DEBUG(99, ("Could not retrieve name status for %s\n",
3779 if (!find_master_ip(name, &server_ss)) {
3780 DEBUG(99, ("Could not find master ip for %s\n", name));
3784 *pp_workgroup_out = talloc_strdup(ctx, name);
3786 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3788 print_sockaddr(addr, sizeof(addr), &server_ss);
3789 cli = get_ipc_connect(addr, &server_ss, user_info);
3795 * Return the IP address and workgroup of a master browser on the network, and
3799 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3800 const struct user_auth_info *user_info,
3801 char **pp_workgroup_out)
3803 struct sockaddr_storage *ip_list;
3804 struct cli_state *cli;
3808 *pp_workgroup_out = NULL;
3810 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3812 /* Go looking for workgroups by broadcasting on the local network */
3814 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3816 if (!NT_STATUS_IS_OK(status)) {
3817 DEBUG(99, ("No master browsers responded: %s\n",
3818 nt_errstr(status)));
3822 for (i = 0; i < count; i++) {
3823 char addr[INET6_ADDRSTRLEN];
3824 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3825 DEBUG(99, ("Found master browser %s\n", addr));
3827 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3828 user_info, pp_workgroup_out);