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 status = cli_set_username(cli, state->user);
286 if (tevent_req_nterror(req, status)) {
289 tevent_req_done(req);
292 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
294 return tevent_req_simple_recv_ntstatus(req);
297 /****************************************************************************
298 Work out suitable capabilities to offer the server.
299 ****************************************************************************/
301 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
302 uint32_t sesssetup_capabilities)
304 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
307 * We only send capabilities based on the mask for:
308 * - client only flags
309 * - flags used in both directions
311 * We do not echo the server only flags, except some legacy flags.
313 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
314 * CAP_LARGE_WRITEX in order to allow us to do large reads
315 * against old Samba releases (<= 3.6.x).
317 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
320 * Session Setup specific flags CAP_DYNAMIC_REAUTH
321 * and CAP_EXTENDED_SECURITY are passed by the caller.
322 * We need that in order to do guest logins even if
323 * CAP_EXTENDED_SECURITY is negotiated.
325 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
326 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
327 client_capabilities |= sesssetup_capabilities;
329 return client_capabilities;
332 /****************************************************************************
333 Do a NT1 guest session setup.
334 ****************************************************************************/
336 struct cli_session_setup_guest_state {
337 struct cli_state *cli;
342 static void cli_session_setup_guest_done(struct tevent_req *subreq);
344 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
345 struct tevent_context *ev,
346 struct cli_state *cli,
347 struct tevent_req **psmbreq)
349 struct tevent_req *req, *subreq;
350 struct cli_session_setup_guest_state *state;
354 req = tevent_req_create(mem_ctx, &state,
355 struct cli_session_setup_guest_state);
362 SCVAL(vwv+0, 0, 0xFF);
365 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
367 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
368 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
373 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
375 bytes = talloc_array(state, uint8_t, 0);
377 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
379 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
381 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
382 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
389 state->bytes.iov_base = (void *)bytes;
390 state->bytes.iov_len = talloc_get_size(bytes);
392 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
394 if (subreq == NULL) {
398 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
403 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
404 struct tevent_context *ev,
405 struct cli_state *cli)
407 struct tevent_req *req, *subreq;
410 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
415 status = smb1cli_req_chain_submit(&subreq, 1);
416 if (!NT_STATUS_IS_OK(status)) {
417 tevent_req_nterror(req, status);
418 return tevent_req_post(req, ev);
423 static void cli_session_setup_guest_done(struct tevent_req *subreq)
425 struct tevent_req *req = tevent_req_callback_data(
426 subreq, struct tevent_req);
427 struct cli_session_setup_guest_state *state = tevent_req_data(
428 req, struct cli_session_setup_guest_state);
429 struct cli_state *cli = state->cli;
440 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
443 if (!NT_STATUS_IS_OK(status)) {
444 tevent_req_nterror(req, status);
448 inhdr = in + NBT_HDR_SIZE;
451 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
453 status = smb_bytes_talloc_string(cli,
460 if (!NT_STATUS_IS_OK(status)) {
461 tevent_req_nterror(req, status);
466 status = smb_bytes_talloc_string(cli,
473 if (!NT_STATUS_IS_OK(status)) {
474 tevent_req_nterror(req, status);
479 status = smb_bytes_talloc_string(cli,
486 if (!NT_STATUS_IS_OK(status)) {
487 tevent_req_nterror(req, status);
492 status = cli_set_username(cli, "");
493 if (!NT_STATUS_IS_OK(status)) {
494 tevent_req_nterror(req, status);
497 tevent_req_done(req);
500 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
502 return tevent_req_simple_recv_ntstatus(req);
505 /****************************************************************************
506 Do a NT1 plaintext session setup.
507 ****************************************************************************/
509 struct cli_session_setup_plain_state {
510 struct cli_state *cli;
515 static void cli_session_setup_plain_done(struct tevent_req *subreq);
517 static struct tevent_req *cli_session_setup_plain_send(
518 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
519 struct cli_state *cli,
520 const char *user, const char *pass, const char *workgroup)
522 struct tevent_req *req, *subreq;
523 struct cli_session_setup_plain_state *state;
529 req = tevent_req_create(mem_ctx, &state,
530 struct cli_session_setup_plain_state);
538 SCVAL(vwv+0, 0, 0xff);
541 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
543 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
544 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
549 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
551 bytes = talloc_array(state, uint8_t, 0);
552 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
554 if (tevent_req_nomem(bytes, req)) {
555 return tevent_req_post(req, ev);
557 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
559 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
560 user, strlen(user)+1, NULL);
561 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
562 workgroup, strlen(workgroup)+1, NULL);
563 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
566 version = talloc_asprintf(talloc_tos(), "Samba %s",
567 samba_version_string());
568 if (tevent_req_nomem(version, req)){
569 return tevent_req_post(req, ev);
571 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
572 version, strlen(version)+1, NULL);
573 TALLOC_FREE(version);
575 if (tevent_req_nomem(bytes, req)) {
576 return tevent_req_post(req, ev);
579 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
580 talloc_get_size(bytes), bytes);
581 if (tevent_req_nomem(subreq, req)) {
582 return tevent_req_post(req, ev);
584 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
588 static void cli_session_setup_plain_done(struct tevent_req *subreq)
590 struct tevent_req *req = tevent_req_callback_data(
591 subreq, struct tevent_req);
592 struct cli_session_setup_plain_state *state = tevent_req_data(
593 req, struct cli_session_setup_plain_state);
594 struct cli_state *cli = state->cli;
605 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
608 if (tevent_req_nterror(req, status)) {
612 inhdr = in + NBT_HDR_SIZE;
615 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
617 status = smb_bytes_talloc_string(cli,
624 if (!NT_STATUS_IS_OK(status)) {
625 tevent_req_nterror(req, status);
630 status = smb_bytes_talloc_string(cli,
637 if (!NT_STATUS_IS_OK(status)) {
638 tevent_req_nterror(req, status);
643 status = smb_bytes_talloc_string(cli,
650 if (!NT_STATUS_IS_OK(status)) {
651 tevent_req_nterror(req, status);
656 status = cli_set_username(cli, state->user);
657 if (tevent_req_nterror(req, status)) {
661 tevent_req_done(req);
664 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
666 return tevent_req_simple_recv_ntstatus(req);
669 /****************************************************************************
670 do a NT1 NTLM/LM encrypted session setup - for when extended security
672 @param cli client state to create do session setup on
674 @param pass *either* cleartext password (passlen !=24) or LM response.
675 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
676 @param workgroup The user's domain.
677 ****************************************************************************/
679 struct cli_session_setup_nt1_state {
680 struct cli_state *cli;
683 DATA_BLOB session_key;
687 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
689 static struct tevent_req *cli_session_setup_nt1_send(
690 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
691 struct cli_state *cli, const char *user,
692 const char *pass, size_t passlen,
693 const char *ntpass, size_t ntpasslen,
694 const char *workgroup)
696 struct tevent_req *req, *subreq;
697 struct cli_session_setup_nt1_state *state;
698 DATA_BLOB lm_response = data_blob_null;
699 DATA_BLOB nt_response = data_blob_null;
700 DATA_BLOB session_key = data_blob_null;
703 char *workgroup_upper;
705 req = tevent_req_create(mem_ctx, &state,
706 struct cli_session_setup_nt1_state);
715 /* do nothing - guest login */
716 } else if (passlen != 24) {
717 if (lp_client_ntlmv2_auth()) {
718 DATA_BLOB server_chal;
719 DATA_BLOB names_blob;
722 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
726 * note that the 'workgroup' here is a best
727 * guess - we don't know the server's domain
728 * at this point. Windows clients also don't
731 names_blob = NTLMv2_generate_names_blob(
732 NULL, NULL, workgroup);
734 if (tevent_req_nomem(names_blob.data, req)) {
735 return tevent_req_post(req, ev);
738 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
739 &server_chal, &names_blob,
740 &lm_response, &nt_response,
741 NULL, &session_key)) {
742 data_blob_free(&names_blob);
744 req, NT_STATUS_ACCESS_DENIED);
745 return tevent_req_post(req, ev);
747 data_blob_free(&names_blob);
751 E_md4hash(pass, nt_hash);
754 nt_response = data_blob_null;
756 nt_response = data_blob(NULL, 24);
757 if (tevent_req_nomem(nt_response.data, req)) {
758 return tevent_req_post(req, ev);
761 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
764 /* non encrypted password supplied. Ignore ntpass. */
765 if (lp_client_lanman_auth()) {
767 lm_response = data_blob(NULL, 24);
768 if (tevent_req_nomem(lm_response.data, req)) {
769 return tevent_req_post(req, ev);
772 if (!SMBencrypt(pass,
773 smb1cli_conn_server_challenge(cli->conn),
776 * Oops, the LM response is
777 * invalid, just put the NT
778 * response there instead
780 data_blob_free(&lm_response);
781 lm_response = data_blob(
787 * LM disabled, place NT# in LM field
790 lm_response = data_blob(
791 nt_response.data, nt_response.length);
794 if (tevent_req_nomem(lm_response.data, req)) {
795 return tevent_req_post(req, ev);
798 session_key = data_blob(NULL, 16);
799 if (tevent_req_nomem(session_key.data, req)) {
800 return tevent_req_post(req, ev);
803 E_deshash(pass, session_key.data);
804 memset(&session_key.data[8], '\0', 8);
806 SMBsesskeygen_ntv1(nt_hash, session_key.data);
810 /* pre-encrypted password supplied. Only used for
811 security=server, can't do
812 signing because we don't have original key */
814 lm_response = data_blob(pass, passlen);
815 if (tevent_req_nomem(lm_response.data, req)) {
816 return tevent_req_post(req, ev);
819 nt_response = data_blob(ntpass, ntpasslen);
820 if (tevent_req_nomem(nt_response.data, req)) {
821 return tevent_req_post(req, ev);
826 state->response = data_blob_talloc(
827 state, lm_response.data, lm_response.length);
829 state->response = data_blob_talloc(
830 state, nt_response.data, nt_response.length);
832 if (tevent_req_nomem(state->response.data, req)) {
833 return tevent_req_post(req, ev);
836 if (session_key.data) {
837 state->session_key = data_blob_talloc(
838 state, session_key.data, session_key.length);
839 if (tevent_req_nomem(state->session_key.data, req)) {
840 return tevent_req_post(req, ev);
843 data_blob_free(&session_key);
845 SCVAL(vwv+0, 0, 0xff);
848 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
850 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
851 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
852 SSVAL(vwv+7, 0, lm_response.length);
853 SSVAL(vwv+8, 0, nt_response.length);
856 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
858 bytes = talloc_array(state, uint8_t,
859 lm_response.length + nt_response.length);
860 if (tevent_req_nomem(bytes, req)) {
861 return tevent_req_post(req, ev);
863 if (lm_response.length != 0) {
864 memcpy(bytes, lm_response.data, lm_response.length);
866 if (nt_response.length != 0) {
867 memcpy(bytes + lm_response.length,
868 nt_response.data, nt_response.length);
870 data_blob_free(&lm_response);
871 data_blob_free(&nt_response);
873 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
874 user, strlen(user)+1, NULL);
877 * Upper case here might help some NTLMv2 implementations
879 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
880 if (tevent_req_nomem(workgroup_upper, req)) {
881 return tevent_req_post(req, ev);
883 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
884 workgroup_upper, strlen(workgroup_upper)+1,
886 TALLOC_FREE(workgroup_upper);
888 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
889 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
890 if (tevent_req_nomem(bytes, req)) {
891 return tevent_req_post(req, ev);
894 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
895 talloc_get_size(bytes), bytes);
896 if (tevent_req_nomem(subreq, req)) {
897 return tevent_req_post(req, ev);
899 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
903 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
905 struct tevent_req *req = tevent_req_callback_data(
906 subreq, struct tevent_req);
907 struct cli_session_setup_nt1_state *state = tevent_req_data(
908 req, struct cli_session_setup_nt1_state);
909 struct cli_state *cli = state->cli;
920 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
923 if (!NT_STATUS_IS_OK(status)) {
924 tevent_req_nterror(req, status);
928 inhdr = in + NBT_HDR_SIZE;
931 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
933 status = smb_bytes_talloc_string(cli,
939 if (!NT_STATUS_IS_OK(status)) {
940 tevent_req_nterror(req, status);
945 status = smb_bytes_talloc_string(cli,
951 if (!NT_STATUS_IS_OK(status)) {
952 tevent_req_nterror(req, status);
957 status = smb_bytes_talloc_string(cli,
963 if (!NT_STATUS_IS_OK(status)) {
964 tevent_req_nterror(req, status);
969 status = cli_set_username(cli, state->user);
970 if (tevent_req_nterror(req, status)) {
973 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
974 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
975 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
978 if (state->session_key.data) {
979 struct smbXcli_session *session = state->cli->smb1.session;
981 status = smb1cli_session_set_session_key(session,
983 if (tevent_req_nterror(req, status)) {
987 tevent_req_done(req);
990 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
992 return tevent_req_simple_recv_ntstatus(req);
995 /* The following is calculated from :
997 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
998 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1002 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1004 struct cli_sesssetup_blob_state {
1005 struct tevent_context *ev;
1006 struct cli_state *cli;
1008 uint16_t max_blob_size;
1012 DATA_BLOB smb2_blob;
1013 struct iovec *recv_iov;
1020 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1021 struct tevent_req **psubreq);
1022 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1024 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1025 struct tevent_context *ev,
1026 struct cli_state *cli,
1029 struct tevent_req *req, *subreq;
1030 struct cli_sesssetup_blob_state *state;
1031 uint32_t usable_space;
1033 req = tevent_req_create(mem_ctx, &state,
1034 struct cli_sesssetup_blob_state);
1042 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1043 usable_space = UINT16_MAX;
1045 usable_space = cli_state_available_size(cli,
1046 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1049 if (usable_space == 0) {
1050 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1051 "(not possible to send %u bytes)\n",
1052 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1053 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1054 return tevent_req_post(req, ev);
1056 state->max_blob_size = MIN(usable_space, 0xFFFF);
1058 if (!cli_sesssetup_blob_next(state, &subreq)) {
1059 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1060 return tevent_req_post(req, ev);
1062 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1066 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1067 struct tevent_req **psubreq)
1069 struct tevent_req *subreq;
1072 thistime = MIN(state->blob.length, state->max_blob_size);
1074 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1076 state->smb2_blob.data = state->blob.data;
1077 state->smb2_blob.length = thistime;
1079 state->blob.data += thistime;
1080 state->blob.length -= thistime;
1082 subreq = smb2cli_session_setup_send(state, state->ev,
1084 state->cli->timeout,
1085 state->cli->smb2.session,
1087 SMB2_CAP_DFS, /* in_capabilities */
1089 0, /* in_previous_session_id */
1091 if (subreq == NULL) {
1098 SCVAL(state->vwv+0, 0, 0xFF);
1099 SCVAL(state->vwv+0, 1, 0);
1100 SSVAL(state->vwv+1, 0, 0);
1101 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1102 SSVAL(state->vwv+3, 0, 2);
1103 SSVAL(state->vwv+4, 0, 1);
1104 SIVAL(state->vwv+5, 0, 0);
1106 SSVAL(state->vwv+7, 0, thistime);
1108 SSVAL(state->vwv+8, 0, 0);
1109 SSVAL(state->vwv+9, 0, 0);
1110 SIVAL(state->vwv+10, 0,
1111 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1113 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1115 if (state->buf == NULL) {
1118 state->blob.data += thistime;
1119 state->blob.length -= thistime;
1121 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1123 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1125 if (state->buf == NULL) {
1128 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1130 talloc_get_size(state->buf), state->buf);
1131 if (subreq == NULL) {
1138 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1140 struct tevent_req *req = tevent_req_callback_data(
1141 subreq, struct tevent_req);
1142 struct cli_sesssetup_blob_state *state = tevent_req_data(
1143 req, struct cli_sesssetup_blob_state);
1144 struct cli_state *cli = state->cli;
1151 uint16_t blob_length;
1156 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1157 status = smb2cli_session_setup_recv(subreq, state,
1161 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1162 &num_bytes, &bytes);
1163 TALLOC_FREE(state->buf);
1165 TALLOC_FREE(subreq);
1166 if (!NT_STATUS_IS_OK(status)
1167 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1168 tevent_req_nterror(req, status);
1172 state->status = status;
1174 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1179 inhdr = in + NBT_HDR_SIZE;
1180 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1182 blob_length = SVAL(vwv+3, 0);
1183 if (blob_length > num_bytes) {
1184 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1187 state->ret_blob = data_blob_const(bytes, blob_length);
1189 p = bytes + blob_length;
1191 status = smb_bytes_talloc_string(cli,
1198 if (!NT_STATUS_IS_OK(status)) {
1199 tevent_req_nterror(req, status);
1204 status = smb_bytes_talloc_string(cli,
1211 if (!NT_STATUS_IS_OK(status)) {
1212 tevent_req_nterror(req, status);
1217 status = smb_bytes_talloc_string(cli,
1219 &cli->server_domain,
1224 if (!NT_STATUS_IS_OK(status)) {
1225 tevent_req_nterror(req, status);
1231 if (state->blob.length != 0) {
1235 if (!cli_sesssetup_blob_next(state, &subreq)) {
1236 tevent_req_oom(req);
1239 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1242 tevent_req_done(req);
1245 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1246 TALLOC_CTX *mem_ctx,
1249 struct iovec **precv_iov)
1251 struct cli_sesssetup_blob_state *state = tevent_req_data(
1252 req, struct cli_sesssetup_blob_state);
1255 struct iovec *recv_iov;
1257 if (tevent_req_is_nterror(req, &status)) {
1258 TALLOC_FREE(state->cli->smb2.session);
1259 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1263 inbuf = talloc_move(mem_ctx, &state->inbuf);
1264 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1265 if (pblob != NULL) {
1266 *pblob = state->ret_blob;
1268 if (pinbuf != NULL) {
1271 if (precv_iov != NULL) {
1272 *precv_iov = recv_iov;
1274 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1275 return state->status;
1280 /****************************************************************************
1281 Use in-memory credentials cache
1282 ****************************************************************************/
1284 static void use_in_memory_ccache(void) {
1285 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1288 #endif /* HAVE_KRB5 */
1290 /****************************************************************************
1291 Do a spnego/NTLMSSP encrypted session setup.
1292 ****************************************************************************/
1294 struct cli_session_setup_gensec_state {
1295 struct tevent_context *ev;
1296 struct cli_state *cli;
1297 struct auth_generic_state *auth_generic;
1301 struct iovec *recv_iov;
1305 DATA_BLOB session_key;
1308 static int cli_session_setup_gensec_state_destructor(
1309 struct cli_session_setup_gensec_state *state)
1311 TALLOC_FREE(state->auth_generic);
1312 data_blob_clear_free(&state->session_key);
1316 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
1317 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
1318 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
1319 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
1320 static void cli_session_setup_gensec_ready(struct tevent_req *req);
1322 static struct tevent_req *cli_session_setup_gensec_send(
1323 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1324 const char *user, const char *pass, const char *domain,
1325 enum credentials_use_kerberos krb5_state,
1326 const char *target_service,
1327 const char *target_hostname,
1328 const char *target_principal)
1330 struct tevent_req *req;
1331 struct cli_session_setup_gensec_state *state;
1333 bool use_spnego_principal = lp_client_use_spnego_principal();
1335 req = tevent_req_create(mem_ctx, &state,
1336 struct cli_session_setup_gensec_state);
1343 talloc_set_destructor(
1344 state, cli_session_setup_gensec_state_destructor);
1346 status = auth_generic_client_prepare(state, &state->auth_generic);
1347 if (tevent_req_nterror(req, status)) {
1348 return tevent_req_post(req, ev);
1351 gensec_want_feature(state->auth_generic->gensec_security,
1352 GENSEC_FEATURE_SESSION_KEY);
1353 if (cli->use_ccache) {
1354 gensec_want_feature(state->auth_generic->gensec_security,
1355 GENSEC_FEATURE_NTLM_CCACHE);
1356 if (pass != NULL && strlen(pass) == 0) {
1358 * some callers pass "" as no password
1360 * GENSEC_FEATURE_NTLM_CCACHE only handles
1361 * NULL as no password.
1367 status = auth_generic_set_username(state->auth_generic, user);
1368 if (tevent_req_nterror(req, status)) {
1369 return tevent_req_post(req, ev);
1372 status = auth_generic_set_domain(state->auth_generic, domain);
1373 if (tevent_req_nterror(req, status)) {
1374 return tevent_req_post(req, ev);
1377 if (cli->pw_nt_hash) {
1378 struct samr_Password nt_hash;
1383 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1384 return tevent_req_post(req, ev);
1387 converted = strhex_to_str((char *)nt_hash.hash,
1388 sizeof(nt_hash.hash),
1389 pass, strlen(pass));
1390 if (converted != sizeof(nt_hash.hash)) {
1391 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1392 return tevent_req_post(req, ev);
1395 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
1396 &nt_hash, CRED_SPECIFIED);
1398 tevent_req_oom(req);
1399 return tevent_req_post(req, ev);
1402 status = auth_generic_set_password(state->auth_generic, pass);
1403 if (tevent_req_nterror(req, status)) {
1404 return tevent_req_post(req, ev);
1408 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
1411 if (krb5_state == CRED_DONT_USE_KERBEROS) {
1412 use_spnego_principal = false;
1415 if (target_service != NULL) {
1416 status = gensec_set_target_service(
1417 state->auth_generic->gensec_security,
1419 if (tevent_req_nterror(req, status)) {
1420 return tevent_req_post(req, ev);
1424 if (target_hostname != NULL) {
1425 status = gensec_set_target_hostname(
1426 state->auth_generic->gensec_security,
1428 if (tevent_req_nterror(req, status)) {
1429 return tevent_req_post(req, ev);
1433 if (target_principal != NULL) {
1434 status = gensec_set_target_principal(
1435 state->auth_generic->gensec_security,
1437 if (tevent_req_nterror(req, status)) {
1438 return tevent_req_post(req, ev);
1440 use_spnego_principal = false;
1441 } else if (target_service != NULL && target_hostname != NULL) {
1442 use_spnego_principal = false;
1445 if (use_spnego_principal) {
1447 b = smbXcli_conn_server_gss_blob(cli->conn);
1449 state->blob_in = *b;
1453 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
1455 status = auth_generic_client_start(state->auth_generic,
1457 if (tevent_req_nterror(req, status)) {
1458 return tevent_req_post(req, ev);
1461 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1462 state->cli->smb2.session = smbXcli_session_create(cli,
1464 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1465 return tevent_req_post(req, ev);
1469 cli_session_setup_gensec_local_next(req);
1470 if (!tevent_req_is_in_progress(req)) {
1471 return tevent_req_post(req, ev);
1477 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
1479 struct cli_session_setup_gensec_state *state =
1480 tevent_req_data(req,
1481 struct cli_session_setup_gensec_state);
1482 struct tevent_req *subreq = NULL;
1484 if (state->local_ready) {
1485 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1489 subreq = gensec_update_send(state, state->ev,
1490 state->auth_generic->gensec_security,
1492 if (tevent_req_nomem(subreq, req)) {
1495 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1498 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1500 struct tevent_req *req =
1501 tevent_req_callback_data(subreq,
1503 struct cli_session_setup_gensec_state *state =
1504 tevent_req_data(req,
1505 struct cli_session_setup_gensec_state);
1508 status = gensec_update_recv(subreq, state, &state->blob_out);
1509 TALLOC_FREE(subreq);
1510 state->blob_in = data_blob_null;
1511 if (!NT_STATUS_IS_OK(status) &&
1512 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1514 tevent_req_nterror(req, status);
1518 if (NT_STATUS_IS_OK(status)) {
1519 state->local_ready = true;
1522 if (state->local_ready && state->remote_ready) {
1523 cli_session_setup_gensec_ready(req);
1527 cli_session_setup_gensec_remote_next(req);
1530 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1532 struct cli_session_setup_gensec_state *state =
1533 tevent_req_data(req,
1534 struct cli_session_setup_gensec_state);
1535 struct tevent_req *subreq = NULL;
1537 if (state->remote_ready) {
1538 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1542 subreq = cli_sesssetup_blob_send(state, state->ev,
1543 state->cli, state->blob_out);
1544 if (tevent_req_nomem(subreq, req)) {
1547 tevent_req_set_callback(subreq,
1548 cli_session_setup_gensec_remote_done,
1552 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1554 struct tevent_req *req =
1555 tevent_req_callback_data(subreq,
1557 struct cli_session_setup_gensec_state *state =
1558 tevent_req_data(req,
1559 struct cli_session_setup_gensec_state);
1562 TALLOC_FREE(state->inbuf);
1563 TALLOC_FREE(state->recv_iov);
1565 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1566 &state->inbuf, &state->recv_iov);
1567 TALLOC_FREE(subreq);
1568 data_blob_free(&state->blob_out);
1569 if (!NT_STATUS_IS_OK(status) &&
1570 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1572 tevent_req_nterror(req, status);
1576 if (NT_STATUS_IS_OK(status)) {
1577 state->remote_ready = true;
1580 if (state->local_ready && state->remote_ready) {
1581 cli_session_setup_gensec_ready(req);
1585 cli_session_setup_gensec_local_next(req);
1588 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1590 struct cli_session_setup_gensec_state *state =
1591 tevent_req_data(req,
1592 struct cli_session_setup_gensec_state);
1593 const char *server_domain = NULL;
1596 if (state->blob_in.length != 0) {
1597 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1601 if (state->blob_out.length != 0) {
1602 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1607 * gensec_ntlmssp_server_domain() returns NULL
1608 * if NTLMSSP is not used.
1610 * We can remove this later
1611 * and leave the server domain empty for SMB2 and above
1612 * in future releases.
1614 server_domain = gensec_ntlmssp_server_domain(
1615 state->auth_generic->gensec_security);
1617 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1618 TALLOC_FREE(state->cli->server_domain);
1619 state->cli->server_domain = talloc_strdup(state->cli,
1621 if (state->cli->server_domain == NULL) {
1622 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1627 status = gensec_session_key(state->auth_generic->gensec_security,
1628 state, &state->session_key);
1629 if (tevent_req_nterror(req, status)) {
1633 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1634 struct smbXcli_session *session = state->cli->smb2.session;
1636 if (state->is_anonymous) {
1638 * Windows server does not set the
1639 * SMB2_SESSION_FLAG_IS_GUEST nor
1640 * SMB2_SESSION_FLAG_IS_NULL flag.
1642 * This fix makes sure we do not try
1643 * to verify a signature on the final
1644 * session setup response.
1646 tevent_req_done(req);
1650 status = smb2cli_session_set_session_key(session,
1653 if (tevent_req_nterror(req, status)) {
1657 struct smbXcli_session *session = state->cli->smb1.session;
1660 status = smb1cli_session_set_session_key(session,
1661 state->session_key);
1662 if (tevent_req_nterror(req, status)) {
1666 active = smb1cli_conn_activate_signing(state->cli->conn,
1672 ok = smb1cli_conn_check_signing(state->cli->conn,
1675 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1681 tevent_req_done(req);
1684 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1686 struct cli_session_setup_gensec_state *state =
1687 tevent_req_data(req,
1688 struct cli_session_setup_gensec_state);
1691 if (tevent_req_is_nterror(req, &status)) {
1692 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1695 return NT_STATUS_OK;
1700 static char *cli_session_setup_get_principal(
1701 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1702 const char *remote_name, const char *dest_realm)
1704 char *principal = NULL;
1706 if (!lp_client_use_spnego_principal() ||
1707 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1708 spnego_principal = NULL;
1710 if (spnego_principal != NULL) {
1711 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1712 "principal %s\n", spnego_principal));
1713 return talloc_strdup(mem_ctx, spnego_principal);
1715 if (is_ipaddress(remote_name) ||
1716 strequal(remote_name, STAR_SMBSERVER)) {
1720 DEBUG(3, ("cli_session_setup_spnego: using target "
1721 "hostname not SPNEGO principal\n"));
1724 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1725 if (realm == NULL) {
1728 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1729 remote_name, realm);
1732 principal = kerberos_get_principal_from_service_hostname(
1733 talloc_tos(), "cifs", remote_name, lp_realm());
1735 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1736 principal ? principal : "<null>"));
1742 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1743 const char *principal)
1747 account = talloc_strdup(mem_ctx, principal);
1748 if (account == NULL) {
1751 p = strchr_m(account, '@');
1758 /****************************************************************************
1759 Do a spnego encrypted session setup.
1761 user_domain: The shortname of the domain the user/machine is a member of.
1762 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1763 ****************************************************************************/
1765 struct cli_session_setup_spnego_state {
1766 struct tevent_context *ev;
1767 struct cli_state *cli;
1768 const char *target_hostname;
1770 const char *account;
1772 const char *user_domain;
1773 const char *dest_realm;
1778 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1781 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1783 static struct tevent_req *cli_session_setup_spnego_send(
1784 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1785 const char *user, const char *pass, const char *user_domain)
1787 struct tevent_req *req, *subreq;
1788 struct cli_session_setup_spnego_state *state;
1789 char *principal = NULL;
1790 char *OIDs[ASN1_MAX_OIDS];
1792 const char *dest_realm = cli_state_remote_realm(cli);
1793 const DATA_BLOB *server_blob;
1796 req = tevent_req_create(mem_ctx, &state,
1797 struct cli_session_setup_spnego_state);
1805 state->user_domain = user_domain;
1806 state->dest_realm = dest_realm;
1808 state->account = cli_session_setup_get_account(state, user);
1809 if (tevent_req_nomem(state->account, req)) {
1810 return tevent_req_post(req, ev);
1813 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1814 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1816 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1817 (unsigned long)server_blob->length));
1819 /* the server might not even do spnego */
1820 if (server_blob->length == 0) {
1821 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1826 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1829 /* The server sent us the first part of the SPNEGO exchange in the
1830 * negprot reply. It is WRONG to depend on the principal sent in the
1831 * negprot reply, but right now we do it. If we don't receive one,
1832 * we try to best guess, then fall back to NTLM. */
1833 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1834 &principal, NULL) ||
1836 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1837 tevent_req_done(req);
1838 return tevent_req_post(req, ev);
1841 /* make sure the server understands kerberos */
1842 for (i=0;OIDs[i];i++) {
1844 DEBUG(3,("got OID=%s\n", OIDs[i]));
1846 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1847 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1848 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1849 cli->got_kerberos_mechanism = True;
1851 talloc_free(OIDs[i]);
1854 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1856 status = cli_set_username(cli, user);
1857 if (!NT_STATUS_IS_OK(status)) {
1858 state->result = ADS_ERROR_NT(status);
1859 tevent_req_done(req);
1860 return tevent_req_post(req, ev);
1864 /* If password is set we reauthenticate to kerberos server
1865 * and do not store results */
1867 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1870 tmp = cli_session_setup_get_principal(
1871 talloc_tos(), principal, state->target_hostname, dest_realm);
1872 TALLOC_FREE(principal);
1875 if (pass && *pass) {
1878 use_in_memory_ccache();
1879 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1882 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1883 TALLOC_FREE(principal);
1884 if (cli->fallback_after_kerberos)
1886 state->result = ADS_ERROR_KRB5(ret);
1887 tevent_req_done(req);
1888 return tevent_req_post(req, ev);
1893 subreq = cli_session_setup_gensec_send(
1895 state->account, pass, user_domain,
1896 CRED_MUST_USE_KERBEROS,
1897 "cifs", state->target_hostname, principal);
1898 if (tevent_req_nomem(subreq, req)) {
1899 return tevent_req_post(req, ev);
1901 tevent_req_set_callback(
1902 subreq, cli_session_setup_spnego_done_krb,
1910 subreq = cli_session_setup_gensec_send(
1911 state, state->ev, state->cli,
1912 state->account, state->pass, state->user_domain,
1913 CRED_DONT_USE_KERBEROS,
1914 "cifs", state->target_hostname, NULL);
1915 if (tevent_req_nomem(subreq, req)) {
1916 return tevent_req_post(req, ev);
1918 tevent_req_set_callback(
1919 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1924 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1926 struct tevent_req *req = tevent_req_callback_data(
1927 subreq, struct tevent_req);
1928 struct cli_session_setup_spnego_state *state = tevent_req_data(
1929 req, struct cli_session_setup_spnego_state);
1932 status = cli_session_setup_gensec_recv(subreq);
1933 TALLOC_FREE(subreq);
1934 state->result = ADS_ERROR_NT(status);
1936 if (ADS_ERR_OK(state->result) ||
1937 !state->cli->fallback_after_kerberos) {
1938 tevent_req_done(req);
1942 subreq = cli_session_setup_gensec_send(
1943 state, state->ev, state->cli,
1944 state->account, state->pass, state->user_domain,
1945 CRED_DONT_USE_KERBEROS,
1946 "cifs", state->target_hostname, NULL);
1947 if (tevent_req_nomem(subreq, req)) {
1950 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1955 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1957 struct tevent_req *req = tevent_req_callback_data(
1958 subreq, struct tevent_req);
1959 struct cli_session_setup_spnego_state *state = tevent_req_data(
1960 req, struct cli_session_setup_spnego_state);
1963 status = cli_session_setup_gensec_recv(subreq);
1964 TALLOC_FREE(subreq);
1965 state->result = ADS_ERROR_NT(status);
1966 tevent_req_done(req);
1969 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1971 struct cli_session_setup_spnego_state *state = tevent_req_data(
1972 req, struct cli_session_setup_spnego_state);
1974 return state->result;
1977 struct cli_session_setup_state {
1981 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1982 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1983 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1984 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1985 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1987 /****************************************************************************
1988 Send a session setup. The username and workgroup is in UNIX character
1989 format and must be converted to DOS codepage format before sending. If the
1990 password is in plaintext, the same should be done.
1991 ****************************************************************************/
1993 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1994 struct tevent_context *ev,
1995 struct cli_state *cli,
1997 const char *pass, int passlen,
1998 const char *ntpass, int ntpasslen,
1999 const char *workgroup)
2001 struct tevent_req *req, *subreq;
2002 struct cli_session_setup_state *state;
2005 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2007 req = tevent_req_create(mem_ctx, &state,
2008 struct cli_session_setup_state);
2014 user2 = talloc_strdup(state, user);
2016 user2 = talloc_strdup(state, "");
2018 if (user2 == NULL) {
2019 tevent_req_oom(req);
2020 return tevent_req_post(req, ev);
2027 /* allow for workgroups as part of the username */
2028 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2029 (p=strchr_m(user2,*lp_winbind_separator()))) {
2032 if (!strupper_m(user2)) {
2033 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2034 return tevent_req_post(req, ev);
2039 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2040 tevent_req_done(req);
2041 return tevent_req_post(req, ev);
2044 /* now work out what sort of session setup we are going to
2045 do. I have split this into separate functions to make the
2046 flow a bit easier to understand (tridge) */
2048 /* if its an older server then we have to use the older request format */
2050 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2051 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2052 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2053 " or 'client ntlmv2 auth = yes'\n"));
2054 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2055 return tevent_req_post(req, ev);
2058 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2059 !lp_client_plaintext_auth() && (*pass)) {
2060 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2061 " or 'client ntlmv2 auth = yes'\n"));
2062 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2063 return tevent_req_post(req, ev);
2066 subreq = cli_session_setup_lanman2_send(
2067 state, ev, cli, user, pass, passlen, workgroup);
2068 if (tevent_req_nomem(subreq, req)) {
2069 return tevent_req_post(req, ev);
2071 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2076 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2077 subreq = cli_session_setup_spnego_send(
2078 state, ev, cli, user, pass, workgroup);
2079 if (tevent_req_nomem(subreq, req)) {
2080 return tevent_req_post(req, ev);
2082 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2087 /* if no user is supplied then we have to do an anonymous connection.
2088 passwords are ignored */
2090 if (!user || !*user) {
2091 subreq = cli_session_setup_guest_send(state, ev, cli);
2092 if (tevent_req_nomem(subreq, req)) {
2093 return tevent_req_post(req, ev);
2095 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2100 /* if the server is share level then send a plaintext null
2101 password at this point. The password is sent in the tree
2104 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2105 subreq = cli_session_setup_plain_send(
2106 state, ev, cli, user, "", workgroup);
2107 if (tevent_req_nomem(subreq, req)) {
2108 return tevent_req_post(req, ev);
2110 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2115 /* if the server doesn't support encryption then we have to use
2116 plaintext. The second password is ignored */
2118 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2119 if (!lp_client_plaintext_auth() && (*pass)) {
2120 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2121 " or 'client ntlmv2 auth = yes'\n"));
2122 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2123 return tevent_req_post(req, ev);
2125 subreq = cli_session_setup_plain_send(
2126 state, ev, cli, user, pass, workgroup);
2127 if (tevent_req_nomem(subreq, req)) {
2128 return tevent_req_post(req, ev);
2130 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2135 /* if the server supports extended security then use SPNEGO */
2137 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2138 subreq = cli_session_setup_spnego_send(
2139 state, ev, cli, user, pass, workgroup);
2140 if (tevent_req_nomem(subreq, req)) {
2141 return tevent_req_post(req, ev);
2143 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2147 /* otherwise do a NT1 style session setup */
2148 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2150 * Don't send an NTLMv2 response without NTLMSSP
2151 * if we want to use spnego support
2153 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2154 " but 'client use spnego = yes"
2155 " and 'client ntlmv2 auth = yes'\n"));
2156 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2157 return tevent_req_post(req, ev);
2160 subreq = cli_session_setup_nt1_send(
2161 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2163 if (tevent_req_nomem(subreq, req)) {
2164 return tevent_req_post(req, ev);
2166 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2171 tevent_req_done(req);
2172 return tevent_req_post(req, ev);
2175 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2177 struct tevent_req *req = tevent_req_callback_data(
2178 subreq, struct tevent_req);
2181 status = cli_session_setup_lanman2_recv(subreq);
2182 TALLOC_FREE(subreq);
2183 if (!NT_STATUS_IS_OK(status)) {
2184 tevent_req_nterror(req, status);
2187 tevent_req_done(req);
2190 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2192 struct tevent_req *req = tevent_req_callback_data(
2193 subreq, struct tevent_req);
2196 status = cli_session_setup_spnego_recv(subreq);
2197 TALLOC_FREE(subreq);
2198 if (!ADS_ERR_OK(status)) {
2199 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2200 tevent_req_nterror(req, ads_ntstatus(status));
2203 tevent_req_done(req);
2206 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2208 struct tevent_req *req = tevent_req_callback_data(
2209 subreq, struct tevent_req);
2212 status = cli_session_setup_guest_recv(subreq);
2213 TALLOC_FREE(subreq);
2214 if (!NT_STATUS_IS_OK(status)) {
2215 tevent_req_nterror(req, status);
2218 tevent_req_done(req);
2221 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2223 struct tevent_req *req = tevent_req_callback_data(
2224 subreq, struct tevent_req);
2227 status = cli_session_setup_plain_recv(subreq);
2228 TALLOC_FREE(subreq);
2229 if (!NT_STATUS_IS_OK(status)) {
2230 tevent_req_nterror(req, status);
2233 tevent_req_done(req);
2236 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2238 struct tevent_req *req = tevent_req_callback_data(
2239 subreq, struct tevent_req);
2242 status = cli_session_setup_nt1_recv(subreq);
2243 TALLOC_FREE(subreq);
2244 if (!NT_STATUS_IS_OK(status)) {
2245 DEBUG(3, ("cli_session_setup: NT1 session setup "
2246 "failed: %s\n", nt_errstr(status)));
2247 tevent_req_nterror(req, status);
2250 tevent_req_done(req);
2253 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2255 return tevent_req_simple_recv_ntstatus(req);
2258 NTSTATUS cli_session_setup(struct cli_state *cli,
2260 const char *pass, int passlen,
2261 const char *ntpass, int ntpasslen,
2262 const char *workgroup)
2264 struct tevent_context *ev;
2265 struct tevent_req *req;
2266 NTSTATUS status = NT_STATUS_NO_MEMORY;
2268 if (smbXcli_conn_has_async_calls(cli->conn)) {
2269 return NT_STATUS_INVALID_PARAMETER;
2271 ev = samba_tevent_context_init(talloc_tos());
2275 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2276 ntpass, ntpasslen, workgroup);
2280 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2283 status = cli_session_setup_recv(req);
2289 /****************************************************************************
2291 *****************************************************************************/
2293 struct cli_ulogoff_state {
2294 struct cli_state *cli;
2298 static void cli_ulogoff_done(struct tevent_req *subreq);
2300 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2301 struct tevent_context *ev,
2302 struct cli_state *cli)
2304 struct tevent_req *req, *subreq;
2305 struct cli_ulogoff_state *state;
2307 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2313 SCVAL(state->vwv+0, 0, 0xFF);
2314 SCVAL(state->vwv+1, 0, 0);
2315 SSVAL(state->vwv+2, 0, 0);
2317 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2319 if (tevent_req_nomem(subreq, req)) {
2320 return tevent_req_post(req, ev);
2322 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2326 static void cli_ulogoff_done(struct tevent_req *subreq)
2328 struct tevent_req *req = tevent_req_callback_data(
2329 subreq, struct tevent_req);
2330 struct cli_ulogoff_state *state = tevent_req_data(
2331 req, struct cli_ulogoff_state);
2334 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2335 if (!NT_STATUS_IS_OK(status)) {
2336 tevent_req_nterror(req, status);
2339 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2340 tevent_req_done(req);
2343 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2345 return tevent_req_simple_recv_ntstatus(req);
2348 NTSTATUS cli_ulogoff(struct cli_state *cli)
2350 struct tevent_context *ev;
2351 struct tevent_req *req;
2352 NTSTATUS status = NT_STATUS_NO_MEMORY;
2354 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2355 status = smb2cli_logoff(cli->conn,
2358 if (!NT_STATUS_IS_OK(status)) {
2361 smb2cli_session_set_id_and_flags(cli->smb2.session,
2363 return NT_STATUS_OK;
2366 if (smbXcli_conn_has_async_calls(cli->conn)) {
2367 return NT_STATUS_INVALID_PARAMETER;
2369 ev = samba_tevent_context_init(talloc_tos());
2373 req = cli_ulogoff_send(ev, ev, cli);
2377 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2380 status = cli_ulogoff_recv(req);
2386 /****************************************************************************
2388 ****************************************************************************/
2390 struct cli_tcon_andx_state {
2391 struct cli_state *cli;
2396 static void cli_tcon_andx_done(struct tevent_req *subreq);
2398 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2399 struct tevent_context *ev,
2400 struct cli_state *cli,
2401 const char *share, const char *dev,
2402 const char *pass, int passlen,
2403 struct tevent_req **psmbreq)
2405 struct tevent_req *req, *subreq;
2406 struct cli_tcon_andx_state *state;
2411 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2412 uint16_t tcon_flags = 0;
2416 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2423 cli->share = talloc_strdup(cli, share);
2428 /* in user level security don't send a password now */
2429 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2432 } else if (pass == NULL) {
2433 DEBUG(1, ("Server not using user level security and no "
2434 "password supplied.\n"));
2438 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2439 *pass && passlen != 24) {
2440 if (!lp_client_lanman_auth()) {
2441 DEBUG(1, ("Server requested LANMAN password "
2442 "(share-level security) but "
2443 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2448 * Non-encrypted passwords - convert to DOS codepage before
2451 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2453 pass = (const char *)p24;
2455 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2456 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2460 if (!lp_client_plaintext_auth() && (*pass)) {
2461 DEBUG(1, ("Server requested PLAINTEXT "
2463 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2468 * Non-encrypted passwords - convert to DOS codepage
2471 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2472 if (tevent_req_nomem(tmp_pass, req)) {
2473 return tevent_req_post(req, ev);
2475 tmp_pass = trans2_bytes_push_str(tmp_pass,
2476 false, /* always DOS */
2480 if (tevent_req_nomem(tmp_pass, req)) {
2481 return tevent_req_post(req, ev);
2483 pass = (const char *)tmp_pass;
2484 passlen = talloc_get_size(tmp_pass);
2488 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2489 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2491 SCVAL(vwv+0, 0, 0xFF);
2494 SSVAL(vwv+2, 0, tcon_flags);
2495 SSVAL(vwv+3, 0, passlen);
2497 if (passlen && pass) {
2498 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2500 bytes = talloc_array(state, uint8_t, 0);
2506 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2507 smbXcli_conn_remote_name(cli->conn), share);
2512 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2517 * Add the devicetype
2519 tmp = talloc_strdup_upper(talloc_tos(), dev);
2524 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2527 if (bytes == NULL) {
2532 state->bytes.iov_base = (void *)bytes;
2533 state->bytes.iov_len = talloc_get_size(bytes);
2535 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2537 if (subreq == NULL) {
2541 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2546 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2547 return tevent_req_post(req, ev);
2550 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2551 struct tevent_context *ev,
2552 struct cli_state *cli,
2553 const char *share, const char *dev,
2554 const char *pass, int passlen)
2556 struct tevent_req *req, *subreq;
2559 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2564 if (subreq == NULL) {
2567 status = smb1cli_req_chain_submit(&subreq, 1);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 tevent_req_nterror(req, status);
2570 return tevent_req_post(req, ev);
2575 static void cli_tcon_andx_done(struct tevent_req *subreq)
2577 struct tevent_req *req = tevent_req_callback_data(
2578 subreq, struct tevent_req);
2579 struct cli_tcon_andx_state *state = tevent_req_data(
2580 req, struct cli_tcon_andx_state);
2581 struct cli_state *cli = state->cli;
2589 uint16_t optional_support = 0;
2591 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2592 &num_bytes, &bytes);
2593 TALLOC_FREE(subreq);
2594 if (!NT_STATUS_IS_OK(status)) {
2595 tevent_req_nterror(req, status);
2599 inhdr = in + NBT_HDR_SIZE;
2602 if (clistr_pull_talloc(cli,
2603 (const char *)inhdr,
2604 SVAL(inhdr, HDR_FLG2),
2608 STR_TERMINATE|STR_ASCII) == -1) {
2609 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2613 cli->dev = talloc_strdup(cli, "");
2614 if (cli->dev == NULL) {
2615 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2620 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2621 /* almost certainly win95 - enable bug fixes */
2626 * Make sure that we have the optional support 16-bit field. WCT > 2.
2627 * Avoids issues when connecting to Win9x boxes sharing files
2630 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2631 optional_support = SVAL(vwv+2, 0);
2634 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2635 smb1cli_session_protect_session_key(cli->smb1.session);
2638 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2639 SVAL(inhdr, HDR_TID),
2641 0, /* maximal_access */
2642 0, /* guest_maximal_access */
2644 NULL); /* fs_type */
2646 tevent_req_done(req);
2649 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2651 return tevent_req_simple_recv_ntstatus(req);
2654 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2655 const char *dev, const char *pass, int passlen)
2657 TALLOC_CTX *frame = talloc_stackframe();
2658 struct tevent_context *ev;
2659 struct tevent_req *req;
2660 NTSTATUS status = NT_STATUS_NO_MEMORY;
2662 if (smbXcli_conn_has_async_calls(cli->conn)) {
2664 * Can't use sync call while an async call is in flight
2666 status = NT_STATUS_INVALID_PARAMETER;
2670 ev = samba_tevent_context_init(frame);
2675 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2680 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2684 status = cli_tcon_andx_recv(req);
2690 struct cli_tree_connect_state {
2691 struct cli_state *cli;
2694 static struct tevent_req *cli_raw_tcon_send(
2695 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2696 const char *service, const char *pass, const char *dev);
2697 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2698 uint16_t *max_xmit, uint16_t *tid);
2700 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2701 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2702 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2704 static struct tevent_req *cli_tree_connect_send(
2705 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2706 const char *share, const char *dev, const char *pass, int passlen)
2708 struct tevent_req *req, *subreq;
2709 struct cli_tree_connect_state *state;
2711 req = tevent_req_create(mem_ctx, &state,
2712 struct cli_tree_connect_state);
2718 cli->share = talloc_strdup(cli, share);
2719 if (tevent_req_nomem(cli->share, req)) {
2720 return tevent_req_post(req, ev);
2723 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2726 cli->smb2.tcon = smbXcli_tcon_create(cli);
2727 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2728 return tevent_req_post(req, ev);
2731 unc = talloc_asprintf(state, "\\\\%s\\%s",
2732 smbXcli_conn_remote_name(cli->conn),
2734 if (tevent_req_nomem(unc, req)) {
2735 return tevent_req_post(req, ev);
2738 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2739 cli->smb2.session, cli->smb2.tcon,
2742 if (tevent_req_nomem(subreq, req)) {
2743 return tevent_req_post(req, ev);
2745 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2750 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2751 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2753 if (tevent_req_nomem(subreq, req)) {
2754 return tevent_req_post(req, ev);
2756 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2761 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2762 if (tevent_req_nomem(subreq, req)) {
2763 return tevent_req_post(req, ev);
2765 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2770 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2772 tevent_req_simple_finish_ntstatus(
2773 subreq, smb2cli_tcon_recv(subreq));
2776 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2778 tevent_req_simple_finish_ntstatus(
2779 subreq, cli_tcon_andx_recv(subreq));
2782 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2784 struct tevent_req *req = tevent_req_callback_data(
2785 subreq, struct tevent_req);
2786 struct cli_tree_connect_state *state = tevent_req_data(
2787 req, struct cli_tree_connect_state);
2789 uint16_t max_xmit = 0;
2792 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2793 if (tevent_req_nterror(req, status)) {
2797 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2799 0, /* optional_support */
2800 0, /* maximal_access */
2801 0, /* guest_maximal_access */
2803 NULL); /* fs_type */
2805 tevent_req_done(req);
2808 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2810 return tevent_req_simple_recv_ntstatus(req);
2813 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2814 const char *dev, const char *pass, int passlen)
2816 struct tevent_context *ev;
2817 struct tevent_req *req;
2818 NTSTATUS status = NT_STATUS_NO_MEMORY;
2820 if (smbXcli_conn_has_async_calls(cli->conn)) {
2821 return NT_STATUS_INVALID_PARAMETER;
2823 ev = samba_tevent_context_init(talloc_tos());
2827 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2831 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2834 status = cli_tree_connect_recv(req);
2840 /****************************************************************************
2841 Send a tree disconnect.
2842 ****************************************************************************/
2844 struct cli_tdis_state {
2845 struct cli_state *cli;
2848 static void cli_tdis_done(struct tevent_req *subreq);
2850 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2851 struct tevent_context *ev,
2852 struct cli_state *cli)
2854 struct tevent_req *req, *subreq;
2855 struct cli_tdis_state *state;
2857 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2863 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2864 if (tevent_req_nomem(subreq, req)) {
2865 return tevent_req_post(req, ev);
2867 tevent_req_set_callback(subreq, cli_tdis_done, req);
2871 static void cli_tdis_done(struct tevent_req *subreq)
2873 struct tevent_req *req = tevent_req_callback_data(
2874 subreq, struct tevent_req);
2875 struct cli_tdis_state *state = tevent_req_data(
2876 req, struct cli_tdis_state);
2879 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2880 TALLOC_FREE(subreq);
2881 if (!NT_STATUS_IS_OK(status)) {
2882 tevent_req_nterror(req, status);
2885 cli_state_set_tid(state->cli, UINT16_MAX);
2886 tevent_req_done(req);
2889 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2891 return tevent_req_simple_recv_ntstatus(req);
2894 NTSTATUS cli_tdis(struct cli_state *cli)
2896 struct tevent_context *ev;
2897 struct tevent_req *req;
2898 NTSTATUS status = NT_STATUS_NO_MEMORY;
2900 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2901 return smb2cli_tdis(cli->conn,
2907 if (smbXcli_conn_has_async_calls(cli->conn)) {
2908 return NT_STATUS_INVALID_PARAMETER;
2910 ev = samba_tevent_context_init(talloc_tos());
2914 req = cli_tdis_send(ev, ev, cli);
2918 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2921 status = cli_tdis_recv(req);
2927 struct cli_connect_sock_state {
2928 const char **called_names;
2929 const char **calling_names;
2935 static void cli_connect_sock_done(struct tevent_req *subreq);
2938 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2942 static struct tevent_req *cli_connect_sock_send(
2943 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2944 const char *host, int name_type, const struct sockaddr_storage *pss,
2945 const char *myname, uint16_t port)
2947 struct tevent_req *req, *subreq;
2948 struct cli_connect_sock_state *state;
2950 struct sockaddr_storage *addrs;
2951 unsigned i, num_addrs;
2954 req = tevent_req_create(mem_ctx, &state,
2955 struct cli_connect_sock_state);
2960 prog = getenv("LIBSMB_PROG");
2962 state->fd = sock_exec(prog);
2963 if (state->fd == -1) {
2964 status = map_nt_error_from_unix(errno);
2965 tevent_req_nterror(req, status);
2968 tevent_req_done(req);
2970 return tevent_req_post(req, ev);
2973 if ((pss == NULL) || is_zero_addr(pss)) {
2976 * Here we cheat. resolve_name_list is not async at all. So
2977 * this call will only be really async if the name lookup has
2978 * been done externally.
2981 status = resolve_name_list(state, host, name_type,
2982 &addrs, &num_addrs);
2983 if (!NT_STATUS_IS_OK(status)) {
2984 tevent_req_nterror(req, status);
2985 return tevent_req_post(req, ev);
2988 addrs = talloc_array(state, struct sockaddr_storage, 1);
2989 if (tevent_req_nomem(addrs, req)) {
2990 return tevent_req_post(req, ev);
2996 state->called_names = talloc_array(state, const char *, num_addrs);
2997 if (tevent_req_nomem(state->called_names, req)) {
2998 return tevent_req_post(req, ev);
3000 state->called_types = talloc_array(state, int, num_addrs);
3001 if (tevent_req_nomem(state->called_types, req)) {
3002 return tevent_req_post(req, ev);
3004 state->calling_names = talloc_array(state, const char *, num_addrs);
3005 if (tevent_req_nomem(state->calling_names, req)) {
3006 return tevent_req_post(req, ev);
3008 for (i=0; i<num_addrs; i++) {
3009 state->called_names[i] = host;
3010 state->called_types[i] = name_type;
3011 state->calling_names[i] = myname;
3014 subreq = smbsock_any_connect_send(
3015 state, ev, addrs, state->called_names, state->called_types,
3016 state->calling_names, NULL, num_addrs, port);
3017 if (tevent_req_nomem(subreq, req)) {
3018 return tevent_req_post(req, ev);
3020 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3024 static void cli_connect_sock_done(struct tevent_req *subreq)
3026 struct tevent_req *req = tevent_req_callback_data(
3027 subreq, struct tevent_req);
3028 struct cli_connect_sock_state *state = tevent_req_data(
3029 req, struct cli_connect_sock_state);
3032 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3034 TALLOC_FREE(subreq);
3035 if (tevent_req_nterror(req, status)) {
3038 set_socket_options(state->fd, lp_socket_options());
3039 tevent_req_done(req);
3042 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3043 int *pfd, uint16_t *pport)
3045 struct cli_connect_sock_state *state = tevent_req_data(
3046 req, struct cli_connect_sock_state);
3049 if (tevent_req_is_nterror(req, &status)) {
3053 *pport = state->port;
3054 return NT_STATUS_OK;
3057 struct cli_connect_nb_state {
3058 const char *desthost;
3061 struct cli_state *cli;
3064 static void cli_connect_nb_done(struct tevent_req *subreq);
3066 static struct tevent_req *cli_connect_nb_send(
3067 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3068 const char *host, const struct sockaddr_storage *dest_ss,
3069 uint16_t port, int name_type, const char *myname,
3070 int signing_state, int flags)
3072 struct tevent_req *req, *subreq;
3073 struct cli_connect_nb_state *state;
3075 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3079 state->signing_state = signing_state;
3080 state->flags = flags;
3083 char *p = strchr(host, '#');
3086 name_type = strtol(p+1, NULL, 16);
3087 host = talloc_strndup(state, host, p - host);
3088 if (tevent_req_nomem(host, req)) {
3089 return tevent_req_post(req, ev);
3093 state->desthost = host;
3095 state->desthost = print_canonical_sockaddr(state, dest_ss);
3096 if (tevent_req_nomem(state->desthost, req)) {
3097 return tevent_req_post(req, ev);
3101 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3103 if (tevent_req_nomem(subreq, req)) {
3104 return tevent_req_post(req, ev);
3106 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3110 static void cli_connect_nb_done(struct tevent_req *subreq)
3112 struct tevent_req *req = tevent_req_callback_data(
3113 subreq, struct tevent_req);
3114 struct cli_connect_nb_state *state = tevent_req_data(
3115 req, struct cli_connect_nb_state);
3120 status = cli_connect_sock_recv(subreq, &fd, &port);
3121 TALLOC_FREE(subreq);
3122 if (tevent_req_nterror(req, status)) {
3126 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3127 state->signing_state, state->flags);
3128 if (tevent_req_nomem(state->cli, req)) {
3132 tevent_req_done(req);
3135 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3136 struct cli_state **pcli)
3138 struct cli_connect_nb_state *state = tevent_req_data(
3139 req, struct cli_connect_nb_state);
3142 if (tevent_req_is_nterror(req, &status)) {
3145 *pcli = talloc_move(NULL, &state->cli);
3146 return NT_STATUS_OK;
3149 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3150 uint16_t port, int name_type, const char *myname,
3151 int signing_state, int flags, struct cli_state **pcli)
3153 struct tevent_context *ev;
3154 struct tevent_req *req;
3155 NTSTATUS status = NT_STATUS_NO_MEMORY;
3157 ev = samba_tevent_context_init(talloc_tos());
3161 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3162 myname, signing_state, flags);
3166 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3169 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3172 status = cli_connect_nb_recv(req, pcli);
3178 struct cli_start_connection_state {
3179 struct tevent_context *ev;
3180 struct cli_state *cli;
3185 static void cli_start_connection_connected(struct tevent_req *subreq);
3186 static void cli_start_connection_done(struct tevent_req *subreq);
3189 establishes a connection to after the negprot.
3190 @param output_cli A fully initialised cli structure, non-null only on success
3191 @param dest_host The netbios name of the remote host
3192 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3193 @param port (optional) The destination port (0 for default)
3196 static struct tevent_req *cli_start_connection_send(
3197 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3198 const char *my_name, const char *dest_host,
3199 const struct sockaddr_storage *dest_ss, int port,
3200 int signing_state, int flags)
3202 struct tevent_req *req, *subreq;
3203 struct cli_start_connection_state *state;
3205 req = tevent_req_create(mem_ctx, &state,
3206 struct cli_start_connection_state);
3212 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3213 state->min_protocol = lp_client_ipc_min_protocol();
3214 state->max_protocol = lp_client_ipc_max_protocol();
3216 state->min_protocol = lp_client_min_protocol();
3217 state->max_protocol = lp_client_max_protocol();
3220 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3221 0x20, my_name, signing_state, flags);
3222 if (tevent_req_nomem(subreq, req)) {
3223 return tevent_req_post(req, ev);
3225 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3229 static void cli_start_connection_connected(struct tevent_req *subreq)
3231 struct tevent_req *req = tevent_req_callback_data(
3232 subreq, struct tevent_req);
3233 struct cli_start_connection_state *state = tevent_req_data(
3234 req, struct cli_start_connection_state);
3237 status = cli_connect_nb_recv(subreq, &state->cli);
3238 TALLOC_FREE(subreq);
3239 if (tevent_req_nterror(req, status)) {
3243 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3244 state->cli->timeout,
3245 state->min_protocol,
3246 state->max_protocol);
3247 if (tevent_req_nomem(subreq, req)) {
3250 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3253 static void cli_start_connection_done(struct tevent_req *subreq)
3255 struct tevent_req *req = tevent_req_callback_data(
3256 subreq, struct tevent_req);
3257 struct cli_start_connection_state *state = tevent_req_data(
3258 req, struct cli_start_connection_state);
3261 status = smbXcli_negprot_recv(subreq);
3262 TALLOC_FREE(subreq);
3263 if (tevent_req_nterror(req, status)) {
3267 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3268 /* Ensure we ask for some initial credits. */
3269 smb2cli_conn_set_max_credits(state->cli->conn,
3270 DEFAULT_SMB2_MAX_CREDITS);
3273 tevent_req_done(req);
3276 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3277 struct cli_state **output_cli)
3279 struct cli_start_connection_state *state = tevent_req_data(
3280 req, struct cli_start_connection_state);
3283 if (tevent_req_is_nterror(req, &status)) {
3286 *output_cli = state->cli;
3288 return NT_STATUS_OK;
3291 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3292 const char *my_name,
3293 const char *dest_host,
3294 const struct sockaddr_storage *dest_ss, int port,
3295 int signing_state, int flags)
3297 struct tevent_context *ev;
3298 struct tevent_req *req;
3299 NTSTATUS status = NT_STATUS_NO_MEMORY;
3301 ev = samba_tevent_context_init(talloc_tos());
3305 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3306 port, signing_state, flags);
3310 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3313 status = cli_start_connection_recv(req, output_cli);
3320 establishes a connection right up to doing tconX, password specified.
3321 @param output_cli A fully initialised cli structure, non-null only on success
3322 @param dest_host The netbios name of the remote host
3323 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3324 @param port (optional) The destination port (0 for default)
3325 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3326 @param service_type The 'type' of serivice.
3327 @param user Username, unix string
3328 @param domain User's domain
3329 @param password User's password, unencrypted unix string.
3332 struct cli_full_connection_state {
3333 struct tevent_context *ev;
3334 const char *service;
3335 const char *service_type;
3338 const char *password;
3341 struct cli_state *cli;
3344 static int cli_full_connection_state_destructor(
3345 struct cli_full_connection_state *s);
3346 static void cli_full_connection_started(struct tevent_req *subreq);
3347 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3348 static void cli_full_connection_done(struct tevent_req *subreq);
3350 struct tevent_req *cli_full_connection_send(
3351 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3352 const char *my_name, const char *dest_host,
3353 const struct sockaddr_storage *dest_ss, int port,
3354 const char *service, const char *service_type,
3355 const char *user, const char *domain,
3356 const char *password, int flags, int signing_state)
3358 struct tevent_req *req, *subreq;
3359 struct cli_full_connection_state *state;
3361 req = tevent_req_create(mem_ctx, &state,
3362 struct cli_full_connection_state);
3366 talloc_set_destructor(state, cli_full_connection_state_destructor);
3369 state->service = service;
3370 state->service_type = service_type;
3372 state->domain = domain;
3373 state->password = password;
3374 state->flags = flags;
3376 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3377 if (state->password == NULL) {
3378 state->password = "";
3381 subreq = cli_start_connection_send(
3382 state, ev, my_name, dest_host, dest_ss, port,
3383 signing_state, flags);
3384 if (tevent_req_nomem(subreq, req)) {
3385 return tevent_req_post(req, ev);
3387 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3391 static int cli_full_connection_state_destructor(
3392 struct cli_full_connection_state *s)
3394 if (s->cli != NULL) {
3395 cli_shutdown(s->cli);
3401 static void cli_full_connection_started(struct tevent_req *subreq)
3403 struct tevent_req *req = tevent_req_callback_data(
3404 subreq, struct tevent_req);
3405 struct cli_full_connection_state *state = tevent_req_data(
3406 req, struct cli_full_connection_state);
3409 status = cli_start_connection_recv(subreq, &state->cli);
3410 TALLOC_FREE(subreq);
3411 if (tevent_req_nterror(req, status)) {
3414 subreq = cli_session_setup_send(
3415 state, state->ev, state->cli, state->user,
3416 state->password, state->pw_len, state->password, state->pw_len,
3418 if (tevent_req_nomem(subreq, req)) {
3421 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3424 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3426 struct tevent_req *req = tevent_req_callback_data(
3427 subreq, struct tevent_req);
3428 struct cli_full_connection_state *state = tevent_req_data(
3429 req, struct cli_full_connection_state);
3432 status = cli_session_setup_recv(subreq);
3433 TALLOC_FREE(subreq);
3435 if (!NT_STATUS_IS_OK(status) &&
3436 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3438 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3440 subreq = cli_session_setup_send(
3441 state, state->ev, state->cli, "", "", 0, "", 0,
3443 if (tevent_req_nomem(subreq, req)) {
3446 tevent_req_set_callback(
3447 subreq, cli_full_connection_sess_set_up, req);
3451 if (tevent_req_nterror(req, status)) {
3455 if (state->service != NULL) {
3456 subreq = cli_tree_connect_send(
3457 state, state->ev, state->cli,
3458 state->service, state->service_type,
3459 state->password, state->pw_len);
3460 if (tevent_req_nomem(subreq, req)) {
3463 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3467 status = cli_init_creds(state->cli, state->user, state->domain,
3469 if (tevent_req_nterror(req, status)) {
3472 tevent_req_done(req);
3475 static void cli_full_connection_done(struct tevent_req *subreq)
3477 struct tevent_req *req = tevent_req_callback_data(
3478 subreq, struct tevent_req);
3479 struct cli_full_connection_state *state = tevent_req_data(
3480 req, struct cli_full_connection_state);
3483 status = cli_tree_connect_recv(subreq);
3484 TALLOC_FREE(subreq);
3485 if (tevent_req_nterror(req, status)) {
3488 status = cli_init_creds(state->cli, state->user, state->domain,
3490 if (tevent_req_nterror(req, status)) {
3493 tevent_req_done(req);
3496 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3497 struct cli_state **output_cli)
3499 struct cli_full_connection_state *state = tevent_req_data(
3500 req, struct cli_full_connection_state);
3503 if (tevent_req_is_nterror(req, &status)) {
3506 *output_cli = state->cli;
3507 talloc_set_destructor(state, NULL);
3508 return NT_STATUS_OK;
3511 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3512 const char *my_name,
3513 const char *dest_host,
3514 const struct sockaddr_storage *dest_ss, int port,
3515 const char *service, const char *service_type,
3516 const char *user, const char *domain,
3517 const char *password, int flags,
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_full_connection_send(
3529 ev, ev, my_name, dest_host, dest_ss, port, service,
3530 service_type, user, domain, password, flags, signing_state);
3534 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3537 status = cli_full_connection_recv(req, output_cli);
3543 /****************************************************************************
3544 Send an old style tcon.
3545 ****************************************************************************/
3546 struct cli_raw_tcon_state {
3550 static void cli_raw_tcon_done(struct tevent_req *subreq);
3552 static struct tevent_req *cli_raw_tcon_send(
3553 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3554 const char *service, const char *pass, const char *dev)
3556 struct tevent_req *req, *subreq;
3557 struct cli_raw_tcon_state *state;
3560 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3565 if (!lp_client_plaintext_auth() && (*pass)) {
3566 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3567 " or 'client ntlmv2 auth = yes'\n"));
3568 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3569 return tevent_req_post(req, ev);
3572 bytes = talloc_array(state, uint8_t, 0);
3573 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3574 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3575 service, strlen(service)+1, NULL);
3576 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3577 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3578 pass, strlen(pass)+1, NULL);
3579 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3580 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3581 dev, strlen(dev)+1, NULL);
3583 if (tevent_req_nomem(bytes, req)) {
3584 return tevent_req_post(req, ev);
3587 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3588 talloc_get_size(bytes), bytes);
3589 if (tevent_req_nomem(subreq, req)) {
3590 return tevent_req_post(req, ev);
3592 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3596 static void cli_raw_tcon_done(struct tevent_req *subreq)
3598 struct tevent_req *req = tevent_req_callback_data(
3599 subreq, struct tevent_req);
3600 struct cli_raw_tcon_state *state = tevent_req_data(
3601 req, struct cli_raw_tcon_state);
3604 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3606 TALLOC_FREE(subreq);
3607 if (tevent_req_nterror(req, status)) {
3610 tevent_req_done(req);
3613 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3614 uint16_t *max_xmit, uint16_t *tid)
3616 struct cli_raw_tcon_state *state = tevent_req_data(
3617 req, struct cli_raw_tcon_state);
3620 if (tevent_req_is_nterror(req, &status)) {
3623 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3624 *tid = SVAL(state->ret_vwv + 1, 0);
3625 return NT_STATUS_OK;
3628 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3629 const char *service, const char *pass, const char *dev,
3630 uint16_t *max_xmit, uint16_t *tid)
3632 struct tevent_context *ev;
3633 struct tevent_req *req;
3634 NTSTATUS status = NT_STATUS_NO_MEMORY;
3636 ev = samba_tevent_context_init(talloc_tos());
3640 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3644 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3647 status = cli_raw_tcon_recv(req, max_xmit, tid);
3653 /* Return a cli_state pointing at the IPC$ share for the given server */
3655 struct cli_state *get_ipc_connect(char *server,
3656 struct sockaddr_storage *server_ss,
3657 const struct user_auth_info *user_info)
3659 struct cli_state *cli;
3661 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3663 if (user_info->use_kerberos) {
3664 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3667 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3668 user_info->username ? user_info->username : "",
3670 user_info->password ? user_info->password : "",
3672 SMB_SIGNING_DEFAULT);
3674 if (NT_STATUS_IS_OK(nt_status)) {
3676 } else if (is_ipaddress(server)) {
3677 /* windows 9* needs a correct NMB name for connections */
3678 fstring remote_name;
3680 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3681 cli = get_ipc_connect(remote_name, server_ss, user_info);
3690 * Given the IP address of a master browser on the network, return its
3691 * workgroup and connect to it.
3693 * This function is provided to allow additional processing beyond what
3694 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3695 * browsers and obtain each master browsers' list of domains (in case the
3696 * first master browser is recently on the network and has not yet
3697 * synchronized with other master browsers and therefore does not yet have the
3698 * entire network browse list)
3701 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3702 struct sockaddr_storage *mb_ip,
3703 const struct user_auth_info *user_info,
3704 char **pp_workgroup_out)
3706 char addr[INET6_ADDRSTRLEN];
3708 struct cli_state *cli;
3709 struct sockaddr_storage server_ss;
3711 *pp_workgroup_out = NULL;
3713 print_sockaddr(addr, sizeof(addr), mb_ip);
3714 DEBUG(99, ("Looking up name of master browser %s\n",
3718 * Do a name status query to find out the name of the master browser.
3719 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3720 * master browser will not respond to a wildcard query (or, at least,
3721 * an NT4 server acting as the domain master browser will not).
3723 * We might be able to use ONLY the query on MSBROWSE, but that's not
3724 * yet been tested with all Windows versions, so until it is, leave
3725 * the original wildcard query as the first choice and fall back to
3726 * MSBROWSE if the wildcard query fails.
3728 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3729 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3731 DEBUG(99, ("Could not retrieve name status for %s\n",
3736 if (!find_master_ip(name, &server_ss)) {
3737 DEBUG(99, ("Could not find master ip for %s\n", name));
3741 *pp_workgroup_out = talloc_strdup(ctx, name);
3743 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3745 print_sockaddr(addr, sizeof(addr), &server_ss);
3746 cli = get_ipc_connect(addr, &server_ss, user_info);
3752 * Return the IP address and workgroup of a master browser on the network, and
3756 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3757 const struct user_auth_info *user_info,
3758 char **pp_workgroup_out)
3760 struct sockaddr_storage *ip_list;
3761 struct cli_state *cli;
3765 *pp_workgroup_out = NULL;
3767 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3769 /* Go looking for workgroups by broadcasting on the local network */
3771 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3773 if (!NT_STATUS_IS_OK(status)) {
3774 DEBUG(99, ("No master browsers responded: %s\n",
3775 nt_errstr(status)));
3779 for (i = 0; i < count; i++) {
3780 char addr[INET6_ADDRSTRLEN];
3781 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3782 DEBUG(99, ("Found master browser %s\n", addr));
3784 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3785 user_info, pp_workgroup_out);