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 "libsmb/namequery.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 "../libcli/smb/smb_seal.h"
41 #include "lib/param/param.h"
42 #include "../libcli/smb/smb2_negotiate_context.h"
44 #define STAR_SMBSERVER "*SMBSERVER"
46 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
47 const char *principal);
49 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
55 bool fallback_after_kerberos,
57 bool password_is_nt_hash)
59 struct loadparm_context *lp_ctx = NULL;
60 struct cli_credentials *creds = NULL;
61 const char *principal = NULL;
66 creds = cli_credentials_init(mem_ctx);
71 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
75 ok = cli_credentials_set_conf(creds, lp_ctx);
80 if (username == NULL) {
84 if (strlen(username) == 0) {
85 if (password != NULL && strlen(password) == 0) {
87 * some callers pass "" as no password
89 * gensec only handles NULL as no password.
93 if (password == NULL) {
94 cli_credentials_set_anonymous(creds);
99 tmp = talloc_strdup(creds, username);
105 /* allow for workgroups as part of the username */
106 if ((p = strchr_m(tmp, '\\')) ||
107 (p = strchr_m(tmp, '/')) ||
108 (p = strchr_m(tmp, *lp_winbind_separator()))) {
114 principal = username;
115 username = cli_session_setup_get_account(creds, principal);
116 if (username == NULL) {
119 ok = strequal(username, principal);
122 * Ok still the same, so it's not a principal
127 if (use_kerberos && fallback_after_kerberos) {
128 cli_credentials_set_kerberos_state(creds,
129 CRED_USE_KERBEROS_DESIRED,
131 } else if (use_kerberos) {
132 cli_credentials_set_kerberos_state(creds,
133 CRED_USE_KERBEROS_REQUIRED,
136 cli_credentials_set_kerberos_state(creds,
137 CRED_USE_KERBEROS_DISABLED,
144 features = cli_credentials_get_gensec_features(creds);
145 features |= GENSEC_FEATURE_NTLM_CCACHE;
146 cli_credentials_set_gensec_features(creds,
150 if (password != NULL && strlen(password) == 0) {
152 * some callers pass "" as no password
154 * GENSEC_FEATURE_NTLM_CCACHE only handles
155 * NULL as no password.
161 ok = cli_credentials_set_username(creds,
168 if (domain != NULL) {
169 ok = cli_credentials_set_domain(creds,
177 if (principal != NULL) {
178 ok = cli_credentials_set_principal(creds,
187 ok = cli_credentials_set_realm(creds,
195 if (password != NULL && strlen(password) > 0) {
196 if (password_is_nt_hash) {
197 struct samr_Password nt_hash;
200 converted = strhex_to_str((char *)nt_hash.hash,
201 sizeof(nt_hash.hash),
204 if (converted != sizeof(nt_hash.hash)) {
208 ok = cli_credentials_set_nt_hash(creds,
215 ok = cli_credentials_set_password(creds,
230 NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
231 struct cli_credentials *creds)
233 TALLOC_CTX *frame = talloc_stackframe();
234 const char *user_principal = NULL;
235 const char *user_account = NULL;
236 const char *user_domain = NULL;
237 const char *pass = NULL;
238 char *canon_principal = NULL;
239 char *canon_realm = NULL;
240 const char *target_hostname = NULL;
241 enum credentials_use_kerberos krb5_state;
242 bool try_kerberos = false;
243 bool need_kinit = false;
244 bool auth_requested = true;
248 target_hostname = smbXcli_conn_remote_name(cli->conn);
250 auth_requested = cli_credentials_authentication_requested(creds);
251 if (auth_requested) {
253 user_principal = cli_credentials_get_principal(creds, frame);
256 return NT_STATUS_NO_MEMORY;
259 user_account = cli_credentials_get_username(creds);
260 user_domain = cli_credentials_get_domain(creds);
261 pass = cli_credentials_get_password(creds);
263 krb5_state = cli_credentials_get_kerberos_state(creds);
265 if (krb5_state != CRED_USE_KERBEROS_DISABLED) {
269 if (user_principal == NULL) {
270 try_kerberos = false;
273 if (target_hostname == NULL) {
274 try_kerberos = false;
275 } else if (is_ipaddress(target_hostname)) {
276 try_kerberos = false;
277 } else if (strequal(target_hostname, "localhost")) {
278 try_kerberos = false;
279 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
280 try_kerberos = false;
281 } else if (!auth_requested) {
282 try_kerberos = false;
285 if (krb5_state == CRED_USE_KERBEROS_REQUIRED && !try_kerberos) {
286 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
287 "'%s' not possible\n",
288 user_principal, user_domain, user_account,
291 return NT_STATUS_ACCESS_DENIED;
294 if (pass == NULL || strlen(pass) == 0) {
296 } else if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
297 need_kinit = try_kerberos;
299 need_kinit = try_kerberos;
307 DBG_INFO("Doing kinit for %s to access %s\n",
308 user_principal, target_hostname);
311 * TODO: This should be done within the gensec layer
314 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
315 ret = kerberos_kinit_password_ext(user_principal,
329 int dbglvl = DBGLVL_NOTICE;
331 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
335 DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
336 user_principal, target_hostname,
337 error_message(ret)));
338 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
340 return krb5_to_nt_status(ret);
344 * Ignore the error and hope that NTLM will work
350 ok = cli_credentials_set_principal(creds,
355 return NT_STATUS_NO_MEMORY;
358 ok = cli_credentials_set_realm(creds,
363 return NT_STATUS_NO_MEMORY;
366 DBG_DEBUG("Successfully authenticated as %s (%s) to access %s using "
376 static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
377 const char *native_os,
378 const char *native_lm,
379 const char *primary_domain)
381 #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
383 if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
384 cli->server_os = talloc_strdup(cli, native_os);
385 if (cli->server_os == NULL) {
386 return NT_STATUS_NO_MEMORY;
390 if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
391 cli->server_type = talloc_strdup(cli, native_lm);
392 if (cli->server_type == NULL) {
393 return NT_STATUS_NO_MEMORY;
397 if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
398 cli->server_domain = talloc_strdup(cli, primary_domain);
399 if (cli->server_domain == NULL) {
400 return NT_STATUS_NO_MEMORY;
408 /********************************************************
409 Utility function to ensure we always return at least
410 a valid char * pointer to an empty string for the
411 cli->server_os, cli->server_type and cli->server_domain
413 *******************************************************/
415 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
422 *destlen = pull_string_talloc(mem_ctx,
429 if (*destlen == -1) {
430 return NT_STATUS_NO_MEMORY;
434 *dest = talloc_strdup(mem_ctx, "");
436 return NT_STATUS_NO_MEMORY;
442 /****************************************************************************
443 Work out suitable capabilities to offer the server.
444 ****************************************************************************/
446 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
447 uint32_t sesssetup_capabilities)
449 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
452 * We only send capabilities based on the mask for:
453 * - client only flags
454 * - flags used in both directions
456 * We do not echo the server only flags, except some legacy flags.
458 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
459 * CAP_LARGE_WRITEX in order to allow us to do large reads
460 * against old Samba releases (<= 3.6.x).
462 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
465 * Session Setup specific flags CAP_DYNAMIC_REAUTH
466 * and CAP_EXTENDED_SECURITY are passed by the caller.
467 * We need that in order to do guest logins even if
468 * CAP_EXTENDED_SECURITY is negotiated.
470 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
471 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
472 client_capabilities |= sesssetup_capabilities;
474 return client_capabilities;
477 /****************************************************************************
478 Do a NT1 guest session setup.
479 ****************************************************************************/
481 struct cli_session_setup_guest_state {
482 struct cli_state *cli;
487 static void cli_session_setup_guest_done(struct tevent_req *subreq);
489 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
490 struct tevent_context *ev,
491 struct cli_state *cli,
492 struct tevent_req **psmbreq)
494 struct tevent_req *req, *subreq;
495 struct cli_session_setup_guest_state *state;
499 req = tevent_req_create(mem_ctx, &state,
500 struct cli_session_setup_guest_state);
507 SCVAL(vwv+0, 0, 0xFF);
510 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
512 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
513 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
518 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
520 bytes = talloc_array(state, uint8_t, 0);
522 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
524 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
526 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
527 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
534 state->bytes.iov_base = (void *)bytes;
535 state->bytes.iov_len = talloc_get_size(bytes);
537 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
538 vwv, 1, &state->bytes);
539 if (subreq == NULL) {
543 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
548 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
549 struct tevent_context *ev,
550 struct cli_state *cli)
552 struct tevent_req *req, *subreq;
555 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
560 status = smb1cli_req_chain_submit(&subreq, 1);
561 if (!NT_STATUS_IS_OK(status)) {
562 tevent_req_nterror(req, status);
563 return tevent_req_post(req, ev);
568 static void cli_session_setup_guest_done(struct tevent_req *subreq)
570 struct tevent_req *req = tevent_req_callback_data(
571 subreq, struct tevent_req);
572 struct cli_session_setup_guest_state *state = tevent_req_data(
573 req, struct cli_session_setup_guest_state);
574 struct cli_state *cli = state->cli;
585 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
588 if (!NT_STATUS_IS_OK(status)) {
589 tevent_req_nterror(req, status);
593 inhdr = in + NBT_HDR_SIZE;
596 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
597 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
599 status = smb_bytes_talloc_string(cli,
606 if (!NT_STATUS_IS_OK(status)) {
607 tevent_req_nterror(req, status);
612 status = smb_bytes_talloc_string(cli,
619 if (!NT_STATUS_IS_OK(status)) {
620 tevent_req_nterror(req, status);
625 status = smb_bytes_talloc_string(cli,
632 if (!NT_STATUS_IS_OK(status)) {
633 tevent_req_nterror(req, status);
637 tevent_req_done(req);
640 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
642 return tevent_req_simple_recv_ntstatus(req);
645 /* The following is calculated from :
647 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
648 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
652 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
654 struct cli_sesssetup_blob_state {
655 struct tevent_context *ev;
656 struct cli_state *cli;
658 uint16_t max_blob_size;
661 struct iovec *recv_iov;
664 const uint8_t *inbuf;
671 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
672 struct tevent_req **psubreq);
673 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
675 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
676 struct tevent_context *ev,
677 struct cli_state *cli,
680 struct tevent_req *req, *subreq;
681 struct cli_sesssetup_blob_state *state;
682 uint32_t usable_space;
684 req = tevent_req_create(mem_ctx, &state,
685 struct cli_sesssetup_blob_state);
693 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
694 usable_space = UINT16_MAX;
696 usable_space = cli_state_available_size(cli,
697 BASE_SESSSETUP_BLOB_PACKET_SIZE);
700 if (usable_space == 0) {
701 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
702 "(not possible to send %u bytes)\n",
703 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
704 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
705 return tevent_req_post(req, ev);
707 state->max_blob_size = MIN(usable_space, 0xFFFF);
709 if (!cli_sesssetup_blob_next(state, &subreq)) {
710 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
711 return tevent_req_post(req, ev);
713 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
717 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
718 struct tevent_req **psubreq)
720 struct tevent_req *subreq;
723 thistime = MIN(state->blob.length, state->max_blob_size);
725 state->this_blob.data = state->blob.data;
726 state->this_blob.length = thistime;
728 state->blob.data += thistime;
729 state->blob.length -= thistime;
731 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
732 subreq = smb2cli_session_setup_send(state, state->ev,
735 state->cli->smb2.session,
737 SMB2_CAP_DFS, /* in_capabilities */
739 0, /* in_previous_session_id */
741 if (subreq == NULL) {
745 uint16_t in_buf_size = 0;
746 uint16_t in_mpx_max = 0;
747 uint16_t in_vc_num = 0;
748 uint32_t in_sess_key = 0;
749 uint32_t in_capabilities = 0;
750 const char *in_native_os = NULL;
751 const char *in_native_lm = NULL;
753 in_buf_size = CLI_BUFFER_SIZE;
754 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
755 in_vc_num = cli_state_get_vc_num(state->cli);
756 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
757 in_capabilities = cli_session_setup_capabilities(state->cli,
758 CAP_EXTENDED_SECURITY);
759 in_native_os = "Unix";
760 in_native_lm = "Samba";
763 * For now we keep the same values as before,
764 * we may remove these in a separate commit later.
770 subreq = smb1cli_session_setup_ext_send(state, state->ev,
773 state->cli->smb1.pid,
774 state->cli->smb1.session,
783 if (subreq == NULL) {
791 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
793 struct tevent_req *req = tevent_req_callback_data(
794 subreq, struct tevent_req);
795 struct cli_sesssetup_blob_state *state = tevent_req_data(
796 req, struct cli_sesssetup_blob_state);
799 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
800 status = smb2cli_session_setup_recv(subreq, state,
804 status = smb1cli_session_setup_ext_recv(subreq, state,
808 &state->out_native_os,
809 &state->out_native_lm);
812 if (!NT_STATUS_IS_OK(status)
813 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
814 tevent_req_nterror(req, status);
818 state->status = status;
820 status = cli_state_update_after_sesssetup(state->cli,
821 state->out_native_os,
822 state->out_native_lm,
824 if (tevent_req_nterror(req, status)) {
828 if (state->blob.length != 0) {
832 if (!cli_sesssetup_blob_next(state, &subreq)) {
836 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
839 tevent_req_done(req);
842 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
845 const uint8_t **pinbuf,
846 struct iovec **precv_iov)
848 struct cli_sesssetup_blob_state *state = tevent_req_data(
849 req, struct cli_sesssetup_blob_state);
851 struct iovec *recv_iov;
853 if (tevent_req_is_nterror(req, &status)) {
854 TALLOC_FREE(state->cli->smb2.session);
855 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
856 tevent_req_received(req);
860 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
862 *pblob = state->ret_blob;
864 if (pinbuf != NULL) {
865 *pinbuf = state->inbuf;
867 if (precv_iov != NULL) {
868 *precv_iov = recv_iov;
870 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
871 status = state->status;
872 tevent_req_received(req);
876 /****************************************************************************
877 Do a spnego/NTLMSSP encrypted session setup.
878 ****************************************************************************/
880 struct cli_session_setup_gensec_state {
881 struct tevent_context *ev;
882 struct cli_state *cli;
883 struct auth_generic_state *auth_generic;
886 const uint8_t *inbuf;
887 struct iovec *recv_iov;
891 DATA_BLOB session_key;
894 static int cli_session_setup_gensec_state_destructor(
895 struct cli_session_setup_gensec_state *state)
897 TALLOC_FREE(state->auth_generic);
898 data_blob_clear_free(&state->session_key);
902 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
903 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
904 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
905 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
906 static void cli_session_setup_gensec_ready(struct tevent_req *req);
908 static struct tevent_req *cli_session_setup_gensec_send(
909 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
910 struct cli_credentials *creds,
911 const char *target_service,
912 const char *target_hostname)
914 struct tevent_req *req;
915 struct cli_session_setup_gensec_state *state;
917 const DATA_BLOB *b = NULL;
919 req = tevent_req_create(mem_ctx, &state,
920 struct cli_session_setup_gensec_state);
927 talloc_set_destructor(
928 state, cli_session_setup_gensec_state_destructor);
930 status = auth_generic_client_prepare(state, &state->auth_generic);
931 if (tevent_req_nterror(req, status)) {
932 return tevent_req_post(req, ev);
935 status = auth_generic_set_creds(state->auth_generic, creds);
936 if (tevent_req_nterror(req, status)) {
937 return tevent_req_post(req, ev);
940 gensec_want_feature(state->auth_generic->gensec_security,
941 GENSEC_FEATURE_SESSION_KEY);
943 if (target_service != NULL) {
944 status = gensec_set_target_service(
945 state->auth_generic->gensec_security,
947 if (tevent_req_nterror(req, status)) {
948 return tevent_req_post(req, ev);
952 if (target_hostname != NULL) {
953 status = gensec_set_target_hostname(
954 state->auth_generic->gensec_security,
956 if (tevent_req_nterror(req, status)) {
957 return tevent_req_post(req, ev);
961 b = smbXcli_conn_server_gss_blob(cli->conn);
966 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
968 status = auth_generic_client_start(state->auth_generic,
970 if (tevent_req_nterror(req, status)) {
971 return tevent_req_post(req, ev);
974 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
975 state->cli->smb2.session = smbXcli_session_create(cli,
977 if (tevent_req_nomem(state->cli->smb2.session, req)) {
978 return tevent_req_post(req, ev);
982 cli_session_setup_gensec_local_next(req);
983 if (!tevent_req_is_in_progress(req)) {
984 return tevent_req_post(req, ev);
990 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
992 struct cli_session_setup_gensec_state *state =
994 struct cli_session_setup_gensec_state);
995 struct tevent_req *subreq = NULL;
997 if (state->local_ready) {
998 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1002 subreq = gensec_update_send(state, state->ev,
1003 state->auth_generic->gensec_security,
1005 if (tevent_req_nomem(subreq, req)) {
1008 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1011 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1013 struct tevent_req *req =
1014 tevent_req_callback_data(subreq,
1016 struct cli_session_setup_gensec_state *state =
1017 tevent_req_data(req,
1018 struct cli_session_setup_gensec_state);
1021 status = gensec_update_recv(subreq, state, &state->blob_out);
1022 TALLOC_FREE(subreq);
1023 state->blob_in = data_blob_null;
1024 if (!NT_STATUS_IS_OK(status) &&
1025 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1027 tevent_req_nterror(req, status);
1031 if (NT_STATUS_IS_OK(status)) {
1032 state->local_ready = true;
1035 if (state->local_ready && state->remote_ready) {
1036 cli_session_setup_gensec_ready(req);
1040 cli_session_setup_gensec_remote_next(req);
1043 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1045 struct cli_session_setup_gensec_state *state =
1046 tevent_req_data(req,
1047 struct cli_session_setup_gensec_state);
1048 struct tevent_req *subreq = NULL;
1050 if (state->remote_ready) {
1051 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1055 subreq = cli_sesssetup_blob_send(state, state->ev,
1056 state->cli, state->blob_out);
1057 if (tevent_req_nomem(subreq, req)) {
1060 tevent_req_set_callback(subreq,
1061 cli_session_setup_gensec_remote_done,
1065 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1067 struct tevent_req *req =
1068 tevent_req_callback_data(subreq,
1070 struct cli_session_setup_gensec_state *state =
1071 tevent_req_data(req,
1072 struct cli_session_setup_gensec_state);
1075 state->inbuf = NULL;
1076 TALLOC_FREE(state->recv_iov);
1078 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1079 &state->inbuf, &state->recv_iov);
1080 TALLOC_FREE(subreq);
1081 data_blob_free(&state->blob_out);
1082 if (!NT_STATUS_IS_OK(status) &&
1083 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1085 tevent_req_nterror(req, status);
1089 if (NT_STATUS_IS_OK(status)) {
1090 struct smbXcli_session *session = NULL;
1091 bool is_guest = false;
1093 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1094 session = state->cli->smb2.session;
1096 session = state->cli->smb1.session;
1099 is_guest = smbXcli_session_is_guest(session);
1102 * We can't finish the gensec handshake, we don't
1103 * have a negotiated session key.
1105 * So just pretend we are completely done,
1106 * we need to continue as anonymous from this point,
1107 * as we can't get a session key.
1109 * Note that smbXcli_session_is_guest()
1110 * always returns false if we require signing.
1112 state->blob_in = data_blob_null;
1113 state->local_ready = true;
1114 state->is_anonymous = true;
1117 state->remote_ready = true;
1120 if (state->local_ready && state->remote_ready) {
1121 cli_session_setup_gensec_ready(req);
1125 cli_session_setup_gensec_local_next(req);
1128 static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
1129 struct smbXcli_session *session,
1130 DATA_BLOB session_key)
1133 DATA_BLOB sig = data_blob_null;
1134 DATA_BLOB app = data_blob_null;
1135 DATA_BLOB enc = data_blob_null;
1136 DATA_BLOB dec = data_blob_null;
1137 uint64_t sid = smb2cli_session_current_id(session);
1139 status = smb2cli_session_signing_key(session, mem_ctx, &sig);
1140 if (!NT_STATUS_IS_OK(status)) {
1143 status = smbXcli_session_application_key(session, mem_ctx, &app);
1144 if (!NT_STATUS_IS_OK(status)) {
1147 status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
1148 if (!NT_STATUS_IS_OK(status)) {
1151 status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
1152 if (!NT_STATUS_IS_OK(status)) {
1156 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
1157 DEBUGADD(0, ("Session Id "));
1158 dump_data(0, (uint8_t*)&sid, sizeof(sid));
1159 DEBUGADD(0, ("Session Key "));
1160 dump_data(0, session_key.data, session_key.length);
1161 DEBUGADD(0, ("Signing Key "));
1162 dump_data(0, sig.data, sig.length);
1163 DEBUGADD(0, ("App Key "));
1164 dump_data(0, app.data, app.length);
1166 /* In client code, ServerIn is the encryption key */
1168 DEBUGADD(0, ("ServerIn Key "));
1169 dump_data(0, enc.data, enc.length);
1170 DEBUGADD(0, ("ServerOut Key "));
1171 dump_data(0, dec.data, dec.length);
1174 data_blob_clear_free(&sig);
1175 data_blob_clear_free(&app);
1176 data_blob_clear_free(&enc);
1177 data_blob_clear_free(&dec);
1180 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1182 struct cli_session_setup_gensec_state *state =
1183 tevent_req_data(req,
1184 struct cli_session_setup_gensec_state);
1185 const char *server_domain = NULL;
1188 if (state->blob_in.length != 0) {
1189 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1193 if (state->blob_out.length != 0) {
1194 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1199 * gensec_ntlmssp_server_domain() returns NULL
1200 * if NTLMSSP is not used.
1202 * We can remove this later
1203 * and leave the server domain empty for SMB2 and above
1204 * in future releases.
1206 server_domain = gensec_ntlmssp_server_domain(
1207 state->auth_generic->gensec_security);
1209 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1210 TALLOC_FREE(state->cli->server_domain);
1211 state->cli->server_domain = talloc_strdup(state->cli,
1213 if (state->cli->server_domain == NULL) {
1214 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1219 if (state->is_anonymous) {
1221 * Windows server does not set the
1222 * SMB2_SESSION_FLAG_IS_NULL flag.
1224 * This fix makes sure we do not try
1225 * to verify a signature on the final
1226 * session setup response.
1228 tevent_req_done(req);
1232 status = gensec_session_key(state->auth_generic->gensec_security,
1233 state, &state->session_key);
1234 if (tevent_req_nterror(req, status)) {
1238 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1239 struct smbXcli_session *session = state->cli->smb2.session;
1241 status = smb2cli_session_set_session_key(session,
1244 if (tevent_req_nterror(req, status)) {
1247 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
1248 && lp_debug_encryption())
1250 cli_session_dump_keys(state, session, state->session_key);
1253 struct smbXcli_session *session = state->cli->smb1.session;
1256 status = smb1cli_session_set_session_key(session,
1257 state->session_key);
1258 if (tevent_req_nterror(req, status)) {
1262 active = smb1cli_conn_activate_signing(state->cli->conn,
1268 ok = smb1cli_conn_check_signing(state->cli->conn,
1271 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1277 tevent_req_done(req);
1280 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1282 struct cli_session_setup_gensec_state *state =
1283 tevent_req_data(req,
1284 struct cli_session_setup_gensec_state);
1287 if (tevent_req_is_nterror(req, &status)) {
1288 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1291 return NT_STATUS_OK;
1294 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1295 const char *principal)
1299 account = talloc_strdup(mem_ctx, principal);
1300 if (account == NULL) {
1303 p = strchr_m(account, '@');
1310 /****************************************************************************
1311 Do a spnego encrypted session setup.
1313 user_domain: The shortname of the domain the user/machine is a member of.
1314 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1315 ****************************************************************************/
1317 struct cli_session_setup_spnego_state {
1321 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1323 static struct tevent_req *cli_session_setup_spnego_send(
1324 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1325 struct cli_credentials *creds)
1327 struct tevent_req *req, *subreq;
1328 struct cli_session_setup_spnego_state *state;
1329 const char *target_service = NULL;
1330 const char *target_hostname = NULL;
1333 req = tevent_req_create(mem_ctx, &state,
1334 struct cli_session_setup_spnego_state);
1339 target_service = "cifs";
1340 target_hostname = smbXcli_conn_remote_name(cli->conn);
1342 status = cli_session_creds_prepare_krb5(cli, creds);
1343 if (tevent_req_nterror(req, status)) {
1344 return tevent_req_post(req, ev);
1347 DBG_INFO("Connect to %s as %s using SPNEGO\n",
1349 cli_credentials_get_principal(creds, talloc_tos()));
1351 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1352 target_service, target_hostname);
1353 if (tevent_req_nomem(subreq, req)) {
1354 return tevent_req_post(req, ev);
1356 tevent_req_set_callback(
1357 subreq, cli_session_setup_spnego_done, req);
1361 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1363 struct tevent_req *req = tevent_req_callback_data(
1364 subreq, struct tevent_req);
1367 status = cli_session_setup_gensec_recv(subreq);
1368 TALLOC_FREE(subreq);
1369 if (tevent_req_nterror(req, status)) {
1373 tevent_req_done(req);
1376 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1378 struct cli_session_setup_spnego_state *state = tevent_req_data(
1379 req, struct cli_session_setup_spnego_state);
1382 if (tevent_req_is_nterror(req, &status)) {
1383 state->result = ADS_ERROR_NT(status);
1386 return state->result;
1389 struct cli_session_setup_creds_state {
1390 struct cli_state *cli;
1391 DATA_BLOB apassword_blob;
1392 DATA_BLOB upassword_blob;
1393 DATA_BLOB lm_session_key;
1394 DATA_BLOB session_key;
1395 char *out_native_os;
1396 char *out_native_lm;
1397 char *out_primary_domain;
1400 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1401 enum tevent_req_state req_state)
1403 struct cli_session_setup_creds_state *state = tevent_req_data(
1404 req, struct cli_session_setup_creds_state);
1406 if (req_state != TEVENT_REQ_RECEIVED) {
1411 * We only call data_blob_clear() as
1412 * some of the blobs point to the same memory.
1414 * We let the talloc hierarchy free the memory.
1416 data_blob_clear(&state->apassword_blob);
1417 data_blob_clear(&state->upassword_blob);
1418 data_blob_clear(&state->lm_session_key);
1419 data_blob_clear(&state->session_key);
1420 ZERO_STRUCTP(state);
1423 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1424 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1425 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1427 /****************************************************************************
1428 Send a session setup. The username and workgroup is in UNIX character
1429 format and must be converted to DOS codepage format before sending. If the
1430 password is in plaintext, the same should be done.
1431 ****************************************************************************/
1433 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1434 struct tevent_context *ev,
1435 struct cli_state *cli,
1436 struct cli_credentials *creds)
1438 struct tevent_req *req, *subreq;
1439 struct cli_session_setup_creds_state *state;
1440 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1441 bool use_spnego = false;
1443 const char *username = "";
1444 const char *domain = "";
1445 DATA_BLOB target_info = data_blob_null;
1446 DATA_BLOB challenge = data_blob_null;
1447 uint16_t in_buf_size = 0;
1448 uint16_t in_mpx_max = 0;
1449 uint16_t in_vc_num = 0;
1450 uint32_t in_sess_key = 0;
1451 const char *in_native_os = NULL;
1452 const char *in_native_lm = NULL;
1453 enum credentials_use_kerberos krb5_state =
1454 cli_credentials_get_kerberos_state(creds);
1457 req = tevent_req_create(mem_ctx, &state,
1458 struct cli_session_setup_creds_state);
1464 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1467 * Now work out what sort of session setup we are going to
1468 * do. I have split this into separate functions to make the flow a bit
1469 * easier to understand (tridge).
1471 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1473 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1475 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1477 * if the server supports extended security then use SPNEGO
1478 * even for anonymous connections.
1486 subreq = cli_session_setup_spnego_send(
1487 state, ev, cli, creds);
1488 if (tevent_req_nomem(subreq, req)) {
1489 return tevent_req_post(req, ev);
1491 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1496 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
1497 DBG_WARNING("Kerberos authentication requested, but "
1498 "the server does not support SPNEGO authentication\n");
1499 tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
1500 return tevent_req_post(req, ev);
1503 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1505 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1506 * this step against older servers.
1508 tevent_req_done(req);
1509 return tevent_req_post(req, ev);
1512 if (cli_credentials_is_anonymous(creds)) {
1514 * Do an anonymous session setup
1516 goto non_spnego_creds_done;
1519 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1521 * Do an anonymous session setup,
1522 * the password is passed via the tree connect.
1524 goto non_spnego_creds_done;
1527 cli_credentials_get_ntlm_username_domain(creds, state,
1530 if (tevent_req_nomem(username, req)) {
1531 return tevent_req_post(req, ev);
1533 if (tevent_req_nomem(domain, req)) {
1534 return tevent_req_post(req, ev);
1537 DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
1539 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1540 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1541 uint8_t *bytes = NULL;
1542 size_t bytes_len = 0;
1543 const char *pw = cli_credentials_get_password(creds);
1549 pw_len = strlen(pw) + 1;
1551 if (!lp_client_plaintext_auth()) {
1552 DEBUG(1, ("Server requested PLAINTEXT password but "
1553 "'client plaintext auth = no'\n"));
1554 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1555 return tevent_req_post(req, ev);
1558 bytes = talloc_array(state, uint8_t, 0);
1559 bytes = trans2_bytes_push_str(bytes, use_unicode,
1560 pw, pw_len, &bytes_len);
1561 if (tevent_req_nomem(bytes, req)) {
1562 return tevent_req_post(req, ev);
1567 * CAP_UNICODE, can only be negotiated by NT1.
1569 state->upassword_blob = data_blob_const(bytes,
1572 state->apassword_blob = data_blob_const(bytes,
1576 goto non_spnego_creds_done;
1579 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1581 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1582 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1584 * Don't send an NTLMv2 response without NTLMSSP if we
1585 * want to use spnego support.
1587 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1588 " but 'client use spnego = yes'"
1589 " and 'client ntlmv2 auth = yes' is set\n"));
1590 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1591 return tevent_req_post(req, ev);
1594 if (lp_client_ntlmv2_auth()) {
1595 flags |= CLI_CRED_NTLMv2_AUTH;
1598 * note that the 'domain' here is a best
1599 * guess - we don't know the server's domain
1600 * at this point. Windows clients also don't
1603 target_info = NTLMv2_generate_names_blob(state,
1606 if (tevent_req_nomem(target_info.data, req)) {
1607 return tevent_req_post(req, ev);
1610 flags |= CLI_CRED_NTLM_AUTH;
1611 if (lp_client_lanman_auth()) {
1612 flags |= CLI_CRED_LANMAN_AUTH;
1616 if (!lp_client_lanman_auth()) {
1617 DEBUG(1, ("Server requested user level LM password but "
1618 "'client lanman auth = no' is set.\n"));
1619 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1620 return tevent_req_post(req, ev);
1623 flags |= CLI_CRED_LANMAN_AUTH;
1626 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1629 &state->apassword_blob,
1630 &state->upassword_blob,
1631 &state->lm_session_key,
1632 &state->session_key);
1633 if (tevent_req_nterror(req, status)) {
1634 return tevent_req_post(req, ev);
1637 non_spnego_creds_done:
1639 in_buf_size = CLI_BUFFER_SIZE;
1640 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1641 in_vc_num = cli_state_get_vc_num(cli);
1642 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1643 in_native_os = "Unix";
1644 in_native_lm = "Samba";
1646 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1647 uint32_t in_capabilities = 0;
1649 in_capabilities = cli_session_setup_capabilities(cli, 0);
1652 * For now we keep the same values as before,
1653 * we may remove these in a separate commit later.
1657 subreq = smb1cli_session_setup_nt1_send(state, ev,
1668 state->apassword_blob,
1669 state->upassword_blob,
1673 if (tevent_req_nomem(subreq, req)) {
1674 return tevent_req_post(req, ev);
1676 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1682 * For now we keep the same values as before,
1683 * we may remove these in a separate commit later.
1688 subreq = smb1cli_session_setup_lm21_send(state, ev,
1699 state->apassword_blob,
1702 if (tevent_req_nomem(subreq, req)) {
1703 return tevent_req_post(req, ev);
1705 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1710 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1712 struct tevent_req *req = tevent_req_callback_data(
1713 subreq, struct tevent_req);
1716 status = cli_session_setup_spnego_recv(subreq);
1717 TALLOC_FREE(subreq);
1718 if (!ADS_ERR_OK(status)) {
1719 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1720 tevent_req_nterror(req, ads_ntstatus(status));
1723 tevent_req_done(req);
1726 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1728 struct tevent_req *req = tevent_req_callback_data(
1729 subreq, struct tevent_req);
1730 struct cli_session_setup_creds_state *state = tevent_req_data(
1731 req, struct cli_session_setup_creds_state);
1732 struct cli_state *cli = state->cli;
1734 struct iovec *recv_iov = NULL;
1735 const uint8_t *inbuf = NULL;
1738 status = smb1cli_session_setup_nt1_recv(subreq, state,
1741 &state->out_native_os,
1742 &state->out_native_lm,
1743 &state->out_primary_domain);
1744 TALLOC_FREE(subreq);
1745 if (tevent_req_nterror(req, status)) {
1746 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1750 status = cli_state_update_after_sesssetup(state->cli,
1751 state->out_native_os,
1752 state->out_native_lm,
1753 state->out_primary_domain);
1754 if (tevent_req_nterror(req, status)) {
1758 ok = smb1cli_conn_activate_signing(cli->conn,
1760 state->upassword_blob);
1762 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1764 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1769 if (state->session_key.data) {
1770 struct smbXcli_session *session = cli->smb1.session;
1772 status = smb1cli_session_set_session_key(session,
1773 state->session_key);
1774 if (tevent_req_nterror(req, status)) {
1779 tevent_req_done(req);
1782 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1784 struct tevent_req *req = tevent_req_callback_data(
1785 subreq, struct tevent_req);
1786 struct cli_session_setup_creds_state *state = tevent_req_data(
1787 req, struct cli_session_setup_creds_state);
1790 status = smb1cli_session_setup_lm21_recv(subreq, state,
1791 &state->out_native_os,
1792 &state->out_native_lm);
1793 TALLOC_FREE(subreq);
1794 if (tevent_req_nterror(req, status)) {
1795 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1799 status = cli_state_update_after_sesssetup(state->cli,
1800 state->out_native_os,
1801 state->out_native_lm,
1803 if (tevent_req_nterror(req, status)) {
1807 tevent_req_done(req);
1810 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1812 return tevent_req_simple_recv_ntstatus(req);
1815 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1816 struct cli_credentials *creds)
1818 struct tevent_context *ev;
1819 struct tevent_req *req;
1820 NTSTATUS status = NT_STATUS_NO_MEMORY;
1822 if (smbXcli_conn_has_async_calls(cli->conn)) {
1823 return NT_STATUS_INVALID_PARAMETER;
1825 ev = samba_tevent_context_init(talloc_tos());
1829 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1833 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1836 status = cli_session_setup_creds_recv(req);
1842 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1845 struct cli_credentials *creds = NULL;
1847 creds = cli_credentials_init_anon(cli);
1848 if (creds == NULL) {
1849 return NT_STATUS_NO_MEMORY;
1852 status = cli_session_setup_creds(cli, creds);
1854 if (!NT_STATUS_IS_OK(status)) {
1858 return NT_STATUS_OK;
1861 /****************************************************************************
1863 *****************************************************************************/
1865 struct cli_ulogoff_state {
1866 struct cli_state *cli;
1870 static void cli_ulogoff_done(struct tevent_req *subreq);
1872 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1873 struct tevent_context *ev,
1874 struct cli_state *cli)
1876 struct tevent_req *req, *subreq;
1877 struct cli_ulogoff_state *state;
1879 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1885 SCVAL(state->vwv+0, 0, 0xFF);
1886 SCVAL(state->vwv+1, 0, 0);
1887 SSVAL(state->vwv+2, 0, 0);
1889 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1891 if (tevent_req_nomem(subreq, req)) {
1892 return tevent_req_post(req, ev);
1894 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1898 static void cli_ulogoff_done(struct tevent_req *subreq)
1900 struct tevent_req *req = tevent_req_callback_data(
1901 subreq, struct tevent_req);
1902 struct cli_ulogoff_state *state = tevent_req_data(
1903 req, struct cli_ulogoff_state);
1906 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1907 if (tevent_req_nterror(req, status)) {
1910 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1911 tevent_req_done(req);
1914 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1916 return tevent_req_simple_recv_ntstatus(req);
1919 NTSTATUS cli_ulogoff(struct cli_state *cli)
1921 struct tevent_context *ev;
1922 struct tevent_req *req;
1923 NTSTATUS status = NT_STATUS_NO_MEMORY;
1925 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1926 status = smb2cli_logoff(cli->conn,
1929 if (!NT_STATUS_IS_OK(status)) {
1932 smb2cli_session_set_id_and_flags(cli->smb2.session,
1934 return NT_STATUS_OK;
1937 if (smbXcli_conn_has_async_calls(cli->conn)) {
1938 return NT_STATUS_INVALID_PARAMETER;
1940 ev = samba_tevent_context_init(talloc_tos());
1944 req = cli_ulogoff_send(ev, ev, cli);
1948 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1951 status = cli_ulogoff_recv(req);
1957 /****************************************************************************
1959 ****************************************************************************/
1961 struct cli_tcon_andx_state {
1962 struct cli_state *cli;
1967 static void cli_tcon_andx_done(struct tevent_req *subreq);
1969 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1970 struct tevent_context *ev,
1971 struct cli_state *cli,
1972 const char *share, const char *dev,
1973 const char *pass, int passlen,
1974 struct tevent_req **psmbreq)
1976 struct tevent_req *req, *subreq;
1977 struct cli_tcon_andx_state *state;
1982 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1983 uint16_t tcon_flags = 0;
1987 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1994 TALLOC_FREE(cli->smb1.tcon);
1995 cli->smb1.tcon = smbXcli_tcon_create(cli);
1996 if (tevent_req_nomem(cli->smb1.tcon, req)) {
1997 return tevent_req_post(req, ev);
1999 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
2001 cli->share = talloc_strdup(cli, share);
2006 /* in user level security don't send a password now */
2007 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2010 } else if (pass == NULL) {
2011 DEBUG(1, ("Server not using user level security and no "
2012 "password supplied.\n"));
2016 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2017 *pass && passlen != 24) {
2018 if (!lp_client_lanman_auth()) {
2019 DEBUG(1, ("Server requested LANMAN password "
2020 "(share-level security) but "
2021 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2026 * Non-encrypted passwords - convert to DOS codepage before
2029 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2031 pass = (const char *)p24;
2033 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2034 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2038 if (!lp_client_plaintext_auth() && (*pass)) {
2039 DEBUG(1, ("Server requested PLAINTEXT "
2041 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2046 * Non-encrypted passwords - convert to DOS codepage
2049 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2050 if (tevent_req_nomem(tmp_pass, req)) {
2051 return tevent_req_post(req, ev);
2053 tmp_pass = trans2_bytes_push_str(tmp_pass,
2054 false, /* always DOS */
2058 if (tevent_req_nomem(tmp_pass, req)) {
2059 return tevent_req_post(req, ev);
2061 pass = (const char *)tmp_pass;
2062 passlen = talloc_get_size(tmp_pass);
2066 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2067 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2069 SCVAL(vwv+0, 0, 0xFF);
2072 SSVAL(vwv+2, 0, tcon_flags);
2073 SSVAL(vwv+3, 0, passlen);
2075 if (passlen && pass) {
2076 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2078 bytes = talloc_array(state, uint8_t, 0);
2084 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2085 smbXcli_conn_remote_name(cli->conn), share);
2090 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2095 * Add the devicetype
2097 tmp = talloc_strdup_upper(talloc_tos(), dev);
2102 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2105 if (bytes == NULL) {
2110 state->bytes.iov_base = (void *)bytes;
2111 state->bytes.iov_len = talloc_get_size(bytes);
2113 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2115 if (subreq == NULL) {
2119 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2124 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2125 return tevent_req_post(req, ev);
2128 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2129 struct tevent_context *ev,
2130 struct cli_state *cli,
2131 const char *share, const char *dev,
2132 const char *pass, int passlen)
2134 struct tevent_req *req, *subreq;
2137 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2142 if (subreq == NULL) {
2145 status = smb1cli_req_chain_submit(&subreq, 1);
2146 if (tevent_req_nterror(req, status)) {
2147 return tevent_req_post(req, ev);
2152 static void cli_tcon_andx_done(struct tevent_req *subreq)
2154 struct tevent_req *req = tevent_req_callback_data(
2155 subreq, struct tevent_req);
2156 struct cli_tcon_andx_state *state = tevent_req_data(
2157 req, struct cli_tcon_andx_state);
2158 struct cli_state *cli = state->cli;
2166 uint16_t optional_support = 0;
2168 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2169 &num_bytes, &bytes);
2170 TALLOC_FREE(subreq);
2171 if (tevent_req_nterror(req, status)) {
2175 inhdr = in + NBT_HDR_SIZE;
2178 if (pull_string_talloc(cli,
2179 (const char *)inhdr,
2180 SVAL(inhdr, HDR_FLG2),
2184 STR_TERMINATE|STR_ASCII) == -1) {
2185 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2189 cli->dev = talloc_strdup(cli, "");
2190 if (cli->dev == NULL) {
2191 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2196 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2197 /* almost certainly win95 - enable bug fixes */
2202 * Make sure that we have the optional support 16-bit field. WCT > 2.
2203 * Avoids issues when connecting to Win9x boxes sharing files
2206 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2207 optional_support = SVAL(vwv+2, 0);
2210 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2211 smb1cli_session_protect_session_key(cli->smb1.session);
2214 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2215 SVAL(inhdr, HDR_TID),
2217 0, /* maximal_access */
2218 0, /* guest_maximal_access */
2220 NULL); /* fs_type */
2222 tevent_req_done(req);
2225 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2227 return tevent_req_simple_recv_ntstatus(req);
2230 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2231 const char *dev, const char *pass, int passlen)
2233 TALLOC_CTX *frame = talloc_stackframe();
2234 struct tevent_context *ev;
2235 struct tevent_req *req;
2236 NTSTATUS status = NT_STATUS_NO_MEMORY;
2238 if (smbXcli_conn_has_async_calls(cli->conn)) {
2240 * Can't use sync call while an async call is in flight
2242 status = NT_STATUS_INVALID_PARAMETER;
2246 ev = samba_tevent_context_init(frame);
2251 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2256 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2260 status = cli_tcon_andx_recv(req);
2266 struct cli_tree_connect_state {
2267 struct cli_state *cli;
2270 static struct tevent_req *cli_raw_tcon_send(
2271 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2272 const char *service, const char *pass, const char *dev);
2273 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2274 uint16_t *max_xmit, uint16_t *tid);
2276 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2277 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2278 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2280 static struct tevent_req *cli_tree_connect_send(
2281 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2282 const char *share, const char *dev, const char *pass)
2284 struct tevent_req *req, *subreq;
2285 struct cli_tree_connect_state *state;
2291 passlen = strlen(pass) + 1;
2293 req = tevent_req_create(mem_ctx, &state,
2294 struct cli_tree_connect_state);
2300 cli->share = talloc_strdup(cli, share);
2301 if (tevent_req_nomem(cli->share, req)) {
2302 return tevent_req_post(req, ev);
2305 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2308 TALLOC_FREE(cli->smb2.tcon);
2309 cli->smb2.tcon = smbXcli_tcon_create(cli);
2310 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2311 return tevent_req_post(req, ev);
2314 unc = talloc_asprintf(state, "\\\\%s\\%s",
2315 smbXcli_conn_remote_name(cli->conn),
2317 if (tevent_req_nomem(unc, req)) {
2318 return tevent_req_post(req, ev);
2321 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2322 cli->smb2.session, cli->smb2.tcon,
2325 if (tevent_req_nomem(subreq, req)) {
2326 return tevent_req_post(req, ev);
2328 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2333 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2334 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2336 if (tevent_req_nomem(subreq, req)) {
2337 return tevent_req_post(req, ev);
2339 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2344 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2345 if (tevent_req_nomem(subreq, req)) {
2346 return tevent_req_post(req, ev);
2348 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2353 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2355 NTSTATUS status = smb2cli_tcon_recv(subreq);
2356 tevent_req_simple_finish_ntstatus(subreq, status);
2359 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2361 NTSTATUS status = cli_tcon_andx_recv(subreq);
2362 tevent_req_simple_finish_ntstatus(subreq, status);
2365 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2367 struct tevent_req *req = tevent_req_callback_data(
2368 subreq, struct tevent_req);
2369 struct cli_tree_connect_state *state = tevent_req_data(
2370 req, struct cli_tree_connect_state);
2372 uint16_t max_xmit = 0;
2375 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2376 if (tevent_req_nterror(req, status)) {
2380 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2382 0, /* optional_support */
2383 0, /* maximal_access */
2384 0, /* guest_maximal_access */
2386 NULL); /* fs_type */
2388 tevent_req_done(req);
2391 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2393 return tevent_req_simple_recv_ntstatus(req);
2396 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2397 const char *dev, const char *pass)
2399 struct tevent_context *ev;
2400 struct tevent_req *req;
2401 NTSTATUS status = NT_STATUS_NO_MEMORY;
2403 if (smbXcli_conn_has_async_calls(cli->conn)) {
2404 return NT_STATUS_INVALID_PARAMETER;
2406 ev = samba_tevent_context_init(talloc_tos());
2410 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2414 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2417 status = cli_tree_connect_recv(req);
2423 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2424 const char *share, const char *dev,
2425 struct cli_credentials *creds)
2427 const char *pw = NULL;
2429 if (creds != NULL) {
2430 pw = cli_credentials_get_password(creds);
2433 return cli_tree_connect(cli, share, dev, pw);
2436 /****************************************************************************
2437 Send a tree disconnect.
2438 ****************************************************************************/
2440 struct cli_tdis_state {
2441 struct cli_state *cli;
2444 static void cli_tdis_done(struct tevent_req *subreq);
2446 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2447 struct tevent_context *ev,
2448 struct cli_state *cli)
2450 struct tevent_req *req, *subreq;
2451 struct cli_tdis_state *state;
2453 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2459 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2460 if (tevent_req_nomem(subreq, req)) {
2461 return tevent_req_post(req, ev);
2463 tevent_req_set_callback(subreq, cli_tdis_done, req);
2467 static void cli_tdis_done(struct tevent_req *subreq)
2469 struct tevent_req *req = tevent_req_callback_data(
2470 subreq, struct tevent_req);
2471 struct cli_tdis_state *state = tevent_req_data(
2472 req, struct cli_tdis_state);
2475 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2476 TALLOC_FREE(subreq);
2477 if (tevent_req_nterror(req, status)) {
2480 TALLOC_FREE(state->cli->smb1.tcon);
2481 tevent_req_done(req);
2484 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2486 return tevent_req_simple_recv_ntstatus(req);
2489 NTSTATUS cli_tdis(struct cli_state *cli)
2491 struct tevent_context *ev;
2492 struct tevent_req *req;
2493 NTSTATUS status = NT_STATUS_NO_MEMORY;
2495 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2496 status = smb2cli_tdis(cli->conn,
2500 if (NT_STATUS_IS_OK(status)) {
2501 TALLOC_FREE(cli->smb2.tcon);
2506 if (smbXcli_conn_has_async_calls(cli->conn)) {
2507 return NT_STATUS_INVALID_PARAMETER;
2509 ev = samba_tevent_context_init(talloc_tos());
2513 req = cli_tdis_send(ev, ev, cli);
2517 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2520 status = cli_tdis_recv(req);
2526 struct cli_connect_sock_state {
2527 const char **called_names;
2528 const char **calling_names;
2534 static void cli_connect_sock_done(struct tevent_req *subreq);
2537 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2541 static struct tevent_req *cli_connect_sock_send(
2542 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2543 const char *host, int name_type, const struct sockaddr_storage *pss,
2544 const char *myname, uint16_t port)
2546 struct tevent_req *req, *subreq;
2547 struct cli_connect_sock_state *state;
2548 struct sockaddr_storage *addrs = NULL;
2550 unsigned num_addrs = 0;
2553 req = tevent_req_create(mem_ctx, &state,
2554 struct cli_connect_sock_state);
2559 if ((pss == NULL) || is_zero_addr(pss)) {
2562 * Here we cheat. resolve_name_list is not async at all. So
2563 * this call will only be really async if the name lookup has
2564 * been done externally.
2567 status = resolve_name_list(state, host, name_type,
2568 &addrs, &num_addrs);
2569 if (tevent_req_nterror(req, status)) {
2570 return tevent_req_post(req, ev);
2573 addrs = talloc_array(state, struct sockaddr_storage, 1);
2574 if (tevent_req_nomem(addrs, req)) {
2575 return tevent_req_post(req, ev);
2581 state->called_names = talloc_array(state, const char *, num_addrs);
2582 if (tevent_req_nomem(state->called_names, req)) {
2583 return tevent_req_post(req, ev);
2585 state->called_types = talloc_array(state, int, num_addrs);
2586 if (tevent_req_nomem(state->called_types, req)) {
2587 return tevent_req_post(req, ev);
2589 state->calling_names = talloc_array(state, const char *, num_addrs);
2590 if (tevent_req_nomem(state->calling_names, req)) {
2591 return tevent_req_post(req, ev);
2593 for (i=0; i<num_addrs; i++) {
2594 state->called_names[i] = host;
2595 state->called_types[i] = name_type;
2596 state->calling_names[i] = myname;
2599 subreq = smbsock_any_connect_send(
2600 state, ev, addrs, state->called_names, state->called_types,
2601 state->calling_names, NULL, num_addrs, port);
2602 if (tevent_req_nomem(subreq, req)) {
2603 return tevent_req_post(req, ev);
2605 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2609 static void cli_connect_sock_done(struct tevent_req *subreq)
2611 struct tevent_req *req = tevent_req_callback_data(
2612 subreq, struct tevent_req);
2613 struct cli_connect_sock_state *state = tevent_req_data(
2614 req, struct cli_connect_sock_state);
2617 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2619 TALLOC_FREE(subreq);
2620 if (tevent_req_nterror(req, status)) {
2623 set_socket_options(state->fd, lp_socket_options());
2624 tevent_req_done(req);
2627 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2628 int *pfd, uint16_t *pport)
2630 struct cli_connect_sock_state *state = tevent_req_data(
2631 req, struct cli_connect_sock_state);
2634 if (tevent_req_is_nterror(req, &status)) {
2638 *pport = state->port;
2639 return NT_STATUS_OK;
2642 struct cli_connect_nb_state {
2643 const char *desthost;
2644 enum smb_signing_setting signing_state;
2646 struct cli_state *cli;
2649 static void cli_connect_nb_done(struct tevent_req *subreq);
2651 static struct tevent_req *cli_connect_nb_send(
2652 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2653 const char *host, const struct sockaddr_storage *dest_ss,
2654 uint16_t port, int name_type, const char *myname,
2655 enum smb_signing_setting signing_state, int flags)
2657 struct tevent_req *req, *subreq;
2658 struct cli_connect_nb_state *state;
2660 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2664 state->signing_state = signing_state;
2665 state->flags = flags;
2668 char *p = strchr(host, '#');
2671 name_type = strtol(p+1, NULL, 16);
2672 host = talloc_strndup(state, host, p - host);
2673 if (tevent_req_nomem(host, req)) {
2674 return tevent_req_post(req, ev);
2678 state->desthost = host;
2679 } else if (dest_ss != NULL) {
2680 state->desthost = print_canonical_sockaddr(state, dest_ss);
2681 if (tevent_req_nomem(state->desthost, req)) {
2682 return tevent_req_post(req, ev);
2685 /* No host or dest_ss given. Error out. */
2686 tevent_req_error(req, EINVAL);
2687 return tevent_req_post(req, ev);
2690 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2692 if (tevent_req_nomem(subreq, req)) {
2693 return tevent_req_post(req, ev);
2695 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2699 static void cli_connect_nb_done(struct tevent_req *subreq)
2701 struct tevent_req *req = tevent_req_callback_data(
2702 subreq, struct tevent_req);
2703 struct cli_connect_nb_state *state = tevent_req_data(
2704 req, struct cli_connect_nb_state);
2709 status = cli_connect_sock_recv(subreq, &fd, &port);
2710 TALLOC_FREE(subreq);
2711 if (tevent_req_nterror(req, status)) {
2715 state->cli = cli_state_create(state, fd, state->desthost,
2716 state->signing_state, state->flags);
2717 if (tevent_req_nomem(state->cli, req)) {
2721 tevent_req_done(req);
2724 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2725 struct cli_state **pcli)
2727 struct cli_connect_nb_state *state = tevent_req_data(
2728 req, struct cli_connect_nb_state);
2731 if (tevent_req_is_nterror(req, &status)) {
2734 *pcli = talloc_move(NULL, &state->cli);
2735 return NT_STATUS_OK;
2738 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2739 uint16_t port, int name_type, const char *myname,
2740 enum smb_signing_setting signing_state, int flags, struct cli_state **pcli)
2742 struct tevent_context *ev;
2743 struct tevent_req *req;
2744 NTSTATUS status = NT_STATUS_NO_MEMORY;
2746 ev = samba_tevent_context_init(talloc_tos());
2750 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2751 myname, signing_state, flags);
2755 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2758 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2761 status = cli_connect_nb_recv(req, pcli);
2767 struct cli_start_connection_state {
2768 struct tevent_context *ev;
2769 struct cli_state *cli;
2772 struct smb2_negotiate_contexts *negotiate_contexts;
2775 static void cli_start_connection_connected(struct tevent_req *subreq);
2776 static void cli_start_connection_done(struct tevent_req *subreq);
2779 establishes a connection to after the negprot.
2780 @param output_cli A fully initialised cli structure, non-null only on success
2781 @param dest_host The netbios name of the remote host
2782 @param dest_ss (optional) The destination IP, NULL for name based lookup
2783 @param port (optional) The destination port (0 for default)
2786 static struct tevent_req *cli_start_connection_send(
2787 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2788 const char *my_name, const char *dest_host,
2789 const struct sockaddr_storage *dest_ss, int port,
2790 enum smb_signing_setting signing_state, int flags,
2791 struct smb2_negotiate_contexts *negotiate_contexts)
2793 struct tevent_req *req, *subreq;
2794 struct cli_start_connection_state *state;
2796 req = tevent_req_create(mem_ctx, &state,
2797 struct cli_start_connection_state);
2803 if (flags & CLI_FULL_CONNECTION_IPC) {
2804 state->min_protocol = lp_client_ipc_min_protocol();
2805 state->max_protocol = lp_client_ipc_max_protocol();
2807 state->min_protocol = lp_client_min_protocol();
2808 state->max_protocol = lp_client_max_protocol();
2811 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2812 state->max_protocol = MIN(state->max_protocol,
2814 state->min_protocol = MIN(state->min_protocol,
2815 state->max_protocol);
2818 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2819 state->min_protocol = MAX(state->min_protocol,
2821 state->max_protocol = MAX(state->max_protocol,
2822 state->min_protocol);
2825 state->negotiate_contexts = talloc_zero(
2826 state, struct smb2_negotiate_contexts);
2827 if (tevent_req_nomem(state->negotiate_contexts, req)) {
2828 return tevent_req_post(req, ev);
2831 if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
2834 status = smb2_negotiate_context_add(
2835 state->negotiate_contexts,
2836 state->negotiate_contexts,
2837 SMB2_POSIX_EXTENSIONS_AVAILABLE,
2838 (const uint8_t *)SMB2_CREATE_TAG_POSIX,
2839 strlen(SMB2_CREATE_TAG_POSIX));
2840 if (tevent_req_nterror(req, status)) {
2841 return tevent_req_post(req, ev);
2845 if (negotiate_contexts != NULL) {
2848 for (i=0; i<negotiate_contexts->num_contexts; i++) {
2849 struct smb2_negotiate_context *ctx =
2850 &negotiate_contexts->contexts[i];
2853 status = smb2_negotiate_context_add(
2854 state->negotiate_contexts,
2855 state->negotiate_contexts,
2859 if (tevent_req_nterror(req, status)) {
2860 return tevent_req_post(req, ev);
2865 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2866 0x20, my_name, signing_state, flags);
2867 if (tevent_req_nomem(subreq, req)) {
2868 return tevent_req_post(req, ev);
2870 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2874 static void cli_start_connection_connected(struct tevent_req *subreq)
2876 struct tevent_req *req = tevent_req_callback_data(
2877 subreq, struct tevent_req);
2878 struct cli_start_connection_state *state = tevent_req_data(
2879 req, struct cli_start_connection_state);
2882 status = cli_connect_nb_recv(subreq, &state->cli);
2883 TALLOC_FREE(subreq);
2884 if (tevent_req_nterror(req, status)) {
2888 subreq = smbXcli_negprot_send(
2892 state->cli->timeout,
2893 state->min_protocol,
2894 state->max_protocol,
2895 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
2896 state->negotiate_contexts);
2897 if (tevent_req_nomem(subreq, req)) {
2900 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2903 static void cli_start_connection_done(struct tevent_req *subreq)
2905 struct tevent_req *req = tevent_req_callback_data(
2906 subreq, struct tevent_req);
2907 struct cli_start_connection_state *state = tevent_req_data(
2908 req, struct cli_start_connection_state);
2911 status = smbXcli_negprot_recv(subreq, NULL, NULL);
2912 TALLOC_FREE(subreq);
2913 if (tevent_req_nterror(req, status)) {
2917 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2918 /* Ensure we ask for some initial credits. */
2919 smb2cli_conn_set_max_credits(state->cli->conn,
2920 DEFAULT_SMB2_MAX_CREDITS);
2923 tevent_req_done(req);
2926 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2927 struct cli_state **output_cli)
2929 struct cli_start_connection_state *state = tevent_req_data(
2930 req, struct cli_start_connection_state);
2933 if (tevent_req_is_nterror(req, &status)) {
2936 *output_cli = state->cli;
2938 return NT_STATUS_OK;
2941 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2942 const char *my_name,
2943 const char *dest_host,
2944 const struct sockaddr_storage *dest_ss, int port,
2945 enum smb_signing_setting signing_state, int flags)
2947 struct tevent_context *ev;
2948 struct tevent_req *req;
2949 NTSTATUS status = NT_STATUS_NO_MEMORY;
2951 ev = samba_tevent_context_init(talloc_tos());
2955 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2956 port, signing_state, flags, NULL);
2960 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2963 status = cli_start_connection_recv(req, output_cli);
2969 struct cli_smb1_setup_encryption_blob_state {
2974 uint16_t enc_ctx_id;
2977 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2979 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2980 struct tevent_context *ev,
2981 struct cli_state *cli,
2984 struct tevent_req *req = NULL;
2985 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2986 struct tevent_req *subreq = NULL;
2988 req = tevent_req_create(mem_ctx, &state,
2989 struct cli_smb1_setup_encryption_blob_state);
2994 if (in.length > CLI_BUFFER_SIZE) {
2995 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2996 return tevent_req_post(req, ev);
2999 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
3000 SSVAL(state->param, 0, 0);
3001 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
3003 subreq = smb1cli_trans_send(state, ev, cli->conn,
3011 NULL, /* pipe_name */
3017 in.data, in.length, CLI_BUFFER_SIZE);
3018 if (tevent_req_nomem(subreq, req)) {
3019 return tevent_req_post(req, ev);
3021 tevent_req_set_callback(subreq,
3022 cli_smb1_setup_encryption_blob_done,
3028 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
3030 struct tevent_req *req =
3031 tevent_req_callback_data(subreq,
3033 struct cli_smb1_setup_encryption_blob_state *state =
3034 tevent_req_data(req,
3035 struct cli_smb1_setup_encryption_blob_state);
3036 uint8_t *rparam=NULL, *rdata=NULL;
3037 uint32_t num_rparam, num_rdata;
3040 status = smb1cli_trans_recv(subreq, state,
3041 NULL, /* recv_flags */
3042 NULL, 0, NULL, /* rsetup */
3043 &rparam, 0, &num_rparam,
3044 &rdata, 0, &num_rdata);
3045 TALLOC_FREE(subreq);
3046 state->status = status;
3047 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
3048 status = NT_STATUS_OK;
3050 if (tevent_req_nterror(req, status)) {
3054 if (num_rparam == 2) {
3055 state->enc_ctx_id = SVAL(rparam, 0);
3057 TALLOC_FREE(rparam);
3059 state->out = data_blob_const(rdata, num_rdata);
3061 tevent_req_done(req);
3064 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
3065 TALLOC_CTX *mem_ctx,
3067 uint16_t *enc_ctx_id)
3069 struct cli_smb1_setup_encryption_blob_state *state =
3070 tevent_req_data(req,
3071 struct cli_smb1_setup_encryption_blob_state);
3074 if (tevent_req_is_nterror(req, &status)) {
3075 tevent_req_received(req);
3079 status = state->status;
3082 talloc_steal(mem_ctx, out->data);
3084 *enc_ctx_id = state->enc_ctx_id;
3086 tevent_req_received(req);
3090 struct cli_smb1_setup_encryption_state {
3091 struct tevent_context *ev;
3092 struct cli_state *cli;
3093 struct smb_trans_enc_state *es;
3100 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3101 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3102 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3103 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3104 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3106 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3107 struct tevent_context *ev,
3108 struct cli_state *cli,
3109 struct cli_credentials *creds)
3111 struct tevent_req *req = NULL;
3112 struct cli_smb1_setup_encryption_state *state = NULL;
3113 struct auth_generic_state *ags = NULL;
3114 const DATA_BLOB *b = NULL;
3115 bool auth_requested = false;
3116 const char *target_service = NULL;
3117 const char *target_hostname = NULL;
3120 req = tevent_req_create(mem_ctx, &state,
3121 struct cli_smb1_setup_encryption_state);
3128 auth_requested = cli_credentials_authentication_requested(creds);
3129 if (!auth_requested) {
3130 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3131 return tevent_req_post(req, ev);
3134 target_service = "cifs";
3135 target_hostname = smbXcli_conn_remote_name(cli->conn);
3137 status = cli_session_creds_prepare_krb5(cli, creds);
3138 if (tevent_req_nterror(req, status)) {
3139 return tevent_req_post(req, ev);
3142 state->es = talloc_zero(state, struct smb_trans_enc_state);
3143 if (tevent_req_nomem(state->es, req)) {
3144 return tevent_req_post(req, ev);
3147 status = auth_generic_client_prepare(state->es, &ags);
3148 if (tevent_req_nterror(req, status)) {
3149 return tevent_req_post(req, ev);
3152 gensec_want_feature(ags->gensec_security,
3153 GENSEC_FEATURE_SIGN);
3154 gensec_want_feature(ags->gensec_security,
3155 GENSEC_FEATURE_SEAL);
3157 status = auth_generic_set_creds(ags, creds);
3158 if (tevent_req_nterror(req, status)) {
3159 return tevent_req_post(req, ev);
3162 if (target_service != NULL) {
3163 status = gensec_set_target_service(ags->gensec_security,
3165 if (tevent_req_nterror(req, status)) {
3166 return tevent_req_post(req, ev);
3170 if (target_hostname != NULL) {
3171 status = gensec_set_target_hostname(ags->gensec_security,
3173 if (tevent_req_nterror(req, status)) {
3174 return tevent_req_post(req, ev);
3178 gensec_set_max_update_size(ags->gensec_security,
3181 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3183 state->blob_in = *b;
3186 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3187 if (tevent_req_nterror(req, status)) {
3188 return tevent_req_post(req, ev);
3192 * We only need the gensec_security part from here.
3194 state->es->gensec_security = talloc_move(state->es,
3195 &ags->gensec_security);
3198 cli_smb1_setup_encryption_local_next(req);
3199 if (!tevent_req_is_in_progress(req)) {
3200 return tevent_req_post(req, ev);
3206 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3208 struct cli_smb1_setup_encryption_state *state =
3209 tevent_req_data(req,
3210 struct cli_smb1_setup_encryption_state);
3211 struct tevent_req *subreq = NULL;
3213 if (state->local_ready) {
3214 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3218 subreq = gensec_update_send(state, state->ev,
3219 state->es->gensec_security,
3221 if (tevent_req_nomem(subreq, req)) {
3224 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3227 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3229 struct tevent_req *req =
3230 tevent_req_callback_data(subreq,
3232 struct cli_smb1_setup_encryption_state *state =
3233 tevent_req_data(req,
3234 struct cli_smb1_setup_encryption_state);
3237 status = gensec_update_recv(subreq, state, &state->blob_out);
3238 TALLOC_FREE(subreq);
3239 state->blob_in = data_blob_null;
3240 if (!NT_STATUS_IS_OK(status) &&
3241 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3243 tevent_req_nterror(req, status);
3247 if (NT_STATUS_IS_OK(status)) {
3248 state->local_ready = true;
3252 * We always get NT_STATUS_OK from the server even if it is not ready.
3253 * So guess the server is ready when we are ready and already sent
3254 * our last blob to the server.
3256 if (state->local_ready && state->blob_out.length == 0) {
3257 state->remote_ready = true;
3260 if (state->local_ready && state->remote_ready) {
3261 cli_smb1_setup_encryption_ready(req);
3265 cli_smb1_setup_encryption_remote_next(req);
3268 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3270 struct cli_smb1_setup_encryption_state *state =
3271 tevent_req_data(req,
3272 struct cli_smb1_setup_encryption_state);
3273 struct tevent_req *subreq = NULL;
3275 if (state->remote_ready) {
3276 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3280 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3281 state->cli, state->blob_out);
3282 if (tevent_req_nomem(subreq, req)) {
3285 tevent_req_set_callback(subreq,
3286 cli_smb1_setup_encryption_remote_done,
3290 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3292 struct tevent_req *req =
3293 tevent_req_callback_data(subreq,
3295 struct cli_smb1_setup_encryption_state *state =
3296 tevent_req_data(req,
3297 struct cli_smb1_setup_encryption_state);
3300 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3302 &state->es->enc_ctx_num);
3303 TALLOC_FREE(subreq);
3304 data_blob_free(&state->blob_out);
3305 if (!NT_STATUS_IS_OK(status) &&
3306 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3308 tevent_req_nterror(req, status);
3313 * We always get NT_STATUS_OK even if the server is not ready.
3314 * So guess the server is ready when we are ready and sent
3315 * our last blob to the server.
3317 if (state->local_ready) {
3318 state->remote_ready = true;
3321 if (state->local_ready && state->remote_ready) {
3322 cli_smb1_setup_encryption_ready(req);
3326 cli_smb1_setup_encryption_local_next(req);
3329 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3331 struct cli_smb1_setup_encryption_state *state =
3332 tevent_req_data(req,
3333 struct cli_smb1_setup_encryption_state);
3334 struct smb_trans_enc_state *es = NULL;
3336 if (state->blob_in.length != 0) {
3337 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3341 if (state->blob_out.length != 0) {
3342 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3346 es = talloc_move(state->cli->conn, &state->es);
3348 smb1cli_conn_set_encryption(state->cli->conn, es);
3351 tevent_req_done(req);
3354 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3356 return tevent_req_simple_recv_ntstatus(req);
3359 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3360 struct cli_credentials *creds)
3362 struct tevent_context *ev = NULL;
3363 struct tevent_req *req = NULL;
3364 NTSTATUS status = NT_STATUS_NO_MEMORY;
3366 ev = samba_tevent_context_init(talloc_tos());
3370 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3374 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3377 status = cli_smb1_setup_encryption_recv(req);
3384 establishes a connection right up to doing tconX, password specified.
3385 @param output_cli A fully initialised cli structure, non-null only on success
3386 @param dest_host The netbios name of the remote host
3387 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3388 @param port (optional) The destination port (0 for default)
3389 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3390 @param service_type The 'type' of service.
3391 @param creds The used user credentials
3394 struct cli_full_connection_creds_state {
3395 struct tevent_context *ev;
3396 const char *service;
3397 const char *service_type;
3398 struct cli_credentials *creds;
3400 struct cli_state *cli;
3403 static int cli_full_connection_creds_state_destructor(
3404 struct cli_full_connection_creds_state *s)
3406 if (s->cli != NULL) {
3407 cli_shutdown(s->cli);
3413 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3414 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3415 static void cli_full_connection_creds_enc_start(struct tevent_req *req);
3416 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
3417 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
3418 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
3419 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
3420 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
3421 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3422 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3424 struct tevent_req *cli_full_connection_creds_send(
3425 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3426 const char *my_name, const char *dest_host,
3427 const struct sockaddr_storage *dest_ss, int port,
3428 const char *service, const char *service_type,
3429 struct cli_credentials *creds,
3431 struct smb2_negotiate_contexts *negotiate_contexts)
3433 struct tevent_req *req, *subreq;
3434 struct cli_full_connection_creds_state *state;
3435 enum smb_signing_setting signing_state;
3436 enum smb_encryption_setting encryption_state =
3437 cli_credentials_get_smb_encryption(creds);
3439 req = tevent_req_create(mem_ctx, &state,
3440 struct cli_full_connection_creds_state);
3444 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3447 state->service = service;
3448 state->service_type = service_type;
3449 state->creds = creds;
3450 state->flags = flags;
3452 if (flags & CLI_FULL_CONNECTION_IPC) {
3453 signing_state = cli_credentials_get_smb_ipc_signing(creds);
3455 signing_state = cli_credentials_get_smb_signing(creds);
3458 if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
3459 if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
3460 encryption_state = SMB_ENCRYPTION_DESIRED;
3464 if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
3465 signing_state = SMB_SIGNING_REQUIRED;
3468 subreq = cli_start_connection_send(
3469 state, ev, my_name, dest_host, dest_ss, port,
3470 signing_state, flags,
3471 negotiate_contexts);
3472 if (tevent_req_nomem(subreq, req)) {
3473 return tevent_req_post(req, ev);
3475 tevent_req_set_callback(subreq,
3476 cli_full_connection_creds_conn_done,
3481 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3483 struct tevent_req *req = tevent_req_callback_data(
3484 subreq, struct tevent_req);
3485 struct cli_full_connection_creds_state *state = tevent_req_data(
3486 req, struct cli_full_connection_creds_state);
3489 status = cli_start_connection_recv(subreq, &state->cli);
3490 TALLOC_FREE(subreq);
3491 if (tevent_req_nterror(req, status)) {
3495 subreq = cli_session_setup_creds_send(
3496 state, state->ev, state->cli, state->creds);
3497 if (tevent_req_nomem(subreq, req)) {
3500 tevent_req_set_callback(subreq,
3501 cli_full_connection_creds_sess_done,
3505 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3507 struct tevent_req *req = tevent_req_callback_data(
3508 subreq, struct tevent_req);
3509 struct cli_full_connection_creds_state *state = tevent_req_data(
3510 req, struct cli_full_connection_creds_state);
3513 status = cli_session_setup_creds_recv(subreq);
3514 TALLOC_FREE(subreq);
3516 if (!NT_STATUS_IS_OK(status) &&
3517 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3519 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3521 state->creds = cli_credentials_init_anon(state);
3522 if (tevent_req_nomem(state->creds, req)) {
3526 subreq = cli_session_setup_creds_send(
3527 state, state->ev, state->cli, state->creds);
3528 if (tevent_req_nomem(subreq, req)) {
3531 tevent_req_set_callback(subreq,
3532 cli_full_connection_creds_sess_done,
3537 if (tevent_req_nterror(req, status)) {
3541 cli_full_connection_creds_enc_start(req);
3544 static void cli_full_connection_creds_enc_start(struct tevent_req *req)
3546 struct cli_full_connection_creds_state *state = tevent_req_data(
3547 req, struct cli_full_connection_creds_state);
3548 enum smb_encryption_setting encryption_state =
3549 cli_credentials_get_smb_encryption(state->creds);
3550 struct tevent_req *subreq = NULL;
3553 if (encryption_state < SMB_ENCRYPTION_DESIRED) {
3554 cli_full_connection_creds_tcon_start(req);
3558 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3559 status = smb2cli_session_encryption_on(state->cli->smb2.session);
3560 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3561 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3562 cli_full_connection_creds_tcon_start(req);
3565 d_printf("Encryption required and "
3566 "server doesn't support "
3567 "SMB3 encryption - failing connect\n");
3568 tevent_req_nterror(req, status);
3570 } else if (!NT_STATUS_IS_OK(status)) {
3571 d_printf("Encryption required and "
3572 "setup failed with error %s.\n",
3574 tevent_req_nterror(req, status);
3578 cli_full_connection_creds_tcon_start(req);
3582 if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
3583 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3584 cli_full_connection_creds_tcon_start(req);
3588 status = NT_STATUS_NOT_SUPPORTED;
3589 d_printf("Encryption required and "
3590 "server doesn't support "
3591 "SMB1 Unix Extensions - failing connect\n");
3592 tevent_req_nterror(req, status);
3597 * We do a tcon on IPC$ just to setup the encryption,
3598 * the real tcon will be encrypted then.
3600 subreq = cli_tree_connect_send(state, state->ev, state->cli,
3601 "IPC$", "IPC", NULL);
3602 if (tevent_req_nomem(subreq, req)) {
3605 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
3608 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
3610 struct tevent_req *req = tevent_req_callback_data(
3611 subreq, struct tevent_req);
3612 struct cli_full_connection_creds_state *state = tevent_req_data(
3613 req, struct cli_full_connection_creds_state);
3616 status = cli_tree_connect_recv(subreq);
3617 TALLOC_FREE(subreq);
3618 if (tevent_req_nterror(req, status)) {
3622 subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
3623 if (tevent_req_nomem(subreq, req)) {
3626 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
3629 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
3631 struct tevent_req *req = tevent_req_callback_data(
3632 subreq, struct tevent_req);
3633 struct cli_full_connection_creds_state *state = tevent_req_data(
3634 req, struct cli_full_connection_creds_state);
3635 enum smb_encryption_setting encryption_state =
3636 cli_credentials_get_smb_encryption(state->creds);
3637 uint16_t major, minor;
3638 uint32_t caplow, caphigh;
3641 status = cli_unix_extensions_version_recv(subreq,
3645 TALLOC_FREE(subreq);
3646 if (!NT_STATUS_IS_OK(status)) {
3647 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3648 /* disconnect ipc$ followed by the real tree connect */
3649 cli_full_connection_creds_enc_tdis(req);
3652 DEBUG(10, ("%s: cli_unix_extensions_version "
3653 "returned %s\n", __func__, nt_errstr(status)));
3654 tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
3658 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
3659 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3660 /* disconnect ipc$ followed by the real tree connect */
3661 cli_full_connection_creds_enc_tdis(req);
3664 DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
3665 "not supported\n", __func__));
3666 tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
3670 subreq = cli_smb1_setup_encryption_send(state, state->ev,
3673 if (tevent_req_nomem(subreq, req)) {
3676 tevent_req_set_callback(subreq,
3677 cli_full_connection_creds_enc_done,
3681 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
3683 struct tevent_req *req = tevent_req_callback_data(
3684 subreq, struct tevent_req);
3687 status = cli_smb1_setup_encryption_recv(subreq);
3688 TALLOC_FREE(subreq);
3689 if (tevent_req_nterror(req, status)) {
3693 /* disconnect ipc$ followed by the real tree connect */
3694 cli_full_connection_creds_enc_tdis(req);
3697 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
3699 struct cli_full_connection_creds_state *state = tevent_req_data(
3700 req, struct cli_full_connection_creds_state);
3701 struct tevent_req *subreq = NULL;
3703 subreq = cli_tdis_send(state, state->ev, state->cli);
3704 if (tevent_req_nomem(subreq, req)) {
3707 tevent_req_set_callback(subreq,
3708 cli_full_connection_creds_enc_finished,
3712 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
3714 struct tevent_req *req = tevent_req_callback_data(
3715 subreq, struct tevent_req);
3718 status = cli_tdis_recv(subreq);
3719 TALLOC_FREE(subreq);
3720 if (tevent_req_nterror(req, status)) {
3724 cli_full_connection_creds_tcon_start(req);
3727 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3729 struct cli_full_connection_creds_state *state = tevent_req_data(
3730 req, struct cli_full_connection_creds_state);
3731 struct tevent_req *subreq = NULL;
3732 const char *password = NULL;
3734 if (state->service == NULL) {
3735 tevent_req_done(req);
3739 password = cli_credentials_get_password(state->creds);
3741 subreq = cli_tree_connect_send(state, state->ev,
3744 state->service_type,
3746 if (tevent_req_nomem(subreq, req)) {
3749 tevent_req_set_callback(subreq,
3750 cli_full_connection_creds_tcon_done,
3754 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3756 struct tevent_req *req = tevent_req_callback_data(
3757 subreq, struct tevent_req);
3760 status = cli_tree_connect_recv(subreq);
3761 TALLOC_FREE(subreq);
3762 if (tevent_req_nterror(req, status)) {
3766 tevent_req_done(req);
3769 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3770 struct cli_state **output_cli)
3772 struct cli_full_connection_creds_state *state = tevent_req_data(
3773 req, struct cli_full_connection_creds_state);
3776 if (tevent_req_is_nterror(req, &status)) {
3779 *output_cli = state->cli;
3780 talloc_set_destructor(state, NULL);
3781 return NT_STATUS_OK;
3784 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3785 const char *my_name,
3786 const char *dest_host,
3787 const struct sockaddr_storage *dest_ss, int port,
3788 const char *service, const char *service_type,
3789 struct cli_credentials *creds,
3792 struct tevent_context *ev;
3793 struct tevent_req *req;
3794 NTSTATUS status = NT_STATUS_NO_MEMORY;
3796 ev = samba_tevent_context_init(talloc_tos());
3800 req = cli_full_connection_creds_send(
3801 ev, ev, my_name, dest_host, dest_ss, port, service,
3802 service_type, creds, flags,
3807 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3810 status = cli_full_connection_creds_recv(req, output_cli);
3816 /****************************************************************************
3817 Send an old style tcon.
3818 ****************************************************************************/
3819 struct cli_raw_tcon_state {
3823 static void cli_raw_tcon_done(struct tevent_req *subreq);
3825 static struct tevent_req *cli_raw_tcon_send(
3826 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3827 const char *service, const char *pass, const char *dev)
3829 struct tevent_req *req, *subreq;
3830 struct cli_raw_tcon_state *state;
3833 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3838 if (!lp_client_plaintext_auth() && (*pass)) {
3839 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3840 " or 'client ntlmv2 auth = yes'\n"));
3841 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3842 return tevent_req_post(req, ev);
3845 TALLOC_FREE(cli->smb1.tcon);
3846 cli->smb1.tcon = smbXcli_tcon_create(cli);
3847 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3848 return tevent_req_post(req, ev);
3850 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3852 bytes = talloc_array(state, uint8_t, 0);
3853 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3854 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3855 service, strlen(service)+1, NULL);
3856 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3857 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3858 pass, strlen(pass)+1, NULL);
3859 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3860 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3861 dev, strlen(dev)+1, NULL);
3863 if (tevent_req_nomem(bytes, req)) {
3864 return tevent_req_post(req, ev);
3867 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3868 talloc_get_size(bytes), bytes);
3869 if (tevent_req_nomem(subreq, req)) {
3870 return tevent_req_post(req, ev);
3872 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3876 static void cli_raw_tcon_done(struct tevent_req *subreq)
3878 struct tevent_req *req = tevent_req_callback_data(
3879 subreq, struct tevent_req);
3880 struct cli_raw_tcon_state *state = tevent_req_data(
3881 req, struct cli_raw_tcon_state);
3884 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3886 TALLOC_FREE(subreq);
3887 if (tevent_req_nterror(req, status)) {
3890 tevent_req_done(req);
3893 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3894 uint16_t *max_xmit, uint16_t *tid)
3896 struct cli_raw_tcon_state *state = tevent_req_data(
3897 req, struct cli_raw_tcon_state);
3900 if (tevent_req_is_nterror(req, &status)) {
3903 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3904 *tid = SVAL(state->ret_vwv + 1, 0);
3905 return NT_STATUS_OK;
3908 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3909 const char *service, const char *pass, const char *dev,
3910 uint16_t *max_xmit, uint16_t *tid)
3912 struct tevent_context *ev;
3913 struct tevent_req *req;
3914 NTSTATUS status = NT_STATUS_NO_MEMORY;
3916 ev = samba_tevent_context_init(talloc_tos());
3920 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3924 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3927 status = cli_raw_tcon_recv(req, max_xmit, tid);
3933 /* Return a cli_state pointing at the IPC$ share for the given server */
3935 struct cli_state *get_ipc_connect(char *server,
3936 struct sockaddr_storage *server_ss,
3937 struct cli_credentials *creds)
3939 struct cli_state *cli;
3941 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3943 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3944 flags |= CLI_FULL_CONNECTION_IPC;
3946 nt_status = cli_full_connection_creds(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3950 if (NT_STATUS_IS_OK(nt_status)) {
3953 if (is_ipaddress(server)) {
3954 /* windows 9* needs a correct NMB name for connections */
3955 fstring remote_name;
3957 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3958 cli = get_ipc_connect(remote_name, server_ss, creds);
3967 * Given the IP address of a master browser on the network, return its
3968 * workgroup and connect to it.
3970 * This function is provided to allow additional processing beyond what
3971 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3972 * browsers and obtain each master browsers' list of domains (in case the
3973 * first master browser is recently on the network and has not yet
3974 * synchronized with other master browsers and therefore does not yet have the
3975 * entire network browse list)
3978 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3979 struct sockaddr_storage *mb_ip,
3980 struct cli_credentials *creds,
3981 char **pp_workgroup_out)
3983 char addr[INET6_ADDRSTRLEN];
3985 struct cli_state *cli;
3986 struct sockaddr_storage server_ss;
3988 *pp_workgroup_out = NULL;
3990 print_sockaddr(addr, sizeof(addr), mb_ip);
3991 DEBUG(99, ("Looking up name of master browser %s\n",
3995 * Do a name status query to find out the name of the master browser.
3996 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3997 * master browser will not respond to a wildcard query (or, at least,
3998 * an NT4 server acting as the domain master browser will not).
4000 * We might be able to use ONLY the query on MSBROWSE, but that's not
4001 * yet been tested with all Windows versions, so until it is, leave
4002 * the original wildcard query as the first choice and fall back to
4003 * MSBROWSE if the wildcard query fails.
4005 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
4006 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
4008 DEBUG(99, ("Could not retrieve name status for %s\n",
4013 if (!find_master_ip(name, &server_ss)) {
4014 DEBUG(99, ("Could not find master ip for %s\n", name));
4018 *pp_workgroup_out = talloc_strdup(ctx, name);
4020 DEBUG(4, ("found master browser %s, %s\n", name, addr));
4022 print_sockaddr(addr, sizeof(addr), &server_ss);
4023 cli = get_ipc_connect(addr, &server_ss, creds);