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"
40 #include "lib/param/param.h"
42 #define STAR_SMBSERVER "*SMBSERVER"
44 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
45 const char *principal);
47 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
53 bool fallback_after_kerberos,
55 bool password_is_nt_hash)
57 struct loadparm_context *lp_ctx = NULL;
58 struct cli_credentials *creds = NULL;
59 const char *principal = NULL;
64 creds = cli_credentials_init(mem_ctx);
69 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
73 cli_credentials_set_conf(creds, lp_ctx);
79 if (username == NULL) {
83 if (strlen(username) == 0) {
84 if (password != NULL && strlen(password) == 0) {
86 * some callers pass "" as no password
88 * gensec only handles NULL as no password.
92 if (password == NULL) {
93 cli_credentials_set_anonymous(creds);
98 tmp = talloc_strdup(creds, username);
104 /* allow for workgroups as part of the username */
105 if ((p = strchr_m(tmp, '\\')) ||
106 (p = strchr_m(tmp, '/')) ||
107 (p = strchr_m(tmp, *lp_winbind_separator()))) {
113 principal = username;
114 username = cli_session_setup_get_account(creds, principal);
115 if (username == NULL) {
118 ok = strequal(username, principal);
121 * Ok still the same, so it's not a principal
126 if (use_kerberos && fallback_after_kerberos) {
127 cli_credentials_set_kerberos_state(creds,
128 CRED_AUTO_USE_KERBEROS);
129 } else if (use_kerberos) {
130 cli_credentials_set_kerberos_state(creds,
131 CRED_MUST_USE_KERBEROS);
133 cli_credentials_set_kerberos_state(creds,
134 CRED_DONT_USE_KERBEROS);
140 features = cli_credentials_get_gensec_features(creds);
141 features |= GENSEC_FEATURE_NTLM_CCACHE;
142 cli_credentials_set_gensec_features(creds, features);
144 if (password != NULL && strlen(password) == 0) {
146 * some callers pass "" as no password
148 * GENSEC_FEATURE_NTLM_CCACHE only handles
149 * NULL as no password.
155 ok = cli_credentials_set_username(creds,
162 ok = cli_credentials_set_domain(creds,
169 if (principal != NULL) {
170 ok = cli_credentials_set_principal(creds,
179 ok = cli_credentials_set_realm(creds,
187 if (password != NULL && strlen(password) > 0) {
188 if (password_is_nt_hash) {
189 struct samr_Password nt_hash;
192 converted = strhex_to_str((char *)nt_hash.hash,
193 sizeof(nt_hash.hash),
196 if (converted != sizeof(nt_hash.hash)) {
200 ok = cli_credentials_set_nt_hash(creds,
207 ok = cli_credentials_set_password(creds,
222 /********************************************************
223 Utility function to ensure we always return at least
224 a valid char * pointer to an empty string for the
225 cli->server_os, cli->server_type and cli->server_domain
227 *******************************************************/
229 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
236 *destlen = clistr_pull_talloc(mem_ctx,
243 if (*destlen == -1) {
244 return NT_STATUS_NO_MEMORY;
248 *dest = talloc_strdup(mem_ctx, "");
250 return NT_STATUS_NO_MEMORY;
256 /****************************************************************************
257 Work out suitable capabilities to offer the server.
258 ****************************************************************************/
260 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
261 uint32_t sesssetup_capabilities)
263 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
266 * We only send capabilities based on the mask for:
267 * - client only flags
268 * - flags used in both directions
270 * We do not echo the server only flags, except some legacy flags.
272 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
273 * CAP_LARGE_WRITEX in order to allow us to do large reads
274 * against old Samba releases (<= 3.6.x).
276 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
279 * Session Setup specific flags CAP_DYNAMIC_REAUTH
280 * and CAP_EXTENDED_SECURITY are passed by the caller.
281 * We need that in order to do guest logins even if
282 * CAP_EXTENDED_SECURITY is negotiated.
284 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
285 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
286 client_capabilities |= sesssetup_capabilities;
288 return client_capabilities;
291 /****************************************************************************
292 Do a NT1 guest session setup.
293 ****************************************************************************/
295 struct cli_session_setup_guest_state {
296 struct cli_state *cli;
301 static void cli_session_setup_guest_done(struct tevent_req *subreq);
303 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
304 struct tevent_context *ev,
305 struct cli_state *cli,
306 struct tevent_req **psmbreq)
308 struct tevent_req *req, *subreq;
309 struct cli_session_setup_guest_state *state;
313 req = tevent_req_create(mem_ctx, &state,
314 struct cli_session_setup_guest_state);
321 SCVAL(vwv+0, 0, 0xFF);
324 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
326 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
327 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
332 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
334 bytes = talloc_array(state, uint8_t, 0);
336 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
338 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
340 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
341 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
348 state->bytes.iov_base = (void *)bytes;
349 state->bytes.iov_len = talloc_get_size(bytes);
351 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
352 vwv, 1, &state->bytes);
353 if (subreq == NULL) {
357 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
362 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
363 struct tevent_context *ev,
364 struct cli_state *cli)
366 struct tevent_req *req, *subreq;
369 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
374 status = smb1cli_req_chain_submit(&subreq, 1);
375 if (!NT_STATUS_IS_OK(status)) {
376 tevent_req_nterror(req, status);
377 return tevent_req_post(req, ev);
382 static void cli_session_setup_guest_done(struct tevent_req *subreq)
384 struct tevent_req *req = tevent_req_callback_data(
385 subreq, struct tevent_req);
386 struct cli_session_setup_guest_state *state = tevent_req_data(
387 req, struct cli_session_setup_guest_state);
388 struct cli_state *cli = state->cli;
399 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
402 if (!NT_STATUS_IS_OK(status)) {
403 tevent_req_nterror(req, status);
407 inhdr = in + NBT_HDR_SIZE;
410 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
411 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
413 status = smb_bytes_talloc_string(cli,
420 if (!NT_STATUS_IS_OK(status)) {
421 tevent_req_nterror(req, status);
426 status = smb_bytes_talloc_string(cli,
433 if (!NT_STATUS_IS_OK(status)) {
434 tevent_req_nterror(req, status);
439 status = smb_bytes_talloc_string(cli,
446 if (!NT_STATUS_IS_OK(status)) {
447 tevent_req_nterror(req, status);
452 tevent_req_done(req);
455 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
457 return tevent_req_simple_recv_ntstatus(req);
460 /* The following is calculated from :
462 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
463 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
467 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
469 struct cli_sesssetup_blob_state {
470 struct tevent_context *ev;
471 struct cli_state *cli;
473 uint16_t max_blob_size;
476 struct iovec *recv_iov;
479 const uint8_t *inbuf;
486 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
487 struct tevent_req **psubreq);
488 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
490 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
491 struct tevent_context *ev,
492 struct cli_state *cli,
495 struct tevent_req *req, *subreq;
496 struct cli_sesssetup_blob_state *state;
497 uint32_t usable_space;
499 req = tevent_req_create(mem_ctx, &state,
500 struct cli_sesssetup_blob_state);
508 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
509 usable_space = UINT16_MAX;
511 usable_space = cli_state_available_size(cli,
512 BASE_SESSSETUP_BLOB_PACKET_SIZE);
515 if (usable_space == 0) {
516 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
517 "(not possible to send %u bytes)\n",
518 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
519 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
520 return tevent_req_post(req, ev);
522 state->max_blob_size = MIN(usable_space, 0xFFFF);
524 if (!cli_sesssetup_blob_next(state, &subreq)) {
525 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
526 return tevent_req_post(req, ev);
528 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
532 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
533 struct tevent_req **psubreq)
535 struct tevent_req *subreq;
538 thistime = MIN(state->blob.length, state->max_blob_size);
540 state->this_blob.data = state->blob.data;
541 state->this_blob.length = thistime;
543 state->blob.data += thistime;
544 state->blob.length -= thistime;
546 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
547 subreq = smb2cli_session_setup_send(state, state->ev,
550 state->cli->smb2.session,
552 SMB2_CAP_DFS, /* in_capabilities */
554 0, /* in_previous_session_id */
556 if (subreq == NULL) {
560 uint16_t in_buf_size = 0;
561 uint16_t in_mpx_max = 0;
562 uint16_t in_vc_num = 0;
563 uint32_t in_sess_key = 0;
564 uint32_t in_capabilities = 0;
565 const char *in_native_os = NULL;
566 const char *in_native_lm = NULL;
568 in_buf_size = CLI_BUFFER_SIZE;
569 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
570 in_vc_num = cli_state_get_vc_num(state->cli);
571 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
572 in_capabilities = cli_session_setup_capabilities(state->cli,
573 CAP_EXTENDED_SECURITY);
574 in_native_os = "Unix";
575 in_native_lm = "Samba";
578 * For now we keep the same values as before,
579 * we may remove these in a separate commit later.
585 subreq = smb1cli_session_setup_ext_send(state, state->ev,
588 state->cli->smb1.pid,
589 state->cli->smb1.session,
598 if (subreq == NULL) {
606 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
608 struct tevent_req *req = tevent_req_callback_data(
609 subreq, struct tevent_req);
610 struct cli_sesssetup_blob_state *state = tevent_req_data(
611 req, struct cli_sesssetup_blob_state);
612 struct cli_state *cli = state->cli;
615 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
616 status = smb2cli_session_setup_recv(subreq, state,
620 status = smb1cli_session_setup_ext_recv(subreq, state,
624 &state->out_native_os,
625 &state->out_native_lm);
628 if (!NT_STATUS_IS_OK(status)
629 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
630 tevent_req_nterror(req, status);
634 if (cli->server_os == NULL) {
635 cli->server_os = talloc_move(cli, &state->out_native_os);
637 if (cli->server_type == NULL) {
638 cli->server_type = talloc_move(cli, &state->out_native_lm);
641 state->status = status;
643 if (state->blob.length != 0) {
647 if (!cli_sesssetup_blob_next(state, &subreq)) {
651 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
654 tevent_req_done(req);
657 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
660 const uint8_t **pinbuf,
661 struct iovec **precv_iov)
663 struct cli_sesssetup_blob_state *state = tevent_req_data(
664 req, struct cli_sesssetup_blob_state);
666 struct iovec *recv_iov;
668 if (tevent_req_is_nterror(req, &status)) {
669 TALLOC_FREE(state->cli->smb2.session);
670 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
671 tevent_req_received(req);
675 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
677 *pblob = state->ret_blob;
679 if (pinbuf != NULL) {
680 *pinbuf = state->inbuf;
682 if (precv_iov != NULL) {
683 *precv_iov = recv_iov;
685 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
686 status = state->status;
687 tevent_req_received(req);
691 /****************************************************************************
692 Use in-memory credentials cache
693 ****************************************************************************/
695 static void use_in_memory_ccache(void) {
696 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
699 /****************************************************************************
700 Do a spnego/NTLMSSP encrypted session setup.
701 ****************************************************************************/
703 struct cli_session_setup_gensec_state {
704 struct tevent_context *ev;
705 struct cli_state *cli;
706 struct auth_generic_state *auth_generic;
709 const uint8_t *inbuf;
710 struct iovec *recv_iov;
714 DATA_BLOB session_key;
717 static int cli_session_setup_gensec_state_destructor(
718 struct cli_session_setup_gensec_state *state)
720 TALLOC_FREE(state->auth_generic);
721 data_blob_clear_free(&state->session_key);
725 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
726 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
727 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
728 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
729 static void cli_session_setup_gensec_ready(struct tevent_req *req);
731 static struct tevent_req *cli_session_setup_gensec_send(
732 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
733 struct cli_credentials *creds,
734 const char *target_service,
735 const char *target_hostname)
737 struct tevent_req *req;
738 struct cli_session_setup_gensec_state *state;
740 const DATA_BLOB *b = NULL;
742 req = tevent_req_create(mem_ctx, &state,
743 struct cli_session_setup_gensec_state);
750 talloc_set_destructor(
751 state, cli_session_setup_gensec_state_destructor);
753 status = auth_generic_client_prepare(state, &state->auth_generic);
754 if (tevent_req_nterror(req, status)) {
755 return tevent_req_post(req, ev);
758 status = auth_generic_set_creds(state->auth_generic, creds);
759 if (tevent_req_nterror(req, status)) {
760 return tevent_req_post(req, ev);
763 gensec_want_feature(state->auth_generic->gensec_security,
764 GENSEC_FEATURE_SESSION_KEY);
766 if (target_service != NULL) {
767 status = gensec_set_target_service(
768 state->auth_generic->gensec_security,
770 if (tevent_req_nterror(req, status)) {
771 return tevent_req_post(req, ev);
775 if (target_hostname != NULL) {
776 status = gensec_set_target_hostname(
777 state->auth_generic->gensec_security,
779 if (tevent_req_nterror(req, status)) {
780 return tevent_req_post(req, ev);
784 b = smbXcli_conn_server_gss_blob(cli->conn);
789 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
791 status = auth_generic_client_start(state->auth_generic,
793 if (tevent_req_nterror(req, status)) {
794 return tevent_req_post(req, ev);
797 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
798 state->cli->smb2.session = smbXcli_session_create(cli,
800 if (tevent_req_nomem(state->cli->smb2.session, req)) {
801 return tevent_req_post(req, ev);
805 cli_session_setup_gensec_local_next(req);
806 if (!tevent_req_is_in_progress(req)) {
807 return tevent_req_post(req, ev);
813 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
815 struct cli_session_setup_gensec_state *state =
817 struct cli_session_setup_gensec_state);
818 struct tevent_req *subreq = NULL;
820 if (state->local_ready) {
821 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
825 subreq = gensec_update_send(state, state->ev,
826 state->auth_generic->gensec_security,
828 if (tevent_req_nomem(subreq, req)) {
831 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
834 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
836 struct tevent_req *req =
837 tevent_req_callback_data(subreq,
839 struct cli_session_setup_gensec_state *state =
841 struct cli_session_setup_gensec_state);
844 status = gensec_update_recv(subreq, state, &state->blob_out);
846 state->blob_in = data_blob_null;
847 if (!NT_STATUS_IS_OK(status) &&
848 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
850 tevent_req_nterror(req, status);
854 if (NT_STATUS_IS_OK(status)) {
855 state->local_ready = true;
858 if (state->local_ready && state->remote_ready) {
859 cli_session_setup_gensec_ready(req);
863 cli_session_setup_gensec_remote_next(req);
866 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
868 struct cli_session_setup_gensec_state *state =
870 struct cli_session_setup_gensec_state);
871 struct tevent_req *subreq = NULL;
873 if (state->remote_ready) {
874 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
878 subreq = cli_sesssetup_blob_send(state, state->ev,
879 state->cli, state->blob_out);
880 if (tevent_req_nomem(subreq, req)) {
883 tevent_req_set_callback(subreq,
884 cli_session_setup_gensec_remote_done,
888 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
890 struct tevent_req *req =
891 tevent_req_callback_data(subreq,
893 struct cli_session_setup_gensec_state *state =
895 struct cli_session_setup_gensec_state);
899 TALLOC_FREE(state->recv_iov);
901 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
902 &state->inbuf, &state->recv_iov);
904 data_blob_free(&state->blob_out);
905 if (!NT_STATUS_IS_OK(status) &&
906 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
908 tevent_req_nterror(req, status);
912 if (NT_STATUS_IS_OK(status)) {
913 struct smbXcli_session *session = NULL;
914 bool is_guest = false;
916 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
917 session = state->cli->smb2.session;
919 session = state->cli->smb1.session;
922 is_guest = smbXcli_session_is_guest(session);
925 * We can't finish the gensec handshake, we don't
926 * have a negotiated session key.
928 * So just pretend we are completely done.
930 * Note that smbXcli_session_is_guest()
931 * always returns false if we require signing.
933 state->blob_in = data_blob_null;
934 state->local_ready = true;
937 state->remote_ready = true;
940 if (state->local_ready && state->remote_ready) {
941 cli_session_setup_gensec_ready(req);
945 cli_session_setup_gensec_local_next(req);
948 static void cli_session_setup_gensec_ready(struct tevent_req *req)
950 struct cli_session_setup_gensec_state *state =
952 struct cli_session_setup_gensec_state);
953 const char *server_domain = NULL;
956 if (state->blob_in.length != 0) {
957 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
961 if (state->blob_out.length != 0) {
962 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
967 * gensec_ntlmssp_server_domain() returns NULL
968 * if NTLMSSP is not used.
970 * We can remove this later
971 * and leave the server domain empty for SMB2 and above
972 * in future releases.
974 server_domain = gensec_ntlmssp_server_domain(
975 state->auth_generic->gensec_security);
977 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
978 TALLOC_FREE(state->cli->server_domain);
979 state->cli->server_domain = talloc_strdup(state->cli,
981 if (state->cli->server_domain == NULL) {
982 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
987 if (state->is_anonymous) {
989 * Windows server does not set the
990 * SMB2_SESSION_FLAG_IS_NULL flag.
992 * This fix makes sure we do not try
993 * to verify a signature on the final
994 * session setup response.
996 tevent_req_done(req);
1000 status = gensec_session_key(state->auth_generic->gensec_security,
1001 state, &state->session_key);
1002 if (tevent_req_nterror(req, status)) {
1006 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1007 struct smbXcli_session *session = state->cli->smb2.session;
1009 status = smb2cli_session_set_session_key(session,
1012 if (tevent_req_nterror(req, status)) {
1016 struct smbXcli_session *session = state->cli->smb1.session;
1019 status = smb1cli_session_set_session_key(session,
1020 state->session_key);
1021 if (tevent_req_nterror(req, status)) {
1025 active = smb1cli_conn_activate_signing(state->cli->conn,
1031 ok = smb1cli_conn_check_signing(state->cli->conn,
1034 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1040 tevent_req_done(req);
1043 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1045 struct cli_session_setup_gensec_state *state =
1046 tevent_req_data(req,
1047 struct cli_session_setup_gensec_state);
1050 if (tevent_req_is_nterror(req, &status)) {
1051 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1054 return NT_STATUS_OK;
1057 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1058 const char *principal)
1062 account = talloc_strdup(mem_ctx, principal);
1063 if (account == NULL) {
1066 p = strchr_m(account, '@');
1073 /****************************************************************************
1074 Do a spnego encrypted session setup.
1076 user_domain: The shortname of the domain the user/machine is a member of.
1077 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1078 ****************************************************************************/
1080 struct cli_session_setup_spnego_state {
1084 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1086 static struct tevent_req *cli_session_setup_spnego_send(
1087 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1088 struct cli_credentials *creds)
1090 struct tevent_req *req, *subreq;
1091 struct cli_session_setup_spnego_state *state;
1092 const char *user_principal = NULL;
1093 const char *user_account = NULL;
1094 const char *user_domain = NULL;
1095 const char *pass = NULL;
1096 const char *target_hostname = NULL;
1097 const DATA_BLOB *server_blob = NULL;
1098 enum credentials_use_kerberos krb5_state;
1099 bool try_kerberos = false;
1100 bool need_kinit = false;
1101 bool auth_requested = true;
1103 req = tevent_req_create(mem_ctx, &state,
1104 struct cli_session_setup_spnego_state);
1109 target_hostname = smbXcli_conn_remote_name(cli->conn);
1110 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1112 /* the server might not even do spnego */
1113 if (server_blob != NULL && server_blob->length != 0) {
1114 char *principal = NULL;
1115 char *OIDs[ASN1_MAX_OIDS];
1118 /* The server sent us the first part of the SPNEGO exchange in the
1119 * negprot reply. It is WRONG to depend on the principal sent in the
1120 * negprot reply, but right now we do it. If we don't receive one,
1121 * we try to best guess, then fall back to NTLM. */
1122 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1123 &principal, NULL) ||
1125 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1126 tevent_req_done(req);
1127 return tevent_req_post(req, ev);
1129 TALLOC_FREE(principal);
1131 /* make sure the server understands kerberos */
1132 for (i = 0; OIDs[i] != NULL; i++) {
1134 DEBUG(3,("got OID=%s\n", OIDs[i]));
1136 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1139 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1140 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1141 cli->got_kerberos_mechanism = True;
1143 talloc_free(OIDs[i]);
1147 auth_requested = cli_credentials_authentication_requested(creds);
1148 if (auth_requested) {
1149 user_principal = cli_credentials_get_principal(creds, state);
1150 if (tevent_req_nomem(user_principal, req)) {
1151 return tevent_req_post(req, ev);
1154 user_account = cli_credentials_get_username(creds);
1155 user_domain = cli_credentials_get_domain(creds);
1156 pass = cli_credentials_get_password(creds);
1158 krb5_state = cli_credentials_get_kerberos_state(creds);
1160 if (krb5_state != CRED_DONT_USE_KERBEROS) {
1161 try_kerberos = true;
1164 if (target_hostname == NULL) {
1165 try_kerberos = false;
1166 } else if (is_ipaddress(target_hostname)) {
1167 try_kerberos = false;
1168 } else if (strequal(target_hostname, "localhost")) {
1169 try_kerberos = false;
1170 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
1171 try_kerberos = false;
1172 } else if (!auth_requested) {
1173 try_kerberos = false;
1176 if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
1177 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
1178 "'%s' not possible\n",
1179 user_principal, user_domain, user_account,
1181 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1182 return tevent_req_post(req, ev);
1185 if (pass == NULL || strlen(pass) == 0) {
1187 } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
1188 need_kinit = try_kerberos;
1189 } else if (!cli->got_kerberos_mechanism) {
1191 * Most likely the server doesn't support
1192 * Kerberos, don't waste time doing a kinit
1196 need_kinit = try_kerberos;
1202 use_in_memory_ccache();
1203 ret = kerberos_kinit_password(user_principal, pass,
1204 0 /* no time correction for now */,
1208 DEBUG(0, ("Kinit for %s to access %s failed: %s\n",
1209 user_principal, target_hostname,
1210 error_message(ret)));
1211 if (krb5_state == CRED_MUST_USE_KERBEROS) {
1212 state->result = ADS_ERROR_KRB5(ret);
1213 tevent_req_done(req);
1214 return tevent_req_post(req, ev);
1218 * Ignore the error and hope that NTLM will work
1224 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1225 "cifs", target_hostname);
1226 if (tevent_req_nomem(subreq, req)) {
1227 return tevent_req_post(req, ev);
1229 tevent_req_set_callback(
1230 subreq, cli_session_setup_spnego_done, req);
1234 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1236 struct tevent_req *req = tevent_req_callback_data(
1237 subreq, struct tevent_req);
1240 status = cli_session_setup_gensec_recv(subreq);
1241 TALLOC_FREE(subreq);
1242 if (tevent_req_nterror(req, status)) {
1246 tevent_req_done(req);
1249 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1251 struct cli_session_setup_spnego_state *state = tevent_req_data(
1252 req, struct cli_session_setup_spnego_state);
1255 if (tevent_req_is_nterror(req, &status)) {
1256 state->result = ADS_ERROR_NT(status);
1259 return state->result;
1262 struct cli_session_setup_creds_state {
1263 struct cli_state *cli;
1264 DATA_BLOB apassword_blob;
1265 DATA_BLOB upassword_blob;
1266 DATA_BLOB lm_session_key;
1267 DATA_BLOB session_key;
1268 char *out_native_os;
1269 char *out_native_lm;
1270 char *out_primary_domain;
1273 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1274 enum tevent_req_state req_state)
1276 struct cli_session_setup_creds_state *state = tevent_req_data(
1277 req, struct cli_session_setup_creds_state);
1279 if (req_state != TEVENT_REQ_RECEIVED) {
1284 * We only call data_blob_clear() as
1285 * some of the blobs point to the same memory.
1287 * We let the talloc hierachy free the memory.
1289 data_blob_clear(&state->apassword_blob);
1290 data_blob_clear(&state->upassword_blob);
1291 data_blob_clear(&state->lm_session_key);
1292 data_blob_clear(&state->session_key);
1293 ZERO_STRUCTP(state);
1296 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1297 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1298 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1300 /****************************************************************************
1301 Send a session setup. The username and workgroup is in UNIX character
1302 format and must be converted to DOS codepage format before sending. If the
1303 password is in plaintext, the same should be done.
1304 ****************************************************************************/
1306 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1307 struct tevent_context *ev,
1308 struct cli_state *cli,
1309 struct cli_credentials *creds)
1311 struct tevent_req *req, *subreq;
1312 struct cli_session_setup_creds_state *state;
1313 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1314 bool use_spnego = false;
1316 enum credentials_use_kerberos krb5_state;
1317 uint32_t gensec_features;
1318 const char *username = "";
1319 const char *domain = "";
1320 DATA_BLOB target_info = data_blob_null;
1321 DATA_BLOB challenge = data_blob_null;
1322 uint16_t in_buf_size = 0;
1323 uint16_t in_mpx_max = 0;
1324 uint16_t in_vc_num = 0;
1325 uint32_t in_sess_key = 0;
1326 const char *in_native_os = NULL;
1327 const char *in_native_lm = NULL;
1330 req = tevent_req_create(mem_ctx, &state,
1331 struct cli_session_setup_creds_state);
1337 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1339 krb5_state = cli_credentials_get_kerberos_state(creds);
1340 gensec_features = cli_credentials_get_gensec_features(creds);
1342 switch (krb5_state) {
1343 case CRED_MUST_USE_KERBEROS:
1344 cli->use_kerberos = true;
1345 cli->fallback_after_kerberos = false;
1347 case CRED_AUTO_USE_KERBEROS:
1348 cli->use_kerberos = true;
1349 cli->fallback_after_kerberos = true;
1351 case CRED_DONT_USE_KERBEROS:
1352 cli->use_kerberos = false;
1353 cli->fallback_after_kerberos = false;
1357 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1358 cli->use_ccache = true;
1360 cli->use_ccache = false;
1364 * Now work out what sort of session setup we are going to
1365 * do. I have split this into separate functions to make the flow a bit
1366 * easier to understand (tridge).
1368 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1370 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1372 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1374 * if the server supports extended security then use SPNEGO
1375 * even for anonymous connections.
1383 subreq = cli_session_setup_spnego_send(
1384 state, ev, cli, creds);
1385 if (tevent_req_nomem(subreq, req)) {
1386 return tevent_req_post(req, ev);
1388 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1393 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1395 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1396 * this step against older servers.
1398 tevent_req_done(req);
1399 return tevent_req_post(req, ev);
1402 if (cli_credentials_is_anonymous(creds)) {
1404 * Do an anonymous session setup
1406 goto non_spnego_creds_done;
1409 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1411 * Do an anonymous session setup,
1412 * the password is passed via the tree connect.
1414 goto non_spnego_creds_done;
1417 cli_credentials_get_ntlm_username_domain(creds, state,
1420 if (tevent_req_nomem(username, req)) {
1421 return tevent_req_post(req, ev);
1423 if (tevent_req_nomem(domain, req)) {
1424 return tevent_req_post(req, ev);
1427 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1428 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1429 uint8_t *bytes = NULL;
1430 size_t bytes_len = 0;
1431 const char *pw = cli_credentials_get_password(creds);
1437 pw_len = strlen(pw) + 1;
1439 if (!lp_client_plaintext_auth()) {
1440 DEBUG(1, ("Server requested PLAINTEXT password but "
1441 "'client plaintext auth = no'\n"));
1442 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1443 return tevent_req_post(req, ev);
1446 bytes = talloc_array(state, uint8_t, 0);
1447 bytes = trans2_bytes_push_str(bytes, use_unicode,
1448 pw, pw_len, &bytes_len);
1449 if (tevent_req_nomem(bytes, req)) {
1450 return tevent_req_post(req, ev);
1455 * CAP_UNICODE, can only be negotiated by NT1.
1457 state->upassword_blob = data_blob_const(bytes,
1460 state->apassword_blob = data_blob_const(bytes,
1464 goto non_spnego_creds_done;
1467 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1469 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1470 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1472 * Don't send an NTLMv2 response without NTLMSSP if we
1473 * want to use spnego support.
1475 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1476 " but 'client use spnego = yes'"
1477 " and 'client ntlmv2 auth = yes' is set\n"));
1478 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1479 return tevent_req_post(req, ev);
1482 if (lp_client_ntlmv2_auth()) {
1483 flags |= CLI_CRED_NTLMv2_AUTH;
1486 * note that the 'domain' here is a best
1487 * guess - we don't know the server's domain
1488 * at this point. Windows clients also don't
1491 target_info = NTLMv2_generate_names_blob(state,
1494 if (tevent_req_nomem(target_info.data, req)) {
1495 return tevent_req_post(req, ev);
1498 flags |= CLI_CRED_NTLM_AUTH;
1499 if (lp_client_lanman_auth()) {
1500 flags |= CLI_CRED_LANMAN_AUTH;
1504 if (!lp_client_lanman_auth()) {
1505 DEBUG(1, ("Server requested user level LM password but "
1506 "'client lanman auth = no' is set.\n"));
1507 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1508 return tevent_req_post(req, ev);
1511 flags |= CLI_CRED_LANMAN_AUTH;
1514 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1517 &state->apassword_blob,
1518 &state->upassword_blob,
1519 &state->lm_session_key,
1520 &state->session_key);
1521 if (tevent_req_nterror(req, status)) {
1522 return tevent_req_post(req, ev);
1525 non_spnego_creds_done:
1527 in_buf_size = CLI_BUFFER_SIZE;
1528 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1529 in_vc_num = cli_state_get_vc_num(cli);
1530 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1531 in_native_os = "Unix";
1532 in_native_lm = "Samba";
1534 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1535 uint32_t in_capabilities = 0;
1537 in_capabilities = cli_session_setup_capabilities(cli, 0);
1540 * For now we keep the same values as before,
1541 * we may remove these in a separate commit later.
1545 subreq = smb1cli_session_setup_nt1_send(state, ev,
1556 state->apassword_blob,
1557 state->upassword_blob,
1561 if (tevent_req_nomem(subreq, req)) {
1562 return tevent_req_post(req, ev);
1564 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1570 * For now we keep the same values as before,
1571 * we may remove these in a separate commit later.
1576 subreq = smb1cli_session_setup_lm21_send(state, ev,
1587 state->apassword_blob,
1590 if (tevent_req_nomem(subreq, req)) {
1591 return tevent_req_post(req, ev);
1593 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1598 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1600 struct tevent_req *req = tevent_req_callback_data(
1601 subreq, struct tevent_req);
1604 status = cli_session_setup_spnego_recv(subreq);
1605 TALLOC_FREE(subreq);
1606 if (!ADS_ERR_OK(status)) {
1607 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1608 tevent_req_nterror(req, ads_ntstatus(status));
1611 tevent_req_done(req);
1614 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1616 struct tevent_req *req = tevent_req_callback_data(
1617 subreq, struct tevent_req);
1618 struct cli_session_setup_creds_state *state = tevent_req_data(
1619 req, struct cli_session_setup_creds_state);
1620 struct cli_state *cli = state->cli;
1622 struct iovec *recv_iov = NULL;
1623 const uint8_t *inbuf = NULL;
1626 status = smb1cli_session_setup_nt1_recv(subreq, state,
1629 &state->out_native_os,
1630 &state->out_native_lm,
1631 &state->out_primary_domain);
1632 TALLOC_FREE(subreq);
1633 if (!NT_STATUS_IS_OK(status)) {
1634 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1635 tevent_req_nterror(req, status);
1639 if (cli->server_os == NULL) {
1640 cli->server_os = talloc_move(cli, &state->out_native_os);
1642 if (cli->server_type == NULL) {
1643 cli->server_type = talloc_move(cli, &state->out_native_lm);
1645 if (cli->server_domain == NULL) {
1646 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1649 ok = smb1cli_conn_activate_signing(cli->conn,
1651 state->upassword_blob);
1653 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1655 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1660 if (state->session_key.data) {
1661 struct smbXcli_session *session = cli->smb1.session;
1663 status = smb1cli_session_set_session_key(session,
1664 state->session_key);
1665 if (tevent_req_nterror(req, status)) {
1670 tevent_req_done(req);
1673 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1675 struct tevent_req *req = tevent_req_callback_data(
1676 subreq, struct tevent_req);
1677 struct cli_session_setup_creds_state *state = tevent_req_data(
1678 req, struct cli_session_setup_creds_state);
1679 struct cli_state *cli = state->cli;
1682 status = smb1cli_session_setup_lm21_recv(subreq, state,
1683 &state->out_native_os,
1684 &state->out_native_lm);
1685 TALLOC_FREE(subreq);
1686 if (!NT_STATUS_IS_OK(status)) {
1687 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1688 tevent_req_nterror(req, status);
1692 if (cli->server_os == NULL) {
1693 cli->server_os = talloc_move(cli, &state->out_native_os);
1695 if (cli->server_type == NULL) {
1696 cli->server_type = talloc_move(cli, &state->out_native_lm);
1699 tevent_req_done(req);
1702 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1704 return tevent_req_simple_recv_ntstatus(req);
1707 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1708 struct cli_credentials *creds)
1710 struct tevent_context *ev;
1711 struct tevent_req *req;
1712 NTSTATUS status = NT_STATUS_NO_MEMORY;
1714 if (smbXcli_conn_has_async_calls(cli->conn)) {
1715 return NT_STATUS_INVALID_PARAMETER;
1717 ev = samba_tevent_context_init(talloc_tos());
1721 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1725 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1728 status = cli_session_setup_creds_recv(req);
1734 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1736 NTSTATUS status = NT_STATUS_NO_MEMORY;
1737 struct cli_credentials *creds = NULL;
1739 creds = cli_credentials_init_anon(cli);
1740 if (creds == NULL) {
1741 return NT_STATUS_NO_MEMORY;
1744 status = cli_session_setup_creds(cli, creds);
1746 if (!NT_STATUS_IS_OK(status)) {
1750 return NT_STATUS_OK;
1753 NTSTATUS cli_session_setup(struct cli_state *cli,
1756 const char *workgroup)
1758 NTSTATUS status = NT_STATUS_NO_MEMORY;
1759 const char *dest_realm = NULL;
1760 struct cli_credentials *creds = NULL;
1763 * dest_realm is only valid in the winbindd use case,
1764 * where we also have the account in that realm.
1766 dest_realm = cli_state_remote_realm(cli);
1768 creds = cli_session_creds_init(cli,
1774 cli->fallback_after_kerberos,
1777 if (creds == NULL) {
1778 return NT_STATUS_NO_MEMORY;
1781 status = cli_session_setup_creds(cli, creds);
1783 if (!NT_STATUS_IS_OK(status)) {
1787 return NT_STATUS_OK;
1790 /****************************************************************************
1792 *****************************************************************************/
1794 struct cli_ulogoff_state {
1795 struct cli_state *cli;
1799 static void cli_ulogoff_done(struct tevent_req *subreq);
1801 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1802 struct tevent_context *ev,
1803 struct cli_state *cli)
1805 struct tevent_req *req, *subreq;
1806 struct cli_ulogoff_state *state;
1808 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1814 SCVAL(state->vwv+0, 0, 0xFF);
1815 SCVAL(state->vwv+1, 0, 0);
1816 SSVAL(state->vwv+2, 0, 0);
1818 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1820 if (tevent_req_nomem(subreq, req)) {
1821 return tevent_req_post(req, ev);
1823 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1827 static void cli_ulogoff_done(struct tevent_req *subreq)
1829 struct tevent_req *req = tevent_req_callback_data(
1830 subreq, struct tevent_req);
1831 struct cli_ulogoff_state *state = tevent_req_data(
1832 req, struct cli_ulogoff_state);
1835 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1836 if (!NT_STATUS_IS_OK(status)) {
1837 tevent_req_nterror(req, status);
1840 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1841 tevent_req_done(req);
1844 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1846 return tevent_req_simple_recv_ntstatus(req);
1849 NTSTATUS cli_ulogoff(struct cli_state *cli)
1851 struct tevent_context *ev;
1852 struct tevent_req *req;
1853 NTSTATUS status = NT_STATUS_NO_MEMORY;
1855 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1856 status = smb2cli_logoff(cli->conn,
1859 if (!NT_STATUS_IS_OK(status)) {
1862 smb2cli_session_set_id_and_flags(cli->smb2.session,
1864 return NT_STATUS_OK;
1867 if (smbXcli_conn_has_async_calls(cli->conn)) {
1868 return NT_STATUS_INVALID_PARAMETER;
1870 ev = samba_tevent_context_init(talloc_tos());
1874 req = cli_ulogoff_send(ev, ev, cli);
1878 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1881 status = cli_ulogoff_recv(req);
1887 /****************************************************************************
1889 ****************************************************************************/
1891 struct cli_tcon_andx_state {
1892 struct cli_state *cli;
1897 static void cli_tcon_andx_done(struct tevent_req *subreq);
1899 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1900 struct tevent_context *ev,
1901 struct cli_state *cli,
1902 const char *share, const char *dev,
1903 const char *pass, int passlen,
1904 struct tevent_req **psmbreq)
1906 struct tevent_req *req, *subreq;
1907 struct cli_tcon_andx_state *state;
1912 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1913 uint16_t tcon_flags = 0;
1917 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1924 cli->share = talloc_strdup(cli, share);
1929 /* in user level security don't send a password now */
1930 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1933 } else if (pass == NULL) {
1934 DEBUG(1, ("Server not using user level security and no "
1935 "password supplied.\n"));
1939 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1940 *pass && passlen != 24) {
1941 if (!lp_client_lanman_auth()) {
1942 DEBUG(1, ("Server requested LANMAN password "
1943 "(share-level security) but "
1944 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1949 * Non-encrypted passwords - convert to DOS codepage before
1952 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1954 pass = (const char *)p24;
1956 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1957 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1961 if (!lp_client_plaintext_auth() && (*pass)) {
1962 DEBUG(1, ("Server requested PLAINTEXT "
1964 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1969 * Non-encrypted passwords - convert to DOS codepage
1972 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1973 if (tevent_req_nomem(tmp_pass, req)) {
1974 return tevent_req_post(req, ev);
1976 tmp_pass = trans2_bytes_push_str(tmp_pass,
1977 false, /* always DOS */
1981 if (tevent_req_nomem(tmp_pass, req)) {
1982 return tevent_req_post(req, ev);
1984 pass = (const char *)tmp_pass;
1985 passlen = talloc_get_size(tmp_pass);
1989 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1990 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1992 SCVAL(vwv+0, 0, 0xFF);
1995 SSVAL(vwv+2, 0, tcon_flags);
1996 SSVAL(vwv+3, 0, passlen);
1998 if (passlen && pass) {
1999 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2001 bytes = talloc_array(state, uint8_t, 0);
2007 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2008 smbXcli_conn_remote_name(cli->conn), share);
2013 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2018 * Add the devicetype
2020 tmp = talloc_strdup_upper(talloc_tos(), dev);
2025 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2028 if (bytes == NULL) {
2033 state->bytes.iov_base = (void *)bytes;
2034 state->bytes.iov_len = talloc_get_size(bytes);
2036 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2038 if (subreq == NULL) {
2042 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2047 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2048 return tevent_req_post(req, ev);
2051 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2052 struct tevent_context *ev,
2053 struct cli_state *cli,
2054 const char *share, const char *dev,
2055 const char *pass, int passlen)
2057 struct tevent_req *req, *subreq;
2060 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2065 if (subreq == NULL) {
2068 status = smb1cli_req_chain_submit(&subreq, 1);
2069 if (!NT_STATUS_IS_OK(status)) {
2070 tevent_req_nterror(req, status);
2071 return tevent_req_post(req, ev);
2076 static void cli_tcon_andx_done(struct tevent_req *subreq)
2078 struct tevent_req *req = tevent_req_callback_data(
2079 subreq, struct tevent_req);
2080 struct cli_tcon_andx_state *state = tevent_req_data(
2081 req, struct cli_tcon_andx_state);
2082 struct cli_state *cli = state->cli;
2090 uint16_t optional_support = 0;
2092 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2093 &num_bytes, &bytes);
2094 TALLOC_FREE(subreq);
2095 if (!NT_STATUS_IS_OK(status)) {
2096 tevent_req_nterror(req, status);
2100 inhdr = in + NBT_HDR_SIZE;
2103 if (clistr_pull_talloc(cli,
2104 (const char *)inhdr,
2105 SVAL(inhdr, HDR_FLG2),
2109 STR_TERMINATE|STR_ASCII) == -1) {
2110 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2114 cli->dev = talloc_strdup(cli, "");
2115 if (cli->dev == NULL) {
2116 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2121 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2122 /* almost certainly win95 - enable bug fixes */
2127 * Make sure that we have the optional support 16-bit field. WCT > 2.
2128 * Avoids issues when connecting to Win9x boxes sharing files
2131 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2132 optional_support = SVAL(vwv+2, 0);
2135 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2136 smb1cli_session_protect_session_key(cli->smb1.session);
2139 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2140 SVAL(inhdr, HDR_TID),
2142 0, /* maximal_access */
2143 0, /* guest_maximal_access */
2145 NULL); /* fs_type */
2147 tevent_req_done(req);
2150 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2152 return tevent_req_simple_recv_ntstatus(req);
2155 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2156 const char *dev, const char *pass, int passlen)
2158 TALLOC_CTX *frame = talloc_stackframe();
2159 struct tevent_context *ev;
2160 struct tevent_req *req;
2161 NTSTATUS status = NT_STATUS_NO_MEMORY;
2163 if (smbXcli_conn_has_async_calls(cli->conn)) {
2165 * Can't use sync call while an async call is in flight
2167 status = NT_STATUS_INVALID_PARAMETER;
2171 ev = samba_tevent_context_init(frame);
2176 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2181 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2185 status = cli_tcon_andx_recv(req);
2191 struct cli_tree_connect_state {
2192 struct cli_state *cli;
2195 static struct tevent_req *cli_raw_tcon_send(
2196 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2197 const char *service, const char *pass, const char *dev);
2198 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2199 uint16_t *max_xmit, uint16_t *tid);
2201 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2202 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2203 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2205 static struct tevent_req *cli_tree_connect_send(
2206 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2207 const char *share, const char *dev, const char *pass, int passlen)
2209 struct tevent_req *req, *subreq;
2210 struct cli_tree_connect_state *state;
2212 req = tevent_req_create(mem_ctx, &state,
2213 struct cli_tree_connect_state);
2219 cli->share = talloc_strdup(cli, share);
2220 if (tevent_req_nomem(cli->share, req)) {
2221 return tevent_req_post(req, ev);
2224 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2227 cli->smb2.tcon = smbXcli_tcon_create(cli);
2228 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2229 return tevent_req_post(req, ev);
2232 unc = talloc_asprintf(state, "\\\\%s\\%s",
2233 smbXcli_conn_remote_name(cli->conn),
2235 if (tevent_req_nomem(unc, req)) {
2236 return tevent_req_post(req, ev);
2239 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2240 cli->smb2.session, cli->smb2.tcon,
2243 if (tevent_req_nomem(subreq, req)) {
2244 return tevent_req_post(req, ev);
2246 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2251 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2252 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2254 if (tevent_req_nomem(subreq, req)) {
2255 return tevent_req_post(req, ev);
2257 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2262 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2263 if (tevent_req_nomem(subreq, req)) {
2264 return tevent_req_post(req, ev);
2266 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2271 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2273 tevent_req_simple_finish_ntstatus(
2274 subreq, smb2cli_tcon_recv(subreq));
2277 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2279 tevent_req_simple_finish_ntstatus(
2280 subreq, cli_tcon_andx_recv(subreq));
2283 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2285 struct tevent_req *req = tevent_req_callback_data(
2286 subreq, struct tevent_req);
2287 struct cli_tree_connect_state *state = tevent_req_data(
2288 req, struct cli_tree_connect_state);
2290 uint16_t max_xmit = 0;
2293 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2294 if (tevent_req_nterror(req, status)) {
2298 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2300 0, /* optional_support */
2301 0, /* maximal_access */
2302 0, /* guest_maximal_access */
2304 NULL); /* fs_type */
2306 tevent_req_done(req);
2309 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2311 return tevent_req_simple_recv_ntstatus(req);
2314 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2315 const char *dev, const char *pass, int passlen)
2317 struct tevent_context *ev;
2318 struct tevent_req *req;
2319 NTSTATUS status = NT_STATUS_NO_MEMORY;
2321 if (smbXcli_conn_has_async_calls(cli->conn)) {
2322 return NT_STATUS_INVALID_PARAMETER;
2324 ev = samba_tevent_context_init(talloc_tos());
2328 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2332 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2335 status = cli_tree_connect_recv(req);
2341 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2342 const char *share, const char *dev,
2343 struct cli_credentials *creds)
2345 const char *pw = NULL;
2348 if (creds != NULL) {
2349 pw = cli_credentials_get_password(creds);
2355 pw_len = strlen(pw) + 1;
2357 return cli_tree_connect(cli, share, dev, pw, pw_len);
2360 /****************************************************************************
2361 Send a tree disconnect.
2362 ****************************************************************************/
2364 struct cli_tdis_state {
2365 struct cli_state *cli;
2368 static void cli_tdis_done(struct tevent_req *subreq);
2370 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2371 struct tevent_context *ev,
2372 struct cli_state *cli)
2374 struct tevent_req *req, *subreq;
2375 struct cli_tdis_state *state;
2377 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2383 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2384 if (tevent_req_nomem(subreq, req)) {
2385 return tevent_req_post(req, ev);
2387 tevent_req_set_callback(subreq, cli_tdis_done, req);
2391 static void cli_tdis_done(struct tevent_req *subreq)
2393 struct tevent_req *req = tevent_req_callback_data(
2394 subreq, struct tevent_req);
2395 struct cli_tdis_state *state = tevent_req_data(
2396 req, struct cli_tdis_state);
2399 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2400 TALLOC_FREE(subreq);
2401 if (!NT_STATUS_IS_OK(status)) {
2402 tevent_req_nterror(req, status);
2405 cli_state_set_tid(state->cli, UINT16_MAX);
2406 tevent_req_done(req);
2409 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2411 return tevent_req_simple_recv_ntstatus(req);
2414 NTSTATUS cli_tdis(struct cli_state *cli)
2416 struct tevent_context *ev;
2417 struct tevent_req *req;
2418 NTSTATUS status = NT_STATUS_NO_MEMORY;
2420 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2421 return smb2cli_tdis(cli->conn,
2427 if (smbXcli_conn_has_async_calls(cli->conn)) {
2428 return NT_STATUS_INVALID_PARAMETER;
2430 ev = samba_tevent_context_init(talloc_tos());
2434 req = cli_tdis_send(ev, ev, cli);
2438 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2441 status = cli_tdis_recv(req);
2447 struct cli_connect_sock_state {
2448 const char **called_names;
2449 const char **calling_names;
2455 static void cli_connect_sock_done(struct tevent_req *subreq);
2458 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2462 static struct tevent_req *cli_connect_sock_send(
2463 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2464 const char *host, int name_type, const struct sockaddr_storage *pss,
2465 const char *myname, uint16_t port)
2467 struct tevent_req *req, *subreq;
2468 struct cli_connect_sock_state *state;
2470 struct sockaddr_storage *addrs;
2471 unsigned i, num_addrs;
2474 req = tevent_req_create(mem_ctx, &state,
2475 struct cli_connect_sock_state);
2480 prog = getenv("LIBSMB_PROG");
2482 state->fd = sock_exec(prog);
2483 if (state->fd == -1) {
2484 status = map_nt_error_from_unix(errno);
2485 tevent_req_nterror(req, status);
2488 tevent_req_done(req);
2490 return tevent_req_post(req, ev);
2493 if ((pss == NULL) || is_zero_addr(pss)) {
2496 * Here we cheat. resolve_name_list is not async at all. So
2497 * this call will only be really async if the name lookup has
2498 * been done externally.
2501 status = resolve_name_list(state, host, name_type,
2502 &addrs, &num_addrs);
2503 if (!NT_STATUS_IS_OK(status)) {
2504 tevent_req_nterror(req, status);
2505 return tevent_req_post(req, ev);
2508 addrs = talloc_array(state, struct sockaddr_storage, 1);
2509 if (tevent_req_nomem(addrs, req)) {
2510 return tevent_req_post(req, ev);
2516 state->called_names = talloc_array(state, const char *, num_addrs);
2517 if (tevent_req_nomem(state->called_names, req)) {
2518 return tevent_req_post(req, ev);
2520 state->called_types = talloc_array(state, int, num_addrs);
2521 if (tevent_req_nomem(state->called_types, req)) {
2522 return tevent_req_post(req, ev);
2524 state->calling_names = talloc_array(state, const char *, num_addrs);
2525 if (tevent_req_nomem(state->calling_names, req)) {
2526 return tevent_req_post(req, ev);
2528 for (i=0; i<num_addrs; i++) {
2529 state->called_names[i] = host;
2530 state->called_types[i] = name_type;
2531 state->calling_names[i] = myname;
2534 subreq = smbsock_any_connect_send(
2535 state, ev, addrs, state->called_names, state->called_types,
2536 state->calling_names, NULL, num_addrs, port);
2537 if (tevent_req_nomem(subreq, req)) {
2538 return tevent_req_post(req, ev);
2540 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2544 static void cli_connect_sock_done(struct tevent_req *subreq)
2546 struct tevent_req *req = tevent_req_callback_data(
2547 subreq, struct tevent_req);
2548 struct cli_connect_sock_state *state = tevent_req_data(
2549 req, struct cli_connect_sock_state);
2552 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2554 TALLOC_FREE(subreq);
2555 if (tevent_req_nterror(req, status)) {
2558 set_socket_options(state->fd, lp_socket_options());
2559 tevent_req_done(req);
2562 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2563 int *pfd, uint16_t *pport)
2565 struct cli_connect_sock_state *state = tevent_req_data(
2566 req, struct cli_connect_sock_state);
2569 if (tevent_req_is_nterror(req, &status)) {
2573 *pport = state->port;
2574 return NT_STATUS_OK;
2577 struct cli_connect_nb_state {
2578 const char *desthost;
2581 struct cli_state *cli;
2584 static void cli_connect_nb_done(struct tevent_req *subreq);
2586 static struct tevent_req *cli_connect_nb_send(
2587 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2588 const char *host, const struct sockaddr_storage *dest_ss,
2589 uint16_t port, int name_type, const char *myname,
2590 int signing_state, int flags)
2592 struct tevent_req *req, *subreq;
2593 struct cli_connect_nb_state *state;
2595 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2599 state->signing_state = signing_state;
2600 state->flags = flags;
2603 char *p = strchr(host, '#');
2606 name_type = strtol(p+1, NULL, 16);
2607 host = talloc_strndup(state, host, p - host);
2608 if (tevent_req_nomem(host, req)) {
2609 return tevent_req_post(req, ev);
2613 state->desthost = host;
2614 } else if (dest_ss != NULL) {
2615 state->desthost = print_canonical_sockaddr(state, dest_ss);
2616 if (tevent_req_nomem(state->desthost, req)) {
2617 return tevent_req_post(req, ev);
2620 /* No host or dest_ss given. Error out. */
2621 tevent_req_error(req, EINVAL);
2622 return tevent_req_post(req, ev);
2625 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2627 if (tevent_req_nomem(subreq, req)) {
2628 return tevent_req_post(req, ev);
2630 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2634 static void cli_connect_nb_done(struct tevent_req *subreq)
2636 struct tevent_req *req = tevent_req_callback_data(
2637 subreq, struct tevent_req);
2638 struct cli_connect_nb_state *state = tevent_req_data(
2639 req, struct cli_connect_nb_state);
2644 status = cli_connect_sock_recv(subreq, &fd, &port);
2645 TALLOC_FREE(subreq);
2646 if (tevent_req_nterror(req, status)) {
2650 state->cli = cli_state_create(state, fd, state->desthost, NULL,
2651 state->signing_state, state->flags);
2652 if (tevent_req_nomem(state->cli, req)) {
2656 tevent_req_done(req);
2659 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2660 struct cli_state **pcli)
2662 struct cli_connect_nb_state *state = tevent_req_data(
2663 req, struct cli_connect_nb_state);
2666 if (tevent_req_is_nterror(req, &status)) {
2669 *pcli = talloc_move(NULL, &state->cli);
2670 return NT_STATUS_OK;
2673 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2674 uint16_t port, int name_type, const char *myname,
2675 int signing_state, int flags, struct cli_state **pcli)
2677 struct tevent_context *ev;
2678 struct tevent_req *req;
2679 NTSTATUS status = NT_STATUS_NO_MEMORY;
2681 ev = samba_tevent_context_init(talloc_tos());
2685 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2686 myname, signing_state, flags);
2690 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2693 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2696 status = cli_connect_nb_recv(req, pcli);
2702 struct cli_start_connection_state {
2703 struct tevent_context *ev;
2704 struct cli_state *cli;
2709 static void cli_start_connection_connected(struct tevent_req *subreq);
2710 static void cli_start_connection_done(struct tevent_req *subreq);
2713 establishes a connection to after the negprot.
2714 @param output_cli A fully initialised cli structure, non-null only on success
2715 @param dest_host The netbios name of the remote host
2716 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2717 @param port (optional) The destination port (0 for default)
2720 static struct tevent_req *cli_start_connection_send(
2721 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2722 const char *my_name, const char *dest_host,
2723 const struct sockaddr_storage *dest_ss, int port,
2724 int signing_state, int flags)
2726 struct tevent_req *req, *subreq;
2727 struct cli_start_connection_state *state;
2729 req = tevent_req_create(mem_ctx, &state,
2730 struct cli_start_connection_state);
2736 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2737 state->min_protocol = lp_client_ipc_min_protocol();
2738 state->max_protocol = lp_client_ipc_max_protocol();
2740 state->min_protocol = lp_client_min_protocol();
2741 state->max_protocol = lp_client_max_protocol();
2744 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2745 0x20, my_name, signing_state, flags);
2746 if (tevent_req_nomem(subreq, req)) {
2747 return tevent_req_post(req, ev);
2749 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2753 static void cli_start_connection_connected(struct tevent_req *subreq)
2755 struct tevent_req *req = tevent_req_callback_data(
2756 subreq, struct tevent_req);
2757 struct cli_start_connection_state *state = tevent_req_data(
2758 req, struct cli_start_connection_state);
2761 status = cli_connect_nb_recv(subreq, &state->cli);
2762 TALLOC_FREE(subreq);
2763 if (tevent_req_nterror(req, status)) {
2767 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2768 state->cli->timeout,
2769 state->min_protocol,
2770 state->max_protocol);
2771 if (tevent_req_nomem(subreq, req)) {
2774 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2777 static void cli_start_connection_done(struct tevent_req *subreq)
2779 struct tevent_req *req = tevent_req_callback_data(
2780 subreq, struct tevent_req);
2781 struct cli_start_connection_state *state = tevent_req_data(
2782 req, struct cli_start_connection_state);
2785 status = smbXcli_negprot_recv(subreq);
2786 TALLOC_FREE(subreq);
2787 if (tevent_req_nterror(req, status)) {
2791 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2792 /* Ensure we ask for some initial credits. */
2793 smb2cli_conn_set_max_credits(state->cli->conn,
2794 DEFAULT_SMB2_MAX_CREDITS);
2797 tevent_req_done(req);
2800 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2801 struct cli_state **output_cli)
2803 struct cli_start_connection_state *state = tevent_req_data(
2804 req, struct cli_start_connection_state);
2807 if (tevent_req_is_nterror(req, &status)) {
2810 *output_cli = state->cli;
2812 return NT_STATUS_OK;
2815 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2816 const char *my_name,
2817 const char *dest_host,
2818 const struct sockaddr_storage *dest_ss, int port,
2819 int signing_state, int flags)
2821 struct tevent_context *ev;
2822 struct tevent_req *req;
2823 NTSTATUS status = NT_STATUS_NO_MEMORY;
2825 ev = samba_tevent_context_init(talloc_tos());
2829 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2830 port, signing_state, flags);
2834 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2837 status = cli_start_connection_recv(req, output_cli);
2844 establishes a connection right up to doing tconX, password specified.
2845 @param output_cli A fully initialised cli structure, non-null only on success
2846 @param dest_host The netbios name of the remote host
2847 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2848 @param port (optional) The destination port (0 for default)
2849 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2850 @param service_type The 'type' of serivice.
2851 @param creds The used user credentials
2854 struct cli_full_connection_creds_state {
2855 struct tevent_context *ev;
2856 const char *service;
2857 const char *service_type;
2858 struct cli_credentials *creds;
2860 struct cli_state *cli;
2863 static int cli_full_connection_creds_state_destructor(
2864 struct cli_full_connection_creds_state *s)
2866 if (s->cli != NULL) {
2867 cli_shutdown(s->cli);
2873 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
2874 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
2875 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
2876 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
2877 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
2879 struct tevent_req *cli_full_connection_creds_send(
2880 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2881 const char *my_name, const char *dest_host,
2882 const struct sockaddr_storage *dest_ss, int port,
2883 const char *service, const char *service_type,
2884 struct cli_credentials *creds,
2885 int flags, int signing_state)
2887 struct tevent_req *req, *subreq;
2888 struct cli_full_connection_creds_state *state;
2889 enum credentials_use_kerberos krb5_state;
2890 uint32_t gensec_features = 0;
2892 req = tevent_req_create(mem_ctx, &state,
2893 struct cli_full_connection_creds_state);
2897 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
2899 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
2900 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
2901 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
2902 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
2904 krb5_state = cli_credentials_get_kerberos_state(creds);
2905 switch (krb5_state) {
2906 case CRED_MUST_USE_KERBEROS:
2907 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2908 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
2910 case CRED_AUTO_USE_KERBEROS:
2911 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2912 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
2914 case CRED_DONT_USE_KERBEROS:
2918 gensec_features = cli_credentials_get_gensec_features(creds);
2919 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
2920 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
2924 state->service = service;
2925 state->service_type = service_type;
2926 state->creds = creds;
2927 state->flags = flags;
2929 subreq = cli_start_connection_send(
2930 state, ev, my_name, dest_host, dest_ss, port,
2931 signing_state, flags);
2932 if (tevent_req_nomem(subreq, req)) {
2933 return tevent_req_post(req, ev);
2935 tevent_req_set_callback(subreq,
2936 cli_full_connection_creds_conn_done,
2941 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
2943 struct tevent_req *req = tevent_req_callback_data(
2944 subreq, struct tevent_req);
2945 struct cli_full_connection_creds_state *state = tevent_req_data(
2946 req, struct cli_full_connection_creds_state);
2949 status = cli_start_connection_recv(subreq, &state->cli);
2950 TALLOC_FREE(subreq);
2951 if (tevent_req_nterror(req, status)) {
2955 cli_full_connection_creds_sess_start(req);
2958 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
2960 struct cli_full_connection_creds_state *state = tevent_req_data(
2961 req, struct cli_full_connection_creds_state);
2962 struct tevent_req *subreq = NULL;
2964 subreq = cli_session_setup_creds_send(
2965 state, state->ev, state->cli, state->creds);
2966 if (tevent_req_nomem(subreq, req)) {
2969 tevent_req_set_callback(subreq,
2970 cli_full_connection_creds_sess_done,
2974 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
2976 struct tevent_req *req = tevent_req_callback_data(
2977 subreq, struct tevent_req);
2978 struct cli_full_connection_creds_state *state = tevent_req_data(
2979 req, struct cli_full_connection_creds_state);
2982 status = cli_session_setup_creds_recv(subreq);
2983 TALLOC_FREE(subreq);
2985 if (!NT_STATUS_IS_OK(status) &&
2986 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2988 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2990 state->creds = cli_credentials_init_anon(state);
2991 if (tevent_req_nomem(state->creds, req)) {
2995 cli_full_connection_creds_sess_start(req);
2999 if (tevent_req_nterror(req, status)) {
3003 cli_full_connection_creds_tcon_start(req);
3006 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3008 struct cli_full_connection_creds_state *state = tevent_req_data(
3009 req, struct cli_full_connection_creds_state);
3010 struct tevent_req *subreq = NULL;
3011 const char *password = NULL;
3014 if (state->service == NULL) {
3015 tevent_req_done(req);
3019 password = cli_credentials_get_password(state->creds);
3020 if (password == NULL) {
3024 pw_len = strlen(password) + 1;
3027 subreq = cli_tree_connect_send(state, state->ev,
3030 state->service_type,
3032 if (tevent_req_nomem(subreq, req)) {
3035 tevent_req_set_callback(subreq,
3036 cli_full_connection_creds_tcon_done,
3040 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3042 struct tevent_req *req = tevent_req_callback_data(
3043 subreq, struct tevent_req);
3046 status = cli_tree_connect_recv(subreq);
3047 TALLOC_FREE(subreq);
3048 if (tevent_req_nterror(req, status)) {
3052 tevent_req_done(req);
3055 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3056 struct cli_state **output_cli)
3058 struct cli_full_connection_creds_state *state = tevent_req_data(
3059 req, struct cli_full_connection_creds_state);
3062 if (tevent_req_is_nterror(req, &status)) {
3065 *output_cli = state->cli;
3066 talloc_set_destructor(state, NULL);
3067 return NT_STATUS_OK;
3070 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3071 const char *my_name,
3072 const char *dest_host,
3073 const struct sockaddr_storage *dest_ss, int port,
3074 const char *service, const char *service_type,
3075 struct cli_credentials *creds,
3079 struct tevent_context *ev;
3080 struct tevent_req *req;
3081 NTSTATUS status = NT_STATUS_NO_MEMORY;
3083 ev = samba_tevent_context_init(talloc_tos());
3087 req = cli_full_connection_creds_send(
3088 ev, ev, my_name, dest_host, dest_ss, port, service,
3089 service_type, creds, flags, signing_state);
3093 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3096 status = cli_full_connection_creds_recv(req, output_cli);
3102 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3103 const char *my_name,
3104 const char *dest_host,
3105 const struct sockaddr_storage *dest_ss, int port,
3106 const char *service, const char *service_type,
3107 const char *user, const char *domain,
3108 const char *password, int flags,
3111 TALLOC_CTX *frame = talloc_stackframe();
3113 bool use_kerberos = false;
3114 bool fallback_after_kerberos = false;
3115 bool use_ccache = false;
3116 bool pw_nt_hash = false;
3117 struct cli_credentials *creds = NULL;
3119 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3120 use_kerberos = true;
3123 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3124 fallback_after_kerberos = true;
3127 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3131 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3135 creds = cli_session_creds_init(frame,
3138 NULL, /* realm (use default) */
3141 fallback_after_kerberos,
3144 if (creds == NULL) {
3146 return NT_STATUS_NO_MEMORY;
3149 status = cli_full_connection_creds(output_cli, my_name,
3150 dest_host, dest_ss, port,
3151 service, service_type,
3152 creds, flags, signing_state);
3153 if (!NT_STATUS_IS_OK(status)) {
3159 return NT_STATUS_OK;
3162 /****************************************************************************
3163 Send an old style tcon.
3164 ****************************************************************************/
3165 struct cli_raw_tcon_state {
3169 static void cli_raw_tcon_done(struct tevent_req *subreq);
3171 static struct tevent_req *cli_raw_tcon_send(
3172 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3173 const char *service, const char *pass, const char *dev)
3175 struct tevent_req *req, *subreq;
3176 struct cli_raw_tcon_state *state;
3179 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3184 if (!lp_client_plaintext_auth() && (*pass)) {
3185 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3186 " or 'client ntlmv2 auth = yes'\n"));
3187 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3188 return tevent_req_post(req, ev);
3191 bytes = talloc_array(state, uint8_t, 0);
3192 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3193 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3194 service, strlen(service)+1, NULL);
3195 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3196 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3197 pass, strlen(pass)+1, NULL);
3198 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3199 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3200 dev, strlen(dev)+1, NULL);
3202 if (tevent_req_nomem(bytes, req)) {
3203 return tevent_req_post(req, ev);
3206 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3207 talloc_get_size(bytes), bytes);
3208 if (tevent_req_nomem(subreq, req)) {
3209 return tevent_req_post(req, ev);
3211 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3215 static void cli_raw_tcon_done(struct tevent_req *subreq)
3217 struct tevent_req *req = tevent_req_callback_data(
3218 subreq, struct tevent_req);
3219 struct cli_raw_tcon_state *state = tevent_req_data(
3220 req, struct cli_raw_tcon_state);
3223 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3225 TALLOC_FREE(subreq);
3226 if (tevent_req_nterror(req, status)) {
3229 tevent_req_done(req);
3232 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3233 uint16_t *max_xmit, uint16_t *tid)
3235 struct cli_raw_tcon_state *state = tevent_req_data(
3236 req, struct cli_raw_tcon_state);
3239 if (tevent_req_is_nterror(req, &status)) {
3242 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3243 *tid = SVAL(state->ret_vwv + 1, 0);
3244 return NT_STATUS_OK;
3247 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3248 const char *service, const char *pass, const char *dev,
3249 uint16_t *max_xmit, uint16_t *tid)
3251 struct tevent_context *ev;
3252 struct tevent_req *req;
3253 NTSTATUS status = NT_STATUS_NO_MEMORY;
3255 ev = samba_tevent_context_init(talloc_tos());
3259 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3263 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3266 status = cli_raw_tcon_recv(req, max_xmit, tid);
3272 /* Return a cli_state pointing at the IPC$ share for the given server */
3274 struct cli_state *get_ipc_connect(char *server,
3275 struct sockaddr_storage *server_ss,
3276 const struct user_auth_info *user_info)
3278 struct cli_state *cli;
3280 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3282 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3283 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3286 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3287 get_cmdline_auth_info_username(user_info),
3289 get_cmdline_auth_info_password(user_info),
3291 SMB_SIGNING_DEFAULT);
3293 if (NT_STATUS_IS_OK(nt_status)) {
3295 } else if (is_ipaddress(server)) {
3296 /* windows 9* needs a correct NMB name for connections */
3297 fstring remote_name;
3299 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3300 cli = get_ipc_connect(remote_name, server_ss, user_info);
3309 * Given the IP address of a master browser on the network, return its
3310 * workgroup and connect to it.
3312 * This function is provided to allow additional processing beyond what
3313 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3314 * browsers and obtain each master browsers' list of domains (in case the
3315 * first master browser is recently on the network and has not yet
3316 * synchronized with other master browsers and therefore does not yet have the
3317 * entire network browse list)
3320 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3321 struct sockaddr_storage *mb_ip,
3322 const struct user_auth_info *user_info,
3323 char **pp_workgroup_out)
3325 char addr[INET6_ADDRSTRLEN];
3327 struct cli_state *cli;
3328 struct sockaddr_storage server_ss;
3330 *pp_workgroup_out = NULL;
3332 print_sockaddr(addr, sizeof(addr), mb_ip);
3333 DEBUG(99, ("Looking up name of master browser %s\n",
3337 * Do a name status query to find out the name of the master browser.
3338 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3339 * master browser will not respond to a wildcard query (or, at least,
3340 * an NT4 server acting as the domain master browser will not).
3342 * We might be able to use ONLY the query on MSBROWSE, but that's not
3343 * yet been tested with all Windows versions, so until it is, leave
3344 * the original wildcard query as the first choice and fall back to
3345 * MSBROWSE if the wildcard query fails.
3347 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3348 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3350 DEBUG(99, ("Could not retrieve name status for %s\n",
3355 if (!find_master_ip(name, &server_ss)) {
3356 DEBUG(99, ("Could not find master ip for %s\n", name));
3360 *pp_workgroup_out = talloc_strdup(ctx, name);
3362 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3364 print_sockaddr(addr, sizeof(addr), &server_ss);
3365 cli = get_ipc_connect(addr, &server_ss, user_info);
3371 * Return the IP address and workgroup of a master browser on the network, and
3375 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3376 const struct user_auth_info *user_info,
3377 char **pp_workgroup_out)
3379 struct sockaddr_storage *ip_list;
3380 struct cli_state *cli;
3384 *pp_workgroup_out = NULL;
3386 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3388 /* Go looking for workgroups by broadcasting on the local network */
3390 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3392 if (!NT_STATUS_IS_OK(status)) {
3393 DEBUG(99, ("No master browsers responded: %s\n",
3394 nt_errstr(status)));
3398 for (i = 0; i < count; i++) {
3399 char addr[INET6_ADDRSTRLEN];
3400 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3401 DEBUG(99, ("Found master browser %s\n", addr));
3403 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3404 user_info, pp_workgroup_out);