2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
41 #define STAR_SMBSERVER "*SMBSERVER"
43 /********************************************************
44 Utility function to ensure we always return at least
45 a valid char * pointer to an empty string for the
46 cli->server_os, cli->server_type and cli->server_domain
48 *******************************************************/
50 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
57 *destlen = clistr_pull_talloc(mem_ctx,
65 return NT_STATUS_NO_MEMORY;
69 *dest = talloc_strdup(mem_ctx, "");
71 return NT_STATUS_NO_MEMORY;
77 /****************************************************************************
78 Do an old lanman2 style session setup.
79 ****************************************************************************/
81 struct cli_session_setup_lanman2_state {
82 struct cli_state *cli;
87 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
89 static struct tevent_req *cli_session_setup_lanman2_send(
90 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
91 struct cli_state *cli, const char *user,
92 const char *pass, size_t passlen,
93 const char *workgroup)
95 struct tevent_req *req, *subreq;
96 struct cli_session_setup_lanman2_state *state;
97 DATA_BLOB lm_response = data_blob_null;
101 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
103 req = tevent_req_create(mem_ctx, &state,
104 struct cli_session_setup_lanman2_state);
113 * if in share level security then don't send a password now
115 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
120 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
123 * Encrypted mode needed, and non encrypted password
126 lm_response = data_blob(NULL, 24);
127 if (tevent_req_nomem(lm_response.data, req)) {
128 return tevent_req_post(req, ev);
131 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
132 (uint8_t *)lm_response.data)) {
133 DEBUG(1, ("Password is > 14 chars in length, and is "
134 "therefore incompatible with Lanman "
135 "authentication\n"));
136 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
137 return tevent_req_post(req, ev);
139 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
142 * Encrypted mode needed, and encrypted password
145 lm_response = data_blob(pass, passlen);
146 if (tevent_req_nomem(lm_response.data, req)) {
147 return tevent_req_post(req, ev);
149 } else if (passlen > 0) {
151 size_t converted_size;
153 * Plaintext mode needed, assume plaintext supplied.
155 buf = talloc_array(talloc_tos(), uint8_t, 0);
156 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
158 if (tevent_req_nomem(buf, req)) {
159 return tevent_req_post(req, ev);
161 lm_response = data_blob(pass, passlen);
163 if (tevent_req_nomem(lm_response.data, req)) {
164 return tevent_req_post(req, ev);
168 SCVAL(vwv+0, 0, 0xff);
171 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
174 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
175 SSVAL(vwv+7, 0, lm_response.length);
177 bytes = talloc_array(state, uint8_t, lm_response.length);
178 if (tevent_req_nomem(bytes, req)) {
179 return tevent_req_post(req, ev);
181 if (lm_response.length != 0) {
182 memcpy(bytes, lm_response.data, lm_response.length);
184 data_blob_free(&lm_response);
186 tmp = talloc_strdup_upper(talloc_tos(), user);
187 if (tevent_req_nomem(tmp, req)) {
188 return tevent_req_post(req, ev);
190 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
194 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
195 if (tevent_req_nomem(tmp, req)) {
196 return tevent_req_post(req, ev);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
200 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
201 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
203 if (tevent_req_nomem(bytes, req)) {
204 return tevent_req_post(req, ev);
207 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
208 talloc_get_size(bytes), bytes);
209 if (tevent_req_nomem(subreq, req)) {
210 return tevent_req_post(req, ev);
212 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
216 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
218 struct tevent_req *req = tevent_req_callback_data(
219 subreq, struct tevent_req);
220 struct cli_session_setup_lanman2_state *state = tevent_req_data(
221 req, struct cli_session_setup_lanman2_state);
222 struct cli_state *cli = state->cli;
233 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
236 if (!NT_STATUS_IS_OK(status)) {
237 tevent_req_nterror(req, status);
241 inhdr = in + NBT_HDR_SIZE;
244 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
246 status = smb_bytes_talloc_string(cli,
253 if (!NT_STATUS_IS_OK(status)) {
254 tevent_req_nterror(req, status);
259 status = smb_bytes_talloc_string(cli,
266 if (!NT_STATUS_IS_OK(status)) {
267 tevent_req_nterror(req, status);
272 status = smb_bytes_talloc_string(cli,
279 if (!NT_STATUS_IS_OK(status)) {
280 tevent_req_nterror(req, status);
285 tevent_req_done(req);
288 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
290 return tevent_req_simple_recv_ntstatus(req);
293 /****************************************************************************
294 Work out suitable capabilities to offer the server.
295 ****************************************************************************/
297 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
298 uint32_t sesssetup_capabilities)
300 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
303 * We only send capabilities based on the mask for:
304 * - client only flags
305 * - flags used in both directions
307 * We do not echo the server only flags, except some legacy flags.
309 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
310 * CAP_LARGE_WRITEX in order to allow us to do large reads
311 * against old Samba releases (<= 3.6.x).
313 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
316 * Session Setup specific flags CAP_DYNAMIC_REAUTH
317 * and CAP_EXTENDED_SECURITY are passed by the caller.
318 * We need that in order to do guest logins even if
319 * CAP_EXTENDED_SECURITY is negotiated.
321 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
322 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
323 client_capabilities |= sesssetup_capabilities;
325 return client_capabilities;
328 /****************************************************************************
329 Do a NT1 guest session setup.
330 ****************************************************************************/
332 struct cli_session_setup_guest_state {
333 struct cli_state *cli;
338 static void cli_session_setup_guest_done(struct tevent_req *subreq);
340 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
341 struct tevent_context *ev,
342 struct cli_state *cli,
343 struct tevent_req **psmbreq)
345 struct tevent_req *req, *subreq;
346 struct cli_session_setup_guest_state *state;
350 req = tevent_req_create(mem_ctx, &state,
351 struct cli_session_setup_guest_state);
358 SCVAL(vwv+0, 0, 0xFF);
361 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
363 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
364 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
369 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
371 bytes = talloc_array(state, uint8_t, 0);
373 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
375 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
377 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
385 state->bytes.iov_base = (void *)bytes;
386 state->bytes.iov_len = talloc_get_size(bytes);
388 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
390 if (subreq == NULL) {
394 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
399 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
400 struct tevent_context *ev,
401 struct cli_state *cli)
403 struct tevent_req *req, *subreq;
406 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
411 status = smb1cli_req_chain_submit(&subreq, 1);
412 if (!NT_STATUS_IS_OK(status)) {
413 tevent_req_nterror(req, status);
414 return tevent_req_post(req, ev);
419 static void cli_session_setup_guest_done(struct tevent_req *subreq)
421 struct tevent_req *req = tevent_req_callback_data(
422 subreq, struct tevent_req);
423 struct cli_session_setup_guest_state *state = tevent_req_data(
424 req, struct cli_session_setup_guest_state);
425 struct cli_state *cli = state->cli;
436 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
439 if (!NT_STATUS_IS_OK(status)) {
440 tevent_req_nterror(req, status);
444 inhdr = in + NBT_HDR_SIZE;
447 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
449 status = smb_bytes_talloc_string(cli,
456 if (!NT_STATUS_IS_OK(status)) {
457 tevent_req_nterror(req, status);
462 status = smb_bytes_talloc_string(cli,
469 if (!NT_STATUS_IS_OK(status)) {
470 tevent_req_nterror(req, status);
475 status = smb_bytes_talloc_string(cli,
482 if (!NT_STATUS_IS_OK(status)) {
483 tevent_req_nterror(req, status);
488 tevent_req_done(req);
491 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
493 return tevent_req_simple_recv_ntstatus(req);
496 /****************************************************************************
497 Do a NT1 plaintext session setup.
498 ****************************************************************************/
500 struct cli_session_setup_plain_state {
501 struct cli_state *cli;
506 static void cli_session_setup_plain_done(struct tevent_req *subreq);
508 static struct tevent_req *cli_session_setup_plain_send(
509 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
510 struct cli_state *cli,
511 const char *user, const char *pass, const char *workgroup)
513 struct tevent_req *req, *subreq;
514 struct cli_session_setup_plain_state *state;
520 req = tevent_req_create(mem_ctx, &state,
521 struct cli_session_setup_plain_state);
529 SCVAL(vwv+0, 0, 0xff);
532 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
534 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
535 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
540 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
542 bytes = talloc_array(state, uint8_t, 0);
543 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
545 if (tevent_req_nomem(bytes, req)) {
546 return tevent_req_post(req, ev);
548 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
550 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
551 user, strlen(user)+1, NULL);
552 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
553 workgroup, strlen(workgroup)+1, NULL);
554 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
557 version = talloc_asprintf(talloc_tos(), "Samba %s",
558 samba_version_string());
559 if (tevent_req_nomem(version, req)){
560 return tevent_req_post(req, ev);
562 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
563 version, strlen(version)+1, NULL);
564 TALLOC_FREE(version);
566 if (tevent_req_nomem(bytes, req)) {
567 return tevent_req_post(req, ev);
570 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
571 talloc_get_size(bytes), bytes);
572 if (tevent_req_nomem(subreq, req)) {
573 return tevent_req_post(req, ev);
575 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
579 static void cli_session_setup_plain_done(struct tevent_req *subreq)
581 struct tevent_req *req = tevent_req_callback_data(
582 subreq, struct tevent_req);
583 struct cli_session_setup_plain_state *state = tevent_req_data(
584 req, struct cli_session_setup_plain_state);
585 struct cli_state *cli = state->cli;
596 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
599 if (tevent_req_nterror(req, status)) {
603 inhdr = in + NBT_HDR_SIZE;
606 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
608 status = smb_bytes_talloc_string(cli,
615 if (!NT_STATUS_IS_OK(status)) {
616 tevent_req_nterror(req, status);
621 status = smb_bytes_talloc_string(cli,
628 if (!NT_STATUS_IS_OK(status)) {
629 tevent_req_nterror(req, status);
634 status = smb_bytes_talloc_string(cli,
641 if (!NT_STATUS_IS_OK(status)) {
642 tevent_req_nterror(req, status);
647 tevent_req_done(req);
650 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
652 return tevent_req_simple_recv_ntstatus(req);
655 /****************************************************************************
656 do a NT1 NTLM/LM encrypted session setup - for when extended security
658 @param cli client state to create do session setup on
660 @param pass *either* cleartext password (passlen !=24) or LM response.
661 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
662 @param workgroup The user's domain.
663 ****************************************************************************/
665 struct cli_session_setup_nt1_state {
666 struct cli_state *cli;
669 DATA_BLOB session_key;
673 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
675 static struct tevent_req *cli_session_setup_nt1_send(
676 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
677 struct cli_state *cli, const char *user,
678 const char *pass, size_t passlen,
679 const char *ntpass, size_t ntpasslen,
680 const char *workgroup)
682 struct tevent_req *req, *subreq;
683 struct cli_session_setup_nt1_state *state;
684 DATA_BLOB lm_response = data_blob_null;
685 DATA_BLOB nt_response = data_blob_null;
686 DATA_BLOB session_key = data_blob_null;
689 char *workgroup_upper;
691 req = tevent_req_create(mem_ctx, &state,
692 struct cli_session_setup_nt1_state);
701 /* do nothing - guest login */
702 } else if (passlen != 24) {
703 if (lp_client_ntlmv2_auth()) {
704 DATA_BLOB server_chal;
705 DATA_BLOB names_blob;
708 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
712 * note that the 'workgroup' here is a best
713 * guess - we don't know the server's domain
714 * at this point. Windows clients also don't
717 names_blob = NTLMv2_generate_names_blob(
718 NULL, NULL, workgroup);
720 if (tevent_req_nomem(names_blob.data, req)) {
721 return tevent_req_post(req, ev);
724 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
725 &server_chal, &names_blob,
726 &lm_response, &nt_response,
727 NULL, &session_key)) {
728 data_blob_free(&names_blob);
730 req, NT_STATUS_ACCESS_DENIED);
731 return tevent_req_post(req, ev);
733 data_blob_free(&names_blob);
737 E_md4hash(pass, nt_hash);
740 nt_response = data_blob_null;
742 nt_response = data_blob(NULL, 24);
743 if (tevent_req_nomem(nt_response.data, req)) {
744 return tevent_req_post(req, ev);
747 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
750 /* non encrypted password supplied. Ignore ntpass. */
751 if (lp_client_lanman_auth()) {
753 lm_response = data_blob(NULL, 24);
754 if (tevent_req_nomem(lm_response.data, req)) {
755 return tevent_req_post(req, ev);
758 if (!SMBencrypt(pass,
759 smb1cli_conn_server_challenge(cli->conn),
762 * Oops, the LM response is
763 * invalid, just put the NT
764 * response there instead
766 data_blob_free(&lm_response);
767 lm_response = data_blob(
773 * LM disabled, place NT# in LM field
776 lm_response = data_blob(
777 nt_response.data, nt_response.length);
780 if (tevent_req_nomem(lm_response.data, req)) {
781 return tevent_req_post(req, ev);
784 session_key = data_blob(NULL, 16);
785 if (tevent_req_nomem(session_key.data, req)) {
786 return tevent_req_post(req, ev);
789 E_deshash(pass, session_key.data);
790 memset(&session_key.data[8], '\0', 8);
792 SMBsesskeygen_ntv1(nt_hash, session_key.data);
796 /* pre-encrypted password supplied. Only used for
797 security=server, can't do
798 signing because we don't have original key */
800 lm_response = data_blob(pass, passlen);
801 if (tevent_req_nomem(lm_response.data, req)) {
802 return tevent_req_post(req, ev);
805 nt_response = data_blob(ntpass, ntpasslen);
806 if (tevent_req_nomem(nt_response.data, req)) {
807 return tevent_req_post(req, ev);
812 state->response = data_blob_talloc(
813 state, lm_response.data, lm_response.length);
815 state->response = data_blob_talloc(
816 state, nt_response.data, nt_response.length);
818 if (tevent_req_nomem(state->response.data, req)) {
819 return tevent_req_post(req, ev);
822 if (session_key.data) {
823 state->session_key = data_blob_talloc(
824 state, session_key.data, session_key.length);
825 if (tevent_req_nomem(state->session_key.data, req)) {
826 return tevent_req_post(req, ev);
829 data_blob_free(&session_key);
831 SCVAL(vwv+0, 0, 0xff);
834 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
836 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
837 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
838 SSVAL(vwv+7, 0, lm_response.length);
839 SSVAL(vwv+8, 0, nt_response.length);
842 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
844 bytes = talloc_array(state, uint8_t,
845 lm_response.length + nt_response.length);
846 if (tevent_req_nomem(bytes, req)) {
847 return tevent_req_post(req, ev);
849 if (lm_response.length != 0) {
850 memcpy(bytes, lm_response.data, lm_response.length);
852 if (nt_response.length != 0) {
853 memcpy(bytes + lm_response.length,
854 nt_response.data, nt_response.length);
856 data_blob_free(&lm_response);
857 data_blob_free(&nt_response);
859 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
860 user, strlen(user)+1, NULL);
863 * Upper case here might help some NTLMv2 implementations
865 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
866 if (tevent_req_nomem(workgroup_upper, req)) {
867 return tevent_req_post(req, ev);
869 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
870 workgroup_upper, strlen(workgroup_upper)+1,
872 TALLOC_FREE(workgroup_upper);
874 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
875 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
876 if (tevent_req_nomem(bytes, req)) {
877 return tevent_req_post(req, ev);
880 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
881 talloc_get_size(bytes), bytes);
882 if (tevent_req_nomem(subreq, req)) {
883 return tevent_req_post(req, ev);
885 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
889 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
891 struct tevent_req *req = tevent_req_callback_data(
892 subreq, struct tevent_req);
893 struct cli_session_setup_nt1_state *state = tevent_req_data(
894 req, struct cli_session_setup_nt1_state);
895 struct cli_state *cli = state->cli;
906 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
909 if (!NT_STATUS_IS_OK(status)) {
910 tevent_req_nterror(req, status);
914 inhdr = in + NBT_HDR_SIZE;
917 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
919 status = smb_bytes_talloc_string(cli,
925 if (!NT_STATUS_IS_OK(status)) {
926 tevent_req_nterror(req, status);
931 status = smb_bytes_talloc_string(cli,
937 if (!NT_STATUS_IS_OK(status)) {
938 tevent_req_nterror(req, status);
943 status = smb_bytes_talloc_string(cli,
949 if (!NT_STATUS_IS_OK(status)) {
950 tevent_req_nterror(req, status);
955 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
956 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
957 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
960 if (state->session_key.data) {
961 struct smbXcli_session *session = state->cli->smb1.session;
963 status = smb1cli_session_set_session_key(session,
965 if (tevent_req_nterror(req, status)) {
969 tevent_req_done(req);
972 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
974 return tevent_req_simple_recv_ntstatus(req);
977 /* The following is calculated from :
979 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
980 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
984 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
986 struct cli_sesssetup_blob_state {
987 struct tevent_context *ev;
988 struct cli_state *cli;
990 uint16_t max_blob_size;
995 struct iovec *recv_iov;
1002 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1003 struct tevent_req **psubreq);
1004 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1006 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1007 struct tevent_context *ev,
1008 struct cli_state *cli,
1011 struct tevent_req *req, *subreq;
1012 struct cli_sesssetup_blob_state *state;
1013 uint32_t usable_space;
1015 req = tevent_req_create(mem_ctx, &state,
1016 struct cli_sesssetup_blob_state);
1024 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1025 usable_space = UINT16_MAX;
1027 usable_space = cli_state_available_size(cli,
1028 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1031 if (usable_space == 0) {
1032 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1033 "(not possible to send %u bytes)\n",
1034 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1035 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1036 return tevent_req_post(req, ev);
1038 state->max_blob_size = MIN(usable_space, 0xFFFF);
1040 if (!cli_sesssetup_blob_next(state, &subreq)) {
1041 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1042 return tevent_req_post(req, ev);
1044 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1048 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1049 struct tevent_req **psubreq)
1051 struct tevent_req *subreq;
1054 thistime = MIN(state->blob.length, state->max_blob_size);
1056 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1058 state->smb2_blob.data = state->blob.data;
1059 state->smb2_blob.length = thistime;
1061 state->blob.data += thistime;
1062 state->blob.length -= thistime;
1064 subreq = smb2cli_session_setup_send(state, state->ev,
1066 state->cli->timeout,
1067 state->cli->smb2.session,
1069 SMB2_CAP_DFS, /* in_capabilities */
1071 0, /* in_previous_session_id */
1073 if (subreq == NULL) {
1080 SCVAL(state->vwv+0, 0, 0xFF);
1081 SCVAL(state->vwv+0, 1, 0);
1082 SSVAL(state->vwv+1, 0, 0);
1083 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1084 SSVAL(state->vwv+3, 0, 2);
1085 SSVAL(state->vwv+4, 0, 1);
1086 SIVAL(state->vwv+5, 0, 0);
1088 SSVAL(state->vwv+7, 0, thistime);
1090 SSVAL(state->vwv+8, 0, 0);
1091 SSVAL(state->vwv+9, 0, 0);
1092 SIVAL(state->vwv+10, 0,
1093 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1095 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1097 if (state->buf == NULL) {
1100 state->blob.data += thistime;
1101 state->blob.length -= thistime;
1103 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1105 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1107 if (state->buf == NULL) {
1110 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1112 talloc_get_size(state->buf), state->buf);
1113 if (subreq == NULL) {
1120 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1122 struct tevent_req *req = tevent_req_callback_data(
1123 subreq, struct tevent_req);
1124 struct cli_sesssetup_blob_state *state = tevent_req_data(
1125 req, struct cli_sesssetup_blob_state);
1126 struct cli_state *cli = state->cli;
1133 uint16_t blob_length;
1138 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1139 status = smb2cli_session_setup_recv(subreq, state,
1143 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1144 &num_bytes, &bytes);
1145 TALLOC_FREE(state->buf);
1147 TALLOC_FREE(subreq);
1148 if (!NT_STATUS_IS_OK(status)
1149 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1150 tevent_req_nterror(req, status);
1154 state->status = status;
1156 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1161 inhdr = in + NBT_HDR_SIZE;
1162 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1164 blob_length = SVAL(vwv+3, 0);
1165 if (blob_length > num_bytes) {
1166 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1169 state->ret_blob = data_blob_const(bytes, blob_length);
1171 p = bytes + blob_length;
1173 status = smb_bytes_talloc_string(cli,
1180 if (!NT_STATUS_IS_OK(status)) {
1181 tevent_req_nterror(req, status);
1186 status = smb_bytes_talloc_string(cli,
1193 if (!NT_STATUS_IS_OK(status)) {
1194 tevent_req_nterror(req, status);
1199 status = smb_bytes_talloc_string(cli,
1201 &cli->server_domain,
1206 if (!NT_STATUS_IS_OK(status)) {
1207 tevent_req_nterror(req, status);
1213 if (state->blob.length != 0) {
1217 if (!cli_sesssetup_blob_next(state, &subreq)) {
1218 tevent_req_oom(req);
1221 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1224 tevent_req_done(req);
1227 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1228 TALLOC_CTX *mem_ctx,
1231 struct iovec **precv_iov)
1233 struct cli_sesssetup_blob_state *state = tevent_req_data(
1234 req, struct cli_sesssetup_blob_state);
1237 struct iovec *recv_iov;
1239 if (tevent_req_is_nterror(req, &status)) {
1240 TALLOC_FREE(state->cli->smb2.session);
1241 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1245 inbuf = talloc_move(mem_ctx, &state->inbuf);
1246 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1247 if (pblob != NULL) {
1248 *pblob = state->ret_blob;
1250 if (pinbuf != NULL) {
1253 if (precv_iov != NULL) {
1254 *precv_iov = recv_iov;
1256 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1257 return state->status;
1262 /****************************************************************************
1263 Use in-memory credentials cache
1264 ****************************************************************************/
1266 static void use_in_memory_ccache(void) {
1267 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1270 #endif /* HAVE_KRB5 */
1272 /****************************************************************************
1273 Do a spnego/NTLMSSP encrypted session setup.
1274 ****************************************************************************/
1276 struct cli_session_setup_gensec_state {
1277 struct tevent_context *ev;
1278 struct cli_state *cli;
1279 struct auth_generic_state *auth_generic;
1283 struct iovec *recv_iov;
1287 DATA_BLOB session_key;
1290 static int cli_session_setup_gensec_state_destructor(
1291 struct cli_session_setup_gensec_state *state)
1293 TALLOC_FREE(state->auth_generic);
1294 data_blob_clear_free(&state->session_key);
1298 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
1299 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
1300 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
1301 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
1302 static void cli_session_setup_gensec_ready(struct tevent_req *req);
1304 static struct tevent_req *cli_session_setup_gensec_send(
1305 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1306 const char *user, const char *pass, const char *domain,
1307 enum credentials_use_kerberos krb5_state,
1308 const char *target_service,
1309 const char *target_hostname,
1310 const char *target_principal)
1312 struct tevent_req *req;
1313 struct cli_session_setup_gensec_state *state;
1315 bool use_spnego_principal = lp_client_use_spnego_principal();
1317 req = tevent_req_create(mem_ctx, &state,
1318 struct cli_session_setup_gensec_state);
1325 talloc_set_destructor(
1326 state, cli_session_setup_gensec_state_destructor);
1328 status = auth_generic_client_prepare(state, &state->auth_generic);
1329 if (tevent_req_nterror(req, status)) {
1330 return tevent_req_post(req, ev);
1333 gensec_want_feature(state->auth_generic->gensec_security,
1334 GENSEC_FEATURE_SESSION_KEY);
1335 if (cli->use_ccache) {
1336 gensec_want_feature(state->auth_generic->gensec_security,
1337 GENSEC_FEATURE_NTLM_CCACHE);
1338 if (pass != NULL && strlen(pass) == 0) {
1340 * some callers pass "" as no password
1342 * GENSEC_FEATURE_NTLM_CCACHE only handles
1343 * NULL as no password.
1349 status = auth_generic_set_username(state->auth_generic, user);
1350 if (tevent_req_nterror(req, status)) {
1351 return tevent_req_post(req, ev);
1354 status = auth_generic_set_domain(state->auth_generic, domain);
1355 if (tevent_req_nterror(req, status)) {
1356 return tevent_req_post(req, ev);
1359 if (cli->pw_nt_hash) {
1360 struct samr_Password nt_hash;
1365 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1366 return tevent_req_post(req, ev);
1369 converted = strhex_to_str((char *)nt_hash.hash,
1370 sizeof(nt_hash.hash),
1371 pass, strlen(pass));
1372 if (converted != sizeof(nt_hash.hash)) {
1373 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1374 return tevent_req_post(req, ev);
1377 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
1378 &nt_hash, CRED_SPECIFIED);
1380 tevent_req_oom(req);
1381 return tevent_req_post(req, ev);
1384 status = auth_generic_set_password(state->auth_generic, pass);
1385 if (tevent_req_nterror(req, status)) {
1386 return tevent_req_post(req, ev);
1390 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
1393 if (krb5_state == CRED_DONT_USE_KERBEROS) {
1394 use_spnego_principal = false;
1397 if (target_service != NULL) {
1398 status = gensec_set_target_service(
1399 state->auth_generic->gensec_security,
1401 if (tevent_req_nterror(req, status)) {
1402 return tevent_req_post(req, ev);
1406 if (target_hostname != NULL) {
1407 status = gensec_set_target_hostname(
1408 state->auth_generic->gensec_security,
1410 if (tevent_req_nterror(req, status)) {
1411 return tevent_req_post(req, ev);
1415 if (target_principal != NULL) {
1416 status = gensec_set_target_principal(
1417 state->auth_generic->gensec_security,
1419 if (tevent_req_nterror(req, status)) {
1420 return tevent_req_post(req, ev);
1422 use_spnego_principal = false;
1423 } else if (target_service != NULL && target_hostname != NULL) {
1424 use_spnego_principal = false;
1427 if (use_spnego_principal) {
1429 b = smbXcli_conn_server_gss_blob(cli->conn);
1431 state->blob_in = *b;
1435 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
1437 status = auth_generic_client_start(state->auth_generic,
1439 if (tevent_req_nterror(req, status)) {
1440 return tevent_req_post(req, ev);
1443 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1444 state->cli->smb2.session = smbXcli_session_create(cli,
1446 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1447 return tevent_req_post(req, ev);
1451 cli_session_setup_gensec_local_next(req);
1452 if (!tevent_req_is_in_progress(req)) {
1453 return tevent_req_post(req, ev);
1459 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
1461 struct cli_session_setup_gensec_state *state =
1462 tevent_req_data(req,
1463 struct cli_session_setup_gensec_state);
1464 struct tevent_req *subreq = NULL;
1466 if (state->local_ready) {
1467 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1471 subreq = gensec_update_send(state, state->ev,
1472 state->auth_generic->gensec_security,
1474 if (tevent_req_nomem(subreq, req)) {
1477 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1480 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1482 struct tevent_req *req =
1483 tevent_req_callback_data(subreq,
1485 struct cli_session_setup_gensec_state *state =
1486 tevent_req_data(req,
1487 struct cli_session_setup_gensec_state);
1490 status = gensec_update_recv(subreq, state, &state->blob_out);
1491 TALLOC_FREE(subreq);
1492 state->blob_in = data_blob_null;
1493 if (!NT_STATUS_IS_OK(status) &&
1494 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1496 tevent_req_nterror(req, status);
1500 if (NT_STATUS_IS_OK(status)) {
1501 state->local_ready = true;
1504 if (state->local_ready && state->remote_ready) {
1505 cli_session_setup_gensec_ready(req);
1509 cli_session_setup_gensec_remote_next(req);
1512 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1514 struct cli_session_setup_gensec_state *state =
1515 tevent_req_data(req,
1516 struct cli_session_setup_gensec_state);
1517 struct tevent_req *subreq = NULL;
1519 if (state->remote_ready) {
1520 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1524 subreq = cli_sesssetup_blob_send(state, state->ev,
1525 state->cli, state->blob_out);
1526 if (tevent_req_nomem(subreq, req)) {
1529 tevent_req_set_callback(subreq,
1530 cli_session_setup_gensec_remote_done,
1534 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1536 struct tevent_req *req =
1537 tevent_req_callback_data(subreq,
1539 struct cli_session_setup_gensec_state *state =
1540 tevent_req_data(req,
1541 struct cli_session_setup_gensec_state);
1544 TALLOC_FREE(state->inbuf);
1545 TALLOC_FREE(state->recv_iov);
1547 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1548 &state->inbuf, &state->recv_iov);
1549 TALLOC_FREE(subreq);
1550 data_blob_free(&state->blob_out);
1551 if (!NT_STATUS_IS_OK(status) &&
1552 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1554 tevent_req_nterror(req, status);
1558 if (NT_STATUS_IS_OK(status)) {
1559 state->remote_ready = true;
1562 if (state->local_ready && state->remote_ready) {
1563 cli_session_setup_gensec_ready(req);
1567 cli_session_setup_gensec_local_next(req);
1570 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1572 struct cli_session_setup_gensec_state *state =
1573 tevent_req_data(req,
1574 struct cli_session_setup_gensec_state);
1575 const char *server_domain = NULL;
1578 if (state->blob_in.length != 0) {
1579 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1583 if (state->blob_out.length != 0) {
1584 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1589 * gensec_ntlmssp_server_domain() returns NULL
1590 * if NTLMSSP is not used.
1592 * We can remove this later
1593 * and leave the server domain empty for SMB2 and above
1594 * in future releases.
1596 server_domain = gensec_ntlmssp_server_domain(
1597 state->auth_generic->gensec_security);
1599 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1600 TALLOC_FREE(state->cli->server_domain);
1601 state->cli->server_domain = talloc_strdup(state->cli,
1603 if (state->cli->server_domain == NULL) {
1604 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1609 status = gensec_session_key(state->auth_generic->gensec_security,
1610 state, &state->session_key);
1611 if (tevent_req_nterror(req, status)) {
1615 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1616 struct smbXcli_session *session = state->cli->smb2.session;
1618 if (state->is_anonymous) {
1620 * Windows server does not set the
1621 * SMB2_SESSION_FLAG_IS_GUEST nor
1622 * SMB2_SESSION_FLAG_IS_NULL flag.
1624 * This fix makes sure we do not try
1625 * to verify a signature on the final
1626 * session setup response.
1628 tevent_req_done(req);
1632 status = smb2cli_session_set_session_key(session,
1635 if (tevent_req_nterror(req, status)) {
1639 struct smbXcli_session *session = state->cli->smb1.session;
1642 status = smb1cli_session_set_session_key(session,
1643 state->session_key);
1644 if (tevent_req_nterror(req, status)) {
1648 active = smb1cli_conn_activate_signing(state->cli->conn,
1654 ok = smb1cli_conn_check_signing(state->cli->conn,
1657 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1663 tevent_req_done(req);
1666 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1668 struct cli_session_setup_gensec_state *state =
1669 tevent_req_data(req,
1670 struct cli_session_setup_gensec_state);
1673 if (tevent_req_is_nterror(req, &status)) {
1674 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1677 return NT_STATUS_OK;
1682 static char *cli_session_setup_get_principal(
1683 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1684 const char *remote_name, const char *dest_realm)
1686 char *principal = NULL;
1688 if (!lp_client_use_spnego_principal() ||
1689 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1690 spnego_principal = NULL;
1692 if (spnego_principal != NULL) {
1693 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1694 "principal %s\n", spnego_principal));
1695 return talloc_strdup(mem_ctx, spnego_principal);
1697 if (is_ipaddress(remote_name) ||
1698 strequal(remote_name, STAR_SMBSERVER)) {
1702 DEBUG(3, ("cli_session_setup_spnego: using target "
1703 "hostname not SPNEGO principal\n"));
1706 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1707 if (realm == NULL) {
1710 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1711 remote_name, realm);
1714 principal = kerberos_get_principal_from_service_hostname(
1715 talloc_tos(), "cifs", remote_name, lp_realm());
1717 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1718 principal ? principal : "<null>"));
1724 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1725 const char *principal)
1729 account = talloc_strdup(mem_ctx, principal);
1730 if (account == NULL) {
1733 p = strchr_m(account, '@');
1740 /****************************************************************************
1741 Do a spnego encrypted session setup.
1743 user_domain: The shortname of the domain the user/machine is a member of.
1744 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1745 ****************************************************************************/
1747 struct cli_session_setup_spnego_state {
1748 struct tevent_context *ev;
1749 struct cli_state *cli;
1750 const char *target_hostname;
1752 const char *account;
1754 const char *user_domain;
1755 const char *dest_realm;
1760 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1763 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1765 static struct tevent_req *cli_session_setup_spnego_send(
1766 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1767 const char *user, const char *pass, const char *user_domain)
1769 struct tevent_req *req, *subreq;
1770 struct cli_session_setup_spnego_state *state;
1771 char *principal = NULL;
1772 char *OIDs[ASN1_MAX_OIDS];
1774 const char *dest_realm = cli_state_remote_realm(cli);
1775 const DATA_BLOB *server_blob;
1777 req = tevent_req_create(mem_ctx, &state,
1778 struct cli_session_setup_spnego_state);
1786 state->user_domain = user_domain;
1787 state->dest_realm = dest_realm;
1789 state->account = cli_session_setup_get_account(state, user);
1790 if (tevent_req_nomem(state->account, req)) {
1791 return tevent_req_post(req, ev);
1794 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1795 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1797 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1798 (unsigned long)server_blob->length));
1800 /* the server might not even do spnego */
1801 if (server_blob->length == 0) {
1802 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1807 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1810 /* The server sent us the first part of the SPNEGO exchange in the
1811 * negprot reply. It is WRONG to depend on the principal sent in the
1812 * negprot reply, but right now we do it. If we don't receive one,
1813 * we try to best guess, then fall back to NTLM. */
1814 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1815 &principal, NULL) ||
1817 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1818 tevent_req_done(req);
1819 return tevent_req_post(req, ev);
1822 /* make sure the server understands kerberos */
1823 for (i=0;OIDs[i];i++) {
1825 DEBUG(3,("got OID=%s\n", OIDs[i]));
1827 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1828 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1829 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1830 cli->got_kerberos_mechanism = True;
1832 talloc_free(OIDs[i]);
1835 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1838 /* If password is set we reauthenticate to kerberos server
1839 * and do not store results */
1841 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1844 tmp = cli_session_setup_get_principal(
1845 talloc_tos(), principal, state->target_hostname, dest_realm);
1846 TALLOC_FREE(principal);
1849 if (pass && *pass) {
1852 use_in_memory_ccache();
1853 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1856 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1857 TALLOC_FREE(principal);
1858 if (cli->fallback_after_kerberos)
1860 state->result = ADS_ERROR_KRB5(ret);
1861 tevent_req_done(req);
1862 return tevent_req_post(req, ev);
1867 subreq = cli_session_setup_gensec_send(
1869 state->account, pass, user_domain,
1870 CRED_MUST_USE_KERBEROS,
1871 "cifs", state->target_hostname, principal);
1872 if (tevent_req_nomem(subreq, req)) {
1873 return tevent_req_post(req, ev);
1875 tevent_req_set_callback(
1876 subreq, cli_session_setup_spnego_done_krb,
1884 subreq = cli_session_setup_gensec_send(
1885 state, state->ev, state->cli,
1886 state->account, state->pass, state->user_domain,
1887 CRED_DONT_USE_KERBEROS,
1888 "cifs", state->target_hostname, NULL);
1889 if (tevent_req_nomem(subreq, req)) {
1890 return tevent_req_post(req, ev);
1892 tevent_req_set_callback(
1893 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1898 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1900 struct tevent_req *req = tevent_req_callback_data(
1901 subreq, struct tevent_req);
1902 struct cli_session_setup_spnego_state *state = tevent_req_data(
1903 req, struct cli_session_setup_spnego_state);
1906 status = cli_session_setup_gensec_recv(subreq);
1907 TALLOC_FREE(subreq);
1908 state->result = ADS_ERROR_NT(status);
1910 if (ADS_ERR_OK(state->result) ||
1911 !state->cli->fallback_after_kerberos) {
1912 tevent_req_done(req);
1916 subreq = cli_session_setup_gensec_send(
1917 state, state->ev, state->cli,
1918 state->account, state->pass, state->user_domain,
1919 CRED_DONT_USE_KERBEROS,
1920 "cifs", state->target_hostname, NULL);
1921 if (tevent_req_nomem(subreq, req)) {
1924 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1929 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1931 struct tevent_req *req = tevent_req_callback_data(
1932 subreq, struct tevent_req);
1933 struct cli_session_setup_spnego_state *state = tevent_req_data(
1934 req, struct cli_session_setup_spnego_state);
1937 status = cli_session_setup_gensec_recv(subreq);
1938 TALLOC_FREE(subreq);
1939 state->result = ADS_ERROR_NT(status);
1940 tevent_req_done(req);
1943 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1945 struct cli_session_setup_spnego_state *state = tevent_req_data(
1946 req, struct cli_session_setup_spnego_state);
1948 return state->result;
1951 struct cli_session_setup_state {
1955 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1956 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1957 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1958 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1959 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1961 /****************************************************************************
1962 Send a session setup. The username and workgroup is in UNIX character
1963 format and must be converted to DOS codepage format before sending. If the
1964 password is in plaintext, the same should be done.
1965 ****************************************************************************/
1967 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1968 struct tevent_context *ev,
1969 struct cli_state *cli,
1971 const char *pass, int passlen,
1972 const char *ntpass, int ntpasslen,
1973 const char *workgroup)
1975 struct tevent_req *req, *subreq;
1976 struct cli_session_setup_state *state;
1979 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1981 req = tevent_req_create(mem_ctx, &state,
1982 struct cli_session_setup_state);
1988 user2 = talloc_strdup(state, user);
1990 user2 = talloc_strdup(state, "");
1992 if (user2 == NULL) {
1993 tevent_req_oom(req);
1994 return tevent_req_post(req, ev);
2001 /* allow for workgroups as part of the username */
2002 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2003 (p=strchr_m(user2,*lp_winbind_separator()))) {
2006 if (!strupper_m(user2)) {
2007 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2008 return tevent_req_post(req, ev);
2013 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2014 tevent_req_done(req);
2015 return tevent_req_post(req, ev);
2018 /* now work out what sort of session setup we are going to
2019 do. I have split this into separate functions to make the
2020 flow a bit easier to understand (tridge) */
2022 /* if its an older server then we have to use the older request format */
2024 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2025 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2026 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2027 " or 'client ntlmv2 auth = yes'\n"));
2028 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2029 return tevent_req_post(req, ev);
2032 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2033 !lp_client_plaintext_auth() && (*pass)) {
2034 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2035 " or 'client ntlmv2 auth = yes'\n"));
2036 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2037 return tevent_req_post(req, ev);
2040 subreq = cli_session_setup_lanman2_send(
2041 state, ev, cli, user, pass, passlen, workgroup);
2042 if (tevent_req_nomem(subreq, req)) {
2043 return tevent_req_post(req, ev);
2045 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2050 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2051 subreq = cli_session_setup_spnego_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_spnego,
2061 /* if no user is supplied then we have to do an anonymous connection.
2062 passwords are ignored */
2064 if (!user || !*user) {
2065 subreq = cli_session_setup_guest_send(state, ev, cli);
2066 if (tevent_req_nomem(subreq, req)) {
2067 return tevent_req_post(req, ev);
2069 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2074 /* if the server is share level then send a plaintext null
2075 password at this point. The password is sent in the tree
2078 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2079 subreq = cli_session_setup_plain_send(
2080 state, ev, cli, user, "", workgroup);
2081 if (tevent_req_nomem(subreq, req)) {
2082 return tevent_req_post(req, ev);
2084 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2089 /* if the server doesn't support encryption then we have to use
2090 plaintext. The second password is ignored */
2092 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2093 if (!lp_client_plaintext_auth() && (*pass)) {
2094 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2095 " or 'client ntlmv2 auth = yes'\n"));
2096 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2097 return tevent_req_post(req, ev);
2099 subreq = cli_session_setup_plain_send(
2100 state, ev, cli, user, pass, workgroup);
2101 if (tevent_req_nomem(subreq, req)) {
2102 return tevent_req_post(req, ev);
2104 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2109 /* if the server supports extended security then use SPNEGO */
2111 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2112 subreq = cli_session_setup_spnego_send(
2113 state, ev, cli, user, pass, workgroup);
2114 if (tevent_req_nomem(subreq, req)) {
2115 return tevent_req_post(req, ev);
2117 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2121 /* otherwise do a NT1 style session setup */
2122 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2124 * Don't send an NTLMv2 response without NTLMSSP
2125 * if we want to use spnego support
2127 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2128 " but 'client use spnego = yes"
2129 " and 'client ntlmv2 auth = yes'\n"));
2130 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2131 return tevent_req_post(req, ev);
2134 subreq = cli_session_setup_nt1_send(
2135 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2137 if (tevent_req_nomem(subreq, req)) {
2138 return tevent_req_post(req, ev);
2140 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2145 tevent_req_done(req);
2146 return tevent_req_post(req, ev);
2149 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2151 struct tevent_req *req = tevent_req_callback_data(
2152 subreq, struct tevent_req);
2155 status = cli_session_setup_lanman2_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_spnego(struct tevent_req *subreq)
2166 struct tevent_req *req = tevent_req_callback_data(
2167 subreq, struct tevent_req);
2170 status = cli_session_setup_spnego_recv(subreq);
2171 TALLOC_FREE(subreq);
2172 if (!ADS_ERR_OK(status)) {
2173 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2174 tevent_req_nterror(req, ads_ntstatus(status));
2177 tevent_req_done(req);
2180 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2182 struct tevent_req *req = tevent_req_callback_data(
2183 subreq, struct tevent_req);
2186 status = cli_session_setup_guest_recv(subreq);
2187 TALLOC_FREE(subreq);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 tevent_req_nterror(req, status);
2192 tevent_req_done(req);
2195 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2197 struct tevent_req *req = tevent_req_callback_data(
2198 subreq, struct tevent_req);
2201 status = cli_session_setup_plain_recv(subreq);
2202 TALLOC_FREE(subreq);
2203 if (!NT_STATUS_IS_OK(status)) {
2204 tevent_req_nterror(req, status);
2207 tevent_req_done(req);
2210 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2212 struct tevent_req *req = tevent_req_callback_data(
2213 subreq, struct tevent_req);
2216 status = cli_session_setup_nt1_recv(subreq);
2217 TALLOC_FREE(subreq);
2218 if (!NT_STATUS_IS_OK(status)) {
2219 DEBUG(3, ("cli_session_setup: NT1 session setup "
2220 "failed: %s\n", nt_errstr(status)));
2221 tevent_req_nterror(req, status);
2224 tevent_req_done(req);
2227 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2229 return tevent_req_simple_recv_ntstatus(req);
2232 NTSTATUS cli_session_setup(struct cli_state *cli,
2234 const char *pass, int passlen,
2235 const char *ntpass, int ntpasslen,
2236 const char *workgroup)
2238 struct tevent_context *ev;
2239 struct tevent_req *req;
2240 NTSTATUS status = NT_STATUS_NO_MEMORY;
2242 if (smbXcli_conn_has_async_calls(cli->conn)) {
2243 return NT_STATUS_INVALID_PARAMETER;
2245 ev = samba_tevent_context_init(talloc_tos());
2249 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2250 ntpass, ntpasslen, workgroup);
2254 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2257 status = cli_session_setup_recv(req);
2263 /****************************************************************************
2265 *****************************************************************************/
2267 struct cli_ulogoff_state {
2268 struct cli_state *cli;
2272 static void cli_ulogoff_done(struct tevent_req *subreq);
2274 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2275 struct tevent_context *ev,
2276 struct cli_state *cli)
2278 struct tevent_req *req, *subreq;
2279 struct cli_ulogoff_state *state;
2281 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2287 SCVAL(state->vwv+0, 0, 0xFF);
2288 SCVAL(state->vwv+1, 0, 0);
2289 SSVAL(state->vwv+2, 0, 0);
2291 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2293 if (tevent_req_nomem(subreq, req)) {
2294 return tevent_req_post(req, ev);
2296 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2300 static void cli_ulogoff_done(struct tevent_req *subreq)
2302 struct tevent_req *req = tevent_req_callback_data(
2303 subreq, struct tevent_req);
2304 struct cli_ulogoff_state *state = tevent_req_data(
2305 req, struct cli_ulogoff_state);
2308 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 tevent_req_nterror(req, status);
2313 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2314 tevent_req_done(req);
2317 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2319 return tevent_req_simple_recv_ntstatus(req);
2322 NTSTATUS cli_ulogoff(struct cli_state *cli)
2324 struct tevent_context *ev;
2325 struct tevent_req *req;
2326 NTSTATUS status = NT_STATUS_NO_MEMORY;
2328 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2329 status = smb2cli_logoff(cli->conn,
2332 if (!NT_STATUS_IS_OK(status)) {
2335 smb2cli_session_set_id_and_flags(cli->smb2.session,
2337 return NT_STATUS_OK;
2340 if (smbXcli_conn_has_async_calls(cli->conn)) {
2341 return NT_STATUS_INVALID_PARAMETER;
2343 ev = samba_tevent_context_init(talloc_tos());
2347 req = cli_ulogoff_send(ev, ev, cli);
2351 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2354 status = cli_ulogoff_recv(req);
2360 /****************************************************************************
2362 ****************************************************************************/
2364 struct cli_tcon_andx_state {
2365 struct cli_state *cli;
2370 static void cli_tcon_andx_done(struct tevent_req *subreq);
2372 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2373 struct tevent_context *ev,
2374 struct cli_state *cli,
2375 const char *share, const char *dev,
2376 const char *pass, int passlen,
2377 struct tevent_req **psmbreq)
2379 struct tevent_req *req, *subreq;
2380 struct cli_tcon_andx_state *state;
2385 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2386 uint16_t tcon_flags = 0;
2390 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2397 cli->share = talloc_strdup(cli, share);
2402 /* in user level security don't send a password now */
2403 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2406 } else if (pass == NULL) {
2407 DEBUG(1, ("Server not using user level security and no "
2408 "password supplied.\n"));
2412 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2413 *pass && passlen != 24) {
2414 if (!lp_client_lanman_auth()) {
2415 DEBUG(1, ("Server requested LANMAN password "
2416 "(share-level security) but "
2417 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2422 * Non-encrypted passwords - convert to DOS codepage before
2425 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2427 pass = (const char *)p24;
2429 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2430 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2434 if (!lp_client_plaintext_auth() && (*pass)) {
2435 DEBUG(1, ("Server requested PLAINTEXT "
2437 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2442 * Non-encrypted passwords - convert to DOS codepage
2445 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2446 if (tevent_req_nomem(tmp_pass, req)) {
2447 return tevent_req_post(req, ev);
2449 tmp_pass = trans2_bytes_push_str(tmp_pass,
2450 false, /* always DOS */
2454 if (tevent_req_nomem(tmp_pass, req)) {
2455 return tevent_req_post(req, ev);
2457 pass = (const char *)tmp_pass;
2458 passlen = talloc_get_size(tmp_pass);
2462 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2463 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2465 SCVAL(vwv+0, 0, 0xFF);
2468 SSVAL(vwv+2, 0, tcon_flags);
2469 SSVAL(vwv+3, 0, passlen);
2471 if (passlen && pass) {
2472 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2474 bytes = talloc_array(state, uint8_t, 0);
2480 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2481 smbXcli_conn_remote_name(cli->conn), share);
2486 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2491 * Add the devicetype
2493 tmp = talloc_strdup_upper(talloc_tos(), dev);
2498 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2501 if (bytes == NULL) {
2506 state->bytes.iov_base = (void *)bytes;
2507 state->bytes.iov_len = talloc_get_size(bytes);
2509 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2511 if (subreq == NULL) {
2515 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2520 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2521 return tevent_req_post(req, ev);
2524 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2525 struct tevent_context *ev,
2526 struct cli_state *cli,
2527 const char *share, const char *dev,
2528 const char *pass, int passlen)
2530 struct tevent_req *req, *subreq;
2533 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2538 if (subreq == NULL) {
2541 status = smb1cli_req_chain_submit(&subreq, 1);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 tevent_req_nterror(req, status);
2544 return tevent_req_post(req, ev);
2549 static void cli_tcon_andx_done(struct tevent_req *subreq)
2551 struct tevent_req *req = tevent_req_callback_data(
2552 subreq, struct tevent_req);
2553 struct cli_tcon_andx_state *state = tevent_req_data(
2554 req, struct cli_tcon_andx_state);
2555 struct cli_state *cli = state->cli;
2563 uint16_t optional_support = 0;
2565 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2566 &num_bytes, &bytes);
2567 TALLOC_FREE(subreq);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 tevent_req_nterror(req, status);
2573 inhdr = in + NBT_HDR_SIZE;
2576 if (clistr_pull_talloc(cli,
2577 (const char *)inhdr,
2578 SVAL(inhdr, HDR_FLG2),
2582 STR_TERMINATE|STR_ASCII) == -1) {
2583 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2587 cli->dev = talloc_strdup(cli, "");
2588 if (cli->dev == NULL) {
2589 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2594 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2595 /* almost certainly win95 - enable bug fixes */
2600 * Make sure that we have the optional support 16-bit field. WCT > 2.
2601 * Avoids issues when connecting to Win9x boxes sharing files
2604 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2605 optional_support = SVAL(vwv+2, 0);
2608 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2609 smb1cli_session_protect_session_key(cli->smb1.session);
2612 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2613 SVAL(inhdr, HDR_TID),
2615 0, /* maximal_access */
2616 0, /* guest_maximal_access */
2618 NULL); /* fs_type */
2620 tevent_req_done(req);
2623 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2625 return tevent_req_simple_recv_ntstatus(req);
2628 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2629 const char *dev, const char *pass, int passlen)
2631 TALLOC_CTX *frame = talloc_stackframe();
2632 struct tevent_context *ev;
2633 struct tevent_req *req;
2634 NTSTATUS status = NT_STATUS_NO_MEMORY;
2636 if (smbXcli_conn_has_async_calls(cli->conn)) {
2638 * Can't use sync call while an async call is in flight
2640 status = NT_STATUS_INVALID_PARAMETER;
2644 ev = samba_tevent_context_init(frame);
2649 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2654 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2658 status = cli_tcon_andx_recv(req);
2664 struct cli_tree_connect_state {
2665 struct cli_state *cli;
2668 static struct tevent_req *cli_raw_tcon_send(
2669 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2670 const char *service, const char *pass, const char *dev);
2671 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2672 uint16_t *max_xmit, uint16_t *tid);
2674 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2675 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2676 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2678 static struct tevent_req *cli_tree_connect_send(
2679 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2680 const char *share, const char *dev, const char *pass, int passlen)
2682 struct tevent_req *req, *subreq;
2683 struct cli_tree_connect_state *state;
2685 req = tevent_req_create(mem_ctx, &state,
2686 struct cli_tree_connect_state);
2692 cli->share = talloc_strdup(cli, share);
2693 if (tevent_req_nomem(cli->share, req)) {
2694 return tevent_req_post(req, ev);
2697 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2700 cli->smb2.tcon = smbXcli_tcon_create(cli);
2701 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2702 return tevent_req_post(req, ev);
2705 unc = talloc_asprintf(state, "\\\\%s\\%s",
2706 smbXcli_conn_remote_name(cli->conn),
2708 if (tevent_req_nomem(unc, req)) {
2709 return tevent_req_post(req, ev);
2712 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2713 cli->smb2.session, cli->smb2.tcon,
2716 if (tevent_req_nomem(subreq, req)) {
2717 return tevent_req_post(req, ev);
2719 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2724 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2725 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2727 if (tevent_req_nomem(subreq, req)) {
2728 return tevent_req_post(req, ev);
2730 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2735 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2736 if (tevent_req_nomem(subreq, req)) {
2737 return tevent_req_post(req, ev);
2739 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2744 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2746 tevent_req_simple_finish_ntstatus(
2747 subreq, smb2cli_tcon_recv(subreq));
2750 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2752 tevent_req_simple_finish_ntstatus(
2753 subreq, cli_tcon_andx_recv(subreq));
2756 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2758 struct tevent_req *req = tevent_req_callback_data(
2759 subreq, struct tevent_req);
2760 struct cli_tree_connect_state *state = tevent_req_data(
2761 req, struct cli_tree_connect_state);
2763 uint16_t max_xmit = 0;
2766 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2767 if (tevent_req_nterror(req, status)) {
2771 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2773 0, /* optional_support */
2774 0, /* maximal_access */
2775 0, /* guest_maximal_access */
2777 NULL); /* fs_type */
2779 tevent_req_done(req);
2782 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2784 return tevent_req_simple_recv_ntstatus(req);
2787 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2788 const char *dev, const char *pass, int passlen)
2790 struct tevent_context *ev;
2791 struct tevent_req *req;
2792 NTSTATUS status = NT_STATUS_NO_MEMORY;
2794 if (smbXcli_conn_has_async_calls(cli->conn)) {
2795 return NT_STATUS_INVALID_PARAMETER;
2797 ev = samba_tevent_context_init(talloc_tos());
2801 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2805 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2808 status = cli_tree_connect_recv(req);
2814 /****************************************************************************
2815 Send a tree disconnect.
2816 ****************************************************************************/
2818 struct cli_tdis_state {
2819 struct cli_state *cli;
2822 static void cli_tdis_done(struct tevent_req *subreq);
2824 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2825 struct tevent_context *ev,
2826 struct cli_state *cli)
2828 struct tevent_req *req, *subreq;
2829 struct cli_tdis_state *state;
2831 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2837 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2838 if (tevent_req_nomem(subreq, req)) {
2839 return tevent_req_post(req, ev);
2841 tevent_req_set_callback(subreq, cli_tdis_done, req);
2845 static void cli_tdis_done(struct tevent_req *subreq)
2847 struct tevent_req *req = tevent_req_callback_data(
2848 subreq, struct tevent_req);
2849 struct cli_tdis_state *state = tevent_req_data(
2850 req, struct cli_tdis_state);
2853 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2854 TALLOC_FREE(subreq);
2855 if (!NT_STATUS_IS_OK(status)) {
2856 tevent_req_nterror(req, status);
2859 cli_state_set_tid(state->cli, UINT16_MAX);
2860 tevent_req_done(req);
2863 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2865 return tevent_req_simple_recv_ntstatus(req);
2868 NTSTATUS cli_tdis(struct cli_state *cli)
2870 struct tevent_context *ev;
2871 struct tevent_req *req;
2872 NTSTATUS status = NT_STATUS_NO_MEMORY;
2874 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2875 return smb2cli_tdis(cli->conn,
2881 if (smbXcli_conn_has_async_calls(cli->conn)) {
2882 return NT_STATUS_INVALID_PARAMETER;
2884 ev = samba_tevent_context_init(talloc_tos());
2888 req = cli_tdis_send(ev, ev, cli);
2892 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2895 status = cli_tdis_recv(req);
2901 struct cli_connect_sock_state {
2902 const char **called_names;
2903 const char **calling_names;
2909 static void cli_connect_sock_done(struct tevent_req *subreq);
2912 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2916 static struct tevent_req *cli_connect_sock_send(
2917 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2918 const char *host, int name_type, const struct sockaddr_storage *pss,
2919 const char *myname, uint16_t port)
2921 struct tevent_req *req, *subreq;
2922 struct cli_connect_sock_state *state;
2924 struct sockaddr_storage *addrs;
2925 unsigned i, num_addrs;
2928 req = tevent_req_create(mem_ctx, &state,
2929 struct cli_connect_sock_state);
2934 prog = getenv("LIBSMB_PROG");
2936 state->fd = sock_exec(prog);
2937 if (state->fd == -1) {
2938 status = map_nt_error_from_unix(errno);
2939 tevent_req_nterror(req, status);
2942 tevent_req_done(req);
2944 return tevent_req_post(req, ev);
2947 if ((pss == NULL) || is_zero_addr(pss)) {
2950 * Here we cheat. resolve_name_list is not async at all. So
2951 * this call will only be really async if the name lookup has
2952 * been done externally.
2955 status = resolve_name_list(state, host, name_type,
2956 &addrs, &num_addrs);
2957 if (!NT_STATUS_IS_OK(status)) {
2958 tevent_req_nterror(req, status);
2959 return tevent_req_post(req, ev);
2962 addrs = talloc_array(state, struct sockaddr_storage, 1);
2963 if (tevent_req_nomem(addrs, req)) {
2964 return tevent_req_post(req, ev);
2970 state->called_names = talloc_array(state, const char *, num_addrs);
2971 if (tevent_req_nomem(state->called_names, req)) {
2972 return tevent_req_post(req, ev);
2974 state->called_types = talloc_array(state, int, num_addrs);
2975 if (tevent_req_nomem(state->called_types, req)) {
2976 return tevent_req_post(req, ev);
2978 state->calling_names = talloc_array(state, const char *, num_addrs);
2979 if (tevent_req_nomem(state->calling_names, req)) {
2980 return tevent_req_post(req, ev);
2982 for (i=0; i<num_addrs; i++) {
2983 state->called_names[i] = host;
2984 state->called_types[i] = name_type;
2985 state->calling_names[i] = myname;
2988 subreq = smbsock_any_connect_send(
2989 state, ev, addrs, state->called_names, state->called_types,
2990 state->calling_names, NULL, num_addrs, port);
2991 if (tevent_req_nomem(subreq, req)) {
2992 return tevent_req_post(req, ev);
2994 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2998 static void cli_connect_sock_done(struct tevent_req *subreq)
3000 struct tevent_req *req = tevent_req_callback_data(
3001 subreq, struct tevent_req);
3002 struct cli_connect_sock_state *state = tevent_req_data(
3003 req, struct cli_connect_sock_state);
3006 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3008 TALLOC_FREE(subreq);
3009 if (tevent_req_nterror(req, status)) {
3012 set_socket_options(state->fd, lp_socket_options());
3013 tevent_req_done(req);
3016 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3017 int *pfd, uint16_t *pport)
3019 struct cli_connect_sock_state *state = tevent_req_data(
3020 req, struct cli_connect_sock_state);
3023 if (tevent_req_is_nterror(req, &status)) {
3027 *pport = state->port;
3028 return NT_STATUS_OK;
3031 struct cli_connect_nb_state {
3032 const char *desthost;
3035 struct cli_state *cli;
3038 static void cli_connect_nb_done(struct tevent_req *subreq);
3040 static struct tevent_req *cli_connect_nb_send(
3041 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3042 const char *host, const struct sockaddr_storage *dest_ss,
3043 uint16_t port, int name_type, const char *myname,
3044 int signing_state, int flags)
3046 struct tevent_req *req, *subreq;
3047 struct cli_connect_nb_state *state;
3049 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3053 state->signing_state = signing_state;
3054 state->flags = flags;
3057 char *p = strchr(host, '#');
3060 name_type = strtol(p+1, NULL, 16);
3061 host = talloc_strndup(state, host, p - host);
3062 if (tevent_req_nomem(host, req)) {
3063 return tevent_req_post(req, ev);
3067 state->desthost = host;
3069 state->desthost = print_canonical_sockaddr(state, dest_ss);
3070 if (tevent_req_nomem(state->desthost, req)) {
3071 return tevent_req_post(req, ev);
3075 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3077 if (tevent_req_nomem(subreq, req)) {
3078 return tevent_req_post(req, ev);
3080 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3084 static void cli_connect_nb_done(struct tevent_req *subreq)
3086 struct tevent_req *req = tevent_req_callback_data(
3087 subreq, struct tevent_req);
3088 struct cli_connect_nb_state *state = tevent_req_data(
3089 req, struct cli_connect_nb_state);
3094 status = cli_connect_sock_recv(subreq, &fd, &port);
3095 TALLOC_FREE(subreq);
3096 if (tevent_req_nterror(req, status)) {
3100 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3101 state->signing_state, state->flags);
3102 if (tevent_req_nomem(state->cli, req)) {
3106 tevent_req_done(req);
3109 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3110 struct cli_state **pcli)
3112 struct cli_connect_nb_state *state = tevent_req_data(
3113 req, struct cli_connect_nb_state);
3116 if (tevent_req_is_nterror(req, &status)) {
3119 *pcli = talloc_move(NULL, &state->cli);
3120 return NT_STATUS_OK;
3123 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3124 uint16_t port, int name_type, const char *myname,
3125 int signing_state, int flags, struct cli_state **pcli)
3127 struct tevent_context *ev;
3128 struct tevent_req *req;
3129 NTSTATUS status = NT_STATUS_NO_MEMORY;
3131 ev = samba_tevent_context_init(talloc_tos());
3135 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3136 myname, signing_state, flags);
3140 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3143 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3146 status = cli_connect_nb_recv(req, pcli);
3152 struct cli_start_connection_state {
3153 struct tevent_context *ev;
3154 struct cli_state *cli;
3159 static void cli_start_connection_connected(struct tevent_req *subreq);
3160 static void cli_start_connection_done(struct tevent_req *subreq);
3163 establishes a connection to after the negprot.
3164 @param output_cli A fully initialised cli structure, non-null only on success
3165 @param dest_host The netbios name of the remote host
3166 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3167 @param port (optional) The destination port (0 for default)
3170 static struct tevent_req *cli_start_connection_send(
3171 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3172 const char *my_name, const char *dest_host,
3173 const struct sockaddr_storage *dest_ss, int port,
3174 int signing_state, int flags)
3176 struct tevent_req *req, *subreq;
3177 struct cli_start_connection_state *state;
3179 req = tevent_req_create(mem_ctx, &state,
3180 struct cli_start_connection_state);
3186 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3187 state->min_protocol = lp_client_ipc_min_protocol();
3188 state->max_protocol = lp_client_ipc_max_protocol();
3190 state->min_protocol = lp_client_min_protocol();
3191 state->max_protocol = lp_client_max_protocol();
3194 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3195 0x20, my_name, signing_state, flags);
3196 if (tevent_req_nomem(subreq, req)) {
3197 return tevent_req_post(req, ev);
3199 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3203 static void cli_start_connection_connected(struct tevent_req *subreq)
3205 struct tevent_req *req = tevent_req_callback_data(
3206 subreq, struct tevent_req);
3207 struct cli_start_connection_state *state = tevent_req_data(
3208 req, struct cli_start_connection_state);
3211 status = cli_connect_nb_recv(subreq, &state->cli);
3212 TALLOC_FREE(subreq);
3213 if (tevent_req_nterror(req, status)) {
3217 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3218 state->cli->timeout,
3219 state->min_protocol,
3220 state->max_protocol);
3221 if (tevent_req_nomem(subreq, req)) {
3224 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3227 static void cli_start_connection_done(struct tevent_req *subreq)
3229 struct tevent_req *req = tevent_req_callback_data(
3230 subreq, struct tevent_req);
3231 struct cli_start_connection_state *state = tevent_req_data(
3232 req, struct cli_start_connection_state);
3235 status = smbXcli_negprot_recv(subreq);
3236 TALLOC_FREE(subreq);
3237 if (tevent_req_nterror(req, status)) {
3241 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3242 /* Ensure we ask for some initial credits. */
3243 smb2cli_conn_set_max_credits(state->cli->conn,
3244 DEFAULT_SMB2_MAX_CREDITS);
3247 tevent_req_done(req);
3250 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3251 struct cli_state **output_cli)
3253 struct cli_start_connection_state *state = tevent_req_data(
3254 req, struct cli_start_connection_state);
3257 if (tevent_req_is_nterror(req, &status)) {
3260 *output_cli = state->cli;
3262 return NT_STATUS_OK;
3265 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3266 const char *my_name,
3267 const char *dest_host,
3268 const struct sockaddr_storage *dest_ss, int port,
3269 int signing_state, int flags)
3271 struct tevent_context *ev;
3272 struct tevent_req *req;
3273 NTSTATUS status = NT_STATUS_NO_MEMORY;
3275 ev = samba_tevent_context_init(talloc_tos());
3279 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3280 port, signing_state, flags);
3284 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3287 status = cli_start_connection_recv(req, output_cli);
3294 establishes a connection right up to doing tconX, password specified.
3295 @param output_cli A fully initialised cli structure, non-null only on success
3296 @param dest_host The netbios name of the remote host
3297 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3298 @param port (optional) The destination port (0 for default)
3299 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3300 @param service_type The 'type' of serivice.
3301 @param user Username, unix string
3302 @param domain User's domain
3303 @param password User's password, unencrypted unix string.
3306 struct cli_full_connection_state {
3307 struct tevent_context *ev;
3308 const char *service;
3309 const char *service_type;
3312 const char *password;
3315 struct cli_state *cli;
3318 static int cli_full_connection_state_destructor(
3319 struct cli_full_connection_state *s);