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 (0 && 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 (!NT_STATUS_IS_OK(status)) {
1746 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1747 tevent_req_nterror(req, status);
1751 status = cli_state_update_after_sesssetup(state->cli,
1752 state->out_native_os,
1753 state->out_native_lm,
1754 state->out_primary_domain);
1755 if (tevent_req_nterror(req, status)) {
1759 ok = smb1cli_conn_activate_signing(cli->conn,
1761 state->upassword_blob);
1763 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1765 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1770 if (state->session_key.data) {
1771 struct smbXcli_session *session = cli->smb1.session;
1773 status = smb1cli_session_set_session_key(session,
1774 state->session_key);
1775 if (tevent_req_nterror(req, status)) {
1780 tevent_req_done(req);
1783 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1785 struct tevent_req *req = tevent_req_callback_data(
1786 subreq, struct tevent_req);
1787 struct cli_session_setup_creds_state *state = tevent_req_data(
1788 req, struct cli_session_setup_creds_state);
1791 status = smb1cli_session_setup_lm21_recv(subreq, state,
1792 &state->out_native_os,
1793 &state->out_native_lm);
1794 TALLOC_FREE(subreq);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1797 tevent_req_nterror(req, status);
1801 status = cli_state_update_after_sesssetup(state->cli,
1802 state->out_native_os,
1803 state->out_native_lm,
1805 if (tevent_req_nterror(req, status)) {
1809 tevent_req_done(req);
1812 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1814 return tevent_req_simple_recv_ntstatus(req);
1817 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1818 struct cli_credentials *creds)
1820 struct tevent_context *ev;
1821 struct tevent_req *req;
1822 NTSTATUS status = NT_STATUS_NO_MEMORY;
1824 if (smbXcli_conn_has_async_calls(cli->conn)) {
1825 return NT_STATUS_INVALID_PARAMETER;
1827 ev = samba_tevent_context_init(talloc_tos());
1831 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1835 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1838 status = cli_session_setup_creds_recv(req);
1844 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1847 struct cli_credentials *creds = NULL;
1849 creds = cli_credentials_init_anon(cli);
1850 if (creds == NULL) {
1851 return NT_STATUS_NO_MEMORY;
1854 status = cli_session_setup_creds(cli, creds);
1856 if (!NT_STATUS_IS_OK(status)) {
1860 return NT_STATUS_OK;
1863 /****************************************************************************
1865 *****************************************************************************/
1867 struct cli_ulogoff_state {
1868 struct cli_state *cli;
1872 static void cli_ulogoff_done(struct tevent_req *subreq);
1874 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1875 struct tevent_context *ev,
1876 struct cli_state *cli)
1878 struct tevent_req *req, *subreq;
1879 struct cli_ulogoff_state *state;
1881 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1887 SCVAL(state->vwv+0, 0, 0xFF);
1888 SCVAL(state->vwv+1, 0, 0);
1889 SSVAL(state->vwv+2, 0, 0);
1891 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1893 if (tevent_req_nomem(subreq, req)) {
1894 return tevent_req_post(req, ev);
1896 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1900 static void cli_ulogoff_done(struct tevent_req *subreq)
1902 struct tevent_req *req = tevent_req_callback_data(
1903 subreq, struct tevent_req);
1904 struct cli_ulogoff_state *state = tevent_req_data(
1905 req, struct cli_ulogoff_state);
1908 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 tevent_req_nterror(req, status);
1913 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1914 tevent_req_done(req);
1917 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1919 return tevent_req_simple_recv_ntstatus(req);
1922 NTSTATUS cli_ulogoff(struct cli_state *cli)
1924 struct tevent_context *ev;
1925 struct tevent_req *req;
1926 NTSTATUS status = NT_STATUS_NO_MEMORY;
1928 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1929 status = smb2cli_logoff(cli->conn,
1932 if (!NT_STATUS_IS_OK(status)) {
1935 smb2cli_session_set_id_and_flags(cli->smb2.session,
1937 return NT_STATUS_OK;
1940 if (smbXcli_conn_has_async_calls(cli->conn)) {
1941 return NT_STATUS_INVALID_PARAMETER;
1943 ev = samba_tevent_context_init(talloc_tos());
1947 req = cli_ulogoff_send(ev, ev, cli);
1951 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1954 status = cli_ulogoff_recv(req);
1960 /****************************************************************************
1962 ****************************************************************************/
1964 struct cli_tcon_andx_state {
1965 struct cli_state *cli;
1970 static void cli_tcon_andx_done(struct tevent_req *subreq);
1972 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1973 struct tevent_context *ev,
1974 struct cli_state *cli,
1975 const char *share, const char *dev,
1976 const char *pass, int passlen,
1977 struct tevent_req **psmbreq)
1979 struct tevent_req *req, *subreq;
1980 struct cli_tcon_andx_state *state;
1985 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1986 uint16_t tcon_flags = 0;
1990 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1997 TALLOC_FREE(cli->smb1.tcon);
1998 cli->smb1.tcon = smbXcli_tcon_create(cli);
1999 if (tevent_req_nomem(cli->smb1.tcon, req)) {
2000 return tevent_req_post(req, ev);
2002 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
2004 cli->share = talloc_strdup(cli, share);
2009 /* in user level security don't send a password now */
2010 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2013 } else if (pass == NULL) {
2014 DEBUG(1, ("Server not using user level security and no "
2015 "password supplied.\n"));
2019 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2020 *pass && passlen != 24) {
2021 if (!lp_client_lanman_auth()) {
2022 DEBUG(1, ("Server requested LANMAN password "
2023 "(share-level security) but "
2024 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2029 * Non-encrypted passwords - convert to DOS codepage before
2032 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2034 pass = (const char *)p24;
2036 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2037 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2041 if (!lp_client_plaintext_auth() && (*pass)) {
2042 DEBUG(1, ("Server requested PLAINTEXT "
2044 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2049 * Non-encrypted passwords - convert to DOS codepage
2052 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2053 if (tevent_req_nomem(tmp_pass, req)) {
2054 return tevent_req_post(req, ev);
2056 tmp_pass = trans2_bytes_push_str(tmp_pass,
2057 false, /* always DOS */
2061 if (tevent_req_nomem(tmp_pass, req)) {
2062 return tevent_req_post(req, ev);
2064 pass = (const char *)tmp_pass;
2065 passlen = talloc_get_size(tmp_pass);
2069 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2070 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2072 SCVAL(vwv+0, 0, 0xFF);
2075 SSVAL(vwv+2, 0, tcon_flags);
2076 SSVAL(vwv+3, 0, passlen);
2078 if (passlen && pass) {
2079 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2081 bytes = talloc_array(state, uint8_t, 0);
2087 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2088 smbXcli_conn_remote_name(cli->conn), share);
2093 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2098 * Add the devicetype
2100 tmp = talloc_strdup_upper(talloc_tos(), dev);
2105 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2108 if (bytes == NULL) {
2113 state->bytes.iov_base = (void *)bytes;
2114 state->bytes.iov_len = talloc_get_size(bytes);
2116 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2118 if (subreq == NULL) {
2122 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2127 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2128 return tevent_req_post(req, ev);
2131 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2132 struct tevent_context *ev,
2133 struct cli_state *cli,
2134 const char *share, const char *dev,
2135 const char *pass, int passlen)
2137 struct tevent_req *req, *subreq;
2140 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2145 if (subreq == NULL) {
2148 status = smb1cli_req_chain_submit(&subreq, 1);
2149 if (!NT_STATUS_IS_OK(status)) {
2150 tevent_req_nterror(req, status);
2151 return tevent_req_post(req, ev);
2156 static void cli_tcon_andx_done(struct tevent_req *subreq)
2158 struct tevent_req *req = tevent_req_callback_data(
2159 subreq, struct tevent_req);
2160 struct cli_tcon_andx_state *state = tevent_req_data(
2161 req, struct cli_tcon_andx_state);
2162 struct cli_state *cli = state->cli;
2170 uint16_t optional_support = 0;
2172 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2173 &num_bytes, &bytes);
2174 TALLOC_FREE(subreq);
2175 if (!NT_STATUS_IS_OK(status)) {
2176 tevent_req_nterror(req, status);
2180 inhdr = in + NBT_HDR_SIZE;
2183 if (pull_string_talloc(cli,
2184 (const char *)inhdr,
2185 SVAL(inhdr, HDR_FLG2),
2189 STR_TERMINATE|STR_ASCII) == -1) {
2190 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2194 cli->dev = talloc_strdup(cli, "");
2195 if (cli->dev == NULL) {
2196 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2201 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2202 /* almost certainly win95 - enable bug fixes */
2207 * Make sure that we have the optional support 16-bit field. WCT > 2.
2208 * Avoids issues when connecting to Win9x boxes sharing files
2211 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2212 optional_support = SVAL(vwv+2, 0);
2215 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2216 smb1cli_session_protect_session_key(cli->smb1.session);
2219 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2220 SVAL(inhdr, HDR_TID),
2222 0, /* maximal_access */
2223 0, /* guest_maximal_access */
2225 NULL); /* fs_type */
2227 tevent_req_done(req);
2230 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2232 return tevent_req_simple_recv_ntstatus(req);
2235 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2236 const char *dev, const char *pass, int passlen)
2238 TALLOC_CTX *frame = talloc_stackframe();
2239 struct tevent_context *ev;
2240 struct tevent_req *req;
2241 NTSTATUS status = NT_STATUS_NO_MEMORY;
2243 if (smbXcli_conn_has_async_calls(cli->conn)) {
2245 * Can't use sync call while an async call is in flight
2247 status = NT_STATUS_INVALID_PARAMETER;
2251 ev = samba_tevent_context_init(frame);
2256 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2261 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2265 status = cli_tcon_andx_recv(req);
2271 struct cli_tree_connect_state {
2272 struct cli_state *cli;
2275 static struct tevent_req *cli_raw_tcon_send(
2276 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2277 const char *service, const char *pass, const char *dev);
2278 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2279 uint16_t *max_xmit, uint16_t *tid);
2281 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2282 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2283 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2285 static struct tevent_req *cli_tree_connect_send(
2286 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2287 const char *share, const char *dev, const char *pass)
2289 struct tevent_req *req, *subreq;
2290 struct cli_tree_connect_state *state;
2296 passlen = strlen(pass) + 1;
2298 req = tevent_req_create(mem_ctx, &state,
2299 struct cli_tree_connect_state);
2305 cli->share = talloc_strdup(cli, share);
2306 if (tevent_req_nomem(cli->share, req)) {
2307 return tevent_req_post(req, ev);
2310 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2313 TALLOC_FREE(cli->smb2.tcon);
2314 cli->smb2.tcon = smbXcli_tcon_create(cli);
2315 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2316 return tevent_req_post(req, ev);
2319 unc = talloc_asprintf(state, "\\\\%s\\%s",
2320 smbXcli_conn_remote_name(cli->conn),
2322 if (tevent_req_nomem(unc, req)) {
2323 return tevent_req_post(req, ev);
2326 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2327 cli->smb2.session, cli->smb2.tcon,
2330 if (tevent_req_nomem(subreq, req)) {
2331 return tevent_req_post(req, ev);
2333 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2338 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2339 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2341 if (tevent_req_nomem(subreq, req)) {
2342 return tevent_req_post(req, ev);
2344 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2349 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2350 if (tevent_req_nomem(subreq, req)) {
2351 return tevent_req_post(req, ev);
2353 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2358 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2360 tevent_req_simple_finish_ntstatus(
2361 subreq, smb2cli_tcon_recv(subreq));
2364 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2366 tevent_req_simple_finish_ntstatus(
2367 subreq, cli_tcon_andx_recv(subreq));
2370 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2372 struct tevent_req *req = tevent_req_callback_data(
2373 subreq, struct tevent_req);
2374 struct cli_tree_connect_state *state = tevent_req_data(
2375 req, struct cli_tree_connect_state);
2377 uint16_t max_xmit = 0;
2380 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2381 if (tevent_req_nterror(req, status)) {
2385 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2387 0, /* optional_support */
2388 0, /* maximal_access */
2389 0, /* guest_maximal_access */
2391 NULL); /* fs_type */
2393 tevent_req_done(req);
2396 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2398 return tevent_req_simple_recv_ntstatus(req);
2401 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2402 const char *dev, const char *pass)
2404 struct tevent_context *ev;
2405 struct tevent_req *req;
2406 NTSTATUS status = NT_STATUS_NO_MEMORY;
2408 if (smbXcli_conn_has_async_calls(cli->conn)) {
2409 return NT_STATUS_INVALID_PARAMETER;
2411 ev = samba_tevent_context_init(talloc_tos());
2415 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2419 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2422 status = cli_tree_connect_recv(req);
2428 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2429 const char *share, const char *dev,
2430 struct cli_credentials *creds)
2432 const char *pw = NULL;
2434 if (creds != NULL) {
2435 pw = cli_credentials_get_password(creds);
2438 return cli_tree_connect(cli, share, dev, pw);
2441 /****************************************************************************
2442 Send a tree disconnect.
2443 ****************************************************************************/
2445 struct cli_tdis_state {
2446 struct cli_state *cli;
2449 static void cli_tdis_done(struct tevent_req *subreq);
2451 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2452 struct tevent_context *ev,
2453 struct cli_state *cli)
2455 struct tevent_req *req, *subreq;
2456 struct cli_tdis_state *state;
2458 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2464 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2465 if (tevent_req_nomem(subreq, req)) {
2466 return tevent_req_post(req, ev);
2468 tevent_req_set_callback(subreq, cli_tdis_done, req);
2472 static void cli_tdis_done(struct tevent_req *subreq)
2474 struct tevent_req *req = tevent_req_callback_data(
2475 subreq, struct tevent_req);
2476 struct cli_tdis_state *state = tevent_req_data(
2477 req, struct cli_tdis_state);
2480 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2481 TALLOC_FREE(subreq);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 tevent_req_nterror(req, status);
2486 TALLOC_FREE(state->cli->smb1.tcon);
2487 tevent_req_done(req);
2490 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2492 return tevent_req_simple_recv_ntstatus(req);
2495 NTSTATUS cli_tdis(struct cli_state *cli)
2497 struct tevent_context *ev;
2498 struct tevent_req *req;
2499 NTSTATUS status = NT_STATUS_NO_MEMORY;
2501 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2502 status = smb2cli_tdis(cli->conn,
2506 if (NT_STATUS_IS_OK(status)) {
2507 TALLOC_FREE(cli->smb2.tcon);
2512 if (smbXcli_conn_has_async_calls(cli->conn)) {
2513 return NT_STATUS_INVALID_PARAMETER;
2515 ev = samba_tevent_context_init(talloc_tos());
2519 req = cli_tdis_send(ev, ev, cli);
2523 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2526 status = cli_tdis_recv(req);
2532 struct cli_connect_sock_state {
2533 const char **called_names;
2534 const char **calling_names;
2540 static void cli_connect_sock_done(struct tevent_req *subreq);
2543 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2547 static struct tevent_req *cli_connect_sock_send(
2548 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2549 const char *host, int name_type, const struct sockaddr_storage *pss,
2550 const char *myname, uint16_t port)
2552 struct tevent_req *req, *subreq;
2553 struct cli_connect_sock_state *state;
2554 struct sockaddr_storage *addrs = NULL;
2556 unsigned num_addrs = 0;
2559 req = tevent_req_create(mem_ctx, &state,
2560 struct cli_connect_sock_state);
2565 if ((pss == NULL) || is_zero_addr(pss)) {
2568 * Here we cheat. resolve_name_list is not async at all. So
2569 * this call will only be really async if the name lookup has
2570 * been done externally.
2573 status = resolve_name_list(state, host, name_type,
2574 &addrs, &num_addrs);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 tevent_req_nterror(req, status);
2577 return tevent_req_post(req, ev);
2580 addrs = talloc_array(state, struct sockaddr_storage, 1);
2581 if (tevent_req_nomem(addrs, req)) {
2582 return tevent_req_post(req, ev);
2588 state->called_names = talloc_array(state, const char *, num_addrs);
2589 if (tevent_req_nomem(state->called_names, req)) {
2590 return tevent_req_post(req, ev);
2592 state->called_types = talloc_array(state, int, num_addrs);
2593 if (tevent_req_nomem(state->called_types, req)) {
2594 return tevent_req_post(req, ev);
2596 state->calling_names = talloc_array(state, const char *, num_addrs);
2597 if (tevent_req_nomem(state->calling_names, req)) {
2598 return tevent_req_post(req, ev);
2600 for (i=0; i<num_addrs; i++) {
2601 state->called_names[i] = host;
2602 state->called_types[i] = name_type;
2603 state->calling_names[i] = myname;
2606 subreq = smbsock_any_connect_send(
2607 state, ev, addrs, state->called_names, state->called_types,
2608 state->calling_names, NULL, num_addrs, port);
2609 if (tevent_req_nomem(subreq, req)) {
2610 return tevent_req_post(req, ev);
2612 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2616 static void cli_connect_sock_done(struct tevent_req *subreq)
2618 struct tevent_req *req = tevent_req_callback_data(
2619 subreq, struct tevent_req);
2620 struct cli_connect_sock_state *state = tevent_req_data(
2621 req, struct cli_connect_sock_state);
2624 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2626 TALLOC_FREE(subreq);
2627 if (tevent_req_nterror(req, status)) {
2630 set_socket_options(state->fd, lp_socket_options());
2631 tevent_req_done(req);
2634 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2635 int *pfd, uint16_t *pport)
2637 struct cli_connect_sock_state *state = tevent_req_data(
2638 req, struct cli_connect_sock_state);
2641 if (tevent_req_is_nterror(req, &status)) {
2645 *pport = state->port;
2646 return NT_STATUS_OK;
2649 struct cli_connect_nb_state {
2650 const char *desthost;
2651 enum smb_signing_setting signing_state;
2653 struct cli_state *cli;
2656 static void cli_connect_nb_done(struct tevent_req *subreq);
2658 static struct tevent_req *cli_connect_nb_send(
2659 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2660 const char *host, const struct sockaddr_storage *dest_ss,
2661 uint16_t port, int name_type, const char *myname,
2662 enum smb_signing_setting signing_state, int flags)
2664 struct tevent_req *req, *subreq;
2665 struct cli_connect_nb_state *state;
2667 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2671 state->signing_state = signing_state;
2672 state->flags = flags;
2675 char *p = strchr(host, '#');
2678 name_type = strtol(p+1, NULL, 16);
2679 host = talloc_strndup(state, host, p - host);
2680 if (tevent_req_nomem(host, req)) {
2681 return tevent_req_post(req, ev);
2685 state->desthost = host;
2686 } else if (dest_ss != NULL) {
2687 state->desthost = print_canonical_sockaddr(state, dest_ss);
2688 if (tevent_req_nomem(state->desthost, req)) {
2689 return tevent_req_post(req, ev);
2692 /* No host or dest_ss given. Error out. */
2693 tevent_req_error(req, EINVAL);
2694 return tevent_req_post(req, ev);
2697 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2699 if (tevent_req_nomem(subreq, req)) {
2700 return tevent_req_post(req, ev);
2702 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2706 static void cli_connect_nb_done(struct tevent_req *subreq)
2708 struct tevent_req *req = tevent_req_callback_data(
2709 subreq, struct tevent_req);
2710 struct cli_connect_nb_state *state = tevent_req_data(
2711 req, struct cli_connect_nb_state);
2716 status = cli_connect_sock_recv(subreq, &fd, &port);
2717 TALLOC_FREE(subreq);
2718 if (tevent_req_nterror(req, status)) {
2722 state->cli = cli_state_create(state, fd, state->desthost,
2723 state->signing_state, state->flags);
2724 if (tevent_req_nomem(state->cli, req)) {
2728 tevent_req_done(req);
2731 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2732 struct cli_state **pcli)
2734 struct cli_connect_nb_state *state = tevent_req_data(
2735 req, struct cli_connect_nb_state);
2738 if (tevent_req_is_nterror(req, &status)) {
2741 *pcli = talloc_move(NULL, &state->cli);
2742 return NT_STATUS_OK;
2745 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2746 uint16_t port, int name_type, const char *myname,
2747 enum smb_signing_setting signing_state, int flags, struct cli_state **pcli)
2749 struct tevent_context *ev;
2750 struct tevent_req *req;
2751 NTSTATUS status = NT_STATUS_NO_MEMORY;
2753 ev = samba_tevent_context_init(talloc_tos());
2757 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2758 myname, signing_state, flags);
2762 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2765 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2768 status = cli_connect_nb_recv(req, pcli);
2774 struct cli_start_connection_state {
2775 struct tevent_context *ev;
2776 struct cli_state *cli;
2781 static void cli_start_connection_connected(struct tevent_req *subreq);
2782 static void cli_start_connection_done(struct tevent_req *subreq);
2785 establishes a connection to after the negprot.
2786 @param output_cli A fully initialised cli structure, non-null only on success
2787 @param dest_host The netbios name of the remote host
2788 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2789 @param port (optional) The destination port (0 for default)
2792 static struct tevent_req *cli_start_connection_send(
2793 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2794 const char *my_name, const char *dest_host,
2795 const struct sockaddr_storage *dest_ss, int port,
2796 enum smb_signing_setting signing_state, int flags)
2798 struct tevent_req *req, *subreq;
2799 struct cli_start_connection_state *state;
2801 req = tevent_req_create(mem_ctx, &state,
2802 struct cli_start_connection_state);
2808 if (flags & CLI_FULL_CONNECTION_IPC) {
2809 state->min_protocol = lp_client_ipc_min_protocol();
2810 state->max_protocol = lp_client_ipc_max_protocol();
2812 state->min_protocol = lp_client_min_protocol();
2813 state->max_protocol = lp_client_max_protocol();
2816 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2817 state->max_protocol = MIN(state->max_protocol,
2819 state->min_protocol = MIN(state->min_protocol,
2820 state->max_protocol);
2823 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2824 state->min_protocol = MAX(state->min_protocol,
2826 state->max_protocol = MAX(state->max_protocol,
2827 state->min_protocol);
2830 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2831 0x20, my_name, signing_state, flags);
2832 if (tevent_req_nomem(subreq, req)) {
2833 return tevent_req_post(req, ev);
2835 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2839 static void cli_start_connection_connected(struct tevent_req *subreq)
2841 struct tevent_req *req = tevent_req_callback_data(
2842 subreq, struct tevent_req);
2843 struct cli_start_connection_state *state = tevent_req_data(
2844 req, struct cli_start_connection_state);
2847 status = cli_connect_nb_recv(subreq, &state->cli);
2848 TALLOC_FREE(subreq);
2849 if (tevent_req_nterror(req, status)) {
2853 subreq = smbXcli_negprot_send(
2857 state->cli->timeout,
2858 state->min_protocol,
2859 state->max_protocol,
2860 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
2862 if (tevent_req_nomem(subreq, req)) {
2865 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2868 static void cli_start_connection_done(struct tevent_req *subreq)
2870 struct tevent_req *req = tevent_req_callback_data(
2871 subreq, struct tevent_req);
2872 struct cli_start_connection_state *state = tevent_req_data(
2873 req, struct cli_start_connection_state);
2876 status = smbXcli_negprot_recv(subreq, NULL, NULL);
2877 TALLOC_FREE(subreq);
2878 if (tevent_req_nterror(req, status)) {
2882 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2883 /* Ensure we ask for some initial credits. */
2884 smb2cli_conn_set_max_credits(state->cli->conn,
2885 DEFAULT_SMB2_MAX_CREDITS);
2888 tevent_req_done(req);
2891 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2892 struct cli_state **output_cli)
2894 struct cli_start_connection_state *state = tevent_req_data(
2895 req, struct cli_start_connection_state);
2898 if (tevent_req_is_nterror(req, &status)) {
2901 *output_cli = state->cli;
2903 return NT_STATUS_OK;
2906 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2907 const char *my_name,
2908 const char *dest_host,
2909 const struct sockaddr_storage *dest_ss, int port,
2910 enum smb_signing_setting signing_state, int flags)
2912 struct tevent_context *ev;
2913 struct tevent_req *req;
2914 NTSTATUS status = NT_STATUS_NO_MEMORY;
2916 ev = samba_tevent_context_init(talloc_tos());
2920 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2921 port, signing_state, flags);
2925 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2928 status = cli_start_connection_recv(req, output_cli);
2934 struct cli_smb1_setup_encryption_blob_state {
2939 uint16_t enc_ctx_id;
2942 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2944 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2945 struct tevent_context *ev,
2946 struct cli_state *cli,
2949 struct tevent_req *req = NULL;
2950 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2951 struct tevent_req *subreq = NULL;
2953 req = tevent_req_create(mem_ctx, &state,
2954 struct cli_smb1_setup_encryption_blob_state);
2959 if (in.length > CLI_BUFFER_SIZE) {
2960 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2961 return tevent_req_post(req, ev);
2964 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2965 SSVAL(state->param, 0, 0);
2966 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2968 subreq = smb1cli_trans_send(state, ev, cli->conn,
2976 NULL, /* pipe_name */
2982 in.data, in.length, CLI_BUFFER_SIZE);
2983 if (tevent_req_nomem(subreq, req)) {
2984 return tevent_req_post(req, ev);
2986 tevent_req_set_callback(subreq,
2987 cli_smb1_setup_encryption_blob_done,
2993 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2995 struct tevent_req *req =
2996 tevent_req_callback_data(subreq,
2998 struct cli_smb1_setup_encryption_blob_state *state =
2999 tevent_req_data(req,
3000 struct cli_smb1_setup_encryption_blob_state);
3001 uint8_t *rparam=NULL, *rdata=NULL;
3002 uint32_t num_rparam, num_rdata;
3005 status = smb1cli_trans_recv(subreq, state,
3006 NULL, /* recv_flags */
3007 NULL, 0, NULL, /* rsetup */
3008 &rparam, 0, &num_rparam,
3009 &rdata, 0, &num_rdata);
3010 TALLOC_FREE(subreq);
3011 state->status = status;
3012 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
3013 status = NT_STATUS_OK;
3015 if (tevent_req_nterror(req, status)) {
3019 if (num_rparam == 2) {
3020 state->enc_ctx_id = SVAL(rparam, 0);
3022 TALLOC_FREE(rparam);
3024 state->out = data_blob_const(rdata, num_rdata);
3026 tevent_req_done(req);
3029 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
3030 TALLOC_CTX *mem_ctx,
3032 uint16_t *enc_ctx_id)
3034 struct cli_smb1_setup_encryption_blob_state *state =
3035 tevent_req_data(req,
3036 struct cli_smb1_setup_encryption_blob_state);
3039 if (tevent_req_is_nterror(req, &status)) {
3040 tevent_req_received(req);
3044 status = state->status;
3047 talloc_steal(mem_ctx, out->data);
3049 *enc_ctx_id = state->enc_ctx_id;
3051 tevent_req_received(req);
3055 struct cli_smb1_setup_encryption_state {
3056 struct tevent_context *ev;
3057 struct cli_state *cli;
3058 struct smb_trans_enc_state *es;
3065 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3066 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3067 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3068 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3069 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3071 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3072 struct tevent_context *ev,
3073 struct cli_state *cli,
3074 struct cli_credentials *creds)
3076 struct tevent_req *req = NULL;
3077 struct cli_smb1_setup_encryption_state *state = NULL;
3078 struct auth_generic_state *ags = NULL;
3079 const DATA_BLOB *b = NULL;
3080 bool auth_requested = false;
3081 const char *target_service = NULL;
3082 const char *target_hostname = NULL;
3085 req = tevent_req_create(mem_ctx, &state,
3086 struct cli_smb1_setup_encryption_state);
3093 auth_requested = cli_credentials_authentication_requested(creds);
3094 if (!auth_requested) {
3095 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3096 return tevent_req_post(req, ev);
3099 target_service = "cifs";
3100 target_hostname = smbXcli_conn_remote_name(cli->conn);
3102 status = cli_session_creds_prepare_krb5(cli, creds);
3103 if (tevent_req_nterror(req, status)) {
3104 return tevent_req_post(req, ev);
3107 state->es = talloc_zero(state, struct smb_trans_enc_state);
3108 if (tevent_req_nomem(state->es, req)) {
3109 return tevent_req_post(req, ev);
3112 status = auth_generic_client_prepare(state->es, &ags);
3113 if (tevent_req_nterror(req, status)) {
3114 return tevent_req_post(req, ev);
3117 gensec_want_feature(ags->gensec_security,
3118 GENSEC_FEATURE_SIGN);
3119 gensec_want_feature(ags->gensec_security,
3120 GENSEC_FEATURE_SEAL);
3122 status = auth_generic_set_creds(ags, creds);
3123 if (tevent_req_nterror(req, status)) {
3124 return tevent_req_post(req, ev);
3127 if (target_service != NULL) {
3128 status = gensec_set_target_service(ags->gensec_security,
3130 if (tevent_req_nterror(req, status)) {
3131 return tevent_req_post(req, ev);
3135 if (target_hostname != NULL) {
3136 status = gensec_set_target_hostname(ags->gensec_security,
3138 if (tevent_req_nterror(req, status)) {
3139 return tevent_req_post(req, ev);
3143 gensec_set_max_update_size(ags->gensec_security,
3146 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3148 state->blob_in = *b;
3151 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3152 if (tevent_req_nterror(req, status)) {
3153 return tevent_req_post(req, ev);
3157 * We only need the gensec_security part from here.
3159 state->es->gensec_security = talloc_move(state->es,
3160 &ags->gensec_security);
3163 cli_smb1_setup_encryption_local_next(req);
3164 if (!tevent_req_is_in_progress(req)) {
3165 return tevent_req_post(req, ev);
3171 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3173 struct cli_smb1_setup_encryption_state *state =
3174 tevent_req_data(req,
3175 struct cli_smb1_setup_encryption_state);
3176 struct tevent_req *subreq = NULL;
3178 if (state->local_ready) {
3179 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3183 subreq = gensec_update_send(state, state->ev,
3184 state->es->gensec_security,
3186 if (tevent_req_nomem(subreq, req)) {
3189 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3192 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3194 struct tevent_req *req =
3195 tevent_req_callback_data(subreq,
3197 struct cli_smb1_setup_encryption_state *state =
3198 tevent_req_data(req,
3199 struct cli_smb1_setup_encryption_state);
3202 status = gensec_update_recv(subreq, state, &state->blob_out);
3203 TALLOC_FREE(subreq);
3204 state->blob_in = data_blob_null;
3205 if (!NT_STATUS_IS_OK(status) &&
3206 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3208 tevent_req_nterror(req, status);
3212 if (NT_STATUS_IS_OK(status)) {
3213 state->local_ready = true;
3217 * We always get NT_STATUS_OK from the server even if it is not ready.
3218 * So guess the server is ready when we are ready and already sent
3219 * our last blob to the server.
3221 if (state->local_ready && state->blob_out.length == 0) {
3222 state->remote_ready = true;
3225 if (state->local_ready && state->remote_ready) {
3226 cli_smb1_setup_encryption_ready(req);
3230 cli_smb1_setup_encryption_remote_next(req);
3233 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3235 struct cli_smb1_setup_encryption_state *state =
3236 tevent_req_data(req,
3237 struct cli_smb1_setup_encryption_state);
3238 struct tevent_req *subreq = NULL;
3240 if (state->remote_ready) {
3241 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3245 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3246 state->cli, state->blob_out);
3247 if (tevent_req_nomem(subreq, req)) {
3250 tevent_req_set_callback(subreq,
3251 cli_smb1_setup_encryption_remote_done,
3255 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3257 struct tevent_req *req =
3258 tevent_req_callback_data(subreq,
3260 struct cli_smb1_setup_encryption_state *state =
3261 tevent_req_data(req,
3262 struct cli_smb1_setup_encryption_state);
3265 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3267 &state->es->enc_ctx_num);
3268 TALLOC_FREE(subreq);
3269 data_blob_free(&state->blob_out);
3270 if (!NT_STATUS_IS_OK(status) &&
3271 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3273 tevent_req_nterror(req, status);
3278 * We always get NT_STATUS_OK even if the server is not ready.
3279 * So guess the server is ready when we are ready and sent
3280 * our last blob to the server.
3282 if (state->local_ready) {
3283 state->remote_ready = true;
3286 if (state->local_ready && state->remote_ready) {
3287 cli_smb1_setup_encryption_ready(req);
3291 cli_smb1_setup_encryption_local_next(req);
3294 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3296 struct cli_smb1_setup_encryption_state *state =
3297 tevent_req_data(req,
3298 struct cli_smb1_setup_encryption_state);
3299 struct smb_trans_enc_state *es = NULL;
3301 if (state->blob_in.length != 0) {
3302 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3306 if (state->blob_out.length != 0) {
3307 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3311 es = talloc_move(state->cli->conn, &state->es);
3313 smb1cli_conn_set_encryption(state->cli->conn, es);
3316 tevent_req_done(req);
3319 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3321 return tevent_req_simple_recv_ntstatus(req);
3324 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3325 struct cli_credentials *creds)
3327 struct tevent_context *ev = NULL;
3328 struct tevent_req *req = NULL;
3329 NTSTATUS status = NT_STATUS_NO_MEMORY;
3331 ev = samba_tevent_context_init(talloc_tos());
3335 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3339 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3342 status = cli_smb1_setup_encryption_recv(req);
3349 establishes a connection right up to doing tconX, password specified.
3350 @param output_cli A fully initialised cli structure, non-null only on success
3351 @param dest_host The netbios name of the remote host
3352 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3353 @param port (optional) The destination port (0 for default)
3354 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3355 @param service_type The 'type' of serivice.
3356 @param creds The used user credentials
3359 struct cli_full_connection_creds_state {
3360 struct tevent_context *ev;
3361 const char *service;
3362 const char *service_type;
3363 struct cli_credentials *creds;
3365 struct cli_state *cli;
3368 static int cli_full_connection_creds_state_destructor(
3369 struct cli_full_connection_creds_state *s)
3371 if (s->cli != NULL) {
3372 cli_shutdown(s->cli);
3378 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3379 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3380 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3381 static void cli_full_connection_creds_enc_start(struct tevent_req *req);
3382 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
3383 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
3384 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
3385 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
3386 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
3387 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3388 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3390 struct tevent_req *cli_full_connection_creds_send(
3391 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3392 const char *my_name, const char *dest_host,
3393 const struct sockaddr_storage *dest_ss, int port,
3394 const char *service, const char *service_type,
3395 struct cli_credentials *creds,
3398 struct tevent_req *req, *subreq;
3399 struct cli_full_connection_creds_state *state;
3400 enum smb_signing_setting signing_state;
3401 enum smb_encryption_setting encryption_state =
3402 cli_credentials_get_smb_encryption(creds);
3404 req = tevent_req_create(mem_ctx, &state,
3405 struct cli_full_connection_creds_state);
3409 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3412 state->service = service;
3413 state->service_type = service_type;
3414 state->creds = creds;
3415 state->flags = flags;
3417 if (flags & CLI_FULL_CONNECTION_IPC) {
3418 signing_state = cli_credentials_get_smb_ipc_signing(creds);
3420 signing_state = cli_credentials_get_smb_signing(creds);
3423 if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
3424 if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
3425 encryption_state = SMB_ENCRYPTION_DESIRED;
3429 if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
3430 signing_state = SMB_SIGNING_REQUIRED;
3433 subreq = cli_start_connection_send(
3434 state, ev, my_name, dest_host, dest_ss, port,
3435 signing_state, flags);
3436 if (tevent_req_nomem(subreq, req)) {
3437 return tevent_req_post(req, ev);
3439 tevent_req_set_callback(subreq,
3440 cli_full_connection_creds_conn_done,
3445 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3447 struct tevent_req *req = tevent_req_callback_data(
3448 subreq, struct tevent_req);
3449 struct cli_full_connection_creds_state *state = tevent_req_data(
3450 req, struct cli_full_connection_creds_state);
3453 status = cli_start_connection_recv(subreq, &state->cli);
3454 TALLOC_FREE(subreq);
3455 if (tevent_req_nterror(req, status)) {
3459 cli_full_connection_creds_sess_start(req);
3462 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3464 struct cli_full_connection_creds_state *state = tevent_req_data(
3465 req, struct cli_full_connection_creds_state);
3466 struct tevent_req *subreq = NULL;
3468 subreq = cli_session_setup_creds_send(
3469 state, state->ev, state->cli, state->creds);
3470 if (tevent_req_nomem(subreq, req)) {
3473 tevent_req_set_callback(subreq,
3474 cli_full_connection_creds_sess_done,
3478 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3480 struct tevent_req *req = tevent_req_callback_data(
3481 subreq, struct tevent_req);
3482 struct cli_full_connection_creds_state *state = tevent_req_data(
3483 req, struct cli_full_connection_creds_state);
3486 status = cli_session_setup_creds_recv(subreq);
3487 TALLOC_FREE(subreq);
3489 if (!NT_STATUS_IS_OK(status) &&
3490 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3492 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3494 state->creds = cli_credentials_init_anon(state);
3495 if (tevent_req_nomem(state->creds, req)) {
3499 cli_full_connection_creds_sess_start(req);
3503 if (tevent_req_nterror(req, status)) {
3507 cli_full_connection_creds_enc_start(req);
3510 static void cli_full_connection_creds_enc_start(struct tevent_req *req)
3512 struct cli_full_connection_creds_state *state = tevent_req_data(
3513 req, struct cli_full_connection_creds_state);
3514 enum smb_encryption_setting encryption_state =
3515 cli_credentials_get_smb_encryption(state->creds);
3516 struct tevent_req *subreq = NULL;
3519 if (encryption_state < SMB_ENCRYPTION_DESIRED) {
3520 cli_full_connection_creds_tcon_start(req);
3524 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3525 status = smb2cli_session_encryption_on(state->cli->smb2.session);
3526 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3527 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3528 cli_full_connection_creds_tcon_start(req);
3531 d_printf("Encryption required and "
3532 "server doesn't support "
3533 "SMB3 encryption - failing connect\n");
3534 tevent_req_nterror(req, status);
3536 } else if (!NT_STATUS_IS_OK(status)) {
3537 d_printf("Encryption required and "
3538 "setup failed with error %s.\n",
3540 tevent_req_nterror(req, status);
3544 cli_full_connection_creds_tcon_start(req);
3548 if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
3549 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3550 cli_full_connection_creds_tcon_start(req);
3554 status = NT_STATUS_NOT_SUPPORTED;
3555 d_printf("Encryption required and "
3556 "server doesn't support "
3557 "SMB1 Unix Extensions - failing connect\n");
3558 tevent_req_nterror(req, status);
3563 * We do a tcon on IPC$ just to setup the encryption,
3564 * the real tcon will be encrypted then.
3566 subreq = cli_tree_connect_send(state, state->ev, state->cli,
3567 "IPC$", "IPC", NULL);
3568 if (tevent_req_nomem(subreq, req)) {
3571 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
3574 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
3576 struct tevent_req *req = tevent_req_callback_data(
3577 subreq, struct tevent_req);
3578 struct cli_full_connection_creds_state *state = tevent_req_data(
3579 req, struct cli_full_connection_creds_state);
3582 status = cli_tree_connect_recv(subreq);
3583 TALLOC_FREE(subreq);
3584 if (tevent_req_nterror(req, status)) {
3588 subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
3589 if (tevent_req_nomem(subreq, req)) {
3592 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
3595 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
3597 struct tevent_req *req = tevent_req_callback_data(
3598 subreq, struct tevent_req);
3599 struct cli_full_connection_creds_state *state = tevent_req_data(
3600 req, struct cli_full_connection_creds_state);
3601 enum smb_encryption_setting encryption_state =
3602 cli_credentials_get_smb_encryption(state->creds);
3603 uint16_t major, minor;
3604 uint32_t caplow, caphigh;
3607 status = cli_unix_extensions_version_recv(subreq,
3611 TALLOC_FREE(subreq);
3612 if (!NT_STATUS_IS_OK(status)) {
3613 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3614 /* disconnect ipc$ followed by the real tree connect */
3615 cli_full_connection_creds_enc_tdis(req);
3618 DEBUG(10, ("%s: cli_unix_extensions_version "
3619 "returned %s\n", __func__, nt_errstr(status)));
3620 tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
3624 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
3625 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3626 /* disconnect ipc$ followed by the real tree connect */
3627 cli_full_connection_creds_enc_tdis(req);
3630 DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
3631 "not supported\n", __func__));
3632 tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
3636 subreq = cli_smb1_setup_encryption_send(state, state->ev,
3639 if (tevent_req_nomem(subreq, req)) {
3642 tevent_req_set_callback(subreq,
3643 cli_full_connection_creds_enc_done,
3647 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
3649 struct tevent_req *req = tevent_req_callback_data(
3650 subreq, struct tevent_req);
3653 status = cli_smb1_setup_encryption_recv(subreq);
3654 TALLOC_FREE(subreq);
3655 if (tevent_req_nterror(req, status)) {
3659 /* disconnect ipc$ followed by the real tree connect */
3660 cli_full_connection_creds_enc_tdis(req);
3663 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
3665 struct cli_full_connection_creds_state *state = tevent_req_data(
3666 req, struct cli_full_connection_creds_state);
3667 struct tevent_req *subreq = NULL;
3669 subreq = cli_tdis_send(state, state->ev, state->cli);
3670 if (tevent_req_nomem(subreq, req)) {
3673 tevent_req_set_callback(subreq,
3674 cli_full_connection_creds_enc_finished,
3678 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
3680 struct tevent_req *req = tevent_req_callback_data(
3681 subreq, struct tevent_req);
3684 status = cli_tdis_recv(subreq);
3685 TALLOC_FREE(subreq);
3686 if (tevent_req_nterror(req, status)) {
3690 cli_full_connection_creds_tcon_start(req);
3693 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3695 struct cli_full_connection_creds_state *state = tevent_req_data(
3696 req, struct cli_full_connection_creds_state);
3697 struct tevent_req *subreq = NULL;
3698 const char *password = NULL;
3700 if (state->service == NULL) {
3701 tevent_req_done(req);
3705 password = cli_credentials_get_password(state->creds);
3707 subreq = cli_tree_connect_send(state, state->ev,
3710 state->service_type,
3712 if (tevent_req_nomem(subreq, req)) {
3715 tevent_req_set_callback(subreq,
3716 cli_full_connection_creds_tcon_done,
3720 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3722 struct tevent_req *req = tevent_req_callback_data(
3723 subreq, struct tevent_req);
3726 status = cli_tree_connect_recv(subreq);
3727 TALLOC_FREE(subreq);
3728 if (tevent_req_nterror(req, status)) {
3732 tevent_req_done(req);
3735 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3736 struct cli_state **output_cli)
3738 struct cli_full_connection_creds_state *state = tevent_req_data(
3739 req, struct cli_full_connection_creds_state);
3742 if (tevent_req_is_nterror(req, &status)) {
3745 *output_cli = state->cli;
3746 talloc_set_destructor(state, NULL);
3747 return NT_STATUS_OK;
3750 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3751 const char *my_name,
3752 const char *dest_host,
3753 const struct sockaddr_storage *dest_ss, int port,
3754 const char *service, const char *service_type,
3755 struct cli_credentials *creds,
3758 struct tevent_context *ev;
3759 struct tevent_req *req;
3760 NTSTATUS status = NT_STATUS_NO_MEMORY;
3762 ev = samba_tevent_context_init(talloc_tos());
3766 req = cli_full_connection_creds_send(
3767 ev, ev, my_name, dest_host, dest_ss, port, service,
3768 service_type, creds, flags);
3772 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3775 status = cli_full_connection_creds_recv(req, output_cli);
3781 /****************************************************************************
3782 Send an old style tcon.
3783 ****************************************************************************/
3784 struct cli_raw_tcon_state {
3788 static void cli_raw_tcon_done(struct tevent_req *subreq);
3790 static struct tevent_req *cli_raw_tcon_send(
3791 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3792 const char *service, const char *pass, const char *dev)
3794 struct tevent_req *req, *subreq;
3795 struct cli_raw_tcon_state *state;
3798 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3803 if (!lp_client_plaintext_auth() && (*pass)) {
3804 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3805 " or 'client ntlmv2 auth = yes'\n"));
3806 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3807 return tevent_req_post(req, ev);
3810 TALLOC_FREE(cli->smb1.tcon);
3811 cli->smb1.tcon = smbXcli_tcon_create(cli);
3812 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3813 return tevent_req_post(req, ev);
3815 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3817 bytes = talloc_array(state, uint8_t, 0);
3818 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3819 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3820 service, strlen(service)+1, NULL);
3821 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3822 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3823 pass, strlen(pass)+1, NULL);
3824 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3825 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3826 dev, strlen(dev)+1, NULL);
3828 if (tevent_req_nomem(bytes, req)) {
3829 return tevent_req_post(req, ev);
3832 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3833 talloc_get_size(bytes), bytes);
3834 if (tevent_req_nomem(subreq, req)) {
3835 return tevent_req_post(req, ev);
3837 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3841 static void cli_raw_tcon_done(struct tevent_req *subreq)
3843 struct tevent_req *req = tevent_req_callback_data(
3844 subreq, struct tevent_req);
3845 struct cli_raw_tcon_state *state = tevent_req_data(
3846 req, struct cli_raw_tcon_state);
3849 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3851 TALLOC_FREE(subreq);
3852 if (tevent_req_nterror(req, status)) {
3855 tevent_req_done(req);
3858 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3859 uint16_t *max_xmit, uint16_t *tid)
3861 struct cli_raw_tcon_state *state = tevent_req_data(
3862 req, struct cli_raw_tcon_state);
3865 if (tevent_req_is_nterror(req, &status)) {
3868 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3869 *tid = SVAL(state->ret_vwv + 1, 0);
3870 return NT_STATUS_OK;
3873 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3874 const char *service, const char *pass, const char *dev,
3875 uint16_t *max_xmit, uint16_t *tid)
3877 struct tevent_context *ev;
3878 struct tevent_req *req;
3879 NTSTATUS status = NT_STATUS_NO_MEMORY;
3881 ev = samba_tevent_context_init(talloc_tos());
3885 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3889 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3892 status = cli_raw_tcon_recv(req, max_xmit, tid);
3898 /* Return a cli_state pointing at the IPC$ share for the given server */
3900 struct cli_state *get_ipc_connect(char *server,
3901 struct sockaddr_storage *server_ss,
3902 struct cli_credentials *creds)
3904 struct cli_state *cli;
3906 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3908 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3909 flags |= CLI_FULL_CONNECTION_IPC;
3911 nt_status = cli_full_connection_creds(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3915 if (NT_STATUS_IS_OK(nt_status)) {
3918 if (is_ipaddress(server)) {
3919 /* windows 9* needs a correct NMB name for connections */
3920 fstring remote_name;
3922 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3923 cli = get_ipc_connect(remote_name, server_ss, creds);
3932 * Given the IP address of a master browser on the network, return its
3933 * workgroup and connect to it.
3935 * This function is provided to allow additional processing beyond what
3936 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3937 * browsers and obtain each master browsers' list of domains (in case the
3938 * first master browser is recently on the network and has not yet
3939 * synchronized with other master browsers and therefore does not yet have the
3940 * entire network browse list)
3943 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3944 struct sockaddr_storage *mb_ip,
3945 struct cli_credentials *creds,
3946 char **pp_workgroup_out)
3948 char addr[INET6_ADDRSTRLEN];
3950 struct cli_state *cli;
3951 struct sockaddr_storage server_ss;
3953 *pp_workgroup_out = NULL;
3955 print_sockaddr(addr, sizeof(addr), mb_ip);
3956 DEBUG(99, ("Looking up name of master browser %s\n",
3960 * Do a name status query to find out the name of the master browser.
3961 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3962 * master browser will not respond to a wildcard query (or, at least,
3963 * an NT4 server acting as the domain master browser will not).
3965 * We might be able to use ONLY the query on MSBROWSE, but that's not
3966 * yet been tested with all Windows versions, so until it is, leave
3967 * the original wildcard query as the first choice and fall back to
3968 * MSBROWSE if the wildcard query fails.
3970 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3971 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3973 DEBUG(99, ("Could not retrieve name status for %s\n",
3978 if (!find_master_ip(name, &server_ss)) {
3979 DEBUG(99, ("Could not find master ip for %s\n", name));
3983 *pp_workgroup_out = talloc_strdup(ctx, name);
3985 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3987 print_sockaddr(addr, sizeof(addr), &server_ss);
3988 cli = get_ipc_connect(addr, &server_ss, creds);