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 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, 13, vwv,
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, 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, 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,
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);
1753 principal = kerberos_get_principal_from_service_hostname(
1754 talloc_tos(), "cifs", remote_name, lp_realm());
1756 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1757 principal ? principal : "<null>"));
1763 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1764 const char *principal)
1768 account = talloc_strdup(mem_ctx, principal);
1769 if (account == NULL) {
1772 p = strchr_m(account, '@');
1779 /****************************************************************************
1780 Do a spnego encrypted session setup.
1782 user_domain: The shortname of the domain the user/machine is a member of.
1783 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1784 ****************************************************************************/
1786 struct cli_session_setup_spnego_state {
1787 struct tevent_context *ev;
1788 struct cli_state *cli;
1789 const char *target_hostname;
1791 const char *account;
1793 const char *user_domain;
1794 const char *dest_realm;
1799 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1802 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1804 static struct tevent_req *cli_session_setup_spnego_send(
1805 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1806 const char *user, const char *pass, const char *user_domain)
1808 struct tevent_req *req, *subreq;
1809 struct cli_session_setup_spnego_state *state;
1810 char *principal = NULL;
1811 char *OIDs[ASN1_MAX_OIDS];
1813 const char *dest_realm = cli_state_remote_realm(cli);
1814 const DATA_BLOB *server_blob;
1816 req = tevent_req_create(mem_ctx, &state,
1817 struct cli_session_setup_spnego_state);
1825 state->user_domain = user_domain;
1826 state->dest_realm = dest_realm;
1828 state->account = cli_session_setup_get_account(state, user);
1829 if (tevent_req_nomem(state->account, req)) {
1830 return tevent_req_post(req, ev);
1833 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1834 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1836 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1837 (unsigned long)server_blob->length));
1839 /* the server might not even do spnego */
1840 if (server_blob->length == 0) {
1841 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1846 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1849 /* The server sent us the first part of the SPNEGO exchange in the
1850 * negprot reply. It is WRONG to depend on the principal sent in the
1851 * negprot reply, but right now we do it. If we don't receive one,
1852 * we try to best guess, then fall back to NTLM. */
1853 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1854 &principal, NULL) ||
1856 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1857 tevent_req_done(req);
1858 return tevent_req_post(req, ev);
1861 /* make sure the server understands kerberos */
1862 for (i=0;OIDs[i];i++) {
1864 DEBUG(3,("got OID=%s\n", OIDs[i]));
1866 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1867 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1868 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1869 cli->got_kerberos_mechanism = True;
1871 talloc_free(OIDs[i]);
1874 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1877 /* If password is set we reauthenticate to kerberos server
1878 * and do not store results */
1880 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1883 tmp = cli_session_setup_get_principal(
1884 talloc_tos(), principal, state->target_hostname, dest_realm);
1885 TALLOC_FREE(principal);
1888 if (pass && *pass) {
1891 use_in_memory_ccache();
1892 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1895 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1896 TALLOC_FREE(principal);
1897 if (cli->fallback_after_kerberos)
1899 state->result = ADS_ERROR_KRB5(ret);
1900 tevent_req_done(req);
1901 return tevent_req_post(req, ev);
1906 subreq = cli_session_setup_gensec_send(
1908 state->account, pass, user_domain,
1909 CRED_MUST_USE_KERBEROS,
1910 "cifs", state->target_hostname, principal);
1911 if (tevent_req_nomem(subreq, req)) {
1912 return tevent_req_post(req, ev);
1914 tevent_req_set_callback(
1915 subreq, cli_session_setup_spnego_done_krb,
1923 subreq = cli_session_setup_gensec_send(
1924 state, state->ev, state->cli,
1925 state->account, state->pass, state->user_domain,
1926 CRED_DONT_USE_KERBEROS,
1927 "cifs", state->target_hostname, NULL);
1928 if (tevent_req_nomem(subreq, req)) {
1929 return tevent_req_post(req, ev);
1931 tevent_req_set_callback(
1932 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1937 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1939 struct tevent_req *req = tevent_req_callback_data(
1940 subreq, struct tevent_req);
1941 struct cli_session_setup_spnego_state *state = tevent_req_data(
1942 req, struct cli_session_setup_spnego_state);
1945 status = cli_session_setup_gensec_recv(subreq);
1946 TALLOC_FREE(subreq);
1947 state->result = ADS_ERROR_NT(status);
1949 if (ADS_ERR_OK(state->result) ||
1950 !state->cli->fallback_after_kerberos) {
1951 tevent_req_done(req);
1955 subreq = cli_session_setup_gensec_send(
1956 state, state->ev, state->cli,
1957 state->account, state->pass, state->user_domain,
1958 CRED_DONT_USE_KERBEROS,
1959 "cifs", state->target_hostname, NULL);
1960 if (tevent_req_nomem(subreq, req)) {
1963 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1968 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1970 struct tevent_req *req = tevent_req_callback_data(
1971 subreq, struct tevent_req);
1972 struct cli_session_setup_spnego_state *state = tevent_req_data(
1973 req, struct cli_session_setup_spnego_state);
1976 status = cli_session_setup_gensec_recv(subreq);
1977 TALLOC_FREE(subreq);
1978 state->result = ADS_ERROR_NT(status);
1979 tevent_req_done(req);
1982 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1984 struct cli_session_setup_spnego_state *state = tevent_req_data(
1985 req, struct cli_session_setup_spnego_state);
1987 return state->result;
1990 struct cli_session_setup_state {
1994 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1995 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1996 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1997 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1998 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
2000 /****************************************************************************
2001 Send a session setup. The username and workgroup is in UNIX character
2002 format and must be converted to DOS codepage format before sending. If the
2003 password is in plaintext, the same should be done.
2004 ****************************************************************************/
2006 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
2007 struct tevent_context *ev,
2008 struct cli_state *cli,
2010 const char *pass, int passlen,
2011 const char *ntpass, int ntpasslen,
2012 const char *workgroup)
2014 struct tevent_req *req, *subreq;
2015 struct cli_session_setup_state *state;
2018 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2020 req = tevent_req_create(mem_ctx, &state,
2021 struct cli_session_setup_state);
2027 user2 = talloc_strdup(state, user);
2029 user2 = talloc_strdup(state, "");
2031 if (user2 == NULL) {
2032 tevent_req_oom(req);
2033 return tevent_req_post(req, ev);
2040 /* allow for workgroups as part of the username */
2041 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2042 (p=strchr_m(user2,*lp_winbind_separator()))) {
2045 if (!strupper_m(user2)) {
2046 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2047 return tevent_req_post(req, ev);
2052 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2053 tevent_req_done(req);
2054 return tevent_req_post(req, ev);
2057 /* now work out what sort of session setup we are going to
2058 do. I have split this into separate functions to make the
2059 flow a bit easier to understand (tridge) */
2061 /* if its an older server then we have to use the older request format */
2063 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2064 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2065 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2066 " or 'client ntlmv2 auth = yes'\n"));
2067 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2068 return tevent_req_post(req, ev);
2071 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2072 !lp_client_plaintext_auth() && (*pass)) {
2073 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2074 " or 'client ntlmv2 auth = yes'\n"));
2075 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2076 return tevent_req_post(req, ev);
2079 subreq = cli_session_setup_lanman2_send(
2080 state, ev, cli, user, pass, passlen, workgroup);
2081 if (tevent_req_nomem(subreq, req)) {
2082 return tevent_req_post(req, ev);
2084 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2089 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2090 subreq = cli_session_setup_spnego_send(
2091 state, ev, cli, user, pass, workgroup);
2092 if (tevent_req_nomem(subreq, req)) {
2093 return tevent_req_post(req, ev);
2095 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2101 * if the server supports extended security then use SPNEGO
2102 * even for anonymous connections.
2104 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2105 subreq = cli_session_setup_spnego_send(
2106 state, ev, cli, user, pass, 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_spnego,
2115 /* if no user is supplied then we have to do an anonymous connection.
2116 passwords are ignored */
2118 if (!user || !*user) {
2119 subreq = cli_session_setup_guest_send(state, ev, cli);
2120 if (tevent_req_nomem(subreq, req)) {
2121 return tevent_req_post(req, ev);
2123 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2128 /* if the server is share level then send a plaintext null
2129 password at this point. The password is sent in the tree
2132 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2133 subreq = cli_session_setup_plain_send(
2134 state, ev, cli, user, "", workgroup);
2135 if (tevent_req_nomem(subreq, req)) {
2136 return tevent_req_post(req, ev);
2138 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2143 /* if the server doesn't support encryption then we have to use
2144 plaintext. The second password is ignored */
2146 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2147 if (!lp_client_plaintext_auth() && (*pass)) {
2148 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2149 " or 'client ntlmv2 auth = yes'\n"));
2150 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2151 return tevent_req_post(req, ev);
2153 subreq = cli_session_setup_plain_send(
2154 state, ev, cli, user, pass, workgroup);
2155 if (tevent_req_nomem(subreq, req)) {
2156 return tevent_req_post(req, ev);
2158 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2164 /* otherwise do a NT1 style session setup */
2165 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2167 * Don't send an NTLMv2 response without NTLMSSP
2168 * if we want to use spnego support
2170 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2171 " but 'client use spnego = yes"
2172 " and 'client ntlmv2 auth = yes'\n"));
2173 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2174 return tevent_req_post(req, ev);
2177 subreq = cli_session_setup_nt1_send(
2178 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2180 if (tevent_req_nomem(subreq, req)) {
2181 return tevent_req_post(req, ev);
2183 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2188 tevent_req_done(req);
2189 return tevent_req_post(req, ev);
2192 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2194 struct tevent_req *req = tevent_req_callback_data(
2195 subreq, struct tevent_req);
2198 status = cli_session_setup_lanman2_recv(subreq);
2199 TALLOC_FREE(subreq);
2200 if (!NT_STATUS_IS_OK(status)) {
2201 tevent_req_nterror(req, status);
2204 tevent_req_done(req);
2207 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2209 struct tevent_req *req = tevent_req_callback_data(
2210 subreq, struct tevent_req);
2213 status = cli_session_setup_spnego_recv(subreq);
2214 TALLOC_FREE(subreq);
2215 if (!ADS_ERR_OK(status)) {
2216 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2217 tevent_req_nterror(req, ads_ntstatus(status));
2220 tevent_req_done(req);
2223 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2225 struct tevent_req *req = tevent_req_callback_data(
2226 subreq, struct tevent_req);
2229 status = cli_session_setup_guest_recv(subreq);
2230 TALLOC_FREE(subreq);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 tevent_req_nterror(req, status);
2235 tevent_req_done(req);
2238 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2240 struct tevent_req *req = tevent_req_callback_data(
2241 subreq, struct tevent_req);
2244 status = cli_session_setup_plain_recv(subreq);
2245 TALLOC_FREE(subreq);
2246 if (!NT_STATUS_IS_OK(status)) {
2247 tevent_req_nterror(req, status);
2250 tevent_req_done(req);
2253 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2255 struct tevent_req *req = tevent_req_callback_data(
2256 subreq, struct tevent_req);
2259 status = cli_session_setup_nt1_recv(subreq);
2260 TALLOC_FREE(subreq);
2261 if (!NT_STATUS_IS_OK(status)) {
2262 DEBUG(3, ("cli_session_setup: NT1 session setup "
2263 "failed: %s\n", nt_errstr(status)));
2264 tevent_req_nterror(req, status);
2267 tevent_req_done(req);
2270 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2272 return tevent_req_simple_recv_ntstatus(req);
2275 NTSTATUS cli_session_setup(struct cli_state *cli,
2277 const char *pass, int passlen,
2278 const char *ntpass, int ntpasslen,
2279 const char *workgroup)
2281 struct tevent_context *ev;
2282 struct tevent_req *req;
2283 NTSTATUS status = NT_STATUS_NO_MEMORY;
2285 if (smbXcli_conn_has_async_calls(cli->conn)) {
2286 return NT_STATUS_INVALID_PARAMETER;
2288 ev = samba_tevent_context_init(talloc_tos());
2292 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2293 ntpass, ntpasslen, workgroup);
2297 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2300 status = cli_session_setup_recv(req);
2306 /****************************************************************************
2308 *****************************************************************************/
2310 struct cli_ulogoff_state {
2311 struct cli_state *cli;
2315 static void cli_ulogoff_done(struct tevent_req *subreq);
2317 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2318 struct tevent_context *ev,
2319 struct cli_state *cli)
2321 struct tevent_req *req, *subreq;
2322 struct cli_ulogoff_state *state;
2324 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2330 SCVAL(state->vwv+0, 0, 0xFF);
2331 SCVAL(state->vwv+1, 0, 0);
2332 SSVAL(state->vwv+2, 0, 0);
2334 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2336 if (tevent_req_nomem(subreq, req)) {
2337 return tevent_req_post(req, ev);
2339 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2343 static void cli_ulogoff_done(struct tevent_req *subreq)
2345 struct tevent_req *req = tevent_req_callback_data(
2346 subreq, struct tevent_req);
2347 struct cli_ulogoff_state *state = tevent_req_data(
2348 req, struct cli_ulogoff_state);
2351 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2352 if (!NT_STATUS_IS_OK(status)) {
2353 tevent_req_nterror(req, status);
2356 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2357 tevent_req_done(req);
2360 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2362 return tevent_req_simple_recv_ntstatus(req);
2365 NTSTATUS cli_ulogoff(struct cli_state *cli)
2367 struct tevent_context *ev;
2368 struct tevent_req *req;
2369 NTSTATUS status = NT_STATUS_NO_MEMORY;
2371 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2372 status = smb2cli_logoff(cli->conn,
2375 if (!NT_STATUS_IS_OK(status)) {
2378 smb2cli_session_set_id_and_flags(cli->smb2.session,
2380 return NT_STATUS_OK;
2383 if (smbXcli_conn_has_async_calls(cli->conn)) {
2384 return NT_STATUS_INVALID_PARAMETER;
2386 ev = samba_tevent_context_init(talloc_tos());
2390 req = cli_ulogoff_send(ev, ev, cli);
2394 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2397 status = cli_ulogoff_recv(req);
2403 /****************************************************************************
2405 ****************************************************************************/
2407 struct cli_tcon_andx_state {
2408 struct cli_state *cli;
2413 static void cli_tcon_andx_done(struct tevent_req *subreq);
2415 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2416 struct tevent_context *ev,
2417 struct cli_state *cli,
2418 const char *share, const char *dev,
2419 const char *pass, int passlen,
2420 struct tevent_req **psmbreq)
2422 struct tevent_req *req, *subreq;
2423 struct cli_tcon_andx_state *state;
2428 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2429 uint16_t tcon_flags = 0;
2433 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2440 cli->share = talloc_strdup(cli, share);
2445 /* in user level security don't send a password now */
2446 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2449 } else if (pass == NULL) {
2450 DEBUG(1, ("Server not using user level security and no "
2451 "password supplied.\n"));
2455 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2456 *pass && passlen != 24) {
2457 if (!lp_client_lanman_auth()) {
2458 DEBUG(1, ("Server requested LANMAN password "
2459 "(share-level security) but "
2460 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2465 * Non-encrypted passwords - convert to DOS codepage before
2468 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2470 pass = (const char *)p24;
2472 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2473 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2477 if (!lp_client_plaintext_auth() && (*pass)) {
2478 DEBUG(1, ("Server requested PLAINTEXT "
2480 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2485 * Non-encrypted passwords - convert to DOS codepage
2488 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2489 if (tevent_req_nomem(tmp_pass, req)) {
2490 return tevent_req_post(req, ev);
2492 tmp_pass = trans2_bytes_push_str(tmp_pass,
2493 false, /* always DOS */
2497 if (tevent_req_nomem(tmp_pass, req)) {
2498 return tevent_req_post(req, ev);
2500 pass = (const char *)tmp_pass;
2501 passlen = talloc_get_size(tmp_pass);
2505 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2506 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2508 SCVAL(vwv+0, 0, 0xFF);
2511 SSVAL(vwv+2, 0, tcon_flags);
2512 SSVAL(vwv+3, 0, passlen);
2514 if (passlen && pass) {
2515 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2517 bytes = talloc_array(state, uint8_t, 0);
2523 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2524 smbXcli_conn_remote_name(cli->conn), share);
2529 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2534 * Add the devicetype
2536 tmp = talloc_strdup_upper(talloc_tos(), dev);
2541 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2544 if (bytes == NULL) {
2549 state->bytes.iov_base = (void *)bytes;
2550 state->bytes.iov_len = talloc_get_size(bytes);
2552 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2554 if (subreq == NULL) {
2558 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2563 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2564 return tevent_req_post(req, ev);
2567 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2568 struct tevent_context *ev,
2569 struct cli_state *cli,
2570 const char *share, const char *dev,
2571 const char *pass, int passlen)
2573 struct tevent_req *req, *subreq;
2576 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2581 if (subreq == NULL) {
2584 status = smb1cli_req_chain_submit(&subreq, 1);
2585 if (!NT_STATUS_IS_OK(status)) {
2586 tevent_req_nterror(req, status);
2587 return tevent_req_post(req, ev);
2592 static void cli_tcon_andx_done(struct tevent_req *subreq)
2594 struct tevent_req *req = tevent_req_callback_data(
2595 subreq, struct tevent_req);
2596 struct cli_tcon_andx_state *state = tevent_req_data(
2597 req, struct cli_tcon_andx_state);
2598 struct cli_state *cli = state->cli;
2606 uint16_t optional_support = 0;
2608 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2609 &num_bytes, &bytes);
2610 TALLOC_FREE(subreq);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 tevent_req_nterror(req, status);
2616 inhdr = in + NBT_HDR_SIZE;
2619 if (clistr_pull_talloc(cli,
2620 (const char *)inhdr,
2621 SVAL(inhdr, HDR_FLG2),
2625 STR_TERMINATE|STR_ASCII) == -1) {
2626 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2630 cli->dev = talloc_strdup(cli, "");
2631 if (cli->dev == NULL) {
2632 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2637 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2638 /* almost certainly win95 - enable bug fixes */
2643 * Make sure that we have the optional support 16-bit field. WCT > 2.
2644 * Avoids issues when connecting to Win9x boxes sharing files
2647 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2648 optional_support = SVAL(vwv+2, 0);
2651 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2652 smb1cli_session_protect_session_key(cli->smb1.session);
2655 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2656 SVAL(inhdr, HDR_TID),
2658 0, /* maximal_access */
2659 0, /* guest_maximal_access */
2661 NULL); /* fs_type */
2663 tevent_req_done(req);
2666 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2668 return tevent_req_simple_recv_ntstatus(req);
2671 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2672 const char *dev, const char *pass, int passlen)
2674 TALLOC_CTX *frame = talloc_stackframe();
2675 struct tevent_context *ev;
2676 struct tevent_req *req;
2677 NTSTATUS status = NT_STATUS_NO_MEMORY;
2679 if (smbXcli_conn_has_async_calls(cli->conn)) {
2681 * Can't use sync call while an async call is in flight
2683 status = NT_STATUS_INVALID_PARAMETER;
2687 ev = samba_tevent_context_init(frame);
2692 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2697 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2701 status = cli_tcon_andx_recv(req);
2707 struct cli_tree_connect_state {
2708 struct cli_state *cli;
2711 static struct tevent_req *cli_raw_tcon_send(
2712 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2713 const char *service, const char *pass, const char *dev);
2714 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2715 uint16_t *max_xmit, uint16_t *tid);
2717 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2718 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2719 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2721 static struct tevent_req *cli_tree_connect_send(
2722 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2723 const char *share, const char *dev, const char *pass, int passlen)
2725 struct tevent_req *req, *subreq;
2726 struct cli_tree_connect_state *state;
2728 req = tevent_req_create(mem_ctx, &state,
2729 struct cli_tree_connect_state);
2735 cli->share = talloc_strdup(cli, share);
2736 if (tevent_req_nomem(cli->share, req)) {
2737 return tevent_req_post(req, ev);
2740 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2743 cli->smb2.tcon = smbXcli_tcon_create(cli);
2744 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2745 return tevent_req_post(req, ev);
2748 unc = talloc_asprintf(state, "\\\\%s\\%s",
2749 smbXcli_conn_remote_name(cli->conn),
2751 if (tevent_req_nomem(unc, req)) {
2752 return tevent_req_post(req, ev);
2755 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2756 cli->smb2.session, cli->smb2.tcon,
2759 if (tevent_req_nomem(subreq, req)) {
2760 return tevent_req_post(req, ev);
2762 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2767 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2768 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2770 if (tevent_req_nomem(subreq, req)) {
2771 return tevent_req_post(req, ev);
2773 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2778 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2779 if (tevent_req_nomem(subreq, req)) {
2780 return tevent_req_post(req, ev);
2782 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2787 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2789 tevent_req_simple_finish_ntstatus(
2790 subreq, smb2cli_tcon_recv(subreq));
2793 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2795 tevent_req_simple_finish_ntstatus(
2796 subreq, cli_tcon_andx_recv(subreq));
2799 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2801 struct tevent_req *req = tevent_req_callback_data(
2802 subreq, struct tevent_req);
2803 struct cli_tree_connect_state *state = tevent_req_data(
2804 req, struct cli_tree_connect_state);
2806 uint16_t max_xmit = 0;
2809 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2810 if (tevent_req_nterror(req, status)) {
2814 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2816 0, /* optional_support */
2817 0, /* maximal_access */
2818 0, /* guest_maximal_access */
2820 NULL); /* fs_type */
2822 tevent_req_done(req);
2825 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2827 return tevent_req_simple_recv_ntstatus(req);
2830 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2831 const char *dev, const char *pass, int passlen)
2833 struct tevent_context *ev;
2834 struct tevent_req *req;
2835 NTSTATUS status = NT_STATUS_NO_MEMORY;
2837 if (smbXcli_conn_has_async_calls(cli->conn)) {
2838 return NT_STATUS_INVALID_PARAMETER;
2840 ev = samba_tevent_context_init(talloc_tos());
2844 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2848 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2851 status = cli_tree_connect_recv(req);
2857 /****************************************************************************
2858 Send a tree disconnect.
2859 ****************************************************************************/
2861 struct cli_tdis_state {
2862 struct cli_state *cli;
2865 static void cli_tdis_done(struct tevent_req *subreq);
2867 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2868 struct tevent_context *ev,
2869 struct cli_state *cli)
2871 struct tevent_req *req, *subreq;
2872 struct cli_tdis_state *state;
2874 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2880 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2881 if (tevent_req_nomem(subreq, req)) {
2882 return tevent_req_post(req, ev);
2884 tevent_req_set_callback(subreq, cli_tdis_done, req);
2888 static void cli_tdis_done(struct tevent_req *subreq)
2890 struct tevent_req *req = tevent_req_callback_data(
2891 subreq, struct tevent_req);
2892 struct cli_tdis_state *state = tevent_req_data(
2893 req, struct cli_tdis_state);
2896 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2897 TALLOC_FREE(subreq);
2898 if (!NT_STATUS_IS_OK(status)) {
2899 tevent_req_nterror(req, status);
2902 cli_state_set_tid(state->cli, UINT16_MAX);
2903 tevent_req_done(req);
2906 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2908 return tevent_req_simple_recv_ntstatus(req);
2911 NTSTATUS cli_tdis(struct cli_state *cli)
2913 struct tevent_context *ev;
2914 struct tevent_req *req;
2915 NTSTATUS status = NT_STATUS_NO_MEMORY;
2917 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2918 return smb2cli_tdis(cli->conn,
2924 if (smbXcli_conn_has_async_calls(cli->conn)) {
2925 return NT_STATUS_INVALID_PARAMETER;
2927 ev = samba_tevent_context_init(talloc_tos());
2931 req = cli_tdis_send(ev, ev, cli);
2935 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2938 status = cli_tdis_recv(req);
2944 struct cli_connect_sock_state {
2945 const char **called_names;
2946 const char **calling_names;
2952 static void cli_connect_sock_done(struct tevent_req *subreq);
2955 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2959 static struct tevent_req *cli_connect_sock_send(
2960 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2961 const char *host, int name_type, const struct sockaddr_storage *pss,
2962 const char *myname, uint16_t port)
2964 struct tevent_req *req, *subreq;
2965 struct cli_connect_sock_state *state;
2967 struct sockaddr_storage *addrs;
2968 unsigned i, num_addrs;
2971 req = tevent_req_create(mem_ctx, &state,
2972 struct cli_connect_sock_state);
2977 prog = getenv("LIBSMB_PROG");
2979 state->fd = sock_exec(prog);
2980 if (state->fd == -1) {
2981 status = map_nt_error_from_unix(errno);
2982 tevent_req_nterror(req, status);
2985 tevent_req_done(req);
2987 return tevent_req_post(req, ev);
2990 if ((pss == NULL) || is_zero_addr(pss)) {
2993 * Here we cheat. resolve_name_list is not async at all. So
2994 * this call will only be really async if the name lookup has
2995 * been done externally.
2998 status = resolve_name_list(state, host, name_type,
2999 &addrs, &num_addrs);
3000 if (!NT_STATUS_IS_OK(status)) {
3001 tevent_req_nterror(req, status);
3002 return tevent_req_post(req, ev);
3005 addrs = talloc_array(state, struct sockaddr_storage, 1);
3006 if (tevent_req_nomem(addrs, req)) {
3007 return tevent_req_post(req, ev);
3013 state->called_names = talloc_array(state, const char *, num_addrs);
3014 if (tevent_req_nomem(state->called_names, req)) {
3015 return tevent_req_post(req, ev);
3017 state->called_types = talloc_array(state, int, num_addrs);
3018 if (tevent_req_nomem(state->called_types, req)) {
3019 return tevent_req_post(req, ev);
3021 state->calling_names = talloc_array(state, const char *, num_addrs);
3022 if (tevent_req_nomem(state->calling_names, req)) {
3023 return tevent_req_post(req, ev);
3025 for (i=0; i<num_addrs; i++) {
3026 state->called_names[i] = host;
3027 state->called_types[i] = name_type;
3028 state->calling_names[i] = myname;
3031 subreq = smbsock_any_connect_send(
3032 state, ev, addrs, state->called_names, state->called_types,
3033 state->calling_names, NULL, num_addrs, port);
3034 if (tevent_req_nomem(subreq, req)) {
3035 return tevent_req_post(req, ev);
3037 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3041 static void cli_connect_sock_done(struct tevent_req *subreq)
3043 struct tevent_req *req = tevent_req_callback_data(
3044 subreq, struct tevent_req);
3045 struct cli_connect_sock_state *state = tevent_req_data(
3046 req, struct cli_connect_sock_state);
3049 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3051 TALLOC_FREE(subreq);
3052 if (tevent_req_nterror(req, status)) {
3055 set_socket_options(state->fd, lp_socket_options());
3056 tevent_req_done(req);
3059 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3060 int *pfd, uint16_t *pport)
3062 struct cli_connect_sock_state *state = tevent_req_data(
3063 req, struct cli_connect_sock_state);
3066 if (tevent_req_is_nterror(req, &status)) {
3070 *pport = state->port;
3071 return NT_STATUS_OK;
3074 struct cli_connect_nb_state {
3075 const char *desthost;
3078 struct cli_state *cli;
3081 static void cli_connect_nb_done(struct tevent_req *subreq);
3083 static struct tevent_req *cli_connect_nb_send(
3084 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3085 const char *host, const struct sockaddr_storage *dest_ss,
3086 uint16_t port, int name_type, const char *myname,
3087 int signing_state, int flags)
3089 struct tevent_req *req, *subreq;
3090 struct cli_connect_nb_state *state;
3092 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3096 state->signing_state = signing_state;
3097 state->flags = flags;
3100 char *p = strchr(host, '#');
3103 name_type = strtol(p+1, NULL, 16);
3104 host = talloc_strndup(state, host, p - host);
3105 if (tevent_req_nomem(host, req)) {
3106 return tevent_req_post(req, ev);
3110 state->desthost = host;
3111 } else if (dest_ss != NULL) {
3112 state->desthost = print_canonical_sockaddr(state, dest_ss);
3113 if (tevent_req_nomem(state->desthost, req)) {
3114 return tevent_req_post(req, ev);
3117 /* No host or dest_ss given. Error out. */
3118 tevent_req_error(req, EINVAL);
3119 return tevent_req_post(req, ev);
3122 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3124 if (tevent_req_nomem(subreq, req)) {
3125 return tevent_req_post(req, ev);
3127 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3131 static void cli_connect_nb_done(struct tevent_req *subreq)
3133 struct tevent_req *req = tevent_req_callback_data(
3134 subreq, struct tevent_req);
3135 struct cli_connect_nb_state *state = tevent_req_data(
3136 req, struct cli_connect_nb_state);
3141 status = cli_connect_sock_recv(subreq, &fd, &port);
3142 TALLOC_FREE(subreq);
3143 if (tevent_req_nterror(req, status)) {
3147 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3148 state->signing_state, state->flags);
3149 if (tevent_req_nomem(state->cli, req)) {
3153 tevent_req_done(req);
3156 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3157 struct cli_state **pcli)
3159 struct cli_connect_nb_state *state = tevent_req_data(
3160 req, struct cli_connect_nb_state);
3163 if (tevent_req_is_nterror(req, &status)) {
3166 *pcli = talloc_move(NULL, &state->cli);
3167 return NT_STATUS_OK;
3170 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3171 uint16_t port, int name_type, const char *myname,
3172 int signing_state, int flags, struct cli_state **pcli)
3174 struct tevent_context *ev;
3175 struct tevent_req *req;
3176 NTSTATUS status = NT_STATUS_NO_MEMORY;
3178 ev = samba_tevent_context_init(talloc_tos());
3182 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3183 myname, signing_state, flags);
3187 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3190 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3193 status = cli_connect_nb_recv(req, pcli);
3199 struct cli_start_connection_state {
3200 struct tevent_context *ev;
3201 struct cli_state *cli;
3206 static void cli_start_connection_connected(struct tevent_req *subreq);
3207 static void cli_start_connection_done(struct tevent_req *subreq);
3210 establishes a connection to after the negprot.
3211 @param output_cli A fully initialised cli structure, non-null only on success
3212 @param dest_host The netbios name of the remote host
3213 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3214 @param port (optional) The destination port (0 for default)
3217 static struct tevent_req *cli_start_connection_send(
3218 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3219 const char *my_name, const char *dest_host,
3220 const struct sockaddr_storage *dest_ss, int port,
3221 int signing_state, int flags)
3223 struct tevent_req *req, *subreq;
3224 struct cli_start_connection_state *state;
3226 req = tevent_req_create(mem_ctx, &state,
3227 struct cli_start_connection_state);
3233 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3234 state->min_protocol = lp_client_ipc_min_protocol();
3235 state->max_protocol = lp_client_ipc_max_protocol();
3237 state->min_protocol = lp_client_min_protocol();
3238 state->max_protocol = lp_client_max_protocol();
3241 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3242 0x20, my_name, signing_state, flags);
3243 if (tevent_req_nomem(subreq, req)) {
3244 return tevent_req_post(req, ev);
3246 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3250 static void cli_start_connection_connected(struct tevent_req *subreq)
3252 struct tevent_req *req = tevent_req_callback_data(
3253 subreq, struct tevent_req);
3254 struct cli_start_connection_state *state = tevent_req_data(
3255 req, struct cli_start_connection_state);
3258 status = cli_connect_nb_recv(subreq, &state->cli);
3259 TALLOC_FREE(subreq);
3260 if (tevent_req_nterror(req, status)) {
3264 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3265 state->cli->timeout,
3266 state->min_protocol,
3267 state->max_protocol);
3268 if (tevent_req_nomem(subreq, req)) {
3271 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3274 static void cli_start_connection_done(struct tevent_req *subreq)
3276 struct tevent_req *req = tevent_req_callback_data(
3277 subreq, struct tevent_req);
3278 struct cli_start_connection_state *state = tevent_req_data(
3279 req, struct cli_start_connection_state);
3282 status = smbXcli_negprot_recv(subreq);
3283 TALLOC_FREE(subreq);
3284 if (tevent_req_nterror(req, status)) {
3288 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3289 /* Ensure we ask for some initial credits. */
3290 smb2cli_conn_set_max_credits(state->cli->conn,
3291 DEFAULT_SMB2_MAX_CREDITS);
3294 tevent_req_done(req);
3297 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3298 struct cli_state **output_cli)
3300 struct cli_start_connection_state *state = tevent_req_data(
3301 req, struct cli_start_connection_state);
3304 if (tevent_req_is_nterror(req, &status)) {
3307 *output_cli = state->cli;
3309 return NT_STATUS_OK;
3312 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3313 const char *my_name,
3314 const char *dest_host,
3315 const struct sockaddr_storage *dest_ss, int port,
3316 int signing_state, int flags)
3318 struct tevent_context *ev;
3319 struct tevent_req *req;
3320 NTSTATUS status = NT_STATUS_NO_MEMORY;
3322 ev = samba_tevent_context_init(talloc_tos());
3326 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3327 port, signing_state, flags);
3331 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3334 status = cli_start_connection_recv(req, output_cli);
3341 establishes a connection right up to doing tconX, password specified.
3342 @param output_cli A fully initialised cli structure, non-null only on success
3343 @param dest_host The netbios name of the remote host
3344 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3345 @param port (optional) The destination port (0 for default)
3346 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3347 @param service_type The 'type' of serivice.
3348 @param user Username, unix string
3349 @param domain User's domain
3350 @param password User's password, unencrypted unix string.
3353 struct cli_full_connection_state {
3354 struct tevent_context *ev;
3355 const char *service;
3356 const char *service_type;
3359 const char *password;
3362 struct cli_state *cli;
3365 static int cli_full_connection_state_destructor(
3366 struct cli_full_connection_state *s);
3367 static void cli_full_connection_started(struct tevent_req *subreq);
3368 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3369 static void cli_full_connection_done(struct tevent_req *subreq);
3371 struct tevent_req *cli_full_connection_send(
3372 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3373 const char *my_name, const char *dest_host,
3374 const struct sockaddr_storage *dest_ss, int port,
3375 const char *service, const char *service_type,
3376 const char *user, const char *domain,
3377 const char *password, int flags, int signing_state)
3379 struct tevent_req *req, *subreq;
3380 struct cli_full_connection_state *state;
3382 req = tevent_req_create(mem_ctx, &state,
3383 struct cli_full_connection_state);
3387 talloc_set_destructor(state, cli_full_connection_state_destructor);
3390 state->service = service;
3391 state->service_type = service_type;
3393 state->domain = domain;
3394 state->password = password;
3395 state->flags = flags;
3397 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3398 if (state->password == NULL) {
3399 state->password = "";
3402 subreq = cli_start_connection_send(
3403 state, ev, my_name, dest_host, dest_ss, port,
3404 signing_state, flags);
3405 if (tevent_req_nomem(subreq, req)) {
3406 return tevent_req_post(req, ev);
3408 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3412 static int cli_full_connection_state_destructor(
3413 struct cli_full_connection_state *s)
3415 if (s->cli != NULL) {
3416 cli_shutdown(s->cli);
3422 static void cli_full_connection_started(struct tevent_req *subreq)
3424 struct tevent_req *req = tevent_req_callback_data(
3425 subreq, struct tevent_req);
3426 struct cli_full_connection_state *state = tevent_req_data(
3427 req, struct cli_full_connection_state);
3430 status = cli_start_connection_recv(subreq, &state->cli);
3431 TALLOC_FREE(subreq);
3432 if (tevent_req_nterror(req, status)) {
3435 subreq = cli_session_setup_send(
3436 state, state->ev, state->cli, state->user,
3437 state->password, state->pw_len, state->password, state->pw_len,
3439 if (tevent_req_nomem(subreq, req)) {
3442 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3445 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3447 struct tevent_req *req = tevent_req_callback_data(
3448 subreq, struct tevent_req);
3449 struct cli_full_connection_state *state = tevent_req_data(
3450 req, struct cli_full_connection_state);
3453 status = cli_session_setup_recv(subreq);
3454 TALLOC_FREE(subreq);
3456 if (!NT_STATUS_IS_OK(status) &&
3457 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3459 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3461 subreq = cli_session_setup_send(
3462 state, state->ev, state->cli, "", "", 0, "", 0,
3464 if (tevent_req_nomem(subreq, req)) {
3467 tevent_req_set_callback(
3468 subreq, cli_full_connection_sess_set_up, req);
3472 if (tevent_req_nterror(req, status)) {
3476 if (state->service != NULL) {
3477 subreq = cli_tree_connect_send(
3478 state, state->ev, state->cli,
3479 state->service, state->service_type,
3480 state->password, state->pw_len);
3481 if (tevent_req_nomem(subreq, req)) {
3484 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3488 tevent_req_done(req);
3491 static void cli_full_connection_done(struct tevent_req *subreq)
3493 struct tevent_req *req = tevent_req_callback_data(
3494 subreq, struct tevent_req);
3497 status = cli_tree_connect_recv(subreq);
3498 TALLOC_FREE(subreq);
3499 if (tevent_req_nterror(req, status)) {
3503 tevent_req_done(req);
3506 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3507 struct cli_state **output_cli)
3509 struct cli_full_connection_state *state = tevent_req_data(
3510 req, struct cli_full_connection_state);
3513 if (tevent_req_is_nterror(req, &status)) {
3516 *output_cli = state->cli;
3517 talloc_set_destructor(state, NULL);
3518 return NT_STATUS_OK;
3521 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3522 const char *my_name,
3523 const char *dest_host,
3524 const struct sockaddr_storage *dest_ss, int port,
3525 const char *service, const char *service_type,
3526 const char *user, const char *domain,
3527 const char *password, int flags,
3530 struct tevent_context *ev;
3531 struct tevent_req *req;
3532 NTSTATUS status = NT_STATUS_NO_MEMORY;
3534 ev = samba_tevent_context_init(talloc_tos());
3538 req = cli_full_connection_send(
3539 ev, ev, my_name, dest_host, dest_ss, port, service,
3540 service_type, user, domain, password, flags, signing_state);
3544 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3547 status = cli_full_connection_recv(req, output_cli);
3553 /****************************************************************************
3554 Send an old style tcon.
3555 ****************************************************************************/
3556 struct cli_raw_tcon_state {
3560 static void cli_raw_tcon_done(struct tevent_req *subreq);
3562 static struct tevent_req *cli_raw_tcon_send(
3563 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3564 const char *service, const char *pass, const char *dev)
3566 struct tevent_req *req, *subreq;
3567 struct cli_raw_tcon_state *state;
3570 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3575 if (!lp_client_plaintext_auth() && (*pass)) {
3576 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3577 " or 'client ntlmv2 auth = yes'\n"));
3578 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3579 return tevent_req_post(req, ev);
3582 bytes = talloc_array(state, uint8_t, 0);
3583 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3584 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3585 service, strlen(service)+1, NULL);
3586 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3587 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3588 pass, strlen(pass)+1, NULL);
3589 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3590 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3591 dev, strlen(dev)+1, NULL);
3593 if (tevent_req_nomem(bytes, req)) {
3594 return tevent_req_post(req, ev);
3597 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3598 talloc_get_size(bytes), bytes);
3599 if (tevent_req_nomem(subreq, req)) {
3600 return tevent_req_post(req, ev);
3602 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3606 static void cli_raw_tcon_done(struct tevent_req *subreq)
3608 struct tevent_req *req = tevent_req_callback_data(
3609 subreq, struct tevent_req);
3610 struct cli_raw_tcon_state *state = tevent_req_data(
3611 req, struct cli_raw_tcon_state);
3614 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3616 TALLOC_FREE(subreq);
3617 if (tevent_req_nterror(req, status)) {
3620 tevent_req_done(req);
3623 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3624 uint16_t *max_xmit, uint16_t *tid)
3626 struct cli_raw_tcon_state *state = tevent_req_data(
3627 req, struct cli_raw_tcon_state);
3630 if (tevent_req_is_nterror(req, &status)) {
3633 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3634 *tid = SVAL(state->ret_vwv + 1, 0);
3635 return NT_STATUS_OK;
3638 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3639 const char *service, const char *pass, const char *dev,
3640 uint16_t *max_xmit, uint16_t *tid)
3642 struct tevent_context *ev;
3643 struct tevent_req *req;
3644 NTSTATUS status = NT_STATUS_NO_MEMORY;
3646 ev = samba_tevent_context_init(talloc_tos());
3650 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3654 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3657 status = cli_raw_tcon_recv(req, max_xmit, tid);
3663 /* Return a cli_state pointing at the IPC$ share for the given server */
3665 struct cli_state *get_ipc_connect(char *server,
3666 struct sockaddr_storage *server_ss,
3667 const struct user_auth_info *user_info)
3669 struct cli_state *cli;
3671 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3673 if (user_info->use_kerberos) {
3674 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3677 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3678 user_info->username ? user_info->username : "",
3680 user_info->password ? user_info->password : "",
3682 SMB_SIGNING_DEFAULT);
3684 if (NT_STATUS_IS_OK(nt_status)) {
3686 } else if (is_ipaddress(server)) {
3687 /* windows 9* needs a correct NMB name for connections */
3688 fstring remote_name;
3690 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3691 cli = get_ipc_connect(remote_name, server_ss, user_info);
3700 * Given the IP address of a master browser on the network, return its
3701 * workgroup and connect to it.
3703 * This function is provided to allow additional processing beyond what
3704 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3705 * browsers and obtain each master browsers' list of domains (in case the
3706 * first master browser is recently on the network and has not yet
3707 * synchronized with other master browsers and therefore does not yet have the
3708 * entire network browse list)
3711 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3712 struct sockaddr_storage *mb_ip,
3713 const struct user_auth_info *user_info,
3714 char **pp_workgroup_out)
3716 char addr[INET6_ADDRSTRLEN];
3718 struct cli_state *cli;
3719 struct sockaddr_storage server_ss;
3721 *pp_workgroup_out = NULL;
3723 print_sockaddr(addr, sizeof(addr), mb_ip);
3724 DEBUG(99, ("Looking up name of master browser %s\n",
3728 * Do a name status query to find out the name of the master browser.
3729 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3730 * master browser will not respond to a wildcard query (or, at least,
3731 * an NT4 server acting as the domain master browser will not).
3733 * We might be able to use ONLY the query on MSBROWSE, but that's not
3734 * yet been tested with all Windows versions, so until it is, leave
3735 * the original wildcard query as the first choice and fall back to
3736 * MSBROWSE if the wildcard query fails.
3738 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3739 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3741 DEBUG(99, ("Could not retrieve name status for %s\n",
3746 if (!find_master_ip(name, &server_ss)) {
3747 DEBUG(99, ("Could not find master ip for %s\n", name));
3751 *pp_workgroup_out = talloc_strdup(ctx, name);
3753 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3755 print_sockaddr(addr, sizeof(addr), &server_ss);
3756 cli = get_ipc_connect(addr, &server_ss, user_info);
3762 * Return the IP address and workgroup of a master browser on the network, and
3766 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3767 const struct user_auth_info *user_info,
3768 char **pp_workgroup_out)
3770 struct sockaddr_storage *ip_list;
3771 struct cli_state *cli;
3775 *pp_workgroup_out = NULL;
3777 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3779 /* Go looking for workgroups by broadcasting on the local network */
3781 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3783 if (!NT_STATUS_IS_OK(status)) {
3784 DEBUG(99, ("No master browsers responded: %s\n",
3785 nt_errstr(status)));
3789 for (i = 0; i < count; i++) {
3790 char addr[INET6_ADDRSTRLEN];
3791 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3792 DEBUG(99, ("Found master browser %s\n", addr));
3794 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3795 user_info, pp_workgroup_out);