2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
29 #include "../auth/ntlmssp/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "librpc/ndr/libndr.h"
36 #include "../libcli/smb/smbXcli_base.h"
38 #define STAR_SMBSERVER "*SMBSERVER"
40 /********************************************************
41 Utility function to ensure we always return at least
42 a valid char * pointer to an empty string for the
43 cli->server_os, cli->server_type and cli->server_domain
45 *******************************************************/
47 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
54 *destlen = clistr_pull_talloc(mem_ctx,
62 return NT_STATUS_NO_MEMORY;
66 *dest = talloc_strdup(mem_ctx, "");
68 return NT_STATUS_NO_MEMORY;
74 /****************************************************************************
75 Do an old lanman2 style session setup.
76 ****************************************************************************/
78 struct cli_session_setup_lanman2_state {
79 struct cli_state *cli;
84 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
86 static struct tevent_req *cli_session_setup_lanman2_send(
87 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
88 struct cli_state *cli, const char *user,
89 const char *pass, size_t passlen,
90 const char *workgroup)
92 struct tevent_req *req, *subreq;
93 struct cli_session_setup_lanman2_state *state;
94 DATA_BLOB lm_response = data_blob_null;
98 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
100 req = tevent_req_create(mem_ctx, &state,
101 struct cli_session_setup_lanman2_state);
110 * if in share level security then don't send a password now
112 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
117 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
120 * Encrypted mode needed, and non encrypted password
123 lm_response = data_blob(NULL, 24);
124 if (tevent_req_nomem(lm_response.data, req)) {
125 return tevent_req_post(req, ev);
128 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
129 (uint8_t *)lm_response.data)) {
130 DEBUG(1, ("Password is > 14 chars in length, and is "
131 "therefore incompatible with Lanman "
132 "authentication\n"));
133 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
134 return tevent_req_post(req, ev);
136 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
139 * Encrypted mode needed, and encrypted password
142 lm_response = data_blob(pass, passlen);
143 if (tevent_req_nomem(lm_response.data, req)) {
144 return tevent_req_post(req, ev);
146 } else if (passlen > 0) {
148 size_t converted_size;
150 * Plaintext mode needed, assume plaintext supplied.
152 buf = talloc_array(talloc_tos(), uint8_t, 0);
153 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
155 if (tevent_req_nomem(buf, req)) {
156 return tevent_req_post(req, ev);
158 lm_response = data_blob(pass, passlen);
160 if (tevent_req_nomem(lm_response.data, req)) {
161 return tevent_req_post(req, ev);
165 SCVAL(vwv+0, 0, 0xff);
168 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
171 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
172 SSVAL(vwv+7, 0, lm_response.length);
174 bytes = talloc_array(state, uint8_t, lm_response.length);
175 if (tevent_req_nomem(bytes, req)) {
176 return tevent_req_post(req, ev);
178 if (lm_response.length != 0) {
179 memcpy(bytes, lm_response.data, lm_response.length);
181 data_blob_free(&lm_response);
183 tmp = talloc_strdup_upper(talloc_tos(), user);
184 if (tevent_req_nomem(tmp, req)) {
185 return tevent_req_post(req, ev);
187 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
191 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
192 if (tevent_req_nomem(tmp, req)) {
193 return tevent_req_post(req, ev);
195 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
197 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
200 if (tevent_req_nomem(bytes, req)) {
201 return tevent_req_post(req, ev);
204 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
205 talloc_get_size(bytes), bytes);
206 if (tevent_req_nomem(subreq, req)) {
207 return tevent_req_post(req, ev);
209 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
213 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
215 struct tevent_req *req = tevent_req_callback_data(
216 subreq, struct tevent_req);
217 struct cli_session_setup_lanman2_state *state = tevent_req_data(
218 req, struct cli_session_setup_lanman2_state);
219 struct cli_state *cli = state->cli;
230 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
233 if (!NT_STATUS_IS_OK(status)) {
234 tevent_req_nterror(req, status);
238 inhdr = in + NBT_HDR_SIZE;
241 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
243 status = smb_bytes_talloc_string(cli,
250 if (!NT_STATUS_IS_OK(status)) {
251 tevent_req_nterror(req, status);
256 status = smb_bytes_talloc_string(cli,
263 if (!NT_STATUS_IS_OK(status)) {
264 tevent_req_nterror(req, status);
269 status = smb_bytes_talloc_string(cli,
276 if (!NT_STATUS_IS_OK(status)) {
277 tevent_req_nterror(req, status);
282 status = cli_set_username(cli, state->user);
283 if (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));
450 status = smb_bytes_talloc_string(cli,
457 if (!NT_STATUS_IS_OK(status)) {
458 tevent_req_nterror(req, status);
463 status = smb_bytes_talloc_string(cli,
470 if (!NT_STATUS_IS_OK(status)) {
471 tevent_req_nterror(req, status);
476 status = smb_bytes_talloc_string(cli,
483 if (!NT_STATUS_IS_OK(status)) {
484 tevent_req_nterror(req, status);
489 status = cli_set_username(cli, "");
490 if (!NT_STATUS_IS_OK(status)) {
491 tevent_req_nterror(req, status);
494 tevent_req_done(req);
497 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
499 return tevent_req_simple_recv_ntstatus(req);
502 /****************************************************************************
503 Do a NT1 plaintext session setup.
504 ****************************************************************************/
506 struct cli_session_setup_plain_state {
507 struct cli_state *cli;
512 static void cli_session_setup_plain_done(struct tevent_req *subreq);
514 static struct tevent_req *cli_session_setup_plain_send(
515 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
516 struct cli_state *cli,
517 const char *user, const char *pass, const char *workgroup)
519 struct tevent_req *req, *subreq;
520 struct cli_session_setup_plain_state *state;
526 req = tevent_req_create(mem_ctx, &state,
527 struct cli_session_setup_plain_state);
535 SCVAL(vwv+0, 0, 0xff);
538 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
540 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
541 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
546 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
548 bytes = talloc_array(state, uint8_t, 0);
549 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
551 if (tevent_req_nomem(bytes, req)) {
552 return tevent_req_post(req, ev);
554 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
556 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
557 user, strlen(user)+1, NULL);
558 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
559 workgroup, strlen(workgroup)+1, NULL);
560 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
563 version = talloc_asprintf(talloc_tos(), "Samba %s",
564 samba_version_string());
565 if (tevent_req_nomem(version, req)){
566 return tevent_req_post(req, ev);
568 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
569 version, strlen(version)+1, NULL);
570 TALLOC_FREE(version);
572 if (tevent_req_nomem(bytes, req)) {
573 return tevent_req_post(req, ev);
576 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
577 talloc_get_size(bytes), bytes);
578 if (tevent_req_nomem(subreq, req)) {
579 return tevent_req_post(req, ev);
581 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
585 static void cli_session_setup_plain_done(struct tevent_req *subreq)
587 struct tevent_req *req = tevent_req_callback_data(
588 subreq, struct tevent_req);
589 struct cli_session_setup_plain_state *state = tevent_req_data(
590 req, struct cli_session_setup_plain_state);
591 struct cli_state *cli = state->cli;
602 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
605 if (tevent_req_nterror(req, status)) {
609 inhdr = in + NBT_HDR_SIZE;
612 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
614 status = smb_bytes_talloc_string(cli,
621 if (!NT_STATUS_IS_OK(status)) {
622 tevent_req_nterror(req, status);
627 status = smb_bytes_talloc_string(cli,
634 if (!NT_STATUS_IS_OK(status)) {
635 tevent_req_nterror(req, status);
640 status = smb_bytes_talloc_string(cli,
647 if (!NT_STATUS_IS_OK(status)) {
648 tevent_req_nterror(req, status);
653 status = cli_set_username(cli, state->user);
654 if (tevent_req_nterror(req, status)) {
658 tevent_req_done(req);
661 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
663 return tevent_req_simple_recv_ntstatus(req);
666 /****************************************************************************
667 do a NT1 NTLM/LM encrypted session setup - for when extended security
669 @param cli client state to create do session setup on
671 @param pass *either* cleartext password (passlen !=24) or LM response.
672 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
673 @param workgroup The user's domain.
674 ****************************************************************************/
676 struct cli_session_setup_nt1_state {
677 struct cli_state *cli;
680 DATA_BLOB session_key;
684 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
686 static struct tevent_req *cli_session_setup_nt1_send(
687 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
688 struct cli_state *cli, const char *user,
689 const char *pass, size_t passlen,
690 const char *ntpass, size_t ntpasslen,
691 const char *workgroup)
693 struct tevent_req *req, *subreq;
694 struct cli_session_setup_nt1_state *state;
695 DATA_BLOB lm_response = data_blob_null;
696 DATA_BLOB nt_response = data_blob_null;
697 DATA_BLOB session_key = data_blob_null;
700 char *workgroup_upper;
702 req = tevent_req_create(mem_ctx, &state,
703 struct cli_session_setup_nt1_state);
712 /* do nothing - guest login */
713 } else if (passlen != 24) {
714 if (lp_client_ntlmv2_auth()) {
715 DATA_BLOB server_chal;
716 DATA_BLOB names_blob;
719 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
723 * note that the 'workgroup' here is a best
724 * guess - we don't know the server's domain
725 * at this point. Windows clients also don't
728 names_blob = NTLMv2_generate_names_blob(
729 NULL, NULL, workgroup);
731 if (tevent_req_nomem(names_blob.data, req)) {
732 return tevent_req_post(req, ev);
735 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
736 &server_chal, &names_blob,
737 &lm_response, &nt_response,
738 NULL, &session_key)) {
739 data_blob_free(&names_blob);
741 req, NT_STATUS_ACCESS_DENIED);
742 return tevent_req_post(req, ev);
744 data_blob_free(&names_blob);
748 E_md4hash(pass, nt_hash);
751 nt_response = data_blob_null;
753 nt_response = data_blob(NULL, 24);
754 if (tevent_req_nomem(nt_response.data, req)) {
755 return tevent_req_post(req, ev);
758 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
761 /* non encrypted password supplied. Ignore ntpass. */
762 if (lp_client_lanman_auth()) {
764 lm_response = data_blob(NULL, 24);
765 if (tevent_req_nomem(lm_response.data, req)) {
766 return tevent_req_post(req, ev);
769 if (!SMBencrypt(pass,
770 smb1cli_conn_server_challenge(cli->conn),
773 * Oops, the LM response is
774 * invalid, just put the NT
775 * response there instead
777 data_blob_free(&lm_response);
778 lm_response = data_blob(
784 * LM disabled, place NT# in LM field
787 lm_response = data_blob(
788 nt_response.data, nt_response.length);
791 if (tevent_req_nomem(lm_response.data, req)) {
792 return tevent_req_post(req, ev);
795 session_key = data_blob(NULL, 16);
796 if (tevent_req_nomem(session_key.data, req)) {
797 return tevent_req_post(req, ev);
800 E_deshash(pass, session_key.data);
801 memset(&session_key.data[8], '\0', 8);
803 SMBsesskeygen_ntv1(nt_hash, session_key.data);
807 /* pre-encrypted password supplied. Only used for
808 security=server, can't do
809 signing because we don't have original key */
811 lm_response = data_blob(pass, passlen);
812 if (tevent_req_nomem(lm_response.data, req)) {
813 return tevent_req_post(req, ev);
816 nt_response = data_blob(ntpass, ntpasslen);
817 if (tevent_req_nomem(nt_response.data, req)) {
818 return tevent_req_post(req, ev);
823 state->response = data_blob_talloc(
824 state, lm_response.data, lm_response.length);
826 state->response = data_blob_talloc(
827 state, nt_response.data, nt_response.length);
829 if (tevent_req_nomem(state->response.data, req)) {
830 return tevent_req_post(req, ev);
833 if (session_key.data) {
834 state->session_key = data_blob_talloc(
835 state, session_key.data, session_key.length);
836 if (tevent_req_nomem(state->session_key.data, req)) {
837 return tevent_req_post(req, ev);
840 data_blob_free(&session_key);
842 SCVAL(vwv+0, 0, 0xff);
845 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
847 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
848 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
849 SSVAL(vwv+7, 0, lm_response.length);
850 SSVAL(vwv+8, 0, nt_response.length);
853 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
855 bytes = talloc_array(state, uint8_t,
856 lm_response.length + nt_response.length);
857 if (tevent_req_nomem(bytes, req)) {
858 return tevent_req_post(req, ev);
860 if (lm_response.length != 0) {
861 memcpy(bytes, lm_response.data, lm_response.length);
863 if (nt_response.length != 0) {
864 memcpy(bytes + lm_response.length,
865 nt_response.data, nt_response.length);
867 data_blob_free(&lm_response);
868 data_blob_free(&nt_response);
870 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
871 user, strlen(user)+1, NULL);
874 * Upper case here might help some NTLMv2 implementations
876 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
877 if (tevent_req_nomem(workgroup_upper, req)) {
878 return tevent_req_post(req, ev);
880 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
881 workgroup_upper, strlen(workgroup_upper)+1,
883 TALLOC_FREE(workgroup_upper);
885 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
886 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
887 if (tevent_req_nomem(bytes, req)) {
888 return tevent_req_post(req, ev);
891 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
892 talloc_get_size(bytes), bytes);
893 if (tevent_req_nomem(subreq, req)) {
894 return tevent_req_post(req, ev);
896 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
900 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
902 struct tevent_req *req = tevent_req_callback_data(
903 subreq, struct tevent_req);
904 struct cli_session_setup_nt1_state *state = tevent_req_data(
905 req, struct cli_session_setup_nt1_state);
906 struct cli_state *cli = state->cli;
917 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
920 if (!NT_STATUS_IS_OK(status)) {
921 tevent_req_nterror(req, status);
925 inhdr = in + NBT_HDR_SIZE;
928 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
930 status = smb_bytes_talloc_string(cli,
936 if (!NT_STATUS_IS_OK(status)) {
937 tevent_req_nterror(req, status);
942 status = smb_bytes_talloc_string(cli,
948 if (!NT_STATUS_IS_OK(status)) {
949 tevent_req_nterror(req, status);
954 status = smb_bytes_talloc_string(cli,
960 if (!NT_STATUS_IS_OK(status)) {
961 tevent_req_nterror(req, status);
966 status = cli_set_username(cli, state->user);
967 if (tevent_req_nterror(req, status)) {
970 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
971 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
972 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
975 if (state->session_key.data) {
976 struct smbXcli_session *session = state->cli->smb1.session;
978 status = smb1cli_session_set_session_key(session,
980 if (tevent_req_nterror(req, status)) {
984 tevent_req_done(req);
987 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
989 return tevent_req_simple_recv_ntstatus(req);
992 /* The following is calculated from :
994 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
995 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
999 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1001 struct cli_sesssetup_blob_state {
1002 struct tevent_context *ev;
1003 struct cli_state *cli;
1005 uint16_t max_blob_size;
1009 DATA_BLOB smb2_blob;
1010 struct iovec *recv_iov;
1017 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1018 struct tevent_req **psubreq);
1019 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1021 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1022 struct tevent_context *ev,
1023 struct cli_state *cli,
1026 struct tevent_req *req, *subreq;
1027 struct cli_sesssetup_blob_state *state;
1028 uint32_t usable_space;
1030 req = tevent_req_create(mem_ctx, &state,
1031 struct cli_sesssetup_blob_state);
1039 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1040 usable_space = UINT16_MAX;
1042 usable_space = cli_state_available_size(cli,
1043 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1046 if (usable_space == 0) {
1047 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1048 "(not possible to send %u bytes)\n",
1049 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1050 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1051 return tevent_req_post(req, ev);
1053 state->max_blob_size = MIN(usable_space, 0xFFFF);
1055 if (!cli_sesssetup_blob_next(state, &subreq)) {
1056 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1057 return tevent_req_post(req, ev);
1059 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1063 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1064 struct tevent_req **psubreq)
1066 struct tevent_req *subreq;
1069 thistime = MIN(state->blob.length, state->max_blob_size);
1071 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1073 state->smb2_blob.data = state->blob.data;
1074 state->smb2_blob.length = thistime;
1076 state->blob.data += thistime;
1077 state->blob.length -= thistime;
1079 subreq = smb2cli_session_setup_send(state, state->ev,
1081 state->cli->timeout,
1082 state->cli->smb2.session,
1084 SMB2_CAP_DFS, /* in_capabilities */
1086 0, /* in_previous_session_id */
1088 if (subreq == NULL) {
1095 SCVAL(state->vwv+0, 0, 0xFF);
1096 SCVAL(state->vwv+0, 1, 0);
1097 SSVAL(state->vwv+1, 0, 0);
1098 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1099 SSVAL(state->vwv+3, 0, 2);
1100 SSVAL(state->vwv+4, 0, 1);
1101 SIVAL(state->vwv+5, 0, 0);
1103 SSVAL(state->vwv+7, 0, thistime);
1105 SSVAL(state->vwv+8, 0, 0);
1106 SSVAL(state->vwv+9, 0, 0);
1107 SIVAL(state->vwv+10, 0,
1108 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1110 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1112 if (state->buf == NULL) {
1115 state->blob.data += thistime;
1116 state->blob.length -= thistime;
1118 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1120 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1122 if (state->buf == NULL) {
1125 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1127 talloc_get_size(state->buf), state->buf);
1128 if (subreq == NULL) {
1135 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1137 struct tevent_req *req = tevent_req_callback_data(
1138 subreq, struct tevent_req);
1139 struct cli_sesssetup_blob_state *state = tevent_req_data(
1140 req, struct cli_sesssetup_blob_state);
1141 struct cli_state *cli = state->cli;
1148 uint16_t blob_length;
1153 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1154 status = smb2cli_session_setup_recv(subreq, state,
1158 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1159 &num_bytes, &bytes);
1160 TALLOC_FREE(state->buf);
1162 TALLOC_FREE(subreq);
1163 if (!NT_STATUS_IS_OK(status)
1164 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1165 tevent_req_nterror(req, status);
1169 state->status = status;
1171 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1176 inhdr = in + NBT_HDR_SIZE;
1177 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1179 blob_length = SVAL(vwv+3, 0);
1180 if (blob_length > num_bytes) {
1181 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1184 state->ret_blob = data_blob_const(bytes, blob_length);
1186 p = bytes + blob_length;
1188 status = smb_bytes_talloc_string(cli,
1195 if (!NT_STATUS_IS_OK(status)) {
1196 tevent_req_nterror(req, status);
1201 status = smb_bytes_talloc_string(cli,
1208 if (!NT_STATUS_IS_OK(status)) {
1209 tevent_req_nterror(req, status);
1214 status = smb_bytes_talloc_string(cli,
1216 &cli->server_domain,
1221 if (!NT_STATUS_IS_OK(status)) {
1222 tevent_req_nterror(req, status);
1228 if (state->blob.length != 0) {
1232 if (!cli_sesssetup_blob_next(state, &subreq)) {
1233 tevent_req_oom(req);
1236 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1239 tevent_req_done(req);
1242 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1243 TALLOC_CTX *mem_ctx,
1246 struct iovec **precv_iov)
1248 struct cli_sesssetup_blob_state *state = tevent_req_data(
1249 req, struct cli_sesssetup_blob_state);
1252 struct iovec *recv_iov;
1254 if (tevent_req_is_nterror(req, &status)) {
1255 TALLOC_FREE(state->cli->smb2.session);
1256 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1260 inbuf = talloc_move(mem_ctx, &state->inbuf);
1261 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1262 if (pblob != NULL) {
1263 *pblob = state->ret_blob;
1265 if (pinbuf != NULL) {
1268 if (precv_iov != NULL) {
1269 *precv_iov = recv_iov;
1271 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1272 return state->status;
1277 /****************************************************************************
1278 Use in-memory credentials cache
1279 ****************************************************************************/
1281 static void use_in_memory_ccache(void) {
1282 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1285 /****************************************************************************
1286 Do a spnego/kerberos encrypted session setup.
1287 ****************************************************************************/
1289 struct cli_session_setup_kerberos_state {
1290 struct cli_state *cli;
1291 DATA_BLOB negTokenTarg;
1292 DATA_BLOB session_key_krb5;
1293 ADS_STATUS ads_status;
1296 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1298 static struct tevent_req *cli_session_setup_kerberos_send(
1299 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1300 const char *principal)
1302 struct tevent_req *req, *subreq;
1303 struct cli_session_setup_kerberos_state *state;
1306 DEBUG(2,("Doing kerberos session setup\n"));
1308 req = tevent_req_create(mem_ctx, &state,
1309 struct cli_session_setup_kerberos_state);
1314 state->ads_status = ADS_SUCCESS;
1317 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1318 * we have to acquire a ticket. To be fixed later :-)
1320 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1321 &state->session_key_krb5, 0, NULL, NULL);
1323 DEBUG(1, ("cli_session_setup_kerberos: "
1324 "spnego_gen_krb5_negTokenInit failed: %s\n",
1325 error_message(rc)));
1326 state->ads_status = ADS_ERROR_KRB5(rc);
1327 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1328 return tevent_req_post(req, ev);
1332 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1333 state->negTokenTarg.length);
1336 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1337 state->cli->smb2.session = smbXcli_session_create(cli,
1339 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1340 return tevent_req_post(req, ev);
1344 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1345 if (tevent_req_nomem(subreq, req)) {
1346 return tevent_req_post(req, ev);
1348 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1352 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1354 struct tevent_req *req = tevent_req_callback_data(
1355 subreq, struct tevent_req);
1356 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1357 req, struct cli_session_setup_kerberos_state);
1358 uint8_t *inbuf = NULL;
1359 struct iovec *recv_iov = NULL;
1362 status = cli_sesssetup_blob_recv(subreq, state,
1363 NULL, &inbuf, &recv_iov);
1364 TALLOC_FREE(subreq);
1365 if (!NT_STATUS_IS_OK(status)) {
1366 tevent_req_nterror(req, status);
1370 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1371 struct smbXcli_session *session = state->cli->smb2.session;
1372 status = smb2cli_session_set_session_key(session,
1373 state->session_key_krb5,
1375 if (tevent_req_nterror(req, status)) {
1379 struct smbXcli_session *session = state->cli->smb1.session;
1381 status = smb1cli_session_set_session_key(session,
1382 state->session_key_krb5);
1383 if (tevent_req_nterror(req, status)) {
1387 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1389 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1390 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1395 tevent_req_done(req);
1398 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1400 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1401 req, struct cli_session_setup_kerberos_state);
1404 if (tevent_req_is_nterror(req, &status)) {
1405 return ADS_ERROR_NT(status);
1407 return state->ads_status;
1410 #endif /* HAVE_KRB5 */
1412 /****************************************************************************
1413 Do a spnego/NTLMSSP encrypted session setup.
1414 ****************************************************************************/
1416 struct cli_session_setup_ntlmssp_state {
1417 struct tevent_context *ev;
1418 struct cli_state *cli;
1419 struct ntlmssp_state *ntlmssp_state;
1424 static int cli_session_setup_ntlmssp_state_destructor(
1425 struct cli_session_setup_ntlmssp_state *state)
1427 if (state->ntlmssp_state != NULL) {
1428 TALLOC_FREE(state->ntlmssp_state);
1433 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1435 static struct tevent_req *cli_session_setup_ntlmssp_send(
1436 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1437 const char *user, const char *pass, const char *domain)
1439 struct tevent_req *req, *subreq;
1440 struct cli_session_setup_ntlmssp_state *state;
1443 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1445 req = tevent_req_create(mem_ctx, &state,
1446 struct cli_session_setup_ntlmssp_state);
1454 state->ntlmssp_state = NULL;
1455 talloc_set_destructor(
1456 state, cli_session_setup_ntlmssp_state_destructor);
1458 status = ntlmssp_client_start(state,
1461 lp_client_ntlmv2_auth(),
1462 &state->ntlmssp_state);
1463 if (!NT_STATUS_IS_OK(status)) {
1466 ntlmssp_want_feature(state->ntlmssp_state,
1467 NTLMSSP_FEATURE_SESSION_KEY);
1468 if (cli->use_ccache) {
1469 ntlmssp_want_feature(state->ntlmssp_state,
1470 NTLMSSP_FEATURE_CCACHE);
1472 status = ntlmssp_set_username(state->ntlmssp_state, user);
1473 if (!NT_STATUS_IS_OK(status)) {
1476 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1477 if (!NT_STATUS_IS_OK(status)) {
1480 if (cli->pw_nt_hash) {
1481 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1483 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1485 if (!NT_STATUS_IS_OK(status)) {
1488 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1490 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1494 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1495 data_blob_free(&blob_out);
1497 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1498 state->cli->smb2.session = smbXcli_session_create(cli,
1500 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1501 return tevent_req_post(req, ev);
1505 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1506 if (tevent_req_nomem(subreq, req)) {
1507 return tevent_req_post(req, ev);
1509 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1512 tevent_req_nterror(req, status);
1513 return tevent_req_post(req, ev);
1516 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1518 struct tevent_req *req = tevent_req_callback_data(
1519 subreq, struct tevent_req);
1520 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1521 req, struct cli_session_setup_ntlmssp_state);
1522 DATA_BLOB blob_in, msg_in, blob_out;
1523 uint8_t *inbuf = NULL;
1524 struct iovec *recv_iov = NULL;
1528 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1530 TALLOC_FREE(subreq);
1531 data_blob_free(&state->blob_out);
1533 if (NT_STATUS_IS_OK(status)) {
1534 if (state->cli->server_domain[0] == '\0') {
1535 TALLOC_FREE(state->cli->server_domain);
1536 state->cli->server_domain = talloc_strdup(state->cli,
1537 state->ntlmssp_state->server.netbios_domain);
1538 if (state->cli->server_domain == NULL) {
1539 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1544 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1545 struct smbXcli_session *session = state->cli->smb2.session;
1547 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1549 * Windows server does not set the
1550 * SMB2_SESSION_FLAG_IS_GUEST nor
1551 * SMB2_SESSION_FLAG_IS_NULL flag.
1553 * This fix makes sure we do not try
1554 * to verify a signature on the final
1555 * session setup response.
1557 TALLOC_FREE(state->ntlmssp_state);
1558 tevent_req_done(req);
1562 status = smb2cli_session_set_session_key(session,
1563 state->ntlmssp_state->session_key,
1565 if (tevent_req_nterror(req, status)) {
1569 struct smbXcli_session *session = state->cli->smb1.session;
1571 status = smb1cli_session_set_session_key(session,
1572 state->ntlmssp_state->session_key);
1573 if (tevent_req_nterror(req, status)) {
1577 if (smb1cli_conn_activate_signing(
1578 state->cli->conn, state->ntlmssp_state->session_key,
1580 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1581 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1585 TALLOC_FREE(state->ntlmssp_state);
1586 tevent_req_done(req);
1589 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1590 tevent_req_nterror(req, status);
1594 if (blob_in.length == 0) {
1595 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1599 if ((state->turn == 1)
1600 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1601 DATA_BLOB tmp_blob = data_blob_null;
1602 /* the server might give us back two challenges */
1603 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1605 data_blob_free(&tmp_blob);
1607 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1608 OID_NTLMSSP, &msg_in);
1613 DEBUG(3,("Failed to parse auth response\n"));
1614 if (NT_STATUS_IS_OK(status)
1615 || NT_STATUS_EQUAL(status,
1616 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1618 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1623 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1625 if (!NT_STATUS_IS_OK(status)
1626 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1627 TALLOC_FREE(state->ntlmssp_state);
1628 tevent_req_nterror(req, status);
1632 state->blob_out = spnego_gen_auth(state, blob_out);
1633 if (tevent_req_nomem(state->blob_out.data, req)) {
1637 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1639 if (tevent_req_nomem(subreq, req)) {
1642 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1645 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1647 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1648 req, struct cli_session_setup_ntlmssp_state);
1651 if (tevent_req_is_nterror(req, &status)) {
1652 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1655 return NT_STATUS_OK;
1660 static char *cli_session_setup_get_principal(
1661 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1662 const char *remote_name, const char *dest_realm)
1664 char *principal = NULL;
1666 if (!lp_client_use_spnego_principal() ||
1667 strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1668 spnego_principal = NULL;
1670 if (spnego_principal != NULL) {
1671 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1672 "principal %s\n", spnego_principal));
1673 return talloc_strdup(mem_ctx, spnego_principal);
1675 if (is_ipaddress(remote_name) ||
1676 strequal(remote_name, STAR_SMBSERVER)) {
1680 DEBUG(3, ("cli_session_setup_spnego: using target "
1681 "hostname not SPNEGO principal\n"));
1684 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1685 if (realm == NULL) {
1688 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1689 remote_name, realm);
1692 principal = kerberos_get_principal_from_service_hostname(
1693 talloc_tos(), "cifs", remote_name, lp_realm());
1695 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1696 principal ? principal : "<null>"));
1702 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1703 const char *principal)
1707 account = talloc_strdup(mem_ctx, principal);
1708 if (account == NULL) {
1711 p = strchr_m(account, '@');
1718 /****************************************************************************
1719 Do a spnego encrypted session setup.
1721 user_domain: The shortname of the domain the user/machine is a member of.
1722 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1723 ****************************************************************************/
1725 struct cli_session_setup_spnego_state {
1726 struct tevent_context *ev;
1727 struct cli_state *cli;
1729 const char *account;
1731 const char *user_domain;
1732 const char *dest_realm;
1737 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1740 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1742 static struct tevent_req *cli_session_setup_spnego_send(
1743 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1744 const char *user, const char *pass, const char *user_domain,
1745 const char *dest_realm)
1747 struct tevent_req *req, *subreq;
1748 struct cli_session_setup_spnego_state *state;
1749 char *principal = NULL;
1750 char *OIDs[ASN1_MAX_OIDS];
1752 const DATA_BLOB *server_blob;
1755 req = tevent_req_create(mem_ctx, &state,
1756 struct cli_session_setup_spnego_state);
1764 state->user_domain = user_domain;
1765 state->dest_realm = dest_realm;
1767 state->account = cli_session_setup_get_account(state, user);
1768 if (tevent_req_nomem(state->account, req)) {
1769 return tevent_req_post(req, ev);
1772 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1774 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1775 (unsigned long)server_blob->length));
1777 /* the server might not even do spnego */
1778 if (server_blob->length == 0) {
1779 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1784 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1787 /* The server sent us the first part of the SPNEGO exchange in the
1788 * negprot reply. It is WRONG to depend on the principal sent in the
1789 * negprot reply, but right now we do it. If we don't receive one,
1790 * we try to best guess, then fall back to NTLM. */
1791 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1792 &principal, NULL) ||
1794 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1795 tevent_req_done(req);
1796 return tevent_req_post(req, ev);
1799 /* make sure the server understands kerberos */
1800 for (i=0;OIDs[i];i++) {
1802 DEBUG(3,("got OID=%s\n", OIDs[i]));
1804 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1805 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1806 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1807 cli->got_kerberos_mechanism = True;
1809 talloc_free(OIDs[i]);
1812 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1814 status = cli_set_username(cli, user);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 state->result = ADS_ERROR_NT(status);
1817 tevent_req_done(req);
1818 return tevent_req_post(req, ev);
1822 /* If password is set we reauthenticate to kerberos server
1823 * and do not store results */
1825 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1826 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1830 tmp = cli_session_setup_get_principal(
1831 talloc_tos(), principal, remote_name, dest_realm);
1832 TALLOC_FREE(principal);
1835 if (pass && *pass) {
1838 use_in_memory_ccache();
1839 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1842 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1843 TALLOC_FREE(principal);
1844 if (cli->fallback_after_kerberos)
1846 state->result = ADS_ERROR_KRB5(ret);
1847 tevent_req_done(req);
1848 return tevent_req_post(req, ev);
1853 subreq = cli_session_setup_kerberos_send(
1854 state, ev, cli, principal);
1855 if (tevent_req_nomem(subreq, req)) {
1856 return tevent_req_post(req, ev);
1858 tevent_req_set_callback(
1859 subreq, cli_session_setup_spnego_done_krb,
1867 subreq = cli_session_setup_ntlmssp_send(
1868 state, ev, cli, state->account, pass, user_domain);
1869 if (tevent_req_nomem(subreq, req)) {
1870 return tevent_req_post(req, ev);
1872 tevent_req_set_callback(
1873 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1878 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1880 struct tevent_req *req = tevent_req_callback_data(
1881 subreq, struct tevent_req);
1882 struct cli_session_setup_spnego_state *state = tevent_req_data(
1883 req, struct cli_session_setup_spnego_state);
1885 state->result = cli_session_setup_kerberos_recv(subreq);
1886 TALLOC_FREE(subreq);
1888 if (ADS_ERR_OK(state->result) ||
1889 !state->cli->fallback_after_kerberos) {
1890 tevent_req_done(req);
1894 subreq = cli_session_setup_ntlmssp_send(
1895 state, state->ev, state->cli, state->account, state->pass,
1896 state->user_domain);
1897 if (tevent_req_nomem(subreq, req)) {
1900 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1905 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1907 struct tevent_req *req = tevent_req_callback_data(
1908 subreq, struct tevent_req);
1909 struct cli_session_setup_spnego_state *state = tevent_req_data(
1910 req, struct cli_session_setup_spnego_state);
1913 status = cli_session_setup_ntlmssp_recv(subreq);
1914 TALLOC_FREE(subreq);
1915 state->result = ADS_ERROR_NT(status);
1916 tevent_req_done(req);
1919 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1921 struct cli_session_setup_spnego_state *state = tevent_req_data(
1922 req, struct cli_session_setup_spnego_state);
1924 return state->result;
1927 struct cli_session_setup_state {
1931 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1932 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1933 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1934 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1935 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1937 /****************************************************************************
1938 Send a session setup. The username and workgroup is in UNIX character
1939 format and must be converted to DOS codepage format before sending. If the
1940 password is in plaintext, the same should be done.
1941 ****************************************************************************/
1943 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1944 struct tevent_context *ev,
1945 struct cli_state *cli,
1947 const char *pass, int passlen,
1948 const char *ntpass, int ntpasslen,
1949 const char *workgroup)
1951 struct tevent_req *req, *subreq;
1952 struct cli_session_setup_state *state;
1955 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1957 req = tevent_req_create(mem_ctx, &state,
1958 struct cli_session_setup_state);
1964 user2 = talloc_strdup(state, user);
1966 user2 = talloc_strdup(state, "");
1968 if (user2 == NULL) {
1969 tevent_req_oom(req);
1970 return tevent_req_post(req, ev);
1977 /* allow for workgroups as part of the username */
1978 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1979 (p=strchr_m(user2,*lp_winbind_separator()))) {
1982 if (!strupper_m(user2)) {
1983 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1984 return tevent_req_post(req, ev);
1989 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1990 tevent_req_done(req);
1991 return tevent_req_post(req, ev);
1994 /* now work out what sort of session setup we are going to
1995 do. I have split this into separate functions to make the
1996 flow a bit easier to understand (tridge) */
1998 /* if its an older server then we have to use the older request format */
2000 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2001 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2002 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2003 " or 'client ntlmv2 auth = yes'\n"));
2004 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2005 return tevent_req_post(req, ev);
2008 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2009 !lp_client_plaintext_auth() && (*pass)) {
2010 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2011 " or 'client ntlmv2 auth = yes'\n"));
2012 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2013 return tevent_req_post(req, ev);
2016 subreq = cli_session_setup_lanman2_send(
2017 state, ev, cli, user, pass, passlen, workgroup);
2018 if (tevent_req_nomem(subreq, req)) {
2019 return tevent_req_post(req, ev);
2021 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2026 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2027 const char *remote_realm = cli_state_remote_realm(cli);
2029 subreq = cli_session_setup_spnego_send(
2030 state, ev, cli, user, pass, workgroup, remote_realm);
2031 if (tevent_req_nomem(subreq, req)) {
2032 return tevent_req_post(req, ev);
2034 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2039 /* if no user is supplied then we have to do an anonymous connection.
2040 passwords are ignored */
2042 if (!user || !*user) {
2043 subreq = cli_session_setup_guest_send(state, ev, cli);
2044 if (tevent_req_nomem(subreq, req)) {
2045 return tevent_req_post(req, ev);
2047 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2052 /* if the server is share level then send a plaintext null
2053 password at this point. The password is sent in the tree
2056 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2057 subreq = cli_session_setup_plain_send(
2058 state, ev, cli, user, "", workgroup);
2059 if (tevent_req_nomem(subreq, req)) {
2060 return tevent_req_post(req, ev);
2062 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2067 /* if the server doesn't support encryption then we have to use
2068 plaintext. The second password is ignored */
2070 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2071 if (!lp_client_plaintext_auth() && (*pass)) {
2072 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2073 " or 'client ntlmv2 auth = yes'\n"));
2074 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2075 return tevent_req_post(req, ev);
2077 subreq = cli_session_setup_plain_send(
2078 state, ev, cli, user, pass, workgroup);
2079 if (tevent_req_nomem(subreq, req)) {
2080 return tevent_req_post(req, ev);
2082 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2087 /* if the server supports extended security then use SPNEGO */
2089 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2090 const char *remote_realm = cli_state_remote_realm(cli);
2092 subreq = cli_session_setup_spnego_send(
2093 state, ev, cli, user, pass, workgroup, remote_realm);
2094 if (tevent_req_nomem(subreq, req)) {
2095 return tevent_req_post(req, ev);
2097 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2101 /* otherwise do a NT1 style session setup */
2103 subreq = cli_session_setup_nt1_send(
2104 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2106 if (tevent_req_nomem(subreq, req)) {
2107 return tevent_req_post(req, ev);
2109 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2114 tevent_req_done(req);
2115 return tevent_req_post(req, ev);
2118 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2120 struct tevent_req *req = tevent_req_callback_data(
2121 subreq, struct tevent_req);
2124 status = cli_session_setup_lanman2_recv(subreq);
2125 TALLOC_FREE(subreq);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 tevent_req_nterror(req, status);
2130 tevent_req_done(req);
2133 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2135 struct tevent_req *req = tevent_req_callback_data(
2136 subreq, struct tevent_req);
2139 status = cli_session_setup_spnego_recv(subreq);
2140 TALLOC_FREE(subreq);
2141 if (!ADS_ERR_OK(status)) {
2142 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2143 tevent_req_nterror(req, ads_ntstatus(status));
2146 tevent_req_done(req);
2149 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2151 struct tevent_req *req = tevent_req_callback_data(
2152 subreq, struct tevent_req);
2155 status = cli_session_setup_guest_recv(subreq);
2156 TALLOC_FREE(subreq);
2157 if (!NT_STATUS_IS_OK(status)) {
2158 tevent_req_nterror(req, status);
2161 tevent_req_done(req);
2164 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2166 struct tevent_req *req = tevent_req_callback_data(
2167 subreq, struct tevent_req);
2170 status = cli_session_setup_plain_recv(subreq);
2171 TALLOC_FREE(subreq);
2172 if (!NT_STATUS_IS_OK(status)) {
2173 tevent_req_nterror(req, status);
2176 tevent_req_done(req);
2179 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2181 struct tevent_req *req = tevent_req_callback_data(
2182 subreq, struct tevent_req);
2185 status = cli_session_setup_nt1_recv(subreq);
2186 TALLOC_FREE(subreq);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 DEBUG(3, ("cli_session_setup: NT1 session setup "
2189 "failed: %s\n", nt_errstr(status)));
2190 tevent_req_nterror(req, status);
2193 tevent_req_done(req);
2196 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2198 return tevent_req_simple_recv_ntstatus(req);
2201 NTSTATUS cli_session_setup(struct cli_state *cli,
2203 const char *pass, int passlen,
2204 const char *ntpass, int ntpasslen,
2205 const char *workgroup)
2207 struct tevent_context *ev;
2208 struct tevent_req *req;
2209 NTSTATUS status = NT_STATUS_NO_MEMORY;
2211 if (smbXcli_conn_has_async_calls(cli->conn)) {
2212 return NT_STATUS_INVALID_PARAMETER;
2214 ev = samba_tevent_context_init(talloc_tos());
2218 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2219 ntpass, ntpasslen, workgroup);
2223 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2226 status = cli_session_setup_recv(req);
2232 /****************************************************************************
2234 *****************************************************************************/
2236 struct cli_ulogoff_state {
2237 struct cli_state *cli;
2241 static void cli_ulogoff_done(struct tevent_req *subreq);
2243 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2244 struct tevent_context *ev,
2245 struct cli_state *cli)
2247 struct tevent_req *req, *subreq;
2248 struct cli_ulogoff_state *state;
2250 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2256 SCVAL(state->vwv+0, 0, 0xFF);
2257 SCVAL(state->vwv+1, 0, 0);
2258 SSVAL(state->vwv+2, 0, 0);
2260 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2262 if (tevent_req_nomem(subreq, req)) {
2263 return tevent_req_post(req, ev);
2265 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2269 static void cli_ulogoff_done(struct tevent_req *subreq)
2271 struct tevent_req *req = tevent_req_callback_data(
2272 subreq, struct tevent_req);
2273 struct cli_ulogoff_state *state = tevent_req_data(
2274 req, struct cli_ulogoff_state);
2277 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2278 if (!NT_STATUS_IS_OK(status)) {
2279 tevent_req_nterror(req, status);
2282 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2283 tevent_req_done(req);
2286 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2288 return tevent_req_simple_recv_ntstatus(req);
2291 NTSTATUS cli_ulogoff(struct cli_state *cli)
2293 struct tevent_context *ev;
2294 struct tevent_req *req;
2295 NTSTATUS status = NT_STATUS_NO_MEMORY;
2297 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2298 status = smb2cli_logoff(cli->conn,
2301 if (!NT_STATUS_IS_OK(status)) {
2304 smb2cli_session_set_id_and_flags(cli->smb2.session,
2306 return NT_STATUS_OK;
2309 if (smbXcli_conn_has_async_calls(cli->conn)) {
2310 return NT_STATUS_INVALID_PARAMETER;
2312 ev = samba_tevent_context_init(talloc_tos());
2316 req = cli_ulogoff_send(ev, ev, cli);
2320 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2323 status = cli_ulogoff_recv(req);
2329 /****************************************************************************
2331 ****************************************************************************/
2333 struct cli_tcon_andx_state {
2334 struct cli_state *cli;
2339 static void cli_tcon_andx_done(struct tevent_req *subreq);
2341 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2342 struct tevent_context *ev,
2343 struct cli_state *cli,
2344 const char *share, const char *dev,
2345 const char *pass, int passlen,
2346 struct tevent_req **psmbreq)
2348 struct tevent_req *req, *subreq;
2349 struct cli_tcon_andx_state *state;
2354 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2355 uint16_t tcon_flags = 0;
2359 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2366 cli->share = talloc_strdup(cli, share);
2371 /* in user level security don't send a password now */
2372 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2375 } else if (pass == NULL) {
2376 DEBUG(1, ("Server not using user level security and no "
2377 "password supplied.\n"));
2381 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2382 *pass && passlen != 24) {
2383 if (!lp_client_lanman_auth()) {
2384 DEBUG(1, ("Server requested LANMAN password "
2385 "(share-level security) but "
2386 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2391 * Non-encrypted passwords - convert to DOS codepage before
2394 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2396 pass = (const char *)p24;
2398 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2399 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2403 if (!lp_client_plaintext_auth() && (*pass)) {
2404 DEBUG(1, ("Server requested PLAINTEXT "
2406 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2411 * Non-encrypted passwords - convert to DOS codepage
2414 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2415 if (tevent_req_nomem(tmp_pass, req)) {
2416 return tevent_req_post(req, ev);
2418 tmp_pass = trans2_bytes_push_str(tmp_pass,
2419 false, /* always DOS */
2423 if (tevent_req_nomem(tmp_pass, req)) {
2424 return tevent_req_post(req, ev);
2426 pass = (const char *)tmp_pass;
2427 passlen = talloc_get_size(tmp_pass);
2431 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2432 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2434 SCVAL(vwv+0, 0, 0xFF);
2437 SSVAL(vwv+2, 0, tcon_flags);
2438 SSVAL(vwv+3, 0, passlen);
2440 if (passlen && pass) {
2441 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2443 bytes = talloc_array(state, uint8_t, 0);
2449 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2450 smbXcli_conn_remote_name(cli->conn), share);
2455 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2460 * Add the devicetype
2462 tmp = talloc_strdup_upper(talloc_tos(), dev);
2467 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2470 if (bytes == NULL) {
2475 state->bytes.iov_base = (void *)bytes;
2476 state->bytes.iov_len = talloc_get_size(bytes);
2478 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2480 if (subreq == NULL) {
2484 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2489 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2490 return tevent_req_post(req, ev);
2493 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2494 struct tevent_context *ev,
2495 struct cli_state *cli,
2496 const char *share, const char *dev,
2497 const char *pass, int passlen)
2499 struct tevent_req *req, *subreq;
2502 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2507 if (subreq == NULL) {
2510 status = smb1cli_req_chain_submit(&subreq, 1);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 tevent_req_nterror(req, status);
2513 return tevent_req_post(req, ev);
2518 static void cli_tcon_andx_done(struct tevent_req *subreq)
2520 struct tevent_req *req = tevent_req_callback_data(
2521 subreq, struct tevent_req);
2522 struct cli_tcon_andx_state *state = tevent_req_data(
2523 req, struct cli_tcon_andx_state);
2524 struct cli_state *cli = state->cli;
2532 uint16_t optional_support = 0;
2534 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2535 &num_bytes, &bytes);
2536 TALLOC_FREE(subreq);
2537 if (!NT_STATUS_IS_OK(status)) {
2538 tevent_req_nterror(req, status);
2542 inhdr = in + NBT_HDR_SIZE;
2545 if (clistr_pull_talloc(cli,
2546 (const char *)inhdr,
2547 SVAL(inhdr, HDR_FLG2),
2551 STR_TERMINATE|STR_ASCII) == -1) {
2552 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2556 cli->dev = talloc_strdup(cli, "");
2557 if (cli->dev == NULL) {
2558 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2563 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2564 /* almost certainly win95 - enable bug fixes */
2569 * Make sure that we have the optional support 16-bit field. WCT > 2.
2570 * Avoids issues when connecting to Win9x boxes sharing files
2573 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2574 optional_support = SVAL(vwv+2, 0);
2577 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2578 smb1cli_session_protect_session_key(cli->smb1.session);
2581 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2582 SVAL(inhdr, HDR_TID),
2584 0, /* maximal_access */
2585 0, /* guest_maximal_access */
2587 NULL); /* fs_type */
2589 tevent_req_done(req);
2592 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2594 return tevent_req_simple_recv_ntstatus(req);
2597 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2598 const char *dev, const char *pass, int passlen)
2600 TALLOC_CTX *frame = talloc_stackframe();
2601 struct tevent_context *ev;
2602 struct tevent_req *req;
2603 NTSTATUS status = NT_STATUS_NO_MEMORY;
2605 if (smbXcli_conn_has_async_calls(cli->conn)) {
2607 * Can't use sync call while an async call is in flight
2609 status = NT_STATUS_INVALID_PARAMETER;
2613 ev = samba_tevent_context_init(frame);
2618 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2623 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2627 status = cli_tcon_andx_recv(req);
2633 struct cli_tree_connect_state {
2634 struct cli_state *cli;
2637 static struct tevent_req *cli_raw_tcon_send(
2638 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2639 const char *service, const char *pass, const char *dev);
2640 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2641 uint16 *max_xmit, uint16 *tid);
2643 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2644 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2645 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2647 static struct tevent_req *cli_tree_connect_send(
2648 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2649 const char *share, const char *dev, const char *pass, int passlen)
2651 struct tevent_req *req, *subreq;
2652 struct cli_tree_connect_state *state;
2654 req = tevent_req_create(mem_ctx, &state,
2655 struct cli_tree_connect_state);
2661 cli->share = talloc_strdup(cli, share);
2662 if (tevent_req_nomem(cli->share, req)) {
2663 return tevent_req_post(req, ev);
2666 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2669 cli->smb2.tcon = smbXcli_tcon_create(cli);
2670 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2671 return tevent_req_post(req, ev);
2674 unc = talloc_asprintf(state, "\\\\%s\\%s",
2675 smbXcli_conn_remote_name(cli->conn),
2677 if (tevent_req_nomem(unc, req)) {
2678 return tevent_req_post(req, ev);
2681 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2682 cli->smb2.session, cli->smb2.tcon,
2685 if (tevent_req_nomem(subreq, req)) {
2686 return tevent_req_post(req, ev);
2688 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2693 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2694 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2696 if (tevent_req_nomem(subreq, req)) {
2697 return tevent_req_post(req, ev);
2699 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2704 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2705 if (tevent_req_nomem(subreq, req)) {
2706 return tevent_req_post(req, ev);
2708 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2713 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2715 tevent_req_simple_finish_ntstatus(
2716 subreq, smb2cli_tcon_recv(subreq));
2719 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2721 tevent_req_simple_finish_ntstatus(
2722 subreq, cli_tcon_andx_recv(subreq));
2725 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2727 struct tevent_req *req = tevent_req_callback_data(
2728 subreq, struct tevent_req);
2729 struct cli_tree_connect_state *state = tevent_req_data(
2730 req, struct cli_tree_connect_state);
2732 uint16_t max_xmit = 0;
2735 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2736 if (tevent_req_nterror(req, status)) {
2740 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2742 0, /* optional_support */
2743 0, /* maximal_access */
2744 0, /* guest_maximal_access */
2746 NULL); /* fs_type */
2748 tevent_req_done(req);
2751 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2753 return tevent_req_simple_recv_ntstatus(req);
2756 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2757 const char *dev, const char *pass, int passlen)
2759 struct tevent_context *ev;
2760 struct tevent_req *req;
2761 NTSTATUS status = NT_STATUS_NO_MEMORY;
2763 if (smbXcli_conn_has_async_calls(cli->conn)) {
2764 return NT_STATUS_INVALID_PARAMETER;
2766 ev = samba_tevent_context_init(talloc_tos());
2770 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2774 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2777 status = cli_tree_connect_recv(req);
2783 /****************************************************************************
2784 Send a tree disconnect.
2785 ****************************************************************************/
2787 struct cli_tdis_state {
2788 struct cli_state *cli;
2791 static void cli_tdis_done(struct tevent_req *subreq);
2793 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2794 struct tevent_context *ev,
2795 struct cli_state *cli)
2797 struct tevent_req *req, *subreq;
2798 struct cli_tdis_state *state;
2800 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2806 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2807 if (tevent_req_nomem(subreq, req)) {
2808 return tevent_req_post(req, ev);
2810 tevent_req_set_callback(subreq, cli_tdis_done, req);
2814 static void cli_tdis_done(struct tevent_req *subreq)
2816 struct tevent_req *req = tevent_req_callback_data(
2817 subreq, struct tevent_req);
2818 struct cli_tdis_state *state = tevent_req_data(
2819 req, struct cli_tdis_state);
2822 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2823 TALLOC_FREE(subreq);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 tevent_req_nterror(req, status);
2828 cli_state_set_tid(state->cli, UINT16_MAX);
2829 tevent_req_done(req);
2832 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2834 return tevent_req_simple_recv_ntstatus(req);
2837 NTSTATUS cli_tdis(struct cli_state *cli)
2839 struct tevent_context *ev;
2840 struct tevent_req *req;
2841 NTSTATUS status = NT_STATUS_NO_MEMORY;
2843 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2844 return smb2cli_tdis(cli->conn,
2850 if (smbXcli_conn_has_async_calls(cli->conn)) {
2851 return NT_STATUS_INVALID_PARAMETER;
2853 ev = samba_tevent_context_init(talloc_tos());
2857 req = cli_tdis_send(ev, ev, cli);
2861 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2864 status = cli_tdis_recv(req);
2870 struct cli_connect_sock_state {
2871 const char **called_names;
2872 const char **calling_names;
2878 static void cli_connect_sock_done(struct tevent_req *subreq);
2881 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2885 static struct tevent_req *cli_connect_sock_send(
2886 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2887 const char *host, int name_type, const struct sockaddr_storage *pss,
2888 const char *myname, uint16_t port)
2890 struct tevent_req *req, *subreq;
2891 struct cli_connect_sock_state *state;
2893 struct sockaddr_storage *addrs;
2894 unsigned i, num_addrs;
2897 req = tevent_req_create(mem_ctx, &state,
2898 struct cli_connect_sock_state);
2903 prog = getenv("LIBSMB_PROG");
2905 state->fd = sock_exec(prog);
2906 if (state->fd == -1) {
2907 status = map_nt_error_from_unix(errno);
2908 tevent_req_nterror(req, status);
2911 tevent_req_done(req);
2913 return tevent_req_post(req, ev);
2916 if ((pss == NULL) || is_zero_addr(pss)) {
2919 * Here we cheat. resolve_name_list is not async at all. So
2920 * this call will only be really async if the name lookup has
2921 * been done externally.
2924 status = resolve_name_list(state, host, name_type,
2925 &addrs, &num_addrs);
2926 if (!NT_STATUS_IS_OK(status)) {
2927 tevent_req_nterror(req, status);
2928 return tevent_req_post(req, ev);
2931 addrs = talloc_array(state, struct sockaddr_storage, 1);
2932 if (tevent_req_nomem(addrs, req)) {
2933 return tevent_req_post(req, ev);
2939 state->called_names = talloc_array(state, const char *, num_addrs);
2940 if (tevent_req_nomem(state->called_names, req)) {
2941 return tevent_req_post(req, ev);
2943 state->called_types = talloc_array(state, int, num_addrs);
2944 if (tevent_req_nomem(state->called_types, req)) {
2945 return tevent_req_post(req, ev);
2947 state->calling_names = talloc_array(state, const char *, num_addrs);
2948 if (tevent_req_nomem(state->calling_names, req)) {
2949 return tevent_req_post(req, ev);
2951 for (i=0; i<num_addrs; i++) {
2952 state->called_names[i] = host;
2953 state->called_types[i] = name_type;
2954 state->calling_names[i] = myname;
2957 subreq = smbsock_any_connect_send(
2958 state, ev, addrs, state->called_names, state->called_types,
2959 state->calling_names, NULL, num_addrs, port);
2960 if (tevent_req_nomem(subreq, req)) {
2961 return tevent_req_post(req, ev);
2963 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2967 static void cli_connect_sock_done(struct tevent_req *subreq)
2969 struct tevent_req *req = tevent_req_callback_data(
2970 subreq, struct tevent_req);
2971 struct cli_connect_sock_state *state = tevent_req_data(
2972 req, struct cli_connect_sock_state);
2975 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2977 TALLOC_FREE(subreq);
2978 if (tevent_req_nterror(req, status)) {
2981 set_socket_options(state->fd, lp_socket_options());
2982 tevent_req_done(req);
2985 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2986 int *pfd, uint16_t *pport)
2988 struct cli_connect_sock_state *state = tevent_req_data(
2989 req, struct cli_connect_sock_state);
2992 if (tevent_req_is_nterror(req, &status)) {
2996 *pport = state->port;
2997 return NT_STATUS_OK;
3000 struct cli_connect_nb_state {
3001 const char *desthost;
3004 struct cli_state *cli;
3007 static void cli_connect_nb_done(struct tevent_req *subreq);
3009 static struct tevent_req *cli_connect_nb_send(
3010 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3011 const char *host, const struct sockaddr_storage *dest_ss,
3012 uint16_t port, int name_type, const char *myname,
3013 int signing_state, int flags)
3015 struct tevent_req *req, *subreq;
3016 struct cli_connect_nb_state *state;
3019 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3023 state->desthost = host;
3024 state->signing_state = signing_state;
3025 state->flags = flags;
3027 p = strchr(host, '#');
3029 name_type = strtol(p+1, NULL, 16);
3030 host = talloc_strndup(state, host, p - host);
3031 if (tevent_req_nomem(host, req)) {
3032 return tevent_req_post(req, ev);
3036 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3038 if (tevent_req_nomem(subreq, req)) {
3039 return tevent_req_post(req, ev);
3041 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3045 static void cli_connect_nb_done(struct tevent_req *subreq)
3047 struct tevent_req *req = tevent_req_callback_data(
3048 subreq, struct tevent_req);
3049 struct cli_connect_nb_state *state = tevent_req_data(
3050 req, struct cli_connect_nb_state);
3055 status = cli_connect_sock_recv(subreq, &fd, &port);
3056 TALLOC_FREE(subreq);
3057 if (tevent_req_nterror(req, status)) {
3061 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3062 state->signing_state, state->flags);
3063 if (tevent_req_nomem(state->cli, req)) {
3067 tevent_req_done(req);
3070 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3071 struct cli_state **pcli)
3073 struct cli_connect_nb_state *state = tevent_req_data(
3074 req, struct cli_connect_nb_state);
3077 if (tevent_req_is_nterror(req, &status)) {
3080 *pcli = talloc_move(NULL, &state->cli);
3081 return NT_STATUS_OK;
3084 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3085 uint16_t port, int name_type, const char *myname,
3086 int signing_state, int flags, struct cli_state **pcli)
3088 struct tevent_context *ev;
3089 struct tevent_req *req;
3090 NTSTATUS status = NT_STATUS_NO_MEMORY;
3092 ev = samba_tevent_context_init(talloc_tos());
3096 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3097 myname, signing_state, flags);
3101 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3104 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3107 status = cli_connect_nb_recv(req, pcli);
3113 struct cli_start_connection_state {
3114 struct tevent_context *ev;
3115 struct cli_state *cli;
3118 static void cli_start_connection_connected(struct tevent_req *subreq);
3119 static void cli_start_connection_done(struct tevent_req *subreq);
3122 establishes a connection to after the negprot.
3123 @param output_cli A fully initialised cli structure, non-null only on success
3124 @param dest_host The netbios name of the remote host
3125 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3126 @param port (optional) The destination port (0 for default)
3129 static struct tevent_req *cli_start_connection_send(
3130 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3131 const char *my_name, const char *dest_host,
3132 const struct sockaddr_storage *dest_ss, int port,
3133 int signing_state, int flags)
3135 struct tevent_req *req, *subreq;
3136 struct cli_start_connection_state *state;
3138 req = tevent_req_create(mem_ctx, &state,
3139 struct cli_start_connection_state);
3145 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3146 0x20, my_name, signing_state, flags);
3147 if (tevent_req_nomem(subreq, req)) {
3148 return tevent_req_post(req, ev);
3150 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3154 static void cli_start_connection_connected(struct tevent_req *subreq)
3156 struct tevent_req *req = tevent_req_callback_data(
3157 subreq, struct tevent_req);
3158 struct cli_start_connection_state *state = tevent_req_data(
3159 req, struct cli_start_connection_state);
3162 status = cli_connect_nb_recv(subreq, &state->cli);
3163 TALLOC_FREE(subreq);
3164 if (tevent_req_nterror(req, status)) {
3168 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3169 state->cli->timeout,
3170 lp_client_min_protocol(),
3171 lp_client_max_protocol());
3172 if (tevent_req_nomem(subreq, req)) {
3175 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3178 static void cli_start_connection_done(struct tevent_req *subreq)
3180 struct tevent_req *req = tevent_req_callback_data(
3181 subreq, struct tevent_req);
3182 struct cli_start_connection_state *state = tevent_req_data(
3183 req, struct cli_start_connection_state);
3186 status = smbXcli_negprot_recv(subreq);
3187 TALLOC_FREE(subreq);
3188 if (tevent_req_nterror(req, status)) {
3192 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3193 /* Ensure we ask for some initial credits. */
3194 smb2cli_conn_set_max_credits(state->cli->conn,
3195 DEFAULT_SMB2_MAX_CREDITS);
3198 tevent_req_done(req);
3201 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3202 struct cli_state **output_cli)
3204 struct cli_start_connection_state *state = tevent_req_data(
3205 req, struct cli_start_connection_state);
3208 if (tevent_req_is_nterror(req, &status)) {
3211 *output_cli = state->cli;
3213 return NT_STATUS_OK;
3216 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3217 const char *my_name,
3218 const char *dest_host,
3219 const struct sockaddr_storage *dest_ss, int port,
3220 int signing_state, int flags)
3222 struct tevent_context *ev;
3223 struct tevent_req *req;
3224 NTSTATUS status = NT_STATUS_NO_MEMORY;
3226 ev = samba_tevent_context_init(talloc_tos());
3230 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3231 port, signing_state, flags);
3235 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3238 status = cli_start_connection_recv(req, output_cli);
3245 establishes a connection right up to doing tconX, password specified.
3246 @param output_cli A fully initialised cli structure, non-null only on success
3247 @param dest_host The netbios name of the remote host
3248 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3249 @param port (optional) The destination port (0 for default)
3250 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3251 @param service_type The 'type' of serivice.
3252 @param user Username, unix string
3253 @param domain User's domain
3254 @param password User's password, unencrypted unix string.
3257 struct cli_full_connection_state {
3258 struct tevent_context *ev;
3259 const char *service;
3260 const char *service_type;
3263 const char *password;
3266 struct cli_state *cli;
3269 static int cli_full_connection_state_destructor(
3270 struct cli_full_connection_state *s);
3271 static void cli_full_connection_started(struct tevent_req *subreq);
3272 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3273 static void cli_full_connection_done(struct tevent_req *subreq);
3275 struct tevent_req *cli_full_connection_send(
3276 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3277 const char *my_name, const char *dest_host,
3278 const struct sockaddr_storage *dest_ss, int port,
3279 const char *service, const char *service_type,
3280 const char *user, const char *domain,
3281 const char *password, int flags, int signing_state)
3283 struct tevent_req *req, *subreq;
3284 struct cli_full_connection_state *state;
3286 req = tevent_req_create(mem_ctx, &state,
3287 struct cli_full_connection_state);
3291 talloc_set_destructor(state, cli_full_connection_state_destructor);
3294 state->service = service;
3295 state->service_type = service_type;
3297 state->domain = domain;
3298 state->password = password;
3299 state->flags = flags;
3301 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3302 if (state->password == NULL) {
3303 state->password = "";
3306 subreq = cli_start_connection_send(
3307 state, ev, my_name, dest_host, dest_ss, port,
3308 signing_state, flags);
3309 if (tevent_req_nomem(subreq, req)) {
3310 return tevent_req_post(req, ev);
3312 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3316 static int cli_full_connection_state_destructor(
3317 struct cli_full_connection_state *s)
3319 if (s->cli != NULL) {
3320 cli_shutdown(s->cli);
3326 static void cli_full_connection_started(struct tevent_req *subreq)
3328 struct tevent_req *req = tevent_req_callback_data(
3329 subreq, struct tevent_req);
3330 struct cli_full_connection_state *state = tevent_req_data(
3331 req, struct cli_full_connection_state);
3334 status = cli_start_connection_recv(subreq, &state->cli);
3335 TALLOC_FREE(subreq);
3336 if (tevent_req_nterror(req, status)) {
3339 subreq = cli_session_setup_send(
3340 state, state->ev, state->cli, state->user,
3341 state->password, state->pw_len, state->password, state->pw_len,
3343 if (tevent_req_nomem(subreq, req)) {
3346 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3349 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3351 struct tevent_req *req = tevent_req_callback_data(
3352 subreq, struct tevent_req);
3353 struct cli_full_connection_state *state = tevent_req_data(
3354 req, struct cli_full_connection_state);
3357 status = cli_session_setup_recv(subreq);
3358 TALLOC_FREE(subreq);
3360 if (!NT_STATUS_IS_OK(status) &&
3361 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3363 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3365 subreq = cli_session_setup_send(
3366 state, state->ev, state->cli, "", "", 0, "", 0,
3368 if (tevent_req_nomem(subreq, req)) {
3371 tevent_req_set_callback(
3372 subreq, cli_full_connection_sess_set_up, req);
3376 if (tevent_req_nterror(req, status)) {
3380 if (state->service != NULL) {
3381 subreq = cli_tree_connect_send(
3382 state, state->ev, state->cli,
3383 state->service, state->service_type,
3384 state->password, state->pw_len);
3385 if (tevent_req_nomem(subreq, req)) {
3388 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3392 status = cli_init_creds(state->cli, state->user, state->domain);
3393 if (tevent_req_nterror(req, status)) {
3396 tevent_req_done(req);
3399 static void cli_full_connection_done(struct tevent_req *subreq)
3401 struct tevent_req *req = tevent_req_callback_data(
3402 subreq, struct tevent_req);
3403 struct cli_full_connection_state *state = tevent_req_data(
3404 req, struct cli_full_connection_state);
3407 status = cli_tree_connect_recv(subreq);
3408 TALLOC_FREE(subreq);
3409 if (tevent_req_nterror(req, status)) {
3412 status = cli_init_creds(state->cli, state->user, state->domain);
3413 if (tevent_req_nterror(req, status)) {
3416 tevent_req_done(req);
3419 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3420 struct cli_state **output_cli)
3422 struct cli_full_connection_state *state = tevent_req_data(
3423 req, struct cli_full_connection_state);
3426 if (tevent_req_is_nterror(req, &status)) {
3429 *output_cli = state->cli;
3430 talloc_set_destructor(state, NULL);
3431 return NT_STATUS_OK;
3434 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3435 const char *my_name,
3436 const char *dest_host,
3437 const struct sockaddr_storage *dest_ss, int port,
3438 const char *service, const char *service_type,
3439 const char *user, const char *domain,
3440 const char *password, int flags,
3443 struct tevent_context *ev;
3444 struct tevent_req *req;
3445 NTSTATUS status = NT_STATUS_NO_MEMORY;
3447 ev = samba_tevent_context_init(talloc_tos());
3451 req = cli_full_connection_send(
3452 ev, ev, my_name, dest_host, dest_ss, port, service,
3453 service_type, user, domain, password, flags, signing_state);
3457 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3460 status = cli_full_connection_recv(req, output_cli);
3466 /****************************************************************************
3467 Send an old style tcon.
3468 ****************************************************************************/
3469 struct cli_raw_tcon_state {
3473 static void cli_raw_tcon_done(struct tevent_req *subreq);
3475 static struct tevent_req *cli_raw_tcon_send(
3476 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3477 const char *service, const char *pass, const char *dev)
3479 struct tevent_req *req, *subreq;
3480 struct cli_raw_tcon_state *state;
3483 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3488 if (!lp_client_plaintext_auth() && (*pass)) {
3489 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3490 " or 'client ntlmv2 auth = yes'\n"));
3491 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3492 return tevent_req_post(req, ev);
3495 bytes = talloc_array(state, uint8_t, 0);
3496 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3497 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3498 service, strlen(service)+1, NULL);
3499 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3500 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3501 pass, strlen(pass)+1, NULL);
3502 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3503 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3504 dev, strlen(dev)+1, NULL);
3506 if (tevent_req_nomem(bytes, req)) {
3507 return tevent_req_post(req, ev);
3510 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3511 talloc_get_size(bytes), bytes);
3512 if (tevent_req_nomem(subreq, req)) {
3513 return tevent_req_post(req, ev);
3515 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3519 static void cli_raw_tcon_done(struct tevent_req *subreq)
3521 struct tevent_req *req = tevent_req_callback_data(
3522 subreq, struct tevent_req);
3523 struct cli_raw_tcon_state *state = tevent_req_data(
3524 req, struct cli_raw_tcon_state);
3527 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3529 TALLOC_FREE(subreq);
3530 if (tevent_req_nterror(req, status)) {
3533 tevent_req_done(req);
3536 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3537 uint16 *max_xmit, uint16 *tid)
3539 struct cli_raw_tcon_state *state = tevent_req_data(
3540 req, struct cli_raw_tcon_state);
3543 if (tevent_req_is_nterror(req, &status)) {
3546 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3547 *tid = SVAL(state->ret_vwv + 1, 0);
3548 return NT_STATUS_OK;
3551 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3552 const char *service, const char *pass, const char *dev,
3553 uint16 *max_xmit, uint16 *tid)
3555 struct tevent_context *ev;
3556 struct tevent_req *req;
3557 NTSTATUS status = NT_STATUS_NO_MEMORY;
3559 ev = samba_tevent_context_init(talloc_tos());
3563 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3567 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3570 status = cli_raw_tcon_recv(req, max_xmit, tid);
3576 /* Return a cli_state pointing at the IPC$ share for the given server */
3578 struct cli_state *get_ipc_connect(char *server,
3579 struct sockaddr_storage *server_ss,
3580 const struct user_auth_info *user_info)
3582 struct cli_state *cli;
3584 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3586 if (user_info->use_kerberos) {
3587 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3590 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3591 user_info->username ? user_info->username : "",
3593 user_info->password ? user_info->password : "",
3595 SMB_SIGNING_DEFAULT);
3597 if (NT_STATUS_IS_OK(nt_status)) {
3599 } else if (is_ipaddress(server)) {
3600 /* windows 9* needs a correct NMB name for connections */
3601 fstring remote_name;
3603 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3604 cli = get_ipc_connect(remote_name, server_ss, user_info);
3613 * Given the IP address of a master browser on the network, return its
3614 * workgroup and connect to it.
3616 * This function is provided to allow additional processing beyond what
3617 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3618 * browsers and obtain each master browsers' list of domains (in case the
3619 * first master browser is recently on the network and has not yet
3620 * synchronized with other master browsers and therefore does not yet have the
3621 * entire network browse list)
3624 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3625 struct sockaddr_storage *mb_ip,
3626 const struct user_auth_info *user_info,
3627 char **pp_workgroup_out)
3629 char addr[INET6_ADDRSTRLEN];
3631 struct cli_state *cli;
3632 struct sockaddr_storage server_ss;
3634 *pp_workgroup_out = NULL;
3636 print_sockaddr(addr, sizeof(addr), mb_ip);
3637 DEBUG(99, ("Looking up name of master browser %s\n",
3641 * Do a name status query to find out the name of the master browser.
3642 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3643 * master browser will not respond to a wildcard query (or, at least,
3644 * an NT4 server acting as the domain master browser will not).
3646 * We might be able to use ONLY the query on MSBROWSE, but that's not
3647 * yet been tested with all Windows versions, so until it is, leave
3648 * the original wildcard query as the first choice and fall back to
3649 * MSBROWSE if the wildcard query fails.
3651 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3652 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3654 DEBUG(99, ("Could not retrieve name status for %s\n",
3659 if (!find_master_ip(name, &server_ss)) {
3660 DEBUG(99, ("Could not find master ip for %s\n", name));
3664 *pp_workgroup_out = talloc_strdup(ctx, name);
3666 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3668 print_sockaddr(addr, sizeof(addr), &server_ss);
3669 cli = get_ipc_connect(addr, &server_ss, user_info);
3675 * Return the IP address and workgroup of a master browser on the network, and
3679 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3680 const struct user_auth_info *user_info,
3681 char **pp_workgroup_out)
3683 struct sockaddr_storage *ip_list;
3684 struct cli_state *cli;
3688 *pp_workgroup_out = NULL;
3690 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3692 /* Go looking for workgroups by broadcasting on the local network */
3694 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3696 if (!NT_STATUS_IS_OK(status)) {
3697 DEBUG(99, ("No master browsers responded: %s\n",
3698 nt_errstr(status)));
3702 for (i = 0; i < count; i++) {
3703 char addr[INET6_ADDRSTRLEN];
3704 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3705 DEBUG(99, ("Found master browser %s\n", addr));
3707 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3708 user_info, pp_workgroup_out);