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, 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 tevent_req_done(req);
289 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
291 return tevent_req_simple_recv_ntstatus(req);
294 /****************************************************************************
295 Work out suitable capabilities to offer the server.
296 ****************************************************************************/
298 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
299 uint32_t sesssetup_capabilities)
301 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
304 * We only send capabilities based on the mask for:
305 * - client only flags
306 * - flags used in both directions
308 * We do not echo the server only flags, except some legacy flags.
310 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
311 * CAP_LARGE_WRITEX in order to allow us to do large reads
312 * against old Samba releases (<= 3.6.x).
314 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
317 * Session Setup specific flags CAP_DYNAMIC_REAUTH
318 * and CAP_EXTENDED_SECURITY are passed by the caller.
319 * We need that in order to do guest logins even if
320 * CAP_EXTENDED_SECURITY is negotiated.
322 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
323 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
324 client_capabilities |= sesssetup_capabilities;
326 return client_capabilities;
329 /****************************************************************************
330 Do a NT1 guest session setup.
331 ****************************************************************************/
333 struct cli_session_setup_guest_state {
334 struct cli_state *cli;
339 static void cli_session_setup_guest_done(struct tevent_req *subreq);
341 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
342 struct tevent_context *ev,
343 struct cli_state *cli,
344 struct tevent_req **psmbreq)
346 struct tevent_req *req, *subreq;
347 struct cli_session_setup_guest_state *state;
351 req = tevent_req_create(mem_ctx, &state,
352 struct cli_session_setup_guest_state);
359 SCVAL(vwv+0, 0, 0xFF);
362 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
364 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
365 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
370 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
372 bytes = talloc_array(state, uint8_t, 0);
374 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
376 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
379 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
386 state->bytes.iov_base = (void *)bytes;
387 state->bytes.iov_len = talloc_get_size(bytes);
389 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
390 vwv, 1, &state->bytes);
391 if (subreq == NULL) {
395 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
400 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
401 struct tevent_context *ev,
402 struct cli_state *cli)
404 struct tevent_req *req, *subreq;
407 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
412 status = smb1cli_req_chain_submit(&subreq, 1);
413 if (!NT_STATUS_IS_OK(status)) {
414 tevent_req_nterror(req, status);
415 return tevent_req_post(req, ev);
420 static void cli_session_setup_guest_done(struct tevent_req *subreq)
422 struct tevent_req *req = tevent_req_callback_data(
423 subreq, struct tevent_req);
424 struct cli_session_setup_guest_state *state = tevent_req_data(
425 req, struct cli_session_setup_guest_state);
426 struct cli_state *cli = state->cli;
437 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
440 if (!NT_STATUS_IS_OK(status)) {
441 tevent_req_nterror(req, status);
445 inhdr = in + NBT_HDR_SIZE;
448 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
449 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
451 status = smb_bytes_talloc_string(cli,
458 if (!NT_STATUS_IS_OK(status)) {
459 tevent_req_nterror(req, status);
464 status = smb_bytes_talloc_string(cli,
471 if (!NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
477 status = smb_bytes_talloc_string(cli,
484 if (!NT_STATUS_IS_OK(status)) {
485 tevent_req_nterror(req, status);
490 tevent_req_done(req);
493 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
495 return tevent_req_simple_recv_ntstatus(req);
498 /****************************************************************************
499 Do a NT1 plaintext session setup.
500 ****************************************************************************/
502 struct cli_session_setup_plain_state {
503 struct cli_state *cli;
508 static void cli_session_setup_plain_done(struct tevent_req *subreq);
510 static struct tevent_req *cli_session_setup_plain_send(
511 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
512 struct cli_state *cli,
513 const char *user, const char *pass, const char *workgroup)
515 struct tevent_req *req, *subreq;
516 struct cli_session_setup_plain_state *state;
522 req = tevent_req_create(mem_ctx, &state,
523 struct cli_session_setup_plain_state);
531 SCVAL(vwv+0, 0, 0xff);
534 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
536 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
537 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
542 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
544 bytes = talloc_array(state, uint8_t, 0);
545 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
547 if (tevent_req_nomem(bytes, req)) {
548 return tevent_req_post(req, ev);
550 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
552 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
553 user, strlen(user)+1, NULL);
554 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
555 workgroup, strlen(workgroup)+1, NULL);
556 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
559 version = talloc_asprintf(talloc_tos(), "Samba %s",
560 samba_version_string());
561 if (tevent_req_nomem(version, req)){
562 return tevent_req_post(req, ev);
564 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
565 version, strlen(version)+1, NULL);
566 TALLOC_FREE(version);
568 if (tevent_req_nomem(bytes, req)) {
569 return tevent_req_post(req, ev);
572 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 0, 13, vwv,
573 talloc_get_size(bytes), bytes);
574 if (tevent_req_nomem(subreq, req)) {
575 return tevent_req_post(req, ev);
577 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
581 static void cli_session_setup_plain_done(struct tevent_req *subreq)
583 struct tevent_req *req = tevent_req_callback_data(
584 subreq, struct tevent_req);
585 struct cli_session_setup_plain_state *state = tevent_req_data(
586 req, struct cli_session_setup_plain_state);
587 struct cli_state *cli = state->cli;
598 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
601 if (tevent_req_nterror(req, status)) {
605 inhdr = in + NBT_HDR_SIZE;
608 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
609 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
611 status = smb_bytes_talloc_string(cli,
618 if (!NT_STATUS_IS_OK(status)) {
619 tevent_req_nterror(req, status);
624 status = smb_bytes_talloc_string(cli,
631 if (!NT_STATUS_IS_OK(status)) {
632 tevent_req_nterror(req, status);
637 status = smb_bytes_talloc_string(cli,
644 if (!NT_STATUS_IS_OK(status)) {
645 tevent_req_nterror(req, status);
650 tevent_req_done(req);
653 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
655 return tevent_req_simple_recv_ntstatus(req);
658 /****************************************************************************
659 do a NT1 NTLM/LM encrypted session setup - for when extended security
661 @param cli client state to create do session setup on
663 @param pass *either* cleartext password (passlen !=24) or LM response.
664 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
665 @param workgroup The user's domain.
666 ****************************************************************************/
668 struct cli_session_setup_nt1_state {
669 struct cli_state *cli;
672 DATA_BLOB session_key;
676 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
678 static struct tevent_req *cli_session_setup_nt1_send(
679 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
680 struct cli_state *cli, const char *user,
681 const char *pass, size_t passlen,
682 const char *ntpass, size_t ntpasslen,
683 const char *workgroup)
685 struct tevent_req *req, *subreq;
686 struct cli_session_setup_nt1_state *state;
687 DATA_BLOB lm_response = data_blob_null;
688 DATA_BLOB nt_response = data_blob_null;
689 DATA_BLOB session_key = data_blob_null;
692 char *workgroup_upper;
694 req = tevent_req_create(mem_ctx, &state,
695 struct cli_session_setup_nt1_state);
704 /* do nothing - guest login */
705 } else if (passlen != 24) {
706 if (lp_client_ntlmv2_auth()) {
707 DATA_BLOB server_chal;
708 DATA_BLOB names_blob;
711 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
715 * note that the 'workgroup' here is a best
716 * guess - we don't know the server's domain
717 * at this point. Windows clients also don't
720 names_blob = NTLMv2_generate_names_blob(
721 NULL, NULL, workgroup);
723 if (tevent_req_nomem(names_blob.data, req)) {
724 return tevent_req_post(req, ev);
727 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
728 &server_chal, &names_blob,
729 &lm_response, &nt_response,
730 NULL, &session_key)) {
731 data_blob_free(&names_blob);
733 req, NT_STATUS_ACCESS_DENIED);
734 return tevent_req_post(req, ev);
736 data_blob_free(&names_blob);
740 E_md4hash(pass, nt_hash);
743 nt_response = data_blob_null;
745 nt_response = data_blob(NULL, 24);
746 if (tevent_req_nomem(nt_response.data, req)) {
747 return tevent_req_post(req, ev);
750 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
753 /* non encrypted password supplied. Ignore ntpass. */
754 if (lp_client_lanman_auth()) {
756 lm_response = data_blob(NULL, 24);
757 if (tevent_req_nomem(lm_response.data, req)) {
758 return tevent_req_post(req, ev);
761 if (!SMBencrypt(pass,
762 smb1cli_conn_server_challenge(cli->conn),
765 * Oops, the LM response is
766 * invalid, just put the NT
767 * response there instead
769 data_blob_free(&lm_response);
770 lm_response = data_blob(
776 * LM disabled, place NT# in LM field
779 lm_response = data_blob(
780 nt_response.data, nt_response.length);
783 if (tevent_req_nomem(lm_response.data, req)) {
784 return tevent_req_post(req, ev);
787 session_key = data_blob(NULL, 16);
788 if (tevent_req_nomem(session_key.data, req)) {
789 return tevent_req_post(req, ev);
792 E_deshash(pass, session_key.data);
793 memset(&session_key.data[8], '\0', 8);
795 SMBsesskeygen_ntv1(nt_hash, session_key.data);
799 /* pre-encrypted password supplied. Only used for
800 security=server, can't do
801 signing because we don't have original key */
803 lm_response = data_blob(pass, passlen);
804 if (tevent_req_nomem(lm_response.data, req)) {
805 return tevent_req_post(req, ev);
808 nt_response = data_blob(ntpass, ntpasslen);
809 if (tevent_req_nomem(nt_response.data, req)) {
810 return tevent_req_post(req, ev);
815 state->response = data_blob_talloc(
816 state, lm_response.data, lm_response.length);
818 state->response = data_blob_talloc(
819 state, nt_response.data, nt_response.length);
821 if (tevent_req_nomem(state->response.data, req)) {
822 return tevent_req_post(req, ev);
825 if (session_key.data) {
826 state->session_key = data_blob_talloc(
827 state, session_key.data, session_key.length);
828 if (tevent_req_nomem(state->session_key.data, req)) {
829 return tevent_req_post(req, ev);
832 data_blob_free(&session_key);
834 SCVAL(vwv+0, 0, 0xff);
837 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
839 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
840 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
841 SSVAL(vwv+7, 0, lm_response.length);
842 SSVAL(vwv+8, 0, nt_response.length);
845 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
847 bytes = talloc_array(state, uint8_t,
848 lm_response.length + nt_response.length);
849 if (tevent_req_nomem(bytes, req)) {
850 return tevent_req_post(req, ev);
852 if (lm_response.length != 0) {
853 memcpy(bytes, lm_response.data, lm_response.length);
855 if (nt_response.length != 0) {
856 memcpy(bytes + lm_response.length,
857 nt_response.data, nt_response.length);
859 data_blob_free(&lm_response);
860 data_blob_free(&nt_response);
862 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
863 user, strlen(user)+1, NULL);
866 * Upper case here might help some NTLMv2 implementations
868 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
869 if (tevent_req_nomem(workgroup_upper, req)) {
870 return tevent_req_post(req, ev);
872 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
873 workgroup_upper, strlen(workgroup_upper)+1,
875 TALLOC_FREE(workgroup_upper);
877 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
878 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
879 if (tevent_req_nomem(bytes, req)) {
880 return tevent_req_post(req, ev);
883 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 0, 13, vwv,
884 talloc_get_size(bytes), bytes);
885 if (tevent_req_nomem(subreq, req)) {
886 return tevent_req_post(req, ev);
888 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
892 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
894 struct tevent_req *req = tevent_req_callback_data(
895 subreq, struct tevent_req);
896 struct cli_session_setup_nt1_state *state = tevent_req_data(
897 req, struct cli_session_setup_nt1_state);
898 struct cli_state *cli = state->cli;
909 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
912 if (!NT_STATUS_IS_OK(status)) {
913 tevent_req_nterror(req, status);
917 inhdr = in + NBT_HDR_SIZE;
920 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
921 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
923 status = smb_bytes_talloc_string(cli,
929 if (!NT_STATUS_IS_OK(status)) {
930 tevent_req_nterror(req, status);
935 status = smb_bytes_talloc_string(cli,
941 if (!NT_STATUS_IS_OK(status)) {
942 tevent_req_nterror(req, status);
947 status = smb_bytes_talloc_string(cli,
953 if (!NT_STATUS_IS_OK(status)) {
954 tevent_req_nterror(req, status);
959 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
960 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
961 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
964 if (state->session_key.data) {
965 struct smbXcli_session *session = state->cli->smb1.session;
967 status = smb1cli_session_set_session_key(session,
969 if (tevent_req_nterror(req, status)) {
973 tevent_req_done(req);
976 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
978 return tevent_req_simple_recv_ntstatus(req);
981 /* The following is calculated from :
983 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
984 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
988 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
990 struct cli_sesssetup_blob_state {
991 struct tevent_context *ev;
992 struct cli_state *cli;
994 uint16_t max_blob_size;
999 struct iovec *recv_iov;
1006 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1007 struct tevent_req **psubreq);
1008 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1010 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1011 struct tevent_context *ev,
1012 struct cli_state *cli,
1015 struct tevent_req *req, *subreq;
1016 struct cli_sesssetup_blob_state *state;
1017 uint32_t usable_space;
1019 req = tevent_req_create(mem_ctx, &state,
1020 struct cli_sesssetup_blob_state);
1028 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1029 usable_space = UINT16_MAX;
1031 usable_space = cli_state_available_size(cli,
1032 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1035 if (usable_space == 0) {
1036 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1037 "(not possible to send %u bytes)\n",
1038 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1039 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1040 return tevent_req_post(req, ev);
1042 state->max_blob_size = MIN(usable_space, 0xFFFF);
1044 if (!cli_sesssetup_blob_next(state, &subreq)) {
1045 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1046 return tevent_req_post(req, ev);
1048 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1052 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1053 struct tevent_req **psubreq)
1055 struct tevent_req *subreq;
1058 thistime = MIN(state->blob.length, state->max_blob_size);
1060 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1062 state->smb2_blob.data = state->blob.data;
1063 state->smb2_blob.length = thistime;
1065 state->blob.data += thistime;
1066 state->blob.length -= thistime;
1068 subreq = smb2cli_session_setup_send(state, state->ev,
1070 state->cli->timeout,
1071 state->cli->smb2.session,
1073 SMB2_CAP_DFS, /* in_capabilities */
1075 0, /* in_previous_session_id */
1077 if (subreq == NULL) {
1084 SCVAL(state->vwv+0, 0, 0xFF);
1085 SCVAL(state->vwv+0, 1, 0);
1086 SSVAL(state->vwv+1, 0, 0);
1087 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1088 SSVAL(state->vwv+3, 0, 2);
1089 SSVAL(state->vwv+4, 0, 1);
1090 SIVAL(state->vwv+5, 0, 0);
1092 SSVAL(state->vwv+7, 0, thistime);
1094 SSVAL(state->vwv+8, 0, 0);
1095 SSVAL(state->vwv+9, 0, 0);
1096 SIVAL(state->vwv+10, 0,
1097 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1099 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1101 if (state->buf == NULL) {
1104 state->blob.data += thistime;
1105 state->blob.length -= thistime;
1107 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1109 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1111 if (state->buf == NULL) {
1114 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0, 0,
1116 talloc_get_size(state->buf), state->buf);
1117 if (subreq == NULL) {
1124 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1126 struct tevent_req *req = tevent_req_callback_data(
1127 subreq, struct tevent_req);
1128 struct cli_sesssetup_blob_state *state = tevent_req_data(
1129 req, struct cli_sesssetup_blob_state);
1130 struct cli_state *cli = state->cli;
1137 uint16_t blob_length;
1142 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1143 status = smb2cli_session_setup_recv(subreq, state,
1147 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1148 &num_bytes, &bytes);
1149 TALLOC_FREE(state->buf);
1151 TALLOC_FREE(subreq);
1152 if (!NT_STATUS_IS_OK(status)
1153 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1154 tevent_req_nterror(req, status);
1158 state->status = status;
1160 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1165 inhdr = in + NBT_HDR_SIZE;
1166 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1167 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
1169 blob_length = SVAL(vwv+3, 0);
1170 if (blob_length > num_bytes) {
1171 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1174 state->ret_blob = data_blob_const(bytes, blob_length);
1176 p = bytes + blob_length;
1178 status = smb_bytes_talloc_string(cli,
1185 if (!NT_STATUS_IS_OK(status)) {
1186 tevent_req_nterror(req, status);
1191 status = smb_bytes_talloc_string(cli,
1198 if (!NT_STATUS_IS_OK(status)) {
1199 tevent_req_nterror(req, status);
1204 status = smb_bytes_talloc_string(cli,
1206 &cli->server_domain,
1211 if (!NT_STATUS_IS_OK(status)) {
1212 tevent_req_nterror(req, status);
1218 if (state->blob.length != 0) {
1222 if (!cli_sesssetup_blob_next(state, &subreq)) {
1223 tevent_req_oom(req);
1226 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1229 tevent_req_done(req);
1232 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1233 TALLOC_CTX *mem_ctx,
1236 struct iovec **precv_iov)
1238 struct cli_sesssetup_blob_state *state = tevent_req_data(
1239 req, struct cli_sesssetup_blob_state);
1242 struct iovec *recv_iov;
1244 if (tevent_req_is_nterror(req, &status)) {
1245 TALLOC_FREE(state->cli->smb2.session);
1246 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1250 inbuf = talloc_move(mem_ctx, &state->inbuf);
1251 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1252 if (pblob != NULL) {
1253 *pblob = state->ret_blob;
1255 if (pinbuf != NULL) {
1258 if (precv_iov != NULL) {
1259 *precv_iov = recv_iov;
1261 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1262 return state->status;
1267 /****************************************************************************
1268 Use in-memory credentials cache
1269 ****************************************************************************/
1271 static void use_in_memory_ccache(void) {
1272 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1275 #endif /* HAVE_KRB5 */
1277 /****************************************************************************
1278 Do a spnego/NTLMSSP encrypted session setup.
1279 ****************************************************************************/
1281 struct cli_session_setup_gensec_state {
1282 struct tevent_context *ev;
1283 struct cli_state *cli;
1284 struct auth_generic_state *auth_generic;
1288 struct iovec *recv_iov;
1292 DATA_BLOB session_key;
1295 static int cli_session_setup_gensec_state_destructor(
1296 struct cli_session_setup_gensec_state *state)
1298 TALLOC_FREE(state->auth_generic);
1299 data_blob_clear_free(&state->session_key);
1303 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
1304 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
1305 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
1306 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
1307 static void cli_session_setup_gensec_ready(struct tevent_req *req);
1309 static struct tevent_req *cli_session_setup_gensec_send(
1310 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1311 const char *user, const char *pass, const char *domain,
1312 enum credentials_use_kerberos krb5_state,
1313 const char *target_service,
1314 const char *target_hostname,
1315 const char *target_principal)
1317 struct tevent_req *req;
1318 struct cli_session_setup_gensec_state *state;
1320 bool use_spnego_principal = lp_client_use_spnego_principal();
1322 req = tevent_req_create(mem_ctx, &state,
1323 struct cli_session_setup_gensec_state);
1330 talloc_set_destructor(
1331 state, cli_session_setup_gensec_state_destructor);
1333 if (user == NULL || strlen(user) == 0) {
1334 if (pass != NULL && strlen(pass) == 0) {
1336 * some callers pass "" as no password
1338 * gensec only handles NULL as no password.
1344 status = auth_generic_client_prepare(state, &state->auth_generic);
1345 if (tevent_req_nterror(req, status)) {
1346 return tevent_req_post(req, ev);
1349 gensec_want_feature(state->auth_generic->gensec_security,
1350 GENSEC_FEATURE_SESSION_KEY);
1351 if (cli->use_ccache) {
1352 gensec_want_feature(state->auth_generic->gensec_security,
1353 GENSEC_FEATURE_NTLM_CCACHE);
1354 if (pass != NULL && strlen(pass) == 0) {
1356 * some callers pass "" as no password
1358 * GENSEC_FEATURE_NTLM_CCACHE only handles
1359 * NULL as no password.
1365 status = auth_generic_set_username(state->auth_generic, user);
1366 if (tevent_req_nterror(req, status)) {
1367 return tevent_req_post(req, ev);
1370 status = auth_generic_set_domain(state->auth_generic, domain);
1371 if (tevent_req_nterror(req, status)) {
1372 return tevent_req_post(req, ev);
1375 if (cli->pw_nt_hash) {
1376 struct samr_Password nt_hash;
1381 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1382 return tevent_req_post(req, ev);
1385 converted = strhex_to_str((char *)nt_hash.hash,
1386 sizeof(nt_hash.hash),
1387 pass, strlen(pass));
1388 if (converted != sizeof(nt_hash.hash)) {
1389 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1390 return tevent_req_post(req, ev);
1393 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
1394 &nt_hash, CRED_SPECIFIED);
1396 tevent_req_oom(req);
1397 return tevent_req_post(req, ev);
1400 status = auth_generic_set_password(state->auth_generic, pass);
1401 if (tevent_req_nterror(req, status)) {
1402 return tevent_req_post(req, ev);
1406 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
1409 if (krb5_state == CRED_DONT_USE_KERBEROS) {
1410 use_spnego_principal = false;
1413 if (target_service != NULL) {
1414 status = gensec_set_target_service(
1415 state->auth_generic->gensec_security,
1417 if (tevent_req_nterror(req, status)) {
1418 return tevent_req_post(req, ev);
1422 if (target_hostname != NULL) {
1423 status = gensec_set_target_hostname(
1424 state->auth_generic->gensec_security,
1426 if (tevent_req_nterror(req, status)) {
1427 return tevent_req_post(req, ev);
1431 if (target_principal != NULL) {
1432 status = gensec_set_target_principal(
1433 state->auth_generic->gensec_security,
1435 if (tevent_req_nterror(req, status)) {
1436 return tevent_req_post(req, ev);
1438 use_spnego_principal = false;
1439 } else if (target_service != NULL && target_hostname != NULL) {
1440 use_spnego_principal = false;
1443 if (use_spnego_principal) {
1445 b = smbXcli_conn_server_gss_blob(cli->conn);
1447 state->blob_in = *b;
1451 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
1453 status = auth_generic_client_start(state->auth_generic,
1455 if (tevent_req_nterror(req, status)) {
1456 return tevent_req_post(req, ev);
1459 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1460 state->cli->smb2.session = smbXcli_session_create(cli,
1462 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1463 return tevent_req_post(req, ev);
1467 cli_session_setup_gensec_local_next(req);
1468 if (!tevent_req_is_in_progress(req)) {
1469 return tevent_req_post(req, ev);
1475 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
1477 struct cli_session_setup_gensec_state *state =
1478 tevent_req_data(req,
1479 struct cli_session_setup_gensec_state);
1480 struct tevent_req *subreq = NULL;
1482 if (state->local_ready) {
1483 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1487 subreq = gensec_update_send(state, state->ev,
1488 state->auth_generic->gensec_security,
1490 if (tevent_req_nomem(subreq, req)) {
1493 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1496 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1498 struct tevent_req *req =
1499 tevent_req_callback_data(subreq,
1501 struct cli_session_setup_gensec_state *state =
1502 tevent_req_data(req,
1503 struct cli_session_setup_gensec_state);
1506 status = gensec_update_recv(subreq, state, &state->blob_out);
1507 TALLOC_FREE(subreq);
1508 state->blob_in = data_blob_null;
1509 if (!NT_STATUS_IS_OK(status) &&
1510 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1512 tevent_req_nterror(req, status);
1516 if (NT_STATUS_IS_OK(status)) {
1517 state->local_ready = true;
1520 if (state->local_ready && state->remote_ready) {
1521 cli_session_setup_gensec_ready(req);
1525 cli_session_setup_gensec_remote_next(req);
1528 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1530 struct cli_session_setup_gensec_state *state =
1531 tevent_req_data(req,
1532 struct cli_session_setup_gensec_state);
1533 struct tevent_req *subreq = NULL;
1535 if (state->remote_ready) {
1536 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1540 subreq = cli_sesssetup_blob_send(state, state->ev,
1541 state->cli, state->blob_out);
1542 if (tevent_req_nomem(subreq, req)) {
1545 tevent_req_set_callback(subreq,
1546 cli_session_setup_gensec_remote_done,
1550 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1552 struct tevent_req *req =
1553 tevent_req_callback_data(subreq,
1555 struct cli_session_setup_gensec_state *state =
1556 tevent_req_data(req,
1557 struct cli_session_setup_gensec_state);
1560 TALLOC_FREE(state->inbuf);
1561 TALLOC_FREE(state->recv_iov);
1563 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1564 &state->inbuf, &state->recv_iov);
1565 TALLOC_FREE(subreq);
1566 data_blob_free(&state->blob_out);
1567 if (!NT_STATUS_IS_OK(status) &&
1568 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1570 tevent_req_nterror(req, status);
1574 if (NT_STATUS_IS_OK(status)) {
1575 struct smbXcli_session *session = NULL;
1576 bool is_guest = false;
1578 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1579 session = state->cli->smb2.session;
1581 session = state->cli->smb1.session;
1584 is_guest = smbXcli_session_is_guest(session);
1587 * We can't finish the gensec handshake, we don't
1588 * have a negotiated session key.
1590 * So just pretend we are completely done.
1592 * Note that smbXcli_session_is_guest()
1593 * always returns false if we require signing.
1595 state->blob_in = data_blob_null;
1596 state->local_ready = true;
1599 state->remote_ready = true;
1602 if (state->local_ready && state->remote_ready) {
1603 cli_session_setup_gensec_ready(req);
1607 cli_session_setup_gensec_local_next(req);
1610 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1612 struct cli_session_setup_gensec_state *state =
1613 tevent_req_data(req,
1614 struct cli_session_setup_gensec_state);
1615 const char *server_domain = NULL;
1618 if (state->blob_in.length != 0) {
1619 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1623 if (state->blob_out.length != 0) {
1624 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1629 * gensec_ntlmssp_server_domain() returns NULL
1630 * if NTLMSSP is not used.
1632 * We can remove this later
1633 * and leave the server domain empty for SMB2 and above
1634 * in future releases.
1636 server_domain = gensec_ntlmssp_server_domain(
1637 state->auth_generic->gensec_security);
1639 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1640 TALLOC_FREE(state->cli->server_domain);
1641 state->cli->server_domain = talloc_strdup(state->cli,
1643 if (state->cli->server_domain == NULL) {
1644 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1649 if (state->is_anonymous) {
1651 * Windows server does not set the
1652 * SMB2_SESSION_FLAG_IS_NULL flag.
1654 * This fix makes sure we do not try
1655 * to verify a signature on the final
1656 * session setup response.
1658 tevent_req_done(req);
1662 status = gensec_session_key(state->auth_generic->gensec_security,
1663 state, &state->session_key);
1664 if (tevent_req_nterror(req, status)) {
1668 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1669 struct smbXcli_session *session = state->cli->smb2.session;
1671 status = smb2cli_session_set_session_key(session,
1674 if (tevent_req_nterror(req, status)) {
1678 struct smbXcli_session *session = state->cli->smb1.session;
1681 status = smb1cli_session_set_session_key(session,
1682 state->session_key);
1683 if (tevent_req_nterror(req, status)) {
1687 active = smb1cli_conn_activate_signing(state->cli->conn,
1693 ok = smb1cli_conn_check_signing(state->cli->conn,
1696 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1702 tevent_req_done(req);
1705 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1707 struct cli_session_setup_gensec_state *state =
1708 tevent_req_data(req,
1709 struct cli_session_setup_gensec_state);
1712 if (tevent_req_is_nterror(req, &status)) {
1713 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1716 return NT_STATUS_OK;
1721 static char *cli_session_setup_get_principal(
1722 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1723 const char *remote_name, const char *dest_realm)
1725 char *principal = NULL;
1727 if (!lp_client_use_spnego_principal() ||
1728 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1729 spnego_principal = NULL;
1731 if (spnego_principal != NULL) {
1732 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1733 "principal %s\n", spnego_principal));
1734 return talloc_strdup(mem_ctx, spnego_principal);
1736 if (is_ipaddress(remote_name) ||
1737 strequal(remote_name, STAR_SMBSERVER)) {
1741 DEBUG(3, ("cli_session_setup_spnego: using target "
1742 "hostname not SPNEGO principal\n"));
1745 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1746 if (realm == NULL) {
1749 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1750 remote_name, realm);
1754 smb_krb5_get_principal_from_service_hostname(talloc_tos(),
1759 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1760 principal ? principal : "<null>"));
1766 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1767 const char *principal)
1771 account = talloc_strdup(mem_ctx, principal);
1772 if (account == NULL) {
1775 p = strchr_m(account, '@');
1782 /****************************************************************************
1783 Do a spnego encrypted session setup.
1785 user_domain: The shortname of the domain the user/machine is a member of.
1786 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1787 ****************************************************************************/
1789 struct cli_session_setup_spnego_state {
1790 struct tevent_context *ev;
1791 struct cli_state *cli;
1792 const char *target_hostname;
1794 const char *account;
1796 const char *user_domain;
1797 const char *dest_realm;
1802 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1805 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1807 static struct tevent_req *cli_session_setup_spnego_send(
1808 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1809 const char *user, const char *pass, const char *user_domain)
1811 struct tevent_req *req, *subreq;
1812 struct cli_session_setup_spnego_state *state;
1813 char *principal = NULL;
1814 char *OIDs[ASN1_MAX_OIDS];
1816 const char *dest_realm = cli_state_remote_realm(cli);
1817 const DATA_BLOB *server_blob;
1819 req = tevent_req_create(mem_ctx, &state,
1820 struct cli_session_setup_spnego_state);
1828 state->user_domain = user_domain;
1829 state->dest_realm = dest_realm;
1831 state->account = cli_session_setup_get_account(state, user);
1832 if (tevent_req_nomem(state->account, req)) {
1833 return tevent_req_post(req, ev);
1836 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1837 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1839 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1840 (unsigned long)server_blob->length));
1842 /* the server might not even do spnego */
1843 if (server_blob->length == 0) {
1844 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1849 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1852 /* The server sent us the first part of the SPNEGO exchange in the
1853 * negprot reply. It is WRONG to depend on the principal sent in the
1854 * negprot reply, but right now we do it. If we don't receive one,
1855 * we try to best guess, then fall back to NTLM. */
1856 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1857 &principal, NULL) ||
1859 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1860 tevent_req_done(req);
1861 return tevent_req_post(req, ev);
1864 /* make sure the server understands kerberos */
1865 for (i=0;OIDs[i];i++) {
1867 DEBUG(3,("got OID=%s\n", OIDs[i]));
1869 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1870 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1871 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1872 cli->got_kerberos_mechanism = True;
1874 talloc_free(OIDs[i]);
1877 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
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,
2014 const char *workgroup)
2016 struct tevent_req *req, *subreq;
2017 struct cli_session_setup_state *state;
2020 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2021 bool use_spnego = false;
2025 passlen = strlen(pass);
2028 * If we have a realm password
2029 * we include the terminating '\0'
2035 req = tevent_req_create(mem_ctx, &state,
2036 struct cli_session_setup_state);
2042 user2 = talloc_strdup(state, user);
2044 user2 = talloc_strdup(state, "");
2046 if (user2 == NULL) {
2047 tevent_req_oom(req);
2048 return tevent_req_post(req, ev);
2055 /* allow for workgroups as part of the username */
2056 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2057 (p=strchr_m(user2,*lp_winbind_separator()))) {
2060 if (!strupper_m(user2)) {
2061 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2062 return tevent_req_post(req, ev);
2068 * Now work out what sort of session setup we are going to
2069 * do. I have split this into separate functions to make the flow a bit
2070 * easier to understand (tridge).
2072 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2074 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2076 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2078 * if the server supports extended security then use SPNEGO
2079 * even for anonymous connections.
2087 subreq = cli_session_setup_spnego_send(
2088 state, ev, cli, user, pass, workgroup);
2089 if (tevent_req_nomem(subreq, req)) {
2090 return tevent_req_post(req, ev);
2092 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2097 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2099 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
2100 * this step against older servers.
2102 tevent_req_done(req);
2103 return tevent_req_post(req, ev);
2106 /* if its an older server then we have to use the older request format */
2108 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2109 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2110 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2111 " or 'client ntlmv2 auth = yes'\n"));
2112 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2113 return tevent_req_post(req, ev);
2116 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2117 !lp_client_plaintext_auth() && (*pass)) {
2118 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2119 " or 'client ntlmv2 auth = yes'\n"));
2120 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2121 return tevent_req_post(req, ev);
2124 subreq = cli_session_setup_lanman2_send(
2125 state, ev, cli, user, pass, passlen, workgroup);
2126 if (tevent_req_nomem(subreq, req)) {
2127 return tevent_req_post(req, ev);
2129 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2134 /* if no user is supplied then we have to do an anonymous connection.
2135 passwords are ignored */
2137 if (!user || !*user) {
2138 subreq = cli_session_setup_guest_send(state, ev, cli);
2139 if (tevent_req_nomem(subreq, req)) {
2140 return tevent_req_post(req, ev);
2142 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2147 /* if the server is share level then send a plaintext null
2148 password at this point. The password is sent in the tree
2151 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2152 subreq = cli_session_setup_plain_send(
2153 state, ev, cli, user, "", workgroup);
2154 if (tevent_req_nomem(subreq, req)) {
2155 return tevent_req_post(req, ev);
2157 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2162 /* if the server doesn't support encryption then we have to use
2163 plaintext. The second password is ignored */
2165 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2166 if (!lp_client_plaintext_auth() && (*pass)) {
2167 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2168 " or 'client ntlmv2 auth = yes'\n"));
2169 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2170 return tevent_req_post(req, ev);
2172 subreq = cli_session_setup_plain_send(
2173 state, ev, cli, user, pass, workgroup);
2174 if (tevent_req_nomem(subreq, req)) {
2175 return tevent_req_post(req, ev);
2177 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2183 /* otherwise do a NT1 style session setup */
2184 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2186 * Don't send an NTLMv2 response without NTLMSSP
2187 * if we want to use spnego support
2189 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2190 " but 'client use spnego = yes"
2191 " and 'client ntlmv2 auth = yes'\n"));
2192 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2193 return tevent_req_post(req, ev);
2196 subreq = cli_session_setup_nt1_send(
2197 state, ev, cli, user, pass, passlen, pass, passlen,
2199 if (tevent_req_nomem(subreq, req)) {
2200 return tevent_req_post(req, ev);
2202 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2207 tevent_req_done(req);
2208 return tevent_req_post(req, ev);
2211 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2213 struct tevent_req *req = tevent_req_callback_data(
2214 subreq, struct tevent_req);
2217 status = cli_session_setup_lanman2_recv(subreq);
2218 TALLOC_FREE(subreq);
2219 if (!NT_STATUS_IS_OK(status)) {
2220 tevent_req_nterror(req, status);
2223 tevent_req_done(req);
2226 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2228 struct tevent_req *req = tevent_req_callback_data(
2229 subreq, struct tevent_req);
2232 status = cli_session_setup_spnego_recv(subreq);
2233 TALLOC_FREE(subreq);
2234 if (!ADS_ERR_OK(status)) {
2235 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2236 tevent_req_nterror(req, ads_ntstatus(status));
2239 tevent_req_done(req);
2242 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2244 struct tevent_req *req = tevent_req_callback_data(
2245 subreq, struct tevent_req);
2248 status = cli_session_setup_guest_recv(subreq);
2249 TALLOC_FREE(subreq);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 tevent_req_nterror(req, status);
2254 tevent_req_done(req);
2257 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2259 struct tevent_req *req = tevent_req_callback_data(
2260 subreq, struct tevent_req);
2263 status = cli_session_setup_plain_recv(subreq);
2264 TALLOC_FREE(subreq);
2265 if (!NT_STATUS_IS_OK(status)) {
2266 tevent_req_nterror(req, status);
2269 tevent_req_done(req);
2272 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2274 struct tevent_req *req = tevent_req_callback_data(
2275 subreq, struct tevent_req);
2278 status = cli_session_setup_nt1_recv(subreq);
2279 TALLOC_FREE(subreq);
2280 if (!NT_STATUS_IS_OK(status)) {
2281 DEBUG(3, ("cli_session_setup: NT1 session setup "
2282 "failed: %s\n", nt_errstr(status)));
2283 tevent_req_nterror(req, status);
2286 tevent_req_done(req);
2289 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2291 return tevent_req_simple_recv_ntstatus(req);
2294 NTSTATUS cli_session_setup(struct cli_state *cli,
2297 const char *workgroup)
2299 struct tevent_context *ev;
2300 struct tevent_req *req;
2301 NTSTATUS status = NT_STATUS_NO_MEMORY;
2303 if (smbXcli_conn_has_async_calls(cli->conn)) {
2304 return NT_STATUS_INVALID_PARAMETER;
2306 ev = samba_tevent_context_init(talloc_tos());
2310 req = cli_session_setup_send(ev, ev, cli, user, pass, workgroup);
2314 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2317 status = cli_session_setup_recv(req);
2323 /****************************************************************************
2325 *****************************************************************************/
2327 struct cli_ulogoff_state {
2328 struct cli_state *cli;
2332 static void cli_ulogoff_done(struct tevent_req *subreq);
2334 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2335 struct tevent_context *ev,
2336 struct cli_state *cli)
2338 struct tevent_req *req, *subreq;
2339 struct cli_ulogoff_state *state;
2341 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2347 SCVAL(state->vwv+0, 0, 0xFF);
2348 SCVAL(state->vwv+1, 0, 0);
2349 SSVAL(state->vwv+2, 0, 0);
2351 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
2353 if (tevent_req_nomem(subreq, req)) {
2354 return tevent_req_post(req, ev);
2356 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2360 static void cli_ulogoff_done(struct tevent_req *subreq)
2362 struct tevent_req *req = tevent_req_callback_data(
2363 subreq, struct tevent_req);
2364 struct cli_ulogoff_state *state = tevent_req_data(
2365 req, struct cli_ulogoff_state);
2368 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2369 if (!NT_STATUS_IS_OK(status)) {
2370 tevent_req_nterror(req, status);
2373 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2374 tevent_req_done(req);
2377 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2379 return tevent_req_simple_recv_ntstatus(req);
2382 NTSTATUS cli_ulogoff(struct cli_state *cli)
2384 struct tevent_context *ev;
2385 struct tevent_req *req;
2386 NTSTATUS status = NT_STATUS_NO_MEMORY;
2388 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2389 status = smb2cli_logoff(cli->conn,
2392 if (!NT_STATUS_IS_OK(status)) {
2395 smb2cli_session_set_id_and_flags(cli->smb2.session,
2397 return NT_STATUS_OK;
2400 if (smbXcli_conn_has_async_calls(cli->conn)) {
2401 return NT_STATUS_INVALID_PARAMETER;
2403 ev = samba_tevent_context_init(talloc_tos());
2407 req = cli_ulogoff_send(ev, ev, cli);
2411 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2414 status = cli_ulogoff_recv(req);
2420 /****************************************************************************
2422 ****************************************************************************/
2424 struct cli_tcon_andx_state {
2425 struct cli_state *cli;
2430 static void cli_tcon_andx_done(struct tevent_req *subreq);
2432 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2433 struct tevent_context *ev,
2434 struct cli_state *cli,
2435 const char *share, const char *dev,
2436 const char *pass, int passlen,
2437 struct tevent_req **psmbreq)
2439 struct tevent_req *req, *subreq;
2440 struct cli_tcon_andx_state *state;
2445 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2446 uint16_t tcon_flags = 0;
2450 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2457 cli->share = talloc_strdup(cli, share);
2462 /* in user level security don't send a password now */
2463 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2466 } else if (pass == NULL) {
2467 DEBUG(1, ("Server not using user level security and no "
2468 "password supplied.\n"));
2472 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2473 *pass && passlen != 24) {
2474 if (!lp_client_lanman_auth()) {
2475 DEBUG(1, ("Server requested LANMAN password "
2476 "(share-level security) but "
2477 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2482 * Non-encrypted passwords - convert to DOS codepage before
2485 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2487 pass = (const char *)p24;
2489 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2490 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2494 if (!lp_client_plaintext_auth() && (*pass)) {
2495 DEBUG(1, ("Server requested PLAINTEXT "
2497 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2502 * Non-encrypted passwords - convert to DOS codepage
2505 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2506 if (tevent_req_nomem(tmp_pass, req)) {
2507 return tevent_req_post(req, ev);
2509 tmp_pass = trans2_bytes_push_str(tmp_pass,
2510 false, /* always DOS */
2514 if (tevent_req_nomem(tmp_pass, req)) {
2515 return tevent_req_post(req, ev);
2517 pass = (const char *)tmp_pass;
2518 passlen = talloc_get_size(tmp_pass);
2522 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2523 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2525 SCVAL(vwv+0, 0, 0xFF);
2528 SSVAL(vwv+2, 0, tcon_flags);
2529 SSVAL(vwv+3, 0, passlen);
2531 if (passlen && pass) {
2532 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2534 bytes = talloc_array(state, uint8_t, 0);
2540 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2541 smbXcli_conn_remote_name(cli->conn), share);
2546 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2551 * Add the devicetype
2553 tmp = talloc_strdup_upper(talloc_tos(), dev);
2558 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2561 if (bytes == NULL) {
2566 state->bytes.iov_base = (void *)bytes;
2567 state->bytes.iov_len = talloc_get_size(bytes);
2569 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2571 if (subreq == NULL) {
2575 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2580 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2581 return tevent_req_post(req, ev);
2584 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2585 struct tevent_context *ev,
2586 struct cli_state *cli,
2587 const char *share, const char *dev,
2588 const char *pass, int passlen)
2590 struct tevent_req *req, *subreq;
2593 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2598 if (subreq == NULL) {
2601 status = smb1cli_req_chain_submit(&subreq, 1);
2602 if (!NT_STATUS_IS_OK(status)) {
2603 tevent_req_nterror(req, status);
2604 return tevent_req_post(req, ev);
2609 static void cli_tcon_andx_done(struct tevent_req *subreq)
2611 struct tevent_req *req = tevent_req_callback_data(
2612 subreq, struct tevent_req);
2613 struct cli_tcon_andx_state *state = tevent_req_data(
2614 req, struct cli_tcon_andx_state);
2615 struct cli_state *cli = state->cli;
2623 uint16_t optional_support = 0;
2625 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2626 &num_bytes, &bytes);
2627 TALLOC_FREE(subreq);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 tevent_req_nterror(req, status);
2633 inhdr = in + NBT_HDR_SIZE;
2636 if (clistr_pull_talloc(cli,
2637 (const char *)inhdr,
2638 SVAL(inhdr, HDR_FLG2),
2642 STR_TERMINATE|STR_ASCII) == -1) {
2643 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2647 cli->dev = talloc_strdup(cli, "");
2648 if (cli->dev == NULL) {
2649 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2654 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2655 /* almost certainly win95 - enable bug fixes */
2660 * Make sure that we have the optional support 16-bit field. WCT > 2.
2661 * Avoids issues when connecting to Win9x boxes sharing files
2664 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2665 optional_support = SVAL(vwv+2, 0);
2668 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2669 smb1cli_session_protect_session_key(cli->smb1.session);
2672 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2673 SVAL(inhdr, HDR_TID),
2675 0, /* maximal_access */
2676 0, /* guest_maximal_access */
2678 NULL); /* fs_type */
2680 tevent_req_done(req);
2683 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2685 return tevent_req_simple_recv_ntstatus(req);
2688 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2689 const char *dev, const char *pass, int passlen)
2691 TALLOC_CTX *frame = talloc_stackframe();
2692 struct tevent_context *ev;
2693 struct tevent_req *req;
2694 NTSTATUS status = NT_STATUS_NO_MEMORY;
2696 if (smbXcli_conn_has_async_calls(cli->conn)) {
2698 * Can't use sync call while an async call is in flight
2700 status = NT_STATUS_INVALID_PARAMETER;
2704 ev = samba_tevent_context_init(frame);
2709 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2714 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2718 status = cli_tcon_andx_recv(req);
2724 struct cli_tree_connect_state {
2725 struct cli_state *cli;
2728 static struct tevent_req *cli_raw_tcon_send(
2729 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2730 const char *service, const char *pass, const char *dev);
2731 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2732 uint16_t *max_xmit, uint16_t *tid);
2734 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2735 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2736 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2738 static struct tevent_req *cli_tree_connect_send(
2739 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2740 const char *share, const char *dev, const char *pass, int passlen)
2742 struct tevent_req *req, *subreq;
2743 struct cli_tree_connect_state *state;
2745 req = tevent_req_create(mem_ctx, &state,
2746 struct cli_tree_connect_state);
2752 cli->share = talloc_strdup(cli, share);
2753 if (tevent_req_nomem(cli->share, req)) {
2754 return tevent_req_post(req, ev);
2757 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2760 cli->smb2.tcon = smbXcli_tcon_create(cli);
2761 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2762 return tevent_req_post(req, ev);
2765 unc = talloc_asprintf(state, "\\\\%s\\%s",
2766 smbXcli_conn_remote_name(cli->conn),
2768 if (tevent_req_nomem(unc, req)) {
2769 return tevent_req_post(req, ev);
2772 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2773 cli->smb2.session, cli->smb2.tcon,
2776 if (tevent_req_nomem(subreq, req)) {
2777 return tevent_req_post(req, ev);
2779 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2784 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2785 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2787 if (tevent_req_nomem(subreq, req)) {
2788 return tevent_req_post(req, ev);
2790 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2795 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2796 if (tevent_req_nomem(subreq, req)) {
2797 return tevent_req_post(req, ev);
2799 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2804 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2806 tevent_req_simple_finish_ntstatus(
2807 subreq, smb2cli_tcon_recv(subreq));
2810 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2812 tevent_req_simple_finish_ntstatus(
2813 subreq, cli_tcon_andx_recv(subreq));
2816 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2818 struct tevent_req *req = tevent_req_callback_data(
2819 subreq, struct tevent_req);
2820 struct cli_tree_connect_state *state = tevent_req_data(
2821 req, struct cli_tree_connect_state);
2823 uint16_t max_xmit = 0;
2826 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2827 if (tevent_req_nterror(req, status)) {
2831 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2833 0, /* optional_support */
2834 0, /* maximal_access */
2835 0, /* guest_maximal_access */
2837 NULL); /* fs_type */
2839 tevent_req_done(req);
2842 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2844 return tevent_req_simple_recv_ntstatus(req);
2847 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2848 const char *dev, const char *pass, int passlen)
2850 struct tevent_context *ev;
2851 struct tevent_req *req;
2852 NTSTATUS status = NT_STATUS_NO_MEMORY;
2854 if (smbXcli_conn_has_async_calls(cli->conn)) {
2855 return NT_STATUS_INVALID_PARAMETER;
2857 ev = samba_tevent_context_init(talloc_tos());
2861 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2865 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2868 status = cli_tree_connect_recv(req);
2874 /****************************************************************************
2875 Send a tree disconnect.
2876 ****************************************************************************/
2878 struct cli_tdis_state {
2879 struct cli_state *cli;
2882 static void cli_tdis_done(struct tevent_req *subreq);
2884 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2885 struct tevent_context *ev,
2886 struct cli_state *cli)
2888 struct tevent_req *req, *subreq;
2889 struct cli_tdis_state *state;
2891 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2897 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2898 if (tevent_req_nomem(subreq, req)) {
2899 return tevent_req_post(req, ev);
2901 tevent_req_set_callback(subreq, cli_tdis_done, req);
2905 static void cli_tdis_done(struct tevent_req *subreq)
2907 struct tevent_req *req = tevent_req_callback_data(
2908 subreq, struct tevent_req);
2909 struct cli_tdis_state *state = tevent_req_data(
2910 req, struct cli_tdis_state);
2913 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2914 TALLOC_FREE(subreq);
2915 if (!NT_STATUS_IS_OK(status)) {
2916 tevent_req_nterror(req, status);
2919 cli_state_set_tid(state->cli, UINT16_MAX);
2920 tevent_req_done(req);
2923 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2925 return tevent_req_simple_recv_ntstatus(req);
2928 NTSTATUS cli_tdis(struct cli_state *cli)
2930 struct tevent_context *ev;
2931 struct tevent_req *req;
2932 NTSTATUS status = NT_STATUS_NO_MEMORY;
2934 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2935 return smb2cli_tdis(cli->conn,
2941 if (smbXcli_conn_has_async_calls(cli->conn)) {
2942 return NT_STATUS_INVALID_PARAMETER;
2944 ev = samba_tevent_context_init(talloc_tos());
2948 req = cli_tdis_send(ev, ev, cli);
2952 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2955 status = cli_tdis_recv(req);
2961 struct cli_connect_sock_state {
2962 const char **called_names;
2963 const char **calling_names;
2969 static void cli_connect_sock_done(struct tevent_req *subreq);
2972 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2976 static struct tevent_req *cli_connect_sock_send(
2977 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2978 const char *host, int name_type, const struct sockaddr_storage *pss,
2979 const char *myname, uint16_t port)
2981 struct tevent_req *req, *subreq;
2982 struct cli_connect_sock_state *state;
2984 struct sockaddr_storage *addrs;
2985 unsigned i, num_addrs;
2988 req = tevent_req_create(mem_ctx, &state,
2989 struct cli_connect_sock_state);
2994 prog = getenv("LIBSMB_PROG");
2996 state->fd = sock_exec(prog);
2997 if (state->fd == -1) {
2998 status = map_nt_error_from_unix(errno);
2999 tevent_req_nterror(req, status);
3002 tevent_req_done(req);
3004 return tevent_req_post(req, ev);
3007 if ((pss == NULL) || is_zero_addr(pss)) {
3010 * Here we cheat. resolve_name_list is not async at all. So
3011 * this call will only be really async if the name lookup has
3012 * been done externally.
3015 status = resolve_name_list(state, host, name_type,
3016 &addrs, &num_addrs);
3017 if (!NT_STATUS_IS_OK(status)) {
3018 tevent_req_nterror(req, status);
3019 return tevent_req_post(req, ev);
3022 addrs = talloc_array(state, struct sockaddr_storage, 1);
3023 if (tevent_req_nomem(addrs, req)) {
3024 return tevent_req_post(req, ev);
3030 state->called_names = talloc_array(state, const char *, num_addrs);
3031 if (tevent_req_nomem(state->called_names, req)) {
3032 return tevent_req_post(req, ev);
3034 state->called_types = talloc_array(state, int, num_addrs);
3035 if (tevent_req_nomem(state->called_types, req)) {
3036 return tevent_req_post(req, ev);
3038 state->calling_names = talloc_array(state, const char *, num_addrs);
3039 if (tevent_req_nomem(state->calling_names, req)) {
3040 return tevent_req_post(req, ev);
3042 for (i=0; i<num_addrs; i++) {
3043 state->called_names[i] = host;
3044 state->called_types[i] = name_type;
3045 state->calling_names[i] = myname;
3048 subreq = smbsock_any_connect_send(
3049 state, ev, addrs, state->called_names, state->called_types,
3050 state->calling_names, NULL, num_addrs, port);
3051 if (tevent_req_nomem(subreq, req)) {
3052 return tevent_req_post(req, ev);
3054 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3058 static void cli_connect_sock_done(struct tevent_req *subreq)
3060 struct tevent_req *req = tevent_req_callback_data(
3061 subreq, struct tevent_req);
3062 struct cli_connect_sock_state *state = tevent_req_data(
3063 req, struct cli_connect_sock_state);
3066 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3068 TALLOC_FREE(subreq);
3069 if (tevent_req_nterror(req, status)) {
3072 set_socket_options(state->fd, lp_socket_options());
3073 tevent_req_done(req);
3076 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3077 int *pfd, uint16_t *pport)
3079 struct cli_connect_sock_state *state = tevent_req_data(
3080 req, struct cli_connect_sock_state);
3083 if (tevent_req_is_nterror(req, &status)) {
3087 *pport = state->port;
3088 return NT_STATUS_OK;
3091 struct cli_connect_nb_state {
3092 const char *desthost;
3095 struct cli_state *cli;
3098 static void cli_connect_nb_done(struct tevent_req *subreq);
3100 static struct tevent_req *cli_connect_nb_send(
3101 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3102 const char *host, const struct sockaddr_storage *dest_ss,
3103 uint16_t port, int name_type, const char *myname,
3104 int signing_state, int flags)
3106 struct tevent_req *req, *subreq;
3107 struct cli_connect_nb_state *state;
3109 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3113 state->signing_state = signing_state;
3114 state->flags = flags;
3117 char *p = strchr(host, '#');
3120 name_type = strtol(p+1, NULL, 16);
3121 host = talloc_strndup(state, host, p - host);
3122 if (tevent_req_nomem(host, req)) {
3123 return tevent_req_post(req, ev);
3127 state->desthost = host;
3128 } else if (dest_ss != NULL) {
3129 state->desthost = print_canonical_sockaddr(state, dest_ss);
3130 if (tevent_req_nomem(state->desthost, req)) {
3131 return tevent_req_post(req, ev);
3134 /* No host or dest_ss given. Error out. */
3135 tevent_req_error(req, EINVAL);
3136 return tevent_req_post(req, ev);
3139 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3141 if (tevent_req_nomem(subreq, req)) {
3142 return tevent_req_post(req, ev);
3144 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3148 static void cli_connect_nb_done(struct tevent_req *subreq)
3150 struct tevent_req *req = tevent_req_callback_data(
3151 subreq, struct tevent_req);
3152 struct cli_connect_nb_state *state = tevent_req_data(
3153 req, struct cli_connect_nb_state);
3158 status = cli_connect_sock_recv(subreq, &fd, &port);
3159 TALLOC_FREE(subreq);
3160 if (tevent_req_nterror(req, status)) {
3164 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3165 state->signing_state, state->flags);
3166 if (tevent_req_nomem(state->cli, req)) {
3170 tevent_req_done(req);
3173 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3174 struct cli_state **pcli)
3176 struct cli_connect_nb_state *state = tevent_req_data(
3177 req, struct cli_connect_nb_state);
3180 if (tevent_req_is_nterror(req, &status)) {
3183 *pcli = talloc_move(NULL, &state->cli);
3184 return NT_STATUS_OK;
3187 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3188 uint16_t port, int name_type, const char *myname,
3189 int signing_state, int flags, struct cli_state **pcli)
3191 struct tevent_context *ev;
3192 struct tevent_req *req;
3193 NTSTATUS status = NT_STATUS_NO_MEMORY;
3195 ev = samba_tevent_context_init(talloc_tos());
3199 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3200 myname, signing_state, flags);
3204 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3207 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3210 status = cli_connect_nb_recv(req, pcli);
3216 struct cli_start_connection_state {
3217 struct tevent_context *ev;
3218 struct cli_state *cli;
3223 static void cli_start_connection_connected(struct tevent_req *subreq);
3224 static void cli_start_connection_done(struct tevent_req *subreq);
3227 establishes a connection to after the negprot.
3228 @param output_cli A fully initialised cli structure, non-null only on success
3229 @param dest_host The netbios name of the remote host
3230 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3231 @param port (optional) The destination port (0 for default)
3234 static struct tevent_req *cli_start_connection_send(
3235 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3236 const char *my_name, const char *dest_host,
3237 const struct sockaddr_storage *dest_ss, int port,
3238 int signing_state, int flags)
3240 struct tevent_req *req, *subreq;
3241 struct cli_start_connection_state *state;
3243 req = tevent_req_create(mem_ctx, &state,
3244 struct cli_start_connection_state);
3250 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3251 state->min_protocol = lp_client_ipc_min_protocol();
3252 state->max_protocol = lp_client_ipc_max_protocol();
3254 state->min_protocol = lp_client_min_protocol();
3255 state->max_protocol = lp_client_max_protocol();
3258 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3259 0x20, my_name, signing_state, flags);
3260 if (tevent_req_nomem(subreq, req)) {
3261 return tevent_req_post(req, ev);
3263 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3267 static void cli_start_connection_connected(struct tevent_req *subreq)
3269 struct tevent_req *req = tevent_req_callback_data(
3270 subreq, struct tevent_req);
3271 struct cli_start_connection_state *state = tevent_req_data(
3272 req, struct cli_start_connection_state);
3275 status = cli_connect_nb_recv(subreq, &state->cli);
3276 TALLOC_FREE(subreq);
3277 if (tevent_req_nterror(req, status)) {
3281 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3282 state->cli->timeout,
3283 state->min_protocol,
3284 state->max_protocol);
3285 if (tevent_req_nomem(subreq, req)) {
3288 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3291 static void cli_start_connection_done(struct tevent_req *subreq)
3293 struct tevent_req *req = tevent_req_callback_data(
3294 subreq, struct tevent_req);
3295 struct cli_start_connection_state *state = tevent_req_data(
3296 req, struct cli_start_connection_state);
3299 status = smbXcli_negprot_recv(subreq);
3300 TALLOC_FREE(subreq);
3301 if (tevent_req_nterror(req, status)) {
3305 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3306 /* Ensure we ask for some initial credits. */
3307 smb2cli_conn_set_max_credits(state->cli->conn,
3308 DEFAULT_SMB2_MAX_CREDITS);
3311 tevent_req_done(req);
3314 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3315 struct cli_state **output_cli)
3317 struct cli_start_connection_state *state = tevent_req_data(
3318 req, struct cli_start_connection_state);
3321 if (tevent_req_is_nterror(req, &status)) {
3324 *output_cli = state->cli;
3326 return NT_STATUS_OK;
3329 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3330 const char *my_name,
3331 const char *dest_host,
3332 const struct sockaddr_storage *dest_ss, int port,
3333 int signing_state, int flags)
3335 struct tevent_context *ev;
3336 struct tevent_req *req;
3337 NTSTATUS status = NT_STATUS_NO_MEMORY;
3339 ev = samba_tevent_context_init(talloc_tos());
3343 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3344 port, signing_state, flags);
3348 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3351 status = cli_start_connection_recv(req, output_cli);
3358 establishes a connection right up to doing tconX, password specified.
3359 @param output_cli A fully initialised cli structure, non-null only on success
3360 @param dest_host The netbios name of the remote host
3361 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3362 @param port (optional) The destination port (0 for default)
3363 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3364 @param service_type The 'type' of serivice.
3365 @param user Username, unix string
3366 @param domain User's domain
3367 @param password User's password, unencrypted unix string.
3370 struct cli_full_connection_state {
3371 struct tevent_context *ev;
3372 const char *service;
3373 const char *service_type;
3376 const char *password;
3379 struct cli_state *cli;
3382 static int cli_full_connection_state_destructor(
3383 struct cli_full_connection_state *s);
3384 static void cli_full_connection_started(struct tevent_req *subreq);
3385 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3386 static void cli_full_connection_done(struct tevent_req *subreq);
3388 struct tevent_req *cli_full_connection_send(
3389 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3390 const char *my_name, const char *dest_host,
3391 const struct sockaddr_storage *dest_ss, int port,
3392 const char *service, const char *service_type,
3393 const char *user, const char *domain,
3394 const char *password, int flags, int signing_state)
3396 struct tevent_req *req, *subreq;
3397 struct cli_full_connection_state *state;
3399 req = tevent_req_create(mem_ctx, &state,
3400 struct cli_full_connection_state);
3404 talloc_set_destructor(state, cli_full_connection_state_destructor);
3407 state->service = service;
3408 state->service_type = service_type;
3410 state->domain = domain;
3411 state->password = password;
3412 state->flags = flags;
3414 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3415 if (state->password == NULL) {
3416 state->password = "";
3419 subreq = cli_start_connection_send(
3420 state, ev, my_name, dest_host, dest_ss, port,
3421 signing_state, flags);
3422 if (tevent_req_nomem(subreq, req)) {
3423 return tevent_req_post(req, ev);
3425 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3429 static int cli_full_connection_state_destructor(
3430 struct cli_full_connection_state *s)
3432 if (s->cli != NULL) {
3433 cli_shutdown(s->cli);
3439 static void cli_full_connection_started(struct tevent_req *subreq)
3441 struct tevent_req *req = tevent_req_callback_data(
3442 subreq, struct tevent_req);
3443 struct cli_full_connection_state *state = tevent_req_data(
3444 req, struct cli_full_connection_state);
3447 status = cli_start_connection_recv(subreq, &state->cli);
3448 TALLOC_FREE(subreq);
3449 if (tevent_req_nterror(req, status)) {
3452 subreq = cli_session_setup_send(
3453 state, state->ev, state->cli, state->user,
3454 state->password, state->domain);
3455 if (tevent_req_nomem(subreq, req)) {
3458 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3461 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3463 struct tevent_req *req = tevent_req_callback_data(
3464 subreq, struct tevent_req);
3465 struct cli_full_connection_state *state = tevent_req_data(
3466 req, struct cli_full_connection_state);
3469 status = cli_session_setup_recv(subreq);
3470 TALLOC_FREE(subreq);
3472 if (!NT_STATUS_IS_OK(status) &&
3473 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3475 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3477 subreq = cli_session_setup_send(
3478 state, state->ev, state->cli, "", "",
3480 if (tevent_req_nomem(subreq, req)) {
3483 tevent_req_set_callback(
3484 subreq, cli_full_connection_sess_set_up, req);
3488 if (tevent_req_nterror(req, status)) {
3492 if (state->service != NULL) {
3493 subreq = cli_tree_connect_send(
3494 state, state->ev, state->cli,
3495 state->service, state->service_type,
3496 state->password, state->pw_len);
3497 if (tevent_req_nomem(subreq, req)) {
3500 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3504 tevent_req_done(req);
3507 static void cli_full_connection_done(struct tevent_req *subreq)
3509 struct tevent_req *req = tevent_req_callback_data(
3510 subreq, struct tevent_req);
3513 status = cli_tree_connect_recv(subreq);
3514 TALLOC_FREE(subreq);
3515 if (tevent_req_nterror(req, status)) {
3519 tevent_req_done(req);
3522 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3523 struct cli_state **output_cli)
3525 struct cli_full_connection_state *state = tevent_req_data(
3526 req, struct cli_full_connection_state);
3529 if (tevent_req_is_nterror(req, &status)) {
3532 *output_cli = state->cli;
3533 talloc_set_destructor(state, NULL);
3534 return NT_STATUS_OK;
3537 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3538 const char *my_name,
3539 const char *dest_host,
3540 const struct sockaddr_storage *dest_ss, int port,
3541 const char *service, const char *service_type,
3542 const char *user, const char *domain,
3543 const char *password, int flags,
3546 struct tevent_context *ev;
3547 struct tevent_req *req;
3548 NTSTATUS status = NT_STATUS_NO_MEMORY;
3550 ev = samba_tevent_context_init(talloc_tos());
3554 req = cli_full_connection_send(
3555 ev, ev, my_name, dest_host, dest_ss, port, service,
3556 service_type, user, domain, password, flags, signing_state);
3560 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3563 status = cli_full_connection_recv(req, output_cli);
3569 /****************************************************************************
3570 Send an old style tcon.
3571 ****************************************************************************/
3572 struct cli_raw_tcon_state {
3576 static void cli_raw_tcon_done(struct tevent_req *subreq);
3578 static struct tevent_req *cli_raw_tcon_send(
3579 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3580 const char *service, const char *pass, const char *dev)
3582 struct tevent_req *req, *subreq;
3583 struct cli_raw_tcon_state *state;
3586 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3591 if (!lp_client_plaintext_auth() && (*pass)) {
3592 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3593 " or 'client ntlmv2 auth = yes'\n"));
3594 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3595 return tevent_req_post(req, ev);
3598 bytes = talloc_array(state, uint8_t, 0);
3599 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3600 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3601 service, strlen(service)+1, NULL);
3602 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3603 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3604 pass, strlen(pass)+1, NULL);
3605 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3606 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3607 dev, strlen(dev)+1, NULL);
3609 if (tevent_req_nomem(bytes, req)) {
3610 return tevent_req_post(req, ev);
3613 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3614 talloc_get_size(bytes), bytes);
3615 if (tevent_req_nomem(subreq, req)) {
3616 return tevent_req_post(req, ev);
3618 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3622 static void cli_raw_tcon_done(struct tevent_req *subreq)
3624 struct tevent_req *req = tevent_req_callback_data(
3625 subreq, struct tevent_req);
3626 struct cli_raw_tcon_state *state = tevent_req_data(
3627 req, struct cli_raw_tcon_state);
3630 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3632 TALLOC_FREE(subreq);
3633 if (tevent_req_nterror(req, status)) {
3636 tevent_req_done(req);
3639 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3640 uint16_t *max_xmit, uint16_t *tid)
3642 struct cli_raw_tcon_state *state = tevent_req_data(
3643 req, struct cli_raw_tcon_state);
3646 if (tevent_req_is_nterror(req, &status)) {
3649 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3650 *tid = SVAL(state->ret_vwv + 1, 0);
3651 return NT_STATUS_OK;
3654 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3655 const char *service, const char *pass, const char *dev,
3656 uint16_t *max_xmit, uint16_t *tid)
3658 struct tevent_context *ev;
3659 struct tevent_req *req;
3660 NTSTATUS status = NT_STATUS_NO_MEMORY;
3662 ev = samba_tevent_context_init(talloc_tos());
3666 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3670 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3673 status = cli_raw_tcon_recv(req, max_xmit, tid);
3679 /* Return a cli_state pointing at the IPC$ share for the given server */
3681 struct cli_state *get_ipc_connect(char *server,
3682 struct sockaddr_storage *server_ss,
3683 const struct user_auth_info *user_info)
3685 struct cli_state *cli;
3687 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3689 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3690 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3693 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3694 get_cmdline_auth_info_username(user_info),
3696 get_cmdline_auth_info_password(user_info),
3698 SMB_SIGNING_DEFAULT);
3700 if (NT_STATUS_IS_OK(nt_status)) {
3702 } else if (is_ipaddress(server)) {
3703 /* windows 9* needs a correct NMB name for connections */
3704 fstring remote_name;
3706 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3707 cli = get_ipc_connect(remote_name, server_ss, user_info);
3716 * Given the IP address of a master browser on the network, return its
3717 * workgroup and connect to it.
3719 * This function is provided to allow additional processing beyond what
3720 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3721 * browsers and obtain each master browsers' list of domains (in case the
3722 * first master browser is recently on the network and has not yet
3723 * synchronized with other master browsers and therefore does not yet have the
3724 * entire network browse list)
3727 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3728 struct sockaddr_storage *mb_ip,
3729 const struct user_auth_info *user_info,
3730 char **pp_workgroup_out)
3732 char addr[INET6_ADDRSTRLEN];
3734 struct cli_state *cli;
3735 struct sockaddr_storage server_ss;
3737 *pp_workgroup_out = NULL;
3739 print_sockaddr(addr, sizeof(addr), mb_ip);
3740 DEBUG(99, ("Looking up name of master browser %s\n",
3744 * Do a name status query to find out the name of the master browser.
3745 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3746 * master browser will not respond to a wildcard query (or, at least,
3747 * an NT4 server acting as the domain master browser will not).
3749 * We might be able to use ONLY the query on MSBROWSE, but that's not
3750 * yet been tested with all Windows versions, so until it is, leave
3751 * the original wildcard query as the first choice and fall back to
3752 * MSBROWSE if the wildcard query fails.
3754 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3755 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3757 DEBUG(99, ("Could not retrieve name status for %s\n",
3762 if (!find_master_ip(name, &server_ss)) {
3763 DEBUG(99, ("Could not find master ip for %s\n", name));
3767 *pp_workgroup_out = talloc_strdup(ctx, name);
3769 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3771 print_sockaddr(addr, sizeof(addr), &server_ss);
3772 cli = get_ipc_connect(addr, &server_ss, user_info);
3778 * Return the IP address and workgroup of a master browser on the network, and
3782 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3783 const struct user_auth_info *user_info,
3784 char **pp_workgroup_out)
3786 struct sockaddr_storage *ip_list;
3787 struct cli_state *cli;
3791 *pp_workgroup_out = NULL;
3793 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3795 /* Go looking for workgroups by broadcasting on the local network */
3797 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3799 if (!NT_STATUS_IS_OK(status)) {
3800 DEBUG(99, ("No master browsers responded: %s\n",
3801 nt_errstr(status)));
3805 for (i = 0; i < count; i++) {
3806 char addr[INET6_ADDRSTRLEN];
3807 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3808 DEBUG(99, ("Found master browser %s\n", addr));
3810 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3811 user_info, pp_workgroup_out);