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 tevent_req_done(req);
285 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
287 return tevent_req_simple_recv_ntstatus(req);
290 /****************************************************************************
291 Work out suitable capabilities to offer the server.
292 ****************************************************************************/
294 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
295 uint32_t sesssetup_capabilities)
297 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
300 * We only send capabilities based on the mask for:
301 * - client only flags
302 * - flags used in both directions
304 * We do not echo the server only flags, except some legacy flags.
306 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
307 * CAP_LARGE_WRITEX in order to allow us to do large reads
308 * against old Samba releases (<= 3.6.x).
310 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
313 * Session Setup specific flags CAP_DYNAMIC_REAUTH
314 * and CAP_EXTENDED_SECURITY are passed by the caller.
315 * We need that in order to do guest logins even if
316 * CAP_EXTENDED_SECURITY is negotiated.
318 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
319 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
320 client_capabilities |= sesssetup_capabilities;
322 return client_capabilities;
325 /****************************************************************************
326 Do a NT1 guest session setup.
327 ****************************************************************************/
329 struct cli_session_setup_guest_state {
330 struct cli_state *cli;
335 static void cli_session_setup_guest_done(struct tevent_req *subreq);
337 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
338 struct tevent_context *ev,
339 struct cli_state *cli,
340 struct tevent_req **psmbreq)
342 struct tevent_req *req, *subreq;
343 struct cli_session_setup_guest_state *state;
347 req = tevent_req_create(mem_ctx, &state,
348 struct cli_session_setup_guest_state);
355 SCVAL(vwv+0, 0, 0xFF);
358 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
360 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
361 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
366 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
368 bytes = talloc_array(state, uint8_t, 0);
370 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
372 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
374 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
375 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
382 state->bytes.iov_base = (void *)bytes;
383 state->bytes.iov_len = talloc_get_size(bytes);
385 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
387 if (subreq == NULL) {
391 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
396 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
397 struct tevent_context *ev,
398 struct cli_state *cli)
400 struct tevent_req *req, *subreq;
403 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
408 status = smb1cli_req_chain_submit(&subreq, 1);
409 if (!NT_STATUS_IS_OK(status)) {
410 tevent_req_nterror(req, status);
411 return tevent_req_post(req, ev);
416 static void cli_session_setup_guest_done(struct tevent_req *subreq)
418 struct tevent_req *req = tevent_req_callback_data(
419 subreq, struct tevent_req);
420 struct cli_session_setup_guest_state *state = tevent_req_data(
421 req, struct cli_session_setup_guest_state);
422 struct cli_state *cli = state->cli;
433 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
436 if (!NT_STATUS_IS_OK(status)) {
437 tevent_req_nterror(req, status);
441 inhdr = in + NBT_HDR_SIZE;
444 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
446 status = smb_bytes_talloc_string(cli,
453 if (!NT_STATUS_IS_OK(status)) {
454 tevent_req_nterror(req, status);
459 status = smb_bytes_talloc_string(cli,
466 if (!NT_STATUS_IS_OK(status)) {
467 tevent_req_nterror(req, status);
472 status = smb_bytes_talloc_string(cli,
479 if (!NT_STATUS_IS_OK(status)) {
480 tevent_req_nterror(req, status);
485 tevent_req_done(req);
488 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
490 return tevent_req_simple_recv_ntstatus(req);
493 /****************************************************************************
494 Do a NT1 plaintext session setup.
495 ****************************************************************************/
497 struct cli_session_setup_plain_state {
498 struct cli_state *cli;
503 static void cli_session_setup_plain_done(struct tevent_req *subreq);
505 static struct tevent_req *cli_session_setup_plain_send(
506 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
507 struct cli_state *cli,
508 const char *user, const char *pass, const char *workgroup)
510 struct tevent_req *req, *subreq;
511 struct cli_session_setup_plain_state *state;
517 req = tevent_req_create(mem_ctx, &state,
518 struct cli_session_setup_plain_state);
526 SCVAL(vwv+0, 0, 0xff);
529 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
531 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
532 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
537 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
539 bytes = talloc_array(state, uint8_t, 0);
540 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
542 if (tevent_req_nomem(bytes, req)) {
543 return tevent_req_post(req, ev);
545 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
547 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
548 user, strlen(user)+1, NULL);
549 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
550 workgroup, strlen(workgroup)+1, NULL);
551 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
554 version = talloc_asprintf(talloc_tos(), "Samba %s",
555 samba_version_string());
556 if (tevent_req_nomem(version, req)){
557 return tevent_req_post(req, ev);
559 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
560 version, strlen(version)+1, NULL);
561 TALLOC_FREE(version);
563 if (tevent_req_nomem(bytes, req)) {
564 return tevent_req_post(req, ev);
567 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
568 talloc_get_size(bytes), bytes);
569 if (tevent_req_nomem(subreq, req)) {
570 return tevent_req_post(req, ev);
572 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
576 static void cli_session_setup_plain_done(struct tevent_req *subreq)
578 struct tevent_req *req = tevent_req_callback_data(
579 subreq, struct tevent_req);
580 struct cli_session_setup_plain_state *state = tevent_req_data(
581 req, struct cli_session_setup_plain_state);
582 struct cli_state *cli = state->cli;
593 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
596 if (tevent_req_nterror(req, status)) {
600 inhdr = in + NBT_HDR_SIZE;
603 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
605 status = smb_bytes_talloc_string(cli,
612 if (!NT_STATUS_IS_OK(status)) {
613 tevent_req_nterror(req, status);
618 status = smb_bytes_talloc_string(cli,
625 if (!NT_STATUS_IS_OK(status)) {
626 tevent_req_nterror(req, status);
631 status = smb_bytes_talloc_string(cli,
638 if (!NT_STATUS_IS_OK(status)) {
639 tevent_req_nterror(req, status);
644 tevent_req_done(req);
647 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
649 return tevent_req_simple_recv_ntstatus(req);
652 /****************************************************************************
653 do a NT1 NTLM/LM encrypted session setup - for when extended security
655 @param cli client state to create do session setup on
657 @param pass *either* cleartext password (passlen !=24) or LM response.
658 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
659 @param workgroup The user's domain.
660 ****************************************************************************/
662 struct cli_session_setup_nt1_state {
663 struct cli_state *cli;
666 DATA_BLOB session_key;
670 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
672 static struct tevent_req *cli_session_setup_nt1_send(
673 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
674 struct cli_state *cli, const char *user,
675 const char *pass, size_t passlen,
676 const char *ntpass, size_t ntpasslen,
677 const char *workgroup)
679 struct tevent_req *req, *subreq;
680 struct cli_session_setup_nt1_state *state;
681 DATA_BLOB lm_response = data_blob_null;
682 DATA_BLOB nt_response = data_blob_null;
683 DATA_BLOB session_key = data_blob_null;
686 char *workgroup_upper;
688 req = tevent_req_create(mem_ctx, &state,
689 struct cli_session_setup_nt1_state);
698 /* do nothing - guest login */
699 } else if (passlen != 24) {
700 if (lp_client_ntlmv2_auth()) {
701 DATA_BLOB server_chal;
702 DATA_BLOB names_blob;
705 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
709 * note that the 'workgroup' here is a best
710 * guess - we don't know the server's domain
711 * at this point. Windows clients also don't
714 names_blob = NTLMv2_generate_names_blob(
715 NULL, NULL, workgroup);
717 if (tevent_req_nomem(names_blob.data, req)) {
718 return tevent_req_post(req, ev);
721 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
722 &server_chal, &names_blob,
723 &lm_response, &nt_response,
724 NULL, &session_key)) {
725 data_blob_free(&names_blob);
727 req, NT_STATUS_ACCESS_DENIED);
728 return tevent_req_post(req, ev);
730 data_blob_free(&names_blob);
734 E_md4hash(pass, nt_hash);
737 nt_response = data_blob_null;
739 nt_response = data_blob(NULL, 24);
740 if (tevent_req_nomem(nt_response.data, req)) {
741 return tevent_req_post(req, ev);
744 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
747 /* non encrypted password supplied. Ignore ntpass. */
748 if (lp_client_lanman_auth()) {
750 lm_response = data_blob(NULL, 24);
751 if (tevent_req_nomem(lm_response.data, req)) {
752 return tevent_req_post(req, ev);
755 if (!SMBencrypt(pass,
756 smb1cli_conn_server_challenge(cli->conn),
759 * Oops, the LM response is
760 * invalid, just put the NT
761 * response there instead
763 data_blob_free(&lm_response);
764 lm_response = data_blob(
770 * LM disabled, place NT# in LM field
773 lm_response = data_blob(
774 nt_response.data, nt_response.length);
777 if (tevent_req_nomem(lm_response.data, req)) {
778 return tevent_req_post(req, ev);
781 session_key = data_blob(NULL, 16);
782 if (tevent_req_nomem(session_key.data, req)) {
783 return tevent_req_post(req, ev);
786 E_deshash(pass, session_key.data);
787 memset(&session_key.data[8], '\0', 8);
789 SMBsesskeygen_ntv1(nt_hash, session_key.data);
793 /* pre-encrypted password supplied. Only used for
794 security=server, can't do
795 signing because we don't have original key */
797 lm_response = data_blob(pass, passlen);
798 if (tevent_req_nomem(lm_response.data, req)) {
799 return tevent_req_post(req, ev);
802 nt_response = data_blob(ntpass, ntpasslen);
803 if (tevent_req_nomem(nt_response.data, req)) {
804 return tevent_req_post(req, ev);
809 state->response = data_blob_talloc(
810 state, lm_response.data, lm_response.length);
812 state->response = data_blob_talloc(
813 state, nt_response.data, nt_response.length);
815 if (tevent_req_nomem(state->response.data, req)) {
816 return tevent_req_post(req, ev);
819 if (session_key.data) {
820 state->session_key = data_blob_talloc(
821 state, session_key.data, session_key.length);
822 if (tevent_req_nomem(state->session_key.data, req)) {
823 return tevent_req_post(req, ev);
826 data_blob_free(&session_key);
828 SCVAL(vwv+0, 0, 0xff);
831 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
833 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
834 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
835 SSVAL(vwv+7, 0, lm_response.length);
836 SSVAL(vwv+8, 0, nt_response.length);
839 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
841 bytes = talloc_array(state, uint8_t,
842 lm_response.length + nt_response.length);
843 if (tevent_req_nomem(bytes, req)) {
844 return tevent_req_post(req, ev);
846 if (lm_response.length != 0) {
847 memcpy(bytes, lm_response.data, lm_response.length);
849 if (nt_response.length != 0) {
850 memcpy(bytes + lm_response.length,
851 nt_response.data, nt_response.length);
853 data_blob_free(&lm_response);
854 data_blob_free(&nt_response);
856 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
857 user, strlen(user)+1, NULL);
860 * Upper case here might help some NTLMv2 implementations
862 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
863 if (tevent_req_nomem(workgroup_upper, req)) {
864 return tevent_req_post(req, ev);
866 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
867 workgroup_upper, strlen(workgroup_upper)+1,
869 TALLOC_FREE(workgroup_upper);
871 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
872 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
873 if (tevent_req_nomem(bytes, req)) {
874 return tevent_req_post(req, ev);
877 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
878 talloc_get_size(bytes), bytes);
879 if (tevent_req_nomem(subreq, req)) {
880 return tevent_req_post(req, ev);
882 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
886 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
888 struct tevent_req *req = tevent_req_callback_data(
889 subreq, struct tevent_req);
890 struct cli_session_setup_nt1_state *state = tevent_req_data(
891 req, struct cli_session_setup_nt1_state);
892 struct cli_state *cli = state->cli;
903 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
906 if (!NT_STATUS_IS_OK(status)) {
907 tevent_req_nterror(req, status);
911 inhdr = in + NBT_HDR_SIZE;
914 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
916 status = smb_bytes_talloc_string(cli,
922 if (!NT_STATUS_IS_OK(status)) {
923 tevent_req_nterror(req, status);
928 status = smb_bytes_talloc_string(cli,
934 if (!NT_STATUS_IS_OK(status)) {
935 tevent_req_nterror(req, status);
940 status = smb_bytes_talloc_string(cli,
946 if (!NT_STATUS_IS_OK(status)) {
947 tevent_req_nterror(req, status);
952 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
953 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
954 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
957 if (state->session_key.data) {
958 struct smbXcli_session *session = state->cli->smb1.session;
960 status = smb1cli_session_set_session_key(session,
962 if (tevent_req_nterror(req, status)) {
966 tevent_req_done(req);
969 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
971 return tevent_req_simple_recv_ntstatus(req);
974 /* The following is calculated from :
976 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
977 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
981 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
983 struct cli_sesssetup_blob_state {
984 struct tevent_context *ev;
985 struct cli_state *cli;
987 uint16_t max_blob_size;
992 struct iovec *recv_iov;
999 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1000 struct tevent_req **psubreq);
1001 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1003 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1004 struct tevent_context *ev,
1005 struct cli_state *cli,
1008 struct tevent_req *req, *subreq;
1009 struct cli_sesssetup_blob_state *state;
1010 uint32_t usable_space;
1012 req = tevent_req_create(mem_ctx, &state,
1013 struct cli_sesssetup_blob_state);
1021 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1022 usable_space = UINT16_MAX;
1024 usable_space = cli_state_available_size(cli,
1025 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1028 if (usable_space == 0) {
1029 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1030 "(not possible to send %u bytes)\n",
1031 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1032 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1033 return tevent_req_post(req, ev);
1035 state->max_blob_size = MIN(usable_space, 0xFFFF);
1037 if (!cli_sesssetup_blob_next(state, &subreq)) {
1038 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1039 return tevent_req_post(req, ev);
1041 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1045 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1046 struct tevent_req **psubreq)
1048 struct tevent_req *subreq;
1051 thistime = MIN(state->blob.length, state->max_blob_size);
1053 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1055 state->smb2_blob.data = state->blob.data;
1056 state->smb2_blob.length = thistime;
1058 state->blob.data += thistime;
1059 state->blob.length -= thistime;
1061 subreq = smb2cli_session_setup_send(state, state->ev,
1063 state->cli->timeout,
1064 state->cli->smb2.session,
1066 SMB2_CAP_DFS, /* in_capabilities */
1068 0, /* in_previous_session_id */
1070 if (subreq == NULL) {
1077 SCVAL(state->vwv+0, 0, 0xFF);
1078 SCVAL(state->vwv+0, 1, 0);
1079 SSVAL(state->vwv+1, 0, 0);
1080 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1081 SSVAL(state->vwv+3, 0, 2);
1082 SSVAL(state->vwv+4, 0, 1);
1083 SIVAL(state->vwv+5, 0, 0);
1085 SSVAL(state->vwv+7, 0, thistime);
1087 SSVAL(state->vwv+8, 0, 0);
1088 SSVAL(state->vwv+9, 0, 0);
1089 SIVAL(state->vwv+10, 0,
1090 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1092 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1094 if (state->buf == NULL) {
1097 state->blob.data += thistime;
1098 state->blob.length -= thistime;
1100 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1102 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1104 if (state->buf == NULL) {
1107 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1109 talloc_get_size(state->buf), state->buf);
1110 if (subreq == NULL) {
1117 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1119 struct tevent_req *req = tevent_req_callback_data(
1120 subreq, struct tevent_req);
1121 struct cli_sesssetup_blob_state *state = tevent_req_data(
1122 req, struct cli_sesssetup_blob_state);
1123 struct cli_state *cli = state->cli;
1130 uint16_t blob_length;
1135 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1136 status = smb2cli_session_setup_recv(subreq, state,
1140 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1141 &num_bytes, &bytes);
1142 TALLOC_FREE(state->buf);
1144 TALLOC_FREE(subreq);
1145 if (!NT_STATUS_IS_OK(status)
1146 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1147 tevent_req_nterror(req, status);
1151 state->status = status;
1153 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1158 inhdr = in + NBT_HDR_SIZE;
1159 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1161 blob_length = SVAL(vwv+3, 0);
1162 if (blob_length > num_bytes) {
1163 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1166 state->ret_blob = data_blob_const(bytes, blob_length);
1168 p = bytes + blob_length;
1170 status = smb_bytes_talloc_string(cli,
1177 if (!NT_STATUS_IS_OK(status)) {
1178 tevent_req_nterror(req, status);
1183 status = smb_bytes_talloc_string(cli,
1190 if (!NT_STATUS_IS_OK(status)) {
1191 tevent_req_nterror(req, status);
1196 status = smb_bytes_talloc_string(cli,
1198 &cli->server_domain,
1203 if (!NT_STATUS_IS_OK(status)) {
1204 tevent_req_nterror(req, status);
1210 if (state->blob.length != 0) {
1214 if (!cli_sesssetup_blob_next(state, &subreq)) {
1215 tevent_req_oom(req);
1218 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1221 tevent_req_done(req);
1224 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1225 TALLOC_CTX *mem_ctx,
1228 struct iovec **precv_iov)
1230 struct cli_sesssetup_blob_state *state = tevent_req_data(
1231 req, struct cli_sesssetup_blob_state);
1234 struct iovec *recv_iov;
1236 if (tevent_req_is_nterror(req, &status)) {
1237 TALLOC_FREE(state->cli->smb2.session);
1238 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1242 inbuf = talloc_move(mem_ctx, &state->inbuf);
1243 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1244 if (pblob != NULL) {
1245 *pblob = state->ret_blob;
1247 if (pinbuf != NULL) {
1250 if (precv_iov != NULL) {
1251 *precv_iov = recv_iov;
1253 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1254 return state->status;
1259 /****************************************************************************
1260 Use in-memory credentials cache
1261 ****************************************************************************/
1263 static void use_in_memory_ccache(void) {
1264 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1267 /****************************************************************************
1268 Do a spnego/kerberos encrypted session setup.
1269 ****************************************************************************/
1271 struct cli_session_setup_kerberos_state {
1272 struct cli_state *cli;
1273 DATA_BLOB negTokenTarg;
1274 DATA_BLOB session_key_krb5;
1275 ADS_STATUS ads_status;
1278 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1280 static struct tevent_req *cli_session_setup_kerberos_send(
1281 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1282 const char *principal)
1284 struct tevent_req *req, *subreq;
1285 struct cli_session_setup_kerberos_state *state;
1288 DEBUG(2,("Doing kerberos session setup\n"));
1290 req = tevent_req_create(mem_ctx, &state,
1291 struct cli_session_setup_kerberos_state);
1296 state->ads_status = ADS_SUCCESS;
1299 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1300 * we have to acquire a ticket. To be fixed later :-)
1302 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1303 &state->session_key_krb5, 0, NULL, NULL);
1305 DEBUG(1, ("cli_session_setup_kerberos: "
1306 "spnego_gen_krb5_negTokenInit failed: %s\n",
1307 error_message(rc)));
1308 state->ads_status = ADS_ERROR_KRB5(rc);
1309 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1310 return tevent_req_post(req, ev);
1314 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1315 state->negTokenTarg.length);
1318 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1319 state->cli->smb2.session = smbXcli_session_create(cli,
1321 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1322 return tevent_req_post(req, ev);
1326 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1327 if (tevent_req_nomem(subreq, req)) {
1328 return tevent_req_post(req, ev);
1330 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1334 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1336 struct tevent_req *req = tevent_req_callback_data(
1337 subreq, struct tevent_req);
1338 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1339 req, struct cli_session_setup_kerberos_state);
1340 uint8_t *inbuf = NULL;
1341 struct iovec *recv_iov = NULL;
1344 status = cli_sesssetup_blob_recv(subreq, state,
1345 NULL, &inbuf, &recv_iov);
1346 TALLOC_FREE(subreq);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 tevent_req_nterror(req, status);
1352 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1353 struct smbXcli_session *session = state->cli->smb2.session;
1354 status = smb2cli_session_set_session_key(session,
1355 state->session_key_krb5,
1357 if (tevent_req_nterror(req, status)) {
1361 struct smbXcli_session *session = state->cli->smb1.session;
1363 status = smb1cli_session_set_session_key(session,
1364 state->session_key_krb5);
1365 if (tevent_req_nterror(req, status)) {
1369 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1371 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1372 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1377 tevent_req_done(req);
1380 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1382 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1383 req, struct cli_session_setup_kerberos_state);
1386 if (tevent_req_is_nterror(req, &status)) {
1387 return ADS_ERROR_NT(status);
1389 return state->ads_status;
1392 #endif /* HAVE_KRB5 */
1394 /****************************************************************************
1395 Do a spnego/NTLMSSP encrypted session setup.
1396 ****************************************************************************/
1398 struct cli_session_setup_ntlmssp_state {
1399 struct tevent_context *ev;
1400 struct cli_state *cli;
1401 struct ntlmssp_state *ntlmssp_state;
1406 static int cli_session_setup_ntlmssp_state_destructor(
1407 struct cli_session_setup_ntlmssp_state *state)
1409 if (state->ntlmssp_state != NULL) {
1410 TALLOC_FREE(state->ntlmssp_state);
1415 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1417 static struct tevent_req *cli_session_setup_ntlmssp_send(
1418 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1419 const char *user, const char *pass, const char *domain)
1421 struct tevent_req *req, *subreq;
1422 struct cli_session_setup_ntlmssp_state *state;
1425 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1427 req = tevent_req_create(mem_ctx, &state,
1428 struct cli_session_setup_ntlmssp_state);
1436 state->ntlmssp_state = NULL;
1437 talloc_set_destructor(
1438 state, cli_session_setup_ntlmssp_state_destructor);
1440 status = ntlmssp_client_start(state,
1443 lp_client_ntlmv2_auth(),
1444 &state->ntlmssp_state);
1445 if (!NT_STATUS_IS_OK(status)) {
1448 ntlmssp_want_feature(state->ntlmssp_state,
1449 NTLMSSP_FEATURE_SESSION_KEY);
1450 if (cli->use_ccache) {
1451 ntlmssp_want_feature(state->ntlmssp_state,
1452 NTLMSSP_FEATURE_CCACHE);
1454 status = ntlmssp_set_username(state->ntlmssp_state, user);
1455 if (!NT_STATUS_IS_OK(status)) {
1458 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1459 if (!NT_STATUS_IS_OK(status)) {
1462 if (cli->pw_nt_hash) {
1463 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1465 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1467 if (!NT_STATUS_IS_OK(status)) {
1470 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1472 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1476 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1477 data_blob_free(&blob_out);
1479 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1480 state->cli->smb2.session = smbXcli_session_create(cli,
1482 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1483 return tevent_req_post(req, ev);
1487 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1488 if (tevent_req_nomem(subreq, req)) {
1489 return tevent_req_post(req, ev);
1491 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1494 tevent_req_nterror(req, status);
1495 return tevent_req_post(req, ev);
1498 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1500 struct tevent_req *req = tevent_req_callback_data(
1501 subreq, struct tevent_req);
1502 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1503 req, struct cli_session_setup_ntlmssp_state);
1504 DATA_BLOB blob_in, msg_in, blob_out;
1505 uint8_t *inbuf = NULL;
1506 struct iovec *recv_iov = NULL;
1510 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1512 TALLOC_FREE(subreq);
1513 data_blob_free(&state->blob_out);
1515 if (NT_STATUS_IS_OK(status)) {
1516 if (state->cli->server_domain[0] == '\0') {
1517 TALLOC_FREE(state->cli->server_domain);
1518 state->cli->server_domain = talloc_strdup(state->cli,
1519 state->ntlmssp_state->server.netbios_domain);
1520 if (state->cli->server_domain == NULL) {
1521 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1526 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1527 struct smbXcli_session *session = state->cli->smb2.session;
1529 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1531 * Windows server does not set the
1532 * SMB2_SESSION_FLAG_IS_GUEST nor
1533 * SMB2_SESSION_FLAG_IS_NULL flag.
1535 * This fix makes sure we do not try
1536 * to verify a signature on the final
1537 * session setup response.
1539 TALLOC_FREE(state->ntlmssp_state);
1540 tevent_req_done(req);
1544 status = smb2cli_session_set_session_key(session,
1545 state->ntlmssp_state->session_key,
1547 if (tevent_req_nterror(req, status)) {
1551 struct smbXcli_session *session = state->cli->smb1.session;
1553 status = smb1cli_session_set_session_key(session,
1554 state->ntlmssp_state->session_key);
1555 if (tevent_req_nterror(req, status)) {
1559 if (smb1cli_conn_activate_signing(
1560 state->cli->conn, state->ntlmssp_state->session_key,
1562 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1563 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1567 TALLOC_FREE(state->ntlmssp_state);
1568 tevent_req_done(req);
1571 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1572 tevent_req_nterror(req, status);
1576 if (blob_in.length == 0) {
1577 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1581 if ((state->turn == 1)
1582 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1583 DATA_BLOB tmp_blob = data_blob_null;
1584 /* the server might give us back two challenges */
1585 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1587 data_blob_free(&tmp_blob);
1589 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1590 OID_NTLMSSP, &msg_in);
1595 DEBUG(3,("Failed to parse auth response\n"));
1596 if (NT_STATUS_IS_OK(status)
1597 || NT_STATUS_EQUAL(status,
1598 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1600 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1605 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1607 if (!NT_STATUS_IS_OK(status)
1608 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1609 TALLOC_FREE(state->ntlmssp_state);
1610 tevent_req_nterror(req, status);
1614 state->blob_out = spnego_gen_auth(state, blob_out);
1615 if (tevent_req_nomem(state->blob_out.data, req)) {
1619 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1621 if (tevent_req_nomem(subreq, req)) {
1624 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1627 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1629 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1630 req, struct cli_session_setup_ntlmssp_state);
1633 if (tevent_req_is_nterror(req, &status)) {
1634 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1637 return NT_STATUS_OK;
1642 static char *cli_session_setup_get_principal(
1643 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1644 const char *remote_name, const char *dest_realm)
1646 char *principal = NULL;
1648 if (!lp_client_use_spnego_principal() ||
1649 strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1650 spnego_principal = NULL;
1652 if (spnego_principal != NULL) {
1653 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1654 "principal %s\n", spnego_principal));
1655 return talloc_strdup(mem_ctx, spnego_principal);
1657 if (is_ipaddress(remote_name) ||
1658 strequal(remote_name, STAR_SMBSERVER)) {
1662 DEBUG(3, ("cli_session_setup_spnego: using target "
1663 "hostname not SPNEGO principal\n"));
1666 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1667 if (realm == NULL) {
1670 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1671 remote_name, realm);
1674 principal = kerberos_get_principal_from_service_hostname(
1675 talloc_tos(), "cifs", remote_name, lp_realm());
1677 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1678 principal ? principal : "<null>"));
1684 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1685 const char *principal)
1689 account = talloc_strdup(mem_ctx, principal);
1690 if (account == NULL) {
1693 p = strchr_m(account, '@');
1700 /****************************************************************************
1701 Do a spnego encrypted session setup.
1703 user_domain: The shortname of the domain the user/machine is a member of.
1704 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1705 ****************************************************************************/
1707 struct cli_session_setup_spnego_state {
1708 struct tevent_context *ev;
1709 struct cli_state *cli;
1711 const char *account;
1713 const char *user_domain;
1714 const char *dest_realm;
1719 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1722 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1724 static struct tevent_req *cli_session_setup_spnego_send(
1725 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1726 const char *user, const char *pass, const char *user_domain,
1727 const char *dest_realm)
1729 struct tevent_req *req, *subreq;
1730 struct cli_session_setup_spnego_state *state;
1731 char *principal = NULL;
1732 char *OIDs[ASN1_MAX_OIDS];
1734 const DATA_BLOB *server_blob;
1736 req = tevent_req_create(mem_ctx, &state,
1737 struct cli_session_setup_spnego_state);
1745 state->user_domain = user_domain;
1746 state->dest_realm = dest_realm;
1748 state->account = cli_session_setup_get_account(state, user);
1749 if (tevent_req_nomem(state->account, req)) {
1750 return tevent_req_post(req, ev);
1753 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1755 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1756 (unsigned long)server_blob->length));
1758 /* the server might not even do spnego */
1759 if (server_blob->length == 0) {
1760 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1765 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1768 /* The server sent us the first part of the SPNEGO exchange in the
1769 * negprot reply. It is WRONG to depend on the principal sent in the
1770 * negprot reply, but right now we do it. If we don't receive one,
1771 * we try to best guess, then fall back to NTLM. */
1772 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1773 &principal, NULL) ||
1775 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1776 tevent_req_done(req);
1777 return tevent_req_post(req, ev);
1780 /* make sure the server understands kerberos */
1781 for (i=0;OIDs[i];i++) {
1783 DEBUG(3,("got OID=%s\n", OIDs[i]));
1785 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1786 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1787 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1788 cli->got_kerberos_mechanism = True;
1790 talloc_free(OIDs[i]);
1793 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1796 /* If password is set we reauthenticate to kerberos server
1797 * and do not store results */
1799 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1800 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1804 tmp = cli_session_setup_get_principal(
1805 talloc_tos(), principal, remote_name, dest_realm);
1806 TALLOC_FREE(principal);
1809 if (pass && *pass) {
1812 use_in_memory_ccache();
1813 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1816 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1817 TALLOC_FREE(principal);
1818 if (cli->fallback_after_kerberos)
1820 state->result = ADS_ERROR_KRB5(ret);
1821 tevent_req_done(req);
1822 return tevent_req_post(req, ev);
1827 subreq = cli_session_setup_kerberos_send(
1828 state, ev, cli, principal);
1829 if (tevent_req_nomem(subreq, req)) {
1830 return tevent_req_post(req, ev);
1832 tevent_req_set_callback(
1833 subreq, cli_session_setup_spnego_done_krb,
1841 subreq = cli_session_setup_ntlmssp_send(
1842 state, ev, cli, state->account, pass, user_domain);
1843 if (tevent_req_nomem(subreq, req)) {
1844 return tevent_req_post(req, ev);
1846 tevent_req_set_callback(
1847 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1852 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1854 struct tevent_req *req = tevent_req_callback_data(
1855 subreq, struct tevent_req);
1856 struct cli_session_setup_spnego_state *state = tevent_req_data(
1857 req, struct cli_session_setup_spnego_state);
1859 state->result = cli_session_setup_kerberos_recv(subreq);
1860 TALLOC_FREE(subreq);
1862 if (ADS_ERR_OK(state->result) ||
1863 !state->cli->fallback_after_kerberos) {
1864 tevent_req_done(req);
1868 subreq = cli_session_setup_ntlmssp_send(
1869 state, state->ev, state->cli, state->account, state->pass,
1870 state->user_domain);
1871 if (tevent_req_nomem(subreq, req)) {
1874 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1879 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1881 struct tevent_req *req = tevent_req_callback_data(
1882 subreq, struct tevent_req);
1883 struct cli_session_setup_spnego_state *state = tevent_req_data(
1884 req, struct cli_session_setup_spnego_state);
1887 status = cli_session_setup_ntlmssp_recv(subreq);
1888 TALLOC_FREE(subreq);
1889 state->result = ADS_ERROR_NT(status);
1890 tevent_req_done(req);
1893 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1895 struct cli_session_setup_spnego_state *state = tevent_req_data(
1896 req, struct cli_session_setup_spnego_state);
1898 return state->result;
1901 struct cli_session_setup_state {
1905 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1906 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1907 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1908 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1909 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1911 /****************************************************************************
1912 Send a session setup. The username and workgroup is in UNIX character
1913 format and must be converted to DOS codepage format before sending. If the
1914 password is in plaintext, the same should be done.
1915 ****************************************************************************/
1917 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1918 struct tevent_context *ev,
1919 struct cli_state *cli,
1921 const char *pass, int passlen,
1922 const char *ntpass, int ntpasslen,
1923 const char *workgroup)
1925 struct tevent_req *req, *subreq;
1926 struct cli_session_setup_state *state;
1929 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1931 req = tevent_req_create(mem_ctx, &state,
1932 struct cli_session_setup_state);
1938 user2 = talloc_strdup(state, user);
1940 user2 = talloc_strdup(state, "");
1942 if (user2 == NULL) {
1943 tevent_req_oom(req);
1944 return tevent_req_post(req, ev);
1951 /* allow for workgroups as part of the username */
1952 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1953 (p=strchr_m(user2,*lp_winbind_separator()))) {
1956 if (!strupper_m(user2)) {
1957 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1958 return tevent_req_post(req, ev);
1963 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1964 tevent_req_done(req);
1965 return tevent_req_post(req, ev);
1968 /* now work out what sort of session setup we are going to
1969 do. I have split this into separate functions to make the
1970 flow a bit easier to understand (tridge) */
1972 /* if its an older server then we have to use the older request format */
1974 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1975 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1976 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1977 " or 'client ntlmv2 auth = yes'\n"));
1978 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1979 return tevent_req_post(req, ev);
1982 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1983 !lp_client_plaintext_auth() && (*pass)) {
1984 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
1985 " or 'client ntlmv2 auth = yes'\n"));
1986 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1987 return tevent_req_post(req, ev);
1990 subreq = cli_session_setup_lanman2_send(
1991 state, ev, cli, user, pass, passlen, workgroup);
1992 if (tevent_req_nomem(subreq, req)) {
1993 return tevent_req_post(req, ev);
1995 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2000 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2001 const char *remote_realm = cli_state_remote_realm(cli);
2003 subreq = cli_session_setup_spnego_send(
2004 state, ev, cli, user, pass, workgroup, remote_realm);
2005 if (tevent_req_nomem(subreq, req)) {
2006 return tevent_req_post(req, ev);
2008 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2013 /* if no user is supplied then we have to do an anonymous connection.
2014 passwords are ignored */
2016 if (!user || !*user) {
2017 subreq = cli_session_setup_guest_send(state, ev, cli);
2018 if (tevent_req_nomem(subreq, req)) {
2019 return tevent_req_post(req, ev);
2021 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2026 /* if the server is share level then send a plaintext null
2027 password at this point. The password is sent in the tree
2030 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2031 subreq = cli_session_setup_plain_send(
2032 state, ev, cli, user, "", workgroup);
2033 if (tevent_req_nomem(subreq, req)) {
2034 return tevent_req_post(req, ev);
2036 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2041 /* if the server doesn't support encryption then we have to use
2042 plaintext. The second password is ignored */
2044 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2045 if (!lp_client_plaintext_auth() && (*pass)) {
2046 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2047 " or 'client ntlmv2 auth = yes'\n"));
2048 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2049 return tevent_req_post(req, ev);
2051 subreq = cli_session_setup_plain_send(
2052 state, ev, cli, user, pass, workgroup);
2053 if (tevent_req_nomem(subreq, req)) {
2054 return tevent_req_post(req, ev);
2056 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2061 /* if the server supports extended security then use SPNEGO */
2063 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2064 const char *remote_realm = cli_state_remote_realm(cli);
2066 subreq = cli_session_setup_spnego_send(
2067 state, ev, cli, user, pass, workgroup, remote_realm);
2068 if (tevent_req_nomem(subreq, req)) {
2069 return tevent_req_post(req, ev);
2071 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2075 /* otherwise do a NT1 style session setup */
2077 subreq = cli_session_setup_nt1_send(
2078 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2080 if (tevent_req_nomem(subreq, req)) {
2081 return tevent_req_post(req, ev);
2083 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2088 tevent_req_done(req);
2089 return tevent_req_post(req, ev);
2092 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2094 struct tevent_req *req = tevent_req_callback_data(
2095 subreq, struct tevent_req);
2098 status = cli_session_setup_lanman2_recv(subreq);
2099 TALLOC_FREE(subreq);
2100 if (!NT_STATUS_IS_OK(status)) {
2101 tevent_req_nterror(req, status);
2104 tevent_req_done(req);
2107 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2109 struct tevent_req *req = tevent_req_callback_data(
2110 subreq, struct tevent_req);
2113 status = cli_session_setup_spnego_recv(subreq);
2114 TALLOC_FREE(subreq);
2115 if (!ADS_ERR_OK(status)) {
2116 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2117 tevent_req_nterror(req, ads_ntstatus(status));
2120 tevent_req_done(req);
2123 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2125 struct tevent_req *req = tevent_req_callback_data(
2126 subreq, struct tevent_req);
2129 status = cli_session_setup_guest_recv(subreq);
2130 TALLOC_FREE(subreq);
2131 if (!NT_STATUS_IS_OK(status)) {
2132 tevent_req_nterror(req, status);
2135 tevent_req_done(req);
2138 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2140 struct tevent_req *req = tevent_req_callback_data(
2141 subreq, struct tevent_req);
2144 status = cli_session_setup_plain_recv(subreq);
2145 TALLOC_FREE(subreq);
2146 if (!NT_STATUS_IS_OK(status)) {
2147 tevent_req_nterror(req, status);
2150 tevent_req_done(req);
2153 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2155 struct tevent_req *req = tevent_req_callback_data(
2156 subreq, struct tevent_req);
2159 status = cli_session_setup_nt1_recv(subreq);
2160 TALLOC_FREE(subreq);
2161 if (!NT_STATUS_IS_OK(status)) {
2162 DEBUG(3, ("cli_session_setup: NT1 session setup "
2163 "failed: %s\n", nt_errstr(status)));
2164 tevent_req_nterror(req, status);
2167 tevent_req_done(req);
2170 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2172 return tevent_req_simple_recv_ntstatus(req);
2175 NTSTATUS cli_session_setup(struct cli_state *cli,
2177 const char *pass, int passlen,
2178 const char *ntpass, int ntpasslen,
2179 const char *workgroup)
2181 struct tevent_context *ev;
2182 struct tevent_req *req;
2183 NTSTATUS status = NT_STATUS_NO_MEMORY;
2185 if (smbXcli_conn_has_async_calls(cli->conn)) {
2186 return NT_STATUS_INVALID_PARAMETER;
2188 ev = samba_tevent_context_init(talloc_tos());
2192 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2193 ntpass, ntpasslen, workgroup);
2197 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2200 status = cli_session_setup_recv(req);
2206 /****************************************************************************
2208 *****************************************************************************/
2210 struct cli_ulogoff_state {
2211 struct cli_state *cli;
2215 static void cli_ulogoff_done(struct tevent_req *subreq);
2217 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2218 struct tevent_context *ev,
2219 struct cli_state *cli)
2221 struct tevent_req *req, *subreq;
2222 struct cli_ulogoff_state *state;
2224 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2230 SCVAL(state->vwv+0, 0, 0xFF);
2231 SCVAL(state->vwv+1, 0, 0);
2232 SSVAL(state->vwv+2, 0, 0);
2234 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2236 if (tevent_req_nomem(subreq, req)) {
2237 return tevent_req_post(req, ev);
2239 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2243 static void cli_ulogoff_done(struct tevent_req *subreq)
2245 struct tevent_req *req = tevent_req_callback_data(
2246 subreq, struct tevent_req);
2247 struct cli_ulogoff_state *state = tevent_req_data(
2248 req, struct cli_ulogoff_state);
2251 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 tevent_req_nterror(req, status);
2256 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2257 tevent_req_done(req);
2260 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2262 return tevent_req_simple_recv_ntstatus(req);
2265 NTSTATUS cli_ulogoff(struct cli_state *cli)
2267 struct tevent_context *ev;
2268 struct tevent_req *req;
2269 NTSTATUS status = NT_STATUS_NO_MEMORY;
2271 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2272 status = smb2cli_logoff(cli->conn,
2275 if (!NT_STATUS_IS_OK(status)) {
2278 smb2cli_session_set_id_and_flags(cli->smb2.session,
2280 return NT_STATUS_OK;
2283 if (smbXcli_conn_has_async_calls(cli->conn)) {
2284 return NT_STATUS_INVALID_PARAMETER;
2286 ev = samba_tevent_context_init(talloc_tos());
2290 req = cli_ulogoff_send(ev, ev, cli);
2294 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2297 status = cli_ulogoff_recv(req);
2303 /****************************************************************************
2305 ****************************************************************************/
2307 struct cli_tcon_andx_state {
2308 struct cli_state *cli;
2313 static void cli_tcon_andx_done(struct tevent_req *subreq);
2315 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2316 struct tevent_context *ev,
2317 struct cli_state *cli,
2318 const char *share, const char *dev,
2319 const char *pass, int passlen,
2320 struct tevent_req **psmbreq)
2322 struct tevent_req *req, *subreq;
2323 struct cli_tcon_andx_state *state;
2328 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2329 uint16_t tcon_flags = 0;
2333 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2340 cli->share = talloc_strdup(cli, share);
2345 /* in user level security don't send a password now */
2346 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2349 } else if (pass == NULL) {
2350 DEBUG(1, ("Server not using user level security and no "
2351 "password supplied.\n"));
2355 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2356 *pass && passlen != 24) {
2357 if (!lp_client_lanman_auth()) {
2358 DEBUG(1, ("Server requested LANMAN password "
2359 "(share-level security) but "
2360 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2365 * Non-encrypted passwords - convert to DOS codepage before
2368 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2370 pass = (const char *)p24;
2372 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2373 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2377 if (!lp_client_plaintext_auth() && (*pass)) {
2378 DEBUG(1, ("Server requested PLAINTEXT "
2380 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2385 * Non-encrypted passwords - convert to DOS codepage
2388 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2389 if (tevent_req_nomem(tmp_pass, req)) {
2390 return tevent_req_post(req, ev);
2392 tmp_pass = trans2_bytes_push_str(tmp_pass,
2393 false, /* always DOS */
2397 if (tevent_req_nomem(tmp_pass, req)) {
2398 return tevent_req_post(req, ev);
2400 pass = (const char *)tmp_pass;
2401 passlen = talloc_get_size(tmp_pass);
2405 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2406 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2408 SCVAL(vwv+0, 0, 0xFF);
2411 SSVAL(vwv+2, 0, tcon_flags);
2412 SSVAL(vwv+3, 0, passlen);
2414 if (passlen && pass) {
2415 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2417 bytes = talloc_array(state, uint8_t, 0);
2423 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2424 smbXcli_conn_remote_name(cli->conn), share);
2429 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2434 * Add the devicetype
2436 tmp = talloc_strdup_upper(talloc_tos(), dev);
2441 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2444 if (bytes == NULL) {
2449 state->bytes.iov_base = (void *)bytes;
2450 state->bytes.iov_len = talloc_get_size(bytes);
2452 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2454 if (subreq == NULL) {
2458 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2463 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2464 return tevent_req_post(req, ev);
2467 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2468 struct tevent_context *ev,
2469 struct cli_state *cli,
2470 const char *share, const char *dev,
2471 const char *pass, int passlen)
2473 struct tevent_req *req, *subreq;
2476 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2481 if (subreq == NULL) {
2484 status = smb1cli_req_chain_submit(&subreq, 1);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 tevent_req_nterror(req, status);
2487 return tevent_req_post(req, ev);
2492 static void cli_tcon_andx_done(struct tevent_req *subreq)
2494 struct tevent_req *req = tevent_req_callback_data(
2495 subreq, struct tevent_req);
2496 struct cli_tcon_andx_state *state = tevent_req_data(
2497 req, struct cli_tcon_andx_state);
2498 struct cli_state *cli = state->cli;
2506 uint16_t optional_support = 0;
2508 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2509 &num_bytes, &bytes);
2510 TALLOC_FREE(subreq);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 tevent_req_nterror(req, status);
2516 inhdr = in + NBT_HDR_SIZE;
2519 if (clistr_pull_talloc(cli,
2520 (const char *)inhdr,
2521 SVAL(inhdr, HDR_FLG2),
2525 STR_TERMINATE|STR_ASCII) == -1) {
2526 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2530 cli->dev = talloc_strdup(cli, "");
2531 if (cli->dev == NULL) {
2532 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2537 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2538 /* almost certainly win95 - enable bug fixes */
2543 * Make sure that we have the optional support 16-bit field. WCT > 2.
2544 * Avoids issues when connecting to Win9x boxes sharing files
2547 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2548 optional_support = SVAL(vwv+2, 0);
2551 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2552 smb1cli_session_protect_session_key(cli->smb1.session);
2555 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2556 SVAL(inhdr, HDR_TID),
2558 0, /* maximal_access */
2559 0, /* guest_maximal_access */
2561 NULL); /* fs_type */
2563 tevent_req_done(req);
2566 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2568 return tevent_req_simple_recv_ntstatus(req);
2571 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2572 const char *dev, const char *pass, int passlen)
2574 TALLOC_CTX *frame = talloc_stackframe();
2575 struct tevent_context *ev;
2576 struct tevent_req *req;
2577 NTSTATUS status = NT_STATUS_NO_MEMORY;
2579 if (smbXcli_conn_has_async_calls(cli->conn)) {
2581 * Can't use sync call while an async call is in flight
2583 status = NT_STATUS_INVALID_PARAMETER;
2587 ev = samba_tevent_context_init(frame);
2592 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2597 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2601 status = cli_tcon_andx_recv(req);
2607 struct cli_tree_connect_state {
2608 struct cli_state *cli;
2611 static struct tevent_req *cli_raw_tcon_send(
2612 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2613 const char *service, const char *pass, const char *dev);
2614 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2615 uint16 *max_xmit, uint16 *tid);
2617 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2618 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2619 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2621 static struct tevent_req *cli_tree_connect_send(
2622 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2623 const char *share, const char *dev, const char *pass, int passlen)
2625 struct tevent_req *req, *subreq;
2626 struct cli_tree_connect_state *state;
2628 req = tevent_req_create(mem_ctx, &state,
2629 struct cli_tree_connect_state);
2635 cli->share = talloc_strdup(cli, share);
2636 if (tevent_req_nomem(cli->share, req)) {
2637 return tevent_req_post(req, ev);
2640 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2643 cli->smb2.tcon = smbXcli_tcon_create(cli);
2644 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2645 return tevent_req_post(req, ev);
2648 unc = talloc_asprintf(state, "\\\\%s\\%s",
2649 smbXcli_conn_remote_name(cli->conn),
2651 if (tevent_req_nomem(unc, req)) {
2652 return tevent_req_post(req, ev);
2655 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2656 cli->smb2.session, cli->smb2.tcon,
2659 if (tevent_req_nomem(subreq, req)) {
2660 return tevent_req_post(req, ev);
2662 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2667 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2668 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2670 if (tevent_req_nomem(subreq, req)) {
2671 return tevent_req_post(req, ev);
2673 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2678 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2679 if (tevent_req_nomem(subreq, req)) {
2680 return tevent_req_post(req, ev);
2682 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2687 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2689 tevent_req_simple_finish_ntstatus(
2690 subreq, smb2cli_tcon_recv(subreq));
2693 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2695 tevent_req_simple_finish_ntstatus(
2696 subreq, cli_tcon_andx_recv(subreq));
2699 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2701 struct tevent_req *req = tevent_req_callback_data(
2702 subreq, struct tevent_req);
2703 struct cli_tree_connect_state *state = tevent_req_data(
2704 req, struct cli_tree_connect_state);
2706 uint16_t max_xmit = 0;
2709 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2710 if (tevent_req_nterror(req, status)) {
2714 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2716 0, /* optional_support */
2717 0, /* maximal_access */
2718 0, /* guest_maximal_access */
2720 NULL); /* fs_type */
2722 tevent_req_done(req);
2725 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2727 return tevent_req_simple_recv_ntstatus(req);
2730 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2731 const char *dev, const char *pass, int passlen)
2733 struct tevent_context *ev;
2734 struct tevent_req *req;
2735 NTSTATUS status = NT_STATUS_NO_MEMORY;
2737 if (smbXcli_conn_has_async_calls(cli->conn)) {
2738 return NT_STATUS_INVALID_PARAMETER;
2740 ev = samba_tevent_context_init(talloc_tos());
2744 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2748 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2751 status = cli_tree_connect_recv(req);
2757 /****************************************************************************
2758 Send a tree disconnect.
2759 ****************************************************************************/
2761 struct cli_tdis_state {
2762 struct cli_state *cli;
2765 static void cli_tdis_done(struct tevent_req *subreq);
2767 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2768 struct tevent_context *ev,
2769 struct cli_state *cli)
2771 struct tevent_req *req, *subreq;
2772 struct cli_tdis_state *state;
2774 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2780 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2781 if (tevent_req_nomem(subreq, req)) {
2782 return tevent_req_post(req, ev);
2784 tevent_req_set_callback(subreq, cli_tdis_done, req);
2788 static void cli_tdis_done(struct tevent_req *subreq)
2790 struct tevent_req *req = tevent_req_callback_data(
2791 subreq, struct tevent_req);
2792 struct cli_tdis_state *state = tevent_req_data(
2793 req, struct cli_tdis_state);
2796 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2797 TALLOC_FREE(subreq);
2798 if (!NT_STATUS_IS_OK(status)) {
2799 tevent_req_nterror(req, status);
2802 cli_state_set_tid(state->cli, UINT16_MAX);
2803 tevent_req_done(req);
2806 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2808 return tevent_req_simple_recv_ntstatus(req);
2811 NTSTATUS cli_tdis(struct cli_state *cli)
2813 struct tevent_context *ev;
2814 struct tevent_req *req;
2815 NTSTATUS status = NT_STATUS_NO_MEMORY;
2817 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2818 return smb2cli_tdis(cli->conn,
2824 if (smbXcli_conn_has_async_calls(cli->conn)) {
2825 return NT_STATUS_INVALID_PARAMETER;
2827 ev = samba_tevent_context_init(talloc_tos());
2831 req = cli_tdis_send(ev, ev, cli);
2835 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2838 status = cli_tdis_recv(req);
2844 struct cli_connect_sock_state {
2845 const char **called_names;
2846 const char **calling_names;
2852 static void cli_connect_sock_done(struct tevent_req *subreq);
2855 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2859 static struct tevent_req *cli_connect_sock_send(
2860 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2861 const char *host, int name_type, const struct sockaddr_storage *pss,
2862 const char *myname, uint16_t port)
2864 struct tevent_req *req, *subreq;
2865 struct cli_connect_sock_state *state;
2867 struct sockaddr_storage *addrs;
2868 unsigned i, num_addrs;
2871 req = tevent_req_create(mem_ctx, &state,
2872 struct cli_connect_sock_state);
2877 prog = getenv("LIBSMB_PROG");
2879 state->fd = sock_exec(prog);
2880 if (state->fd == -1) {
2881 status = map_nt_error_from_unix(errno);
2882 tevent_req_nterror(req, status);
2885 tevent_req_done(req);
2887 return tevent_req_post(req, ev);
2890 if ((pss == NULL) || is_zero_addr(pss)) {
2893 * Here we cheat. resolve_name_list is not async at all. So
2894 * this call will only be really async if the name lookup has
2895 * been done externally.
2898 status = resolve_name_list(state, host, name_type,
2899 &addrs, &num_addrs);
2900 if (!NT_STATUS_IS_OK(status)) {
2901 tevent_req_nterror(req, status);
2902 return tevent_req_post(req, ev);
2905 addrs = talloc_array(state, struct sockaddr_storage, 1);
2906 if (tevent_req_nomem(addrs, req)) {
2907 return tevent_req_post(req, ev);
2913 state->called_names = talloc_array(state, const char *, num_addrs);
2914 if (tevent_req_nomem(state->called_names, req)) {
2915 return tevent_req_post(req, ev);
2917 state->called_types = talloc_array(state, int, num_addrs);
2918 if (tevent_req_nomem(state->called_types, req)) {
2919 return tevent_req_post(req, ev);
2921 state->calling_names = talloc_array(state, const char *, num_addrs);
2922 if (tevent_req_nomem(state->calling_names, req)) {
2923 return tevent_req_post(req, ev);
2925 for (i=0; i<num_addrs; i++) {
2926 state->called_names[i] = host;
2927 state->called_types[i] = name_type;
2928 state->calling_names[i] = myname;
2931 subreq = smbsock_any_connect_send(
2932 state, ev, addrs, state->called_names, state->called_types,
2933 state->calling_names, NULL, num_addrs, port);
2934 if (tevent_req_nomem(subreq, req)) {
2935 return tevent_req_post(req, ev);
2937 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2941 static void cli_connect_sock_done(struct tevent_req *subreq)
2943 struct tevent_req *req = tevent_req_callback_data(
2944 subreq, struct tevent_req);
2945 struct cli_connect_sock_state *state = tevent_req_data(
2946 req, struct cli_connect_sock_state);
2949 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2951 TALLOC_FREE(subreq);
2952 if (tevent_req_nterror(req, status)) {
2955 set_socket_options(state->fd, lp_socket_options());
2956 tevent_req_done(req);
2959 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2960 int *pfd, uint16_t *pport)
2962 struct cli_connect_sock_state *state = tevent_req_data(
2963 req, struct cli_connect_sock_state);
2966 if (tevent_req_is_nterror(req, &status)) {
2970 *pport = state->port;
2971 return NT_STATUS_OK;
2974 struct cli_connect_nb_state {
2975 const char *desthost;
2978 struct cli_state *cli;
2981 static void cli_connect_nb_done(struct tevent_req *subreq);
2983 static struct tevent_req *cli_connect_nb_send(
2984 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2985 const char *host, const struct sockaddr_storage *dest_ss,
2986 uint16_t port, int name_type, const char *myname,
2987 int signing_state, int flags)
2989 struct tevent_req *req, *subreq;
2990 struct cli_connect_nb_state *state;
2993 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2997 state->desthost = host;
2998 state->signing_state = signing_state;
2999 state->flags = flags;
3001 p = strchr(host, '#');
3003 name_type = strtol(p+1, NULL, 16);
3004 host = talloc_strndup(state, host, p - host);
3005 if (tevent_req_nomem(host, req)) {
3006 return tevent_req_post(req, ev);
3010 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3012 if (tevent_req_nomem(subreq, req)) {
3013 return tevent_req_post(req, ev);
3015 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3019 static void cli_connect_nb_done(struct tevent_req *subreq)
3021 struct tevent_req *req = tevent_req_callback_data(
3022 subreq, struct tevent_req);
3023 struct cli_connect_nb_state *state = tevent_req_data(
3024 req, struct cli_connect_nb_state);
3029 status = cli_connect_sock_recv(subreq, &fd, &port);
3030 TALLOC_FREE(subreq);
3031 if (tevent_req_nterror(req, status)) {
3035 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3036 state->signing_state, state->flags);
3037 if (tevent_req_nomem(state->cli, req)) {
3041 tevent_req_done(req);
3044 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3045 struct cli_state **pcli)
3047 struct cli_connect_nb_state *state = tevent_req_data(
3048 req, struct cli_connect_nb_state);
3051 if (tevent_req_is_nterror(req, &status)) {
3054 *pcli = talloc_move(NULL, &state->cli);
3055 return NT_STATUS_OK;
3058 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3059 uint16_t port, int name_type, const char *myname,
3060 int signing_state, int flags, struct cli_state **pcli)
3062 struct tevent_context *ev;
3063 struct tevent_req *req;
3064 NTSTATUS status = NT_STATUS_NO_MEMORY;
3066 ev = samba_tevent_context_init(talloc_tos());
3070 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3071 myname, signing_state, flags);
3075 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3078 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3081 status = cli_connect_nb_recv(req, pcli);
3087 struct cli_start_connection_state {
3088 struct tevent_context *ev;
3089 struct cli_state *cli;
3092 static void cli_start_connection_connected(struct tevent_req *subreq);
3093 static void cli_start_connection_done(struct tevent_req *subreq);
3096 establishes a connection to after the negprot.
3097 @param output_cli A fully initialised cli structure, non-null only on success
3098 @param dest_host The netbios name of the remote host
3099 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3100 @param port (optional) The destination port (0 for default)
3103 static struct tevent_req *cli_start_connection_send(
3104 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3105 const char *my_name, const char *dest_host,
3106 const struct sockaddr_storage *dest_ss, int port,
3107 int signing_state, int flags)
3109 struct tevent_req *req, *subreq;
3110 struct cli_start_connection_state *state;
3112 req = tevent_req_create(mem_ctx, &state,
3113 struct cli_start_connection_state);
3119 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3120 0x20, my_name, signing_state, flags);
3121 if (tevent_req_nomem(subreq, req)) {
3122 return tevent_req_post(req, ev);
3124 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3128 static void cli_start_connection_connected(struct tevent_req *subreq)
3130 struct tevent_req *req = tevent_req_callback_data(
3131 subreq, struct tevent_req);
3132 struct cli_start_connection_state *state = tevent_req_data(
3133 req, struct cli_start_connection_state);
3136 status = cli_connect_nb_recv(subreq, &state->cli);
3137 TALLOC_FREE(subreq);
3138 if (tevent_req_nterror(req, status)) {
3142 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3143 state->cli->timeout,
3144 lp_client_min_protocol(),
3145 lp_client_max_protocol());
3146 if (tevent_req_nomem(subreq, req)) {
3149 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3152 static void cli_start_connection_done(struct tevent_req *subreq)
3154 struct tevent_req *req = tevent_req_callback_data(
3155 subreq, struct tevent_req);
3156 struct cli_start_connection_state *state = tevent_req_data(
3157 req, struct cli_start_connection_state);
3160 status = smbXcli_negprot_recv(subreq);
3161 TALLOC_FREE(subreq);
3162 if (tevent_req_nterror(req, status)) {
3166 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3167 /* Ensure we ask for some initial credits. */
3168 smb2cli_conn_set_max_credits(state->cli->conn,
3169 DEFAULT_SMB2_MAX_CREDITS);
3172 tevent_req_done(req);
3175 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3176 struct cli_state **output_cli)
3178 struct cli_start_connection_state *state = tevent_req_data(
3179 req, struct cli_start_connection_state);
3182 if (tevent_req_is_nterror(req, &status)) {
3185 *output_cli = state->cli;
3187 return NT_STATUS_OK;
3190 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3191 const char *my_name,
3192 const char *dest_host,
3193 const struct sockaddr_storage *dest_ss, int port,
3194 int signing_state, int flags)
3196 struct tevent_context *ev;
3197 struct tevent_req *req;
3198 NTSTATUS status = NT_STATUS_NO_MEMORY;
3200 ev = samba_tevent_context_init(talloc_tos());
3204 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3205 port, signing_state, flags);
3209 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3212 status = cli_start_connection_recv(req, output_cli);
3219 establishes a connection right up to doing tconX, password specified.
3220 @param output_cli A fully initialised cli structure, non-null only on success
3221 @param dest_host The netbios name of the remote host
3222 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3223 @param port (optional) The destination port (0 for default)
3224 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3225 @param service_type The 'type' of serivice.
3226 @param user Username, unix string
3227 @param domain User's domain
3228 @param password User's password, unencrypted unix string.
3231 struct cli_full_connection_state {
3232 struct tevent_context *ev;
3233 const char *service;
3234 const char *service_type;
3237 const char *password;
3240 struct cli_state *cli;
3243 static int cli_full_connection_state_destructor(
3244 struct cli_full_connection_state *s);
3245 static void cli_full_connection_started(struct tevent_req *subreq);
3246 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3247 static void cli_full_connection_done(struct tevent_req *subreq);
3249 struct tevent_req *cli_full_connection_send(
3250 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3251 const char *my_name, const char *dest_host,
3252 const struct sockaddr_storage *dest_ss, int port,
3253 const char *service, const char *service_type,
3254 const char *user, const char *domain,
3255 const char *password, int flags, int signing_state)
3257 struct tevent_req *req, *subreq;
3258 struct cli_full_connection_state *state;
3260 req = tevent_req_create(mem_ctx, &state,
3261 struct cli_full_connection_state);
3265 talloc_set_destructor(state, cli_full_connection_state_destructor);
3268 state->service = service;
3269 state->service_type = service_type;
3271 state->domain = domain;
3272 state->password = password;
3273 state->flags = flags;
3275 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3276 if (state->password == NULL) {
3277 state->password = "";
3280 subreq = cli_start_connection_send(
3281 state, ev, my_name, dest_host, dest_ss, port,
3282 signing_state, flags);
3283 if (tevent_req_nomem(subreq, req)) {
3284 return tevent_req_post(req, ev);
3286 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3290 static int cli_full_connection_state_destructor(
3291 struct cli_full_connection_state *s)
3293 if (s->cli != NULL) {
3294 cli_shutdown(s->cli);
3300 static void cli_full_connection_started(struct tevent_req *subreq)
3302 struct tevent_req *req = tevent_req_callback_data(
3303 subreq, struct tevent_req);
3304 struct cli_full_connection_state *state = tevent_req_data(
3305 req, struct cli_full_connection_state);
3308 status = cli_start_connection_recv(subreq, &state->cli);
3309 TALLOC_FREE(subreq);
3310 if (tevent_req_nterror(req, status)) {
3313 subreq = cli_session_setup_send(
3314 state, state->ev, state->cli, state->user,
3315 state->password, state->pw_len, state->password, state->pw_len,
3317 if (tevent_req_nomem(subreq, req)) {
3320 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3323 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3325 struct tevent_req *req = tevent_req_callback_data(
3326 subreq, struct tevent_req);
3327 struct cli_full_connection_state *state = tevent_req_data(
3328 req, struct cli_full_connection_state);
3331 status = cli_session_setup_recv(subreq);
3332 TALLOC_FREE(subreq);
3334 if (!NT_STATUS_IS_OK(status) &&
3335 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3337 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3339 subreq = cli_session_setup_send(
3340 state, state->ev, state->cli, "", "", 0, "", 0,
3342 if (tevent_req_nomem(subreq, req)) {
3345 tevent_req_set_callback(
3346 subreq, cli_full_connection_sess_set_up, req);
3350 if (tevent_req_nterror(req, status)) {
3354 if (state->service != NULL) {
3355 subreq = cli_tree_connect_send(
3356 state, state->ev, state->cli,
3357 state->service, state->service_type,
3358 state->password, state->pw_len);
3359 if (tevent_req_nomem(subreq, req)) {
3362 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3366 tevent_req_done(req);
3369 static void cli_full_connection_done(struct tevent_req *subreq)
3371 struct tevent_req *req = tevent_req_callback_data(
3372 subreq, struct tevent_req);
3375 status = cli_tree_connect_recv(subreq);
3376 TALLOC_FREE(subreq);
3377 if (tevent_req_nterror(req, status)) {
3381 tevent_req_done(req);
3384 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3385 struct cli_state **output_cli)
3387 struct cli_full_connection_state *state = tevent_req_data(
3388 req, struct cli_full_connection_state);
3391 if (tevent_req_is_nterror(req, &status)) {
3394 *output_cli = state->cli;
3395 talloc_set_destructor(state, NULL);
3396 return NT_STATUS_OK;
3399 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3400 const char *my_name,
3401 const char *dest_host,
3402 const struct sockaddr_storage *dest_ss, int port,
3403 const char *service, const char *service_type,
3404 const char *user, const char *domain,
3405 const char *password, int flags,
3408 struct tevent_context *ev;
3409 struct tevent_req *req;
3410 NTSTATUS status = NT_STATUS_NO_MEMORY;
3412 ev = samba_tevent_context_init(talloc_tos());
3416 req = cli_full_connection_send(
3417 ev, ev, my_name, dest_host, dest_ss, port, service,
3418 service_type, user, domain, password, flags, signing_state);
3422 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3425 status = cli_full_connection_recv(req, output_cli);
3431 /****************************************************************************
3432 Send an old style tcon.
3433 ****************************************************************************/
3434 struct cli_raw_tcon_state {
3438 static void cli_raw_tcon_done(struct tevent_req *subreq);
3440 static struct tevent_req *cli_raw_tcon_send(
3441 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3442 const char *service, const char *pass, const char *dev)
3444 struct tevent_req *req, *subreq;
3445 struct cli_raw_tcon_state *state;
3448 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3453 if (!lp_client_plaintext_auth() && (*pass)) {
3454 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3455 " or 'client ntlmv2 auth = yes'\n"));
3456 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3457 return tevent_req_post(req, ev);
3460 bytes = talloc_array(state, uint8_t, 0);
3461 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3462 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3463 service, strlen(service)+1, NULL);
3464 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3465 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3466 pass, strlen(pass)+1, NULL);
3467 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3468 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3469 dev, strlen(dev)+1, NULL);
3471 if (tevent_req_nomem(bytes, req)) {
3472 return tevent_req_post(req, ev);
3475 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3476 talloc_get_size(bytes), bytes);
3477 if (tevent_req_nomem(subreq, req)) {
3478 return tevent_req_post(req, ev);
3480 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3484 static void cli_raw_tcon_done(struct tevent_req *subreq)
3486 struct tevent_req *req = tevent_req_callback_data(
3487 subreq, struct tevent_req);
3488 struct cli_raw_tcon_state *state = tevent_req_data(
3489 req, struct cli_raw_tcon_state);
3492 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3494 TALLOC_FREE(subreq);
3495 if (tevent_req_nterror(req, status)) {
3498 tevent_req_done(req);
3501 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3502 uint16 *max_xmit, uint16 *tid)
3504 struct cli_raw_tcon_state *state = tevent_req_data(
3505 req, struct cli_raw_tcon_state);
3508 if (tevent_req_is_nterror(req, &status)) {
3511 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3512 *tid = SVAL(state->ret_vwv + 1, 0);
3513 return NT_STATUS_OK;
3516 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3517 const char *service, const char *pass, const char *dev,
3518 uint16 *max_xmit, uint16 *tid)
3520 struct tevent_context *ev;
3521 struct tevent_req *req;
3522 NTSTATUS status = NT_STATUS_NO_MEMORY;
3524 ev = samba_tevent_context_init(talloc_tos());
3528 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3532 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3535 status = cli_raw_tcon_recv(req, max_xmit, tid);
3541 /* Return a cli_state pointing at the IPC$ share for the given server */
3543 struct cli_state *get_ipc_connect(char *server,
3544 struct sockaddr_storage *server_ss,
3545 const struct user_auth_info *user_info)
3547 struct cli_state *cli;
3549 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3551 if (user_info->use_kerberos) {
3552 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3555 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3556 user_info->username ? user_info->username : "",
3558 user_info->password ? user_info->password : "",
3560 SMB_SIGNING_DEFAULT);
3562 if (NT_STATUS_IS_OK(nt_status)) {
3564 } else if (is_ipaddress(server)) {
3565 /* windows 9* needs a correct NMB name for connections */
3566 fstring remote_name;
3568 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3569 cli = get_ipc_connect(remote_name, server_ss, user_info);
3578 * Given the IP address of a master browser on the network, return its
3579 * workgroup and connect to it.
3581 * This function is provided to allow additional processing beyond what
3582 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3583 * browsers and obtain each master browsers' list of domains (in case the
3584 * first master browser is recently on the network and has not yet
3585 * synchronized with other master browsers and therefore does not yet have the
3586 * entire network browse list)
3589 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3590 struct sockaddr_storage *mb_ip,
3591 const struct user_auth_info *user_info,
3592 char **pp_workgroup_out)
3594 char addr[INET6_ADDRSTRLEN];
3596 struct cli_state *cli;
3597 struct sockaddr_storage server_ss;
3599 *pp_workgroup_out = NULL;
3601 print_sockaddr(addr, sizeof(addr), mb_ip);
3602 DEBUG(99, ("Looking up name of master browser %s\n",
3606 * Do a name status query to find out the name of the master browser.
3607 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3608 * master browser will not respond to a wildcard query (or, at least,
3609 * an NT4 server acting as the domain master browser will not).
3611 * We might be able to use ONLY the query on MSBROWSE, but that's not
3612 * yet been tested with all Windows versions, so until it is, leave
3613 * the original wildcard query as the first choice and fall back to
3614 * MSBROWSE if the wildcard query fails.
3616 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3617 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3619 DEBUG(99, ("Could not retrieve name status for %s\n",
3624 if (!find_master_ip(name, &server_ss)) {
3625 DEBUG(99, ("Could not find master ip for %s\n", name));
3629 *pp_workgroup_out = talloc_strdup(ctx, name);
3631 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3633 print_sockaddr(addr, sizeof(addr), &server_ss);
3634 cli = get_ipc_connect(addr, &server_ss, user_info);
3640 * Return the IP address and workgroup of a master browser on the network, and
3644 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3645 const struct user_auth_info *user_info,
3646 char **pp_workgroup_out)
3648 struct sockaddr_storage *ip_list;
3649 struct cli_state *cli;
3653 *pp_workgroup_out = NULL;
3655 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3657 /* Go looking for workgroups by broadcasting on the local network */
3659 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3661 if (!NT_STATUS_IS_OK(status)) {
3662 DEBUG(99, ("No master browsers responded: %s\n",
3663 nt_errstr(status)));
3667 for (i = 0; i < count; i++) {
3668 char addr[INET6_ADDRSTRLEN];
3669 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3670 DEBUG(99, ("Found master browser %s\n", addr));
3672 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3673 user_info, pp_workgroup_out);